From 9acad5fcefac3c4f9083d6fa1e6d18ff9ce6fae2 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Tue, 3 Jun 2014 17:10:40 +0200 Subject: [PATCH 001/602] Release 1.0 --- ...ino-usbserial-atmega16u2-Mega2560-Rev3.hex | 254 +++++++ ...uino-usbserial-atmega16u2-MegaADK-Rev3.hex | 254 +++++++ .../Arduino-usbserial-atmega16u2-Uno-Rev3.hex | 254 +++++++ .../KeyboardioHID/Firmwares/Hoodloader.hex | 473 +++++++++++++ plugins/KeyboardioHID/Flip_1.PNG | Bin 0 -> 74947 bytes plugins/KeyboardioHID/Flip_2.PNG | Bin 0 -> 92225 bytes plugins/KeyboardioHID/Flip_3.PNG | Bin 0 -> 74966 bytes plugins/KeyboardioHID/HID.cpp | 516 +++++++++++++++ plugins/KeyboardioHID/HID.h | 296 +++++++++ plugins/KeyboardioHID/HID_Reports.h | 207 ++++++ plugins/KeyboardioHID/Hoodloader/Board/LEDs.h | 110 ++++ .../Hoodloader/Config/LUFAConfig.h | 126 ++++ .../KeyboardioHID/Hoodloader/Descriptors.c | 619 ++++++++++++++++++ .../KeyboardioHID/Hoodloader/Descriptors.h | 121 ++++ plugins/KeyboardioHID/Hoodloader/Hoodloader.c | 555 ++++++++++++++++ plugins/KeyboardioHID/Hoodloader/Hoodloader.h | 111 ++++ .../KeyboardioHID/Hoodloader/Hoodloader.inf | 66 ++ .../Hoodloader/Lib/LightweightRingBuff.h | 197 ++++++ plugins/KeyboardioHID/Hoodloader/makefile | 52 ++ plugins/KeyboardioHID/IMG_5687.JPG | Bin 0 -> 73455 bytes plugins/KeyboardioHID/IMG_5688.JPG | Bin 0 -> 74968 bytes plugins/KeyboardioHID/Readme.md | 164 +++++ .../examples/AdvancedHID/AdvancedHID.ino | 125 ++++ .../examples/Gamepad/Gamepad.ino | 91 +++ .../examples/Joystick/Joystick.ino | 77 +++ .../examples/Keyboard/Keyboard.ino | 105 +++ .../KeyboardioHID/examples/Media/Media.ino | 74 +++ .../KeyboardioHID/examples/Mouse/Mouse.ino | 61 ++ .../KeyboardioHID/examples/System/System.ino | 62 ++ plugins/KeyboardioHID/keywords.txt | 174 +++++ 30 files changed, 5144 insertions(+) create mode 100644 plugins/KeyboardioHID/Firmwares/Arduino-usbserial-atmega16u2-Mega2560-Rev3.hex create mode 100644 plugins/KeyboardioHID/Firmwares/Arduino-usbserial-atmega16u2-MegaADK-Rev3.hex create mode 100644 plugins/KeyboardioHID/Firmwares/Arduino-usbserial-atmega16u2-Uno-Rev3.hex create mode 100644 plugins/KeyboardioHID/Firmwares/Hoodloader.hex create mode 100644 plugins/KeyboardioHID/Flip_1.PNG create mode 100644 plugins/KeyboardioHID/Flip_2.PNG create mode 100644 plugins/KeyboardioHID/Flip_3.PNG create mode 100644 plugins/KeyboardioHID/HID.cpp create mode 100644 plugins/KeyboardioHID/HID.h create mode 100644 plugins/KeyboardioHID/HID_Reports.h create mode 100644 plugins/KeyboardioHID/Hoodloader/Board/LEDs.h create mode 100644 plugins/KeyboardioHID/Hoodloader/Config/LUFAConfig.h create mode 100644 plugins/KeyboardioHID/Hoodloader/Descriptors.c create mode 100644 plugins/KeyboardioHID/Hoodloader/Descriptors.h create mode 100644 plugins/KeyboardioHID/Hoodloader/Hoodloader.c create mode 100644 plugins/KeyboardioHID/Hoodloader/Hoodloader.h create mode 100644 plugins/KeyboardioHID/Hoodloader/Hoodloader.inf create mode 100644 plugins/KeyboardioHID/Hoodloader/Lib/LightweightRingBuff.h create mode 100644 plugins/KeyboardioHID/Hoodloader/makefile create mode 100644 plugins/KeyboardioHID/IMG_5687.JPG create mode 100644 plugins/KeyboardioHID/IMG_5688.JPG create mode 100644 plugins/KeyboardioHID/Readme.md create mode 100644 plugins/KeyboardioHID/examples/AdvancedHID/AdvancedHID.ino create mode 100644 plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino create mode 100644 plugins/KeyboardioHID/examples/Joystick/Joystick.ino create mode 100644 plugins/KeyboardioHID/examples/Keyboard/Keyboard.ino create mode 100644 plugins/KeyboardioHID/examples/Media/Media.ino create mode 100644 plugins/KeyboardioHID/examples/Mouse/Mouse.ino create mode 100644 plugins/KeyboardioHID/examples/System/System.ino create mode 100644 plugins/KeyboardioHID/keywords.txt diff --git a/plugins/KeyboardioHID/Firmwares/Arduino-usbserial-atmega16u2-Mega2560-Rev3.hex b/plugins/KeyboardioHID/Firmwares/Arduino-usbserial-atmega16u2-Mega2560-Rev3.hex new file mode 100644 index 0000000000..6ff3644796 --- /dev/null +++ b/plugins/KeyboardioHID/Firmwares/Arduino-usbserial-atmega16u2-Mega2560-Rev3.hex @@ -0,0 +1,254 @@ +:1000000090C00000A9C00000A7C00000A5C000006B +:10001000A3C00000A1C000009FC000009DC0000060 +:100020009BC0000099C0000097C0000048C40000B9 +:100030000CC4000091C000008FC000008DC0000003 +:100040008BC0000089C0000087C0000085C0000090 +:1000500083C0000081C000007FC0000002C100001A +:100060007BC0000079C0000077C0000075C00000B0 +:1000700073C0000071C000006FC000006DC00000C0 +:100080006BC0000069C0000067C0000065C00000D0 +:1000900063C0000061C000001201100102000008EE +:1000A0004123420001000102DC0109023E0002017D +:1000B00000C0320904000001020201000524000111 +:1000C0001004240206052406000107058203080027 +:1000D000FF09040100020A000000070504024000B5 +:1000E00001070583024000010403090432034100B3 +:1000F00072006400750069006E006F002000280027 +:100100007700770077002E006100720064007500B0 +:1001100069006E006F002E0063006300290000007C +:10012000000011241FBECFEFD2E0DEBFCDBF11E033 +:10013000A0E0B1E0ECEAFFE002C005900D92A6312C +:10014000B107D9F712E0A6E1B1E001C01D92AF32CC +:10015000B107E1F7F1D028C753CF9C01DC01AE57BE +:10016000BF4FED91FC91119741911196FC93EE9345 +:1001700080589F4FE817F90711F42D933C939FB7D0 +:10018000F894F901EC57FF4F8081815080839FBF25 +:10019000842F0895DF92EF92FF920F931F93FC013B +:1001A0008489813019F0823021F405C040E3D42ED7 +:1001B00004C0DD2402C030E2D32E8389823011F4E2 +:1001C00088E0D82A8589873031F0883031F0863050 +:1001D00031F482E003C084E001C086E0D82A1092A6 +:1001E000C9001092C8001092CA00E784F088018903 +:1001F000128980E0E81681EEF80680E0080780E0CA +:10020000180719F420E130E00FC0C801B701969536 +:1002100087957795679560587B47814E9F4FA801DA +:100220009701A0D6215030403093CD002093CC00D0 +:10023000D092CA0080E0E81681EEF80680E0080758 +:1002400080E0180711F082E001C080E08093C800D0 +:1002500088E98093C9001F910F91FF90EF90DF9084 +:1002600008951F920F920FB60F9211242F938F9320 +:100270009F93EF93FF939091CE008EB38430F1F46F +:10028000E0919901F0919A019083E0919901F091A8 +:100290009A01CF01019690939A018093990189590F +:1002A000914021F489E191E0928381839FB7F89492 +:1002B00080919D018F5F80939D019FBFFF91EF9182 +:1002C0009F918F912F910F900FBE0F901F901895B7 +:1002D000FC01858580FF02C05F9808955F9A0895AC +:1002E00080E091E0D5C580E091E088C584B7877F44 +:1002F00084BF28E10FB6F89420936000109260004C +:100300000FBE87E690E09093CD008093CC0086E00E +:100310008093CA001092C8002093C900539A5A9A39 +:100320008AB180638AB98BB180638BB983D284E050 +:1003300085BD5F9A579A08950F931F93CF93DF93CC +:10034000D5DF2FB7F8948EE991E090931F02809348 +:100350001E0290932102809320022FBF2FB7F894A2 +:1003600089E191E090939A018093990190939C0187 +:1003700080939B012FBF7894CEE9D1E003E08FB743 +:10038000F894909122028FBF903809F180E091E0BB +:10039000ABD497FD1CC0E0911E02F0911F02808338 +:1003A000E0911E02F0911F02CF01019690931F026F +:1003B00080931E028E51924011F4D283C1839FB765 +:1003C000F894809122028F5F809322029FBF8FB7A3 +:1003D000F89410919D018FBFA89902C0113678F151 +:1003E000A89A80919D01882361F05D980093160181 +:1003F00008C089E191E0B1DE682F80E091E0DAD4B5 +:1004000011501123B1F780911601882351F080918A +:10041000160181508093160180911601882309F4FA +:100420005D9A80911701882351F0809117018150C6 +:100430008093170180911701882309F45C9A8FB784 +:10044000F894909122028FBF992369F08EE991E090 +:1004500084DE982F8091C80085FFFCCF9093CE005A +:100460005C980093170180E091E095D42AD487CF5F +:10047000DA01923049F0933061F09130F9F4E8E913 +:10048000F0E022E130E01EC0EAEAF0E02EE330E0E6 +:1004900019C0813049F0813018F0823079F408C0F9 +:1004A000E8EEF0E0849107C0ECEEF0E0849103C048 +:1004B000E0E2F1E08491282F30E004C0E0E0F0E0D9 +:1004C00020E030E0ED93FC93C901089528E030E08E +:1004D00040E003C04F5F220F331F28173907D0F3C6 +:1004E000842F8295807F08958093E9008091EB00AE +:1004F00081608093EB001092ED006093EC004093DC +:10050000ED008091EE00881F8827881F08951092C3 +:10051000F40090E09093E9001092F0001092E8004F +:100520001092ED008091EB008E7F8093EB009F5F37 +:10053000953081F708958091270288238CF403C0B9 +:100540008EB38823B1F08091E80082FFF9CF8091CB +:10055000E8008B778093E80008958EB3882349F0F4 +:100560008091E80080FFF9CF8091E8008E7780933A +:10057000E800089594E68091EC0080FF05C080912A +:10058000E80080FF05C023C08091E80082FD1FC005 +:100590008EB3882311F482E008958EB3853011F470 +:1005A00083E008958091EB0085FF02C081E008950B +:1005B0008091E10082FFDFCF8091E1008B7F80930B +:1005C000E100992311F484E008959150D4CF80E0A4 +:1005D00008959C0140912D0250912E024617570715 +:1005E00018F4F90120E038C06115710511F0AB0174 +:1005F000F8CF8091E8008E778093E80040E050E0EB +:10060000F0CF8091E80083FF02C081E008958091DF +:10061000E80082FD2DC08EB3882381F18EB3853032 +:1006200079F18091E80080FF17C09091F20006C038 +:1006300081918093F100415050409F5F41155105D9 +:1006400011F09830A8F320E0983009F421E080916F +:10065000E8008E778093E8004115510591F622233A +:1006600081F606C08EB3882349F08EB3853041F001 +:100670008091E80082FFF6CF80E0089582E008953F +:1006800083E008959C0140912D0250912E0246175F +:10069000570710F490E03BC06115710511F0AB01F4 +:1006A000F9CF8091E8008E778093E80040E050E039 +:1006B000F1CF8091E80083FF02C081E0089580912E +:1006C000E80082FD30C08EB3882399F18EB3853067 +:1006D00091F18091E80080FF1AC08091F20009C07A +:1006E000F9012F5F3F4FE491E093F10041505040FA +:1006F0008F5F4115510511F0883090F390E08830FC +:1007000009F491E08091E8008E778093E80041152C +:10071000510579F6992369F606C08EB3882349F00E +:100720008EB3853041F08091E80082FFF6CF80E003 +:10073000089582E0089583E008959C016115710594 +:1007400029F48091E8008B778093E800F90120C0BC +:100750008091E80083FF02C081E008958EB3882372 +:1007600039F18EB3853031F18091E80082FFF0CF0E +:1007700006C08091F10081936150704021F080911A +:10078000F2008823B1F78091E8008B778093E8002E +:1007900061157105E9F606C08EB3882349F08EB362 +:1007A000853041F08091E80080FFF6CF80E0089529 +:1007B00082E0089583E0089542D044D01EBA10929A +:1007C0002502109224021092230284E089BD89B58B +:1007D000826089BD09B400FEFDCF8091D800982FBA +:1007E0009F779093D80080688093D80080916300B1 +:1007F0008E7F809363008091D8008F7D8093D80096 +:100800008091E0008E7F8093E0008091E1008E7FF8 +:100810008093E1008091E20081608093E20080910A +:10082000E100877F8093E1008091E20088608093FF +:10083000E2000895C1DF81E08093260208951092BE +:10084000E20008951092E10008951F920F920FB6F2 +:100850000F9211241F932F933F934F935F936F93A6 +:100860007F938F939F93AF93BF93EF93FF93E9EEA3 +:10087000F0E0108117701082E0EFF0E08081877F58 +:1008800080837894C3D0F894A9EEB0E01C92E0EF96 +:10089000F0E08081886080831C93FF91EF91BF918D +:1008A000AF919F918F917F916F915F914F913F9108 +:1008B0002F911F910F900FBE0F901F9018951F92B0 +:1008C0000F920FB60F9211242F933F934F935F9384 +:1008D0006F937F938F939F93AF93BF93EF93FF9308 +:1008E0008091E10080FF1BC08091E20080FF17C073 +:1008F0008091E1008E7F8093E1008091E2008E7F05 +:100900008093E2008091E20080618093E200809118 +:10091000D80080628093D80019BC1EBAD1D18091D2 +:10092000E10084FF29C08091E20084FF25C084E0BB +:1009300089BD89B5826089BD09B400FEFDCF809173 +:10094000D8008F7D8093D8008091E1008F7E8093C6 +:10095000E1008091E2008F7E8093E2008091E200CE +:1009600081608093E20080912502882311F481E068 +:1009700001C084E08EBBA4D18091E10083FF27C039 +:100980008091E20083FF23C08091E100877F809304 +:10099000E10082E08EBB109225028091E1008E7F03 +:1009A0008093E1008091E2008E7F8093E20080914D +:1009B000E20080618093E200AADD80E060E042E036 +:1009C00093DD8091F00088608093F00079D1809170 +:1009D000E10082FF0AC08091E20082FF06C08091A0 +:1009E000E1008B7F8093E1006BD1FF91EF91BF918C +:1009F000AF919F918F917F916F915F914F913F91B7 +:100A00002F910F900FBE0F901F9018951F93DF939B +:100A1000CF93CDB7DEB7AC970FB6F894DEBF0FBE5D +:100A2000CDBFE7E2F2E08091F100819322E0EF3266 +:100A3000F207C9F78091270230912802353009F476 +:100A400087C0363040F43130C9F1313070F0333086 +:100A500009F01DC133C0383009F4EFC0393009F452 +:100A6000FEC0363009F013C192C0803821F08238C0 +:100A700009F00DC108C090912302809124028823BF +:100A800099F0926011C080912B0287708093E900E9 +:100A90008091EB0090E025E0969587952A95E1F707 +:100AA000982F91701092E9008091E800877F8093E1 +:100AB000E8009093F1001092F100CAC0882319F069 +:100AC000823009F0E4C090E08F719070009721F0BF +:100AD000029709F0DDC00CC080912902813009F035 +:100AE000D7C010922402333069F5809324022AC0C3 +:100AF00080912902882331F520912B02277009F477 +:100B0000C7C02093E9008091EB0080FFC1C0333063 +:100B100021F48091EB00806213C08091EB00806132 +:100B20008093EB0081E090E002C0880F991F2A9526 +:100B3000E2F78093EA001092EA008091EB0088606F +:100B40008093EB001092E9008091E800877F83C0DA +:100B5000882309F09CC0109129028091E800877FCA +:100B60008093E800E8DC04C08EB3882309F490C0C9 +:100B70008091E80080FFF8CF812F8F7711F492E009 +:100B800001C093E09EBB80688093E30081C08058E1 +:100B9000823008F07CC08091290290912A0223E0E3 +:100BA0008C3D920799F55FB7F894DE0115964EE0FB +:100BB00020E030E061E2E42FF0E0609357008491A0 +:100BC00020FF03C082958F704F5F982F9F70892FF1 +:100BD000805D8A3308F0895F8C9311961C9211977F +:100BE0002F5F3F4F12962431310529F75FBF8AE20C +:100BF0008B8383E08C838091E800877F8093E8007B +:100C0000CE0103966AE270E0E4DC11C060912B0231 +:100C1000AE014F5F5F4F2CDCBC010097C9F18091A2 +:100C2000E800877F8093E80089819A812BDD80919D +:100C3000E8008B778093E8002BC0803841F58091E5 +:100C4000E800877F8093E800809125028093F1007F +:100C50008091E8008E778093E8006DDC19C08823CE +:100C6000B1F490912902923098F48091E800877F46 +:100C70008093E800909325025EDC80912502882312 +:100C800011F483E001C084E08EBB2DDB01C028DBC2 +:100C90008091E80083FF0AC08091EB00806280931E +:100CA000EB008091E800877F8093E800AC960FB658 +:100CB000F894DEBF0FBECDBFCF91DF911F91089595 +:100CC00008951F938EB3882361F01091E90010926C +:100CD000E9008091E80083FF01C098DE177010934F +:100CE000E9001F9108950895FC018EB3843021F529 +:100CF00087859089A189B2890097A105B105E1F0A6 +:100D000085818093E9008091E80082FF15C0809181 +:100D1000F200882319F42FEF3FEF04C08091F10017 +:100D2000282F30E08091F200882341F48091E80080 +:100D30008B778093E80002C02FEF3FEFC901089541 +:100D4000FC018EB3843011F587859089A189B28921 +:100D50000097A105B105D1F081818093E9008091D0 +:100D6000F2008823A9F09091E8008091E8008E7746 +:100D70008093E80095FD0CC0FDDB982F882349F493 +:100D80008091E8008E778093E80003C092E001C074 +:100D900090E0892F0895FC018EB3843051F487854B +:100DA0009089A189B2890097A105B10511F0CF0101 +:100DB000C7CF08951F93FC01162F8EB38430D9F44A +:100DC00087859089A189B2890097A105B10599F01D +:100DD00081818093E9008091E80085FD08C08091C1 +:100DE000E8008E778093E800C5DB882329F4109310 +:100DF000F10080E001C082E01F9108950F931F93DE +:100E0000CF93DF93EC010D96FC0189E0DF011D9289 +:100E10008A95E9F72A813B8109818C81882311F425 +:100E200010E001C014E0C90151DB182B1260802FC3 +:100E300061E8412F59DB882329F12E813F810D8103 +:100E40008885882311F410E001C014E0C9013EDB5D +:100E5000182B1260802F60E8412F46DB882391F029 +:100E60002A853B8509858C85882311F410E001C013 +:100E700014E0C9012BDB182B1260802F61EC412F8D +:100E800033DB01C080E0DF91CF911F910F91089576 +:100E9000CF93DF93EC018091E80083FF60C08881ED +:100EA00090E020912B0230912C022817390709F08D +:100EB00056C080912802813261F0823220F4803263 +:100EC00009F04DC019C0823269F1833209F047C080 +:100ED00038C080912702813A09F041C08091E80032 +:100EE000877F8093E800CE010F9667E070E071DBAA +:100EF0008091E8008B7713C080912702813279F5C9 +:100F00008091E800877F8093E800CE010F9667E02C +:100F100070E013DCCE013ED98091E8008E7780939B +:100F2000E8001DC0809127028132C9F48091E80059 +:100F3000877F8093E800809129028D87CE01C8D9F0 +:100F40000DC080912702813251F48091E800877FA3 +:100F50008093E800CE0160912902C5DEECDADF91D2 +:100F6000CF910895A1E21A2EAA1BBB1BFD010DC053 +:100F7000AA1FBB1FEE1FFF1FA217B307E407F50749 +:100F800020F0A21BB30BE40BF50B661F771F881F25 +:100F9000991F1A9469F760957095809590959B01BB +:0C0FA000AC01BD01CF010895F894FFCF13 +:100FAC0000034000000440000002080000000000A4 +:060FBC000000000000002F +:00000001FF diff --git a/plugins/KeyboardioHID/Firmwares/Arduino-usbserial-atmega16u2-MegaADK-Rev3.hex b/plugins/KeyboardioHID/Firmwares/Arduino-usbserial-atmega16u2-MegaADK-Rev3.hex new file mode 100644 index 0000000000..1ca40e2e57 --- /dev/null +++ b/plugins/KeyboardioHID/Firmwares/Arduino-usbserial-atmega16u2-MegaADK-Rev3.hex @@ -0,0 +1,254 @@ +:1000000090C00000A9C00000A7C00000A5C000006B +:10001000A3C00000A1C000009FC000009DC0000060 +:100020009BC0000099C0000097C0000048C40000B9 +:100030000CC4000091C000008FC000008DC0000003 +:100040008BC0000089C0000087C0000085C0000090 +:1000500083C0000081C000007FC0000002C100001A +:100060007BC0000079C0000077C0000075C00000B0 +:1000700073C0000071C000006FC000006DC00000C0 +:100080006BC0000069C0000067C0000065C00000D0 +:1000900063C0000061C000001201100102000008EE +:1000A0004123440001000102DC0109023E0002017B +:1000B00000C0320904000001020201000524000111 +:1000C0001004240206052406000107058203080027 +:1000D000FF09040100020A000000070504024000B5 +:1000E00001070583024000010403090432034100B3 +:1000F00072006400750069006E006F002000280027 +:100100007700770077002E006100720064007500B0 +:1001100069006E006F002E0063006300290000007C +:10012000000011241FBECFEFD2E0DEBFCDBF11E033 +:10013000A0E0B1E0ECEAFFE002C005900D92A6312C +:10014000B107D9F712E0A6E1B1E001C01D92AF32CC +:10015000B107E1F7F1D028C753CF9C01DC01AE57BE +:10016000BF4FED91FC91119741911196FC93EE9345 +:1001700080589F4FE817F90711F42D933C939FB7D0 +:10018000F894F901EC57FF4F8081815080839FBF25 +:10019000842F0895DF92EF92FF920F931F93FC013B +:1001A0008489813019F0823021F405C040E3D42ED7 +:1001B00004C0DD2402C030E2D32E8389823011F4E2 +:1001C00088E0D82A8589873031F0883031F0863050 +:1001D00031F482E003C084E001C086E0D82A1092A6 +:1001E000C9001092C8001092CA00E784F088018903 +:1001F000128980E0E81681EEF80680E0080780E0CA +:10020000180719F420E130E00FC0C801B701969536 +:1002100087957795679560587B47814E9F4FA801DA +:100220009701A0D6215030403093CD002093CC00D0 +:10023000D092CA0080E0E81681EEF80680E0080758 +:1002400080E0180711F082E001C080E08093C800D0 +:1002500088E98093C9001F910F91FF90EF90DF9084 +:1002600008951F920F920FB60F9211242F938F9320 +:100270009F93EF93FF939091CE008EB38430F1F46F +:10028000E0919901F0919A019083E0919901F091A8 +:100290009A01CF01019690939A018093990189590F +:1002A000914021F489E191E0928381839FB7F89492 +:1002B00080919D018F5F80939D019FBFFF91EF9182 +:1002C0009F918F912F910F900FBE0F901F901895B7 +:1002D000FC01858580FF02C05F9808955F9A0895AC +:1002E00080E091E0D5C580E091E088C584B7877F44 +:1002F00084BF28E10FB6F89420936000109260004C +:100300000FBE87E690E09093CD008093CC0086E00E +:100310008093CA001092C8002093C900539A5A9A39 +:100320008AB180638AB98BB180638BB983D284E050 +:1003300085BD5F9A579A08950F931F93CF93DF93CC +:10034000D5DF2FB7F8948EE991E090931F02809348 +:100350001E0290932102809320022FBF2FB7F894A2 +:1003600089E191E090939A018093990190939C0187 +:1003700080939B012FBF7894CEE9D1E003E08FB743 +:10038000F894909122028FBF903809F180E091E0BB +:10039000ABD497FD1CC0E0911E02F0911F02808338 +:1003A000E0911E02F0911F02CF01019690931F026F +:1003B00080931E028E51924011F4D283C1839FB765 +:1003C000F894809122028F5F809322029FBF8FB7A3 +:1003D000F89410919D018FBFA89902C0113678F151 +:1003E000A89A80919D01882361F05D980093160181 +:1003F00008C089E191E0B1DE682F80E091E0DAD4B5 +:1004000011501123B1F780911601882351F080918A +:10041000160181508093160180911601882309F4FA +:100420005D9A80911701882351F0809117018150C6 +:100430008093170180911701882309F45C9A8FB784 +:10044000F894909122028FBF992369F08EE991E090 +:1004500084DE982F8091C80085FFFCCF9093CE005A +:100460005C980093170180E091E095D42AD487CF5F +:10047000DA01923049F0933061F09130F9F4E8E913 +:10048000F0E022E130E01EC0EAEAF0E02EE330E0E6 +:1004900019C0813049F0813018F0823079F408C0F9 +:1004A000E8EEF0E0849107C0ECEEF0E0849103C048 +:1004B000E0E2F1E08491282F30E004C0E0E0F0E0D9 +:1004C00020E030E0ED93FC93C901089528E030E08E +:1004D00040E003C04F5F220F331F28173907D0F3C6 +:1004E000842F8295807F08958093E9008091EB00AE +:1004F00081608093EB001092ED006093EC004093DC +:10050000ED008091EE00881F8827881F08951092C3 +:10051000F40090E09093E9001092F0001092E8004F +:100520001092ED008091EB008E7F8093EB009F5F37 +:10053000953081F708958091270288238CF403C0B9 +:100540008EB38823B1F08091E80082FFF9CF8091CB +:10055000E8008B778093E80008958EB3882349F0F4 +:100560008091E80080FFF9CF8091E8008E7780933A +:10057000E800089594E68091EC0080FF05C080912A +:10058000E80080FF05C023C08091E80082FD1FC005 +:100590008EB3882311F482E008958EB3853011F470 +:1005A00083E008958091EB0085FF02C081E008950B +:1005B0008091E10082FFDFCF8091E1008B7F80930B +:1005C000E100992311F484E008959150D4CF80E0A4 +:1005D00008959C0140912D0250912E024617570715 +:1005E00018F4F90120E038C06115710511F0AB0174 +:1005F000F8CF8091E8008E778093E80040E050E0EB +:10060000F0CF8091E80083FF02C081E008958091DF +:10061000E80082FD2DC08EB3882381F18EB3853032 +:1006200079F18091E80080FF17C09091F20006C038 +:1006300081918093F100415050409F5F41155105D9 +:1006400011F09830A8F320E0983009F421E080916F +:10065000E8008E778093E8004115510591F622233A +:1006600081F606C08EB3882349F08EB3853041F001 +:100670008091E80082FFF6CF80E0089582E008953F +:1006800083E008959C0140912D0250912E0246175F +:10069000570710F490E03BC06115710511F0AB01F4 +:1006A000F9CF8091E8008E778093E80040E050E039 +:1006B000F1CF8091E80083FF02C081E0089580912E +:1006C000E80082FD30C08EB3882399F18EB3853067 +:1006D00091F18091E80080FF1AC08091F20009C07A +:1006E000F9012F5F3F4FE491E093F10041505040FA +:1006F0008F5F4115510511F0883090F390E08830FC +:1007000009F491E08091E8008E778093E80041152C +:10071000510579F6992369F606C08EB3882349F00E +:100720008EB3853041F08091E80082FFF6CF80E003 +:10073000089582E0089583E008959C016115710594 +:1007400029F48091E8008B778093E800F90120C0BC +:100750008091E80083FF02C081E008958EB3882372 +:1007600039F18EB3853031F18091E80082FFF0CF0E +:1007700006C08091F10081936150704021F080911A +:10078000F2008823B1F78091E8008B778093E8002E +:1007900061157105E9F606C08EB3882349F08EB362 +:1007A000853041F08091E80080FFF6CF80E0089529 +:1007B00082E0089583E0089542D044D01EBA10929A +:1007C0002502109224021092230284E089BD89B58B +:1007D000826089BD09B400FEFDCF8091D800982FBA +:1007E0009F779093D80080688093D80080916300B1 +:1007F0008E7F809363008091D8008F7D8093D80096 +:100800008091E0008E7F8093E0008091E1008E7FF8 +:100810008093E1008091E20081608093E20080910A +:10082000E100877F8093E1008091E20088608093FF +:10083000E2000895C1DF81E08093260208951092BE +:10084000E20008951092E10008951F920F920FB6F2 +:100850000F9211241F932F933F934F935F936F93A6 +:100860007F938F939F93AF93BF93EF93FF93E9EEA3 +:10087000F0E0108117701082E0EFF0E08081877F58 +:1008800080837894C3D0F894A9EEB0E01C92E0EF96 +:10089000F0E08081886080831C93FF91EF91BF918D +:1008A000AF919F918F917F916F915F914F913F9108 +:1008B0002F911F910F900FBE0F901F9018951F92B0 +:1008C0000F920FB60F9211242F933F934F935F9384 +:1008D0006F937F938F939F93AF93BF93EF93FF9308 +:1008E0008091E10080FF1BC08091E20080FF17C073 +:1008F0008091E1008E7F8093E1008091E2008E7F05 +:100900008093E2008091E20080618093E200809118 +:10091000D80080628093D80019BC1EBAD1D18091D2 +:10092000E10084FF29C08091E20084FF25C084E0BB +:1009300089BD89B5826089BD09B400FEFDCF809173 +:10094000D8008F7D8093D8008091E1008F7E8093C6 +:10095000E1008091E2008F7E8093E2008091E200CE +:1009600081608093E20080912502882311F481E068 +:1009700001C084E08EBBA4D18091E10083FF27C039 +:100980008091E20083FF23C08091E100877F809304 +:10099000E10082E08EBB109225028091E1008E7F03 +:1009A0008093E1008091E2008E7F8093E20080914D +:1009B000E20080618093E200AADD80E060E042E036 +:1009C00093DD8091F00088608093F00079D1809170 +:1009D000E10082FF0AC08091E20082FF06C08091A0 +:1009E000E1008B7F8093E1006BD1FF91EF91BF918C +:1009F000AF919F918F917F916F915F914F913F91B7 +:100A00002F910F900FBE0F901F9018951F93DF939B +:100A1000CF93CDB7DEB7AC970FB6F894DEBF0FBE5D +:100A2000CDBFE7E2F2E08091F100819322E0EF3266 +:100A3000F207C9F78091270230912802353009F476 +:100A400087C0363040F43130C9F1313070F0333086 +:100A500009F01DC133C0383009F4EFC0393009F452 +:100A6000FEC0363009F013C192C0803821F08238C0 +:100A700009F00DC108C090912302809124028823BF +:100A800099F0926011C080912B0287708093E900E9 +:100A90008091EB0090E025E0969587952A95E1F707 +:100AA000982F91701092E9008091E800877F8093E1 +:100AB000E8009093F1001092F100CAC0882319F069 +:100AC000823009F0E4C090E08F719070009721F0BF +:100AD000029709F0DDC00CC080912902813009F035 +:100AE000D7C010922402333069F5809324022AC0C3 +:100AF00080912902882331F520912B02277009F477 +:100B0000C7C02093E9008091EB0080FFC1C0333063 +:100B100021F48091EB00806213C08091EB00806132 +:100B20008093EB0081E090E002C0880F991F2A9526 +:100B3000E2F78093EA001092EA008091EB0088606F +:100B40008093EB001092E9008091E800877F83C0DA +:100B5000882309F09CC0109129028091E800877FCA +:100B60008093E800E8DC04C08EB3882309F490C0C9 +:100B70008091E80080FFF8CF812F8F7711F492E009 +:100B800001C093E09EBB80688093E30081C08058E1 +:100B9000823008F07CC08091290290912A0223E0E3 +:100BA0008C3D920799F55FB7F894DE0115964EE0FB +:100BB00020E030E061E2E42FF0E0609357008491A0 +:100BC00020FF03C082958F704F5F982F9F70892FF1 +:100BD000805D8A3308F0895F8C9311961C9211977F +:100BE0002F5F3F4F12962431310529F75FBF8AE20C +:100BF0008B8383E08C838091E800877F8093E8007B +:100C0000CE0103966AE270E0E4DC11C060912B0231 +:100C1000AE014F5F5F4F2CDCBC010097C9F18091A2 +:100C2000E800877F8093E80089819A812BDD80919D +:100C3000E8008B778093E8002BC0803841F58091E5 +:100C4000E800877F8093E800809125028093F1007F +:100C50008091E8008E778093E8006DDC19C08823CE +:100C6000B1F490912902923098F48091E800877F46 +:100C70008093E800909325025EDC80912502882312 +:100C800011F483E001C084E08EBB2DDB01C028DBC2 +:100C90008091E80083FF0AC08091EB00806280931E +:100CA000EB008091E800877F8093E800AC960FB658 +:100CB000F894DEBF0FBECDBFCF91DF911F91089595 +:100CC00008951F938EB3882361F01091E90010926C +:100CD000E9008091E80083FF01C098DE177010934F +:100CE000E9001F9108950895FC018EB3843021F529 +:100CF00087859089A189B2890097A105B105E1F0A6 +:100D000085818093E9008091E80082FF15C0809181 +:100D1000F200882319F42FEF3FEF04C08091F10017 +:100D2000282F30E08091F200882341F48091E80080 +:100D30008B778093E80002C02FEF3FEFC901089541 +:100D4000FC018EB3843011F587859089A189B28921 +:100D50000097A105B105D1F081818093E9008091D0 +:100D6000F2008823A9F09091E8008091E8008E7746 +:100D70008093E80095FD0CC0FDDB982F882349F493 +:100D80008091E8008E778093E80003C092E001C074 +:100D900090E0892F0895FC018EB3843051F487854B +:100DA0009089A189B2890097A105B10511F0CF0101 +:100DB000C7CF08951F93FC01162F8EB38430D9F44A +:100DC00087859089A189B2890097A105B10599F01D +:100DD00081818093E9008091E80085FD08C08091C1 +:100DE000E8008E778093E800C5DB882329F4109310 +:100DF000F10080E001C082E01F9108950F931F93DE +:100E0000CF93DF93EC010D96FC0189E0DF011D9289 +:100E10008A95E9F72A813B8109818C81882311F425 +:100E200010E001C014E0C90151DB182B1260802FC3 +:100E300061E8412F59DB882329F12E813F810D8103 +:100E40008885882311F410E001C014E0C9013EDB5D +:100E5000182B1260802F60E8412F46DB882391F029 +:100E60002A853B8509858C85882311F410E001C013 +:100E700014E0C9012BDB182B1260802F61EC412F8D +:100E800033DB01C080E0DF91CF911F910F91089576 +:100E9000CF93DF93EC018091E80083FF60C08881ED +:100EA00090E020912B0230912C022817390709F08D +:100EB00056C080912802813261F0823220F4803263 +:100EC00009F04DC019C0823269F1833209F047C080 +:100ED00038C080912702813A09F041C08091E80032 +:100EE000877F8093E800CE010F9667E070E071DBAA +:100EF0008091E8008B7713C080912702813279F5C9 +:100F00008091E800877F8093E800CE010F9667E02C +:100F100070E013DCCE013ED98091E8008E7780939B +:100F2000E8001DC0809127028132C9F48091E80059 +:100F3000877F8093E800809129028D87CE01C8D9F0 +:100F40000DC080912702813251F48091E800877FA3 +:100F50008093E800CE0160912902C5DEECDADF91D2 +:100F6000CF910895A1E21A2EAA1BBB1BFD010DC053 +:100F7000AA1FBB1FEE1FFF1FA217B307E407F50749 +:100F800020F0A21BB30BE40BF50B661F771F881F25 +:100F9000991F1A9469F760957095809590959B01BB +:0C0FA000AC01BD01CF010895F894FFCF13 +:100FAC0000034000000440000002080000000000A4 +:060FBC000000000000002F +:00000001FF diff --git a/plugins/KeyboardioHID/Firmwares/Arduino-usbserial-atmega16u2-Uno-Rev3.hex b/plugins/KeyboardioHID/Firmwares/Arduino-usbserial-atmega16u2-Uno-Rev3.hex new file mode 100644 index 0000000000..711fabfb2d --- /dev/null +++ b/plugins/KeyboardioHID/Firmwares/Arduino-usbserial-atmega16u2-Uno-Rev3.hex @@ -0,0 +1,254 @@ +:1000000090C00000A9C00000A7C00000A5C000006B +:10001000A3C00000A1C000009FC000009DC0000060 +:100020009BC0000099C0000097C0000048C40000B9 +:100030000CC4000091C000008FC000008DC0000003 +:100040008BC0000089C0000087C0000085C0000090 +:1000500083C0000081C000007FC0000002C100001A +:100060007BC0000079C0000077C0000075C00000B0 +:1000700073C0000071C000006FC000006DC00000C0 +:100080006BC0000069C0000067C0000065C00000D0 +:1000900063C0000061C000001201100102000008EE +:1000A0004123430001000102DC0109023E0002017C +:1000B00000C0320904000001020201000524000111 +:1000C0001004240206052406000107058203080027 +:1000D000FF09040100020A000000070504024000B5 +:1000E00001070583024000010403090432034100B3 +:1000F00072006400750069006E006F002000280027 +:100100007700770077002E006100720064007500B0 +:1001100069006E006F002E0063006300290000007C +:10012000000011241FBECFEFD2E0DEBFCDBF11E033 +:10013000A0E0B1E0ECEAFFE002C005900D92A6312C +:10014000B107D9F712E0A6E1B1E001C01D92AF32CC +:10015000B107E1F7F1D028C753CF9C01DC01AE57BE +:10016000BF4FED91FC91119741911196FC93EE9345 +:1001700080589F4FE817F90711F42D933C939FB7D0 +:10018000F894F901EC57FF4F8081815080839FBF25 +:10019000842F0895DF92EF92FF920F931F93FC013B +:1001A0008489813019F0823021F405C040E3D42ED7 +:1001B00004C0DD2402C030E2D32E8389823011F4E2 +:1001C00088E0D82A8589873031F0883031F0863050 +:1001D00031F482E003C084E001C086E0D82A1092A6 +:1001E000C9001092C8001092CA00E784F088018903 +:1001F000128980E0E81681EEF80680E0080780E0CA +:10020000180719F420E130E00FC0C801B701969536 +:1002100087957795679560587B47814E9F4FA801DA +:100220009701A0D6215030403093CD002093CC00D0 +:10023000D092CA0080E0E81681EEF80680E0080758 +:1002400080E0180711F082E001C080E08093C800D0 +:1002500088E98093C9001F910F91FF90EF90DF9084 +:1002600008951F920F920FB60F9211242F938F9320 +:100270009F93EF93FF939091CE008EB38430F1F46F +:10028000E0919901F0919A019083E0919901F091A8 +:100290009A01CF01019690939A018093990189590F +:1002A000914021F489E191E0928381839FB7F89492 +:1002B00080919D018F5F80939D019FBFFF91EF9182 +:1002C0009F918F912F910F900FBE0F901F901895B7 +:1002D000FC01858580FF02C05F9808955F9A0895AC +:1002E00080E091E0D5C580E091E088C584B7877F44 +:1002F00084BF28E10FB6F89420936000109260004C +:100300000FBE87E690E09093CD008093CC0086E00E +:100310008093CA001092C8002093C900539A5A9A39 +:100320008AB180638AB98BB180638BB983D284E050 +:1003300085BD5F9A579A08950F931F93CF93DF93CC +:10034000D5DF2FB7F8948EE991E090931F02809348 +:100350001E0290932102809320022FBF2FB7F894A2 +:1003600089E191E090939A018093990190939C0187 +:1003700080939B012FBF7894CEE9D1E003E08FB743 +:10038000F894909122028FBF903809F180E091E0BB +:10039000ABD497FD1CC0E0911E02F0911F02808338 +:1003A000E0911E02F0911F02CF01019690931F026F +:1003B00080931E028E51924011F4D283C1839FB765 +:1003C000F894809122028F5F809322029FBF8FB7A3 +:1003D000F89410919D018FBFA89902C0113678F151 +:1003E000A89A80919D01882361F05D980093160181 +:1003F00008C089E191E0B1DE682F80E091E0DAD4B5 +:1004000011501123B1F780911601882351F080918A +:10041000160181508093160180911601882309F4FA +:100420005D9A80911701882351F0809117018150C6 +:100430008093170180911701882309F45C9A8FB784 +:10044000F894909122028FBF992369F08EE991E090 +:1004500084DE982F8091C80085FFFCCF9093CE005A +:100460005C980093170180E091E095D42AD487CF5F +:10047000DA01923049F0933061F09130F9F4E8E913 +:10048000F0E022E130E01EC0EAEAF0E02EE330E0E6 +:1004900019C0813049F0813018F0823079F408C0F9 +:1004A000E8EEF0E0849107C0ECEEF0E0849103C048 +:1004B000E0E2F1E08491282F30E004C0E0E0F0E0D9 +:1004C00020E030E0ED93FC93C901089528E030E08E +:1004D00040E003C04F5F220F331F28173907D0F3C6 +:1004E000842F8295807F08958093E9008091EB00AE +:1004F00081608093EB001092ED006093EC004093DC +:10050000ED008091EE00881F8827881F08951092C3 +:10051000F40090E09093E9001092F0001092E8004F +:100520001092ED008091EB008E7F8093EB009F5F37 +:10053000953081F708958091270288238CF403C0B9 +:100540008EB38823B1F08091E80082FFF9CF8091CB +:10055000E8008B778093E80008958EB3882349F0F4 +:100560008091E80080FFF9CF8091E8008E7780933A +:10057000E800089594E68091EC0080FF05C080912A +:10058000E80080FF05C023C08091E80082FD1FC005 +:100590008EB3882311F482E008958EB3853011F470 +:1005A00083E008958091EB0085FF02C081E008950B +:1005B0008091E10082FFDFCF8091E1008B7F80930B +:1005C000E100992311F484E008959150D4CF80E0A4 +:1005D00008959C0140912D0250912E024617570715 +:1005E00018F4F90120E038C06115710511F0AB0174 +:1005F000F8CF8091E8008E778093E80040E050E0EB +:10060000F0CF8091E80083FF02C081E008958091DF +:10061000E80082FD2DC08EB3882381F18EB3853032 +:1006200079F18091E80080FF17C09091F20006C038 +:1006300081918093F100415050409F5F41155105D9 +:1006400011F09830A8F320E0983009F421E080916F +:10065000E8008E778093E8004115510591F622233A +:1006600081F606C08EB3882349F08EB3853041F001 +:100670008091E80082FFF6CF80E0089582E008953F +:1006800083E008959C0140912D0250912E0246175F +:10069000570710F490E03BC06115710511F0AB01F4 +:1006A000F9CF8091E8008E778093E80040E050E039 +:1006B000F1CF8091E80083FF02C081E0089580912E +:1006C000E80082FD30C08EB3882399F18EB3853067 +:1006D00091F18091E80080FF1AC08091F20009C07A +:1006E000F9012F5F3F4FE491E093F10041505040FA +:1006F0008F5F4115510511F0883090F390E08830FC +:1007000009F491E08091E8008E778093E80041152C +:10071000510579F6992369F606C08EB3882349F00E +:100720008EB3853041F08091E80082FFF6CF80E003 +:10073000089582E0089583E008959C016115710594 +:1007400029F48091E8008B778093E800F90120C0BC +:100750008091E80083FF02C081E008958EB3882372 +:1007600039F18EB3853031F18091E80082FFF0CF0E +:1007700006C08091F10081936150704021F080911A +:10078000F2008823B1F78091E8008B778093E8002E +:1007900061157105E9F606C08EB3882349F08EB362 +:1007A000853041F08091E80080FFF6CF80E0089529 +:1007B00082E0089583E0089542D044D01EBA10929A +:1007C0002502109224021092230284E089BD89B58B +:1007D000826089BD09B400FEFDCF8091D800982FBA +:1007E0009F779093D80080688093D80080916300B1 +:1007F0008E7F809363008091D8008F7D8093D80096 +:100800008091E0008E7F8093E0008091E1008E7FF8 +:100810008093E1008091E20081608093E20080910A +:10082000E100877F8093E1008091E20088608093FF +:10083000E2000895C1DF81E08093260208951092BE +:10084000E20008951092E10008951F920F920FB6F2 +:100850000F9211241F932F933F934F935F936F93A6 +:100860007F938F939F93AF93BF93EF93FF93E9EEA3 +:10087000F0E0108117701082E0EFF0E08081877F58 +:1008800080837894C3D0F894A9EEB0E01C92E0EF96 +:10089000F0E08081886080831C93FF91EF91BF918D +:1008A000AF919F918F917F916F915F914F913F9108 +:1008B0002F911F910F900FBE0F901F9018951F92B0 +:1008C0000F920FB60F9211242F933F934F935F9384 +:1008D0006F937F938F939F93AF93BF93EF93FF9308 +:1008E0008091E10080FF1BC08091E20080FF17C073 +:1008F0008091E1008E7F8093E1008091E2008E7F05 +:100900008093E2008091E20080618093E200809118 +:10091000D80080628093D80019BC1EBAD1D18091D2 +:10092000E10084FF29C08091E20084FF25C084E0BB +:1009300089BD89B5826089BD09B400FEFDCF809173 +:10094000D8008F7D8093D8008091E1008F7E8093C6 +:10095000E1008091E2008F7E8093E2008091E200CE +:1009600081608093E20080912502882311F481E068 +:1009700001C084E08EBBA4D18091E10083FF27C039 +:100980008091E20083FF23C08091E100877F809304 +:10099000E10082E08EBB109225028091E1008E7F03 +:1009A0008093E1008091E2008E7F8093E20080914D +:1009B000E20080618093E200AADD80E060E042E036 +:1009C00093DD8091F00088608093F00079D1809170 +:1009D000E10082FF0AC08091E20082FF06C08091A0 +:1009E000E1008B7F8093E1006BD1FF91EF91BF918C +:1009F000AF919F918F917F916F915F914F913F91B7 +:100A00002F910F900FBE0F901F9018951F93DF939B +:100A1000CF93CDB7DEB7AC970FB6F894DEBF0FBE5D +:100A2000CDBFE7E2F2E08091F100819322E0EF3266 +:100A3000F207C9F78091270230912802353009F476 +:100A400087C0363040F43130C9F1313070F0333086 +:100A500009F01DC133C0383009F4EFC0393009F452 +:100A6000FEC0363009F013C192C0803821F08238C0 +:100A700009F00DC108C090912302809124028823BF +:100A800099F0926011C080912B0287708093E900E9 +:100A90008091EB0090E025E0969587952A95E1F707 +:100AA000982F91701092E9008091E800877F8093E1 +:100AB000E8009093F1001092F100CAC0882319F069 +:100AC000823009F0E4C090E08F719070009721F0BF +:100AD000029709F0DDC00CC080912902813009F035 +:100AE000D7C010922402333069F5809324022AC0C3 +:100AF00080912902882331F520912B02277009F477 +:100B0000C7C02093E9008091EB0080FFC1C0333063 +:100B100021F48091EB00806213C08091EB00806132 +:100B20008093EB0081E090E002C0880F991F2A9526 +:100B3000E2F78093EA001092EA008091EB0088606F +:100B40008093EB001092E9008091E800877F83C0DA +:100B5000882309F09CC0109129028091E800877FCA +:100B60008093E800E8DC04C08EB3882309F490C0C9 +:100B70008091E80080FFF8CF812F8F7711F492E009 +:100B800001C093E09EBB80688093E30081C08058E1 +:100B9000823008F07CC08091290290912A0223E0E3 +:100BA0008C3D920799F55FB7F894DE0115964EE0FB +:100BB00020E030E061E2E42FF0E0609357008491A0 +:100BC00020FF03C082958F704F5F982F9F70892FF1 +:100BD000805D8A3308F0895F8C9311961C9211977F +:100BE0002F5F3F4F12962431310529F75FBF8AE20C +:100BF0008B8383E08C838091E800877F8093E8007B +:100C0000CE0103966AE270E0E4DC11C060912B0231 +:100C1000AE014F5F5F4F2CDCBC010097C9F18091A2 +:100C2000E800877F8093E80089819A812BDD80919D +:100C3000E8008B778093E8002BC0803841F58091E5 +:100C4000E800877F8093E800809125028093F1007F +:100C50008091E8008E778093E8006DDC19C08823CE +:100C6000B1F490912902923098F48091E800877F46 +:100C70008093E800909325025EDC80912502882312 +:100C800011F483E001C084E08EBB2DDB01C028DBC2 +:100C90008091E80083FF0AC08091EB00806280931E +:100CA000EB008091E800877F8093E800AC960FB658 +:100CB000F894DEBF0FBECDBFCF91DF911F91089595 +:100CC00008951F938EB3882361F01091E90010926C +:100CD000E9008091E80083FF01C098DE177010934F +:100CE000E9001F9108950895FC018EB3843021F529 +:100CF00087859089A189B2890097A105B105E1F0A6 +:100D000085818093E9008091E80082FF15C0809181 +:100D1000F200882319F42FEF3FEF04C08091F10017 +:100D2000282F30E08091F200882341F48091E80080 +:100D30008B778093E80002C02FEF3FEFC901089541 +:100D4000FC018EB3843011F587859089A189B28921 +:100D50000097A105B105D1F081818093E9008091D0 +:100D6000F2008823A9F09091E8008091E8008E7746 +:100D70008093E80095FD0CC0FDDB982F882349F493 +:100D80008091E8008E778093E80003C092E001C074 +:100D900090E0892F0895FC018EB3843051F487854B +:100DA0009089A189B2890097A105B10511F0CF0101 +:100DB000C7CF08951F93FC01162F8EB38430D9F44A +:100DC00087859089A189B2890097A105B10599F01D +:100DD00081818093E9008091E80085FD08C08091C1 +:100DE000E8008E778093E800C5DB882329F4109310 +:100DF000F10080E001C082E01F9108950F931F93DE +:100E0000CF93DF93EC010D96FC0189E0DF011D9289 +:100E10008A95E9F72A813B8109818C81882311F425 +:100E200010E001C014E0C90151DB182B1260802FC3 +:100E300061E8412F59DB882329F12E813F810D8103 +:100E40008885882311F410E001C014E0C9013EDB5D +:100E5000182B1260802F60E8412F46DB882391F029 +:100E60002A853B8509858C85882311F410E001C013 +:100E700014E0C9012BDB182B1260802F61EC412F8D +:100E800033DB01C080E0DF91CF911F910F91089576 +:100E9000CF93DF93EC018091E80083FF60C08881ED +:100EA00090E020912B0230912C022817390709F08D +:100EB00056C080912802813261F0823220F4803263 +:100EC00009F04DC019C0823269F1833209F047C080 +:100ED00038C080912702813A09F041C08091E80032 +:100EE000877F8093E800CE010F9667E070E071DBAA +:100EF0008091E8008B7713C080912702813279F5C9 +:100F00008091E800877F8093E800CE010F9667E02C +:100F100070E013DCCE013ED98091E8008E7780939B +:100F2000E8001DC0809127028132C9F48091E80059 +:100F3000877F8093E800809129028D87CE01C8D9F0 +:100F40000DC080912702813251F48091E800877FA3 +:100F50008093E800CE0160912902C5DEECDADF91D2 +:100F6000CF910895A1E21A2EAA1BBB1BFD010DC053 +:100F7000AA1FBB1FEE1FFF1FA217B307E407F50749 +:100F800020F0A21BB30BE40BF50B661F771F881F25 +:100F9000991F1A9469F760957095809590959B01BB +:0C0FA000AC01BD01CF010895F894FFCF13 +:100FAC0000034000000440000002080000000000A4 +:060FBC000000000000002F +:00000001FF diff --git a/plugins/KeyboardioHID/Firmwares/Hoodloader.hex b/plugins/KeyboardioHID/Firmwares/Hoodloader.hex new file mode 100644 index 0000000000..7ba766649e --- /dev/null +++ b/plugins/KeyboardioHID/Firmwares/Hoodloader.hex @@ -0,0 +1,473 @@ +:1000000073C100008DC100008BC1000089C10000D8 +:1000100087C1000085C1000083C1000081C10000CC +:100020007FC100007DC100007BC100000C947E08F0 +:100030000C94270975C1000073C1000071C1000054 +:100040006FC100006DC100006BC1000069C10000FC +:1000500067C1000065C1000063C10000BDC30000AE +:100060005FC100005DC100005BC1000059C100001C +:1000700057C1000030034100720064007500690040 +:100080006E006F00200048006F006F0064006C007D +:100090006F0061006400650072002000420065008E +:1000A00074006100000012034E00690063006F00DD +:1000B00048006F006F006400000004030904090297 +:1000C0005F00030100C032080B00020202010009B8 +:1000D00004000001020201000524001001042402B2 +:1000E000060524060001070582030800FF09040134 +:1000F00000020A0000000705040240000107058312 +:10010000024000010904020001030000000921115E +:1001100001000122B801070581032000011201102E +:1001200001EF020108EB03684E01000102DC01054A +:10013000010902A1010901A100850105091901298F +:10014000051500250195057501810295017503814D +:100150000305010930093109381581257F75089596 +:10016000038106C0C005010906A101850205071922 +:10017000E029E715002501750195088102950175B3 +:1001800008810395067508150025650507190029DE +:1001900065810005081901290595057501910295EC +:1001A0000175039103C006C0FF0A000CA10185037D +:1001B0007508150026FF0095400901810295400948 +:1001C000029102C0050C0901A1018504150026FF5A +:1001D000FF19002AFFFF950475108100C005010971 +:1001E00080A1018505150026FF00190029FF950152 +:1001F00075088100C005010905A1018506050919D9 +:10020000012920150025017501952081020501A114 +:10021000000930093109320933093409351500273D +:10022000FFFF0000751095068102C005010939091C +:100230003915012508950275048102C005010905DB +:10024000A10185070509190129201500250175015E +:10025000952081020501A1000930093109320933D5 +:1002600009340935150027FFFF0000751095068138 +:1002700002C0093909391501250895027504810262 +:10028000C005010904A1018508A10005091901297A +:100290000215002501750195028102050109300949 +:1002A00031150026FF03750A95028102750295013A +:1002B0008103C0C005010904A1018509A100050948 +:1002C0001901290215002501750195028102050118 +:1002D00009300931150026FF03750A950281027560 +:1002E0000295018103C0C00011241FBECFEFD2E0F0 +:1002F000DEBFCDBF11E0A0E0B1E0EEE4FDE102C061 +:1003000005900D92AE32B107D9F712E0AEE2B1E03E +:1003100001C01D92A738B107E1F70BD10C94A50ECF +:100320006FCECF93DF9384B7877F84BF28E10FB66A +:10033000F89420936000109260000FBE80E190E07E +:100340009093CD008093CC00CAECD0E096E09883E7 +:10035000A8ECB0E082E08C93E9ECF0E02083539AC3 +:100360005A9A5B9A10821C92188298838C9388E91F +:1003700080835B988AB180638AB98BB180638BB9C3 +:10038000AED684E085BD5F9A579A22982A9ADF916B +:10039000CF9108950F931F93CF93DF93C9E6D2E0D7 +:1003A000082F10E00AC08091200180FF05C06881FD +:1003B00080E191E00E940D0B2196CE01895692407A +:1003C0008017910784F3DF91CF911F910F910895CA +:1003D000CF93DF9360913B02662311F180913D0240 +:1003E000882319F010923B021BC070E0716081E01D +:1003F00013D4C2E6D2E00AC08091200180FF05C07C +:10040000688180E191E00E940D0B21969E012256A9 +:1004100032408091610290E0281739076CF3E2CFF7 +:10042000DF91CF9108951F93CF93DF9382D38823D9 +:1004300009F47BC01A9B79C09ED28130C9F5AAD23B +:1004400080FF36C0C5DFA3D280933B0210923D02ED +:1004500091E1EFE3F2E0DF01292F1D922A95E9F700 +:100460008530A9F038F4823081F0843071F0813029 +:10047000C9F405C0883088F08A30A0F411C094E037 +:1004800090933C0280933E020FC088E001C082E05E +:1004900080933C0210923E0207C090933C02FACF38 +:1004A00083E0F6CF10923B02DF91CF911F915FC2A4 +:1004B00080913B028823C9F15ED210913D02C12F89 +:1004C000D0E090E09E012E5F3F4F359527952F5F3E +:1004D0003F4F8217930729F55AD2C15CDD4F8883BD +:1004E000C12FCF5FC0933D0280913C028C1749F031 +:1004F00051D2EC2FF0E0E15CFD4F80831E5F109342 +:100500003D0290913C0280913D029813CDCF04C0F2 +:1005100080E091E00E94A20D80913B028111F8CF12 +:10052000C3CFDF91CF911F9153CFDF91CF911F9117 +:100530000895F7DE2FB7F89481E391E09093B2012C +:100540008093B1019093B4018093B3012FBF2FB773 +:10055000F89486EB91E09093370280933602909363 +:100560003902809338022FBF789410923D02109286 +:100570003B02239A219AC1E3D1E08C0153E0E52E9E +:100580009FB7F8948091B5019FBF803819F180E141 +:1005900091E00E94750B97FD1DC0E091B101F091B3 +:1005A000B20180838091B1019091B2010196909344 +:1005B000B2018093B101815B914021F4D093B201EB +:1005C000C093B1019FB7F8948091B5018F5F80937C +:1005D000B5019FBF8FB7F894F0903A028FBFA899EA +:1005E00004C080E68F1508F050C0A89A80913A02A6 +:1005F000882329F15D98E0922E0121C0CED1877F1A +:1006000021F0E6DE80916802C5DEE0913802F091CB +:1006100039028191F0933902E0933802E653F240B7 +:1006200021F410933902009338022FB7F894909177 +:100630003A02915090933A022FBFF5DEFA94F110EE +:10064000DDCF80912E018823A1F080912E01815071 +:1006500080932E0181110DC0BBDE9FD183FD07C0A9 +:10066000F09068029AD187FDF3948F2D93DE7FD1AD +:100670005D9A80912F01882341F080912F01815054 +:1006800080932F01811101C05C9A9FB7F8948091EB +:10069000B5019FBF882309F1E091B301F091B40146 +:1006A0009191F093B401E093B301E15BF14021F447 +:1006B000D093B401C093B3012FB7F8948091B501E2 +:1006C00081508093B5012FBF8091C80085FFFCCF7A +:1006D0009093CE005C98E0922F0180E191E0EFD7FB +:1006E0005BD74ECF08950895CF9380E091E00E94AC +:1006F0008D0DC82F80E191E06BD79091E20094605E +:100700009093E200882321F0CC2311F080E001C017 +:1007100080E39BB18095906389238BB9CF91089535 +:100720001F93CF93DF93EC01E98DE150E23028F481 +:10073000F0E0E45DFE4F108101C010E0888D823052 +:1007400009F418608A8D873031F0883031F08630B6 +:1007500029F4126003C0146001C016605B9A109205 +:10076000C9001092C8001092CA002C893D894E8998 +:100770005F89211581EE38074105510579F0CA01DD +:10078000B901969587957795679560587B47814E17 +:100790009F4F0E94660E2150310902C020E130E0D7 +:1007A0003093CD002093CC001093CA008C899D8992 +:1007B000AE89BF898115914EA105B10511F480E084 +:1007C00001C082E08093C80088E98093C9005B98EB +:1007D000DF91CF911F9108951F920F920FB60F9244 +:1007E00011242F938F939F93EF93FF938091CE00CB +:1007F00090917E029430F1F4E0913602F09137024C +:100800008083E0913602F0913702CF0101969093F8 +:100810003702809336028653924021F486EB91E0B2 +:10082000928381839FB7F89480913A028F5F80937F +:100830003A029FBFFF91EF919F918F912F910F905F +:100840000FBE0F901F901895FC01208920FF02C059 +:100850005F9808955F9A8BB180638BB9089580E1AA +:1008600091E071D780E091E00C94560C80910E01DC +:1008700090910F01009729F0019790930F018093B9 +:100880000E010895EF92FF920F931F93CF93DF9382 +:100890007B01C901E80110913C02EFE3F2E0412F36 +:1008A00050E0BF010E94950EEBE3F2E08081D7019A +:1008B0008C9318831982108280913E02DF91CF9130 +:1008C0001F910F91FF90EF9008950895292F3327DE +:1008D00023303105B1F04CF42130310509F439C031 +:1008E0002230310509F03AC007C02132310539F113 +:1008F0002232310549F132C0EFE5F0E08EEB90E0B5 +:1009000031C099278130910561F08230910581F0E5 +:10091000892B21F5EAEBF0E0E491F0E08AEB90E03E +:1009200021C0E6EAF0E0E491F0E086EA90E01AC047 +:10093000E4E7F0E0E491F0E084E790E013C0E9E060 +:10094000F0E08DE091E00EC0E8EBF1E08FE291E0A5 +:1009500009C0E2E1F0E08DE191E004C0E0E0F0E008 +:1009600080E090E0DA018D939C93CF01089588E0B8 +:1009700080932B0108958091700208956091710217 +:100980007091720280917302909174020895809127 +:100990007102089580917202089580912B0108954B +:1009A000982F80912B018823E9F083FF0AC01092D1 +:1009B00075021092760210927702109278021092CD +:1009C000790287FF0DC040916802E42FF0E0E759FB +:1009D000FD4F80818093690281E08093680202C0AC +:1009E0001092680210926F021092700210927102BF +:1009F00010927202109273021092740210922B01E4 +:100A000020916802E22FF0E0E759FD4F9083822F9A +:100A10008F5F80936802392F307C80917502303867 +:100A200009F440C0303C09F05EC0882329F080E919 +:100A300080932B0120936802292F287326952695F1 +:100A40002695223018F02730E1F40AC09F709F5F8E +:100A500090936F021092750280912B0185603DC0CA +:100A6000492F4F7050E060E070E040937602509361 +:100A70007702609378027093790285E08093750223 +:100A800056C0892F877090E0A0E0B0E08093760296 +:100A900090937702A0937802B0937902215020932B +:100AA000750245C0282F2150209375028130C9F46A +:100AB0009F739F5F9093700280917602909177026E +:100AC000A0917802B09179028093710290937202A2 +:100AD000A0937302B093740283E080932B0181E0B2 +:100AE000089580E507C0282F215020937502823099 +:100AF00030F480E380932B011092750218C040916E +:100B0000760250917702609178027091790287E0C5 +:100B1000440F551F661F771F8A95D1F7492B4093C5 +:100B2000760250937702609378027093790280E0A6 +:100B300008950F931F9334DF8823A9F01CDF8823C7 +:100B400091F01CDF8C0122273327DC01CB01AA277F +:100B5000BB27082719272A273B2781E00F3F1F4F74 +:100B60002105310509F080E01F910F9108950F9341 +:100B70001F93A0916202ECE1F0E097E08A019B01F3 +:100B80000E2E04C036952795179507950A94D2F72F +:100B9000083040F0A0936202973059F4009362024B +:100BA00096E007C091503797A02F923039F7009305 +:100BB0006202A92FA25013C0EA2FF0E0EE59FD4FB8 +:100BC0008A019B010F771127222733270083E7E053 +:100BD0007695679557954795EA95D1F7A150A1115C +:100BE000EBCF492F50E09A0163E0220F331F6A9543 +:100BF000E1F7206C3F6F30916202322B309362023A +:100C0000FA01EF59FD4F81508F7380688083909374 +:100C100061021F910F9108950F931F938B01AB01F8 +:100C20004095509560E070E0BA015527442720E0D8 +:100C300030E0402B512B622B732B1F910F9197CFDC +:100C4000BF92CF92DF92EF92FF920F931F93CF93B9 +:100C5000DF937C018B01EA01D7D1B82E811132C01C +:100C6000209731F028813981021B130BE20EF31E0D +:100C7000C12CD12C22C08091E80085FD14C0809148 +:100C8000E8008E778093E800209749F08881998169 +:100C90008C0D9D1D9983888325E0B22E13C0B4D19D +:100CA000882359F00EC0F70181917F018093F100F4 +:100CB00001501109FFEFCF1ADF0A01151105D9F60E +:100CC00001C0B82E8B2DDF91CF911F910F91FF9016 +:100CD000EF90DF90CF90BF900895209185023091E2 +:100CE00086022617370748F06115710539F42091FF +:100CF000E8002E772093E80001C0B9019C0180E054 +:100D000034C090917E02992309F443C0953009F4D0 +:100D100042C09091E80093FD3AC09091E80092FDA6 +:100D200030C09091E80090FF20C08091F20090E0E8 +:100D3000F901821B930B05C021912093F1006150B2 +:100D400071099F01280F391F6115710519F02830AD +:100D5000310590F381E02830310509F080E0909171 +:100D6000E8009E779093E8009F016115710549F6B0 +:100D70008111C7CF06C080917E02882351F0853053 +:100D800051F08091E80082FFF6CF80E0089581E085 +:100D9000089582E0089583E008956115710529F4AE +:100DA0002091E8002B772093E8009C0121C08091DE +:100DB0007E02882381F1853041F18091E80083FD36 +:100DC00026C08091E80082FFF2CFF90107C0809130 +:100DD000F10081939F016150710929F09F01809179 +:100DE000F2008111F4CF8091E8008B778093E800C6 +:100DF00061157105E1F68091E80080FD0AC08091DF +:100E00007E02882341F08530B1F783E0089581E0C8 +:100E1000089580E0089582E0089520918502309140 +:100E200086022617370748F06115710539F42091BD +:100E3000E8002E772093E80001C0B9019C0180E012 +:100E400035C090917E02992309F444C0953009F48D +:100E500043C09091E80093FD3BC09091E80092FD63 +:100E600031C09091E80090FF21C08091F20090E0A5 +:100E7000F901821B930B06C024912093F100319657 +:100E8000615071099C012E0F3F1F6115710519F00A +:100E90002830310588F381E02830310509F080E001 +:100EA0009091E8009E779093E8009F01611571058D +:100EB00041F68111C6CF06C080917E02882351F091 +:100EC000853051F08091E80082FFF6CF80E00895F0 +:100ED00081E0089582E0089583E00895982F2CC062 +:100EE0009093E900981739F07091EC002091ED0093 +:100EF0005091F00003C0242F762F50E021FD02C056 +:100F00009F5F1AC03091EB003E7F3093EB00309131 +:100F1000ED003D7F3093ED003091EB003160309378 +:100F2000EB007093EC002093ED005093F0002091C3 +:100F3000EE0027FDE5CF07C0953090F28F708093CB +:100F4000E90081E0089580E008950F931F93CF9307 +:100F5000DF93062FEC0110E02EC09881911103C0A1 +:100F60001F5F259628C02C81E981FA816B81892F2A +:100F70008F70853010F080E021C0223010F056E0F4 +:100F800001C052E028E030E040E003C04F5F220F94 +:100F9000331F2E173F07D0F34295407F452B991FF3 +:100FA0009927991F6295660F660F607C692B96DF03 +:100FB0008111D6CFE0CF1013D0CF81E0DF91CF9158 +:100FC0001F910F91089580917F0287FD05C0809148 +:100FD000E80080FF0EC012C08091E80082FD05C0CD +:100FE00080917E028111F8CF08958091E8008B777F +:100FF00008C080917E028111EACF08958091E800B7 +:101000008E778093E80008958091E4009091E50048 +:1010100045E62091EC0020FD1FC023C020917E02F8 +:10102000222391F0253091F02091EB0025FD10C096 +:101030002091E4003091E5002817390751F3415021 +:10104000C90139F784E0089582E0089583E00895A6 +:1010500081E0089580E008952091E80020FFDECF30 +:10106000F9CF2091E80022FFD9CFF4CF41D043D06F +:101070008091D8008F778093D8008091D8008068C5 +:101080008093D8008091D8008F7D8093D80084E031 +:1010900089BD86E089BD09B400FEFDCF10927E02B5 +:1010A00010927A0210927C0210927B0242E060E081 +:1010B00080E014DF8091E1008E7F8093E1008091D9 +:1010C000E20081608093E2008091E200886080937A +:1010D000E2008091E0008E7F8093E0000895E3E6D7 +:1010E000F0E080818E7F808381E080937D02BECF9F +:1010F0001092E20008951092E10008951F920F925D +:101100000FB60F9211242F933F934F935F936F93DA +:101110007F938F939F93AF93BF93EF93FF938091B0 +:10112000E10082FF0AC08091E20082FF06C0809148 +:10113000E1008B7F8093E10099DB8091E10080FFEB +:1011400017C08091E20080FF13C08091E2008E7F83 +:101150008093E2008091E20080618093E2008091C0 +:10116000D80080628093D80019BC10927E02BBDA4E +:101170008091E10084FF2FC08091E20084FF2BC0AA +:1011800084E089BD86E089BD09B400FEFDCF809171 +:10119000D8008F7D8093D8008091E1008F7E80936E +:1011A000E1008091E2008F7E8093E2008091E20076 +:1011B00081608093E20080917A02882311F084E0BC +:1011C00007C08091E30087FF02C083E001C081E097 +:1011D00080937E0287DA8091E10083FF27C08091AF +:1011E000E20083FF23C08091E100877F8093E100CC +:1011F00082E080937E0210927A028091E1008E7FDD +:101200008093E1008091E2008E7F8093E2008091E4 +:10121000E20080618093E20042E060E080E05EDE18 +:101220008091F00088608093F000B5D1FF91EF913C +:10123000BF91AF919F918F917F916F915F914F91EE +:101240003F912F910F900FBE0F901F9018951F92F6 +:101250000F920FB60F9211242F933F934F935F93EA +:101260006F937F938F939F93AF93BF93CF93EF939E +:10127000FF938091E9008F709091EC0090FF02C085 +:1012800090E801C090E0C92FC82B1092E90080912E +:10129000F000877F8093F00078941CD01092E900D2 +:1012A0008091F00088608093F000CF70C093E900D7 +:1012B000FF91EF91CF91BF91AF919F918F917F91CE +:1012C0006F915F914F913F912F910F900FBE0F90B3 +:1012D0001F9018951F93CF93DF93CDB7DEB7AC97D0 +:1012E0000FB6F894DEBF0FBECDBFEFE7F2E08091FE +:1012F000F100819322E0E738F207C9F7B0DA809174 +:10130000E80083FF30C180917F0290918002953088 +:1013100009F487C038F49130B1F170F0933009F0DE +:1013200022C131C0983009F4F3C0993009F4FFC0EC +:10133000963009F018C19BC0803821F0823809F03E +:1013400012C108C080917B0290917C02992389F0A0 +:1013500082600FC080918302909184028F709927E0 +:101360008093E9008091EB0085FB882780F910923B +:10137000E9009091E800977F9093E8008093F10056 +:101380001092F100D0C0882319F0823009F0EBC030 +:101390008F7121F0823009F0E6C00BC0809181028C +:1013A000813009F0E0C0933009F080E080937C0246 +:1013B0002FC08091810281112BC080918302909176 +:1013C00084028F709927009709F4CDC08093E900BB +:1013D0002091EB0020FF1CC020918002233021F4DB +:1013E0008091EB00806212C09091EB00906190932D +:1013F000EB0021E030E001C0220F8A95EAF720934C +:10140000EA001092EA008091EB0088608093EB0084 +:101410001092E9008091E800877F8093E800D3DD97 +:10142000A2C08111A0C080918102909182028F7729 +:101430009927182F9091E3009078982B9093E300D0 +:101440008091E800877F8093E800BDDD8091E8000F +:1014500080FFFCCF8091E30080688093E30011233C +:1014600011F083E001C082E080937E027CC080584E +:10147000823008F078C080918102909182028C3D88 +:1014800023E0920771F583E08A838AE289834FB76C +:10149000F894DE01139620E03EE051E2E32FF0E005 +:1014A00050935700E49120FF03C0E295EF703F5F37 +:1014B000EF708E2F90E0EA3010F0C79601C0C09612 +:1014C0008D939D932F5F243149F74FBF8091E800A2 +:1014D000877F8093E8006AE270E0CE010196FDDB31 +:1014E00011C0AE01455D5F4F60918302EFD9009757 +:1014F000D1F12091E800277F2093E800BC018BA563 +:101500009CA58BDC8091E8008B778093E8002BC052 +:10151000803849F58091E800877F8093E8008091CA +:101520007A028093F1008091E8008E7776CF811166 +:101530001AC0909181029230B0F48091E800877FC8 +:101540008093E80090937A023EDD80917A028111C7 +:1015500004C08091E30087FF02C084E001C081E005 +:1015600080937E02C1D88091E80083FF0AC08091F9 +:10157000E800877F8093E8008091EB008062809391 +:10158000EB00AC960FB6F894DEBF0FBECDBFDF9177 +:10159000CF911F9108950895CF9380917E02882363 +:1015A000A9F08091E9008F709091EC0090FF02C04B +:1015B00090E801C090E0C92FC82B1092E9008091FB +:1015C000E80083FD87DECF70C093E900CF910895D6 +:1015D000CF93DF93EC014096FC018BE0DF011D927D +:1015E0008A95E9F782E08C83898783E08E8761E0C2 +:1015F000CE010196AADC882361F061E0CE01069657 +:10160000A4DC882331F061E0CE010B96DF91CF910D +:101610009CCC80E0DF91CF910895CF93C62F20918D +:101620007E022430F1F4FC0144895589668977896A +:10163000452B462B472BA9F081818F708093E900C1 +:101640008091E80085FF04C0C093F10080E00AC0EB +:101650008091E8008E778093E800D6DC8823A1F3A0 +:1016600001C082E0CF91089520917E02243029F5B7 +:10167000FC014489558966897789452B462B472B80 +:10168000E1F081818F708093E9008091F2008111F7 +:1016900002C080E008959091E8008091E8008E7784 +:1016A0008093E80095FDF5CFAFDC811107C09091E4 +:1016B000E8009E779093E800089582E008952091D5 +:1016C0007E02243089F4FC01448955896689778932 +:1016D000452B462B472B41F021812F702093E900A9 +:1016E0002091E80020FDC0CF089520917E02243093 +:1016F00019F02FEF3FEF24C0FC014489558966891A +:101700007789452B462B472BA1F386818F708093D9 +:10171000E9008091E80082FFECCF8091F2008823FD +:1017200021F02091F10030E002C02FEF3FEF8091D7 +:10173000F200811105C08091E8008B778093E8006A +:10174000C90108950895CF93DF93EC018091E800DB +:1017500083FFA9C0888190E02091830230918402A8 +:101760002817390709F09FC080918002813261F00B +:1017700020F4803209F097C03DC0823209F46EC077 +:10178000833209F090C07FC080917F02813A09F0D6 +:101790008AC08091E800877F8093E8008091E8000C +:1017A00080FFFCCF4C895D896E897F894093F10071 +:1017B000BB27A72F962F852F8093F100CB01AA2757 +:1017C000BB278093F100472F552766277727409343 +:1017D000F100888D8093F100898D8093F1008A8DCE +:1017E0008093F1008091E8008E778093E800DF918C +:1017F000CF91E9CB80917F02813209F054C0809172 +:10180000E800877F8093E80005C080917E028823EE +:1018100009F449C08091E80082FFF7CF3091F100D0 +:101820002091F1009091F1008091F1003C8B2D8B83 +:101830009E8B8F8B8091F100888F8091F100898F32 +:101840008091F1008A8F8091E8008B778093E80087 +:10185000BADBCE01DF91CF910C94900380917F028F +:10186000813209F58091E800877F8093E800ABDB47 +:101870008091810290918202998B888BCE01DF91B9 +:10188000CF910C94240480917F02813261F4809185 +:10189000E800877F8093E80096DB60918102CE01AB +:1018A000DF91CF914FCFDF91CF9108956F927F92CB +:1018B0008F929F92AF92BF92CF92DF92EF92FF9260 +:1018C0000F931F93CF93DF9300D01F92CDB7DEB756 +:1018D0007C01ADB6BEB68091E80083FF07C1F70179 +:1018E000808190E02091830230918402281739078B +:1018F00009F0FCC080918002833009F49EC030F46E +:10190000813071F0823009F0F1C0D4C08A3009F41E +:10191000B9C08B3009F4A2C0893009F0E7C04CC0CF +:1019200080917F02813A09F0E1C08DB69EB61A829D +:10193000198280918102109182028B83F701408588 +:101940008DB79EB7841B91090FB6F8949EBF0FBE4A +:101950008DBFCDB6DEB6EFEFCE1ADE0A360150E00F +:1019600060E070E0C601EAD1412F41508E010F5F67 +:101970001F4F9601BE016D5F7F4FC7010E94420459 +:10198000F701268137812115310529F0408550E086 +:10199000B601C901CAD11092E9008091E800877FA1 +:1019A0008093E80069817A81C30197D98091E8002A +:1019B0008B778093E80039C080917F02813209F0F3 +:1019C00095C08DB69EB600918502109186027090EA +:1019D0008102609082028DB79EB7801B910B0FB67B +:1019E000F8949EBF0FBE8DBFCDB6DEB6EFEFCE1A18 +:1019F000DE0A8091E800877F8093E800B801C60185 +:101A0000CCD98091E8008E778093E80021E07110B6 +:101A100001C020E030E0021B130B2C0D3D1D462DB4 +:101A20004150672DC7010E946504882D992D0FB67E +:101A3000F8949EBF0FBE8DBF59C080917F02813A3E +:101A400009F054C08091E800877F8093E80080917E +:101A5000E80080FFFCCFF701818540C080917F02C4 +:101A6000813209F043C08091E800877F8093E800CD +:101A7000AADA9091810281E0911101C080E0F70122 +:101A8000818734C080917F02813281F58091E800A6 +:101A9000877F8093E80097DA80918102909182029B +:101AA000882736E0969587953A95E1F7F70195876F +:101AB00084871CC080917F02813AC1F48091E80044 +:101AC000877F8093E8008091E80080FFFCCFF701DA +:101AD0008485958596958795969587958093F10051 +:101AE0008091E8008E778093E8006DDA0FB6F89465 +:101AF000BEBE0FBEADBE0F900F900F90DF91CF9185 +:101B00001F910F91FF90EF90DF90CF90BF90AF901B +:101B10009F908F907F906F9008959C01275F3F4F1B +:101B2000F90127E0DF011D922A95E9F721E0FC0188 +:101B3000218724EF31E03587248723E0248361E087 +:101B4000019603CA4F925F926F927F928F929F92FB +:101B5000AF92BF92CF92DF92EF92FF920F931F93BB +:101B6000CF93DF9300D01F92CDB7DEB77C01ADB627 +:101B7000BEB680917E02843009F08FC08091E4006F +:101B80009091E500F701228533852817390709F47C +:101B900084C081818F708093E9008091E80085FF87 +:101BA0007CC06DB67EB640858DB79EB7841B91090B +:101BB0000FB6F8949EBF0FBE8DBFCDB6DEB6EFEF69 +:101BC000CE1ADE0A1B821A821982460150E060E0BA +:101BD00070E0C601B3D08E010F5F1F4F960140E049 +:101BE000BE016D5F7F4FC7010E944204582EF7016E +:101BF00084859585892B31F001E010E086859785F5 +:101C0000892B11F000E010E0F701C680D780C114E5 +:101C1000D10489F049815A81B601C40179D04424A4 +:101C20004394009709F4412CF701408550E0B4013A +:101C3000C6017BD001C0412C89819A81892BF9F0A2 +:101C4000511004C0411002C000FF19C0F701848583 +:101C500095859787868781818F708093E9008B8136 +:101C600081118093F10069817A8140E050E0C401E4 +:101C70000E9420068091E8008E778093E800809192 +:101C8000E4009091E500F70193878287862D972DD8 +:101C90000FB6F8949EBF0FBE8DBF0FB6F894BEBEB0 +:101CA0000FBEADBE0F900F900F90DF91CF911F919F +:101CB0000F91FF90EF90DF90CF90BF90AF909F90EB +:101CC0008F907F906F905F904F900895A1E21A2EB1 +:101CD000AA1BBB1BFD010DC0AA1FBB1FEE1FFF1FD0 +:101CE000A217B307E407F50720F0A21BB30BE40B20 +:101CF000F50B661F771F881F991F1A9469F7609567 +:101D00007095809590959B01AC01BD01CF01089520 +:101D1000FB01DC0104C08D910190801921F4415038 +:101D20005040C8F7881B990B0895FB01DC0102C0E5 +:101D300001900D9241505040D8F70895DC0101C048 +:0E1D40006D9341505040E0F70895F894FFCFA6 +:101D4E00028120000001500211000000000000007E +:101D5E0000834000000104400000018208000001E1 +:0E1D6E0000000000000000000000000830200F +:00000001FF diff --git a/plugins/KeyboardioHID/Flip_1.PNG b/plugins/KeyboardioHID/Flip_1.PNG new file mode 100644 index 0000000000000000000000000000000000000000..46f0952f3350b5e77e88a3f674194b87e4587374 GIT binary patch literal 74947 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
<<=@p{ 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%0A{K&0cz*(oG*D_; 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Ņ=HW)Oc)1J6L}CdC5#S;%6(Zzl&9@zdy-Bmd4ga%5Q@iiI(9zE z4~dr82Rc1ERUFu-3fZ#BjsZQU13nQd1chWp9E9x>Vu$);Af?a|IZlKun<E5uY{WJsAv7B$>k@Sn&SEUur@k3-H;u+o)HOxaJ6W_dnZ$+= zGD||MB9~J+Dlf!`W;JckgYg`Aig>O_7-?IoCrFI(Br(Q;OOi2GNZqJ~aTqy&Ge#~T z#C^f2gQ%g170f~YPbboAT? zh9qNLa1zEY5|SwxEAEe9oGg}$=bgk}jKM_XIiT^Ux=r~b@gw0Q*)wPNY_pg)xu=H28d)Wu}i6Y%a0S=B-Q;k|z)NikL7RM@LGYidER!g05bHt{)PyKX%C@#Br%L z+4Ds7T*)4vy6qZ}<0S5BkTZDXZsc%_7cWM7dOG&(*@Kdj5(G3fG@z=g3dP06QuN3I zX}T{wCP`kUakWu(xXF=2uCaXpk}gcKVY`syw2cEA>QAFwa>_08q7FMJJ*TdP(%KU! zu5Lup{$nVtq7Uge$cqK?D~{Nq<+PqIq9_sNX&ZYTPW=$5^$Tbl^8ychI}U9*x2Z0t zawcY9s4m$bf!Tk@eK>-B<#fTuArCk#%WA3c5Tkq^A?nO6JBZv;LCFE+2=*2Wit25M z`#B{CCApY{$|EYhUc` zi26)y_1pH>+~=0Zw)JM;Bs4~{9ycg`w3W4OOZ!0V6?N|^u19uJouC$3g*6Jbav80o zGE{ai^+UF8)@feYV~m~AhPf}cZCd(oUA|Y;yGJ~yd#HVCPqs;Y5pBxl0&1I{f4Pm= z-rhcqH;t)yy;jj{TfBbdYnU$Fp!bM)%}b2;i(GHJNJzd9<@?X};rVj;x5NC~!gMG! zu68VctGgY>KDj_WPPL$XkY96rYZZBnq+@3HL3hmW?rhkYAf1iejRY?(Elqwu9?jxa zR#qb5)TvWAdh{p`9y};TZ`-zQ2n`LDS7$KYjOT1TN<8~I9)9LEJoNM{c<{-W@xUKn z!u^sLasLwnaZAe|dg>Kf?vZC-6WhHmx0Us@R=+6wh}iDor(czIJouDo<4L0pQU85U zywJkqE%(i~ZP?0F-)LK^L-t41DeDz|cdYwG+$-w3=dr)w?nkXWui-Da#}h<-T8#Df z`X3?wj6M$&e?o8Kp+DiS2cHwz?)QG^&tkc)j4W@qVd7M`(O0V1fVP))7>{l3K5w*3 z>&&(+$Ue2SZ{JoO3(@wykNs7QqkwMh82z!gW2xJ~wyz56dUH&SKG+{StT)$L${5`B z5Y_n{{vhi9!-LP_&Ig`Bult`CJY_)lZO}R@LuGB-xoJbJqyEZzAF$O+w{~PbD$mF= zciwNdZ^c+|-`3U#v;96a<}}t~oXyw0`CgD?Ps{0jA>SLe_re48ex%pFd_U5Av6c5D z!!V41K7+S?`*yqF(YL0Qm6f5ct_}egE?hu!b2CnyIDx~552L!eTAsem&CQkHu|gZs zRT>Ei3G$L$`hq=zzD=3wK8zYQ$_~xg>dLf-v17+d%*P=iA@*e^v`pQ`#9Xgir?PnH z8+huCp;)Y0w>juzW!+*7ed8&79AqhDDJSduILNuo<{*6h)EgMO*m~buMrmX5P`qI; z=UMyavY?Nj!c(FyJLY;>=f?`o%B|<0Ynxk(ZI9(S;WDIXpT|OS5<+d9}5* z2)K0V63(ALkEW(3yXcYq(KH{;?B(U<$&IqIvgCKJkoXZ~i%j=n^5n^qu&^-g`t~w? z`gDo9Z0*{$_T_Y6U8kbkR>!)){&>EBAl7Nt?VLYQS+@>>{h!Cc`Ia)4awRk(rHyrg=x;CQS^Ktao_FYj!#>LO12NxNXUEgF>{$BhfM)x(L-54) zPhe=6vdqpb^i$TY9r6UO?>Ea*#!^n!*AKIt%Iw6fe%IrPp|;ngdf!^6rH!>1@l3xnAvq!#>*9_nT#`v*T%7Ejad7hvWD$48ybq)5XZk$j|6XT9P~Z93J@_dEDW{ bhw=XdEHwHUp@^xg00000NkvXXu0mjfs^OjO literal 0 HcmV?d00001 diff --git a/plugins/KeyboardioHID/Flip_3.PNG b/plugins/KeyboardioHID/Flip_3.PNG new file mode 100644 index 0000000000000000000000000000000000000000..32439649a45a444e98323b8921b70016724fe956 GIT binary patch literal 74966 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
  • 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 literal 0 HcmV?d00001 diff --git a/plugins/KeyboardioHID/HID.cpp b/plugins/KeyboardioHID/HID.cpp new file mode 100644 index 0000000000..bde3f82451 --- /dev/null +++ b/plugins/KeyboardioHID/HID.cpp @@ -0,0 +1,516 @@ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +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 "HID.h" + +//================================================================================ +// HID +//================================================================================ + +HID_ HID; + +void HID_::sendReport(uint8_t ReportID, const void* HIDReport, uint8_t length){ + // write the Report via Protocol and checksum. 16bit for each sending + // send control address + NHPHID.sendChecksum(NHP_ADDRESS_CONTROL, (NHP_USAGE_ARDUINOHID<<8)|ReportID , Serial); + const uint8_t* report = (const uint8_t*)HIDReport; + for(int i = 0; i 0) + return true; + return false; +} + +//================================================================================ +// Keyboard +//================================================================================ + +Keyboard_ Keyboard; + +Keyboard_::Keyboard_(void){ + // empty +} + +void Keyboard_::begin(void){ + memset(&_report, 0, sizeof(_report)); + HID.sendReport(HID_REPORTID_KeyboardReport, &_report, sizeof(_report)); +} + +void Keyboard_::end(void){ + begin(); +} + +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 +}; + +// removed <-- +//uint8_t USBPutChar(uint8_t c); + +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 +} + +// 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 + _report.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 + _report.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 (_report.keys[0] != k && _report.keys[1] != k && + _report.keys[2] != k && _report.keys[3] != k && + _report.keys[4] != k && _report.keys[5] != k) { + + for (i=0; i<6; i++) { + if (_report.keys[i] == 0x00) { + _report.keys[i] = k; + break; + } + } + if (i == 6) { + setWriteError(); + return 0; + } + } + HID.sendReport(HID_REPORTID_KeyboardReport, &_report, sizeof(_report)); + 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 + _report.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 + _report.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 && _report.keys[i] == k) { + _report.keys[i] = 0x00; + } + } + + HID.sendReport(HID_REPORTID_KeyboardReport, &_report, sizeof(_report)); + return 1; +} + +void Keyboard_::releaseAll(void){ + begin(); +} + +//================================================================================ +// Media +//================================================================================ + +Media_ Media; + +Media_::Media_(void){ + // empty +} + +void Media_::begin(void){ + memset(&_report, 0, sizeof(_report)); + HID.sendReport(HID_REPORTID_MediaReport, &_report, sizeof(_report)); +} + +void Media_::end(void){ + begin(); +} + +void Media_::write(uint16_t m){ + press(m); + release(m); +} + +void Media_::press(uint16_t m){ + // search for a free spot + for (int i=0; i +#include "HID_Reports.h" +// somehow you need to declare it in the main program too +#include + +//================================================================================ +// HID +//================================================================================ + +class HID_{ +public: + inline HID_(void){} + inline void begin(void){Serial.begin(115200);} + inline void end(void){Serial.end();} + + // everything public for your own modifications + NHProtocol NHPHID; + void sendReport(uint8_t ReportID, const void* HIDReport, uint8_t length); +private: +}; +extern HID_ HID; + +//================================================================================ +// Mouse +//================================================================================ + +#define MOUSE_LEFT 0x01 +#define MOUSE_RIGHT 0x02 +#define MOUSE_MIDDLE 0x04 +#define MOUSE_PREV 0x08 +#define MOUSE_NEXT 0x10 +#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE | MOUSE_PREV | MOUSE_NEXT) + +class Mouse_{ +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 + void releaseAll(void); + bool isPressed(uint8_t b = MOUSE_LEFT); // check LEFT by default +private: + void buttons(uint8_t b); + HID_MouseReport_Data_t _report; +}; +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 + +//Keyboard fixed/added missing Keys +#define KEY_PRINT 0xCE +#define KEY_SCROLL_LOCK 0xCF +#define KEY_PAUSE 0xD0 + +//Raw Keyboard definitions +#define RAW_KEYBOARD_LEFT_CTRL B00000001 +#define RAW_KEYBOARD_LEFT_SHIFT B00000010 +#define RAW_KEYBOARD_LEFT_ALT B00000100 +#define RAW_KEYBOARD_LEFT_GUI B00001000 +#define RAW_KEYBOARD_RIGHT_CTRL B00010000 +#define RAW_KEYBOARD_RIGHT_SHIFT B00100000 +#define RAW_KEYBOARD_RIGHT_ALT B01000000 +#define RAW_KEYBOARD_RIGHT_GUI B10000000 + +#define RAW_KEYBOARD_UP_ARROW 0x52 +#define RAW_KEYBOARD_DOWN_ARROW 0x51 +#define RAW_KEYBOARD_LEFT_ARROW 0x50 +#define RAW_KEYBOARD_RIGHT_ARROW 0x4F +#define RAW_KEYBOARD_SPACEBAR 0x2C +#define RAW_KEYBOARD_BACKSPACE 0x2A +#define RAW_KEYBOARD_TAB 0x2B +#define RAW_KEYBOARD_RETURN 0x28 +#define RAW_KEYBOARD_ESC 0x29 +#define RAW_KEYBOARD_INSERT 0x49 +#define RAW_KEYBOARD_DELETE 0x4C +#define RAW_KEYBOARD_PAGE_UP 0x4B +#define RAW_KEYBOARD_PAGE_DOWN 0x4E +#define RAW_KEYBOARD_HOME 0x4A +#define RAW_KEYBOARD_END 0x4D +#define RAW_KEYBOARD_CAPS_LOCK 0x39 +#define RAW_KEYBOARD_F1 0x3A +#define RAW_KEYBOARD_F2 0x3B +#define RAW_KEYBOARD_F3 0x3C +#define RAW_KEYBOARD_F4 0x3D +#define RAW_KEYBOARD_F5 0x3E +#define RAW_KEYBOARD_F6 0x3F +#define RAW_KEYBOARD_F7 0x40 +#define RAW_KEYBOARD_F8 0x41 +#define RAW_KEYBOARD_F9 0x42 +#define RAW_KEYBOARD_F10 0x43 +#define RAW_KEYBOARD_F11 0x44 +#define RAW_KEYBOARD_F12 0x45 +#define RAW_KEYBOARD_PRINT 0x46 +#define RAW_KEYBOARD_SCROLL_LOCK 0x47 +#define RAW_KEYBOARD_PAUSE 0x48 + +//Keyboard fixed/added missing Keys +#define KEY_PRINT 0xCE +#define KEY_SCROLL_LOCK 0xCF +#define KEY_PAUSE 0xD0 + +class Keyboard_ : public Print{ +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); +private: + HID_KeyboardReport_Data_t _report; +}; +extern Keyboard_ Keyboard; + +//================================================================================ +// Media +//================================================================================ + +#define MEDIA_FAST_FORWARD 0xB3 +#define MEDIA_REWIND 0xB4 +#define MEDIA_NEXT 0xB5 +#define MEDIA_PREVIOUS 0xB6 +#define MEDIA_STOP 0xB7 +#define MEDIA_PLAY_PAUSE 0xCD + +#define MEDIA_VOLUME_MUTE 0xE2 +#define MEDIA_VOLUME_UP 0xE9 +#define MEDIA_VOLUME_DOWN 0xEA + +#define MEDIA_EMAIL_READER 0x18A +#define MEDIA_CALCULATOR 0x192 +#define MEDIA_EXPLORER 0x194 + +#define MEDIA_BROWSER_HOME 0x223 +#define MEDIA_BROWSER_BACK 0x224 +#define MEDIA_BROWSER_FORWARD 0x225 +#define MEDIA_BROWSER_REFRESH 0x227 +#define MEDIA_BROWSER_BOOKMARKS 0x22A + +class Media_{ +public: + Media_(void); + void begin(void); + void end(void); + void write(uint16_t m); + void press(uint16_t m); + void release(uint16_t m); + void releaseAll(void); +private: + HID_MediaReport_Data_t _report; +}; +extern Media_ Media; + +//================================================================================ +// System +//================================================================================ + +#define SYSTEM_POWER_DOWN 0x81 +#define SYSTEM_SLEEP 0x82 +#define SYSTEM_WAKE_UP 0x83 + +class System_{ +public: + System_(void); + void begin(void); + void end(void); + void write(uint16_t s); + void press(uint16_t s); + void release(void); + void releaseAll(void); +}; +extern System_ System; + +//================================================================================ +// Gamepad +//================================================================================ + +class Gamepad_{ +public: + Gamepad_(uint8_t reportID); + void begin(void); + void end(void); + void write(void); + void press(uint8_t b); + void release(uint8_t b); + void releaseAll(void); + inline void buttons(uint32_t b){ _report.whole32[0]=b; } + inline void xAxis(uint16_t a){ _report.xAxis=a; } + inline void yAxis(uint16_t a){ _report.yAxis=a; } + inline void zAxis(uint16_t a){ _report.zAxis=a; } + inline void rxAxis(uint16_t a){ _report.rxAxis=a; } + inline void ryAxis(uint16_t a){ _report.ryAxis=a; } + inline void rzAxis(uint16_t a){ _report.rzAxis=a; } + inline void dPad1(uint8_t d){ _report.dPad1=d; } + inline void dPad2(uint8_t d){ _report.dPad2=d; } +private: + HID_GamepadReport_Data_t _report; + uint8_t _reportID; +}; +extern Gamepad_ Gamepad1; +extern Gamepad_ Gamepad2; + +//================================================================================ +// Joystick +//================================================================================ + +class Joystick_{ +public: + Joystick_(uint8_t reportID); + void begin(void); + void end(void); + void write(void); + void press(uint8_t b); + void release(uint8_t b); + void releaseAll(void); + inline void xAxis(uint16_t a){ _report.xAxis=a; } + inline void yAxis(uint16_t a){ _report.yAxis=a; } + +private: + HID_JoystickReport_Data_t _report; + uint8_t _reportID; +}; +extern Joystick_ Joystick1; +extern Joystick_ Joystick2; + +#endif + diff --git a/plugins/KeyboardioHID/HID_Reports.h b/plugins/KeyboardioHID/HID_Reports.h new file mode 100644 index 0000000000..0129e89917 --- /dev/null +++ b/plugins/KeyboardioHID/HID_Reports.h @@ -0,0 +1,207 @@ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +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 HID_REPORTS_H +#define HID_REPORTS_H + +//================================================================================ +//Settings +//================================================================================ + +#define HID_MOUSE_ENABLE +#define HID_KEYBOARD_ENABLE +#define HID_RAWKEYBOARD_ENABLE +#define HID_MEDIA_ENABLE +#define HID_SYSTEM_ENABLE +#define HID_GAMEPAD1_ENABLE +#define HID_GAMEPAD2_ENABLE +#define HID_JOYSTICK1_ENABLE +#define HID_JOYSTICK2_ENABLE +//#define HID_MIDI_ENABLE + +//================================================================================ +//Definitions +//================================================================================ + +// empty + +//================================================================================ +//Report Typedefinitions +//================================================================================ + +typedef union{ + // mouse report: 5 buttons, position, wheel + uint8_t whole8[4]; + uint16_t whole16[4/2]; + uint32_t whole32[4/4]; + + struct{ + uint8_t buttons:5; + uint8_t reserved:3; + int8_t xAxis; + int8_t yAxis; + int8_t wheel; + }; +} HID_MouseReport_Data_t; + + +typedef union{ + // Low level key report: up to 6 keys and shift, ctrl etc at once + uint8_t whole8[8]; + uint16_t whole16[8/2]; + uint32_t whole32[8/4]; + + struct{ + uint8_t modifiers; + uint8_t reserved; + uint8_t keys[6]; + }; +} HID_KeyboardReport_Data_t; + + +typedef union{ + // every usable media key possible. Only one at the same time. + uint8_t whole8[8]; + uint16_t whole16[8/2]; + uint32_t whole32[8/4]; + + struct{ + uint16_t key1; + uint16_t key2; + uint16_t key3; + uint16_t key4; + }; +} HID_MediaReport_Data_t; + + +typedef union{ + // every usable system control key possible. Only one at the same time. + uint8_t whole8[2]; + uint16_t whole16[2/2]; + uint16_t key; +} HID_SystemReport_Data_t; + + +typedef union { + // 32 Buttons, 6 Axis, 2 D-Pads + uint8_t whole8[17]; + uint16_t whole16[17/2]; + uint32_t whole32[17/4]; + uint32_t buttons; + + struct{ + uint8_t button1 :1; + uint8_t button2 :1; + uint8_t button3 :1; + uint8_t button4 :1; + uint8_t button5 :1; + uint8_t button6 :1; + uint8_t button7 :1; + uint8_t button8 :1; + + uint8_t button9 :1; + uint8_t button10 :1; + uint8_t button11 :1; + uint8_t button12 :1; + uint8_t button13 :1; + uint8_t button14 :1; + uint8_t button15 :1; + uint8_t button16 :1; + + uint8_t button17 :1; + uint8_t button18 :1; + uint8_t button19 :1; + uint8_t button20 :1; + uint8_t button21 :1; + uint8_t button22 :1; + uint8_t button23 :1; + uint8_t button24 :1; + + uint8_t button25 :1; + uint8_t button26 :1; + uint8_t button27 :1; + uint8_t button28 :1; + uint8_t button29 :1; + uint8_t button30 :1; + uint8_t button31 :1; + uint8_t button32 :1; + + uint16_t xAxis; + uint16_t yAxis; + uint16_t zAxis; + + uint16_t rxAxis; + uint16_t ryAxis; + uint16_t rzAxis; + + uint8_t dPad1: 4; + uint8_t dPad2: 4; + + // deactivated because windows only supports 7 axis. should be enough. + //uint8_t throttle; + //uint8_t rudder; + + }; +} HID_GamepadReport_Data_t; + + +typedef union{ + // 2 Buttons, 2 Axis + uint8_t whole8[3]; + uint16_t whole16[3/2]; + + struct{ + uint16_t button1 :1; + uint16_t button2 :1; + uint16_t xAxis :10; + uint16_t yAxis :10; + uint16_t reserved :2; + }; +} HID_JoystickReport_Data_t; + + +typedef union{ + HID_MouseReport_Data_t Mouse; + HID_KeyboardReport_Data_t Keyboard; + HID_MediaReport_Data_t Media; + HID_GamepadReport_Data_t Gamepad1; + HID_GamepadReport_Data_t Gamepad2; + HID_JoystickReport_Data_t Joystick1; + HID_JoystickReport_Data_t Joystick2; +} HID_HIDReport_Data_t; + + +/** Enum for the HID report IDs used in the device. */ +typedef enum{ + HID_REPORTID_MouseReport = 0x01, /**< Report ID for the Mouse report within the device. */ + HID_REPORTID_KeyboardReport = 0x02, /**< Report ID for the Keyboard report within the device. */ + HID_REPORTID_RawKeyboardReport=0x03, /**< Report ID for the Raw Keyboard report within the device. */ + HID_REPORTID_MediaReport = 0x04, /**< Report ID for the Media report within the device. */ + HID_REPORTID_SystemReport = 0x05, /**< Report ID for the Power report within the device. */ + HID_REPORTID_Gamepad1Report = 0x06, /**< Report ID for the Gamepad1 report within the device. */ + HID_REPORTID_Gamepad2Report = 0x07, /**< Report ID for the Gamepad2 report within the device. */ + HID_REPORTID_Joystick1Report = 0x08, /**< Report ID for the Joystick1 report within the device. */ + HID_REPORTID_Joystick2Report = 0x09, /**< Report ID for the Joystick2 report within the device. */ +} HID_Report_IDs; + +#endif \ No newline at end of file diff --git a/plugins/KeyboardioHID/Hoodloader/Board/LEDs.h b/plugins/KeyboardioHID/Hoodloader/Board/LEDs.h new file mode 100644 index 0000000000..ff1157ef11 --- /dev/null +++ b/plugins/KeyboardioHID/Hoodloader/Board/LEDs.h @@ -0,0 +1,110 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the 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. +*/ + +/* + Board LEDs driver for the Benito board, from www.dorkbotpdx.org. +*/ + +#ifndef __LEDS_ARDUINOUNO_H__ +#define __LEDS_ARDUINOUNO_H__ + + /* Includes: */ + #include + +/* 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 << 4) + + /** 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_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 | ActiveMask) & ~LEDMask); + } + + static inline void LEDs_ToggleLEDs(const uint8_t LEDMask) + { + PORTD ^= 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/plugins/KeyboardioHID/Hoodloader/Config/LUFAConfig.h b/plugins/KeyboardioHID/Hoodloader/Config/LUFAConfig.h new file mode 100644 index 0000000000..3c3b68bb1a --- /dev/null +++ b/plugins/KeyboardioHID/Hoodloader/Config/LUFAConfig.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 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 + + #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 (USB_DEVICE_OPT_FULLSPEED | USB_OPT_RC32MCLKSRC | USB_OPT_BUSEVENT_PRIHIGH) +// #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 MAX_ENDPOINT_INDEX 4 +// #define NO_DEVICE_REMOTE_WAKEUP +// #define NO_DEVICE_SELF_POWER + + #else + + #error Unsupported architecture for this LUFA configuration file. + + #endif +#endif diff --git a/plugins/KeyboardioHID/Hoodloader/Descriptors.c b/plugins/KeyboardioHID/Hoodloader/Descriptors.c new file mode 100644 index 0000000000..ec022ea5fa --- /dev/null +++ b/plugins/KeyboardioHID/Hoodloader/Descriptors.c @@ -0,0 +1,619 @@ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +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. +*/ + +/** \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. +* +* This descriptor describes the multiple possible reports of the HID interface's report structure. +*/ + +const USB_Descriptor_HIDReport_Datatype_t PROGMEM HIDReport[] = +{ + +#ifdef HID_MOUSE_ENABLE + // 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, HID_REPORTID_MouseReport,// REPORT_ID + // 5 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) + 0x95, 0x05, // REPORT_COUNT (5) + 0x75, 0x01, // REPORT_SIZE (1) + 0x81, 0x02, // INPUT (Data,Var,Abs) + // reserved + 0x95, 0x01, // REPORT_COUNT (1) + 0x75, 0x03, // REPORT_SIZE (3) + 0x81, 0x03, // INPUT (Cnst,Var,Abs) + // x, y, wheel + 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) + // end + 0xc0, // END_COLLECTION + 0xc0, // END_COLLECTION +#endif + +#ifdef HID_KEYBOARD_ENABLE + // Keyboard + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x06, // USAGE (Keyboard) + 0xa1, 0x01, // COLLECTION (Application) + 0x85, HID_REPORTID_KeyboardReport, // REPORT_ID + 0x05, 0x07, // USAGE_PAGE (Keyboard) + // modifiers + 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) + // reserved byte + 0x95, 0x01, // REPORT_COUNT (1) + 0x75, 0x08, // REPORT_SIZE (8) + 0x81, 0x03, // INPUT (Cnst,Var,Abs) + // Key[6] Array + 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) + // LEDs for num lock etc + 0x05, 0x08, /* USAGE_PAGE (LEDs) */ + 0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */ + 0x29, 0x05, /* USAGE_MAXIMUM (Kana) */ + 0x95, 0x05, /* REPORT_COUNT (5) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */ + // Reserved 3 bits + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x03, /* REPORT_SIZE (3) */ + 0x91, 0x03, /* OUTPUT (Cnst,Var,Abs) */ + // end + 0xc0, // END_COLLECTION +#endif + +#ifdef HID_RAWKEYBOARD_ENABLE + // RAW HID + 0x06, 0xC0, 0xFF, + 0x0A, 0x00, 0x0C, + + 0xA1, 0x01, // Collection 0x01 + 0x85, HID_REPORTID_RawKeyboardReport, // REPORT_ID + 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 + +#ifdef HID_MEDIA_ENABLE + // Media + 0x05, 0x0C, // usage page (consumer device) + 0x09, 0x01, // usage -- consumer control + 0xA1, 0x01, // collection (application) + 0x85, HID_REPORTID_MediaReport, // report id + // 4 media Keys + 0x15, 0x00, //logical minimum + 0x26, 0xFF, 0xFF, //logical maximum (3ff) + 0x19, 0x00, // usage minimum (0) + 0x2A, 0xFF, 0xFF, //usage maximum (3ff) + 0x95, 0x04, //report count (4) + 0x75, 0x10, //report size (16) + 0x81, 0x00, //input + 0xC0, //end collection +#endif + +#ifdef HID_SYSTEM_ENABLE + // System + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x80, // USAGE (System Control) + 0xa1, 0x01, // COLLECTION (Application) + 0x85, HID_REPORTID_SystemReport, // REPORT_ID + // 1 system key + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255) + 0x19, 0x00, // USAGE_MINIMUM (Undefined) + 0x29, 0xff, // USAGE_MAXIMUM (System Menu Down) + 0x95, 0x01, // REPORT_COUNT (1) + 0x75, 0x08, // REPORT_SIZE (8) + 0x81, 0x00, // INPUT (Data,Ary,Abs) + 0xc0, // END_COLLECTION +#endif + +#ifdef HID_GAMEPAD1_ENABLE + // Gamepad1 + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x05, // USAGE (Game Pad) + 0xa1, 0x01, // COLLECTION (Application) + 0x85, HID_REPORTID_Gamepad1Report, // REPORT_ID + // 32 Buttons + 0x05, 0x09, // USAGE_PAGE (Button) + 0x19, 0x01, // USAGE_MINIMUM (Button 1) + 0x29, 0x20, // USAGE_MAXIMUM (Button 32) + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x25, 0x01, // LOGICAL_MAXIMUM (1) + 0x75, 0x01, // REPORT_SIZE (1) + 0x95, 0x20, // REPORT_COUNT (32) + 0x81, 0x02, // INPUT (Data,Var,Abs) + // 6 16bit Axis + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0xa1, 0x00, // COLLECTION (Physical) + 0x09, 0x30, // USAGE (X) + 0x09, 0x31, // USAGE (Y) + 0x09, 0x32, // USAGE (Z) + 0x09, 0x33, // USAGE (Rx) + 0x09, 0x34, // USAGE (Ry) + 0x09, 0x35, // USAGE (Rz) + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x27, 0xff, 0xff, 0x00, 0x00, // LOGICAL_MAXIMUM (65535) + 0x75, 0x10, // REPORT_SIZE (16) + 0x95, 0x06, // REPORT_COUNT (6) + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0xc0, // END_COLLECTION + // 2 Hat Switches + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x39, // USAGE (Hat switch) + 0x09, 0x39, // USAGE (Hat switch) + 0x15, 0x01, // LOGICAL_MINIMUM (1) + 0x25, 0x08, // LOGICAL_MAXIMUM (8) + 0x95, 0x02, // REPORT_COUNT (2) + 0x75, 0x04, // REPORT_SIZE (4) + 0x81, 0x02, // INPUT (Data,Var,Abs) + // 8bit Throttle + Rudder + //0x05, 0x02, // USAGE_PAGE (Simulation Controls) + //0xa1, 0x00, // COLLECTION (Physical) + //0x15, 0x00, // LOGICAL_MINIMUM (0) + //0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255) + //0x09, 0xbb, // USAGE (Throttle) + //0x09, 0xba, // USAGE (Rudder) + //0x75, 0x08, // REPORT_SIZE (8) + //0x95, 0x02, // REPORT_COUNT (2) + //0x81, 0x02, // INPUT (Data,Var,Abs) + //0xc0, // END_COLLECTION + 0xc0, // END_COLLECTION +#endif + +#ifdef HID_GAMEPAD2_ENABLE + // Gamepad2 + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x05, // USAGE (Game Pad) + 0xa1, 0x01, // COLLECTION (Application) + 0x85, HID_REPORTID_Gamepad2Report, // REPORT_ID + // 32 Buttons + 0x05, 0x09, // USAGE_PAGE (Button) + 0x19, 0x01, // USAGE_MINIMUM (Button 1) + 0x29, 0x20, // USAGE_MAXIMUM (Button 32) + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x25, 0x01, // LOGICAL_MAXIMUM (1) + 0x75, 0x01, // REPORT_SIZE (1) + 0x95, 0x20, // REPORT_COUNT (32) + 0x81, 0x02, // INPUT (Data,Var,Abs) + // 6 16bit Axis + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0xa1, 0x00, // COLLECTION (Physical) + 0x09, 0x30, // USAGE (X) + 0x09, 0x31, // USAGE (Y) + 0x09, 0x32, // USAGE (Z) + 0x09, 0x33, // USAGE (Rx) + 0x09, 0x34, // USAGE (Ry) + 0x09, 0x35, // USAGE (Rz) + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x27, 0xff, 0xff, 0x00, 0x00, // LOGICAL_MAXIMUM (65535) + 0x75, 0x10, // REPORT_SIZE (16) + 0x95, 0x06, // REPORT_COUNT (6) + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0xc0, // END_COLLECTION + // 2 Hat Switches + 0x09, 0x39, // USAGE (Hat switch) + 0x09, 0x39, // USAGE (Hat switch) + 0x15, 0x01, // LOGICAL_MINIMUM (1) + 0x25, 0x08, // LOGICAL_MAXIMUM (8) + 0x95, 0x02, // REPORT_COUNT (2) + 0x75, 0x04, // REPORT_SIZE (4) + 0x81, 0x02, // INPUT (Data,Var,Abs) + // 8bit Throttle + Rudder + //0x05, 0x02, // USAGE_PAGE (Simulation Controls) + //0xa1, 0x00, // COLLECTION (Physical) + //0x15, 0x00, // LOGICAL_MINIMUM (0) + //0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255) + //0x09, 0xbb, // USAGE (Throttle) + //0x09, 0xba, // USAGE (Rudder) + //0x75, 0x08, // REPORT_SIZE (8) + //0x95, 0x02, // REPORT_COUNT (2) + //0x81, 0x02, // INPUT (Data,Var,Abs) + //0xc0, // END_COLLECTION + 0xc0, // END_COLLECTION +#endif + +#ifdef HID_JOYSTICK1_ENABLE + // Joystick1 + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x04, // USAGE (Joystick) + 0xa1, 0x01, // COLLECTION (Application) + 0x85, HID_REPORTID_Joystick1Report, // REPORT_ID + 0xa1, 0x00, // COLLECTION (Physical) + 0x05, 0x09, // USAGE_PAGE (Button) + 0x19, 0x01, // USAGE_MINIMUM (Button 1) + 0x29, 0x02, // USAGE_MAXIMUM (Button 2) + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x25, 0x01, // LOGICAL_MAXIMUM (1) + 0x75, 0x01, // REPORT_SIZE (1) + 0x95, 0x02, // REPORT_COUNT (2) + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x30, // USAGE (X) + 0x09, 0x31, // USAGE (Y) + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x26, 0xff, 0x03, // LOGICAL_MAXIMUM (1023) + 0x75, 0x0a, // REPORT_SIZE (10) + 0x95, 0x02, // REPORT_COUNT (2) + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0x75, 0x02, // REPORT_SIZE (2) + 0x95, 0x01, // REPORT_COUNT (1) + 0x81, 0x03, // INPUT (Cnst,Var,Abs) + 0xc0, // END_COLLECTION + 0xc0, // END_COLLECTION +#endif + +#ifdef HID_JOYSTICK2_ENABLE + // Joystick2 + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x04, // USAGE (Joystick) + 0xa1, 0x01, // COLLECTION (Application) + 0x85, HID_REPORTID_Joystick2Report, // REPORT_ID + 0xa1, 0x00, // COLLECTION (Physical) + 0x05, 0x09, // USAGE_PAGE (Button) + 0x19, 0x01, // USAGE_MINIMUM (Button 1) + 0x29, 0x02, // USAGE_MAXIMUM (Button 2) + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x25, 0x01, // LOGICAL_MAXIMUM (1) + 0x75, 0x01, // REPORT_SIZE (1) + 0x95, 0x02, // REPORT_COUNT (2) + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x30, // USAGE (X) + 0x09, 0x31, // USAGE (Y) + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x26, 0xff, 0x03, // LOGICAL_MAXIMUM (1023) + 0x75, 0x0a, // REPORT_SIZE (10) + 0x95, 0x02, // REPORT_COUNT (2) + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0x75, 0x02, // REPORT_SIZE (2) + 0x95, 0x01, // REPORT_COUNT (1) + 0x81, 0x03, // INPUT (Cnst,Var,Abs) + 0xc0, // END_COLLECTION + 0xc0 // END_COLLECTION +#endif + +}; + +/** Device descriptor structure. This descriptor, located in FLASH 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 PROGMEM DeviceDescriptor = +{ + .Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device}, + + .USBSpecification = VERSION_BCD(1,1,0), + .Class = USB_CSCP_IADDeviceClass, + .SubClass = USB_CSCP_IADDeviceSubclass, + .Protocol = USB_CSCP_IADDeviceProtocol, + + .Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE, + + //new, passed by makefile <-- + .VendorID = HOODLOADER_VID, //used by Lufa + .ProductID = HOODLOADER_PID, //created for ArduinoHID + + //.VendorID = 0x2341, // Arduino + //.ProductID = 0x0043, // Arduino Uno + + .ReleaseNumber = VERSION_BCD(0,0,1), + + .ManufacturerStrIndex = STRING_ID_Manufacturer, + .ProductStrIndex = STRING_ID_Product, + .SerialNumStrIndex = USE_INTERNAL_SERIAL, + + .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 PROGMEM ConfigurationDescriptor = +{ + .Config = + { + .Header = {.Size = sizeof(USB_Descriptor_Configuration_Header_t), .Type = DTYPE_Configuration}, + + .TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t), + .TotalInterfaces = 3, + + .ConfigurationNumber = 1, + .ConfigurationStrIndex = NO_DESCRIPTOR, + + .ConfigAttributes = (USB_CONFIG_ATTR_RESERVED | USB_CONFIG_ATTR_SELFPOWERED), + + .MaxPowerConsumption = USB_CONFIG_POWER_MA(100) + }, + + .CDC_IAD = + { + .Header = {.Size = sizeof(USB_Descriptor_Interface_Association_t), .Type = DTYPE_InterfaceAssociation}, + + .FirstInterfaceIndex = INTERFACE_ID_CDC_CCI, + .TotalInterfaces = 2, + + .Class = CDC_CSCP_CDCClass, + .SubClass = CDC_CSCP_ACMSubclass, + .Protocol = CDC_CSCP_ATCommandProtocol, + + .IADStrIndex = NO_DESCRIPTOR + }, + + .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 = CDC_DSUBTYPE_CSInterface_Header, + + .CDCSpecification = VERSION_BCD(1,1,0), + }, + + .CDC_Functional_ACM = + { + .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalACM_t), .Type = DTYPE_CSInterface}, + .Subtype = CDC_DSUBTYPE_CSInterface_ACM, + + .Capabilities = 0x06, + }, + + .CDC_Functional_Union = + { + .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalUnion_t), .Type = DTYPE_CSInterface}, + .Subtype = CDC_DSUBTYPE_CSInterface_Union, + + .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 = 0x01 //new<-- + }, + + .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 = 0x01 //new<-- + }, + + + //new <-- + .HID_Interface = + { + .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, + + .InterfaceNumber = INTERFACE_ID_HID, + .AlternateSetting = 0x00, + + .TotalEndpoints = 1, + + .Class = HID_CSCP_HIDClass, + .SubClass = HID_CSCP_NonBootSubclass, + .Protocol = HID_CSCP_NonBootProtocol, + + .InterfaceStrIndex = NO_DESCRIPTOR + }, + + .HID_HIDData = + { + .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_EPSIZE, + .PollingIntervalMS = 0x01 //new<-- + } +}; + +/** 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 PROGMEM 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 PROGMEM ManufacturerString = USB_STRING_DESCRIPTOR(L"NicoHood"); + +/** 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 PROGMEM ProductString = USB_STRING_DESCRIPTOR(L"Arduino Hoodloader Beta"); + + +/** 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 = pgm_read_byte(&LanguageString.Header.Size); + break; + case STRING_ID_Manufacturer: + Address = &ManufacturerString; + Size = pgm_read_byte(&ManufacturerString.Header.Size); + break; + case STRING_ID_Product: + Address = &ProductString; + Size = pgm_read_byte(&ProductString.Header.Size); + break; + } + + break; + + //new <-- + case HID_DTYPE_HID: + Address = &ConfigurationDescriptor.HID_HIDData; + Size = sizeof(USB_HID_Descriptor_HID_t); + break; + case HID_DTYPE_Report: + Address = &HIDReport; + Size = sizeof(HIDReport); + break; + } + + *DescriptorAddress = Address; + return Size; +} + diff --git a/plugins/KeyboardioHID/Hoodloader/Descriptors.h b/plugins/KeyboardioHID/Hoodloader/Descriptors.h new file mode 100644 index 0000000000..c07979c86b --- /dev/null +++ b/plugins/KeyboardioHID/Hoodloader/Descriptors.h @@ -0,0 +1,121 @@ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +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. +*/ + +/** \file +* +* Header file for Descriptors.c. +*/ + +#ifndef _DESCRIPTORS_H_ +#define _DESCRIPTORS_H_ + +/* Includes: */ +#include +#include +#include <../HID_Reports.h> + +/* Macros: */ +/** Endpoint address of the CDC device-to-host notification IN endpoint. */ +#define CDC_NOTIFICATION_EPADDR (ENDPOINT_DIR_IN | 2) + +/** Endpoint address of the CDC device-to-host data IN endpoint. */ +#define CDC_TX_EPADDR (ENDPOINT_DIR_IN | 3) + +/** Endpoint address of the CDC host-to-device data OUT endpoint. */ +#define CDC_RX_EPADDR (ENDPOINT_DIR_OUT | 4) + +/** Size in bytes of the CDC device-to-host notification IN endpoint. */ +#define CDC_NOTIFICATION_EPSIZE 8 + +/** Size in bytes of the CDC data IN and OUT endpoints. */ +#define CDC_TXRX_EPSIZE 64 //<--new + + +/** Endpoint address of the HID reporting IN endpoint. */ +#define HID_IN_EPADDR (ENDPOINT_DIR_IN | 1) + +/** Size in bytes of each of the HID reporting IN endpoint. */ +// important: only use 8,16,32,64 here!! <-- +#define HID_EPSIZE 32 + + +/* 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_Association_t CDC_IAD; //<--new + 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; + + // HID Interface + USB_Descriptor_Interface_t HID_Interface; + USB_HID_Descriptor_HID_t HID_HIDData; + USB_Descriptor_Endpoint_t HID_ReportINEndpoint; + +} USB_Descriptor_Configuration_t; + +/* Enums: */ + +/** 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 */ + INTERFACE_ID_HID = 2, /**< HID 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/plugins/KeyboardioHID/Hoodloader/Hoodloader.c b/plugins/KeyboardioHID/Hoodloader/Hoodloader.c new file mode 100644 index 0000000000..8678f20cea --- /dev/null +++ b/plugins/KeyboardioHID/Hoodloader/Hoodloader.c @@ -0,0 +1,555 @@ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +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. +*/ + +/** \file +* +* Main source file for the VirtualSerialMouse demo. This file contains the main tasks of +* the demo and is responsible for the initial application hardware configuration. +*/ + +#include "Hoodloader.h" + + +/** Circular buffer to hold data from the host before it is sent to the device via the serial port. */ +//new important ram fix!! <-- +static RingBuff_t USBtoUSART_Buffer; + +/** Circular buffer to hold data from the serial port before it is sent to the host. */ +static RingBuff_t USARTtoUSB_Buffer; + +/** Pulse generation counters to keep track of the number of milliseconds remaining for each pulse type */ +//new important ram fix!! <-- +static volatile struct +{ + uint8_t TxLEDPulse; /**< Milliseconds remaining for data Tx LED pulse */ + uint8_t RxLEDPulse; /**< Milliseconds remaining for data Rx LED pulse */ + uint8_t PingPongLEDPulse; /**< Milliseconds remaining for enumeration Tx/Rx ping-pong LED pulse */ +} PulseMSRemaining; + + +/** LUFA CDC Class driver interface configuration and state information. This structure is +* passed to all CDC Class driver functions, so that multiple instances of the same class +* within a device can be differentiated from one another. +*/ +USB_ClassInfo_CDC_Device_t VirtualSerial_CDC_Interface = +{ + .Config = + { + .ControlInterfaceNumber = INTERFACE_ID_CDC_CCI, + .DataINEndpoint = + { + .Address = CDC_TX_EPADDR, + .Size = CDC_TXRX_EPSIZE, + .Banks = 1, + }, + .DataOUTEndpoint = + { + .Address = CDC_RX_EPADDR, + .Size = CDC_TXRX_EPSIZE, + .Banks = 1, + }, + .NotificationEndpoint = + { + .Address = CDC_NOTIFICATION_EPADDR, + .Size = CDC_NOTIFICATION_EPSIZE, + .Banks = 1, + }, + }, +}; + +/** Buffer to hold the previously generated HID report, for comparison purposes inside the HID class driver. */ +static uint8_t PrevHIDReportBuffer[sizeof(HID_HIDReport_Data_t)]; +static uint8_t CurrentHIDReportBuffer[sizeof(HID_HIDReport_Data_t)]; + +static struct{ + // variable to perform a "HID flush" and to indicate what report should be written down + uint8_t ID; + // length of the report + uint8_t length; + // number of bytes received + uint8_t recvlength; + // should the report been written even if nothing changed? important for mouse + bool forcewrite; +} HIDReportState; + +/** LUFA HID Class driver interface configuration and state information. This structure is +* passed to all HID Class driver functions, so that multiple instances of the same class +* within a device can be differentiated from one another. +*/ +USB_ClassInfo_HID_Device_t Device_HID_Interface = +{ + .Config = + { + .InterfaceNumber = INTERFACE_ID_HID, + .ReportINEndpoint = + { + .Address = HID_IN_EPADDR, + .Size = HID_EPSIZE, + .Banks = 1, + }, + .PrevReportINBuffer = PrevHIDReportBuffer, + .PrevReportINBufferSize = sizeof(PrevHIDReportBuffer), + }, +}; + +/** 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(); + + RingBuffer_InitBuffer(&USBtoUSART_Buffer); + RingBuffer_InitBuffer(&USARTtoUSB_Buffer); + + GlobalInterruptEnable(); + + // Protocolsetup + HIDReportState.recvlength=0; + HIDReportState.ID=0; + + // Debug + DDRB |= 0x08; //led out + DDRB |= 0x02; //led out + + for (;;) + { + /* Only try to read in bytes from the CDC interface if the transmit buffer is not full */ + if (!(RingBuffer_IsFull(&USBtoUSART_Buffer))) + { + int16_t ReceivedByte = CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface); + + /* Read bytes from the USB OUT endpoint into the USART transmit buffer */ + if (!(ReceivedByte < 0)) + RingBuffer_Insert(&USBtoUSART_Buffer, ReceivedByte); + } + + /* Check if the UART receive buffer flush timer has expired or the buffer is nearly full */ + RingBuff_Count_t BufferCount = RingBuffer_GetCount(&USARTtoUSB_Buffer); + if ((TIFR0 & (1 << TOV0)) || (BufferCount > BUFFER_NEARLY_FULL)) + { + TIFR0 |= (1 << TOV0); + + if (USARTtoUSB_Buffer.Count) { + LEDs_TurnOnLEDs(LEDMASK_TX); + PulseMSRemaining.TxLEDPulse = TX_RX_LED_PULSE_MS; + } + + /* Read bytes from the USART receive buffer*/ + while (BufferCount--){ + //new Protocol check<-- + // if a reading finished succesfull without valid checksum or an error occured (ignore a reset) + if(NHPgetErrorLevel()&(~NHP_INPUT_RESET)){ + // check if previous reading was a valid Control Address and write it down + checkNHPControlAddressError(); + + // Write the last invalid signals. This will not write a possible new lead to keep + // it for the next reading. This is implemented in the Protocol itself. + writeNHPreadBuffer(NHPreadlength); + } + + //read newest byte and check for Protocol + RingBuff_Data_t b = RingBuffer_Remove(&USARTtoUSB_Buffer); + checkNHPProtocol(b); + } + + // if reading has timed out write the buffers down the serial and turn off the led + if (PulseMSRemaining.TxLEDPulse && !(--PulseMSRemaining.TxLEDPulse)){ + + // check if previous reading was a valid Control Address and write it down + checkNHPControlAddressError(); + + // only write if there is input (ignore a reset) + if(!(NHPgetErrorLevel() & NHP_INPUT_RESET)){ + // Lead errors are not in the buff length to keep them for next reading. + // But we want to write it down now after timeout. + uint8_t len= NHPreadlength; + if(NHPgetErrorLevel()& NHP_ERR_LEAD) len++; + writeNHPreadBuffer(len); + } + // do not write again in the while loop above anyways + NHPreset(); + + /* Turn off TX LED(s) once the TX pulse period has elapsed */ + LEDs_TurnOffLEDs(LEDMASK_TX); + } + + /* Turn off RX LED(s) once the RX pulse period has elapsed */ + if (PulseMSRemaining.RxLEDPulse && !(--PulseMSRemaining.RxLEDPulse)) + LEDs_TurnOffLEDs(LEDMASK_RX); + } + + /* Load the next byte from the USART transmit buffer into the USART */ + if (!(RingBuffer_IsEmpty(&USBtoUSART_Buffer))) { + Serial_SendByte(RingBuffer_Remove(&USBtoUSART_Buffer)); //<--new syntax + + LEDs_TurnOnLEDs(LEDMASK_RX); + PulseMSRemaining.RxLEDPulse = TX_RX_LED_PULSE_MS; + } + + //new Send reports <-- + CDC_Device_USBTask(&VirtualSerial_CDC_Interface); + 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(); + + /* Hardware Initialization */ + Serial_Init(115200, true); + + /* Must turn off USART before reconfiguring it, otherwise incorrect operation may occur */ + // Added for correct Serial connection at baud 115200 <-- + PORTD |= (1 << PD3); // Turn ON Tx while USART is being reconfigured + UCSR1B = 0; + UCSR1A = 0; + UCSR1C = 0; + + UCSR1C = ((1 << UCSZ11) | (1 << UCSZ10)); //C: 0x06 + UCSR1A = (1 << U2X1); //A: 0x02 + UCSR1B = ((1 << RXCIE1) | (1 << TXEN1) | (1 << RXEN1)); //B: 0x98 + PORTD &= ~(1 << PD3); // And turn OFF Tx once USART has been reconfigured (this is overridden by TXEN) + + LEDs_Init(); + USB_Init(); + + /* Start the flush timer so that overflows occur rapidly to push received bytes to the USB interface */ + TCCR0B = (1 << CS02); + + /* Pull target /RESET line high */ + AVR_RESET_LINE_PORT |= AVR_RESET_LINE_MASK; + AVR_RESET_LINE_DDR |= AVR_RESET_LINE_MASK; + + // Hardwaresetup to turn off the HID function with shorting the MOSI pin with GND next to it + AVR_NO_HID_DDR &= ~AVR_NO_HID_MASK; // Input + AVR_NO_HID_PORT |= AVR_NO_HID_MASK; // Pullup +} + +/** Writes the NHP read buffer with the given length */ +void writeNHPreadBuffer(uint8_t length){ + for(int i=0; iState.LineEncoding.ParityType) + { + case CDC_PARITY_Odd: + ConfigMask = ((1 << UPM11) | (1 << UPM10)); + break; + case CDC_PARITY_Even: + ConfigMask = (1 << UPM11); + break; + } + + if (CDCInterfaceInfo->State.LineEncoding.CharFormat == CDC_LINEENCODING_TwoStopBits) + ConfigMask |= (1 << USBS1); + + switch (CDCInterfaceInfo->State.LineEncoding.DataBits) + { + case 6: + ConfigMask |= (1 << UCSZ10); + break; + case 7: + ConfigMask |= (1 << UCSZ11); + break; + case 8: + ConfigMask |= ((1 << UCSZ11) | (1 << UCSZ10)); + break; + } + + /* Must turn off USART before reconfiguring it, otherwise incorrect operation may occur */ + PORTD |= (1 << PD3); // Turn ON Tx while USART is being reconfigured + UCSR1B = 0; + UCSR1A = 0; + UCSR1C = 0; + + /* Special case 57600 baud for compatibility with the ATmega328 bootloader. */ + UBRR1 = (CDCInterfaceInfo->State.LineEncoding.BaudRateBPS == 57600) + ? SERIAL_UBBRVAL(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS) + : SERIAL_2X_UBBRVAL(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS); + + UCSR1C = ConfigMask; + UCSR1A = (CDCInterfaceInfo->State.LineEncoding.BaudRateBPS == 57600) ? 0 : (1 << U2X1); + UCSR1B = ((1 << RXCIE1) | (1 << TXEN1) | (1 << RXEN1)); + PORTD &= ~(1 << PD3); // And turn OFF Tx once USART has been reconfigured (this is overridden by TXEN) +} + +/** ISR to manage the reception of data from the serial port, placing received bytes into a circular buffer +* for later transmission to the host. +*/ +ISR(USART1_RX_vect, ISR_BLOCK) +{ + uint8_t ReceivedByte = UDR1; + + if (USB_DeviceState == DEVICE_STATE_Configured) + RingBuffer_Insert(&USARTtoUSB_Buffer, ReceivedByte); +} + +/** Event handler for the CDC Class driver Host-to-Device Line Encoding Changed event. +* +* \param[in] CDCInterfaceInfo Pointer to the CDC class interface configuration structure being referenced +*/ +void EVENT_CDC_Device_ControLineStateChanged(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) +{ + bool CurrentDTRState = (CDCInterfaceInfo->State.ControlLineStates.HostToDevice & CDC_CONTROL_LINE_OUT_DTR); + + if (CurrentDTRState){ + AVR_RESET_LINE_PORT &= ~AVR_RESET_LINE_MASK; + } + else{ + AVR_RESET_LINE_PORT |= AVR_RESET_LINE_MASK; + LEDs_SetAllLEDs(LEDS_NO_LEDS); //<--new + } +} + +/** Event handler for the library USB Control Request reception event. */ +void EVENT_USB_Device_ControlRequest(void) +{ + CDC_Device_ProcessControlRequest(&VirtualSerial_CDC_Interface); + HID_Device_ProcessControlRequest(&Device_HID_Interface); //<--new +} + +/** Event handler for the USB device Start Of Frame event. */ +void EVENT_USB_Device_StartOfFrame(void) +{ + HID_Device_MillisecondElapsed(&Device_HID_Interface); +} + +/** HID class driver callback function for the creation of HID reports to the host. +* +* \param[in] HIDInterfaceInfo Pointer to the HID class interface configuration structure being referenced +* \param[in,out] ReportID Report ID requested by the host if non-zero, otherwise callback should set to the generated report ID +* \param[in] ReportType Type of the report to create, either HID_REPORT_ITEM_In or HID_REPORT_ITEM_Feature +* \param[out] ReportData Pointer to a buffer where the created report should be stored +* \param[out] ReportSize Number of bytes written in the report (or zero if no report is to be sent) +* +* \return Boolean \c true to force the sending of the report, \c false to let the library determine if it needs to be sent +*/ +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) +{ + //write report and reset ID + memcpy(ReportData, CurrentHIDReportBuffer, HIDReportState.length); + *ReportID = HIDReportState.ID; + *ReportSize = HIDReportState.length; + HIDReportState.ID=0; + return HIDReportState.forcewrite; +} + +/** HID class driver callback function for the processing of HID reports from the host. +* +* \param[in] HIDInterfaceInfo Pointer to the HID class interface configuration structure being referenced +* \param[in] ReportID Report ID of the received report from the host +* \param[in] ReportType The type of report that the host has sent, either HID_REPORT_ITEM_Out or HID_REPORT_ITEM_Feature +* \param[in] ReportData Pointer to a buffer where the received report has been stored +* \param[in] ReportSize Size in bytes of the received HID report +*/ +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) +{ + // Unused (but mandatory for the HID class driver) in this demo, since there are no Host->Device reports + // uint8_t* LEDReport = (uint8_t*)ReportData; +} + diff --git a/plugins/KeyboardioHID/Hoodloader/Hoodloader.h b/plugins/KeyboardioHID/Hoodloader/Hoodloader.h new file mode 100644 index 0000000000..170c602b69 --- /dev/null +++ b/plugins/KeyboardioHID/Hoodloader/Hoodloader.h @@ -0,0 +1,111 @@ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +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. +*/ + +/** \file +* +* Header file for Hoodloader.c. +*/ + +#ifndef HOODLOADER_H +#define HOODLOADER_H + +/* Includes: */ +#include +#include +#include +#include +#include + +#include "Descriptors.h" + +#include "Lib/LightweightRingBuff.h" + +#include +#include +#include + +//new, version: unnecessary? help <-- +#include +#include + +#include "../../NicoHoodProtocol/NicoHoodProtocol_c.h" + +/* Macros: */ + +//new, normally passed through makefile <-- +#define TX_RX_LED_PULSE_MS 3 +#define PING_PONG_LED_PULSE_MS 100 + +#define AVR_RESET_LINE_PORT PORTD +#define AVR_RESET_LINE_DDR DDRD +#define AVR_RESET_LINE_MASK (1 << 7) + +#define AVR_NO_HID_PORT PORTB +#define AVR_NO_HID_DDR DDRB +#define AVR_NO_HID_PIN PINB +#define AVR_NO_HID_MASK (1 << 2) + +/** LED mask for the library LED driver, to indicate TX activity. */ +#define LEDMASK_TX LEDS_LED1 + +/** LED mask for the library LED driver, to indicate RX activity. */ +#define LEDMASK_RX LEDS_LED2 + +/** LED mask for the library LED driver, to indicate that an error has occurred in the USB interface. */ +#define LEDMASK_ERROR (LEDS_LED1 | LEDS_LED2) + +/** LED mask for the library LED driver, to indicate that the USB interface is busy. */ +#define LEDMASK_BUSY (LEDS_LED1 | LEDS_LED2) + + +/* Function Prototypes: */ +void SetupHardware(void); + +void checkNHPProtocol(RingBuff_Data_t input); +void checkNHPControlAddressError(void); +void writeNHPreadBuffer(uint8_t length); + +void EVENT_USB_Device_Connect(void); +void EVENT_USB_Device_Disconnect(void); +void EVENT_USB_Device_ConfigurationChanged(void); +void EVENT_USB_Device_UnhandledControlRequest(void); + +void EVENT_CDC_Device_LineEncodingChanged(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo); +void EVENT_CDC_Device_ControLineStateChanged(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo); + +// new <-- +void EVENT_USB_Device_ControlRequest(void); +void EVENT_USB_Device_StartOfFrame(void); + +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); +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); +#endif + diff --git a/plugins/KeyboardioHID/Hoodloader/Hoodloader.inf b/plugins/KeyboardioHID/Hoodloader/Hoodloader.inf new file mode 100644 index 0000000000..983b3e4fdd --- /dev/null +++ b/plugins/KeyboardioHID/Hoodloader/Hoodloader.inf @@ -0,0 +1,66 @@ +;************************************************************ +; Windows USB CDC ACM Setup File +; Copyright (c) 2000 Microsoft Corporation +;************************************************************ + +[DefaultInstall] +CopyINF="Hoodloader.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_4E68&MI_00 + +[DeviceList.NTx86] +%DESCRIPTION%=DriverInstall, USB\VID_03EB&PID_4E68&MI_00 + +[DeviceList.NTamd64] +%DESCRIPTION%=DriverInstall, USB\VID_03EB&PID_4E68&MI_00 + +[DeviceList.NTia64] +%DESCRIPTION%=DriverInstall, USB\VID_03EB&PID_4E68&MI_00 + +;------------------------------------------------------------------------------ +; String Definitions +;------------------------------------------------------------------------------ +;Modify these strings to customize your device +;------------------------------------------------------------------------------ +[Strings] +MFGNAME="NicoHood" +DESCRIPTION="Arduino Hoodloader" \ No newline at end of file diff --git a/plugins/KeyboardioHID/Hoodloader/Lib/LightweightRingBuff.h b/plugins/KeyboardioHID/Hoodloader/Lib/LightweightRingBuff.h new file mode 100644 index 0000000000..5a9a125c18 --- /dev/null +++ b/plugins/KeyboardioHID/Hoodloader/Lib/LightweightRingBuff.h @@ -0,0 +1,197 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the 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 + * + * Ultra lightweight ring buffer, for fast insertion/deletion. + */ + +#ifndef _ULW_RING_BUFF_H_ +#define _ULW_RING_BUFF_H_ + + /* Includes: */ + #include + + #include + #include + + /* Defines: */ + /** Size of each ring buffer, in data elements - must be between 1 and 255. */ + #define BUFFER_SIZE 128 + + /** Maximum number of data elements to buffer before forcing a flush. + * Must be less than BUFFER_SIZE + */ + #define BUFFER_NEARLY_FULL 96 + + /** Type of data to store into the buffer. */ + #define RingBuff_Data_t uint8_t + + /** Datatype which may be used to store the count of data stored in a buffer, retrieved + * via a call to \ref RingBuffer_GetCount(). + */ + #if (BUFFER_SIZE <= 0xFF) + #define RingBuff_Count_t uint8_t + #else + #define RingBuff_Count_t uint16_t + #endif + + /* Type Defines: */ + /** Type define for a new ring buffer object. Buffers should be initialized via a call to + * \ref RingBuffer_InitBuffer() before use. + */ + typedef struct + { + RingBuff_Data_t Buffer[BUFFER_SIZE]; /**< Internal ring buffer data, referenced by the buffer pointers. */ + RingBuff_Data_t* In; /**< Current storage location in the circular buffer */ + RingBuff_Data_t* Out; /**< Current retrieval location in the circular buffer */ + RingBuff_Count_t Count; + } RingBuff_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 + */ + static inline void RingBuffer_InitBuffer(RingBuff_t* const Buffer) + { + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + Buffer->In = Buffer->Buffer; + Buffer->Out = Buffer->Buffer; + } + } + + /** Retrieves the minimum number of bytes stored in a particular buffer. This value is computed + * by entering an atomic lock on the buffer while the IN and OUT locations are fetched, 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 and so + * 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 + */ + static inline RingBuff_Count_t RingBuffer_GetCount(RingBuff_t* const Buffer) + { + RingBuff_Count_t Count; + + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + Count = Buffer->Count; + } + + return Count; + } + + /** 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 true if the buffer contains no free space, false otherwise + */ + static inline bool RingBuffer_IsFull(RingBuff_t* const Buffer) + { + return (RingBuffer_GetCount(Buffer) == BUFFER_SIZE); + } + + /** 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 true if the buffer contains no free space, false otherwise + */ + static inline bool RingBuffer_IsEmpty(RingBuff_t* const Buffer) + { + return (RingBuffer_GetCount(Buffer) == 0); + } + + /** Inserts an element into the ring buffer. + * + * \note 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(RingBuff_t* const Buffer, + const RingBuff_Data_t Data) + { + *Buffer->In = Data; + + if (++Buffer->In == &Buffer->Buffer[BUFFER_SIZE]) + Buffer->In = Buffer->Buffer; + + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + Buffer->Count++; + } + } + + /** Removes an element from the ring buffer. + * + * \note 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 RingBuff_Data_t RingBuffer_Remove(RingBuff_t* const Buffer) + { + RingBuff_Data_t Data = *Buffer->Out; + + if (++Buffer->Out == &Buffer->Buffer[BUFFER_SIZE]) + Buffer->Out = Buffer->Buffer; + + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + Buffer->Count--; + } + + return Data; + } + +#endif diff --git a/plugins/KeyboardioHID/Hoodloader/makefile b/plugins/KeyboardioHID/Hoodloader/makefile new file mode 100644 index 0000000000..bea89daba4 --- /dev/null +++ b/plugins/KeyboardioHID/Hoodloader/makefile @@ -0,0 +1,52 @@ +# +# 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. + +# This work for the 8u2 and 16u2 +MCU = atmega8u2 +MCU_AVRDUDE = atmega8u2 +MCU_DFU = atmega8u2 + +F_CPU = 16000000 +BOARD = USER + +#Vendor ID from lufa +#Product ID created my own +ARDUNIOHID_OPTS = -DHOODLOADER_VID=0x03EB +ARDUNIOHID_OPTS += -DHOODLOADER_PID=0x4E68 +#You can also use the native Arduino VID and PID +#VendorID Arduino 0x2341 +#ProductID Arduino Uno 0x0001 +#ProductID Arduino Mega 0x0010 + +ARCH = AVR8 +F_USB = $(F_CPU) +OPTIMIZATION = s +TARGET = Hoodloader +SRC = $(TARGET).c Descriptors.c ../../NicoHoodProtocol/NicoHoodProtocol_c.c $(LUFA_SRC_USB) $(LUFA_SRC_USBCLASS) +LUFA_PATH = ../lufa-LUFA-140302/LUFA +CC_FLAGS = -DUSE_LUFA_CONFIG_HEADER -IConfig/ $(ARDUNIOHID_OPTS) +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/plugins/KeyboardioHID/IMG_5687.JPG b/plugins/KeyboardioHID/IMG_5687.JPG new file mode 100644 index 0000000000000000000000000000000000000000..c8aefcc81bbd802a4b9dde9b48ba6e303dcf02db GIT binary patch literal 73455 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 literal 0 HcmV?d00001 diff --git a/plugins/KeyboardioHID/IMG_5688.JPG b/plugins/KeyboardioHID/IMG_5688.JPG new file mode 100644 index 0000000000000000000000000000000000000000..87954a7ce61dd9d08d63dd0119f5ca98a3a22154 GIT binary patch literal 74968 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

    3TdlVRYu1)7sCWI7!Z zdebldj-y=i+M=KSMyj>6kCaCSNVjKT^{YQnta0>hv|l`bq<>`h@*1wJt8U+^-W``| z$9{b(lKFeF*OlLG>0 zXwGL;Tz={A-sbsKG?42I41f${z-jZFE`APd! zo|+QogO62`3apZkRFVl>`#rmOiWKc!8gVuIxTIqi$ocFunuwKxw%!}D-AHVA9R2Ap zMUD3n@z>^ENRq$TFRv_aEkec;Rm01JoMx(~2So}w+vUwkk)AV(ZIm*c4s*t6Ej%Eq zDuFFj@;j5ZLS0A09lW=8$9jvB7RGt2HOxh%ZpWHr+W9t=8%H@5scDy?b)EW^v_ZRZ zT#8?WLEJD#DsD>qE4lIo<2edSrB1(MPVz$az0aNX6y7k)-u6$*)BYvfQoF=hd-O58@HL$((s}p45~{ zJ8vFS=xXani`5nUc5iY%ICWM8HS=-k0I4fyxP~AaSsqVP)P)bc4gUa4pGt6m8ymUz z2fbc8d{OBXmaigL+M#XH*oAZrr18rjD537SmrV1O+GaqjMI~s zW0vzsWeF;uD9>t5m2 zxhHloC=CkpQnb|`Z5}xq;3EyHGTVJ6YSy}=PorDQJ;KI!M;aH( zdgKpEtI0TP#RUW77U1B>e3iA6&YgMwIR)#szg3QGLK7iu}jp+`t z)b+h>wM%;yHx_VgTT4L1xGlK1IXn|wWS;c+{tnw~W8_y^UTS)tq}O`Aw3fFM4a_G} zyRbbo_5z_Ip58Etc>WoFMhBbe_NmW^9Y?Ne*H){oTS;v2N47X+i(%M#%|+i|TU^*j zZuaqskSdu0`L>=bzbv_9jw&_#ba1v~d1bk<3DQe*6pp84jpclB-uS1lB}ZivZe>;D z2L^+?z22z?CXil>e##+z#GAcj*>yV?mDNHM#SlS*eUc*&}7pzI%-^uIYE{Z4aK^CI0~8a!qU+cTMQ}mqNz|)JKMA z258_5DGTN0y+QAasZY~-O^o+32=3(A*cp*mIQH__IZhAI>1@clWjexmpms!nyGxDU zFE}(U^~9GtgrPGWYT5tQ!qH>liIo$nMyI`kmw2nyT7N_x#DMyzG~6>TcK?A-3Ly-S!9kznU>{q z!zgTFc;Mott^OS8SBBbaX{HdR#F5Uf*)FR4Mh-YQ6!o49hGz0+`Z4{)HL z{a_sZYhSbYb)()jmDDdNx66s+FOv9TqX*NqWw*BCE9uhTJ{m~De%YsEn#p^81(Qht+ES<4b}u%6iab5lCMM`%e2 znJi2W9xby8*}PKBHz@@1O7r9Bhb%H^$lK%vm3M!H8e=cJ%BOFyHM8FI=8HAVix!+> zHkXk?-gaRswlX>U)OM$%X?kUa?aHne_7tm+NgYBh)PyP1B_OMb)~<*0#t_ z*7fqyeH$L#15><@O#D`%Zt96|EPK!XS~8kZPuvO*brr|4xf@U8*q`u~{{UJ;Y1beA z`zJr*TD)2twCUNeEVMYJ)FinnEwe-qhCQ+AR2lEDd}bejWjncFYP25f3tK_%?JpuH z!Zy%i-z*+wjxKWdFwaT`h=F@xJaYLL_rrim8s->UG*eE$F=N|X49 zL!x6{ES({z5P56%ILEToGD_3jhmb2A@wilvP;dVLX0+Aa$+?jC`U-=N5~#B=!WO{W zRFn9Iu8lXPo>b^=p#T)~MmGNdXQ=1$6*S@b{xnp3Oln66 z!y>z_+QF>Z*<0U69W0rQKjGcne=2$yOYBf_`y#VqSsdlRuR-}x0=)z;6n>D?e(SPoMY-c9w|%ElaTH5Ml+s1wb)`&hkjeoRF;FK!*eyby3}pF zTbN#DSYIYQ4i&TeMytBqSDIf?NeALXq&em=RN(z97EOLA@Qv{B?2_e^HjLkmONg=h zvA8RNwEKga5_J+6lXut6QE97P+sNJ&kI3M)Bx*N#-ehjv=ZZ@47+uik;nS+JRbmYp zCkH3JC_=*u`0x@zM(Oiv*>zN_Ovv(EgC4^;zy2ICu|PugNzeRkBDP^ ziI;}uT@ii&-R?ypAm=-~R*S5BHoUf$C@n9o=eY15c~P7oR1dexPjmFF?Pl;Lk_Q9C zU)odJv}4pmFUZWfwApcUGDWh`d{N4xRT3UbAm$tmqP0+?R@P z8D);)Jj7rSRF6<|{Hcv51+cP67cQuwd-wX%)@k{!EpT1KAC#qk7qC=pv;MVCC0|Ny z3kHT%AuzMAUP zb2Kdj;N!~J{{Tu{kVJVVjJea)X|~hZx)zdS6o^MEF~c9Hdcmr3OO$WYx4VGvik(?y zt!Nr8j-7JzEwdSAM~tg0l>-^}?@@mYb#KreO%46t`)CAgtFd$6xAUNGE#gTKjfH{z zn)TwNItbg5-2VWjV}_0r<-QGb)=hAcYxsfH_Z?NLtkUxxx|pClaCT>m)k&I7s!niw zQd)lqZC-e$4byteF!?ouf22Dhi7U^4z8v;lRM8A!IvU za7P=x=zkSM0;dPwh@Nzk+dsGOK{QRQbSZB(Pc*o|N6GnpN796X>6og8-I2f?n&RF8 zxnCR}c*ZF1NE;>DAuK4%lrM~&mi6a~8IVJJ3#iW08kCnRIAU?>U4_lv>`_EOE_V5- zOKV(~hU?(Cj<&he_pP*sOJ?Wr(x+qJh7}Wi)K{0+w-Z^Hjczu(p~uaP8jI>U4w-b2 zO|Z+cU&?qPhG~myv_@7s$Q;O-n0Cpm@?_C^CbdMls*D6{hv>sbK>o5!#jU-fuFV?VOJP09v9! zI=<6_N%W%9MQf;`E3i8%mLs-(YU&tkp&n*yq|0ud*LuB$qQL;SF(W%J^vUybeSOVE zL#j@6$?SYMj1$ZzEKqL^^lxf!sBGiW?rmYWoi37iyiMo_my$4f@5Km{ssIXkyVaML z)uq`b=G{oLU-h=P9qEN-j6iLLxrb+yZauyJv{YSFtWRw;(oYwhASz=RJ3d@-!K%%> zLw&8M<7E6SZQZfDr8<=??6i^kI`Ca@lP!hD-YUQ4T8({%uQjdL!6SFoTIQ@$8_S~+ zQXB+8o?+PVDHr`+t~}70^%BxsKIqD-_r^28=Bc*VG8mI7!5#BL-pM}p1#&$wc&jfh zdLph_8GK%_*DtPO4|vY&m0Ti@8^5Iis&&QYpQ_sFv0U6G#j4>Lc2IpPn`J%BQ=`PY zWDGXo)sJ0kd9M%ae93weKgb7shw5uqa-EdVX#@FVc&5jgq3RIR)7s=3F| zDl%oNE12%$+*u^gs?f9C*;@IUA@!(x8w<9*4+O$6{$JSu(sj)q<(u`BmSyfY3{+E( zsCLL{wd)ab`=Cvk`qM`G-b1}0hiUCd8W@*rG?T~2%aOK}oi7`%<&yyVc(lJYUjq~w zov+R-Wa*2APM7}x7l&BLBYM`m)1V%n9R9^(j|rNZvWIgsyo@vZb!X8}{-U`50EE;` zmQWUAS+klx-1vGt;XSJGd_7jjak2F)B+DU zIqy>!jK88G4hZI~uO0>J=ZMbhx7B%+hE03XFy)iOFXic~3Pj)i)sM z`bs2dn0ZN%FPXktu6S%!Sh2yXKFh9+LqfVK@at4WBrDGv{{TPvR1TB3@$i;h`Nd7? z3m^WCuB0#KdD5V?*WY_?oDHweJ!^g+oqonV{{Sm2QZ6aa;?qiRg2{cULu?0$FXd1=?z{Ni8fa}ANbdYZ*n4F;&p*P2 zeHT-o&G>m6^P%U^HAGzg3V-~S$<*uRk!_C%>*@3n#`iUBlIh)U>%_OSka&`Q)8?(w zYIdyaystfg#b&m)cXpSk)59!Zb;U_SyJU7JoO9;wS=O&2Rc5ck<8J7`PkCnxvcAyZ zbJ&V+@s?yU-kWNNGl?IDV3_8dmIsNj%t$@4+O7D>gYcNmD@=kr{{Z`At&e6`clW%IGAvzMyIu;g$;&B{8U+&rWB zb4e4fed!(&h2z$To*kofdB?42wNzw`Re@d1%p@7@Ro2IkmhGCHyGKN3Wx_b}=hmR) zkwm8+ja6Y_hX4-?Pj0Behx`ftn7xqG=LcJWzF88;`@Z-aXOXm*0(_H|O57ZCcg~OQ%?F zMEed5tBf)C6@9t6=ydVnTYHtYdvZKz8zfD<_GbN^xUA1rme=vJi#Bh=?(zfeU2GGY z?*9OKIeNIJmqNKJGC;}BeQVDvCPYM)?ac#~W%9RbWZkg9Q~6e%{-y;0`7R~Kz6ze>$tpv|_`32DFcY82M>QdEqacpQdUiTZawpO}x&%h&inD z&ZIgxTtcS2ZOp?s&S-SK-7skh13cr}hMH$+$ZTW30)unGtn0p#b}qcaqNRTfrXLFqwhcX2|9*FW5jNIt(xZueKPzSV!RTFGw|kA#h7IA7yg z9$9;v7AS_gr;C7(fn1bDkU(HPIjJx9eq~=Sn|S4i&XZ(Sds5SN4L!@Hq&B)|uy&y#k3=;nUN&?)+bFD<0czHvwnmHRB{p#ob&Rzt^=#tyH z{`HMj=W!2}61-9w3ZX0;J?_79u5yIhnf=((^rZf#lQLtGfu(y~hgPqNj zpS2Tz(z?q*wKRaB@#Ne{s`>3c!{tP+l-QfLkGAUK$r~pMHxF}OywEir8J6Q$vbv7X zb{WEuDLpM^CZ&0BZA1+hiG>sQ`cd;`S7h?z>^!rm`IHaNlGg=fNdQoLj2gHBIQoaniA|SM3zlM-_7&&Wd|jeI zn-pP9Td%$tbuH!$kVHuBwL<>@N~U$EP2cp_;q7%xPX6)5JCd`G{JAVqDy7*PpH!51RE=*fWZ55KsqQYeDV95c7n02x;)5E{k~WQ; z?Ox{{>tC1P=BIHM4yiE=JxdWlUi=T#ZLDXO+V(Rdp}=Ufx`cB%2V_jj&F(LE3pAc! zhaN@E7|`Cvq?;SkF~QkR^qq?7b4zQg+FnO;j#L=)wX0;(z7;O5r$KuK#mGsMa9zjC z{OU_9i>6JnqX#;JG=WkHLB}}mDf&j1c{iC(YuZ+X+92UioZN*^%CN#9Flz|N3{97N4R}LcDJ?=tc%~r zlVwgzrryI3o^3RL{!cY))%r#*i|Q$3vHTs~te$YU50+E+tq-DfJrAfXWs_1{7-dH7 zyV9AFWP?ek$rFo5&#$Rp#V>-ZZpx?T_x$PI8uI5`yYQltD^Q)oJxCj;?`>nUm3K62=3UgtW6w0|Em2n}uF6f;g{bUZ+Rcv9*+ef@ z*~X}oIt5n>ak*hU*U=ppdDHjM&-!M2aVoczk&Y_OzoLKr=Gv(U=9f`ywZ!-ZK4JH* zf2UY~v+57-Rz(;0i(1x*yL1eHf~vYKR%dTBVEUSR8GrRu!|6dzd1`t&F{a1|997d7 zBtfb3W8R#{siYus&FxMilisZnY?9O){{U8740_Z-Zakyc+NCeqmcrS6IjHp7RYoz6 zYOk{K=p(3OW2R{#RI@jUjJ%QzG zZXcZ^CV!QaT9nys>JV-pDE*q`g_$`x2AH@TM(*Sqa$GcHkG*xSjx$zAUpJJD;}jN> z3u@Nc{{Y&L>rU$T5ZicZD{W~$T-P)pA6m8TgD9?Mt0HcZ)6&7Fn?|E=G;l4%o(}g# z8xOJF-mIDp%iUYMO8b3xtkbmNGvJ{{T9+K857;5de>V z7@UunKD8o>>oINd$nJl-%}1b7a0cQ|eL2MvfXTXMj}AL-ZvOz4T?;MUA#&>$qaq!S zLXHnB=BXL4bxUnUrH@s+-TS6f?dec`4gI1mL>w>5N&M=`_!hspk~NW4qy6sH($Tmi z+`SAMw~;iUE>5i1uomL_;^HE|Bgk89?`rTCiW#x=cWZAKW@Xwel1lnjmB)Fg^j4Y&io zD2-au>r1tcTeJP^5x4e+C_fch7oWL#g7$m9Z z%(TaewbPD0eze8b6z`8dv)vm9r%{{H0cAL&} zFh8Y6PiD-D!?iW|76cU-u6(e1q;zAcRZWslbRYF{W5dWhN4H|A=kU*) zZAG<|-?RDCM#@0hXEeVmUc(l6`;tOej`_CDy4@U@o7{S4teror>3VJ5gX%UZc^pLe zis&7C{^{>j)Ifs_OMU5T&5S4&WsbW8&+KcH{6x^@mC?F>+FM`3m{KP|svmhf_K#k} z@~qnGRV>XG?&r&n!lLD7!@FXivgzN}g7+98{?Dazax7N7A1t}eNL$Ua z;4mbqY?{vdH6!RRh8q5Zr}Uf_x~0eVxZSc?WaH9{>#cL8buOB_v{qSKMd3E`O=F9; zRSbh*BhtLl>JPjGjJ~jQmd;2T<$3ibxo#;LL|hzxUhoImXp!OMPoWGorRU~oFgDpkf_H7r%k%MV;TF`zX1sI zZ4_pr)g?sa*WviDqYGGp)0=vz2k%L5i<(~6156^a7PCg|Db%ruV*VQuCQBc{B&g50F*RN`FfwOvHOOq?3c#p7+)&z^wuxqv zelcKqG`K3A*L`TcPGB=>@Gpa(+090qDE2AZF-{9Ogj>}?HG5S`DFADvI-Y);zK-I? z2+rTw+s8F_e~db@`7K}v{tBo=W}M+gI+lAu@`L$MjYrXa3E45O{7%*NJvLiuAc!OJ z!gi`OH@7QzvqFVs?mU%cOF%KXMk)UQ!$wD7O&Lpn6b^&q_?^_t0-<~|t~gp^e~7(N zBuu_DoQ!<5+gm7$+L!oHRX{aml2PGT(GrnPmTgYvcAb&SGj26y(>j}|?QE6^t}YTa z9$Xqe8-0Z31wRF{x0Tx-)l}M+?^0SKp=w3}Ua7|d{7yixiM^(FW%VbE^BlX3TR#ZEyE6PhDq zdI}Jn3gF)GptB#n^B08Yau8ZlVQ6*EA$<={@QQ+)hd6( zP9qJYDl<`9>4S4VL4%n<9`&v0>cc?CZzW{VF!7L&de}6Qqo(X~r! zYi6+VL)^JIL_N6mt=K+u9(8eG_o=n`Yy(cpc*kt^q+NNC7iR_z4qKnrntnVUZE`AkqmQ(GebiBD)_NIh zduu41s9oL~jB!-{jlG5RO>zsslI4I_Z?UhREqaqsgiM!HJn16gceiSK->UU17^IHU zKo!1Wx4kiFlC+;?7OoUa{6uKX7IE$JDmVatty5!dqaL`Ub=_|3Rq)bf+Y$~HN3X3# ztK;dOJJ#Jgc%Y)rcCJy$k;)*_i^()?#+!X@8@fMbsJBd_Tf zIwqwho#O174?I+JsXPwe^;FYb1;xeF5aathGLGK4p&0(Ck=}`)hzRdOImAY*F^~wF zK-QM(JMYaM3;AOh8O=t-OFg_})}+)Fl~DQ`&igbji!=d_9Q?my0oM2HFqiwqV zshO}_wgp@RF&{4;v_Wzc6w_d10+I_1oKUcZMA-8aMR?kywyDDO)fwM|voOQbgfK-){7{ zqbxY!de@5Hh$TkThOaBRHoG zlf?=wga#&sk)SQ73P(6TwCpi`G4!X}*rMZllb_i&A#Z1lw1+2eZ)!XM3Oj!gb~qID zc8urBha#md&@4-g3QF$Y%&mYZSS*hgtQ-T9!?>r60LSG_H5U%&XJ;6$q06bq6*&ch zLkltUFRdHk5I&Ui;BDM6X?|U;-i@#fcrCLk1$iTo5k*81Q`dDl;3)Uac=mk#CKk&3mIp$w&a*D^aTCP_C*gI?f@wSkLMgI@74ep*KC4>0`e zxiw@1ks|iV*Zn1pG}b=8;>TAxr~iC zRC1|nu1Or#miFBjNerjbthyC0%Ay7@jL~tSPnA@(?3%~Jnm1-b4|Gge84qT%F8IwEZ36FF85=e!jzYiFYQxP#jxZKDXOVr zPF-H|NPIsX{69qokLcE8tts``-_onKW9UZNt|MbOR^p$hZRL%L)PJQf(7IgB{eA1YhC`kH^wq)KFjYs|yKS5ZuW%`38yjly#~}L9cGo7_^(G6Qhd8IM zNdm{&gL3 zaLO>F*0MTATuVEuAys^pk@yW!oi6)rCOd)gBt@<3r*5rQQD-_Lyf6OrjAPRRpA52s z_)w|gSsx~3oe4d}aHzP4dB#XN$4#f!=L7fd(=xw z?goCfYxt1Sy!NFC+`E9s?*9PRYLO(L{i}W)yP%}|Ir@w$6WW5jU9zb-%6~fVid~8H zsP=3cTr4*Lc&ogg!juIwy3fUS;h3tQ=SYy|X2p7Al&hZP7!H#*CN{DDRHAnt@Xx21LbdBYfovvEk-htqu z$>TrDuUhX~=y%$KT;AAQNoeiJSb#al2aany>FBMb*KAWz3T+I7#SCx=`_;#)G#-|{ z)cid)*3Q~YuqiI>qz>M1turE5Z3@GCX&L6FG;>~0CAI`xvWh*Z4ey=_r|zO#d#PfL ziz=PDrshJZ4?gsp8AaDa>Ki>C=SZJTBk>SL`sWLh9QW^6Zm{dvHO`*8x0>o>EXoGP z9r>(2)fpXGTzk}m?wIb8^2V76r`cI#X;MP*5Ps)vZ~YO~&wJAr@mp=Rg4#dA_;K^Q z0A;^A`SL3_nn02A$F*BJRcC`wmN?n>2~KuZ^2(7+5l!+l@m%V-rtMtGDsDcwr4BD}0$^WWD0_f^DmvXivneB;v^?8F z;QH0dg5ZPAI;amcqJ?pTnt37Yc{%Mus3#EtAXC$_K?#yZ!1~knkv9FKwLxoBv)oAs zWm8sM5G{2m3iyXU5aV@8TbSmL#D#+c>a|I^d@jMl{VGqQFN$i7X!$Y9J5*EVh}Q+6 zLgy{J2Aox8z*FDT6#d$&$aZ|bl$a0gcEw(bjyz`o@m`KL36}S!mGF5vr_uMX&A|7g zL^wWd?c`F1UD=Z#YI06gV?Dcyay3;|Vc*t?1Y5**Htzn^OnX+{qvLjSOzn~PGM~07 zghd4dW4`~!~s8%?lX0(Ym`N;-{2#tZq3kids zMMhuK+E69TiY3~)9J*J#i z-i_s5%ie>@-MWf)27?yYbbI^LQ$yjXD@5B|0KV19Cs%H9x~`Lbm23yi=}QqY8Rop< zvRfQdM3RBVe}!I&XUSIl+%G=0t=ljE0Ee58_jQuljNC`}t$94XHd~+W>k8=B*`D^B z>}%S-qawtxt9gBCxn<0>2BJrcQcSE+i6+Ims*YclG&xdF(wuB=Pi#{v+oV4Esuw#V zGVsF~rnoER{OG4|5Jk6yUz&vD#&W+YJXAyxAjU`2nh=UFYe+nxmL`j}&@~Iz{?Bg5 zJ-2a0ggse090t~KfA(!%Zj08HcMEOb@UW?FnCZ<^PrhmIEnXQ5Dbzl2bU?y?nc#;FpApwD@|_u zPZTrSvNy|C#kE&P4BJ&kK=(8xwwsS*!KKekUOKjl0% zk?GABon$Y%n>SMljEO6TKD($5R@zuK7<>stkg_W=U)es?QO_KTwj{YGNj@0!UR^VO zwr6iPc{!;YeR}%S{_8nL^+4A7yuhzGsnX!9xjsb$oSfHFhT@U+r7xJRM8QLxc&Q+z#9s6D2Is|he!v2(|iC_l67nyA~&CA)a2?H)Ta zoEl(ix3SJA=b+HIAbqg6ue-a+O@+Wz&e>6Xi3 zqCqZ^9CryS2W8JW$2E^2Rg4J^Da(8Nm=4&kU03`pX_JbV45lgUY_ohv({6te1?|Ux zj$#%Hx^~7-Wfb#VOK~Y{x!z6P_Z;SxCYZMz#f(rqmRwY1!zodxT!D5C0A{<0D5<+_Ea(@XH3Mda zZf)Bb1e%eyU+pQLeDtqTriBpx%!ePdLyL0ELEurg$-31>dkXTd);{#)R2AVI4&&aI zA|MPODD! zJ{}3c_NQV{s(8rHtr83H&KRlS*Ht{2CW(xBay!uSf=ZI0Fz-YMLm1-(F40f2F#!5{ zQg$g-Iql6j(iX?^pnw;qLcSvI;DJxyE3VcoGEM~x9LIkgW7eFMnRf3vqg;S8Wh)F# zkPbUh5+RX80DjWOOkw~P})H2Q6K9Dd(%6BVztN#L(etWlW5(H`_ZZ( zhRXe^#cU3Ljd|lkwflzcU5pkO{uDq_)QH#X(qRk|V^{6i?)pDC|+#1BdxnvuS( z*(mu|&p(Jyy=*D^&YECH`?|<1LmQ~T@4K~a>22Y3!?PdvS*&S%EYi%LXt5&?;ZeGP zJ~lmtOHU{+c;=#SSec2Xu%QSKgSe^x01wuhRspFh&Zji$+wb$Q@SqX30#r6^aiYYUr)(+p^TzD_Nv|0&*8Nh z?Zmu9#d1GttmQzfAm2#~a0AL2v6ji;Q%W7a0e7RMIvW|L&+1InxBZt?oY$x_757Ifx{0Fy2u8{)$OcGt;-}&# z?nS4@y$dFX)R5V9)~#c4YaH|56fw--G+R&X)FWycJ*akz$)DM-2&2a*lS9ssUKla) zeV>?8qPh;jRZeJ831) zaD8cpm6ApQLHk!;;j%EMi<)SvgNv}ZauGuwamlA247~Qu2^`tti(-5_d>x@PO);h$ zTLA7+T~C{eLu55AP7Zx2HUxs-4K(~<04Q6za|$nDrkwFtY|TJQ`@MXl)~PAb=)%PD z@7}DP1*1i;^)05KJf0kL6S@7cGgY1GyRpaKrn+t|Q7@9`O0l_?MEPA%;*|0#Tpj8k>rKL zs;JK()!SH~sP)_Cy-hCeG=DbLLII`8sdngeV?aG=p=p{Pq+qbTl4$lE_=QOgkEKLt zw?lV^%t1Y=zM#{!cALe#vbs(??5HfXc=Hu;{HVrMM!7Az))!8b&))zFtzF}0SG5rrXVvISPu5LnF^!r~EOqC$(ux(6Bd;2g=po)*v2~Ud6z` z{OioTU<}cqgZO2cUp!Y174yz0g;v>sDYF~r?NJcpyFT5jFgw>&DL5<0q7vL5bAl-` zjqwr}kZKTOG$64*DWgrdl@9|nGdWG5udP02cJdQ|D9{<{m>xX`705nsd{Ux8BIgyv zjHx8?LWmK+%Z&3*t{8KQ6+(qP^H0Frv600Th%dsx&+?}dJ{3LayFN?L-6SGq~osQ_eZA+)R-ucV#p(-bX8K1a3X5Qy^Y) z-!*zv^5i!(JASTQV1}#9iH}=!NCf zekHxUvPRvQEk@LPV5Z3hxR-#fPdw+s<^0Bjipx>(*A|lQ_QgZ$dfavw4{v)D$0GU~ zk#Uzyjx3*9-)=KqSsx!Y383%REezIb8Al&AO55odo6n82Z_%ocBonJ9#=!|Y#W>CR zR8G67E`@lJT@Asx8(N6z?LyaId1Hb=o*(a18%bLR$u<{}?@2F5of!wss359$TFf** z3>*kjd$u)MGfyuk0T!le@>gaJtn)r1iUPPW;;6-mFXCcKW&g7exO6_`v@F^P;Nr zE2LRsK3UUFFXI0Ij<$=IKkUKh{ndKCNsszvpJrPsg8ci`P1An0js<$XNqv?>QLh=P z7%SE4gk-g-%s`qcRBYsCy*@-pk^&Fmsq7<#NB**Vkh!aRRk4p7=s=$UNjYQjjWSV$@k}l8(HR|;R(O?^f zBH@&94>Y2HBYOSo)#_KNbav4d!){UE+LJ61GdGZaRqFK;tYM)}R~%6G@gW?odc9C3 zr$N(gfLZotMI2_UT|qmW#wQuidi8pW=pLZ9081MdA1}2T6})n1c5Bt@46un}SmIV* z=9Wk5L9bV-__}6ny^J}>o7R`zMS8tfeHBBIE?}FJQIa1%J*(B~M9mO34}~2kq+aPw zsb1UuB6Q_eQ)<#+dJg7w2syoLB`aIyyj|lOZ^-SF1J_+(|Xa z{ks(t0obK897}GD(dQ)BtJR=TqQ}AC`%O~a8Kzt6`t`l7=KlZ*&zoVvuUD#*=rKNr zx6pLHow8A;SwfAEo!4_8&ZF-&yS0le;g9?^>h&`eQ&!Ok33`_J&EdLRx*tZ4hw3h$ z(=|ONOS!F5Il#{7e6{NJT5(Bmf{boxmMf_vTJ(`3@ocBqQ80P!Nj2*AYF!Fq70xT3BOKSO)p8*#BM8{~ z=9A*LiRs09y+DGXnb@43^s9Cu+Xug;dc9PAmybZV?!lDinzWhTY%$Jj)#|$Ft1O9Z zz7k>FQ4(qKehH4}$gfwaO|gj-tF2Pz3zkG-v>#Ddo{Q7r)pWBh(S7@|`7nho&^(y`}#E&s1-S)~Tb(0@$;r?)hr)DpEYa6-0NJHoOWEJZ5J}voRU7tX% z-v&1DqR!F#G!CPGBv!NRjxUh@&3e646k_D96>Xn4O{(2CrFWKJpFOL6=uK|vdREVf zxL@6`SE-IFS!tkT;sLjvQ>ezLZ-f5;lCTcB*DtR6mgY%j=e8HMdc9keaj{tQ#T_?XYwssF%s$oX^i#MUns6MuPN} literal 0 HcmV?d00001 diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md new file mode 100644 index 0000000000..f9ca1b78c1 --- /dev/null +++ b/plugins/KeyboardioHID/Readme.md @@ -0,0 +1,164 @@ +Arduino HID Project +=================== +Dont you always wanted to turn your Arduino in a Generic HID device like a Keyboard or a Gamepad? +Disappointed that the Uno doesnt support this at all and the Micro/Leonardo only Mouse + Keyboard? + +Introducing the Arduino HID Project that gives you everything you need for that. +No need for extra hardware. You just need one of the Arduinos and an USB cable. + +Features +======== +Use your *Arduino Uno, Mega, Micro, Leonardo or Micro Pro* as Generic HID Device and still be able to upload sketches how you are used to do. +This project provides a new bootloader for the 8u2/16u2 and HID libraries Arduino Uno/Mega and Micro/Leonardo. +I also corrected some bugs in the original sources. + +Software includes: + +* Arduino HID Uno/Mega library +* Arduino HID Micro/Leonardo library +* Arduino HID Bootloader +* [NicoHoodProtocol](https://github.com/NicoHood/NicoHoodProtocol) library needed for the Uno/Mega! + +The following devices are supported: + +* Keyboard (modifiers + 6 keys) +* Mouse (5 buttons, move, wheel) +* Media Keys (4 keys for music player) +* System Key (for PC standby/shutdown) +* 2 Gamepads (32 buttons, 6 16bit axis, 2 D-Pads) +* 2 Joysticks (2 buttons, 2 10bit axis) + +Projects can be found here: +http://nicohood.wordpress.com/ + +Installation +============ +Download the library and rename the folder. See [this instruction](http://arduino.cc/en/Guide/Libraries) how to install new libraries. + +[NicoHoodProtocol](https://github.com/NicoHood/NicoHoodProtocol) library needed for the Uno/Mega! + +*Always release buttons to not cause any erros. Replug USB cable to reset the values if anything went wrong. +Connect GND and MOSI2 to deactivate HID function on Uno/Mega* + +*Arduino Uno/Mega only* +To install the new bootloader connect your Arduino to your PC and put it into DFU mode. +See [this](http://arduino.cc/en/Hacking/DFUProgramming8U2) and [this](http://forum.arduino.cc/index.php?topic=111.0) +and also [this](http://andrewmemory.wordpress.com/2011/04/14/upgrading-the-arduino-uno-8u2-using-flip/) on how to upload +the hey file to your Arduino. Some notes here: The Arduino R3 doesnt need a resistor or so, just connect the two pins near +the USB B jack. Choose atmega16u2 for the new R3 version. For older version you need to check the links. + +Upload the hex file to your Arduino. It doesnt care if its a Uno/Mega/Mega ADK. It will just work the same. +Unplug the Arduino if it sais successful and plug it back in. You cannot destroy anything here and you can always +switch back to the original firmware. +You need to install new drivers for that on Windows. Actually they are not new, its just an .inf file that tells +Windows to use its built in CDC Serial driver. Ironically Microsoft never signed its own driver. +Also see [this tutorial](http://arduino.cc/en/guide/windows) on how to install the drivers. + +You are ready to use the libraries. Just have a look at the examples and test it out. +The libraries will work for all Arduinos listed above but it will use 2 different libraries. +On Arduino/Mega you can only use baud 115200 for HID due to programming reasons. Its not bad anyways +because its the fastest baud and you want fast HID recognition. You still can use any other baud for +normal sketches without HID. + +For Arduino Mega2560 I recommend the nightly IDE. See Issue on Github. +``` +https://github.com/arduino/Arduino/issues/1071 +http://downloads.arduino.cc/arduino-avr-toolchain-nightly-gcc-4.8.1-linux32.tgz +http://downloads.arduino.cc/arduino-avr-toolchain-nightly-gcc-4.8.1-linux64.tgz +http://downloads.arduino.cc/arduino-avr-toolchain-nightly-gcc-4.8.1-macosx.zip +http://downloads.arduino.cc/arduino-avr-toolchain-nightly-gcc-4.8.1-windows.zip +``` + +This library wouldnt be possible without +======================================== + +[Lufa 140302 from Dean Camera](http://www.fourwalledcubicle.com/LUFA.php) +[Darran's HID Projects] (https://github.com/harlequin-tech/arduino-usb) +[Connor's Joystick for the Leonardo](http://www.imaginaryindustries.com/blog/?p=80) +[Stefan Jones Multimedia Keys Example](http://stefanjones.ca/blog/arduino-leonardo-remote-multimedia-keys/) +[Athanasios Douitsis Multimedia Keys Example](https://github.com/aduitsis/ardumultimedia) +[The Original Arduino Sources](https://github.com/arduino/Arduino/tree/master/hardware/arduino/firmwares/atmegaxxu2/arduino-usbserial) +A lot of searching through the web +The awesome official Arduino IRC chat! +[The NicoHood Protocol ^.^](https://github.com/NicoHood/NicoHoodProtocol) + +For donations please contact me on my blog :) + +Todo +==== +Micro/Leonardo library +License!!! +Remove debug leds +Add more devices +Add ICSP Programmer function +Add rumble support +Add Xbox Support +Add Midi Support +Add Report Out function (for Keyboard Leds etc) +To deactivate the HID function bridge Pin x with x + +Known Bugs +========== +HID only works with baud 115200 because there is no "programming finished" indicator. If you dont use HID you can still choose the baud of your choice + +System Wakeup is currently not working for Arduino Uno/Mega. + +Not tested on the 8u2 + +If you get a checksum Error after Uploading please message me and send me the whole project. +Same if your Arduino crashes and dont want to upload sketches anymore (Replug usb fixes this). +These bugs occured while devoloping the bootloader and should be fixed. Just in case it happens again I noted it here. + +Version History +=============== +``` +1.0 Beta Release (03.06.2014) +``` + +Licence and Copyright +===================== +If you use this library for any cool project let me know! + +``` +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +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. +``` + +For Developers +============== +If you deactivate some reports it can occur that windows will cause problems and recognize it as different device. +While developing i had that much trouble that i had to change the PID. No way to repair the broken windows driver settings. +So be careful if you change the source on your own with important PIDs. +Therefore uninstall the divers for any device or just dont touch the HID reports. + +You need to install avr-gcc for compiling +``` +sudo apt-get install avr-gcc +``` + +To uninstall the drivers on windows you need [registrar](http://www.resplendence.com/registrar). +Delete these entrys (my gamepad driver with the PID was still broken. If you know how to fix this message me): +``` +HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\VID_03EB&PID_4E48 +HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\VID_03EB&PID_4E48&MI_00 +HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\VID_03EB&PID_4E48&MI_02 +``` + diff --git a/plugins/KeyboardioHID/examples/AdvancedHID/AdvancedHID.ino b/plugins/KeyboardioHID/examples/AdvancedHID/AdvancedHID.ino new file mode 100644 index 0000000000..72e8106dd0 --- /dev/null +++ b/plugins/KeyboardioHID/examples/AdvancedHID/AdvancedHID.ino @@ -0,0 +1,125 @@ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +Advanced HID example +*/ + +// The protocol ist still needed for Uno/Mega here +#include +#include + +const int pinLed = 13; +const int pinButton = 8; + +// see HID_Reports.h for all data structures +HID_GamepadReport_Data_t Gamepadreport; + +void setup() { + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); + + // Starts Serial at baud 115200. end just ends the Serial + // Make sure to end your special HIDs before, this does not clear them! + // You need this baud for the HID library but still can use other bauds + // without HID functions. + HID.begin(); + + // Sends a clean report to the host. This is important because + // the 16u2 of the Uno/Mega is not turned off while programming + // so you want to start with a clear report to avoid strange bugs. + // its exactly the same like the end() function. + // You can also unplug the device if anything goes wrong. + // To prevent the 16u2 to send more reports just pull the Serial TX (pin1) low + // or see readme for turning off HID functions. + // If you did anything wrong (keyboard is doing weird stuff) + // just logout (no shutdown needed). + memset(&Gamepadreport, 0, sizeof(Gamepadreport)); + HID.sendReport(HID_REPORTID_Gamepad1Report, &Gamepadreport, sizeof(Gamepadreport)); + pressRawKeyboard(0, 0); +} + +void loop() { + // press a button and demonstrate Joystick actions + if (!digitalRead(pinButton)) { + digitalWrite(pinLed, HIGH); + + // This demo is actually made for advanced users to show them how they can write an own report. + // This might be useful for a Gamepad or a especially Keyboard if you only use one key, + // because the library has a lot of code for simple use + + // count with buttons binary + static uint32_t count = 0; + Gamepadreport.whole32[0] = count++; + + // move x/y Axis to a new position (16bit) + Gamepadreport.whole16[2] = (random(0xFFFF)); + + // functions before only set the values + // this writes the report to the host + HID.sendReport(HID_REPORTID_Gamepad1Report, &Gamepadreport, sizeof(Gamepadreport)); + + + // press STRG + ALT + DEL on keyboard (see usb documentation) + //pressRawKeyboard(0, 4); //modifiers + 4 + //pressRawKeyboard(0, 29); //modifiers + z + pressRawKeyboard(RAW_KEYBOARD_LEFT_CTRL | RAW_KEYBOARD_LEFT_ALT , RAW_KEYBOARD_DELETE); //modifiers + key + pressRawKeyboard(0, 0); // release! Important + + // simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } +} + +void pressRawKeyboard(uint8_t modifiers, uint8_t key) { + uint8_t keys[8] = { modifiers, 0, key, 0, 0, 0, 0, 0 }; //modifiers, reserved, key[0] + HID.sendReport(HID_REPORTID_KeyboardReport, keys, sizeof(keys)); +} + +/* +See Hut1_12v2.pdf Chapter 10 (Page 53) for more Keys +(especially a-z, a=0x04 z=29) +Definitions: + +RAW_KEYBOARD_LEFT_CTRL +RAW_KEYBOARD_LEFT_SHIFT +RAW_KEYBOARD_LEFT_ALT +RAW_KEYBOARD_LEFT_GUI +RAW_KEYBOARD_RIGHT_CTRL +RAW_KEYBOARD_RIGHT_SHIFT +RAW_KEYBOARD_RIGHT_ALT +RAW_KEYBOARD_RIGHT_GUI + +RAW_KEYBOARD_UP_ARROW +RAW_KEYBOARD_DOWN_ARROW +RAW_KEYBOARD_LEFT_ARROW +RAW_KEYBOARD_RIGHT_ARROW +RAW_KEYBOARD_SPACEBAR +RAW_KEYBOARD_BACKSPACE +RAW_KEYBOARD_TAB +RAW_KEYBOARD_RETURN +RAW_KEYBOARD_ESC +RAW_KEYBOARD_INSERT +RAW_KEYBOARD_DELETE +RAW_KEYBOARD_PAGE_UP +RAW_KEYBOARD_PAGE_DOWN +RAW_KEYBOARD_HOME +RAW_KEYBOARD_END +RAW_KEYBOARD_CAPS_LOCK +RAW_KEYBOARD_F1 +RAW_KEYBOARD_F2 +RAW_KEYBOARD_F3 +RAW_KEYBOARD_F4 +RAW_KEYBOARD_F5 +RAW_KEYBOARD_F6 +RAW_KEYBOARD_F7 +RAW_KEYBOARD_F8 +RAW_KEYBOARD_F9 +RAW_KEYBOARD_F10 +RAW_KEYBOARD_F11 +RAW_KEYBOARD_F12 +RAW_KEYBOARD_PRINT +RAW_KEYBOARD_SCROLL_LOCK +RAW_KEYBOARD_PAUSE +*/ diff --git a/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino b/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino new file mode 100644 index 0000000000..456481986a --- /dev/null +++ b/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino @@ -0,0 +1,91 @@ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +Gamepad example +*/ + +// The protocol ist still needed for Uno/Mega here +#include +#include + +const int pinLed = 13; +const int pinButton = 8; + +void setup() { + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); + + // Starts Serial at baud 115200. end just ends the Serial + // Make sure to end your special HIDs before, this does not clear them! + // You need this baud for the HID library but still can use other bauds + // without HID functions. + HID.begin(); + + // Sends a clean report to the host. This is important because + // the 16u2 of the Uno/Mega is not turned off while programming + // so you want to start with a clear report to avoid strange bugs. + // its exactly the same like the end() function. + // You can also unplug the device if anything goes wrong. + // To prevent the 16u2 to send more reports just pull the Serial TX (pin1) low + // or see readme for turning off HID functions. + // If you did anything wrong (keyboard is doing weird stuff) + // just logout (no shutdown needed). + Gamepad1.begin(); +} + +void loop() { + // press a button and demonstrate Gamepad actions + if (!digitalRead(pinButton)) { + digitalWrite(pinLed, HIGH); + + // press button 1-32 and reset (34 becaue its written later) + static uint8_t count = 1; + Gamepad1.press(count++); + if (count == 34) { + Gamepad1.releaseAll(); + count = 1; + } + + // move x/y Axis to a new position (16bit) + Gamepad1.xAxis(random(0xFFFF)); + Gamepad1.yAxis(analogRead(A0) << 6); + + // go through all dPad positions + // values: 0-8 (0==centred) + static uint8_t dpad1 = 0; + Gamepad1.dPad1(dpad1++); + if (dpad1 == 9) dpad1 = 0; + static int8_t dpad2 = 0; + Gamepad1.dPad2(dpad2--); + if (dpad2 == -1) dpad2 = 8; + + // functions before only set the values + // this writes the report to the host + Gamepad1.write(); + + // simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } +} + +/* +Prototypes: + +void begin(void); +void end(void); +void write(void); +void press(uint8_t b); +void release(uint8_t b); +void releaseAll(void); +void buttons(uint32_t b); +void xAxis(uint16_t a); +void yAxis(uint16_t a); +void zAxis(uint16_t a); +void rxAxis(uint16_t a); +void ryAxis(uint16_t a); +void rzAxis(uint16_t a); +void dPad1(uint8_t d); +void dPad2(uint8_t d); +*/ diff --git a/plugins/KeyboardioHID/examples/Joystick/Joystick.ino b/plugins/KeyboardioHID/examples/Joystick/Joystick.ino new file mode 100644 index 0000000000..16c5c462b4 --- /dev/null +++ b/plugins/KeyboardioHID/examples/Joystick/Joystick.ino @@ -0,0 +1,77 @@ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +Joystick example +*/ + +// The protocol ist still needed for Uno/Mega here +#include +#include + +const int pinLed = 13; +const int pinButton = 8; + +void setup() { + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); + + // Starts Serial at baud 115200. end just ends the Serial + // Make sure to end your special HIDs before, this does not clear them! + // You need this baud for the HID library but still can use other bauds + // without HID functions. + HID.begin(); + + // Sends a clean report to the host. This is important because + // the 16u2 of the Uno/Mega is not turned off while programming + // so you want to start with a clear report to avoid strange bugs. + // its exactly the same like the end() function. + // You can also unplug the device if anything goes wrong. + // To prevent the 16u2 to send more reports just pull the Serial TX (pin1) low + // or see readme for turning off HID functions. + // If you did anything wrong (keyboard is doing weird stuff) + // just logout (no shutdown needed). + Joystick1.begin(); +} + +void loop() { + // press a button and demonstrate Joystick actions + if (!digitalRead(pinButton)) { + digitalWrite(pinLed, HIGH); + + // press button 1-2 and reset + static uint8_t count = 0; + if (++count == 3) { + count = 0; + Joystick1.releaseAll(); + } + else + Joystick1.press(count); + + // move x/y Axis to a new position (10bit) + Joystick1.xAxis(random(1023)); + Joystick1.yAxis(analogRead(A0)); + + // functions before only set the values + // this writes the report to the host + Joystick1.write(); + + // simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } +} + +/* +Prototypes: + +void begin(void); +void end(void); +void write(void); +void press(uint8_t b); +void release(uint8_t b); +void releaseAll(void); +void xAxis(uint16_t a); +void yAxis(uint16_t a); + +*/ diff --git a/plugins/KeyboardioHID/examples/Keyboard/Keyboard.ino b/plugins/KeyboardioHID/examples/Keyboard/Keyboard.ino new file mode 100644 index 0000000000..0395d8cc5f --- /dev/null +++ b/plugins/KeyboardioHID/examples/Keyboard/Keyboard.ino @@ -0,0 +1,105 @@ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +Keyboard example +*/ + +// The protocol ist still needed for Uno/Mega here +#include +#include + +const int pinLed = 13; +const int pinButton = 8; + +void setup() { + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); + + // Starts Serial at baud 115200. end just ends the Serial + // Make sure to end your special HIDs before, this does not clear them! + // You need this baud for the HID library but still can use other bauds + // without HID functions. + HID.begin(); + + // Sends a clean report to the host. This is important because + // the 16u2 of the Uno/Mega is not turned off while programming + // so you want to start with a clear report to avoid strange bugs. + // its exactly the same like the end() function. + // You can also unplug the device if anything goes wrong. + // To prevent the 16u2 to send more reports just pull the Serial TX (pin1) low + // or see readme for turning off HID functions. + // If you did anything wrong (keyboard is doing weird stuff) + // just logout (no shutdown needed). + Keyboard.begin(); +} + +void loop() { + // press a button to write some text to your pc + if (!digitalRead(pinButton)) { + digitalWrite(pinLed, HIGH); + + // Same use as the official library, pretty much self explaining + Keyboard.println("This message was sent with my Arduino."); + Serial.println("Serial port is still working and not glitching out"); + + // you can press any key, see list below + static uint8_t count = 0; + if (++count == 10) { + Keyboard.press(KEY_LEFT_CTRL); + Keyboard.press(KEY_LEFT_ALT); + Keyboard.press(KEY_DELETE); + Keyboard.releaseAll(); + count = 0; + } + + // simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } +} + +/* +Definitions: + +KEY_LEFT_CTRL +KEY_LEFT_SHIFT +KEY_LEFT_ALT +KEY_LEFT_GUI +KEY_RIGHT_CTRL +KEY_RIGHT_SHIFT +KEY_RIGHT_ALT +KEY_RIGHT_GUI + +KEY_UP_ARROW +KEY_DOWN_ARROW +KEY_LEFT_ARROW +KEY_RIGHT_ARROW +KEY_BACKSPACE +KEY_TAB +KEY_RETURN +KEY_ESC +KEY_INSERT +KEY_DELETE +KEY_PAGE_UP +KEY_PAGE_DOWN +KEY_HOME +KEY_END +KEY_CAPS_LOCK +KEY_F1 +KEY_F2 +KEY_F3 +KEY_F4 +KEY_F5 +KEY_F6 +KEY_F7 +KEY_F8 +KEY_F9 +KEY_F10 +KEY_F11 +KEY_F12 + +KEY_PRINT +KEY_SCROLL_LOCK +KEY_PAUSE +*/ diff --git a/plugins/KeyboardioHID/examples/Media/Media.ino b/plugins/KeyboardioHID/examples/Media/Media.ino new file mode 100644 index 0000000000..ae757d9ab1 --- /dev/null +++ b/plugins/KeyboardioHID/examples/Media/Media.ino @@ -0,0 +1,74 @@ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +Media example +*/ + +// The protocol ist still needed for Uno/Mega here +#include +#include + +const int pinLed = 13; +const int pinButton = 8; + +void setup() { + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); + + // Starts Serial at baud 115200. end just ends the Serial + // Make sure to end your special HIDs before, this does not clear them! + // You need this baud for the HID library but still can use other bauds + // without HID functions. + HID.begin(); + + // Sends a clean report to the host. This is important because + // the 16u2 of the Uno/Mega is not turned off while programming + // so you want to start with a clear report to avoid strange bugs. + // its exactly the same like the end() function. + // You can also unplug the device if anything goes wrong. + // To prevent the 16u2 to send more reports just pull the Serial TX (pin1) low + // or see readme for turning off HID functions. + // If you did anything wrong (keyboard is doing weird stuff) + // just logout (no shutdown needed). + Media.begin(); +} + +void loop() { + // press a button to play/pause music player + if (!digitalRead(pinButton)) { + digitalWrite(pinLed, HIGH); + + // See list below for more definitions or the official usb documentation + Media.write(MEDIA_PLAY_PAUSE); + + // simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } +} + +/* +Definitions: + +MEDIA_FAST_FORWARD +MEDIA_REWIND +MEDIA_NEXT +MEDIA_PREVIOUS +MEDIA_STOP +MEDIA_PLAY_PAUSE + +MEDIA_VOLUME_MUTE +MEDIA_VOLUME_UP +MEDIA_VOLUME_DOWN + +MEDIA_EMAIL_READER +MEDIA_CALCULATOR +MEDIA_EXPLORER + +MEDIA_BROWSER_HOME +MEDIA_BROWSER_BACK +MEDIA_BROWSER_FORWARD +MEDIA_BROWSER_REFRESH +MEDIA_BROWSER_BOOKMARKS +*/ diff --git a/plugins/KeyboardioHID/examples/Mouse/Mouse.ino b/plugins/KeyboardioHID/examples/Mouse/Mouse.ino new file mode 100644 index 0000000000..048c9e0a90 --- /dev/null +++ b/plugins/KeyboardioHID/examples/Mouse/Mouse.ino @@ -0,0 +1,61 @@ +/* +Copyright (c) 2014 NicoHood + See the readme for credit to other people. + + Mouse example + */ + +// The protocol ist still needed for Uno/Mega here +#include +#include + +const int pinLed = 13; +const int pinButton = 8; + +void setup() { + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); + + // Starts Serial at baud 115200. end just ends the Serial + // Make sure to end your special HIDs before, this does not clear them! + // You need this baud for the HID library but still can use other bauds + // without HID functions. + HID.begin(); + + // Sends a clean report to the host. This is important because + // the 16u2 of the Uno/Mega is not turned off while programming + // so you want to start with a clear report to avoid strange bugs. + // its exactly the same like the end() function. + // You can also unplug the device if anything goes wrong. + // To prevent the 16u2 to send more reports just pull the Serial TX (pin1) low + // or see readme for turning off HID functions. + // If you did anything wrong (keyboard is doing weird stuff) + // just logout (no shutdown needed). + Mouse.begin(); +} + +void loop() { + // press a button to click with mouse + if (!digitalRead(pinButton)) { + digitalWrite(pinLed, HIGH); + + // Same use as the official library, pretty much self explaining + Mouse.click(); + Serial.println("Serial port is still working and not glitching out"); + + // simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } +} + +/* +Definitions: + + MOUSE_LEFT + MOUSE_RIGHT + MOUSE_MIDDLE + MOUSE_PREV + MOUSE_NEXT + */ + diff --git a/plugins/KeyboardioHID/examples/System/System.ino b/plugins/KeyboardioHID/examples/System/System.ino new file mode 100644 index 0000000000..61517229c2 --- /dev/null +++ b/plugins/KeyboardioHID/examples/System/System.ino @@ -0,0 +1,62 @@ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +System example +*/ + +// The protocol ist still needed for Uno/Mega here +#include +#include + +const int pinLed = 13; +const int pinButton = 8; + +void setup() { + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); + + // Starts Serial at baud 115200. end just ends the Serial + // Make sure to end your special HIDs before, this does not clear them! + // You need this baud for the HID library but still can use other bauds + // without HID functions. + HID.begin(); + + // Sends a clean report to the host. This is important because + // the 16u2 of the Uno/Mega is not turned off while programming + // so you want to start with a clear report to avoid strange bugs. + // its exactly the same like the end() function. + // You can also unplug the device if anything goes wrong. + // To prevent the 16u2 to send more reports just pull the Serial TX (pin1) low + // or see readme for turning off HID functions. + // If you did anything wrong (keyboard is doing weird stuff) + // just logout (no shutdown needed). + System.begin(); +} + +void loop() { + // press a button to put pc into standby mode/wake up + if (!digitalRead(pinButton)) { + digitalWrite(pinLed, HIGH); + + // See list below for more definitions or the official usb documentation + static bool on = true; + if (on) + System.write(SYSTEM_SLEEP); + else + // System Wakeup is currently not working for Arduino Uno/Mega. + System.write(SYSTEM_WAKE_UP); + + // simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } +} + +/* +Definitions: + +SYSTEM_POWER_DOWN +SYSTEM_SLEEP +SYSTEM_WAKE_UP +*/ diff --git a/plugins/KeyboardioHID/keywords.txt b/plugins/KeyboardioHID/keywords.txt new file mode 100644 index 0000000000..6c86cc6de1 --- /dev/null +++ b/plugins/KeyboardioHID/keywords.txt @@ -0,0 +1,174 @@ +####################################### +# Syntax Coloring Map For HID +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +begin KEYWORD2 +end KEYWORD2 +click KEYWORD2 +move KEYWORD2 +write KEYWORD2 +press KEYWORD2 +isPressed KEYWORD2 +releaseAll KEYWORD2 +xAxis KEYWORD2 +yAxis KEYWORD2 +zAxis KEYWORD2 +rxAxis KEYWORD2 +ryAxis KEYWORD2 +rzAxis KEYWORD2 +dPad1 KEYWORD2 +dPad2 KEYWORD2 +sendReport KEYWORD2 + +####################################### +# Classes (KEYWORD3) +####################################### + +HID KEYWORD3 +Mouse KEYWORD3 +Keyboard KEYWORD3 +Media KEYWORD3 +System KEYWORD3 +Gamepad1 KEYWORD3 +Gamepad2 KEYWORD3 +Joystick1 KEYWORD3 +Joystick2 KEYWORD3 + +####################################### +# Instances (KEYWORD2) +####################################### + +####################################### +# Constants (LITERAL1) +####################################### + +#Mouse + +MOUSE_LEFT LITERAL1 +MOUSE_RIGHT LITERAL1 +MOUSE_MIDDLE LITERAL1 +MOUSE_PREV LITERAL1 +MOUSE_NEXT LITERAL1 + +#Keyboard + +KEY_LEFT_CTRL LITERAL1 +KEY_LEFT_SHIFT LITERAL1 +KEY_LEFT_ALT LITERAL1 +KEY_LEFT_GUI LITERAL1 +KEY_RIGHT_CTRL LITERAL1 +KEY_RIGHT_SHIFT LITERAL1 +KEY_RIGHT_ALT LITERAL1 +KEY_RIGHT_GUI LITERAL1 + +KEY_UP_ARROW LITERAL1 +KEY_DOWN_ARROW LITERAL1 +KEY_LEFT_ARROW LITERAL1 +KEY_RIGHT_ARROW LITERAL1 +KEY_BACKSPACE LITERAL1 +KEY_TAB LITERAL1 +KEY_RETURN LITERAL1 +KEY_ESC LITERAL1 +KEY_INSERT LITERAL1 +KEY_DELETE LITERAL1 +KEY_PAGE_UP LITERAL1 +KEY_PAGE_DOWN LITERAL1 +KEY_HOME LITERAL1 +KEY_END LITERAL1 +KEY_CAPS_LOCK LITERAL1 +KEY_F1 LITERAL1 +KEY_F2 LITERAL1 +KEY_F3 LITERAL1 +KEY_F4 LITERAL1 +KEY_F5 LITERAL1 +KEY_F6 LITERAL1 +KEY_F7 LITERAL1 +KEY_F8 LITERAL1 +KEY_F9 LITERAL1 +KEY_F10 LITERAL1 +KEY_F11 LITERAL1 +KEY_F12 LITERAL1 + +KEY_PRINT LITERAL1 +KEY_SCROLL_LOCK LITERAL1 +KEY_PAUSE LITERAL1 + +#Raw Keyboard definitions + +RAW_KEYBOARD_LEFT_CTRL LITERAL1 +RAW_KEYBOARD_LEFT_SHIFT LITERAL1 +RAW_KEYBOARD_LEFT_ALT LITERAL1 +RAW_KEYBOARD_LEFT_GUI LITERAL1 +RAW_KEYBOARD_RIGHT_CTRL LITERAL1 +RAW_KEYBOARD_RIGHT_SHIFT LITERAL1 +RAW_KEYBOARD_RIGHT_ALT LITERAL1 +RAW_KEYBOARD_RIGHT_GUI LITERAL1 + +RAW_KEYBOARD_UP_ARROW LITERAL1 +RAW_KEYBOARD_DOWN_ARROW LITERAL1 +RAW_KEYBOARD_LEFT_ARROW LITERAL1 +RAW_KEYBOARD_RIGHT_ARROW LITERAL1 +RAW_KEYBOARD_SPACEBAR LITERAL1 +RAW_KEYBOARD_BACKSPACE LITERAL1 +RAW_KEYBOARD_TAB LITERAL1 +RAW_KEYBOARD_RETURN LITERAL1 +RAW_KEYBOARD_ESC LITERAL1 +RAW_KEYBOARD_INSERT LITERAL1 +RAW_KEYBOARD_DELETE LITERAL1 +RAW_KEYBOARD_PAGE_UP LITERAL1 +RAW_KEYBOARD_PAGE_DOWN LITERAL1 +RAW_KEYBOARD_HOME LITERAL1 +RAW_KEYBOARD_END LITERAL1 +RAW_KEYBOARD_CAPS_LOCK LITERAL1 +RAW_KEYBOARD_F1 LITERAL1 +RAW_KEYBOARD_F2 LITERAL1 +RAW_KEYBOARD_F3 LITERAL1 +RAW_KEYBOARD_F4 LITERAL1 +RAW_KEYBOARD_F5 LITERAL1 +RAW_KEYBOARD_F6 LITERAL1 +RAW_KEYBOARD_F7 LITERAL1 +RAW_KEYBOARD_F8 LITERAL1 +RAW_KEYBOARD_F9 LITERAL1 +RAW_KEYBOARD_F10 LITERAL1 +RAW_KEYBOARD_F11 LITERAL1 +RAW_KEYBOARD_F12 LITERAL1 +RAW_KEYBOARD_PRINT LITERAL1 +RAW_KEYBOARD_SCROLL_LOCK LITERAL1 +RAW_KEYBOARD_PAUSE LITERAL1 + +#Media + +MEDIA_FAST_FORWARD LITERAL1 +MEDIA_REWIND LITERAL1 +MEDIA_NEXT LITERAL1 +MEDIA_PREVIOUS LITERAL1 +MEDIA_STOP LITERAL1 +MEDIA_PLAY_PAUSE LITERAL1 + +MEDIA_VOLUME_MUTE LITERAL1 +MEDIA_VOLUME_UP LITERAL1 +MEDIA_VOLUME_DOWN LITERAL1 + +MEDIA_EMAIL_READER LITERAL1 +MEDIA_CALCULATOR LITERAL1 +MEDIA_EXPLORER LITERAL1 + +MEDIA_BROWSER_HOME LITERAL1 +MEDIA_BROWSER_BACK LITERAL1 +MEDIA_BROWSER_FORWARD LITERAL1 +MEDIA_BROWSER_REFRESH LITERAL1 +MEDIA_BROWSER_BOOKMARKS LITERAL1 + +#System + +SYSTEM_POWER_DOWN LITERAL1 +SYSTEM_SLEEP LITERAL1 +SYSTEM_WAKE_UP LITERAL1 From d8f9ade60b97bda41c695d6a6b0dedcf799e4922 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Tue, 3 Jun 2014 17:11:57 +0200 Subject: [PATCH 002/602] readme update --- plugins/KeyboardioHID/Readme.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index f9ca1b78c1..cd17e423e6 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -8,7 +8,7 @@ No need for extra hardware. You just need one of the Arduinos and an USB cable. Features ======== -Use your *Arduino Uno, Mega, Micro, Leonardo or Micro Pro* as Generic HID Device and still be able to upload sketches how you are used to do. +Use your **Arduino Uno, Mega, Micro, Leonardo or Micro Pro** as Generic HID Device and still be able to upload sketches how you are used to do. This project provides a new bootloader for the 8u2/16u2 and HID libraries Arduino Uno/Mega and Micro/Leonardo. I also corrected some bugs in the original sources. @@ -37,8 +37,8 @@ Download the library and rename the folder. See [this instruction](http://arduin [NicoHoodProtocol](https://github.com/NicoHood/NicoHoodProtocol) library needed for the Uno/Mega! -*Always release buttons to not cause any erros. Replug USB cable to reset the values if anything went wrong. -Connect GND and MOSI2 to deactivate HID function on Uno/Mega* +**Always release buttons to not cause any erros. Replug USB cable to reset the values if anything went wrong. +Connect GND and MOSI2 to deactivate HID function on Uno/Mega** *Arduino Uno/Mega only* To install the new bootloader connect your Arduino to your PC and put it into DFU mode. From 27fc3909675edcd098f9082eed83d44404802960 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Tue, 3 Jun 2014 17:24:57 +0200 Subject: [PATCH 003/602] Lufa upload --- .../{IMG_5687.JPG => DFU_Bridge.JPG} | Bin .../{IMG_5688.JPG => No_HID_Bridge.JPG} | Bin plugins/KeyboardioHID/Readme.md | 2 +- .../KeyboardioHID/lufa-LUFA-140302/.gitignore | 16 + .../Bootloaders/CDC/BootloaderAPI.c | 75 + .../Bootloaders/CDC/BootloaderAPI.h | 58 + .../Bootloaders/CDC/BootloaderAPITable.S | 91 + .../Bootloaders/CDC/BootloaderCDC.c | 641 +++++ .../Bootloaders/CDC/BootloaderCDC.h | 144 + .../Bootloaders/CDC/BootloaderCDC.txt | 224 ++ .../Bootloaders/CDC/Config/AppConfig.h | 50 + .../Bootloaders/CDC/Config/LUFAConfig.h | 93 + .../Bootloaders/CDC/Descriptors.c | 244 ++ .../Bootloaders/CDC/Descriptors.h | 158 ++ .../Bootloaders/CDC/LUFA CDC Bootloader.inf | 66 + .../lufa-LUFA-140302/Bootloaders/CDC/asf.xml | 161 ++ .../lufa-LUFA-140302/Bootloaders/CDC/doxyfile | 2337 ++++++++++++++++ .../lufa-LUFA-140302/Bootloaders/CDC/makefile | 55 + .../Bootloaders/DFU/BootloaderAPI.c | 76 + .../Bootloaders/DFU/BootloaderAPI.h | 58 + .../Bootloaders/DFU/BootloaderAPITable.S | 91 + .../Bootloaders/DFU/BootloaderDFU.c | 804 ++++++ .../Bootloaders/DFU/BootloaderDFU.h | 216 ++ .../Bootloaders/DFU/BootloaderDFU.txt | 217 ++ .../Bootloaders/DFU/Config/AppConfig.h | 48 + .../Bootloaders/DFU/Config/LUFAConfig.h | 93 + .../Bootloaders/DFU/Descriptors.c | 185 ++ .../Bootloaders/DFU/Descriptors.h | 194 ++ .../lufa-LUFA-140302/Bootloaders/DFU/asf.xml | 156 ++ .../lufa-LUFA-140302/Bootloaders/DFU/doxyfile | 2337 ++++++++++++++++ .../lufa-LUFA-140302/Bootloaders/DFU/makefile | 55 + .../Bootloaders/HID/BootloaderHID.c | 190 ++ .../Bootloaders/HID/BootloaderHID.h | 73 + .../Bootloaders/HID/BootloaderHID.txt | 99 + .../Bootloaders/HID/Config/LUFAConfig.h | 93 + .../Bootloaders/HID/Descriptors.c | 187 ++ .../Bootloaders/HID/Descriptors.h | 80 + .../Bootloaders/HID/HostLoaderApp/Makefile | 39 + .../HID/HostLoaderApp/Makefile.bsd | 21 + .../Bootloaders/HID/HostLoaderApp/gpl3.txt | 674 +++++ .../HID/HostLoaderApp/hid_bootloader_cli.c | 1010 +++++++ .../hid_bootloader_loader.py | 120 + .../lufa-LUFA-140302/Bootloaders/HID/asf.xml | 123 + .../lufa-LUFA-140302/Bootloaders/HID/doxyfile | 2339 ++++++++++++++++ .../lufa-LUFA-140302/Bootloaders/HID/makefile | 48 + .../Bootloaders/MassStorage/BootloaderAPI.c | 76 + .../Bootloaders/MassStorage/BootloaderAPI.h | 63 + .../MassStorage/BootloaderAPITable.S | 102 + .../MassStorage/BootloaderMassStorage.c | 238 ++ .../MassStorage/BootloaderMassStorage.h | 99 + .../MassStorage/BootloaderMassStorage.txt | 209 ++ .../MassStorage/Config/AppConfig.h | 47 + .../MassStorage/Config/LUFAConfig.h | 93 + .../Bootloaders/MassStorage/Descriptors.c | 157 ++ .../Bootloaders/MassStorage/Descriptors.h | 88 + .../Bootloaders/MassStorage/Lib/SCSI.c | 294 +++ .../Bootloaders/MassStorage/Lib/SCSI.h | 84 + .../Bootloaders/MassStorage/Lib/VirtualFAT.c | 482 ++++ .../Bootloaders/MassStorage/Lib/VirtualFAT.h | 302 +++ .../Bootloaders/MassStorage/asf.xml | 156 ++ .../Bootloaders/MassStorage/doxyfile | 2337 ++++++++++++++++ .../Bootloaders/MassStorage/makefile | 68 + .../Bootloaders/Printer/BootloaderAPI.c | 75 + .../Bootloaders/Printer/BootloaderAPI.h | 56 + .../Bootloaders/Printer/BootloaderAPITable.S | 91 + .../Bootloaders/Printer/BootloaderPrinter.c | 431 +++ .../Bootloaders/Printer/BootloaderPrinter.h | 108 + .../Bootloaders/Printer/BootloaderPrinter.txt | 184 ++ .../Bootloaders/Printer/Config/LUFAConfig.h | 93 + .../Bootloaders/Printer/Descriptors.c | 194 ++ .../Bootloaders/Printer/Descriptors.h | 96 + .../Bootloaders/Printer/asf.xml | 159 ++ .../Bootloaders/Printer/doxyfile | 2337 ++++++++++++++++ .../Bootloaders/Printer/makefile | 55 + .../lufa-LUFA-140302/Bootloaders/makefile | 46 + .../BuildTests/BoardDriverTest/Board/Board.h | 82 + .../BoardDriverTest/Board/Buttons.h | 92 + .../BoardDriverTest/Board/Dataflash.h | 197 ++ .../BoardDriverTest/Board/Joystick.h | 104 + .../BuildTests/BoardDriverTest/Board/LEDs.h | 132 + .../BoardDriverTest/BoardDeviceMap.cfg | 85 + .../BuildTests/BoardDriverTest/Test.c | 115 + .../BuildTests/BoardDriverTest/makefile | 68 + .../BuildTests/BoardDriverTest/makefile.test | 27 + .../BootloaderTest/BootloaderDeviceMap.cfg | 167 ++ .../BuildTests/BootloaderTest/makefile | 64 + .../BuildTests/ModuleTest/Dummy.S | 41 + .../BuildTests/ModuleTest/Modules.h | 56 + .../BuildTests/ModuleTest/Test_C.c | 31 + .../BuildTests/ModuleTest/Test_CPP.cpp | 31 + .../BuildTests/ModuleTest/makefile | 66 + .../BuildTests/ModuleTest/makefile.test | 88 + .../BuildTests/SingleUSBModeTest/Dummy.S | 42 + .../BuildTests/SingleUSBModeTest/Test.c | 32 + .../BuildTests/SingleUSBModeTest/makefile | 56 + .../SingleUSBModeTest/makefile.test | 69 + .../BuildTests/StaticAnalysisTest/makefile | 47 + .../lufa-LUFA-140302/BuildTests/makefile | 24 + .../HID_EEPROM_Loader/HID_EEPROM_Loader.c | 61 + .../LUFA/Build/HID_EEPROM_Loader/makefile | 42 + .../LUFA/Build/lufa_atprogram.mk | 103 + .../LUFA/Build/lufa_avrdude.mk | 86 + .../lufa-LUFA-140302/LUFA/Build/lufa_build.mk | 343 +++ .../lufa-LUFA-140302/LUFA/Build/lufa_core.mk | 175 ++ .../LUFA/Build/lufa_cppcheck.mk | 107 + .../lufa-LUFA-140302/LUFA/Build/lufa_dfu.mk | 95 + .../LUFA/Build/lufa_doxygen.mk | 100 + .../lufa-LUFA-140302/LUFA/Build/lufa_hid.mk | 96 + .../LUFA/Build/lufa_sources.mk | 144 + .../DeviceTemplate/Descriptors.c | 180 ++ .../DeviceTemplate/Descriptors.h | 59 + .../DeviceTemplate/DeviceApplication.c | 106 + .../DeviceTemplate/DeviceApplication.h | 53 + .../LUFA/CodeTemplates/DeviceTemplate/asf.xml | 55 + .../LUFA/CodeTemplates/DriverStubs/Board.h | 82 + .../LUFA/CodeTemplates/DriverStubs/Buttons.h | 90 + .../CodeTemplates/DriverStubs/Dataflash.h | 223 ++ .../LUFA/CodeTemplates/DriverStubs/Joystick.h | 102 + .../LUFA/CodeTemplates/DriverStubs/LEDs.h | 130 + .../HostTemplate/HostApplication.c | 133 + .../HostTemplate/HostApplication.h | 56 + .../LUFA/CodeTemplates/HostTemplate/asf.xml | 41 + .../LUFA/CodeTemplates/LUFAConfig.h | 167 ++ .../CodeTemplates/WindowsINF/LUFA CDC-ACM.inf | 64 + .../CodeTemplates/WindowsINF/LUFA RNDIS.inf | 59 + .../LUFA/CodeTemplates/makefile_template | 38 + .../LUFA/Common/ArchitectureSpecific.h | 177 ++ .../LUFA/Common/Architectures.h | 84 + .../lufa-LUFA-140302/LUFA/Common/Attributes.h | 150 ++ .../lufa-LUFA-140302/LUFA/Common/BoardTypes.h | 248 ++ .../lufa-LUFA-140302/LUFA/Common/Common.h | 401 +++ .../LUFA/Common/CompilerSpecific.h | 97 + .../lufa-LUFA-140302/LUFA/Common/Endianness.h | 493 ++++ .../LUFA/DoxygenPages/BuildSystem.txt | 971 +++++++ .../BuildingLinkableLibraries.txt | 23 + .../LUFA/DoxygenPages/ChangeLog.txt | 1563 +++++++++++ .../LUFA/DoxygenPages/CompileTimeTokens.txt | 223 ++ .../LUFA/DoxygenPages/CompilingApps.txt | 46 + .../LUFA/DoxygenPages/ConfiguringApps.txt | 104 + .../LUFA/DoxygenPages/DevelopingWithLUFA.txt | 24 + .../LUFA/DoxygenPages/DeviceSupport.txt | 420 +++ .../LUFA/DoxygenPages/DirectorySummaries.txt | 80 + .../LUFA/DoxygenPages/Donating.txt | 26 + .../LUFA/DoxygenPages/ExportingLibrary.txt | 112 + .../LUFA/DoxygenPages/FutureChanges.txt | 47 + .../LUFA/DoxygenPages/GettingStarted.txt | 25 + .../LUFA/DoxygenPages/Groups.txt | 38 + .../AS5_AS6_Import/AS5_AS6_Import_Step1.png | Bin 0 -> 98201 bytes .../AS5_AS6_Import/AS5_AS6_Import_Step2.png | Bin 0 -> 100532 bytes .../AS5_AS6_Import/AS5_AS6_Import_Step3.png | Bin 0 -> 32987 bytes .../AS5_AS6_Import/AS5_AS6_Import_Step4.png | Bin 0 -> 161824 bytes .../AS5_AS6_Import/AS5_AS6_Import_Step5_1.png | Bin 0 -> 43666 bytes .../AS5_AS6_Import/AS5_AS6_Import_Step5_2.png | Bin 0 -> 28918 bytes .../AS5_AS6_Import/AS5_AS6_Import_Step5_3.png | Bin 0 -> 23561 bytes .../LUFA/DoxygenPages/Images/Author.jpg | Bin 0 -> 28410 bytes .../LUFA/DoxygenPages/Images/LUFA.png | Bin 0 -> 10296 bytes .../LUFA/DoxygenPages/Images/LUFA_thumb.png | Bin 0 -> 3729 bytes .../LUFA/DoxygenPages/KnownIssues.txt | 138 + .../LUFA/DoxygenPages/LUFAPoweredProjects.txt | 221 ++ .../LUFA/DoxygenPages/LibraryResources.txt | 33 + .../LUFA/DoxygenPages/LicenseInfo.txt | 43 + .../LUFA/DoxygenPages/MainPage.txt | 52 + .../DoxygenPages/MigrationInformation.txt | 703 +++++ .../LUFA/DoxygenPages/OSDrivers.txt | 111 + .../LUFA/DoxygenPages/ProgrammingApps.txt | 30 + .../DoxygenPages/SoftwareBootloaderJump.txt | 71 + .../LUFA/DoxygenPages/Style/Footer.htm | 35 + .../LUFA/DoxygenPages/Style/Style.css | 93 + .../LUFA/DoxygenPages/VIDAndPIDValues.txt | 199 ++ .../LUFA/DoxygenPages/WritingBoardDrivers.txt | 47 + .../Drivers/Board/AVR8/ADAFRUITU4/Board.h | 78 + .../LUFA/Drivers/Board/AVR8/ADAFRUITU4/LEDs.h | 135 + .../Drivers/Board/AVR8/ATAVRUSBRF01/Board.h | 82 + .../Drivers/Board/AVR8/ATAVRUSBRF01/Buttons.h | 103 + .../Drivers/Board/AVR8/ATAVRUSBRF01/LEDs.h | 139 + .../LUFA/Drivers/Board/AVR8/BENITO/Board.h | 82 + .../LUFA/Drivers/Board/AVR8/BENITO/Buttons.h | 103 + .../LUFA/Drivers/Board/AVR8/BENITO/LEDs.h | 139 + .../LUFA/Drivers/Board/AVR8/BIGMULTIO/Board.h | 78 + .../LUFA/Drivers/Board/AVR8/BIGMULTIO/LEDs.h | 161 ++ .../LUFA/Drivers/Board/AVR8/BLACKCAT/Board.h | 78 + .../LUFA/Drivers/Board/AVR8/BLACKCAT/LEDs.h | 139 + .../LUFA/Drivers/Board/AVR8/BUI/Board.h | 78 + .../LUFA/Drivers/Board/AVR8/BUI/LEDs.h | 143 + .../LUFA/Drivers/Board/AVR8/BUMBLEB/Board.h | 86 + .../LUFA/Drivers/Board/AVR8/BUMBLEB/Buttons.h | 105 + .../Drivers/Board/AVR8/BUMBLEB/Joystick.h | 123 + .../LUFA/Drivers/Board/AVR8/BUMBLEB/LEDs.h | 149 ++ .../LUFA/Drivers/Board/AVR8/CULV3/Board.h | 82 + .../LUFA/Drivers/Board/AVR8/CULV3/Buttons.h | 103 + .../LUFA/Drivers/Board/AVR8/CULV3/LEDs.h | 135 + .../LUFA/Drivers/Board/AVR8/DUCE/Board.h | 78 + .../LUFA/Drivers/Board/AVR8/DUCE/LEDs.h | 147 ++ .../LUFA/Drivers/Board/AVR8/EVK527/Board.h | 90 + .../LUFA/Drivers/Board/AVR8/EVK527/Buttons.h | 103 + .../Drivers/Board/AVR8/EVK527/Dataflash.h | 222 ++ .../LUFA/Drivers/Board/AVR8/EVK527/Joystick.h | 130 + .../LUFA/Drivers/Board/AVR8/EVK527/LEDs.h | 143 + .../LUFA/Drivers/Board/AVR8/JMDBU2/Board.h | 82 + .../LUFA/Drivers/Board/AVR8/JMDBU2/Buttons.h | 103 + .../LUFA/Drivers/Board/AVR8/JMDBU2/LEDs.h | 135 + .../LUFA/Drivers/Board/AVR8/LEONARDO/Board.h | 78 + .../LUFA/Drivers/Board/AVR8/LEONARDO/LEDs.h | 169 ++ .../LUFA/Drivers/Board/AVR8/MAXIMUS/Board.h | 78 + .../LUFA/Drivers/Board/AVR8/MAXIMUS/LEDs.h | 139 + .../Drivers/Board/AVR8/MICROPENDOUS/Board.h | 149 ++ .../Drivers/Board/AVR8/MICROPENDOUS/Buttons.h | 205 ++ .../Drivers/Board/AVR8/MICROPENDOUS/LEDs.h | 174 ++ .../Drivers/Board/AVR8/MICROSIN162/Board.h | 82 + .../Drivers/Board/AVR8/MICROSIN162/Buttons.h | 103 + .../Drivers/Board/AVR8/MICROSIN162/LEDs.h | 135 + .../LUFA/Drivers/Board/AVR8/MINIMUS/Board.h | 82 + .../LUFA/Drivers/Board/AVR8/MINIMUS/Buttons.h | 103 + .../LUFA/Drivers/Board/AVR8/MINIMUS/LEDs.h | 139 + .../LUFA/Drivers/Board/AVR8/MULTIO/Board.h | 78 + .../LUFA/Drivers/Board/AVR8/MULTIO/LEDs.h | 161 ++ .../LUFA/Drivers/Board/AVR8/OLIMEX162/Board.h | 82 + .../Drivers/Board/AVR8/OLIMEX162/Buttons.h | 103 + .../LUFA/Drivers/Board/AVR8/OLIMEX162/LEDs.h | 135 + .../Drivers/Board/AVR8/OLIMEX32U4/Board.h | 82 + .../Drivers/Board/AVR8/OLIMEX32U4/Buttons.h | 103 + .../LUFA/Drivers/Board/AVR8/OLIMEX32U4/LEDs.h | 179 ++ .../Drivers/Board/AVR8/OLIMEXISPMK2/Board.h | 82 + .../Drivers/Board/AVR8/OLIMEXISPMK2/Buttons.h | 103 + .../Drivers/Board/AVR8/OLIMEXISPMK2/LEDs.h | 143 + .../Drivers/Board/AVR8/OLIMEXT32U4/Board.h | 82 + .../Drivers/Board/AVR8/OLIMEXT32U4/Buttons.h | 103 + .../Drivers/Board/AVR8/OLIMEXT32U4/LEDs.h | 169 ++ .../Drivers/Board/AVR8/RZUSBSTICK/Board.h | 78 + .../LUFA/Drivers/Board/AVR8/RZUSBSTICK/LEDs.h | 175 ++ .../Drivers/Board/AVR8/SPARKFUN8U2/Board.h | 78 + .../Drivers/Board/AVR8/SPARKFUN8U2/LEDs.h | 135 + .../Drivers/Board/AVR8/STANGE_ISP/Board.h | 82 + .../Drivers/Board/AVR8/STANGE_ISP/Buttons.h | 103 + .../LUFA/Drivers/Board/AVR8/STANGE_ISP/LEDs.h | 138 + .../LUFA/Drivers/Board/AVR8/STK525/Board.h | 90 + .../LUFA/Drivers/Board/AVR8/STK525/Buttons.h | 103 + .../Drivers/Board/AVR8/STK525/Dataflash.h | 222 ++ .../LUFA/Drivers/Board/AVR8/STK525/Joystick.h | 130 + .../LUFA/Drivers/Board/AVR8/STK525/LEDs.h | 147 ++ .../LUFA/Drivers/Board/AVR8/STK526/Board.h | 90 + .../LUFA/Drivers/Board/AVR8/STK526/Buttons.h | 103 + .../Drivers/Board/AVR8/STK526/Dataflash.h | 222 ++ .../LUFA/Drivers/Board/AVR8/STK526/Joystick.h | 123 + .../LUFA/Drivers/Board/AVR8/STK526/LEDs.h | 147 ++ .../LUFA/Drivers/Board/AVR8/TEENSY/Board.h | 85 + .../LUFA/Drivers/Board/AVR8/TEENSY/LEDs.h | 176 ++ .../LUFA/Drivers/Board/AVR8/TUL/Board.h | 82 + .../LUFA/Drivers/Board/AVR8/TUL/Buttons.h | 103 + .../LUFA/Drivers/Board/AVR8/TUL/LEDs.h | 135 + .../LUFA/Drivers/Board/AVR8/U2S/Board.h | 82 + .../LUFA/Drivers/Board/AVR8/U2S/Buttons.h | 103 + .../LUFA/Drivers/Board/AVR8/U2S/LEDs.h | 135 + .../LUFA/Drivers/Board/AVR8/UDIP/Board.h | 82 + .../LUFA/Drivers/Board/AVR8/UDIP/Buttons.h | 103 + .../LUFA/Drivers/Board/AVR8/UDIP/LEDs.h | 163 ++ .../LUFA/Drivers/Board/AVR8/UNO/Board.h | 78 + .../LUFA/Drivers/Board/AVR8/UNO/LEDs.h | 139 + .../LUFA/Drivers/Board/AVR8/USB2AX/Board.h | 105 + .../LUFA/Drivers/Board/AVR8/USB2AX/Buttons.h | 120 + .../LUFA/Drivers/Board/AVR8/USB2AX/LEDs.h | 218 ++ .../LUFA/Drivers/Board/AVR8/USBFOO/Board.h | 82 + .../LUFA/Drivers/Board/AVR8/USBFOO/Buttons.h | 103 + .../LUFA/Drivers/Board/AVR8/USBFOO/LEDs.h | 135 + .../LUFA/Drivers/Board/AVR8/USBKEY/Board.h | 90 + .../LUFA/Drivers/Board/AVR8/USBKEY/Buttons.h | 103 + .../Drivers/Board/AVR8/USBKEY/Dataflash.h | 237 ++ .../LUFA/Drivers/Board/AVR8/USBKEY/Joystick.h | 130 + .../LUFA/Drivers/Board/AVR8/USBKEY/LEDs.h | 147 ++ .../Drivers/Board/AVR8/USBTINYMKII/Board.h | 82 + .../Drivers/Board/AVR8/USBTINYMKII/Buttons.h | 103 + .../Drivers/Board/AVR8/USBTINYMKII/LEDs.h | 143 + .../LUFA/Drivers/Board/AVR8/XPLAIN/Board.h | 89 + .../Drivers/Board/AVR8/XPLAIN/Dataflash.h | 245 ++ .../LUFA/Drivers/Board/AVR8/XPLAIN/LEDs.h | 142 + .../LUFA/Drivers/Board/Board.h | 163 ++ .../LUFA/Drivers/Board/Buttons.h | 188 ++ .../LUFA/Drivers/Board/Dataflash.h | 266 ++ .../LUFA/Drivers/Board/Joystick.h | 151 ++ .../LUFA/Drivers/Board/LEDs.h | 294 +++ .../LUFA/Drivers/Board/Temperature.c | 66 + .../LUFA/Drivers/Board/Temperature.h | 147 ++ .../LUFA/Drivers/Board/UC3/EVK1100/Board.h | 86 + .../LUFA/Drivers/Board/UC3/EVK1100/Buttons.h | 117 + .../LUFA/Drivers/Board/UC3/EVK1100/Joystick.h | 122 + .../LUFA/Drivers/Board/UC3/EVK1100/LEDs.h | 173 ++ .../LUFA/Drivers/Board/UC3/EVK1101/Board.h | 86 + .../LUFA/Drivers/Board/UC3/EVK1101/Buttons.h | 113 + .../LUFA/Drivers/Board/UC3/EVK1101/Joystick.h | 131 + .../LUFA/Drivers/Board/UC3/EVK1101/LEDs.h | 156 ++ .../LUFA/Drivers/Board/UC3/EVK1104/Board.h | 82 + .../LUFA/Drivers/Board/UC3/EVK1104/Buttons.h | 109 + .../LUFA/Drivers/Board/UC3/EVK1104/LEDs.h | 174 ++ .../Drivers/Board/UC3/UC3A3_XPLAINED/Board.h | 82 + .../Board/UC3/UC3A3_XPLAINED/Buttons.h | 109 + .../Drivers/Board/UC3/UC3A3_XPLAINED/LEDs.h | 182 ++ .../Drivers/Board/XMEGA/A3BU_XPLAINED/Board.h | 86 + .../Board/XMEGA/A3BU_XPLAINED/Buttons.h | 119 + .../Board/XMEGA/A3BU_XPLAINED/Dataflash.h | 228 ++ .../Drivers/Board/XMEGA/A3BU_XPLAINED/LEDs.h | 181 ++ .../Drivers/Board/XMEGA/B1_XPLAINED/Board.h | 86 + .../Drivers/Board/XMEGA/B1_XPLAINED/Buttons.h | 119 + .../Board/XMEGA/B1_XPLAINED/Dataflash.h | 229 ++ .../Drivers/Board/XMEGA/B1_XPLAINED/LEDs.h | 183 ++ .../Drivers/Board/XMEGA/C3_XPLAINED/Board.h | 83 + .../Drivers/Board/XMEGA/C3_XPLAINED/Buttons.h | 109 + .../Drivers/Board/XMEGA/C3_XPLAINED/LEDs.h | 181 ++ .../LUFA/Drivers/Misc/AT45DB321C.h | 100 + .../LUFA/Drivers/Misc/AT45DB642D.h | 116 + .../LUFA/Drivers/Misc/RingBuffer.h | 308 +++ .../LUFA/Drivers/Misc/TerminalCodes.h | 231 ++ .../LUFA/Drivers/Peripheral/ADC.h | 75 + .../LUFA/Drivers/Peripheral/AVR8/ADC_AVR8.h | 446 ++++ .../LUFA/Drivers/Peripheral/AVR8/SPI_AVR8.h | 258 ++ .../Drivers/Peripheral/AVR8/SerialSPI_AVR8.h | 200 ++ .../Drivers/Peripheral/AVR8/Serial_AVR8.c | 119 + .../Drivers/Peripheral/AVR8/Serial_AVR8.h | 245 ++ .../LUFA/Drivers/Peripheral/AVR8/TWI_AVR8.c | 209 ++ .../LUFA/Drivers/Peripheral/AVR8/TWI_AVR8.h | 305 +++ .../LUFA/Drivers/Peripheral/SPI.h | 76 + .../LUFA/Drivers/Peripheral/Serial.h | 76 + .../LUFA/Drivers/Peripheral/SerialSPI.h | 76 + .../LUFA/Drivers/Peripheral/TWI.h | 76 + .../LUFA/Drivers/Peripheral/XMEGA/SPI_XMEGA.h | 251 ++ .../Peripheral/XMEGA/SerialSPI_XMEGA.h | 212 ++ .../Drivers/Peripheral/XMEGA/Serial_XMEGA.c | 122 + .../Drivers/Peripheral/XMEGA/Serial_XMEGA.h | 257 ++ .../LUFA/Drivers/Peripheral/XMEGA/TWI_XMEGA.c | 185 ++ .../LUFA/Drivers/Peripheral/XMEGA/TWI_XMEGA.h | 302 +++ .../Drivers/USB/Class/AndroidAccessoryClass.h | 77 + .../LUFA/Drivers/USB/Class/AudioClass.h | 81 + .../LUFA/Drivers/USB/Class/CDCClass.h | 81 + .../Common/AndroidAccessoryClassCommon.h | 129 + .../USB/Class/Common/AudioClassCommon.h | 780 ++++++ .../Drivers/USB/Class/Common/CDCClassCommon.h | 391 +++ .../Drivers/USB/Class/Common/HIDClassCommon.h | 665 +++++ .../LUFA/Drivers/USB/Class/Common/HIDParser.c | 389 +++ .../LUFA/Drivers/USB/Class/Common/HIDParser.h | 364 +++ .../Drivers/USB/Class/Common/HIDReportData.h | 126 + .../USB/Class/Common/MIDIClassCommon.h | 363 +++ .../USB/Class/Common/MassStorageClassCommon.h | 368 +++ .../USB/Class/Common/PrinterClassCommon.h | 119 + .../USB/Class/Common/RNDISClassCommon.h | 414 +++ .../USB/Class/Common/StillImageClassCommon.h | 161 ++ .../USB/Class/Device/AudioClassDevice.c | 197 ++ .../USB/Class/Device/AudioClassDevice.h | 396 +++ .../Drivers/USB/Class/Device/CDCClassDevice.c | 341 +++ .../Drivers/USB/Class/Device/CDCClassDevice.h | 352 +++ .../Drivers/USB/Class/Device/HIDClassDevice.c | 207 ++ .../Drivers/USB/Class/Device/HIDClassDevice.h | 210 ++ .../USB/Class/Device/MIDIClassDevice.c | 131 + .../USB/Class/Device/MIDIClassDevice.h | 175 ++ .../USB/Class/Device/MassStorageClassDevice.c | 215 ++ .../USB/Class/Device/MassStorageClassDevice.h | 161 ++ .../USB/Class/Device/PrinterClassDevice.c | 314 +++ .../USB/Class/Device/PrinterClassDevice.h | 293 +++ .../USB/Class/Device/RNDISClassDevice.c | 502 ++++ .../USB/Class/Device/RNDISClassDevice.h | 203 ++ .../LUFA/Drivers/USB/Class/HIDClass.h | 82 + .../Class/Host/AndroidAccessoryClassHost.c | 422 +++ .../Class/Host/AndroidAccessoryClassHost.h | 314 +++ .../Drivers/USB/Class/Host/AudioClassHost.c | 223 ++ .../Drivers/USB/Class/Host/AudioClassHost.h | 411 +++ .../Drivers/USB/Class/Host/CDCClassHost.c | 477 ++++ .../Drivers/USB/Class/Host/CDCClassHost.h | 351 +++ .../Drivers/USB/Class/Host/HIDClassHost.c | 399 +++ .../Drivers/USB/Class/Host/HIDClassHost.h | 313 +++ .../Drivers/USB/Class/Host/MIDIClassHost.c | 231 ++ .../Drivers/USB/Class/Host/MIDIClassHost.h | 190 ++ .../USB/Class/Host/MassStorageClassHost.c | 579 ++++ .../USB/Class/Host/MassStorageClassHost.h | 335 +++ .../Drivers/USB/Class/Host/PrinterClassHost.c | 400 +++ .../Drivers/USB/Class/Host/PrinterClassHost.h | 285 ++ .../Drivers/USB/Class/Host/RNDISClassHost.c | 476 ++++ .../Drivers/USB/Class/Host/RNDISClassHost.h | 270 ++ .../USB/Class/Host/StillImageClassHost.c | 436 +++ .../USB/Class/Host/StillImageClassHost.h | 317 +++ .../LUFA/Drivers/USB/Class/MIDIClass.h | 84 + .../LUFA/Drivers/USB/Class/MassStorageClass.h | 81 + .../LUFA/Drivers/USB/Class/PrinterClass.h | 83 + .../LUFA/Drivers/USB/Class/RNDISClass.h | 81 + .../LUFA/Drivers/USB/Class/StillImageClass.h | 76 + .../LUFA/Drivers/USB/Core/AVR8/Device_AVR8.c | 57 + .../LUFA/Drivers/USB/Core/AVR8/Device_AVR8.h | 269 ++ .../USB/Core/AVR8/EndpointStream_AVR8.c | 275 ++ .../USB/Core/AVR8/EndpointStream_AVR8.h | 658 +++++ .../Drivers/USB/Core/AVR8/Endpoint_AVR8.c | 201 ++ .../Drivers/USB/Core/AVR8/Endpoint_AVR8.h | 819 ++++++ .../LUFA/Drivers/USB/Core/AVR8/Host_AVR8.c | 297 +++ .../LUFA/Drivers/USB/Core/AVR8/Host_AVR8.h | 372 +++ .../LUFA/Drivers/USB/Core/AVR8/OTG_AVR8.h | 159 ++ .../Drivers/USB/Core/AVR8/PipeStream_AVR8.c | 221 ++ .../Drivers/USB/Core/AVR8/PipeStream_AVR8.h | 442 ++++ .../LUFA/Drivers/USB/Core/AVR8/Pipe_AVR8.c | 210 ++ .../LUFA/Drivers/USB/Core/AVR8/Pipe_AVR8.h | 922 +++++++ .../Template/Template_Endpoint_Control_R.c | 84 + .../Template/Template_Endpoint_Control_W.c | 93 + .../Core/AVR8/Template/Template_Endpoint_RW.c | 89 + .../USB/Core/AVR8/Template/Template_Pipe_RW.c | 88 + .../USB/Core/AVR8/USBController_AVR8.c | 273 ++ .../USB/Core/AVR8/USBController_AVR8.h | 432 +++ .../Drivers/USB/Core/AVR8/USBInterrupt_AVR8.c | 279 ++ .../Drivers/USB/Core/AVR8/USBInterrupt_AVR8.h | 375 +++ .../LUFA/Drivers/USB/Core/ConfigDescriptors.c | 146 + .../LUFA/Drivers/USB/Core/ConfigDescriptors.h | 287 ++ .../LUFA/Drivers/USB/Core/Device.h | 159 ++ .../LUFA/Drivers/USB/Core/DeviceStandardReq.c | 380 +++ .../LUFA/Drivers/USB/Core/DeviceStandardReq.h | 158 ++ .../LUFA/Drivers/USB/Core/Endpoint.h | 130 + .../LUFA/Drivers/USB/Core/EndpointStream.h | 124 + .../LUFA/Drivers/USB/Core/Events.c | 39 + .../LUFA/Drivers/USB/Core/Events.h | 372 +++ .../LUFA/Drivers/USB/Core/Host.h | 139 + .../LUFA/Drivers/USB/Core/HostStandardReq.c | 322 +++ .../LUFA/Drivers/USB/Core/HostStandardReq.h | 292 ++ .../LUFA/Drivers/USB/Core/OTG.h | 80 + .../LUFA/Drivers/USB/Core/Pipe.h | 144 + .../LUFA/Drivers/USB/Core/PipeStream.h | 100 + .../LUFA/Drivers/USB/Core/StdDescriptors.h | 765 ++++++ .../LUFA/Drivers/USB/Core/StdRequestType.h | 258 ++ .../LUFA/Drivers/USB/Core/UC3/Device_UC3.c | 51 + .../LUFA/Drivers/USB/Core/UC3/Device_UC3.h | 267 ++ .../Drivers/USB/Core/UC3/EndpointStream_UC3.c | 235 ++ .../Drivers/USB/Core/UC3/EndpointStream_UC3.h | 438 +++ .../LUFA/Drivers/USB/Core/UC3/Endpoint_UC3.c | 196 ++ .../LUFA/Drivers/USB/Core/UC3/Endpoint_UC3.h | 794 ++++++ .../LUFA/Drivers/USB/Core/UC3/Host_UC3.c | 297 +++ .../LUFA/Drivers/USB/Core/UC3/Host_UC3.h | 363 +++ .../Drivers/USB/Core/UC3/PipeStream_UC3.c | 166 ++ .../Drivers/USB/Core/UC3/PipeStream_UC3.h | 352 +++ .../LUFA/Drivers/USB/Core/UC3/Pipe_UC3.c | 209 ++ .../LUFA/Drivers/USB/Core/UC3/Pipe_UC3.h | 924 +++++++ .../Template/Template_Endpoint_Control_R.c | 84 + .../Template/Template_Endpoint_Control_W.c | 93 + .../Core/UC3/Template/Template_Endpoint_RW.c | 89 + .../USB/Core/UC3/Template/Template_Pipe_RW.c | 88 + .../Drivers/USB/Core/UC3/USBController_UC3.c | 222 ++ .../Drivers/USB/Core/UC3/USBController_UC3.h | 353 +++ .../Drivers/USB/Core/UC3/USBInterrupt_UC3.c | 228 ++ .../Drivers/USB/Core/UC3/USBInterrupt_UC3.h | 376 +++ .../LUFA/Drivers/USB/Core/USBController.h | 165 ++ .../LUFA/Drivers/USB/Core/USBInterrupt.h | 73 + .../LUFA/Drivers/USB/Core/USBMode.h | 283 ++ .../LUFA/Drivers/USB/Core/USBTask.c | 89 + .../LUFA/Drivers/USB/Core/USBTask.h | 200 ++ .../Drivers/USB/Core/XMEGA/Device_XMEGA.c | 49 + .../Drivers/USB/Core/XMEGA/Device_XMEGA.h | 266 ++ .../USB/Core/XMEGA/EndpointStream_XMEGA.c | 275 ++ .../USB/Core/XMEGA/EndpointStream_XMEGA.h | 658 +++++ .../Drivers/USB/Core/XMEGA/Endpoint_XMEGA.c | 268 ++ .../Drivers/USB/Core/XMEGA/Endpoint_XMEGA.h | 689 +++++ .../LUFA/Drivers/USB/Core/XMEGA/Host_XMEGA.c | 41 + .../Drivers/USB/Core/XMEGA/PipeStream_XMEGA.c | 41 + .../LUFA/Drivers/USB/Core/XMEGA/Pipe_XMEGA.c | 37 + .../Template/Template_Endpoint_Control_R.c | 86 + .../Template/Template_Endpoint_Control_W.c | 95 + .../XMEGA/Template/Template_Endpoint_RW.c | 89 + .../USB/Core/XMEGA/USBController_XMEGA.c | 193 ++ .../USB/Core/XMEGA/USBController_XMEGA.h | 313 +++ .../USB/Core/XMEGA/USBInterrupt_XMEGA.c | 106 + .../USB/Core/XMEGA/USBInterrupt_XMEGA.h | 172 ++ .../lufa-LUFA-140302/LUFA/Drivers/USB/USB.h | 422 +++ .../lufa-LUFA-140302/LUFA/License.txt | 24 + .../lufa-LUFA-140302/LUFA/Platform/Platform.h | 80 + .../LUFA/Platform/UC3/ClockManagement.h | 338 +++ .../LUFA/Platform/UC3/Exception.S | 128 + .../LUFA/Platform/UC3/InterruptManagement.c | 62 + .../LUFA/Platform/UC3/InterruptManagement.h | 174 ++ .../LUFA/Platform/UC3/UC3ExperimentalInfo.txt | 1 + .../LUFA/Platform/XMEGA/ClockManagement.h | 397 +++ .../Platform/XMEGA/XMEGAExperimentalInfo.txt | 1 + .../HV1/helpcontentsetup.msha | 27 + .../HV1/lufa_docbook_transform.xslt | 808 ++++++ .../HV1/lufa_helpcontentsetup_transform.xslt | 43 + .../HV1/lufa_hv1_transform.xslt | 45 + .../HV1/lufa_studio_help_styling.css | 53 + .../LUFA/StudioIntegration/VSIX/LUFA.dll | Bin 0 -> 748544 bytes .../LUFA/StudioIntegration/VSIX/LUFA.pkgdef | Bin 0 -> 2242 bytes .../VSIX/[Content_Types].xml | 13 + .../StudioIntegration/VSIX/asf-manifest.xml | 18 + .../VSIX/extension.vsixmanifest | 33 + .../StudioIntegration/VSIX/generate_caches.py | 38 + .../VSIX/lufa_asfmanifest_transform.xslt | 36 + .../VSIX/lufa_vsmanifest_transform.xslt | 33 + .../XDK/lufa_extension_transform.xslt | 68 + .../XDK/lufa_filelist_transform.xslt | 35 + .../XDK/lufa_indent_transform.xslt | 23 + .../XDK/lufa_module_transform.xslt | 66 + .../LUFA/StudioIntegration/lufa.xml | 96 + .../LUFA/StudioIntegration/lufa_common.xml | 34 + .../StudioIntegration/lufa_drivers_board.xml | 114 + .../lufa_drivers_board_names.xml | 827 ++++++ .../StudioIntegration/lufa_drivers_misc.xml | 57 + .../lufa_drivers_peripheral.xml | 198 ++ .../StudioIntegration/lufa_drivers_usb.xml | 32 + .../lufa_drivers_usb_class.xml | 32 + .../lufa_drivers_usb_class_android.xml | 54 + .../lufa_drivers_usb_class_audio.xml | 109 + .../lufa_drivers_usb_class_cdc.xml | 99 + .../lufa_drivers_usb_class_hid.xml | 99 + .../lufa_drivers_usb_class_midi.xml | 99 + .../lufa_drivers_usb_class_ms.xml | 99 + .../lufa_drivers_usb_class_printer.xml | 99 + .../lufa_drivers_usb_class_rndis.xml | 99 + .../lufa_drivers_usb_class_si.xml | 56 + .../lufa_drivers_usb_core.xml | 85 + .../lufa_drivers_usb_core_avr8.xml | 43 + .../lufa_drivers_usb_core_uc3.xml | 42 + .../lufa_drivers_usb_core_xmega.xml | 36 + .../LUFA/StudioIntegration/lufa_platform.xml | 60 + .../StudioIntegration/lufa_platform_uc3.xml | 26 + .../StudioIntegration/lufa_platform_xmega.xml | 23 + .../LUFA/StudioIntegration/lufa_toolchain.xml | 43 + .../LUFA/StudioIntegration/makefile | 140 + .../lufa-LUFA-140302/LUFA/Version.h | 52 + .../lufa-LUFA-140302/LUFA/doxyfile | 2340 +++++++++++++++++ .../lufa-LUFA-140302/LUFA/makefile | 53 + .../lufa_functionlist_transform.xslt | 19 + .../lufa-LUFA-140302/Maintenance/makefile | 94 + .../KeyboardioHID/lufa-LUFA-140302/README.txt | 56 + .../KeyboardioHID/lufa-LUFA-140302/makefile | 26 + 521 files changed, 100192 insertions(+), 1 deletion(-) rename plugins/KeyboardioHID/{IMG_5687.JPG => DFU_Bridge.JPG} (100%) rename plugins/KeyboardioHID/{IMG_5688.JPG => No_HID_Bridge.JPG} (100%) create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/.gitignore create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/BootloaderAPI.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/BootloaderAPI.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/BootloaderAPITable.S create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/BootloaderCDC.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/BootloaderCDC.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/BootloaderCDC.txt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/Config/AppConfig.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/Config/LUFAConfig.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/Descriptors.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/Descriptors.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/LUFA CDC Bootloader.inf create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/asf.xml create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/doxyfile create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/makefile create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/DFU/BootloaderAPI.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/DFU/BootloaderAPI.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/DFU/BootloaderAPITable.S create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/DFU/BootloaderDFU.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/DFU/BootloaderDFU.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/DFU/BootloaderDFU.txt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/DFU/Config/AppConfig.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/DFU/Config/LUFAConfig.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/DFU/Descriptors.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/DFU/Descriptors.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/DFU/asf.xml create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/DFU/doxyfile create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/DFU/makefile create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/HID/BootloaderHID.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/HID/BootloaderHID.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/HID/BootloaderHID.txt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/HID/Config/LUFAConfig.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/HID/Descriptors.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/HID/Descriptors.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/HID/HostLoaderApp/Makefile create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/HID/HostLoaderApp/Makefile.bsd create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/HID/HostLoaderApp/gpl3.txt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/HID/HostLoaderApp/hid_bootloader_cli.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/HID/HostLoaderApp_Python/hid_bootloader_loader.py create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/HID/asf.xml create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/HID/doxyfile create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/HID/makefile create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/MassStorage/BootloaderAPI.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/MassStorage/BootloaderAPI.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/MassStorage/BootloaderAPITable.S create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/MassStorage/BootloaderMassStorage.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/MassStorage/BootloaderMassStorage.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/MassStorage/BootloaderMassStorage.txt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/MassStorage/Config/AppConfig.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/MassStorage/Config/LUFAConfig.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/MassStorage/Descriptors.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/MassStorage/Descriptors.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/MassStorage/Lib/SCSI.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/MassStorage/Lib/SCSI.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/MassStorage/Lib/VirtualFAT.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/MassStorage/Lib/VirtualFAT.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/MassStorage/asf.xml create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/MassStorage/doxyfile create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/MassStorage/makefile create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/Printer/BootloaderAPI.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/Printer/BootloaderAPI.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/Printer/BootloaderAPITable.S create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/Printer/BootloaderPrinter.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/Printer/BootloaderPrinter.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/Printer/BootloaderPrinter.txt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/Printer/Config/LUFAConfig.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/Printer/Descriptors.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/Printer/Descriptors.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/Printer/asf.xml create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/Printer/doxyfile create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/Printer/makefile create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/makefile create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/BuildTests/BoardDriverTest/Board/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/BuildTests/BoardDriverTest/Board/Buttons.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/BuildTests/BoardDriverTest/Board/Dataflash.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/BuildTests/BoardDriverTest/Board/Joystick.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/BuildTests/BoardDriverTest/Board/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/BuildTests/BoardDriverTest/BoardDeviceMap.cfg create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/BuildTests/BoardDriverTest/Test.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/BuildTests/BoardDriverTest/makefile create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/BuildTests/BoardDriverTest/makefile.test create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/BuildTests/BootloaderTest/BootloaderDeviceMap.cfg create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/BuildTests/BootloaderTest/makefile create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/BuildTests/ModuleTest/Dummy.S create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/BuildTests/ModuleTest/Modules.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/BuildTests/ModuleTest/Test_C.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/BuildTests/ModuleTest/Test_CPP.cpp create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/BuildTests/ModuleTest/makefile create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/BuildTests/ModuleTest/makefile.test create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/BuildTests/SingleUSBModeTest/Dummy.S create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/BuildTests/SingleUSBModeTest/Test.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/BuildTests/SingleUSBModeTest/makefile create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/BuildTests/SingleUSBModeTest/makefile.test create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/BuildTests/StaticAnalysisTest/makefile create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/BuildTests/makefile create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Build/HID_EEPROM_Loader/HID_EEPROM_Loader.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Build/HID_EEPROM_Loader/makefile create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Build/lufa_atprogram.mk create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Build/lufa_avrdude.mk create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Build/lufa_build.mk create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Build/lufa_core.mk create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Build/lufa_cppcheck.mk create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Build/lufa_dfu.mk create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Build/lufa_doxygen.mk create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Build/lufa_hid.mk create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Build/lufa_sources.mk create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/CodeTemplates/DeviceTemplate/Descriptors.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/CodeTemplates/DeviceTemplate/Descriptors.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/CodeTemplates/DeviceTemplate/DeviceApplication.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/CodeTemplates/DeviceTemplate/DeviceApplication.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/CodeTemplates/DeviceTemplate/asf.xml create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/CodeTemplates/DriverStubs/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/CodeTemplates/DriverStubs/Buttons.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/CodeTemplates/DriverStubs/Dataflash.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/CodeTemplates/DriverStubs/Joystick.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/CodeTemplates/DriverStubs/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/CodeTemplates/HostTemplate/HostApplication.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/CodeTemplates/HostTemplate/HostApplication.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/CodeTemplates/HostTemplate/asf.xml create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/CodeTemplates/LUFAConfig.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/CodeTemplates/WindowsINF/LUFA CDC-ACM.inf create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/CodeTemplates/WindowsINF/LUFA RNDIS.inf create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/CodeTemplates/makefile_template create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Common/ArchitectureSpecific.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Common/Architectures.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Common/Attributes.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Common/BoardTypes.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Common/Common.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Common/CompilerSpecific.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Common/Endianness.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/BuildSystem.txt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/BuildingLinkableLibraries.txt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/ChangeLog.txt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/CompileTimeTokens.txt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/CompilingApps.txt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/ConfiguringApps.txt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/DevelopingWithLUFA.txt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/DeviceSupport.txt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/DirectorySummaries.txt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/Donating.txt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/ExportingLibrary.txt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/FutureChanges.txt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/GettingStarted.txt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/Groups.txt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step1.png create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step2.png create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step3.png create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step4.png create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step5_1.png create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step5_2.png create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step5_3.png create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/Images/Author.jpg create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/Images/LUFA.png create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/Images/LUFA_thumb.png create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/KnownIssues.txt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/LUFAPoweredProjects.txt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/LibraryResources.txt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/LicenseInfo.txt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/MainPage.txt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/MigrationInformation.txt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/OSDrivers.txt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/ProgrammingApps.txt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/SoftwareBootloaderJump.txt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/Style/Footer.htm create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/Style/Style.css create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/VIDAndPIDValues.txt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/WritingBoardDrivers.txt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/ADAFRUITU4/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/ADAFRUITU4/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/ATAVRUSBRF01/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/ATAVRUSBRF01/Buttons.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/ATAVRUSBRF01/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BENITO/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BENITO/Buttons.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BENITO/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BIGMULTIO/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BIGMULTIO/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BLACKCAT/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BLACKCAT/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BUI/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BUI/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BUMBLEB/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BUMBLEB/Buttons.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BUMBLEB/Joystick.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BUMBLEB/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/CULV3/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/CULV3/Buttons.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/CULV3/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/DUCE/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/DUCE/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/EVK527/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/EVK527/Buttons.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/EVK527/Dataflash.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/EVK527/Joystick.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/EVK527/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/JMDBU2/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/JMDBU2/Buttons.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/JMDBU2/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/LEONARDO/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/LEONARDO/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MAXIMUS/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MAXIMUS/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MICROPENDOUS/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MICROPENDOUS/Buttons.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MICROPENDOUS/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MICROSIN162/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MICROSIN162/Buttons.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MICROSIN162/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MINIMUS/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MINIMUS/Buttons.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MINIMUS/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MULTIO/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MULTIO/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEX162/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEX162/Buttons.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEX162/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEX32U4/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEX32U4/Buttons.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEX32U4/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEXISPMK2/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEXISPMK2/Buttons.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEXISPMK2/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEXT32U4/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEXT32U4/Buttons.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEXT32U4/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/RZUSBSTICK/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/RZUSBSTICK/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/SPARKFUN8U2/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/SPARKFUN8U2/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STANGE_ISP/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STANGE_ISP/Buttons.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STANGE_ISP/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK525/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK525/Buttons.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK525/Dataflash.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK525/Joystick.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK525/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK526/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK526/Buttons.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK526/Dataflash.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK526/Joystick.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK526/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/TEENSY/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/TEENSY/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/TUL/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/TUL/Buttons.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/TUL/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/U2S/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/U2S/Buttons.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/U2S/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/UDIP/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/UDIP/Buttons.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/UDIP/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/UNO/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/UNO/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USB2AX/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USB2AX/Buttons.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USB2AX/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBFOO/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBFOO/Buttons.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBFOO/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBKEY/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBKEY/Buttons.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBKEY/Dataflash.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBKEY/Joystick.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBKEY/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBTINYMKII/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBTINYMKII/Buttons.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBTINYMKII/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/XPLAIN/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/XPLAIN/Dataflash.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/XPLAIN/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/Buttons.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/Dataflash.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/Joystick.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/Temperature.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/Temperature.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1100/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1100/Buttons.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1100/Joystick.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1100/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1101/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1101/Buttons.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1101/Joystick.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1101/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1104/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1104/Buttons.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1104/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/UC3A3_XPLAINED/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/UC3A3_XPLAINED/Buttons.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/UC3A3_XPLAINED/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/Buttons.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/Dataflash.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/Buttons.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/Dataflash.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/C3_XPLAINED/Board.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/C3_XPLAINED/Buttons.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/C3_XPLAINED/LEDs.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Misc/AT45DB321C.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Misc/AT45DB642D.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Misc/RingBuffer.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Misc/TerminalCodes.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/ADC.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/ADC_AVR8.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/SPI_AVR8.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/SerialSPI_AVR8.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/Serial_AVR8.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/Serial_AVR8.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/TWI_AVR8.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/TWI_AVR8.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/SPI.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/Serial.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/SerialSPI.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/TWI.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/XMEGA/SPI_XMEGA.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/XMEGA/SerialSPI_XMEGA.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/XMEGA/Serial_XMEGA.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/XMEGA/Serial_XMEGA.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/XMEGA/TWI_XMEGA.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/XMEGA/TWI_XMEGA.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/AndroidAccessoryClass.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/AudioClass.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/CDCClass.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/AndroidAccessoryClassCommon.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/AudioClassCommon.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/CDCClassCommon.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/HIDClassCommon.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/HIDParser.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/HIDParser.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/HIDReportData.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/MIDIClassCommon.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/MassStorageClassCommon.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/PrinterClassCommon.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/RNDISClassCommon.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/StillImageClassCommon.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/AudioClassDevice.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/AudioClassDevice.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/CDCClassDevice.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/CDCClassDevice.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/HIDClassDevice.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/HIDClassDevice.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/MIDIClassDevice.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/MIDIClassDevice.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/PrinterClassDevice.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/PrinterClassDevice.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/RNDISClassDevice.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/RNDISClassDevice.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/HIDClass.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/AndroidAccessoryClassHost.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/AndroidAccessoryClassHost.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/AudioClassHost.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/AudioClassHost.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/CDCClassHost.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/CDCClassHost.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/HIDClassHost.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/HIDClassHost.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/MIDIClassHost.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/MIDIClassHost.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/MassStorageClassHost.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/MassStorageClassHost.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/PrinterClassHost.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/PrinterClassHost.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/RNDISClassHost.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/RNDISClassHost.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/StillImageClassHost.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/StillImageClassHost.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/MIDIClass.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/MassStorageClass.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/PrinterClass.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/RNDISClass.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/StillImageClass.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Device_AVR8.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Device_AVR8.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/EndpointStream_AVR8.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/EndpointStream_AVR8.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Endpoint_AVR8.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Endpoint_AVR8.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Host_AVR8.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Host_AVR8.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/OTG_AVR8.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/PipeStream_AVR8.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/PipeStream_AVR8.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Pipe_AVR8.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Pipe_AVR8.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Template/Template_Endpoint_Control_R.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Template/Template_Endpoint_Control_W.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Template/Template_Endpoint_RW.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Template/Template_Pipe_RW.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/USBController_AVR8.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/USBController_AVR8.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/USBInterrupt_AVR8.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/USBInterrupt_AVR8.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/ConfigDescriptors.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/ConfigDescriptors.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/Device.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/DeviceStandardReq.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/DeviceStandardReq.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/Endpoint.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/EndpointStream.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/Events.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/Events.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/Host.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/HostStandardReq.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/HostStandardReq.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/OTG.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/Pipe.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/PipeStream.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/StdDescriptors.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/StdRequestType.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Device_UC3.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Device_UC3.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/EndpointStream_UC3.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/EndpointStream_UC3.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Endpoint_UC3.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Endpoint_UC3.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Host_UC3.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Host_UC3.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/PipeStream_UC3.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/PipeStream_UC3.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Pipe_UC3.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Pipe_UC3.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Template/Template_Endpoint_Control_R.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Template/Template_Endpoint_Control_W.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Template/Template_Endpoint_RW.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Template/Template_Pipe_RW.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/USBController_UC3.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/USBController_UC3.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/USBInterrupt_UC3.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/USBInterrupt_UC3.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/USBController.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/USBInterrupt.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/USBMode.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/USBTask.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/USBTask.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Device_XMEGA.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Device_XMEGA.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/EndpointStream_XMEGA.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/EndpointStream_XMEGA.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Host_XMEGA.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/PipeStream_XMEGA.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Pipe_XMEGA.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Template/Template_Endpoint_Control_R.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Template/Template_Endpoint_Control_W.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Template/Template_Endpoint_RW.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/USBInterrupt_XMEGA.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/USBInterrupt_XMEGA.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/USB.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/License.txt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Platform/Platform.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Platform/UC3/ClockManagement.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Platform/UC3/Exception.S create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Platform/UC3/InterruptManagement.c create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Platform/UC3/InterruptManagement.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Platform/UC3/UC3ExperimentalInfo.txt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Platform/XMEGA/ClockManagement.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Platform/XMEGA/XMEGAExperimentalInfo.txt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/HV1/helpcontentsetup.msha create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/HV1/lufa_docbook_transform.xslt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/HV1/lufa_helpcontentsetup_transform.xslt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/HV1/lufa_hv1_transform.xslt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/HV1/lufa_studio_help_styling.css create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/LUFA.dll create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/LUFA.pkgdef create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/[Content_Types].xml create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/asf-manifest.xml create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/extension.vsixmanifest create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/generate_caches.py create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/lufa_asfmanifest_transform.xslt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/lufa_vsmanifest_transform.xslt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/XDK/lufa_extension_transform.xslt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/XDK/lufa_filelist_transform.xslt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/XDK/lufa_indent_transform.xslt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/XDK/lufa_module_transform.xslt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa.xml create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_common.xml create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_board.xml create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_board_names.xml create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_misc.xml create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_peripheral.xml create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb.xml create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class.xml create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_android.xml create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_audio.xml create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_cdc.xml create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_hid.xml create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_midi.xml create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_ms.xml create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_printer.xml create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_rndis.xml create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_si.xml create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_core.xml create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_core_avr8.xml create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_core_uc3.xml create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_core_xmega.xml create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_platform.xml create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_platform_uc3.xml create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_platform_xmega.xml create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_toolchain.xml create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/makefile create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Version.h create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/doxyfile create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/makefile create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Maintenance/lufa_functionlist_transform.xslt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/Maintenance/makefile create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/README.txt create mode 100644 plugins/KeyboardioHID/lufa-LUFA-140302/makefile diff --git a/plugins/KeyboardioHID/IMG_5687.JPG b/plugins/KeyboardioHID/DFU_Bridge.JPG similarity index 100% rename from plugins/KeyboardioHID/IMG_5687.JPG rename to plugins/KeyboardioHID/DFU_Bridge.JPG diff --git a/plugins/KeyboardioHID/IMG_5688.JPG b/plugins/KeyboardioHID/No_HID_Bridge.JPG similarity index 100% rename from plugins/KeyboardioHID/IMG_5688.JPG rename to plugins/KeyboardioHID/No_HID_Bridge.JPG diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index cd17e423e6..c76ac8cb55 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -44,7 +44,7 @@ Connect GND and MOSI2 to deactivate HID function on Uno/Mega** To install the new bootloader connect your Arduino to your PC and put it into DFU mode. See [this](http://arduino.cc/en/Hacking/DFUProgramming8U2) and [this](http://forum.arduino.cc/index.php?topic=111.0) and also [this](http://andrewmemory.wordpress.com/2011/04/14/upgrading-the-arduino-uno-8u2-using-flip/) on how to upload -the hey file to your Arduino. Some notes here: The Arduino R3 doesnt need a resistor or so, just connect the two pins near +the hex file to your Arduino. Some notes here: The Arduino R3 doesnt need a resistor or so, just connect the two pins near the USB B jack. Choose atmega16u2 for the new R3 version. For older version you need to check the links. Upload the hex file to your Arduino. It doesnt care if its a Uno/Mega/Mega ADK. It will just work the same. diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/.gitignore b/plugins/KeyboardioHID/lufa-LUFA-140302/.gitignore new file mode 100644 index 0000000000..f9b900b00f --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/.gitignore @@ -0,0 +1,16 @@ +*.o +*.d +*.elf +*.hex +*.eep +*.sym +*.bin +*.lss +*.map +*.bak +*.class +Documentation/ +LUFA/StudioIntegration/ProjectGenerator/* +LUFA/StudioIntegration/DocBook/* +Demos/* +Projects/* diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/BootloaderAPI.c b/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/BootloaderAPI.c new file mode 100644 index 0000000000..f7564e9827 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/BootloaderAPI.h b/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/BootloaderAPI.h new file mode 100644 index 0000000000..2462cacdd0 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 + #include + #include + + #include + + #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/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/BootloaderAPITable.S b/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/BootloaderAPITable.S new file mode 100644 index 0000000000..69ebd387a9 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/BootloaderCDC.c b/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/BootloaderCDC.c new file mode 100644 index 0000000000..f66a483e6e --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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< 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_write_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_write_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/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/BootloaderCDC.h b/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/BootloaderCDC.h new file mode 100644 index 0000000000..9b326abc39 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 + #include + #include + #include + #include + #include + #include + + #include "Descriptors.h" + #include "BootloaderAPI.h" + #include "Config/AppConfig.h" + + #include + #include + #include + + /* 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/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/BootloaderCDC.txt b/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/BootloaderCDC.txt new file mode 100644 index 0000000000..1e054de45f --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/BootloaderCDC.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. + */ + +/** \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. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    USB Mode:Device
    USB Class:Communications Device Class (CDC)
    USB Subclass:Abstract Control Model (ACM)
    Relevant Standards:USBIF CDC Class Standard
    Supported USB Speeds:Full Speed Mode
    + * + * \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 THIS BOOTLOADER IS NOT SECURE. Malicious entities can recover written data, even if the device + * lockbits are set. + * + * \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 here for resolution steps. + * If the issue still persists then uninstall modemmanager by executing sudo apt-get remove modemmanager, 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 here 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. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    Define Name:Location:Description:
    NO_BLOCK_SUPPORTAppConfig.hDefine to disable memory block read/write support in the bootloader, requiring all reads and writes to be made + * using the byte-level commands.
    NO_EEPROM_BYTE_SUPPORTAppConfig.hDefine 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.
    NO_FLASH_BYTE_SUPPORTAppConfig.hDefine 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.
    NO_LOCK_BYTE_WRITE_SUPPORTAppConfig.hDefine to disable lock byte write support in the bootloader, preventing the lock bits from being set programmatically.
    + */ + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/Config/AppConfig.h b/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/Config/AppConfig.h new file mode 100644 index 0000000000..bbb5cb227e --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/Config/LUFAConfig.h b/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/Config/LUFAConfig.h new file mode 100644 index 0000000000..af2dd3060e --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/Descriptors.c b/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/Descriptors.c new file mode 100644 index 0000000000..2ff6b503ba --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/Descriptors.h b/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/Descriptors.h new file mode 100644 index 0000000000..ef04379179 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 + + #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/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/LUFA CDC Bootloader.inf b/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/LUFA CDC Bootloader.inf new file mode 100644 index 0000000000..61624c7318 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/asf.xml b/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/asf.xml new file mode 100644 index 0000000000..02e7063c66 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/asf.xml @@ -0,0 +1,161 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CDC Class Bootloader, capable of reprogramming a device using avrdude or other AVR109 protocol compliant software when plugged into a host. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/doxyfile b/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/doxyfile new file mode 100644 index 0000000000..5419c450d0 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/doxyfile @@ -0,0 +1,2337 @@ +# Doxyfile 1.8.6 + +# 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 + +# 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, 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 ... \endif and \cond +# ... \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. Do not use file names with spaces, bibtex cannot handle them. 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: +# +# +# +# where is the value of the INPUT_FILTER tag, and 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 acurate 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 an additional user- +# defined cascading style sheet that is 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 file to the output directory. 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. +# 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 + S +# (what the is depends on the OS and browser, but it is typically +# , /

    FPqH^r|^y4RA)#RWsuiSb%AAf1zTW*g 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 YNg#YQXZJ!({000eE2zt(WnTsU57kNqO#lD@ literal 0 HcmV?d00001 diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step2.png b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step2.png new file mode 100644 index 0000000000000000000000000000000000000000..6e309ae4151a4e02a859aca3a48319dd43807a2b GIT binary patch literal 100532 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

    N`w6 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 HhtK{GPaXat literal 0 HcmV?d00001 diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step5_2.png b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step5_2.png new file mode 100644 index 0000000000000000000000000000000000000000..078f4ec8d7b3b3920c1a65a7b0b52d8fbee3b7d9 GIT binary patch literal 28918 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 literal 0 HcmV?d00001 diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step5_3.png b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step5_3.png new file mode 100644 index 0000000000000000000000000000000000000000..8a8571bd86868ef9a1bfb12214138c17221c4bd8 GIT binary patch literal 23561 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 F|JfK#>ahR- literal 0 HcmV?d00001 diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/Images/LUFA.png b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/Images/LUFA.png new file mode 100644 index 0000000000000000000000000000000000000000..54fa1a66433491cb4b8cd9f5cdc6269f928f901c GIT binary patch literal 10296 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 v$pN2bPDNB8 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 literal 0 HcmV?d00001 diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/KnownIssues.txt b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/KnownIssues.txt new file mode 100644 index 0000000000..d283b0f84f --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/KnownIssues.txt @@ -0,0 +1,138 @@ +/** \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_KnownIssues140302 Version 140302 + * - AVR8 Architecture + * - No known issues. + * - UC3 Architecture + * \warning The UC3 device support is currently experimental (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 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 experimental (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 (Project->Project {name} Properties... 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 experimental (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 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 experimental (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 (Project->Project {name} Properties... 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 experimental (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 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 experimental (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 experimental (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 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 experimental (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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/LUFAPoweredProjects.txt b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/LUFAPoweredProjects.txt new file mode 100644 index 0000000000..aac397afb5 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/LUFAPoweredProjects.txt @@ -0,0 +1,221 @@ +/** \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://www.cappels.org/dproj/AttoBasic2_1/AttoBasic_2.1_with_USB_and_Arduino_support.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 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 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 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.dyndns.org: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 "nxpusblib" LUFA fork, for LPC devices: http://www.lpcware.com/content/project/nxpusblib + * \li Kevin Mehall's LUFA port to the NXP LPC13xx: https://github.com/kevinmehall/LUFA-LPC13xx + * \li Mark Ding's port for the Silabs SiM3U1xx: https://www.github.com/MarkDing/USB_CDC + * + */ diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/LibraryResources.txt b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/LibraryResources.txt new file mode 100644 index 0000000000..f69d4344c1 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/LicenseInfo.txt b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/LicenseInfo.txt new file mode 100644 index 0000000000..86ed124bb2 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 must 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/MainPage.txt b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/MainPage.txt new file mode 100644 index 0000000000..e737c39b5a --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 + *

    + * \n + * + * \n + * + * LUFA is donationware. For author and donation information, see \ref Page_Donating. + * + * 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. + * + * Subsections: + * \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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/MigrationInformation.txt b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/MigrationInformation.txt new file mode 100644 index 0000000000..cf3cc17492 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/MigrationInformation.txt @@ -0,0 +1,703 @@ +/** \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_Migration140302 Migrating from 130901 to 140302 + * USB Core + * - 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. + * + * Non-USB Library Components + * - 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. + * + * Build System + * - 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 + * Non-USB Library Components + * - The Board Dataflash \c Dataflash_Init() function now automatically configures the appropriate communication interface. + * + * \section Sec_Migration130303 Migrating from 120730 to 130303 + * Device Mode + * - 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. + * + * Host Mode + * - 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 + * Device Mode + * - 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. + * + * Host Mode + * - 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 + * USB Core + * - 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. + * + * Device Mode + * - 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 + * Non-USB Library Components + * - The \c JTAG_DEBUG_ASSERT() macro has been renamed \ref JTAG_ASSERT() to be consistent with \ref STDOUT_ASSERT(). + * + * USB Core + * - 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. + * + * Device Mode + * - 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. + * + * Host Mode + * - 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 + * USB Core + * - 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. + * + * Device Mode + * - 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. + * + * Host Mode + * - 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 + * + * Non-USB Library Components + * - 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. + * + * USB Core + * - 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. + * + * Device Mode + * - 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. + * + * Host Mode + * - 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 + * + * Non-USB Library Components + * - 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. + * + * Device Mode + * - 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. + * + * Host Mode + * - 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 + * + * Non-USB Library Components + * - 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. + * + * Host Mode + * - 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(). + * + * Device Mode + * - 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 + * + * Host Mode + * - 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. + * + * Device Mode + * - 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 + * + * Host Mode + * - 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 + * + * Non-USB Library Components + * - 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 + * + * Host Mode + * - 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. + * + * Device Mode + * - 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 + * + * All + * - The "Simple Scheduler" has been deprecated, 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. + * + * Non-USB Library Components + * - 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. + * + * Library Demos + * - 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. + * + * Host Mode + * - 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. + * + * Device Mode + * - 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 + * + * Device Mode + * - 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 must be implemented in the user application. + * + * Host Mode + * - 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 + * + * All + * - 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. + * + * Dual Role Mode + * - 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. + * + * Device Mode + * - 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. + * + * Host Mode + * - 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 + * + * All + * - 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 and call \c clock_prescale_set(clock_div_1); instead on recent avr-libc distributions. + * + * Library Demos + * - The USBtoSerial demo now discards all data when not connected to a host, rather than buffering it for later transmission. + * + * Non-USB Library Components + * - 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(). + * + * Device Mode + * - 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 + * + * Device Mode + * - 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. + * + * Host Mode + * - 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. + * + * Non-USB Library Components + * - 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 + * + * All + * - 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. + * + * Library Demos + * - 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. + * + * Non-USB Library Components + * - The Serial_IsCharReceived() macro has been changed to the correct spelling of Serial_IsCharReceived() in Serial.h. + * + * Device Mode + * - 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. + * + * Host Mode + * - 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 + * + * Library Demos + * - 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. + * + * Device Mode + * - 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. + * + * Host Mode + * - 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 + * + * Library Demos + * - 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 + * + * Library Demos + * - 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 + * + * Library Demos + * - 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. + * + * Non-USB Library Components + * - 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. + * + * Device Mode + * - 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 not 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. + * + * Host Mode + * - 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. + * + * Dual Role Mode + * - 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/OSDrivers.txt b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/OSDrivers.txt new file mode 100644 index 0000000000..4823c5b089 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 + * native support on modern operating systems. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    USB ClassAndroidWindowsLinuxOS X
    Android Open Accessory2.3.4+N/AN/AN/A
    Audio 1.0N/AXP+2.6.?+10.?+
    CDC-ACMN/AXP+2.6.?+10.?+
    HID3.?+XP+2.6.?+10.?+
    MIDIN/AXP+2.6.?+10.?+
    Mass StorageN/AXP+2.6.?+10.?+
    PrinterN/AXP+2.6.?+10.?+
    RNDISN/AXP+2.6.?+N/A
    Still ImageN/AXP+2.6.?+10.?+
    + * + * \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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/ProgrammingApps.txt b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/ProgrammingApps.txt new file mode 100644 index 0000000000..4759ac87ae --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 atmel.com 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/SoftwareBootloaderJump.txt b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/SoftwareBootloaderJump.txt new file mode 100644 index 0000000000..0b69612b68 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 + * #include + * #include + * + * #include + * #include + * + * 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 FLASH_SIZE_BYTES and + * BOOTLOADER_SEC_SIZE_BYTES 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/Style/Footer.htm b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/Style/Footer.htm new file mode 100644 index 0000000000..a72c5bdd24 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/Style/Footer.htm @@ -0,0 +1,35 @@ + + + + + + + + + \ No newline at end of file diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/Style/Style.css b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/Style/Style.css new file mode 100644 index 0000000000..933215546f --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/VIDAndPIDValues.txt b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/VIDAndPIDValues.txt new file mode 100644 index 0000000000..6d39ce7f90 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * These VID/PID values should not be used in commercial designs under any circumstances. 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. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    VIDPIDUsage
    0x03EB0x2040Test VID/PID (See \ref Sec_Test_VIDPID)
    0x03EB0x2041Mouse Demo Application
    0x03EB0x2042Keyboard Demo Application
    0x03EB0x2043Joystick Demo Application
    0x03EB0x2044CDC Demo Application
    0x03EB0x2045Mass Storage Demo Application
    0x03EB0x2046Audio Output Demo Application
    0x03EB0x2047Audio Input Demo Application
    0x03EB0x2048MIDI Demo Application
    0x03EB0x2049MagStripe Project
    0x03EB0x204ACDC Class Bootloader
    0x03EB0x204BUSB to Serial Demo Application
    0x03EB0x204CRNDIS Demo Application
    0x03EB0x204DCombined Keyboard and Mouse Demo Application
    0x03EB0x204EDual CDC Demo Application
    0x03EB + * 0x204F + * Generic HID Demo Application
    0x03EB0x2060Benito Programmer Project
    0x03EB0x2061Combined Mass Storage and Keyboard Demo
    0x03EB0x2062Combined CDC and Mouse Demo
    0x03EB0x2063Mass Storage/HID Interface Datalogger Project
    0x03EB0x2064Interfaceless Control-Only LUFA Devices
    0x03EB0x2065Test and Measurement Demo
    0x03EB + * 0x2066 + * Multiple Report Keyboard/Mouse HID Demo
    0x03EB0x2067HID Class Bootloader
    0x03EB0x2068Virtual Serial/Mass Storage Demo
    0x03EB + * 0x2069 + * Webserver Project
    0x03EB0x206AMedia Control Project
    0x03EB0x206BPrinter Class Bootloader
    0x03EB0x206CBulk Vendor Demo
    0x03EB0x206DCurrently Unallocated
    0x03EB0x206ECurrently Unallocated
    0x03EB0x206FCurrently Unallocated
    + * + * \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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/WritingBoardDrivers.txt b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/DoxygenPages/WritingBoardDrivers.txt new file mode 100644 index 0000000000..b2ff07e666 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 LUFA/Drivers/Board, you must also indicate which + * board hardware you are using in your project makefile. This is done by defining the BOARD macro using + * the -D switch passed to the compiler, with a constant of BOARD_{Name}. For example, + * -DBOARD=BOARD_USBKEY instructs the compiler to use the USBKEY board hardware drivers. + * + * If your application does not use any board level drivers, you can omit the definition of the BOARD + * 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 BOARD macro should be defined to the value BOARD_USER. + * 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 LUFA/CodeTemplates/DriverStubs folder should be copied to + * the user application's Board/ 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 + * LUFA/Drivers/Board/ 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 + * \include "DriverStubs/Board.h" + * + * \subsection SSec_BoardTemplates_Buttons Template for USER + * \include "DriverStubs/Buttons.h" + * + * \subsection SSec_BoardTemplates_Dataflash Template for USER + * \include "DriverStubs/Dataflash.h" + * + * \subsection SSec_BoardTemplates_Joystick Template for USER + * \include "DriverStubs/Joystick.h" + * + * \subsection SSec_BoardTemplates_LEDs Template for USER + * \include "DriverStubs/LEDs.h" + */ + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/ADAFRUITU4/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/ADAFRUITU4/Board.h new file mode 100644 index 0000000000..48016e0bf4 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/ADAFRUITU4/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/ADAFRUITU4/LEDs.h new file mode 100644 index 0000000000..9f312207b8 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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). + * + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenGeneral IndicatorHighPORTE.6
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/ATAVRUSBRF01/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/ATAVRUSBRF01/Board.h new file mode 100644 index 0000000000..07000ecddf --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/ATAVRUSBRF01/Buttons.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/ATAVRUSBRF01/Buttons.h new file mode 100644 index 0000000000..8b815dbcb6 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * + * + * + *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTD.7
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/ATAVRUSBRF01/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/ATAVRUSBRF01/LEDs.h new file mode 100644 index 0000000000..76e89fd0df --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenRX LEDHighPORTD.0
    LEDS_LED2RedTX LEDHighPORTD.1
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BENITO/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BENITO/Board.h new file mode 100644 index 0000000000..5584e1ea7e --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BENITO/Buttons.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BENITO/Buttons.h new file mode 100644 index 0000000000..96d14a3ae0 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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). + * + * + * + * + *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTD.7
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BENITO/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BENITO/LEDs.h new file mode 100644 index 0000000000..49df441918 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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). + * + * + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenTX LEDLowPORTC.7
    LEDS_LED2RedRX LEDLowPORTC.6
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BIGMULTIO/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BIGMULTIO/Board.h new file mode 100644 index 0000000000..9d4e301306 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BIGMULTIO/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BIGMULTIO/LEDs.h new file mode 100644 index 0000000000..93d5bec97e --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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). + * + * + * + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1UnknownLED0HighPORTF.6
    LEDS_LED2UnknownLED1HighPORTF.7
    LEDS_LED3UnknownLED2HighPORTE.2
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BLACKCAT/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BLACKCAT/Board.h new file mode 100644 index 0000000000..6eec7bf7d1 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BLACKCAT/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BLACKCAT/LEDs.h new file mode 100644 index 0000000000..4a72039aed --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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). + * + * + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1UnknownLED0HighPORTD.6
    LEDS_LED2UnknownLED1HighPORTD.3
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BUI/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BUI/Board.h new file mode 100644 index 0000000000..067e870d88 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BUI/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BUI/LEDs.h new file mode 100644 index 0000000000..e06edb5fc1 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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). + * + * + * + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1RedRGB LEDHighPORTC.2
    LEDS_LED2GreenRGB LEDHighPORTC.3
    LEDS_LED3BlueRGB LEDHighPORTC.4
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BUMBLEB/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BUMBLEB/Board.h new file mode 100644 index 0000000000..906f0b5e06 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BUMBLEB/Buttons.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BUMBLEB/Buttons.h new file mode 100644 index 0000000000..0495425919 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * + * + * + *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTD.7
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BUMBLEB/Joystick.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BUMBLEB/Joystick.h new file mode 100644 index 0000000000..82d085e89c --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * + * + * + *
    Left Port PinUp Port PinRight Port PinDown Port PinPress Port Pin
    PORTD.2PORTD.3PORTD.0PORTD.1PORTD.4
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BUMBLEB/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BUMBLEB/LEDs.h new file mode 100644 index 0000000000..5cd7b483c6 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * + * + * + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1N/AUser SuppliedHighPORTB.4
    LEDS_LED2N/AUser SuppliedHighPORTB.5
    LEDS_LED3N/AUser SuppliedHighPORTB.6
    LEDS_LED4N/AUser SuppliedHighPORTB.7
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/CULV3/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/CULV3/Board.h new file mode 100644 index 0000000000..777902d274 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/CULV3/Buttons.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/CULV3/Buttons.h new file mode 100644 index 0000000000..6a26a99808 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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). + * + * + * + * + *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTE.2
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/CULV3/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/CULV3/LEDs.h new file mode 100644 index 0000000000..3d2b8fda07 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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). + * + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1YellowGeneral IndicatorHighPORTE.6
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/DUCE/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/DUCE/Board.h new file mode 100644 index 0000000000..44cf6918bf --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/DUCE/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/DUCE/LEDs.h new file mode 100644 index 0000000000..83cadedffa --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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). + * + * + * + * + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1RedBicolor Indicator 1HighPORTC.4
    LEDS_LED2GreenBicolor Indicator 1HighPORTC.5
    LEDS_LED3RedBicolor Indicator 2HighPORTC.6
    LEDS_LED4GreenBicolor Indicator 2HighPORTC.7
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/EVK527/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/EVK527/Board.h new file mode 100644 index 0000000000..c77c18b9b8 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/EVK527/Buttons.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/EVK527/Buttons.h new file mode 100644 index 0000000000..239880cc63 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * + * + * + *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTE.2
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/EVK527/Dataflash.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/EVK527/Dataflash.h new file mode 100644 index 0000000000..38b2b58892 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * + * + * + *
    NameInfoSelect PinSPI Port
    DATAFLASH_CHIP1AT45DB321C (4MB)PORTE.6SPI0
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/EVK527/Joystick.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/EVK527/Joystick.h new file mode 100644 index 0000000000..492c706993 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * + * + * + *
    Left Port PinUp Port PinRight Port PinDown Port PinPress Port Pin
    PORTF.4PORTF.5PORTF.7PORTC.6PORTF.6
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/EVK527/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/EVK527/LEDs.h new file mode 100644 index 0000000000..84e689a4b7 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * + * + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenGeneral IndicatorHighPORTD.5
    LEDS_LED2GreenGeneral IndicatorHighPORTD.6
    LEDS_LED3GreenGeneral IndicatorHighPORTD.7
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/JMDBU2/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/JMDBU2/Board.h new file mode 100644 index 0000000000..0f1aca09dd --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/JMDBU2/Buttons.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/JMDBU2/Buttons.h new file mode 100644 index 0000000000..80500993dc --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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). + * + * + * + * + *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTD.7
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/JMDBU2/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/JMDBU2/LEDs.h new file mode 100644 index 0000000000..562103e33b --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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). + * + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenGeneral IndicatorHighPORTD.4
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/LEONARDO/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/LEONARDO/Board.h new file mode 100644 index 0000000000..95ef437f56 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/LEONARDO/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/LEONARDO/LEDs.h new file mode 100644 index 0000000000..28a4802676 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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). + * + * + * + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1YellowRXLowPORTB.0
    LEDS_LED2YellowTXLowPORTD.5
    LEDS_LED1YellowGeneral IndicatorHighPORTC.7
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MAXIMUS/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MAXIMUS/Board.h new file mode 100644 index 0000000000..929e60a8cc --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MAXIMUS/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MAXIMUS/LEDs.h new file mode 100644 index 0000000000..695949a176 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/). + * + * + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenLGHighPORTB.6
    LEDS_LED2RedLRHighPORTB.7
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MICROPENDOUS/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MICROPENDOUS/Board.h new file mode 100644 index 0000000000..b84bf790b1 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MICROPENDOUS/Buttons.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MICROPENDOUS/Buttons.h new file mode 100644 index 0000000000..8adff2d30d --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 BOARD = MICROPENDOUS_{VERSION}. + * + * Board specific Buttons driver header for the Micropendous 32U2 (https://code.google.com/p/micropendous/wiki/Micropendous_32U2). + * + * BOARD_MICROPENDOUS_1 and BOARD_MICROPENDOUS_32U2: + * + * + * + *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTD.7
    + * + * Other Revisions: + * + * + * + *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTE.2
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MICROPENDOUS/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MICROPENDOUS/LEDs.h new file mode 100644 index 0000000000..253ad31422 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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). + * + * BOARD_MICROPENDOUS_32U2: + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenGeneral IndicatorHighPORTD.6
    + * + * Other Revisions: + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenGeneral IndicatorHighPORTB.1
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MICROSIN162/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MICROSIN162/Board.h new file mode 100644 index 0000000000..3ffb028c0d --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MICROSIN162/Buttons.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MICROSIN162/Buttons.h new file mode 100644 index 0000000000..68344feb22 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/). + * + * + * + * + *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTD.7
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MICROSIN162/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MICROSIN162/LEDs.h new file mode 100644 index 0000000000..51d1b3eba8 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/). + * + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenGeneral IndicatorLowPORTD.4
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MINIMUS/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MINIMUS/Board.h new file mode 100644 index 0000000000..80b8b3c86c --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MINIMUS/Buttons.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MINIMUS/Buttons.h new file mode 100644 index 0000000000..ec94445a80 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * + * + * + *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTD.7
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MINIMUS/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MINIMUS/LEDs.h new file mode 100644 index 0000000000..adc34686fe --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/). + * + * + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1BlueGeneral IndicatorLowPORTD.5
    LEDS_LED2RedGeneral IndicatorLowPORTD.6
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MULTIO/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MULTIO/Board.h new file mode 100644 index 0000000000..84f3d87250 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MULTIO/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MULTIO/LEDs.h new file mode 100644 index 0000000000..ca6d440414 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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). + * + * + * + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenGeneral IndicatorHighPORTD.0
    LEDS_LED2GreenGeneral IndicatorHighPORTC.2
    LEDS_LED3GreenGeneral IndicatorHighPORTD.7
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEX162/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEX162/Board.h new file mode 100644 index 0000000000..b9bcf77344 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEX162/Buttons.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEX162/Buttons.h new file mode 100644 index 0000000000..3714c5e9ae --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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). + * + * + * + * + *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTD.7
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEX162/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEX162/LEDs.h new file mode 100644 index 0000000000..5ecc1f5d79 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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). + * + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1YellowGeneral IndicatorHighPORTD.4
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEX32U4/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEX32U4/Board.h new file mode 100644 index 0000000000..657b15c6d7 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEX32U4/Buttons.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEX32U4/Buttons.h new file mode 100644 index 0000000000..8e33fd965c --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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). + * + * + * + * + *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTE.2
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEX32U4/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEX32U4/LEDs.h new file mode 100644 index 0000000000..259859c90c --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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). + * + * + * + * + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenTXHighPORTD.5
    LEDS_LED2YellowRXHighPORTB.0
    LEDS_LED3GreenGeneral Indicator (Default Unconnected)HighPORTE.6
    LEDS_LED4YellowGeneral Indicator (Default Unconnected)HighPORTB.5
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEXISPMK2/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEXISPMK2/Board.h new file mode 100644 index 0000000000..d318a82b03 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEXISPMK2/Buttons.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEXISPMK2/Buttons.h new file mode 100644 index 0000000000..aff10b1035 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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). + * + * + * + * + *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTD.7
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEXISPMK2/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEXISPMK2/LEDs.h new file mode 100644 index 0000000000..033fca05e6 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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). + * + * + * + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1YellowTarget PowerHighPORTB.5
    LEDS_LED2RedActivityHighPORTB.6
    LEDS_LED3GreenReadyHighPORTB.7
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEXT32U4/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEXT32U4/Board.h new file mode 100644 index 0000000000..690fee1534 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEXT32U4/Buttons.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEXT32U4/Buttons.h new file mode 100644 index 0000000000..634eda9cb8 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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). + * + * + * + * + *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTE.2
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEXT32U4/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEXT32U4/LEDs.h new file mode 100644 index 0000000000..2bbaf6826e --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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). + * + * + * + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1YellowRXHighPORTB.0
    LEDS_LED2GreenTXHighPORTD.5
    LEDS_LED3N/AGeneral Indicator (Not Mounted)HighPORTE.6
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/RZUSBSTICK/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/RZUSBSTICK/Board.h new file mode 100644 index 0000000000..6fc3666739 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/RZUSBSTICK/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/RZUSBSTICK/LEDs.h new file mode 100644 index 0000000000..6ebcdfc6b0 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * + * + * + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1BlueGeneral IndicatorHighPORTD.7
    LEDS_LED1RedGeneral IndicatorLowPORTD.5
    LEDS_LED1GreenGeneral IndicatorLowPORTE.6
    LEDS_LED1YellowGeneral IndicatorLowPORTE.7
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/SPARKFUN8U2/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/SPARKFUN8U2/Board.h new file mode 100644 index 0000000000..49cc2e5105 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/SPARKFUN8U2/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/SPARKFUN8U2/LEDs.h new file mode 100644 index 0000000000..b8eb4abfea --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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). + * + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenGeneral IndicatorLowPORTB.4
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STANGE_ISP/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STANGE_ISP/Board.h new file mode 100644 index 0000000000..36594fcc03 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STANGE_ISP/Buttons.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STANGE_ISP/Buttons.h new file mode 100644 index 0000000000..d4576b6885 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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). + * + * + * + * + *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTD.7
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STANGE_ISP/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STANGE_ISP/LEDs.h new file mode 100644 index 0000000000..9f10683795 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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). + * + * + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenGeneral IndicatorLowPORTD.0
    LEDS_LED2RedGeneral IndicatorLowPORTD.1
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK525/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK525/Board.h new file mode 100644 index 0000000000..bda925bb5b --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK525/Buttons.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK525/Buttons.h new file mode 100644 index 0000000000..532a46f1dd --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * + * + * + *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTE.2
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK525/Dataflash.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK525/Dataflash.h new file mode 100644 index 0000000000..825a7a524f --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * + * + * + *
    NameInfoSelect PinSPI Port
    DATAFLASH_CHIP1AT45DB321C (4MB)PORTB.4SPI0
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK525/Joystick.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK525/Joystick.h new file mode 100644 index 0000000000..6b9b4f42c6 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * + * + * + *
    Left Port PinUp Port PinRight Port PinDown Port PinPress Port Pin
    PORTB.6PORTB.7PORTE.4PORTE.5PORTB.5
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK525/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK525/LEDs.h new file mode 100644 index 0000000000..53948b461b --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * + * + * + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenGeneral IndicatorHighPORTD.4
    LEDS_LED2GreenGeneral IndicatorHighPORTD.5
    LEDS_LED3GreenGeneral IndicatorHighPORTD.6
    LEDS_LED4GreenGeneral IndicatorHighPORTD.7
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK526/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK526/Board.h new file mode 100644 index 0000000000..6be146fcd5 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK526/Buttons.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK526/Buttons.h new file mode 100644 index 0000000000..bc598d389c --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * + * + * + *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTD.7
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK526/Dataflash.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK526/Dataflash.h new file mode 100644 index 0000000000..d2a59b12e2 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * + * + * + *
    NameInfoSelect PinSPI Port
    DATAFLASH_CHIP1AT45DB642D (8MB)PORTC.2SPI0
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK526/Joystick.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK526/Joystick.h new file mode 100644 index 0000000000..7decabc5da --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * + * + * + *
    Left Port PinUp Port PinRight Port PinDown Port PinPress Port Pin
    PORTB.4PORTB.5PORTB.6PORTB.7PORTB.0
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK526/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK526/LEDs.h new file mode 100644 index 0000000000..71525e9619 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * + * + * + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenGeneral IndicatorHighPORTD.1
    LEDS_LED2GreenGeneral IndicatorHighPORTD.0
    LEDS_LED3GreenGeneral IndicatorHighPORTD.5
    LEDS_LED4GreenGeneral IndicatorHighPORTD.4
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/TEENSY/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/TEENSY/Board.h new file mode 100644 index 0000000000..52e4d61148 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/TEENSY/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/TEENSY/LEDs.h new file mode 100644 index 0000000000..9f872247ed --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 BOARD = TEENSY2. + * + * Board specific LED driver header for the PJRC Teensy boards (http://www.pjrc.com/teensy/index.html). + * + * TEENSY: + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenGeneral IndicatorHighPORTD.6
    + * + * TEENSY2: + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenGeneral IndicatorLowPORTD.6
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/TUL/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/TUL/Board.h new file mode 100644 index 0000000000..7759c37cb7 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/TUL/Buttons.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/TUL/Buttons.h new file mode 100644 index 0000000000..bbcca263d4 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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). + * + * + * + * + *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTE.2
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/TUL/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/TUL/LEDs.h new file mode 100644 index 0000000000..8a14b8a9a6 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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). + * + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenGeneral IndicatorHighPORTF.0
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/U2S/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/U2S/Board.h new file mode 100644 index 0000000000..128580a95b --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/U2S/Buttons.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/U2S/Buttons.h new file mode 100644 index 0000000000..30f0a9f5b5 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/). + * + * + * + * + *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTC.4
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/U2S/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/U2S/LEDs.h new file mode 100644 index 0000000000..d7cf7cfb17 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/). + * + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1RedGeneral IndicatorLowPORTC.2
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/UDIP/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/UDIP/Board.h new file mode 100644 index 0000000000..3a400053c4 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/UDIP/Buttons.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/UDIP/Buttons.h new file mode 100644 index 0000000000..dab29a60a8 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/). + * + * + * + * + *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTD.7
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/UDIP/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/UDIP/LEDs.h new file mode 100644 index 0000000000..fbcc8ff660 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/). + * + * + * + * + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenBicolor Indicator 1HighPORTB.6
    LEDS_LED2RedBicolor Indicator 1HighPORTB.5
    LEDS_LED3GreenBicolor Indicator 2HighPORTD.5
    LEDS_LED4RedBicolor Indicator 2HighPORTD.4
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/UNO/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/UNO/Board.h new file mode 100644 index 0000000000..b23f8d0fd4 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/UNO/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/UNO/LEDs.h new file mode 100644 index 0000000000..006c3a5ddf --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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). + * + * + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1YellowRXLowPORTD.4
    LEDS_LED2YellowTXLowPORTD.5
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USB2AX/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USB2AX/Board.h new file mode 100644 index 0000000000..05a4dea5a9 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USB2AX/Buttons.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USB2AX/Buttons.h new file mode 100644 index 0000000000..170a9affb2 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 BOARD = USB2AX_V3 and for version 3.1, with BOARD = USB2AX_V31. + * + * Board specific Buttons driver header for the Paranoid Studio USB2AX (http://paranoidstudio.assembla.com/wiki/show/paranoidstudio/USB2AX). + * + * + * + * + *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTD.7
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USB2AX/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USB2AX/LEDs.h new file mode 100644 index 0000000000..03550fc00d --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 BOARD = USB2AX_V3 and for version 3.1, with BOARD = USB2AX_V31. + * + * Board specific LED driver header for the Xevelabs USB2AX (http://paranoidstudio.assembla.com/wiki/show/paranoidstudio/USB2AX). + * + * USB2AX: + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenGeneral IndicatorHighPORTC.6
    + * + * USB2AX_V3: + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenGeneral IndicatorHighPORTD.1
    + * + * USB2AX_V31: + * + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenGeneral IndicatorHighPORTD.5
    LEDS_LED2RedGeneral IndicatorHighPORTD.6
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBFOO/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBFOO/Board.h new file mode 100644 index 0000000000..15c41ab5ec --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBFOO/Buttons.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBFOO/Buttons.h new file mode 100644 index 0000000000..e901437d71 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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). + * + * + * + * + *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTD.7
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBFOO/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBFOO/LEDs.h new file mode 100644 index 0000000000..e396630df5 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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). + * + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenGeneral IndicatorLowPORTD.4
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBKEY/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBKEY/Board.h new file mode 100644 index 0000000000..3663056566 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBKEY/Buttons.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBKEY/Buttons.h new file mode 100644 index 0000000000..3ec7b3acd2 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * + * + * + *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTE.2
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBKEY/Dataflash.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBKEY/Dataflash.h new file mode 100644 index 0000000000..85a8dda3d4 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * + * + * + * + *
    NameInfoSelect PinSPI Port
    DATAFLASH_CHIP1AT45DB642D (8MB)PORTE.0SPI0
    DATAFLASH_CHIP2AT45DB642D (8MB)PORTE.1SPI0
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBKEY/Joystick.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBKEY/Joystick.h new file mode 100644 index 0000000000..45d5a66a88 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * + * + * + *
    Left Port PinUp Port PinRight Port PinDown Port PinPress Port Pin
    PORTB.6PORTB.7PORTE.4PORTE.5PORTB.5
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBKEY/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBKEY/LEDs.h new file mode 100644 index 0000000000..dc02da52e3 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * + * + * + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1RedBicolor Indicator 1HighPORTD.4
    LEDS_LED2GreenBicolor Indicator 1HighPORTD.5
    LEDS_LED3RedBicolor Indicator 2HighPORTD.6
    LEDS_LED4GreenBicolor Indicator 2HighPORTD.7
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBTINYMKII/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBTINYMKII/Board.h new file mode 100644 index 0000000000..492aced782 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBTINYMKII/Buttons.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBTINYMKII/Buttons.h new file mode 100644 index 0000000000..682239cd72 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/). + * + * + * + * + *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTD.7
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBTINYMKII/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBTINYMKII/LEDs.h new file mode 100644 index 0000000000..a2decbc497 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/). + * + * + * + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1RedBicolor Indicator 1HighPORTB.6
    LEDS_LED2GreenBicolor Indicator 1HighPORTB.7
    LEDS_LED3RedTarget PowerHighPORTB.5
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/XPLAIN/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/XPLAIN/Board.h new file mode 100644 index 0000000000..57ad4c98b1 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/XPLAIN/Dataflash.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/XPLAIN/Dataflash.h new file mode 100644 index 0000000000..a8078f61f6 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 BOARD = BOARD_XPLAIN_REV1. + * + * Board specific Dataflash driver header for the Atmel XPLAIN. + * + * Revision 1 Boards: + * + * + * + *
    NameInfoSelect PinSPI Port
    DATAFLASH_CHIP1AT45DB041D (512KB)PORTB.5SPI0
    + * + * Other Board Revisions: + * + * + * + *
    NameInfoSelect PinSPI Port
    DATAFLASH_CHIP1AT45DB642D (8MB)PORTB.5SPI0
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/XPLAIN/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/XPLAIN/LEDs.h new file mode 100644 index 0000000000..338b1b419c --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenGeneral IndicatorLowPORTB.6
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/Board.h new file mode 100644 index 0000000000..9372d0b499 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/Board.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 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" + #else + #include "Board/Board.h" + #endif + +#endif + +/** @} */ + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/Buttons.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/Buttons.h new file mode 100644 index 0000000000..dc22cc1ab5 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/Dataflash.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/Dataflash.h new file mode 100644 index 0000000000..134a08de0b --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/Dataflash.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 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 SPI and board Dataflash drivers before first use + * SPI_Init(SPI_SPEED_FCPU_DIV_2 | SPI_ORDER_MSB_FIRST | SPI_SCK_LEAD_FALLING | + * SPI_SAMPLE_TRAILING | SPI_MODE_MASTER); + * 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/Joystick.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/Joystick.h new file mode 100644 index 0000000000..4ecf61fefc --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/LEDs.h new file mode 100644 index 0000000000..90485c83e1 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/LEDs.h @@ -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 + * \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" + #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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/Temperature.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/Temperature.c new file mode 100644 index 0000000000..8b09f1094b --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/Temperature.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/Temperature.h new file mode 100644 index 0000000000..d20c6f7018 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 (Makefile source module name: LUFA_SRC_TEMPERATURE) + * + * \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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1100/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1100/Board.h new file mode 100644 index 0000000000..0c34a3f049 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1100/Buttons.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1100/Buttons.h new file mode 100644 index 0000000000..fa452003fe --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * + * + * + * + * + *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1SW0 ButtonLowGPIO88
    BUTTONS_BUTTON2SW1 ButtonLowGPIO85
    BUTTONS_BUTTON3SW2 ButtonLowGPIO82
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1100/Joystick.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1100/Joystick.h new file mode 100644 index 0000000000..72dd769b05 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * + * + * + *
    Left Port PinUp Port PinRight Port PinDown Port PinPress Port Pin
    GPIO25GPIO26GPIO28GPIO27GPIO20
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1100/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1100/LEDs.h new file mode 100644 index 0000000000..f66eddbc1e --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * + * + * + * + * + * + * + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenLED0 LEDLowGPIO51
    LEDS_LED2GreenLED1 LEDLowGPIO52
    LEDS_LED3GreenLED2 LEDLowGPIO53
    LEDS_LED4GreenLED3 LEDLowGPIO54
    LEDS_LED5GreenLED4 LEDLowGPIO59
    LEDS_LED6GreenLED5 LEDLowGPIO60
    LEDS_LED7GreenLED6 LEDLowGPIO61
    LEDS_LED8GreenLED7 LEDLowGPIO62
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1101/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1101/Board.h new file mode 100644 index 0000000000..5d5f95a6a5 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1101/Buttons.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1101/Buttons.h new file mode 100644 index 0000000000..3de4b3373c --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * + * + * + * + *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1SW0 ButtonLowGPIO34
    BUTTONS_BUTTON2SW1 ButtonLowGPIO35
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1101/Joystick.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1101/Joystick.h new file mode 100644 index 0000000000..f7a9a7538b --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * + * + * + *
    Left Port PinUp Port PinRight Port PinDown Port PinPress Port Pin
    GPIO38GPIO39GPIO41GPIO40GPIO13
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1101/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1101/LEDs.h new file mode 100644 index 0000000000..dad7771a26 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * + * + * + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenLED0 LEDLowGPIO7
    LEDS_LED2GreenLED1 LEDLowGPIO8
    LEDS_LED3GreenLED2 LEDLowGPIO21
    LEDS_LED4GreenLED3 LEDLowGPIO22
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1104/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1104/Board.h new file mode 100644 index 0000000000..aa7adbfb0c --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1104/Buttons.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1104/Buttons.h new file mode 100644 index 0000000000..dfcfb665ea --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * + * + * + *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1SW0 ButtonLowGPIO42
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1104/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1104/LEDs.h new file mode 100644 index 0000000000..2258a267f1 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * + * + * + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenLED0 LEDLowGPIO67
    LEDS_LED2GreenLED1 LEDLowGPIO101
    LEDS_LED3GreenLED2 LEDLowGPIO102
    LEDS_LED4GreenLED3 LEDLowGPIO105
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/UC3A3_XPLAINED/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/UC3A3_XPLAINED/Board.h new file mode 100644 index 0000000000..ec4d9c7c94 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/UC3A3_XPLAINED/Buttons.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/UC3A3_XPLAINED/Buttons.h new file mode 100644 index 0000000000..8accb6fe1c --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * + * + * + *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1SW0 ButtonLowGPIO32
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/UC3A3_XPLAINED/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/UC3A3_XPLAINED/LEDs.h new file mode 100644 index 0000000000..66b7834c73 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * + * + * + * + * + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1YellowLED0 LEDLowGPIO35
    LEDS_LED2YellowLED1 LEDLowGPIO73
    LEDS_LED3YellowLED2 LEDLowGPIO34
    LEDS_LED4YellowLED3 LEDLowGPIO38
    LEDS_LED5GreenStatusLowGPIO50
    LEDS_LED6RedPowerHighGPIO49
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/Board.h new file mode 100644 index 0000000000..824c3db498 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/Buttons.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/Buttons.h new file mode 100644 index 0000000000..d5119eb5ca --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * + * + * + * + * + *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1SW0 ButtonLowPORTE.5
    BUTTONS_BUTTON2SW1 ButtonLowPORTF.1
    BUTTONS_BUTTON3SW2 ButtonLowPORTF.2
    + * + * @{ + */ + +#ifndef __BUTTONS_A3BU_XPLAINED_H__ +#define __BUTTONS_A3BU_XPLAINED_H__ + + /* Includes: */ + #include + + /* 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/Dataflash.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/Dataflash.h new file mode 100644 index 0000000000..2d0983941c --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * + * + * + *
    NameInfoSelect PinSPI Port
    DATAFLASH_CHIP1AT45DB642D (8MB)PORTF.4USARTD0 (In SPI Mode)
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/LEDs.h new file mode 100644 index 0000000000..16abfbc974 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * + * + * + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1YellowLED0 LEDLowPORTR.0
    LEDS_LED2YellowLED1 LEDLowPORTR.1
    LEDS_LED3RedStatus Bicolour Red LEDLowPORTD.4
    LEDS_LED4GreenStatus Bicolour Green LEDHighPORTD.5
    + * + * @{ + */ + +#ifndef __LEDS_A3BU_XPLAINED_H__ +#define __LEDS_A3BU_XPLAINED_H__ + + /* Includes: */ + #include + + /* 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/Board.h new file mode 100644 index 0000000000..d807d18b34 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/Buttons.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/Buttons.h new file mode 100644 index 0000000000..9c458b4966 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * + * + * + * + * + * + *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1Touch CS0 ButtonLowPORTE.0
    BUTTONS_BUTTON2Touch CS1 ButtonLowPORTE.1
    BUTTONS_BUTTON3Touch CS2 ButtonLowPORTE.2
    BUTTONS_BUTTON4Touch CS3 ButtonLowPORTE.3
    + * + * @{ + */ + +#ifndef __BUTTONS_B1_XPLAINED_H__ +#define __BUTTONS_B1_XPLAINED_H__ + + /* Includes: */ + #include + + /* 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/Dataflash.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/Dataflash.h new file mode 100644 index 0000000000..f02ca4af0f --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * + * + * + *
    NameInfoSelect PinSPI Port
    DATAFLASH_CHIP1AT45DB642D (8MB)PORTD.2USARTC0 (In SPI Mode, Remapped)
    + * + * @{ + */ + +#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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/LEDs.h new file mode 100644 index 0000000000..7bd31ad094 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * + * + * + * + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1YellowLED0 LEDHighPORTB.4
    LEDS_LED2YellowLED1 LEDHighPORTB.5
    LEDS_LED3YellowLED2 LEDHighPORTB.6
    LEDS_LED4YellowLED3 LEDHighPORTB.7
    LEDS_LED5GreenUSB LEDLowPORTE.4
    + * + * @{ + */ + +#ifndef __LEDS_B1_XPLAINED_H__ +#define __LEDS_B1_XPLAINED_H__ + + /* Includes: */ + #include + + /* 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/C3_XPLAINED/Board.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/C3_XPLAINED/Board.h new file mode 100644 index 0000000000..d90cc3a5c6 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/C3_XPLAINED/Buttons.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/C3_XPLAINED/Buttons.h new file mode 100644 index 0000000000..db62b1d1f1 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * + * + * + * + *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1SW0 ButtonLowPORTF.1
    BUTTONS_BUTTON2SW1 ButtonLowPORTF.2
    + * + * @{ + */ + +#ifndef __BUTTONS_C3_XPLAINED_H__ +#define __BUTTONS_C3_XPLAINED_H__ + + /* Includes: */ + #include + + /* 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/C3_XPLAINED/LEDs.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/C3_XPLAINED/LEDs.h new file mode 100644 index 0000000000..737624bd39 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * + * + * + * + * + * + *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1YellowLED0 LEDLowPORTR.0
    LEDS_LED2YellowLED1 LEDLowPORTR.1
    LEDS_LED3RedStatus Bicolour Red LEDLowPORTD.4
    LEDS_LED4GreenStatus Bicolour Green LEDHighPORTD.5
    + * + * @{ + */ + +#ifndef __LEDS_C3_XPLAINED_H__ +#define __LEDS_C3_XPLAINED_H__ + + /* Includes: */ + #include + + /* 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Misc/AT45DB321C.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Misc/AT45DB321C.h new file mode 100644 index 0000000000..25069286fe --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Misc/AT45DB642D.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Misc/AT45DB642D.h new file mode 100644 index 0000000000..ebbad71f95 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Misc/RingBuffer.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Misc/RingBuffer.h new file mode 100644 index 0000000000..68fdb8e92c --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Misc/TerminalCodes.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Misc/TerminalCodes.h new file mode 100644 index 0000000000..d43fe010c5 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/ADC.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/ADC.h new file mode 100644 index 0000000000..295c6e1e85 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/ADC_AVR8.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/ADC_AVR8.h new file mode 100644 index 0000000000..03b6ed0c29 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 not 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 not 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/SPI_AVR8.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/SPI_AVR8.h new file mode 100644 index 0000000000..1b8f53e2b1 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/SerialSPI_AVR8.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/SerialSPI_AVR8.h new file mode 100644 index 0000000000..7afaf1bd43 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/SerialSPI_AVR8.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 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 | SPI_SAMPLE_LEADING | 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 + + /* 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 SPI_Init(). Indicates that the SCK should lead on the rising edge. */ + #define USART_SPI_SCK_LEAD_RISING (0 << UCPOL) + + /** 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 << UCPOL) + //@} + + /** \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 << UPCHA) + + /** 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 << UPCHA) + //@} + + /** \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 << UDORD) + + /** SPI data order mask for \ref SerialSPI_Init(). Indicates that data should be shifted out LSB first. */ + #define USART_SPI_ORDER_LSB_FIRST (1 << UDORD) + //@} + + /* 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/Serial_AVR8.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/Serial_AVR8.c new file mode 100644 index 0000000000..8785a4b6db --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/Serial_AVR8.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/Serial_AVR8.h new file mode 100644 index 0000000000..f951f6b74c --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/Serial_AVR8.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 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 + + /* 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 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); + } + + /** Transmits a given byte through the USART. + * + * \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 (!(UCSR1A & (1 << UDRE1))); + 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/TWI_AVR8.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/TWI_AVR8.c new file mode 100644 index 0000000000..2a6c160e8f --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/TWI_AVR8.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/TWI_AVR8.h new file mode 100644 index 0000000000..584b584fe0 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * Low Level API Example: + * \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 + * + * High Level API Example: + * \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 + #include + + /* 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
    F_CPU / (16 + 2 * BitLength + 4 ^ Prescale)
    . + * + * \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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/SPI.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/SPI.h new file mode 100644 index 0000000000..54c46423e8 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/Serial.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/Serial.h new file mode 100644 index 0000000000..46ee61b209 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/ARCH/Serial_ARCH.c (Makefile source module name: LUFA_SRC_SERIAL) + * + * \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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/SerialSPI.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/SerialSPI.h new file mode 100644 index 0000000000..9a42ba5d96 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/TWI.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/TWI.h new file mode 100644 index 0000000000..5290e66795 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/ARCH/TWI_ARCH.c (Makefile source module name: LUFA_SRC_TWI) + * + * \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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/XMEGA/SPI_XMEGA.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/XMEGA/SPI_XMEGA.h new file mode 100644 index 0000000000..c6230481ed --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/XMEGA/SerialSPI_XMEGA.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/XMEGA/SerialSPI_XMEGA.h new file mode 100644 index 0000000000..a981ce6a6d --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 + + /* 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/XMEGA/Serial_XMEGA.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/XMEGA/Serial_XMEGA.c new file mode 100644 index 0000000000..4e2935730e --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/XMEGA/Serial_XMEGA.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/XMEGA/Serial_XMEGA.h new file mode 100644 index 0000000000..1161ef674c --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/XMEGA/Serial_XMEGA.h @@ -0,0 +1,257 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2014. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaims all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an 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 + + /* 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 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); + } + + /** Transmits a given byte through the USART. + * + * \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 (!(USART->STATUS & USART_DREIF_bm)); + 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/XMEGA/TWI_XMEGA.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/XMEGA/TWI_XMEGA.c new file mode 100644 index 0000000000..457b87cd06 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/XMEGA/TWI_XMEGA.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/Peripheral/XMEGA/TWI_XMEGA.h new file mode 100644 index 0000000000..72437e5e15 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * Low Level API Example: + * \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 + * + * High Level API Example: + * \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 + + /* 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
    F_CPU / (2 * (5 + (BAUD)))
    . + * + * \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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/AndroidAccessoryClass.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/AndroidAccessoryClass.h new file mode 100644 index 0000000000..24978ca2e3 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/AudioClass.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/AudioClass.h new file mode 100644 index 0000000000..0e3ca8d751 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 (Makefile source module name: LUFA_SRC_USBCLASS) + * - LUFA/Drivers/USB/Class/Host/AudioClassHost.c (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/CDCClass.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/CDCClass.h new file mode 100644 index 0000000000..3bad74bfa1 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 (Makefile source module name: LUFA_SRC_USBCLASS) + * - LUFA/Drivers/USB/Class/Host/CDCClassHost.c (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/AndroidAccessoryClassCommon.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/AndroidAccessoryClassCommon.h new file mode 100644 index 0000000000..c3153dab71 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/AudioClassCommon.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/AudioClassCommon.h new file mode 100644 index 0000000000..2db5eeea1d --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 must 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 must 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/CDCClassCommon.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/CDCClassCommon.h new file mode 100644 index 0000000000..94e6c68db1 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/HIDClassCommon.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/HIDClassCommon.h new file mode 100644 index 0000000000..f1e1d070d3 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/HIDClassCommon.h @@ -0,0 +1,665 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2014. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaims all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an 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_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_MANU 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_SISREQ 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_ANDPROPS 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 + //@} + + /** \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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/HIDParser.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/HIDParser.c new file mode 100644 index 0000000000..d93508f495 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/HIDParser.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/HIDParser.h new file mode 100644 index 0000000000..1f84ef44ff --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 (Makefile source module name: LUFA_SRC_USB) + * + * \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 must 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/HIDReportData.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/HIDReportData.h new file mode 100644 index 0000000000..df4302cc73 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/MIDIClassCommon.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/MIDIClassCommon.h new file mode 100644 index 0000000000..3e601ea5e5 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/MassStorageClassCommon.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/MassStorageClassCommon.h new file mode 100644 index 0000000000..8a12f31b80 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/PrinterClassCommon.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/PrinterClassCommon.h new file mode 100644 index 0000000000..1edd1dd0e1 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/RNDISClassCommon.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/RNDISClassCommon.h new file mode 100644 index 0000000000..5c6d3fdcc5 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/RNDISClassCommon.h @@ -0,0 +1,414 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2014. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaims all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an 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 a RNDIS control message which can be sent or received. */ + #define RNDIS_MESSAGE_BUFFER_SIZE 128 + + /** 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/StillImageClassCommon.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/StillImageClassCommon.h new file mode 100644 index 0000000000..09a9eab35e --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/AudioClassDevice.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/AudioClassDevice.c new file mode 100644 index 0000000000..f862ba7647 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/AudioClassDevice.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/AudioClassDevice.h new file mode 100644 index 0000000000..6cdf4db700 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \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 + * must 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/CDCClassDevice.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/CDCClassDevice.c new file mode 100644 index 0000000000..f4e74cf906 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/CDCClassDevice.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/CDCClassDevice.h new file mode 100644 index 0000000000..05c0fdddb3 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \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 + + /* 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 + * must 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 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 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/HIDClassDevice.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/HIDClassDevice.c new file mode 100644 index 0000000000..e46330f945 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/HIDClassDevice.c @@ -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. +*/ + +#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(); + 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/HIDClassDevice.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/HIDClassDevice.h new file mode 100644 index 0000000000..f373cf0769 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \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 + * must 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/MIDIClassDevice.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/MIDIClassDevice.c new file mode 100644 index 0000000000..b002525975 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/MIDIClassDevice.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/MIDIClassDevice.h new file mode 100644 index 0000000000..70eb442911 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \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 + * must 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.c new file mode 100644 index 0000000000..d0907963a3 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.h new file mode 100644 index 0000000000..513221308d --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \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 + * must 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/PrinterClassDevice.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/PrinterClassDevice.c new file mode 100644 index 0000000000..fd3454b1ad --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/PrinterClassDevice.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/PrinterClassDevice.h new file mode 100644 index 0000000000..d9d9644cbe --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \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 + + /* 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 + * must 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 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 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/RNDISClassDevice.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/RNDISClassDevice.c new file mode 100644 index 0000000000..061f1b2496 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/RNDISClassDevice.c @@ -0,0 +1,502 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2014. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaims all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + 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->State.RNDISMessageBuffer, 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->State.RNDISMessageBuffer; + + if (!(MessageHeader->MessageLength)) + { + RNDISInterfaceInfo->State.RNDISMessageBuffer[0] = 0; + MessageHeader->MessageLength = CPU_TO_LE32(1); + } + + Endpoint_ClearSETUP(); + Endpoint_Write_Control_Stream_LE(RNDISInterfaceInfo->State.RNDISMessageBuffer, 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 (!(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->State.RNDISMessageBuffer; + + 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->State.RNDISMessageBuffer; + RNDIS_Initialize_Complete_t* INITIALIZE_Response = + (RNDIS_Initialize_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer; + + 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->State.RNDISMessageBuffer; + RNDIS_Query_Complete_t* QUERY_Response = (RNDIS_Query_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer; + uint32_t Query_Oid = CPU_TO_LE32(QUERY_Message->Oid); + + void* QueryData = &RNDISInterfaceInfo->State.RNDISMessageBuffer[sizeof(RNDIS_Message_Header_t) + + le32_to_cpu(QUERY_Message->InformationBufferOffset)]; + void* ResponseData = &RNDISInterfaceInfo->State.RNDISMessageBuffer[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->State.RNDISMessageBuffer; + RNDIS_Set_Complete_t* SET_Response = (RNDIS_Set_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer; + 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->State.RNDISMessageBuffer[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->State.RNDISMessageBuffer; + + 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->State.RNDISMessageBuffer; + RNDIS_KeepAlive_Complete_t* KEEPALIVE_Response = + (RNDIS_KeepAlive_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer; + + 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(RNDIS_MESSAGE_BUFFER_SIZE + 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/RNDISClassDevice.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/RNDISClassDevice.h new file mode 100644 index 0000000000..4ba729a7e9 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/RNDISClassDevice.h @@ -0,0 +1,203 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2014. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaims all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an 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 (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \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. */ + } Config; /**< Config data for the USB class interface within the device. All elements in this section + * must be set or the interface will fail to enumerate and operate correctly. + */ + struct + { + uint8_t RNDISMessageBuffer[RNDIS_MESSAGE_BUFFER_SIZE]; /**< Buffer to hold RNDIS messages to and from the host, + * managed by the class driver. + */ + 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__) + /* 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/HIDClass.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/HIDClass.h new file mode 100644 index 0000000000..d2eea75321 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 (Makefile source module name: LUFA_SRC_USBCLASS) + * - LUFA/Drivers/USB/Class/Host/HIDClassHost.c (Makefile source module name: LUFA_SRC_USBCLASS) + * - LUFA/Drivers/USB/Class/Host/HIDParser.c (Makefile source module name: LUFA_SRC_USB) + * + * \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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/AndroidAccessoryClassHost.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/AndroidAccessoryClassHost.c new file mode 100644 index 0000000000..57a619ff47 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 false; + + if (!(Pipe_ConfigurePipeTable(&AOAInterfaceInfo->Config.DataOUTPipe, 1))) + return false; + + 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/AndroidAccessoryClassHost.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/AndroidAccessoryClassHost.h new file mode 100644 index 0000000000..0476f2e023 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \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 + + /* 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 + * must 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 + * may 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 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 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/AudioClassHost.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/AudioClassHost.c new file mode 100644 index 0000000000..c437654b60 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 false; + + if (!(Pipe_ConfigurePipeTable(&AudioInterfaceInfo->Config.DataOUTPipe, 1))) + return false; + + 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/AudioClassHost.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/AudioClassHost.h new file mode 100644 index 0000000000..b00bb5fcd3 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \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 + * must 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 + * may 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/CDCClassHost.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/CDCClassHost.c new file mode 100644 index 0000000000..a575c1bbf6 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 false; + + if (!(Pipe_ConfigurePipeTable(&CDCInterfaceInfo->Config.DataOUTPipe, 1))) + return false; + + if (!(Pipe_ConfigurePipeTable(&CDCInterfaceInfo->Config.NotificationPipe, 1))) + return false; + + 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/CDCClassHost.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/CDCClassHost.h new file mode 100644 index 0000000000..aeee23e50b --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \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 + + /* 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 + * must 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 + * may 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 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 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/HIDClassHost.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/HIDClassHost.c new file mode 100644 index 0000000000..c3375e67e3 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 false; + + 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 false; + } + + 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 false; + + 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/HIDClassHost.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/HIDClassHost.h new file mode 100644 index 0000000000..703b698dfb --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \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 + * must 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 + * may 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 must 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 must 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/MIDIClassHost.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/MIDIClassHost.c new file mode 100644 index 0000000000..7ec26549d5 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 false; + + if (!(Pipe_ConfigurePipeTable(&MIDIInterfaceInfo->Config.DataOUTPipe, 1))) + return false; + + 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/MIDIClassHost.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/MIDIClassHost.h new file mode 100644 index 0000000000..7624f8ed93 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \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 + * must 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 + * may 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/MassStorageClassHost.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/MassStorageClassHost.c new file mode 100644 index 0000000000..d5bace70e8 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 false; + + if (!(Pipe_ConfigurePipeTable(&MSInterfaceInfo->Config.DataOUTPipe, 1))) + return false; + + 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/MassStorageClassHost.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/MassStorageClassHost.h new file mode 100644 index 0000000000..6e558073b8 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \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 + * must 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 + * may 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/PrinterClassHost.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/PrinterClassHost.c new file mode 100644 index 0000000000..7eda9f605e --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 false; + + if (!(Pipe_ConfigurePipeTable(&PRNTInterfaceInfo->Config.DataOUTPipe, 1))) + return false; + + 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/PrinterClassHost.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/PrinterClassHost.h new file mode 100644 index 0000000000..8089aa5921 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \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 + * must 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 + * may 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/RNDISClassHost.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/RNDISClassHost.c new file mode 100644 index 0000000000..9072d3aa64 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 false; + + if (!(Pipe_ConfigurePipeTable(&RNDISInterfaceInfo->Config.DataOUTPipe, 1))) + return false; + + if (!(Pipe_ConfigurePipeTable(&RNDISInterfaceInfo->Config.NotificationPipe, 1))) + return false; + + 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/RNDISClassHost.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/RNDISClassHost.h new file mode 100644 index 0000000000..79334b41b0 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \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 + * must 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 + * may 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/StillImageClassHost.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/StillImageClassHost.c new file mode 100644 index 0000000000..b3d74bc1ef --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 false; + + if (!(Pipe_ConfigurePipeTable(&SIInterfaceInfo->Config.DataOUTPipe, 1))) + return false; + + if (!(Pipe_ConfigurePipeTable(&SIInterfaceInfo->Config.EventsPipe, 1))) + return false; + + 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/StillImageClassHost.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/StillImageClassHost.h new file mode 100644 index 0000000000..f9f41adb69 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \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 + * must 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 + * may 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/MIDIClass.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/MIDIClass.h new file mode 100644 index 0000000000..7e6ba1c5b9 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 (Makefile source module name: LUFA_SRC_USBCLASS) + * - LUFA/Drivers/USB/Class/Host/MIDIClassHost.c (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/MassStorageClass.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/MassStorageClass.h new file mode 100644 index 0000000000..79a052163a --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 (Makefile source module name: LUFA_SRC_USBCLASS) + * - LUFA/Drivers/USB/Class/Host/MassStorageClassHost.c (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/PrinterClass.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/PrinterClass.h new file mode 100644 index 0000000000..91121b5d04 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 (Makefile source module name: LUFA_SRC_USBCLASS) + * - LUFA/Drivers/USB/Class/Host/PrinterClassHost.c (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/RNDISClass.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/RNDISClass.h new file mode 100644 index 0000000000..1555f0d232 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 (Makefile source module name: LUFA_SRC_USBCLASS) + * - LUFA/Drivers/USB/Class/Host/RNDISClassHost.c (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/StillImageClass.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Class/StillImageClass.h new file mode 100644 index 0000000000..f2ec37b03b --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 (Makefile source module name: LUFA_SRC_USBCLASS) + * + * \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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Device_AVR8.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Device_AVR8.c new file mode 100644 index 0000000000..d23e7b8468 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Device_AVR8.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Device_AVR8.h new file mode 100644 index 0000000000..5efffe7b8d --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/EndpointStream_AVR8.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/EndpointStream_AVR8.c new file mode 100644 index 0000000000..5782824cc4 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/EndpointStream_AVR8.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/EndpointStream_AVR8.h new file mode 100644 index 0000000000..2032789764 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * Single Stream Transfer Example: + * \code + * uint8_t ErrorCode; + * + * if ((ErrorCode = Endpoint_Discard_Stream(512, NULL)) != ENDPOINT_RWSTREAM_NoError) + * { + * // Stream failed to complete - check ErrorCode here + * } + * \endcode + * + * Partial Stream Transfers Example: + * \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. + * + * Single Stream Transfer Example: + * \code + * uint8_t ErrorCode; + * + * if ((ErrorCode = Endpoint_Null_Stream(512, NULL)) != ENDPOINT_RWSTREAM_NoError) + * { + * // Stream failed to complete - check ErrorCode here + * } + * \endcode + * + * Partial Stream Transfers Example: + * \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. + * + * Single Stream Transfer Example: + * \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 + * + * Partial Stream Transfers Example: + * \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. + * + * Single Stream Transfer Example: + * \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 + * + * Partial Stream Transfers Example: + * \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 status 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 status 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 status 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 status 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 status 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 status 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 status 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 status 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 status 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 status 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Endpoint_AVR8.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Endpoint_AVR8.c new file mode 100644 index 0000000000..f5d20341b7 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Endpoint_AVR8.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Endpoint_AVR8.h new file mode 100644 index 0000000000..1632d93cfc --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 must 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 (1 << {Endpoint Number}). + * + * \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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Host_AVR8.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Host_AVR8.c new file mode 100644 index 0000000000..4e38c75a60 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Host_AVR8.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Host_AVR8.h new file mode 100644 index 0000000000..f0ffa5a54c --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/OTG_AVR8.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/OTG_AVR8.h new file mode 100644 index 0000000000..c2e8496274 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/PipeStream_AVR8.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/PipeStream_AVR8.c new file mode 100644 index 0000000000..47169b3feb --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/PipeStream_AVR8.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/PipeStream_AVR8.h new file mode 100644 index 0000000000..264dab54e9 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * Single Stream Transfer Example: + * \code + * uint8_t ErrorCode; + * + * if ((ErrorCode = Pipe_Discard_Stream(512, NULL)) != PIPE_RWSTREAM_NoError) + * { + * // Stream failed to complete - check ErrorCode here + * } + * \endcode + * + * Partial Stream Transfers Example: + * \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. + * + * Single Stream Transfer Example: + * \code + * uint8_t ErrorCode; + * + * if ((ErrorCode = Pipe_Null_Stream(512, NULL)) != PIPE_RWSTREAM_NoError) + * { + * // Stream failed to complete - check ErrorCode here + * } + * \endcode + * + * Partial Stream Transfers Example: + * \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. + * + * Single Stream Transfer Example: + * \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 + * + * Partial Stream Transfers Example: + * \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. + * + * Single Stream Transfer Example: + * \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 + * + * Partial Stream Transfers Example: + * \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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Pipe_AVR8.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Pipe_AVR8.c new file mode 100644 index 0000000000..fc99ae416d --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Pipe_AVR8.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Pipe_AVR8.h new file mode 100644 index 0000000000..bac324ffc0 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 must 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Template/Template_Endpoint_Control_R.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Template/Template_Endpoint_Control_R.c new file mode 100644 index 0000000000..59c620ae59 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Template/Template_Endpoint_Control_W.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Template/Template_Endpoint_Control_W.c new file mode 100644 index 0000000000..4fc242f34b --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Template/Template_Endpoint_Control_W.c @@ -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. +*/ + +#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; + } + + return ENDPOINT_RWCSTREAM_NoError; +} + +#undef TEMPLATE_BUFFER_OFFSET +#undef TEMPLATE_BUFFER_MOVE +#undef TEMPLATE_FUNC_NAME +#undef TEMPLATE_TRANSFER_BYTE + +#endif + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Template/Template_Endpoint_RW.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Template/Template_Endpoint_RW.c new file mode 100644 index 0000000000..d51afdfb16 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Template/Template_Pipe_RW.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Template/Template_Pipe_RW.c new file mode 100644 index 0000000000..2685c9b9db --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/USBController_AVR8.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/USBController_AVR8.c new file mode 100644 index 0000000000..71c5f916d7 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/USBController_AVR8.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/USBController_AVR8.h new file mode 100644 index 0000000000..de34f42a17 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/USBInterrupt_AVR8.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/USBInterrupt_AVR8.c new file mode 100644 index 0000000000..7efaea65a0 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/USBInterrupt_AVR8.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/USBInterrupt_AVR8.h new file mode 100644 index 0000000000..e6f5ff994e --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/ConfigDescriptors.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/ConfigDescriptors.c new file mode 100644 index 0000000000..da6812a323 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/ConfigDescriptors.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/ConfigDescriptors.h new file mode 100644 index 0000000000..b4a9788c28 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/Device.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/Device.h new file mode 100644 index 0000000000..10d739f569 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/DeviceStandardReq.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/DeviceStandardReq.c new file mode 100644 index 0000000000..adf615a9c4 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/DeviceStandardReq.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/DeviceStandardReq.h new file mode 100644 index 0000000000..396e205547 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/Endpoint.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/Endpoint.h new file mode 100644 index 0000000000..bf41376f4f --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/EndpointStream.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/EndpointStream.h new file mode 100644 index 0000000000..5675c323cc --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/Events.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/Events.c new file mode 100644 index 0000000000..a63b002fec --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/Events.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/Events.h new file mode 100644 index 0000000000..9c85112fb8 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/Host.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/Host.h new file mode 100644 index 0000000000..6146cc5aeb --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/HostStandardReq.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/HostStandardReq.c new file mode 100644 index 0000000000..4a21ce73c0 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/HostStandardReq.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/HostStandardReq.h new file mode 100644 index 0000000000..bd67bcb9e9 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/OTG.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/OTG.h new file mode 100644 index 0000000000..58d47bace3 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/Pipe.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/Pipe.h new file mode 100644 index 0000000000..ca3fdbe7ad --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/PipeStream.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/PipeStream.h new file mode 100644 index 0000000000..2399696874 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/StdDescriptors.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/StdDescriptors.h new file mode 100644 index 0000000000..e0a1a37f4f --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 + * http://www.usb.org/developers/docs/InterfaceAssociationDescriptor_ecn.pdf. 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 + * http://www.usb.org/developers/docs/InterfaceAssociationDescriptor_ecn.pdf. 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/StdRequestType.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/StdRequestType.h new file mode 100644 index 0000000000..b2506cd7d2 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Device_UC3.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Device_UC3.c new file mode 100644 index 0000000000..6f6de3f5e9 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Device_UC3.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Device_UC3.h new file mode 100644 index 0000000000..5579ea0bc4 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/EndpointStream_UC3.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/EndpointStream_UC3.c new file mode 100644 index 0000000000..6e98629277 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/EndpointStream_UC3.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/EndpointStream_UC3.h new file mode 100644 index 0000000000..831c714070 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * Single Stream Transfer Example: + * \code + * uint8_t ErrorCode; + * + * if ((ErrorCode = Endpoint_Discard_Stream(512, NULL)) != ENDPOINT_RWSTREAM_NoError) + * { + * // Stream failed to complete - check ErrorCode here + * } + * \endcode + * + * Partial Stream Transfers Example: + * \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. + * + * Single Stream Transfer Example: + * \code + * uint8_t ErrorCode; + * + * if ((ErrorCode = Endpoint_Null_Stream(512, NULL)) != ENDPOINT_RWSTREAM_NoError) + * { + * // Stream failed to complete - check ErrorCode here + * } + * \endcode + * + * Partial Stream Transfers Example: + * \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. + * + * Single Stream Transfer Example: + * \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 + * + * Partial Stream Transfers Example: + * \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. + * + * Single Stream Transfer Example: + * \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 + * + * Partial Stream Transfers Example: + * \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 status 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 status 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 status 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 status 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Endpoint_UC3.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Endpoint_UC3.c new file mode 100644 index 0000000000..5dce488f20 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Endpoint_UC3.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Endpoint_UC3.h new file mode 100644 index 0000000000..cf35d2b60c --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 must 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 (1 << {Endpoint Number}). + * + * \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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Host_UC3.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Host_UC3.c new file mode 100644 index 0000000000..77807525f0 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Host_UC3.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Host_UC3.h new file mode 100644 index 0000000000..eb803b073e --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/PipeStream_UC3.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/PipeStream_UC3.c new file mode 100644 index 0000000000..7dfe448585 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/PipeStream_UC3.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/PipeStream_UC3.h new file mode 100644 index 0000000000..4dd79c975f --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * Single Stream Transfer Example: + * \code + * uint8_t ErrorCode; + * + * if ((ErrorCode = Pipe_Discard_Stream(512, NULL)) != PIPE_RWSTREAM_NoError) + * { + * // Stream failed to complete - check ErrorCode here + * } + * \endcode + * + * Partial Stream Transfers Example: + * \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. + * + * Single Stream Transfer Example: + * \code + * uint8_t ErrorCode; + * + * if ((ErrorCode = Pipe_Null_Stream(512, NULL)) != PIPE_RWSTREAM_NoError) + * { + * // Stream failed to complete - check ErrorCode here + * } + * \endcode + * + * Partial Stream Transfers Example: + * \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. + * + * Single Stream Transfer Example: + * \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 + * + * Partial Stream Transfers Example: + * \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. + * + * Single Stream Transfer Example: + * \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 + * + * Partial Stream Transfers Example: + * \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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Pipe_UC3.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Pipe_UC3.c new file mode 100644 index 0000000000..a24c7b1d6a --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Pipe_UC3.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Pipe_UC3.h new file mode 100644 index 0000000000..1a0ada8b7b --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 must 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Template/Template_Endpoint_Control_R.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Template/Template_Endpoint_Control_R.c new file mode 100644 index 0000000000..59c620ae59 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Template/Template_Endpoint_Control_W.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Template/Template_Endpoint_Control_W.c new file mode 100644 index 0000000000..4fc242f34b --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Template/Template_Endpoint_Control_W.c @@ -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. +*/ + +#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; + } + + return ENDPOINT_RWCSTREAM_NoError; +} + +#undef TEMPLATE_BUFFER_OFFSET +#undef TEMPLATE_BUFFER_MOVE +#undef TEMPLATE_FUNC_NAME +#undef TEMPLATE_TRANSFER_BYTE + +#endif + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Template/Template_Endpoint_RW.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Template/Template_Endpoint_RW.c new file mode 100644 index 0000000000..d51afdfb16 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Template/Template_Pipe_RW.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Template/Template_Pipe_RW.c new file mode 100644 index 0000000000..2685c9b9db --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/USBController_UC3.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/USBController_UC3.c new file mode 100644 index 0000000000..fda0ddc393 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/USBController_UC3.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/USBController_UC3.h new file mode 100644 index 0000000000..2e824583a5 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/USBInterrupt_UC3.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/USBInterrupt_UC3.c new file mode 100644 index 0000000000..83ada8cc18 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/USBInterrupt_UC3.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/USBInterrupt_UC3.h new file mode 100644 index 0000000000..ddd5389c2e --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 must 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/USBController.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/USBController.h new file mode 100644 index 0000000000..c1d74c32b9 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/USBInterrupt.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/USBInterrupt.h new file mode 100644 index 0000000000..3dcfd5fed0 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/USBMode.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/USBMode.h new file mode 100644 index 0000000000..09cf3076b7 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/USBTask.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/USBTask.c new file mode 100644 index 0000000000..30a3cd682c --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/USBTask.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/USBTask.h new file mode 100644 index 0000000000..7c0917fc19 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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) MACROS{ USB_HostState = HOST_STATE_WaitForDevice; \ + WaitMSRemaining = (Duration); \ + PostWaitState = (NextState); }MACROE + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Device_XMEGA.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Device_XMEGA.c new file mode 100644 index 0000000000..10c3279f35 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Device_XMEGA.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Device_XMEGA.h new file mode 100644 index 0000000000..b203e10266 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/EndpointStream_XMEGA.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/EndpointStream_XMEGA.c new file mode 100644 index 0000000000..421d717099 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/EndpointStream_XMEGA.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/EndpointStream_XMEGA.h new file mode 100644 index 0000000000..cba6537db3 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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. + * + * Single Stream Transfer Example: + * \code + * uint8_t ErrorCode; + * + * if ((ErrorCode = Endpoint_Discard_Stream(512, NULL)) != ENDPOINT_RWSTREAM_NoError) + * { + * // Stream failed to complete - check ErrorCode here + * } + * \endcode + * + * Partial Stream Transfers Example: + * \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. + * + * Single Stream Transfer Example: + * \code + * uint8_t ErrorCode; + * + * if ((ErrorCode = Endpoint_Null_Stream(512, NULL)) != ENDPOINT_RWSTREAM_NoError) + * { + * // Stream failed to complete - check ErrorCode here + * } + * \endcode + * + * Partial Stream Transfers Example: + * \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. + * + * Single Stream Transfer Example: + * \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 + * + * Partial Stream Transfers Example: + * \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. + * + * Single Stream Transfer Example: + * \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 + * + * Partial Stream Transfers Example: + * \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 status 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 status 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 status 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 status 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 status 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 status 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 status 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 status 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 status 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 status 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.c new file mode 100644 index 0000000000..8155ecf7d0 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.h new file mode 100644 index 0000000000..42c476b249 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Host_XMEGA.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Host_XMEGA.c new file mode 100644 index 0000000000..c467733038 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/PipeStream_XMEGA.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/PipeStream_XMEGA.c new file mode 100644 index 0000000000..c467733038 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Pipe_XMEGA.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Pipe_XMEGA.c new file mode 100644 index 0000000000..69f369e430 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Template/Template_Endpoint_Control_R.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Template/Template_Endpoint_Control_R.c new file mode 100644 index 0000000000..0bd3843485 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Template/Template_Endpoint_Control_W.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Template/Template_Endpoint_Control_W.c new file mode 100644 index 0000000000..5bd4092e41 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/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; + + 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; + } + + return ENDPOINT_RWCSTREAM_NoError; +} + +#undef TEMPLATE_BUFFER_OFFSET +#undef TEMPLATE_BUFFER_MOVE +#undef TEMPLATE_FUNC_NAME +#undef TEMPLATE_TRANSFER_BYTE + +#endif + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Template/Template_Endpoint_RW.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Template/Template_Endpoint_RW.c new file mode 100644 index 0000000000..d51afdfb16 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.c new file mode 100644 index 0000000000..f8b0fc6af5 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.c @@ -0,0 +1,193 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2014. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaims all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + 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) +{ + #if defined(USB_DEVICE_OPT_FULLSPEED) + if (USB_Options & USB_DEVICE_OPT_LOWSPEED) + CLK.USBCTRL = (((F_USB / 6000000) - 1) << CLK_USBPSDIV_gp); + else + CLK.USBCTRL = (((F_USB / 48000000) - 1) << CLK_USBPSDIV_gp); + #else + CLK.USBCTRL = (((F_USB / 6000000) - 1) << CLK_USBPSDIV_gp); + #endif + + 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.h new file mode 100644 index 0000000000..15d4eec348 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/USBInterrupt_XMEGA.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/USBInterrupt_XMEGA.c new file mode 100644 index 0000000000..f03f3f2926 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/USBInterrupt_XMEGA.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/USBInterrupt_XMEGA.h new file mode 100644 index 0000000000..e224e225a2 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/USB.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Drivers/USB/USB.h new file mode 100644 index 0000000000..a8df26fd1d --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 (Makefile source module name: LUFA_SRC_USB) + * - LUFA/Drivers/USB/Core/DeviceStandardReq.c (Makefile source module name: LUFA_SRC_USB) + * - LUFA/Drivers/USB/Core/Events.c (Makefile source module name: LUFA_SRC_USB) + * - LUFA/Drivers/USB/Core/HostStandardReq.c (Makefile source module name: LUFA_SRC_USB) + * - LUFA/Drivers/USB/Core/USBTask.c (Makefile source module name: LUFA_SRC_USB) + * - LUFA/Drivers/USB/Core/ARCH/Device_ARCH.c (Makefile source module name: LUFA_SRC_USB) + * - LUFA/Drivers/USB/Core/ARCH/Endpoint_ARCH.c (Makefile source module name: LUFA_SRC_USB) + * - LUFA/Drivers/USB/Core/ARCH/EndpointStream_ARCH.c (Makefile source module name: LUFA_SRC_USB) + * - LUFA/Drivers/USB/Core/ARCH/Host_ARCH.c (Makefile source module name: LUFA_SRC_USB) + * - LUFA/Drivers/USB/Core/ARCH/Pipe_ARCH.c (Makefile source module name: LUFA_SRC_USB) + * - LUFA/Drivers/USB/Core/ARCH/PipeStream_ARCH.c (Makefile source module name: LUFA_SRC_USB) + * - LUFA/Drivers/USB/Core/ARCH/USBController_ARCH.c (Makefile source module name: LUFA_SRC_USB) + * - LUFA/Drivers/USB/Core/ARCH/USBInterrupt_ARCH.c (Makefile source module name: LUFA_SRC_USB) + * - LUFA/Drivers/USB/Class/Common/HIDParser.c (Makefile source module name: LUFA_SRC_USB) + * + * \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. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    USB ClassDevice ModeHost Mode
    Android Open AccessoryNoYes
    Audio 1.0YesYes
    CDC-ACMYesYes
    HIDYesYes
    MIDIYesYes
    Mass StorageYesYes
    PrinterYesYes
    RNDISYesYes
    Still ImageNoYes
    + * + * + * \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 USB_ClassInfo_{Class Name}_Device_t, 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 must have all fields set by the user application + * 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 {Class Name}_Device_ConfigureEndpoints() 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 + * {Class Name}_Device_USBTask() 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 + * {Class Name}_Device_ProcessControlRequest(), 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 must 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 may 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 USB_ClassInfo_{Class Name}_Host_t, 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 must have all fields set by the user application + * 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 {Class Name}_Host_ConfigurePipes() 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 {Class Name}_EnumerationFailure_ErrorCodes_t 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 + * {Class Name}_Host_USBTask() 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 must 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 may 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/License.txt b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/License.txt new file mode 100644 index 0000000000..8d4ad75364 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Platform/Platform.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Platform/Platform.h new file mode 100644 index 0000000000..a9eedebc4a --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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: + * - UC3 Architecture Only: LUFA/Platform/UC3/InterruptManagement.c (Makefile source module name: LUFA_SRC_PLATFORM) + * - UC3 Architecture Only: LUFA/Platform/UC3/Exception.S (Makefile source module name: LUFA_SRC_PLATFORM) + * + * \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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Platform/UC3/ClockManagement.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Platform/UC3/ClockManagement.h new file mode 100644 index 0000000000..fb062628e8 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 + * + * 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Platform/UC3/Exception.S b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Platform/UC3/Exception.S new file mode 100644 index 0000000000..3a5f240059 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 + +.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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Platform/UC3/InterruptManagement.c b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Platform/UC3/InterruptManagement.c new file mode 100644 index 0000000000..80d193f129 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Platform/UC3/InterruptManagement.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Platform/UC3/InterruptManagement.h new file mode 100644 index 0000000000..90198cddda --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 (Makefile source module name: LUFA_SRC_PLATFORM) + * - LUFA/Platform/UC3/Exception.S (Makefile source module name: LUFA_SRC_PLATFORM) + * + * \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 + * + * 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Platform/UC3/UC3ExperimentalInfo.txt b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Platform/UC3/UC3ExperimentalInfo.txt new file mode 100644 index 0000000000..8aadb3ed79 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Platform/XMEGA/ClockManagement.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Platform/XMEGA/ClockManagement.h new file mode 100644 index 0000000000..ed48d6ee1e --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 + * + * 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 uint8_t XMEGACLK_StartInternalOscillator(const uint8_t Source) ATTR_ALWAYS_INLINE; + static inline uint8_t 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 / 1000); + + 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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Platform/XMEGA/XMEGAExperimentalInfo.txt b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Platform/XMEGA/XMEGAExperimentalInfo.txt new file mode 100644 index 0000000000..42144aac48 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/HV1/helpcontentsetup.msha b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/HV1/helpcontentsetup.msha new file mode 100644 index 0000000000..cb1c4b9eb9 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/HV1/helpcontentsetup.msha @@ -0,0 +1,27 @@ + + + + + LUFA Help + + +
    + FourWalledCubicle + LUFA + LUFA Help + en-us +
    +
    + +
    + + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/HV1/lufa_docbook_transform.xslt b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/HV1/lufa_docbook_transform.xslt new file mode 100644 index 0000000000..2ebda6d5dc --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/HV1/lufa_docbook_transform.xslt @@ -0,0 +1,808 @@ + + + + + + + + + + LUFA Library + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <xsl:value-of select="$book.title"/> + + + + + + + + + + + + + + + + Modules + + + + + + + + + + + + + + + + LUFA. + + + + + + + + + <xsl:value-of select="$page.title"/> + + + + + + + Subsections: + + + + + + + + + + + + + + + + + + + +
    + + <xsl:value-of select="title"/> + + + + LUFA. + + + + + + + + + + + + Subgroups: + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + +
    + + <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"/> + + + + + + + + + + + + <xsl:value-of select="$name"/> + + + + + + Type + Name + Description + + + + + + + + + + + + + [] + + + + + . + + + + + + + + + + + + + + +
    +
    +
    +
    + + +
    + + <xsl:text>Function </xsl:text> + <xsl:value-of select="name"/> + <xsl:text>()</xsl:text> + + + + + + + + + + + + + + + + + + + ( + + + + void + + + + + + , + + + + + + + + + + + + ) + + + +
    +
    + + +
    + + <xsl:text>Enum </xsl:text> + <xsl:value-of select="name"/> + + + + + + + + + + Members + + + + Enum Value + Description + + + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + +
    + + <xsl:text>Macro </xsl:text> + <xsl:value-of select="name"/> + + + + + + + + + #define + + + ( + + + , + + + + ) + + + + + + \ + + + + + + + + +
    +
    + + +
    + + <xsl:text>Type </xsl:text> + <xsl:value-of select="name"/> + + + + + + + + + typedef + + + + + + + + + +
    +
    + + + +
    + + <xsl:text>Variable </xsl:text> + <xsl:value-of select="name"/> + + + + + + + + + + + + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <xsl:value-of select="title"/> + + + + + + + + Returns + + + + + + + Warning + + + + + + + Precondition + + + + + + + See also + + + + + + + Note + + + + + + + + + + Parameters + + + + Data Direction + Parameter Name + Description + + + + + + + + + + +
    +
    + + + + Return Values + + + + Return Value + Description + + + + + + + + + + +
    +
    + + + + + + + + ? + + + + + [] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <xsl:value-of select="caption"/> + + + + + + + + + + + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + images/ + + + + + + + + + + + + +
    + + + + + + + + <xsl:value-of select="title"/> + + + +
    +
    + + + + + + + + + + + + + NO XSL TEMPLATE MATCH: + + +
    diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/HV1/lufa_helpcontentsetup_transform.xslt b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/HV1/lufa_helpcontentsetup_transform.xslt new file mode 100644 index 0000000000..b43354f8d7 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/HV1/lufa_helpcontentsetup_transform.xslt @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + lufa_help_ + + .mshc + + + lufa_help_ + + .mshc + + + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/HV1/lufa_hv1_transform.xslt b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/HV1/lufa_hv1_transform.xslt new file mode 100644 index 0000000000..8aa4a9413e --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/HV1/lufa_hv1_transform.xslt @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/HV1/lufa_studio_help_styling.css b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/HV1/lufa_studio_help_styling.css new file mode 100644 index 0000000000..0b6ccbd8c1 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/LUFA.dll b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/LUFA.dll new file mode 100644 index 0000000000000000000000000000000000000000..49313b59cc9b683ca47ec3f04791c510371c11f9 GIT binary patch literal 748544 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

    ?C!!p8;u?w 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

    %Ii9@Yv#xJ9IP=S*P2I>zV_v% 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%0A`kQ;3^|I+0x;mZDsVKvZZIqu> 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,oaW% z3c#o{2kt(qdd}51vCqjRe?#E61@0I4J%K+4v}^gm`L_sHmi!&y@{+#?Y%6&Zb@i4! zgAyJtc^UA4z@G{H2yg|}xaxJA|8ZBl-ZzmG_yxcfbe*dcr-C1K^#i`)`ZP|K7PxiL zXFXrk9rP8?m(aa;dmsneSo$&@2tbVVx!Ir9>rs0}onUm0V9geGn_$0|lsP)NoKxaf z3+MAZgf*~6do1ibdNZ(V6eeZrbdzBF=wI}8(6ygh*daXx?9usL%09f*XajWZr-FTj zN*vg+pyk*qBDz{ianiYhDL$R_b-|vcoTDE0|F13V2EiV;ux|?1cp8_Iqeldb3HCX9 zNwDUH9QQf;iC|YL%&PC3g1uRK#IX}KbS;vUh`R<@>~zL*H150(QhZ!e=IFtyhg}|e z-ol;&Rz^Rxuor-p)Bmxse*=bvgOr)0*MU`0i(vb(N_oQNr>{y4+}iJAl(nCs>btV! z1&qRN7Ip`)ljt46_RXF-a|6wxTFlQxU!jGr27L}aDwvYs$@G+p^Q>~MqmyYd4#eK@P0<&b#S*pw-*BW3y5KN^!g$}7Wl+vxALd}agr5(3WFvZy^v{taI zM7pO?n_xG3-g6Bg-&Gb?>W%^XqJ_{ez?kg72=+? zu-k#nrT?(7ZvhL?`xf>cVDqUmsPcUu*lAQ}VLt)3h!$Je5nyM~#THiSxeE4m)WYTg zTTEA4STnF7-DF`Mz#8dZ3+n;4l%BJ&2(V`QsbFtv4|?h`qGz)UM2EF!JvU$kKWe4C ztfn45(NXDJ)!J3$mj3%34bSXyv%iFwe0Uf-OABxY!aAKKlz9@am+<3om~?s)P^14& zc&U_jwv-$?F1)c6w;QNO=!&;%CFPAm`Ts3^v+#D0@b-9>8>7b$D;%Qt(G!P>?crO1 zx9U>@KM<&COeq!U6F5g;oxpm5O@Pg`T3|>hodVAncp>1OdK~c2^__tAG%oZ~l%I8! z(tpjkRfo4)zQ?goVh_@0*xTE*ua@T=_k;3z$KBeu%dbPqe<=To<1wwI;&#XLQi2a9 z)YCx;zasFkc727z`IdHPg$MAyic04P+7lJk&MED=iaLR30KNc3w~75jBu3~ zE!9sIcov{fU+WDzeR_+xp62ME@~$J!+u^L!zwX`SoFlb|q=ZhuTlMn+UvWkN&n$@p zp6sd@8D6NjRjzQ2>las^l8@^@ zsk|7u7F7+o?#ISx2Jjq#=T+@N_|t>_i>wDn5^tM%AsZ$F#3|_n?-`tNzmUkp4xa zc}%~(>Ot3qw7_?(p3}R0&%2)2clus*#lhR>9f!fg&s}c;{-Z6$fw>hF*EF*(r%jB?_TYAb>>CxPDg$9 zkh@$sj5r3WFLy^AM)e);ddH6Hush_~19(`ww%Xy$>9-=xJ^qjGIdnh5Q`+BFzX-}> z)vN>Gt$rD$9jboa9e0FWKSS(f^}8tTeUx@T%CGW_qg^$g93Xm`Hq5%nbD@68tf=Q9 z#Kr+fW{r9FA@(z#)u7bV-IDTt$1AhG3Y2&)w3ZSLl?QyF5=jf;IPg z4ob>u8mM{Llhb$9)OZeq@-xqrcXNNu>dy1cY*~hfBE2ak6uz^J3?S>pIsxu2)?)%(Ny8qq%GJWWF zdvAdVcK^%9#3hNkD$=xL!%mrDb0$4slEjMnl3PyU!GC-#DVg`6Cojqsz_@=B7Z9^n$? zEXC-mz^;-P7dEn?7v+#+IsKS!cE2Il`|hLkzO;qbcBf+5gt4BwdOJeFSRz3ij7$dG zOyNucDwXJuCu6By)RD@j`y+{j5o^s3#-j-%$oXjVXeORYnw*$68i~=) zq?tjg?nn}pw2(qkP9oK8i9~mBN>m+5w8bNd)bPegGL}$zxwgSbx;=^AF2khO)W`@T zJKIcZkC+)F-99`_8?y0OSKQ1{`|ga9G*NJ8awwG^iAWvc?FQN*jBPa%M#MCF#z#?9 zDBM9?4HHd>0-N5>k7-$un`BaVJep3Ksi91;FK%WdiEt(xi>HE8QLw2o*!WvhP(grO zB1wZ(lSNn~W;B&f#0M!nj<$`^=D|yiD4Lbbj!-BwVkClgRYrO&4z`1xNyuO*!Yw#q z0!8gJ2;(dBgU>&dWXeQK3{7JJ(5b8 z)N2}P3$fE&5E)6>VY{C0NP0(hlseIYqp2i{N1h}amrBz>6lH-zK|#?cMkWjiClXsy zW?cFZTt4H&^(F|t$+#LmHp%M9&Ll(=NyIM$$35+; z*n!PS8K~J&7IVVL7}Ot0Cp(8WCt^_dJ|oS8LmEC^-$naanD)q11Mp)My)P{C6EMIH z2`hD^%?YF1NM@};YEuVBK+7XM5V!0YCgE6Bm*$SK26{_2lSw6Q`d}tGolydX`>iV# zjUG|BWARkhBQ?NFS7dlZyi!mHe(lA>;2(>TVc>$C?K4h2~b#FkTxZh74WA#K) zTBfv)#KIVVa&ti}YrX;%!G#Eb*C6K}xX4jvtf!PaadlT8~u zE#wnhG~xN!0-0Sqo~?=IZU5rqq-p?{lZg|eCLsWfik3{NBU8-uWrhDGD< zD^h-ox_Q*Vd?>ciqT~m_bn@mThK-m;D_!gMNOIWd%GcQ)A5M!rH>EO$X(c+3JFe3- zvw2DvW~QWRGX?EMuUm=Pe)FW480bnxV$cO;=lkNuE{r4|z={B*$Jm`gd(rle6sk)z zo}VhL+yxt$pH_~MZ&1xU!4u3oL2CwrPa!iAiLIxI@=S_tmNif)YC9hU;{&e*yyfkN z8qC%xwk9+g0b|POvd>}j21}oTWl)oM%C?>+ZO&#w84SEZs02z*#vld*wF-Oe)x-#H z7-vetZN>bu1e#YNlOVYie{n9UtC)f~cM}RAmJI!|}yg1FaANJ%CRZ zA1rQAYgd@nBN2}zi%Q>QWHaeV!XEi%7j!)f1uT?hvt~*6_=t{p!ZnKZfmEok%44JjdW(*=9JqgPAhj-0{v;m zhtb+r)ISX4Ul1)bh*_Qoei89R1F7IzfsbW)I2&`hnMsf51LqmzBo0buo&f{xyW_lU8H=Y= zNv>IX4^taFUM%#Kqur9)ZLNKvTbMA5=*kJiLMxxL6IM|CR!kDIT(smR;iPQ7n$R*OXUc z`@)u+34=aR6wG_`G!TP2<6xzML8ar=$<0O- zoE^A@vgqXOb}%(M(3v!LVhs#?L%_PwV?A&iq{F)-mtuJbCjsF+*}l1 zPOah7)~;VYFwlzO1|ybCCC5kLw09eDykfSs859%6etc>)9_2pnXu^QR0vViQ#f~wm zrbJU(a13e8+!Ps$v(>V8NXW+jpNv*;6?PWFeWomXtUkdJpQ0YJ?UmJeMKN}VVWDN^ zWdB+j5$>9zWrtF`B7(gRk>$qmI#-;sSnGtYmMEf|#p#MxHq#1J`YI`9)nmEUGM3Hp zWE55ga|tuN3ENNnyAh5*oM!ljytE3#>tJ1hoy6p>+#F8TlfniR8VsWbmmK}ql|lz% z#(~w!WHBqHrLY3V#!fuWU{p3G)~=5Z3|Q8^H4!n*r61R2`8_CmanhNmz$D8)$J!0Y zEuoYSGpkl2wjpA6S@Z1yhR)9ymM{K9G;0@u4ZgJ_Mm_0qRC|Jm0)Mvpv|{T;`G{sv zruBG~I@_@c1?7elb4im3%Wh3aHW|HSX(4Z6jRR}HQ#P+uKI+HBj`@iDVa<-1z?EVbTDB1mhENO|x5whx2Wv^EcA3+i#A6~@J&*IA?ClMccmt^eD%NkXA8i(erQ()U zB1Wv!?aCXFDZG$AkA`_msZ-X11x1h&6cM|H5-B8>orUt;-hzJEQCvx(1ZWMq7hY9p z2&*}4)ryN@8>6+yt_;G z;51YKr@IWw;6F~7B!Pz!j!+uVpcrWvw$d8h1=|8j3h`;gjUZJA(kGC@L|iw*QHeK^ zW(YY0xC3V(eiWfT#2T~~s~Z=W9I?1kJk!JzDxvD0q%>&>G9`rx6F9S* zkm9&;%pUfjq>v7)_~+~5z2saY$m2M>w&z4KfWm}tOQEq#uf6-hq}e^&ppGj zNr~mg?3QM#T92=VH6#Q5up3e+@wX5A>BBF8TgP#_3_?kZ@VK6c)XVKw`pB*44q#bu zTe*8Vo$7!=#O($}VcfzL^>9~{GJ_oGk+6^mM9UdFXUfUL! z?Ygq?Y_ZuaunL_4)d?e}9$}>}+&KlC$O2>o!sCVOQ^L9wX_ZB_1wDdvY&4X$RO3Y1 zLN*kvW)SSe!I1R)@q>nkHM0>o&M0#u0+!hh;+G9HH=CJCSpBaUWcFka6R{&=wb=gI zTBP(3w?IJQ^!C_fU1i$wHD8V%xB_fnjy~Z!kLQ|)y1Q4TrRLXyN~>xLa#YQ*8_5dD zX^V$E%ZvviH^CH1Dhs77AvQrkQ+-~@eQa->NbYB&%u(qVHoV->Y|+r+X0d=rAvCUo zXIIsSL*Rr3SuhI4+O+}P^3Y~sj&t9xEX48R*F7a0xV%|AQzw3%(*46s+rmpm3KDlXlMUm!9WUZZEfw{T}V2-#0%`p;44!>oJ=) zk!j}v}qYRtVY~jVuEEZX*0*8L9v{bI@@I~C?4D@k6jO|A`9BK zbzELM>fq^5jhJ@uJB*IdI-9`5GIU@R_Gu+-R|E2`gxy+-P&24Qh+|q4{<#YWVb2<2 z2iXR4t`#Ve^Jym)lqQUN?5Uh82cR%)$%nwxFdpGl?x5|Bkb4FAXd*gwy0_9NoZ5qq zhL1IY+w!(~8|;nkpcU7Ayp*;PD=SOER`?j)UY1C{p2}nJ(jN5SDAJIlk*ISO9KR6S z%N9Qbxiz5uZICU8nneyP5o*DIJMacrK@K-VS|LbbH6V_XqP1G+_nUpTf`ekG5?)uy zI4Csp3`=p@uChI?$DG$AsoCUkJ|5W0T+r$Eav%u)c7w_@CC4k-+fxC~0iAc^p~X`O z>n~44%4Dz(6nmb0h>lGSyVX4RqsK%4-Lj~&(8IsmAhG+-iwQPVJR`92GN3KO%O6-0 z`%t#)stg8o|6x3x2Y%RtNkSJ36Tu%^8jo{cWUy9a@r_^ZA=>bV@z#dCycDw+nbf-^ zKg!Ow`jw3@d!y_IOke0M5jhu@sA`v{TEBGk_JRL=<~bL6 z9z18@v%c?_t?@i^*|xqp&4>1Sz8CY=$76}-Jx$+P)%U=PP0JlF|3*iEG~K1+M|a|t zHoD^s(s2^ci=%6ruNoo5dK@lawK|HYp)Mz%-b3Dnxax5QaGikyW+U%xgd1=*;hOCZ z=$gODKih?0kAJz-f!t0fgAxWV25tr(0Awh~wHnttTp`riUILE%`0kIc`8s{wy30HE z`wj9xmW#RZk7cDcE=8vg;TjYrf2V?v~30z%+J)mxIP@>=>{inLv1|Xoi7Y zNgMxIvkb(1z7sDU@H#yB&MY2+z$s5}m2WLj9dT>X6}{+s01p7L3vpe+zaz;vo)uCho#%R&q`d4j$u(DXSLnt>I7; zpS9%2@IHORn*9y4|FM6~eFN+7xO&G#;?Mr;2XEi<=C`!_`hRtF?7^^ci~sTcd-^9< z2Hvjt*Begy)Ia}4_lqr0j_x_!dkHF@xY#wX88ytKFO)wlY79Xn<3do6$Y%7bTLyuaf8t6#0h zHw9W7mo_%9Y-wufXj|UY(7b#_OT+5rZA}d;IyzRa3@r^ctyYiD}`daZxrl~ZdmND!fWJhdfmr2G#a21GR)`P!4b-xyFQ=mLC{lFrd+O?PC6 z5y)&e0ukP-YvAL50f0m-5DAzG-ds$K2XN}e2<+M(A2G2hmk8jtXViet>2&!g-UCa3 zUa(Y)A&r+Ad0lSZ%MtjhfVZ|*Xtf^F{JBzpuEgthBZ(Iw;J#`%IT^(ZI!b)GS^ha* zuP-;pmpc`s7N4fz&gs!l!mg{@0mq3x>kKE(uZ(Lfx24gc=wQ@nY*^JC9faIs(S}va znwB?2Be7*etCkL~ZeFpH=q!Bs=kicnM{9HYispvKWvf>(88yXu!jjgMj zni?CMJFdVsNx%hO8_*7y-iEhtea!w}(ZScU{LZ^s&fAB9uJ~X&k{+L2yPJ)VbXu-q z;wShL`o|Q8{o#*2d8<=T@5Gl2_mEF;4z@k&G5%j1 zunt$OORAF+ivwG-gV=$^{jMI|aZj!rY+N?9d}!rRQ&VhtV`N#RL@HzD>e0R3xT71F z{e0|$o5U*V^~}qV32C}DNFp;b_q z2B4e_D&;TtH{ndW?(c<>2$09cx^^nmOY@%UEpt1Wekus10f!&D)!@#$ov$4aK?kTpD%}STLC9T)#3<=zMDP$o zyHJzvt@7vYE(_2sf9`$=?dDPh9^hp9oGMKh>Rc5mKM&xEJH4cgQcH>ABicx059RvT*q@x2_i~Lb?t|86J#+u%$#M zhzz)R&g=0=3Ep#|>GmlXd&CC$KCp>H%{V47jDtwnj?WKgxd~{b-TW#9{PSUUU5Dx5 zj(d*#4EEwVm<0cY%x=W%zlg=_%l!+cb)5|yGLSF#ilV-PwrEPihoy)&JZSkZAelF~ zEWB@=(0p!T?%)EAYKo8T2`4=fbB9@AMi}tr-m{cuiY;qy3RNqW=1TonY7V#N*`U$M z!As}g-KcHKBn8xg^}y1` zrp9eJNx|oI&28Kc1yX~TZnIA13n4ff8zlNE>a_oka5!LN(|;%P>2TXL-Nug?;6SXL zqBjhAe1X#+T}Xj*r)T^G`xBA?zkvYH#$c~=dZX1~g=IO8&gnMdy5O!E^lfEKn1nF= zEo?P}X#lVt%knT5Yny2k@J_%Eg!%6Y=etML6FK&%Qond1mi##Zi;5Lm8=!_#d0X3F z-scyBh&zovQ*17&dt4?Kc1DgZLT z_6OdcCtEzcnZV2KakNO?YU1+kHPFXz84y+pn0oVdwqbc`VlBbE6gI)QEPI2C!;L)u z=kpx1ZG(7q|B^TE`QkcCk)9=^Ho_gqm(upOjX4CBGOVpR*R zYfZNf`E6OuT(XAMScR;{$QtbFvNy7QwA$9OTl-}9?VdfgCl=TXEMHk>@6nzy687|v zL^kCFtt)nHZ_zurGu!m1~5Ft9_kFF7?uK4M2^U);L^B7uv4 zkI1KJJ?EV{>__$i-4pBE0QBl$KVaRn*W{_ssGxhy@HToxGA7zZapEozU7wwjkHnri z3(3moP5fnX=JfIi*7=H&&k9e=nReiCPl+eRMqJ7~$;G@Tp0s&~pxprF4zn5~<_TF( zoQA$C8&!7fyYE^z`RbV$?3B&QV{F&>pYi+HS(imW#P#yn2gEZc{zXv{yZ0+Fad~a0 z0wznlDD3K6?U&gR=at(9?7L)VUQr8|CEpqP_LVP+#8;e;C$I2_*l3YA;o*6;$)CIu zcG+QaJLRbVZA_=D9;0qErOwqYGCJnnex_)}I@Px_A8axDU&Wf+QBJ&tD)R(CG{*Q8 z!p?^4QK9R~Ehp>3h`Q_7s-K8?gIZ}Z>gI@*AX# zC%?lquveTbzUEPtow2?jw)66TGf<9?XItLoV{o~qPIRB1Q4e*VCVeb|F(LTJ;I5f6 z&_=4Rrkho=Hs2@cc0fcKt+|`0x$0_pwe7x&wsY`j_sdIiw{$F+^Iu}bOf{o^k@tEr YwhSYmJMFlk19=7vxcv?bMykGk0)Z=6o&W#< literal 0 HcmV?d00001 diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/[Content_Types].xml b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/[Content_Types].xml new file mode 100644 index 0000000000..112d169942 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/[Content_Types].xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/asf-manifest.xml b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/asf-manifest.xml new file mode 100644 index 0000000000..bd969518a1 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/asf-manifest.xml @@ -0,0 +1,18 @@ + + + FourWalledCubicle + LUFA + Dean Camera + + True + + + + 0 + + + content.xml.cache + + + + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/extension.vsixmanifest b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/extension.vsixmanifest new file mode 100644 index 0000000000..8475017443 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/extension.vsixmanifest @@ -0,0 +1,33 @@ + + + + + LUFA Library + Dean Camera + 0 + http://www.lufa-lib.org + LUFA, the Lightweight USB Framework for AVRs. + + License.txt + LUFA_thumb.png + LUFA.png + + + AtmelStudio + AtmelStudio + + + + 1033 + + false + + + + + + LUFA.pkgdef + helpcontentsetup.msha + asf-manifest.xml + + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/generate_caches.py b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/generate_caches.py new file mode 100644 index 0000000000..eb4b71efdf --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/lufa_asfmanifest_transform.xslt b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/lufa_asfmanifest_transform.xslt new file mode 100644 index 0000000000..8fc98412fe --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/lufa_asfmanifest_transform.xslt @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + . + + . + + + + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/lufa_vsmanifest_transform.xslt b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/lufa_vsmanifest_transform.xslt new file mode 100644 index 0000000000..db12d9ea26 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/lufa_vsmanifest_transform.xslt @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/XDK/lufa_extension_transform.xslt b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/XDK/lufa_extension_transform.xslt new file mode 100644 index 0000000000..f50f8a4ddb --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/XDK/lufa_extension_transform.xslt @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + This file has been automatically generated from the LUFA Atmel Studio integration XML files. + + + + + + + + + + + + + + + + + + + + . + + . + + + + + + + + + + /html/ + + + + + + + + /html/ + + + + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/XDK/lufa_filelist_transform.xslt b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/XDK/lufa_filelist_transform.xslt new file mode 100644 index 0000000000..9affc9f67c --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/XDK/lufa_filelist_transform.xslt @@ -0,0 +1,35 @@ + + + + + + + + + + + + Sourced from + + + + + + + + + + + + + + + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/XDK/lufa_indent_transform.xslt b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/XDK/lufa_indent_transform.xslt new file mode 100644 index 0000000000..166f42571c --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/XDK/lufa_indent_transform.xslt @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/XDK/lufa_module_transform.xslt b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/XDK/lufa_module_transform.xslt new file mode 100644 index 0000000000..ee9a050c1d --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/XDK/lufa_module_transform.xslt @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + This file has been automatically generated from the LUFA Atmel Studio integration XML files. + + + + Sourced from + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa.xml b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa.xml new file mode 100644 index 0000000000..86cfc0409d --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa.xml @@ -0,0 +1,96 @@ + + + + + + + + + Lightweight USB Framework for AVRs (LUFA), a USB software stack/framework. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_common.xml b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_common.xml new file mode 100644 index 0000000000..c2ef7af4c7 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_common.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_board.xml b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_board.xml new file mode 100644 index 0000000000..e150aa6458 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_board.xml @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_board_names.xml b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_board_names.xml new file mode 100644 index 0000000000..ab7a3418eb --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_board_names.xml @@ -0,0 +1,827 @@ + + + + + + + + + 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). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_misc.xml b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_misc.xml new file mode 100644 index 0000000000..4311ae87b7 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_misc.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_peripheral.xml b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_peripheral.xml new file mode 100644 index 0000000000..76ea516dbc --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_peripheral.xml @@ -0,0 +1,198 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb.xml b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb.xml new file mode 100644 index 0000000000..263c411dff --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class.xml b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class.xml new file mode 100644 index 0000000000..67ab760d33 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_android.xml b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_android.xml new file mode 100644 index 0000000000..3451712574 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_android.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + Common definitions and Host mode implementation of the Android Open Accessory USB class. + + + + + + + + + + + + + + + + + + + Common definitions only (no implementations) of the Android Open Accessory USB class. + + + + + + + + + + + + + + + + + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_audio.xml b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_audio.xml new file mode 100644 index 0000000000..5f7c3ad4d1 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_audio.xml @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + Common definitions and Host/Device mode implementations of the Audio 1.0 USB class. + + + + + + + + + + + + + + + + + + + + + Common definitions and Host mode implementation of the Audio 1.0 USB class. + + + + + + + + + + + + + + + + + + + + Common definitions and Device mode implementation of the Audio 1.0 USB class. + + + + + + + + + + + + + + + + + + + + Common definitions only (no implementations) of the Audio 1.0 USB class. + + + + + + + + + + + + + + + + + + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_cdc.xml b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_cdc.xml new file mode 100644 index 0000000000..65d8cc98f7 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_cdc.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + Common definitions and Host/Device mode implementations of the CDC USB class. + + + + + + + + + + + + + + + + + + + + + Common definitions and Host mode implementation of the CDC USB class. + + + + + + + + + + + + + + + + + + + + Common definitions and Device mode implementation of the CDC USB class. + + + + + + + + + + + + + + + + + + + + Common definitions only (no implementations) of the CDC USB class. + + + + + + + + + + + + + + + + + + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_hid.xml b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_hid.xml new file mode 100644 index 0000000000..3d533fb537 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_hid.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + Common definitions and Host/Device mode implementations of the HID USB class. + + + + + + + + + + + + + + + + + + + + + Common definitions and Host mode implementation of the HID USB class. + + + + + + + + + + + + + + + + + + + + Common definitions and Device mode implementation of the HID USB class. + + + + + + + + + + + + + + + + + + + + Common definitions only (no implementations) of the HID USB class. + + + + + + + + + + + + + + + + + + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_midi.xml b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_midi.xml new file mode 100644 index 0000000000..3ddab0bbdd --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_midi.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + Common definitions and Host/Device mode implementations of the MIDI USB class. + + + + + + + + + + + + + + + + + + + + + Common definitions and Host mode implementation of the MIDI USB class. + + + + + + + + + + + + + + + + + + + + Common definitions and Device mode implementation of the MIDI USB class. + + + + + + + + + + + + + + + + + + + + Common definitions only (no implementations) of the MIDI USB class. + + + + + + + + + + + + + + + + + + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_ms.xml b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_ms.xml new file mode 100644 index 0000000000..283b85ca7a --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_ms.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + Common definitions and Host/Device mode implementations of the Mass Storage USB class. + + + + + + + + + + + + + + + + + + + + + Common definitions and Host mode implementation of the Mass Storage USB class. + + + + + + + + + + + + + + + + + + + + Common definitions and Device mode implementation of the Mass Storage USB class. + + + + + + + + + + + + + + + + + + + + Common definitions only (no implementations) of the Mass Storage USB class. + + + + + + + + + + + + + + + + + + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_printer.xml b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_printer.xml new file mode 100644 index 0000000000..2465035ce8 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_printer.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + Common definitions and Host/Device mode implementations of the Printer USB class. + + + + + + + + + + + + + + + + + + + + + Common definitions and Host mode implementation of the Printer USB class. + + + + + + + + + + + + + + + + + + + + Common definitions and Device mode implementation of the Printer USB class. + + + + + + + + + + + + + + + + + + + + Common definitions only (no implementations) of the Printer USB class. + + + + + + + + + + + + + + + + + + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_rndis.xml b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_rndis.xml new file mode 100644 index 0000000000..6a606679d4 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_rndis.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + Common definitions and Host/Device mode implementations of the RNDIS Ethernet USB class. + + + + + + + + + + + + + + + + + + + + + Common definitions and Host mode implementation of the RNDIS Ethernet USB class. + + + + + + + + + + + + + + + + + + + + Common definitions and Device mode implementation of the RNDIS Ethernet USB class. + + + + + + + + + + + + + + + + + + + + Common definitions only (no implementations) of the RNDIS Ethernet USB class. + + + + + + + + + + + + + + + + + + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_si.xml b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_si.xml new file mode 100644 index 0000000000..c1bf8d560e --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_si.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + Common definitions and Host mode implementation of the Still Image USB class. + + + + + + + + + + + + + + + + + + + Common definitions only (no implementations) of the Still Image USB class. + + + + + + + + + + + + + + + + + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_core.xml b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_core.xml new file mode 100644 index 0000000000..58a0b388f6 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_core.xml @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_core_avr8.xml b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_core_avr8.xml new file mode 100644 index 0000000000..4688f05f91 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_core_avr8.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_core_uc3.xml b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_core_uc3.xml new file mode 100644 index 0000000000..2e7185f24a --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_core_uc3.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_core_xmega.xml b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_core_xmega.xml new file mode 100644 index 0000000000..c79a0f5b52 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_core_xmega.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_platform.xml b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_platform.xml new file mode 100644 index 0000000000..4ee51f6ee0 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_platform.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_platform_uc3.xml b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_platform_uc3.xml new file mode 100644 index 0000000000..98017b08ad --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_platform_uc3.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_platform_xmega.xml b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_platform_xmega.xml new file mode 100644 index 0000000000..e613fe5206 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_platform_xmega.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_toolchain.xml b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_toolchain.xml new file mode 100644 index 0000000000..723b3bec6f --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_toolchain.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/makefile b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/StudioIntegration/makefile new file mode 100644 index 0000000000..2649598d9f --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 "\n" $(LUFA_VERSION_NUM) $(DOXYGEN_TAG_FILE_XML) $(DOXYGEN_COMBINED_XML) > $@ + @for i in $(XML_FILES); do \ + printf "\t\n" $$i >> $@; \ + done; + @echo '' >> $@ + +$(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/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Version.h b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/Version.h new file mode 100644 index 0000000000..d3ee7f30eb --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/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 0x140302 + + /** Indicates the version number of the library, as a string. */ + #define LUFA_VERSION_STRING "140302" + +#endif + diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/doxyfile b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/doxyfile new file mode 100644 index 0000000000..f903293706 --- /dev/null +++ b/plugins/KeyboardioHID/lufa-LUFA-140302/LUFA/doxyfile @@ -0,0 +1,2340 @@ +# Doxyfile 1.8.6 + +# 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 + +# 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, 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 ... \endif and \cond +# ... \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. Do not use file names with spaces, bibtex cannot handle them. 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: +# +# +# +# where is the value of the INPUT_FILTER tag, and 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 acurate 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 an additional user- +# defined cascading style sheet that is 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 file to the output directory. 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. +# 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 + S +# (what the is depends on the OS and browser, but it is typically +# , /here for resolution steps. - * If the issue still persists then uninstall modemmanager by executing sudo apt-get remove modemmanager, 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 here 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. - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    Define Name:Location:Description:
    NO_BLOCK_SUPPORTAppConfig.hDefine to disable memory block read/write support in the bootloader, requiring all reads and writes to be made - * using the byte-level commands.
    NO_EEPROM_BYTE_SUPPORTAppConfig.hDefine 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.
    NO_FLASH_BYTE_SUPPORTAppConfig.hDefine 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.
    NO_LOCK_BYTE_WRITE_SUPPORTAppConfig.hDefine to disable lock byte write support in the bootloader, preventing the lock bits from being set programmatically.
    - */ - diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/Config/AppConfig.h b/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/Config/AppConfig.h deleted file mode 100644 index bbb5cb227e..0000000000 --- a/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/Config/AppConfig.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/Config/LUFAConfig.h b/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/Config/LUFAConfig.h deleted file mode 100644 index af2dd3060e..0000000000 --- a/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/Config/LUFAConfig.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/Descriptors.c b/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/Descriptors.c deleted file mode 100644 index 2ff6b503ba..0000000000 --- a/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/Descriptors.c +++ /dev/null @@ -1,244 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in 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/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/Descriptors.h b/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/Descriptors.h deleted file mode 100644 index ef04379179..0000000000 --- a/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/Descriptors.h +++ /dev/null @@ -1,158 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in 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 - - #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/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/LUFA CDC Bootloader.inf b/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/LUFA CDC Bootloader.inf deleted file mode 100644 index 61624c7318..0000000000 --- a/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/LUFA CDC Bootloader.inf +++ /dev/null @@ -1,66 +0,0 @@ -;************************************************************ -; 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/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/asf.xml b/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/asf.xml deleted file mode 100644 index 02e7063c66..0000000000 --- a/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/asf.xml +++ /dev/null @@ -1,161 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CDC Class Bootloader, capable of reprogramming a device using avrdude or other AVR109 protocol compliant software when plugged into a host. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/doxyfile b/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/doxyfile deleted file mode 100644 index 5419c450d0..0000000000 --- a/plugins/KeyboardioHID/lufa-LUFA-140302/Bootloaders/CDC/doxyfile +++ /dev/null @@ -1,2337 +0,0 @@ -# Doxyfile 1.8.6 - -# 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 - -# 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, 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 ... \endif and \cond -# ... \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. Do not use file names with spaces, bibtex cannot handle them. 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: -# -# -# -# where is the value of the INPUT_FILTER tag, and 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 acurate 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 an additional user- -# defined cascading style sheet that is 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 file to the output directory. 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. -# 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 + S -# (what the is depends on the OS and browser, but it is typically -# , /

    FPqH^r|^y4RA)#RWsuiSb%AAf1zTW*g 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 YNg#YQXZJ!({000eE2zt(WnTsU57kNqO#lD@ diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step2.png b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step2.png deleted file mode 100644 index 6e309ae4151a4e02a859aca3a48319dd43807a2b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 100532 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

    N`w6 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 HhtK{GPaXat diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step5_2.png b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step5_2.png deleted file mode 100644 index 078f4ec8d7b3b3920c1a65a7b0b52d8fbee3b7d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28918 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 diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step5_3.png b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step5_3.png deleted file mode 100644 index 8a8571bd86868ef9a1bfb12214138c17221c4bd8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23561 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 F|JfK#>ahR- diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/Images/LUFA.png b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/Images/LUFA.png deleted file mode 100644 index 54fa1a66433491cb4b8cd9f5cdc6269f928f901c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10296 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 v$pN2bPDNB8 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 diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/KnownIssues.txt b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/KnownIssues.txt deleted file mode 100644 index d283b0f84f..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/KnownIssues.txt +++ /dev/null @@ -1,138 +0,0 @@ -/** \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_KnownIssues140302 Version 140302 - * - AVR8 Architecture - * - No known issues. - * - UC3 Architecture - * \warning The UC3 device support is currently experimental (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 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 experimental (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 (Project->Project {name} Properties... 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 experimental (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 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 experimental (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 (Project->Project {name} Properties... 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 experimental (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 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 experimental (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 experimental (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 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 experimental (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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/LUFAPoweredProjects.txt b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/LUFAPoweredProjects.txt deleted file mode 100644 index aac397afb5..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/LUFAPoweredProjects.txt +++ /dev/null @@ -1,221 +0,0 @@ -/** \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://www.cappels.org/dproj/AttoBasic2_1/AttoBasic_2.1_with_USB_and_Arduino_support.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 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 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 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.dyndns.org: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 "nxpusblib" LUFA fork, for LPC devices: http://www.lpcware.com/content/project/nxpusblib - * \li Kevin Mehall's LUFA port to the NXP LPC13xx: https://github.com/kevinmehall/LUFA-LPC13xx - * \li Mark Ding's port for the Silabs SiM3U1xx: https://www.github.com/MarkDing/USB_CDC - * - */ diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/LibraryResources.txt b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/LibraryResources.txt deleted file mode 100644 index f69d4344c1..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/LibraryResources.txt +++ /dev/null @@ -1,33 +0,0 @@ -/** \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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/LicenseInfo.txt b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/LicenseInfo.txt deleted file mode 100644 index 86ed124bb2..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/LicenseInfo.txt +++ /dev/null @@ -1,43 +0,0 @@ -/** \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 must 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/MainPage.txt b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/MainPage.txt deleted file mode 100644 index e737c39b5a..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/MainPage.txt +++ /dev/null @@ -1,52 +0,0 @@ -/** \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 - *

    - * \n - * - * \n - * - * LUFA is donationware. For author and donation information, see \ref Page_Donating. - * - * 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. - * - * Subsections: - * \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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/MigrationInformation.txt b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/MigrationInformation.txt deleted file mode 100644 index cf3cc17492..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/MigrationInformation.txt +++ /dev/null @@ -1,703 +0,0 @@ -/** \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_Migration140302 Migrating from 130901 to 140302 - * USB Core - * - 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. - * - * Non-USB Library Components - * - 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. - * - * Build System - * - 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 - * Non-USB Library Components - * - The Board Dataflash \c Dataflash_Init() function now automatically configures the appropriate communication interface. - * - * \section Sec_Migration130303 Migrating from 120730 to 130303 - * Device Mode - * - 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. - * - * Host Mode - * - 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 - * Device Mode - * - 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. - * - * Host Mode - * - 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 - * USB Core - * - 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. - * - * Device Mode - * - 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 - * Non-USB Library Components - * - The \c JTAG_DEBUG_ASSERT() macro has been renamed \ref JTAG_ASSERT() to be consistent with \ref STDOUT_ASSERT(). - * - * USB Core - * - 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. - * - * Device Mode - * - 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. - * - * Host Mode - * - 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 - * USB Core - * - 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. - * - * Device Mode - * - 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. - * - * Host Mode - * - 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 - * - * Non-USB Library Components - * - 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. - * - * USB Core - * - 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. - * - * Device Mode - * - 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. - * - * Host Mode - * - 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 - * - * Non-USB Library Components - * - 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. - * - * Device Mode - * - 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. - * - * Host Mode - * - 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 - * - * Non-USB Library Components - * - 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. - * - * Host Mode - * - 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(). - * - * Device Mode - * - 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 - * - * Host Mode - * - 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. - * - * Device Mode - * - 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 - * - * Host Mode - * - 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 - * - * Non-USB Library Components - * - 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 - * - * Host Mode - * - 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. - * - * Device Mode - * - 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 - * - * All - * - The "Simple Scheduler" has been deprecated, 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. - * - * Non-USB Library Components - * - 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. - * - * Library Demos - * - 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. - * - * Host Mode - * - 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. - * - * Device Mode - * - 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 - * - * Device Mode - * - 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 must be implemented in the user application. - * - * Host Mode - * - 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 - * - * All - * - 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. - * - * Dual Role Mode - * - 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. - * - * Device Mode - * - 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. - * - * Host Mode - * - 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 - * - * All - * - 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 and call \c clock_prescale_set(clock_div_1); instead on recent avr-libc distributions. - * - * Library Demos - * - The USBtoSerial demo now discards all data when not connected to a host, rather than buffering it for later transmission. - * - * Non-USB Library Components - * - 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(). - * - * Device Mode - * - 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 - * - * Device Mode - * - 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. - * - * Host Mode - * - 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. - * - * Non-USB Library Components - * - 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 - * - * All - * - 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. - * - * Library Demos - * - 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. - * - * Non-USB Library Components - * - The Serial_IsCharReceived() macro has been changed to the correct spelling of Serial_IsCharReceived() in Serial.h. - * - * Device Mode - * - 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. - * - * Host Mode - * - 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 - * - * Library Demos - * - 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. - * - * Device Mode - * - 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. - * - * Host Mode - * - 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 - * - * Library Demos - * - 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 - * - * Library Demos - * - 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 - * - * Library Demos - * - 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. - * - * Non-USB Library Components - * - 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. - * - * Device Mode - * - 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 not 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. - * - * Host Mode - * - 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. - * - * Dual Role Mode - * - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/OSDrivers.txt b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/OSDrivers.txt deleted file mode 100644 index 4823c5b089..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/OSDrivers.txt +++ /dev/null @@ -1,111 +0,0 @@ -/** \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 - * native support on modern operating systems. - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    USB ClassAndroidWindowsLinuxOS X
    Android Open Accessory2.3.4+N/AN/AN/A
    Audio 1.0N/AXP+2.6.?+10.?+
    CDC-ACMN/AXP+2.6.?+10.?+
    HID3.?+XP+2.6.?+10.?+
    MIDIN/AXP+2.6.?+10.?+
    Mass StorageN/AXP+2.6.?+10.?+
    PrinterN/AXP+2.6.?+10.?+
    RNDISN/AXP+2.6.?+N/A
    Still ImageN/AXP+2.6.?+10.?+
    - * - * \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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/ProgrammingApps.txt b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/ProgrammingApps.txt deleted file mode 100644 index 4759ac87ae..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/ProgrammingApps.txt +++ /dev/null @@ -1,30 +0,0 @@ -/** \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 atmel.com 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/SoftwareBootloaderJump.txt b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/SoftwareBootloaderJump.txt deleted file mode 100644 index 0b69612b68..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/SoftwareBootloaderJump.txt +++ /dev/null @@ -1,71 +0,0 @@ -/** \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 - * #include - * #include - * - * #include - * #include - * - * 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 FLASH_SIZE_BYTES and - * BOOTLOADER_SEC_SIZE_BYTES 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/Style/Footer.htm b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/Style/Footer.htm deleted file mode 100644 index a72c5bdd24..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/Style/Footer.htm +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/Style/Style.css b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/Style/Style.css deleted file mode 100644 index 933215546f..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/Style/Style.css +++ /dev/null @@ -1,93 +0,0 @@ -/* ============================= */ -/* 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/VIDAndPIDValues.txt b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/VIDAndPIDValues.txt deleted file mode 100644 index 6d39ce7f90..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/VIDAndPIDValues.txt +++ /dev/null @@ -1,199 +0,0 @@ -/** \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. - * - * These VID/PID values should not be used in commercial designs under any circumstances. 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. - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    VIDPIDUsage
    0x03EB0x2040Test VID/PID (See \ref Sec_Test_VIDPID)
    0x03EB0x2041Mouse Demo Application
    0x03EB0x2042Keyboard Demo Application
    0x03EB0x2043Joystick Demo Application
    0x03EB0x2044CDC Demo Application
    0x03EB0x2045Mass Storage Demo Application
    0x03EB0x2046Audio Output Demo Application
    0x03EB0x2047Audio Input Demo Application
    0x03EB0x2048MIDI Demo Application
    0x03EB0x2049MagStripe Project
    0x03EB0x204ACDC Class Bootloader
    0x03EB0x204BUSB to Serial Demo Application
    0x03EB0x204CRNDIS Demo Application
    0x03EB0x204DCombined Keyboard and Mouse Demo Application
    0x03EB0x204EDual CDC Demo Application
    0x03EB - * 0x204F - * Generic HID Demo Application
    0x03EB0x2060Benito Programmer Project
    0x03EB0x2061Combined Mass Storage and Keyboard Demo
    0x03EB0x2062Combined CDC and Mouse Demo
    0x03EB0x2063Mass Storage/HID Interface Datalogger Project
    0x03EB0x2064Interfaceless Control-Only LUFA Devices
    0x03EB0x2065Test and Measurement Demo
    0x03EB - * 0x2066 - * Multiple Report Keyboard/Mouse HID Demo
    0x03EB0x2067HID Class Bootloader
    0x03EB0x2068Virtual Serial/Mass Storage Demo
    0x03EB - * 0x2069 - * Webserver Project
    0x03EB0x206AMedia Control Project
    0x03EB0x206BPrinter Class Bootloader
    0x03EB0x206CBulk Vendor Demo
    0x03EB0x206DCurrently Unallocated
    0x03EB0x206ECurrently Unallocated
    0x03EB0x206FCurrently Unallocated
    - * - * \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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/WritingBoardDrivers.txt b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/WritingBoardDrivers.txt deleted file mode 100644 index b2ff07e666..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/DoxygenPages/WritingBoardDrivers.txt +++ /dev/null @@ -1,47 +0,0 @@ -/** \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 LUFA/Drivers/Board, you must also indicate which - * board hardware you are using in your project makefile. This is done by defining the BOARD macro using - * the -D switch passed to the compiler, with a constant of BOARD_{Name}. For example, - * -DBOARD=BOARD_USBKEY instructs the compiler to use the USBKEY board hardware drivers. - * - * If your application does not use any board level drivers, you can omit the definition of the BOARD - * 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 BOARD macro should be defined to the value BOARD_USER. - * 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 LUFA/CodeTemplates/DriverStubs folder should be copied to - * the user application's Board/ 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 - * LUFA/Drivers/Board/ 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 - * \include "DriverStubs/Board.h" - * - * \subsection SSec_BoardTemplates_Buttons Template for USER - * \include "DriverStubs/Buttons.h" - * - * \subsection SSec_BoardTemplates_Dataflash Template for USER - * \include "DriverStubs/Dataflash.h" - * - * \subsection SSec_BoardTemplates_Joystick Template for USER - * \include "DriverStubs/Joystick.h" - * - * \subsection SSec_BoardTemplates_LEDs Template for USER - * \include "DriverStubs/LEDs.h" - */ - diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/ADAFRUITU4/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/ADAFRUITU4/Board.h deleted file mode 100644 index 48016e0bf4..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/ADAFRUITU4/Board.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/ADAFRUITU4/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/ADAFRUITU4/LEDs.h deleted file mode 100644 index 9f312207b8..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/ADAFRUITU4/LEDs.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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). - * - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenGeneral IndicatorHighPORTE.6
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/ATAVRUSBRF01/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/ATAVRUSBRF01/Board.h deleted file mode 100644 index 07000ecddf..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/ATAVRUSBRF01/Board.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/ATAVRUSBRF01/Buttons.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/ATAVRUSBRF01/Buttons.h deleted file mode 100644 index 8b815dbcb6..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/ATAVRUSBRF01/Buttons.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * - * - * - *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTD.7
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/ATAVRUSBRF01/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/ATAVRUSBRF01/LEDs.h deleted file mode 100644 index 76e89fd0df..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/ATAVRUSBRF01/LEDs.h +++ /dev/null @@ -1,139 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenRX LEDHighPORTD.0
    LEDS_LED2RedTX LEDHighPORTD.1
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BENITO/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BENITO/Board.h deleted file mode 100644 index 5584e1ea7e..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BENITO/Board.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BENITO/Buttons.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BENITO/Buttons.h deleted file mode 100644 index 96d14a3ae0..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BENITO/Buttons.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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). - * - * - * - * - *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTD.7
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BENITO/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BENITO/LEDs.h deleted file mode 100644 index 49df441918..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BENITO/LEDs.h +++ /dev/null @@ -1,139 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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). - * - * - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenTX LEDLowPORTC.7
    LEDS_LED2RedRX LEDLowPORTC.6
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BIGMULTIO/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BIGMULTIO/Board.h deleted file mode 100644 index 9d4e301306..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BIGMULTIO/Board.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BIGMULTIO/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BIGMULTIO/LEDs.h deleted file mode 100644 index 93d5bec97e..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BIGMULTIO/LEDs.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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). - * - * - * - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1UnknownLED0HighPORTF.6
    LEDS_LED2UnknownLED1HighPORTF.7
    LEDS_LED3UnknownLED2HighPORTE.2
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BLACKCAT/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BLACKCAT/Board.h deleted file mode 100644 index 6eec7bf7d1..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BLACKCAT/Board.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BLACKCAT/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BLACKCAT/LEDs.h deleted file mode 100644 index 4a72039aed..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BLACKCAT/LEDs.h +++ /dev/null @@ -1,139 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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). - * - * - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1UnknownLED0HighPORTD.6
    LEDS_LED2UnknownLED1HighPORTD.3
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BUI/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BUI/Board.h deleted file mode 100644 index 067e870d88..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BUI/Board.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BUI/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BUI/LEDs.h deleted file mode 100644 index e06edb5fc1..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BUI/LEDs.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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). - * - * - * - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1RedRGB LEDHighPORTC.2
    LEDS_LED2GreenRGB LEDHighPORTC.3
    LEDS_LED3BlueRGB LEDHighPORTC.4
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BUMBLEB/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BUMBLEB/Board.h deleted file mode 100644 index 906f0b5e06..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BUMBLEB/Board.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BUMBLEB/Buttons.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BUMBLEB/Buttons.h deleted file mode 100644 index 0495425919..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BUMBLEB/Buttons.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * - * - * - *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTD.7
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BUMBLEB/Joystick.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BUMBLEB/Joystick.h deleted file mode 100644 index 82d085e89c..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BUMBLEB/Joystick.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * - * - * - *
    Left Port PinUp Port PinRight Port PinDown Port PinPress Port Pin
    PORTD.2PORTD.3PORTD.0PORTD.1PORTD.4
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BUMBLEB/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BUMBLEB/LEDs.h deleted file mode 100644 index 5cd7b483c6..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/BUMBLEB/LEDs.h +++ /dev/null @@ -1,149 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * - * - * - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1N/AUser SuppliedHighPORTB.4
    LEDS_LED2N/AUser SuppliedHighPORTB.5
    LEDS_LED3N/AUser SuppliedHighPORTB.6
    LEDS_LED4N/AUser SuppliedHighPORTB.7
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/CULV3/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/CULV3/Board.h deleted file mode 100644 index 777902d274..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/CULV3/Board.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/CULV3/Buttons.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/CULV3/Buttons.h deleted file mode 100644 index 6a26a99808..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/CULV3/Buttons.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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). - * - * - * - * - *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTE.2
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/CULV3/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/CULV3/LEDs.h deleted file mode 100644 index 3d2b8fda07..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/CULV3/LEDs.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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). - * - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1YellowGeneral IndicatorHighPORTE.6
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/DUCE/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/DUCE/Board.h deleted file mode 100644 index 44cf6918bf..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/DUCE/Board.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/DUCE/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/DUCE/LEDs.h deleted file mode 100644 index 83cadedffa..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/DUCE/LEDs.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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). - * - * - * - * - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1RedBicolor Indicator 1HighPORTC.4
    LEDS_LED2GreenBicolor Indicator 1HighPORTC.5
    LEDS_LED3RedBicolor Indicator 2HighPORTC.6
    LEDS_LED4GreenBicolor Indicator 2HighPORTC.7
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/EVK527/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/EVK527/Board.h deleted file mode 100644 index c77c18b9b8..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/EVK527/Board.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/EVK527/Buttons.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/EVK527/Buttons.h deleted file mode 100644 index 239880cc63..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/EVK527/Buttons.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * - * - * - *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTE.2
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/EVK527/Dataflash.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/EVK527/Dataflash.h deleted file mode 100644 index 38b2b58892..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/EVK527/Dataflash.h +++ /dev/null @@ -1,222 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * - * - * - *
    NameInfoSelect PinSPI Port
    DATAFLASH_CHIP1AT45DB321C (4MB)PORTE.6SPI0
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/EVK527/Joystick.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/EVK527/Joystick.h deleted file mode 100644 index 492c706993..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/EVK527/Joystick.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * - * - * - *
    Left Port PinUp Port PinRight Port PinDown Port PinPress Port Pin
    PORTF.4PORTF.5PORTF.7PORTC.6PORTF.6
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/EVK527/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/EVK527/LEDs.h deleted file mode 100644 index 84e689a4b7..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/EVK527/LEDs.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * - * - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenGeneral IndicatorHighPORTD.5
    LEDS_LED2GreenGeneral IndicatorHighPORTD.6
    LEDS_LED3GreenGeneral IndicatorHighPORTD.7
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/JMDBU2/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/JMDBU2/Board.h deleted file mode 100644 index 0f1aca09dd..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/JMDBU2/Board.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/JMDBU2/Buttons.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/JMDBU2/Buttons.h deleted file mode 100644 index 80500993dc..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/JMDBU2/Buttons.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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). - * - * - * - * - *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTD.7
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/JMDBU2/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/JMDBU2/LEDs.h deleted file mode 100644 index 562103e33b..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/JMDBU2/LEDs.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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). - * - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenGeneral IndicatorHighPORTD.4
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/LEONARDO/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/LEONARDO/Board.h deleted file mode 100644 index 95ef437f56..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/LEONARDO/Board.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/LEONARDO/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/LEONARDO/LEDs.h deleted file mode 100644 index 28a4802676..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/LEONARDO/LEDs.h +++ /dev/null @@ -1,169 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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). - * - * - * - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1YellowRXLowPORTB.0
    LEDS_LED2YellowTXLowPORTD.5
    LEDS_LED1YellowGeneral IndicatorHighPORTC.7
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MAXIMUS/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MAXIMUS/Board.h deleted file mode 100644 index 929e60a8cc..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MAXIMUS/Board.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MAXIMUS/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MAXIMUS/LEDs.h deleted file mode 100644 index 695949a176..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MAXIMUS/LEDs.h +++ /dev/null @@ -1,139 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/). - * - * - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenLGHighPORTB.6
    LEDS_LED2RedLRHighPORTB.7
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MICROPENDOUS/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MICROPENDOUS/Board.h deleted file mode 100644 index b84bf790b1..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MICROPENDOUS/Board.h +++ /dev/null @@ -1,149 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MICROPENDOUS/Buttons.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MICROPENDOUS/Buttons.h deleted file mode 100644 index 8adff2d30d..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MICROPENDOUS/Buttons.h +++ /dev/null @@ -1,205 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 BOARD = MICROPENDOUS_{VERSION}. - * - * Board specific Buttons driver header for the Micropendous 32U2 (https://code.google.com/p/micropendous/wiki/Micropendous_32U2). - * - * BOARD_MICROPENDOUS_1 and BOARD_MICROPENDOUS_32U2: - * - * - * - *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTD.7
    - * - * Other Revisions: - * - * - * - *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTE.2
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MICROPENDOUS/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MICROPENDOUS/LEDs.h deleted file mode 100644 index 253ad31422..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MICROPENDOUS/LEDs.h +++ /dev/null @@ -1,174 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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). - * - * BOARD_MICROPENDOUS_32U2: - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenGeneral IndicatorHighPORTD.6
    - * - * Other Revisions: - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenGeneral IndicatorHighPORTB.1
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MICROSIN162/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MICROSIN162/Board.h deleted file mode 100644 index 3ffb028c0d..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MICROSIN162/Board.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MICROSIN162/Buttons.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MICROSIN162/Buttons.h deleted file mode 100644 index 68344feb22..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MICROSIN162/Buttons.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/). - * - * - * - * - *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTD.7
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MICROSIN162/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MICROSIN162/LEDs.h deleted file mode 100644 index 51d1b3eba8..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MICROSIN162/LEDs.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/). - * - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenGeneral IndicatorLowPORTD.4
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MINIMUS/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MINIMUS/Board.h deleted file mode 100644 index 80b8b3c86c..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MINIMUS/Board.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MINIMUS/Buttons.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MINIMUS/Buttons.h deleted file mode 100644 index ec94445a80..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MINIMUS/Buttons.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * - * - * - *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTD.7
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MINIMUS/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MINIMUS/LEDs.h deleted file mode 100644 index adc34686fe..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MINIMUS/LEDs.h +++ /dev/null @@ -1,139 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/). - * - * - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1BlueGeneral IndicatorLowPORTD.5
    LEDS_LED2RedGeneral IndicatorLowPORTD.6
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MULTIO/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MULTIO/Board.h deleted file mode 100644 index 84f3d87250..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MULTIO/Board.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MULTIO/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MULTIO/LEDs.h deleted file mode 100644 index ca6d440414..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/MULTIO/LEDs.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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). - * - * - * - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenGeneral IndicatorHighPORTD.0
    LEDS_LED2GreenGeneral IndicatorHighPORTC.2
    LEDS_LED3GreenGeneral IndicatorHighPORTD.7
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEX162/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEX162/Board.h deleted file mode 100644 index b9bcf77344..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEX162/Board.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEX162/Buttons.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEX162/Buttons.h deleted file mode 100644 index 3714c5e9ae..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEX162/Buttons.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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). - * - * - * - * - *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTD.7
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEX162/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEX162/LEDs.h deleted file mode 100644 index 5ecc1f5d79..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEX162/LEDs.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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). - * - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1YellowGeneral IndicatorHighPORTD.4
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEX32U4/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEX32U4/Board.h deleted file mode 100644 index 657b15c6d7..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEX32U4/Board.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEX32U4/Buttons.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEX32U4/Buttons.h deleted file mode 100644 index 8e33fd965c..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEX32U4/Buttons.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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). - * - * - * - * - *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTE.2
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEX32U4/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEX32U4/LEDs.h deleted file mode 100644 index 259859c90c..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEX32U4/LEDs.h +++ /dev/null @@ -1,179 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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). - * - * - * - * - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenTXHighPORTD.5
    LEDS_LED2YellowRXHighPORTB.0
    LEDS_LED3GreenGeneral Indicator (Default Unconnected)HighPORTE.6
    LEDS_LED4YellowGeneral Indicator (Default Unconnected)HighPORTB.5
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEXISPMK2/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEXISPMK2/Board.h deleted file mode 100644 index d318a82b03..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEXISPMK2/Board.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEXISPMK2/Buttons.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEXISPMK2/Buttons.h deleted file mode 100644 index aff10b1035..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEXISPMK2/Buttons.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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). - * - * - * - * - *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTD.7
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEXISPMK2/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEXISPMK2/LEDs.h deleted file mode 100644 index 033fca05e6..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEXISPMK2/LEDs.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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). - * - * - * - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1YellowTarget PowerHighPORTB.5
    LEDS_LED2RedActivityHighPORTB.6
    LEDS_LED3GreenReadyHighPORTB.7
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEXT32U4/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEXT32U4/Board.h deleted file mode 100644 index 690fee1534..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEXT32U4/Board.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEXT32U4/Buttons.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEXT32U4/Buttons.h deleted file mode 100644 index 634eda9cb8..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEXT32U4/Buttons.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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). - * - * - * - * - *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTE.2
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEXT32U4/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEXT32U4/LEDs.h deleted file mode 100644 index 2bbaf6826e..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/OLIMEXT32U4/LEDs.h +++ /dev/null @@ -1,169 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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). - * - * - * - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1YellowRXHighPORTB.0
    LEDS_LED2GreenTXHighPORTD.5
    LEDS_LED3N/AGeneral Indicator (Not Mounted)HighPORTE.6
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/RZUSBSTICK/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/RZUSBSTICK/Board.h deleted file mode 100644 index 6fc3666739..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/RZUSBSTICK/Board.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/RZUSBSTICK/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/RZUSBSTICK/LEDs.h deleted file mode 100644 index 6ebcdfc6b0..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/RZUSBSTICK/LEDs.h +++ /dev/null @@ -1,175 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * - * - * - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1BlueGeneral IndicatorHighPORTD.7
    LEDS_LED1RedGeneral IndicatorLowPORTD.5
    LEDS_LED1GreenGeneral IndicatorLowPORTE.6
    LEDS_LED1YellowGeneral IndicatorLowPORTE.7
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/SPARKFUN8U2/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/SPARKFUN8U2/Board.h deleted file mode 100644 index 49cc2e5105..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/SPARKFUN8U2/Board.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/SPARKFUN8U2/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/SPARKFUN8U2/LEDs.h deleted file mode 100644 index b8eb4abfea..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/SPARKFUN8U2/LEDs.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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). - * - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenGeneral IndicatorLowPORTB.4
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STANGE_ISP/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STANGE_ISP/Board.h deleted file mode 100644 index 36594fcc03..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STANGE_ISP/Board.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STANGE_ISP/Buttons.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STANGE_ISP/Buttons.h deleted file mode 100644 index d4576b6885..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STANGE_ISP/Buttons.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the 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). - * - * - * - * - *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTD.7
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STANGE_ISP/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STANGE_ISP/LEDs.h deleted file mode 100644 index 9f10683795..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STANGE_ISP/LEDs.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the 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). - * - * - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenGeneral IndicatorLowPORTD.0
    LEDS_LED2RedGeneral IndicatorLowPORTD.1
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK525/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK525/Board.h deleted file mode 100644 index bda925bb5b..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK525/Board.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK525/Buttons.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK525/Buttons.h deleted file mode 100644 index 532a46f1dd..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK525/Buttons.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * - * - * - *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTE.2
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK525/Dataflash.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK525/Dataflash.h deleted file mode 100644 index 825a7a524f..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK525/Dataflash.h +++ /dev/null @@ -1,222 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * - * - * - *
    NameInfoSelect PinSPI Port
    DATAFLASH_CHIP1AT45DB321C (4MB)PORTB.4SPI0
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK525/Joystick.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK525/Joystick.h deleted file mode 100644 index 6b9b4f42c6..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK525/Joystick.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * - * - * - *
    Left Port PinUp Port PinRight Port PinDown Port PinPress Port Pin
    PORTB.6PORTB.7PORTE.4PORTE.5PORTB.5
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK525/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK525/LEDs.h deleted file mode 100644 index 53948b461b..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK525/LEDs.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * - * - * - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenGeneral IndicatorHighPORTD.4
    LEDS_LED2GreenGeneral IndicatorHighPORTD.5
    LEDS_LED3GreenGeneral IndicatorHighPORTD.6
    LEDS_LED4GreenGeneral IndicatorHighPORTD.7
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK526/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK526/Board.h deleted file mode 100644 index 6be146fcd5..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK526/Board.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK526/Buttons.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK526/Buttons.h deleted file mode 100644 index bc598d389c..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK526/Buttons.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * - * - * - *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTD.7
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK526/Dataflash.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK526/Dataflash.h deleted file mode 100644 index d2a59b12e2..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK526/Dataflash.h +++ /dev/null @@ -1,222 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * - * - * - *
    NameInfoSelect PinSPI Port
    DATAFLASH_CHIP1AT45DB642D (8MB)PORTC.2SPI0
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK526/Joystick.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK526/Joystick.h deleted file mode 100644 index 7decabc5da..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK526/Joystick.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * - * - * - *
    Left Port PinUp Port PinRight Port PinDown Port PinPress Port Pin
    PORTB.4PORTB.5PORTB.6PORTB.7PORTB.0
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK526/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK526/LEDs.h deleted file mode 100644 index 71525e9619..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/STK526/LEDs.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * - * - * - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenGeneral IndicatorHighPORTD.1
    LEDS_LED2GreenGeneral IndicatorHighPORTD.0
    LEDS_LED3GreenGeneral IndicatorHighPORTD.5
    LEDS_LED4GreenGeneral IndicatorHighPORTD.4
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/TEENSY/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/TEENSY/Board.h deleted file mode 100644 index 52e4d61148..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/TEENSY/Board.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/TEENSY/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/TEENSY/LEDs.h deleted file mode 100644 index 9f872247ed..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/TEENSY/LEDs.h +++ /dev/null @@ -1,176 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 BOARD = TEENSY2. - * - * Board specific LED driver header for the PJRC Teensy boards (http://www.pjrc.com/teensy/index.html). - * - * TEENSY: - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenGeneral IndicatorHighPORTD.6
    - * - * TEENSY2: - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenGeneral IndicatorLowPORTD.6
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/TUL/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/TUL/Board.h deleted file mode 100644 index 7759c37cb7..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/TUL/Board.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/TUL/Buttons.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/TUL/Buttons.h deleted file mode 100644 index bbcca263d4..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/TUL/Buttons.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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). - * - * - * - * - *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTE.2
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/TUL/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/TUL/LEDs.h deleted file mode 100644 index 8a14b8a9a6..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/TUL/LEDs.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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). - * - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenGeneral IndicatorHighPORTF.0
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/U2S/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/U2S/Board.h deleted file mode 100644 index 128580a95b..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/U2S/Board.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/U2S/Buttons.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/U2S/Buttons.h deleted file mode 100644 index 30f0a9f5b5..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/U2S/Buttons.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/). - * - * - * - * - *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTC.4
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/U2S/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/U2S/LEDs.h deleted file mode 100644 index d7cf7cfb17..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/U2S/LEDs.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/). - * - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1RedGeneral IndicatorLowPORTC.2
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/UDIP/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/UDIP/Board.h deleted file mode 100644 index 3a400053c4..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/UDIP/Board.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/UDIP/Buttons.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/UDIP/Buttons.h deleted file mode 100644 index dab29a60a8..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/UDIP/Buttons.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/). - * - * - * - * - *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTD.7
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/UDIP/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/UDIP/LEDs.h deleted file mode 100644 index fbcc8ff660..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/UDIP/LEDs.h +++ /dev/null @@ -1,163 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/). - * - * - * - * - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenBicolor Indicator 1HighPORTB.6
    LEDS_LED2RedBicolor Indicator 1HighPORTB.5
    LEDS_LED3GreenBicolor Indicator 2HighPORTD.5
    LEDS_LED4RedBicolor Indicator 2HighPORTD.4
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/UNO/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/UNO/Board.h deleted file mode 100644 index b23f8d0fd4..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/UNO/Board.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/UNO/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/UNO/LEDs.h deleted file mode 100644 index 006c3a5ddf..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/UNO/LEDs.h +++ /dev/null @@ -1,139 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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). - * - * - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1YellowRXLowPORTD.4
    LEDS_LED2YellowTXLowPORTD.5
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USB2AX/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USB2AX/Board.h deleted file mode 100644 index 05a4dea5a9..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USB2AX/Board.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USB2AX/Buttons.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USB2AX/Buttons.h deleted file mode 100644 index 170a9affb2..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USB2AX/Buttons.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 BOARD = USB2AX_V3 and for version 3.1, with BOARD = USB2AX_V31. - * - * Board specific Buttons driver header for the Paranoid Studio USB2AX (http://paranoidstudio.assembla.com/wiki/show/paranoidstudio/USB2AX). - * - * - * - * - *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTD.7
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USB2AX/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USB2AX/LEDs.h deleted file mode 100644 index 03550fc00d..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USB2AX/LEDs.h +++ /dev/null @@ -1,218 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 BOARD = USB2AX_V3 and for version 3.1, with BOARD = USB2AX_V31. - * - * Board specific LED driver header for the Xevelabs USB2AX (http://paranoidstudio.assembla.com/wiki/show/paranoidstudio/USB2AX). - * - * USB2AX: - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenGeneral IndicatorHighPORTC.6
    - * - * USB2AX_V3: - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenGeneral IndicatorHighPORTD.1
    - * - * USB2AX_V31: - * - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenGeneral IndicatorHighPORTD.5
    LEDS_LED2RedGeneral IndicatorHighPORTD.6
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBFOO/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBFOO/Board.h deleted file mode 100644 index 15c41ab5ec..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBFOO/Board.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBFOO/Buttons.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBFOO/Buttons.h deleted file mode 100644 index e901437d71..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBFOO/Buttons.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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). - * - * - * - * - *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTD.7
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBFOO/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBFOO/LEDs.h deleted file mode 100644 index e396630df5..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBFOO/LEDs.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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). - * - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenGeneral IndicatorLowPORTD.4
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBKEY/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBKEY/Board.h deleted file mode 100644 index 3663056566..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBKEY/Board.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBKEY/Buttons.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBKEY/Buttons.h deleted file mode 100644 index 3ec7b3acd2..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBKEY/Buttons.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * - * - * - *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTE.2
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBKEY/Dataflash.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBKEY/Dataflash.h deleted file mode 100644 index 85a8dda3d4..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBKEY/Dataflash.h +++ /dev/null @@ -1,237 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * - * - * - * - *
    NameInfoSelect PinSPI Port
    DATAFLASH_CHIP1AT45DB642D (8MB)PORTE.0SPI0
    DATAFLASH_CHIP2AT45DB642D (8MB)PORTE.1SPI0
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBKEY/Joystick.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBKEY/Joystick.h deleted file mode 100644 index 45d5a66a88..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBKEY/Joystick.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * - * - * - *
    Left Port PinUp Port PinRight Port PinDown Port PinPress Port Pin
    PORTB.6PORTB.7PORTE.4PORTE.5PORTB.5
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBKEY/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBKEY/LEDs.h deleted file mode 100644 index dc02da52e3..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBKEY/LEDs.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * - * - * - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1RedBicolor Indicator 1HighPORTD.4
    LEDS_LED2GreenBicolor Indicator 1HighPORTD.5
    LEDS_LED3RedBicolor Indicator 2HighPORTD.6
    LEDS_LED4GreenBicolor Indicator 2HighPORTD.7
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBTINYMKII/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBTINYMKII/Board.h deleted file mode 100644 index 492aced782..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBTINYMKII/Board.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBTINYMKII/Buttons.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBTINYMKII/Buttons.h deleted file mode 100644 index 682239cd72..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBTINYMKII/Buttons.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/). - * - * - * - * - *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1HWB ButtonLowPORTD.7
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBTINYMKII/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBTINYMKII/LEDs.h deleted file mode 100644 index a2decbc497..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/USBTINYMKII/LEDs.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/). - * - * - * - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1RedBicolor Indicator 1HighPORTB.6
    LEDS_LED2GreenBicolor Indicator 1HighPORTB.7
    LEDS_LED3RedTarget PowerHighPORTB.5
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/XPLAIN/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/XPLAIN/Board.h deleted file mode 100644 index 57ad4c98b1..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/XPLAIN/Board.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/XPLAIN/Dataflash.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/XPLAIN/Dataflash.h deleted file mode 100644 index a8078f61f6..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/XPLAIN/Dataflash.h +++ /dev/null @@ -1,245 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 BOARD = BOARD_XPLAIN_REV1. - * - * Board specific Dataflash driver header for the Atmel XPLAIN. - * - * Revision 1 Boards: - * - * - * - *
    NameInfoSelect PinSPI Port
    DATAFLASH_CHIP1AT45DB041D (512KB)PORTB.5SPI0
    - * - * Other Board Revisions: - * - * - * - *
    NameInfoSelect PinSPI Port
    DATAFLASH_CHIP1AT45DB642D (8MB)PORTB.5SPI0
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/XPLAIN/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/XPLAIN/LEDs.h deleted file mode 100644 index 338b1b419c..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/AVR8/XPLAIN/LEDs.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenGeneral IndicatorLowPORTB.6
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/Board.h deleted file mode 100644 index 9372d0b499..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/Board.h +++ /dev/null @@ -1,163 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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" - #else - #include "Board/Board.h" - #endif - -#endif - -/** @} */ - diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/Buttons.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/Buttons.h deleted file mode 100644 index dc22cc1ab5..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/Buttons.h +++ /dev/null @@ -1,188 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/Dataflash.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/Dataflash.h deleted file mode 100644 index 134a08de0b..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/Dataflash.h +++ /dev/null @@ -1,266 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 SPI and board Dataflash drivers before first use - * SPI_Init(SPI_SPEED_FCPU_DIV_2 | SPI_ORDER_MSB_FIRST | SPI_SCK_LEAD_FALLING | - * SPI_SAMPLE_TRAILING | SPI_MODE_MASTER); - * 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/Joystick.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/Joystick.h deleted file mode 100644 index 4ecf61fefc..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/Joystick.h +++ /dev/null @@ -1,151 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/LEDs.h deleted file mode 100644 index 90485c83e1..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/LEDs.h +++ /dev/null @@ -1,294 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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" - #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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/Temperature.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/Temperature.c deleted file mode 100644 index 8b09f1094b..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/Temperature.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/Temperature.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/Temperature.h deleted file mode 100644 index d20c6f7018..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/Temperature.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 (Makefile source module name: LUFA_SRC_TEMPERATURE) - * - * \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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1100/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1100/Board.h deleted file mode 100644 index 0c34a3f049..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1100/Board.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1100/Buttons.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1100/Buttons.h deleted file mode 100644 index fa452003fe..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1100/Buttons.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * - * - * - * - * - *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1SW0 ButtonLowGPIO88
    BUTTONS_BUTTON2SW1 ButtonLowGPIO85
    BUTTONS_BUTTON3SW2 ButtonLowGPIO82
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1100/Joystick.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1100/Joystick.h deleted file mode 100644 index 72dd769b05..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1100/Joystick.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * - * - * - *
    Left Port PinUp Port PinRight Port PinDown Port PinPress Port Pin
    GPIO25GPIO26GPIO28GPIO27GPIO20
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1100/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1100/LEDs.h deleted file mode 100644 index f66eddbc1e..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1100/LEDs.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * - * - * - * - * - * - * - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenLED0 LEDLowGPIO51
    LEDS_LED2GreenLED1 LEDLowGPIO52
    LEDS_LED3GreenLED2 LEDLowGPIO53
    LEDS_LED4GreenLED3 LEDLowGPIO54
    LEDS_LED5GreenLED4 LEDLowGPIO59
    LEDS_LED6GreenLED5 LEDLowGPIO60
    LEDS_LED7GreenLED6 LEDLowGPIO61
    LEDS_LED8GreenLED7 LEDLowGPIO62
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1101/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1101/Board.h deleted file mode 100644 index 5d5f95a6a5..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1101/Board.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1101/Buttons.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1101/Buttons.h deleted file mode 100644 index 3de4b3373c..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1101/Buttons.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * - * - * - * - *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1SW0 ButtonLowGPIO34
    BUTTONS_BUTTON2SW1 ButtonLowGPIO35
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1101/Joystick.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1101/Joystick.h deleted file mode 100644 index f7a9a7538b..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1101/Joystick.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * - * - * - *
    Left Port PinUp Port PinRight Port PinDown Port PinPress Port Pin
    GPIO38GPIO39GPIO41GPIO40GPIO13
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1101/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1101/LEDs.h deleted file mode 100644 index dad7771a26..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1101/LEDs.h +++ /dev/null @@ -1,156 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * - * - * - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenLED0 LEDLowGPIO7
    LEDS_LED2GreenLED1 LEDLowGPIO8
    LEDS_LED3GreenLED2 LEDLowGPIO21
    LEDS_LED4GreenLED3 LEDLowGPIO22
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1104/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1104/Board.h deleted file mode 100644 index aa7adbfb0c..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1104/Board.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1104/Buttons.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1104/Buttons.h deleted file mode 100644 index dfcfb665ea..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1104/Buttons.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * - * - * - *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1SW0 ButtonLowGPIO42
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1104/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1104/LEDs.h deleted file mode 100644 index 2258a267f1..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/EVK1104/LEDs.h +++ /dev/null @@ -1,174 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * - * - * - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1GreenLED0 LEDLowGPIO67
    LEDS_LED2GreenLED1 LEDLowGPIO101
    LEDS_LED3GreenLED2 LEDLowGPIO102
    LEDS_LED4GreenLED3 LEDLowGPIO105
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/UC3A3_XPLAINED/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/UC3A3_XPLAINED/Board.h deleted file mode 100644 index ec4d9c7c94..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/UC3A3_XPLAINED/Board.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/UC3A3_XPLAINED/Buttons.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/UC3A3_XPLAINED/Buttons.h deleted file mode 100644 index 8accb6fe1c..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/UC3A3_XPLAINED/Buttons.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * - * - * - *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1SW0 ButtonLowGPIO32
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/UC3A3_XPLAINED/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/UC3A3_XPLAINED/LEDs.h deleted file mode 100644 index 66b7834c73..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/UC3/UC3A3_XPLAINED/LEDs.h +++ /dev/null @@ -1,182 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * - * - * - * - * - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1YellowLED0 LEDLowGPIO35
    LEDS_LED2YellowLED1 LEDLowGPIO73
    LEDS_LED3YellowLED2 LEDLowGPIO34
    LEDS_LED4YellowLED3 LEDLowGPIO38
    LEDS_LED5GreenStatusLowGPIO50
    LEDS_LED6RedPowerHighGPIO49
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/Board.h deleted file mode 100644 index 824c3db498..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/Board.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/Buttons.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/Buttons.h deleted file mode 100644 index d5119eb5ca..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/Buttons.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * - * - * - * - * - *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1SW0 ButtonLowPORTE.5
    BUTTONS_BUTTON2SW1 ButtonLowPORTF.1
    BUTTONS_BUTTON3SW2 ButtonLowPORTF.2
    - * - * @{ - */ - -#ifndef __BUTTONS_A3BU_XPLAINED_H__ -#define __BUTTONS_A3BU_XPLAINED_H__ - - /* Includes: */ - #include - - /* 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/Dataflash.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/Dataflash.h deleted file mode 100644 index 2d0983941c..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/Dataflash.h +++ /dev/null @@ -1,228 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * - * - * - *
    NameInfoSelect PinSPI Port
    DATAFLASH_CHIP1AT45DB642D (8MB)PORTF.4USARTD0 (In SPI Mode)
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/LEDs.h deleted file mode 100644 index 16abfbc974..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/LEDs.h +++ /dev/null @@ -1,181 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * - * - * - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1YellowLED0 LEDLowPORTR.0
    LEDS_LED2YellowLED1 LEDLowPORTR.1
    LEDS_LED3RedStatus Bicolour Red LEDLowPORTD.4
    LEDS_LED4GreenStatus Bicolour Green LEDHighPORTD.5
    - * - * @{ - */ - -#ifndef __LEDS_A3BU_XPLAINED_H__ -#define __LEDS_A3BU_XPLAINED_H__ - - /* Includes: */ - #include - - /* 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/Board.h deleted file mode 100644 index d807d18b34..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/Board.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/Buttons.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/Buttons.h deleted file mode 100644 index 9c458b4966..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/Buttons.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * - * - * - * - * - * - *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1Touch CS0 ButtonLowPORTE.0
    BUTTONS_BUTTON2Touch CS1 ButtonLowPORTE.1
    BUTTONS_BUTTON3Touch CS2 ButtonLowPORTE.2
    BUTTONS_BUTTON4Touch CS3 ButtonLowPORTE.3
    - * - * @{ - */ - -#ifndef __BUTTONS_B1_XPLAINED_H__ -#define __BUTTONS_B1_XPLAINED_H__ - - /* Includes: */ - #include - - /* 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/Dataflash.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/Dataflash.h deleted file mode 100644 index f02ca4af0f..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/Dataflash.h +++ /dev/null @@ -1,229 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * - * - * - *
    NameInfoSelect PinSPI Port
    DATAFLASH_CHIP1AT45DB642D (8MB)PORTD.2USARTC0 (In SPI Mode, Remapped)
    - * - * @{ - */ - -#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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/LEDs.h deleted file mode 100644 index 7bd31ad094..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/LEDs.h +++ /dev/null @@ -1,183 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * - * - * - * - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1YellowLED0 LEDHighPORTB.4
    LEDS_LED2YellowLED1 LEDHighPORTB.5
    LEDS_LED3YellowLED2 LEDHighPORTB.6
    LEDS_LED4YellowLED3 LEDHighPORTB.7
    LEDS_LED5GreenUSB LEDLowPORTE.4
    - * - * @{ - */ - -#ifndef __LEDS_B1_XPLAINED_H__ -#define __LEDS_B1_XPLAINED_H__ - - /* Includes: */ - #include - - /* 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/C3_XPLAINED/Board.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/C3_XPLAINED/Board.h deleted file mode 100644 index d90cc3a5c6..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/C3_XPLAINED/Board.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/C3_XPLAINED/Buttons.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/C3_XPLAINED/Buttons.h deleted file mode 100644 index db62b1d1f1..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/C3_XPLAINED/Buttons.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * - * - * - * - *
    NameInfoActive LevelPort Pin
    BUTTONS_BUTTON1SW0 ButtonLowPORTF.1
    BUTTONS_BUTTON2SW1 ButtonLowPORTF.2
    - * - * @{ - */ - -#ifndef __BUTTONS_C3_XPLAINED_H__ -#define __BUTTONS_C3_XPLAINED_H__ - - /* Includes: */ - #include - - /* 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/C3_XPLAINED/LEDs.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/C3_XPLAINED/LEDs.h deleted file mode 100644 index 737624bd39..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Board/XMEGA/C3_XPLAINED/LEDs.h +++ /dev/null @@ -1,181 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * - * - * - * - * - * - *
    NameColorInfoActive LevelPort Pin
    LEDS_LED1YellowLED0 LEDLowPORTR.0
    LEDS_LED2YellowLED1 LEDLowPORTR.1
    LEDS_LED3RedStatus Bicolour Red LEDLowPORTD.4
    LEDS_LED4GreenStatus Bicolour Green LEDHighPORTD.5
    - * - * @{ - */ - -#ifndef __LEDS_C3_XPLAINED_H__ -#define __LEDS_C3_XPLAINED_H__ - - /* Includes: */ - #include - - /* 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Misc/AT45DB321C.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Misc/AT45DB321C.h deleted file mode 100644 index 25069286fe..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Misc/AT45DB321C.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Misc/AT45DB642D.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Misc/AT45DB642D.h deleted file mode 100644 index ebbad71f95..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Misc/AT45DB642D.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Misc/RingBuffer.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Misc/RingBuffer.h deleted file mode 100644 index 68fdb8e92c..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Misc/RingBuffer.h +++ /dev/null @@ -1,308 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Misc/TerminalCodes.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Misc/TerminalCodes.h deleted file mode 100644 index d43fe010c5..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Misc/TerminalCodes.h +++ /dev/null @@ -1,231 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/ADC.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/ADC.h deleted file mode 100644 index 295c6e1e85..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/ADC.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/ADC_AVR8.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/ADC_AVR8.h deleted file mode 100644 index 03b6ed0c29..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/ADC_AVR8.h +++ /dev/null @@ -1,446 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 not 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 not 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/SPI_AVR8.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/SPI_AVR8.h deleted file mode 100644 index 1b8f53e2b1..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/SPI_AVR8.h +++ /dev/null @@ -1,258 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/SerialSPI_AVR8.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/SerialSPI_AVR8.h deleted file mode 100644 index 7afaf1bd43..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/SerialSPI_AVR8.h +++ /dev/null @@ -1,200 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 | SPI_SAMPLE_LEADING | 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 - - /* 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 SPI_Init(). Indicates that the SCK should lead on the rising edge. */ - #define USART_SPI_SCK_LEAD_RISING (0 << UCPOL) - - /** 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 << UCPOL) - //@} - - /** \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 << UPCHA) - - /** 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 << UPCHA) - //@} - - /** \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 << UDORD) - - /** SPI data order mask for \ref SerialSPI_Init(). Indicates that data should be shifted out LSB first. */ - #define USART_SPI_ORDER_LSB_FIRST (1 << UDORD) - //@} - - /* 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/Serial_AVR8.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/Serial_AVR8.c deleted file mode 100644 index 8785a4b6db..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/Serial_AVR8.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/Serial_AVR8.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/Serial_AVR8.h deleted file mode 100644 index f951f6b74c..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/Serial_AVR8.h +++ /dev/null @@ -1,245 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 - - /* 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 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); - } - - /** Transmits a given byte through the USART. - * - * \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 (!(UCSR1A & (1 << UDRE1))); - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/TWI_AVR8.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/TWI_AVR8.c deleted file mode 100644 index 2a6c160e8f..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/TWI_AVR8.c +++ /dev/null @@ -1,209 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/TWI_AVR8.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/TWI_AVR8.h deleted file mode 100644 index 584b584fe0..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/AVR8/TWI_AVR8.h +++ /dev/null @@ -1,305 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * Low Level API Example: - * \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 - * - * High Level API Example: - * \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 - #include - - /* 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
    F_CPU / (16 + 2 * BitLength + 4 ^ Prescale)
    . - * - * \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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/SPI.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/SPI.h deleted file mode 100644 index 54c46423e8..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/SPI.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/Serial.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/Serial.h deleted file mode 100644 index 46ee61b209..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/Serial.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/ARCH/Serial_ARCH.c (Makefile source module name: LUFA_SRC_SERIAL) - * - * \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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/SerialSPI.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/SerialSPI.h deleted file mode 100644 index 9a42ba5d96..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/SerialSPI.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/TWI.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/TWI.h deleted file mode 100644 index 5290e66795..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/TWI.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/ARCH/TWI_ARCH.c (Makefile source module name: LUFA_SRC_TWI) - * - * \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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/XMEGA/SPI_XMEGA.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/XMEGA/SPI_XMEGA.h deleted file mode 100644 index c6230481ed..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/XMEGA/SPI_XMEGA.h +++ /dev/null @@ -1,251 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/XMEGA/SerialSPI_XMEGA.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/XMEGA/SerialSPI_XMEGA.h deleted file mode 100644 index a981ce6a6d..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/XMEGA/SerialSPI_XMEGA.h +++ /dev/null @@ -1,212 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 - - /* 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/XMEGA/Serial_XMEGA.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/XMEGA/Serial_XMEGA.c deleted file mode 100644 index 4e2935730e..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/XMEGA/Serial_XMEGA.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/XMEGA/Serial_XMEGA.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/XMEGA/Serial_XMEGA.h deleted file mode 100644 index 1161ef674c..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/XMEGA/Serial_XMEGA.h +++ /dev/null @@ -1,257 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 - - /* 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 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); - } - - /** Transmits a given byte through the USART. - * - * \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 (!(USART->STATUS & USART_DREIF_bm)); - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/XMEGA/TWI_XMEGA.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/XMEGA/TWI_XMEGA.c deleted file mode 100644 index 457b87cd06..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/XMEGA/TWI_XMEGA.c +++ /dev/null @@ -1,185 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/XMEGA/TWI_XMEGA.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/XMEGA/TWI_XMEGA.h deleted file mode 100644 index 72437e5e15..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/Peripheral/XMEGA/TWI_XMEGA.h +++ /dev/null @@ -1,302 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * Low Level API Example: - * \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 - * - * High Level API Example: - * \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 - - /* 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
    F_CPU / (2 * (5 + (BAUD)))
    . - * - * \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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/AndroidAccessoryClass.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/AndroidAccessoryClass.h deleted file mode 100644 index 24978ca2e3..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/AndroidAccessoryClass.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/AudioClass.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/AudioClass.h deleted file mode 100644 index 0e3ca8d751..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/AudioClass.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 (Makefile source module name: LUFA_SRC_USBCLASS) - * - LUFA/Drivers/USB/Class/Host/AudioClassHost.c (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/CDCClass.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/CDCClass.h deleted file mode 100644 index 3bad74bfa1..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/CDCClass.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 (Makefile source module name: LUFA_SRC_USBCLASS) - * - LUFA/Drivers/USB/Class/Host/CDCClassHost.c (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/AndroidAccessoryClassCommon.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/AndroidAccessoryClassCommon.h deleted file mode 100644 index c3153dab71..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/AndroidAccessoryClassCommon.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/AudioClassCommon.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/AudioClassCommon.h deleted file mode 100644 index 2db5eeea1d..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/AudioClassCommon.h +++ /dev/null @@ -1,780 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 must 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 must 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/CDCClassCommon.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/CDCClassCommon.h deleted file mode 100644 index 94e6c68db1..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/CDCClassCommon.h +++ /dev/null @@ -1,391 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/HIDClassCommon.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/HIDClassCommon.h deleted file mode 100644 index f1e1d070d3..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/HIDClassCommon.h +++ /dev/null @@ -1,665 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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_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_MANU 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_SISREQ 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_ANDPROPS 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 - //@} - - /** \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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/HIDParser.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/HIDParser.c deleted file mode 100644 index d93508f495..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/HIDParser.c +++ /dev/null @@ -1,389 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/HIDParser.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/HIDParser.h deleted file mode 100644 index 1f84ef44ff..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/HIDParser.h +++ /dev/null @@ -1,364 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 (Makefile source module name: LUFA_SRC_USB) - * - * \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 must 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/HIDReportData.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/HIDReportData.h deleted file mode 100644 index df4302cc73..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/HIDReportData.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/MIDIClassCommon.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/MIDIClassCommon.h deleted file mode 100644 index 3e601ea5e5..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/MIDIClassCommon.h +++ /dev/null @@ -1,363 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/MassStorageClassCommon.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/MassStorageClassCommon.h deleted file mode 100644 index 8a12f31b80..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/MassStorageClassCommon.h +++ /dev/null @@ -1,368 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/PrinterClassCommon.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/PrinterClassCommon.h deleted file mode 100644 index 1edd1dd0e1..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/PrinterClassCommon.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/RNDISClassCommon.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/RNDISClassCommon.h deleted file mode 100644 index 5c6d3fdcc5..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/RNDISClassCommon.h +++ /dev/null @@ -1,414 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 a RNDIS control message which can be sent or received. */ - #define RNDIS_MESSAGE_BUFFER_SIZE 128 - - /** 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/StillImageClassCommon.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/StillImageClassCommon.h deleted file mode 100644 index 09a9eab35e..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Common/StillImageClassCommon.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/AudioClassDevice.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/AudioClassDevice.c deleted file mode 100644 index f862ba7647..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/AudioClassDevice.c +++ /dev/null @@ -1,197 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/AudioClassDevice.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/AudioClassDevice.h deleted file mode 100644 index 6cdf4db700..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/AudioClassDevice.h +++ /dev/null @@ -1,396 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \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 - * must 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/CDCClassDevice.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/CDCClassDevice.c deleted file mode 100644 index f4e74cf906..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/CDCClassDevice.c +++ /dev/null @@ -1,341 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/CDCClassDevice.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/CDCClassDevice.h deleted file mode 100644 index 05c0fdddb3..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/CDCClassDevice.h +++ /dev/null @@ -1,352 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \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 - - /* 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 - * must 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 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 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/HIDClassDevice.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/HIDClassDevice.c deleted file mode 100644 index e46330f945..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/HIDClassDevice.c +++ /dev/null @@ -1,207 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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(); - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/HIDClassDevice.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/HIDClassDevice.h deleted file mode 100644 index f373cf0769..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/HIDClassDevice.h +++ /dev/null @@ -1,210 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \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 - * must 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/MIDIClassDevice.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/MIDIClassDevice.c deleted file mode 100644 index b002525975..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/MIDIClassDevice.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/MIDIClassDevice.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/MIDIClassDevice.h deleted file mode 100644 index 70eb442911..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/MIDIClassDevice.h +++ /dev/null @@ -1,175 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \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 - * must 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.c deleted file mode 100644 index d0907963a3..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.c +++ /dev/null @@ -1,215 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.h deleted file mode 100644 index 513221308d..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \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 - * must 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/PrinterClassDevice.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/PrinterClassDevice.c deleted file mode 100644 index fd3454b1ad..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/PrinterClassDevice.c +++ /dev/null @@ -1,314 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/PrinterClassDevice.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/PrinterClassDevice.h deleted file mode 100644 index d9d9644cbe..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/PrinterClassDevice.h +++ /dev/null @@ -1,293 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \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 - - /* 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 - * must 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 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 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/RNDISClassDevice.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/RNDISClassDevice.c deleted file mode 100644 index 061f1b2496..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/RNDISClassDevice.c +++ /dev/null @@ -1,502 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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->State.RNDISMessageBuffer, 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->State.RNDISMessageBuffer; - - if (!(MessageHeader->MessageLength)) - { - RNDISInterfaceInfo->State.RNDISMessageBuffer[0] = 0; - MessageHeader->MessageLength = CPU_TO_LE32(1); - } - - Endpoint_ClearSETUP(); - Endpoint_Write_Control_Stream_LE(RNDISInterfaceInfo->State.RNDISMessageBuffer, 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 (!(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->State.RNDISMessageBuffer; - - 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->State.RNDISMessageBuffer; - RNDIS_Initialize_Complete_t* INITIALIZE_Response = - (RNDIS_Initialize_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer; - - 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->State.RNDISMessageBuffer; - RNDIS_Query_Complete_t* QUERY_Response = (RNDIS_Query_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer; - uint32_t Query_Oid = CPU_TO_LE32(QUERY_Message->Oid); - - void* QueryData = &RNDISInterfaceInfo->State.RNDISMessageBuffer[sizeof(RNDIS_Message_Header_t) + - le32_to_cpu(QUERY_Message->InformationBufferOffset)]; - void* ResponseData = &RNDISInterfaceInfo->State.RNDISMessageBuffer[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->State.RNDISMessageBuffer; - RNDIS_Set_Complete_t* SET_Response = (RNDIS_Set_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer; - 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->State.RNDISMessageBuffer[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->State.RNDISMessageBuffer; - - 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->State.RNDISMessageBuffer; - RNDIS_KeepAlive_Complete_t* KEEPALIVE_Response = - (RNDIS_KeepAlive_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer; - - 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(RNDIS_MESSAGE_BUFFER_SIZE + 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/RNDISClassDevice.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/RNDISClassDevice.h deleted file mode 100644 index 4ba729a7e9..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Device/RNDISClassDevice.h +++ /dev/null @@ -1,203 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \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. */ - } Config; /**< Config data for the USB class interface within the device. All elements in this section - * must be set or the interface will fail to enumerate and operate correctly. - */ - struct - { - uint8_t RNDISMessageBuffer[RNDIS_MESSAGE_BUFFER_SIZE]; /**< Buffer to hold RNDIS messages to and from the host, - * managed by the class driver. - */ - 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__) - /* 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/HIDClass.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/HIDClass.h deleted file mode 100644 index d2eea75321..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/HIDClass.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 (Makefile source module name: LUFA_SRC_USBCLASS) - * - LUFA/Drivers/USB/Class/Host/HIDClassHost.c (Makefile source module name: LUFA_SRC_USBCLASS) - * - LUFA/Drivers/USB/Class/Host/HIDParser.c (Makefile source module name: LUFA_SRC_USB) - * - * \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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/AndroidAccessoryClassHost.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/AndroidAccessoryClassHost.c deleted file mode 100644 index 57a619ff47..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/AndroidAccessoryClassHost.c +++ /dev/null @@ -1,422 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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 false; - - if (!(Pipe_ConfigurePipeTable(&AOAInterfaceInfo->Config.DataOUTPipe, 1))) - return false; - - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/AndroidAccessoryClassHost.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/AndroidAccessoryClassHost.h deleted file mode 100644 index 0476f2e023..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/AndroidAccessoryClassHost.h +++ /dev/null @@ -1,314 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \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 - - /* 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 - * must 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 - * may 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 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 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/AudioClassHost.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/AudioClassHost.c deleted file mode 100644 index c437654b60..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/AudioClassHost.c +++ /dev/null @@ -1,223 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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 false; - - if (!(Pipe_ConfigurePipeTable(&AudioInterfaceInfo->Config.DataOUTPipe, 1))) - return false; - - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/AudioClassHost.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/AudioClassHost.h deleted file mode 100644 index b00bb5fcd3..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/AudioClassHost.h +++ /dev/null @@ -1,411 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \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 - * must 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 - * may 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/CDCClassHost.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/CDCClassHost.c deleted file mode 100644 index a575c1bbf6..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/CDCClassHost.c +++ /dev/null @@ -1,477 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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 false; - - if (!(Pipe_ConfigurePipeTable(&CDCInterfaceInfo->Config.DataOUTPipe, 1))) - return false; - - if (!(Pipe_ConfigurePipeTable(&CDCInterfaceInfo->Config.NotificationPipe, 1))) - return false; - - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/CDCClassHost.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/CDCClassHost.h deleted file mode 100644 index aeee23e50b..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/CDCClassHost.h +++ /dev/null @@ -1,351 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \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 - - /* 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 - * must 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 - * may 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 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 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/HIDClassHost.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/HIDClassHost.c deleted file mode 100644 index c3375e67e3..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/HIDClassHost.c +++ /dev/null @@ -1,399 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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 false; - - 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 false; - } - - 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 false; - - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/HIDClassHost.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/HIDClassHost.h deleted file mode 100644 index 703b698dfb..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/HIDClassHost.h +++ /dev/null @@ -1,313 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \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 - * must 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 - * may 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 must 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 must 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/MIDIClassHost.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/MIDIClassHost.c deleted file mode 100644 index 7ec26549d5..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/MIDIClassHost.c +++ /dev/null @@ -1,231 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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 false; - - if (!(Pipe_ConfigurePipeTable(&MIDIInterfaceInfo->Config.DataOUTPipe, 1))) - return false; - - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/MIDIClassHost.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/MIDIClassHost.h deleted file mode 100644 index 7624f8ed93..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/MIDIClassHost.h +++ /dev/null @@ -1,190 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \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 - * must 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 - * may 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/MassStorageClassHost.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/MassStorageClassHost.c deleted file mode 100644 index d5bace70e8..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/MassStorageClassHost.c +++ /dev/null @@ -1,579 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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 false; - - if (!(Pipe_ConfigurePipeTable(&MSInterfaceInfo->Config.DataOUTPipe, 1))) - return false; - - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/MassStorageClassHost.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/MassStorageClassHost.h deleted file mode 100644 index 6e558073b8..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/MassStorageClassHost.h +++ /dev/null @@ -1,335 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \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 - * must 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 - * may 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/PrinterClassHost.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/PrinterClassHost.c deleted file mode 100644 index 7eda9f605e..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/PrinterClassHost.c +++ /dev/null @@ -1,400 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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 false; - - if (!(Pipe_ConfigurePipeTable(&PRNTInterfaceInfo->Config.DataOUTPipe, 1))) - return false; - - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/PrinterClassHost.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/PrinterClassHost.h deleted file mode 100644 index 8089aa5921..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/PrinterClassHost.h +++ /dev/null @@ -1,285 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \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 - * must 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 - * may 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/RNDISClassHost.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/RNDISClassHost.c deleted file mode 100644 index 9072d3aa64..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/RNDISClassHost.c +++ /dev/null @@ -1,476 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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 false; - - if (!(Pipe_ConfigurePipeTable(&RNDISInterfaceInfo->Config.DataOUTPipe, 1))) - return false; - - if (!(Pipe_ConfigurePipeTable(&RNDISInterfaceInfo->Config.NotificationPipe, 1))) - return false; - - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/RNDISClassHost.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/RNDISClassHost.h deleted file mode 100644 index 79334b41b0..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/RNDISClassHost.h +++ /dev/null @@ -1,270 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \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 - * must 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 - * may 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/StillImageClassHost.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/StillImageClassHost.c deleted file mode 100644 index b3d74bc1ef..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/StillImageClassHost.c +++ /dev/null @@ -1,436 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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 false; - - if (!(Pipe_ConfigurePipeTable(&SIInterfaceInfo->Config.DataOUTPipe, 1))) - return false; - - if (!(Pipe_ConfigurePipeTable(&SIInterfaceInfo->Config.EventsPipe, 1))) - return false; - - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/StillImageClassHost.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/StillImageClassHost.h deleted file mode 100644 index f9f41adb69..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/Host/StillImageClassHost.h +++ /dev/null @@ -1,317 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \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 - * must 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 - * may 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/MIDIClass.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/MIDIClass.h deleted file mode 100644 index 7e6ba1c5b9..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/MIDIClass.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 (Makefile source module name: LUFA_SRC_USBCLASS) - * - LUFA/Drivers/USB/Class/Host/MIDIClassHost.c (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/MassStorageClass.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/MassStorageClass.h deleted file mode 100644 index 79a052163a..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/MassStorageClass.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 (Makefile source module name: LUFA_SRC_USBCLASS) - * - LUFA/Drivers/USB/Class/Host/MassStorageClassHost.c (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/PrinterClass.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/PrinterClass.h deleted file mode 100644 index 91121b5d04..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/PrinterClass.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 (Makefile source module name: LUFA_SRC_USBCLASS) - * - LUFA/Drivers/USB/Class/Host/PrinterClassHost.c (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/RNDISClass.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/RNDISClass.h deleted file mode 100644 index 1555f0d232..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/RNDISClass.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 (Makefile source module name: LUFA_SRC_USBCLASS) - * - LUFA/Drivers/USB/Class/Host/RNDISClassHost.c (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/StillImageClass.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/StillImageClass.h deleted file mode 100644 index f2ec37b03b..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Class/StillImageClass.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 (Makefile source module name: LUFA_SRC_USBCLASS) - * - * \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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Device_AVR8.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Device_AVR8.c deleted file mode 100644 index d23e7b8468..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Device_AVR8.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Device_AVR8.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Device_AVR8.h deleted file mode 100644 index 5efffe7b8d..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Device_AVR8.h +++ /dev/null @@ -1,269 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/EndpointStream_AVR8.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/EndpointStream_AVR8.c deleted file mode 100644 index 5782824cc4..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/EndpointStream_AVR8.c +++ /dev/null @@ -1,275 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/EndpointStream_AVR8.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/EndpointStream_AVR8.h deleted file mode 100644 index 2032789764..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/EndpointStream_AVR8.h +++ /dev/null @@ -1,658 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * Single Stream Transfer Example: - * \code - * uint8_t ErrorCode; - * - * if ((ErrorCode = Endpoint_Discard_Stream(512, NULL)) != ENDPOINT_RWSTREAM_NoError) - * { - * // Stream failed to complete - check ErrorCode here - * } - * \endcode - * - * Partial Stream Transfers Example: - * \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. - * - * Single Stream Transfer Example: - * \code - * uint8_t ErrorCode; - * - * if ((ErrorCode = Endpoint_Null_Stream(512, NULL)) != ENDPOINT_RWSTREAM_NoError) - * { - * // Stream failed to complete - check ErrorCode here - * } - * \endcode - * - * Partial Stream Transfers Example: - * \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. - * - * Single Stream Transfer Example: - * \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 - * - * Partial Stream Transfers Example: - * \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. - * - * Single Stream Transfer Example: - * \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 - * - * Partial Stream Transfers Example: - * \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 status 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 status 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 status 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 status 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 status 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 status 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 status 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 status 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 status 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 status 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Endpoint_AVR8.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Endpoint_AVR8.c deleted file mode 100644 index f5d20341b7..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Endpoint_AVR8.c +++ /dev/null @@ -1,201 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Endpoint_AVR8.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Endpoint_AVR8.h deleted file mode 100644 index 1632d93cfc..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Endpoint_AVR8.h +++ /dev/null @@ -1,819 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 must 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 (1 << {Endpoint Number}). - * - * \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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Host_AVR8.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Host_AVR8.c deleted file mode 100644 index 4e38c75a60..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Host_AVR8.c +++ /dev/null @@ -1,297 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Host_AVR8.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Host_AVR8.h deleted file mode 100644 index f0ffa5a54c..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Host_AVR8.h +++ /dev/null @@ -1,372 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/OTG_AVR8.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/OTG_AVR8.h deleted file mode 100644 index c2e8496274..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/OTG_AVR8.h +++ /dev/null @@ -1,159 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/PipeStream_AVR8.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/PipeStream_AVR8.c deleted file mode 100644 index 47169b3feb..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/PipeStream_AVR8.c +++ /dev/null @@ -1,221 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/PipeStream_AVR8.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/PipeStream_AVR8.h deleted file mode 100644 index 264dab54e9..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/PipeStream_AVR8.h +++ /dev/null @@ -1,442 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * Single Stream Transfer Example: - * \code - * uint8_t ErrorCode; - * - * if ((ErrorCode = Pipe_Discard_Stream(512, NULL)) != PIPE_RWSTREAM_NoError) - * { - * // Stream failed to complete - check ErrorCode here - * } - * \endcode - * - * Partial Stream Transfers Example: - * \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. - * - * Single Stream Transfer Example: - * \code - * uint8_t ErrorCode; - * - * if ((ErrorCode = Pipe_Null_Stream(512, NULL)) != PIPE_RWSTREAM_NoError) - * { - * // Stream failed to complete - check ErrorCode here - * } - * \endcode - * - * Partial Stream Transfers Example: - * \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. - * - * Single Stream Transfer Example: - * \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 - * - * Partial Stream Transfers Example: - * \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. - * - * Single Stream Transfer Example: - * \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 - * - * Partial Stream Transfers Example: - * \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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Pipe_AVR8.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Pipe_AVR8.c deleted file mode 100644 index fc99ae416d..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Pipe_AVR8.c +++ /dev/null @@ -1,210 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Pipe_AVR8.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Pipe_AVR8.h deleted file mode 100644 index bac324ffc0..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Pipe_AVR8.h +++ /dev/null @@ -1,922 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 must 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Template/Template_Endpoint_Control_R.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Template/Template_Endpoint_Control_R.c deleted file mode 100644 index 59c620ae59..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Template/Template_Endpoint_Control_R.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Template/Template_Endpoint_Control_W.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Template/Template_Endpoint_Control_W.c deleted file mode 100644 index 4fc242f34b..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Template/Template_Endpoint_Control_W.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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; - } - - return ENDPOINT_RWCSTREAM_NoError; -} - -#undef TEMPLATE_BUFFER_OFFSET -#undef TEMPLATE_BUFFER_MOVE -#undef TEMPLATE_FUNC_NAME -#undef TEMPLATE_TRANSFER_BYTE - -#endif - diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Template/Template_Endpoint_RW.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Template/Template_Endpoint_RW.c deleted file mode 100644 index d51afdfb16..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Template/Template_Endpoint_RW.c +++ /dev/null @@ -1,89 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Template/Template_Pipe_RW.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Template/Template_Pipe_RW.c deleted file mode 100644 index 2685c9b9db..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/Template/Template_Pipe_RW.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/USBController_AVR8.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/USBController_AVR8.c deleted file mode 100644 index 71c5f916d7..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/USBController_AVR8.c +++ /dev/null @@ -1,273 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/USBController_AVR8.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/USBController_AVR8.h deleted file mode 100644 index de34f42a17..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/USBController_AVR8.h +++ /dev/null @@ -1,432 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/USBInterrupt_AVR8.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/USBInterrupt_AVR8.c deleted file mode 100644 index 7efaea65a0..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/USBInterrupt_AVR8.c +++ /dev/null @@ -1,279 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/USBInterrupt_AVR8.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/USBInterrupt_AVR8.h deleted file mode 100644 index e6f5ff994e..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/AVR8/USBInterrupt_AVR8.h +++ /dev/null @@ -1,375 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/ConfigDescriptors.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/ConfigDescriptors.c deleted file mode 100644 index da6812a323..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/ConfigDescriptors.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/ConfigDescriptors.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/ConfigDescriptors.h deleted file mode 100644 index b4a9788c28..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/ConfigDescriptors.h +++ /dev/null @@ -1,287 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/Device.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/Device.h deleted file mode 100644 index 10d739f569..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/Device.h +++ /dev/null @@ -1,159 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/DeviceStandardReq.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/DeviceStandardReq.c deleted file mode 100644 index adf615a9c4..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/DeviceStandardReq.c +++ /dev/null @@ -1,380 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/DeviceStandardReq.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/DeviceStandardReq.h deleted file mode 100644 index 396e205547..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/DeviceStandardReq.h +++ /dev/null @@ -1,158 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/Endpoint.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/Endpoint.h deleted file mode 100644 index bf41376f4f..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/Endpoint.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/EndpointStream.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/EndpointStream.h deleted file mode 100644 index 5675c323cc..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/EndpointStream.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/Events.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/Events.c deleted file mode 100644 index a63b002fec..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/Events.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/Events.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/Events.h deleted file mode 100644 index 9c85112fb8..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/Events.h +++ /dev/null @@ -1,372 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/Host.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/Host.h deleted file mode 100644 index 6146cc5aeb..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/Host.h +++ /dev/null @@ -1,139 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/HostStandardReq.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/HostStandardReq.c deleted file mode 100644 index 4a21ce73c0..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/HostStandardReq.c +++ /dev/null @@ -1,322 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/HostStandardReq.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/HostStandardReq.h deleted file mode 100644 index bd67bcb9e9..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/HostStandardReq.h +++ /dev/null @@ -1,292 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/OTG.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/OTG.h deleted file mode 100644 index 58d47bace3..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/OTG.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/Pipe.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/Pipe.h deleted file mode 100644 index ca3fdbe7ad..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/Pipe.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/PipeStream.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/PipeStream.h deleted file mode 100644 index 2399696874..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/PipeStream.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/StdDescriptors.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/StdDescriptors.h deleted file mode 100644 index e0a1a37f4f..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/StdDescriptors.h +++ /dev/null @@ -1,765 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 - * http://www.usb.org/developers/docs/InterfaceAssociationDescriptor_ecn.pdf. 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 - * http://www.usb.org/developers/docs/InterfaceAssociationDescriptor_ecn.pdf. 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/StdRequestType.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/StdRequestType.h deleted file mode 100644 index b2506cd7d2..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/StdRequestType.h +++ /dev/null @@ -1,258 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Device_UC3.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Device_UC3.c deleted file mode 100644 index 6f6de3f5e9..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Device_UC3.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Device_UC3.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Device_UC3.h deleted file mode 100644 index 5579ea0bc4..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Device_UC3.h +++ /dev/null @@ -1,267 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/EndpointStream_UC3.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/EndpointStream_UC3.c deleted file mode 100644 index 6e98629277..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/EndpointStream_UC3.c +++ /dev/null @@ -1,235 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/EndpointStream_UC3.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/EndpointStream_UC3.h deleted file mode 100644 index 831c714070..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/EndpointStream_UC3.h +++ /dev/null @@ -1,438 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * Single Stream Transfer Example: - * \code - * uint8_t ErrorCode; - * - * if ((ErrorCode = Endpoint_Discard_Stream(512, NULL)) != ENDPOINT_RWSTREAM_NoError) - * { - * // Stream failed to complete - check ErrorCode here - * } - * \endcode - * - * Partial Stream Transfers Example: - * \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. - * - * Single Stream Transfer Example: - * \code - * uint8_t ErrorCode; - * - * if ((ErrorCode = Endpoint_Null_Stream(512, NULL)) != ENDPOINT_RWSTREAM_NoError) - * { - * // Stream failed to complete - check ErrorCode here - * } - * \endcode - * - * Partial Stream Transfers Example: - * \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. - * - * Single Stream Transfer Example: - * \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 - * - * Partial Stream Transfers Example: - * \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. - * - * Single Stream Transfer Example: - * \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 - * - * Partial Stream Transfers Example: - * \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 status 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 status 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 status 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 status 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Endpoint_UC3.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Endpoint_UC3.c deleted file mode 100644 index 5dce488f20..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Endpoint_UC3.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Endpoint_UC3.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Endpoint_UC3.h deleted file mode 100644 index cf35d2b60c..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Endpoint_UC3.h +++ /dev/null @@ -1,794 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 must 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 (1 << {Endpoint Number}). - * - * \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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Host_UC3.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Host_UC3.c deleted file mode 100644 index 77807525f0..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Host_UC3.c +++ /dev/null @@ -1,297 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Host_UC3.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Host_UC3.h deleted file mode 100644 index eb803b073e..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Host_UC3.h +++ /dev/null @@ -1,363 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/PipeStream_UC3.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/PipeStream_UC3.c deleted file mode 100644 index 7dfe448585..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/PipeStream_UC3.c +++ /dev/null @@ -1,166 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/PipeStream_UC3.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/PipeStream_UC3.h deleted file mode 100644 index 4dd79c975f..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/PipeStream_UC3.h +++ /dev/null @@ -1,352 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * Single Stream Transfer Example: - * \code - * uint8_t ErrorCode; - * - * if ((ErrorCode = Pipe_Discard_Stream(512, NULL)) != PIPE_RWSTREAM_NoError) - * { - * // Stream failed to complete - check ErrorCode here - * } - * \endcode - * - * Partial Stream Transfers Example: - * \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. - * - * Single Stream Transfer Example: - * \code - * uint8_t ErrorCode; - * - * if ((ErrorCode = Pipe_Null_Stream(512, NULL)) != PIPE_RWSTREAM_NoError) - * { - * // Stream failed to complete - check ErrorCode here - * } - * \endcode - * - * Partial Stream Transfers Example: - * \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. - * - * Single Stream Transfer Example: - * \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 - * - * Partial Stream Transfers Example: - * \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. - * - * Single Stream Transfer Example: - * \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 - * - * Partial Stream Transfers Example: - * \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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Pipe_UC3.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Pipe_UC3.c deleted file mode 100644 index a24c7b1d6a..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Pipe_UC3.c +++ /dev/null @@ -1,209 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Pipe_UC3.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Pipe_UC3.h deleted file mode 100644 index 1a0ada8b7b..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Pipe_UC3.h +++ /dev/null @@ -1,924 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 must 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Template/Template_Endpoint_Control_R.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Template/Template_Endpoint_Control_R.c deleted file mode 100644 index 59c620ae59..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Template/Template_Endpoint_Control_R.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Template/Template_Endpoint_Control_W.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Template/Template_Endpoint_Control_W.c deleted file mode 100644 index 4fc242f34b..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Template/Template_Endpoint_Control_W.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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; - } - - return ENDPOINT_RWCSTREAM_NoError; -} - -#undef TEMPLATE_BUFFER_OFFSET -#undef TEMPLATE_BUFFER_MOVE -#undef TEMPLATE_FUNC_NAME -#undef TEMPLATE_TRANSFER_BYTE - -#endif - diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Template/Template_Endpoint_RW.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Template/Template_Endpoint_RW.c deleted file mode 100644 index d51afdfb16..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Template/Template_Endpoint_RW.c +++ /dev/null @@ -1,89 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Template/Template_Pipe_RW.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Template/Template_Pipe_RW.c deleted file mode 100644 index 2685c9b9db..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/Template/Template_Pipe_RW.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/USBController_UC3.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/USBController_UC3.c deleted file mode 100644 index fda0ddc393..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/USBController_UC3.c +++ /dev/null @@ -1,222 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/USBController_UC3.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/USBController_UC3.h deleted file mode 100644 index 2e824583a5..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/USBController_UC3.h +++ /dev/null @@ -1,353 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/USBInterrupt_UC3.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/USBInterrupt_UC3.c deleted file mode 100644 index 83ada8cc18..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/USBInterrupt_UC3.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/USBInterrupt_UC3.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/USBInterrupt_UC3.h deleted file mode 100644 index ddd5389c2e..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/UC3/USBInterrupt_UC3.h +++ /dev/null @@ -1,376 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 must 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/USBController.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/USBController.h deleted file mode 100644 index c1d74c32b9..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/USBController.h +++ /dev/null @@ -1,165 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/USBInterrupt.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/USBInterrupt.h deleted file mode 100644 index 3dcfd5fed0..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/USBInterrupt.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/USBMode.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/USBMode.h deleted file mode 100644 index 09cf3076b7..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/USBMode.h +++ /dev/null @@ -1,283 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/USBTask.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/USBTask.c deleted file mode 100644 index 30a3cd682c..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/USBTask.c +++ /dev/null @@ -1,89 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/USBTask.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/USBTask.h deleted file mode 100644 index 7c0917fc19..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/USBTask.h +++ /dev/null @@ -1,200 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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) MACROS{ USB_HostState = HOST_STATE_WaitForDevice; \ - WaitMSRemaining = (Duration); \ - PostWaitState = (NextState); }MACROE - #endif - - /* Disable C linkage for C++ Compilers: */ - #if defined(__cplusplus) - } - #endif - -#endif - diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Device_XMEGA.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Device_XMEGA.c deleted file mode 100644 index 10c3279f35..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Device_XMEGA.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Device_XMEGA.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Device_XMEGA.h deleted file mode 100644 index b203e10266..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Device_XMEGA.h +++ /dev/null @@ -1,266 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/EndpointStream_XMEGA.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/EndpointStream_XMEGA.c deleted file mode 100644 index 421d717099..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/EndpointStream_XMEGA.c +++ /dev/null @@ -1,275 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/EndpointStream_XMEGA.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/EndpointStream_XMEGA.h deleted file mode 100644 index cba6537db3..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/EndpointStream_XMEGA.h +++ /dev/null @@ -1,658 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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. - * - * Single Stream Transfer Example: - * \code - * uint8_t ErrorCode; - * - * if ((ErrorCode = Endpoint_Discard_Stream(512, NULL)) != ENDPOINT_RWSTREAM_NoError) - * { - * // Stream failed to complete - check ErrorCode here - * } - * \endcode - * - * Partial Stream Transfers Example: - * \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. - * - * Single Stream Transfer Example: - * \code - * uint8_t ErrorCode; - * - * if ((ErrorCode = Endpoint_Null_Stream(512, NULL)) != ENDPOINT_RWSTREAM_NoError) - * { - * // Stream failed to complete - check ErrorCode here - * } - * \endcode - * - * Partial Stream Transfers Example: - * \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. - * - * Single Stream Transfer Example: - * \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 - * - * Partial Stream Transfers Example: - * \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. - * - * Single Stream Transfer Example: - * \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 - * - * Partial Stream Transfers Example: - * \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 status 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 status 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 status 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 status 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 status 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 status 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 status 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 status 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 status 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 status 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.c deleted file mode 100644 index 8155ecf7d0..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.c +++ /dev/null @@ -1,268 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.h deleted file mode 100644 index 42c476b249..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.h +++ /dev/null @@ -1,689 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Host_XMEGA.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Host_XMEGA.c deleted file mode 100644 index c467733038..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Host_XMEGA.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/PipeStream_XMEGA.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/PipeStream_XMEGA.c deleted file mode 100644 index c467733038..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/PipeStream_XMEGA.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Pipe_XMEGA.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Pipe_XMEGA.c deleted file mode 100644 index 69f369e430..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Pipe_XMEGA.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Template/Template_Endpoint_Control_R.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Template/Template_Endpoint_Control_R.c deleted file mode 100644 index 0bd3843485..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Template/Template_Endpoint_Control_R.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Template/Template_Endpoint_Control_W.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Template/Template_Endpoint_Control_W.c deleted file mode 100644 index 5bd4092e41..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Template/Template_Endpoint_Control_W.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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; - } - - return ENDPOINT_RWCSTREAM_NoError; -} - -#undef TEMPLATE_BUFFER_OFFSET -#undef TEMPLATE_BUFFER_MOVE -#undef TEMPLATE_FUNC_NAME -#undef TEMPLATE_TRANSFER_BYTE - -#endif - diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Template/Template_Endpoint_RW.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Template/Template_Endpoint_RW.c deleted file mode 100644 index d51afdfb16..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/Template/Template_Endpoint_RW.c +++ /dev/null @@ -1,89 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.c deleted file mode 100644 index f8b0fc6af5..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.c +++ /dev/null @@ -1,193 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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) -{ - #if defined(USB_DEVICE_OPT_FULLSPEED) - if (USB_Options & USB_DEVICE_OPT_LOWSPEED) - CLK.USBCTRL = (((F_USB / 6000000) - 1) << CLK_USBPSDIV_gp); - else - CLK.USBCTRL = (((F_USB / 48000000) - 1) << CLK_USBPSDIV_gp); - #else - CLK.USBCTRL = (((F_USB / 6000000) - 1) << CLK_USBPSDIV_gp); - #endif - - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.h deleted file mode 100644 index 15d4eec348..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.h +++ /dev/null @@ -1,313 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/USBInterrupt_XMEGA.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/USBInterrupt_XMEGA.c deleted file mode 100644 index f03f3f2926..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/USBInterrupt_XMEGA.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/USBInterrupt_XMEGA.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/USBInterrupt_XMEGA.h deleted file mode 100644 index e224e225a2..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/Core/XMEGA/USBInterrupt_XMEGA.h +++ /dev/null @@ -1,172 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/USB.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/USB.h deleted file mode 100644 index a8df26fd1d..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Drivers/USB/USB.h +++ /dev/null @@ -1,422 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 (Makefile source module name: LUFA_SRC_USB) - * - LUFA/Drivers/USB/Core/DeviceStandardReq.c (Makefile source module name: LUFA_SRC_USB) - * - LUFA/Drivers/USB/Core/Events.c (Makefile source module name: LUFA_SRC_USB) - * - LUFA/Drivers/USB/Core/HostStandardReq.c (Makefile source module name: LUFA_SRC_USB) - * - LUFA/Drivers/USB/Core/USBTask.c (Makefile source module name: LUFA_SRC_USB) - * - LUFA/Drivers/USB/Core/ARCH/Device_ARCH.c (Makefile source module name: LUFA_SRC_USB) - * - LUFA/Drivers/USB/Core/ARCH/Endpoint_ARCH.c (Makefile source module name: LUFA_SRC_USB) - * - LUFA/Drivers/USB/Core/ARCH/EndpointStream_ARCH.c (Makefile source module name: LUFA_SRC_USB) - * - LUFA/Drivers/USB/Core/ARCH/Host_ARCH.c (Makefile source module name: LUFA_SRC_USB) - * - LUFA/Drivers/USB/Core/ARCH/Pipe_ARCH.c (Makefile source module name: LUFA_SRC_USB) - * - LUFA/Drivers/USB/Core/ARCH/PipeStream_ARCH.c (Makefile source module name: LUFA_SRC_USB) - * - LUFA/Drivers/USB/Core/ARCH/USBController_ARCH.c (Makefile source module name: LUFA_SRC_USB) - * - LUFA/Drivers/USB/Core/ARCH/USBInterrupt_ARCH.c (Makefile source module name: LUFA_SRC_USB) - * - LUFA/Drivers/USB/Class/Common/HIDParser.c (Makefile source module name: LUFA_SRC_USB) - * - * \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. - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    USB ClassDevice ModeHost Mode
    Android Open AccessoryNoYes
    Audio 1.0YesYes
    CDC-ACMYesYes
    HIDYesYes
    MIDIYesYes
    Mass StorageYesYes
    PrinterYesYes
    RNDISYesYes
    Still ImageNoYes
    - * - * - * \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 USB_ClassInfo_{Class Name}_Device_t, 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 must have all fields set by the user application - * 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 {Class Name}_Device_ConfigureEndpoints() 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 - * {Class Name}_Device_USBTask() 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 - * {Class Name}_Device_ProcessControlRequest(), 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 must 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 may 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 USB_ClassInfo_{Class Name}_Host_t, 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 must have all fields set by the user application - * 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 {Class Name}_Host_ConfigurePipes() 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 {Class Name}_EnumerationFailure_ErrorCodes_t 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 - * {Class Name}_Host_USBTask() 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 must 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 may 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/License.txt b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/License.txt deleted file mode 100644 index 8d4ad75364..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/License.txt +++ /dev/null @@ -1,24 +0,0 @@ - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Platform/Platform.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Platform/Platform.h deleted file mode 100644 index a9eedebc4a..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Platform/Platform.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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: - * - UC3 Architecture Only: LUFA/Platform/UC3/InterruptManagement.c (Makefile source module name: LUFA_SRC_PLATFORM) - * - UC3 Architecture Only: LUFA/Platform/UC3/Exception.S (Makefile source module name: LUFA_SRC_PLATFORM) - * - * \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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Platform/UC3/ClockManagement.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Platform/UC3/ClockManagement.h deleted file mode 100644 index fb062628e8..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Platform/UC3/ClockManagement.h +++ /dev/null @@ -1,338 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 - * - * 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Platform/UC3/Exception.S b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Platform/UC3/Exception.S deleted file mode 100644 index 3a5f240059..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Platform/UC3/Exception.S +++ /dev/null @@ -1,128 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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 - -.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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Platform/UC3/InterruptManagement.c b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Platform/UC3/InterruptManagement.c deleted file mode 100644 index 80d193f129..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Platform/UC3/InterruptManagement.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Platform/UC3/InterruptManagement.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Platform/UC3/InterruptManagement.h deleted file mode 100644 index 90198cddda..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Platform/UC3/InterruptManagement.h +++ /dev/null @@ -1,174 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 (Makefile source module name: LUFA_SRC_PLATFORM) - * - LUFA/Platform/UC3/Exception.S (Makefile source module name: LUFA_SRC_PLATFORM) - * - * \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 - * - * 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Platform/UC3/UC3ExperimentalInfo.txt b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Platform/UC3/UC3ExperimentalInfo.txt deleted file mode 100644 index 8aadb3ed79..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Platform/UC3/UC3ExperimentalInfo.txt +++ /dev/null @@ -1 +0,0 @@ -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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Platform/XMEGA/ClockManagement.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Platform/XMEGA/ClockManagement.h deleted file mode 100644 index ed48d6ee1e..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Platform/XMEGA/ClockManagement.h +++ /dev/null @@ -1,397 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 - * - * 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 uint8_t XMEGACLK_StartInternalOscillator(const uint8_t Source) ATTR_ALWAYS_INLINE; - static inline uint8_t 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 / 1000); - - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Platform/XMEGA/XMEGAExperimentalInfo.txt b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Platform/XMEGA/XMEGAExperimentalInfo.txt deleted file mode 100644 index 42144aac48..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Platform/XMEGA/XMEGAExperimentalInfo.txt +++ /dev/null @@ -1 +0,0 @@ -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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/HV1/helpcontentsetup.msha b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/HV1/helpcontentsetup.msha deleted file mode 100644 index cb1c4b9eb9..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/HV1/helpcontentsetup.msha +++ /dev/null @@ -1,27 +0,0 @@ - - - - - LUFA Help - - -
    - FourWalledCubicle - LUFA - LUFA Help - en-us -
    -
    - -
    - - diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/HV1/lufa_docbook_transform.xslt b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/HV1/lufa_docbook_transform.xslt deleted file mode 100644 index 2ebda6d5dc..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/HV1/lufa_docbook_transform.xslt +++ /dev/null @@ -1,808 +0,0 @@ - - - - - - - - - - LUFA Library - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <xsl:value-of select="$book.title"/> - - - - - - - - - - - - - - - - Modules - - - - - - - - - - - - - - - - LUFA. - - - - - - - - - <xsl:value-of select="$page.title"/> - - - - - - - Subsections: - - - - - - - - - - - - - - - - - - - -
    - - <xsl:value-of select="title"/> - - - - LUFA. - - - - - - - - - - - - Subgroups: - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - -
    - - <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"/> - - - - - - - - - - - - <xsl:value-of select="$name"/> - - - - - - Type - Name - Description - - - - - - - - - - - - - [] - - - - - . - - - - - - - - - - - - - - -
    -
    -
    -
    - - -
    - - <xsl:text>Function </xsl:text> - <xsl:value-of select="name"/> - <xsl:text>()</xsl:text> - - - - - - - - - - - - - - - - - - - ( - - - - void - - - - - - , - - - - - - - - - - - - ) - - - -
    -
    - - -
    - - <xsl:text>Enum </xsl:text> - <xsl:value-of select="name"/> - - - - - - - - - - Members - - - - Enum Value - Description - - - - - - - - - - - - - - - - - - - - - - -
    -
    -
    - - -
    - - <xsl:text>Macro </xsl:text> - <xsl:value-of select="name"/> - - - - - - - - - #define - - - ( - - - , - - - - ) - - - - - - \ - - - - - - - - -
    -
    - - -
    - - <xsl:text>Type </xsl:text> - <xsl:value-of select="name"/> - - - - - - - - - typedef - - - - - - - - - -
    -
    - - - -
    - - <xsl:text>Variable </xsl:text> - <xsl:value-of select="name"/> - - - - - - - - - - - - - - - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <xsl:value-of select="title"/> - - - - - - - - Returns - - - - - - - Warning - - - - - - - Precondition - - - - - - - See also - - - - - - - Note - - - - - - - - - - Parameters - - - - Data Direction - Parameter Name - Description - - - - - - - - - - -
    -
    - - - - Return Values - - - - Return Value - Description - - - - - - - - - - -
    -
    - - - - - - - - ? - - - - - [] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <xsl:value-of select="caption"/> - - - - - - - - - - - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - images/ - - - - - - - - - - - - -
    - - - - - - - - <xsl:value-of select="title"/> - - - -
    -
    - - - - - - - - - - - - - NO XSL TEMPLATE MATCH: - - -
    diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/HV1/lufa_helpcontentsetup_transform.xslt b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/HV1/lufa_helpcontentsetup_transform.xslt deleted file mode 100644 index b43354f8d7..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/HV1/lufa_helpcontentsetup_transform.xslt +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - lufa_help_ - - .mshc - - - lufa_help_ - - .mshc - - - diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/HV1/lufa_hv1_transform.xslt b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/HV1/lufa_hv1_transform.xslt deleted file mode 100644 index 8aa4a9413e..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/HV1/lufa_hv1_transform.xslt +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/HV1/lufa_studio_help_styling.css b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/HV1/lufa_studio_help_styling.css deleted file mode 100644 index 0b6ccbd8c1..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/HV1/lufa_studio_help_styling.css +++ /dev/null @@ -1,53 +0,0 @@ -/* - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/LUFA.dll b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/LUFA.dll deleted file mode 100644 index 49313b59cc9b683ca47ec3f04791c510371c11f9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 748544 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

    ?C!!p8;u?w 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

    %Ii9@Yv#xJ9IP=S*P2I>zV_v% zm-|?Mh%`&5y#3Z-f+x)BTu5jmFK|FTh9E)!9^{7w^^}FpB9X|pO|f=JdE~+cS5I{J z4;`sDC6l~S_k~@MCu9KO0VtQjTL`m#lm5t>lyBE%XkW=|T2c6FefbSz>5ycCXy2Oq z(;G8sZ`sze3cpuuNBIGrxA={CxGIqY=4As95CO&NGYWD}??%rJDwEzm|HsHdXZ&-5 zrjmt&2zQWe@%P#*#OCe+?GooUu-psLXL+kFsNW+&<=3JE;>LM^O z&|5qD_l#}n)=Djt*N4{je?qmW&CFKZL#&+z-#1o>uL zCP|Ju$DI0v;n8$x$cOX&64}*pjW?g!sxTTX*3pUZ7-n4jlu~WTs$Vl#5jkZ^kqDAf z3j5-$+GtVB6bXF$r*};uBvHxdHaW_2__ORO(t=^g+FiiO+RLl+D`cx>BO8WvzaTUv zvcZ#5ZJwA|#%80yB@wn_n6Xc}K>}q@HQ)gw4yZZHC0;uWV%Cus5qUzaEdg zYMQa^N;r9^SqN|mM9EPG&<69gvad~B_6a{Ho|{+|F#tLYLyK$q*orHKW23W@ z6|fTNbH&;7KiuHVumc9`g3!14+D8(UyVQa*UMP32P%24|{LJ(J$A(~Ez{2#IiG>4e zko{}HTB9A^vFn5jy~Fr^q99G#>~(98XX7) z_&iopmT_5(hx6WwJ6O;3s03UBXY3ei5rIX$bVa0rO1)_N`Ko312h&~p-BoIi9yWrN z+4o7Tkw=*h@oamAkF)_CR_F2t3vah+dp*-`@9lMw%6 zsb^7M!m$6m0O=h+o8V!7c0~gB3NO;)ME7KuoyPs#!nYZMAcr%~{|+s9GMz=tdB9r4 zLGK~L{#BVw!w}o(X!_nJmWiVhlEWN@wN;Xb9`h4A89P-bO4Pf-GZSfHxZkxU=;3#Q z8_obgI@p$TJAuz^?*NKr#5t)+Vcl|=C@26UY(9LeeLe^K+k1MMMd;7YnLM=F7agB^ z28hl!OlmCOGUnqlqTTJ3P-ULMVlkl(6R7;U{_$0!jOfHa{uy2}I9_l9fcTiR$%SYc z!88Z;Woks(LoRtF{H5u*ffYF(z=(_6P+yyx98U(H^r+x2AUoHvkLn~oXOt0kHTK-$ zsCi=Yel|BsQ8@YntMM>sD=knri=9k6N`>^o=6=fOU8OK6-M=o_jjBtMBGcQ2=EL2O zD4XvQEdd-rj;Lw2{^lPe1^d`_?ha(@5#C$u$Qwim3D`IYfcp{p$=G;F*l^3e8KIJQ zCeXQHN8eVZCHRH@u{Pq($CSu4^>PCaSlc)EsY$8J)At3oL2hvSfej6>8Mngk2R~QX z4wm-a_PNi~Tt11E1nk_6v_A{;+V2PmLgAYK7_8qkyLkm7CLWt$*L$Pb+H;ou zU&)SMl*U)N{e(g5vzVwg*8wTy`x2=~=e_qAg`8vJIj+(l>OIGHVBG)2=4pN>i`yB# zkYnoHCkz?Y`Q~#Xb6Viru-Pzg2qcUf_GtzPfB!2eR3Mp%^!Z9|M10O`QLc`g=VHSr zR&0MEcO?ZON35*fDy4_hwi9H&zOHbeZqUKtZ zM*~&9=o&XyJO~N&h0R#ceopH+;?t;UBXSDO4a!G0)#&MAYg_UZ-m-9{NqocOg4nWw$!X z-p<^9Bzof|K|RD7d<)d&8?qg|!*IJ-(R`xMJyFyU`8EmHgjD3*=5Zt;Fhw?dCvU3&(y4ufHTT;{3F zA#|3lb~Y9Xma6UU)WuxSc1uJ!3ki?6u$w7b)TKm(6sqlO0YqxS>_UAEy12KF^rcgl z$kihhD*L#%)iAQ5*dyQ$lHr_fqjSN2b0Q{x2q<$I8zkPqhFUq8LJ@osRVlPvnYO$I zl08X*xS&mAN__ugJj_G(3C2AQ4=5lIw(p7k#Efc5G4cospA5K8gz8SEoEQ4%wp@UE zLD5Kk2`h>`_5)L=^DbdZLQbJmq?8b@y5-DfW(j6HU2BwwZIo}dT7yw}&F=4C2mDU) z9$^G&4e+b3sK(u`P2x)ife{3Kzd+WB?vTTBX-p$3hnL!;Hf9+p!bQC{_2(wHW+Lc{ zb|Zh(bAJVkpO!CZj7*9UH$}g*T;W1pJev(5rNx39j5xWSWffCk4VA4;jusPj_|veac;T@Muu&nHcRT4$>`}k9srrBLT7sC{ZC%#a9QR^ zQlj*iywsm0Y_|l=--;IH*GgzEd~-KNXDZrncS-*i>^yaWUh+|aV$T(OX%YAdToH_7 zRvj!nUCW4ESf?ZrJd3Ki1g$%DjWYm04A)H4AI2huK^kCPp>gR64)@57Q6Fb5k;PfFg!X0yKY|e_j;?Xha5++~|A;<)& zkv{(=Mv=cogTa}!e7AO1)53RJwx1nUIP~PLpB6=J?l$qZ9P^z7;k<@TZs=?eYP2Q6 zho@pNd>g!7$ijM4nLUz0v1#`==!7#s==ZBUl+StJOpgb{)tz;*)1%(dTyXE@XBPqCo|HO%bs3wAJxd&;cvdDFZVC>TQ9o zY*8uEV@DbVL~PG1{X^SZ>-c8H(D;|86wGXRdCwshAWsWytoKkY-21+Oz8mCV0>0%0g_46aEtMj z>h-Z-ufP@X51>$B#xHtGl!7+~??DP`EH;D43h;pB`w=#8Q5W+m=y@P}trcdk+5)>1 zB71HOk_!#8901lj(sjRVE0l|1MKs2JW@{p_)NA&V;^Sb4SwwGEelKWK$27NAUyPHA zQ=mRXC&jKabM@!^0O zG!;hp2Up-xHIo~Bxl3nJO0H99b}~p>uwxzqECJYsg&G2WiC&$;av+?eDOr%@F8Oc1h48tFwV7aj$m6xvo;w0Lb{gf~1!7`rduCN*+n2Eov&o6` z!LK0`aeYK+Lw!L?#QwG5<@=^cTsnDky&e3QB#UN4Ry@^S>w~Zz{T}=DY@k}MPACzb z-@|%Zds+A9B>^GO6+;7#oj1R;V;r-<5Ab*MB(2!w8~V&A4CM9J1Xr{TRJ9Yr2gB=a z&|)!DLHp$+KfZr55&`jf5LT%Qrk~e?s~k5&j5xoQcj@>q;0p=H?8PExoj8$8OqRfd z7BubItH%sPtE~S!ctru`#T$gvPJ2{3(F_K-2{yke}7TlGVT1-yCySTgmZ>YjoW{AhXa0;#GXUlg^M6oIp>1M zN_yS0BN2!+vdS}D_A>U3+4@Y z5+H~3O|Rt{nYs{MuLmrbro0{tY%n~2qK*+#!Nu>+^MliQkY#i?j9;gq97ihU`8AMJ zwDCV;z=;4Cth(vz0(n(o;`4}N9HyZDfsQ&!r0)Qwb)|zf9uhXr987qcBt^$D1P$M% zF#Fa5n~pDX7MI_*==~@C4q1SfD!66Pft`GOt zd-Qh;f&s;oc^%;B?RLUT7W(bEI~2k+aUAq$1G4JhCW;u){Zr5w2l$@@78q zfKKpKxYeXH{Xrp*8rdF!uxCDKfAOPUcn7KrVu(CXf5hP)Ai>FG7l{uehcpxl1S(L9 zp9=n%#7Qw227{EfUy_UUx!Z1G_i_&v-$<{X=n~;*f#ZR6+;p?MP;w`BqQ_JeI)=_0 zc}+CImSPa5FbvD-0N+kLY^Px_C{fcp84FVl%$(E$Hr!a+#K`&&3UlsL3cng(0m?J_ z-Ky=1JiEUzUX{c>%r*!(?sBhR8}-)lp_X6}C=cjeSJ05U?(oyO`pb62A_EDpJGiQf z-cC|fUfYw?bJZ;2N-`Ns3 z1KK%svo=zB=tJ_T0}miIiwEhZoh8&TI_>>T9&tpN*MUXM0>x&|@^=`aHNkH{fZAX( z(1l{iSDGZ?^O>xj4Ysc~T}XeoFHPrc|0~Q|JK>zuB&UEVu)LM()WtRY=spsH65_#V zcsIRA-rBv!?&~n83{1nIOZ9$p2Hs~TP$D;m9Z8V9ba*wyZ^SrT&kf*2wwKsW#?}vg zr+u+yR$UxweZmsAk0Zx~|ICgg{WQ2BzA%&xl|dC?K_i=l zl~)iCZ2yEz4%uTKl!LhP2b3s zi_l*~WC6CBuva6W_@NX=SPFsuJJxN7XM_2L6W(#(Ka9HJDyg4_-FK3!LFKhOPsUe; z{y?M$<8tjiHL%qJ&5d9U(rvb{B(MdcGtEIB2I=3Hv z%zCq$O;*6(ZSS>M$LtB8CaX={7Q;I`1oEj?TJ!Cy$)S%8n$OQQC0AzHI^2l7DUl=3{pf3Y&X&sHZTrDEMd{!){OQJD4DDOnaarlv8{Gx_$p zPb9X!gjONKR%f_83WnG1IjHY;u6mjCpWy8x^ilW;rQhJ)2p=^TRSDJsn_~b`k3KH% zXPE`8?!=z4f|b+*dWpr*j_rKZtw;L)@%u?+gA0^~)`%NZ8q5%ad@SBfNymsdkR9s@ z2z2zj8D{$a59B0;!%7jk)vb_sY!I;R(lx^TXR-CuFY})+IHq( zl6`UR+iM<20G+*~_g&%oySu^mGvm6)mccdKhZURs1YarX#94ce`c+;&ob(=@yM-#A zB4*GOX!+5LbE|+7!oirQA_!%y5uHgK`1CtAJ#t)!(@2Znc$JpPxz&MS%jIQ6 z%ce;a#QFS6aG$&7gEqbDVvl~cv5c0bXCRg7C4I3piVM$;@TL|2if{@M+a<{_99q~!+^qe-3n@0o`#vFFF1#3_eU7op3;6K9)K zNH9Cb>ni%1IkSOsvp)byAKqmxia)yCWCHa!fA|m?C4$N5pLL)rNQj5zDvzV4fs}%d z_=E!T;m4&O-bWA>M}@9Cu?NLg=_uuOG&nYQlh5E})DQf@qJMffx(EBa!qbO!D2<-A z|9o{4gZjwat&ZCJF#;XvD7uXy%v9ULeZ4e$E=Ti#xERD34VL_2=u}&FR$nt_B7l3m z1@-D6#g`GWo*R1?`wV27DXbm%_E$S#6L@iSe&4-O2miy6z3i$l575R3uTHlRTX$>fWPM5Fa46yaB*U!>GTWL3)N#Dz1}qh zF;Y7yjPe^%p_9nf{DcH+`TxUG?1TGc@ zNXxm;X^)u>A>b156S5(fk;RBrIStb!)na%MEUEJ)O825(2SdMpoj3H??WJIz@fZ}g z8fJ52+Js8y_W&JZkfy(;hY5g>#VLVvMLm5C(R|1I`fXbH@fsGMT>gSUEgaM%UK|A) z8BKYdR&_D>bMSWivJ88}z+IAcw}y^Z4oDzR6$~(_$XOpx62W}*(N?)wZMEo79O>um z!!oof2%pf-#(+WX9~K&|8lAl`GvV`rkT8*+0QgDs%UthfWwX#|_KMBJR<&dbog`cP zZmZw0DLSNGh+-N5&GAee6s37lQqfJ4NfAiuXkfL~Xly~k(Qme8EM|O5L2^Earl(+a zb94f?MSm;>SXoG$nbAagyvTS5lY)e2PJZNc%dH|%eYs+*+`=^&YBjd(vf_SM2sS^kiNK2ENbV7h~ z$t*o=LejvClOX6#C+E5 z?}4Td0K+ptrR>e(Ub$7p)Jp!Mb?h; z?^_rZKt3m@a3LHUg;{Vgb^(mFc>Gd4x}YdB#YCxc|w*_(ZyscCJKnM=6mIP+nZ|;X_XIq#abUn9ouL; zDO+U(=%$jYD9z5sV`rn$cnlE17`x?o`-p%Xwwj-o%ZHe>@|9xIa4i0?_qYkJ-iU_r zc+RFjl6(nSWMaBICB&2XH#PmS5BjBh&5Bi7Yi_qJljaU9U)^oCDuCUu)wU}@?-FWO zO{Et@Azb39w5X+*aj{i2$OlM=v$l#YJe6D3!d4%dg@AV;rIN2r;vX&EeIXW~k>HSF z64=$&8Qt?sqBW}{K-x6aCT$b*}Yp1Gv+)IpV#W-i4iLcZ912tQwx1(RU(;eT_j zP$(dGes8b1Rco5?41RA_wlETsd-oa$xDtNMP=0wdqG*bvu}HD`DVthOYBJkvb!%jM zyIeCT5OiLy>=ld6!o$78X1NT+rzENG#V6IMPdFKdsAKW@2`wv#9Q243dvmK;=|iiq zX5!U{Si$P!ip`BGf+YNuQq#heDqWC>FNi^lQ1yMcVOLD=y7jOHnXG(Pl_nIVokhGg z_ES7q6TTTWG=sA(mW-Tyq$cJE@xWT+VWrY55pS-#Rn0+chUo`&2@^nmbFWo(G~x?S zUB$B=33ia$EtAEFx+u2xaLd-rR^e`;k2vst8iY#CsD&oTaTdE-YE|}{hn2!!vxhGha-y+iCAEOMRRQ%e8efvd z@mo#6{Avefs6s(u@Q30!=VP(7Tx{N}o)D2QKwCJk#(gS=j!6dY7`a!x*Mc)nZojPT z;X(obSK?Y!q(zmnYiaCl*P7K657vcPB#V^-XN*J^v(an{EAUFC={vQ`7mU8CwPwRu zGM^Q8quug%%}o$DvGkXwLddIEv_)wqg}X2$Dm1j07gWK1v{@-Mdo60%4B}d~$X4Y6 z2&@=~B$e4{JSEL5fb6BCaoAD_bX9hxK7OdO`apFcgtoUxA-U3tu1J( zYldkNN;(@`obgL?tNCTgF=J_MIpj-cQ!yodlJ6iwX$eAT!?h5PaGPHitr`i!AJ?Ay z8koSCp@l7JxR;jZZ`p2n;T1Ci-}jS$l_ zmMD|v&)0&E2c{1NYf>Vwx{l|C378g|%J-_d)(+-FR>vBfN*0?tvr`-{GAp$)k?W>qVJ z4T@zle27Kh0Yy6V^XwKuxNmHzii6WZC}4h3Xj#?5{`E+=)W6k^;bTsbYV+ta{|ae2PCoQZh&Og%Y&<8CAa5S@BlUF#4{8 z?TBVf?Hv--vnel)++knzQQoFBDs?JPWDq-)6PJd@F>ihi6cf*z@XfxqW=I$aW4SuW?=NFijqyhYU)exhgnnSdkKDI= zHNWDxQ_nDV&Wkcw`dt~sGV?bfHh(%A-@75l}yap zK$QlEhEWk}9};b4dOmH!0fG z0hOA@iFg9a$?7B>*qWXDyb~@`QQ@%-%e^L7>DaI_6ToU59i+EFFOpmJBq1rGke?UU zIt$GXo<>>1#HciZut0G%fU!*96mZ~I9N(!bgmi}{P=%c&cRv-Z5Mg`wI_F@|QyGkR zah3dR9&FlUEA9F5x~K2L+)}0kPgfqJQUMTRrMJICdRuO}=E8y&k*gMc(|+so5zy@A z#z|Cw0ALi2eu|i{+bhGCBDbfD^=!gxMh-g>U<_u*SEDHIp4I%k{qBil*`GZ&T|yAq z#}-*&kFMcm0b`7g5Y{EI4OITqPPT{6$rc5+uu0P4?a{;miDAN&;EjpsBTR3h7d|#) zXjbxWBv*cfmMNHrNw_c|S~T}Z{dOl2s7{EWn6o?_`UTfAZ{XzpwR&i}g>`6T;H^CI z0Fr*Iej~X4^qR-U)Bv9jH)NAW!BUxc)k!v~Fv>m&r7|V_1H$@@sU*AV!`Q_Z8&mIB zM@SxBC|ufML+6apfiuIdPssf?&%C)2$I#9o*2^_KxDz5mx@*o)*Vx)9X+m&a#E_Wq zvtgL6iz5*h{QgMq+srep)u9~1w=;}EJ(j}{Z9w#>^Lc(yf6|d#6ojy52yaW_8(XId z8yf#MLOj$BzT(#(0|0l34OV?AP&BU~GZ;5!?A$GE2|9^BN$K0J!0oms9@`_mP6l_z z)LTgWJOt{Lqo1ExtUY~EncJWguWNx_B?yy;t1^t}0IYfhdam1~KAz6CHKY|MA6rzR zgZY&FgjoV-PMwBs_4bcAnG}{p1^ynDKo*Kqfp7>nN2|T)Mc^!JI?l0?WU5W*NoQGmpdV^Eik~EC3XUs z@R=%W^FLn2D`OOa(;kw*24g?j9Z||{!Sv=dZs*T_xXwD<4;dh#5Y@cEZH~!%jNY?H z!p+Xrh8dT);6GpQXwA+-(9EzFCHP4FPw(0*VGMvOG$QI%Z3ug3z3C=^wVnQPf!lV; zPe`1vK)KqUk-?qmjm#BM)J+@8TKjY-+jyEN!r>&}uJHE9>`oH06>Lp^$D9F@$*%5y z*gMjjll&jUt8H{5?P#!Q@$UZA|5n9g<=4xh;EulG4i;TYz+XX`3l;^XN(Jc&L{j+riVGDOvoU9L?DO8B>E z7G9Bvw`ha>L!6UrgR8&MDx_~#y2OgteqLUOy zz5>Utfu-aBWVu?I$Hftx%$P{nG8S-oxw`a4B!wg0LrbVnjh2YIILNVwb|lXGs?KJ|H9;E`nMF=jD@g^i95+)vVT zpF+w?1ve&n<0{13#zMe6%iFSBX}Bpd05Jm6De77F=ZFAs@p-f_h|92XmH=!`M7d^s z{9o!RVq->!?p-+g5X3-8#a$6l9EdTG@%si0$;*M&47wF5_R6FXgFtjBagre&`sB;x z8etMRqO{;z9^W5c6OXXYYR^?gj+`IFuYwxECwu{m=aSbS{9(E0N<8Ob7z_eT`?s(_ zz9iFmjorm$GK?Aa_CHdxIpfU%1ZXh-v5P>Zm3e04;Nts=mzi4~A$@P9uG<%e>@ypF z9)*Tk#uGj(Ji*}%PNrZ)Fzx;vfsPu+y*%FTe`zAVAb@hj^{9Qh%S3<-H7{uF+R_W>ew$apmBM`9QxBJfWl@R{^5pN9woQCVI4J3JI`3}4L zKd!@nhJ`cE)Fe=N3TH&(p`=Xz-*#5@w8r@TM8h34qsI(VIOU#%>aiC7bOPCJ?r5OC z#O}zbg|Y%5+04Xtv8SB!oKqCcQ8zXV_Z4LUg5pBJ#!kHp2!!<}r zFA0{k@9ra?KD?W3Y}Iv3odLF|JbUrJjNO6}hxn{O9*m((=)>2p!~Lc7Iv)!qY2R8 z*R$k-?Gy)vwhY-PcHEic9yu`;P=E0$5!>nURY`6zAA)A4^+7z@Ht0zi1!g`f@A0$9 zKRxbT=1G^H2JwZk>;%iaJ9zaFhYJSGn9ZP|1TF~3^Ci}{l`y1?zq-|)GkW$lNVyE@ zbz4U15^Rz+M*dw}ZGkjM^AKpF)YCSJ%mgULOj{&w6l1q-2?R(hVs_f%P4-)xy3BK17rP$zVd`%Cb&M?HlB8Tal88$JbX7|vF8fQ>tU@9wf=pz7mvhc{ z&j0-XvhrUIF>YNR-hB;b-EhC-FrQgzUyabOr)80U+U`+EFa+KzA+kNEwe1s29cg@z zzp)UYro!2UBg$=f$|ufSu~XKpoT~o!WJQ|Qm3*(T-J*g^5mNFQRxhTWNCZhB zN1lp)chWb$#@)MS`a3NvM)BKJ?rU4Mp5bgmZS?IK;pFF(K|1Z5Qj$a=IhM##zILlu zhhHM}Po$_g4Kj$hc7VAXw%Kui+J7n4VU|M@sCHI*6rBfg4TE=W7Gy;+Ykf+ z%@6%)kw(`OClj9kmobvv0-X9;k?MAvIeBBI1 z)svk3@5)p0NUnzrOz_~%Pr%3yeFENWs#>n*#o+KKcA?zPf%soq<(A@VeK5Y?oIZWp z^mX!SlRQ+)pNRP<=HtrBApOQ+{ZJ>z#v>y5FSb1-82-3hL?5MpT_stcIqlt6wg6ZR-vjIK z{mjI{RhwrIma?^i>uSZ)inYyJAgYp-9KTu3Hg)?tKUbH{ z*u>a+aeFcyGg`FA?9HpRSj0V`rt?F$Z^R|vNZPm%@m5Qt$+|xhh@FT&wR}2t0W@Vk z44ZzAf(ht9lsjN(6DMO{D`F>?Ynvc4OXLgG#~sT<=p|d4hzMUe**$5Z z<=fhV@gVr0OV~P^c=q!~2eUq+yM7TejCNtODk$WL;iB}$He6IP<-f%wVk?9rK3Ep?!rBEtCq8X z`Y3L5atgEPJDpA^2_HPY7r~n}(g7rHhVNKDLpvVp28>AD5v(*MU&jt}1C{EzRj(`EtvZ>f zaOy>kMVK<8-a1I`ZWq1PLXJ%vJ1lkUonpO{|Im;|#@FiZ_(EhgFNF5ZZrU)tU)uE% z|`ux(WL_I6wj3w{)m96H;Jcpj_;QsO>z?`dbHLTq zay3`9g3IMDMl87A2)$BAKz&v+K#-%fF|Dh+v43dHbu1x5QO_;d8})~EA;&r=`&UG# znRMP^&VTlf9n3G%>{dsnWDdg_h`6rn!q+pe$+N9;&GqJ&KqZg8A+Gf_<;=np+mrEC zo3G!W3#X&gY?1JUk&fw#d$u*|r?NL6o0#xJToFpjF*qh{&%LtMF9Of)_A=GxaxuH! z-LJQ@H7XUw4t7tvXiUcgi|Irn9gENV!lv3I#8o2|pD<0>MI!!1V<2IU_)V&*>G`R2 zd?XZK7zu|)%qTUoM4Y;3XaUh9T|Mb7$DiaW{%k?DP+r@BE}{StaIUyks8kEp;(EEV z-6_-|x$1N{rTVni-QpKDw8d&vz$&<`M^*2pRn3+vg?g(Z+7vS>bLYCt^dv~aKM@OE zkMzWR6aESP;3APd>sy@Wh_$OcSa>0iH$U(U9@Tx1Y-OXnWqE2;iRWCY(4|NiEx+-6 z;9*1Oc!;k=@lJc!FD^&jDJdNF#f=$tH(A zoYK?d2Upcm-4zWl#1`fPi9l%DOkwup3vn2ZF2+)+1fT#j#+aDtba=uHpw~rvzeXWO zdUCst&n{KhikpQ>r2>OWAy>@qSKGy6E8Bilg)OFP?HB4hMW|!;YXwTVnO3D+a$p^m z^8RXZtC%gIrl_{JyA`sM0}=aKsRFgchFWcJZNqwZ3fy-|Ej7dsmyVi|j8i=dM^q#y z^@AHe|8%f1oFBhCF|-#Iqp_0|O3D*tKq>T{fFi=@PQ*@w3W=tpeoSxtbb=X0f6I-L z2rndKG4y&?#A);xXfYBErTyVpd@(`wi&A;|l4-_#ZXZz`gbC6M>jj!@`G*$5f`oZLc8c4@ zEi1R}U@LN^LK(TSo$Wg0Cf`@v1-NR;S*U+D>$M%l)9$tlrTy*NcAZtWR$t2()|?gI z#*x{jLE`QJ^E{#Mj%6b5^w_trJb0}!Hxn9(M~&%-dQw~I+HK1_NMb|D4}Ds+-mv0A zI=lPl*4gz3Xz%`^~0uPJIol>>ZsaPmjS1gns z92GHZM^2*q^> zKcpW|nWl6pJ_n&mM4F!RoxQ8Bw`*(puS%_KiGkRFQAAlU71wIz>L>YDw$tiVHcB~k zCG$ttQLR|6)a-FcH=pH->xJziNSy)$w%yJao>gn>#pU%v_F21Ct8Le+=)8H$ok8W? ztQ`srPK22m3;{EiX8I;5?@~k!4a8#HW*}xDT$KA_EmtTNcb-u_EpAn)T^A9*ENz$S zwJxVoVZ^4*^u=&|Af7@ub3Qg5PNk>fiBNhTI7>VY2xgk=hIl1CGT@KKqG7)oi^U^8 zsu!!Z%J+rJPVte0+$pp=wR*ixUv#@(bL%~Ekv}ZlMINyXt>oMU+btB0fifBpKcD^A zsC$Z%{%IpIKamK>=9BRh;~k#hzN2PD(!CG$mciT>VFs-k`Ls!o{?$=1E>At%;x*)HP%QCf~}O$ElC>L&Q2rdD3+`l1_~< zzzd-PLy8##@igJ=!0_Y0&bximC2>+8newL%5;j6kK3%n6)TLHk*~&kw)pF&+2Jw11 zYaLNP(yA8MxjyH|DG$bD>GWbe!KI=`nib>=geIb{w5eCb^A)Z?}v2O-p%%Rp}P(zOwYA4I5@^AfCW2`9V7fcdB#T zfz(_AlqXIHK@CpM`lbMEk+;eZ6}!tnkCml;;q6MVm%b@=?i63t+STm$?b?PdkjM#- zA6!#@)*IL9y%EqQDxY+p*`2EB?#0D>nk~1a^Lz7>6rY%fX<=Z%G@`M04Relk)B}B| z3$e%eA5r)Ii}iZ0?%5s67_Z--3SUozCdRF+x->uFlVq{oP;%9+LYBxm;N80lMzp*G z3rVdFBV*v1g<4*6H>Fy$9npDIwd9iv@sXJCQY-!IBEKZFAJBS?(Aj&`L#C>`ukS56YYs&Hn(*Y4Ui57* z`r@qGR5E@!D6R_dS!^iDADT%TCb4y=oh{y!-q=Q8W5gK1>sEWcc|B)+58S4k&A9(} zp+29jp8ds{dsIAwjtbNiw6B)0b1bg^Sof)}vn$iyTlGN$ab8;Y&MxQEkkDQq;;>4A z)i$TkuJ@pqunw$2-wvxe^_Dbrn_^E~Y0T)IZlNBCgvS0BLdj+l@YM0~(txhnDbM}u z<2hH%yKMt@vvu*L9QIfXjHekG`ckEcV~*e1;a36bRJVS?>3#BXKrh-UzVumUxK$BvAN6o=ah|M%hGcLXwE%yT?5Bow$JIM;|B0*s44`G z+!pSO&n%;z_fw>Hz4Ph7>)Svx{c0A{V-D}_IBMbWA*)QxAmDtEbJ3%5m@7s}IUx`)h(@Ht<0>yS45ld(TMvd<{Mv~5bSVl`7 z*?4_N(xsI5r?);8QtSntRetZ|rS@^q+_oW241aNOc3J2WvgjH8CJEWW@r{7z{>84W z*Esm>^dOFsbWc6AwTdNqa>Vf2hJ)5wE>ba&KAuNM=Rt;F90~8*I)grQIt^Cau=nKU@z!rY0EcR5R&_QbNVh z9^Z0JA$Kiyr`6`1@N0+;4)tDrL}P7Z8g!)EM0u}o+b2?iS{B@mDX3&)8XO*N5iCoHkyqEne)AG%V1t-SGT z%a6KCq`h$x+{#pc-KC4SjSjpZPs-iEoER9pB}LU*De%IMY*}hIL2tc|4+W`x?ju;P zs6N4SpVQU zt%Iu^a9oiNCNie<&TAq%aE+QyOtGKm0})TLnf%I{9tUrJVnN$-f_zfaMu9rGTK64V zv4;}fv+eu>hg--7;SWK#IJ5|U-}HexiFB(Ero_c3mZ^1i=lb)SoQ8_esn=1(79?$D zu;5aA?|LvR#o!f%lg>;#nfgwyvur2E)&|EmjstgrBr~OQ-bj1NL&$REtLiQUCB_cj z59LSp_{z0l9xRYbb0Up7P$DOubCwc{u`qNmptla71WxFle6+HAB?@7z!m-lwf%5a_&(VYTFrQW_S+2XU zf|2m>ldE#FBP;9O#=Mqu#~xYH%G7yB8l?vPQdbwn-zEZ{(8qHrsRigrT&y zNfZZyd1d$P*R$R5>pxwrxl;y3`Tn1-QPZ(Vp3QdT*S6JdEH4@37iAmjY53*jkoOZ8 z7>NiB6|Q%_T`C+yd8pWPHs^;|ekB2QGk4d47Md`Uwr#MkiSh4i6jt7Y{&$!@OOCE2 z$us_^rB1f~Ybz?)9s7Hiodk4FItP}RT;{sO(b&7z7~UQF*AFT-`I5{6dHu#mD&}MU zndP$sHX@B{{bi)snpf4F1WuQ_h5;;E(n}|!hq=)R@SWjx zvI`bEfXxL~11xX%NudPu*NuG({nUZ+TVxz9pR(1wDr(jUye?33VF>*HlpoP}m>pcu zSuC7WuU2=br15`U&=THH+@=cDBBl0D`A$a^l2jizFG3^+&OpgNK!gb^tUSJIQ?~Bb z8w+I5gy$C2Xs;AyWo1D3tU=Tc7oW|eyvqh`TZk!{E{{ja^!Ps zItsa4J`Cu~JSw?^Yizj6wk#&jW@-6XYrcn{%0|^aS7{g`^^hhF$*0|s-xYuS*FQVR zeC3{JJE*P?(1i{x0MjD0vp$~&h56g*6l}0swXo#?VzZzg#X~N|AMag2Wj9EJ1zx{dtV^Lq9gu6T zRxNIl;5FkU(gzkGZB({?zG0dMLe??3(!W4{d8d}49hkP`7}y$Tk7F|MiI8mXG8PGjif%4)XgjL0{L zlV_b+O7fd#B0Uj1%sEHmEerT9(KhMA5Zx!M)=YwDfu)I0Q16jLn}`R0U9@B#XCLhH z_9$~Q$p|75>UQ{Xk4SLwBznzmmtTAXktp=d-OVBt@qX$!bv)A-B_S{Bo7TygpS2@j zq4E-&VCW6CesTdeE5H|tAa|LwLu~W!%1}q#*{W4blA&V%pkM9&m@P8t-Ol$}>q1n7 z#%yg=;E@Lb6sZF zCmb6MFy1+a7q<$|#nsM!PEJ9b|6{Qv0x5N?tbR}Mywl(;66dNN+&BfJMBEIg5vw=C zi?pee>x%^8e=LEn z#N=4Y&0J$9<|8uz9&{l-VaN;g?x=!1PjNI3&#u8yur?Se*xt{x?2l}575I6r>O4xZ zSSmoMPj<-;EOJ+cTo+rXl*K=7mH>Q~DS*X2Irrt5a9s~g>+)=>t^8Gt*q#AA(mmX3juV%tqkG z*?IN8n{3qL9cQtSHrsN}^tD>I{RI?lk|AF}lzgj}Ei0?FD*IWhR{pk#yC|JV`Dfrq zUZltpcM|tHAr?jjR}&)iRAKTbJFg2Ysy`7ow1*`e1E)i??+&v7MQhCx)U8&F#ns~e zTAfk}vs(O3maky6spjm57$Lqz^6eY;fInF8Y`@2B#!fr-fNWZ5W+5s~$DI8j2IjFI ze7(T?5cDnRUDu5m)tYbM`d+U(TZ&DKtya68y7wkY6=FfI&PpNyQgn927Sqo^rLmw@ z^B2GY>e4w3=8P_6d zqWpXv=hRuv&*(K*iujsGy@cxkLV1}WgtVySS+=!(XVxv>VV0s-!+cVdr%ej>@E$Aq z(>Pp+L9a*UMe@NIa(_&mbXJhhyIxrf8mTyvACIo#I&%rLlaH4xV4s_iD`j(Av?Fd5Nv*ka~xp?SvkJY z(3gV=Opo6%wF2?a|AsBDcWO^@<3io46)*y|O)gQ~%JFS1-2OLCIO0TDg=~$^L=c|? zm*a1zW2Z6nAt!epGkjs5fU+GlHMo2IZ^%ei{D!|?6kJXB%> ztZzwl>S83lkT%ot#08vQ)Xy+R{d#vaZL%wk_9oqgRerFrRw_ExGW`)NO-?K%oRni| zF>UY+X^LyE8}WsgvuTx#H%X@*&i6K*lLPNtf56X)Lox0q(GS*S6h3tr}%jHUA!aT3pt8{#vinTh}L zgFF~N{qh>lC+Ee4$&%qyD3PLI;=GUZJD3gJ9F~dR32s3BO_r1*H_z>`7`L2xs*pI$T_3(a?t3lS}PJh7j5lXfo>;f!U!{p7}=dty^<}g5;R#-DCPf;&Ykld{B;J0 z`V;}Svg5P`<82F$VCyBOi5J->YF8Q|@|a-RF_a00&iOt5F>s5{HyPBI-{VDRe0haG z4w=0(;4fcd-1!@K!Y~GV8h;JsUNXsGQYj-8uMb{vE}japXK+-`jKy&9LV7Pv09)I! zE~GhBNFnqI3_R+iVquj*#ldOcID?rbh9toKX02#*upxr*$4qUL@!#1hF>q`GXSAIU zj3fiZFz#%<99v#xRN2K0EOW(0`QH{1OjkIVqv|(K^u)r;)}P`-_~H)6h0nz`PzlZn zM0kfhzpz>)o00%1;tT?3B*(8WviMb| zOEUHgL%Nz?iM6uYJa(vy(U*qCW*5v;9J-g2xb%zu?NOT}pBYV~%`6}8QW%Z$OAC1QaatZS_! zFA&5|aGY}t@3gc2|Nqs`U^@HC**1)C%ru#+0e;ks>*U5&$YY)r@2oj@RNNsh#AUHV ztA!%&iQaMI)Hs2J=?h-{<)LSLz8_%oCRg-L;}>i66Q9w!~r)d=^{sg*gO zdY1x%)fFEh(77+qZi8NR&nl{CCG0DX4n4R^ipoOOwI4w(p$o73l?IslNIg&k@oY%G zA0joLYw{FXv;4@|Jy~=w4*gOdwT}nowxurM1B!dr4h{NJ|;;*uoT_fuU*ov?tA2MfUcbY5rM$ME&V4 z0Q>UL*O5nVEdz_!@cr`}gOu8l?3jApQmhmdFH`mIkvuQ@R8z?P+tK02v*A~)5hass z$%f>CdHLWJYG9MIP(B7U$$LB59aUE%wL#^<`}q+M?Mnj=mNcojp1bK_)VfAQEp3br zugH)oTT12wyFEa=gU9vOeTRVxlDvPR6@tR#{W%zBRAcSf@VBX!2)dSNJ@+Z)2_+xU zwbnLb08?OlErMU7-;rHz~R3E)>3#!Q64>+u08M=Hq*B zeQLscWVxlzo}Q^ASP4<>@ckQ|JOmc{vGHv;1(*t`ctn=}S$f}!uJvkp7et5o`7`(I z(D{N}ef(Fqef3FiCg5+^&ylHZoz!aT4-3e%_!Ll=kqs%{SCGg5`z#W;<13-f6WRl# zT~{V)t{06MS{CnYbF#_|M6~Y^T7Y0m+>iF#Cdhv+lh(HL&E)OHS1IP_C1qP&>bIAM z_w?H!p%HRjnLm^19P6`2)clf~KW|G);Du{;TN<}~zTmB%=&QDVKknV|17ka>wF6$V zi>^?wvNECn#-3MKaB411NY8EDoB3-}mZ$!u&zjfrrO7wSu=~s?w0HzvSs@HYcJX0P$yP_-7`(>D?eFbPMUHvXywLv=leyZBj zpP%b*lKOq~Hrzs%DbQeC>4i9_&29O&1|u5-{Z^EQGhOoB6W$Y%`rx5GTa_d5#aMk} zNo!l-Q<*`fYa9mNcre?Bg2zW+-zzIL*2JE70)A)|p4#({#OG`=uOr%}t=D!hMW3l! zadau~Lprlp7y4b%JwXP3s~$+U|2TJKY26X2Lt9dh)D!%A9FqSoja^9?-uA{maUtnI zrwp7jeb$_A!JsR;r1te~Y1+?0LLEiyzEthLt^PdpkCD}5!h!?+{7R(mh*6W00Vz`6 z{itQn!QFgU1YE|EeSVwf>KXQo@>r?5)xm! z#r^7Z%U(r_N{6=X_x|c&YUj9?mxeLOSG}@kJ2?El zeGvmTF#2l89B#}*-)I=)w~z5tvhmMI#M35iOFKw$1UvLd1j~!VUq{wxLUl*A?=6?q zkw5h0(|W$WB0pJ)2SL*_8Y7Y)==`Bfy9C{_;MiaJFQz(uLpE-tE$wC4BT8YUOg*w>7#{Mu2AkIBToj=@ruX2jOS=5xr$YwP;Wi*1iDvABLEy zBUL9)t;kTkd3mA_d)zoFb&Ee=RUFAn z%Rinwh$7nZ!I4|NZAwxbHFt=kU{3D0k12UKjCjC>yA#TnE+gY{iHN5?auE^jq(|+~!=kn1ZA43{(eL0n>9Kpk79V^5wR z`fSj8y3|7xEUq3~~;&*W&INZNLD{K4?wFZD^fh*SpqcauVa z=z5!WY4dPbGZ|%^-l>mI2sEa#D+AR(&7#OSK}UK?-gEeLQcX_}jH3 z>xole_Q2?^wPe#yymCK6rm6gMQu9?l9n=ru;G9x+gTEi!V7+5ryeGzUA=*FSci(m? zjf*^D`yg67qS1G6c3ajC-nlJwO>7JVD+9wTZtu^3or%9-6&c;`#-fsmZo5@gG9S8w zw*$}&NNvgUnEt#EJks#NY|bt0*&0D#{HXH>=#oCru}`5j*Y`yjBT{fHxQuAGp*@KFF!rfC`pl(utk`qJ)`f=Xc_Y~qy!T*2 z+h|6b!P^o|;Un7m$na;dKDu1SSJG1H0M!5wU2&)Tn;^3zTAyn?@3h4bjLcRf@JQjm z*iIpI@ViLyoO++yU!NUAWZw7GI_Z_i@@Un#$MV;o{FbHUQ#eJ&o;(hg&6Kt*yuBZ& zrTkT|q+6lF@%~1F{)4d$WP4LjT@e7@9d%HYkEzt;xtipAZTsLF zTViK)temJGyt%uSajBW}>=EOr(~KDd4}X_b0Fm4x@|JyXeF9CIOUwJTG6FQx`4yk< zNVw>i6s=?8Gx>Z`3NW64U6OSX+5Pj~S&6gl`ib$bufKXc4#l~wbO+94#Mu37PJft0 zCJECU=oz}b-^=i+-=4`Q3GUo~lc(C-gA8miZ>8V39UmgoL5w}}=l2HnZE;peUAk(; zTreLY8U9Pi6=5xaK-P->+MV2h(v&OL5p;!gqY*mwsqCXO_7TeEFq^mO4f9f`b-}j@%V9JZICLRT<&j>0 zJi7tE;%td#GGFz?|7@d;;dhDL<5T}nq^N|}PHUYWdVp6*&|PyT&!@+pXY`2n>|j>S zBPY~8_g9&QZ?Nydd}r^i-0@)3vwNQNQ}`9Iz89&`1oIyRGp9jh*bDtu$Mr$=4+i18 zzfaaO(KGh*{~FE7=SzP7(26t*vGh|4?(ihMo_X6_x96hm!XJ|NWX(K6d&Dn!|Nded z!inc#sRSq9K}CM&6B$(v`sa7a;fcKWc6!L3+81wGQ^uR0xO9&_KXiYo>qwye*LOC= zRCnx?3H7&;&zeHk>PPt--b|_witG+#{P~Hh8ybkA+Y>a3j=OwgpGc~G4e!($sfZq5 zHPA24Z%@Lks_ZV68zHYP>AA-r?Kg>{U^UXM|Fkma%|ZTF?}e0G79qy^nJ_ec%jI3^ zCFRm>$ZWuxE7=Oakj}!BQMLz9-8(MYd$YzP!D+QkV1HGs*a2INfC_WLtvGPLJn@8# z_u`>_-u87}Z)6ZOOLhky61@0n#c97c`~Yr)&>^Pg`m??BC@bAxP*)`3uhOu0=2vdB zV_PGA4HHV^`at#Pv!8`LKg>GV2@BeqdXIkF=-)%s4sgEfP_SD_T`HsF`O~z%dLLh` zHlk0l3#d6Ny=U_3w;%LL$-1qBG07O~|M69Ow%a(HiEuJ~kSx32*>L+>cEp9WMd3s+ zpX@Zx{PwTwqcn$lWRXd=K>jY}T(foY0Anz|H~e*?ZHtwdBL9cx2b*rNRKfgTeLM9O zMp3sDa_in6B~QS_-j4{YJgVep>phA!K>K4)a-*q1N@`z9F7Y{HMt$ zy|eJ+cA4}zUG-6@@^eqTbX zHlF`*QFX-zl4Aa_LA$H0?OP#zVv4X{JS|Iy<$&oe!*=q@T6LRa%{t4o=6d5E7<15n z$;YsG&y%O|Pj!0du*s-WN34^+(-cvnZL5-bSI_%(sc%Czg2jV3?@iLGj5(nlXi6M9 zN=x3GdC+LpY+>(WD5Am&Sdxz(f6yWQu6#L3w`9xGs8;yKzi6aDgq_x#7opcN-_tv? zZ(#ht-O%bBRS?NhP7iILX8F}Ro2YtU5@m9(Vsds3Iqxpef|0RXwx>Qa&d}Jwm1yA7 zVZF5>QE2TVx*fdhibwW$7dYLbeW-Lh`5V!8>BLo){ye2Ip1B^}#S70v93-CRFPOsA z%64nDG#XdRrcd8G7TM`a^cw5-jp4PL<$ty8qfPbojnOF)(rUHRapl3qN;C3!XO3wcS)2X70Z z{~uPg;u`zmDvc(YDbOm`Ji-2Pqbp8FRpGV5iSe6s0x`(?#}>p03V`8mu@SR9f1KLN zm3vYi$l!`l-2-iCECj98xfm?|u7%+>*EMoOT`3T`W4nC9_3!RlYTcb&Z;(V2V!u2Y zS5b4%QDAYP~U~5tI53K7dUsCxxO;!{0wa zb7(?A5f*-c9V{u@&Mxb&>< z2eDA7Sk%?*fhlOoU{`3DI_^22w!E9B`_<<;_(&@fxvdwK&+-v&Bd7 z53l9i^T?*e2Ir0>r?xr$Y8iAj&7(g5(7o>Nha?tS$VslF$zFc>RVe^W?V+9aF)TKn z0;5s7BWF0t!geMlf*)^C(3F)g&_ye;50%y3=z4Ezc%8f=HA3IhY)QVRSBkxn#&s5{ z=)zD1JyFm)jmr|T!(HSd640F}?zzJvBs;2WX^nKAuT|@0%=RCr9$AZ1?UE}}IYB8= zih4m|Q@YWXAM=Von7=W+&1f0On2g^G(-)=oq{r{daqUFBe|um!C!3yIa`ecG3AVBN zhh!-XqfUN7xoIr~ORoOyK(v*UQD4xJj&LW7%}5}*X^%vT?u*{dJS?<<;axbN`?m+t z)l7Cqr#wgn-eZT^KCd;eki&9R(b51g_?P}-oFE|zhrgAhxL!kG9S=X5_ z>XYZQgAthAL7`eOmU!h?t+Y39R`N$oz!RIgIBX`C*8AH1i(-0scdlwtb(jaWxlY-**SgfOFG0T3>x@-8S zYu>D!1QkwfXt@DCiq7ukp>>|=8UV%#y|@RCq%n5)7!Y&{`nK_+IoEbw6j^Igt97Bc z9v%8Jpj8?v1;GPR?42s?rM!jRYaRdyz&+|cX&ybT=7eTN!>4Y#lC^;67AoE)D_B0A z2(C#}kdsFD0XI`>S=+lloD)$|$;XcBt=*-rBo-q)lRT1+KPiWT_CN|`s9tDZ?BFS1 z%Uq%@g1rqJLje9cC>!Ga%Y^1tc?xvp3+treg{%0HHKGGG6k-}Kd2fC)rj*`x3|z6; zJ4c2Es+>Z#c}2?%0-y|mlXp~Hy|>(Y4o|k$8?7|b^p!@|WuN$8+rgv%_R1HJuRbf5 z!!W4^?HP*LC2&XT_teL`>Q>#>HmN!ndgs-~v<{|Ys`0 zqgvgM%TD=*Z&Er>8{SWZyr2ui`jnrvz;ghCnjcYs0{~|_ zWcgj+{?FG9zLu|~V*{5a(gvt5pU)JcV$t;fqf?g4Qt#avAu;g2c5y*&{J zfD&a{X@lIg2^34)L1T%@0ktuz=LY+4v7|(p+1;m6{~4UHIRc4+C|EnmsPxW@fs~lw zS%gy%=JRA)XV22bxd~8+Z9z4)ny15WGOnx@oEq&G=m?;13e`VV{xC|=xldnDZZPEo zWh27#<}`>tfPrYnAK{<2L2dvClfk%k_wP`bq$W%iihIJzz4sC+Q>iP<&aS^sOIRWv z25AQ($OKiT?r%9GM#<1Y8A5peNP#iFJC1L%yB%y0u?U_P1)uv|-_3yX{&Kr;&0U~9V7Rm$#Q6yO7l zy^3V*Z>z4PPE6XJtOo&Q<5>O|9v<-{59e27)pZFZJnAc!yv`=ZuRfBoT8tD5TF>y(-tUJ0{mbR z)d_vj2qM=$$*h2&#sv>2w^Z0BDmbF}gre73eKct&+VDkS%BX zhZ#!1EShwh9WC0cU;=8kvbj@avF)$fR43DEow9Hi^a0O&+yT0nFHijwG3BwdR;Eq= z1vX#EG=p2KtDyNt7+~Ju__PsP;EjF4eVxiMT<_UccE9)YH9%G@o+?jNt1k0Qbo-Su(wVZcP)|!k=omT!G%@EAhDAUgJg@SHK#w zj=fvoP*4V}g2n3AO5NXNsl`%s&js}2{#Sf$4KnrEIu?>r6Rr=LAYT~xAqx_7QZ0AN zA#d*gUVgcMLV!5w4Ywo#NrU{6vt7D_DI^;K{&c`Ou#D3{N&yzzBH;M$0P7u-A^DtH zh=)>Y=PNpY*}uga7@cmdxCMgbiql|A1)l?bFgMDmEu_HdQj3xRKLLVfGpVZ%hQu+N z;2!{)V7UZvpc*GLRt~RQAF+d-(FVgaKfQZ&+3JHcP@j4a_#BJpNGYb{rIj6~2(5#9mpeVKz8ufhQeEbId6=S)GDI zl{R=e1v5pqfj_2MU%8oOwz?qF0hJVN+!}NRKuFo{7*V>{6EW#MEEU#lU;xo_z!q(CSraDXmk;Pt21BN$Xb2$Mx1ep@jsCFA7O5V>$(F$0w@8_8*pkO z`jpMBl%%7z0x+`bGB5@-&*+)c|AS>P!NsI3fQp;{WRY`)=a9TddAny|aeMFsw$F_8oqLF|HBt zoxG3+?E|zIG-B=1rn3SVk{X`Z!hQ{=@Ep2*?&V_?cH{l{cPsE3{dt~c3oIpGC#0!=oU8=%=8%!O6~+it%dcL);%=hw`Ym>&2LBvCvD zOi)Os?&kFowstz&abGrZ_v58=z_4Te>(cn=*mj|Izp2uK+}?ItYtmwNNLN;a|r+?<4_aFkftnPz(wZon237Vr*oQ z-=gg3x}jI{BSDC70S^UB-G63PuCX>9x5(Us>c_H*jvbCNGjY6Y9N1Whjp=kQEz;Y{ zW}DWFKzUi0#fJVHaA4KFYf4Fu{z&4mJn5i7d}dmwT?n&77lrR>ISl%9zLf(~S*img zf_4SOY)Z*r!9k!q)JPb?aT<8n~@1~_j0*WjF-V8JnBSTJkELGXarVUhA2 zG0&Q<{GD?ZKcSYg-pQg6EZU#vWID+>qr2koPV0nLLVi2JvSlZwhnI`BAAwr|N@C7% zE9#GqL#q`S#1a>A;0IeABA&x(tF`L7g&OS0G#LZIES$M%Nx|=N25ZFv zxWkHLqnQA_w5?W(b)w8TfJJNaB?t|pVuXk${knZ6+94b$6ai2Hj^XLD_y&&Afe*3Q z;TeJvX8~$~%WOzC8Y>}gQc6e%tE(9OPO|NMgbSH6+?!trC+FL`teP6I{jD#90A}pmU{M=MK1F7QqgqRaY?{w2*|S)3FgY zvV$}tyR*F49XLT!hp6bHTra15s*P0Y}_ zKv=dA^-lv3BRIfHdDp?Y)2~9eU_7qxgIo11J4065ak@D=I1vf_r5RlQ!!~YQ!}cCpw=9U(wse zoGV#+@^QUe+aZAA-H2rhSC-s@I|J(GT03_t5|Afk9TU8uLC$VU;%9<)NgTPe(bjsnJQ+;{6h3reG zf?av}6feE^OLS;9TXj~k^FvzzcCpP)l=1Q<=L07t=YxZ1b6()O&LB8r!XG~KeP?u? zPtIUD_)n7Y1?%M`m&KdATZ_F>uC>XK+43XYRmE z>ymSFZU2f3aXa7)IqdSaGfhkvZ->kUa8uy_F@gTUJohEVLi1wA2yir||7VqBlBh{> z+WF$+1x`%ig_kxEuzeDn12{7sAs!D!dm@xw|4a88T8}?m)bh=X{qlK2jL;Bi$gF#U zG7{v}YU7%k0aJ07q|a{DHTz4KTKaj(Lf}{J{p+udHk!SfrUD00{o~!viD3(1(P@S6 zAwd)Q4dsNq$4vpLOxRED`n^-P$ts8e2Wx=3NUtvSXTm-YX{_d~sP%}ZaxNm&hW-Ky zZRz!&KB$c-kI#P#Z}5>k^ey-msKS*8*E+7hToK;7Xuc}{MJC>7>q=hSb7%@O@}X;~ z1)aJ&pgcai5~a~s;xXRJEWys#qpXDbclC^{TW9X}L{R5sndo0JQ|6ZoW|pCVR#{sl)Zmy#QJF2?Wc_3*3qRHxH0 z+O^Bx6*aT?N`6ZDot_`t2oK*+LKcl~ru)tORdT$lOM7%u@2Ik-Ony+`i}u+gG}6$f z2$*BU+xyP8fv6j8!?(dwtb^QSoCke7wr+_L&u5ZeaOwNDJ)-5${L-zj!=c|y-g0Zj z5W0Fmgj%D2ftIA@{g<)Zk;=gmi#?M+rc=gi11z%MSs^cO%f((jYx$q=CDnR($l}*N z>6xNb~n*7fkvx$yzzd{r@4d0I%MTtSMpxt)QWvVfdTM#!{08*9}KMsK$$}spD%Jt zx~dEL(3+F9&gs}rudgFQ$-?M(CJak3HL>H06>X2S|JA5SVLchJE3-KXSX_pi+Ki%8zscdO0W4WTvP z*o~B>?Az*Y|ASdYQx9HgzG)>p(yPam-P!UnrkT=IC-BHMYmFQ>A~w{*!EeuRj}GTK zO?u?W%Al|!^|xEQv-N4h!9Go7S-d*4;NuNvHZgAIryMX z**0QNLhjz3Mvk|=H|CzL_=7*pW&-`LWKj;aYJW&p^K*sf+03PfR;(tyPUCq~WR%Aj z52YYjg+1+?gQa?-Uq1EVeQWNaodj}eN4^K%r*?M@=~qqQ5+HYW zo$G@QB5*cOHLo!G{)Su4lQ8sdA6M=#X?fw&cTO;p{l_$+9m-2J*Qp}^lPP%=jX`UNiQ6x zCt*gZ3E;-)@6YSoFmJme59aD}R0{rl zHTan;b|kZJw@>=35;5!Zy;-lU3@VMK0{M}DYlZt=Z^CSGaOSq&lHbouOx_Q#{c!D& z6@XTPD*`75sah= zbq`_V@l4=M&J}E)x;^LV(OT$$w)T=160vsZ>}Ne5D;$sftz>o>Pv3JfM_pL8V!`Iv zC!tr^e@3AvmPPMfs57jHs>Kd%i@yB4 z*GjV5e4^Y7Q^-`&5ob|FVDfzntDhRqPk~98qxGv#B*q`4ll{$f1@I@EJnVJr?SlL2 zGXWDwyXW->QxHc_{bo15vp0t#aL(_ML_Q6Gv*x@9ntRHp(nU2dATY2}Li;lB7ByeL zG}qs;MuyiAEGfsSq1(nIS?hFrBgIm}_&?pl8PK%UIpjIvz1=wxIaI;`q>Lj=n%&jQ zHf173WG2Z?g`QXt(s%z572W>gyTFyyFlNf*#};T(RN1r_yni2-b|mP3Ph~E8f9r?~ z2qI_cSEyKakOxuZD}WzrsycACi`Db~c4_#FpJUlS1c7|!0_H!nn0JvGoo06xlkw{yJx8YRuO=^JbYVHMYJN4nGwWUeg*{g)Q)>@ zHx2osvRUIA_)nh1>+%vW|@RnJ(ACVA~58B(WLwyn!gFOG~rz_J-D`| znylsBM?KI%v_@aEfOSWNDRQb0-sJVcSGyq}u2}bUF}X{k>#_Uoi%x}wiv6MMtzUxW z!F2{+vrO>nd%!OBZTsi5nO>2x-7=buC8FflOUqK^vmV9u`aLjD4v5O|KA4Dc>HdtI z+)ZjSR9T?ARk(qH!GW87X45^Rj-Jo_e;mDAa2r>i=6Ny`ASDucK>`%Ft3)6Z0L9(1 zMI;iSIMZd5xKQ@PPFWx+SHJ9zd2#RT%XW*Bs=RMqj~&&e%f`M;M7Je&?8`=%MZ!BT zGi?zBT^q5sMF2_Kvn!FfBuH1aL;{HfC|6S?khvc!>J}x*6p1`}&j0-X-}n2vdaTdeCm_(L-oTp~VCZ)J9=RB|npgRhbHSV)vt(y}m|5*IBbl<_}+{7bs zkiyv4AUG?W#9fq&#AWv6XRF*{9O5oDIL5728J1olf{GaLiIFFE!1J;tIpX^cb~j-K zj}7GPm?8{{W|I5Ipo`E#)v+*WUqJ$qfSj8^r-t&iXbdNSkJwV`qvQBX11^gW9qXRZ zo0iPcL|CU3(j5zbH~YM;6iBSok{gFp%ulywc^xt2&xQdEo!XjSo%63E0|qVtt1_uP z2Chm{>{ohZU%%b0C0LU^xh3#L&s6)Z%yr*Z=IsM>naA%9I_Ue5UpaF#>yYa`_$c<0Q$W~fRp6L{f2w>moHwuA~egaH*M)c*p zPz--%G8ET>Ksm}i!ly09w|AtDSEZk~r}7@?nhnl|=1p0hWe;z?fNY6Ma2Dl%Os|X^ znCwrmjBwB6UyZPM0FV!J!hgoO5#-Rq+=G*tBy{SW1ZUsq2+>j@6LBj?MlAjY>LAFC zv69_qUf-{Xq(@|#`r0<%BMoPVzOkxuxoLy8uY}iH$cIqMP+kFL({zsOQTFwKIqO0+ z?SHFZ;vn3m{0B%;rHJtQV#z6p;m3qQP}Svwg>6Qm!x@lwpdJP_#R*a0$OAZI@V3X; z=BQ-)8vj62E-h`3B63XjhU8u#aK8d`Y!Kxz}oQC0E4g&jsufQ$>mfNaoS|l)FzGGeytkNaH z7-DyB2{{XaFbJI!24PNEeSJrZ(?5GCZtyTw5}#fcXiCp|1a ziCyFodE?vlyI*Kw6 z5LMw#r>m88OKbGihtTkczfEqR#2c+MM!`mo`&{G|5pn@Cq~zSJ``7~FIK1BHBI7$L zu75luun_J6K1xZSFEBr<&_WRSEqCN^b%o53%(NEZ3I}sQfF3!xA~jyt{sQ2dB?8C@ z;&O4v@tYq2sYYGRk&aV(YK?j0AFlhREx;AWE@zrnWv|nRtxf zRPtEE4kwW|X}>&)SDbznGl0oSYtZS%kR5UCn0ibpJ5kr};!6mh(ZLLG@M`U(*)ho& z6E@vYhjtn6b-F=Dc3l4w&w72|0R!eC)sV>j24613!CFM9#1{lbH|#FdN~ay!_wbu! zLOD0(GeT2bd)DGww_rJRbM(K_r0Plf6sCfXJ_9e5pxY&!V!D8Cu?Gkt5A+k>3*ROx zuuwP!cV}}LGH`v!hlR0@vmziA^w9VkJzbPXFCra$j2I!3`>hz>yig+VvNTq`SeKk8aT?`2{Tb&%- zT_jD$U-byBTOAWtvov*em4TXKX(Wf>E8$o>{{6`R=7z-~Clo@glg)b1Au-0bO6s04 zlZNW%?{Kj-k-asbW1onlTflERRDacw^zq-e7qs5paG0z8yPQKjw`nBJN)UyXiIZ(b zsH^{&f({VbnG`cS$#2EG#Cq(Ea5;jlj^=Zt=Y%{!!75waX7sWqi4-a1Kau#cbkclZWu(w^+*(btHT}b%nfxYn6%UYlM%1I8?NC7| zHuds9DX5HV{@2O_XgPzhAqZs9DU`v34IoLI39pZFdcx(EGH$GJ!ee@6w8kHf3I!w_ z1By*>G`X}yr!5`P;U=dq4IqgYw_(P^-KXM^?7%Z(U+e6u>|tE}sun$OhqZWiNXjvm z0~zNCLVSTxL&mS)C<5HJKz3A=4w6NnC1nJDYjz*9vOb7y{dfVY3{a2{eCf2#JB(aUo8@pjwkavwecys<%~ zeI*28jgE(=*8!LDCb-JCD{TMtCV@#)*pW)_L#K!OuTG=C($OV2@94`-R3U+Gj+WWL zZ_UMXSR3?E0+D1$6DkkmkI<1z{>Mz1f(r1)Vfu`cFo!C7=DD5=Pq!xW_J89(>*Y9PF_2sFAN3_TLo`Bm5so54umwf=v_6Q`os**j^bww(BG< zydi3dq~S1=vJPoqgag&(xtt3T=Ate)-uLS=-&R0S`z6-7+j9Zs25#59K63%2aESP; z4gthC#}Wu_v)x|2n9`^^(plgu=^KdQ_arkpj?`Ep0z(f9?b5IvUiqkoXif= z)0@=ziPHY-Rj8;IdoHv_dxqT^|D&u^ryAp+2+U`-754?3CqsNcr^z<pP@%YdaM3#difcqdv9BzIq zb&lOBNKagZ4S~xZECHD*JSLHsa6xzxf)gUEtpE#y)#i|l6fC#ka+2&&xC)PmuNfWR zO?T*b^tARKdl1*$oELA~MHEGZyUw8=XN!{`Ra%mOc2y%JvX9MKHn-%{(1_?jp(k?) z&N#Jc%0+wC{{mNPZG0207a}AsR1sefK`%t%T@<~ZQ%b_rZ@8!Np5!$t->3LtvL4Xp zeY#LI{bL^)r~-ilwUI{I9vv`3xG{1$<-E0somznK5qpkC@mtr_mpci35sjm7HR&K%vdi!P z446q?qxE_73EwR<0$bS3ws*~T1TX0Oc zq4GvQM!1)|izmJd({OPAb!5NgCJHD$Q`$}W3yjl@+}$^=$RJiaLCjSx!I^gdNEY@$ zX1pLHBdIlO>mK2^rV>3poQAPeo36#X`UI5UBts%2pZ6SM7Bh}Zl0#)zX&BL<8~Oc0 z{bcqGcQXc!Hj_SYyvDhp*p~*iE4&UNC;6YrAJ5vSzTdPG=TyQnha%P`rA#CfK45x2 zVO?=;jtW%x+kcx&qAaMA)-pQ8usddeR>r{OpPNBcOZ{@`B+{{Ah%Vlm(?P@^;Gnn(R#;7L$&cjM#^S20aS4#?LoRPmxBRS2D?-?kIv zeCw`|cSKoun5)+#+;$5pSbu>8@Rmeb=Eg>)ACf$1S!rSa^=+YmYawm`&B?@hm5H#L z^bbWR$RJ=x)xi0jM^C6S9N->7B~EVoK!!C-eTllxL#ws54!3Lt9E(i(Sp_ z#l&K6ur}{@X|qQVELT0UzxwgWV+vj)XxD2gexr6BLTLHSOkRM1O@N{uAm;XxYiCY? zhTnIu5Bg?i9^Tk)^-{#5lSex6oq0wjR(+ek#ahH8d(!`;Cj7K63SP6%fHH6}D(}Ao!c&4W|~xT01<+Ea2!7!IGZ9e@1gt&sDt>RKq`jlot^gW=?s z-TVEV=T&pa4b=za<&bvI_$o|1-=4$dCQo~26iR*G6s3ug2gp~!N<}rFWv1>k$~KCp zZGA?uhazX?Vf-SxCm4vVqZ{l%*g## z(0{P(%HxMB?aYTaCjmAMoM|)Y(Na-Y(d*iPIiSD@SrP*u7eYK5zLh1m;sm1h$<7?i z7s|61EDAYheBGmTNoxE_O?7ReayRAf?l15qJaNM-?U||zLGYKNTmjr{Jvf4>)UxTo zW;zRPg?TwM?<-j+w^1WvX_E6QVQ!yRduODIwJbo~bX~AL{5I?&#h`3szk*Ez1HZ^O zIugxAF3S~8-p-^3squ9pdE%7v&wzOk$yU9#%;n$}K;3c=8J~wsM6UyL+KSZSrsRw< zbVgL~_$JM^?}>9{eh?8C`nWAdsc(UBTb3S;4HPximF$h8xw>BrLDD%VQ9FrnnE zC7;7s#9&B^GMJXC%NPHoQA4v37y%QX2Si0u76gI!@vx;QSo0e0c0u85{8bMBnq@Fc zz^p~;{b`K<}joib+iL()1*W%yWLFJCTr@O9uW8k-%&pVmB4 zfWL7Tbj@G-RvFxTvdq={dhaHVpJR@NAZ^W5j_D=bm6E3hRzf{*(G#clRJ|5WsH5e=MZhxzHc*@RV0#NFpp z;~6%qW#5MBP>z`;Tz(XIl%#xxh~u9x@$K6H1xEmDjsp0MF0TYfwdp>uQu7JF{j$nP zpvvnpzRDde3!1V~wP3dhd~yq&2vRqrRHw*DCi{RM(4rk=KXm)&V6{No+RD=K=syR% znwI+Fl~I3@I)Y0C+m=_^aNJmH)RqX7uta2-2YmO*t4d4mU{9I6jlZciA$Z{T=rRj^ zm&uOxKTuacxkV?v0k_J1KX5Qo0BUl*X%g1yYrv(`$o53nZUtd@jyUjOnDRB}k}F?Cs$ z)r2QD6Of3RR6NNGaB{`wXHiE-rD3$mi8UtkZpr=v>ceM1|7s&oOV6sEa;~0l6bvqh z-HO=U8q)6WDB`@=lL~;vpcH=@f;I==Exja-qFfDnQi@cten|aD>ljSpFF{l`^I875 z*{we_bnd8L$yTs;mbFt+RF4G}^ z@Z8?(Da6w7*F2&ikL%9KlqV)aEH|?#U~{^{n%pD!BZTZTqmZu}YnA;*-N38^Feif} zgXYyws}@@kL6#Na5t=s@-*T3-1U)W@h98Q0}+IIn^^01kl!#lu1(1 z#~?Fx2iQ{gshJcf`CRxO_Na2b)2Vjr)z)YbR7GyB**JzWGHdI0_Tc6u5UFZZor|cc zn-TXlk@qNE4SK1`S=F7I6|W^lj|fMKh>S7+25|3-xB!p^*6tKvl+8UuK!U-T3@?;b zaC9_cK;CP`9a2(#R?(f%g#2mL(KA%AQRc&~vl7$pE5+0)zXN4P^P` zUv#aa#u~U%#%Xs8HR$aZWZ)r z`qdm(vO5(b-bG)(IysY^i_mPnv1i(wMt2ioUC0-zY-cOSAeLiT*R`r+$w@Ve9k{1K zRKYgS@Anj60gk}lb#u;hU2$U=I`fwk6OhjF)%~(LXdLwdmhd4WxN^HxuVa2{!coT1 z?}dUvkK(zmE+?Vz^FY099B0cLPs`X>yJBEa!^AM^ZBW~0bYUt*jU`*;feTv|r zZX=IawqpZAx_Tp@&sL$kH$YA-R51InO;`KwwGcc7*lsE>AlutMZd9@ca&tB-r3Un% z@Ra5APa%Lb%7r}xpN>(gLr{5)C#l;^fWD%RUc)DZ5IY1>#k?U8bcM)M>jh^4Njj5E zBoomI{Hv!`OybRrdSg&3L*5t*c>~c|75i2wdJQ7IWGuRbD616ylk5pWlQA`>CPPSQ z3wdM}Ou{*ehTIi@S3s4|>rd+qy1jjQQoN6OO0}&(yWw=KmiwEnrl3%mde(i z)yQ@s9^7c`K@M7e)@UIAYO_*@)Eehxc%$$niyyavM++)osUV)VrVYkl*hI*;84Y5xu6H*m#R1xw^azt!TyoLs(8IY|4Dn9l zxRE)f>R@>o(k+(pzn*#kiNmY~riA+i(}l@fwoW`q64Siw@boG*ZF;QT%Z|4}>DUPaKt&BY15M^) z3$1X!Hs&|6Al`-%yNyz9({XO{uNQD*=+JW_0r9^0Au-93gM6Dd9ImF5<_zxj;9+{B zJ$RTf+7f4~!T)Hvx$mVv_*PpIC=mE>B7@s60^Eo!QYXKSgHg3;(EzXUCUL<9L zEFU7qeb}mF{6nuFWC~1JyWan^73bPQ>mpIgSNyA#$XkTdX3pqagJ7fzkX%?Wx{QB$ zo6U8{dMLD-RB=kV0a{t7!*EX@BBYv73mq^=By;E$29F4r$hVh9es^Ivj@w({!naeI zkW7tiW93YK0L3Uhz8dlABB{nuL7=Pm6*Kj{vNOkLoNgECYG{H?xZl{c9AGm#yw{lt zmx+GSTu%z|9@b^I$;>PJj(0b`g!$R3hdsIaosxBu*CP*uKt>rS{MOaafd}$c2ThJ% zxzMD2IjMdLG1Y8K$`EG{1*F4_3UJo_kneDM)5ErJY*K-Si3U1p^7s~^EJXpNU4G!W znsIj=1MTUD9ySv(YDy8&M$^^gOKPeby7feK*5kv4`91nGiM!Gv)0%Uh)}T#$h{0W7OFcaiE%KWLY8M4#4O z4@cSBG$O>vv&PQ#k%wm3V3f!7)lJ$@!`NLJ=ALLbVd&qd(;D+`hJmuUc80s>lt75eVCpTH+)28_OhaeJNNCZH{j?VC z;HhA}M#*=Jq=;b7W`7v)rJBT3lJ|n1wwbG$ps}NjjjuZ(NfKOr#2h+Dvt~yfM3)q~ z>Ppe!DYX||Oc+ms8h5;%W4e>$EvO>mRrt^@m>x9L4nD{^_?rm?l7cr!BcBpucaUCWAD$Oa+Xi!m~;i}Dq_33qnIJt)+P<~BQ5HGK)Q0i1wFuIzu z6*!;#VAF}K9|)?GA2eya$@n~Gcxw^{%|>_LhcIoE@i*S+kQ%2O)*-3Mz2;gb*6LnEvBrs7%v54++-L!5{& zDa8!>GI6QfTJax*bMx$BdcTh%qza~twYw;^#(hWUm-b@VR!Dt!0S0iwxGKCVCR?gdr)V!v_!}4zL#}=`V>|YoLJnw!A2k6~ag2B{CU1hS#n7GIsQ+K{($ zj4PA$Lp~>+n^#-1V*V1NL4q?;eSuC$Abqg~Y|?brb9E;@z>NIvqbBo~p2YD-xQEf7 zG!w)e`CTF(axu!iKBC2K$eezr4uX8)LgBqcWyzTZbU_c`ima1)BY$!O*aMPM>4K4P;XqdD1Pu`ue%JC8wbWvk^k=YGw7P>X&v8B zK$l-J!oj=QOTL}>nZut`^w?l7+QocVc#cP@4pbpLwVeJMhCLDghBu5=uE`x!rHHhT z!BZ0_-b2ca3C|Eu_uV_6Cok}_|3Juy{O55=YYjRsYz{=FfHZueH+O>`!e^r3ab1G69vtG@&mKnKE=J#gbj)C>>yEvX zcsb}hd}|AASU++$t7HBxBzd#nPr*ij@gj1|U%Q&>JNM#52 zf4Q6U^>3$Ez5EsgMuO1Xxr;y2?tU!8oEQFP_lA!XVqS*NO?q71(a75kTQ zd`Q;^nvCFuGEO3YhYF`EN}6kZG;EHvmFMj=BqcPfDb`Ks*(t?%+%IDoNlf42&vvH} zqB+Lal+Pnz%|PjWL!Ub$f+)ZV(slDYE60rT0y{P7Uh`!n0vS4I=U%TIdEPC0h1O*) zPEj{LWzskaxrWyd#{8JnG%iU6cL$@QcMD4Y$}4*O;6_h8lwpOaHk!H)x+E&WIZg z;NZyjr|mdS&&JqgeUUTY`5ppe*U9*ovyj2;B=;fYbAa*5!uO%F)KBR@2a*cK%>;BZ zJX&vlEee8X&T-C+H%AA_NAR66$BwHS^mvdBTg=Gr!rHKJCt}be-^cTc{wK9Xi*%STa81?(InC;J>LFky^m~3CPi{`b(s4uzV7hp z3QP<-R@MzI(shJ0@pFd#_Vy_q);!qYGPLj8X)TVSx=l$B4w0vIiR96yF~`6V)I=<| zytj8~GnX@|aNgnieWc((dt6%exDLYo96q}CxE29I>zcss{#k2(drkh|?CT z9#nfEpg}BYj<=@^0lI#2_2g&wub_(7JlqkbLZKF5|9~4xkjweC`Dx8X_&;3zKftbj zfvb{uidx)r5uYqZ#3EmJx*Q*5WWPpLoU@?#?Z$V<^|!Q}{;K?(PJ;vWda5e-gcF=y z{(Z7Lx<|zu{e**H+vQj|r^hq0gEUJ}dkKYp=+-*d$U*qN!(U6I7$`98>v+y{ZqgpU zQk}d3!9qWDhULlejAFqr5nnrrmQWwhogYM)Qw&*YZg-_ixKrL~rzGrwI6!{dj2nf(UKNiToxBMFMW2W$s zC>@M)I@$^r$|{QY2yQ-*{Ps^hqN{o{D*uqG-+6H3cjb~Sk1Pf(s?eDAu(YO*$l zT^f`L>72&d^No3n{Q+BF2YBx&dx)p#qCNs`%?xj);f~1xy{+ck@oosy*;nui;YnYu zdepl24HMpa*Nh+cM1^Oxg1Z_1srFUpB=I{xa?TIZA5}*I-Xsq8%kjh8{Bdi6J&9-B zWykpL!T??~67L>k1%EsBuOBo`aSl$P+=|_Y7N$MwGRF_`=1lFRjcZunxQgoP5e{|& znayA03RPy7#xv2cnT2Zf0yiX66HHcoEgnr^?x<}hHL`c}bA5M}@2LQd>ZkZLG7(z=7%zv;drY{iR?Y3#NQdd0;P z6*aKvKe;xr^HEK5^S&MfwJcGfe>gvYH=;&<(72>fP@@D#G>m_P3CJtIvNo{^iu}-&CT56gQ-N z?G)-b)KTI}g5|Xv)a9KSU+$-m=^G}5+!)C6LoQRutzfq|6+IC7JLc+Y5Ej!FobLfN zPkt%rL@CgVyxA}06ts$rK6#MU5c907?>-jY5EpSB{X?aGiEnb1Nr{6XR8zUtpI+iffV+VNOGf6-RWkj6{ub;oQe2eBPD8jBQwvf zN^3Y@iCfB}SAsharz_hn0BogFAL3|sLS5!o2_`$-EX`EB*vD?&;tnNSE>4a>3j$j4 z2bxm+klkJ6Jl*!)PAg%dEL6{^X)VO&lnTvleX!23IWV;)rz?jYZ>o(`ToR5?(&r@Z zx0rNJ3~R~oGbTM)LufpNcx-=KpE#$}Xm;eFQ#O&`L*BpvJYhIm~h5pkYu? z-9|z(!a~?BYRiNS75RsPXB$_-9%qjcOZ{ytpfR+l5WGA@Y zFcNMvGzVSo7{4oR!Wij7o^4K4tO}VMz{TCcpS<(?^fPS#xPzb$xd5WFL+My{8<)QF zAJiAv?@XE3CN5Wp+(#a$fu$yudi#%xcCDii)|Ol?92_pw|JWhfMAu4vFsr$UFUJ$| zuW6S?M+PtPIf2CsIIb_Ul=1|_l4B|XA+An$^fAKcLayARP=@lPQt5-oc)BSz#@;%GyS+&ACAkk!Jw(q&vf zO#SK_SM_o`DYm8jFttv?t+x)8CVkqD5Ep1vFAGlCaai-1;U@omZiv?*&xOLpzQk82 ze5(#0Iy$O9S_g&a z#)d9;_YLrU$zP;jVUrd4lUoq^IS>Rcb?J{07!~0hkaQt3fC7%hbf|9%wn-_rV=gfA zE00h%?Y-u31Os*;%A}1dEiOUd8d?ItX}>k2O7z0HK~O^8CMM;WBdxF|zFa3R2<&_MJ)jbdyBU(gV|heWIl#SJQANpng8KpEa4JNb|)>Ojk|51|)Y1vylcS z#T}SNYfHS@b>KcEH6a(Fg8x~kx;wMyn#W%NixTnIIq-u)K|Os)0fL3GLMh86L8`&b z)_-!FGlvwk^8T3Q`jmzVd&hl*lA;QZcTc8%ZJW^d#RM2YU@m_N!_k<`IgsZl#zsC* zQnB7<30Qz0?G`D%-cGNX>}!a7%Y8CHozP@!+;?g8GIyqb1E~ZyU-X6xPNgMjRYE zf15WPkwNT)RV2INN1|l-c`V0m=&Atzi#H&JqJAO4zE$Cy-s`>LKF%K7vX8LAt~G5> z_+GY2$NXqJLub#LA^2Mm<$YWc(Y2&TZ;EcWI-!DV8m(o4nE~mWy^p3xG~9-?FL*_!??|~J zfd^-wS+I;JIWeY~)Hmjmz?O~9!ClOs)~ZJHSQF2yd~-DE1|4SiZc@;$;CjGT0fK@B zJAfbIFB5FF`-sTMBp%2yl4l9B8fm|+9Nb2~@%!6u&p_F3=;VDsEP+8I*RI}c!wE20 zFnd_@-&AZQSlg|;5<=#e(59%+7ZHk%-;B-#iI@CE5@%so_pJd?ExYnCR`3+N&VjvR zCb}=SE7ms^!nd#$;TrJ$CvhH48Eocplj0!U`wZev4Juusinp3lU+NQ)P6b6P7>eC} zlij_|H}X5Po~!rFGu(lzjh?EoQ>E1R?R zSApVwpQ!Z7h%rryg3IKd6g{cb9FN8UkChX?SJ|(c28J-B?0p-!Vp@7qXem!mlB`ZK zQSu48YoVZEhA!to#PL_hQj$f@%qPIyGfYZUo)-y^*?e8+zt|{3W^B&LSUK0;Qx&pb zM)s~6g=}ojUp92JlSSOG`gMhh*f#Fme^`ITHxoam7hmeoiczUI$Q}3N@zP*t1!VF?1z^Htgaw8G zkB#{58K%i2>u(t5Mt^Y>d8HDpuaC^A`+Bb`srB*|%)8)?V4_Z*K}_hmj%eV4rxj41 zML;WYp^JQloLcZ-NC^Dm`4|vbTc5}fK>`i&4SJ04$B7%=G3e9XLgft6wuGxnU$oq1#fxPk0wx}loQotj8$hn28HEh^=t91m#Tugo zPkaMZ5=FZUP#0j7)I`KpHd?8mbX+mtgTD5tVtraffp%2IXm(qpWzdHt^0Gj`X)-=? z^Y#7qOXm9BB&yGeKuFra%jN~5O;4TbDwzyd?Co;)WR`NjX;Mf(SSNL6*7(!znhKVCR{qCMZx*-hS5t*CeKZ1c}X6y`sWB)?1qVyR~Nt^43P@Yn`M>@1I zso=+mZ^e^$&p=y=weFNQnoV!G8YIExWu=K5-22fa#F~J&Bl&w|4aKf&!{#l=JP$o# zftfpEVPnvukgnOMCHvWbuEZ@;?X{g+`EfiYhOPu^4quxyaxd*5G)6YZn@N2QYR!G zJSs$Cx=(daUvFA+n)F5`;vkq!P|MA^v|(7 zal9V~i=0i)ip;#*BIlq5P0)kTTWo7V>gBudq$W}0k1QHoO5nZ{0S4^Fqx!4$TsC`h;)^+c^zp+uf8!k7EBEX_A^y@g#`0bV|Mx$5%wn|A2I5_B=pofFe zKO^Yg6nK^+_fQ<-6fJ2V;)93reLLT}39+!TaR}VWkP0P6XQMw#C_>l_>LNGg<{gW5 zDj4tT*lfIN=x$1}p#6G% z2Q7Q>UZ<0s1W-DACvPjdrBFp-KD9k04|Z z$!-u?iS)ErB>>;rzX(R?vfrGSngoFfDPZu4>$55erTnNB1IVU{3fvdfF*O!BDp=(T zkIS6tez`fB;4RoOuSqa9ke*89S(7dHMlgZ7Hx<)yGr~SXw;BLo&Um)bN@1fTS0Hvo zkqv1uUzxm%U%`CJ?Jt!J4wbp{o~5!x6|j{>{G+4-NXT3`MTT+ zE+^2s#eza6gRPIsm$0|JsDeKqy(yKS>EJqyKSDV|Li6k+1Nczz8iMR5HHpbSK9hj^ zW>O>#pmhQ>2wAK!%P9d7iC|*`A5Gy z@E#U1GLI4QK5`ELbXWsZDOIv*SfoaI2z2s!Gy49VTY}VBjDCog23j2dAwY#9+&*4N zu3oS!Z=NDIMc7$HA!g|yecF!Lm3hUmKCKY%b#Ry2+MI~h(7QkXg&Ligx&Z9rL5G$V zc4HqbKQ$$MR<;SYN@F`~evEppTe=7GIqkWtf=Q@P1fzZwa;eZP3YPa&R|VwISkm@XxF#x`k`jgU&N}<$fl*=gI5zs*m^l*t)5{Rg3@(MVRGjb>hW$0}cc*vL-n+!yg z5uR)0HPSsQebXppA?$2a43qEzMCqkw8IdJ(p=)w72yA#Trq0aA<|jgO#7zsWd8y^Q zUw~e=X?03_ka1Rw0-%RR!EAi`BwN@tEY7g=g^tlJRk}}YYm=+%u151o8P}je!}_dV zD%9&%qW~5rn3x--MgdA$y_7BNcP;P&L`jUzEGI`*NIxOxjX??OQNgE-C6m#lM~%$Q zMv|&0+EalqCS$4j(O?wHSaIh1XfOeJ=mh?`ApRkwy2pYk{C6OF4FXZG7+}O;a6S=8 z$U?+z(aP}cM|yUN)MIM*jY0xlpWtiCI4fnX+&UWoWrj$X9wW$hCSGH`iX2LAGESO#`3rMyUjC zZ?@U2nBSDQ*C39q=IfnG5jtAnE}^KmvK1p+K0d}@(=fW*`8~*Op%Sf^vkizxn>sa* z8+ua3o-d4n>8VB`x9|O!_@F|e;HZkvCzzVU`Uob2(9=RNoJy#(azG8t1yf6bWKbq7 zU!v!{%QDcksi?Py6~{+>Ef@<0@uhm7HomBuOpbc+{-%=n=qEhMWHJ^CBqBkN2VWGw zFGeG362NL%#uigAe+4x!r0X>II-V3%#do6bitj_Mn(0qh6_$3@Bis zuWdGry}G^MtUy)^j|gD=SPF)*1_3QpvkmBED~PSHY-Ilg>a-d~tITt`Z~?~?4B$oP zcDVK94MGpk1q6vTDL`s*lV1r&-EK03c=h=}MB(s}!QBDz{e(cv9ZIRq;|HCI1yrf3 z2S1!o1wBDoM(rjZlXLhwOZ81OKLg4jqSN=g-SWN#UG+vaziHsx!T+z9_VQV%dU-S< z^J^6plfXPTbzq@zzaG9b9|MJ4@avXkzp&BqksIWnOAZ$fwC3cjVD{3KC+7kQ2^ZXu zK&Cb7tIAQnw2zCC7`;u3-HoE9Tl;3Ct!$!gsW_9~32}Z7i&wDerPzEjqR=oXp$pxO;rBu?h%=I7>+V;+-ZvLL$jc?6mVWds29X!XINKoIS` z+0bN2MTHju)^r&>Tu82?c;@((#YhA%OELkZwkP-@p1Lfn3VI3dv&Qi;pyGILrg@aN zUv;^S{Uf_sG|G4ZDsXQAKmASln@SmbX}xGt%w)_n3hnhoKu$#_V&a6Gij$C_V}us| zGWpUb-C}v8tg%^hc&y3Z=bs!lCKG&YFPWE{5aqx#cAd98uvUpFdx*XH+|mVE|5 zeKnuOy0OdrUU{$3ELEF@YGuvHXB*pAy=YgeERMsyZM$sFhEf6=U}FMG16ZRNZj)Hf zfcx%DC>lZ?sHBpJUI@t(bIIr&B;rX`O+`XUM2k&a7lX4Bl@LM^&wLPnHX^%cZU+!= zrlu*n1ATwh(BYbiTP4S$`=%O70#x4*D+B45;KZOVKQi#5_ZB_4u-K3x`R?IiD_Okn zIR3i&bcs=h?|5fayi3>QAP~LDR6G_yx6}}d6Uw!qn3O`1Q1IM=xy&hQx5{=AJ4D8= zm`0V$n`h1Xllrp;DEcJ>+tHCxEmSJcjLHV~mg6oq)gFm9e_SqITjIiRqp9_ z8CEg7(QG_2!xb{}bo7@iXM5e=`&KA*I~6d?JB8*mn`{zZlP7|=XVqxWK!!CD z@_Htsu+xO1^MP2<6I16WL^bKgehenFCximH4&I1j|E0)`if%Lkg0t?sarcbi3@|BB z&#`rQ16WUW;|L1*4HOc+-JxN?!+}8vX49zVn7Nr)XaY=ObuJ1m|3oMdQ?Ww_BNX(I z+`7p2$>tT9c$H?|RBb6nCZo6Ux0 z!^$}k4Z;cOTfHU>DME{Qh2aHxJ`uesLptA%w`bkKILvHt+WAe_8u~AH@FPg#iV&I= zJ$Uam|8Gn*zT}zU&wCC8_|Q^`V3Z!i$sP!~Nu*qAJlm@u*X!kcwzp==)W0KA{mJp< z)pf)YrpuI)i(isn5K8cy(h);ik#pOCmT4L7Ou-2`#2&^v(3a|4E^tle*?XhDjLbbA zQe3c*cl8uft>x)w=#`AIyTU_efRbp4-w=Ei0~FZ1xm|Y6vaPHtU$}Tw>RQ zf^>nWDe!%d^hweb46qt*fMiPIbyM|p4sL8tjA-eySAgo5__h{EEnK99on)uZduIsS z(33*(%0=r6YV8b{8x$`_zzba9NGV4>YNH^ zAe#%yFL&IizpOoA3z4=(#Z55yzJXSX*#=qFw9VUBTT>5$1I!1|6zS6y5raTTz%xKb zBFQpcafBZ;WCa=v?m(Ob&yveH5Y$6jf8Q^_eNgl5AZ4AniTT1zqgdf+k>fKn=Fc%6 zVgi`q^g-(&`OA~H%GQunMS?E{Qj8p6_}XcPMyrAFh2I0REHM8zM|8QRgnuIBAn_>{FqSMeZ2e|9ce6 zHf;cW1pf7(@1`w-qh^Eb)*ToA=U;O513uAwG+LY5x14P2*b1<5?;f70TCQ;;%Z`!&_P6d!44F60*!ZAG(?{F1iT%`g-5E zG6$`0xlAuf0=kAtnaD4(FzJy;EqsrY;m0R&c%s=V!jFdtM0z$&&q&{1teDIw>?Dt< zG?oU>^~n{TUk7`80SRL@;p7&4*{fvQge8mpd>%K)wOlR0P~C6z5NcL%dKX=_@uEoF zBD#UzI+KL5)gX!t56_Y23??Y+sA|rNU6b1!26BtY&7tr!TjXBPk#1S{J$@f85=fK+ z=R`g)m}3#Q8%bg$EnwB7C)05XL04%A0ybmPZwgs@r z7@ZM%nz_@Veq#9P+k-^5phl@hPFM8_QJ@EkJS{R(cjJ2{a|vsyN-_bQGSx`|o}G$$ zSJDJxo->MN{hBCb885;E*ai|pxkJ)o0BomvEAdrLLGdM(xpR9o=&D?jO8p4ZvFzse zpP-z~Ycw58U|4B8Qs{5TF?cColQ6Ge(_7N!q*A8%Djo3rVz5liv03Qy)^$b^K)aw} z0Wn23CuGey!V(ZA<9noi47#tfVZv199;j-}hqy`9D_m$6BCu^9!+egAN^S;f@yt9a zy7VF91mGK<1_8rA3%o&iuBscGbi@-b>Uu=}SlZNvxD1TfM>KBqPuuBApSwv(x(Tf1 z&Q}jeEQ+gEY113vHKEQxNS#to*{UPPuIWP(9&N#VAE3WDBB+S;-~?z3IMjPH8_d3@ zKpBTm@=9b6P>il^0faGpxxl!CA7PX+b6HE+%uB-@4hiGuhQ`E#|363X7u?2~o_l`X z4U!Ux{s(|$&Ws3jH$XC*v4}0$;zxREg=l7g9T~CBJjm04c?X5O|LgHmH2Uxrj{DPg^XVamA4@bLkc$UvOCu;OS zIRxswHXhR}1=I6K=wq?^^iUJRejpAE2x(Q9O&&VjgionGp+134cB@=En8VCZtPXoC zl$c<@HF<0>A@>znF3get%7%E%t)fL`xx1^t+M^QSDQ=dq4xhpK%8YcdEaVso6GyP9 z8Y4!hceY5UQo>$?PN1{Gc>UADOUY4oN=SP2{MZau{@Ank7^s@USrBfE^xE2IB(_C0}A3Z{lyLP_{}IMi0*$ogym#%9dNfM8`d9 z7E4=p*QspTZNi}dTvA~<&O}+AW{poJk0u3_(Ec`@pF55Vm}RJyko?!>3CxkNXSJm? z3iOl~U+6h4SK?Y=8Y%QRt5jWIqmGlf%4i{U1HZq<-b(uu(}rsAa7#D$Hrt1hr$d}UxeRY<4+I@FZ5kk=db%< z{_VMFwmod=yGE=2maeeQ3x7|UB{|NuT=5ZI+=ZbaK z6dO*bz<{j6#r+ZWGP*Q?59NJttSB;cYDXCTmX4j{n%Jzs;ta@cB79k!)@IP)fln88 z=(rY+`21Kme&Fi&_8%c9DDR-~uUh;Ae$x^jXT?!ToW?nP#xSNMTp+9&F+T_^gPV^d;{GN^uKT^wkp*v zN?9Fg@>~+PXKf z(~N&UZCqCa^I#(^CH$Czq@+YDED31uwHs{=7mBF!8pmCy>I#hFZM?E=YeEYz8OFz9 z^m>d~CO$FkM?)zhE36y{r_++)>{YF^ig>SFMOaV=#~Iph#FYjbmo<-W5BGL)T+vXC zu%4f*{%hXu&>lk3hE<}h+fS;^y>6}2E!pHgG|#F0<$S^w|=(8^5rn_rqO)Y-Uhdzz~OveSe5!>y+%sXf7y4{ zU=zv-9%$bY64}5(ZyQC%-eB*>uiC>1{JRzyZalb;c ziYT^zQb-A9=CDkA`D@sSP#Bd5fHhLf$D_&6;rzGQwf$AS(u@9%p$#Mias$ zuBQ}`#XgB$(IS|pqvfbae7-o!YP4G;Sq7q>%sBR&7|M8S?oRhrqg^Rsw?TsholSJr zirA6SL)>p#M;46tAg$m;bb3pgkQsxyo|=ZiAFWLEIpgy_G&9FFPZ%w$_%s}oUs^~B z#&mAO-RtrXyE~=ICZ0>IxyF8DPZS(&kcwry=Oa8@Pb6Jjj5DrWu zEXmjVrik^CF5?A9;-QzIjHw@>_Y=dwH4>`p+tr=s{+6&`h6bU7OW!yK*Pz;|HFI5Y zufo2y6blmcWyEGd88m!7v4qZqkp+k&Zp5!4yqb(kG!~l;kE@!Zgq%qc%SItH61S-O zJU)#djiXzjO08g7q|rO>i%J{3nZ7?FzdpQsyfFDc?=By=R1{JFqqyNCmOBjXadL~q zSn~TMEPFc+f@nwCIF3sQ$(s(t`@j(@Px1&&gE z3v8{WvA~zUhoTAJJS%+BBHa6*1xV8eBL_3}w?u)~womx(FAI>ME2YtE$5yf%Kzzig z#M{hblwR~?&+3;7i+-}-k_zrXMl3*@<%t&j>BBnCWlC%AbJS=Pl27}lt_cAh5s|Aw za8T?{IJsS6R|RuMZknw8ieUUq7Isb+_7PjbqJ*)v^A6Ajy7^0j&aY|R;`5xud7)Mx z51NS%)Mp?40X|N?^_ONiN)Yt}=nj-P0{6TRGaefzKvrhq<_Bhy#o->Rp?}f z`3G#WUn)CDPp?lEpbk9G=mN8IprahTgX^ULF8keWgb~LiqDf!V#i;_zM1pW3BSYe}Z4dg}(Q4l5=WwnzKK1!l1I9&aKL@a- zhj83QMuSMFU(uM0-=(?kN#l|)o+~f_B=#odQsmNS5bh{`Tx%8LV8XZil9tPi zeU*VpWLFhur*bS!{W!;pR$P~!QPtH#cM%QGO04L-{H0hT+?5A?S{EY2sk^L1J#YiT zI38$2r8}yei5e8R!L=}R=P!otB{=Ilx2 za!4a*_2sT5A{|2VLc5cWu7Q$_dXe>AhUEjFeb!nWmyd|P*3x$k(R|awr5v;(?-&I| zdEZp^IZXk#bw*{;yc`6A8ZbdHjhamMm`1H@j5f6;qOD|jt#Ldf3>Up`U6-(v3(*O~JSS6T8lI@RzeCuC_?3{K5UJe3sAh}m z?gu(FxI=8ZXAPra8Rkl54}qr7tqEU5$dULVP!J_9Sir#Nm>!!q0SG*AEr4<=k+3ju z@heQ7C7*(Bb!bG`wb{A40?<-6!&-4ymr={b6CBfl!Cgk8*uLuzUNID&&%U{YvYXB-c`!r}L6f zgsl`%in9SQ9|iWu_%w^|pZ;r8A(#DaM}EhsvwT4jM|eguG~T#Ao{|s978BDQa{v`K#P{6Ik8-+ZjdhO z_gV{ko*3!uF6_Tt5PS-4ZnMi6(kssZCp9G>*=qfV@~A>gx$6XAcN#ocJ%-DdwTG2s zNCRtqtI-++s|B=nTT;_x4zYuj2|>q&m=j|!_I77fB7mWBTiETXprI?6CAGkmBRFTR z>sh6z5gZ8-RU7((g;48Xq2%@}Rsj0PQf1qdX5_Z}q7NBmZ|y#)g%FiDIag!G(9fLA zdPTNjf@Yk?e99xVB;OmjBe-lA-~HPv7h}WAZ(U9)#D%iEO6*-G+FSNLiY+`#X{}?bLr*H?kIHV`WX=@oz>cbP|5O0 zNED(+=zf<^m*25bQv$YtOQF|vp{B`$4cWkJ!r;2p!!&E@7Hf0 zwHEN)QTHT!42J@h6jhO-!=UP69~1&x$0yf>r^`d4ibxor_}xOco1YkL#fb5aPQjDT zj|(1eK@|~K(1q4-5?FY#1&0_DR>}=?B5DQBqg_@d9=zw?kh#1A4XtOY>&=7d@%W}d z8J=)U!3TKC)#>Czv{t#!B)%KZe&bQwK5sdk5^D6ri%2J<7YgI5NR=F(W8r&!#9L;` zq}(QUztNz2{4kfazgt8T2_o5#kqu+lH3|D8z%N40p5r3mU6(vGWgqh&72Zx5Fu4ErhBg zLtV^gB#z`eLVyjc|3rHt28GRj%UvqswV>TfuGjT-E@opj4$@_zkL2L$gLV6e2~{OB zsw(29n$Y#9<3*hb}J!F`#-|D`4olAlh}DHgq8-M$>mck5WPm*B~v z_P~vf2S|06v}u|ybe#bS-3EWM zIV+aY8(SNe3W6=|jH(PnE<7NL&p1ahK}%BMhbvV}jvyDcPi4Ht666EKCmlI{%xuP) z8uh6&;)ByGcBLASexZN9-nLT*ub`qOp4{_^HjzC*)|E*o!hJyM^} zpZ;}a;07sJDe0`q#@HEMd{JX{IJs+xnnq3Ie*JPqs1iq&Z@~srG8c8cD*h7|5VwHs z8)1F71$d0bZJPfwz>NRR^*R*8DT7DWtV9NYPjEbuhRc zhO!>s^3J_7nNNo$4EufhZ1OzCB-xynOj0ouXO=Xwh)ux~%ag>j0A?7DH@CbH{)wYT z)NY;*Zr~Utv*Du>kc)m~hOlXGzF+kc9`9+7e(_&!OYJ-n`V1Ya;!Ud0MA03u+LH?s zPJ9@Vu(L^;e2X>BhP7{<2s{+2km+f6IPG04AzGQpVa2D7lYP`ng83=xn9A%W^P1#z zt)bo23-pIb+w@vj0d6~3Xd}Ol`oujjGZ5EC#oKe$W5zdT# zf|nSP`xHzY>O+T(3_^8lg<7HfsMKJT9mE5K<7in?E+bXdL#M%Jxy+C&+1#|hSEoJP z;Qgx@BW=J}9rviu>I*<-10|LvIm!;=$x@UpGiuEc{I6z94rjoAV}vzrF=XPm6q@WR zgd%56A`hpfZ7b5YQlT=q;F%$+9gMyjY_}~A?Ns!0h z)`HA`Q|b#Va&*(NuBOOdld_RyuvAddTTH*VzISq4mi8QxO?XW(pOjmn+RRuUbap0G zGOuC+*)EW@F|Hj$=06`hXA_bhvXV$Kd8~@lu(^OTKePu`G7(QhpOfT}PY)~iJ$x>$ zJD~@zPub7+sXlo~a9@J*ENsYvf6$d0mxafM)G7V2m?Rq(JkL0R5LkRQ4I4aOjbE+e zzRKkF+`U@w9jOC(8^F=3)Brmq9cBKw5P?zTsKX}kOjnEf%NQBy<}hjC?($97XB6QEC^{Y~q z3o@x4D|nA4d?OjeM6z0q`_l(_kkNf^n_|zZ$LRb0K;FLDB07R)Iu(yXR>cBFi82iF zU&0_UE>}9G$ut2l9uMb=(ruux^WGMl@y8Hga;N5*mia=}TvB>*CcqH)B^06CS)=HQ zx(!H<5<>&YJ){K^on681M8Z?K=HnIAe;M6J4o$!I46=Q0`QIfVvN(YkC}{Y6we~uu zX6E|%&%#4bZwggVC0h%~rFnT9e_nMrM`d9~Fy-0@AxK_v0QJSX)5CSlQw}#*ztbAQh*@)O<=c?GJi1}w5EnpXREv<;ku}@&B>VFsr&;*351^&T2gxK?&5iHN=_7VM(24G zjB%+fzXKd+7MT=C4MM(C;{|&SHt`Pl2r|8LAN90Eu7rD__k%Z>`&J? zU~_st{aAN0WRYsOPgx&OsN_q6EAR!vi!6)66?cRjC`5uqw_Y0Qg|UOFljW}oK~{1< zUPN~>ZYSi@P8VIDWTStqknNgbgo}>M-Dyev3UX;&pw4b~axSwXxqOoWS9|>w;(VGRjoZwvcSO!mBU@RvWa64$7ap}QM`r{-40+f6M8(aFc;RT(L7zQ zX=?cVE(A^wPcD4HrdWB%6kDrY=l=RG-U@f@TMxpWEH)*M-E8l|uFzcj2y! zBbt@OgR=mgir~>g&nRj`-Sb`PFG(yK(03Ya67Xj6*>4wQ?2!!j%CSE;BTKQa z_<%-FZ*^?@`>YTaJYt3!^6ws}8+&J4{&lMUra5P52?l!!M<@K+q4ODJXyzJw%q>(Esp zy0gdOojqeOJVl(v0(1*XIWYz_k^kAtR2#g8I6^PIErWQ59Ka5AIzx8Dp*^8fU-9er z3XB{>T%xnbUMUB77!YZ=Z4S$1K_R_@&L0zJ-!J-(kd=kw<(TIuW#fqbS$;&Ii^9ug z!jN@`Rk-W2UD;g~19SIViWN1lhX}gjV!=6qENz8|-{NW`-QHw}m>VIRfoMUy_=Uqh zf%(txTl89eq74lE7K)a{Adb9JbN-yghU(Fp46X87Sa&fYNjhi0rhaxwFO{%f zmXuP%k~-#Xo?8_PUYgc2Q%|EghXy7u_YD8}$({_&Okfh=fB!!-l7qH)(^|xA&?3#h zcR1y;%s;1YYmq;hDiN@u@6O9`XL7NC@ZB%)E9`*)w$imOSjSs!ud~%k`IZKub&!}DzU*|lRI?xajWI;YE%WT9-HQYIR%8&#o@ltB+*xFC zWnGTp2C<_;aLT2X{uNTAOXra-*AKP+CQSp>w(YbS^6iO?qR_GXW8~@>(s%9Vq@*qg zxh|*hlOMJ8vo16wHgotH4dGa*A!JD$JGk+D8;!v6v5l^S_^qig(EklNeOhKNM|=^a z*6SW!JOc(+G2ZRdPHRQN7~*Y(yRt>wMVEtQ6jcCPcuNWm{mS;lVL+vqMyGyIJ1n24 z&g)wlDMYSVK#`v6fcTGBwW7QTQV z^LkZ7QU-?CQIeK#4wZPgw2~c0+03!ynwKh#*Lu;PRNj01v%6uTm4)z8L<59oWKv(4 zNsFkX&vvh4!3ie(*}`wL>>Gy+mLsV)Z=&-~toS=i%KPVXzGxv$devD!d^9M)Uc-6% z)TFElZb4NhlL&|)v#SX9BrQWZ zs|o8Z1=y35sVe8qjZ0GLbm5^#_jX9~1=R@Y(;xPJ45%!1Z%h2((CiUx2u*1*Z%zQE zWD?Cs6R3fO?uJz<;>b~MLX6pQn(S?!Ub|3m{bAi( z-Tfdgj{Y?;9urVlEm-9b8&#LMr(KPT^a z=GGVpKf0Lw1WhlZkCY>qs$qS|3D0Od{fcP_o{MX6)`6?mw#&mqDAekq!Zax}cv3u4 zhEU^gz6X*hXbJx%MLL^JbU1J(V8wpHjMfu}77{Pe)!}=I<1)kk&bk3|R4oiTTp{%w zvnEbBiLQ-%PZnz25M3rM0$w9bk|v&R41JN-L}lF1TcLXD3`ENC&;VYO2!$FXL?Efu zvt1|;uGD-D?$18cFc^K##F~A`U~7V8aG5V~jTX|O76h@w{Al;qAdxK6>C-9lXRjS| zmvWlWAI$~42T4)pxu2T1_}?x#fFv&Pek81-v_exEH@t+SmkRxTS<# z^m4SeidGCtJm@uke{F*FnX7ttsDJMtO7(cL2FtYDQo z?JZ;taeNhk^&BLcIMryHdOLW!Dsrp-NB~Zf>l(ZUS@p6O2#e#WJcj7=O7R|SG(A@V z#A9}Iz1yzZ`+$51>q5K6mkzu&vN;_5L62lm^hS*9sX*92dEk`#7WLbcsd2*1e0`SB7eyMel7U{N7!+n+sqm5SchE*amO~? zW5`^fI@~W-w;dbZLehhaj40MT;2#DtriEce9FNjWY%%z6N@3cNBTKq}$>&Q&GV__m zL?)h?R}va)_`>O{@S+U+7@3&bHYE?uW0aa$vjemic?;5O5w94j_pio4=tK?}(LL*M#@y zUT3e?+~4m!x2y2{*-nrt_ zQcS=H%N>RcL>`x+BtC)YoiAE#s3reG8J?D86$uE^zBxGu&-M>`JuZ2mhnM=YIOUS0 zm>|FZ6H~ZjHFM1^2fo^3@yr$)h;7gW_6lytxbO>&Eb5tTIISXNO6gByC?VS9cXoGw z4-PnpbdD?4BRGxlf%&rQPytVy$-E$58>AV6=3*r7(=v(l(tIL55szQi!Z9h#_s5Y% zGo!%9Htu761X{*uj>$)5G$N;R z(8Ag|eqF5Ww;g-Sl8$g%g!i6jhHUvw5h#aQg(fNboFa^_KhBdav%5pjy1W3)$GIG} z9E&^O^zQ68pf!S43T84$Vyl&HnANHb^my(g%b(^xh4c_&Udw<8y!(&>6;uEIOX4%L5mQKf41AaWT@puHD z-5G>_%^MImPNxIoeimy4W&X((E4uGd7X!DjJ0z|`51H`$3`3hR;@6E~tOu`s%`e9?V#LNu6KxWnzH{cAKSGW-$;p zB5^sPhqDlBE+ON^=l5efnO3;)cqFr!hNm#0$>EetF82V|rwU{b-9xBtO}g#4rQWVa z#m&xfr`g=WA@7yl-7>xV5dLn^ITW%k*J-j|`Zxa)%-1CfZ})UWim3i2IUWTQSR^I( zRl|MKJZ?6&nvdZBf?yIJ#A>lx$s-A@TkhCrF7M3CBjGfj)NCZ4f%rMCL+!PsB#gc= zH=V%V*>g-w^ZM&Fla5UqDssDEzl>=9n5GjyKOlZJmuJ281!htK8Af_g>soIdci$2@ z=B)Ch0uLC(Y@HJ9pxr{s=91{~;2BbC3DEjZZqmdU(!5wQpt4C~oYAS`2EE`6<+?DC z<@Yx&gc>yvFt%UXFIO6k&RN&BJ2v*Uy^>QVLMNj5F2{_>b$q8PE9Oi65G(5D`4a?n{LEqhBv0C1 zp-{Di`}Q7l-swEF;s4%(*!on*p2;j?P))$O{uLDpa}|sHBZZ3dlIJFNjp;B9$O*sZ zU&PiER?JJeXN7ii=fz$X-q>cbvVlOH8m|5pq=Lmg5s6tiXz3n)beZ}UCjN;!5%_?`=M1)Zt!sDkQ_R`i2DFELz5jsdx>`&)f zQ#Qw!&-S{ny4@}7g@qJ1Y(hoQJcfN3rPJ9oR`9Hk&1g%;C{&$kD4p?`7}^Z}hZfdP zSI$_};oGouHg~E!rADdT(_uGz?@7DC{tX#FS!@0;gNXF|xF-kyB(5bgYGhvZUpJ=X z8p5vPa2+Ge2;0+D$RnYT?7islA1$1g;|dd6Cr_%KV)M%)9H^V{g+e&KUB&jdU&LRq z!E7Q22Wz~7UVtV}F2cN_!TUQ_NIkMd^XGB+!7~Otn33yHOG45(4cj7wqlq3I4BF=A zlTC*}6^n_K3xlL!@Ac3D@V@Tvz_;C#cj6O~F<3=l67D5-08n88*}#Jz|2Q#^S90&a z@SOL)IewW8{@PRUXArGrs3HKJvhd|TwD=%5bl_ht!W8fbgdv#-Use%;2ppM98hAs& z)>^?|+|I8nc6Bn_DRI}0nO;6rJgzd4-gSaUR12%J${2k08&d&ABd{dxRk^uM`@}saTDNqS(JEy zqS!QFUy|kFCA`-X@NK7Y54CvWa_^Tgu%TQv#3op)4~rD`)&@+Q7WoZ&uV;VX`%(Bf zyeIG~LhHu{WJuX}M&=cuf7-Z1%uEaueP3kWkPyX8C$WT(w{{g59g8K6#e+qpfjUw1 zNA1Q#d%Jg;zrpth)2@jhTLbSZpjTSP(5A(Fn2BK%h2)44zQi@F?7=OM&o9;p6z@%Z z80of@`Y#h$B1jUxjj*l=%;#|pvkzc@XkaOvQQHqKai{7~CXj05!ta&3k7@`iEul?% zTy=py689_u9P~k!{Z!#@g(wpN`zDInqHJpHHa1e_!=lID^k2 zeM`~(mQrEhk^daGlE|+fRk0I6{0_SU4J-TAZV}rP2_!fB^?gd-6%oW}z)8kn(P3nU zz0kOvfTKk~9%QeRhE6FQBmOt{oX(~LoFSGm?K<5jMTfYP1^|MhXAv?q(H>1p3}IBF zd<}Mi_#0@m@zfQoT_m4DVGU$Nm0JQ`4Q#Kt8u$d)9*0y=9MagYuF6 znA6a_^tRt`VZyL&2Tu6(yPELO0=}$E#;+Q%M$l=MH$PFC`Iu<8Fqzygv6;}rs@vJA z(oR`?dRqcL*RKp?BYIP~Y^bu&ARmA{vkuV{z zBqG;Ad0RnL8y>K@N{}r#t~B=_?cnwRspM5&7$p6Vz>A;DF2yy;*SkhnaT_Eb7#eCMh3q=4`fqot zw%Y-jtjQ?fI7}FClK2Np`2Kjp+htieS(IlGH4Vm6u?z0rY?=pOCWsFz7EvE>qAy0s zBrtz634elZ4D9oafiq0m_h?$=Y9^x+7Or&P5)OjIukSPbCU(ja zB@NS`79O5nhg5>QrCmm3AYLAT%P`(8#t6N5RKdmR?fm4ph+Mx%fb9^R5D0J&3B?|n z*H8su^T)FJ&`>o@sQ_&2Px~^egeMR8?Fl{tFYR%xc|3Osh5Hn{l!3DQnH33PQ>eN~ zI_%vo_^2MjQ`N;wytr2)UU1+<^*F(IeU#Tz8S-Zmn?P# zg}IC;8Oh=S{5@eH&zk!?Z1b=<;a_pO1Nt_Xbpsg4c0vicZba2wFQXsJjOR*q4aXg1F;@dG9Ij0^5IrE>gR!{&l6&d<0fgSY)29W5|Xd-I`Yfhji^{o0c4cb4H$>2O%z=na28zlmChQ zY5z|D2k>%Y=&9H)BmKqPeU}9{)CY#2*J7ne5IOT(M1#RX3zb-({w*NC&ANKbUHRNX zw+zssH^>~vQ0D>vih1&mYS{k&gmcD$9HfYoWNHk`IVJ{mP}@Y|4&xLQ02A) zu6O4od9R*UIt~*^zuP%6d>3;5-c(Gyhmw<|k!`IIVvWZKcavy|))g~*hMPDNTw@8V z0kP#-6tM@0TZj^268e2^?#@YCsDP1&K?T6BF*WWz`SDYTNEO0wwa}CrjyO`y|iUXD})x9ZBq&qgBE!pt71YLWSG1 zBD7+^JHbFG4S=x1-?J7mQ!X)aM9`xfCkcglsYquo=F~kvwfdy~=+;QoioJlG)aNzH z>(tKar7r@}s!!NmlG-&^)#6hd?CoHQn^E@aNT5~4JeD6-zCp)AK;{b#z5eJ6$}Hh) zDbG)E2ietV3A?rAx%4@g;^AXJ-T#lEwL<>KVL~QYUg(%w(Yw%+dkY}m#{`QYOCT=x zkLAM>zAjK%GFZk3x8#Tyx~GoQr{HykkyN|*dWFwL@JSd|ROQa+`4JUbkw2t5q}uCkR%L9edJ{8ex9xuvlYXV;5*XI>|yO9Z7quwkIv%xdz9$3j3So)4w^r z*^|HzRyqEGEF1Vdu*R;5UF;pgF%W4(Wlk?n>cx{J(ev!P1AU_}1X{5qnPE`gi>J6P zdvM53gr!Gxo^`MhUB47lw;TJ%fO?#<+zoj6K1;}c%&=w1IZ9;)I>lL1P5n9ykR&>h`C%kCy;lMT;+<^81FA1qehxI*6;&9r%E{B!b zx%;f@i{^ps)*rFyw-rnEqAiQBL-_S(7g}IC8&=TX+Hdx!x&dXs+e&pn5C}-jx%+sk zY{vupbPzi*BTpD@s@!WOFgyGgM=R+Hv)`G@?|&c_d6+Y-K)Co6L}ji4?=z1QANCv!vG&+h7f*P_{KN>KyXS~Z@oLdFcz-S9Ri(#8$R_a?Njahf`=235fse6mhapa>{?UWbF4M zv=XdDJf8?)%=`6idm;lG8o*iVcI#7|q$N`m1m;|Yjcy`1ut*!uJ7jrPJQ)$rJ@F(B z@ouwkUK6U#=X3&J?PN73OOpn_rjQ> z`biFsL;TZY_Gh_XA{a3E(2e+owE-|Zp$APLi7W{WITMo2%$1mMr1RJi9pj%yL}bLV zq+fr~N_HWuitesHCuuJeg3oHXakAV~SYd~;-EAaIBAD$O($pZXqW;+V%H&jTm}x>f zO*n+kC>y)WkpEuXgd@V6%kq|w*psA8S0G6vCg~@QfKdOd@{IRH13E=Nwg(W3V!u|% zmAjy+C=KV~WU}G`_=t5G?j}YkXP$))j#$eiDLteMQwXCeaTuFo1orfnSXvv7=1!6D zq%;nertUIIg`}f-4w0Xd_`;*&kUJAZ=5Yb23wJuW8$V={xEsTGN$YNHK-q(H2Lhl@ zU+fiLjM2x^&h7$cN`GSMKH1wBKRnQp7czPgztLS*2P*$9jluk?^0{zy4LeMJDQoY zhq#;7lO!*)hH{s^bQfxXINv87w_;ZwF)`$kAf{3R@$(GlSvVFy{Mnjc#Qc9jm=tpy zaVZzP8;*5e&J~`U8RX31xx-SThw7=%A+~IJYN5l>P)OUXcYU#m( z9Tzs>HkJBAcZNe2^^fHOaub&}Ssdn(v?0G3joPdPADlW!ecjjM0RJ>wWrD2*Q&ulf zGJt@~_cq{YWX14#F12?8cYyN58YhTuE1iCnBVq=TKSJvqcf%$sX@9?5?UT+(px6IE zf>eR=kjlWNHG?;kwFxLU;P4i`mS@mJmXRcqD@2_>SI|UeYB&17#)r&d%&hY#fLl#H z7)JC7fsXiEhhoKS_o6PPLX=%@xSa19vn*OMM6K56suKcUY6T(-3`sQ1*w%-=i`7BM z0=#Jh7pv2t2$Eh~?~q<`GNLt>A3)R#T<^3p`hH1VA=FaHN~nRI0m0NjTBU~K+AzHg3utw~}D2ho4U zf;C)_N=9POm}JKjG$r|G4m|$<`<46%DMMR#p1Jf@strq^M-4W%{sP}$6xg{kcL5rk z9h#Lyt1%#pW@8{(CDDVaf5kX`7^nT6LfBl(U47!?7D<}jB`yj4dKg`*q`;W+YIKdPaG5^^`i zLQFn#r+K1_!d4(woP7T-*UL_`WKzI~E|>Zk!VE#`ay7VtKxcS(FInLRlRP65!l$q> zlI2k^jDxenKVLzPjSCAg3!j|v%)&^$@;&cY7?J^Iw zSL%#S3f&hY${7K zfP zhvQIGI?e%C=TozBwXpG2jYa{V93#bza{3eq%zvR&??n6Z6*cPY0*@Bb?0hAPl zNhR>A9)D(~IyF=W5Mx^s;WxRYc$Q}dfgnIvNNs*y!l_zpI+II7rgqlS1y4-e96O_pW<%uyYnERAl@e)j*(l6^?`D7 z6EBbIWH_|D80s|zCZP@vK3%RtYB3Na?C%_pQmn$BMvm){>})zHxw+tmKa{83if{rg zVX_7)0U1s47`oQ8E*nAb;ovX-77bRy7lB@nNcRdz@gqgM<+1iHgVXYl?sHtmnzt zrjX|U2w@)`Af(P8BrC$E!wL`USz+74;l0A%5=`s{zvh-P=Hil7BvfAd!VkT90*?QP zvc-l@7f>SM;MEsuWhHgcgpIYOlTZPT-;ed`xQ-+tPTwAhntFa5C4=Be`x4~ks)mzB z?*_WQiR(&(?)Bl7j%LrhlT{$FCINLo;)mahTJ7ZGzb@xEK=vv8-Pva?Jm-Xa?^k^x z9KL6Pi-4rtg<3)rXOn^6AhF<+y5eLOBnq(VUG^G0C0ru*-1ZpwclU{~n|$H!A^gU6 zd|rqA&eEC|NLp3qToooI-#doCLlFc72&tK z^j%H7hZCAmvhx$sGI@eICIN!dTxgsqRWTn9ZuxLXDN^y@l12Bpj`O5XD7C_iXeAzT zHwEs!4L_zWIKMN;r^_O%h53I?iT)oK0zM;r-a>IfjQPLg>Q6ch=eRXzZJY;KkDEul4j9p{EgrF9+8yucVFq8vGsxO1fQ z5`|nM^QMAuufR}Y5qiaaDvQq?5$?k+Fn=k!Yu(=*EQ_!vRk`FtD-lGV-K9G$#94Rt zKo$gYMtio!=-ie2tOyfROQB2f2fsSO1@@xA6Kk0_HRQ#0E2k?;)0*JF@MEx8l9&~A zPLOfqWfvTwFIm-wu+XYhVbqUPUbN>tdQJU%{3C{cKvnq=_nd4)T8<`<_W<1{iQ_>J zc#Q>>7Q5B3JeyX!+||UCd5f@0Uy^3n`4B3{1I)Z}Aup%-DjO{riD>x=;v!zqFlmJj z7D}-77cTz4IJ-%$_rLH5Ylr(S0wLi&GuyG+2mrv|B3Kcl8;Wi){sdpKS>hHNmWI@=^iUNq##S8p26Dr$eLS{?O;NCh6?(opjetrO zJ1m!dVa@8)i%Vg~sE?hN#xXHLIXR>65QSck0<*%-ty8?Awp{0I$4VZ-?o42#vd-lr zV{jTEehi`C=?R!b^Q{TT_{zr^$%wGO+v`#9ESi;Z2JY9?L#t?%jF|afe9p z3TS@6;)@@iBs;87#`D*iT)^RS7(F7)HC&ca{K_}=sexM{7Va~GIrTXZZG$D!z(Bl= zPnW9fSU!}8N<1T27w;;KQQdl1_DHR%9Q1NhiR_quRruV}AL6hX#yT;umt+i}YZPQC z-A3uxhV=H>LVncZS7m6 zAU$JL_p*Y2y}HvEgFODjSU^E1+LNVzOtWZ26(^BsCc&;UYj~Y*bzE^_kBTJ38oP*i z91Za@RzQm^4#6EV5`tY7-S}ulCVycNRp8#NajGoj&|y?c$7Y<*@n|+PXnXs_VnN)m zht>nxjuX+n80}X2m+(4O_!6uCrdjl?%7~$udqBj-3#vkpth@jRjRA}d6WHj(FY!r? ze!OWBAM`NYm$%d|)ewF$yV@5e&d{FsF4s0c1-IQNFe$I;^KNxV<;Xj;4J5EdUIZX?DV!+hae$3Ib?BeKYBZ68023JhT4ph zTN$#H%J7iovnMfVXsxsf05gI|-y7Dvj3Jy683nOqdB)6PL;V^}dQVDMUT|4HqEsNy z1rPzChOoDOjo(#Sk^KeE2#URFv4-6J<{`5xSyXJVb2#S1FU`Pe& zZ-qn7tWf3yX^6o;9d!NTOVyR1( zo&jgQ%Yi$I3`4Vr1_SJ9AQ?c?<5Uj6I1n_X%tDJrCFWZzE+Z}V+*(VPr44-5pp`W) zZbPg|mqmEEIW?0klBsnoOHK%k?O|ncY{Q<(=vS5IQ@!Wad2)&fFUe-lm_>oYA6fkH z1_rmiQQO5l3IMc>CF}h=wO)V!o!zX_+Jwx1S@V+tz&4n0=(`*5sK)qW-Wmzjf5{9{ za-bhER|E{zSpGsNI5i4}DGlSoLPVBNERtpa^D2(7 z1lJFPUt#~;hEJC460k5Ef(zp%8@}bwd=mw!>7F@4-w8~l`Oa`yN2ckofVvNM-4N>Z z#qN0ym6;A#P~)?!}LOL zg~e3+iIYWhm7af(vKo!#)J8H4d!<$OhlTEuRDgYn|0qYDwBR%fO4`jmI)!yug9a|! zEuPX$5L)JI%zWExX_9YrL)fx%qhEt5Dp`ruku}DTe0hB0vC6sP0R>V_{S)qMrPjJw z@$n{=hF~tH=jenI5T>czK`Sdgf}D%khIAKOXY%te+@fBe_n3-) z9jD?+=#Xth2GDm#j;x-vFmt8P=~uabk!tk&KA}Uy-P^Ibt^Jkw$W{p+((ahQE6C~q zJ!*>I|$Dz4|dyE>dBMWIo8>av3lPJA5=Not#F~owh5Q_7ZNZe zMDzpEvJDc_b(X~}?}v}?(-R1R+0$rtT7eH;jH?ciyM_*M)-YNv!hL<+??a*u;%*bV zE@Wi?7Fxgga~Ao2u?d;$H5b}WAeX(-Ny>3qi`v^K#MtROeH=5;&p4dcC}MpA4{qp~ zkHVK-Jg38vmneUshy4BF9Xjfwx!`w^d!TOzg4-IM)y&`kxObP?{S{W1DilUrFCNpd z_^cD<;ypCEU`|}37g%o$hvxwe$8pVM{-QD|wf<`VI!8r+(5z`VGa%2@u|HHb7%7z-f z58fyAy{-yq(9S~{0!1JTM2jL)fY`JaiKr}Vtt*cakl}AC?ZJ$yXz@o^?oko}3ugiJ zGRYf?aeJ>;gbs`h2lXXxKP#a8e!UVpT?v5F(1CCsx+wHO$qmKdTD?xig)ib1X>(%I={mVk9CDr|p6XD&|*Gnv& zax+L*ID5N4-oWM)6YLKwY`K^8q9$AB3X@#jv2JjWX{2AXaOa%(VX-+J1@m?{!%`!E zT;W<5z7P+OezAtN+hZ&eb~pY)?>wFi7Xlu?1&aCDpp`>ovFn2_5=+k%GUzN~QUk`< z6(9i$T9cXh{y#vIPmfj6h(dF9u=Vo-tZdmwp3x$$94&lDrQxX9(psxR;KQp$0*lvd z*vb$DQGR+3RSKt~@^%52o(J~v&cCB7{~AZDQr#pjv{LuS6&^kv|fM||lfJ#AH?kSZ&l^U+2$J)M4 z;Q+gfgt-?hJZ~H7H2_7>vvM-WLbZg@&;p^nf2X;kcnux}Ve8^=Q5U39<5bWPKT}3_ zJ_x5nbUexL?G7+9Vz`yM+XAlXjfFfgPQfP5Z}r%5{b`S$%Ch?s#33ICC1wf3@eFZ{ z<15cU!%-vQNc`Z?(37FAO7sebQkm~?CBjo34Z`YXff?O~IFQ!Uk3Fb^38mFh>025MlL3ck*D&4ZxJq4O+^!aCs0=F^Kw*H+A zcUWIMB(}W|=6L6&Hmn5&;Dpe)6VXI$oPrn(A;C0PiM-oF zPN(q9&v)oxR?Tqccl#OGX@hS=(8(!WhEaL5CB3>uWk+8B-F=z|{VZ^3fsI53Bx(ta zsrz(*E0yUSyKT`IAc%7aozXZU_U~O7S9dDGq}G=~Jp}N?R19Sj;DPAlqHg{)fi?@Q z4*6QiYwYH=Uc>MqeJhMhJhw9?xlDLVKiPtoI^xj#`rK$iq(pp$8|T1M0P#At<{YhR zKvRD#-EYUK-18jfM}7>3wBUbo4$_8wzl6itE3_*FC#u*$W64bz7j|QjW=0 zWjK)=tPm-n3J|iXOo!c|)c($j$hO@q1BcHcqc z%qBtYjYV}WQBCvhvO5$m2Y(J#C4odH`WL%shT9I<>=1B@6ZlrV+08*XclcJPg%HBg zAALb10P3+#iv;JtvSfU*@}WLPj8<&!+&XlK7DZ_bEoXI7tI$*U^jUD!!oBu>ER+s_ z(*ftu2*3_N@)2-C=zmTAckf@dwcivsfs5t80~`aSmXbazQvpEk-Owx$!*H&b$RwM58LH@3_ColE@#wi4~|WN2VI2dK3IW< z6+$QQMcD;P7UtUyEdxLSFc%V%gp5esx(Wyuvm^wwSwvJ4OkC3T_KF6;z68)}r}tfI zGS2ts!8G#aXXCtk2`9hTfd2yr#+Ca^xXS^~el?qz1yB^Y|72X51bQ$50BBZC2z0N@ z1fJ0rT4pdYcmkLxoPoVgJr-Y6rIC?Rs$H zLCJX5llJzydqs;h%9zy@aep>=52g*|P>)&BV?E%nO|M~?Ks{bd&dtUHL9KbbjPBA9 zP8s|c`l=Ll56X$%Kvt*vR5hrLpIEY6O%r+VT0N3%vjQSx| z>hULBfjOLqOG5y%>a%l65SV&z3O9uJh8qD*V-gD^5Z-e5Jv_)JmVm!Zf_Gvxe7UY= z!F0_M8o$$d9O0t>fy-?=ge`+!PzIQouQkh%Am~D3c{~FXSnOj!)iD*4#oIE3NhrK$ zfNrZj9tE&AJ$i!ysIq}t(s1AQ-bS-do>)Sc62rf%6KWE9O(cD2L74%N?b!QGz>|p@ z{;Foe;kRqpB{vA{GvU#Eoz5o!hy)HB7Uk2ui)$3InppF#IW#N7=TxAV|133*_XIl4 zWENZ(Yf1%YC7T621z2JvF7>g*bRMJAU;DSv_KM*d-Me$edA#R+yR2y0(Y*|Bj>n;2h*Tr)H_?fH^|%u zqX#`#VfZ!(Tk3KzQ;5vbM zS3wBgz!h_*@6+CTOw1w1#Bs=h+X5;Ge&OXJY6y|UC;2#OZ1y1NK)Txw4S2rLrEefg z0oAN116y=XxrTeE5{XZ;GGD7=@pYcz-tnmb_{`!tNu8&l5bzDW6cB*aIQtYlo>n$F z7Z32YI*msty~HJ={|uhaS5Mpm6cEqia15gA76l{vQ7j7rLfR zfz5zFkzj26Mndh8!EWSw&p@04w-rpQ9@n9Zh+i^5|G*+6-920~E{_<#8%Y`a3?|Kp zjo5O&8@OHq>^%PmtYlm_!XC`=@Fu~d!5zT;!@$=uc`SwA*66XfdjF4+3Zdun;8`Oo zW+Xz|PvC10d_Fu;YetKx$X<=FRmWm3>NN)!y*Z|lHcw-cJRx-gA;(_zFjYZhojaUW68hW013h=Wv zHhcRR0TU-q*YOTF@q_UsU=P#49ifAok99Up3Ix3f{5$c;xz^PTfcOU`eC{j?PSP<6 za~n4@do`H=c?qXNK8e*D2wqhJBBCldcw_n5#Hk3;D7UZw-3Diy2U}&MZMozCyjr8? zfah928-`nPA71VGIP6<9(543&TbYfB`Gk62=5+@%g$hh;w%~qPvO5;BzS{Z@@4nWA z3nWg#ze3$&B53!488(*|lz9O(GszHsXLj9;a0%&x2oNw|v}i5B-`&Oztib}pEP}yK zy(k~n;BAqCNI*mspmnmGh>)6TTHXC$d~OkQNO+xMuWFaz6{*3X3rT$<+OJU=Zo?1H zf#uANbOxmB0IuO4mvX1TRn*c z=eA$1OscYEG>YVBWtd)I9X8DG{>;`Y0h=iKYfqq*z=JtZV3avUu%Y);r|8HHcur5~ zAHe1|tJS7iX=M_bAWdJ(<&#O+r*V2~HXBOD*M4eM%WUeB(D>CT9qAa1J z0oUs^?4r8e*15+VJWh=*n}yxOvs$HMco4qGozG^K3;_kyBGXIibX>`30@bS*sSn1U z?YB+)WvzSC<-1!j8LiaKW~T`qKorK4DjiCTiDl#)stAeHqlFY38N^~Y?`cO zkS8VK5d+`Nv=WRns+vAcYlSH#qK>N&GK5rtx&R4)NJ32~@Fk*#r(G=SAQ^SGO5JBQ z8zK(frgh?ud_jRqZL&}8b_vIv-Y$1&z5`J~0|j10C>3 zUbnR7!7!dsQqNpAT5lKa7rM}CorY%!Es%M?QF^x5=~Rs(SU4Rx#a5y3V>s@&u!U{5 zagw0}^3r41Dz5!}fw~RW7Yw7a8EpS7ia9kg8_%W_`FJ*$Q4@kLQ`s$Wa2$9#`dHHaHg>i_;=`mBGIn z^=jGZo2g?~1+Ur<PB(Tb}dq~lwzTvOC!ik;P^B>?>s^eF4swAT3~LWL*JVDV~m=TPsJrM#o4Wat$J;( zX74o}@bPTN&&-#7gZ4?oEm`oeeQGsqd(Ae=rrD@D+?wfa8N_tBubLp=HyclI=5HIN z@{Y^%isZ^tT)eunkX8~JITb+l9g2@-Q`wBV5QA<&en|zNQk|2fj7BF^RaT=86Qxt% zdIv@yG#L_k6^ehpESQ41v^o~R$btu4*4*p*9Uro{+}jp7E}$*$fjw_}w$nL!_rEIq z4;i$Jgd&(7nm#_UPBhOVPoDPFFly~040k=(?TSC&alylCm#nuI)gjTHDmL<*D#x(Cre9V7y-5CqJz!fw-z%%cK!q zdk2Ur_yj5w?VgnC-LgAaYGtlvbLm)CL_TZ&cv}oYX|z7;ubd!d*4-Y(Tuvqe+^NaQ zOR9=!a~`J*7{DHXDo%C>A39ynD8EIfX;WhQqpdA$OK4VLtu8O1uoMDUv$-7NWG*fS z(BMK#>Z>grIVR3hR23Bq4dB6I(OB0J9<4Ge^{z7Tw9&9#N=8;Rr@*|vl}YAE!Sja3 z;v!cyUM~i-;iCC!US0~@Cl)gXsvSPn<_PLfbfRrWaPP!pW0T4>%yyQNT|E^ZruEQ;>Zg_~_Nr{fVclH2&`2>;!q+LY1dsszURmP$yBSWgXz|3X8ZJ*ytT_i*Yb6v2$ID8t&Fl35yb9GEX9fOZPV0= zJevpv6aKAd;Gg1{LOR^b!I93{Cj8t{nbeG)Pw}6#@*y zZkWXyzUI*Ga2{JNt$|NmZ*SImTwiQ5I9Zjdb_GeA=QKLa2j%T;+pJslim?gTK73;h zA|ze3C(5;FkZ`fFXAFDWh7hij1%Y%@&5S9TY$lVA#p07FWRS+eIXVuVgop}%D5Yl! z-Gf==v6Iw9Hizy5e(U9W8I-U1SLA_e3_an=Ob+`E@jtJs3tBuAn}vWERuzMfqp%0!!tZa1FpAR-_!?mU5SeHZ(_*l@uJRbXj?xtf3LB?M+{NF0sqv}-0Z@ki(d*xPUfqDU|KPVo<_ zji$$SZSSecz3@DnxP3xkrmkw2;PSC)O(~fLWc-Rk-juQIVU&T>4`nu@MV+()N?>>r zDmAKtlzbuHbKZ-`DY#2tg&GPNcF5dH#WF+?x)7Q@Kdofq6fx`c_*hU$N2b&y_9oP) zl2f4&xSPCb!sI!T)_7NF-Ii3z=4*Xv=Bj)iZw=dU%QPvC$#P6g;U1I0x1za&SFyi@41hGIe*D5x^h%S;d z`h5|FV-2cV&9>pu%h~+AEc8lKY%Ro%WLlvJ(T3xRG4#i4TU%@Rh^FnC-Ojd+>Zxp& zU2$qQf{-N;NCIYNakN6oMwCTDi^^+_L#2>6y7%;&@9WV_w4cxPr;ETuW-dpEIqqkZ?-*=sM2-~g$;EFViggU>aqOC@`)*s$CVgg+T5`R#7o|$0>3aRh%QWsK{)q%=&I%0A`kQ;3^|I+0x;mZDsVKvZZIqu> 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,oaW% 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 YwhSYmJMFlk19=7vxcv?bMykGk0)Z=6o&W#< diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/[Content_Types].xml b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/[Content_Types].xml deleted file mode 100644 index 112d169942..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/[Content_Types].xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/asf-manifest.xml b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/asf-manifest.xml deleted file mode 100644 index bd969518a1..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/asf-manifest.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - FourWalledCubicle - LUFA - Dean Camera - - True - - - - 0 - - - content.xml.cache - - - - diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/extension.vsixmanifest b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/extension.vsixmanifest deleted file mode 100644 index 8475017443..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/extension.vsixmanifest +++ /dev/null @@ -1,33 +0,0 @@ - - - - - LUFA Library - Dean Camera - 0 - http://www.lufa-lib.org - LUFA, the Lightweight USB Framework for AVRs. - - License.txt - LUFA_thumb.png - LUFA.png - - - AtmelStudio - AtmelStudio - - - - 1033 - - false - - - - - - LUFA.pkgdef - helpcontentsetup.msha - asf-manifest.xml - - diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/generate_caches.py b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/generate_caches.py deleted file mode 100644 index eb4b71efdf..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/generate_caches.py +++ /dev/null @@ -1,38 +0,0 @@ -""" - 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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/lufa_asfmanifest_transform.xslt b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/lufa_asfmanifest_transform.xslt deleted file mode 100644 index 8fc98412fe..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/lufa_asfmanifest_transform.xslt +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - . - - . - - - - diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/lufa_vsmanifest_transform.xslt b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/lufa_vsmanifest_transform.xslt deleted file mode 100644 index db12d9ea26..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/VSIX/lufa_vsmanifest_transform.xslt +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/XDK/lufa_extension_transform.xslt b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/XDK/lufa_extension_transform.xslt deleted file mode 100644 index f50f8a4ddb..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/XDK/lufa_extension_transform.xslt +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - - - This file has been automatically generated from the LUFA Atmel Studio integration XML files. - - - - - - - - - - - - - - - - - - - - . - - . - - - - - - - - - - /html/ - - - - - - - - /html/ - - - - diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/XDK/lufa_filelist_transform.xslt b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/XDK/lufa_filelist_transform.xslt deleted file mode 100644 index 9affc9f67c..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/XDK/lufa_filelist_transform.xslt +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - Sourced from - - - - - - - - - - - - - - - diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/XDK/lufa_indent_transform.xslt b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/XDK/lufa_indent_transform.xslt deleted file mode 100644 index 166f42571c..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/XDK/lufa_indent_transform.xslt +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/XDK/lufa_module_transform.xslt b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/XDK/lufa_module_transform.xslt deleted file mode 100644 index ee9a050c1d..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/XDK/lufa_module_transform.xslt +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - - - - - - - - This file has been automatically generated from the LUFA Atmel Studio integration XML files. - - - - Sourced from - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa.xml b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa.xml deleted file mode 100644 index 86cfc0409d..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa.xml +++ /dev/null @@ -1,96 +0,0 @@ - - - - - - - - - Lightweight USB Framework for AVRs (LUFA), a USB software stack/framework. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_common.xml b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_common.xml deleted file mode 100644 index c2ef7af4c7..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_common.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_board.xml b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_board.xml deleted file mode 100644 index e150aa6458..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_board.xml +++ /dev/null @@ -1,114 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_board_names.xml b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_board_names.xml deleted file mode 100644 index ab7a3418eb..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_board_names.xml +++ /dev/null @@ -1,827 +0,0 @@ - - - - - - - - - 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). - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_misc.xml b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_misc.xml deleted file mode 100644 index 4311ae87b7..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_misc.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_peripheral.xml b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_peripheral.xml deleted file mode 100644 index 76ea516dbc..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_peripheral.xml +++ /dev/null @@ -1,198 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb.xml b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb.xml deleted file mode 100644 index 263c411dff..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class.xml b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class.xml deleted file mode 100644 index 67ab760d33..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_android.xml b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_android.xml deleted file mode 100644 index 3451712574..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_android.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - Common definitions and Host mode implementation of the Android Open Accessory USB class. - - - - - - - - - - - - - - - - - - - Common definitions only (no implementations) of the Android Open Accessory USB class. - - - - - - - - - - - - - - - - - diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_audio.xml b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_audio.xml deleted file mode 100644 index 5f7c3ad4d1..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_audio.xml +++ /dev/null @@ -1,109 +0,0 @@ - - - - - - - - - - - - - - - - - - Common definitions and Host/Device mode implementations of the Audio 1.0 USB class. - - - - - - - - - - - - - - - - - - - - - Common definitions and Host mode implementation of the Audio 1.0 USB class. - - - - - - - - - - - - - - - - - - - - Common definitions and Device mode implementation of the Audio 1.0 USB class. - - - - - - - - - - - - - - - - - - - - Common definitions only (no implementations) of the Audio 1.0 USB class. - - - - - - - - - - - - - - - - - - diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_cdc.xml b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_cdc.xml deleted file mode 100644 index 65d8cc98f7..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_cdc.xml +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - - - - - - - Common definitions and Host/Device mode implementations of the CDC USB class. - - - - - - - - - - - - - - - - - - - - - Common definitions and Host mode implementation of the CDC USB class. - - - - - - - - - - - - - - - - - - - - Common definitions and Device mode implementation of the CDC USB class. - - - - - - - - - - - - - - - - - - - - Common definitions only (no implementations) of the CDC USB class. - - - - - - - - - - - - - - - - - - diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_hid.xml b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_hid.xml deleted file mode 100644 index 3d533fb537..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_hid.xml +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - - - - - - - Common definitions and Host/Device mode implementations of the HID USB class. - - - - - - - - - - - - - - - - - - - - - Common definitions and Host mode implementation of the HID USB class. - - - - - - - - - - - - - - - - - - - - Common definitions and Device mode implementation of the HID USB class. - - - - - - - - - - - - - - - - - - - - Common definitions only (no implementations) of the HID USB class. - - - - - - - - - - - - - - - - - - diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_midi.xml b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_midi.xml deleted file mode 100644 index 3ddab0bbdd..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_midi.xml +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - - - - - - - Common definitions and Host/Device mode implementations of the MIDI USB class. - - - - - - - - - - - - - - - - - - - - - Common definitions and Host mode implementation of the MIDI USB class. - - - - - - - - - - - - - - - - - - - - Common definitions and Device mode implementation of the MIDI USB class. - - - - - - - - - - - - - - - - - - - - Common definitions only (no implementations) of the MIDI USB class. - - - - - - - - - - - - - - - - - - diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_ms.xml b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_ms.xml deleted file mode 100644 index 283b85ca7a..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_ms.xml +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - - - - - - - Common definitions and Host/Device mode implementations of the Mass Storage USB class. - - - - - - - - - - - - - - - - - - - - - Common definitions and Host mode implementation of the Mass Storage USB class. - - - - - - - - - - - - - - - - - - - - Common definitions and Device mode implementation of the Mass Storage USB class. - - - - - - - - - - - - - - - - - - - - Common definitions only (no implementations) of the Mass Storage USB class. - - - - - - - - - - - - - - - - - - diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_printer.xml b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_printer.xml deleted file mode 100644 index 2465035ce8..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_printer.xml +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - - - - - - - Common definitions and Host/Device mode implementations of the Printer USB class. - - - - - - - - - - - - - - - - - - - - - Common definitions and Host mode implementation of the Printer USB class. - - - - - - - - - - - - - - - - - - - - Common definitions and Device mode implementation of the Printer USB class. - - - - - - - - - - - - - - - - - - - - Common definitions only (no implementations) of the Printer USB class. - - - - - - - - - - - - - - - - - - diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_rndis.xml b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_rndis.xml deleted file mode 100644 index 6a606679d4..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_rndis.xml +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - - - - - - - Common definitions and Host/Device mode implementations of the RNDIS Ethernet USB class. - - - - - - - - - - - - - - - - - - - - - Common definitions and Host mode implementation of the RNDIS Ethernet USB class. - - - - - - - - - - - - - - - - - - - - Common definitions and Device mode implementation of the RNDIS Ethernet USB class. - - - - - - - - - - - - - - - - - - - - Common definitions only (no implementations) of the RNDIS Ethernet USB class. - - - - - - - - - - - - - - - - - - diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_si.xml b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_si.xml deleted file mode 100644 index c1bf8d560e..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_class_si.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - Common definitions and Host mode implementation of the Still Image USB class. - - - - - - - - - - - - - - - - - - - Common definitions only (no implementations) of the Still Image USB class. - - - - - - - - - - - - - - - - - diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_core.xml b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_core.xml deleted file mode 100644 index 58a0b388f6..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_core.xml +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_core_avr8.xml b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_core_avr8.xml deleted file mode 100644 index 4688f05f91..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_core_avr8.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_core_uc3.xml b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_core_uc3.xml deleted file mode 100644 index 2e7185f24a..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_core_uc3.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_core_xmega.xml b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_core_xmega.xml deleted file mode 100644 index c79a0f5b52..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_drivers_usb_core_xmega.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_platform.xml b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_platform.xml deleted file mode 100644 index 4ee51f6ee0..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_platform.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_platform_uc3.xml b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_platform_uc3.xml deleted file mode 100644 index 98017b08ad..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_platform_uc3.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_platform_xmega.xml b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_platform_xmega.xml deleted file mode 100644 index e613fe5206..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_platform_xmega.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_toolchain.xml b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_toolchain.xml deleted file mode 100644 index 723b3bec6f..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/lufa_toolchain.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/makefile b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/makefile deleted file mode 100644 index 2649598d9f..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/StudioIntegration/makefile +++ /dev/null @@ -1,140 +0,0 @@ -# -# 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 "\n" $(LUFA_VERSION_NUM) $(DOXYGEN_TAG_FILE_XML) $(DOXYGEN_COMBINED_XML) > $@ - @for i in $(XML_FILES); do \ - printf "\t\n" $$i >> $@; \ - done; - @echo '' >> $@ - -$(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/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Version.h b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Version.h deleted file mode 100644 index d3ee7f30eb..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/Version.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an 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 0x140302 - - /** Indicates the version number of the library, as a string. */ - #define LUFA_VERSION_STRING "140302" - -#endif - diff --git a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/doxyfile b/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/doxyfile deleted file mode 100644 index f903293706..0000000000 --- a/plugins/KeyboardioHID/Hoodloader_Source/lufa-LUFA-140302/LUFA/doxyfile +++ /dev/null @@ -1,2340 +0,0 @@ -# Doxyfile 1.8.6 - -# 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 - -# 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, 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 ... \endif and \cond -# ... \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. Do not use file names with spaces, bibtex cannot handle them. 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: -# -# -# -# where is the value of the INPUT_FILTER tag, and 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 acurate 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 an additional user- -# defined cascading style sheet that is 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 file to the output directory. 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. -# 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 + S -# (what the is depends on the OS and browser, but it is typically -# , /

    <<=@p{ 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%0A{K&0cz*(oG*D_; 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Ņ=HW)Oc)1J6L}CdC5#S;%6(Zzl&9@zdy-Bmd4ga%5Q@iiI(9zE z4~dr82Rc1ERUFu-3fZ#BjsZQU13nQd1chWp9E9x>Vu$);Af?a|IZlKun<E5uY{WJsAv7B$>k@Sn&SEUur@k3-H;u+o)HOxaJ6W_dnZ$+= zGD||MB9~J+Dlf!`W;JckgYg`Aig>O_7-?IoCrFI(Br(Q;OOi2GNZqJ~aTqy&Ge#~T z#C^f2gQ%g170f~YPbboAT? zh9qNLa1zEY5|SwxEAEe9oGg}$=bgk}jKM_XIiT^Ux=r~b@gw0Q*)wPNY_pg)xu=H28d)Wu}i6Y%a0S=B-Q;k|z)NikL7RM@LGYidER!g05bHt{)PyKX%C@#Br%L z+4Ds7T*)4vy6qZ}<0S5BkTZDXZsc%_7cWM7dOG&(*@Kdj5(G3fG@z=g3dP06QuN3I zX}T{wCP`kUakWu(xXF=2uCaXpk}gcKVY`syw2cEA>QAFwa>_08q7FMJJ*TdP(%KU! zu5Lup{$nVtq7Uge$cqK?D~{Nq<+PqIq9_sNX&ZYTPW=$5^$Tbl^8ychI}U9*x2Z0t zawcY9s4m$bf!Tk@eK>-B<#fTuArCk#%WA3c5Tkq^A?nO6JBZv;LCFE+2=*2Wit25M z`#B{CCApY{$|EYhUc` zi26)y_1pH>+~=0Zw)JM;Bs4~{9ycg`w3W4OOZ!0V6?N|^u19uJouC$3g*6Jbav80o zGE{ai^+UF8)@feYV~m~AhPf}cZCd(oUA|Y;yGJ~yd#HVCPqs;Y5pBxl0&1I{f4Pm= z-rhcqH;t)yy;jj{TfBbdYnU$Fp!bM)%}b2;i(GHJNJzd9<@?X};rVj;x5NC~!gMG! zu68VctGgY>KDj_WPPL$XkY96rYZZBnq+@3HL3hmW?rhkYAf1iejRY?(Elqwu9?jxa zR#qb5)TvWAdh{p`9y};TZ`-zQ2n`LDS7$KYjOT1TN<8~I9)9LEJoNM{c<{-W@xUKn z!u^sLasLwnaZAe|dg>Kf?vZC-6WhHmx0Us@R=+6wh}iDor(czIJouDo<4L0pQU85U zywJkqE%(i~ZP?0F-)LK^L-t41DeDz|cdYwG+$-w3=dr)w?nkXWui-Da#}h<-T8#Df z`X3?wj6M$&e?o8Kp+DiS2cHwz?)QG^&tkc)j4W@qVd7M`(O0V1fVP))7>{l3K5w*3 z>&&(+$Ue2SZ{JoO3(@wykNs7QqkwMh82z!gW2xJ~wyz56dUH&SKG+{StT)$L${5`B z5Y_n{{vhi9!-LP_&Ig`Bult`CJY_)lZO}R@LuGB-xoJbJqyEZzAF$O+w{~PbD$mF= zciwNdZ^c+|-`3U#v;96a<}}t~oXyw0`CgD?Ps{0jA>SLe_re48ex%pFd_U5Av6c5D z!!V41K7+S?`*yqF(YL0Qm6f5ct_}egE?hu!b2CnyIDx~552L!eTAsem&CQkHu|gZs zRT>Ei3G$L$`hq=zzD=3wK8zYQ$_~xg>dLf-v17+d%*P=iA@*e^v`pQ`#9Xgir?PnH z8+huCp;)Y0w>juzW!+*7ed8&79AqhDDJSduILNuo<{*6h)EgMO*m~buMrmX5P`qI; z=UMyavY?Nj!c(FyJLY;>=f?`o%B|<0Ynxk(ZI9(S;WDIXpT|OS5<+d9}5* z2)K0V63(ALkEW(3yXcYq(KH{;?B(U<$&IqIvgCKJkoXZ~i%j=n^5n^qu&^-g`t~w? z`gDo9Z0*{$_T_Y6U8kbkR>!)){&>EBAl7Nt?VLYQS+@>>{h!Cc`Ia)4awRk(rHyrg=x;CQS^Ktao_FYj!#>LO12NxNXUEgF>{$BhfM)x(L-54) zPhe=6vdqpb^i$TY9r6UO?>Ea*#!^n!*AKIt%Iw6fe%IrPp|;ngdf!^6rH!>1@l3xnAvq!#>*9_nT#`v*T%7Ejad7hvWD$48ybq)5XZk$j|6XT9P~Z93J@_dEDW{ bhw=XdEHwHUp@^xg00000NkvXXu0mjfs^OjO diff --git a/plugins/KeyboardioHID/Firmwares/Flip_3.PNG b/plugins/KeyboardioHID/Firmwares/Flip_3.PNG deleted file mode 100644 index 32439649a45a444e98323b8921b70016724fe956..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 74966 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
  • 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 diff --git a/plugins/KeyboardioHID/Firmwares/Hoodloader1_6.hex b/plugins/KeyboardioHID/Firmwares/Hoodloader1_6.hex new file mode 100644 index 0000000000..2ed4f7bcd5 --- /dev/null +++ b/plugins/KeyboardioHID/Firmwares/Hoodloader1_6.hex @@ -0,0 +1,474 @@ +:1000000073C100008DC100008BC1000089C10000D8 +:1000100087C1000085C1000083C1000081C10000CC +:100020007FC100007DC100007BC100000C94670807 +:100030000C94100975C1000073C1000071C100006B +:100040006FC100006DC100006BC1000069C10000FC +:1000500067C1000065C1000063C1000009C2000063 +:100060005FC100005DC100005BC1000059C100001C +:1000700057C1000030034100720064007500690040 +:100080006E006F00200048006F006F0064006C007D +:100090006F0061006400650072002000420065008E +:1000A00074006100000012034E00690063006F00DD +:1000B00048006F006F006400000004030904090297 +:1000C0005F00030100C032080B00020202010009B8 +:1000D00004000001020201000524001001042402B2 +:1000E000060524060001070582030800FF09040134 +:1000F00000020A0000000705040240000107058312 +:10010000024000010904020001030000000921115E +:1001100001000122B801070581032000011201102E +:1001200001EF020108EB03686E16000102DC010515 +:10013000010902A1010901A100850105091901298F +:10014000051500250195057501810295017503814D +:100150000305010930093109381581257F75089596 +:10016000038106C0C005010906A101850205071922 +:10017000E029E715002501750195088102950175B3 +:1001800008810395067508150025650507190029DE +:1001900065810005081901290595057501910295EC +:1001A0000175039103C006C0FF0A000CA10185037D +:1001B0007508150026FF00953F09018102953F094A +:1001C000029102C0050C0901A1018504150026FF5A +:1001D000FF19002AFFFF950475108100C005010971 +:1001E00080A1018505150026FF00190029FF950152 +:1001F00075088100C005010905A1018506050919D9 +:10020000012920150025017501952081020501A114 +:10021000000930093109320933093409351500273D +:10022000FFFF0000751095068102C005010939091C +:100230003915012508950275048102C005010905DB +:10024000A10185070509190129201500250175015E +:10025000952081020501A1000930093109320933D5 +:1002600009340935150027FFFF0000751095068138 +:1002700002C0093909391501250895027504810262 +:10028000C005010904A1018508A10005091901297A +:100290000215002501750195028102050109300949 +:1002A00031150026FF03750A95028102750295013A +:1002B0008103C0C005010904A1018509A100050948 +:1002C0001901290215002501750195028102050118 +:1002D00009300931150026FF03750A950281027560 +:1002E0000295018103C0C00011241FBECFEFD2E0F0 +:1002F000DEBFCDBF11E0A0E0B1E0EEE5FDE102C060 +:1003000005900D92AE32B107D9F712E0AEE2B1E03E +:1003100001C01D92A434B107E1F720D30C94AD0EB7 +:100320006FCECF93DF9384B7877F84BF28E10FB66A +:10033000F89420936000109260000FBE80E190E07E +:100340009093CD008093CC00CAECD0E096E09883E7 +:10035000A8ECB0E082E08C93E9ECF0E02083539AC3 +:100360005A9A5B9A10821C92188298838C9388E91F +:1003700080835B988AB180638AB98BB180638BB9C3 +:1003800097D684E085BD5F9A579A84B184B9229844 +:100390002A9ADF91CF9108950895089580E091E021 +:1003A0000E94950D80E191E00E94D20AE2EEF0E019 +:1003B00080818460808308951F93CF93DF93EC0145 +:1003C000E98DE150E23028F4F0E0E55DFE4F108168 +:1003D00001C010E0888D823009F418608A8D873062 +:1003E00031F0883031F0863029F4126003C0146097 +:1003F00001C016605B9A1092C9001092C80010925A +:10040000CA002C893D894E895F89211581EE380704 +:100410004105510579F0CA01B901969587957795FF +:10042000679560587B47814E9F4F0E946E0E21500A +:10043000310902C020E130E03093CD002093CC00A0 +:100440001093CA008C899D89AE89BF898115914E10 +:10045000A105B10511F480E001C082E08093C800DD +:1004600088E98093C9005B98DF91CF911F9108952F +:100470001F920F920FB60F9211242F933F938F93D9 +:100480009F93AF93BF93EF93FF938091CE00909192 +:100490002E019430F9F090913B029430D9F4EFE2C0 +:1004A000F1E0A081B1818C9380819181019691834B +:1004B0008083268137818217930721F48481958177 +:1004C000918380832FB7F8948285938501969387D3 +:1004D00082872FBFFF91EF91BF91AF919F918F9135 +:1004E0003F912F910F900FBE0F901F901895FC0118 +:1004F000208920FF02C05F9808955F9A8BB18063C6 +:100500008BB9089580E191E00E94AB0B80E091E00F +:100510000C945E0C80910E0190910F01009729F0D0 +:10052000019790930F0180930E010895EF92FF922F +:100530000F931F93CF93DF937B01C901E8012091B3 +:10054000BD012223E1F04091BE012091BF01421381 +:1005500016C0E0ECF1E050E0BF010E949D0E8091DA +:10056000BD01F70180838091BE01888319821092BA +:10057000BD011092BF011092BE0181E001C080E078 +:10058000DF91CF911F910F91FF90EF9008950F93FE +:100590001F93C901633039F45C986093BC01B801C2 +:1005A0001F910F9126C31F910F91089510920B0276 +:1005B0001092FF010895462F209111012F70209372 +:1005C000E9002091E80020FFFCCF2091200120FFCE +:1005D00006C050E0BC0180E191E00C94F70A089558 +:1005E000CF92DF92EF92FF920F931F93FA018B014C +:1005F0000095109520E030E0980111270027AB010D +:1006000060E070E0042B152B262B372B4CE150E0DB +:1006100097E068017901042E04C0F694E794D7941A +:10062000C7940A94D2F76C2D683028F0973059F4AB +:10063000C08296E008C0C0829150C11004C04750EB +:100640005109923031F7492F425013C0DF01A40FF6 +:10065000B11D68017901E894C7F8DD24EE24FF2478 +:10066000CC92B7E03695279517950795BA95D1F7AF +:1006700041504111EBCF492F50E09A01A3E0220FE6 +:10068000331FAA95E1F7206C3F6F3081322B308306 +:10069000E40FF51F319781508F7380688083892F15 +:1006A0001F910F91FF90EF90DF90CF900895CF931F +:1006B000DF9300D000D000D0CDB7DEB76091BD0190 +:1006C000662379F08091BF0181110BC070E07160E9 +:1006D000AE014F5F5F4F81E083DF682FCE0101964F +:1006E0006ADF1092BD0126960FB6F894DEBF0FBEEA +:1006F000CDBFDF91CF9108950F931F93982F409115 +:100700000B02E42FF0E0EB5FFD4F808380910B0242 +:100710008F5F80930B02892F807C803809F444C05E +:10072000803C09F05FC0292F2873269526952695D1 +:10073000223008F477C0273079F4492F4F7050E009 +:1007400060E070E040930002509301026093020267 +:100750007093030215E00FC0892F877090E0A0E02E +:10076000B0E08093000290930102A0930202B09344 +:100770000302122F11508091FF01882391F097DF1F +:1007800060910B02615085E092E015DFE0910B0271 +:10079000F0E0EC5FFD4F80818093050281E0809363 +:1007A0000B021093FF0145C08091FF018130D1F50C +:1007B0000091000210910102209102023091030287 +:1007C000A901662777272227332740275127622749 +:1007D00073274F3F5F4F6105710521F5892F8F7397 +:1007E0008F5F28C08091FF018230E0F081508093BC +:1007F000FF0140910002509101026091020270914C +:10080000030227E0440F551F661F771F2A95D1F773 +:10081000492B4093000250930102609302027093AF +:10082000030207C044DF60910B0285E092E0C3DE63 +:10083000BDDE80E01F910F910895CF935DDFC82F3B +:10084000882309F489C08091BD01811104C0C130A1 +:1008500009F046C010C09091BE018091BF0198136D +:10086000F6CF04C080E091E00E94AA0D8091BD0106 +:100870008111F8CFECCF80910102813089F517DF2B +:10088000909100029093BD011092BF018FE3E0ECC4 +:10089000F1E0DF01282F1D922A95E9F79530A9F0A4 +:1008A00058F4923081F018F49130C1F40AC09330BA +:1008B00091F0943099F407C0983050F09A3070F469 +:1008C00009C084E008C088E006C0C093BE0142C0F1 +:1008D00081E101C083E08093BE013CC0E8DE3AC004 +:1008E0008091BD01882381F16091BF01462F50E0C6 +:1008F0008C2F90E09A012E5F3F4F359527952F5F03 +:100900003F4F8217930701F5FA01E054FE4F8091A3 +:1009100000028083E62FEF5FE093BF018091BE016C +:100920008E1749F0F0E0E054FE4F90910102908361 +:100930006E5F6093BF019091BF0189130BC080E08F +:1009400091E00E94AA0D06C0B2DE60910B0285E024 +:1009500092E031DECF912ACECF910895E2DC109261 +:100960002E01EFE2F1E02FB7F8948BE391E0918351 +:10097000808393838283958384838BEB91E0978339 +:10098000868380E890E091878087138612862FBF48 +:100990007894E2E08E2E0FE211E0CBE3D1E0FBEBA6 +:1009A000EF2EF1E0FF2EA0E8CA2ED12CB3E09B2E53 +:1009B0008091240190912501A0912601B0912701F9 +:1009C00020912E010097A105B10529F08115924CC7 +:1009D000A140B10529F52430B9F4F8018FB7F89496 +:1009E000D183C083D383C283D583C483F782E68255 +:1009F000D186C086138612868FBF1092BB011092DB +:100A0000BC018BB180638BB91A9B11C080912E0100 +:100A1000823019F0CBDD1092BD0180922E0109C009 +:100A2000243029F410922F011092300102C010924C +:100A30002E0180E191E061D697FD09C05C9890920B +:100A4000BC019091C80095FFFCCF8093CE002FB7DA +:100A5000F8948091390190913A012FBF009719F4D1 +:100A6000A89949C068C05D989092BB01209111017E +:100A70002F702093E9002091E80020FFF1CF80340F +:100A8000910510F08FE390E0782EA12CB12C30C0AE +:100A900080912E01882361F0F801A281B3818D91AC +:100AA000B383A28326813781A217B30781F40BC0D9 +:100AB000E0913101F0913201608180E191E0B5D5A2 +:100AC000882351F3CDCF24813581338322839FB78F +:100AD000F8942285338521503109338722879FBFBF +:100AE00090912E01923009F4A8DE8FEFA81AB80A6F +:100AF0007A10CECFB5CFA89A8091BB01882389F018 +:100B000081508093BB0181110CC080912E018230F5 +:100B100039F4CDDD60910B0285E092E04CDD46DDDD +:100B20005D9A8091BC01882331F081508093BC0193 +:100B3000811101C05C9A80912E01823021F480E005 +:100B400091E00E94AA0D80E191E0C1D50FD530CF90 +:100B5000292F332723303105B1F04CF421303105F2 +:100B600009F439C02230310509F03AC007C02132FA +:100B7000310539F12232310549F132C0EFE5F0E0BB +:100B80008EEB90E031C099278130910561F0823081 +:100B9000910581F0892B21F5EAEBF0E0E491F0E09A +:100BA0008AEB90E021C0E6EAF0E0E491F0E086EA2A +:100BB00090E01AC0E4E7F0E0E491F0E084E790E030 +:100BC00013C0E9E0F0E08DE091E00EC0E8EBF1E069 +:100BD0008FE291E009C0E2E1F0E08DE191E004C034 +:100BE000E0E0F0E080E090E0DA018D939C93CF01AB +:100BF0000895680F791F09C0FC012191CF01309140 +:100C0000C80035FFFCCF2093CE0086179707A1F7C9 +:100C10000895BF92CF92DF92EF92FF920F931F93AE +:100C2000CF93DF937C018B01EA01D7D1B82E8111DC +:100C300032C0209731F028813981021B130BE20E5C +:100C4000F31EC12CD12C22C08091E80085FD14C078 +:100C50008091E8008E778093E800209749F08881A2 +:100C600099818C0D9D1D9983888325E0B22E13C038 +:100C7000B4D1882359F00EC0F70181917F01809390 +:100C8000F10001501109FFEFCF1ADF0A011511051C +:100C9000D9F601C0B82E8B2DDF91CF911F910F9106 +:100CA000FF90EF90DF90CF90BF9008952091420287 +:100CB000309143022617370748F06115710539F462 +:100CC0002091E8002E772093E80001C0B9019C0133 +:100CD00080E034C090913B02992309F443C09530E1 +:100CE00009F442C09091E80093FD3AC09091E80069 +:100CF00092FD30C09091E80090FF20C08091F200FA +:100D000090E0F901821B930B05C021912093F10023 +:100D1000615071099F01280F391F6115710519F084 +:100D20002830310590F381E02830310509F080E06A +:100D30009091E8009E779093E8009F0161157105FE +:100D400049F68111C7CF06C080913B02882351F03C +:100D5000853051F08091E80082FFF6CF80E0089561 +:100D600081E0089582E0089583E00895611571059A +:100D700029F42091E8002B772093E8009C0121C002 +:100D800080913B02882381F1853041F18091E80018 +:100D900083FD26C08091E80082FFF2CFF90107C0F1 +:100DA0008091F10081939F016150710929F09F01A9 +:100DB0008091F2008111F4CF8091E8008B778093CD +:100DC000E80061157105E1F68091E80080FD0AC038 +:100DD00080913B02882341F08530B1F783E008958C +:100DE00081E0089580E0089582E008952091420214 +:100DF000309143022617370748F06115710539F421 +:100E00002091E8002E772093E80001C0B9019C01F1 +:100E100080E035C090913B02992309F444C095309D +:100E200009F443C09091E80093FD3BC09091E80025 +:100E300092FD31C09091E80090FF21C08091F200B6 +:100E400090E0F901821B930B06C024912093F100DE +:100E50003196615071099C012E0F3F1F611571057C +:100E600019F02830310588F381E02830310509F088 +:100E700080E09091E8009E779093E8009F016115D3 +:100E8000710541F68111C6CF06C080913B028823CF +:100E900051F0853051F08091E80082FFF6CF80E07C +:100EA000089581E0089582E0089583E00895982FE1 +:100EB0002CC09093E900981739F07091EC002091C4 +:100EC000ED005091F00003C0242F762F50E021FD5B +:100ED00002C09F5F1AC03091EB003E7F3093EB0061 +:100EE0003091ED003D7F3093ED003091EB003160AB +:100EF0003093EB007093EC002093ED005093F000E2 +:100F00002091EE0027FDE5CF07C0953090F28F705D +:100F10008093E90081E0089580E008950F931F9386 +:100F2000CF93DF93062FEC0110E02EC09881911132 +:100F300003C01F5F259628C02C81E981FA816B814F +:100F4000892F8F70853010F080E021C0223010F0A2 +:100F500056E001C052E028E030E040E003C04F5FBF +:100F6000220F331F2E173F07D0F34295407F452BAA +:100F7000991F9927991F6295660F660F607C692BF0 +:100F800096DF8111D6CFE0CF1013D0CF81E0DF9173 +:100F9000CF911F910F91089580913C0287FD05C06C +:100FA0008091E80080FF0EC012C08091E80082FDB1 +:100FB00005C080913B028111F8CF08958091E8002F +:100FC0008B7708C080913B028111EACF0895809110 +:100FD000E8008E778093E80008958091E400909176 +:100FE000E50045E62091EC0020FD1FC023C02091C4 +:100FF0003B02222391F0253091F02091EB0025FD5A +:1010000010C02091E4003091E5002817390751F312 +:101010004150C90139F784E0089582E0089583E0E2 +:10102000089581E0089580E008952091E80020FF70 +:10103000DECFF9CF2091E80022FFD9CFF4CF41D005 +:1010400043D08091D8008F778093D8008091D800CA +:1010500080688093D8008091D8008F7D8093D800DD +:1010600084E089BD86E089BD09B400FEFDCF109201 +:101070003B0210923702109239021092380242E07D +:1010800060E080E014DF8091E1008E7F8093E100DA +:101090008091E20081608093E2008091E2008860AC +:1010A0008093E2008091E0008E7F8093E0000895BD +:1010B000E3E6F0E080818E7F808381E080933A02D6 +:1010C000BECF1092E20008951092E10008951F92A1 +:1010D0000F920FB60F9211242F933F934F935F936C +:1010E0006F937F938F939F93AF93BF93EF93FF93F0 +:1010F0008091E10082FF0AC08091E20082FF06C079 +:101100008091E1008B7F8093E10004DA8091E1001F +:1011100080FF17C08091E20080FF13C08091E20041 +:101120008E7F8093E2008091E20080618093E200F4 +:101130008091D80080628093D80019BC10923B0245 +:101140002CD98091E10084FF2FC08091E20084FFC0 +:101150002BC084E089BD86E089BD09B400FEFDCFC7 +:101160008091D8008F7D8093D8008091E1008F7EA0 +:101170008093E1008091E2008F7E8093E200809175 +:10118000E20081608093E20080913702882311F0B1 +:1011900084E007C08091E30087FF02C083E001C0C4 +:1011A00081E080933B02F8D88091E10083FF27C063 +:1011B0008091E20083FF23C08091E100877F8093CC +:1011C000E10082E080933B02109237028091E100BF +:1011D0008E7F8093E1008091E2008E7F8093E20019 +:1011E0008091E20080618093E20042E060E080E074 +:1011F0005EDE8091F00088608093F000B6D1FF91B0 +:10120000EF91BF91AF919F918F917F916F915F917E +:101210004F913F912F910F900FBE0F901F901895F7 +:101220001F920F920FB60F9211242F933F934F935B +:101230005F936F937F938F939F93AF93BF93CF935E +:10124000EF93FF938091E9008F709091EC0090FFF5 +:1012500002C090E801C090E0C92FC82B1092E900AD +:101260008091F000877F8093F00078941CD01092DA +:10127000E9008091F00088608093F000CF70C09307 +:10128000E900FF91EF91CF91BF91AF919F918F9125 +:101290007F916F915F914F913F912F910F900FBE72 +:1012A0000F901F9018951F93CF93DF93CDB7DEB7A4 +:1012B000AC970FB6F894DEBF0FBECDBFECE3F2E003 +:1012C0008091F100819322E0E434F207C9F71AD942 +:1012D0008091E80083FF31C180913C0290913D02F2 +:1012E000953009F487C038F49130B1F170F0933043 +:1012F00009F023C131C0983009F4F3C0993009F4E2 +:10130000FFC0963009F019C19BC0803821F08238A7 +:1013100009F013C108C080913802909139029923D5 +:1013200089F082600FC080914002909141028F70DD +:1013300099278093E9008091EB0085FB882780F94D +:101340001092E9009091E800977F9093E8008093D5 +:10135000F1001092F100D0C0882319F0823009F01A +:10136000ECC08F7121F0823009F0E7C00BC0809192 +:101370003E02813009F0E1C0933009F080E08093B3 +:1013800039022FC080913E0281112BC08091400212 +:10139000909141028F709927009709F4CEC08093F5 +:1013A000E9002091EB0020FF1CC020913D0223307A +:1013B00021F48091EB00806212C09091EB0090616B +:1013C0009093EB0021E030E001C0220F8A95EAF70C +:1013D0002093EA001092EA008091EB0088608093ED +:1013E000EB001092E9008091E800877F8093E8008D +:1013F000D3DDA3C08111A1C080913E0290913F0234 +:101400008F779927182F9091E3009078982B9093DD +:10141000E3008091E800877F8093E800BDDD809144 +:10142000E80080FFFCCF8091E30080688093E300B8 +:10143000112311F083E001C082E080933B027DC064 +:101440008058823008F079C080913E0290913F022E +:101450008C3D23E0920771F583E08A838AE28983D9 +:101460004FB7F894DE01139620E03EE051E2E32FFF +:10147000F0E050935700E49120FF03C0E295EF7035 +:101480003F5FEF708E2F90E0EA3010F0C79601C0FA +:10149000C0968D939D932F5F243149F74FBF809164 +:1014A000E800877F8093E8006AE270E0CE01019651 +:1014B000FDDB11C0AE01455D5F4F6091400248DB2E +:1014C0000097D9F12091E800277F2093E800BC0124 +:1014D0008BA59CA58BDC8091E8008B778093E8003E +:1014E0002CC0803851F58091E800877F8093E80018 +:1014F000809137028093F1008091E8008E7776CF5B +:1015000081111BC090913E029230B8F48091E800A6 +:10151000877F8093E800909337023EDD8091370209 +:10152000811104C08091E30087FF02C084E001C004 +:1015300081E080933B020E94CE018091E80083FF0E +:101540000AC08091E800877F8093E8008091EB00DB +:1015500080628093EB00AC960FB6F894DEBF0FBEAE +:10156000CDBFDF91CF911F9108950895CF938091C2 +:101570003B028823A9F08091E9008F709091EC00E4 +:1015800090FF02C090E801C090E0C92FC82B1092D4 +:10159000E9008091E80083FD86DECF70C093E9000A +:1015A000CF910895CF93DF93EC014096FC018BE03F +:1015B000DF011D928A95E9F782E08C83898783E0B9 +:1015C0008E8761E0CE010196A9DC882361F061E09D +:1015D000CE010696A3DC882331F061E0CE010B96A4 +:1015E000DF91CF919BCC80E0DF91CF9108950F9355 +:1015F0001F93FC01CB01BA0120913B02243089F4F6 +:101600000489158926893789012B022B032B49F080 +:1016100021812F702093E90040E050E01F910F914D +:10162000F8CA82E01F910F910895CF93C62F2091A1 +:101630003B022430F1F4FC0144895589668977899D +:10164000452B462B472BA9F081818F708093E900B1 +:101650008091E80085FF04C0C093F10080E00AC0DB +:101660008091E8008E778093E800B7DC8823A1F3AF +:1016700001C082E0CF91089520913B02243029F5EA +:10168000FC014489558966897789452B462B472B70 +:10169000E1F081818F708093E9008091F2008111E7 +:1016A00002C080E008959091E8008091E8008E7774 +:1016B0008093E80095FDF5CF90DC811107C09091F3 +:1016C000E8009E779093E800089582E008952091C5 +:1016D0003B02243089F4FC01448955896689778965 +:1016E000452B462B472B41F021812F702093E90099 +:1016F0002091E80020FDC0CF089520913B022430C6 +:1017000019F02FEF3FEF24C0FC0144895589668909 +:101710007789452B462B472BA1F386818F708093C9 +:10172000E9008091E80082FFECCF8091F2008823ED +:1017300021F02091F10030E002C02FEF3FEF8091C7 +:10174000F200811105C08091E8008B778093E8005A +:10175000C90108950895CF93DF93EC018091E800CB +:1017600083FFA9C0888190E020914002309141021E +:101770002817390709F09FC080913D02813261F03E +:1017800020F4803209F097C03DC0823209F46EC067 +:10179000833209F090C07FC080913C02813A09F009 +:1017A0008AC08091E800877F8093E8008091E800FC +:1017B00080FFFCCF4C895D896E897F894093F10061 +:1017C000BB27A72F962F852F8093F100CB01AA2747 +:1017D000BB278093F100472F552766277727409333 +:1017E000F100888D8093F100898D8093F1008A8DBE +:1017F0008093F1008091E8008E778093E800DF917C +:10180000CF91CACB80913C02813209F054C08091C3 +:10181000E800877F8093E80005C080913B02882321 +:1018200009F449C08091E80082FFF7CF3091F100C0 +:101830002091F1009091F1008091F1003C8B2D8B73 +:101840009E8B8F8B8091F100888F8091F100898F22 +:101850008091F1008A8F8091E8008B778093E80077 +:101860009BDBCE01DF91CF910C94DC0180913C0297 +:10187000813209F58091E800877F8093E8008CDB56 +:1018800080913E0290913F02998B888BCE01DF912F +:10189000CF910C94770280913C02813261F4809167 +:1018A000E800877F8093E80077DB60913E02CE01FD +:1018B000DF91CF914FCFDF91CF9108956F927F92BB +:1018C0008F929F92AF92BF92CF92DF92EF92FF9250 +:1018D0000F931F93CF93DF9300D01F92CDB7DEB746 +:1018E0007C01ADB6BEB68091E80083FF07C1F70169 +:1018F000808190E020914002309141022817390701 +:1019000009F0FCC080913D02833009F49EC030F4A0 +:10191000813071F0823009F0F1C0D4C08A3009F40E +:10192000B9C08B3009F4A2C0893009F0E7C04CC0BF +:1019300080913C02813A09F0E1C08DB69EB61A82D0 +:10194000198280913E0210913F028B83F7014085FE +:101950008DB79EB7841B91090FB6F8949EBF0FBE3A +:101960008DBFCDB6DEB6EFEFCE1ADE0A360150E0FF +:1019700060E070E0C601EAD1412F41508E010F5F57 +:101980001F4F9601BE016D5F7F4FC7010E949602F7 +:10199000F701268137812115310529F0408550E076 +:1019A000B601C901CAD11092E9008091E800877F91 +:1019B0008093E80069817A81C30178D98091E80039 +:1019C0008B778093E80039C080913C02813209F026 +:1019D00095C08DB69EB60091420210914302709060 +:1019E0003E0260903F028DB79EB7801B910B0FB6F1 +:1019F000F8949EBF0FBE8DBFCDB6DEB6EFEFCE1A08 +:101A0000DE0A8091E800877F8093E800B801C60174 +:101A1000ADD98091E8008E778093E80021E07110C5 +:101A200001C020E030E0021B130B2C0D3D1D462DA4 +:101A30004150672DC7010E94C702882D992D0FB60E +:101A4000F8949EBF0FBE8DBF59C080913C02813A71 +:101A500009F054C08091E800877F8093E80080916E +:101A6000E80080FFFCCFF701818540C080913C02F7 +:101A7000813209F043C08091E800877F8093E800BD +:101A80008BDA90913E0281E0911101C080E0F70174 +:101A9000818734C080913C02813281F58091E800D9 +:101AA000877F8093E80078DA80913E0290913F0230 +:101AB000882736E0969587953A95E1F7F70195875F +:101AC00084871CC080913C02813AC1F48091E80077 +:101AD000877F8093E8008091E80080FFFCCFF701CA +:101AE0008485958596958795969587958093F10041 +:101AF0008091E8008E778093E8004EDA0FB6F89474 +:101B0000BEBE0FBEADBE0F900F900F90DF91CF9174 +:101B10001F910F91FF90EF90DF90CF90BF90AF900B +:101B20009F908F907F906F9008959C01275F3F4F0B +:101B3000F90127E0DF011D922A95E9F721E0FC0178 +:101B4000218724EF31E03587248723E0248361E077 +:101B50000196E4C94F925F926F927F928F929F920B +:101B6000AF92BF92CF92DF92EF92FF920F931F93AB +:101B7000CF93DF9300D01F92CDB7DEB77C01ADB617 +:101B8000BEB680913B02843009F08FC08091E400A2 +:101B90009091E500F701228533852817390709F46C +:101BA00084C081818F708093E9008091E80085FF77 +:101BB0007CC06DB67EB640858DB79EB7841B9109FB +:101BC0000FB6F8949EBF0FBE8DBFCDB6DEB6EFEF59 +:101BD000CE1ADE0A1B821A821982460150E060E0AA +:101BE00070E0C601B3D08E010F5F1F4F960140E039 +:101BF000BE016D5F7F4FC7010E949602582EF7010C +:101C000084859585892B31F001E010E086859785E4 +:101C1000892B11F000E010E0F701C680D780C114D5 +:101C2000D10489F049815A81B601C40179D0442494 +:101C30004394009709F4412CF701408550E0B4012A +:101C4000C6017BD001C0412C89819A81892BF9F092 +:101C5000511004C0411002C000FF19C0F701848573 +:101C600095859787868781818F708093E9008B8126 +:101C700081118093F10069817A8140E050E0C401D4 +:101C80000E9409068091E8008E778093E800809199 +:101C9000E4009091E500F70193878287862D972DC8 +:101CA0000FB6F8949EBF0FBE8DBF0FB6F894BEBEA0 +:101CB0000FBEADBE0F900F900F90DF91CF911F918F +:101CC0000F91FF90EF90DF90CF90BF90AF909F90DB +:101CD0008F907F906F905F904F900895A1E21A2EA1 +:101CE000AA1BBB1BFD010DC0AA1FBB1FEE1FFF1FC0 +:101CF000A217B307E407F50720F0A21BB30BE40B10 +:101D0000F50B661F771F881F991F1A9469F7609556 +:101D10007095809590959B01AC01BD01CF01089510 +:101D2000FB01DC0104C08D910190801921F4415028 +:101D30005040C8F7881B990B0895FB01DC0102C0D5 +:101D400001900D9241505040D8F70895DC0101C038 +:0E1D50006D9341505040E0F70895F894FFCF96 +:101D5E0002812000000100003F0000000000000092 +:101D6E0000834000000104400000018208000001D1 +:0E1D7E00000000000000000000000030200007 +:00000001FF diff --git a/plugins/KeyboardioHID/Firmwares/Hoodloader1_7.hex b/plugins/KeyboardioHID/Firmwares/Hoodloader1_7.hex new file mode 100644 index 0000000000..156b82aebd --- /dev/null +++ b/plugins/KeyboardioHID/Firmwares/Hoodloader1_7.hex @@ -0,0 +1,605 @@ +:1000000073C100008DC100008BC1000089C10000D8 +:1000100087C1000085C1000083C1000081C10000CC +:100020007FC100007DC100007BC100000C94770CF3 +:100030000C94230D75C1000073C1000071C1000054 +:100040006FC100006DC100006BC1000069C10000FC +:1000500067C1000065C1000063C1000012C200005A +:100060005FC100005DC100005BC1000059C100001C +:1000700057C1000030034100720064007500690040 +:100080006E006F00200048006F006F0064006C007D +:100090006F0061006400650072002000420065008E +:1000A00074006100000012034E00690063006F00DD +:1000B00048006F006F006400000004030904090297 +:1000C0005F00030100C032080B00020202010009B8 +:1000D00004000001020201000524001001042402B2 +:1000E000060524060001070582030800FF09040134 +:1000F00000020A0000000705040240000107058312 +:10010000024000010904020001030000000921115E +:1001100001000122B801070581032000011201102E +:1001200001EF020108EB03686E17000102DC010514 +:10013000010902A1010901A100850105091901298F +:10014000051500250195057501810295017503814D +:100150000305010930093109381581257F75089596 +:10016000038106C0C005010906A101850205071922 +:10017000E029E715002501750195088102950175B3 +:1001800008810395067508150025650507190029DE +:1001900065810005081901290595057501910295EC +:1001A0000175039103C006C0FF0A000CA10185037D +:1001B0007508150026FF00953F09018102953F094A +:1001C000029102C0050C0901A1018504150026FF5A +:1001D000FF19002AFFFF950475108100C005010971 +:1001E00080A1018505150026FF00190029FF950152 +:1001F00075088100C005010905A1018506050919D9 +:10020000012920150025017501952081020501A114 +:10021000000930093109320933093409351500273D +:10022000FFFF0000751095068102C005010939091C +:100230003915012508950275048102C005010905DB +:10024000A10185070509190129201500250175015E +:10025000952081020501A1000930093109320933D5 +:1002600009340935150027FFFF0000751095068138 +:1002700002C0093909391501250895027504810262 +:10028000C005010904A1018508A10005091901297A +:100290000215002501750195028102050109300949 +:1002A00031150026FF03750A95028102750295013A +:1002B0008103C0C005010904A1018509A100050948 +:1002C0001901290215002501750195028102050118 +:1002D00009300931150026FF03750A950281027560 +:1002E0000295018103C0C00011241FBECFEFD2E0F0 +:1002F000DEBFCDBF11E0A0E0B1E0E6E8F5E202C06C +:1003000005900D92AE32B107D9F712E0AEE2B1E03E +:1003100001C01D92A634B107E1F786D70C94C11233 +:100320006FCE9BB1809589238BB908959BB1982B93 +:100330009BB90895CF93DF9384B7877F84BF28E16B +:100340000FB6F89420936000109260000FBE80E119 +:1003500090E09093CD008093CC00CAECD0E096E082 +:100360009883A8ECB0E082E08C93E9ECF0E0208385 +:10037000539A5A9A5B9A10821C92188298838C9393 +:1003800088E980835B988AB180638AB98BB1806386 +:100390008BB90E94680C84E085BD5F9A579A209AB9 +:1003A00022982A9ADF91CF9108950895089580E0C8 +:1003B00091E00E94A91180E191E00E94E60EE2EE38 +:1003C000F0E080818460808308951F93CF93DF9352 +:1003D000EC01E98DE150E23028F4F0E0E55DFE4FFC +:1003E000108101C010E0888D823009F418608A8D78 +:1003F000873031F0883031F0863029F4126003C044 +:10040000146001C016605B9A1092C9001092C80077 +:100410001092CA002C893D894E895F89211581EE91 +:1004200038074105510579F0CA01B90196958795BC +:100430007795679560587B47814E9F4F0E94821247 +:100440002150310902C020E130E03093CD002093EB +:10045000CC001093CA008C899D89AE89BF89811513 +:10046000914EA105B10511F480E001C082E08093B6 +:10047000C80088E98093C9005B98DF91CF911F91F4 +:1004800008951F920F920FB60F9211242F933F934E +:100490008F939F93AF93BF93EF93FF938091CE0081 +:1004A00090912E019330F9F090913D029430D9F45F +:1004B000EFE2F1E0A081B1818C938081918101967E +:1004C00091838083268137818217930721F4848169 +:1004D0009581918380832FB7F894828593850196C7 +:1004E000938782872FBFFF91EF91BF91AF919F912B +:1004F0008F913F912F910F900FBE0F901F901895E5 +:10050000FC01208920FF02C05F9808955F9A8BB19B +:1005100080638BB9089580E191E00E94BF0F80E075 +:1005200091E00C94721080910E0190910F01009750 +:1005300029F0019790930F0180930E010895EF9297 +:10054000FF920F931F93CF93DF937B01C901E801C3 +:100550002091BD012223E1F04091BE012091BF0115 +:10056000421316C0E0ECF1E050E0BF010E94B1126E +:100570008091BD01F70180838091BE01888319823B +:100580001092BD011092BF011092BE0181E001C026 +:1005900080E0DF91CF911F910F91FF90EF90089530 +:1005A000EF92FF920F931F93CF93DF931F92CDB7DC +:1005B000DEB77901633081F480E16983B2DE69815D +:1005C0006093BC01B801C7010F90DF91CF911F91DB +:1005D0000F91FF90EF901DC70F90DF91CF911F916A +:1005E0000F91FF90EF90089510920B021092FF016F +:1005F000089520912E018091240190912501A091D0 +:100600002601B09127010097A105B10539F08115A8 +:1006100032EC930731E0A307B10511F482E007C083 +:100620000197A105B10511F483E001C081E0809339 +:100630002E0180912E01281709F43BC0233011F0C0 +:1006400021111DC0EFE2F1E02FB7F8948BE391E0A8 +:100650009183808393838283958384838BEB91E062 +:100660009783868380E890E091878087138612863F +:100670002FBF1092BB011092BC0180E357DE809126 +:100680002E01823021F4B0DF1092BD010895833035 +:1006900081F41092300110922F01109232011092C9 +:1006A0003101109234011092330180E33FDE229831 +:1006B0002A9A0895462F209111012F702093E90066 +:1006C0002091E80020FFFCCF2091200120FF06C0F0 +:1006D00050E0BC0180E191E00C940B0F0895CF92A3 +:1006E000DF92EF92FF920F931F93FA018B01009517 +:1006F000109520E030E0980111270027AB0160E061 +:1007000070E0042B152B262B372B4CE150E097E0A3 +:1007100068017901042E04C0F694E794D794C79435 +:100720000A94D2F76C2D683028F0973059F4C082C3 +:1007300096E008C0C0829150C11004C047505109D2 +:10074000923031F7492F425013C0DF01A40FB11D81 +:1007500068017901E894C7F8DD24EE24FF24CC92E7 +:10076000B7E03695279517950795BA95D1F741507B +:100770004111EBCF492F50E09A01A3E0220F331F24 +:10078000AA95E1F7206C3F6F3081322B3083E40F64 +:10079000F51F319781508F7380688083892F1F9157 +:1007A0000F91FF90EF90DF90CF900895CF93DF935C +:1007B00000D000D000D0CDB7DEB76091BD01662378 +:1007C00079F08091BF0181110BC070E07160AE01C2 +:1007D0004F5F5F4F81E083DF682FCE0101966ADFB4 +:1007E0001092BD0126960FB6F894DEBF0FBECDBFA6 +:1007F000DF91CF9108950F931F93982F40910B0293 +:10080000E42FF0E0EB5FFD4F808380910B028F5F60 +:1008100080930B02892F807C803809F444C0803C8F +:1008200009F05FC0292F287326952695269522303A +:1008300008F477C0273079F4492F4F7050E060E01A +:1008400070E04093000250930102609302027093A3 +:10085000030215E00FC0892F877090E0A0E0B0E0A0 +:100860008093000290930102A0930202B0930302CE +:10087000122F11508091FF01882391F097DF609132 +:100880000B02615085E092E015DFE0910B02F0E091 +:10089000EC5FFD4F80818093050281E080930B0225 +:1008A0001093FF0145C08091FF018130D1F5009187 +:1008B0000002109101022091020230910302A9016D +:1008C0006627772722273327402751276227732758 +:1008D0004F3F5F4F6105710521F5892F8F738F5F42 +:1008E00028C08091FF018230E0F081508093FF01A9 +:1008F0004091000250910102609102027091030246 +:1009000027E0440F551F661F771F2A95D1F7492B03 +:10091000409300025093010260930202709303021D +:1009200007C044DF60910B0285E092E0C3DE5CDE2D +:1009300080E01F910F910895CF935DDFC82F88232A +:1009400009F489C08091BD01811104C0C13009F052 +:1009500046C010C09091BE018091BF019813F6CFA0 +:1009600004C080E091E00E94BE118091BD01811120 +:10097000F8CFECCF80910102813089F517DF90919B +:1009800000029093BD011092BF018FE3E0ECF1E013 +:10099000DF01282F1D922A95E9F79530A9F058F428 +:1009A000923081F018F49130C1F40AC0933091F084 +:1009B000943099F407C0983050F09A3070F409C020 +:1009C00084E008C088E006C0C093BE0142C081E157 +:1009D00001C083E08093BE013CC0E8DE3AC0809154 +:1009E000BD01882381F16091BF01462F50E08C2F1B +:1009F00090E09A012E5F3F4F359527952F5F3F4F2F +:100A00008217930701F5FA01E054FE4F809100022E +:100A10008083E62FEF5FE093BF018091BE018E17C8 +:100A200049F0F0E0E054FE4F9091010290836E5F38 +:100A30006093BF019091BF0189130BC080E091E0EA +:100A40000E94BE1106C0B2DE60910B0285E092E00A +:100A500031DECF91C9CDCF910895682F80E191E02B +:100A60000E94290F8823E9F080E191E00E947B0F2A +:100A70000E94CA0E80E155DC2FEF81EE94E02150F8 +:100A800080409040E1F700C0000080E14ADC2FEF99 +:100A900081EE94E0215080409040E1F700C00000DA +:100AA000E9CF089580E191E00E94910F97FDFACF80 +:100AB0000895EF92FF920F931F93CF93DF937C01E2 +:100AC00009E311E0C0E0D0E005C0ECDFF80181935C +:100AD0008F012196CE15DF05C4F3DF91CF911F91D1 +:100AE0000F91FF90EF9008959091450180E0209143 +:100AF0004601820F911D90933601809335019091AC +:100B0000470180E020914801820F911D90933801A8 +:100B1000809337010895CF93C82FC4DF803239F412 +:100B200084E19BDF8C2F99DF80E1CF9196CF85E127 +:100B300094DF80912F0190913001019690933001C4 +:100B400080932F01CF910895813859F018F480389F +:100B500071F405C0823839F0833949F406C082E067 +:100B600007C081E005C082E103C083E501C080E0E9 +:100B7000D2CF98DF803221F484E16FDF80E16DCF46 +:100B800080E2CFDB2FEF80E792E021508040904061 +:100B9000E1F700C0000080E2C9DB2FEF80E792E0C0 +:100BA000215080409040E1F700C0000080E2B9DBB6 +:100BB0002FEF80E792E0215080409040E1F700C0A5 +:100BC000000080E2B3DB85E148DF80912F01909146 +:100BD000300101969093300180932F01089583E5B1 +:100BE0008CBD8DB58EB508950DB407FEFDCF08956B +:100BF0008EBDFADF8EB50895CF93DF9300D01F929C +:100C0000CDB7DEB72B834A836983F2DF6981862FF4 +:100C1000EFDF4A81842FECDF2B81822F0F900F9022 +:100C20000F90DF91CF91E4CFDADF249A2C9A219AAA +:100C300029982FEF80E792E0215080409040E1F723 +:100C400000C000002C982FEF80E792E021508040F8 +:100C50009040E1F700C000002398229A20E040E095 +:100C600063E58CEAC9DF81E090E0909332018093E4 +:100C700031010895462F880F880F880F20E0672FD5 +:100C8000805EBACF0F931F93CF93DF938C01C0E0A8 +:100C9000D0E019C0609133017091340180E0EADF47 +:100CA000DCDE609133017091340181E0E3DFD5DE59 +:100CB00020913301309134012F5F3F4F3093340145 +:100CC000209333012296C017D10724F380E1DF91EE +:100CD000CF911F910F91089584E090E0EADE20917A +:100CE0003C0140913B0160913A018091390184DFE0 +:100CF00012CFD8DE803259F080912F0190913001CF +:100D000001969093300180932F0185E115C084E115 +:100D1000A4DE20E040E060E080E36EDF9EDE20E0C5 +:100D200041E060E080E368DF98DE20E042E060E0E0 +:100D300080E362DF92DE80E190CE23982298229AAF +:100D40002198249810923201109231010895CF9287 +:100D5000DF92EF92FF920F931F93CF93DF93D82FE1 +:100D6000C92F7B01CB01A5DE80E2E0DAE9E3CE2EDC +:100D7000E1E0DE2E0D2F1C2FE80111C0F6012191BC +:100D80006F014C2F6D2F80EC37DFFFE722E382E00D +:100D9000F15020408040E1F700C000002196CE01D4 +:100DA000801B910B8E159F054CF380E2BADA80E12F +:100DB000DF91CF911F910F91FF90EF90DF90CF9037 +:100DC00008950F931F93CF93DF93C0913301D09178 +:100DD000340120913701309138012817390724F068 +:100DE000CC0FDD1F8C0112C080912F01909130013A +:100DF00001969093300180932F0181E10EC060E253 +:100E000070E0CE01A4DFA096005211090132110555 +:100E1000B4F7B801CE019BDF80E1DF91CF911F9144 +:100E20000F910895EF92FF920F931F93CF93DF934B +:100E30007C010091330110913401000F111FE80172 +:100E400007C02FEF4C2F6D2F80EAD6DE06DE2196ED +:100E5000CE01801B910B8E159F059CF380E1DF91E5 +:100E6000CF911F910F91FF90EF9008951F93CF9313 +:100E7000DF9318DED82F16DEC82F14DE182F12DEEF +:100E8000803259F080912F0190913001019690931A +:100E9000300180932F0185E113C03D2F20E0C9016F +:100EA0008C0F911DEC0184E1D8DD163419F4CE01CC +:100EB000E9DE06C0153419F4CE01B4DF01C081E1CA +:100EC000DF91CF911F91C9CDCF93DF9300D0CDB7E4 +:100ED000DEB7482F80E249839A8328DA20E04981EF +:100EE0009A81692F8CE488DE2FEF86E791E021500C +:100EF00080409040E1F700C0000080E20F900F902A +:100F0000DF91CF910ECA80913501909136012091E9 +:100F10003301309134018032910511F4207F0EC0ED +:100F20008034910511F4207E09C08038910511F4B8 +:100F3000207C04C08115914009F42078C9010895EE +:100F4000962F672F242F880F880F880F492F805CDA +:100F500053CECF92DF92EF92FF920F931F93CF93D6 +:100F6000DF936C01D0DF8C01C0E0D0E029C0CBDF83 +:100F70000817190721F0C801A7DFC5DF8C01BEE201 +:100F8000EB2EB1E0FB2EEC0EFD1E60913301709153 +:100F90003401F701438580E0D3DF2296609133016D +:100FA00070913401F701448581E0CADF209133015B +:100FB000309134012F5F3F4F309334012093330140 +:100FC000CC15DD05A4F2C8017FDF80E1DF91CF9170 +:100FD0001F910F91FF90EF90DF90CF900895CF93E6 +:100FE000DF93EC0166DD5EDD803229F484E135DDDE +:100FF000CE01AFDF0AC080912F01909130010196A0 +:101000009093300180932F0185E1DF91CF9125CD21 +:10101000CF93DF9347DDD82F80E0C82F43DDC80F83 +:10102000D11DC13081E0D80764F081E116DD8091E7 +:101030002F019091300101969093300180932F0100 +:1010400022C030DD863421F4CE01DF91CF91C7CFAD +:101050008534A9F4CE01B5DEC82F24DD803221F419 +:1010600084E1FBDC8C2F0CC080912F01909130012A +:1010700001969093300180932F0185E101C081E1B9 +:10108000DF91CF91EACCDF91CF910895CF93DF9399 +:101090008091310190913201892B19F080E241D980 +:1010A00002C080E243D980912F0190913001892BB9 +:1010B00019F080E136D902C080E138D980E191E0B1 +:1010C00030D797FDAEC08135910509F485C0E4F4B1 +:1010D0008134910509F452C054F48033910599F19B +:1010E00081339105A9F1809709F089C07EC08534CC +:1010F000910509F44EC08035910509F44EC0823443 +:10110000910509F07CC03EC08136910509F459C0B3 +:101110006CF48635910509F45CC08036910509F4BC +:101120004FC08535910509F06AC039C084379105F3 +:1011300009F44CC08537910509F454C084369105F3 +:1011400009F05DC040C01092300110922F011EC006 +:10115000A9DC803209F065C084E17FDC81E47DDCBC +:1011600086E57BDC82E579DC80E277DC89E475DC8E +:1011700083E573DC80E571DC80E150C093DCDF91B6 +:10118000CF91E2CC84E190E094DCAEDCDF91CF91B2 +:10119000F0CC85E090E08DDCF9CF46DDF7CF82DC46 +:1011A000C82FD0E0D0933401C09333017BDC382FBB +:1011B00020E02C0F3D1F3093340120933301E6CF04 +:1011C00071DC70DCE3CFDF91CF9122CFDF91CF9143 +:1011D0004DCEDF91CF9180CD1092300110922F0132 +:1011E000ACDDD4CFDF91CF9184CD80912F01909150 +:1011F000300101969093300180932F010EC08091B1 +:101200002F019091300101969093300180932F012E +:1012100049DC803211F482E101C085E1DF91CF9198 +:101220001CCCDF91CF91089510922E0183D8789431 +:10123000C3E0FC2E0FE211E0DCD980912E01833057 +:1012400011F424DF90C080E191E06BD6EC0197FDB2 +:101250000AC080E166D8F092BC018091C80085FF89 +:10126000FCCFC093CE008FB7F894C0913901D091D4 +:101270003A018FBF209719F4A89949C06CC080E249 +:1012800050D8F092BB01809111018F708093E900DA +:101290008091E80080FFF0CFCE01C034D10510F07E +:1012A0008FE390E0E82EC0E0D0E02EC080912E01C8 +:1012B000813061F0F801A281B3818D91B383A28363 +:1012C00026813781A217B30781F40BC0E091310169 +:1012D000F0913201608180E191E0BBD5882351F328 +:1012E000CBCF24813581338322839FB7F894228525 +:1012F000338521503109338722879FBF90912E017A +:10130000923009F419DB2196EC12D0CFB5CFA89A10 +:101310008091BB01882399F081508093BB0181119A +:101320000EC080912E01823039F440DA60910B02B8 +:1013300085E092E0BFD958D980E20E949601809161 +:10134000BC01882341F081508093BC01811103C00E +:1013500080E10E94960180912E01823021F480E08C +:1013600091E00E94BE1180E191E0C5D513D564CF14 +:10137000292F332723303105B1F04CF421303105CA +:1013800009F439C02230310509F03AC007C02132D2 +:10139000310539F12232310549F132C0EFE5F0E093 +:1013A0008EEB90E031C099278130910561F0823059 +:1013B000910581F0892B21F5EAEBF0E0E491F0E072 +:1013C0008AEB90E021C0E6EAF0E0E491F0E086EA02 +:1013D00090E01AC0E4E7F0E0E491F0E084E790E008 +:1013E00013C0E9E0F0E08DE091E00EC0E8EBF1E041 +:1013F0008FE291E009C0E2E1F0E08DE191E004C00C +:10140000E0E0F0E080E090E0DA018D939C93CF0182 +:101410000895680F791F09C0FC012191CF01309117 +:10142000C80035FFFCCF2093CE0086179707A1F7A1 +:101430000895BF92CF92DF92EF92FF920F931F9386 +:10144000CF93DF937C018B01EA01D7D1B82E8111B4 +:1014500032C0209731F028813981021B130BE20E34 +:10146000F31EC12CD12C22C08091E80085FD14C050 +:101470008091E8008E778093E800209749F088817A +:1014800099818C0D9D1D9983888325E0B22E13C010 +:10149000B4D1882359F00EC0F70181917F01809368 +:1014A000F10001501109FFEFCF1ADF0A01151105F4 +:1014B000D9F601C0B82E8B2DDF91CF911F910F91DE +:1014C000FF90EF90DF90CF90BF900895209144025D +:1014D000309145022617370748F06115710539F438 +:1014E0002091E8002E772093E80001C0B9019C010B +:1014F00080E034C090913D02992309F443C09530B7 +:1015000009F442C09091E80093FD3AC09091E80040 +:1015100092FD30C09091E80090FF20C08091F200D1 +:1015200090E0F901821B930B05C021912093F100FB +:10153000615071099F01280F391F6115710519F05C +:101540002830310590F381E02830310509F080E042 +:101550009091E8009E779093E8009F0161157105D6 +:1015600049F68111C7CF06C080913D02882351F012 +:10157000853051F08091E80082FFF6CF80E0089539 +:1015800081E0089582E0089583E008956115710572 +:1015900029F42091E8002B772093E8009C0121C0DA +:1015A00080913D02882381F1853041F18091E800EE +:1015B00083FD26C08091E80082FFF2CFF90107C0C9 +:1015C0008091F10081939F016150710929F09F0181 +:1015D0008091F2008111F4CF8091E8008B778093A5 +:1015E000E80061157105E1F68091E80080FD0AC010 +:1015F00080913D02882341F08530B1F783E0089562 +:1016000081E0089580E0089582E0089520914402E9 +:10161000309145022617370748F06115710539F4F6 +:101620002091E8002E772093E80001C0B9019C01C9 +:1016300080E035C090913D02992309F444C0953073 +:1016400009F443C09091E80093FD3BC09091E800FD +:1016500092FD31C09091E80090FF21C08091F2008E +:1016600090E0F901821B930B06C024912093F100B6 +:101670003196615071099C012E0F3F1F6115710554 +:1016800019F02830310588F381E02830310509F060 +:1016900080E09091E8009E779093E8009F016115AB +:1016A000710541F68111C6CF06C080913D028823A5 +:1016B00051F0853051F08091E80082FFF6CF80E054 +:1016C000089581E0089582E0089583E00895982FB9 +:1016D0002CC09093E900981739F07091EC0020919C +:1016E000ED005091F00003C0242F762F50E021FD33 +:1016F00002C09F5F1AC03091EB003E7F3093EB0039 +:101700003091ED003D7F3093ED003091EB00316082 +:101710003093EB007093EC002093ED005093F000B9 +:101720002091EE0027FDE5CF07C0953090F28F7035 +:101730008093E90081E0089580E008950F931F935E +:10174000CF93DF93062FEC0110E02EC0988191110A +:1017500003C01F5F259628C02C81E981FA816B8127 +:10176000892F8F70853010F080E021C0223010F07A +:1017700056E001C052E028E030E040E003C04F5F97 +:10178000220F331F2E173F07D0F34295407F452B82 +:10179000991F9927991F6295660F660F607C692BC8 +:1017A00096DF8111D6CFE0CF1013D0CF81E0DF914B +:1017B000CF911F910F91089580913E0287FD05C042 +:1017C0008091E80080FF0EC012C08091E80082FD89 +:1017D00005C080913D028111F8CF08958091E80005 +:1017E0008B7708C080913D028111EACF08958091E6 +:1017F000E8008E778093E80008958091E40090914E +:10180000E50045E62091EC0020FD1FC023C020919B +:101810003D02222391F0253091F02091EB0025FD2F +:1018200010C02091E4003091E5002817390751F3EA +:101830004150C90139F784E0089582E0089583E0BA +:10184000089581E0089580E008952091E80020FF48 +:10185000DECFF9CF2091E80022FFD9CFF4CF41D0DD +:1018600043D08091D8008F778093D8008091D800A2 +:1018700080688093D8008091D8008F7D8093D800B5 +:1018800084E089BD86E089BD09B400FEFDCF1092D9 +:101890003D021092390210923B0210923A0242E04D +:1018A00060E080E014DF8091E1008E7F8093E100B2 +:1018B0008091E20081608093E2008091E200886084 +:1018C0008093E2008091E0008E7F8093E000089595 +:1018D000E3E6F0E080818E7F808381E080933C02AC +:1018E000BECF1092E20008951092E10008951F9279 +:1018F0000F920FB60F9211242F933F934F935F9344 +:101900006F937F938F939F93AF93BF93EF93FF93C7 +:101910008091E10082FF0BC08091E20082FF07C04E +:101920008091E1008B7F8093E1000E94930280917F +:10193000E10080FF18C08091E20080FF14C0809118 +:10194000E2008E7F8093E2008091E20080618093CC +:10195000E2008091D80080628093D80019BC109278 +:101960003D020E94D6018091E10084FF30C0809149 +:10197000E20084FF2CC084E089BD86E089BD09B403 +:1019800000FEFDCF8091D8008F7D8093D80080919C +:10199000E1008F7E8093E1008091E2008F7E809352 +:1019A000E2008091E20081608093E2008091390240 +:1019B000882311F084E007C08091E30087FF02C014 +:1019C00083E001C081E080933D020E94D5018091B7 +:1019D000E10083FF27C08091E20083FF23C0809154 +:1019E000E100877F8093E10082E080933D021092C6 +:1019F00039028091E1008E7F8093E1008091E200C6 +:101A00008E7F8093E2008091E20080618093E2000B +:101A100042E060E080E05BDE8091F00088608093CF +:101A2000F000B7D1FF91EF91BF91AF919F918F914E +:101A30007F916F915F914F913F912F910F900FBECA +:101A40000F901F9018951F920F920FB60F921124AE +:101A50002F933F934F935F936F937F938F939F93B6 +:101A6000AF93BF93CF93EF93FF938091E9008F7073 +:101A70009091EC0090FF02C090E801C090E0C92F67 +:101A8000C82B1092E9008091F000877F8093F000CE +:101A900078941CD01092E9008091F00088608093C7 +:101AA000F000CF70C093E900FF91EF91CF91BF910B +:101AB000AF919F918F917F916F915F914F913F91E6 +:101AC0002F910F900FBE0F901F9018951F93CF93DB +:101AD000DF93CDB7DEB7AC970FB6F894DEBF0FBE7D +:101AE000CDBFEEE3F2E08091F100819322E0E63495 +:101AF000F207C9F70E948B028091E80083FF31C191 +:101B000080913E0290913F02953009F487C038F4ED +:101B10009130B1F170F0933009F023C131C09830A9 +:101B200009F4F3C0993009F4FFC0963009F019C1E7 +:101B30009BC0803821F0823809F013C108C0809121 +:101B40003A0290913B02992389F082600FC0809104 +:101B50004202909143028F7099278093E90080910F +:101B6000EB0085FB882780F91092E9009091E8004E +:101B7000977F9093E8008093F1001092F100D0C01D +:101B8000882319F0823009F0ECC08F7121F0823087 +:101B900009F0E7C00BC080914002813009F0E1C03C +:101BA000933009F080E080933B022FC08091400287 +:101BB00081112BC080914202909143028F7099272E +:101BC000009709F4CEC08093E9002091EB0020FF3C +:101BD0001CC020913F02233021F48091EB008062F1 +:101BE00012C09091EB0090619093EB0021E030E007 +:101BF00001C0220F8A95EAF72093EA001092EA00CA +:101C00008091EB0088608093EB001092E900809156 +:101C1000E800877F8093E800CFDDA3C08111A1C0D9 +:101C200080914002909141028F779927182F9091CF +:101C3000E3009078982B9093E3008091E800877FF1 +:101C40008093E800B9DD8091E80080FFFCCF8091AF +:101C5000E30080688093E300112311F083E001C06A +:101C600082E080933D027DC08058823008F079C0C8 +:101C700080914002909141028C3D23E0920771F5E2 +:101C800083E08A838AE289834FB7F894DE01139652 +:101C900020E03EE051E2E32FF0E050935700E49162 +:101CA00020FF03C0E295EF703F5FEF708E2F90E052 +:101CB000EA3010F0C79601C0C0968D939D932F5FB8 +:101CC000243149F74FBF8091E800877F8093E80077 +:101CD0006AE270E0CE010196F9DB11C0AE01455D0C +:101CE0005F4F6091420244DB0097D9F12091E800F8 +:101CF000277F2093E800BC018BA59CA587DC809101 +:101D0000E8008B778093E8002CC0803851F58091F3 +:101D1000E800877F8093E800809139028093F1008A +:101D20008091E8008E7776CF81111BC090914002A0 +:101D30009230B8F48091E800877F8093E800909318 +:101D400039023ADD80913902811104C08091E300AB +:101D500087FF02C084E001C081E080933D020E94C1 +:101D6000D7018091E80083FF0AC08091E800877F57 +:101D70008093E8008091EB0080628093EB00AC964A +:101D80000FB6F894DEBF0FBECDBFDF91CF911F918C +:101D900008950895CF9380913D028823A9F0809102 +:101DA000E9008F709091EC0090FF02C090E801C0B4 +:101DB00090E0C92FC82B1092E9008091E80083FDC4 +:101DC00085DECF70C093E900CF910895CF93DF9364 +:101DD000EC014096FC018BE0DF011D928A95E9F74A +:101DE00082E08C83898783E08E8761E0CE01019653 +:101DF000A5DC882361F061E0CE0106969FDC882394 +:101E000031F061E0CE010B96DF91CF9197CC80E06D +:101E1000DF91CF9108950F931F93FC01CB01BA017D +:101E200020913D02243089F4048915892689378957 +:101E3000012B022B032B49F021812F702093E90005 +:101E400040E050E01F910F91F4CA82E01F910F9182 +:101E50000895CF93C62F20913D022430F1F4FC0168 +:101E60004489558966897789452B462B472BA9F0EC +:101E700081818F708093E9008091E80085FF04C024 +:101E8000C093F10080E00AC08091E8008E778093D3 +:101E9000E800B3DC8823A1F301C082E0CF9108956C +:101EA00020913D02243029F5FC0144895589668939 +:101EB0007789452B462B472BE1F081818F708093EA +:101EC000E9008091F200811102C080E008959091B4 +:101ED000E8008091E8008E778093E80095FDF5CFCB +:101EE0008CDC811107C09091E8009E779093E80008 +:101EF000089582E0089520913D02243089F4FC0188 +:101F00004489558966897789452B462B472B41F0B3 +:101F100021812F702093E9002091E80020FDC0CF9F +:101F2000089520913D02243019F02FEF3FEF24C097 +:101F3000FC014489558966897789452B462B472BB7 +:101F4000A1F386818F708093E9008091E80082FF81 +:101F5000ECCF8091F200882321F02091F10030E055 +:101F600002C02FEF3FEF8091F200811105C08091F8 +:101F7000E8008B778093E800C90108950895CF9316 +:101F8000DF93EC018091E80083FFA9C0888190E095 +:101F900020914202309143022817390709F09FC06F +:101FA00080913F02813261F020F4803209F097C0C5 +:101FB0003DC0823209F46EC0833209F090C07FC008 +:101FC00080913E02813A09F08AC08091E800877FC3 +:101FD0008093E8008091E80080FFFCCF4C895D8908 +:101FE0006E897F894093F100BB27A72F962F852FFD +:101FF0008093F100CB01AA27BB278093F100472FE4 +:102000005527662777274093F100888D8093F1004C +:10201000898D8093F1008A8D8093F1008091E80092 +:102020008E778093E800DF91CF91C6CB80913E02FE +:10203000813209F054C08091E800877F8093E800E6 +:1020400005C080913D02882309F449C08091E800D1 +:1020500082FFF7CF3091F1002091F1009091F100D3 +:102060008091F1003C8B2D8B9E8B8F8B8091F100AA +:10207000888F8091F100898F8091F1008A8F809103 +:10208000E8008B778093E80097DBCE01DF91CF915A +:102090000C94E50180913E02813209F58091E800BF +:1020A000877F8093E80088DB809140029091410215 +:1020B000998B888BCE01DF91CF910C948002809117 +:1020C0003E02813261F48091E800877F8093E800CE +:1020D00073DB60914002CE01DF91CF914FCFDF9152 +:1020E000CF9108956F927F928F929F92AF92BF92FD +:1020F000CF92DF92EF92FF920F931F93CF93DF93D4 +:1021000000D01F92CDB7DEB77C01ADB6BEB68091D0 +:10211000E80083FF07C1F701808190E0209142022F +:10212000309143022817390709F0FCC080913F0223 +:10213000833009F49EC030F4813071F0823009F0B0 +:10214000F1C0D4C08A3009F4B9C08B3009F4A2C000 +:10215000893009F0E7C04CC080913E02813A09F015 +:10216000E1C08DB69EB61A8219828091400210910C +:1021700041028B83F70140858DB79EB7841B91097F +:102180000FB6F8949EBF0FBE8DBFCDB6DEB6EFEF93 +:10219000CE1ADE0A360150E060E070E0C601EAD1F6 +:1021A000412F41508E010F5F1F4F9601BE016D5FA1 +:1021B0007F4FC7010E949F02F701268137812115B9 +:1021C000310529F0408550E0B601C901CAD110920D +:1021D000E9008091E800877F8093E80069817A8137 +:1021E000C30174D98091E8008B778093E80039C0EF +:1021F00080913E02813209F095C08DB69EB6009165 +:1022000044021091450270904002609041028DB7E7 +:102210009EB7801B910B0FB6F8949EBF0FBE8DBF6B +:10222000CDB6DEB6EFEFCE1ADE0A8091E800877FEA +:102230008093E800B801C601A9D98091E8008E77A3 +:102240008093E80021E0711001C020E030E0021B23 +:10225000130B2C0D3D1D462D4150672DC7010E94CB +:10226000D002882D992D0FB6F8949EBF0FBE8DBF5A +:1022700059C080913E02813A09F054C08091E80033 +:10228000877F8093E8008091E80080FFFCCFF70112 +:10229000818540C080913E02813209F043C0809127 +:1022A000E800877F8093E80087DA9091400281E020 +:1022B000911101C080E0F701818734C080913E0216 +:1022C000813281F58091E800877F8093E80074DA9D +:1022D0008091400290914102882736E0969587953B +:1022E0003A95E1F7F701958784871CC080913E02FB +:1022F000813AC1F48091E800877F8093E800809163 +:10230000E80080FFFCCFF701848595859695879539 +:10231000969587958093F1008091E8008E77809361 +:10232000E8004ADA0FB6F894BEBE0FBEADBE0F90FD +:102330000F900F90DF91CF911F910F91FF90EF9031 +:10234000DF90CF90BF90AF909F908F907F906F90D5 +:1023500008959C01275F3F4FF90127E0DF011D929F +:102360002A95E9F721E0FC01218724EF31E0358748 +:10237000248723E0248361E00196E0C94F925F92B5 +:102380006F927F928F929F92AF92BF92CF92DF9285 +:10239000EF92FF920F931F93CF93DF9300D01F9282 +:1023A000CDB7DEB77C01ADB6BEB680913D028430BC +:1023B00009F08FC08091E4009091E500F70122853B +:1023C00033852817390709F484C081818F70809381 +:1023D000E9008091E80085FF7CC06DB67EB640853F +:1023E0008DB79EB7841B91090FB6F8949EBF0FBEA0 +:1023F0008DBFCDB6DEB6EFEFCE1ADE0A1B821A8293 +:102400001982460150E060E070E0C601B3D08E0151 +:102410000F5F1F4F960140E0BE016D5F7F4FC70108 +:102420000E949F02582EF70184859585892B31F0F3 +:1024300001E010E086859785892B11F000E010E01F +:10244000F701C680D780C114D10489F049815A812F +:10245000B601C40179D044244394009709F4412C77 +:10246000F701408550E0B401C6017BD001C0412C8A +:1024700089819A81892BF9F0511004C0411002C062 +:1024800000FF19C0F701848595859787868781812C +:102490008F708093E9008B8181118093F1006981B5 +:1024A0007A8140E050E0C4010E94190A8091E8005E +:1024B0008E778093E8008091E4009091E500F70129 +:1024C00093878287862D972D0FB6F8949EBF0FBEF7 +:1024D0008DBF0FB6F894BEBE0FBEADBE0F900F906D +:1024E0000F90DF91CF911F910F91FF90EF90DF90B0 +:1024F000CF90BF90AF909F908F907F906F905F90A4 +:102500004F900895A1E21A2EAA1BBB1BFD010DC01E +:10251000AA1FBB1FEE1FFF1FA217B307E407F50793 +:1025200020F0A21BB30BE40BF50B661F771F881F6F +:10253000991F1A9469F760957095809590959B0105 +:10254000AC01BD01CF010895FB01DC0104C08D91F8 +:102550000190801921F441505040C8F7881B990B15 +:102560000895FB01DC0102C001900D9241505040E2 +:10257000D8F70895DC0101C06D9341505040E0F759 +:062580000895F894FFCF5E +:1025860002812000000100003F0000000000000062 +:1025960000834000000104400000018208000001A1 +:0E25A6000000000000000000000000302000D7 +:00000001FF diff --git a/plugins/KeyboardioHID/Firmwares/No_HID_Bridge.jpg b/plugins/KeyboardioHID/Firmwares/No_HID_Bridge.jpg deleted file mode 100644 index 87954a7ce61dd9d08d63dd0119f5ca98a3a22154..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 74968 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

    3TdlVRYu1)7sCWI7!Z zdebldj-y=i+M=KSMyj>6kCaCSNVjKT^{YQnta0>hv|l`bq<>`h@*1wJt8U+^-W``| z$9{b(lKFeF*OlLG>0 zXwGL;Tz={A-sbsKG?42I41f${z-jZFE`APd! zo|+QogO62`3apZkRFVl>`#rmOiWKc!8gVuIxTIqi$ocFunuwKxw%!}D-AHVA9R2Ap zMUD3n@z>^ENRq$TFRv_aEkec;Rm01JoMx(~2So}w+vUwkk)AV(ZIm*c4s*t6Ej%Eq zDuFFj@;j5ZLS0A09lW=8$9jvB7RGt2HOxh%ZpWHr+W9t=8%H@5scDy?b)EW^v_ZRZ zT#8?WLEJD#DsD>qE4lIo<2edSrB1(MPVz$az0aNX6y7k)-u6$*)BYvfQoF=hd-O58@HL$((s}p45~{ zJ8vFS=xXani`5nUc5iY%ICWM8HS=-k0I4fyxP~AaSsqVP)P)bc4gUa4pGt6m8ymUz z2fbc8d{OBXmaigL+M#XH*oAZrr18rjD537SmrV1O+GaqjMI~s zW0vzsWeF;uD9>t5m2 zxhHloC=CkpQnb|`Z5}xq;3EyHGTVJ6YSy}=PorDQJ;KI!M;aH( zdgKpEtI0TP#RUW77U1B>e3iA6&YgMwIR)#szg3QGLK7iu}jp+`t z)b+h>wM%;yHx_VgTT4L1xGlK1IXn|wWS;c+{tnw~W8_y^UTS)tq}O`Aw3fFM4a_G} zyRbbo_5z_Ip58Etc>WoFMhBbe_NmW^9Y?Ne*H){oTS;v2N47X+i(%M#%|+i|TU^*j zZuaqskSdu0`L>=bzbv_9jw&_#ba1v~d1bk<3DQe*6pp84jpclB-uS1lB}ZivZe>;D z2L^+?z22z?CXil>e##+z#GAcj*>yV?mDNHM#SlS*eUc*&}7pzI%-^uIYE{Z4aK^CI0~8a!qU+cTMQ}mqNz|)JKMA z258_5DGTN0y+QAasZY~-O^o+32=3(A*cp*mIQH__IZhAI>1@clWjexmpms!nyGxDU zFE}(U^~9GtgrPGWYT5tQ!qH>liIo$nMyI`kmw2nyT7N_x#DMyzG~6>TcK?A-3Ly-S!9kznU>{q z!zgTFc;Mott^OS8SBBbaX{HdR#F5Uf*)FR4Mh-YQ6!o49hGz0+`Z4{)HL z{a_sZYhSbYb)()jmDDdNx66s+FOv9TqX*NqWw*BCE9uhTJ{m~De%YsEn#p^81(Qht+ES<4b}u%6iab5lCMM`%e2 znJi2W9xby8*}PKBHz@@1O7r9Bhb%H^$lK%vm3M!H8e=cJ%BOFyHM8FI=8HAVix!+> zHkXk?-gaRswlX>U)OM$%X?kUa?aHne_7tm+NgYBh)PyP1B_OMb)~<*0#t_ z*7fqyeH$L#15><@O#D`%Zt96|EPK!XS~8kZPuvO*brr|4xf@U8*q`u~{{UJ;Y1beA z`zJr*TD)2twCUNeEVMYJ)FinnEwe-qhCQ+AR2lEDd}bejWjncFYP25f3tK_%?JpuH z!Zy%i-z*+wjxKWdFwaT`h=F@xJaYLL_rrim8s->UG*eE$F=N|X49 zL!x6{ES({z5P56%ILEToGD_3jhmb2A@wilvP;dVLX0+Aa$+?jC`U-=N5~#B=!WO{W zRFn9Iu8lXPo>b^=p#T)~MmGNdXQ=1$6*S@b{xnp3Oln66 z!y>z_+QF>Z*<0U69W0rQKjGcne=2$yOYBf_`y#VqSsdlRuR-}x0=)z;6n>D?e(SPoMY-c9w|%ElaTH5Ml+s1wb)`&hkjeoRF;FK!*eyby3}pF zTbN#DSYIYQ4i&TeMytBqSDIf?NeALXq&em=RN(z97EOLA@Qv{B?2_e^HjLkmONg=h zvA8RNwEKga5_J+6lXut6QE97P+sNJ&kI3M)Bx*N#-ehjv=ZZ@47+uik;nS+JRbmYp zCkH3JC_=*u`0x@zM(Oiv*>zN_Ovv(EgC4^;zy2ICu|PugNzeRkBDP^ ziI;}uT@ii&-R?ypAm=-~R*S5BHoUf$C@n9o=eY15c~P7oR1dexPjmFF?Pl;Lk_Q9C zU)odJv}4pmFUZWfwApcUGDWh`d{N4xRT3UbAm$tmqP0+?R@P z8D);)Jj7rSRF6<|{Hcv51+cP67cQuwd-wX%)@k{!EpT1KAC#qk7qC=pv;MVCC0|Ny z3kHT%AuzMAUP zb2Kdj;N!~J{{Tu{kVJVVjJea)X|~hZx)zdS6o^MEF~c9Hdcmr3OO$WYx4VGvik(?y zt!Nr8j-7JzEwdSAM~tg0l>-^}?@@mYb#KreO%46t`)CAgtFd$6xAUNGE#gTKjfH{z zn)TwNItbg5-2VWjV}_0r<-QGb)=hAcYxsfH_Z?NLtkUxxx|pClaCT>m)k&I7s!niw zQd)lqZC-e$4byteF!?ouf22Dhi7U^4z8v;lRM8A!IvU za7P=x=zkSM0;dPwh@Nzk+dsGOK{QRQbSZB(Pc*o|N6GnpN796X>6og8-I2f?n&RF8 zxnCR}c*ZF1NE;>DAuK4%lrM~&mi6a~8IVJJ3#iW08kCnRIAU?>U4_lv>`_EOE_V5- zOKV(~hU?(Cj<&he_pP*sOJ?Wr(x+qJh7}Wi)K{0+w-Z^Hjczu(p~uaP8jI>U4w-b2 zO|Z+cU&?qPhG~myv_@7s$Q;O-n0Cpm@?_C^CbdMls*D6{hv>sbK>o5!#jU-fuFV?VOJP09v9! zI=<6_N%W%9MQf;`E3i8%mLs-(YU&tkp&n*yq|0ud*LuB$qQL;SF(W%J^vUybeSOVE zL#j@6$?SYMj1$ZzEKqL^^lxf!sBGiW?rmYWoi37iyiMo_my$4f@5Km{ssIXkyVaML z)uq`b=G{oLU-h=P9qEN-j6iLLxrb+yZauyJv{YSFtWRw;(oYwhASz=RJ3d@-!K%%> zLw&8M<7E6SZQZfDr8<=??6i^kI`Ca@lP!hD-YUQ4T8({%uQjdL!6SFoTIQ@$8_S~+ zQXB+8o?+PVDHr`+t~}70^%BxsKIqD-_r^28=Bc*VG8mI7!5#BL-pM}p1#&$wc&jfh zdLph_8GK%_*DtPO4|vY&m0Ti@8^5Iis&&QYpQ_sFv0U6G#j4>Lc2IpPn`J%BQ=`PY zWDGXo)sJ0kd9M%ae93weKgb7shw5uqa-EdVX#@FVc&5jgq3RIR)7s=3F| zDl%oNE12%$+*u^gs?f9C*;@IUA@!(x8w<9*4+O$6{$JSu(sj)q<(u`BmSyfY3{+E( zsCLL{wd)ab`=Cvk`qM`G-b1}0hiUCd8W@*rG?T~2%aOK}oi7`%<&yyVc(lJYUjq~w zov+R-Wa*2APM7}x7l&BLBYM`m)1V%n9R9^(j|rNZvWIgsyo@vZb!X8}{-U`50EE;` zmQWUAS+klx-1vGt;XSJGd_7jjak2F)B+DU zIqy>!jK88G4hZI~uO0>J=ZMbhx7B%+hE03XFy)iOFXic~3Pj)i)sM z`bs2dn0ZN%FPXktu6S%!Sh2yXKFh9+LqfVK@at4WBrDGv{{TPvR1TB3@$i;h`Nd7? z3m^WCuB0#KdD5V?*WY_?oDHweJ!^g+oqonV{{Sm2QZ6aa;?qiRg2{cULu?0$FXd1=?z{Ni8fa}ANbdYZ*n4F;&p*P2 zeHT-o&G>m6^P%U^HAGzg3V-~S$<*uRk!_C%>*@3n#`iUBlIh)U>%_OSka&`Q)8?(w zYIdyaystfg#b&m)cXpSk)59!Zb;U_SyJU7JoO9;wS=O&2Rc5ck<8J7`PkCnxvcAyZ zbJ&V+@s?yU-kWNNGl?IDV3_8dmIsNj%t$@4+O7D>gYcNmD@=kr{{Z`At&e6`clW%IGAvzMyIu;g$;&B{8U+&rWB zb4e4fed!(&h2z$To*kofdB?42wNzw`Re@d1%p@7@Ro2IkmhGCHyGKN3Wx_b}=hmR) zkwm8+ja6Y_hX4-?Pj0Behx`ftn7xqG=LcJWzF88;`@Z-aXOXm*0(_H|O57ZCcg~OQ%?F zMEed5tBf)C6@9t6=ydVnTYHtYdvZKz8zfD<_GbN^xUA1rme=vJi#Bh=?(zfeU2GGY z?*9OKIeNIJmqNKJGC;}BeQVDvCPYM)?ac#~W%9RbWZkg9Q~6e%{-y;0`7R~Kz6ze>$tpv|_`32DFcY82M>QdEqacpQdUiTZawpO}x&%h&inD z&ZIgxTtcS2ZOp?s&S-SK-7skh13cr}hMH$+$ZTW30)unGtn0p#b}qcaqNRTfrXLFqwhcX2|9*FW5jNIt(xZueKPzSV!RTFGw|kA#h7IA7yg z9$9;v7AS_gr;C7(fn1bDkU(HPIjJx9eq~=Sn|S4i&XZ(Sds5SN4L!@Hq&B)|uy&y#k3=;nUN&?)+bFD<0czHvwnmHRB{p#ob&Rzt^=#tyH z{`HMj=W!2}61-9w3ZX0;J?_79u5yIhnf=((^rZf#lQLtGfu(y~hgPqNj zpS2Tz(z?q*wKRaB@#Ne{s`>3c!{tP+l-QfLkGAUK$r~pMHxF}OywEir8J6Q$vbv7X zb{WEuDLpM^CZ&0BZA1+hiG>sQ`cd;`S7h?z>^!rm`IHaNlGg=fNdQoLj2gHBIQoaniA|SM3zlM-_7&&Wd|jeI zn-pP9Td%$tbuH!$kVHuBwL<>@N~U$EP2cp_;q7%xPX6)5JCd`G{JAVqDy7*PpH!51RE=*fWZ55KsqQYeDV95c7n02x;)5E{k~WQ; z?Ox{{>tC1P=BIHM4yiE=JxdWlUi=T#ZLDXO+V(Rdp}=Ufx`cB%2V_jj&F(LE3pAc! zhaN@E7|`Cvq?;SkF~QkR^qq?7b4zQg+FnO;j#L=)wX0;(z7;O5r$KuK#mGsMa9zjC z{OU_9i>6JnqX#;JG=WkHLB}}mDf&j1c{iC(YuZ+X+92UioZN*^%CN#9Flz|N3{97N4R}LcDJ?=tc%~r zlVwgzrryI3o^3RL{!cY))%r#*i|Q$3vHTs~te$YU50+E+tq-DfJrAfXWs_1{7-dH7 zyV9AFWP?ek$rFo5&#$Rp#V>-ZZpx?T_x$PI8uI5`yYQltD^Q)oJxCj;?`>nUm3K62=3UgtW6w0|Em2n}uF6f;g{bUZ+Rcv9*+ef@ z*~X}oIt5n>ak*hU*U=ppdDHjM&-!M2aVoczk&Y_OzoLKr=Gv(U=9f`ywZ!-ZK4JH* zf2UY~v+57-Rz(;0i(1x*yL1eHf~vYKR%dTBVEUSR8GrRu!|6dzd1`t&F{a1|997d7 zBtfb3W8R#{siYus&FxMilisZnY?9O){{U8740_Z-Zakyc+NCeqmcrS6IjHp7RYoz6 zYOk{K=p(3OW2R{#RI@jUjJ%QzG zZXcZ^CV!QaT9nys>JV-pDE*q`g_$`x2AH@TM(*Sqa$GcHkG*xSjx$zAUpJJD;}jN> z3u@Nc{{Y&L>rU$T5ZicZD{W~$T-P)pA6m8TgD9?Mt0HcZ)6&7Fn?|E=G;l4%o(}g# z8xOJF-mIDp%iUYMO8b3xtkbmNGvJ{{T9+K857;5de>V z7@UunKD8o>>oINd$nJl-%}1b7a0cQ|eL2MvfXTXMj}AL-ZvOz4T?;MUA#&>$qaq!S zLXHnB=BXL4bxUnUrH@s+-TS6f?dec`4gI1mL>w>5N&M=`_!hspk~NW4qy6sH($Tmi z+`SAMw~;iUE>5i1uomL_;^HE|Bgk89?`rTCiW#x=cWZAKW@Xwel1lnjmB)Fg^j4Y&io zD2-au>r1tcTeJP^5x4e+C_fch7oWL#g7$m9Z z%(TaewbPD0eze8b6z`8dv)vm9r%{{H0cAL&} zFh8Y6PiD-D!?iW|76cU-u6(e1q;zAcRZWslbRYF{W5dWhN4H|A=kU*) zZAG<|-?RDCM#@0hXEeVmUc(l6`;tOej`_CDy4@U@o7{S4teror>3VJ5gX%UZc^pLe zis&7C{^{>j)Ifs_OMU5T&5S4&WsbW8&+KcH{6x^@mC?F>+FM`3m{KP|svmhf_K#k} z@~qnGRV>XG?&r&n!lLD7!@FXivgzN}g7+98{?Dazax7N7A1t}eNL$Ua z;4mbqY?{vdH6!RRh8q5Zr}Uf_x~0eVxZSc?WaH9{>#cL8buOB_v{qSKMd3E`O=F9; zRSbh*BhtLl>JPjGjJ~jQmd;2T<$3ibxo#;LL|hzxUhoImXp!OMPoWGorRU~oFgDpkf_H7r%k%MV;TF`zX1sI zZ4_pr)g?sa*WviDqYGGp)0=vz2k%L5i<(~6156^a7PCg|Db%ruV*VQuCQBc{B&g50F*RN`FfwOvHOOq?3c#p7+)&z^wuxqv zelcKqG`K3A*L`TcPGB=>@Gpa(+090qDE2AZF-{9Ogj>}?HG5S`DFADvI-Y);zK-I? z2+rTw+s8F_e~db@`7K}v{tBo=W}M+gI+lAu@`L$MjYrXa3E45O{7%*NJvLiuAc!OJ z!gi`OH@7QzvqFVs?mU%cOF%KXMk)UQ!$wD7O&Lpn6b^&q_?^_t0-<~|t~gp^e~7(N zBuu_DoQ!<5+gm7$+L!oHRX{aml2PGT(GrnPmTgYvcAb&SGj26y(>j}|?QE6^t}YTa z9$Xqe8-0Z31wRF{x0Tx-)l}M+?^0SKp=w3}Ua7|d{7yixiM^(FW%VbE^BlX3TR#ZEyE6PhDq zdI}Jn3gF)GptB#n^B08Yau8ZlVQ6*EA$<={@QQ+)hd6( zP9qJYDl<`9>4S4VL4%n<9`&v0>cc?CZzW{VF!7L&de}6Qqo(X~r! zYi6+VL)^JIL_N6mt=K+u9(8eG_o=n`Yy(cpc*kt^q+NNC7iR_z4qKnrntnVUZE`AkqmQ(GebiBD)_NIh zduu41s9oL~jB!-{jlG5RO>zsslI4I_Z?UhREqaqsgiM!HJn16gceiSK->UU17^IHU zKo!1Wx4kiFlC+;?7OoUa{6uKX7IE$JDmVatty5!dqaL`Ub=_|3Rq)bf+Y$~HN3X3# ztK;dOJJ#Jgc%Y)rcCJy$k;)*_i^()?#+!X@8@fMbsJBd_Tf zIwqwho#O174?I+JsXPwe^;FYb1;xeF5aathGLGK4p&0(Ck=}`)hzRdOImAY*F^~wF zK-QM(JMYaM3;AOh8O=t-OFg_})}+)Fl~DQ`&igbji!=d_9Q?my0oM2HFqiwqV zshO}_wgp@RF&{4;v_Wzc6w_d10+I_1oKUcZMA-8aMR?kywyDDO)fwM|voOQbgfK-){7{ zqbxY!de@5Hh$TkThOaBRHoG zlf?=wga#&sk)SQ73P(6TwCpi`G4!X}*rMZllb_i&A#Z1lw1+2eZ)!XM3Oj!gb~qID zc8urBha#md&@4-g3QF$Y%&mYZSS*hgtQ-T9!?>r60LSG_H5U%&XJ;6$q06bq6*&ch zLkltUFRdHk5I&Ui;BDM6X?|U;-i@#fcrCLk1$iTo5k*81Q`dDl;3)Uac=mk#CKk&3mIp$w&a*D^aTCP_C*gI?f@wSkLMgI@74ep*KC4>0`e zxiw@1ks|iV*Zn1pG}b=8;>TAxr~iC zRC1|nu1Or#miFBjNerjbthyC0%Ay7@jL~tSPnA@(?3%~Jnm1-b4|Gge84qT%F8IwEZ36FF85=e!jzYiFYQxP#jxZKDXOVr zPF-H|NPIsX{69qokLcE8tts``-_onKW9UZNt|MbOR^p$hZRL%L)PJQf(7IgB{eA1YhC`kH^wq)KFjYs|yKS5ZuW%`38yjly#~}L9cGo7_^(G6Qhd8IM zNdm{&gL3 zaLO>F*0MTATuVEuAys^pk@yW!oi6)rCOd)gBt@<3r*5rQQD-_Lyf6OrjAPRRpA52s z_)w|gSsx~3oe4d}aHzP4dB#XN$4#f!=L7fd(=xw z?goCfYxt1Sy!NFC+`E9s?*9PRYLO(L{i}W)yP%}|Ir@w$6WW5jU9zb-%6~fVid~8H zsP=3cTr4*Lc&ogg!juIwy3fUS;h3tQ=SYy|X2p7Al&hZP7!H#*CN{DDRHAnt@Xx21LbdBYfovvEk-htqu z$>TrDuUhX~=y%$KT;AAQNoeiJSb#al2aany>FBMb*KAWz3T+I7#SCx=`_;#)G#-|{ z)cid)*3Q~YuqiI>qz>M1turE5Z3@GCX&L6FG;>~0CAI`xvWh*Z4ey=_r|zO#d#PfL ziz=PDrshJZ4?gsp8AaDa>Ki>C=SZJTBk>SL`sWLh9QW^6Zm{dvHO`*8x0>o>EXoGP z9r>(2)fpXGTzk}m?wIb8^2V76r`cI#X;MP*5Ps)vZ~YO~&wJAr@mp=Rg4#dA_;K^Q z0A;^A`SL3_nn02A$F*BJRcC`wmN?n>2~KuZ^2(7+5l!+l@m%V-rtMtGDsDcwr4BD}0$^WWD0_f^DmvXivneB;v^?8F z;QH0dg5ZPAI;amcqJ?pTnt37Yc{%Mus3#EtAXC$_K?#yZ!1~knkv9FKwLxoBv)oAs zWm8sM5G{2m3iyXU5aV@8TbSmL#D#+c>a|I^d@jMl{VGqQFN$i7X!$Y9J5*EVh}Q+6 zLgy{J2Aox8z*FDT6#d$&$aZ|bl$a0gcEw(bjyz`o@m`KL36}S!mGF5vr_uMX&A|7g zL^wWd?c`F1UD=Z#YI06gV?Dcyay3;|Vc*t?1Y5**Htzn^OnX+{qvLjSOzn~PGM~07 zghd4dW4`~!~s8%?lX0(Ym`N;-{2#tZq3kids zMMhuK+E69TiY3~)9J*J#i z-i_s5%ie>@-MWf)27?yYbbI^LQ$yjXD@5B|0KV19Cs%H9x~`Lbm23yi=}QqY8Rop< zvRfQdM3RBVe}!I&XUSIl+%G=0t=ljE0Ee58_jQuljNC`}t$94XHd~+W>k8=B*`D^B z>}%S-qawtxt9gBCxn<0>2BJrcQcSE+i6+Ims*YclG&xdF(wuB=Pi#{v+oV4Esuw#V zGVsF~rnoER{OG4|5Jk6yUz&vD#&W+YJXAyxAjU`2nh=UFYe+nxmL`j}&@~Iz{?Bg5 zJ-2a0ggse090t~KfA(!%Zj08HcMEOb@UW?FnCZ<^PrhmIEnXQ5Dbzl2bU?y?nc#;FpApwD@|_u zPZTrSvNy|C#kE&P4BJ&kK=(8xwwsS*!KKekUOKjl0% zk?GABon$Y%n>SMljEO6TKD($5R@zuK7<>stkg_W=U)es?QO_KTwj{YGNj@0!UR^VO zwr6iPc{!;YeR}%S{_8nL^+4A7yuhzGsnX!9xjsb$oSfHFhT@U+r7xJRM8QLxc&Q+z#9s6D2Is|he!v2(|iC_l67nyA~&CA)a2?H)Ta zoEl(ix3SJA=b+HIAbqg6ue-a+O@+Wz&e>6Xi3 zqCqZ^9CryS2W8JW$2E^2Rg4J^Da(8Nm=4&kU03`pX_JbV45lgUY_ohv({6te1?|Ux zj$#%Hx^~7-Wfb#VOK~Y{x!z6P_Z;SxCYZMz#f(rqmRwY1!zodxT!D5C0A{<0D5<+_Ea(@XH3Mda zZf)Bb1e%eyU+pQLeDtqTriBpx%!ePdLyL0ELEurg$-31>dkXTd);{#)R2AVI4&&aI zA|MPODD! zJ{}3c_NQV{s(8rHtr83H&KRlS*Ht{2CW(xBay!uSf=ZI0Fz-YMLm1-(F40f2F#!5{ zQg$g-Iql6j(iX?^pnw;qLcSvI;DJxyE3VcoGEM~x9LIkgW7eFMnRf3vqg;S8Wh)F# zkPbUh5+RX80DjWOOkw~P})H2Q6K9Dd(%6BVztN#L(etWlW5(H`_ZZ( zhRXe^#cU3Ljd|lkwflzcU5pkO{uDq_)QH#X(qRk|V^{6i?)pDC|+#1BdxnvuS( z*(mu|&p(Jyy=*D^&YECH`?|<1LmQ~T@4K~a>22Y3!?PdvS*&S%EYi%LXt5&?;ZeGP zJ~lmtOHU{+c;=#SSec2Xu%QSKgSe^x01wuhRspFh&Zji$+wb$Q@SqX30#r6^aiYYUr)(+p^TzD_Nv|0&*8Nh z?Zmu9#d1GttmQzfAm2#~a0AL2v6ji;Q%W7a0e7RMIvW|L&+1InxBZt?oY$x_757Ifx{0Fy2u8{)$OcGt;-}&# z?nS4@y$dFX)R5V9)~#c4YaH|56fw--G+R&X)FWycJ*akz$)DM-2&2a*lS9ssUKla) zeV>?8qPh;jRZeJ831) zaD8cpm6ApQLHk!;;j%EMi<)SvgNv}ZauGuwamlA247~Qu2^`tti(-5_d>x@PO);h$ zTLA7+T~C{eLu55AP7Zx2HUxs-4K(~<04Q6za|$nDrkwFtY|TJQ`@MXl)~PAb=)%PD z@7}DP1*1i;^)05KJf0kL6S@7cGgY1GyRpaKrn+t|Q7@9`O0l_?MEPA%;*|0#Tpj8k>rKL zs;JK()!SH~sP)_Cy-hCeG=DbLLII`8sdngeV?aG=p=p{Pq+qbTl4$lE_=QOgkEKLt zw?lV^%t1Y=zM#{!cALe#vbs(??5HfXc=Hu;{HVrMM!7Az))!8b&))zFtzF}0SG5rrXVvISPu5LnF^!r~EOqC$(ux(6Bd;2g=po)*v2~Ud6z` z{OioTU<}cqgZO2cUp!Y174yz0g;v>sDYF~r?NJcpyFT5jFgw>&DL5<0q7vL5bAl-` zjqwr}kZKTOG$64*DWgrdl@9|nGdWG5udP02cJdQ|D9{<{m>xX`705nsd{Ux8BIgyv zjHx8?LWmK+%Z&3*t{8KQ6+(qP^H0Frv600Th%dsx&+?}dJ{3LayFN?L-6SGq~osQ_eZA+)R-ucV#p(-bX8K1a3X5Qy^Y) z-!*zv^5i!(JASTQV1}#9iH}=!NCf zekHxUvPRvQEk@LPV5Z3hxR-#fPdw+s<^0Bjipx>(*A|lQ_QgZ$dfavw4{v)D$0GU~ zk#Uzyjx3*9-)=KqSsx!Y383%REezIb8Al&AO55odo6n82Z_%ocBonJ9#=!|Y#W>CR zR8G67E`@lJT@Asx8(N6z?LyaId1Hb=o*(a18%bLR$u<{}?@2F5of!wss359$TFf** z3>*kjd$u)MGfyuk0T!le@>gaJtn)r1iUPPW;;6-mFXCcKW&g7exO6_`v@F^P;Nr zE2LRsK3UUFFXI0Ij<$=IKkUKh{ndKCNsszvpJrPsg8ci`P1An0js<$XNqv?>QLh=P z7%SE4gk-g-%s`qcRBYsCy*@-pk^&Fmsq7<#NB**Vkh!aRRk4p7=s=$UNjYQjjWSV$@k}l8(HR|;R(O?^f zBH@&94>Y2HBYOSo)#_KNbav4d!){UE+LJ61GdGZaRqFK;tYM)}R~%6G@gW?odc9C3 zr$N(gfLZotMI2_UT|qmW#wQuidi8pW=pLZ9081MdA1}2T6})n1c5Bt@46un}SmIV* z=9Wk5L9bV-__}6ny^J}>o7R`zMS8tfeHBBIE?}FJQIa1%J*(B~M9mO34}~2kq+aPw zsb1UuB6Q_eQ)<#+dJg7w2syoLB`aIyyj|lOZ^-SF1J_+(|Xa z{ks(t0obK897}GD(dQ)BtJR=TqQ}AC`%O~a8Kzt6`t`l7=KlZ*&zoVvuUD#*=rKNr zx6pLHow8A;SwfAEo!4_8&ZF-&yS0le;g9?^>h&`eQ&!Ok33`_J&EdLRx*tZ4hw3h$ z(=|ONOS!F5Il#{7e6{NJT5(Bmf{boxmMf_vTJ(`3@ocBqQ80P!Nj2*AYF!Fq70xT3BOKSO)p8*#BM8{~ z=9A*LiRs09y+DGXnb@43^s9Cu+Xug;dc9PAmybZV?!lDinzWhTY%$Jj)#|$Ft1O9Z zz7k>FQ4(qKehH4}$gfwaO|gj-tF2Pz3zkG-v>#Ddo{Q7r)pWBh(S7@|`7nho&^(y`}#E&s1-S)~Tb(0@$;r?)hr)DpEYa6-0NJHoOWEJZ5J}voRU7tX% z-v&1DqR!F#G!CPGBv!NRjxUh@&3e646k_D96>Xn4O{(2CrFWKJpFOL6=uK|vdREVf zxL@6`SE-IFS!tkT;sLjvQ>ezLZ-f5;lCTcB*DtR6mgY%j=e8HMdc9keaj{tQ#T_?XYwssF%s$oX^i#MUns6MuPN} diff --git a/plugins/KeyboardioHID/Firmwares/Readme.md b/plugins/KeyboardioHID/Firmwares/Readme.md index 1cac79b6d9..45e0dd83e8 100644 --- a/plugins/KeyboardioHID/Firmwares/Readme.md +++ b/plugins/KeyboardioHID/Firmwares/Readme.md @@ -1,50 +1,3 @@ -Install new Firmwares with DFU and Flip on Arduino Uno/Mega R3 -============================================================== -From: http://nicohood.wordpress.com/2014/06/03/install-new-firmwares-with-dfu-and-flip-on-arduino-unomega-r3/ -This article is mainly made as an explanation on how to install the Hoodloader which is included in the HID Project. -But you can also flash other firmwares to your Arduino. **This tutorial is for Windows and R3 versions only.** -This method is called “Device Firmware Upgrade” and also works on Linux/Mac and older versions but its not explained in this article. - -**What you need: Arduino Uno/Mega, USB Cable, a normal jumper wire, Flip** - -Flashing the new firmware -========================= - -Install Flip first. This will also install the needed DFU drivers to flash the new firmware. Start Flip. - -**_Briefly_ short these two pins** of the 16u2 with a Wire **(the jumper is only to show the connection)**. -If you have an older Version than the R3 please google how to get in DFU mode. -Today everybody should have an r3 so no resistor and complicated stuff is needed. -![DFU_Bridge.jpg](DFU_Bridge.jpg) - -The device should now show up as Atmega16u2 in the device manager. -If not or if you get Error: **“AtLibUsbDfu.dll not found”** install the drivers manually from the device manager. -Right click the unknown device and select the Flip installation path to search the drivers. - -Click the IC Button an select **Atmega16u2. (same for Uno/Mega).** - -![Flip_1.PNG](Flip_1.PNG) - -**Click File->Load Hex File** and select the Firmware. (The Lite version is only if you have any bugs. Please report bugs.) - -![Flip_2.PNG](Flip_2.PNG) - -Click the USB Cable and **click open.** - -![Flip_2.PNG](Flip_2.PNG) - -**Click run** to upload the firmware. Uncheck Reset and click Start Application to restart your Arduino. Or just **replug the cable.** - -You probably need to **install new drivers for the new firmware.** Right click the device in the device manager and select the .inf file -provided with the firmware. Or just right click the .inf file and hit install. - -You are done! Have fun with your new Arduino Firmware. - -Deactivate HID function -======================= -Its possible to deactivate HID if you messed up something in the code and cannot return easily. -Just short these two pins permanently until you have uploaded your new, working sketch: - -![No_HID_Bridge.jpg](No_HID_Bridge.jpg) - -See http://nicohood.wordpress.com/ for more tutorials and projects \ No newline at end of file +Firmwares +========= +[**See installing instructions on the Hoodloader repository**](https://github.com/NicoHood/Hoodloader) diff --git a/plugins/KeyboardioHID/HID_Source/HID.cpp b/plugins/KeyboardioHID/HID_Source/HID.cpp index e9a843f38f..f632b19dc3 100644 --- a/plugins/KeyboardioHID/HID_Source/HID.cpp +++ b/plugins/KeyboardioHID/HID_Source/HID.cpp @@ -55,14 +55,6 @@ void HID_::sendReport(uint8_t ReportID, const void* HIDReport, uint8_t length){ // 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[] = { @@ -147,20 +139,20 @@ const u8 _hidReportDescriptor[] = { #ifdef HID_RAWKEYBOARD_ENABLE // RAW HID - 0x06, 0xC0, 0xFF, - 0x0A, 0x00, 0x0C, + 0x06, LSB(RAWHID_USAGE_PAGE), MSB(RAWHID_USAGE_PAGE), // 30 + 0x0A, LSB(RAWHID_USAGE), MSB(RAWHID_USAGE), 0xA1, 0x01, // Collection 0x01 - 0x85, HID_REPORTID_RawKeyboardReport, // REPORT_ID + 0x85, HID_REPORTID_RawKeyboardReport, // REPORT_ID 0x75, 0x08, // report size = 8 bits 0x15, 0x00, // logical minimum = 0 0x26, 0xFF, 0x00, // logical maximum = 255 - 0x95, 64, // report count TX + 0x95, RAWHID_TX_SIZE, // report count TX 0x09, 0x01, // usage 0x81, 0x02, // Input (array) - 0x95, 64, // report count RX + 0x95, RAWHID_RX_SIZE, // report count RX 0x09, 0x02, // usage 0x91, 0x02, // Output (array) 0xC0, // end collection @@ -838,6 +830,36 @@ void Keyboard_::releaseAll(void){ begin(); } +//================================================================================ +// RawHID +//================================================================================ + +RawHID_ RawHID; + +RawHID_::RawHID_(void){ + // empty +} + +size_t RawHID_::write(uint8_t b){ + write(&b, 1); +} + +size_t RawHID_::write(const uint8_t *buffer, size_t size){ + size_t bytesleft = size; + // first work through the buffer thats already there + while (bytesleft >= RAWHID_RX_SIZE){ + HID.sendReport(HID_REPORTID_RawKeyboardReport, &buffer[size - bytesleft], RAWHID_RX_SIZE); + bytesleft -= RAWHID_RX_SIZE; + } + // write down the other bytes and fill with zeros + if (bytesleft){ + uint8_t rest[RAWHID_RX_SIZE]; + memcpy(rest, &buffer[size - bytesleft], bytesleft); + memset(&rest[bytesleft], 0, RAWHID_RX_SIZE - bytesleft); + HID.sendReport(HID_REPORTID_RawKeyboardReport, &rest, RAWHID_RX_SIZE); + } +} + //================================================================================ // Media //================================================================================ diff --git a/plugins/KeyboardioHID/HID_Source/HID.h b/plugins/KeyboardioHID/HID_Source/HID.h index 0ec39ffa10..1ecc876d29 100644 --- a/plugins/KeyboardioHID/HID_Source/HID.h +++ b/plugins/KeyboardioHID/HID_Source/HID.h @@ -229,6 +229,20 @@ class Keyboard_ : public Print{ }; extern Keyboard_ Keyboard; +//================================================================================ +// RawHID +//================================================================================ + +class RawHID_ : public Print{ +public: + RawHID_(void); + using Print::write; // to get the String version of write + size_t write(uint8_t b); + size_t write(const uint8_t *buffer, size_t size); + +}; +extern RawHID_ RawHID; + //================================================================================ // Media //================================================================================ diff --git a/plugins/KeyboardioHID/HID_Source/HID_Reports.h b/plugins/KeyboardioHID/HID_Source/HID_Reports.h index 6b8a9fa4c4..5134236c2e 100644 --- a/plugins/KeyboardioHID/HID_Source/HID_Reports.h +++ b/plugins/KeyboardioHID/HID_Source/HID_Reports.h @@ -28,7 +28,13 @@ THE SOFTWARE. //Definitions //================================================================================ -// empty +#define LSB(_x) ((_x) & 0xFF) +#define MSB(_x) ((_x) >> 8) + +#define RAWHID_USAGE_PAGE 0xFFC0 // recommended: 0xFF00 to 0xFFFF +#define RAWHID_USAGE 0x0C00 // recommended: 0x0100 to 0xFFFF +#define RAWHID_TX_SIZE 63 // 1 byte for report ID +#define RAWHID_RX_SIZE 63 // 1 byte for report ID //================================================================================ //Report Typedefinitions @@ -64,6 +70,15 @@ typedef union{ } HID_KeyboardReport_Data_t; +typedef union{ + // a 32 byte buffer for rx or tx + uint8_t whole8[RAWHID_TX_SIZE]; + uint16_t whole16[RAWHID_TX_SIZE / 2]; + uint32_t whole32[RAWHID_TX_SIZE / 4]; + uint8_t buff[RAWHID_TX_SIZE]; +} HID_RawKeyboardReport_Data_t; + + typedef union{ // every usable media key possible. Only one at the same time. uint8_t whole8[8]; @@ -168,6 +183,7 @@ typedef union{ typedef union{ HID_MouseReport_Data_t Mouse; HID_KeyboardReport_Data_t Keyboard; + HID_RawKeyboardReport_Data_t RawKeyboard; HID_MediaReport_Data_t Media; HID_GamepadReport_Data_t Gamepad1; HID_GamepadReport_Data_t Gamepad2; @@ -178,15 +194,15 @@ typedef union{ /** Enum for the HID report IDs used in the device. */ typedef enum{ - HID_REPORTID_MouseReport = 0x01, /**< Report ID for the Mouse report within the device. */ - HID_REPORTID_KeyboardReport = 0x02, /**< Report ID for the Keyboard report within the device. */ - HID_REPORTID_RawKeyboardReport=0x03, /**< Report ID for the Raw Keyboard report within the device. */ - HID_REPORTID_MediaReport = 0x04, /**< Report ID for the Media report within the device. */ - HID_REPORTID_SystemReport = 0x05, /**< Report ID for the Power report within the device. */ - HID_REPORTID_Gamepad1Report = 0x06, /**< Report ID for the Gamepad1 report within the device. */ - HID_REPORTID_Gamepad2Report = 0x07, /**< Report ID for the Gamepad2 report within the device. */ - HID_REPORTID_Joystick1Report = 0x08, /**< Report ID for the Joystick1 report within the device. */ - HID_REPORTID_Joystick2Report = 0x09, /**< Report ID for the Joystick2 report within the device. */ + HID_REPORTID_MouseReport = 0x01, /**< Report ID for the Mouse report within the device. */ + HID_REPORTID_KeyboardReport = 0x02, /**< Report ID for the Keyboard report within the device. */ + HID_REPORTID_RawKeyboardReport = 0x03, /**< Report ID for the Raw Keyboard report within the device. */ + HID_REPORTID_MediaReport = 0x04, /**< Report ID for the Media report within the device. */ + HID_REPORTID_SystemReport = 0x05, /**< Report ID for the Power report within the device. */ + HID_REPORTID_Gamepad1Report = 0x06, /**< Report ID for the Gamepad1 report within the device. */ + HID_REPORTID_Gamepad2Report = 0x07, /**< Report ID for the Gamepad2 report within the device. */ + HID_REPORTID_Joystick1Report = 0x08, /**< Report ID for the Joystick1 report within the device. */ + HID_REPORTID_Joystick2Report = 0x09, /**< Report ID for the Joystick2 report within the device. */ } HID_Report_IDs; #endif \ No newline at end of file diff --git a/plugins/KeyboardioHID/HID_Source/Readme.md b/plugins/KeyboardioHID/HID_Source/Readme.md index 008b7557df..0324e8c0db 100644 --- a/plugins/KeyboardioHID/HID_Source/Readme.md +++ b/plugins/KeyboardioHID/HID_Source/Readme.md @@ -1,4 +1,9 @@ +HID Source +========== + **Move and replace** these files to (depending on your version and path): +``` C:\Arduino\arduino-1.0.5\hardware\arduino\cores\arduino C:\Arduino\arduino-1.5.6-r2\hardware\arduino\avr\cores\arduino -C:\Arduino\arduino-1.5.7\hardware\arduino\avr\cores\arduino \ No newline at end of file +C:\Arduino\arduino-1.5.7\hardware\arduino\avr\cores\arduino +``` \ No newline at end of file diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index de5ee22a8e..1219d79b21 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -1,4 +1,4 @@ -Arduino HID Project BETA 1.5 +Arduino HID Project BETA 1.7 ============================ Dont you always wanted to turn your Arduino in a Generic HID device like a Keyboard or a Gamepad? Disappointed that the Uno doesnt support this at all and the Micro/Leonardo only Mouse + Keyboard? @@ -11,6 +11,8 @@ Before you had to upload a sketch, flash the firmware, test, flash the firmware, **For the Leonardo/Micro it is 'just' new device stuff, no need for a bootloader.** +[Hoodloader Repository moved here.](https://github.com/NicoHood/Hoodloader) + Features ======== Use your **Arduino Uno, Mega, Micro, Leonardo or Micro Pro** as Generic HID Device and still be able to upload sketches how you are used to do. @@ -22,6 +24,7 @@ I also corrected some bugs in the original sources. * Arduino HID Uno/Mega library * Arduino HID Micro/Leonardo library * Arduino HID Bootloader (Hoodloader) + driver +* Arduino as ISP with the 16u2 (Hoodloader only, [more information](https://github.com/NicoHood/Hoodloader)) * Compatible with Linux/Mac/Windows XP/7/8.1* * Compatible with IDE 1.0.x - 1.5.7 (newer versions might need an update) @@ -40,7 +43,7 @@ I also corrected some bugs in the original sources. Installation Leonardo/Micro/Uno/Mega ==================================== -Download the library and install like you are used to. +Download the library and install like you are used to (access the examples and save the firmware). Then **move and replace** all files from "HID_Source" to the folder that matches your Arduino IDE version to one of these paths (depending on your version): ``` @@ -51,11 +54,12 @@ C:\Arduino\arduino-1.5.7\hardware\arduino\avr\cores\arduino The installation path may differ to yours. Newer Versions than 1.5.7 may not work. **I strongly recommend to install the library like this. Otherwise it wont work.** -Now you are able to use the library with all kind of Arduinos. The HID include and HID.begin() is optional for Leonardo/Micro -but necessary for Uno/Mega. I'd recommend to use it every time so you can port the library from one to another device. #### Leonardo/Micro only -**Edit HID.h to de/activate usb functions.** Each function will take some flash, +**Edit HID.h to de/activate usb functions.** +By default Mouse, Keyboard, Media, System, Gamepad1 is activated. + +Each function will take some flash, so if you want to save flash deactivate everything you dont need. By default Mouse, Keyboard, Media, System, Gamepad1 is activated. You cannot use more than 255 bytes HID report on the Leonardo/Micro. @@ -63,57 +67,41 @@ The number after each definition tells you the size of each report. I have no idea why you cannot use more than 255 bytes (yet), its a bug in the Arduino code. #### Uno/Mega only -To **install the new bootloader** connect your Arduino to your PC and put it into DFU mode. +To **install the new bootloader** connect your Arduino to your PC via USB and see +[Hoodloader installing instructions](https://github.com/NicoHood/Hoodloader). **You can always switch back to the original firmware, nothing to break.** -See the readme in the Firmware folder for Windows or [this general (outdated) tutorial](http://arduino.cc/en/Hacking/DFUProgramming8U2) -on how to upload the hex file to your Arduino. Some notes here: The Arduino R3 doesnt need a resistor or so, just connect the two pins near -the USB B jack. Choose atmega16u2 for the new R3 version. For older version you need to check Google. It might not work on older Arduinos. -For a Flip dll error install the drivers manually from the flip directory (see readme) - -Upload the hex file to your Arduino. It doesnt care if its a Uno/Mega. It will just work the same. -Unplug the Arduino if it says successful and plug it back in. You cannot destroy anything here and you can always -switch back to the original firmware which is included with the download. -**You need to install new drivers for the new device on Windows.** Actually they are not new, its just an .inf file that tells -Windows to use its built in CDC Serial driver. Ironically Microsoft never signed its own driver. -Also see [this tutorial](http://arduino.cc/en/guide/windows) on how to install the drivers (rightclick the .inf file and hit install). -[How to install drivers for Windows 8/8.1](https://learn.sparkfun.com/tutorials/disabling-driver-signature-on-windows-8/disabling-signed-driver-enforcement-on-windows-8). -If you want it to be recognized as Uno/Mega edit the makefile and recompile. I dont recommend this to know what -Bootloader currently is on your Board. For Arduino Mega2560 I recommend (in general) the IDE 1.5.7 or higher. [See Issue on Github.](https://github.com/arduino/Arduino/issues/1071) +[Or this Issue.)(http://forum.arduino.cc/index.php?topic=126160.0) #### For all Arduinos -You are ready to use the libraries. **Just have a look at the examples and test it out.** + + +Usage +===== +You are ready to use the libraries. **Just have a look at the examples and test it out.** They are pretty much self explaining. All examples use a button on pin 8 and show the basic usage of the libraries. -The libraries will work for all Arduinos listed above but it will use 2 different HID libraries (automated). +The libraries will work for all Arduinos listed above but it will use 2 different HID libraries (automatically). + **On Arduino/Mega you can only use baud 115200 for HID** due to programming reasons. Its not bad anyway because its the fastest baud and you want fast HID recognition. You still can use any other baud for -normal sketches without HID. The HID include and HID.begin() is not needed for Leonardo/Micro but recommended. -HID.begin() starts the Serial at baud 115200 on Arduino Uno/Mega. Do not call Serial.begin() again. +normal sketches without HID. HID.begin() starts the Serial at baud 115200 on Arduino Uno/Mega. Do not call Serial.begin() again. + +The HID include and HID.begin() is not needed for Leonardo/Micro but I'd recommend +to use it every time so you can port the library from one to another device. **Always release buttons to not cause any erros.** Replug USB cable to reset the values if anything went wrong. -Connect GND and MOSI2 to deactivate HID function on Uno/Mega (see readme in /Firmwares) +See [Deactivate HID function](https://github.com/NicoHood/Hoodloader) if you need to fully disable HID again. + +For Arduino as ISP usage (optional, has nothing to do with HID) see [Hoodloader repository](https://github.com/NicoHood/Hoodloader). How it works ============ For the Leonardo/Micro its just a modified version of the HID descriptor and Classes for the new devices. Its not that complicated, everything you need is in the main 4 .h/cpp files. -For the Uno/Mega you need a special Bootloader. Why? Because the Uno/Mega has 2 chips on board. -The 328/2560 and 16u2 on each. And the only communication between the 16u2 and the main chip is via Serial. -But the Serial is also used to program the chip. So what I do here is to filter out all Serial Data that comes in -via the NicoHoodProtocol (NHP). There is an indicator address 1 which contains the beginning and the Report ID. -If the following Serial information is Address 2 with a valid checksum the report will be created and sent if its -finished successful. If any error occurred within the first 2 Protocol Addresses the information will be sent via Serial. -The Program should forward this information because it could be a normal information. Everything above 2 Addresses that goes -wrong wont be sent and discarded due to a normal wrong HID report. Normally you dont have to worry about getting weird HID -presses. You need to send exactly 6 bytes with the special Numbers and another 6 bytes for the first information with checksum -and complete the full report. You might get weird Serial output if you hit the exact 12 bytes without timeout of a few milliseconds. -And if the reading timed out the Data will also be forwarded. And if you only send Ascii Code the Information is forwarded instantly -because the NHP filters that out instantly (see documentation of the NHP). So filtering should be fine and dont block :) - -To sum it up: Serial information is grabbed by the "man in the middle" and you dont have to worry to get any wrong report. -See picture in readme (/Firmwares) how to deactivate HID function by hardware. +For the Uno/Mega you need a special Bootloader. Why? See [Hoodloader repository](https://github.com/NicoHood/Hoodloader). +To sum it up: Serial information is grabbed by the "man in the middle, 16u2" and you dont have to worry to get any wrong Serial stuff via USB. This library wouldnt be possible without ======================================== @@ -133,17 +121,21 @@ This library wouldnt be possible without Ideas for the future ==================== * Add more devices (even more?) -* Add Midi (do you want that?) -* Add ICSP Programmer function (ram limit is a problem) +* Add Midi (no more free Endpoints) * Add Led/SPI support (discarded, not needed, too slow) -* Add rumble support (very hard) +* Add HID rumble support (very hard) * Add Xbox Support (too hard) * Add Report Out function (for Keyboard Leds etc, maybe the 4 pin header?) -* RAW HID Known Bugs ========== System Wakeup is currently not working on all versions! +System Shutdown is only working on Windows systems. + +RawHID only works on Uno/Mega. + +Programming Arduino Mega with ISP doesnt work because of fuses. Burning Bootloader error is fixed with IDE 1.5.7 or higher (avrdude bug)! +See this for more information: http://forum.arduino.cc/index.php?topic=126160.0 Feel free to open an Issue on Github if you find a bug. Or message me via my [blog](http://nicohood.wordpress.com/)! @@ -152,6 +144,8 @@ Known Issues **Do not name your sketch HID.ino, this wont work!** +**Do not use HID in interrupts because it uses the Serial. Your Arduino can crash!** + **If you get a checksum error after uploading please message me and send me the whole project.** Same if your Arduino crashes and dont want to upload sketches anymore (Replug usb fixes this). These bugs occurred while developing the bootloader and should be fixed. Just in case it happens again I noted it here. @@ -166,7 +160,7 @@ If you dont use HID you can still choose the baud of your choice. XBMC 13.1 (a Media Center) uses Gamepad input. Its seems to not work and may cause weird errors. Even with a standard Gamepad I have these errors. Just want to mention it here. -Not tested on the 8u2 (should only work without DFU due to size. message me if it works!) +Not tested on the 8u2 (should only work without DFU and v1.6 due to size. message me if it works!) Not tested on the Due (message me if it works!) @@ -179,6 +173,18 @@ Oh and by the way: I also removed some bugs from the official firmware. Version History =============== ``` +1.7 Beta Release (09.08.2014) +* Changes in the Hoodloader: + * Works as ISP now. See the [Hoodloader Repository](https://github.com/NicoHood/Hoodloader) for more information. + * Exceeded 8kb limit. For flashing a 8u2 use v1.6 please! +* Changed Readme text + +1.6 Beta Release (09.08.2014) +* Bugfixes in the Hoodloader: + * Changed HID management (not blocking that much, faster) + * added RawHID in/out (HID to Serial) +* Added RawHID Class and example + 1.5 Beta Release (21.07.2014) * Moved Hoodloader source to a [separate Github page](https://github.com/NicoHood/Hoodloader) * Bugfixes in the Hoodloader: @@ -267,7 +273,7 @@ https://support.microsoft.com/kb/315539 The Hootloader was coded with Windows7 and Visual Studio and compiled with a Raspberry Pi. Lufa version 140302 is included! -**To recompile see instructions in [Hoodloader Repository](https://github.com/NicoHood/Hoodloader) ** +**To recompile see instructions in [Hoodloader Repository](https://github.com/NicoHood/Hoodloader).** The difference between the Leonardo/Micro and Uno/Mega is that the HID Class is different. All other classes are the same. The Leonardo/Micro Version uses USBAPI.h and no Serial while the Uno/Mega Version uses Serial. diff --git a/plugins/KeyboardioHID/examples/AdvancedRawHID/AdvancedRawHID.ino b/plugins/KeyboardioHID/examples/AdvancedRawHID/AdvancedRawHID.ino new file mode 100644 index 0000000000..ed7eee1db2 --- /dev/null +++ b/plugins/KeyboardioHID/examples/AdvancedRawHID/AdvancedRawHID.ino @@ -0,0 +1,152 @@ +/* + Copyright (c) 2014 NicoHood + See the readme for credit to other people. + + Advanced RawHID example + Shows how to send bytes via raw HID + Press a button to send some example values. + Keep in mind that you can only send full data packets, the rest is filled with zero! + + Definitions from HID_Reports.h: + RAWHID_USAGE_PAGE 0xFFC0 // recommended: 0xFF00 to 0xFFFF + RAWHID_USAGE 0x0C00 // recommended: 0x0100 to 0xFFFF + RAWHID_TX_SIZE 63 // 1 byte for report ID + RAWHID_RX_SIZE 63 // 1 byte for report ID + */ + +// not needed for Leonardo/Micro +#include + +// for Leonardo/Micro: make sure to activate desired USB functions in HID_Reports.h + +const int pinLed = 13; +const int pinButton = 8; + +void setup() { + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); + + // Starts Serial at baud 115200. end just ends the Serial + // Make sure to end your special HIDs before, this does not clear them! + // You need this baud for the HID library but still can use other bauds + // without HID functions. + // not needed for Leonado/Micro, Serial will not be set + HID.begin(); +} + +void loop() { + if (!digitalRead(pinButton)) { + digitalWrite(pinLed, HIGH); + + // direct without library. Always send RAWHID_RX_SIZE bytes! + uint8_t buff[RAWHID_RX_SIZE]; // unitialized, has random values + HID.sendReport(HID_REPORTID_RawKeyboardReport, buff, sizeof(buff)); + + // with library + memset(&buff, 42, sizeof(buff)); + RawHID.write(buff, sizeof(buff)); + + // write a single byte, will fill the rest with zeros + RawHID.write(0xCD); + + // huge buffer with library, will fill the rest with zeros + uint8_t megabuff[256]; + for (int i = 0; i < sizeof(megabuff); i++) + megabuff[i] = i; + RawHID.write(megabuff, sizeof(megabuff)); + + // You can use print too, but better dont use a linefeed + RawHID.println("Hello World"); + + // And compare it to write: + RawHID.write("Hello World\r\n"); + + // simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } +} + +/* +Expected output: + +// manual with unintialized buff +recv 63 bytes: +1B B7 0B 88 1F 99 1F 5A 95 A9 F7 80 95 90 95 BC +01 CD 01 08 95 A1 E2 1A 2E AA 1B BB 1B FD 01 0D +C0 AA 1F BB 1F EE 1F FF 1F A2 17 B3 07 E4 07 F5 +07 20 F0 A2 1B B3 0B E4 0B F5 0B 66 1F 77 1F + +// filled buff +recv 63 bytes: +2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A +2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A +2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A +2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A + +// single byte filled with zero +recv 63 bytes: +CD 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +// huge buffer filled with zero at the end +recv 63 bytes: +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 1E 1F +20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F +30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E + +recv 63 bytes: +3F 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E +4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E +5F 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E +6F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D + +recv 63 bytes: +7E 7F 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D +8E 8F 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D +9E 9F A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD +AE AF B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC + +recv 63 bytes: +BD BE BF C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC +CD CE CF D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC +DD DE DF E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC +ED EE EF F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB + +recv 63 bytes: +FC FD FE FF 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +// print +recv 63 bytes: +48 65 6C 6C 6F 20 57 6F 72 6C 64 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +//\r +recv 63 bytes: +0D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +//\n +recv 63 bytes: +0A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +//write +recv 63 bytes: +48 65 6C 6C 6F 20 57 6F 72 6C 64 0D 0A 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +*/ \ No newline at end of file diff --git a/plugins/KeyboardioHID/examples/Readme.md b/plugins/KeyboardioHID/examples/Readme.md new file mode 100644 index 0000000000..30a01d3b39 --- /dev/null +++ b/plugins/KeyboardioHID/examples/Readme.md @@ -0,0 +1,4 @@ +Examples +======== + +Just try these examples once the HID Source is installed. Its pretty much self explaining. \ No newline at end of file diff --git a/plugins/KeyboardioHID/hardware/16u2asISP/avr/boards.txt b/plugins/KeyboardioHID/hardware/16u2asISP/avr/boards.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/plugins/KeyboardioHID/hardware/16u2asISP/avr/programmers.txt b/plugins/KeyboardioHID/hardware/16u2asISP/avr/programmers.txt new file mode 100644 index 0000000000..e34a804861 --- /dev/null +++ b/plugins/KeyboardioHID/hardware/16u2asISP/avr/programmers.txt @@ -0,0 +1,8 @@ +arduino16u2asisp.name=16u2 as ISP +arduino16u2asisp.communication=serial +arduino16u2asisp.protocol=stk500v1 +arduino16u2asisp.speed=1 +arduino16u2asisp.program.protocol=stk500v1 +arduino16u2asisp.program.speed=1 +arduino16u2asisp.program.tool=avrdude +arduino16u2asisp.program.extra_params=-P{serial.port} -b{program.speed} diff --git a/plugins/KeyboardioHID/hardware/Readme.md b/plugins/KeyboardioHID/hardware/Readme.md new file mode 100644 index 0000000000..8680a13d8e --- /dev/null +++ b/plugins/KeyboardioHID/hardware/Readme.md @@ -0,0 +1,8 @@ +Hardware +======== + +Put this folder (16u2asISP) into sketchbook/hardware/ like this: +``` +Arduino/sketchbook/hardware/16u2asISP/avr/boards.txt +Arduino/sketchbook/hardware/16u2asISP/avr/programmers.txt +``` \ No newline at end of file diff --git a/plugins/KeyboardioHID/keywords.txt b/plugins/KeyboardioHID/keywords.txt index 72237a192b..8d04ebace5 100644 --- a/plugins/KeyboardioHID/keywords.txt +++ b/plugins/KeyboardioHID/keywords.txt @@ -36,6 +36,7 @@ sendReport KEYWORD2 HID KEYWORD3 Mouse KEYWORD3 Keyboard KEYWORD3 +RawHID KEYWORD3 Media KEYWORD3 System KEYWORD3 Gamepad1 KEYWORD3 @@ -145,6 +146,10 @@ RAW_KEYBOARD_PRINT LITERAL1 RAW_KEYBOARD_SCROLL_LOCK LITERAL1 RAW_KEYBOARD_PAUSE LITERAL1 +#RawHID +RAWHID_RX_SIZE LITERAL1 +RAWHID_TX_SIZE LITERAL1 + #Media MEDIA_FAST_FORWARD LITERAL1 From d516b8d0667bbd09695f2cd934981cb92d7864b5 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 10 Aug 2014 02:37:20 +0200 Subject: [PATCH 039/602] Update 1.7.1 --- .../KeyboardioHID/Firmwares/Hoodloader1_7.hex | 605 ------------------ .../Firmwares/Hoodloader1_7_1.hex | 605 ++++++++++++++++++ plugins/KeyboardioHID/Readme.md | 16 +- 3 files changed, 614 insertions(+), 612 deletions(-) delete mode 100644 plugins/KeyboardioHID/Firmwares/Hoodloader1_7.hex create mode 100644 plugins/KeyboardioHID/Firmwares/Hoodloader1_7_1.hex diff --git a/plugins/KeyboardioHID/Firmwares/Hoodloader1_7.hex b/plugins/KeyboardioHID/Firmwares/Hoodloader1_7.hex deleted file mode 100644 index 156b82aebd..0000000000 --- a/plugins/KeyboardioHID/Firmwares/Hoodloader1_7.hex +++ /dev/null @@ -1,605 +0,0 @@ -:1000000073C100008DC100008BC1000089C10000D8 -:1000100087C1000085C1000083C1000081C10000CC -:100020007FC100007DC100007BC100000C94770CF3 -:100030000C94230D75C1000073C1000071C1000054 -:100040006FC100006DC100006BC1000069C10000FC -:1000500067C1000065C1000063C1000012C200005A -:100060005FC100005DC100005BC1000059C100001C -:1000700057C1000030034100720064007500690040 -:100080006E006F00200048006F006F0064006C007D -:100090006F0061006400650072002000420065008E -:1000A00074006100000012034E00690063006F00DD -:1000B00048006F006F006400000004030904090297 -:1000C0005F00030100C032080B00020202010009B8 -:1000D00004000001020201000524001001042402B2 -:1000E000060524060001070582030800FF09040134 -:1000F00000020A0000000705040240000107058312 -:10010000024000010904020001030000000921115E -:1001100001000122B801070581032000011201102E -:1001200001EF020108EB03686E17000102DC010514 -:10013000010902A1010901A100850105091901298F -:10014000051500250195057501810295017503814D -:100150000305010930093109381581257F75089596 -:10016000038106C0C005010906A101850205071922 -:10017000E029E715002501750195088102950175B3 -:1001800008810395067508150025650507190029DE -:1001900065810005081901290595057501910295EC -:1001A0000175039103C006C0FF0A000CA10185037D -:1001B0007508150026FF00953F09018102953F094A -:1001C000029102C0050C0901A1018504150026FF5A -:1001D000FF19002AFFFF950475108100C005010971 -:1001E00080A1018505150026FF00190029FF950152 -:1001F00075088100C005010905A1018506050919D9 -:10020000012920150025017501952081020501A114 -:10021000000930093109320933093409351500273D -:10022000FFFF0000751095068102C005010939091C -:100230003915012508950275048102C005010905DB -:10024000A10185070509190129201500250175015E -:10025000952081020501A1000930093109320933D5 -:1002600009340935150027FFFF0000751095068138 -:1002700002C0093909391501250895027504810262 -:10028000C005010904A1018508A10005091901297A -:100290000215002501750195028102050109300949 -:1002A00031150026FF03750A95028102750295013A -:1002B0008103C0C005010904A1018509A100050948 -:1002C0001901290215002501750195028102050118 -:1002D00009300931150026FF03750A950281027560 -:1002E0000295018103C0C00011241FBECFEFD2E0F0 -:1002F000DEBFCDBF11E0A0E0B1E0E6E8F5E202C06C -:1003000005900D92AE32B107D9F712E0AEE2B1E03E -:1003100001C01D92A634B107E1F786D70C94C11233 -:100320006FCE9BB1809589238BB908959BB1982B93 -:100330009BB90895CF93DF9384B7877F84BF28E16B -:100340000FB6F89420936000109260000FBE80E119 -:1003500090E09093CD008093CC00CAECD0E096E082 -:100360009883A8ECB0E082E08C93E9ECF0E0208385 -:10037000539A5A9A5B9A10821C92188298838C9393 -:1003800088E980835B988AB180638AB98BB1806386 -:100390008BB90E94680C84E085BD5F9A579A209AB9 -:1003A00022982A9ADF91CF9108950895089580E0C8 -:1003B00091E00E94A91180E191E00E94E60EE2EE38 -:1003C000F0E080818460808308951F93CF93DF9352 -:1003D000EC01E98DE150E23028F4F0E0E55DFE4FFC -:1003E000108101C010E0888D823009F418608A8D78 -:1003F000873031F0883031F0863029F4126003C044 -:10040000146001C016605B9A1092C9001092C80077 -:100410001092CA002C893D894E895F89211581EE91 -:1004200038074105510579F0CA01B90196958795BC -:100430007795679560587B47814E9F4F0E94821247 -:100440002150310902C020E130E03093CD002093EB -:10045000CC001093CA008C899D89AE89BF89811513 -:10046000914EA105B10511F480E001C082E08093B6 -:10047000C80088E98093C9005B98DF91CF911F91F4 -:1004800008951F920F920FB60F9211242F933F934E -:100490008F939F93AF93BF93EF93FF938091CE0081 -:1004A00090912E019330F9F090913D029430D9F45F -:1004B000EFE2F1E0A081B1818C938081918101967E -:1004C00091838083268137818217930721F4848169 -:1004D0009581918380832FB7F894828593850196C7 -:1004E000938782872FBFFF91EF91BF91AF919F912B -:1004F0008F913F912F910F900FBE0F901F901895E5 -:10050000FC01208920FF02C05F9808955F9A8BB19B -:1005100080638BB9089580E191E00E94BF0F80E075 -:1005200091E00C94721080910E0190910F01009750 -:1005300029F0019790930F0180930E010895EF9297 -:10054000FF920F931F93CF93DF937B01C901E801C3 -:100550002091BD012223E1F04091BE012091BF0115 -:10056000421316C0E0ECF1E050E0BF010E94B1126E -:100570008091BD01F70180838091BE01888319823B -:100580001092BD011092BF011092BE0181E001C026 -:1005900080E0DF91CF911F910F91FF90EF90089530 -:1005A000EF92FF920F931F93CF93DF931F92CDB7DC -:1005B000DEB77901633081F480E16983B2DE69815D -:1005C0006093BC01B801C7010F90DF91CF911F91DB -:1005D0000F91FF90EF901DC70F90DF91CF911F916A -:1005E0000F91FF90EF90089510920B021092FF016F -:1005F000089520912E018091240190912501A091D0 -:100600002601B09127010097A105B10539F08115A8 -:1006100032EC930731E0A307B10511F482E007C083 -:100620000197A105B10511F483E001C081E0809339 -:100630002E0180912E01281709F43BC0233011F0C0 -:1006400021111DC0EFE2F1E02FB7F8948BE391E0A8 -:100650009183808393838283958384838BEB91E062 -:100660009783868380E890E091878087138612863F -:100670002FBF1092BB011092BC0180E357DE809126 -:100680002E01823021F4B0DF1092BD010895833035 -:1006900081F41092300110922F01109232011092C9 -:1006A0003101109234011092330180E33FDE229831 -:1006B0002A9A0895462F209111012F702093E90066 -:1006C0002091E80020FFFCCF2091200120FF06C0F0 -:1006D00050E0BC0180E191E00C940B0F0895CF92A3 -:1006E000DF92EF92FF920F931F93FA018B01009517 -:1006F000109520E030E0980111270027AB0160E061 -:1007000070E0042B152B262B372B4CE150E097E0A3 -:1007100068017901042E04C0F694E794D794C79435 -:100720000A94D2F76C2D683028F0973059F4C082C3 -:1007300096E008C0C0829150C11004C047505109D2 -:10074000923031F7492F425013C0DF01A40FB11D81 -:1007500068017901E894C7F8DD24EE24FF24CC92E7 -:10076000B7E03695279517950795BA95D1F741507B -:100770004111EBCF492F50E09A01A3E0220F331F24 -:10078000AA95E1F7206C3F6F3081322B3083E40F64 -:10079000F51F319781508F7380688083892F1F9157 -:1007A0000F91FF90EF90DF90CF900895CF93DF935C -:1007B00000D000D000D0CDB7DEB76091BD01662378 -:1007C00079F08091BF0181110BC070E07160AE01C2 -:1007D0004F5F5F4F81E083DF682FCE0101966ADFB4 -:1007E0001092BD0126960FB6F894DEBF0FBECDBFA6 -:1007F000DF91CF9108950F931F93982F40910B0293 -:10080000E42FF0E0EB5FFD4F808380910B028F5F60 -:1008100080930B02892F807C803809F444C0803C8F -:1008200009F05FC0292F287326952695269522303A -:1008300008F477C0273079F4492F4F7050E060E01A -:1008400070E04093000250930102609302027093A3 -:10085000030215E00FC0892F877090E0A0E0B0E0A0 -:100860008093000290930102A0930202B0930302CE -:10087000122F11508091FF01882391F097DF609132 -:100880000B02615085E092E015DFE0910B02F0E091 -:10089000EC5FFD4F80818093050281E080930B0225 -:1008A0001093FF0145C08091FF018130D1F5009187 -:1008B0000002109101022091020230910302A9016D -:1008C0006627772722273327402751276227732758 -:1008D0004F3F5F4F6105710521F5892F8F738F5F42 -:1008E00028C08091FF018230E0F081508093FF01A9 -:1008F0004091000250910102609102027091030246 -:1009000027E0440F551F661F771F2A95D1F7492B03 -:10091000409300025093010260930202709303021D -:1009200007C044DF60910B0285E092E0C3DE5CDE2D -:1009300080E01F910F910895CF935DDFC82F88232A -:1009400009F489C08091BD01811104C0C13009F052 -:1009500046C010C09091BE018091BF019813F6CFA0 -:1009600004C080E091E00E94BE118091BD01811120 -:10097000F8CFECCF80910102813089F517DF90919B -:1009800000029093BD011092BF018FE3E0ECF1E013 -:10099000DF01282F1D922A95E9F79530A9F058F428 -:1009A000923081F018F49130C1F40AC0933091F084 -:1009B000943099F407C0983050F09A3070F409C020 -:1009C00084E008C088E006C0C093BE0142C081E157 -:1009D00001C083E08093BE013CC0E8DE3AC0809154 -:1009E000BD01882381F16091BF01462F50E08C2F1B -:1009F00090E09A012E5F3F4F359527952F5F3F4F2F -:100A00008217930701F5FA01E054FE4F809100022E -:100A10008083E62FEF5FE093BF018091BE018E17C8 -:100A200049F0F0E0E054FE4F9091010290836E5F38 -:100A30006093BF019091BF0189130BC080E091E0EA -:100A40000E94BE1106C0B2DE60910B0285E092E00A -:100A500031DECF91C9CDCF910895682F80E191E02B -:100A60000E94290F8823E9F080E191E00E947B0F2A -:100A70000E94CA0E80E155DC2FEF81EE94E02150F8 -:100A800080409040E1F700C0000080E14ADC2FEF99 -:100A900081EE94E0215080409040E1F700C00000DA -:100AA000E9CF089580E191E00E94910F97FDFACF80 -:100AB0000895EF92FF920F931F93CF93DF937C01E2 -:100AC00009E311E0C0E0D0E005C0ECDFF80181935C -:100AD0008F012196CE15DF05C4F3DF91CF911F91D1 -:100AE0000F91FF90EF9008959091450180E0209143 -:100AF0004601820F911D90933601809335019091AC -:100B0000470180E020914801820F911D90933801A8 -:100B1000809337010895CF93C82FC4DF803239F412 -:100B200084E19BDF8C2F99DF80E1CF9196CF85E127 -:100B300094DF80912F0190913001019690933001C4 -:100B400080932F01CF910895813859F018F480389F -:100B500071F405C0823839F0833949F406C082E067 -:100B600007C081E005C082E103C083E501C080E0E9 -:100B7000D2CF98DF803221F484E16FDF80E16DCF46 -:100B800080E2CFDB2FEF80E792E021508040904061 -:100B9000E1F700C0000080E2C9DB2FEF80E792E0C0 -:100BA000215080409040E1F700C0000080E2B9DBB6 -:100BB0002FEF80E792E0215080409040E1F700C0A5 -:100BC000000080E2B3DB85E148DF80912F01909146 -:100BD000300101969093300180932F01089583E5B1 -:100BE0008CBD8DB58EB508950DB407FEFDCF08956B -:100BF0008EBDFADF8EB50895CF93DF9300D01F929C -:100C0000CDB7DEB72B834A836983F2DF6981862FF4 -:100C1000EFDF4A81842FECDF2B81822F0F900F9022 -:100C20000F90DF91CF91E4CFDADF249A2C9A219AAA -:100C300029982FEF80E792E0215080409040E1F723 -:100C400000C000002C982FEF80E792E021508040F8 -:100C50009040E1F700C000002398229A20E040E095 -:100C600063E58CEAC9DF81E090E0909332018093E4 -:100C700031010895462F880F880F880F20E0672FD5 -:100C8000805EBACF0F931F93CF93DF938C01C0E0A8 -:100C9000D0E019C0609133017091340180E0EADF47 -:100CA000DCDE609133017091340181E0E3DFD5DE59 -:100CB00020913301309134012F5F3F4F3093340145 -:100CC000209333012296C017D10724F380E1DF91EE -:100CD000CF911F910F91089584E090E0EADE20917A -:100CE0003C0140913B0160913A018091390184DFE0 -:100CF00012CFD8DE803259F080912F0190913001CF -:100D000001969093300180932F0185E115C084E115 -:100D1000A4DE20E040E060E080E36EDF9EDE20E0C5 -:100D200041E060E080E368DF98DE20E042E060E0E0 -:100D300080E362DF92DE80E190CE23982298229AAF -:100D40002198249810923201109231010895CF9287 -:100D5000DF92EF92FF920F931F93CF93DF93D82FE1 -:100D6000C92F7B01CB01A5DE80E2E0DAE9E3CE2EDC -:100D7000E1E0DE2E0D2F1C2FE80111C0F6012191BC -:100D80006F014C2F6D2F80EC37DFFFE722E382E00D -:100D9000F15020408040E1F700C000002196CE01D4 -:100DA000801B910B8E159F054CF380E2BADA80E12F -:100DB000DF91CF911F910F91FF90EF90DF90CF9037 -:100DC00008950F931F93CF93DF93C0913301D09178 -:100DD000340120913701309138012817390724F068 -:100DE000CC0FDD1F8C0112C080912F01909130013A -:100DF00001969093300180932F0181E10EC060E253 -:100E000070E0CE01A4DFA096005211090132110555 -:100E1000B4F7B801CE019BDF80E1DF91CF911F9144 -:100E20000F910895EF92FF920F931F93CF93DF934B -:100E30007C010091330110913401000F111FE80172 -:100E400007C02FEF4C2F6D2F80EAD6DE06DE2196ED -:100E5000CE01801B910B8E159F059CF380E1DF91E5 -:100E6000CF911F910F91FF90EF9008951F93CF9313 -:100E7000DF9318DED82F16DEC82F14DE182F12DEEF -:100E8000803259F080912F0190913001019690931A -:100E9000300180932F0185E113C03D2F20E0C9016F -:100EA0008C0F911DEC0184E1D8DD163419F4CE01CC -:100EB000E9DE06C0153419F4CE01B4DF01C081E1CA -:100EC000DF91CF911F91C9CDCF93DF9300D0CDB7E4 -:100ED000DEB7482F80E249839A8328DA20E04981EF -:100EE0009A81692F8CE488DE2FEF86E791E021500C -:100EF00080409040E1F700C0000080E20F900F902A -:100F0000DF91CF910ECA80913501909136012091E9 -:100F10003301309134018032910511F4207F0EC0ED -:100F20008034910511F4207E09C08038910511F4B8 -:100F3000207C04C08115914009F42078C9010895EE -:100F4000962F672F242F880F880F880F492F805CDA -:100F500053CECF92DF92EF92FF920F931F93CF93D6 -:100F6000DF936C01D0DF8C01C0E0D0E029C0CBDF83 -:100F70000817190721F0C801A7DFC5DF8C01BEE201 -:100F8000EB2EB1E0FB2EEC0EFD1E60913301709153 -:100F90003401F701438580E0D3DF2296609133016D -:100FA00070913401F701448581E0CADF209133015B -:100FB000309134012F5F3F4F309334012093330140 -:100FC000CC15DD05A4F2C8017FDF80E1DF91CF9170 -:100FD0001F910F91FF90EF90DF90CF900895CF93E6 -:100FE000DF93EC0166DD5EDD803229F484E135DDDE -:100FF000CE01AFDF0AC080912F01909130010196A0 -:101000009093300180932F0185E1DF91CF9125CD21 -:10101000CF93DF9347DDD82F80E0C82F43DDC80F83 -:10102000D11DC13081E0D80764F081E116DD8091E7 -:101030002F019091300101969093300180932F0100 -:1010400022C030DD863421F4CE01DF91CF91C7CFAD -:101050008534A9F4CE01B5DEC82F24DD803221F419 -:1010600084E1FBDC8C2F0CC080912F01909130012A -:1010700001969093300180932F0185E101C081E1B9 -:10108000DF91CF91EACCDF91CF910895CF93DF9399 -:101090008091310190913201892B19F080E241D980 -:1010A00002C080E243D980912F0190913001892BB9 -:1010B00019F080E136D902C080E138D980E191E0B1 -:1010C00030D797FDAEC08135910509F485C0E4F4B1 -:1010D0008134910509F452C054F48033910599F19B -:1010E00081339105A9F1809709F089C07EC08534CC -:1010F000910509F44EC08035910509F44EC0823443 -:10110000910509F07CC03EC08136910509F459C0B3 -:101110006CF48635910509F45CC08036910509F4BC -:101120004FC08535910509F06AC039C084379105F3 -:1011300009F44CC08537910509F454C084369105F3 -:1011400009F05DC040C01092300110922F011EC006 -:10115000A9DC803209F065C084E17FDC81E47DDCBC -:1011600086E57BDC82E579DC80E277DC89E475DC8E -:1011700083E573DC80E571DC80E150C093DCDF91B6 -:10118000CF91E2CC84E190E094DCAEDCDF91CF91B2 -:10119000F0CC85E090E08DDCF9CF46DDF7CF82DC46 -:1011A000C82FD0E0D0933401C09333017BDC382FBB -:1011B00020E02C0F3D1F3093340120933301E6CF04 -:1011C00071DC70DCE3CFDF91CF9122CFDF91CF9143 -:1011D0004DCEDF91CF9180CD1092300110922F0132 -:1011E000ACDDD4CFDF91CF9184CD80912F01909150 -:1011F000300101969093300180932F010EC08091B1 -:101200002F019091300101969093300180932F012E -:1012100049DC803211F482E101C085E1DF91CF9198 -:101220001CCCDF91CF91089510922E0183D8789431 -:10123000C3E0FC2E0FE211E0DCD980912E01833057 -:1012400011F424DF90C080E191E06BD6EC0197FDB2 -:101250000AC080E166D8F092BC018091C80085FF89 -:10126000FCCFC093CE008FB7F894C0913901D091D4 -:101270003A018FBF209719F4A89949C06CC080E249 -:1012800050D8F092BB01809111018F708093E900DA -:101290008091E80080FFF0CFCE01C034D10510F07E -:1012A0008FE390E0E82EC0E0D0E02EC080912E01C8 -:1012B000813061F0F801A281B3818D91B383A28363 -:1012C00026813781A217B30781F40BC0E091310169 -:1012D000F0913201608180E191E0BBD5882351F328 -:1012E000CBCF24813581338322839FB7F894228525 -:1012F000338521503109338722879FBF90912E017A -:10130000923009F419DB2196EC12D0CFB5CFA89A10 -:101310008091BB01882399F081508093BB0181119A -:101320000EC080912E01823039F440DA60910B02B8 -:1013300085E092E0BFD958D980E20E949601809161 -:10134000BC01882341F081508093BC01811103C00E -:1013500080E10E94960180912E01823021F480E08C -:1013600091E00E94BE1180E191E0C5D513D564CF14 -:10137000292F332723303105B1F04CF421303105CA -:1013800009F439C02230310509F03AC007C02132D2 -:10139000310539F12232310549F132C0EFE5F0E093 -:1013A0008EEB90E031C099278130910561F0823059 -:1013B000910581F0892B21F5EAEBF0E0E491F0E072 -:1013C0008AEB90E021C0E6EAF0E0E491F0E086EA02 -:1013D00090E01AC0E4E7F0E0E491F0E084E790E008 -:1013E00013C0E9E0F0E08DE091E00EC0E8EBF1E041 -:1013F0008FE291E009C0E2E1F0E08DE191E004C00C -:10140000E0E0F0E080E090E0DA018D939C93CF0182 -:101410000895680F791F09C0FC012191CF01309117 -:10142000C80035FFFCCF2093CE0086179707A1F7A1 -:101430000895BF92CF92DF92EF92FF920F931F9386 -:10144000CF93DF937C018B01EA01D7D1B82E8111B4 -:1014500032C0209731F028813981021B130BE20E34 -:10146000F31EC12CD12C22C08091E80085FD14C050 -:101470008091E8008E778093E800209749F088817A -:1014800099818C0D9D1D9983888325E0B22E13C010 -:10149000B4D1882359F00EC0F70181917F01809368 -:1014A000F10001501109FFEFCF1ADF0A01151105F4 -:1014B000D9F601C0B82E8B2DDF91CF911F910F91DE -:1014C000FF90EF90DF90CF90BF900895209144025D -:1014D000309145022617370748F06115710539F438 -:1014E0002091E8002E772093E80001C0B9019C010B -:1014F00080E034C090913D02992309F443C09530B7 -:1015000009F442C09091E80093FD3AC09091E80040 -:1015100092FD30C09091E80090FF20C08091F200D1 -:1015200090E0F901821B930B05C021912093F100FB -:10153000615071099F01280F391F6115710519F05C -:101540002830310590F381E02830310509F080E042 -:101550009091E8009E779093E8009F0161157105D6 -:1015600049F68111C7CF06C080913D02882351F012 -:10157000853051F08091E80082FFF6CF80E0089539 -:1015800081E0089582E0089583E008956115710572 -:1015900029F42091E8002B772093E8009C0121C0DA -:1015A00080913D02882381F1853041F18091E800EE -:1015B00083FD26C08091E80082FFF2CFF90107C0C9 -:1015C0008091F10081939F016150710929F09F0181 -:1015D0008091F2008111F4CF8091E8008B778093A5 -:1015E000E80061157105E1F68091E80080FD0AC010 -:1015F00080913D02882341F08530B1F783E0089562 -:1016000081E0089580E0089582E0089520914402E9 -:10161000309145022617370748F06115710539F4F6 -:101620002091E8002E772093E80001C0B9019C01C9 -:1016300080E035C090913D02992309F444C0953073 -:1016400009F443C09091E80093FD3BC09091E800FD -:1016500092FD31C09091E80090FF21C08091F2008E -:1016600090E0F901821B930B06C024912093F100B6 -:101670003196615071099C012E0F3F1F6115710554 -:1016800019F02830310588F381E02830310509F060 -:1016900080E09091E8009E779093E8009F016115AB -:1016A000710541F68111C6CF06C080913D028823A5 -:1016B00051F0853051F08091E80082FFF6CF80E054 -:1016C000089581E0089582E0089583E00895982FB9 -:1016D0002CC09093E900981739F07091EC0020919C -:1016E000ED005091F00003C0242F762F50E021FD33 -:1016F00002C09F5F1AC03091EB003E7F3093EB0039 -:101700003091ED003D7F3093ED003091EB00316082 -:101710003093EB007093EC002093ED005093F000B9 -:101720002091EE0027FDE5CF07C0953090F28F7035 -:101730008093E90081E0089580E008950F931F935E -:10174000CF93DF93062FEC0110E02EC0988191110A -:1017500003C01F5F259628C02C81E981FA816B8127 -:10176000892F8F70853010F080E021C0223010F07A -:1017700056E001C052E028E030E040E003C04F5F97 -:10178000220F331F2E173F07D0F34295407F452B82 -:10179000991F9927991F6295660F660F607C692BC8 -:1017A00096DF8111D6CFE0CF1013D0CF81E0DF914B -:1017B000CF911F910F91089580913E0287FD05C042 -:1017C0008091E80080FF0EC012C08091E80082FD89 -:1017D00005C080913D028111F8CF08958091E80005 -:1017E0008B7708C080913D028111EACF08958091E6 -:1017F000E8008E778093E80008958091E40090914E -:10180000E50045E62091EC0020FD1FC023C020919B -:101810003D02222391F0253091F02091EB0025FD2F -:1018200010C02091E4003091E5002817390751F3EA -:101830004150C90139F784E0089582E0089583E0BA -:10184000089581E0089580E008952091E80020FF48 -:10185000DECFF9CF2091E80022FFD9CFF4CF41D0DD -:1018600043D08091D8008F778093D8008091D800A2 -:1018700080688093D8008091D8008F7D8093D800B5 -:1018800084E089BD86E089BD09B400FEFDCF1092D9 -:101890003D021092390210923B0210923A0242E04D -:1018A00060E080E014DF8091E1008E7F8093E100B2 -:1018B0008091E20081608093E2008091E200886084 -:1018C0008093E2008091E0008E7F8093E000089595 -:1018D000E3E6F0E080818E7F808381E080933C02AC -:1018E000BECF1092E20008951092E10008951F9279 -:1018F0000F920FB60F9211242F933F934F935F9344 -:101900006F937F938F939F93AF93BF93EF93FF93C7 -:101910008091E10082FF0BC08091E20082FF07C04E -:101920008091E1008B7F8093E1000E94930280917F -:10193000E10080FF18C08091E20080FF14C0809118 -:10194000E2008E7F8093E2008091E20080618093CC -:10195000E2008091D80080628093D80019BC109278 -:101960003D020E94D6018091E10084FF30C0809149 -:10197000E20084FF2CC084E089BD86E089BD09B403 -:1019800000FEFDCF8091D8008F7D8093D80080919C -:10199000E1008F7E8093E1008091E2008F7E809352 -:1019A000E2008091E20081608093E2008091390240 -:1019B000882311F084E007C08091E30087FF02C014 -:1019C00083E001C081E080933D020E94D5018091B7 -:1019D000E10083FF27C08091E20083FF23C0809154 -:1019E000E100877F8093E10082E080933D021092C6 -:1019F00039028091E1008E7F8093E1008091E200C6 -:101A00008E7F8093E2008091E20080618093E2000B -:101A100042E060E080E05BDE8091F00088608093CF -:101A2000F000B7D1FF91EF91BF91AF919F918F914E -:101A30007F916F915F914F913F912F910F900FBECA -:101A40000F901F9018951F920F920FB60F921124AE -:101A50002F933F934F935F936F937F938F939F93B6 -:101A6000AF93BF93CF93EF93FF938091E9008F7073 -:101A70009091EC0090FF02C090E801C090E0C92F67 -:101A8000C82B1092E9008091F000877F8093F000CE -:101A900078941CD01092E9008091F00088608093C7 -:101AA000F000CF70C093E900FF91EF91CF91BF910B -:101AB000AF919F918F917F916F915F914F913F91E6 -:101AC0002F910F900FBE0F901F9018951F93CF93DB -:101AD000DF93CDB7DEB7AC970FB6F894DEBF0FBE7D -:101AE000CDBFEEE3F2E08091F100819322E0E63495 -:101AF000F207C9F70E948B028091E80083FF31C191 -:101B000080913E0290913F02953009F487C038F4ED -:101B10009130B1F170F0933009F023C131C09830A9 -:101B200009F4F3C0993009F4FFC0963009F019C1E7 -:101B30009BC0803821F0823809F013C108C0809121 -:101B40003A0290913B02992389F082600FC0809104 -:101B50004202909143028F7099278093E90080910F -:101B6000EB0085FB882780F91092E9009091E8004E -:101B7000977F9093E8008093F1001092F100D0C01D -:101B8000882319F0823009F0ECC08F7121F0823087 -:101B900009F0E7C00BC080914002813009F0E1C03C -:101BA000933009F080E080933B022FC08091400287 -:101BB00081112BC080914202909143028F7099272E -:101BC000009709F4CEC08093E9002091EB0020FF3C -:101BD0001CC020913F02233021F48091EB008062F1 -:101BE00012C09091EB0090619093EB0021E030E007 -:101BF00001C0220F8A95EAF72093EA001092EA00CA -:101C00008091EB0088608093EB001092E900809156 -:101C1000E800877F8093E800CFDDA3C08111A1C0D9 -:101C200080914002909141028F779927182F9091CF -:101C3000E3009078982B9093E3008091E800877FF1 -:101C40008093E800B9DD8091E80080FFFCCF8091AF -:101C5000E30080688093E300112311F083E001C06A -:101C600082E080933D027DC08058823008F079C0C8 -:101C700080914002909141028C3D23E0920771F5E2 -:101C800083E08A838AE289834FB7F894DE01139652 -:101C900020E03EE051E2E32FF0E050935700E49162 -:101CA00020FF03C0E295EF703F5FEF708E2F90E052 -:101CB000EA3010F0C79601C0C0968D939D932F5FB8 -:101CC000243149F74FBF8091E800877F8093E80077 -:101CD0006AE270E0CE010196F9DB11C0AE01455D0C -:101CE0005F4F6091420244DB0097D9F12091E800F8 -:101CF000277F2093E800BC018BA59CA587DC809101 -:101D0000E8008B778093E8002CC0803851F58091F3 -:101D1000E800877F8093E800809139028093F1008A -:101D20008091E8008E7776CF81111BC090914002A0 -:101D30009230B8F48091E800877F8093E800909318 -:101D400039023ADD80913902811104C08091E300AB -:101D500087FF02C084E001C081E080933D020E94C1 -:101D6000D7018091E80083FF0AC08091E800877F57 -:101D70008093E8008091EB0080628093EB00AC964A -:101D80000FB6F894DEBF0FBECDBFDF91CF911F918C -:101D900008950895CF9380913D028823A9F0809102 -:101DA000E9008F709091EC0090FF02C090E801C0B4 -:101DB00090E0C92FC82B1092E9008091E80083FDC4 -:101DC00085DECF70C093E900CF910895CF93DF9364 -:101DD000EC014096FC018BE0DF011D928A95E9F74A -:101DE00082E08C83898783E08E8761E0CE01019653 -:101DF000A5DC882361F061E0CE0106969FDC882394 -:101E000031F061E0CE010B96DF91CF9197CC80E06D -:101E1000DF91CF9108950F931F93FC01CB01BA017D -:101E200020913D02243089F4048915892689378957 -:101E3000012B022B032B49F021812F702093E90005 -:101E400040E050E01F910F91F4CA82E01F910F9182 -:101E50000895CF93C62F20913D022430F1F4FC0168 -:101E60004489558966897789452B462B472BA9F0EC -:101E700081818F708093E9008091E80085FF04C024 -:101E8000C093F10080E00AC08091E8008E778093D3 -:101E9000E800B3DC8823A1F301C082E0CF9108956C -:101EA00020913D02243029F5FC0144895589668939 -:101EB0007789452B462B472BE1F081818F708093EA -:101EC000E9008091F200811102C080E008959091B4 -:101ED000E8008091E8008E778093E80095FDF5CFCB -:101EE0008CDC811107C09091E8009E779093E80008 -:101EF000089582E0089520913D02243089F4FC0188 -:101F00004489558966897789452B462B472B41F0B3 -:101F100021812F702093E9002091E80020FDC0CF9F -:101F2000089520913D02243019F02FEF3FEF24C097 -:101F3000FC014489558966897789452B462B472BB7 -:101F4000A1F386818F708093E9008091E80082FF81 -:101F5000ECCF8091F200882321F02091F10030E055 -:101F600002C02FEF3FEF8091F200811105C08091F8 -:101F7000E8008B778093E800C90108950895CF9316 -:101F8000DF93EC018091E80083FFA9C0888190E095 -:101F900020914202309143022817390709F09FC06F -:101FA00080913F02813261F020F4803209F097C0C5 -:101FB0003DC0823209F46EC0833209F090C07FC008 -:101FC00080913E02813A09F08AC08091E800877FC3 -:101FD0008093E8008091E80080FFFCCF4C895D8908 -:101FE0006E897F894093F100BB27A72F962F852FFD -:101FF0008093F100CB01AA27BB278093F100472FE4 -:102000005527662777274093F100888D8093F1004C -:10201000898D8093F1008A8D8093F1008091E80092 -:102020008E778093E800DF91CF91C6CB80913E02FE -:10203000813209F054C08091E800877F8093E800E6 -:1020400005C080913D02882309F449C08091E800D1 -:1020500082FFF7CF3091F1002091F1009091F100D3 -:102060008091F1003C8B2D8B9E8B8F8B8091F100AA -:10207000888F8091F100898F8091F1008A8F809103 -:10208000E8008B778093E80097DBCE01DF91CF915A -:102090000C94E50180913E02813209F58091E800BF -:1020A000877F8093E80088DB809140029091410215 -:1020B000998B888BCE01DF91CF910C948002809117 -:1020C0003E02813261F48091E800877F8093E800CE -:1020D00073DB60914002CE01DF91CF914FCFDF9152 -:1020E000CF9108956F927F928F929F92AF92BF92FD -:1020F000CF92DF92EF92FF920F931F93CF93DF93D4 -:1021000000D01F92CDB7DEB77C01ADB6BEB68091D0 -:10211000E80083FF07C1F701808190E0209142022F -:10212000309143022817390709F0FCC080913F0223 -:10213000833009F49EC030F4813071F0823009F0B0 -:10214000F1C0D4C08A3009F4B9C08B3009F4A2C000 -:10215000893009F0E7C04CC080913E02813A09F015 -:10216000E1C08DB69EB61A8219828091400210910C -:1021700041028B83F70140858DB79EB7841B91097F -:102180000FB6F8949EBF0FBE8DBFCDB6DEB6EFEF93 -:10219000CE1ADE0A360150E060E070E0C601EAD1F6 -:1021A000412F41508E010F5F1F4F9601BE016D5FA1 -:1021B0007F4FC7010E949F02F701268137812115B9 -:1021C000310529F0408550E0B601C901CAD110920D -:1021D000E9008091E800877F8093E80069817A8137 -:1021E000C30174D98091E8008B778093E80039C0EF -:1021F00080913E02813209F095C08DB69EB6009165 -:1022000044021091450270904002609041028DB7E7 -:102210009EB7801B910B0FB6F8949EBF0FBE8DBF6B -:10222000CDB6DEB6EFEFCE1ADE0A8091E800877FEA -:102230008093E800B801C601A9D98091E8008E77A3 -:102240008093E80021E0711001C020E030E0021B23 -:10225000130B2C0D3D1D462D4150672DC7010E94CB -:10226000D002882D992D0FB6F8949EBF0FBE8DBF5A -:1022700059C080913E02813A09F054C08091E80033 -:10228000877F8093E8008091E80080FFFCCFF70112 -:10229000818540C080913E02813209F043C0809127 -:1022A000E800877F8093E80087DA9091400281E020 -:1022B000911101C080E0F701818734C080913E0216 -:1022C000813281F58091E800877F8093E80074DA9D -:1022D0008091400290914102882736E0969587953B -:1022E0003A95E1F7F701958784871CC080913E02FB -:1022F000813AC1F48091E800877F8093E800809163 -:10230000E80080FFFCCFF701848595859695879539 -:10231000969587958093F1008091E8008E77809361 -:10232000E8004ADA0FB6F894BEBE0FBEADBE0F90FD -:102330000F900F90DF91CF911F910F91FF90EF9031 -:10234000DF90CF90BF90AF909F908F907F906F90D5 -:1023500008959C01275F3F4FF90127E0DF011D929F -:102360002A95E9F721E0FC01218724EF31E0358748 -:10237000248723E0248361E00196E0C94F925F92B5 -:102380006F927F928F929F92AF92BF92CF92DF9285 -:10239000EF92FF920F931F93CF93DF9300D01F9282 -:1023A000CDB7DEB77C01ADB6BEB680913D028430BC -:1023B00009F08FC08091E4009091E500F70122853B -:1023C00033852817390709F484C081818F70809381 -:1023D000E9008091E80085FF7CC06DB67EB640853F -:1023E0008DB79EB7841B91090FB6F8949EBF0FBEA0 -:1023F0008DBFCDB6DEB6EFEFCE1ADE0A1B821A8293 -:102400001982460150E060E070E0C601B3D08E0151 -:102410000F5F1F4F960140E0BE016D5F7F4FC70108 -:102420000E949F02582EF70184859585892B31F0F3 -:1024300001E010E086859785892B11F000E010E01F -:10244000F701C680D780C114D10489F049815A812F -:10245000B601C40179D044244394009709F4412C77 -:10246000F701408550E0B401C6017BD001C0412C8A -:1024700089819A81892BF9F0511004C0411002C062 -:1024800000FF19C0F701848595859787868781812C -:102490008F708093E9008B8181118093F1006981B5 -:1024A0007A8140E050E0C4010E94190A8091E8005E -:1024B0008E778093E8008091E4009091E500F70129 -:1024C00093878287862D972D0FB6F8949EBF0FBEF7 -:1024D0008DBF0FB6F894BEBE0FBEADBE0F900F906D -:1024E0000F90DF91CF911F910F91FF90EF90DF90B0 -:1024F000CF90BF90AF909F908F907F906F905F90A4 -:102500004F900895A1E21A2EAA1BBB1BFD010DC01E -:10251000AA1FBB1FEE1FFF1FA217B307E407F50793 -:1025200020F0A21BB30BE40BF50B661F771F881F6F -:10253000991F1A9469F760957095809590959B0105 -:10254000AC01BD01CF010895FB01DC0104C08D91F8 -:102550000190801921F441505040C8F7881B990B15 -:102560000895FB01DC0102C001900D9241505040E2 -:10257000D8F70895DC0101C06D9341505040E0F759 -:062580000895F894FFCF5E -:1025860002812000000100003F0000000000000062 -:1025960000834000000104400000018208000001A1 -:0E25A6000000000000000000000000302000D7 -:00000001FF diff --git a/plugins/KeyboardioHID/Firmwares/Hoodloader1_7_1.hex b/plugins/KeyboardioHID/Firmwares/Hoodloader1_7_1.hex new file mode 100644 index 0000000000..c37d733cde --- /dev/null +++ b/plugins/KeyboardioHID/Firmwares/Hoodloader1_7_1.hex @@ -0,0 +1,605 @@ +:1000000073C100008DC100008BC1000089C10000D8 +:1000100087C1000085C1000083C1000081C10000CC +:100020007FC100007DC100007BC100000C94790CF1 +:100030000C94250D75C1000073C1000071C1000052 +:100040006FC100006DC100006BC1000069C10000FC +:1000500067C1000065C1000063C1000012C200005A +:100060005FC100005DC100005BC1000059C100001C +:1000700057C1000030034100720064007500690040 +:100080006E006F00200048006F006F0064006C007D +:100090006F0061006400650072002000420065008E +:1000A00074006100000012034E00690063006F00DD +:1000B00048006F006F006400000004030904090297 +:1000C0005F00030100C032080B00020202010009B8 +:1000D00004000001020201000524001001042402B2 +:1000E000060524060001070582030800FF09040134 +:1000F00000020A0000000705040240000107058312 +:10010000024000010904020001030000000921115E +:1001100001000122B801070581032000011201102E +:1001200001EF020108EB03686E17000102DC010514 +:10013000010902A1010901A100850105091901298F +:10014000051500250195057501810295017503814D +:100150000305010930093109381581257F75089596 +:10016000038106C0C005010906A101850205071922 +:10017000E029E715002501750195088102950175B3 +:1001800008810395067508150025650507190029DE +:1001900065810005081901290595057501910295EC +:1001A0000175039103C006C0FF0A000CA10185037D +:1001B0007508150026FF00953F09018102953F094A +:1001C000029102C0050C0901A1018504150026FF5A +:1001D000FF19002AFFFF950475108100C005010971 +:1001E00080A1018505150026FF00190029FF950152 +:1001F00075088100C005010905A1018506050919D9 +:10020000012920150025017501952081020501A114 +:10021000000930093109320933093409351500273D +:10022000FFFF0000751095068102C005010939091C +:100230003915012508950275048102C005010905DB +:10024000A10185070509190129201500250175015E +:10025000952081020501A1000930093109320933D5 +:1002600009340935150027FFFF0000751095068138 +:1002700002C0093909391501250895027504810262 +:10028000C005010904A1018508A10005091901297A +:100290000215002501750195028102050109300949 +:1002A00031150026FF03750A95028102750295013A +:1002B0008103C0C005010904A1018509A100050948 +:1002C0001901290215002501750195028102050118 +:1002D00009300931150026FF03750A950281027560 +:1002E0000295018103C0C00011241FBECFEFD2E0F0 +:1002F000DEBFCDBF11E0A0E0B1E0EAE8F5E202C068 +:1003000005900D92AE32B107D9F712E0AEE2B1E03E +:1003100001C01D92A634B107E1F788D70C94C3122F +:100320006FCE9BB1809589238BB908959BB1982B93 +:100330009BB90895CF93DF9384B7877F84BF28E16B +:100340000FB6F89420936000109260000FBE80E119 +:1003500090E09093CD008093CC00CAECD0E096E082 +:100360009883A8ECB0E082E08C93E9ECF0E0208385 +:10037000539A5A9A5B9A10821C92188298838C9393 +:1003800088E980835B988AB180638AB98BB1806386 +:100390008BB90E946A0C84E085BD5F9A579A209AB7 +:1003A00022982A9ADF91CF9108950895089580E0C8 +:1003B00091E00E94AB1180E191E00E94E80EE2EE34 +:1003C000F0E080818460808308951F93CF93DF9352 +:1003D000EC01E98DE150E23028F4F0E0E55DFE4FFC +:1003E000108101C010E0888D823009F418608A8D78 +:1003F000873031F0883031F0863029F4126003C044 +:10040000146001C016605B9A1092C9001092C80077 +:100410001092CA002C893D894E895F89211581EE91 +:1004200038074105510579F0CA01B90196958795BC +:100430007795679560587B47814E9F4F0E94841245 +:100440002150310902C020E130E03093CD002093EB +:10045000CC001093CA008C899D89AE89BF89811513 +:10046000914EA105B10511F480E001C082E08093B6 +:10047000C80088E98093C9005B98DF91CF911F91F4 +:1004800008951F920F920FB60F9211242F933F934E +:100490008F939F93AF93BF93EF93FF938091CE0081 +:1004A00090912E019330F9F090913D029430D9F45F +:1004B000EFE2F1E0A081B1818C938081918101967E +:1004C00091838083268137818217930721F4848169 +:1004D0009581918380832FB7F894828593850196C7 +:1004E000938782872FBFFF91EF91BF91AF919F912B +:1004F0008F913F912F910F900FBE0F901F901895E5 +:10050000FC01208920FF02C05F9808955F9A8BB19B +:1005100080638BB9089580E191E00E94C10F80E073 +:1005200091E00C94741080910E0190910F0100974E +:1005300029F0019790930F0180930E010895EF9297 +:10054000FF920F931F93CF93DF937B01C901E801C3 +:100550002091BD012223E1F04091BE012091BF0115 +:10056000421316C0E0ECF1E050E0BF010E94B3126C +:100570008091BD01F70180838091BE01888319823B +:100580001092BD011092BF011092BE0181E001C026 +:1005900080E0DF91CF911F910F91FF90EF90089530 +:1005A000EF92FF920F931F93CF93DF931F92CDB7DC +:1005B000DEB77901633081F480E16983B2DE69815D +:1005C0006093BC01B801C7010F90DF91CF911F91DB +:1005D0000F91FF90EF901FC70F90DF91CF911F9168 +:1005E0000F91FF90EF90089510920B021092FF016F +:1005F000089520912E018091240190912501A091D0 +:100600002601B09127011A9B0DC00097A105B105E5 +:1006100039F0811532EC930731E0A307B10511F4ED +:1006200082E007C00197A105B10511F483E001C084 +:1006300081E080932E0180912E01281709F43BC0A0 +:10064000233011F021111DC0EFE2F1E02FB7F89433 +:100650008BE391E09183808393838283958384836A +:100660008BEB91E09783868380E890E09187808789 +:10067000138612862FBF1092BB011092BC0180E33B +:1006800055DE80912E01823021F4AEDF1092BD0143 +:100690000895833081F41092300110922F0110924E +:1006A000320110923101109234011092330180E333 +:1006B0003DDE22982A9A0895462F209111012F702D +:1006C0002093E9002091E80020FFFCCF2091200139 +:1006D00020FF06C050E0BC0180E191E00C940D0FBA +:1006E0000895CF92DF92EF92FF920F931F93FA013A +:1006F0008B010095109520E030E09801112700272C +:10070000AB0160E070E0042B152B262B372B4CE15E +:1007100050E097E068017901042E04C0F694E79454 +:10072000D794C7940A94D2F76C2D683028F097308C +:1007300059F4C08296E008C0C0829150C11004C034 +:1007400047505109923031F7492F425013C0DF0111 +:10075000A40FB11D68017901E894C7F8DD24EE24E7 +:10076000FF24CC92B7E03695279517950795BA9553 +:10077000D1F741504111EBCF492F50E09A01A3E04E +:10078000220F331FAA95E1F7206C3F6F3081322B87 +:100790003083E40FF51F319781508F738068808319 +:1007A000892F1F910F91FF90EF90DF90CF900895C8 +:1007B000CF93DF9300D000D000D0CDB7DEB76091EB +:1007C000BD01662379F08091BF0181110BC070E0FB +:1007D0007160AE014F5F5F4F81E083DF682FCE0114 +:1007E00001966ADF1092BD0126960FB6F894DEBF1F +:1007F0000FBECDBFDF91CF9108950F931F93982F18 +:1008000040910B02E42FF0E0EB5FFD4F808380917D +:100810000B028F5F80930B02892F807C803809F454 +:1008200044C0803C09F05FC0292F28732695269587 +:100830002695223008F477C0273079F4492F4F707D +:1008400050E060E070E0409300025093010260933A +:1008500002027093030215E00FC0892F877090E0A9 +:10086000A0E0B0E08093000290930102A093020206 +:10087000B0930302122F11508091FF01882391F051 +:1008800097DF60910B02615085E092E015DFE09107 +:100890000B02F0E0EC5FFD4F80818093050281E068 +:1008A00080930B021093FF0145C08091FF018130BE +:1008B000D1F50091000210910102209102023091C5 +:1008C0000302A901662777272227332740275127CC +:1008D000622773274F3F5F4F6105710521F5892F0F +:1008E0008F738F5F28C08091FF018230E0F08150CC +:1008F0008093FF0140910002509101026091020239 +:100900007091030227E0440F551F661F771F2A9539 +:10091000D1F7492B409300025093010260930202E9 +:100920007093030207C044DF60910B0285E092E000 +:10093000C3DE5ADE80E01F910F910895CF935DDFF3 +:10094000C82F882309F489C08091BD01811104C09A +:10095000C13009F046C010C09091BE018091BF0126 +:100960009813F6CF04C080E091E00E94C0118091FE +:10097000BD018111F8CFECCF80910102813089F562 +:1009800017DF909100029093BD011092BF018FE399 +:10099000E0ECF1E0DF01282F1D922A95E9F7953070 +:1009A000A9F058F4923081F018F49130C1F40AC0E3 +:1009B000933091F0943099F407C0983050F09A3009 +:1009C00070F409C084E008C088E006C0C093BE018E +:1009D00042C081E101C083E08093BE013CC0E8DEFB +:1009E0003AC08091BD01882381F16091BF01462FFB +:1009F00050E08C2F90E09A012E5F3F4F3595279560 +:100A00002F5F3F4F8217930701F5FA01E054FE4F25 +:100A1000809100028083E62FEF5FE093BF01809119 +:100A2000BE018E1749F0F0E0E054FE4F90910102B4 +:100A300090836E5F6093BF019091BF0189130BC0DB +:100A400080E091E00E94C01106C0B2DE60910B020E +:100A500085E092E031DECF91C7CDCF910895682F28 +:100A600080E191E00E942B0F8823E9F080E191E082 +:100A70000E947D0F0E94CC0E80E153DC2FEF81EEAF +:100A800094E0215080409040E1F700C0000080E1F8 +:100A900048DC2FEF81EE94E0215080409040E1F758 +:100AA00000C00000E9CF089580E191E00E94930F1B +:100AB00097FDFACF0895EF92FF920F931F93CF9374 +:100AC000DF937C0109E311E0C0E0D0E005C0ECDF7A +:100AD000F80181938F012196CE15DF05C4F3DF91D4 +:100AE000CF911F910F91FF90EF9008959091450144 +:100AF00080E020914601820F911D909336018093F2 +:100B000035019091470180E020914801820F911DAD +:100B100090933801809337010895CF93C82FC4DF95 +:100B2000803239F484E19BDF8C2F99DF80E1CF9113 +:100B300096CF85E194DF80912F019091300101964D +:100B40009093300180932F01CF910895813859F00F +:100B500018F4803871F405C0823839F0833949F4CB +:100B600006C082E007C081E005C082E103C083E5E2 +:100B700001C080E0D2CF98DF803221F484E16FDFC2 +:100B800080E16DCF80E2CDDB2FEF80E792E0215056 +:100B900080409040E1F700C0000080E2C7DB2FEF0B +:100BA00080E792E0215080409040E1F700C00000D3 +:100BB00080E2B7DB2FEF80E792E021508040904049 +:100BC000E1F700C0000080E2B1DB85E148DF809101 +:100BD0002F019091300101969093300180932F0165 +:100BE000089583E58CBD8DB58EB508950DB407FECF +:100BF000FDCF08958EBDFADF8EB50895CF93DF93B4 +:100C000000D01F92CDB7DEB72B834A836983F2DF12 +:100C10006981862FEFDF4A81842FECDF2B81822FC1 +:100C20000F900F900F90DF91CF91E4CFDADF249AED +:100C30002C9A219A29982FEF80E792E0215080404A +:100C40009040E1F700C000002C982FEF80E792E081 +:100C5000215080409040E1F700C000002398229A84 +:100C600020E040E063E58CEAC9DF81E090E090930A +:100C70003201809331010895462F880F880F880F25 +:100C800020E0672F805EBACF0F931F93CF93DF933F +:100C90008C01C0E0D0E019C0609133017091340143 +:100CA00080E0EADFDCDE609133017091340181E0A5 +:100CB000E3DFD5DE20913301309134012F5F3F4FC8 +:100CC00030933401209333012296C017D10724F3C7 +:100CD00080E1DF91CF911F910F91089584E090E022 +:100CE000EADE20913C0140913B0160913A01809104 +:100CF000390184DF12CFD8DE803259F080912F0184 +:100D00009091300101969093300180932F0185E1FD +:100D100015C084E1A4DE20E040E060E080E36EDF07 +:100D20009EDE20E041E060E080E368DF98DE20E0C6 +:100D300042E060E080E362DF92DE80E190CE2398C3 +:100D40002298229A2198249810923201109231010F +:100D50000895CF92DF92EF92FF920F931F93CF935C +:100D6000DF93D82FC92F7B01CB01A5DE80E2DEDA2D +:100D7000E9E3CE2EE1E0DE2E0D2F1C2FE80111C09D +:100D8000F60121916F014C2F6D2F80EC37DFFFE7CB +:100D900022E382E0F15020408040E1F700C00000F3 +:100DA0002196CE01801B910B8E159F054CF380E29E +:100DB000B8DA80E1DF91CF911F910F91FF90EF9012 +:100DC000DF90CF9008950F931F93CF93DF93C0913F +:100DD0003301D09134012091370130913801281727 +:100DE000390724F0CC0FDD1F8C0112C080912F0138 +:100DF0009091300101969093300180932F0181E111 +:100E00000EC060E270E0CE01A4DFA096005211098E +:100E100001321105B4F7B801CE019BDF80E1DF910B +:100E2000CF911F910F910895EF92FF920F931F930F +:100E3000CF93DF937C010091330110913401000FB7 +:100E4000111FE80107C02FEF4C2F6D2F80EAD6DE6F +:100E500006DE2196CE01801B910B8E159F059CF31B +:100E600080E1DF91CF911F910F91FF90EF90089556 +:100E70001F93CF93DF9318DED82F16DEC82F14DE12 +:100E8000182F12DE803259F080912F01909130019D +:100E900001969093300180932F0185E113C03D2F7F +:100EA00020E0C9018C0F911DEC0184E1D8DD1634DE +:100EB00019F4CE01E9DE06C0153419F4CE01B4DF11 +:100EC00001C081E1DF91CF911F91C9CDCF93DF9315 +:100ED00000D0CDB7DEB7482F80E249839A8326DA67 +:100EE00020E049819A81692F8CE488DE2FEF86E724 +:100EF00091E0215080409040E1F700C0000080E286 +:100F00000F900F90DF91CF910CCA80913501909195 +:100F1000360120913301309134018032910511F472 +:100F2000207F0EC08034910511F4207E09C08038E6 +:100F3000910511F4207C04C08115914009F42078BA +:100F4000C9010895962F672F242F880F880F880FC7 +:100F5000492F805C53CECF92DF92EF92FF920F9396 +:100F60001F93CF93DF936C01D0DF8C01C0E0D0E002 +:100F700029C0CBDF0817190721F0C801A7DFC5DF9B +:100F80008C01BEE2EB2EB1E0FB2EEC0EFD1E60915B +:100F9000330170913401F701438580E0D3DF22965D +:100FA0006091330170913401F701448581E0CADF1B +:100FB00020913301309134012F5F3F4F3093340142 +:100FC00020933301CC15DD05A4F2C8017FDF80E159 +:100FD000DF91CF911F910F91FF90EF90DF90CF9015 +:100FE0000895CF93DF93EC0166DD5EDD803229F456 +:100FF00084E135DDCE01AFDF0AC080912F019091F1 +:10100000300101969093300180932F0185E1DF91AB +:10101000CF9125CDCF93DF9347DDD82F80E0C82F28 +:1010200043DDC80FD11DC13081E0D80764F081E1F4 +:1010300016DD80912F01909130010196909330013F +:1010400080932F0122C030DD863421F4CE01DF9160 +:10105000CF91C7CF8534A9F4CE01B5DEC82F24DDEA +:10106000803221F484E1FBDC8C2F0CC080912F01B5 +:101070009091300101969093300180932F0185E18A +:1010800001C081E1DF91CF91EACCDF91CF9108954A +:10109000CF93DF938091310190913201892B19F028 +:1010A00080E23FD902C080E241D980912F01909126 +:1010B0003001892B19F080E134D902C080E136D9A2 +:1010C00080E191E030D797FDAEC08135910509F4FC +:1010D00085C0E4F48134910509F452C054F480339E +:1010E000910599F181339105A9F1809709F089C0A3 +:1010F0007EC08534910509F44EC08035910509F410 +:101100004EC08234910509F07CC03EC08136910505 +:1011100009F459C06CF48635910509F45CC0803639 +:10112000910509F44FC08535910509F06AC039C0B1 +:101130008437910509F44CC08537910509F454C0F2 +:101140008436910509F05DC040C0109230011092C4 +:101150002F011EC0A9DC803209F065C084E17FDC6C +:1011600081E47DDC86E57BDC82E579DC80E277DC8E +:1011700089E475DC83E573DC80E571DC80E150C0D7 +:1011800093DCDF91CF91E2CC84E190E094DCAEDCA3 +:10119000DF91CF91F0CC85E090E08DDCF9CF46DD9A +:1011A000F7CF82DCC82FD0E0D0933401C093330155 +:1011B0007BDC382F20E02C0F3D1F3093340120932F +:1011C0003301E6CF71DC70DCE3CFDF91CF9122CF2A +:1011D000DF91CF914DCEDF91CF9180CD1092300134 +:1011E00010922F01ACDDD4CFDF91CF9184CD8091CF +:1011F0002F019091300101969093300180932F013F +:101200000EC080912F019091300101969093300192 +:1012100080932F0149DC803211F482E101C085E125 +:10122000DF91CF911CCCDF91CF91089510922E01C8 +:1012300081D87894C3E0FC2E0FE211E0DAD98091D6 +:101240002E01833011F424DF90C080E191E06BD651 +:10125000EC0197FD0AC080E164D8F092BC01809156 +:10126000C80085FFFCCFC093CE008FB7F894C09123 +:101270003901D0913A018FBF209719F4A89949C03C +:101280006CC080E24ED8F092BB01809111018F704A +:101290008093E9008091E80080FFF0CFCE01C03458 +:1012A000D10510F08FE390E0E82EC0E0D0E02EC032 +:1012B00080912E01813061F0F801A281B3818D917E +:1012C000B383A28326813781A217B30781F40BC0B1 +:1012D000E0913101F0913201608180E191E0BBD574 +:1012E000882351F3CBCF24813581338322839FB769 +:1012F000F8942285338521503109338722879FBF97 +:1013000090912E01923009F419DB2196EC12D0CF86 +:10131000B5CFA89A8091BB01882399F08150809322 +:10132000BB0181110EC080912E01823039F440DA68 +:1013300060910B0285E092E0BFD956D980E20E940D +:1013400096018091BC01882341F081508093BC01BB +:10135000811103C080E10E94960180912E018230AC +:1013600021F480E091E00E94C01180E191E0C5D5B8 +:1013700013D564CF292F332723303105B1F04CF436 +:101380002130310509F439C02230310509F03AC065 +:1013900007C02132310539F12232310549F132C01D +:1013A000EFE5F0E08EEB90E031C0992781309105B8 +:1013B00061F08230910581F0892B21F5EAEBF0E0B4 +:1013C000E491F0E08AEB90E021C0E6EAF0E0E491FD +:1013D000F0E086EA90E01AC0E4E7F0E0E491F0E0A3 +:1013E00084E790E013C0E9E0F0E08DE091E00EC00A +:1013F000E8EBF1E08FE291E009C0E2E1F0E08DE19D +:1014000091E004C0E0E0F0E080E090E0DA018D934C +:101410009C93CF010895680F791F09C0FC012191A9 +:10142000CF013091C80035FFFCCF2093CE00861746 +:101430009707A1F70895BF92CF92DF92EF92FF92A4 +:101440000F931F93CF93DF937C018B01EA01D7D1D8 +:10145000B82E811132C0209731F028813981021BCA +:10146000130BE20EF31EC12CD12C22C08091E80098 +:1014700085FD14C08091E8008E778093E800209766 +:1014800049F0888199818C0D9D1D9983888325E081 +:10149000B22E13C0B4D1882359F00EC0F701819148 +:1014A0007F018093F10001501109FFEFCF1ADF0A8D +:1014B00001151105D9F601C0B82E8B2DDF91CF9102 +:1014C0001F910F91FF90EF90DF90CF90BF90089504 +:1014D00020914402309145022617370748F06115E4 +:1014E000710539F42091E8002E772093E80001C0BF +:1014F000B9019C0180E034C090913D02992309F428 +:1015000043C0953009F442C09091E80093FD3AC081 +:101510009091E80092FD30C09091E80090FF20C0CB +:101520008091F20090E0F901821B930B05C021919C +:101530002093F100615071099F01280F391F611537 +:10154000710519F02830310590F381E0283031051C +:1015500009F080E09091E8009E779093E8009F0169 +:101560006115710549F68111C7CF06C080913D0212 +:10157000882351F0853051F08091E80082FFF6CF4A +:1015800080E0089581E0089582E0089583E0089561 +:101590006115710529F42091E8002B772093E8006C +:1015A0009C0121C080913D02882381F1853041F169 +:1015B0008091E80083FD26C08091E80082FFF2CF91 +:1015C000F90107C08091F10081939F016150710979 +:1015D00029F09F018091F2008111F4CF8091E80001 +:1015E0008B778093E80061157105E1F68091E80042 +:1015F00080FD0AC080913D02882341F08530B1F71B +:1016000083E0089581E0089580E0089582E00895E0 +:1016100020914402309145022617370748F06115A2 +:10162000710539F42091E8002E772093E80001C07D +:10163000B9019C0180E035C090913D02992309F4E5 +:1016400044C0953009F443C09091E80093FD3BC03D +:101650009091E80092FD31C09091E80090FF21C088 +:101660008091F20090E0F901821B930B06C0249157 +:101670002093F1003196615071099C012E0F3F1F9C +:101680006115710519F02830310588F381E02830A3 +:10169000310509F080E09091E8009E779093E80092 +:1016A0009F016115710541F68111C6CF06C0809179 +:1016B0003D02882351F0853051F08091E80082FF8F +:1016C000F6CF80E0089581E0089582E0089583E0F8 +:1016D0000895982F2CC09093E900981739F07091D5 +:1016E000EC002091ED005091F00003C0242F762FE4 +:1016F00050E021FD02C09F5F1AC03091EB003E7F99 +:101700003093EB003091ED003D7F3093ED00309150 +:10171000EB0031603093EB007093EC002093ED0010 +:101720005093F0002091EE0027FDE5CF07C09530E3 +:1017300090F28F708093E90081E0089580E0089531 +:101740000F931F93CF93DF93062FEC0110E02EC071 +:101750009881911103C01F5F259628C02C81E981D3 +:10176000FA816B81892F8F70853010F080E021C065 +:10177000223010F056E001C052E028E030E040E0B6 +:1017800003C04F5F220F331F2E173F07D0F3429540 +:10179000407F452B991F9927991F6295660F660F09 +:1017A000607C692B96DF8111D6CFE0CF1013D0CFAC +:1017B00081E0DF91CF911F910F91089580913E02BA +:1017C00087FD05C08091E80080FF0EC012C08091A7 +:1017D000E80082FD05C080913D028111F8CF089597 +:1017E0008091E8008B7708C080913D028111EACF9B +:1017F00008958091E8008E778093E80008958091A5 +:10180000E4009091E50045E62091EC0020FD1FC02A +:1018100023C020913D02222391F0253091F02091A8 +:10182000EB0025FD10C02091E4003091E500281761 +:10183000390751F34150C90139F784E0089582E036 +:10184000089583E0089581E0089580E0089520914F +:10185000E80020FFDECFF9CF2091E80022FFD9CFAA +:10186000F4CF41D043D08091D8008F778093D800B7 +:101870008091D80080688093D8008091D8008F7DB7 +:101880008093D80084E089BD86E089BD09B400FE5C +:10189000FDCF10923D021092390210923B0210923D +:1018A0003A0242E060E080E014DF8091E1008E7F48 +:1018B0008093E1008091E20081608093E20080915A +:1018C000E20088608093E2008091E0008E7F809348 +:1018D000E0000895E3E6F0E080818E7F808381E080 +:1018E00080933C02BECF1092E20008951092E10076 +:1018F00008951F920F920FB60F9211242F933F93CA +:101900004F935F936F937F938F939F93AF93BF9307 +:10191000EF93FF938091E10082FF0BC08091E20082 +:1019200082FF07C08091E1008B7F8093E1000E94DD +:1019300093028091E10080FF18C08091E20080FF57 +:1019400014C08091E2008E7F8093E2008091E200DB +:1019500080618093E2008091D80080628093D800FB +:1019600019BC10923D020E94D6018091E10084FFD3 +:1019700030C08091E20084FF2CC084E089BD86E005 +:1019800089BD09B400FEFDCF8091D8008F7D809382 +:10199000D8008091E1008F7E8093E1008091E20089 +:1019A0008F7E8093E2008091E20081608093E2006C +:1019B00080913902882311F084E007C08091E30010 +:1019C00087FF02C083E001C081E080933D020E9456 +:1019D000D5018091E10083FF27C08091E20083FF61 +:1019E00023C08091E100877F8093E10082E08093B3 +:1019F0003D02109239028091E1008E7F8093E100D8 +:101A00008091E2008E7F8093E2008091E20080610D +:101A10008093E20042E060E080E05BDE8091F000D5 +:101A200088608093F000B7D1FF91EF91BF91AF91A3 +:101A30009F918F917F916F915F914F913F912F91E6 +:101A40000F900FBE0F901F9018951F920F920FB618 +:101A50000F9211242F933F934F935F936F937F9334 +:101A60008F939F93AF93BF93CF93EF93FF93809107 +:101A7000E9008F709091EC0090FF02C090E801C0E7 +:101A800090E0C92FC82B1092E9008091F000877F69 +:101A90008093F00078941CD01092E9008091F000BF +:101AA00088608093F000CF70C093E900FF91EF91C0 +:101AB000CF91BF91AF919F918F917F916F915F91E6 +:101AC0004F913F912F910F900FBE0F901F9018953F +:101AD0001F93CF93DF93CDB7DEB7AC970FB6F894D3 +:101AE000DEBF0FBECDBFEEE3F2E08091F100819347 +:101AF00022E0E634F207C9F70E948B028091E800E9 +:101B000083FF31C180913E0290913F02953009F4EC +:101B100087C038F49130B1F170F0933009F023C1EF +:101B200031C0983009F4F3C0993009F4FFC0963001 +:101B300009F019C19BC0803821F0823809F013C127 +:101B400008C080913A0290913B02992389F082600B +:101B50000FC080914202909143028F709927809329 +:101B6000E9008091EB0085FB882780F91092E9005D +:101B70009091E800977F9093E8008093F100109295 +:101B8000F100D0C0882319F0823009F0ECC08F71C9 +:101B900021F0823009F0E7C00BC080914002813013 +:101BA00009F0E1C0933009F080E080933B022FC040 +:101BB0008091400281112BC080914202909143029A +:101BC0008F709927009709F4CEC08093E900209187 +:101BD000EB0020FF1CC020913F02233021F48091B4 +:101BE000EB00806212C09091EB0090619093EB004B +:101BF00021E030E001C0220F8A95EAF72093EA0045 +:101C00001092EA008091EB0088608093EB001092C4 +:101C1000E9008091E800877F8093E800CFDDA3C0D2 +:101C20008111A1C080914002909141028F77992744 +:101C3000182F9091E3009078982B9093E300809177 +:101C4000E800877F8093E800B9DD8091E80080FF9D +:101C5000FCCF8091E30080688093E300112311F0B2 +:101C600083E001C082E080933D027DC080588230D5 +:101C700008F079C080914002909141028C3D23E0B0 +:101C8000920771F583E08A838AE289834FB7F894DB +:101C9000DE01139620E03EE051E2E32FF0E05093A6 +:101CA0005700E49120FF03C0E295EF703F5FEF70B3 +:101CB0008E2F90E0EA3010F0C79601C0C0968D9349 +:101CC0009D932F5F243149F74FBF8091E800877FB4 +:101CD0008093E8006AE270E0CE010196F9DB11C062 +:101CE000AE01455D5F4F6091420244DB0097D9F140 +:101CF0002091E800277F2093E800BC018BA59CA5DC +:101D000087DC8091E8008B778093E8002CC08038D6 +:101D100051F58091E800877F8093E8008091390237 +:101D20008093F1008091E8008E7776CF81111BC0FF +:101D3000909140029230B8F48091E800877F8093C0 +:101D4000E800909339023ADD80913902811104C094 +:101D50008091E30087FF02C084E001C081E08093AE +:101D60003D020E94D7018091E80083FF0AC0809164 +:101D7000E800877F8093E8008091EB008062809389 +:101D8000EB00AC960FB6F894DEBF0FBECDBFDF916F +:101D9000CF911F9108950895CF9380913D0288239C +:101DA000A9F08091E9008F709091EC0090FF02C043 +:101DB00090E801C090E0C92FC82B1092E9008091F3 +:101DC000E80083FD85DECF70C093E900CF910895D0 +:101DD000CF93DF93EC014096FC018BE0DF011D9275 +:101DE0008A95E9F782E08C83898783E08E8761E0BA +:101DF000CE010196A5DC882361F061E0CE01069654 +:101E00009FDC882331F061E0CE010B96DF91CF910A +:101E100097CC80E0DF91CF9108950F931F93FC0141 +:101E2000CB01BA0120913D02243089F4048915893F +:101E300026893789012B022B032B49F021812F7032 +:101E40002093E90040E050E01F910F91F4CA82E036 +:101E50001F910F910895CF93C62F20913D022430FA +:101E6000F1F4FC014489558966897789452B462B15 +:101E7000472BA9F081818F708093E9008091E80061 +:101E800085FF04C0C093F10080E00AC08091E800A3 +:101E90008E778093E800B3DC8823A1F301C082E051 +:101EA000CF91089520913D02243029F5FC01448909 +:101EB000558966897789452B462B472BE1F081812F +:101EC0008F708093E9008091F200811102C080E060 +:101ED00008959091E8008091E8008E778093E80063 +:101EE00095FDF5CF8CDC811107C09091E8009E77BD +:101EF0009093E800089582E0089520913D022430F7 +:101F000089F4FC014489558966897789452B462BDC +:101F1000472B41F021812F702093E9002091E800A8 +:101F200020FDC0CF089520913D02243019F02FEFFD +:101F30003FEF24C0FC014489558966897789452B88 +:101F4000462B472BA1F386818F708093E900809107 +:101F5000E80082FFECCF8091F200882321F02091ED +:101F6000F10030E002C02FEF3FEF8091F2008111CD +:101F700005C08091E8008B778093E800C90108953F +:101F80000895CF93DF93EC018091E80083FFA9C00F +:101F9000888190E02091420230914302281739074E +:101FA00009F09FC080913F02813261F020F48032BD +:101FB00009F097C03DC0823209F46EC0833209F047 +:101FC00090C07FC080913E02813A09F08AC0809122 +:101FD000E800877F8093E8008091E80080FFFCCFD5 +:101FE0004C895D896E897F894093F100BB27A72FBB +:101FF000962F852F8093F100CB01AA27BB278093D2 +:10200000F100472F5527662777274093F100888DE9 +:102010008093F100898D8093F1008A8D8093F10087 +:102020008091E8008E778093E800DF91CF91C6CB56 +:1020300080913E02813209F054C08091E800877F90 +:102040008093E80005C080913D02882309F449C0CF +:102050008091E80082FFF7CF3091F1002091F100EC +:102060009091F1008091F1003C8B2D8B9E8B8F8B9A +:102070008091F100888F8091F100898F8091F1002B +:102080008A8F8091E8008B778093E80097DBCE0100 +:10209000DF91CF910C94E50180913E02813209F5E8 +:1020A0008091E800877F8093E80088DB8091400280 +:1020B00090914102998B888BCE01DF91CF910C9446 +:1020C000800280913E02813261F48091E800877F36 +:1020D0008093E80073DB60914002CE01DF91CF91E5 +:1020E0004FCFDF91CF9108956F927F928F929F9201 +:1020F000AF92BF92CF92DF92EF92FF920F931F9316 +:10210000CF93DF9300D01F92CDB7DEB77C01ADB681 +:10211000BEB68091E80083FF07C1F701808190E09F +:1021200020914202309143022817390709F0FCC080 +:1021300080913F02833009F49EC030F4813071F009 +:10214000823009F0F1C0D4C08A3009F4B9C08B30B4 +:1021500009F4A2C0893009F0E7C04CC080913E026A +:10216000813A09F0E1C08DB69EB61A82198280913B +:102170004002109141028B83F70140858DB79EB7D5 +:10218000841B91090FB6F8949EBF0FBE8DBFCDB6CC +:10219000DEB6EFEFCE1ADE0A360150E060E070E006 +:1021A000C601EAD1412F41508E010F5F1F4F9601AA +:1021B000BE016D5F7F4FC7010E949F02F70126811C +:1021C00037812115310529F0408550E0B601C9015C +:1021D000CAD11092E9008091E800877F8093E800DF +:1021E00069817A81C30174D98091E8008B778093EB +:1021F000E80039C080913E02813209F095C08DB669 +:102200009EB6009144021091450270904002609089 +:1022100041028DB79EB7801B910B0FB6F8949EBFFD +:102220000FBE8DBFCDB6DEB6EFEFCE1ADE0A8091BF +:10223000E800877F8093E800B801C601A9D98091A2 +:10224000E8008E778093E80021E0711001C020E063 +:1022500030E0021B130B2C0D3D1D462D4150672D08 +:10226000C7010E94D002882D992D0FB6F8949EBF09 +:102270000FBE8DBF59C080913E02813A09F054C013 +:102280008091E800877F8093E8008091E80080FFDC +:10229000FCCFF701818540C080913E02813209F078 +:1022A00043C08091E800877F8093E80087DA9091AF +:1022B000400281E0911101C080E0F701818734C0C4 +:1022C00080913E02813281F58091E800877F809382 +:1022D000E80074DA8091400290914102882736E04C +:1022E000969587953A95E1F7F701958784871CC005 +:1022F00080913E02813AC1F48091E800877F80930B +:10230000E8008091E80080FFFCCFF7018485958587 +:1023100096958795969587958093F1008091E80032 +:102320008E778093E8004ADA0FB6F894BEBE0FBEEF +:10233000ADBE0F900F900F90DF91CF911F910F9135 +:10234000FF90EF90DF90CF90BF90AF909F908F90D5 +:102350007F906F9008959C01275F3F4FF90127E020 +:10236000DF011D922A95E9F721E0FC01218724EF86 +:1023700031E03587248723E0248361E00196E0C9BA +:102380004F925F926F927F928F929F92AF92BF9285 +:10239000CF92DF92EF92FF920F931F93CF93DF9331 +:1023A00000D01F92CDB7DEB77C01ADB6BEB680912E +:1023B0003D02843009F08FC08091E4009091E500E7 +:1023C000F701228533852817390709F484C08181F4 +:1023D0008F708093E9008091E80085FF7CC06DB626 +:1023E0007EB640858DB79EB7841B91090FB6F894D1 +:1023F0009EBF0FBE8DBFCDB6DEB6EFEFCE1ADE0AA2 +:102400001B821A821982460150E060E070E0C6012A +:10241000B3D08E010F5F1F4F960140E0BE016D5F8C +:102420007F4FC7010E949F02582EF7018485958532 +:10243000892B31F001E010E086859785892B11F01A +:1024400000E010E0F701C680D780C114D10489F004 +:1024500049815A81B601C40179D04424439400973C +:1024600009F4412CF701408550E0B401C6017BD04E +:1024700001C0412C89819A81892BF9F0511004C047 +:10248000411002C000FF19C0F70184859585978728 +:10249000868781818F708093E9008B818111809381 +:1024A000F10069817A8140E050E0C4010E941B0A7A +:1024B0008091E8008E778093E8008091E40090910D +:1024C000E500F70193878287862D972D0FB6F89444 +:1024D0009EBF0FBE8DBF0FB6F894BEBE0FBEADBE81 +:1024E0000F900F900F90DF91CF911F910F91FF9060 +:1024F000EF90DF90CF90BF90AF909F908F907F90A4 +:102500006F905F904F900895A1E21A2EAA1BBB1BFB +:10251000FD010DC0AA1FBB1FEE1FFF1FA217B307AF +:10252000E407F50720F0A21BB30BE40BF50B661FC5 +:10253000771F881F991F1A9469F760957095809589 +:1025400090959B01AC01BD01CF010895FB01DC0119 +:1025500004C08D910190801921F441505040C8F77A +:10256000881B990B0895FB01DC0102C001900D92BC +:1025700041505040D8F70895DC0101C06D9341509F +:0A2580005040E0F70895F894FFCFF3 +:10258A0002812000000100003F000000000000005E +:10259A00008340000001044000000182080000019D +:0E25AA000000000000000000000000302000D3 +:00000001FF diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 1219d79b21..a76d19a09b 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -74,21 +74,19 @@ To **install the new bootloader** connect your Arduino to your PC via USB and se For Arduino Mega2560 I recommend (in general) the IDE 1.5.7 or higher. [See Issue on Github.](https://github.com/arduino/Arduino/issues/1071) [Or this Issue.)(http://forum.arduino.cc/index.php?topic=126160.0) -#### For all Arduinos - - Usage ===== You are ready to use the libraries. **Just have a look at the examples and test it out.** They are pretty much self explaining. All examples use a button on pin 8 and show the basic usage of the libraries. The libraries will work for all Arduinos listed above but it will use 2 different HID libraries (automatically). +The HID include and HID.begin() is not needed for **Leonardo/Micro** but I'd recommend +to use it every time so you can port the library from one to another device. + **On Arduino/Mega you can only use baud 115200 for HID** due to programming reasons. Its not bad anyway because its the fastest baud and you want fast HID recognition. You still can use any other baud for -normal sketches without HID. HID.begin() starts the Serial at baud 115200 on Arduino Uno/Mega. Do not call Serial.begin() again. - -The HID include and HID.begin() is not needed for Leonardo/Micro but I'd recommend -to use it every time so you can port the library from one to another device. +normal sketches without but HID wont work. If you try nevertheless it will output Serial crap to the Monitor. +HID.begin() starts the Serial at baud 115200 on Arduino Uno/Mega. Do not call Serial.begin() again. **Always release buttons to not cause any erros.** Replug USB cable to reset the values if anything went wrong. See [Deactivate HID function](https://github.com/NicoHood/Hoodloader) if you need to fully disable HID again. @@ -173,6 +171,10 @@ Oh and by the way: I also removed some bugs from the official firmware. Version History =============== ``` +1.7.1 Beta Release (09.08.2014) +* Changes in the Hoodloader: + * Fixed HID deactivation bug + 1.7 Beta Release (09.08.2014) * Changes in the Hoodloader: * Works as ISP now. See the [Hoodloader Repository](https://github.com/NicoHood/Hoodloader) for more information. From 72bef259eeb3d28360516c57fc22e23fcf23be05 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 10 Aug 2014 22:17:21 +0200 Subject: [PATCH 040/602] Update 1.7.3 --- .../Firmwares/Hoodloader1_4_1.hex | 479 -------------- .../Firmwares/Hoodloader1_4_2.hex | 481 -------------- .../KeyboardioHID/Firmwares/Hoodloader1_5.hex | 466 ------------- .../KeyboardioHID/Firmwares/Hoodloader1_6.hex | 474 -------------- .../Firmwares/Hoodloader1_7_1.hex | 605 ----------------- .../Firmwares/Hoodloader1_7_3.hex | 613 ++++++++++++++++++ ...ino-usbserial-atmega16u2-Mega2560-Rev3.hex | 0 ...uino-usbserial-atmega16u2-MegaADK-Rev3.hex | 0 .../Arduino-usbserial-atmega16u2-Uno-Rev3.hex | 0 plugins/KeyboardioHID/Firmwares/Readme.md | 2 + plugins/KeyboardioHID/HID_Source/HID.h | 29 +- plugins/KeyboardioHID/Readme.md | 22 +- .../hardware/16u2asISP/avr/boards.txt | 0 .../hardware/16u2asISP/avr/programmers.txt | 8 - plugins/KeyboardioHID/hardware/Readme.md | 8 - 15 files changed, 646 insertions(+), 2541 deletions(-) delete mode 100644 plugins/KeyboardioHID/Firmwares/Hoodloader1_4_1.hex delete mode 100644 plugins/KeyboardioHID/Firmwares/Hoodloader1_4_2.hex delete mode 100644 plugins/KeyboardioHID/Firmwares/Hoodloader1_5.hex delete mode 100644 plugins/KeyboardioHID/Firmwares/Hoodloader1_6.hex delete mode 100644 plugins/KeyboardioHID/Firmwares/Hoodloader1_7_1.hex create mode 100644 plugins/KeyboardioHID/Firmwares/Hoodloader1_7_3.hex rename plugins/KeyboardioHID/Firmwares/{ => OriginalFirmwares}/Arduino-usbserial-atmega16u2-Mega2560-Rev3.hex (100%) rename plugins/KeyboardioHID/Firmwares/{ => OriginalFirmwares}/Arduino-usbserial-atmega16u2-MegaADK-Rev3.hex (100%) rename plugins/KeyboardioHID/Firmwares/{ => OriginalFirmwares}/Arduino-usbserial-atmega16u2-Uno-Rev3.hex (100%) delete mode 100644 plugins/KeyboardioHID/hardware/16u2asISP/avr/boards.txt delete mode 100644 plugins/KeyboardioHID/hardware/16u2asISP/avr/programmers.txt delete mode 100644 plugins/KeyboardioHID/hardware/Readme.md diff --git a/plugins/KeyboardioHID/Firmwares/Hoodloader1_4_1.hex b/plugins/KeyboardioHID/Firmwares/Hoodloader1_4_1.hex deleted file mode 100644 index 42eda4b758..0000000000 --- a/plugins/KeyboardioHID/Firmwares/Hoodloader1_4_1.hex +++ /dev/null @@ -1,479 +0,0 @@ -:1000000073C100008DC100008BC1000089C10000D8 -:1000100087C1000085C1000083C1000081C10000CC -:100020007FC100007DC100007BC100000C94AA08C4 -:100030000C94530975C1000073C1000071C1000028 -:100040006FC100006DC100006BC1000069C10000FC -:1000500067C1000065C1000063C10000ECC300007F -:100060005FC100005DC100005BC1000059C100001C -:1000700057C1000030034100720064007500690040 -:100080006E006F00200048006F006F0064006C007D -:100090006F0061006400650072002000420065008E -:1000A00074006100000012034E00690063006F00DD -:1000B00048006F006F006400000004030904090297 -:1000C0005F00030100C032080B00020202010009B8 -:1000D00004000001020201000524001001042402B2 -:1000E000060524060001070582030800FF09040134 -:1000F00000020A0000000705040240000107058312 -:10010000024000010904020001030000000921115E -:1001100001000122B801070581032000011201102E -:1001200001EF020108EB03686E14000102DC010517 -:10013000010902A1010901A100850105091901298F -:10014000051500250195057501810295017503814D -:100150000305010930093109381581257F75089596 -:10016000038106C0C005010906A101850205071922 -:10017000E029E715002501750195088102950175B3 -:1001800008810395067508150025650507190029DE -:1001900065810005081901290595057501910295EC -:1001A0000175039103C006C0FF0A000CA10185037D -:1001B0007508150026FF0095400901810295400948 -:1001C000029102C0050C0901A1018504150026FF5A -:1001D000FF19002AFFFF950475108100C005010971 -:1001E00080A1018505150026FF00190029FF950152 -:1001F00075088100C005010905A1018506050919D9 -:10020000012920150025017501952081020501A114 -:10021000000930093109320933093409351500273D -:10022000FFFF0000751095068102C005010939091C -:100230003915012508950275048102C005010905DB -:10024000A10185070509190129201500250175015E -:10025000952081020501A1000930093109320933D5 -:1002600009340935150027FFFF0000751095068138 -:1002700002C0093909391501250895027504810262 -:10028000C005010904A1018508A10005091901297A -:100290000215002501750195028102050109300949 -:1002A00031150026FF03750A95028102750295013A -:1002B0008103C0C005010904A1018509A100050948 -:1002C0001901290215002501750195028102050118 -:1002D00009300931150026FF03750A950281027560 -:1002E0000295018103C0C00011241FBECFEFD2E0F0 -:1002F000DEBFCDBF11E0A0E0B1E0E6EAFDE102C063 -:1003000005900D92AE32B107D9F712E0AEE2B1E03E -:1003100001C01D92AD34B107E1F736D10C94D10E76 -:100320006FCECF93DF9384B7877F84BF28E10FB66A -:10033000F89420936000109260000FBE80E190E07E -:100340009093CD008093CC00CAECD0E096E09883E7 -:10035000A8ECB0E082E08C93E9ECF0E02083539AC3 -:100360005A9A5B9A10821C92188298838C9388E91F -:1003700080835B988AB180638AB98BB180638BB9C3 -:10038000DAD684E085BD5F9A579A22982A9ADF913F -:10039000CF9108950F931F93CF93DF93CFE2D2E0D5 -:1003A000082F10E00AC08091200180FF05C06881FD -:1003B00080E191E00E94390B2196CE018F5292404C -:1003C0008017910784F3DF91CF911F910F910895CA -:1003D000CF92DF92EF92FF920F931F93CF93DF9311 -:1003E00000D000D000D0CDB7DEB780911C028111C3 -:1003F00022C060911A0270E07160AE014F5F5F4FE2 -:1004000081E034D48E010F5F1F4F6801E82EF12C7C -:100410000CC08091200180FF06C0F801608180E15E -:1004200091E00E94390B0F5F1F4FC8018C199D0985 -:100430008E159F0574F310921A0210921C022696D4 -:100440000FB6F894DEBF0FBECDBFDF91CF911F91E5 -:100450000F91FF90EF90DF90CF9008951F93CF936F -:10046000DF9397D3882309F48BC01A9B89C08091AE -:10047000240190912501A0912601B09127018115B9 -:1004800022EC920721E0A207B10529F0892B8A2BE3 -:100490008B2B09F075C09FD28130A9F5ABD280FFBC -:1004A00032C080911A02811193DFA1D280931A0287 -:1004B00010921C0291E1EDE1F2E0DF01292F1D9283 -:1004C0002A95E9F7853099F038F4823061F084306C -:1004D00051F0813099F405C0883058F08A3070F4BA -:1004E0000BC084E001C088E080931B0208C081E05B -:1004F000FBCF90931B0203C083E0F6CF69DFDF914F -:10050000CF911F9164C280911A028823C9F163D2EE -:1005100010911C02C12FD0E090E09E012E5F3F4F52 -:10052000359527952F5F3F4F8217930729F55FD2A7 -:10053000C35EDD4F8883C12FCF5FC0931C028091C3 -:100540001B028C1749F056D2EC2FF0E0E35EFD4F12 -:1005500080831E5F10931C0290911B0280911C02ED -:100560009813CDCF04C080E091E00E94CE0D809121 -:100570001A028111F8CFC3CFDF91CF911F9128CFFD -:10058000DF91CF911F910895CCDE2FB7F89480E3CF -:1005900091E09093A1018093A0019093A301809397 -:1005A000A2012FBF2FB7F89485EA91E0909316022D -:1005B0008093150290931802809317022FBF7894AE -:1005C00010921C0210921A02C0E3D1E08C0153E099 -:1005D000E52E9FB7F8948091A4019FBF803719F151 -:1005E00080E191E00E94A10B97FD1DC0E091A00168 -:1005F000F091A10180838091A0019091A1010196C9 -:100600009093A1018093A001805A914021F4D0934E -:10061000A101C093A0019FB7F8948091A4018F5FBE -:100620008093A4019FBF8FB7F894F09019028FBFF9 -:10063000A89904C080E58F1508F056C0A89A80914B -:100640001902882341F15D98E0922E0124C0D5D192 -:10065000877F39F080911A028111BADE80912E02D3 -:1006600099DEE0911702F09118028191F09318023F -:10067000E0931702E551F24021F410931802009321 -:1006800017022FB7F8949091190291509093190284 -:100690002FBFE4DEFA94F110DACF80912E01882387 -:1006A000B9F080912E01815080932E01811110C0EC -:1006B00080911A0281118CDEA0D183FD07C0F090D9 -:1006C0002E029BD187FDF3948F2D64DE80D15D9A3D -:1006D00080912F01882341F080912F0181508093D8 -:1006E0002F01811101C05C9A9FB7F8948091A401F9 -:1006F0009FBF882309F1E091A201F091A30191919C -:10070000F093A301E093A201E05AF14021F4D093C9 -:10071000A301C093A2012FB7F8948091A401815046 -:100720008093A4012FBF8091C80085FFFCCF9093D8 -:10073000CE005C98E0922F0180E191E0ECD758D791 -:1007400048CF08950895CF9380E091E00E94B90DBD -:10075000C82F80E191E068D79091E2009460909377 -:10076000E200882321F0CC2311F080E001C080E377 -:100770009BB18095906389238BB9CF9108951F9386 -:10078000CF93DF93EC01E98DE150E23028F4F0E003 -:10079000E45DFE4F108101C010E0888D823009F4C5 -:1007A00018608A8D873031F0883031F0863029F436 -:1007B000126003C0146001C016605B9A1092C900F9 -:1007C0001092C8001092CA002C893D894E895F8919 -:1007D000211581EE38074105510579F0CA01B901AB -:1007E000969587957795679560587B47814E9F4F83 -:1007F0000E94920E2150310902C020E130E0309376 -:10080000CD002093CC001093CA008C899D89AE89BD -:10081000BF898115914EA105B10511F480E001C099 -:1008200082E08093C80088E98093C9005B98DF91DB -:10083000CF911F9108951F920F920FB60F9211241E -:100840002F938F939F93EF93FF938091CE0090917E -:1008500044029430F1F4E0911502F0911602808385 -:10086000E0911502F0911602CF01019690931602C5 -:10087000809315028551924021F485EA91E092839C -:1008800081839FB7F894809119028F5F809319023A -:100890009FBFFF91EF919F918F912F910F900FBE6E -:1008A0000F901F901895FC01208920FF02C05F98CF -:1008B00008955F9A8BB180638BB9089580E191E0D0 -:1008C0006ED780E091E00C94820C80910E019091A3 -:1008D0000F01009729F0019790930F0180930E016B -:1008E0000895EF92FF920F931F93CF93DF937B01B5 -:1008F000C901E80110911B02EDE1F2E0412F50E047 -:10090000BF010E94C10EEAE1F2E08081D7018C9321 -:1009100018831982108210921C0281E0DF91CF911E -:100920001F910F91FF90EF9008950895292F33277D -:1009300023303105B1F04CF42130310509F439C0D0 -:100940002230310509F03AC007C02132310539F1B2 -:100950002232310549F132C0EFE5F0E08EEB90E054 -:1009600031C099278130910561F08230910581F085 -:10097000892B21F5EAEBF0E0E491F0E08AEB90E0DE -:1009800021C0E6EAF0E0E491F0E086EA90E01AC0E7 -:10099000E4E7F0E0E491F0E084E790E013C0E9E000 -:1009A000F0E08DE091E00EC0E8EBF1E08FE291E045 -:1009B00009C0E2E1F0E08DE191E004C0E0E0F0E0A8 -:1009C00080E090E0DA018D939C93CF01089588E058 -:1009D00080932B010895809136020895609137022B -:1009E000709138028091390290913A020895809175 -:1009F0003702089580913802089580912B0108955F -:100A0000982F80912B018823E9F083FF0AC0109270 -:100A10003B0210923C0210923D0210923E02109254 -:100A20003F0287FF0DC040912E02E42FF0E0E15D10 -:100A3000FD4F808180932F0281E080932E0202C0BF -:100A400010922E0210923502109236021092370246 -:100A5000109238021092390210923A0210922B0131 -:100A600020912E02E22FF0E0E15DFD4F9083822F76 -:100A70008F5F80932E02392F307C80913B0230387B -:100A800009F440C0303C09F05EC0882329F080E9B9 -:100A900080932B0120932E02292F287326952695CB -:100AA0002695223018F02730E1F40AC09F709F5F2E -:100AB0009093350210923B0280912B0185603DC0DE -:100AC000492F4F7050E060E070E040933C0250933B -:100AD0003D0260933E0270933F0285E080933B02AB -:100AE00056C0892F877090E0A0E0B0E080933C0270 -:100AF00090933D02A0933E02B0933F022150209379 -:100B00003B0245C0282F215020933B028130C9F47D -:100B10009F739F5F9093360280913C0290913D02BB -:100B2000A0913E02B0913F02809337029093380229 -:100B3000A0933902B0933A0283E080932B0181E0C5 -:100B4000089580E507C0282F215020933B02823072 -:100B500030F480E380932B0110923B0218C0409147 -:100B60003C0250913D0260913E0270913F0287E04D -:100B7000440F551F661F771F8A95D1F7492B409365 -:100B80003C0250933D0260933E0270933F0280E02E -:100B900008950F931F9334DF8823A9F01CDF882367 -:100BA00091F01CDF8C0122273327DC01CB01AA271F -:100BB000BB27082719272A273B2781E00F3F1F4F14 -:100BC0002105310509F080E01F910F9108950F93E1 -:100BD0001F93CF93F901ACE1B0E097E08A019B014C -:100BE0000A2E04C036952795179507950A94D2F7D3 -:100BF000083028F0973051F4008396E007C0008356 -:100C00009150011103C01797923041F7C92FC2507C -:100C100012C0DF01AC0FB11D8A019B010F771127B4 -:100C2000222733270C93A7E076956795579547952C -:100C3000AA95D1F7C150C111ECCF492F50E09A01CC -:100C400063E0220F331F6A95E1F7206C3F6F30811C -:100C5000322B3083E40FF51F319781508F738068FA -:100C60008083892FCF911F910F9108950F931F9328 -:100C70008B01FA01AB014095509560E070E0BA013C -:100C80005527442720E030E0402B512B622B732B5B -:100C90009F011F910F919BCFBF92CF92DF92EF9256 -:100CA000FF920F931F93CF93DF937C018B01EA0197 -:100CB000D7D1B82E811132C0209731F028813981E7 -:100CC000021B130BE20EF31EC12CD12C22C080910B -:100CD000E80085FD14C08091E8008E778093E800DD -:100CE000209749F0888199818C0D9D1D9983888377 -:100CF00025E0B22E13C0B4D1882359F00EC0F701FD -:100D000081917F018093F10001501109FFEFCF1A0B -:100D1000DF0A01151105D9F601C0B82E8B2DDF9120 -:100D2000CF911F910F91FF90EF90DF90CF90BF90E8 -:100D3000089520914B0230914C022617370748F056 -:100D40006115710539F42091E8002E772093E800B1 -:100D500001C0B9019C0180E034C090914402992304 -:100D600009F443C0953009F442C09091E80093FD26 -:100D70003AC09091E80092FD30C09091E80090FF59 -:100D800020C08091F20090E0F901821B930B05C016 -:100D900021912093F100615071099F01280F391FA3 -:100DA0006115710519F02830310590F381E0283084 -:100DB000310509F080E09091E8009E779093E8007B -:100DC0009F016115710549F68111C7CF06C0809159 -:100DD0004402882351F0853051F08091E80082FF71 -:100DE000F6CF80E0089581E0089582E0089583E0E1 -:100DF00008956115710529F42091E8002B7720935F -:100E0000E8009C0121C080914402882381F1853053 -:100E100041F18091E80083FD26C08091E80082FFC7 -:100E2000F2CFF90107C08091F10081939F016150D9 -:100E3000710929F09F018091F2008111F4CF809116 -:100E4000E8008B778093E80061157105E1F68091E9 -:100E5000E80080FD0AC080914402882341F085307B -:100E6000B1F783E0089581E0089580E0089582E07D -:100E7000089520914B0230914C022617370748F015 -:100E80006115710539F42091E8002E772093E80070 -:100E900001C0B9019C0180E035C0909144029923C2 -:100EA00009F444C0953009F443C09091E80093FDE3 -:100EB0003BC09091E80092FD31C09091E80090FF16 -:100EC00021C08091F20090E0F901821B930B06C0D3 -:100ED00024912093F1003196615071099C012E0FED -:100EE0003F1F6115710519F02830310588F381E045 -:100EF0002830310509F080E09091E8009E779093CA -:100F0000E8009F016115710541F68111C6CF06C049 -:100F100080914402882351F0853051F08091E8009F -:100F200082FFF6CF80E0089581E0089582E0089581 -:100F300083E00895982F2CC09093E900981739F01A -:100F40007091EC002091ED005091F00003C0242F2F -:100F5000762F50E021FD02C09F5F1AC03091EB0058 -:100F60003E7F3093EB003091ED003D7F3093ED00FC -:100F70003091EB0031603093EB007093EC002093E4 -:100F8000ED005093F0002091EE0027FDE5CF07C063 -:100F9000953090F28F708093E90081E0089580E0B1 -:100FA00008950F931F93CF93DF93062FEC0110E06A -:100FB0002EC09881911103C01F5F259628C02C81F7 -:100FC000E981FA816B81892F8F70853010F080E084 -:100FD00021C0223010F056E001C052E028E030E09D -:100FE00040E003C04F5F220F331F2E173F07D0F39F -:100FF0004295407F452B991F9927991F6295660F4F -:10100000660F607C692B96DF8111D6CFE0CF10137D -:10101000D0CF81E0DF91CF911F910F910895809102 -:10102000450287FD05C08091E80080FF0EC012C018 -:101030008091E80082FD05C0809144028111F8CFC3 -:1010400008958091E8008B7708C080914402811157 -:10105000EACF08958091E8008E778093E8000895A4 -:101060008091E4009091E50045E62091EC0020FDA0 -:101070001FC023C020914402222391F0253091F01B -:101080002091EB0025FD10C02091E4003091E50097 -:101090002817390751F34150C90139F784E0089501 -:1010A00082E0089583E0089581E0089580E0089546 -:1010B0002091E80020FFDECFF9CF2091E80022FF49 -:1010C000D9CFF4CF41D043D08091D8008F7780938F -:1010D000D8008091D80080688093D8008091D80093 -:1010E0008F7D8093D80084E089BD86E089BD09B4F6 -:1010F00000FEFDCF10924402109240021092420274 -:101100001092410242E060E080E014DF8091E10053 -:101110008E7F8093E1008091E20081608093E20005 -:101120008091E20088608093E2008091E0008E7FF1 -:101130008093E0000895E3E6F0E080818E7F808375 -:1011400081E080934302BECF1092E2000895109296 -:10115000E10008951F920F920FB60F9211242F9362 -:101160003F934F935F936F937F938F939F93AF932F -:10117000BF93EF93FF938091E10082FF0AC08091BB -:10118000E20082FF06C08091E1008B7F8093E10046 -:101190009CDB8091E10080FF17C08091E20080FF1E -:1011A00013C08091E2008E7F8093E2008091E20084 -:1011B00080618093E2008091D80080628093D800A3 -:1011C00019BC10924402BEDA8091E10084FF2FC066 -:1011D0008091E20084FF2BC084E089BD86E089BD58 -:1011E00009B400FEFDCF8091D8008F7D8093D80098 -:1011F0008091E1008F7E8093E1008091E2008F7EFC -:101200008093E2008091E20081608093E20080910F -:101210004002882311F084E007C08091E30087FF3B -:1012200002C083E001C081E0809344028ADA8091A9 -:10123000E10083FF27C08091E20083FF23C08091FB -:10124000E100877F8093E10082E080934402109266 -:1012500040028091E1008E7F8093E1008091E20066 -:101260008E7F8093E2008091E20080618093E200B3 -:1012700042E060E080E05EDE8091F0008860809374 -:10128000F000B5D1FF91EF91BF91AF919F918F91F8 -:101290007F916F915F914F913F912F910F900FBE72 -:1012A0000F901F9018951F920F920FB60F92112456 -:1012B0002F933F934F935F936F937F938F939F935E -:1012C000AF93BF93CF93EF93FF938091E9008F701B -:1012D0009091EC0090FF02C090E801C090E0C92F0F -:1012E000C82B1092E9008091F000877F8093F00076 -:1012F00078941CD01092E9008091F000886080936F -:10130000F000CF70C093E900FF91EF91CF91BF91B2 -:10131000AF919F918F917F916F915F914F913F918D -:101320002F910F900FBE0F901F9018951F93CF9382 -:10133000DF93CDB7DEB7AC970FB6F894DEBF0FBE24 -:10134000CDBFE5E4F2E08091F100819322E0ED343D -:10135000F207C9F7B3DA8091E80083FF30C18091CA -:10136000450290914602953009F487C038F49130D7 -:10137000B1F170F0933009F022C131C0983009F416 -:10138000F3C0993009F4FFC0963009F018C19BC032 -:10139000803821F0823809F012C108C080914102E2 -:1013A00090914202992389F082600FC08091490296 -:1013B00090914A028F7099278093E9008091EB0009 -:1013C00085FB882780F91092E9009091E800977FCB -:1013D0009093E8008093F1001092F100D0C0882330 -:1013E00019F0823009F0EBC08F7121F0823009F0E2 -:1013F000E6C00BC080914702813009F0E0C0933015 -:1014000009F080E0809342022FC080914702811151 -:101410002BC08091490290914A028F7099270097C2 -:1014200009F4CDC08093E9002091EB0020FF1CC09F -:1014300020914602233021F48091EB00806212C09B -:101440009091EB0090619093EB0021E030E001C0BF -:10145000220F8A95EAF72093EA001092EA00809121 -:10146000EB0088608093EB001092E9008091E80027 -:10147000877F8093E800D3DDA2C08111A0C0809156 -:101480004702909148028F779927182F9091E30097 -:101490009078982B9093E3008091E800877F809369 -:1014A000E800BDDD8091E80080FFFCCF8091E30083 -:1014B00080688093E300112311F083E001C082E093 -:1014C000809344027CC08058823008F078C08091BC -:1014D0004702909148028C3D23E0920771F583E02A -:1014E0008A838AE289834FB7F894DE01139620E05D -:1014F0003EE051E2E32FF0E050935700E49120FFEB -:1015000003C0E295EF703F5FEF708E2F90E0EA30FE -:1015100010F0C79601C0C0968D939D932F5F243124 -:1015200049F74FBF8091E800877F8093E8006AE227 -:1015300070E0CE010196FDDB11C0AE01455D5F4F4D -:1015400060914902F3D90097D1F12091E800277FFB -:101550002093E800BC018BA59CA58BDC8091E80062 -:101560008B778093E8002BC0803849F58091E800A4 -:10157000877F8093E800809140028093F100809102 -:10158000E8008E7776CF81111AC090914702923091 -:10159000B0F48091E800877F8093E8009093400248 -:1015A0003EDD80914002811104C08091E30087FFFD -:1015B00002C084E001C081E080934402C4D88091DD -:1015C000E80083FF0AC08091E800877F8093E800ED -:1015D0008091EB0080628093EB00AC960FB6F8949C -:1015E000DEBF0FBECDBFDF91CF911F91089508954B -:1015F000CF93809144028823A9F08091E9008F70F5 -:101600009091EC0090FF02C090E801C090E0C92FDB -:10161000C82B1092E9008091E80083FD87DECF702F -:10162000C093E900CF910895CF93DF93EC014096EA -:10163000FC018BE0DF011D928A95E9F782E08C8343 -:10164000898783E08E8761E0CE010196AADC88233A -:1016500061F061E0CE010696A4DC882331F061E000 -:10166000CE010B96DF91CF919CCC80E0DF91CF91A2 -:101670000895CF93C62F209144022430F1F4FC0149 -:101680004489558966897789452B462B472BA9F0D4 -:1016900081818F708093E9008091E80085FF04C00C -:1016A000C093F10080E00AC08091E8008E778093BB -:1016B000E800D6DC8823A1F301C082E0CF91089531 -:1016C00020914402243029F5FC014489558966891A -:1016D0007789452B462B472BE1F081818F708093D2 -:1016E000E9008091F200811102C080E0089590919C -:1016F000E8008091E8008E778093E80095FDF5CFB3 -:10170000AFDC811107C09091E8009E779093E800CC -:10171000089582E0089520914402243089F4FC0168 -:101720004489558966897789452B462B472B41F09B -:1017300021812F702093E9002091E80020FDC0CF87 -:10174000089520914402243019F02FEF3FEF24C078 -:10175000FC014489558966897789452B462B472B9F -:10176000A1F386818F708093E9008091E80082FF69 -:10177000ECCF8091F200882321F02091F10030E03D -:1017800002C02FEF3FEF8091F200811105C08091E0 -:10179000E8008B778093E800C90108950895CF93FE -:1017A000DF93EC018091E80083FFA9C0888190E07D -:1017B0002091490230914A022817390709F09FC049 -:1017C00080914602813261F020F4803209F097C0A6 -:1017D0003DC0823209F46EC0833209F090C07FC0F0 -:1017E00080914502813A09F08AC08091E800877FA4 -:1017F0008093E8008091E80080FFFCCF4C895D89F0 -:101800006E897F894093F100BB27A72F962F852FE4 -:101810008093F100CB01AA27BB278093F100472FCB -:101820005527662777274093F100888D8093F10034 -:10183000898D8093F1008A8D8093F1008091E8007A -:101840008E778093E800DF91CF91E9CB80914502BC -:10185000813209F054C08091E800877F8093E800CE -:1018600005C080914402882309F449C08091E800B2 -:1018700082FFF7CF3091F1002091F1009091F100BB -:101880008091F1003C8B2D8B9E8B8F8B8091F10092 -:10189000888F8091F100898F8091F1008A8F8091EB -:1018A000E8008B778093E800BADBCE01DF91CF911F -:1018B0000C94BF0380914502813209F58091E800C4 -:1018C000877F8093E800ABDB8091470290914802CC -:1018D000998B888BCE01DF91CF910C94530480912A -:1018E0004502813261F48091E800877F8093E800AF -:1018F00096DB60914702CE01DF91CF914FCFDF9110 -:10190000CF9108956F927F928F929F92AF92BF92E4 -:10191000CF92DF92EF92FF920F931F93CF93DF93BB -:1019200000D01F92CDB7DEB77C01ADB6BEB68091B8 -:10193000E80083FF07C1F701808190E02091490210 -:1019400030914A022817390709F0FCC080914602FD -:10195000833009F49EC030F4813071F0823009F098 -:10196000F1C0D4C08A3009F4B9C08B3009F4A2C0E8 -:10197000893009F0E7C04CC080914502813A09F0F6 -:10198000E1C08DB69EB61A821982809147021091ED -:1019900048028B83F70140858DB79EB7841B910960 -:1019A0000FB6F8949EBF0FBE8DBFCDB6DEB6EFEF7B -:1019B000CE1ADE0A360150E060E070E0C601EAD1DE -:1019C000412F41508E010F5F1F4F9601BE016D5F89 -:1019D0007F4FC7010E947104F701268137812115CD -:1019E000310529F0408550E0B601C901CAD11092F5 -:1019F000E9008091E800877F8093E80069817A811F -:101A0000C30197D98091E8008B778093E80039C0B3 -:101A100080914502813209F095C08DB69EB6009145 -:101A20004B0210914C0270904702609048028DB7B3 -:101A30009EB7801B910B0FB6F8949EBF0FBE8DBF53 -:101A4000CDB6DEB6EFEFCE1ADE0A8091E800877FD2 -:101A50008093E800B801C601CCD98091E8008E7768 -:101A60008093E80021E0711001C020E030E0021B0B -:101A7000130B2C0D3D1D462D4150672DC7010E94B3 -:101A80009504882D992D0FB6F8949EBF0FBE8DBF7B -:101A900059C080914502813A09F054C08091E80014 -:101AA000877F8093E8008091E80080FFFCCFF701FA -:101AB000818540C080914502813209F043C0809108 -:101AC000E800877F8093E800AADA9091470281E0DE -:101AD000911101C080E0F701818734C080914502F7 -:101AE000813281F58091E800877F8093E80097DA62 -:101AF0008091470290914802882736E09695879515 -:101B00003A95E1F7F701958784871CC080914502DB -:101B1000813AC1F48091E800877F8093E80080914A -:101B2000E80080FFFCCFF701848595859695879521 -:101B3000969587958093F1008091E8008E77809349 -:101B4000E8006DDA0FB6F894BEBE0FBEADBE0F90C2 -:101B50000F900F90DF91CF911F910F91FF90EF9019 -:101B6000DF90CF90BF90AF909F908F907F906F90BD -:101B700008959C01275F3F4FF90127E0DF011D9287 -:101B80002A95E9F721E0FC01218724EF31E0358730 -:101B9000248723E0248361E0019603CA4F925F9279 -:101BA0006F927F928F929F92AF92BF92CF92DF926D -:101BB000EF92FF920F931F93CF93DF9300D01F926A -:101BC000CDB7DEB77C01ADB6BEB68091440284309D -:101BD00009F08FC08091E4009091E500F701228523 -:101BE00033852817390709F484C081818F70809369 -:101BF000E9008091E80085FF7CC06DB67EB6408527 -:101C00008DB79EB7841B91090FB6F8949EBF0FBE87 -:101C10008DBFCDB6DEB6EFEFCE1ADE0A1B821A827A -:101C20001982460150E060E070E0C601B3D08E0139 -:101C30000F5F1F4F960140E0BE016D5F7F4FC701F0 -:101C40000E947104582EF70184859585892B31F007 -:101C500001E010E086859785892B11F000E010E007 -:101C6000F701C680D780C114D10489F049815A8117 -:101C7000B601C40179D044244394009709F4412C5F -:101C8000F701408550E0B401C6017BD001C0412C72 -:101C900089819A81892BF9F0511004C0411002C04A -:101CA00000FF19C0F7018485958597878687818114 -:101CB0008F708093E9008B8181118093F10069819D -:101CC0007A8140E050E0C4010E944C068091E80017 -:101CD0008E778093E8008091E4009091E500F70111 -:101CE00093878287862D972D0FB6F8949EBF0FBEDF -:101CF0008DBF0FB6F894BEBE0FBEADBE0F900F9055 -:101D00000F90DF91CF911F910F91FF90EF90DF9097 -:101D1000CF90BF90AF909F908F907F906F905F908B -:101D20004F900895A1E21A2EAA1BBB1BFD010DC006 -:101D3000AA1FBB1FEE1FFF1FA217B307E407F5077B -:101D400020F0A21BB30BE40BF50B661F771F881F57 -:101D5000991F1A9469F760957095809590959B01ED -:101D6000AC01BD01CF010895FB01DC0104C08D91E0 -:101D70000190801921F441505040C8F7881B990BFD -:101D80000895FB01DC0102C001900D9241505040CA -:101D9000D8F70895DC0101C06D9341505040E0F741 -:061DA0000895F894FFCF46 -:101DA6000281200000010000110000000000000078 -:101DB6000083400000010440000001820800000189 -:0E1DC6000000000000000000000000083020B7 -:00000001FF diff --git a/plugins/KeyboardioHID/Firmwares/Hoodloader1_4_2.hex b/plugins/KeyboardioHID/Firmwares/Hoodloader1_4_2.hex deleted file mode 100644 index d6f40b6875..0000000000 --- a/plugins/KeyboardioHID/Firmwares/Hoodloader1_4_2.hex +++ /dev/null @@ -1,481 +0,0 @@ -:1000000073C100008DC100008BC1000089C10000D8 -:1000100087C1000085C1000083C1000081C10000CC -:100020007FC100007DC100007BC100000C94B908B5 -:100030000C94620975C1000073C1000071C1000019 -:100040006FC100006DC100006BC1000069C10000FC -:1000500067C1000065C1000063C10000FBC3000070 -:100060005FC100005DC100005BC1000059C100001C -:1000700057C1000030034100720064007500690040 -:100080006E006F00200048006F006F0064006C007D -:100090006F0061006400650072002000420065008E -:1000A00074006100000012034E00690063006F00DD -:1000B00048006F006F006400000004030904090297 -:1000C0005F00030100C032080B00020202010009B8 -:1000D00004000001020201000524001001042402B2 -:1000E000060524060001070582030800FF09040134 -:1000F00000020A0000000705040240000107058312 -:10010000024000010904020001030000000921115E -:1001100001000122B801070581032000011201102E -:1001200001EF020108EB03686E14000102DC010517 -:10013000010902A1010901A100850105091901298F -:10014000051500250195057501810295017503814D -:100150000305010930093109381581257F75089596 -:10016000038106C0C005010906A101850205071922 -:10017000E029E715002501750195088102950175B3 -:1001800008810395067508150025650507190029DE -:1001900065810005081901290595057501910295EC -:1001A0000175039103C006C0FF0A000CA10185037D -:1001B0007508150026FF0095400901810295400948 -:1001C000029102C0050C0901A1018504150026FF5A -:1001D000FF19002AFFFF950475108100C005010971 -:1001E00080A1018505150026FF00190029FF950152 -:1001F00075088100C005010905A1018506050919D9 -:10020000012920150025017501952081020501A114 -:10021000000930093109320933093409351500273D -:10022000FFFF0000751095068102C005010939091C -:100230003915012508950275048102C005010905DB -:10024000A10185070509190129201500250175015E -:10025000952081020501A1000930093109320933D5 -:1002600009340935150027FFFF0000751095068138 -:1002700002C0093909391501250895027504810262 -:10028000C005010904A1018508A10005091901297A -:100290000215002501750195028102050109300949 -:1002A00031150026FF03750A95028102750295013A -:1002B0008103C0C005010904A1018509A100050948 -:1002C0001901290215002501750195028102050118 -:1002D00009300931150026FF03750A950281027560 -:1002E0000295018103C0C00011241FBECFEFD2E0F0 -:1002F000DEBFCDBF11E0A0E0B1E0E4ECFDE102C063 -:1003000005900D92AE32B107D9F712E0AEE2B1E03E -:1003100001C01D92AF34B107E1F720D10C94E00E7B -:100320006FCECF93DF9384B7877F84BF28E10FB66A -:10033000F89420936000109260000FBE80E190E07E -:100340009093CD008093CC00CAECD0E096E09883E7 -:10035000A8ECB0E082E08C93E9ECF0E02083539AC3 -:100360005A9A5B9A10821C92188298838C9388E91F -:1003700080835B988AB180638AB98BB180638BB9C3 -:10038000E9D684E085BD5F9A579A22982A9ADF9130 -:10039000CF9108950F931F93CF93DF93C1E3D2E0E2 -:1003A000082F10E00AC08091200180FF05C06881FD -:1003B00080E191E00E94480B2196CE01815392404A -:1003C0008017910784F3DF91CF911F910F910895CA -:1003D000CF92DF92EF92FF920F931F93CF93DF9311 -:1003E00000D000D000D0CDB7DEB780911C028111C3 -:1003F00022C060911A0270E07160AE014F5F5F4FE2 -:1004000081E043D48E010F5F1F4F6801E82EF12C6D -:100410000CC08091200180FF06C0F801608180E15E -:1004200091E00E94480B0F5F1F4FC8018C199D0976 -:100430008E159F0574F310921A0210921C022696D4 -:100440000FB6F894DEBF0FBECDBFDF91CF911F91E5 -:100450000F91FF90EF90DF90CF9008951F93CF936F -:10046000DF93A6D3882309F475C0C4D28130A9F5DF -:10047000D0D280FF32C080911A028111A9DFC6D28A -:1004800080931A0210921C0291E1EFE1F2E0DF0189 -:10049000292F1D922A95E9F7853099F038F482309A -:1004A00061F0843051F0813099F405C0883058F003 -:1004B0008A3070F40BC084E001C088E080931B0296 -:1004C00008C081E0FBCF90931B0203C083E0F6CF0E -:1004D0007FDFDF91CF911F9189C280911A0288231B -:1004E000C9F188D210911C02C12FD0E090E09E018A -:1004F0002E5F3F4F359527952F5F3F4F821793070C -:1005000029F584D2C15EDD4F8883C12FCF5FC093B0 -:100510001C0280911B028C1749F07BD2EC2FF0E07B -:10052000E15EFD4F80831E5F10931C0290911B02C1 -:1005300080911C029813CDCF04C080E091E00E940E -:10054000DD0D80911A028111F8CFC3CFDF91CF91D9 -:100550001F913ECFDF91CF911F910895E2DE2FB71B -:10056000F89480E391E09093A1018093A00190938F -:10057000A3018093A2012FBF2FB7F89485EA91E0E1 -:10058000909316028093150290931802809317029D -:100590002FBF10921C0210921A0210921D0210928C -:1005A0001E027894C0E3D1E08C0153E0F52E9FB792 -:1005B000F8948091A4019FBF803719F180E191E008 -:1005C0000E94B00B97FD1DC0E091A001F091A10128 -:1005D00080838091A0019091A10101969093A10147 -:1005E0008093A001805A914021F4D093A101C0933F -:1005F000A0019FB7F8948091A4018F5F8093A4011C -:100600009FBF8FB7F894E09019028FBFA89904C0DC -:1006100080E58E1508F077C0A89A8091190288238A -:1006200009F448C05D98F0922E0144C0E091170291 -:10063000F0911802D190F0931802E0931702E5515F -:10064000F24021F410931802009317028FB7F89428 -:10065000909119029150909319028FBF1A9B13C069 -:10066000409124015091250160912601709127014C -:10067000411582EC580781E06807710571F0452B40 -:10068000462B472B51F0B2D110921A0210921C0245 -:100690006D2D80E191E0FCD70CC0BED1877F39F091 -:1006A00080911A02811194DE8091300273DE8D2DCB -:1006B000D5DEEA94E110BACF80912E018823B9F0FB -:1006C00080912E01815080932E01811110C0809164 -:1006D0001A0281117DDEA0D183FD07C0E0903002B7 -:1006E0009BD187FDE3948E2D55DE80D15D9A80915C -:1006F0002F01882341F080912F01815080932F0199 -:10070000811101C05C9A9FB7F8948091A4019FBFAA -:10071000882309F1E091A201F091A3019191F09356 -:10072000A301E093A201E05AF14021F4D093A30188 -:10073000C093A2012FB7F8948091A40181508093B7 -:10074000A4012FBF8091C80085FFFCCF9093CE00FD -:100750005C98F0922F0180E191E0ECD758D727CF39 -:1007600008950895CF9380E091E00E94C80DC82FAE -:1007700080E191E068D79091E20094609093E2006C -:10078000882321F0CC2311F080E001C080E39BB1ED -:100790008095906389238BB9CF9108951F93CF9350 -:1007A000DF93EC01E98DE150E23028F4F0E0E45D04 -:1007B000FE4F108101C010E0888D823009F418606E -:1007C0008A8D873031F0883031F0863029F412601C -:1007D00003C0146001C016605B9A1092C9001092A9 -:1007E000C8001092CA002C893D894E895F89211565 -:1007F00081EE38074105510579F0CA01B901969596 -:1008000087957795679560587B47814E9F4F0E94EB -:10081000A10E2150310902C020E130E03093CD001B -:100820002093CC001093CA008C899D89AE89BF8922 -:100830008115914EA105B10511F480E001C082E05F -:100840008093C80088E98093C9005B98DF91CF91BD -:100850001F9108951F920F920FB60F9211242F939C -:100860008F939F93EF93FF938091CE0090914602D8 -:100870009430F1F4E0911502F09116028083E0913A -:100880001502F0911602CF01019690931602809303 -:1008900015028551924021F485EA91E0928381838B -:1008A0009FB7F894809119028F5F809319029FBFC0 -:1008B000FF91EF919F918F912F910F900FBE0F900D -:1008C0001F901895FC01208920FF02C05F980895B1 -:1008D0005F9A8BB180638BB9089580E191E06ED708 -:1008E00080E091E00C94910C80910E0190910F01A9 -:1008F000009729F0019790930F0180930E010895BE -:10090000EF92FF920F931F93CF93DF937B01C90167 -:10091000E80110911B02EFE1F2E0412F50E0BF012E -:100920000E94D00EEAE1F2E08081D7018C93188317 -:100930001982108210921C0281E0DF91CF911F91E9 -:100940000F91FF90EF9008950895292F33272330BA -:100950003105B1F04CF42130310509F439C02230B1 -:10096000310509F03AC007C02132310539F1223290 -:10097000310549F132C0EFE5F0E08EEB90E031C097 -:1009800099278130910561F08230910581F0892BA2 -:1009900021F5EAEBF0E0E491F0E08AEB90E021C091 -:1009A000E6EAF0E0E491F0E086EA90E01AC0E4E7DD -:1009B000F0E0E491F0E084E790E013C0E9E0F0E0DB -:1009C0008DE091E00EC0E8EBF1E08FE291E009C02C -:1009D000E2E1F0E08DE191E004C0E0E0F0E080E0F1 -:1009E00090E0DA018D939C93CF01089588E0809385 -:1009F0002B01089580913802089560913902709119 -:100A00003A0280913B0290913C0208958091390214 -:100A1000089580913A02089580912B010895982FAE -:100A200080912B018823E9F083FF0AC010923D02D8 -:100A300010923E0210923F02109240021092410228 -:100A400087FF0DC040913002E42FF0E0EF5CFD4FD6 -:100A500080818093310281E08093300202C0109245 -:100A6000300210923702109238021092390210921E -:100A70003A0210923B0210923C0210922B012091FC -:100A80003002E22FF0E0EF5CFD4F9083822F8F5F0A -:100A900080933002392F307C80913D02303809F448 -:100AA00040C0303C09F05EC0882329F080E9809383 -:100AB0002B0120933002292F287326952695269501 -:100AC000223018F02730E1F40AC09F709F5F9093A6 -:100AD000370210923D0280912B0185603DC0492F65 -:100AE0004F7050E060E070E040933E0250933F0250 -:100AF000609340027093410285E080933D0256C0AE -:100B0000892F877090E0A0E0B0E080933E02909340 -:100B10003F02A0934002B0934102215020933D0236 -:100B200045C0282F215020933D028130C9F49F7386 -:100B30009F5F9093380280913E0290913F02A09176 -:100B40004002B09141028093390290933A02A093FF -:100B50003B02B0933C0283E080932B0181E0089537 -:100B600080E507C0282F215020933D02823030F4C9 -:100B700080E380932B0110923D0218C040913E0209 -:100B800050913F02609140027091410287E0440F12 -:100B9000551F661F771F8A95D1F7492B40933E0258 -:100BA00050933F02609340027093410280E00895A9 -:100BB0000F931F9334DF8823A9F01CDF882391F063 -:100BC0001CDF8C0122273327DC01CB01AA27BB279E -:100BD000082719272A273B2781E00F3F1F4F2105B0 -:100BE000310509F080E01F910F9108950F931F9335 -:100BF000CF93F901ACE1B0E097E08A019B010A2EA6 -:100C000004C036952795179507950A94D2F70830B2 -:100C100028F0973051F4008396E007C0008391508C -:100C2000011103C01797923041F7C92FC25012C06B -:100C3000DF01AC0FB11D8A019B010F77112722271D -:100C400033270C93A7E07695679557954795AA9516 -:100C5000D1F7C150C111ECCF492F50E09A0163E0A8 -:100C6000220F331F6A95E1F7206C3F6F3081322BE2 -:100C70003083E40FF51F319781508F738068808334 -:100C8000892FCF911F910F9108950F931F938B017F -:100C9000FA01AB014095509560E070E0BA0155272C -:100CA000442720E030E0402B512B622B732B9F0117 -:100CB0001F910F919BCFBF92CF92DF92EF92FF9245 -:100CC0000F931F93CF93DF937C018B01EA01D7D160 -:100CD000B82E811132C0209731F028813981021B52 -:100CE000130BE20EF31EC12CD12C22C08091E80020 -:100CF00085FD14C08091E8008E778093E8002097EE -:100D000049F0888199818C0D9D1D9983888325E008 -:100D1000B22E13C0B4D1882359F00EC0F7018191CF -:100D20007F018093F10001501109FFEFCF1ADF0A14 -:100D300001151105D9F601C0B82E8B2DDF91CF9189 -:100D40001F910F91FF90EF90DF90CF90BF9008958B -:100D500020914D0230914E022617370748F0611559 -:100D6000710539F42091E8002E772093E80001C046 -:100D7000B9019C0180E034C090914602992309F4A6 -:100D800043C0953009F442C09091E80093FD3AC009 -:100D90009091E80092FD30C09091E80090FF20C053 -:100DA0008091F20090E0F901821B930B05C0219124 -:100DB0002093F100615071099F01280F391F6115BF -:100DC000710519F02830310590F381E028303105A4 -:100DD00009F080E09091E8009E779093E8009F01F1 -:100DE0006115710549F68111C7CF06C08091460291 -:100DF000882351F0853051F08091E80082FFF6CFD2 -:100E000080E0089581E0089582E0089583E00895E8 -:100E10006115710529F42091E8002B772093E800F3 -:100E20009C0121C080914602882381F1853041F1E7 -:100E30008091E80083FD26C08091E80082FFF2CF18 -:100E4000F90107C08091F10081939F016150710900 -:100E500029F09F018091F2008111F4CF8091E80088 -:100E60008B778093E80061157105E1F68091E800C9 -:100E700080FD0AC080914602882341F08530B1F799 -:100E800083E0089581E0089580E0089582E0089568 -:100E900020914D0230914E022617370748F0611518 -:100EA000710539F42091E8002E772093E80001C005 -:100EB000B9019C0180E035C090914602992309F464 -:100EC00044C0953009F443C09091E80093FD3BC0C5 -:100ED0009091E80092FD31C09091E80090FF21C010 -:100EE0008091F20090E0F901821B930B06C02491DF -:100EF0002093F1003196615071099C012E0F3F1F24 -:100F00006115710519F02830310588F381E028302A -:100F1000310509F080E09091E8009E779093E80019 -:100F20009F016115710541F68111C6CF06C0809100 -:100F30004602882351F0853051F08091E80082FF0D -:100F4000F6CF80E0089581E0089582E0089583E07F -:100F50000895982F2CC09093E900981739F070915C -:100F6000EC002091ED005091F00003C0242F762F6B -:100F700050E021FD02C09F5F1AC03091EB003E7F20 -:100F80003093EB003091ED003D7F3093ED003091D8 -:100F9000EB0031603093EB007093EC002093ED0098 -:100FA0005093F0002091EE0027FDE5CF07C095306B -:100FB00090F28F708093E90081E0089580E00895B9 -:100FC0000F931F93CF93DF93062FEC0110E02EC0F9 -:100FD0009881911103C01F5F259628C02C81E9815B -:100FE000FA816B81892F8F70853010F080E021C0ED -:100FF000223010F056E001C052E028E030E040E03E -:1010000003C04F5F220F331F2E173F07D0F34295C7 -:10101000407F452B991F9927991F6295660F660F90 -:10102000607C692B96DF8111D6CFE0CF1013D0CF33 -:1010300081E0DF91CF911F910F9108958091470238 -:1010400087FD05C08091E80080FF0EC012C080912E -:10105000E80082FD05C0809146028111F8CF089515 -:101060008091E8008B7708C0809146028111EACF19 -:1010700008958091E8008E778093E800089580912C -:10108000E4009091E50045E62091EC0020FD1FC0B2 -:1010900023C020914602222391F0253091F0209127 -:1010A000EB0025FD10C02091E4003091E5002817E9 -:1010B000390751F34150C90139F784E0089582E0BE -:1010C000089583E0089581E0089580E008952091D7 -:1010D000E80020FFDECFF9CF2091E80022FFD9CF32 -:1010E000F4CF41D043D08091D8008F778093D8003F -:1010F0008091D80080688093D8008091D8008F7D3F -:101100008093D80084E089BD86E089BD09B400FEE3 -:10111000FDCF1092460210924202109244021092A9 -:10112000430242E060E080E014DF8091E1008E7FC6 -:101130008093E1008091E20081608093E2008091E1 -:10114000E20088608093E2008091E0008E7F8093CF -:10115000E0000895E3E6F0E080818E7F808381E007 -:1011600080934502BECF1092E20008951092E100F4 -:1011700008951F920F920FB60F9211242F933F9351 -:101180004F935F936F937F938F939F93AF93BF938F -:10119000EF93FF938091E10082FF0AC08091E2000B -:1011A00082FF06C08091E1008B7F8093E1009CDB91 -:1011B0008091E10080FF17C08091E20080FF13C0A2 -:1011C0008091E2008E7F8093E2008091E200806156 -:1011D0008093E2008091D80080628093D80019BC8F -:1011E00010924602BEDA8091E10084FF2FC0809108 -:1011F000E20084FF2BC084E089BD86E089BD09B48C -:1012000000FEFDCF8091D8008F7D8093D800809123 -:10121000E1008F7E8093E1008091E2008F7E8093D9 -:10122000E2008091E20081608093E20080914202BE -:10123000882311F084E007C08091E30087FF02C09B -:1012400083E001C081E0809346028ADA8091E10068 -:1012500083FF27C08091E20083FF23C08091E100DB -:10126000877F8093E10082E08093460210924202E1 -:101270008091E1008E7F8093E1008091E2008E7F7B -:101280008093E2008091E20080618093E20042E07E -:1012900060E080E05EDE8091F00088608093F00086 -:1012A000B5D1FF91EF91BF91AF919F918F917F91B8 -:1012B0006F915F914F913F912F910F900FBE0F90C3 -:1012C0001F9018951F920F920FB60F9211242F9313 -:1012D0003F934F935F936F937F938F939F93AF93BE -:1012E000BF93CF93EF93FF938091E9008F7090911C -:1012F000EC0090FF02C090E801C090E0C92FC82B1D -:101300001092E9008091F000877F8093F00078943C -:101310001CD01092E9008091F00088608093F0006A -:10132000CF70C093E900FF91EF91CF91BF91AF9142 -:101330009F918F917F916F915F914F913F912F91ED -:101340000F900FBE0F901F9018951F93CF93DF93B0 -:10135000CDB7DEB7AC970FB6F894DEBF0FBECDBFEA -:10136000E7E4F2E08091F100819322E0EF34F207AC -:10137000C9F7B3DA8091E80083FF30C1809147025A -:1013800090914802953009F487C038F49130B1F15A -:1013900070F0933009F022C131C0983009F4F3C0E5 -:1013A000993009F4FFC0963009F018C19BC080380D -:1013B00021F0823809F012C108C080914302909157 -:1013C0004402992389F082600FC080914B02909172 -:1013D0004C028F7099278093E9008091EB0085FB88 -:1013E000882780F91092E9009091E800977F909308 -:1013F000E8008093F1001092F100D0C0882319F02A -:10140000823009F0EBC08F7121F0823009F0E6C024 -:101410000BC080914902813009F0E0C0933009F09F -:1014200080E0809344022FC08091490281112BC03B -:1014300080914B0290914C028F709927009709F48C -:10144000CDC08093E9002091EB0020FF1CC02091CB -:101450004802233021F48091EB00806212C0909109 -:10146000EB0090619093EB0021E030E001C0220F8F -:101470008A95EAF72093EA001092EA008091EB0047 -:1014800088608093EB001092E9008091E800877FEC -:101490008093E800D3DDA2C08111A0C080914902F1 -:1014A00090914A028F779927182F9091E3009078B6 -:1014B000982B9093E3008091E800877F8093E80069 -:1014C000BDDD8091E80080FFFCCF8091E300806863 -:1014D0008093E300112311F083E001C082E0809348 -:1014E00046027CC08058823008F078C08091490262 -:1014F00090914A028C3D23E0920771F583E08A8344 -:101500008AE289834FB7F894DE01139620E03EE02B -:1015100051E2E32FF0E050935700E49120FF03C025 -:10152000E295EF703F5FEF708E2F90E0EA3010F0A1 -:10153000C79601C0C0968D939D932F5F243149F7C4 -:101540004FBF8091E800877F8093E8006AE270E0F7 -:10155000CE010196FDDB11C0AE01455D5F4F60918C -:101560004B02F3D90097D1F12091E800277F209317 -:10157000E800BC018BA59CA58BDC8091E8008B77F3 -:101580008093E8002BC0803849F58091E800877F80 -:101590008093E800809142028093F1008091E800FE -:1015A0008E7776CF81111AC0909149029230B0F4B3 -:1015B0008091E800877F8093E800909342023EDDAF -:1015C00080914202811104C08091E30087FF02C034 -:1015D00084E001C081E080934602C4D88091E80095 -:1015E00083FF0AC08091E800877F8093E8008091A4 -:1015F000EB0080628093EB00AC960FB6F894DEBFF0 -:101600000FBECDBFDF91CF911F9108950895CF9365 -:10161000809146028823A9F08091E9008F70909113 -:10162000EC0090FF02C090E801C090E0C92FC82BE9 -:101630001092E9008091E80083FD87DECF70C093AF -:10164000E900CF910895CF93DF93EC014096FC0120 -:101650008BE0DF011D928A95E9F782E08C83898710 -:1016600083E08E8761E0CE010196AADC882361F0D9 -:1016700061E0CE010696A4DC882331F061E0CE0162 -:101680000B96DF91CF919CCC80E0DF91CF910895B4 -:10169000CF93C62F209146022430F1F4FC014489F7 -:1016A000558966897789452B462B472BA9F081817F -:1016B0008F708093E9008091E80085FF04C0C0939B -:1016C000F10080E00AC08091E8008E778093E80006 -:1016D000D6DC8823A1F301C082E0CF910895209148 -:1016E0004602243029F5FC014489558966897789A9 -:1016F000452B462B472BE1F081818F708093E900C9 -:101700008091F200811102C080E008959091E8007C -:101710008091E8008E778093E80095FDF5CFAFDCEF -:10172000811107C09091E8009E779093E80008959A -:1017300082E0089520914602243089F4FC01448916 -:10174000558966897789452B462B472B41F02181A6 -:101750002F702093E9002091E80020FDC0CF08956C -:1017600020914602243019F02FEF3FEF24C0FC01F6 -:101770004489558966897789452B462B472BA1F3E8 -:1017800086818F708093E9008091E80082FFECCF22 -:101790008091F200882321F02091F10030E002C016 -:1017A0002FEF3FEF8091F200811105C08091E8009A -:1017B0008B778093E800C90108950895CF93DF9354 -:1017C000EC018091E80083FFA9C0888190E020911E -:1017D0004B0230914C022817390709F09FC08091C5 -:1017E0004802813261F020F4803209F097C03DC098 -:1017F000823209F46EC0833209F090C07FC08091BC -:101800004702813A09F08AC08091E800877F80937F -:10181000E8008091E80080FFFCCF4C895D896E89EB -:101820007F894093F100BB27A72F962F852F8093A8 -:10183000F100CB01AA27BB278093F100472F552742 -:10184000662777274093F100888D8093F100898D7A -:101850008093F1008A8D8093F1008091E8008E776B -:101860008093E800DF91CF91E9CB809147028132EC -:1018700009F054C08091E800877F8093E80005C09C -:1018800080914602882309F449C08091E80082FFD4 -:10189000F7CF3091F1002091F1009091F10080910B -:1018A000F1003C8B2D8B9E8B8F8B8091F100888F6C -:1018B0008091F100898F8091F1008A8F8091E800FA -:1018C0008B778093E800BADBCE01DF91CF910C9447 -:1018D000CE0380914702813209F58091E800877F2D -:1018E0008093E800ABDB8091490290914A02998B8A -:1018F000888BCE01DF91CF910C94620480914702D6 -:10190000813261F48091E800877F8093E80096DB64 -:1019100060914902CE01DF91CF914FCFDF91CF91FE -:1019200008956F927F928F929F92AF92BF92CF92C3 -:10193000DF92EF92FF920F931F93CF93DF9300D02C -:101940001F92CDB7DEB77C01ADB6BEB68091E80080 -:1019500083FF07C1F701808190E020914B02309115 -:101960004C022817390709F0FCC0809148028330E7 -:1019700009F49EC030F4813071F0823009F0F1C07A -:10198000D4C08A3009F4B9C08B3009F4A2C08930C0 -:1019900009F0E7C04CC080914702813A09F0E1C0EC -:1019A0008DB69EB61A8219828091490210914A0220 -:1019B0008B83F70140858DB79EB7841B91090FB6C5 -:1019C000F8949EBF0FBE8DBFCDB6DEB6EFEFCE1A38 -:1019D000DE0A360150E060E070E0C601EAD1412F36 -:1019E00041508E010F5F1F4F9601BE016D5F7F4F0B -:1019F000C7010E948004F701268137812115310536 -:101A000029F0408550E0B601C901CAD11092E90021 -:101A10008091E800877F8093E80069817A81C30123 -:101A200097D98091E8008B778093E80039C0809146 -:101A30004702813209F095C08DB69EB600914D02E5 -:101A400010914E027090490260904A028DB79EB785 -:101A5000801B910B0FB6F8949EBF0FBE8DBFCDB605 -:101A6000DEB6EFEFCE1ADE0A8091E800877F809322 -:101A7000E800B801C601CCD98091E8008E77809348 -:101A8000E80021E0711001C020E030E0021B130BE0 -:101A90002C0D3D1D462D4150672DC7010E94A40409 -:101AA000882D992D0FB6F8949EBF0FBE8DBF59C0DB -:101AB00080914702813A09F054C08091E800877F05 -:101AC0008093E8008091E80080FFFCCFF7018185DA -:101AD00040C080914702813209F043C08091E80004 -:101AE000877F8093E800AADA9091490281E0911102 -:101AF00001C080E0F701818734C0809147028132C4 -:101B000081F58091E800877F8093E80097DA8091E3 -:101B1000490290914A02882736E0969587953A9532 -:101B2000E1F7F701958784871CC080914702813ACD -:101B3000C1F48091E800877F8093E8008091E800FD -:101B400080FFFCCFF70184859585969587959695BE -:101B500087958093F1008091E8008E778093E8006C -:101B60006DDA0FB6F894BEBE0FBEADBE0F900F90EB -:101B70000F90DF91CF911F910F91FF90EF90DF9029 -:101B8000CF90BF90AF909F908F907F906F9008956F -:101B90009C01275F3F4FF90127E0DF011D922A9545 -:101BA000E9F721E0FC01218724EF31E03587248724 -:101BB00023E0248361E0019603CA4F925F926F9203 -:101BC0007F928F929F92AF92BF92CF92DF92EF92CD -:101BD000FF920F931F93CF93DF9300D01F92CDB747 -:101BE000DEB77C01ADB6BEB680914602843009F006 -:101BF0008FC08091E4009091E500F7012285338544 -:101C00002817390709F484C081818F708093E90017 -:101C10008091E80085FF7CC06DB67EB640858DB7AB -:101C20009EB7841B91090FB6F8949EBF0FBE8DBF5F -:101C3000CDB6DEB6EFEFCE1ADE0A1B821A8219820B -:101C4000460150E060E070E0C601B3D08E010F5F46 -:101C50001F4F960140E0BE016D5F7F4FC7010E949C -:101C60008004582EF70184859585892B31F001E099 -:101C700010E086859785892B11F000E010E0F701D0 -:101C8000C680D780C114D10489F049815A81B60138 -:101C9000C40179D044244394009709F4412CF701FE -:101CA000408550E0B401C6017BD001C0412C898140 -:101CB0009A81892BF9F0511004C0411002C000FF35 -:101CC00019C0F701848595859787868781818F70F4 -:101CD0008093E9008B8181118093F10069817A8181 -:101CE00040E050E0C4010E945B068091E8008E77DE -:101CF0008093E8008091E4009091E500F7019387DC -:101D00008287862D972D0FB6F8949EBF0FBE8DBF8C -:101D10000FB6F894BEBE0FBEADBE0F900F900F90E1 -:101D2000DF91CF911F910F91FF90EF90DF90CF90B7 -:101D3000BF90AF909F908F907F906F905F904F90EB -:101D40000895A1E21A2EAA1BBB1BFD010DC0AA1FFC -:101D5000BB1FEE1FFF1FA217B307E407F50720F014 -:101D6000A21BB30BE40BF50B661F771F881F991F8F -:101D70001A9469F760957095809590959B01AC01D8 -:101D8000BD01CF010895FB01DC0104C08D910190DC -:101D9000801921F441505040C8F7881B990B0895D1 -:101DA000FB01DC0102C001900D9241505040D8F778 -:101DB0000895DC0101C06D9341505040E0F7089553 -:041DC000F894FFCFC5 -:101DC400028120000001000011000000000000005A -:101DD400008340000001044000000182080000016B -:0E1DE400000000000000000000000008302099 -:00000001FF diff --git a/plugins/KeyboardioHID/Firmwares/Hoodloader1_5.hex b/plugins/KeyboardioHID/Firmwares/Hoodloader1_5.hex deleted file mode 100644 index 97e84f4511..0000000000 --- a/plugins/KeyboardioHID/Firmwares/Hoodloader1_5.hex +++ /dev/null @@ -1,466 +0,0 @@ -:1000000073C100008DC100008BC1000089C10000D8 -:1000100087C1000085C1000083C1000081C10000CC -:100020007FC100007DC100007BC100000C94270847 -:100030000C94D00875C1000073C1000071C10000AC -:100040006FC100006DC100006BC1000069C10000FC -:1000500067C1000065C1000063C1000009C2000063 -:100060005FC100005DC100005BC1000059C100001C -:1000700057C1000030034100720064007500690040 -:100080006E006F00200048006F006F0064006C007D -:100090006F0061006400650072002000420065008E -:1000A00074006100000012034E00690063006F00DD -:1000B00048006F006F006400000004030904090297 -:1000C0005F00030100C032080B00020202010009B8 -:1000D00004000001020201000524001001042402B2 -:1000E000060524060001070582030800FF09040134 -:1000F00000020A0000000705040240000107058312 -:10010000024000010904020001030000000921115E -:1001100001000122B801070581032000011201102E -:1001200001EF020108EB03686E15000102DC010516 -:10013000010902A1010901A100850105091901298F -:10014000051500250195057501810295017503814D -:100150000305010930093109381581257F75089596 -:10016000038106C0C005010906A101850205071922 -:10017000E029E715002501750195088102950175B3 -:1001800008810395067508150025650507190029DE -:1001900065810005081901290595057501910295EC -:1001A0000175039103C006C0FF0A000CA10185037D -:1001B0007508150026FF0095400901810295400948 -:1001C000029102C0050C0901A1018504150026FF5A -:1001D000FF19002AFFFF950475108100C005010971 -:1001E00080A1018505150026FF00190029FF950152 -:1001F00075088100C005010905A1018506050919D9 -:10020000012920150025017501952081020501A114 -:10021000000930093109320933093409351500273D -:10022000FFFF0000751095068102C005010939091C -:100230003915012508950275048102C005010905DB -:10024000A10185070509190129201500250175015E -:10025000952081020501A1000930093109320933D5 -:1002600009340935150027FFFF0000751095068138 -:1002700002C0093909391501250895027504810262 -:10028000C005010904A1018508A10005091901297A -:100290000215002501750195028102050109300949 -:1002A00031150026FF03750A95028102750295013A -:1002B0008103C0C005010904A1018509A100050948 -:1002C0001901290215002501750195028102050118 -:1002D00009300931150026FF03750A950281027560 -:1002E0000295018103C0C00011241FBECFEFD2E0F0 -:1002F000DEBFCDBF11E0A0E0B1E0EEEDFCE102C059 -:1003000005900D92AE32B107D9F712E0AEE2B1E03E -:1003100001C01D92A434B107E1F7F8D20C946D0E20 -:100320006FCECF93DF9384B7877F84BF28E10FB66A -:10033000F89420936000109260000FBE80E190E07E -:100340009093CD008093CC00CAECD0E096E09883E7 -:10035000A8ECB0E082E08C93E9ECF0E02083539AC3 -:100360005A9A5B9A10821C92188298838C9388E91F -:1003700080835B988AB180638AB98BB180638BB9C3 -:1003800057D684E085BD5F9A579A84B184B9229884 -:100390002A9ADF91CF9108950895089580E091E021 -:1003A0000E94550D80E191E00E94920AE2EEF0E099 -:1003B00080818460808308951F93CF93DF93EC0145 -:1003C000E98DE150E23028F4F0E0E55DFE4F108168 -:1003D00001C010E0888D823009F418608A8D873062 -:1003E00031F0883031F0863029F4126003C0146097 -:1003F00001C016605B9A1092C9001092C80010925A -:10040000CA002C893D894E895F89211581EE380704 -:100410004105510579F0CA01B901969587957795FF -:10042000679560587B47814E9F4F0E942E0E21504A -:10043000310902C020E130E03093CD002093CC00A0 -:100440001093CA008C899D89AE89BF898115914E10 -:10045000A105B10511F480E001C082E08093C800DD -:1004600088E98093C9005B98DF91CF911F9108952F -:100470001F920F920FB60F9211242F933F938F93D9 -:100480009F93AF93BF93EF93FF938091CE00909192 -:100490002E019430F9F090913B029430D9F4EFE2C0 -:1004A000F1E0A081B1818C9380819181019691834B -:1004B0008083268137818217930721F48481958177 -:1004C000918380832FB7F8948285938501969387D3 -:1004D00082872FBFFF91EF91BF91AF919F918F9135 -:1004E0003F912F910F900FBE0F901F901895FC0118 -:1004F000208920FF02C05F9808955F9A8BB18063C6 -:100500008BB9089580E191E00E946B0B80E091E04F -:100510000C941E0C80910E0190910F01009729F010 -:10052000019790930F0180930E010895EF92FF922F -:100530000F931F93CF93DF937B01C901CEEBD1E0E3 -:100540004881E0ECF1E050E0BF010E945D0EEDEB70 -:10055000F1E08081D7018C938881D8018C9311962A -:100560001C9210821092BF01188281E0DF91CF911E -:100570001F910F91FF90EF90089508951092DD0163 -:100580001092D1010895462F209111012F702093D0 -:10059000E9002091E80020FFFCCF2091200120FFFE -:1005A00005C050E0BC0180E191E0E1C70895CF9221 -:1005B000DF92EF92FF920F931F93FA018B01009548 -:1005C000109520E030E0980111270027AB0160E092 -:1005D00070E0042B152B262B372B4CE150E097E0D5 -:1005E00068017901042E04C0F694E794D794C79467 -:1005F0000A94D2F76C2D683028F0973059F4C082F5 -:1006000096E008C0C0829150C11004C04750510903 -:10061000923031F7492F425013C0DF01A40FB11DB2 -:1006200068017901E894C7F8DD24EE24FF24CC9218 -:10063000B7E03695279517950795BA95D1F74150AC -:100640004111EBCF492F50E09A01A3E0220F331F55 -:10065000AA95E1F7206C3F6F3081322B3083E40F95 -:10066000F51F319781508F7380688083892F1F9188 -:100670000F91FF90EF90DF90CF900895CF93DF938D -:1006800000D000D000D0CDB7DEB76091BD016623A9 -:1006900079F08091BF0181110BC070E07160AE01F3 -:1006A0004F5F5F4F81E083DF682FCE0101966BDFE4 -:1006B0001092BD0126960FB6F894DEBF0FBECDBFD7 -:1006C000DF91CF9108950F931F93982F4091DD01F3 -:1006D000E42FF0E0E952FE4F80838091DD018F5FCF -:1006E0008093DD01892F807C803809F444C0803CF0 -:1006F00009F05FC0292F287326952695269522306C -:1007000008F477C0273079F4492F4F7050E060E04B -:1007100070E04093D2015093D3016093D401709361 -:10072000D50115E00FC0892F877090E0A0E0B0E000 -:100730008093D2019093D301A093D401B093D501BB -:10074000122F11508091D101882391F097DF609191 -:10075000DD01615087ED91E016DFE091DD01F0E011 -:10076000EA52FE4F80818093D70181E08093DD01C2 -:100770001093D10145C08091D1018130D1F5009114 -:10078000D2011091D3012091D4013091D501A9015A -:100790006627772722273327402751276227732789 -:1007A0004F3F5F4F6105710521F5892F8F738F5F73 -:1007B00028C08091D1018230E0F081508093D10136 -:1007C0004091D2015091D3016091D4017091D50133 -:1007D00027E0440F551F661F771F2A95D1F7492B35 -:1007E0004093D2015093D3016093D4017093D5010B -:1007F00007C044DF6091DD0187ED91E0C4DEBEDE1D -:1008000080E01F910F910895CF93DF931F92CDB792 -:10081000DEB759DF882309F475C0813089F59091DE -:10082000D301913069F5898329DF9091D2019093AA -:10083000BD011092BF0121E1E0ECF1E0DF01322FB8 -:100840001D923A95E9F789819530A9F038F49230F4 -:1008500061F0943051F0913089F405C0983038F04F -:100860009A3060F407C084E006C088E004C020939A -:10087000BE0144C083E08093BE0140C0FFDE3EC0A5 -:100880009091BD019923A1F16091BF01462F50E0E5 -:1008900090E09A012E5F3F4F359527952F5F3F4F90 -:1008A0008217930729F5FA01E054FE4F8091D20197 -:1008B0008083E62FEF5FE093BF018091BE018E172A -:1008C00049F0F0E0E054FE4F9091D30190836E5FC9 -:1008D0006093BF019091BF01891310C004C080E0F4 -:1008E00091E00E946A0D8091BD018111F8CF06C090 -:1008F000C5DE6091DD0187ED91E045DE0F90DF916F -:10090000CF913CCE0F90DF91CF9108950ADD1092E8 -:100910002E01EFE2F1E02FB7F8948BE391E09183A1 -:10092000808393838283958384838BEB91E0978389 -:10093000868380E890E091878087138612862FBF98 -:100940007894E2E08E2E0FE211E0CBE3D1E0FBEBF6 -:10095000EF2EF1E0FF2EA0E8CA2ED12CB3E09B2EA3 -:100960008091240190912501A0912601B091270149 -:1009700020912E010097A105B10529F08115924C17 -:10098000A140B10529F52430B9F4F8018FB7F894E6 -:10099000D183C083D383C283D583C483F782E682A5 -:1009A000D186C086138612868FBF1092BB0110922B -:1009B000BC018BB180638BB91A9B11C080912E0151 -:1009C000823019F0DBDD1092BD0180922E0109C04A -:1009D000243029F410922F011092300102C010929D -:1009E0002E0180E191E049D697FD09C05C98909274 -:1009F000BC019091C80095FFFCCF8093CE002FB72B -:100A0000F8948091390190913A012FBF009719F421 -:100A1000A89949C068C05D989092BB0120911101CE -:100A20002F702093E9002091E80020FFF1CF80345F -:100A3000910510F08FE390E0782EA12CB12C30C0FE -:100A400080912E01882361F0F801A281B3818D91FC -:100A5000B383A28326813781A217B30781F40BC029 -:100A6000E0913101F0913201608180E191E09DD50A -:100A7000882351F3CDCF24813581338322839FB7DF -:100A8000F8942285338521503109338722879FBF0F -:100A900090912E01923009F4B7DE8FEFA81AB80AB0 -:100AA0007A10CECFB5CFA89A8091BB01882389F068 -:100AB00081508093BB0181110CC080912E01823046 -:100AC00039F4DCDD6091DD0187ED91E05CDD56DD20 -:100AD0005D9A8091BC01882331F081508093BC01E4 -:100AE000811101C05C9A80E191E0B1D5FFD438CF8B -:100AF000292F332723303105B1F04CF42130310553 -:100B000009F439C02230310509F03AC007C021325A -:100B1000310539F12232310549F132C0EFE5F0E01B -:100B20008EEB90E031C099278130910561F08230E1 -:100B3000910581F0892B21F5EAEBF0E0E491F0E0FA -:100B40008AEB90E021C0E6EAF0E0E491F0E086EA8A -:100B500090E01AC0E4E7F0E0E491F0E084E790E090 -:100B600013C0E9E0F0E08DE091E00EC0E8EBF1E0C9 -:100B70008FE291E009C0E2E1F0E08DE191E004C094 -:100B8000E0E0F0E080E090E0DA018D939C93CF010B -:100B90000895BF92CF92DF92EF92FF920F931F932F -:100BA000CF93DF937C018B01EA01D7D1B82E81115D -:100BB00032C0209731F028813981021B130BE20EDD -:100BC000F31EC12CD12C22C08091E80085FD14C0F9 -:100BD0008091E8008E778093E800209749F0888123 -:100BE00099818C0D9D1D9983888325E0B22E13C0B9 -:100BF000B4D1882359F00EC0F70181917F01809311 -:100C0000F10001501109FFEFCF1ADF0A011511059C -:100C1000D9F601C0B82E8B2DDF91CF911F910F9186 -:100C2000FF90EF90DF90CF90BF9008952091420207 -:100C3000309143022617370748F06115710539F4E2 -:100C40002091E8002E772093E80001C0B9019C01B3 -:100C500080E034C090913B02992309F443C0953061 -:100C600009F442C09091E80093FD3AC09091E800E9 -:100C700092FD30C09091E80090FF20C08091F2007A -:100C800090E0F901821B930B05C021912093F100A4 -:100C9000615071099F01280F391F6115710519F005 -:100CA0002830310590F381E02830310509F080E0EB -:100CB0009091E8009E779093E8009F01611571057F -:100CC00049F68111C7CF06C080913B02882351F0BD -:100CD000853051F08091E80082FFF6CF80E00895E2 -:100CE00081E0089582E0089583E00895611571051B -:100CF00029F42091E8002B772093E8009C0121C083 -:100D000080913B02882381F1853041F18091E80098 -:100D100083FD26C08091E80082FFF2CFF90107C071 -:100D20008091F10081939F016150710929F09F0129 -:100D30008091F2008111F4CF8091E8008B7780934D -:100D4000E80061157105E1F68091E80080FD0AC0B8 -:100D500080913B02882341F08530B1F783E008950C -:100D600081E0089580E0089582E008952091420294 -:100D7000309143022617370748F06115710539F4A1 -:100D80002091E8002E772093E80001C0B9019C0172 -:100D900080E035C090913B02992309F444C095301E -:100DA00009F443C09091E80093FD3BC09091E800A6 -:100DB00092FD31C09091E80090FF21C08091F20037 -:100DC00090E0F901821B930B06C024912093F1005F -:100DD0003196615071099C012E0F3F1F61157105FD -:100DE00019F02830310588F381E02830310509F009 -:100DF00080E09091E8009E779093E8009F01611554 -:100E0000710541F68111C6CF06C080913B0288234F -:100E100051F0853051F08091E80082FFF6CF80E0FC -:100E2000089581E0089582E0089583E00895982F61 -:100E30002CC09093E900981739F07091EC00209144 -:100E4000ED005091F00003C0242F762F50E021FDDB -:100E500002C09F5F1AC03091EB003E7F3093EB00E1 -:100E60003091ED003D7F3093ED003091EB0031602B -:100E70003093EB007093EC002093ED005093F00062 -:100E80002091EE0027FDE5CF07C0953090F28F70DE -:100E90008093E90081E0089580E008950F931F9307 -:100EA000CF93DF93062FEC0110E02EC098819111B3 -:100EB00003C01F5F259628C02C81E981FA816B81D0 -:100EC000892F8F70853010F080E021C0223010F023 -:100ED00056E001C052E028E030E040E003C04F5F40 -:100EE000220F331F2E173F07D0F34295407F452B2B -:100EF000991F9927991F6295660F660F607C692B71 -:100F000096DF8111D6CFE0CF1013D0CF81E0DF91F3 -:100F1000CF911F910F91089580913C0287FD05C0EC -:100F20008091E80080FF0EC012C08091E80082FD31 -:100F300005C080913B028111F8CF08958091E800AF -:100F40008B7708C080913B028111EACF0895809190 -:100F5000E8008E778093E80008958091E4009091F6 -:100F6000E50045E62091EC0020FD1FC023C0209144 -:100F70003B02222391F0253091F02091EB0025FDDA -:100F800010C02091E4003091E5002817390751F393 -:100F90004150C90139F784E0089582E0089583E063 -:100FA000089581E0089580E008952091E80020FFF1 -:100FB000DECFF9CF2091E80022FFD9CFF4CF41D086 -:100FC00043D08091D8008F778093D8008091D8004B -:100FD00080688093D8008091D8008F7D8093D8005E -:100FE00084E089BD86E089BD09B400FEFDCF109282 -:100FF0003B0210923702109239021092380242E0FE -:1010000060E080E014DF8091E1008E7F8093E1005A -:101010008091E20081608093E2008091E20088602C -:101020008093E2008091E0008E7F8093E00008953D -:10103000E3E6F0E080818E7F808381E080933A0256 -:10104000BECF1092E20008951092E10008951F9221 -:101050000F920FB60F9211242F933F934F935F93EC -:101060006F937F938F939F93AF93BF93EF93FF9370 -:101070008091E10082FF0AC08091E20082FF06C0F9 -:101080008091E1008B7F8093E10044DA8091E10060 -:1010900080FF17C08091E20080FF13C08091E200C2 -:1010A0008E7F8093E2008091E20080618093E20075 -:1010B0008091D80080628093D80019BC10923B02C6 -:1010C0006CD98091E10084FF2FC08091E20084FF01 -:1010D0002BC084E089BD86E089BD09B400FEFDCF48 -:1010E0008091D8008F7D8093D8008091E1008F7E21 -:1010F0008093E1008091E2008F7E8093E2008091F6 -:10110000E20081608093E20080913702882311F031 -:1011100084E007C08091E30087FF02C083E001C044 -:1011200081E080933B0238D98091E10083FF27C0A2 -:101130008091E20083FF23C08091E100877F80934C -:10114000E10082E080933B02109237028091E1003F -:101150008E7F8093E1008091E2008E7F8093E20099 -:101160008091E20080618093E20042E060E080E0F4 -:101170005EDE8091F00088608093F000B6D1FF9130 -:10118000EF91BF91AF919F918F917F916F915F91FF -:101190004F913F912F910F900FBE0F901F90189578 -:1011A0001F920F920FB60F9211242F933F934F93DC -:1011B0005F936F937F938F939F93AF93BF93CF93DF -:1011C000EF93FF938091E9008F709091EC0090FF76 -:1011D00002C090E801C090E0C92FC82B1092E9002E -:1011E0008091F000877F8093F00078941CD010925B -:1011F000E9008091F00088608093F000CF70C09388 -:10120000E900FF91EF91CF91BF91AF919F918F91A5 -:101210007F916F915F914F913F912F910F900FBEF2 -:101220000F901F9018951F93CF93DF93CDB7DEB724 -:10123000AC970FB6F894DEBF0FBECDBFECE3F2E083 -:101240008091F100819322E0E434F207C9F75AD982 -:101250008091E80083FF31C180913C0290913D0272 -:10126000953009F487C038F49130B1F170F09330C3 -:1012700009F023C131C0983009F4F3C0993009F462 -:10128000FFC0963009F019C19BC0803821F0823828 -:1012900009F013C108C08091380290913902992356 -:1012A00089F082600FC080914002909141028F705E -:1012B00099278093E9008091EB0085FB882780F9CE -:1012C0001092E9009091E800977F9093E800809356 -:1012D000F1001092F100D0C0882319F0823009F09B -:1012E000ECC08F7121F0823009F0E7C00BC0809113 -:1012F0003E02813009F0E1C0933009F080E0809334 -:1013000039022FC080913E0281112BC08091400292 -:10131000909141028F709927009709F4CEC0809375 -:10132000E9002091EB0020FF1CC020913D022330FA -:1013300021F48091EB00806212C09091EB009061EB -:101340009093EB0021E030E001C0220F8A95EAF78C -:101350002093EA001092EA008091EB00886080936D -:10136000EB001092E9008091E800877F8093E8000D -:10137000D3DDA3C08111A1C080913E0290913F02B4 -:101380008F779927182F9091E3009078982B90935E -:10139000E3008091E800877F8093E800BDDD8091C5 -:1013A000E80080FFFCCF8091E30080688093E30039 -:1013B000112311F083E001C082E080933B027DC0E5 -:1013C0008058823008F079C080913E0290913F02AF -:1013D0008C3D23E0920771F583E08A838AE289835A -:1013E0004FB7F894DE01139620E03EE051E2E32F80 -:1013F000F0E050935700E49120FF03C0E295EF70B6 -:101400003F5FEF708E2F90E0EA3010F0C79601C07A -:10141000C0968D939D932F5F243149F74FBF8091E4 -:10142000E800877F8093E8006AE270E0CE010196D1 -:10143000FDDB11C0AE01455D5F4F6091400258DB9E -:101440000097D9F12091E800277F2093E800BC01A4 -:101450008BA59CA58BDC8091E8008B778093E800BE -:101460002CC0803851F58091E800877F8093E80098 -:10147000809137028093F1008091E8008E7776CFDB -:1014800081111BC090913E029230B8F48091E80027 -:10149000877F8093E800909337023EDD809137028A -:1014A000811104C08091E30087FF02C084E001C085 -:1014B00081E080933B020E94CE018091E80083FF8F -:1014C0000AC08091E800877F8093E8008091EB005C -:1014D00080628093EB00AC960FB6F894DEBF0FBE2F -:1014E000CDBFDF91CF911F9108950895CF93809143 -:1014F0003B028823A9F08091E9008F709091EC0065 -:1015000090FF02C090E801C090E0C92FC82B109254 -:10151000E9008091E80083FD86DECF70C093E9008A -:10152000CF910895CF93DF93EC014096FC018BE0BF -:10153000DF011D928A95E9F782E08C83898783E039 -:101540008E8761E0CE010196A9DC882361F061E01D -:10155000CE010696A3DC882331F061E0CE010B9624 -:10156000DF91CF919BCC80E0DF91CF9108950F93D5 -:101570001F93FC01CB01BA0120913B02243089F476 -:101580000489158926893789012B022B032B49F001 -:1015900021812F702093E90040E050E01F910F91CE -:1015A000F8CA82E01F910F910895CF93C62F209122 -:1015B0003B022430F1F4FC0144895589668977891E -:1015C000452B462B472BA9F081818F708093E90032 -:1015D0008091E80085FF04C0C093F10080E00AC05C -:1015E0008091E8008E778093E800B7DC8823A1F330 -:1015F00001C082E0CF91089520913B02243029F56B -:10160000FC014489558966897789452B462B472BF0 -:10161000E1F081818F708093E9008091F200811167 -:1016200002C080E008959091E8008091E8008E77F4 -:101630008093E80095FDF5CF90DC811107C0909173 -:10164000E8009E779093E800089582E00895209145 -:101650003B02243089F4FC014489558966897789E5 -:10166000452B462B472B41F021812F702093E90019 -:101670002091E80020FDC0CF089520913B02243046 -:1016800019F02FEF3FEF24C0FC014489558966898A -:101690007789452B462B472BA1F386818F7080934A -:1016A000E9008091E80082FFECCF8091F20088236E -:1016B00021F02091F10030E002C02FEF3FEF809148 -:1016C000F200811105C08091E8008B778093E800DB -:1016D000C90108950895CF93DF93EC018091E8004C -:1016E00083FFA9C0888190E020914002309141029F -:1016F0002817390709F09FC080913D02813261F0BF -:1017000020F4803209F097C03DC0823209F46EC0E7 -:10171000833209F090C07FC080913C02813A09F089 -:101720008AC08091E800877F8093E8008091E8007C -:1017300080FFFCCF4C895D896E897F894093F100E1 -:10174000BB27A72F962F852F8093F100CB01AA27C7 -:10175000BB278093F100472F5527662777274093B3 -:10176000F100888D8093F100898D8093F1008A8D3E -:101770008093F1008091E8008E778093E800DF91FC -:10178000CF91CACB80913C02813209F054C0809144 -:10179000E800877F8093E80005C080913B028823A2 -:1017A00009F449C08091E80082FFF7CF3091F10041 -:1017B0002091F1009091F1008091F1003C8B2D8BF4 -:1017C0009E8B8F8B8091F100888F8091F100898FA3 -:1017D0008091F1008A8F8091E8008B778093E800F8 -:1017E0009BDBCE01DF91CF910C94DC0180913C0218 -:1017F000813209F58091E800877F8093E8008CDBD7 -:1018000080913E0290913F02998B888BCE01DF91AF -:10181000CF910C94770280913C02813261F48091E7 -:10182000E800877F8093E80077DB60913E02CE017D -:10183000DF91CF914FCFDF91CF9108956F927F923B -:101840008F929F92AF92BF92CF92DF92EF92FF92D0 -:101850000F931F93CF93DF9300D01F92CDB7DEB7C6 -:101860007C01ADB6BEB68091E80083FF07C1F701E9 -:10187000808190E020914002309141022817390781 -:1018800009F0FCC080913D02833009F49EC030F421 -:10189000813071F0823009F0F1C0D4C08A3009F48F -:1018A000B9C08B3009F4A2C0893009F0E7C04CC040 -:1018B00080913C02813A09F0E1C08DB69EB61A8251 -:1018C000198280913E0210913F028B83F70140857F -:1018D0008DB79EB7841B91090FB6F8949EBF0FBEBB -:1018E0008DBFCDB6DEB6EFEFCE1ADE0A360150E080 -:1018F00060E070E0C601EAD1412F41508E010F5FD8 -:101900001F4F9601BE016D5F7F4FC7010E94960277 -:10191000F701268137812115310529F0408550E0F6 -:10192000B601C901CAD11092E9008091E800877F11 -:101930008093E80069817A81C30178D98091E800B9 -:101940008B778093E80039C080913C02813209F0A6 -:1019500095C08DB69EB600914202109143027090E0 -:101960003E0260903F028DB79EB7801B910B0FB671 -:10197000F8949EBF0FBE8DBFCDB6DEB6EFEFCE1A88 -:10198000DE0A8091E800877F8093E800B801C601F5 -:10199000ADD98091E8008E778093E80021E0711046 -:1019A00001C020E030E0021B130B2C0D3D1D462D25 -:1019B0004150672DC7010E94BD02882D992D0FB699 -:1019C000F8949EBF0FBE8DBF59C080913C02813AF2 -:1019D00009F054C08091E800877F8093E8008091EF -:1019E000E80080FFFCCFF701818540C080913C0278 -:1019F000813209F043C08091E800877F8093E8003E -:101A00008BDA90913E0281E0911101C080E0F701F4 -:101A1000818734C080913C02813281F58091E80059 -:101A2000877F8093E80078DA80913E0290913F02B0 -:101A3000882736E0969587953A95E1F7F7019587DF -:101A400084871CC080913C02813AC1F48091E800F7 -:101A5000877F8093E8008091E80080FFFCCFF7014A -:101A60008485958596958795969587958093F100C1 -:101A70008091E8008E778093E8004EDA0FB6F894F4 -:101A8000BEBE0FBEADBE0F900F900F90DF91CF91F5 -:101A90001F910F91FF90EF90DF90CF90BF90AF908C -:101AA0009F908F907F906F9008959C01275F3F4F8C -:101AB000F90127E0DF011D922A95E9F721E0FC01F9 -:101AC000218724EF31E03587248723E0248361E0F8 -:101AD0000196E4C94F925F926F927F928F929F928C -:101AE000AF92BF92CF92DF92EF92FF920F931F932C -:101AF000CF93DF9300D01F92CDB7DEB77C01ADB698 -:101B0000BEB680913B02843009F08FC08091E40022 -:101B10009091E500F701228533852817390709F4EC -:101B200084C081818F708093E9008091E80085FFF7 -:101B30007CC06DB67EB640858DB79EB7841B91097B -:101B40000FB6F8949EBF0FBE8DBFCDB6DEB6EFEFD9 -:101B5000CE1ADE0A1B821A821982460150E060E02A -:101B600070E0C601B3D08E010F5F1F4F960140E0B9 -:101B7000BE016D5F7F4FC7010E949602582EF7018C -:101B800084859585892B31F001E010E08685978565 -:101B9000892B11F000E010E0F701C680D780C11456 -:101BA000D10489F049815A81B601C40179D0442415 -:101BB0004394009709F4412CF701408550E0B401AB -:101BC000C6017BD001C0412C89819A81892BF9F013 -:101BD000511004C0411002C000FF19C0F7018485F4 -:101BE00095859787868781818F708093E9008B81A7 -:101BF00081118093F10069817A8140E050E0C40155 -:101C00000E94C9058091E8008E778093E80080915A -:101C1000E4009091E500F70193878287862D972D48 -:101C20000FB6F8949EBF0FBE8DBF0FB6F894BEBE20 -:101C30000FBEADBE0F900F900F90DF91CF911F910F -:101C40000F91FF90EF90DF90CF90BF90AF909F905B -:101C50008F907F906F905F904F900895A1E21A2E21 -:101C6000AA1BBB1BFD010DC0AA1FBB1FEE1FFF1F40 -:101C7000A217B307E407F50720F0A21BB30BE40B90 -:101C8000F50B661F771F881F991F1A9469F76095D7 -:101C90007095809590959B01AC01BD01CF01089591 -:101CA000FB01DC0104C08D910190801921F44150A9 -:101CB0005040C8F7881B990B0895FB01DC0102C056 -:101CC00001900D9241505040D8F70895DC0101C0B9 -:0E1CD0006D9341505040E0F70895F894FFCF17 -:101CDE000281200000010000110000000000000041 -:101CEE000083400000010440000001820800000152 -:0E1CFE00000000000000000000000030200088 -:00000001FF diff --git a/plugins/KeyboardioHID/Firmwares/Hoodloader1_6.hex b/plugins/KeyboardioHID/Firmwares/Hoodloader1_6.hex deleted file mode 100644 index 2ed4f7bcd5..0000000000 --- a/plugins/KeyboardioHID/Firmwares/Hoodloader1_6.hex +++ /dev/null @@ -1,474 +0,0 @@ -:1000000073C100008DC100008BC1000089C10000D8 -:1000100087C1000085C1000083C1000081C10000CC -:100020007FC100007DC100007BC100000C94670807 -:100030000C94100975C1000073C1000071C100006B -:100040006FC100006DC100006BC1000069C10000FC -:1000500067C1000065C1000063C1000009C2000063 -:100060005FC100005DC100005BC1000059C100001C -:1000700057C1000030034100720064007500690040 -:100080006E006F00200048006F006F0064006C007D -:100090006F0061006400650072002000420065008E -:1000A00074006100000012034E00690063006F00DD -:1000B00048006F006F006400000004030904090297 -:1000C0005F00030100C032080B00020202010009B8 -:1000D00004000001020201000524001001042402B2 -:1000E000060524060001070582030800FF09040134 -:1000F00000020A0000000705040240000107058312 -:10010000024000010904020001030000000921115E -:1001100001000122B801070581032000011201102E -:1001200001EF020108EB03686E16000102DC010515 -:10013000010902A1010901A100850105091901298F -:10014000051500250195057501810295017503814D -:100150000305010930093109381581257F75089596 -:10016000038106C0C005010906A101850205071922 -:10017000E029E715002501750195088102950175B3 -:1001800008810395067508150025650507190029DE -:1001900065810005081901290595057501910295EC -:1001A0000175039103C006C0FF0A000CA10185037D -:1001B0007508150026FF00953F09018102953F094A -:1001C000029102C0050C0901A1018504150026FF5A -:1001D000FF19002AFFFF950475108100C005010971 -:1001E00080A1018505150026FF00190029FF950152 -:1001F00075088100C005010905A1018506050919D9 -:10020000012920150025017501952081020501A114 -:10021000000930093109320933093409351500273D -:10022000FFFF0000751095068102C005010939091C -:100230003915012508950275048102C005010905DB -:10024000A10185070509190129201500250175015E -:10025000952081020501A1000930093109320933D5 -:1002600009340935150027FFFF0000751095068138 -:1002700002C0093909391501250895027504810262 -:10028000C005010904A1018508A10005091901297A -:100290000215002501750195028102050109300949 -:1002A00031150026FF03750A95028102750295013A -:1002B0008103C0C005010904A1018509A100050948 -:1002C0001901290215002501750195028102050118 -:1002D00009300931150026FF03750A950281027560 -:1002E0000295018103C0C00011241FBECFEFD2E0F0 -:1002F000DEBFCDBF11E0A0E0B1E0EEE5FDE102C060 -:1003000005900D92AE32B107D9F712E0AEE2B1E03E -:1003100001C01D92A434B107E1F720D30C94AD0EB7 -:100320006FCECF93DF9384B7877F84BF28E10FB66A -:10033000F89420936000109260000FBE80E190E07E -:100340009093CD008093CC00CAECD0E096E09883E7 -:10035000A8ECB0E082E08C93E9ECF0E02083539AC3 -:100360005A9A5B9A10821C92188298838C9388E91F -:1003700080835B988AB180638AB98BB180638BB9C3 -:1003800097D684E085BD5F9A579A84B184B9229844 -:100390002A9ADF91CF9108950895089580E091E021 -:1003A0000E94950D80E191E00E94D20AE2EEF0E019 -:1003B00080818460808308951F93CF93DF93EC0145 -:1003C000E98DE150E23028F4F0E0E55DFE4F108168 -:1003D00001C010E0888D823009F418608A8D873062 -:1003E00031F0883031F0863029F4126003C0146097 -:1003F00001C016605B9A1092C9001092C80010925A -:10040000CA002C893D894E895F89211581EE380704 -:100410004105510579F0CA01B901969587957795FF -:10042000679560587B47814E9F4F0E946E0E21500A -:10043000310902C020E130E03093CD002093CC00A0 -:100440001093CA008C899D89AE89BF898115914E10 -:10045000A105B10511F480E001C082E08093C800DD -:1004600088E98093C9005B98DF91CF911F9108952F -:100470001F920F920FB60F9211242F933F938F93D9 -:100480009F93AF93BF93EF93FF938091CE00909192 -:100490002E019430F9F090913B029430D9F4EFE2C0 -:1004A000F1E0A081B1818C9380819181019691834B -:1004B0008083268137818217930721F48481958177 -:1004C000918380832FB7F8948285938501969387D3 -:1004D00082872FBFFF91EF91BF91AF919F918F9135 -:1004E0003F912F910F900FBE0F901F901895FC0118 -:1004F000208920FF02C05F9808955F9A8BB18063C6 -:100500008BB9089580E191E00E94AB0B80E091E00F -:100510000C945E0C80910E0190910F01009729F0D0 -:10052000019790930F0180930E010895EF92FF922F -:100530000F931F93CF93DF937B01C901E8012091B3 -:10054000BD012223E1F04091BE012091BF01421381 -:1005500016C0E0ECF1E050E0BF010E949D0E8091DA -:10056000BD01F70180838091BE01888319821092BA -:10057000BD011092BF011092BE0181E001C080E078 -:10058000DF91CF911F910F91FF90EF9008950F93FE -:100590001F93C901633039F45C986093BC01B801C2 -:1005A0001F910F9126C31F910F91089510920B0276 -:1005B0001092FF010895462F209111012F70209372 -:1005C000E9002091E80020FFFCCF2091200120FFCE -:1005D00006C050E0BC0180E191E00C94F70A089558 -:1005E000CF92DF92EF92FF920F931F93FA018B014C -:1005F0000095109520E030E0980111270027AB010D -:1006000060E070E0042B152B262B372B4CE150E0DB -:1006100097E068017901042E04C0F694E794D7941A -:10062000C7940A94D2F76C2D683028F0973059F4AB -:10063000C08296E008C0C0829150C11004C04750EB -:100640005109923031F7492F425013C0DF01A40FF6 -:10065000B11D68017901E894C7F8DD24EE24FF2478 -:10066000CC92B7E03695279517950795BA95D1F7AF -:1006700041504111EBCF492F50E09A01A3E0220FE6 -:10068000331FAA95E1F7206C3F6F3081322B308306 -:10069000E40FF51F319781508F7380688083892F15 -:1006A0001F910F91FF90EF90DF90CF900895CF931F -:1006B000DF9300D000D000D0CDB7DEB76091BD0190 -:1006C000662379F08091BF0181110BC070E07160E9 -:1006D000AE014F5F5F4F81E083DF682FCE0101964F -:1006E0006ADF1092BD0126960FB6F894DEBF0FBEEA -:1006F000CDBFDF91CF9108950F931F93982F409115 -:100700000B02E42FF0E0EB5FFD4F808380910B0242 -:100710008F5F80930B02892F807C803809F444C05E -:10072000803C09F05FC0292F2873269526952695D1 -:10073000223008F477C0273079F4492F4F7050E009 -:1007400060E070E040930002509301026093020267 -:100750007093030215E00FC0892F877090E0A0E02E -:10076000B0E08093000290930102A0930202B09344 -:100770000302122F11508091FF01882391F097DF1F -:1007800060910B02615085E092E015DFE0910B0271 -:10079000F0E0EC5FFD4F80818093050281E0809363 -:1007A0000B021093FF0145C08091FF018130D1F50C -:1007B0000091000210910102209102023091030287 -:1007C000A901662777272227332740275127622749 -:1007D00073274F3F5F4F6105710521F5892F8F7397 -:1007E0008F5F28C08091FF018230E0F081508093BC -:1007F000FF0140910002509101026091020270914C -:10080000030227E0440F551F661F771F2A95D1F773 -:10081000492B4093000250930102609302027093AF -:10082000030207C044DF60910B0285E092E0C3DE63 -:10083000BDDE80E01F910F910895CF935DDFC82F3B -:10084000882309F489C08091BD01811104C0C130A1 -:1008500009F046C010C09091BE018091BF0198136D -:10086000F6CF04C080E091E00E94AA0D8091BD0106 -:100870008111F8CFECCF80910102813089F517DF2B -:10088000909100029093BD011092BF018FE3E0ECC4 -:10089000F1E0DF01282F1D922A95E9F79530A9F0A4 -:1008A00058F4923081F018F49130C1F40AC09330BA -:1008B00091F0943099F407C0983050F09A3070F469 -:1008C00009C084E008C088E006C0C093BE0142C0F1 -:1008D00081E101C083E08093BE013CC0E8DE3AC004 -:1008E0008091BD01882381F16091BF01462F50E0C6 -:1008F0008C2F90E09A012E5F3F4F359527952F5F03 -:100900003F4F8217930701F5FA01E054FE4F8091A3 -:1009100000028083E62FEF5FE093BF018091BE016C -:100920008E1749F0F0E0E054FE4F90910102908361 -:100930006E5F6093BF019091BF0189130BC080E08F -:1009400091E00E94AA0D06C0B2DE60910B0285E024 -:1009500092E031DECF912ACECF910895E2DC109261 -:100960002E01EFE2F1E02FB7F8948BE391E0918351 -:10097000808393838283958384838BEB91E0978339 -:10098000868380E890E091878087138612862FBF48 -:100990007894E2E08E2E0FE211E0CBE3D1E0FBEBA6 -:1009A000EF2EF1E0FF2EA0E8CA2ED12CB3E09B2E53 -:1009B0008091240190912501A0912601B0912701F9 -:1009C00020912E010097A105B10529F08115924CC7 -:1009D000A140B10529F52430B9F4F8018FB7F89496 -:1009E000D183C083D383C283D583C483F782E68255 -:1009F000D186C086138612868FBF1092BB011092DB -:100A0000BC018BB180638BB91A9B11C080912E0100 -:100A1000823019F0CBDD1092BD0180922E0109C009 -:100A2000243029F410922F011092300102C010924C -:100A30002E0180E191E061D697FD09C05C9890920B -:100A4000BC019091C80095FFFCCF8093CE002FB7DA -:100A5000F8948091390190913A012FBF009719F4D1 -:100A6000A89949C068C05D989092BB01209111017E -:100A70002F702093E9002091E80020FFF1CF80340F -:100A8000910510F08FE390E0782EA12CB12C30C0AE -:100A900080912E01882361F0F801A281B3818D91AC -:100AA000B383A28326813781A217B30781F40BC0D9 -:100AB000E0913101F0913201608180E191E0B5D5A2 -:100AC000882351F3CDCF24813581338322839FB78F -:100AD000F8942285338521503109338722879FBFBF -:100AE00090912E01923009F4A8DE8FEFA81AB80A6F -:100AF0007A10CECFB5CFA89A8091BB01882389F018 -:100B000081508093BB0181110CC080912E018230F5 -:100B100039F4CDDD60910B0285E092E04CDD46DDDD -:100B20005D9A8091BC01882331F081508093BC0193 -:100B3000811101C05C9A80912E01823021F480E005 -:100B400091E00E94AA0D80E191E0C1D50FD530CF90 -:100B5000292F332723303105B1F04CF421303105F2 -:100B600009F439C02230310509F03AC007C02132FA -:100B7000310539F12232310549F132C0EFE5F0E0BB -:100B80008EEB90E031C099278130910561F0823081 -:100B9000910581F0892B21F5EAEBF0E0E491F0E09A -:100BA0008AEB90E021C0E6EAF0E0E491F0E086EA2A -:100BB00090E01AC0E4E7F0E0E491F0E084E790E030 -:100BC00013C0E9E0F0E08DE091E00EC0E8EBF1E069 -:100BD0008FE291E009C0E2E1F0E08DE191E004C034 -:100BE000E0E0F0E080E090E0DA018D939C93CF01AB -:100BF0000895680F791F09C0FC012191CF01309140 -:100C0000C80035FFFCCF2093CE0086179707A1F7C9 -:100C10000895BF92CF92DF92EF92FF920F931F93AE -:100C2000CF93DF937C018B01EA01D7D1B82E8111DC -:100C300032C0209731F028813981021B130BE20E5C -:100C4000F31EC12CD12C22C08091E80085FD14C078 -:100C50008091E8008E778093E800209749F08881A2 -:100C600099818C0D9D1D9983888325E0B22E13C038 -:100C7000B4D1882359F00EC0F70181917F01809390 -:100C8000F10001501109FFEFCF1ADF0A011511051C -:100C9000D9F601C0B82E8B2DDF91CF911F910F9106 -:100CA000FF90EF90DF90CF90BF9008952091420287 -:100CB000309143022617370748F06115710539F462 -:100CC0002091E8002E772093E80001C0B9019C0133 -:100CD00080E034C090913B02992309F443C09530E1 -:100CE00009F442C09091E80093FD3AC09091E80069 -:100CF00092FD30C09091E80090FF20C08091F200FA -:100D000090E0F901821B930B05C021912093F10023 -:100D1000615071099F01280F391F6115710519F084 -:100D20002830310590F381E02830310509F080E06A -:100D30009091E8009E779093E8009F0161157105FE -:100D400049F68111C7CF06C080913B02882351F03C -:100D5000853051F08091E80082FFF6CF80E0089561 -:100D600081E0089582E0089583E00895611571059A -:100D700029F42091E8002B772093E8009C0121C002 -:100D800080913B02882381F1853041F18091E80018 -:100D900083FD26C08091E80082FFF2CFF90107C0F1 -:100DA0008091F10081939F016150710929F09F01A9 -:100DB0008091F2008111F4CF8091E8008B778093CD -:100DC000E80061157105E1F68091E80080FD0AC038 -:100DD00080913B02882341F08530B1F783E008958C -:100DE00081E0089580E0089582E008952091420214 -:100DF000309143022617370748F06115710539F421 -:100E00002091E8002E772093E80001C0B9019C01F1 -:100E100080E035C090913B02992309F444C095309D -:100E200009F443C09091E80093FD3BC09091E80025 -:100E300092FD31C09091E80090FF21C08091F200B6 -:100E400090E0F901821B930B06C024912093F100DE -:100E50003196615071099C012E0F3F1F611571057C -:100E600019F02830310588F381E02830310509F088 -:100E700080E09091E8009E779093E8009F016115D3 -:100E8000710541F68111C6CF06C080913B028823CF -:100E900051F0853051F08091E80082FFF6CF80E07C -:100EA000089581E0089582E0089583E00895982FE1 -:100EB0002CC09093E900981739F07091EC002091C4 -:100EC000ED005091F00003C0242F762F50E021FD5B -:100ED00002C09F5F1AC03091EB003E7F3093EB0061 -:100EE0003091ED003D7F3093ED003091EB003160AB -:100EF0003093EB007093EC002093ED005093F000E2 -:100F00002091EE0027FDE5CF07C0953090F28F705D -:100F10008093E90081E0089580E008950F931F9386 -:100F2000CF93DF93062FEC0110E02EC09881911132 -:100F300003C01F5F259628C02C81E981FA816B814F -:100F4000892F8F70853010F080E021C0223010F0A2 -:100F500056E001C052E028E030E040E003C04F5FBF -:100F6000220F331F2E173F07D0F34295407F452BAA -:100F7000991F9927991F6295660F660F607C692BF0 -:100F800096DF8111D6CFE0CF1013D0CF81E0DF9173 -:100F9000CF911F910F91089580913C0287FD05C06C -:100FA0008091E80080FF0EC012C08091E80082FDB1 -:100FB00005C080913B028111F8CF08958091E8002F -:100FC0008B7708C080913B028111EACF0895809110 -:100FD000E8008E778093E80008958091E400909176 -:100FE000E50045E62091EC0020FD1FC023C02091C4 -:100FF0003B02222391F0253091F02091EB0025FD5A -:1010000010C02091E4003091E5002817390751F312 -:101010004150C90139F784E0089582E0089583E0E2 -:10102000089581E0089580E008952091E80020FF70 -:10103000DECFF9CF2091E80022FFD9CFF4CF41D005 -:1010400043D08091D8008F778093D8008091D800CA -:1010500080688093D8008091D8008F7D8093D800DD -:1010600084E089BD86E089BD09B400FEFDCF109201 -:101070003B0210923702109239021092380242E07D -:1010800060E080E014DF8091E1008E7F8093E100DA -:101090008091E20081608093E2008091E2008860AC -:1010A0008093E2008091E0008E7F8093E0000895BD -:1010B000E3E6F0E080818E7F808381E080933A02D6 -:1010C000BECF1092E20008951092E10008951F92A1 -:1010D0000F920FB60F9211242F933F934F935F936C -:1010E0006F937F938F939F93AF93BF93EF93FF93F0 -:1010F0008091E10082FF0AC08091E20082FF06C079 -:101100008091E1008B7F8093E10004DA8091E1001F -:1011100080FF17C08091E20080FF13C08091E20041 -:101120008E7F8093E2008091E20080618093E200F4 -:101130008091D80080628093D80019BC10923B0245 -:101140002CD98091E10084FF2FC08091E20084FFC0 -:101150002BC084E089BD86E089BD09B400FEFDCFC7 -:101160008091D8008F7D8093D8008091E1008F7EA0 -:101170008093E1008091E2008F7E8093E200809175 -:10118000E20081608093E20080913702882311F0B1 -:1011900084E007C08091E30087FF02C083E001C0C4 -:1011A00081E080933B02F8D88091E10083FF27C063 -:1011B0008091E20083FF23C08091E100877F8093CC -:1011C000E10082E080933B02109237028091E100BF -:1011D0008E7F8093E1008091E2008E7F8093E20019 -:1011E0008091E20080618093E20042E060E080E074 -:1011F0005EDE8091F00088608093F000B6D1FF91B0 -:10120000EF91BF91AF919F918F917F916F915F917E -:101210004F913F912F910F900FBE0F901F901895F7 -:101220001F920F920FB60F9211242F933F934F935B -:101230005F936F937F938F939F93AF93BF93CF935E -:10124000EF93FF938091E9008F709091EC0090FFF5 -:1012500002C090E801C090E0C92FC82B1092E900AD -:101260008091F000877F8093F00078941CD01092DA -:10127000E9008091F00088608093F000CF70C09307 -:10128000E900FF91EF91CF91BF91AF919F918F9125 -:101290007F916F915F914F913F912F910F900FBE72 -:1012A0000F901F9018951F93CF93DF93CDB7DEB7A4 -:1012B000AC970FB6F894DEBF0FBECDBFECE3F2E003 -:1012C0008091F100819322E0E434F207C9F71AD942 -:1012D0008091E80083FF31C180913C0290913D02F2 -:1012E000953009F487C038F49130B1F170F0933043 -:1012F00009F023C131C0983009F4F3C0993009F4E2 -:10130000FFC0963009F019C19BC0803821F08238A7 -:1013100009F013C108C080913802909139029923D5 -:1013200089F082600FC080914002909141028F70DD -:1013300099278093E9008091EB0085FB882780F94D -:101340001092E9009091E800977F9093E8008093D5 -:10135000F1001092F100D0C0882319F0823009F01A -:10136000ECC08F7121F0823009F0E7C00BC0809192 -:101370003E02813009F0E1C0933009F080E08093B3 -:1013800039022FC080913E0281112BC08091400212 -:10139000909141028F709927009709F4CEC08093F5 -:1013A000E9002091EB0020FF1CC020913D0223307A -:1013B00021F48091EB00806212C09091EB0090616B -:1013C0009093EB0021E030E001C0220F8A95EAF70C -:1013D0002093EA001092EA008091EB0088608093ED -:1013E000EB001092E9008091E800877F8093E8008D -:1013F000D3DDA3C08111A1C080913E0290913F0234 -:101400008F779927182F9091E3009078982B9093DD -:10141000E3008091E800877F8093E800BDDD809144 -:10142000E80080FFFCCF8091E30080688093E300B8 -:10143000112311F083E001C082E080933B027DC064 -:101440008058823008F079C080913E0290913F022E -:101450008C3D23E0920771F583E08A838AE28983D9 -:101460004FB7F894DE01139620E03EE051E2E32FFF -:10147000F0E050935700E49120FF03C0E295EF7035 -:101480003F5FEF708E2F90E0EA3010F0C79601C0FA -:10149000C0968D939D932F5F243149F74FBF809164 -:1014A000E800877F8093E8006AE270E0CE01019651 -:1014B000FDDB11C0AE01455D5F4F6091400248DB2E -:1014C0000097D9F12091E800277F2093E800BC0124 -:1014D0008BA59CA58BDC8091E8008B778093E8003E -:1014E0002CC0803851F58091E800877F8093E80018 -:1014F000809137028093F1008091E8008E7776CF5B -:1015000081111BC090913E029230B8F48091E800A6 -:10151000877F8093E800909337023EDD8091370209 -:10152000811104C08091E30087FF02C084E001C004 -:1015300081E080933B020E94CE018091E80083FF0E -:101540000AC08091E800877F8093E8008091EB00DB -:1015500080628093EB00AC960FB6F894DEBF0FBEAE -:10156000CDBFDF91CF911F9108950895CF938091C2 -:101570003B028823A9F08091E9008F709091EC00E4 -:1015800090FF02C090E801C090E0C92FC82B1092D4 -:10159000E9008091E80083FD86DECF70C093E9000A -:1015A000CF910895CF93DF93EC014096FC018BE03F -:1015B000DF011D928A95E9F782E08C83898783E0B9 -:1015C0008E8761E0CE010196A9DC882361F061E09D -:1015D000CE010696A3DC882331F061E0CE010B96A4 -:1015E000DF91CF919BCC80E0DF91CF9108950F9355 -:1015F0001F93FC01CB01BA0120913B02243089F4F6 -:101600000489158926893789012B022B032B49F080 -:1016100021812F702093E90040E050E01F910F914D -:10162000F8CA82E01F910F910895CF93C62F2091A1 -:101630003B022430F1F4FC0144895589668977899D -:10164000452B462B472BA9F081818F708093E900B1 -:101650008091E80085FF04C0C093F10080E00AC0DB -:101660008091E8008E778093E800B7DC8823A1F3AF -:1016700001C082E0CF91089520913B02243029F5EA -:10168000FC014489558966897789452B462B472B70 -:10169000E1F081818F708093E9008091F2008111E7 -:1016A00002C080E008959091E8008091E8008E7774 -:1016B0008093E80095FDF5CF90DC811107C09091F3 -:1016C000E8009E779093E800089582E008952091C5 -:1016D0003B02243089F4FC01448955896689778965 -:1016E000452B462B472B41F021812F702093E90099 -:1016F0002091E80020FDC0CF089520913B022430C6 -:1017000019F02FEF3FEF24C0FC0144895589668909 -:101710007789452B462B472BA1F386818F708093C9 -:10172000E9008091E80082FFECCF8091F2008823ED -:1017300021F02091F10030E002C02FEF3FEF8091C7 -:10174000F200811105C08091E8008B778093E8005A -:10175000C90108950895CF93DF93EC018091E800CB -:1017600083FFA9C0888190E020914002309141021E -:101770002817390709F09FC080913D02813261F03E -:1017800020F4803209F097C03DC0823209F46EC067 -:10179000833209F090C07FC080913C02813A09F009 -:1017A0008AC08091E800877F8093E8008091E800FC -:1017B00080FFFCCF4C895D896E897F894093F10061 -:1017C000BB27A72F962F852F8093F100CB01AA2747 -:1017D000BB278093F100472F552766277727409333 -:1017E000F100888D8093F100898D8093F1008A8DBE -:1017F0008093F1008091E8008E778093E800DF917C -:10180000CF91CACB80913C02813209F054C08091C3 -:10181000E800877F8093E80005C080913B02882321 -:1018200009F449C08091E80082FFF7CF3091F100C0 -:101830002091F1009091F1008091F1003C8B2D8B73 -:101840009E8B8F8B8091F100888F8091F100898F22 -:101850008091F1008A8F8091E8008B778093E80077 -:101860009BDBCE01DF91CF910C94DC0180913C0297 -:10187000813209F58091E800877F8093E8008CDB56 -:1018800080913E0290913F02998B888BCE01DF912F -:10189000CF910C94770280913C02813261F4809167 -:1018A000E800877F8093E80077DB60913E02CE01FD -:1018B000DF91CF914FCFDF91CF9108956F927F92BB -:1018C0008F929F92AF92BF92CF92DF92EF92FF9250 -:1018D0000F931F93CF93DF9300D01F92CDB7DEB746 -:1018E0007C01ADB6BEB68091E80083FF07C1F70169 -:1018F000808190E020914002309141022817390701 -:1019000009F0FCC080913D02833009F49EC030F4A0 -:10191000813071F0823009F0F1C0D4C08A3009F40E -:10192000B9C08B3009F4A2C0893009F0E7C04CC0BF -:1019300080913C02813A09F0E1C08DB69EB61A82D0 -:10194000198280913E0210913F028B83F7014085FE -:101950008DB79EB7841B91090FB6F8949EBF0FBE3A -:101960008DBFCDB6DEB6EFEFCE1ADE0A360150E0FF -:1019700060E070E0C601EAD1412F41508E010F5F57 -:101980001F4F9601BE016D5F7F4FC7010E949602F7 -:10199000F701268137812115310529F0408550E076 -:1019A000B601C901CAD11092E9008091E800877F91 -:1019B0008093E80069817A81C30178D98091E80039 -:1019C0008B778093E80039C080913C02813209F026 -:1019D00095C08DB69EB60091420210914302709060 -:1019E0003E0260903F028DB79EB7801B910B0FB6F1 -:1019F000F8949EBF0FBE8DBFCDB6DEB6EFEFCE1A08 -:101A0000DE0A8091E800877F8093E800B801C60174 -:101A1000ADD98091E8008E778093E80021E07110C5 -:101A200001C020E030E0021B130B2C0D3D1D462DA4 -:101A30004150672DC7010E94C702882D992D0FB60E -:101A4000F8949EBF0FBE8DBF59C080913C02813A71 -:101A500009F054C08091E800877F8093E80080916E -:101A6000E80080FFFCCFF701818540C080913C02F7 -:101A7000813209F043C08091E800877F8093E800BD -:101A80008BDA90913E0281E0911101C080E0F70174 -:101A9000818734C080913C02813281F58091E800D9 -:101AA000877F8093E80078DA80913E0290913F0230 -:101AB000882736E0969587953A95E1F7F70195875F -:101AC00084871CC080913C02813AC1F48091E80077 -:101AD000877F8093E8008091E80080FFFCCFF701CA -:101AE0008485958596958795969587958093F10041 -:101AF0008091E8008E778093E8004EDA0FB6F89474 -:101B0000BEBE0FBEADBE0F900F900F90DF91CF9174 -:101B10001F910F91FF90EF90DF90CF90BF90AF900B -:101B20009F908F907F906F9008959C01275F3F4F0B -:101B3000F90127E0DF011D922A95E9F721E0FC0178 -:101B4000218724EF31E03587248723E0248361E077 -:101B50000196E4C94F925F926F927F928F929F920B -:101B6000AF92BF92CF92DF92EF92FF920F931F93AB -:101B7000CF93DF9300D01F92CDB7DEB77C01ADB617 -:101B8000BEB680913B02843009F08FC08091E400A2 -:101B90009091E500F701228533852817390709F46C -:101BA00084C081818F708093E9008091E80085FF77 -:101BB0007CC06DB67EB640858DB79EB7841B9109FB -:101BC0000FB6F8949EBF0FBE8DBFCDB6DEB6EFEF59 -:101BD000CE1ADE0A1B821A821982460150E060E0AA -:101BE00070E0C601B3D08E010F5F1F4F960140E039 -:101BF000BE016D5F7F4FC7010E949602582EF7010C -:101C000084859585892B31F001E010E086859785E4 -:101C1000892B11F000E010E0F701C680D780C114D5 -:101C2000D10489F049815A81B601C40179D0442494 -:101C30004394009709F4412CF701408550E0B4012A -:101C4000C6017BD001C0412C89819A81892BF9F092 -:101C5000511004C0411002C000FF19C0F701848573 -:101C600095859787868781818F708093E9008B8126 -:101C700081118093F10069817A8140E050E0C401D4 -:101C80000E9409068091E8008E778093E800809199 -:101C9000E4009091E500F70193878287862D972DC8 -:101CA0000FB6F8949EBF0FBE8DBF0FB6F894BEBEA0 -:101CB0000FBEADBE0F900F900F90DF91CF911F918F -:101CC0000F91FF90EF90DF90CF90BF90AF909F90DB -:101CD0008F907F906F905F904F900895A1E21A2EA1 -:101CE000AA1BBB1BFD010DC0AA1FBB1FEE1FFF1FC0 -:101CF000A217B307E407F50720F0A21BB30BE40B10 -:101D0000F50B661F771F881F991F1A9469F7609556 -:101D10007095809590959B01AC01BD01CF01089510 -:101D2000FB01DC0104C08D910190801921F4415028 -:101D30005040C8F7881B990B0895FB01DC0102C0D5 -:101D400001900D9241505040D8F70895DC0101C038 -:0E1D50006D9341505040E0F70895F894FFCF96 -:101D5E0002812000000100003F0000000000000092 -:101D6E0000834000000104400000018208000001D1 -:0E1D7E00000000000000000000000030200007 -:00000001FF diff --git a/plugins/KeyboardioHID/Firmwares/Hoodloader1_7_1.hex b/plugins/KeyboardioHID/Firmwares/Hoodloader1_7_1.hex deleted file mode 100644 index c37d733cde..0000000000 --- a/plugins/KeyboardioHID/Firmwares/Hoodloader1_7_1.hex +++ /dev/null @@ -1,605 +0,0 @@ -:1000000073C100008DC100008BC1000089C10000D8 -:1000100087C1000085C1000083C1000081C10000CC -:100020007FC100007DC100007BC100000C94790CF1 -:100030000C94250D75C1000073C1000071C1000052 -:100040006FC100006DC100006BC1000069C10000FC -:1000500067C1000065C1000063C1000012C200005A -:100060005FC100005DC100005BC1000059C100001C -:1000700057C1000030034100720064007500690040 -:100080006E006F00200048006F006F0064006C007D -:100090006F0061006400650072002000420065008E -:1000A00074006100000012034E00690063006F00DD -:1000B00048006F006F006400000004030904090297 -:1000C0005F00030100C032080B00020202010009B8 -:1000D00004000001020201000524001001042402B2 -:1000E000060524060001070582030800FF09040134 -:1000F00000020A0000000705040240000107058312 -:10010000024000010904020001030000000921115E -:1001100001000122B801070581032000011201102E -:1001200001EF020108EB03686E17000102DC010514 -:10013000010902A1010901A100850105091901298F -:10014000051500250195057501810295017503814D -:100150000305010930093109381581257F75089596 -:10016000038106C0C005010906A101850205071922 -:10017000E029E715002501750195088102950175B3 -:1001800008810395067508150025650507190029DE -:1001900065810005081901290595057501910295EC -:1001A0000175039103C006C0FF0A000CA10185037D -:1001B0007508150026FF00953F09018102953F094A -:1001C000029102C0050C0901A1018504150026FF5A -:1001D000FF19002AFFFF950475108100C005010971 -:1001E00080A1018505150026FF00190029FF950152 -:1001F00075088100C005010905A1018506050919D9 -:10020000012920150025017501952081020501A114 -:10021000000930093109320933093409351500273D -:10022000FFFF0000751095068102C005010939091C -:100230003915012508950275048102C005010905DB -:10024000A10185070509190129201500250175015E -:10025000952081020501A1000930093109320933D5 -:1002600009340935150027FFFF0000751095068138 -:1002700002C0093909391501250895027504810262 -:10028000C005010904A1018508A10005091901297A -:100290000215002501750195028102050109300949 -:1002A00031150026FF03750A95028102750295013A -:1002B0008103C0C005010904A1018509A100050948 -:1002C0001901290215002501750195028102050118 -:1002D00009300931150026FF03750A950281027560 -:1002E0000295018103C0C00011241FBECFEFD2E0F0 -:1002F000DEBFCDBF11E0A0E0B1E0EAE8F5E202C068 -:1003000005900D92AE32B107D9F712E0AEE2B1E03E -:1003100001C01D92A634B107E1F788D70C94C3122F -:100320006FCE9BB1809589238BB908959BB1982B93 -:100330009BB90895CF93DF9384B7877F84BF28E16B -:100340000FB6F89420936000109260000FBE80E119 -:1003500090E09093CD008093CC00CAECD0E096E082 -:100360009883A8ECB0E082E08C93E9ECF0E0208385 -:10037000539A5A9A5B9A10821C92188298838C9393 -:1003800088E980835B988AB180638AB98BB1806386 -:100390008BB90E946A0C84E085BD5F9A579A209AB7 -:1003A00022982A9ADF91CF9108950895089580E0C8 -:1003B00091E00E94AB1180E191E00E94E80EE2EE34 -:1003C000F0E080818460808308951F93CF93DF9352 -:1003D000EC01E98DE150E23028F4F0E0E55DFE4FFC -:1003E000108101C010E0888D823009F418608A8D78 -:1003F000873031F0883031F0863029F4126003C044 -:10040000146001C016605B9A1092C9001092C80077 -:100410001092CA002C893D894E895F89211581EE91 -:1004200038074105510579F0CA01B90196958795BC -:100430007795679560587B47814E9F4F0E94841245 -:100440002150310902C020E130E03093CD002093EB -:10045000CC001093CA008C899D89AE89BF89811513 -:10046000914EA105B10511F480E001C082E08093B6 -:10047000C80088E98093C9005B98DF91CF911F91F4 -:1004800008951F920F920FB60F9211242F933F934E -:100490008F939F93AF93BF93EF93FF938091CE0081 -:1004A00090912E019330F9F090913D029430D9F45F -:1004B000EFE2F1E0A081B1818C938081918101967E -:1004C00091838083268137818217930721F4848169 -:1004D0009581918380832FB7F894828593850196C7 -:1004E000938782872FBFFF91EF91BF91AF919F912B -:1004F0008F913F912F910F900FBE0F901F901895E5 -:10050000FC01208920FF02C05F9808955F9A8BB19B -:1005100080638BB9089580E191E00E94C10F80E073 -:1005200091E00C94741080910E0190910F0100974E -:1005300029F0019790930F0180930E010895EF9297 -:10054000FF920F931F93CF93DF937B01C901E801C3 -:100550002091BD012223E1F04091BE012091BF0115 -:10056000421316C0E0ECF1E050E0BF010E94B3126C -:100570008091BD01F70180838091BE01888319823B -:100580001092BD011092BF011092BE0181E001C026 -:1005900080E0DF91CF911F910F91FF90EF90089530 -:1005A000EF92FF920F931F93CF93DF931F92CDB7DC -:1005B000DEB77901633081F480E16983B2DE69815D -:1005C0006093BC01B801C7010F90DF91CF911F91DB -:1005D0000F91FF90EF901FC70F90DF91CF911F9168 -:1005E0000F91FF90EF90089510920B021092FF016F -:1005F000089520912E018091240190912501A091D0 -:100600002601B09127011A9B0DC00097A105B105E5 -:1006100039F0811532EC930731E0A307B10511F4ED -:1006200082E007C00197A105B10511F483E001C084 -:1006300081E080932E0180912E01281709F43BC0A0 -:10064000233011F021111DC0EFE2F1E02FB7F89433 -:100650008BE391E09183808393838283958384836A -:100660008BEB91E09783868380E890E09187808789 -:10067000138612862FBF1092BB011092BC0180E33B -:1006800055DE80912E01823021F4AEDF1092BD0143 -:100690000895833081F41092300110922F0110924E -:1006A000320110923101109234011092330180E333 -:1006B0003DDE22982A9A0895462F209111012F702D -:1006C0002093E9002091E80020FFFCCF2091200139 -:1006D00020FF06C050E0BC0180E191E00C940D0FBA -:1006E0000895CF92DF92EF92FF920F931F93FA013A -:1006F0008B010095109520E030E09801112700272C -:10070000AB0160E070E0042B152B262B372B4CE15E -:1007100050E097E068017901042E04C0F694E79454 -:10072000D794C7940A94D2F76C2D683028F097308C -:1007300059F4C08296E008C0C0829150C11004C034 -:1007400047505109923031F7492F425013C0DF0111 -:10075000A40FB11D68017901E894C7F8DD24EE24E7 -:10076000FF24CC92B7E03695279517950795BA9553 -:10077000D1F741504111EBCF492F50E09A01A3E04E -:10078000220F331FAA95E1F7206C3F6F3081322B87 -:100790003083E40FF51F319781508F738068808319 -:1007A000892F1F910F91FF90EF90DF90CF900895C8 -:1007B000CF93DF9300D000D000D0CDB7DEB76091EB -:1007C000BD01662379F08091BF0181110BC070E0FB -:1007D0007160AE014F5F5F4F81E083DF682FCE0114 -:1007E00001966ADF1092BD0126960FB6F894DEBF1F -:1007F0000FBECDBFDF91CF9108950F931F93982F18 -:1008000040910B02E42FF0E0EB5FFD4F808380917D -:100810000B028F5F80930B02892F807C803809F454 -:1008200044C0803C09F05FC0292F28732695269587 -:100830002695223008F477C0273079F4492F4F707D -:1008400050E060E070E0409300025093010260933A -:1008500002027093030215E00FC0892F877090E0A9 -:10086000A0E0B0E08093000290930102A093020206 -:10087000B0930302122F11508091FF01882391F051 -:1008800097DF60910B02615085E092E015DFE09107 -:100890000B02F0E0EC5FFD4F80818093050281E068 -:1008A00080930B021093FF0145C08091FF018130BE -:1008B000D1F50091000210910102209102023091C5 -:1008C0000302A901662777272227332740275127CC -:1008D000622773274F3F5F4F6105710521F5892F0F -:1008E0008F738F5F28C08091FF018230E0F08150CC -:1008F0008093FF0140910002509101026091020239 -:100900007091030227E0440F551F661F771F2A9539 -:10091000D1F7492B409300025093010260930202E9 -:100920007093030207C044DF60910B0285E092E000 -:10093000C3DE5ADE80E01F910F910895CF935DDFF3 -:10094000C82F882309F489C08091BD01811104C09A -:10095000C13009F046C010C09091BE018091BF0126 -:100960009813F6CF04C080E091E00E94C0118091FE -:10097000BD018111F8CFECCF80910102813089F562 -:1009800017DF909100029093BD011092BF018FE399 -:10099000E0ECF1E0DF01282F1D922A95E9F7953070 -:1009A000A9F058F4923081F018F49130C1F40AC0E3 -:1009B000933091F0943099F407C0983050F09A3009 -:1009C00070F409C084E008C088E006C0C093BE018E -:1009D00042C081E101C083E08093BE013CC0E8DEFB -:1009E0003AC08091BD01882381F16091BF01462FFB -:1009F00050E08C2F90E09A012E5F3F4F3595279560 -:100A00002F5F3F4F8217930701F5FA01E054FE4F25 -:100A1000809100028083E62FEF5FE093BF01809119 -:100A2000BE018E1749F0F0E0E054FE4F90910102B4 -:100A300090836E5F6093BF019091BF0189130BC0DB -:100A400080E091E00E94C01106C0B2DE60910B020E -:100A500085E092E031DECF91C7CDCF910895682F28 -:100A600080E191E00E942B0F8823E9F080E191E082 -:100A70000E947D0F0E94CC0E80E153DC2FEF81EEAF -:100A800094E0215080409040E1F700C0000080E1F8 -:100A900048DC2FEF81EE94E0215080409040E1F758 -:100AA00000C00000E9CF089580E191E00E94930F1B -:100AB00097FDFACF0895EF92FF920F931F93CF9374 -:100AC000DF937C0109E311E0C0E0D0E005C0ECDF7A -:100AD000F80181938F012196CE15DF05C4F3DF91D4 -:100AE000CF911F910F91FF90EF9008959091450144 -:100AF00080E020914601820F911D909336018093F2 -:100B000035019091470180E020914801820F911DAD -:100B100090933801809337010895CF93C82FC4DF95 -:100B2000803239F484E19BDF8C2F99DF80E1CF9113 -:100B300096CF85E194DF80912F019091300101964D -:100B40009093300180932F01CF910895813859F00F -:100B500018F4803871F405C0823839F0833949F4CB -:100B600006C082E007C081E005C082E103C083E5E2 -:100B700001C080E0D2CF98DF803221F484E16FDFC2 -:100B800080E16DCF80E2CDDB2FEF80E792E0215056 -:100B900080409040E1F700C0000080E2C7DB2FEF0B -:100BA00080E792E0215080409040E1F700C00000D3 -:100BB00080E2B7DB2FEF80E792E021508040904049 -:100BC000E1F700C0000080E2B1DB85E148DF809101 -:100BD0002F019091300101969093300180932F0165 -:100BE000089583E58CBD8DB58EB508950DB407FECF -:100BF000FDCF08958EBDFADF8EB50895CF93DF93B4 -:100C000000D01F92CDB7DEB72B834A836983F2DF12 -:100C10006981862FEFDF4A81842FECDF2B81822FC1 -:100C20000F900F900F90DF91CF91E4CFDADF249AED -:100C30002C9A219A29982FEF80E792E0215080404A -:100C40009040E1F700C000002C982FEF80E792E081 -:100C5000215080409040E1F700C000002398229A84 -:100C600020E040E063E58CEAC9DF81E090E090930A -:100C70003201809331010895462F880F880F880F25 -:100C800020E0672F805EBACF0F931F93CF93DF933F -:100C90008C01C0E0D0E019C0609133017091340143 -:100CA00080E0EADFDCDE609133017091340181E0A5 -:100CB000E3DFD5DE20913301309134012F5F3F4FC8 -:100CC00030933401209333012296C017D10724F3C7 -:100CD00080E1DF91CF911F910F91089584E090E022 -:100CE000EADE20913C0140913B0160913A01809104 -:100CF000390184DF12CFD8DE803259F080912F0184 -:100D00009091300101969093300180932F0185E1FD -:100D100015C084E1A4DE20E040E060E080E36EDF07 -:100D20009EDE20E041E060E080E368DF98DE20E0C6 -:100D300042E060E080E362DF92DE80E190CE2398C3 -:100D40002298229A2198249810923201109231010F -:100D50000895CF92DF92EF92FF920F931F93CF935C -:100D6000DF93D82FC92F7B01CB01A5DE80E2DEDA2D -:100D7000E9E3CE2EE1E0DE2E0D2F1C2FE80111C09D -:100D8000F60121916F014C2F6D2F80EC37DFFFE7CB -:100D900022E382E0F15020408040E1F700C00000F3 -:100DA0002196CE01801B910B8E159F054CF380E29E -:100DB000B8DA80E1DF91CF911F910F91FF90EF9012 -:100DC000DF90CF9008950F931F93CF93DF93C0913F -:100DD0003301D09134012091370130913801281727 -:100DE000390724F0CC0FDD1F8C0112C080912F0138 -:100DF0009091300101969093300180932F0181E111 -:100E00000EC060E270E0CE01A4DFA096005211098E -:100E100001321105B4F7B801CE019BDF80E1DF910B -:100E2000CF911F910F910895EF92FF920F931F930F -:100E3000CF93DF937C010091330110913401000FB7 -:100E4000111FE80107C02FEF4C2F6D2F80EAD6DE6F -:100E500006DE2196CE01801B910B8E159F059CF31B -:100E600080E1DF91CF911F910F91FF90EF90089556 -:100E70001F93CF93DF9318DED82F16DEC82F14DE12 -:100E8000182F12DE803259F080912F01909130019D -:100E900001969093300180932F0185E113C03D2F7F -:100EA00020E0C9018C0F911DEC0184E1D8DD1634DE -:100EB00019F4CE01E9DE06C0153419F4CE01B4DF11 -:100EC00001C081E1DF91CF911F91C9CDCF93DF9315 -:100ED00000D0CDB7DEB7482F80E249839A8326DA67 -:100EE00020E049819A81692F8CE488DE2FEF86E724 -:100EF00091E0215080409040E1F700C0000080E286 -:100F00000F900F90DF91CF910CCA80913501909195 -:100F1000360120913301309134018032910511F472 -:100F2000207F0EC08034910511F4207E09C08038E6 -:100F3000910511F4207C04C08115914009F42078BA -:100F4000C9010895962F672F242F880F880F880FC7 -:100F5000492F805C53CECF92DF92EF92FF920F9396 -:100F60001F93CF93DF936C01D0DF8C01C0E0D0E002 -:100F700029C0CBDF0817190721F0C801A7DFC5DF9B -:100F80008C01BEE2EB2EB1E0FB2EEC0EFD1E60915B -:100F9000330170913401F701438580E0D3DF22965D -:100FA0006091330170913401F701448581E0CADF1B -:100FB00020913301309134012F5F3F4F3093340142 -:100FC00020933301CC15DD05A4F2C8017FDF80E159 -:100FD000DF91CF911F910F91FF90EF90DF90CF9015 -:100FE0000895CF93DF93EC0166DD5EDD803229F456 -:100FF00084E135DDCE01AFDF0AC080912F019091F1 -:10100000300101969093300180932F0185E1DF91AB -:10101000CF9125CDCF93DF9347DDD82F80E0C82F28 -:1010200043DDC80FD11DC13081E0D80764F081E1F4 -:1010300016DD80912F01909130010196909330013F -:1010400080932F0122C030DD863421F4CE01DF9160 -:10105000CF91C7CF8534A9F4CE01B5DEC82F24DDEA -:10106000803221F484E1FBDC8C2F0CC080912F01B5 -:101070009091300101969093300180932F0185E18A -:1010800001C081E1DF91CF91EACCDF91CF9108954A -:10109000CF93DF938091310190913201892B19F028 -:1010A00080E23FD902C080E241D980912F01909126 -:1010B0003001892B19F080E134D902C080E136D9A2 -:1010C00080E191E030D797FDAEC08135910509F4FC -:1010D00085C0E4F48134910509F452C054F480339E -:1010E000910599F181339105A9F1809709F089C0A3 -:1010F0007EC08534910509F44EC08035910509F410 -:101100004EC08234910509F07CC03EC08136910505 -:1011100009F459C06CF48635910509F45CC0803639 -:10112000910509F44FC08535910509F06AC039C0B1 -:101130008437910509F44CC08537910509F454C0F2 -:101140008436910509F05DC040C0109230011092C4 -:101150002F011EC0A9DC803209F065C084E17FDC6C -:1011600081E47DDC86E57BDC82E579DC80E277DC8E -:1011700089E475DC83E573DC80E571DC80E150C0D7 -:1011800093DCDF91CF91E2CC84E190E094DCAEDCA3 -:10119000DF91CF91F0CC85E090E08DDCF9CF46DD9A -:1011A000F7CF82DCC82FD0E0D0933401C093330155 -:1011B0007BDC382F20E02C0F3D1F3093340120932F -:1011C0003301E6CF71DC70DCE3CFDF91CF9122CF2A -:1011D000DF91CF914DCEDF91CF9180CD1092300134 -:1011E00010922F01ACDDD4CFDF91CF9184CD8091CF -:1011F0002F019091300101969093300180932F013F -:101200000EC080912F019091300101969093300192 -:1012100080932F0149DC803211F482E101C085E125 -:10122000DF91CF911CCCDF91CF91089510922E01C8 -:1012300081D87894C3E0FC2E0FE211E0DAD98091D6 -:101240002E01833011F424DF90C080E191E06BD651 -:10125000EC0197FD0AC080E164D8F092BC01809156 -:10126000C80085FFFCCFC093CE008FB7F894C09123 -:101270003901D0913A018FBF209719F4A89949C03C -:101280006CC080E24ED8F092BB01809111018F704A -:101290008093E9008091E80080FFF0CFCE01C03458 -:1012A000D10510F08FE390E0E82EC0E0D0E02EC032 -:1012B00080912E01813061F0F801A281B3818D917E -:1012C000B383A28326813781A217B30781F40BC0B1 -:1012D000E0913101F0913201608180E191E0BBD574 -:1012E000882351F3CBCF24813581338322839FB769 -:1012F000F8942285338521503109338722879FBF97 -:1013000090912E01923009F419DB2196EC12D0CF86 -:10131000B5CFA89A8091BB01882399F08150809322 -:10132000BB0181110EC080912E01823039F440DA68 -:1013300060910B0285E092E0BFD956D980E20E940D -:1013400096018091BC01882341F081508093BC01BB -:10135000811103C080E10E94960180912E018230AC -:1013600021F480E091E00E94C01180E191E0C5D5B8 -:1013700013D564CF292F332723303105B1F04CF436 -:101380002130310509F439C02230310509F03AC065 -:1013900007C02132310539F12232310549F132C01D -:1013A000EFE5F0E08EEB90E031C0992781309105B8 -:1013B00061F08230910581F0892B21F5EAEBF0E0B4 -:1013C000E491F0E08AEB90E021C0E6EAF0E0E491FD -:1013D000F0E086EA90E01AC0E4E7F0E0E491F0E0A3 -:1013E00084E790E013C0E9E0F0E08DE091E00EC00A -:1013F000E8EBF1E08FE291E009C0E2E1F0E08DE19D -:1014000091E004C0E0E0F0E080E090E0DA018D934C -:101410009C93CF010895680F791F09C0FC012191A9 -:10142000CF013091C80035FFFCCF2093CE00861746 -:101430009707A1F70895BF92CF92DF92EF92FF92A4 -:101440000F931F93CF93DF937C018B01EA01D7D1D8 -:10145000B82E811132C0209731F028813981021BCA -:10146000130BE20EF31EC12CD12C22C08091E80098 -:1014700085FD14C08091E8008E778093E800209766 -:1014800049F0888199818C0D9D1D9983888325E081 -:10149000B22E13C0B4D1882359F00EC0F701819148 -:1014A0007F018093F10001501109FFEFCF1ADF0A8D -:1014B00001151105D9F601C0B82E8B2DDF91CF9102 -:1014C0001F910F91FF90EF90DF90CF90BF90089504 -:1014D00020914402309145022617370748F06115E4 -:1014E000710539F42091E8002E772093E80001C0BF -:1014F000B9019C0180E034C090913D02992309F428 -:1015000043C0953009F442C09091E80093FD3AC081 -:101510009091E80092FD30C09091E80090FF20C0CB -:101520008091F20090E0F901821B930B05C021919C -:101530002093F100615071099F01280F391F611537 -:10154000710519F02830310590F381E0283031051C -:1015500009F080E09091E8009E779093E8009F0169 -:101560006115710549F68111C7CF06C080913D0212 -:10157000882351F0853051F08091E80082FFF6CF4A -:1015800080E0089581E0089582E0089583E0089561 -:101590006115710529F42091E8002B772093E8006C -:1015A0009C0121C080913D02882381F1853041F169 -:1015B0008091E80083FD26C08091E80082FFF2CF91 -:1015C000F90107C08091F10081939F016150710979 -:1015D00029F09F018091F2008111F4CF8091E80001 -:1015E0008B778093E80061157105E1F68091E80042 -:1015F00080FD0AC080913D02882341F08530B1F71B -:1016000083E0089581E0089580E0089582E00895E0 -:1016100020914402309145022617370748F06115A2 -:10162000710539F42091E8002E772093E80001C07D -:10163000B9019C0180E035C090913D02992309F4E5 -:1016400044C0953009F443C09091E80093FD3BC03D -:101650009091E80092FD31C09091E80090FF21C088 -:101660008091F20090E0F901821B930B06C0249157 -:101670002093F1003196615071099C012E0F3F1F9C -:101680006115710519F02830310588F381E02830A3 -:10169000310509F080E09091E8009E779093E80092 -:1016A0009F016115710541F68111C6CF06C0809179 -:1016B0003D02882351F0853051F08091E80082FF8F -:1016C000F6CF80E0089581E0089582E0089583E0F8 -:1016D0000895982F2CC09093E900981739F07091D5 -:1016E000EC002091ED005091F00003C0242F762FE4 -:1016F00050E021FD02C09F5F1AC03091EB003E7F99 -:101700003093EB003091ED003D7F3093ED00309150 -:10171000EB0031603093EB007093EC002093ED0010 -:101720005093F0002091EE0027FDE5CF07C09530E3 -:1017300090F28F708093E90081E0089580E0089531 -:101740000F931F93CF93DF93062FEC0110E02EC071 -:101750009881911103C01F5F259628C02C81E981D3 -:10176000FA816B81892F8F70853010F080E021C065 -:10177000223010F056E001C052E028E030E040E0B6 -:1017800003C04F5F220F331F2E173F07D0F3429540 -:10179000407F452B991F9927991F6295660F660F09 -:1017A000607C692B96DF8111D6CFE0CF1013D0CFAC -:1017B00081E0DF91CF911F910F91089580913E02BA -:1017C00087FD05C08091E80080FF0EC012C08091A7 -:1017D000E80082FD05C080913D028111F8CF089597 -:1017E0008091E8008B7708C080913D028111EACF9B -:1017F00008958091E8008E778093E80008958091A5 -:10180000E4009091E50045E62091EC0020FD1FC02A -:1018100023C020913D02222391F0253091F02091A8 -:10182000EB0025FD10C02091E4003091E500281761 -:10183000390751F34150C90139F784E0089582E036 -:10184000089583E0089581E0089580E0089520914F -:10185000E80020FFDECFF9CF2091E80022FFD9CFAA -:10186000F4CF41D043D08091D8008F778093D800B7 -:101870008091D80080688093D8008091D8008F7DB7 -:101880008093D80084E089BD86E089BD09B400FE5C -:10189000FDCF10923D021092390210923B0210923D -:1018A0003A0242E060E080E014DF8091E1008E7F48 -:1018B0008093E1008091E20081608093E20080915A -:1018C000E20088608093E2008091E0008E7F809348 -:1018D000E0000895E3E6F0E080818E7F808381E080 -:1018E00080933C02BECF1092E20008951092E10076 -:1018F00008951F920F920FB60F9211242F933F93CA -:101900004F935F936F937F938F939F93AF93BF9307 -:10191000EF93FF938091E10082FF0BC08091E20082 -:1019200082FF07C08091E1008B7F8093E1000E94DD -:1019300093028091E10080FF18C08091E20080FF57 -:1019400014C08091E2008E7F8093E2008091E200DB -:1019500080618093E2008091D80080628093D800FB -:1019600019BC10923D020E94D6018091E10084FFD3 -:1019700030C08091E20084FF2CC084E089BD86E005 -:1019800089BD09B400FEFDCF8091D8008F7D809382 -:10199000D8008091E1008F7E8093E1008091E20089 -:1019A0008F7E8093E2008091E20081608093E2006C -:1019B00080913902882311F084E007C08091E30010 -:1019C00087FF02C083E001C081E080933D020E9456 -:1019D000D5018091E10083FF27C08091E20083FF61 -:1019E00023C08091E100877F8093E10082E08093B3 -:1019F0003D02109239028091E1008E7F8093E100D8 -:101A00008091E2008E7F8093E2008091E20080610D -:101A10008093E20042E060E080E05BDE8091F000D5 -:101A200088608093F000B7D1FF91EF91BF91AF91A3 -:101A30009F918F917F916F915F914F913F912F91E6 -:101A40000F900FBE0F901F9018951F920F920FB618 -:101A50000F9211242F933F934F935F936F937F9334 -:101A60008F939F93AF93BF93CF93EF93FF93809107 -:101A7000E9008F709091EC0090FF02C090E801C0E7 -:101A800090E0C92FC82B1092E9008091F000877F69 -:101A90008093F00078941CD01092E9008091F000BF -:101AA00088608093F000CF70C093E900FF91EF91C0 -:101AB000CF91BF91AF919F918F917F916F915F91E6 -:101AC0004F913F912F910F900FBE0F901F9018953F -:101AD0001F93CF93DF93CDB7DEB7AC970FB6F894D3 -:101AE000DEBF0FBECDBFEEE3F2E08091F100819347 -:101AF00022E0E634F207C9F70E948B028091E800E9 -:101B000083FF31C180913E0290913F02953009F4EC -:101B100087C038F49130B1F170F0933009F023C1EF -:101B200031C0983009F4F3C0993009F4FFC0963001 -:101B300009F019C19BC0803821F0823809F013C127 -:101B400008C080913A0290913B02992389F082600B -:101B50000FC080914202909143028F709927809329 -:101B6000E9008091EB0085FB882780F91092E9005D -:101B70009091E800977F9093E8008093F100109295 -:101B8000F100D0C0882319F0823009F0ECC08F71C9 -:101B900021F0823009F0E7C00BC080914002813013 -:101BA00009F0E1C0933009F080E080933B022FC040 -:101BB0008091400281112BC080914202909143029A -:101BC0008F709927009709F4CEC08093E900209187 -:101BD000EB0020FF1CC020913F02233021F48091B4 -:101BE000EB00806212C09091EB0090619093EB004B -:101BF00021E030E001C0220F8A95EAF72093EA0045 -:101C00001092EA008091EB0088608093EB001092C4 -:101C1000E9008091E800877F8093E800CFDDA3C0D2 -:101C20008111A1C080914002909141028F77992744 -:101C3000182F9091E3009078982B9093E300809177 -:101C4000E800877F8093E800B9DD8091E80080FF9D -:101C5000FCCF8091E30080688093E300112311F0B2 -:101C600083E001C082E080933D027DC080588230D5 -:101C700008F079C080914002909141028C3D23E0B0 -:101C8000920771F583E08A838AE289834FB7F894DB -:101C9000DE01139620E03EE051E2E32FF0E05093A6 -:101CA0005700E49120FF03C0E295EF703F5FEF70B3 -:101CB0008E2F90E0EA3010F0C79601C0C0968D9349 -:101CC0009D932F5F243149F74FBF8091E800877FB4 -:101CD0008093E8006AE270E0CE010196F9DB11C062 -:101CE000AE01455D5F4F6091420244DB0097D9F140 -:101CF0002091E800277F2093E800BC018BA59CA5DC -:101D000087DC8091E8008B778093E8002CC08038D6 -:101D100051F58091E800877F8093E8008091390237 -:101D20008093F1008091E8008E7776CF81111BC0FF -:101D3000909140029230B8F48091E800877F8093C0 -:101D4000E800909339023ADD80913902811104C094 -:101D50008091E30087FF02C084E001C081E08093AE -:101D60003D020E94D7018091E80083FF0AC0809164 -:101D7000E800877F8093E8008091EB008062809389 -:101D8000EB00AC960FB6F894DEBF0FBECDBFDF916F -:101D9000CF911F9108950895CF9380913D0288239C -:101DA000A9F08091E9008F709091EC0090FF02C043 -:101DB00090E801C090E0C92FC82B1092E9008091F3 -:101DC000E80083FD85DECF70C093E900CF910895D0 -:101DD000CF93DF93EC014096FC018BE0DF011D9275 -:101DE0008A95E9F782E08C83898783E08E8761E0BA -:101DF000CE010196A5DC882361F061E0CE01069654 -:101E00009FDC882331F061E0CE010B96DF91CF910A -:101E100097CC80E0DF91CF9108950F931F93FC0141 -:101E2000CB01BA0120913D02243089F4048915893F -:101E300026893789012B022B032B49F021812F7032 -:101E40002093E90040E050E01F910F91F4CA82E036 -:101E50001F910F910895CF93C62F20913D022430FA -:101E6000F1F4FC014489558966897789452B462B15 -:101E7000472BA9F081818F708093E9008091E80061 -:101E800085FF04C0C093F10080E00AC08091E800A3 -:101E90008E778093E800B3DC8823A1F301C082E051 -:101EA000CF91089520913D02243029F5FC01448909 -:101EB000558966897789452B462B472BE1F081812F -:101EC0008F708093E9008091F200811102C080E060 -:101ED00008959091E8008091E8008E778093E80063 -:101EE00095FDF5CF8CDC811107C09091E8009E77BD -:101EF0009093E800089582E0089520913D022430F7 -:101F000089F4FC014489558966897789452B462BDC -:101F1000472B41F021812F702093E9002091E800A8 -:101F200020FDC0CF089520913D02243019F02FEFFD -:101F30003FEF24C0FC014489558966897789452B88 -:101F4000462B472BA1F386818F708093E900809107 -:101F5000E80082FFECCF8091F200882321F02091ED -:101F6000F10030E002C02FEF3FEF8091F2008111CD -:101F700005C08091E8008B778093E800C90108953F -:101F80000895CF93DF93EC018091E80083FFA9C00F -:101F9000888190E02091420230914302281739074E -:101FA00009F09FC080913F02813261F020F48032BD -:101FB00009F097C03DC0823209F46EC0833209F047 -:101FC00090C07FC080913E02813A09F08AC0809122 -:101FD000E800877F8093E8008091E80080FFFCCFD5 -:101FE0004C895D896E897F894093F100BB27A72FBB -:101FF000962F852F8093F100CB01AA27BB278093D2 -:10200000F100472F5527662777274093F100888DE9 -:102010008093F100898D8093F1008A8D8093F10087 -:102020008091E8008E778093E800DF91CF91C6CB56 -:1020300080913E02813209F054C08091E800877F90 -:102040008093E80005C080913D02882309F449C0CF -:102050008091E80082FFF7CF3091F1002091F100EC -:102060009091F1008091F1003C8B2D8B9E8B8F8B9A -:102070008091F100888F8091F100898F8091F1002B -:102080008A8F8091E8008B778093E80097DBCE0100 -:10209000DF91CF910C94E50180913E02813209F5E8 -:1020A0008091E800877F8093E80088DB8091400280 -:1020B00090914102998B888BCE01DF91CF910C9446 -:1020C000800280913E02813261F48091E800877F36 -:1020D0008093E80073DB60914002CE01DF91CF91E5 -:1020E0004FCFDF91CF9108956F927F928F929F9201 -:1020F000AF92BF92CF92DF92EF92FF920F931F9316 -:10210000CF93DF9300D01F92CDB7DEB77C01ADB681 -:10211000BEB68091E80083FF07C1F701808190E09F -:1021200020914202309143022817390709F0FCC080 -:1021300080913F02833009F49EC030F4813071F009 -:10214000823009F0F1C0D4C08A3009F4B9C08B30B4 -:1021500009F4A2C0893009F0E7C04CC080913E026A -:10216000813A09F0E1C08DB69EB61A82198280913B -:102170004002109141028B83F70140858DB79EB7D5 -:10218000841B91090FB6F8949EBF0FBE8DBFCDB6CC -:10219000DEB6EFEFCE1ADE0A360150E060E070E006 -:1021A000C601EAD1412F41508E010F5F1F4F9601AA -:1021B000BE016D5F7F4FC7010E949F02F70126811C -:1021C00037812115310529F0408550E0B601C9015C -:1021D000CAD11092E9008091E800877F8093E800DF -:1021E00069817A81C30174D98091E8008B778093EB -:1021F000E80039C080913E02813209F095C08DB669 -:102200009EB6009144021091450270904002609089 -:1022100041028DB79EB7801B910B0FB6F8949EBFFD -:102220000FBE8DBFCDB6DEB6EFEFCE1ADE0A8091BF -:10223000E800877F8093E800B801C601A9D98091A2 -:10224000E8008E778093E80021E0711001C020E063 -:1022500030E0021B130B2C0D3D1D462D4150672D08 -:10226000C7010E94D002882D992D0FB6F8949EBF09 -:102270000FBE8DBF59C080913E02813A09F054C013 -:102280008091E800877F8093E8008091E80080FFDC -:10229000FCCFF701818540C080913E02813209F078 -:1022A00043C08091E800877F8093E80087DA9091AF -:1022B000400281E0911101C080E0F701818734C0C4 -:1022C00080913E02813281F58091E800877F809382 -:1022D000E80074DA8091400290914102882736E04C -:1022E000969587953A95E1F7F701958784871CC005 -:1022F00080913E02813AC1F48091E800877F80930B -:10230000E8008091E80080FFFCCFF7018485958587 -:1023100096958795969587958093F1008091E80032 -:102320008E778093E8004ADA0FB6F894BEBE0FBEEF -:10233000ADBE0F900F900F90DF91CF911F910F9135 -:10234000FF90EF90DF90CF90BF90AF909F908F90D5 -:102350007F906F9008959C01275F3F4FF90127E020 -:10236000DF011D922A95E9F721E0FC01218724EF86 -:1023700031E03587248723E0248361E00196E0C9BA -:102380004F925F926F927F928F929F92AF92BF9285 -:10239000CF92DF92EF92FF920F931F93CF93DF9331 -:1023A00000D01F92CDB7DEB77C01ADB6BEB680912E -:1023B0003D02843009F08FC08091E4009091E500E7 -:1023C000F701228533852817390709F484C08181F4 -:1023D0008F708093E9008091E80085FF7CC06DB626 -:1023E0007EB640858DB79EB7841B91090FB6F894D1 -:1023F0009EBF0FBE8DBFCDB6DEB6EFEFCE1ADE0AA2 -:102400001B821A821982460150E060E070E0C6012A -:10241000B3D08E010F5F1F4F960140E0BE016D5F8C -:102420007F4FC7010E949F02582EF7018485958532 -:10243000892B31F001E010E086859785892B11F01A -:1024400000E010E0F701C680D780C114D10489F004 -:1024500049815A81B601C40179D04424439400973C -:1024600009F4412CF701408550E0B401C6017BD04E -:1024700001C0412C89819A81892BF9F0511004C047 -:10248000411002C000FF19C0F70184859585978728 -:10249000868781818F708093E9008B818111809381 -:1024A000F10069817A8140E050E0C4010E941B0A7A -:1024B0008091E8008E778093E8008091E40090910D -:1024C000E500F70193878287862D972D0FB6F89444 -:1024D0009EBF0FBE8DBF0FB6F894BEBE0FBEADBE81 -:1024E0000F900F900F90DF91CF911F910F91FF9060 -:1024F000EF90DF90CF90BF90AF909F908F907F90A4 -:102500006F905F904F900895A1E21A2EAA1BBB1BFB -:10251000FD010DC0AA1FBB1FEE1FFF1FA217B307AF -:10252000E407F50720F0A21BB30BE40BF50B661FC5 -:10253000771F881F991F1A9469F760957095809589 -:1025400090959B01AC01BD01CF010895FB01DC0119 -:1025500004C08D910190801921F441505040C8F77A -:10256000881B990B0895FB01DC0102C001900D92BC -:1025700041505040D8F70895DC0101C06D9341509F -:0A2580005040E0F70895F894FFCFF3 -:10258A0002812000000100003F000000000000005E -:10259A00008340000001044000000182080000019D -:0E25AA000000000000000000000000302000D3 -:00000001FF diff --git a/plugins/KeyboardioHID/Firmwares/Hoodloader1_7_3.hex b/plugins/KeyboardioHID/Firmwares/Hoodloader1_7_3.hex new file mode 100644 index 0000000000..a5f35cfc18 --- /dev/null +++ b/plugins/KeyboardioHID/Firmwares/Hoodloader1_7_3.hex @@ -0,0 +1,613 @@ +:1000000073C100008DC100008BC1000089C10000D8 +:1000100087C1000085C1000083C1000081C10000CC +:100020007FC100007DC100007BC100000C94BC0CAE +:100030000C94680D75C1000073C1000071C100000F +:100040006FC100006DC100006BC1000069C10000FC +:1000500067C1000065C1000063C1000012C200005A +:100060005FC100005DC100005BC1000059C100001C +:1000700057C1000030034100720064007500690040 +:100080006E006F00200048006F006F0064006C007D +:100090006F0061006400650072002000420065008E +:1000A00074006100000012034E00690063006F00DD +:1000B00048006F006F006400000004030904090297 +:1000C0005F00030100C032080B00020202010009B8 +:1000D00004000001020201000524001001042402B2 +:1000E000060524060001070582030800FF09040134 +:1000F00000020A0000000705040240000107058312 +:10010000024000010904020001030000000921115E +:1001100001000122B801070581032000011201102E +:1001200001EF020108EB03686E73010102DC0105B7 +:10013000010902A1010901A100850105091901298F +:10014000051500250195057501810295017503814D +:100150000305010930093109381581257F75089596 +:10016000038106C0C005010906A101850205071922 +:10017000E029E715002501750195088102950175B3 +:1001800008810395067508150025650507190029DE +:1001900065810005081901290595057501910295EC +:1001A0000175039103C006C0FF0A000CA10185037D +:1001B0007508150026FF00953F09018102953F094A +:1001C000029102C0050C0901A1018504150026FF5A +:1001D000FF19002AFFFF950475108100C005010971 +:1001E00080A1018505150026FF00190029FF950152 +:1001F00075088100C005010905A1018506050919D9 +:10020000012920150025017501952081020501A114 +:10021000000930093109320933093409351500273D +:10022000FFFF0000751095068102C005010939091C +:100230003915012508950275048102C005010905DB +:10024000A10185070509190129201500250175015E +:10025000952081020501A1000930093109320933D5 +:1002600009340935150027FFFF0000751095068138 +:1002700002C0093909391501250895027504810262 +:10028000C005010904A1018508A10005091901297A +:100290000215002501750195028102050109300949 +:1002A00031150026FF03750A95028102750295013A +:1002B0008103C0C005010904A1018509A100050948 +:1002C0001901290215002501750195028102050118 +:1002D00009300931150026FF03750A950281027560 +:1002E0000295018103C0C00011241FBECFEFD2E0F0 +:1002F000DEBFCDBF11E0A0E0B1E0E0E1F6E202C078 +:1003000005900D92AE32B107D9F712E0AEE2B1E03E +:1003100001C01D92A634B107E1F7BFD70C940613B4 +:100320006FCE9BB1809589238BB908959BB1982B93 +:100330009BB90895CF93DF9384B7877F84BF28E16B +:100340000FB6F89420936000109260000FBE80E119 +:1003500090E09093CD008093CC00CAECD0E096E082 +:100360009883A8ECB0E082E08C93E9ECF0E0208385 +:10037000539A5A9A5B9A10821C92188298838C9393 +:1003800088E980835B988AB180638AB98BB1806386 +:100390008BB90E94AD0C84E085BD5F9A579A209A74 +:1003A00022982A9ADF91CF9108950895089580E0C8 +:1003B00091E00E94EE1180E191E00E942B0FE2EEAD +:1003C000F0E080818460808308951F93CF93DF9352 +:1003D000EC01E98DE150E23028F4F0E0E55DFE4FFC +:1003E000108101C010E0888D823009F418608A8D78 +:1003F000873031F0883031F0863029F4126003C044 +:10040000146001C016605B9A1092C9001092C80077 +:100410001092CA002C893D894E895F89211581EE91 +:1004200038074105510579F0CA01B90196958795BC +:100430007795679560587B47814E9F4F0E94C71202 +:100440002150310902C020E130E03093CD002093EB +:10045000CC001093CA008C899D89AE89BF89811513 +:10046000914EA105B10511F480E001C082E08093B6 +:10047000C80088E98093C9005B98DF91CF911F91F4 +:1004800008951F920F920FB60F9211242F933F934E +:100490008F939F93AF93BF93EF93FF938091CE0081 +:1004A00090912E019330F9F090913D029430D9F45F +:1004B000EFE2F1E0A081B1818C938081918101967E +:1004C00091838083268137818217930721F4848169 +:1004D0009581918380832FB7F894828593850196C7 +:1004E000938782872FBFFF91EF91BF91AF919F912B +:1004F0008F913F912F910F900FBE0F901F901895E5 +:10050000FC01208920FF02C05F9808955F9A8BB19B +:1005100080638BB9089580E191E00E94041080E02F +:1005200091E00C94B71080910E0190910F0100970B +:1005300029F0019790930F0180930E010895EF9297 +:10054000FF920F931F93CF93DF937B01C901E801C3 +:10055000E091BD01EE2319F14091BE012091BF0150 +:1005600042131DC051E05093FF01F0E0E150FE4FF7 +:100570005083E0ECF1E050E0BF010E94F612809160 +:10058000BD01F70180838091BE018883198210929A +:10059000BD011092BF011092BE0181E001C080E058 +:1005A000DF91CF911F910F91FF90EF900895EF92FF +:1005B000FF920F931F93CF93DF931F92CDB7DEB7B8 +:1005C0007901633081F480E16983ABDE69816093F6 +:1005D000BC01B801C7010F90DF91CF911F910F911E +:1005E000FF90EF905BC70F90DF91CF911F910F911C +:1005F000FF90EF900895109215021092090208954D +:1006000020912E018091240190912501A091260135 +:10061000B09127010097A105B10539F0811532ECA1 +:10062000930731E0A307B10521F41A9B02C082E0D1 +:1006300007C00197A105B10511F483E001C081E075 +:1006400080932E0180912E01281709F44BC023308E +:1006500011F021111DC0EFE2F1E02FB7F8948BE308 +:1006600091E09183808393838283958384838BEB52 +:1006700091E09783868380E890E091878087138656 +:1006800012862FBF1092BB011092BC0180E34EDE98 +:1006900080912E01823041F4AEDF1092BD010895A9 +:1006A00080E091E00E9403128091BD01882331F027 +:1006B0009091BE018091BF01981791F380912E0116 +:1006C000833081F41092300110922F011092320188 +:1006D00010923101109234011092330180E326DE32 +:1006E00022982A9A08950F931F93CF93DF931F9216 +:1006F000CDB7DEB78C0180E191E069830E94C00F25 +:10070000809111018F708093E90049818091E80008 +:1007100080FFFCCF8091200180FF0BC050E0B8012A +:1007200080E191E00F90DF91CF911F910F910C9498 +:10073000500F0F90DF91CF911F910F910895CF929D +:10074000DF92EF92FF920F931F93FA018B010095B6 +:10075000109520E030E0980111270027AB0160E000 +:1007600070E0042B152B262B372B4CE150E097E043 +:1007700068017901042E04C0F694E794D794C794D5 +:100780000A94D2F76C2D683028F0973059F4C08263 +:1007900096E008C0C0829150C11004C04750510972 +:1007A000923031F7492F425013C0DF01A40FB11D21 +:1007B00068017901E894C7F8DD24EE24FF24CC9287 +:1007C000B7E03695279517950795BA95D1F741501B +:1007D0004111EBCF492F50E09A01A3E0220F331FC4 +:1007E000AA95E1F7206C3F6F3081322B3083E40F04 +:1007F000F51F319781508F7380688083892F1F91F7 +:100800000F91FF90EF90DF90CF900895CF93DF93FB +:1008100000D000D000D0CDB7DEB76091BD01662317 +:10082000A1F08091BF01811110C070E07160AE0134 +:100830004F5F5F4F81E083DF682FCE01019653DF6A +:1008400004C080E091E00E9403128091BD018823E2 +:1008500031F09091BE018091BF01981791F31092F1 +:10086000BD011092BF011092BE0126960FB6F894FA +:10087000DEBF0FBECDBFDF91CF9108950F931F93C1 +:10088000982F40911502E42FF0E0E15FFD4F808347 +:10089000809115028F5F80931502892F807C8038AC +:1008A00009F444C0803C09F05FC0292F28732695C5 +:1008B00026952695223008F477C0273079F4492F01 +:1008C0004F7050E060E070E040930A0250930B02DA +:1008D00060930C0270930D0215E00FC0892F877092 +:1008E00090E0A0E0B0E080930A0290930B02A09306 +:1008F0000C02B0930D02122F11508091090288232F +:1009000091F084DF6091150261508FE092E0EBDEA0 +:10091000E0911502F0E0E25FFD4F808180930F02CD +:1009200081E0809315021093090245C0809109026D +:100930008130D1F500910A0210910B0220910C0236 +:1009400030910D02A90166277727222733274027F8 +:100950005127622773274F3F5F4F6105710521F5CE +:10096000892F8F738F5F28C0809109028230E0F059 +:1009700081508093090240910A0250910B026091CC +:100980000C0270910D0227E0440F551F661F771F60 +:100990002A95D1F7492B40930A0250930B0260939A +:1009A0000C0270930D0207C031DF609115028FE0D9 +:1009B00092E099DE20DE80E01F910F910895CF93A1 +:1009C0005DDFC82F811105C07FC080E091E00E94EB +:1009D00003128091BD01882331F02091BE019091D6 +:1009E000BF01291791F3C130A9F590910B02913005 +:1009F00089F50CDF90910A029093BD011092BF011E +:100A00008FE3E0ECF1E0DF01282F1D922A95E9F752 +:100A10009530A9F058F4923081F018F49130C1F477 +:100A20000AC0933091F0943099F407C0983050F098 +:100A30009A3070F409C084E008C088E006C0C09312 +:100A4000BE0140C081E101C083E08093BE013AC095 +:100A5000DDDE38C0882381F16091BF01462F50E070 +:100A60008C2F90E09A012E5F3F4F359527952F5F91 +:100A70003F4F8217930701F5FA01E054FE4F809132 +:100A80000A028083E62FEF5FE093BF018091BE01F1 +:100A90008E1749F0F0E0E054FE4F90910B029083E6 +:100AA0006E5F6093BF019091BF0189130BC080E01E +:100AB00091E00E94031206C0A9DE609115028FE04A +:100AC00092E011DECF9197CDCF910895682F80E10C +:100AD00091E00E946E0F8823E9F080E191E00E948E +:100AE000C00F0E940F0F80E11CDC2FEF81EE94E01D +:100AF000215080409040E1F700C0000080E111DC0F +:100B00002FEF81EE94E0215080409040E1F700C04B +:100B10000000E9CF089580E191E00E94D60F97FD93 +:100B2000FACF0895EF92FF920F931F93CF93DF9325 +:100B30007C0109E311E0C0E0D0E005C0ECDFF80182 +:100B400081938F012196CE15DF05C4F3DF91CF91FC +:100B50001F910F91FF90EF9008959091450180E0D3 +:100B600020914601820F911D9093360180933501AB +:100B70009091470180E020914801820F911D909350 +:100B80003801809337010895CF93C82FC4DF803296 +:100B900039F484E19BDF8C2F99DF80E1CF9196CFF0 +:100BA00085E194DF80912F0190913001019690931F +:100BB000300180932F01CF910895813859F018F4B6 +:100BC000803871F405C0823839F0833949F406C0A1 +:100BD00082E007C081E005C082E103C083E501C077 +:100BE00080E0D2CF98DF803221F484E16FDF80E1B2 +:100BF0006DCF80E296DB2FEF80E792E021508040BE +:100C00009040E1F700C0000080E290DB2FEF80E72A +:100C100092E0215080409040E1F700C0000080E267 +:100C200080DB2FEF80E792E0215080409040E1F799 +:100C300000C0000080E27ADB85E148DF80912F016F +:100C40009091300101969093300180932F01089587 +:100C500083E58CBD8DB58EB508950DB407FEFDCF2F +:100C600008958EBDFADF8EB50895CF93DF9300D03F +:100C70001F92CDB7DEB72B834A836983F2DF698188 +:100C8000862FEFDF4A81842FECDF2B81822F0F909C +:100C90000F900F90DF91CF91E4CFDADF249A2C9A56 +:100CA000219A29982FEF80E792E0215080409040D0 +:100CB000E1F700C000002C982FEF80E792E0215070 +:100CC00080409040E1F700C000002398229A20E085 +:100CD00040E063E58CEAC9DF81E090E09093320167 +:100CE000809331010895462F880F880F880F20E0E8 +:100CF000672F805EBACF0F931F93CF93DF938C0142 +:100D0000C0E0D0E019C0609133017091340180E0FF +:100D1000EADFDCDE609133017091340181E0E3DFD2 +:100D2000D5DE20913301309134012F5F3F4F309356 +:100D30003401209333012296C017D10724F380E1B8 +:100D4000DF91CF911F910F91089584E090E0EADE4A +:100D500020913C0140913B0160913A018091390121 +:100D600084DF12CFD8DE803259F080912F0190912C +:100D7000300101969093300180932F0185E115C0D9 +:100D800084E1A4DE20E040E060E080E36EDF9EDEF0 +:100D900020E041E060E080E368DF98DE20E042E0B0 +:100DA00060E080E362DF92DE80E190CE23982298BB +:100DB000229A2198249810923201109231010895BC +:100DC000CF92DF92EF92FF920F931F93CF93DF9317 +:100DD000D82FC92F7B01CB01A5DE80E2A7DAE9E39A +:100DE000CE2EE1E0DE2E0D2F1C2FE80111C0F60102 +:100DF00021916F014C2F6D2F80EC37DFFFE722E34D +:100E000082E0F15020408040E1F700C000002196D0 +:100E1000CE01801B910B8E159F054CF380E281DA89 +:100E200080E1DF91CF911F910F91FF90EF90DF90C4 +:100E3000CF9008950F931F93CF93DF93C091330109 +:100E4000D0913401209137013091380128173907AA +:100E500024F0CC0FDD1F8C0112C080912F019091E6 +:100E6000300101969093300180932F0181E10EC0F3 +:100E700060E270E0CE01A4DFA096005211090132B9 +:100E80001105B4F7B801CE019BDF80E1DF91CF916E +:100E90001F910F910895EF92FF920F931F93CF939D +:100EA000DF937C010091330110913401000F111F79 +:100EB000E80107C02FEF4C2F6D2F80EAD6DE06DE4B +:100EC0002196CE01801B910B8E159F059CF380E12E +:100ED000DF91CF911F910F91FF90EF9008951F9395 +:100EE000CF93DF9318DED82F16DEC82F14DE182F0D +:100EF00012DE803259F080912F01909130010196DD +:100F00009093300180932F0185E113C03D2F20E0A5 +:100F1000C9018C0F911DEC0184E1D8DD163419F460 +:100F2000CE01E9DE06C0153419F4CE01B4DF01C0EC +:100F300081E1DF91CF911F91C9CDCF93DF9300D095 +:100F4000CDB7DEB7482F80E249839A83EFD920E0FE +:100F500049819A81692F8CE488DE2FEF86E791E042 +:100F6000215080409040E1F700C0000080E20F90E7 +:100F70000F90DF91CF91D5C98091350190913601C5 +:100F800020913301309134018032910511F4207F9A +:100F90000EC08034910511F4207E09C0803891057F +:100FA00011F4207C04C08115914009F42078C90116 +:100FB0000895962F672F242F880F880F880F492FA9 +:100FC000805C53CECF92DF92EF92FF920F931F93EC +:100FD000CF93DF936C01D0DF8C01C0E0D0E029C05B +:100FE000CBDF0817190721F0C801A7DFC5DF8C0187 +:100FF000BEE2EB2EB1E0FB2EEC0EFD1E6091330144 +:1010000070913401F701438580E0D3DF229660912F +:10101000330170913401F701448581E0CADF2091EA +:101020003301309134012F5F3F4F309334012093CF +:101030003301CC15DD05A4F2C8017FDF80E1DF912B +:10104000CF911F910F91FF90EF90DF90CF90089577 +:10105000CF93DF93EC0166DD5EDD803229F484E11D +:1010600035DDCE01AFDF0AC080912F0190913001B4 +:1010700001969093300180932F0185E1DF91CF910C +:1010800025CDCF93DF9347DDD82F80E0C82F43DDF8 +:10109000C80FD11DC13081E0D80764F081E116DDB1 +:1010A00080912F01909130010196909330018093AF +:1010B0002F0122C030DD863421F4CE01DF91CF91A3 +:1010C000C7CF8534A9F4CE01B5DEC82F24DD803228 +:1010D00021F484E1FBDC8C2F0CC080912F019091D6 +:1010E000300101969093300180932F0185E101C07A +:1010F00081E1DF91CF91EACCDF91CF910895CF9339 +:10110000DF938091310190913201892B19F080E2B7 +:1011100008D902C080E20AD980912F019091300154 +:10112000892B19F080E1FDD802C080E1FFD880E171 +:1011300091E03CD797FDAEC08135910509F485C09B +:10114000E4F48134910509F452C054F480339105DC +:1011500099F181339105A9F1809709F089C07EC08A +:101160008534910509F44EC08035910509F44EC0CF +:101170008234910509F07CC03EC08136910509F4A6 +:1011800059C06CF48635910509F45CC08036910530 +:1011900009F44FC08535910509F06AC039C084371C +:1011A000910509F44CC08537910509F454C0843683 +:1011B000910509F05DC040C01092300110922F01DE +:1011C0001EC0A9DC803209F065C084E17FDC81E4C7 +:1011D0007DDC86E57BDC82E579DC80E277DC89E416 +:1011E00075DC83E573DC80E571DC80E150C093DC65 +:1011F000DF91CF91E2CC84E190E094DCAEDCDF9132 +:10120000CF91F0CC85E090E08DDCF9CF46DDF7CFD3 +:1012100082DCC82FD0E0D0933401C09333017BDC53 +:10122000382F20E02C0F3D1F3093340120933301E1 +:10123000E6CF71DC70DCE3CFDF91CF9122CFDF917D +:10124000CF914DCEDF91CF9180CD10923001109291 +:101250002F01ACDDD4CFDF91CF9184CD80912F01D0 +:101260009091300101969093300180932F010EC030 +:1012700080912F01909130010196909330018093DD +:101280002F0149DC803211F482E101C085E1DF9158 +:10129000CF911CCCDF91CF91089510922E018AE05E +:1012A000EFEFF1E0DF011D928A95E9F743D87894DA +:1012B000C3E0FC2E0FE211E0A3D98091FF01811160 +:1012C00001C089B180912E01833011F418DF90C0E4 +:1012D00080E191E06BD6EC0197FD0AC080E121D856 +:1012E000F092BC018091C80085FFFCCFC093CE0076 +:1012F0008FB7F894C0913901D0913A018FBF2097F0 +:1013000019F4A89949C06CC080E20BD8F092BB01D7 +:10131000809111018F708093E9008091E80080FF37 +:10132000F0CFCE01C034D10510F08FE390E0E82E6D +:10133000C0E0D0E02EC080912E01813061F0F80134 +:10134000A281B3818D91B383A28326813781A217B5 +:10135000B30781F40BC0E0913101F091320160815B +:1013600080E191E0BBD5882351F3CBCF2481358137 +:10137000338322839FB7F894228533852150310926 +:10138000338722879FBF90912E01923009F417DB9B +:101390002196EC12D0CFB5CFA89A8091BB018823BB +:1013A00099F081508093BB0181110EC080912E0174 +:1013B000823039F42BDA609115028FE092E093D9F4 +:1013C0001AD980E20E9496018091BC01882341F0E5 +:1013D00081508093BC01811103C080E10E9496017D +:1013E00080912E01823021F480E091E00E9403126E +:1013F00080E191E0C5D513D55FCF292F3327233066 +:101400003105B1F04CF42130310509F439C02230F6 +:10141000310509F03AC007C02132310539F12232D5 +:10142000310549F132C0EFE5F0E08EEB90E031C0DC +:1014300099278130910561F08230910581F0892BE7 +:1014400021F5EAEBF0E0E491F0E08AEB90E021C0D6 +:10145000E6EAF0E0E491F0E086EA90E01AC0E4E722 +:10146000F0E0E491F0E084E790E013C0E9E0F0E020 +:101470008DE091E00EC0E8EBF1E08FE291E009C071 +:10148000E2E1F0E08DE191E004C0E0E0F0E080E036 +:1014900090E0DA018D939C93CF010895680F791F36 +:1014A00009C0FC012191CF013091C80035FFFCCF6C +:1014B0002093CE0086179707A1F70895BF92CF9289 +:1014C000DF92EF92FF920F931F93CF93DF937C01F4 +:1014D0008B01EA01D7D1B82E811132C0209731F0AB +:1014E00028813981021B130BE20EF31EC12CD12C73 +:1014F00022C08091E80085FD14C08091E8008E77BD +:101500008093E800209749F0888199818C0D9D1D7A +:101510009983888325E0B22E13C0B4D1882359F073 +:101520000EC0F70181917F018093F10001501109F4 +:10153000FFEFCF1ADF0A01151105D9F601C0B82E49 +:101540008B2DDF91CF911F910F91FF90EF90DF9046 +:10155000CF90BF9008952091440230914502261704 +:10156000370748F06115710539F42091E8002E77AE +:101570002093E80001C0B9019C0180E034C0909143 +:101580003D02992309F443C0953009F442C090917B +:10159000E80093FD3AC09091E80092FD30C0909130 +:1015A000E80090FF20C08091F20090E0F901821BDA +:1015B000930B05C021912093F100615071099F01A7 +:1015C000280F391F6115710519F02830310590F386 +:1015D00081E02830310509F080E09091E8009E77A5 +:1015E0009093E8009F016115710549F68111C7CFFD +:1015F00006C080913D02882351F0853051F08091E2 +:10160000E80082FFF6CF80E0089581E0089582E04F +:10161000089583E008956115710529F42091E8008B +:101620002B772093E8009C0121C080913D02882304 +:1016300081F1853041F18091E80083FD26C08091E1 +:10164000E80082FFF2CFF90107C08091F100819399 +:101650009F016150710929F09F018091F200811171 +:10166000F4CF8091E8008B778093E80061157105D5 +:10167000E1F68091E80080FD0AC080913D02882358 +:1016800041F08530B1F783E0089581E0089580E06E +:10169000089582E008952091440230914502261772 +:1016A000370748F06115710539F42091E8002E776D +:1016B0002093E80001C0B9019C0180E035C0909101 +:1016C0003D02992309F444C0953009F443C0909138 +:1016D000E80093FD3BC09091E80092FD31C09091ED +:1016E000E80090FF21C08091F20090E0F901821B98 +:1016F000930B06C024912093F1003196615071093B +:101700009C012E0F3F1F6115710519F0283031051E +:1017100088F381E02830310509F080E09091E800FD +:101720009E779093E8009F016115710541F6811144 +:10173000C6CF06C080913D02882351F0853051F01C +:101740008091E80082FFF6CF80E0089581E008955F +:1017500082E0089583E00895982F2CC09093E900CB +:10176000981739F07091EC002091ED005091F00045 +:1017700003C0242F762F50E021FD02C09F5F1AC0C6 +:101780003091EB003E7F3093EB003091ED003D7FD8 +:101790003093ED003091EB0031603093EB007093AB +:1017A000EC002093ED005093F0002091EE0027FD17 +:1017B000E5CF07C0953090F28F708093E90081E00B +:1017C000089580E008950F931F93CF93DF93062F22 +:1017D000EC0110E02EC09881911103C01F5F259687 +:1017E00028C02C81E981FA816B81892F8F70853027 +:1017F00010F080E021C0223010F056E001C052E02D +:1018000028E030E040E003C04F5F220F331F2E1767 +:101810003F07D0F34295407F452B991F9927991F89 +:101820006295660F660F607C692B96DF8111D6CFBB +:10183000E0CF1013D0CF81E0DF91CF911F910F91B6 +:10184000089580913E0287FD05C08091E80080FFE9 +:101850000EC012C08091E80082FD05C080913D025B +:101860008111F8CF08958091E8008B7708C08091AE +:101870003D028111EACF08958091E8008E77809330 +:10188000E80008958091E4009091E50045E62091FC +:10189000EC0020FD1FC023C020913D02222391F0C7 +:1018A000253091F02091EB0025FD10C02091E4003F +:1018B0003091E5002817390751F34150C90139F734 +:1018C00084E0089582E0089583E0089581E008951A +:1018D00080E008952091E80020FFDECFF9CF20912D +:1018E000E80022FFD9CFF4CF41D043D08091D80077 +:1018F0008F778093D8008091D80080688093D8003B +:101900008091D8008F7D8093D80084E089BD86E0E7 +:1019100089BD09B400FEFDCF10923D02109239023C +:1019200010923B0210923A0242E060E080E014DF45 +:101930008091E1008E7F8093E1008091E2008160E0 +:101940008093E2008091E20088608093E2008091C1 +:10195000E0008E7F8093E0000895E3E6F0E0808170 +:101960008E7F808381E080933C02BECF1092E200A4 +:1019700008951092E10008951F920F920FB60F92F2 +:1019800011242F933F934F935F936F937F938F9384 +:101990009F93AF93BF93EF93FF938091E10082FFFA +:1019A0000BC08091E20082FF07C08091E1008B7F35 +:1019B0008093E1000E9493028091E10080FF18C0B3 +:1019C0008091E20080FF14C08091E2008E7F8093BE +:1019D000E2008091E20080618093E2008091D80073 +:1019E00080628093D80019BC10923D020E94D601FB +:1019F0008091E10084FF30C08091E20084FF2CC020 +:101A000084E089BD86E089BD09B400FEFDCF8091E8 +:101A1000D8008F7D8093D8008091E1008F7E8093E5 +:101A2000E1008091E2008F7E8093E2008091E200ED +:101A300081608093E20080913902882311F084E074 +:101A400007C08091E30087FF02C083E001C081E00E +:101A500080933D020E94D5018091E10083FF27C061 +:101A60008091E20083FF23C08091E100877F809313 +:101A7000E10082E080933D02109239028091E10002 +:101A80008E7F8093E1008091E2008E7F8093E20060 +:101A90008091E20080618093E20042E060E080E0BB +:101AA0005BDE8091F00088608093F000B7D1FF91F9 +:101AB000EF91BF91AF919F918F917F916F915F91C6 +:101AC0004F913F912F910F900FBE0F901F9018953F +:101AD0001F920F920FB60F9211242F933F934F93A3 +:101AE0005F936F937F938F939F93AF93BF93CF93A6 +:101AF000EF93FF938091E9008F709091EC0090FF3D +:101B000002C090E801C090E0C92FC82B1092E900F4 +:101B10008091F000877F8093F00078941CD0109221 +:101B2000E9008091F00088608093F000CF70C0934E +:101B3000E900FF91EF91CF91BF91AF919F918F916C +:101B40007F916F915F914F913F912F910F900FBEB9 +:101B50000F901F9018951F93CF93DF93CDB7DEB7EB +:101B6000AC970FB6F894DEBF0FBECDBFEEE3F2E048 +:101B70008091F100819322E0E634F207C9F70E94D8 +:101B80008B028091E80083FF31C180913E029091E9 +:101B90003F02953009F487C038F49130B1F170F00C +:101BA000933009F023C131C0983009F4F3C0993063 +:101BB00009F4FFC0963009F019C19BC0803821F0AC +:101BC000823809F013C108C080913A0290913B021B +:101BD000992389F082600FC0809142029091430264 +:101BE0008F7099278093E9008091EB0085FB88270F +:101BF00080F91092E9009091E800977F9093E800B7 +:101C00008093F1001092F100D0C0882319F0823047 +:101C100009F0ECC08F7121F0823009F0E7C00BC0F1 +:101C200080914002813009F0E1C0933009F080E0FA +:101C300080933B022FC08091400281112BC0809184 +:101C40004202909143028F709927009709F4CEC009 +:101C50008093E9002091EB0020FF1CC020913F02FF +:101C6000233021F48091EB00806212C09091EB0050 +:101C700090619093EB0021E030E001C0220F8A9543 +:101C8000EAF72093EA001092EA008091EB00886066 +:101C90008093EB001092E9008091E800877F8093A9 +:101CA000E800CFDDA3C08111A1C0809140029091D6 +:101CB00041028F779927182F9091E3009078982B05 +:101CC0009093E3008091E800877F8093E800B9DD7E +:101CD0008091E80080FFFCCF8091E30080688093D2 +:101CE000E300112311F083E001C082E080933D0204 +:101CF0007DC08058823008F079C080914002909178 +:101D000041028C3D23E0920771F583E08A838AE2E9 +:101D100089834FB7F894DE01139620E03EE051E24C +:101D2000E32FF0E050935700E49120FF03C0E295C9 +:101D3000EF703F5FEF708E2F90E0EA3010F0C796A3 +:101D400001C0C0968D939D932F5F243149F74FBFFB +:101D50008091E800877F8093E8006AE270E0CE011E +:101D60000196F9DB11C0AE01455D5F4F6091420203 +:101D700044DB0097D9F12091E800277F2093E80009 +:101D8000BC018BA59CA587DC8091E8008B778093B4 +:101D9000E8002CC0803851F58091E800877F80935F +:101DA000E800809139028093F1008091E8008E77FD +:101DB00076CF81111BC0909140029230B8F480918F +:101DC000E800877F8093E800909339023ADD8091A4 +:101DD0003902811104C08091E30087FF02C084E0D2 +:101DE00001C081E080933D020E94D7018091E8000C +:101DF00083FF0AC08091E800877F8093E80080918C +:101E0000EB0080628093EB00AC960FB6F894DEBFD7 +:101E10000FBECDBFDF91CF911F9108950895CF934D +:101E200080913D028823A9F08091E9008F70909104 +:101E3000EC0090FF02C090E801C090E0C92FC82BD1 +:101E40001092E9008091E80083FD85DECF70C09399 +:101E5000E900CF910895CF93DF93EC014096FC0108 +:101E60008BE0DF011D928A95E9F782E08C838987F8 +:101E700083E08E8761E0CE010196A5DC882361F0C6 +:101E800061E0CE0106969FDC882331F061E0CE014F +:101E90000B96DF91CF9197CC80E0DF91CF910895A1 +:101EA0000F931F93FC01CB01BA0120913D02243016 +:101EB00089F40489158926893789012B022B032B84 +:101EC00049F021812F702093E90040E050E01F91FC +:101ED0000F91F4CA82E01F910F910895CF93C62FFE +:101EE00020913D022430F1F4FC0144895589668932 +:101EF0007789452B462B472BA9F081818F708093E2 +:101F0000E9008091E80085FF04C0C093F10080E003 +:101F10000AC08091E8008E778093E800B3DC8823C4 +:101F2000A1F301C082E0CF91089520913D022430B9 +:101F300029F5FC014489558966897789452B462B0B +:101F4000472BE1F081818F708093E9008091F2004E +:101F5000811102C080E008959091E8008091E8002E +:101F60008E778093E80095FDF5CF8CDC811107C05A +:101F70009091E8009E779093E800089582E008959C +:101F800020913D02243089F4FC01448955896689F9 +:101F90007789452B462B472B41F021812F702093C9 +:101FA000E9002091E80020FDC0CF089520913D0276 +:101FB000243019F02FEF3FEF24C0FC0144895589EC +:101FC00066897789452B462B472BA1F386818F7035 +:101FD0008093E9008091E80082FFECCF8091F200CD +:101FE000882321F02091F10030E002C02FEF3FEF75 +:101FF0008091F200811105C08091E8008B77809379 +:10200000E800C90108950895CF93DF93EC01809112 +:10201000E80083FFA9C0888190E0209142023091BE +:1020200043022817390709F09FC080913F0281328F +:1020300061F020F4803209F097C03DC0823209F48B +:102040006EC0833209F090C07FC080913E02813A19 +:1020500009F08AC08091E800877F8093E800809132 +:10206000E80080FFFCCF4C895D896E897F894093B1 +:10207000F100BB27A72F962F852F8093F100CB016E +:10208000AA27BB278093F100472F5527662777277C +:102090004093F100888D8093F100898D8093F10049 +:1020A0008A8D8093F1008091E8008E778093E8001C +:1020B000DF91CF91C6CB80913E02813209F054C0AE +:1020C0008091E800877F8093E80005C080913D0201 +:1020D000882309F449C08091E80082FFF7CF30914E +:1020E000F1002091F1009091F1008091F1003C8B82 +:1020F0002D8B9E8B8F8B8091F100888F8091F100CA +:10210000898F8091F1008A8F8091E8008B7780938E +:10211000E80097DBCE01DF91CF910C94E50180912F +:102120003E02813209F58091E800877F8093E800C4 +:1021300088DB8091400290914102998B888BCE017F +:10214000DF91CF910C94800280913E02813261F444 +:102150008091E800877F8093E80073DB6091400204 +:10216000CE01DF91CF914FCFDF91CF9108956F9244 +:102170007F928F929F92AF92BF92CF92DF92EF9217 +:10218000FF920F931F93CF93DF9300D01F92CDB791 +:10219000DEB77C01ADB6BEB68091E80083FF07C113 +:1021A000F701808190E0209142023091430228178C +:1021B000390709F0FCC080913F02833009F49EC0CA +:1021C00030F4813071F0823009F0F1C0D4C08A302F +:1021D00009F4B9C08B3009F4A2C0893009F0E7C016 +:1021E0004CC080913E02813A09F0E1C08DB69EB6A6 +:1021F0001A82198280914002109141028B83F7016B +:1022000040858DB79EB7841B91090FB6F8949EBF89 +:102210000FBE8DBFCDB6DEB6EFEFCE1ADE0A3601A9 +:1022200050E060E070E0C601EAD1412F41508E01DC +:102230000F5F1F4F9601BE016D5F7F4FC7010E9468 +:102240009F02F701268137812115310529F040854C +:1022500050E0B601C901CAD11092E9008091E800AE +:10226000877F8093E80069817A81C30174D9809166 +:10227000E8008B778093E80039C080913E0281327C +:1022800009F095C08DB69EB60091440210914502AA +:1022900070904002609041028DB79EB7801B910BF9 +:1022A0000FB6F8949EBF0FBE8DBFCDB6DEB6EFEF72 +:1022B000CE1ADE0A8091E800877F8093E800B8019B +:1022C000C601A9D98091E8008E778093E80021E0CB +:1022D000711001C020E030E0021B130B2C0D3D1DDE +:1022E000462D4150672DC7010E94D702882D992D98 +:1022F0000FB6F8949EBF0FBE8DBF59C080913E02AD +:10230000813A09F054C08091E800877F8093E8000B +:102310008091E80080FFFCCFF701818540C080916B +:102320003E02813209F043C08091E800877F8093AC +:10233000E80087DA9091400281E0911101C080E0CD +:10234000F701818734C080913E02813281F580910E +:10235000E800877F8093E80074DA809140029091D2 +:102360004102882736E0969587953A95E1F7F7017F +:10237000958784871CC080913E02813AC1F4809188 +:10238000E800877F8093E8008091E80080FFFCCF21 +:10239000F701848595859695879596958795809381 +:1023A000F1008091E8008E778093E8004ADA0FB65A +:1023B000F894BEBE0FBEADBE0F900F900F90DF9190 +:1023C000CF911F910F91FF90EF90DF90CF90BF9032 +:1023D000AF909F908F907F906F9008959C01275FA2 +:1023E0003F4FF90127E0DF011D922A95E9F721E02F +:1023F000FC01218724EF31E03587248723E0248303 +:1024000061E00196E0C94F925F926F927F928F9246 +:102410009F92AF92BF92CF92DF92EF92FF920F9373 +:102420001F93CF93DF9300D01F92CDB7DEB77C010F +:10243000ADB6BEB680913D02843009F08FC0809168 +:10244000E4009091E500F7012285338528173907CC +:1024500009F484C081818F708093E9008091E80045 +:1024600085FF7CC06DB67EB640858DB79EB7841B58 +:1024700091090FB6F8949EBF0FBE8DBFCDB6DEB6E4 +:10248000EFEFCE1ADE0A1B821A821982460150E053 +:1024900060E070E0C601B3D08E010F5F1F4F960160 +:1024A00040E0BE016D5F7F4FC7010E949F02582E22 +:1024B000F70184859585892B31F001E010E0868550 +:1024C0009785892B11F000E010E0F701C680D780D6 +:1024D000C114D10489F049815A81B601C40179D06F +:1024E00044244394009709F4412CF701408550E0BF +:1024F000B401C6017BD001C0412C89819A81892B0E +:10250000F9F0511004C0411002C000FF19C0F701DA +:10251000848595859787868781818F708093E90070 +:102520008B8181118093F10069817A8140E050E0D4 +:10253000C4010E945E0A8091E8008E778093E800D3 +:102540008091E4009091E500F70193878287862DC2 +:10255000972D0FB6F8949EBF0FBE8DBF0FB6F8949F +:10256000BEBE0FBEADBE0F900F900F90DF91CF910A +:102570001F910F91FF90EF90DF90CF90BF90AF90A1 +:102580009F908F907F906F905F904F900895A1E201 +:102590001A2EAA1BBB1BFD010DC0AA1FBB1FEE1FDD +:1025A000FF1FA217B307E407F50720F0A21BB30B28 +:1025B000E40BF50B661F771F881F991F1A9469F7A4 +:1025C00060957095809590959B01AC01BD01CF0100 +:1025D0000895FB01DC0104C08D910190801921F464 +:1025E00041505040C8F7881B990B0895FB01DC014E +:1025F00002C001900D9241505040D8F70895DC017F +:1026000001C06D9341505040E0F70895F894FFCF1A +:1026100002812000000100003F00000000000000D7 +:102620000083400000010440000001820800000116 +:0E26300000000000000000000000003020004C +:00000001FF diff --git a/plugins/KeyboardioHID/Firmwares/Arduino-usbserial-atmega16u2-Mega2560-Rev3.hex b/plugins/KeyboardioHID/Firmwares/OriginalFirmwares/Arduino-usbserial-atmega16u2-Mega2560-Rev3.hex similarity index 100% rename from plugins/KeyboardioHID/Firmwares/Arduino-usbserial-atmega16u2-Mega2560-Rev3.hex rename to plugins/KeyboardioHID/Firmwares/OriginalFirmwares/Arduino-usbserial-atmega16u2-Mega2560-Rev3.hex diff --git a/plugins/KeyboardioHID/Firmwares/Arduino-usbserial-atmega16u2-MegaADK-Rev3.hex b/plugins/KeyboardioHID/Firmwares/OriginalFirmwares/Arduino-usbserial-atmega16u2-MegaADK-Rev3.hex similarity index 100% rename from plugins/KeyboardioHID/Firmwares/Arduino-usbserial-atmega16u2-MegaADK-Rev3.hex rename to plugins/KeyboardioHID/Firmwares/OriginalFirmwares/Arduino-usbserial-atmega16u2-MegaADK-Rev3.hex diff --git a/plugins/KeyboardioHID/Firmwares/Arduino-usbserial-atmega16u2-Uno-Rev3.hex b/plugins/KeyboardioHID/Firmwares/OriginalFirmwares/Arduino-usbserial-atmega16u2-Uno-Rev3.hex similarity index 100% rename from plugins/KeyboardioHID/Firmwares/Arduino-usbserial-atmega16u2-Uno-Rev3.hex rename to plugins/KeyboardioHID/Firmwares/OriginalFirmwares/Arduino-usbserial-atmega16u2-Uno-Rev3.hex diff --git a/plugins/KeyboardioHID/Firmwares/Readme.md b/plugins/KeyboardioHID/Firmwares/Readme.md index 45e0dd83e8..bfe6de1e09 100644 --- a/plugins/KeyboardioHID/Firmwares/Readme.md +++ b/plugins/KeyboardioHID/Firmwares/Readme.md @@ -1,3 +1,5 @@ Firmwares ========= [**See installing instructions on the Hoodloader repository**](https://github.com/NicoHood/Hoodloader) + +There are also other/older Versions of the Hoodloader and the Lite Version for 8u2. \ No newline at end of file diff --git a/plugins/KeyboardioHID/HID_Source/HID.h b/plugins/KeyboardioHID/HID_Source/HID.h index 1ecc876d29..30191425e4 100644 --- a/plugins/KeyboardioHID/HID_Source/HID.h +++ b/plugins/KeyboardioHID/HID_Source/HID.h @@ -111,7 +111,7 @@ class Mouse_{ 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 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 void releaseAll(void); @@ -236,10 +236,11 @@ extern Keyboard_ Keyboard; class RawHID_ : public Print{ public: RawHID_(void); + inline void begin(void){ /*empty*/ } + inline void end(void){ /*empty*/ } using Print::write; // to get the String version of write size_t write(uint8_t b); size_t write(const uint8_t *buffer, size_t size); - }; extern RawHID_ RawHID; @@ -315,15 +316,15 @@ class Gamepad_{ void press(uint8_t b); void release(uint8_t b); void releaseAll(void); - inline void buttons(uint32_t b){ _report.buttons=b; } - inline void xAxis(uint16_t a){ _report.xAxis=a; } - inline void yAxis(uint16_t a){ _report.yAxis=a; } - inline void zAxis(uint16_t a){ _report.zAxis=a; } - inline void rxAxis(uint16_t a){ _report.rxAxis=a; } - inline void ryAxis(uint16_t a){ _report.ryAxis=a; } - inline void rzAxis(uint16_t a){ _report.rzAxis=a; } - inline void dPad1(uint8_t d){ _report.dPad1=d; } - inline void dPad2(uint8_t d){ _report.dPad2=d; } + inline void buttons(uint32_t b){ _report.buttons = b; } + inline void xAxis(uint16_t a){ _report.xAxis = a; } + inline void yAxis(uint16_t a){ _report.yAxis = a; } + inline void zAxis(uint16_t a){ _report.zAxis = a; } + inline void rxAxis(uint16_t a){ _report.rxAxis = a; } + inline void ryAxis(uint16_t a){ _report.ryAxis = a; } + inline void rzAxis(uint16_t a){ _report.rzAxis = a; } + inline void dPad1(uint8_t d){ _report.dPad1 = d; } + inline void dPad2(uint8_t d){ _report.dPad2 = d; } private: HID_GamepadReport_Data_t _report; uint8_t _reportID; @@ -344,9 +345,9 @@ class Joystick_{ void press(uint8_t b); void release(uint8_t b); void releaseAll(void); - inline void buttons(uint8_t b){ _report.buttons=b; } - inline void xAxis(uint16_t a){ _report.xAxis=a; } - inline void yAxis(uint16_t a){ _report.yAxis=a; } + inline void buttons(uint8_t b){ _report.buttons = b; } + inline void xAxis(uint16_t a){ _report.xAxis = a; } + inline void yAxis(uint16_t a){ _report.yAxis = a; } private: HID_JoystickReport_Data_t _report; diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index a76d19a09b..36289f8288 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -30,7 +30,7 @@ I also corrected some bugs in the original sources. **The following devices are supported:** -* Keyboard (modifiers + 6 keys) +* Keyboard (modifiers + 6 keys pressed at the same time) * Mouse (5 buttons, move, wheel) * Media Keys (4 keys for music player and more) * System Key (for PC standby/shutdown) @@ -43,7 +43,7 @@ I also corrected some bugs in the original sources. Installation Leonardo/Micro/Uno/Mega ==================================== -Download the library and install like you are used to (access the examples and save the firmware). +Download the library and install like you are used to (access the examples, keywords.txt with IDE). Then **move and replace** all files from "HID_Source" to the folder that matches your Arduino IDE version to one of these paths (depending on your version): ``` @@ -91,7 +91,7 @@ HID.begin() starts the Serial at baud 115200 on Arduino Uno/Mega. Do not call Se **Always release buttons to not cause any erros.** Replug USB cable to reset the values if anything went wrong. See [Deactivate HID function](https://github.com/NicoHood/Hoodloader) if you need to fully disable HID again. -For Arduino as ISP usage (optional, has nothing to do with HID) see [Hoodloader repository](https://github.com/NicoHood/Hoodloader). +For Arduino as ISP usage (optional, has nothing to do with HID function) see [Hoodloader repository](https://github.com/NicoHood/Hoodloader). How it works ============ @@ -130,7 +130,7 @@ Known Bugs System Wakeup is currently not working on all versions! System Shutdown is only working on Windows systems. -RawHID only works on Uno/Mega. +RawHID only works on Uno/Mega. It still has some bugs. Programming Arduino Mega with ISP doesnt work because of fuses. Burning Bootloader error is fixed with IDE 1.5.7 or higher (avrdude bug)! See this for more information: http://forum.arduino.cc/index.php?topic=126160.0 @@ -171,11 +171,21 @@ Oh and by the way: I also removed some bugs from the official firmware. Version History =============== ``` -1.7.1 Beta Release (09.08.2014) +1.7.3 Beta Release (10.08.2014) +* Changes in the Hoodloader: + * Fixed HID flush bug (1.6 - 1.7.2) + +1.7.2 Beta Release (10.08.2014) +* Changes in the Hoodloader: + * Added Lite version for 8u2 + * Added Versions that show up as Uno/Mega (not recommended) + * Makefile and structure changes + +1.7.1 Beta Release (10.08.2014) * Changes in the Hoodloader: * Fixed HID deactivation bug -1.7 Beta Release (09.08.2014) +1.7 Beta Release (10.08.2014) * Changes in the Hoodloader: * Works as ISP now. See the [Hoodloader Repository](https://github.com/NicoHood/Hoodloader) for more information. * Exceeded 8kb limit. For flashing a 8u2 use v1.6 please! diff --git a/plugins/KeyboardioHID/hardware/16u2asISP/avr/boards.txt b/plugins/KeyboardioHID/hardware/16u2asISP/avr/boards.txt deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/plugins/KeyboardioHID/hardware/16u2asISP/avr/programmers.txt b/plugins/KeyboardioHID/hardware/16u2asISP/avr/programmers.txt deleted file mode 100644 index e34a804861..0000000000 --- a/plugins/KeyboardioHID/hardware/16u2asISP/avr/programmers.txt +++ /dev/null @@ -1,8 +0,0 @@ -arduino16u2asisp.name=16u2 as ISP -arduino16u2asisp.communication=serial -arduino16u2asisp.protocol=stk500v1 -arduino16u2asisp.speed=1 -arduino16u2asisp.program.protocol=stk500v1 -arduino16u2asisp.program.speed=1 -arduino16u2asisp.program.tool=avrdude -arduino16u2asisp.program.extra_params=-P{serial.port} -b{program.speed} diff --git a/plugins/KeyboardioHID/hardware/Readme.md b/plugins/KeyboardioHID/hardware/Readme.md deleted file mode 100644 index 8680a13d8e..0000000000 --- a/plugins/KeyboardioHID/hardware/Readme.md +++ /dev/null @@ -1,8 +0,0 @@ -Hardware -======== - -Put this folder (16u2asISP) into sketchbook/hardware/ like this: -``` -Arduino/sketchbook/hardware/16u2asISP/avr/boards.txt -Arduino/sketchbook/hardware/16u2asISP/avr/programmers.txt -``` \ No newline at end of file From 38fe44c2e7fb9250c80d9dd2adf619d1758f13ac Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 24 Aug 2014 15:51:16 +0200 Subject: [PATCH 041/602] Linux Fix for Gamepad + Media Keys --- plugins/KeyboardioHID/HID_Source/HID.cpp | 11 +++++++---- plugins/KeyboardioHID/HID_Source/HID.h | 1 - plugins/KeyboardioHID/HID_Source/Readme.md | 4 +++- plugins/KeyboardioHID/Readme.md | 3 ++- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/plugins/KeyboardioHID/HID_Source/HID.cpp b/plugins/KeyboardioHID/HID_Source/HID.cpp index f632b19dc3..1758a98ef5 100644 --- a/plugins/KeyboardioHID/HID_Source/HID.cpp +++ b/plugins/KeyboardioHID/HID_Source/HID.cpp @@ -164,13 +164,16 @@ const u8 _hidReportDescriptor[] = { 0x09, 0x01, // usage -- consumer control 0xA1, 0x01, // collection (application) 0x85, HID_REPORTID_MediaReport, // report id + //0x05, 0x0C, // usage page (consumer) + // 4 media Keys 0x15, 0x00, //logical minimum - 0x26, 0xFF, 0xFF, //logical maximum (3ff) + 0x26, 0xFF, 0x03, //logical maximum (3ff) 0x19, 0x00, // usage minimum (0) - 0x2A, 0xFF, 0xFF, //usage maximum (3ff) + 0x2A, 0xFF, 0x03, //usage maximum (3ff) 0x95, 0x04, //report count (4) 0x75, 0x10, //report size (16) + 0x81, 0x00, //input 0xC0, //end collection #endif @@ -195,7 +198,7 @@ const u8 _hidReportDescriptor[] = { #ifdef HID_GAMEPAD1_ENABLE // Gamepad1 0x05, 0x01, // USAGE_PAGE (Generic Desktop) - 0x09, 0x05, // USAGE (Game Pad) + 0x09, 0x04, // USAGE (Joystick) 0xa1, 0x01, // COLLECTION (Application) 0x85, HID_REPORTID_Gamepad1Report, // REPORT_ID // 32 Buttons @@ -248,7 +251,7 @@ const u8 _hidReportDescriptor[] = { #ifdef HID_GAMEPAD2_ENABLE // Gamepad2 0x05, 0x01, // USAGE_PAGE (Generic Desktop) - 0x09, 0x05, // USAGE (Game Pad) + 0x09, 0x04, // USAGE (Joystick) 0xa1, 0x01, // COLLECTION (Application) 0x85, HID_REPORTID_Gamepad2Report, // REPORT_ID // 32 Buttons diff --git a/plugins/KeyboardioHID/HID_Source/HID.h b/plugins/KeyboardioHID/HID_Source/HID.h index 30191425e4..157000b526 100644 --- a/plugins/KeyboardioHID/HID_Source/HID.h +++ b/plugins/KeyboardioHID/HID_Source/HID.h @@ -47,7 +47,6 @@ THE SOFTWARE. //#define HID_GAMEPAD2_ENABLE 71 //#define HID_JOYSTICK1_ENABLE 51 //#define HID_JOYSTICK2_ENABLE 51 -//#define HID_MIDI_ENABLE #endif diff --git a/plugins/KeyboardioHID/HID_Source/Readme.md b/plugins/KeyboardioHID/HID_Source/Readme.md index 0324e8c0db..5e8d1ef7bc 100644 --- a/plugins/KeyboardioHID/HID_Source/Readme.md +++ b/plugins/KeyboardioHID/HID_Source/Readme.md @@ -6,4 +6,6 @@ HID Source C:\Arduino\arduino-1.0.5\hardware\arduino\cores\arduino C:\Arduino\arduino-1.5.6-r2\hardware\arduino\avr\cores\arduino C:\Arduino\arduino-1.5.7\hardware\arduino\avr\cores\arduino -``` \ No newline at end of file +``` + +Restart the IDE! \ No newline at end of file diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 36289f8288..b62e7d9428 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -32,7 +32,7 @@ I also corrected some bugs in the original sources. * Keyboard (modifiers + 6 keys pressed at the same time) * Mouse (5 buttons, move, wheel) -* Media Keys (4 keys for music player and more) +* Media Keys (4 keys for music player, webbrowser and more) * System Key (for PC standby/shutdown) * 2 Gamepads (32 buttons, 6 16bit axis, 2 D-Pads) * 2 Joysticks (2 buttons, 2 10bit axis) @@ -52,6 +52,7 @@ C:\Arduino\arduino-1.5.6-r2\hardware\arduino\avr\cores\arduino C:\Arduino\arduino-1.5.7\hardware\arduino\avr\cores\arduino ``` The installation path may differ to yours. Newer Versions than 1.5.7 may not work. +Restart the IDE! **I strongly recommend to install the library like this. Otherwise it wont work.** From 548a1bc347c732bd3fe7e0fd1f44f58262d2e35c Mon Sep 17 00:00:00 2001 From: NicoHood Date: Mon, 25 Aug 2014 03:05:43 +0200 Subject: [PATCH 042/602] Reworked library completely + HID fixes --- plugins/KeyboardioHID/Firmwares/Joystick.cpp | 63 ++ plugins/KeyboardioHID/Firmwares/Joystick.h | 55 ++ plugins/KeyboardioHID/Gamepad.h | 88 +++ .../KeyboardioHID/{HID_Source => }/HID.cpp | 715 +++--------------- plugins/KeyboardioHID/HID.h | 136 ++++ .../{HID_Source => }/HID_Reports.h | 143 ++-- plugins/KeyboardioHID/HID_Source/HID.h | 359 --------- plugins/KeyboardioHID/HID_Source/Readme.md | 11 - plugins/KeyboardioHID/HID_Source/USBAPI.h | 202 ----- plugins/KeyboardioHID/Keyboard.cpp | 291 +++++++ plugins/KeyboardioHID/Keyboard.h | 151 ++++ plugins/KeyboardioHID/Media.h | 112 +++ plugins/KeyboardioHID/Mouse.cpp | 95 +++ plugins/KeyboardioHID/Mouse.h | 69 ++ plugins/KeyboardioHID/RawHID.h | 78 ++ plugins/KeyboardioHID/Readme.md | 124 +-- plugins/KeyboardioHID/System.h | 79 ++ .../AdvancedRawHID/AdvancedRawHID.ino | 19 +- .../examples/Gamepad/Gamepad.ino | 22 +- .../examples/Joystick/Joystick.ino | 79 -- .../examples/Keyboard/Keyboard.ino | 33 +- .../KeyboardioHID/examples/Media/Media.ino | 21 +- .../KeyboardioHID/examples/Mouse/Mouse.ino | 21 +- .../KeyboardioHID/examples/System/System.ino | 21 +- plugins/KeyboardioHID/keywords.txt | 5 + 25 files changed, 1509 insertions(+), 1483 deletions(-) create mode 100644 plugins/KeyboardioHID/Firmwares/Joystick.cpp create mode 100644 plugins/KeyboardioHID/Firmwares/Joystick.h create mode 100644 plugins/KeyboardioHID/Gamepad.h rename plugins/KeyboardioHID/{HID_Source => }/HID.cpp (61%) create mode 100644 plugins/KeyboardioHID/HID.h rename plugins/KeyboardioHID/{HID_Source => }/HID_Reports.h (60%) delete mode 100644 plugins/KeyboardioHID/HID_Source/HID.h delete mode 100644 plugins/KeyboardioHID/HID_Source/Readme.md delete mode 100644 plugins/KeyboardioHID/HID_Source/USBAPI.h create mode 100644 plugins/KeyboardioHID/Keyboard.cpp create mode 100644 plugins/KeyboardioHID/Keyboard.h create mode 100644 plugins/KeyboardioHID/Media.h create mode 100644 plugins/KeyboardioHID/Mouse.cpp create mode 100644 plugins/KeyboardioHID/Mouse.h create mode 100644 plugins/KeyboardioHID/RawHID.h create mode 100644 plugins/KeyboardioHID/System.h delete mode 100644 plugins/KeyboardioHID/examples/Joystick/Joystick.ino diff --git a/plugins/KeyboardioHID/Firmwares/Joystick.cpp b/plugins/KeyboardioHID/Firmwares/Joystick.cpp new file mode 100644 index 0000000000..1985694393 --- /dev/null +++ b/plugins/KeyboardioHID/Firmwares/Joystick.cpp @@ -0,0 +1,63 @@ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +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 "Joystick.h" + +//================================================================================ +// Joystick +//================================================================================ + +Joystick_ Joystick1(HID_REPORTID_Joystick1Report); +Joystick_ Joystick2(HID_REPORTID_Joystick2Report); + +Joystick_::Joystick_(uint8_t reportID){ + _reportID = reportID; +} + +void Joystick_::begin(void){ + memset(&_report, 0, sizeof(_report)); + HID_SendReport(_reportID, &_report, sizeof(_report)); +} + +void Joystick_::end(void){ + begin(); +} + +void Joystick_::write(void){ + HID_SendReport(_reportID, &_report, sizeof(_report));; +} + +void Joystick_::press(uint8_t b){ + if (b == 1) _report.button1 = 1; + else if (b == 2) _report.button2 = 1; +} + +void Joystick_::release(uint8_t b){ + if (b == 1) _report.button1 = 0; + else if (b == 2) _report.button2 = 0; +} + +void Joystick_::releaseAll(void){ + _report.button1 = 0; + _report.button2 = 0; +} \ No newline at end of file diff --git a/plugins/KeyboardioHID/Firmwares/Joystick.h b/plugins/KeyboardioHID/Firmwares/Joystick.h new file mode 100644 index 0000000000..db0526205e --- /dev/null +++ b/plugins/KeyboardioHID/Firmwares/Joystick.h @@ -0,0 +1,55 @@ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +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 JOYSTICK_H +#define JOYSTICK_H + +#include "HID.h" + +//================================================================================ +// Joystick +//================================================================================ + +class Joystick_{ +public: + Joystick_(uint8_t reportID); + void begin(void); + void end(void); + void write(void); + void press(uint8_t b); + void release(uint8_t b); + void releaseAll(void); + inline void buttons(uint8_t b){ _report.buttons = b; } + inline void xAxis(uint16_t a){ _report.xAxis = a; } + inline void yAxis(uint16_t a){ _report.yAxis = a; } + +private: + HID_JoystickReport_Data_t _report; + uint8_t _reportID; +}; +extern Joystick_ Joystick1; +extern Joystick_ Joystick2; + +#endif + diff --git a/plugins/KeyboardioHID/Gamepad.h b/plugins/KeyboardioHID/Gamepad.h new file mode 100644 index 0000000000..edb1bdd814 --- /dev/null +++ b/plugins/KeyboardioHID/Gamepad.h @@ -0,0 +1,88 @@ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +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 GAMEPAD_H +#define GAMEPAD_H + +#include "HID.h" + +//================================================================================ +// HID +//================================================================================ + +void HID_SendReport(uint8_t id, const void* data, int len); + +//================================================================================ +// Gamepad +//================================================================================ + +class Gamepad{ +public: + inline Gamepad(uint8_t num){ + switch (num){ + case 1: + _reportID = HID_REPORTID_Gamepad1Report; + break; + case 2: + _reportID = HID_REPORTID_Gamepad1Report; + break; + case 3: + _reportID = HID_REPORTID_Gamepad1Report; + break; + case 4: + _reportID = HID_REPORTID_Gamepad1Report; + break; + default: + _reportID = HID_REPORTID_NotAReport; + break; + } + } + + inline void begin(void){ + memset(&_report, 0, sizeof(_report)); + HID_SendReport(_reportID, &_report, sizeof(_report)); + } + + inline void end(void){ begin(); } + inline void write(void){ HID_SendReport(_reportID, &_report, sizeof(_report));} + inline void press(uint8_t b){ _report.buttons |= (uint32_t)1 << (b - 1); } + inline void release(uint8_t b){ _report.buttons &= ~((uint32_t)1 << (b - 1)); } + inline void releaseAll(void){ _report.buttons = 0;} + + inline void buttons(uint32_t b){ _report.buttons = b; } + inline void xAxis(uint16_t a){ _report.xAxis = a; } + inline void yAxis(uint16_t a){ _report.yAxis = a; } + inline void zAxis(uint8_t a){ _report.zAxis = a; } + inline void rxAxis(uint16_t a){ _report.rxAxis = a; } + inline void ryAxis(uint16_t a){ _report.ryAxis = a; } + inline void rzAxis(uint8_t a){ _report.rzAxis = a; } + inline void dPad1(uint8_t d){ _report.dPad1 = d; } + inline void dPad2(uint8_t d){ _report.dPad2 = d; } +private: + HID_GamepadReport_Data_t _report; + uint8_t _reportID; +}; + +#endif + diff --git a/plugins/KeyboardioHID/HID_Source/HID.cpp b/plugins/KeyboardioHID/HID.cpp similarity index 61% rename from plugins/KeyboardioHID/HID_Source/HID.cpp rename to plugins/KeyboardioHID/HID.cpp index 1758a98ef5..77608df4db 100644 --- a/plugins/KeyboardioHID/HID_Source/HID.cpp +++ b/plugins/KeyboardioHID/HID.cpp @@ -24,29 +24,119 @@ THE SOFTWARE. #include "HID.h" //================================================================================ -// HID Leonardo/Micro +// Mouse //================================================================================ -#if defined(USBCON) +Mouse_ Mouse; -HID_ HID; +//================================================================================ +// Keyboard +//================================================================================ -HID_::HID_(void){ - // empty -} +Keyboard_ Keyboard; -void HID_::begin(void){ - // empty -} +//================================================================================ +// RawHID +//================================================================================ + +RawHID_ RawHID; -void HID_::end(void){ - // empty +//================================================================================ +// Media +//================================================================================ + +Media_ Media; + +//================================================================================ +// System +//================================================================================ + +System_ System; + +//================================================================================ +// HID Uno/Mega +//================================================================================ + +#ifndef USBCON + +void HID_SendReport(uint8_t id, const void* data, int len) +{ + // write the Report via Protocol and checksum. 16bit for each sending + // send control address + NHPwriteChecksum(NHP_ADDRESS_CONTROL, (NHP_USAGE_ARDUINOHID << 8) | id); + const uint8_t* report = (const uint8_t*)data; + for (int i = 0; i < len; i++){ + uint8_t data0 = report[i++]; + uint8_t data1 = 0; + if (i != len) + data1 = report[i]; + // valid HID reports start at Address 2 + NHPwriteChecksum(2 + i / 2, (data1 << 8) | data0); + } } -void HID_::sendReport(uint8_t ReportID, const void* HIDReport, uint8_t length){ - HID_SendReport(ReportID, HIDReport, length); +// simple copy/modification of the NicoHoodProtocol writechecksum function +void NHPwriteChecksum(uint8_t address, uint16_t indata){ + // writes two bytes with its inverse + uint32_t temp = ~indata; + uint32_t data = (temp << 16) | indata; + + // buffer for write operation + uint8_t writebuffer[6]; + + // start with the maximum size of blocks + uint8_t blocks = 7; + + // check for the first 7 bit block that doesnt fit into the first 3 bits + while (blocks > 2){ + uint8_t nextvalue = (data >> (7 * (blocks - 3))); + + if (nextvalue > NHP_MASK_DATA_3BIT){ + // special case for the MSB + if (blocks == 7) { + writebuffer[0] = nextvalue; + blocks--; + } + // this block is too big, write this into the next data block + break; + } + else{ + // write the possible first 3 bits and check again after if zero + writebuffer[0] = nextvalue; + blocks--; + // we have our first bits, stop (nonzero) + if (nextvalue) + break; + } + } + + // write the rest of the data bits + uint8_t datablocks = blocks - 2; + while (datablocks > 0){ + writebuffer[datablocks] = data & NHP_MASK_DATA_7BIT; + data >>= 7; + datablocks--; + } + + // write lead + length mask + writebuffer[0] |= NHP_MASK_LEAD | (blocks << 3); + + // write end mask + writebuffer[blocks - 1] = NHP_MASK_END | ((address - 1) & NHP_MASK_ADDRESS); + + // write the buffer + HID_SERIAL.write(writebuffer, blocks); } +#else // #ifdef USBCON + +//================================================================================ +// HID Leonardo/Micro +//================================================================================ + +#include "Platform.h" +#include "USBAPI.h" +#include "USBDesc.h" #ifdef HID_ENABLED @@ -357,7 +447,7 @@ const u8 _hidReportDescriptor[] = { 0x95, 0x01, // REPORT_COUNT (1) 0x81, 0x03, // INPUT (Cnst,Var,Abs) 0xc0, // END_COLLECTION - 0xc0 // END_COLLECTION + 0xc0, // END_COLLECTION #endif }; @@ -391,6 +481,7 @@ int WEAK HID_GetDescriptor(int /* i */) 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); } @@ -430,598 +521,6 @@ bool WEAK HID_Setup(Setup& setup) return false; } -#endif - -//================================================================================ -// HID Uno/Mega -//================================================================================ - -#else /* if defined(USBCON) */ - -HID_ HID; - -HID_::HID_(void){ - // empty -} - -void HID_::begin(void){ - HID_SERIAL.begin(115200); -} - -void HID_::end(void){ - HID_SERIAL.end(); -} - -void HID_::sendReport(uint8_t ReportID, const void* HIDReport, uint8_t length){ - // write the Report via Protocol and checksum. 16bit for each sending - // send control address - NHPwriteChecksum(NHP_ADDRESS_CONTROL, (NHP_USAGE_ARDUINOHID << 8) | ReportID); - const uint8_t* report = (const uint8_t*)HIDReport; - for (int i = 0; i < length; i++){ - uint8_t data0 = report[i++]; - uint8_t data1 = 0; - if (i != length) - data1 = report[i]; - // valid HID reports start at Address 2 - NHPwriteChecksum(2 + i / 2, (data1 << 8) | data0); - } -} -#endif /* if defined(USBCON) */ - -// simple copy/modification of the NicoHoodProtocol writechecksum function -void HID_::NHPwriteChecksum(uint8_t address, uint16_t indata){ - // writes two bytes with its inverse - uint32_t temp = ~indata; - uint32_t data = (temp << 16) | indata; - - // buffer for write operation - uint8_t writebuffer[6]; - - // start with the maximum size of blocks - uint8_t blocks = 7; - - // check for the first 7 bit block that doesnt fit into the first 3 bits - while (blocks > 2){ - uint8_t nextvalue = (data >> (7 * (blocks - 3))); - - if (nextvalue > NHP_MASK_DATA_3BIT){ - // special case for the MSB - if (blocks == 7) { - writebuffer[0] = nextvalue; - blocks--; - } - // this block is too big, write this into the next data block - break; - } - else{ - // write the possible first 3 bits and check again after if zero - writebuffer[0] = nextvalue; - blocks--; - // we have our first bits, stop (nonzero) - if (nextvalue) - break; - } - } - - // write the rest of the data bits - uint8_t datablocks = blocks - 2; - while (datablocks > 0){ - writebuffer[datablocks] = data & NHP_MASK_DATA_7BIT; - data >>= 7; - datablocks--; - } - - // write lead + length mask - writebuffer[0] |= NHP_MASK_LEAD | (blocks << 3); - - // write end mask - writebuffer[blocks - 1] = NHP_MASK_END | ((address - 1) & NHP_MASK_ADDRESS); - - // write the buffer - HID_SERIAL.write(writebuffer, blocks); -} - -//================================================================================ -// Mouse -//================================================================================ - -Mouse_ Mouse; - -Mouse_::Mouse_(void){ - // empty -} - -void Mouse_::begin(void){ - memset(&_report, 0, sizeof(_report)); - HID.sendReport(HID_REPORTID_MouseReport, &_report, sizeof(_report)); -} - -void Mouse_::end(void){ - begin(); -} - -void Mouse_::click(uint8_t b){ - _report.buttons = b; - move(0, 0, 0); - _report.buttons = 0; - move(0, 0, 0); -} - -void Mouse_::move(signed char x, signed char y, signed char wheel){ - _report.xAxis = x; - _report.yAxis = y; - _report.wheel = wheel; - HID.sendReport(HID_REPORTID_MouseReport, &_report, sizeof(HID_MouseReport_Data_t)); -} - -void Mouse_::buttons(uint8_t b){ - if (b != _report.buttons) { - _report.buttons = b; - move(0, 0, 0); - } -} - -void Mouse_::press(uint8_t b){ - buttons(_report.buttons | b); -} - -void Mouse_::release(uint8_t b){ - buttons(_report.buttons & ~b); -} - -void Mouse_::releaseAll(void){ - begin(); -} - -bool Mouse_::isPressed(uint8_t b){ - if ((b & _report.buttons) > 0) - return true; - return false; -} - -//================================================================================ -// Keyboard -//================================================================================ - -Keyboard_ Keyboard; - -Keyboard_::Keyboard_(void){ - // empty -} - -void Keyboard_::begin(void){ - memset(&_report, 0, sizeof(_report)); - HID.sendReport(HID_REPORTID_KeyboardReport, &_report, sizeof(_report)); -} - -void Keyboard_::end(void){ - begin(); -} - -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 -}; - -// removed <-- -//uint8_t USBPutChar(uint8_t c); - -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 -} - -// 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 - _report.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 - _report.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 (_report.keys[0] != k && _report.keys[1] != k && - _report.keys[2] != k && _report.keys[3] != k && - _report.keys[4] != k && _report.keys[5] != k) { - - for (i = 0; i < 6; i++) { - if (_report.keys[i] == 0x00) { - _report.keys[i] = k; - break; - } - } - if (i == 6) { - setWriteError(); - return 0; - } - } - HID.sendReport(HID_REPORTID_KeyboardReport, &_report, sizeof(_report)); - 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 - _report.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 - _report.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 && _report.keys[i] == k) { - _report.keys[i] = 0x00; - } - } - - HID.sendReport(HID_REPORTID_KeyboardReport, &_report, sizeof(_report)); - return 1; -} - -void Keyboard_::releaseAll(void){ - begin(); -} - -//================================================================================ -// RawHID -//================================================================================ - -RawHID_ RawHID; - -RawHID_::RawHID_(void){ - // empty -} - -size_t RawHID_::write(uint8_t b){ - write(&b, 1); -} - -size_t RawHID_::write(const uint8_t *buffer, size_t size){ - size_t bytesleft = size; - // first work through the buffer thats already there - while (bytesleft >= RAWHID_RX_SIZE){ - HID.sendReport(HID_REPORTID_RawKeyboardReport, &buffer[size - bytesleft], RAWHID_RX_SIZE); - bytesleft -= RAWHID_RX_SIZE; - } - // write down the other bytes and fill with zeros - if (bytesleft){ - uint8_t rest[RAWHID_RX_SIZE]; - memcpy(rest, &buffer[size - bytesleft], bytesleft); - memset(&rest[bytesleft], 0, RAWHID_RX_SIZE - bytesleft); - HID.sendReport(HID_REPORTID_RawKeyboardReport, &rest, RAWHID_RX_SIZE); - } -} - -//================================================================================ -// Media -//================================================================================ - -Media_ Media; - -Media_::Media_(void){ - // empty -} - -void Media_::begin(void){ - memset(&_report, 0, sizeof(_report)); - HID.sendReport(HID_REPORTID_MediaReport, &_report, sizeof(_report)); -} - -void Media_::end(void){ - begin(); -} - -void Media_::write(uint16_t m){ - press(m); - release(m); -} - -void Media_::press(uint16_t m){ - // search for a free spot - for (int i = 0; i < sizeof(HID_MediaReport_Data_t) / 2; i++) { - if (_report.whole16[i] == 0x00) { - _report.whole16[i] = m; - break; - } - } - HID.sendReport(HID_REPORTID_MediaReport, &_report, sizeof(_report)); -} - -void Media_::release(uint16_t m){ - // search and release the keypress - for (int i = 0; i < sizeof(HID_MediaReport_Data_t) / 2; i++) { - if (_report.whole16[i] == m) { - _report.whole16[i] = 0x00; - // no break to delete multiple keys - } - } - HID.sendReport(HID_REPORTID_MediaReport, &_report, sizeof(_report)); -} - -void Media_::releaseAll(void){ - begin(); -} - -//================================================================================ -// System -//================================================================================ - -System_ System; - -System_::System_(void){ - // empty -} - -void System_::begin(void){ - uint8_t _report = 0; - HID.sendReport(HID_REPORTID_SystemReport, &_report, sizeof(_report)); -} - -void System_::end(void){ - begin(); -} - -void System_::write(uint8_t s){ - press(s); - release(); -} - -void System_::press(uint8_t s){ - HID.sendReport(HID_REPORTID_SystemReport, &s, sizeof(s)); -} - -void System_::release(void){ - begin(); -} - -void System_::releaseAll(void){ - begin(); -} - -//================================================================================ -// Gamepad -//================================================================================ - -Gamepad_ Gamepad1(HID_REPORTID_Gamepad1Report); -Gamepad_ Gamepad2(HID_REPORTID_Gamepad2Report); - -Gamepad_::Gamepad_(uint8_t reportID){ - _reportID = reportID; - // empty -} - -void Gamepad_::begin(void){ - memset(&_report, 0, sizeof(_report)); - HID.sendReport(_reportID, &_report, sizeof(_report)); -} - -void Gamepad_::end(void){ - begin(); -} - -void Gamepad_::write(void){ - HID.sendReport(_reportID, &_report, sizeof(_report)); -} - -void Gamepad_::press(uint8_t b){ - _report.buttons |= (uint32_t)1 << (b - 1); -} - -void Gamepad_::release(uint8_t b){ - _report.buttons &= ~((uint32_t)1 << (b - 1)); -} - -void Gamepad_::releaseAll(void){ - _report.buttons = 0; -} - -//================================================================================ -// Joystick -//================================================================================ - -Joystick_ Joystick1(HID_REPORTID_Joystick1Report); -Joystick_ Joystick2(HID_REPORTID_Joystick2Report); - -Joystick_::Joystick_(uint8_t reportID){ - _reportID = reportID; - // empty -} - -void Joystick_::begin(void){ - memset(&_report, 0, sizeof(_report)); - HID.sendReport(_reportID, &_report, sizeof(_report)); -} - -void Joystick_::end(void){ - begin(); -} - -void Joystick_::write(void){ - HID.sendReport(_reportID, &_report, sizeof(_report));; -} - -void Joystick_::press(uint8_t b){ - if (b == 1) _report.button1 = 1; - else if (b == 2) _report.button2 = 1; -} - -void Joystick_::release(uint8_t b){ - if (b == 1) _report.button1 = 0; - else if (b == 2) _report.button2 = 0; -} +#endif // #ifdef HID_ENABLED -void Joystick_::releaseAll(void){ - _report.button1 = 0; - _report.button2 = 0; -} \ No newline at end of file +#endif /* if defined(USBCON) */ \ No newline at end of file diff --git a/plugins/KeyboardioHID/HID.h b/plugins/KeyboardioHID/HID.h new file mode 100644 index 0000000000..e08e0dc404 --- /dev/null +++ b/plugins/KeyboardioHID/HID.h @@ -0,0 +1,136 @@ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +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 HID_H +#define HID_H + +#include + +// HID Resources +#include "HID_Reports.h" +#include "RawHID.h" +#include "Media.h" +#include "System.h" +#include "Gamepad.h" +#include "Keyboard.h" +#include "Mouse.h" + +//================================================================================ +//Settings +//================================================================================ + +// deactive unnecessary stuff for Leonardo/Micro +// reports needs to be <=255 bytes for leonardo/micro! +#define HID_MOUSE_ENABLE 54 +#define HID_KEYBOARD_ENABLE 65-18 //18 for missing led out report = 47 +//#define HID_RAWKEYBOARD_ENABLE 30 +#define HID_MEDIA_ENABLE 25 +#define HID_SYSTEM_ENABLE 24 +#define HID_GAMEPAD1_ENABLE 71 +//#define HID_GAMEPAD2_ENABLE 71 +//#define HID_JOYSTICK1_ENABLE 51 +//#define HID_JOYSTICK2_ENABLE 51 + +//================================================================================ +// NHP +//================================================================================ + +// Start Mask +#define NHP_MASK_START 0xC0 //B11|000000 the two MSB bits +#define NHP_MASK_LEAD 0xC0 //B11|000000 +#define NHP_MASK_DATA 0x00 //B0|0000000 only the first MSB is important +#define NHP_MASK_END 0x80 //B10|000000 + +// Content Mask +#define NHP_MASK_LENGTH 0x38 //B00|111|000 +#define NHP_MASK_COMMAND 0x0F //B0000|1111 +#define NHP_MASK_DATA_7BIT 0x7F //B0|1111111 +#define NHP_MASK_DATA_4BIT 0x0F //B0000|1111 +#define NHP_MASK_DATA_3BIT 0x07 //B00000|111 +#define NHP_MASK_ADDRESS 0x3F //B00|111111 + +// Reserved Addresses +#define NHP_ADDRESS_CONTROL 0x01 + +// Reserved Usages +#define NHP_USAGE_ARDUINOHID 0x01 + +// Serial to write Protocol data to. Default: Serial +#define HID_SERIAL Serial +#define SERIAL_HID_BAUD 115200 + +void NHPwriteChecksum(uint8_t address, uint16_t indata); + +//================================================================================ +// Keyboard Definitions +//================================================================================ + +//Keyboard fixed/added missing Keys +#define KEY_PRINT 0xCE +#define KEY_SCROLL_LOCK 0xCF +#define KEY_PAUSE 0xD0 + +//Raw Keyboard definitions +#define RAW_KEYBOARD_LEFT_CTRL B00000001 +#define RAW_KEYBOARD_LEFT_SHIFT B00000010 +#define RAW_KEYBOARD_LEFT_ALT B00000100 +#define RAW_KEYBOARD_LEFT_GUI B00001000 +#define RAW_KEYBOARD_RIGHT_CTRL B00010000 +#define RAW_KEYBOARD_RIGHT_SHIFT B00100000 +#define RAW_KEYBOARD_RIGHT_ALT B01000000 +#define RAW_KEYBOARD_RIGHT_GUI B10000000 + +#define RAW_KEYBOARD_UP_ARROW 0x52 +#define RAW_KEYBOARD_DOWN_ARROW 0x51 +#define RAW_KEYBOARD_LEFT_ARROW 0x50 +#define RAW_KEYBOARD_RIGHT_ARROW 0x4F +#define RAW_KEYBOARD_SPACEBAR 0x2C +#define RAW_KEYBOARD_BACKSPACE 0x2A +#define RAW_KEYBOARD_TAB 0x2B +#define RAW_KEYBOARD_RETURN 0x28 +#define RAW_KEYBOARD_ESC 0x29 +#define RAW_KEYBOARD_INSERT 0x49 +#define RAW_KEYBOARD_DELETE 0x4C +#define RAW_KEYBOARD_PAGE_UP 0x4B +#define RAW_KEYBOARD_PAGE_DOWN 0x4E +#define RAW_KEYBOARD_HOME 0x4A +#define RAW_KEYBOARD_END 0x4D +#define RAW_KEYBOARD_CAPS_LOCK 0x39 +#define RAW_KEYBOARD_F1 0x3A +#define RAW_KEYBOARD_F2 0x3B +#define RAW_KEYBOARD_F3 0x3C +#define RAW_KEYBOARD_F4 0x3D +#define RAW_KEYBOARD_F5 0x3E +#define RAW_KEYBOARD_F6 0x3F +#define RAW_KEYBOARD_F7 0x40 +#define RAW_KEYBOARD_F8 0x41 +#define RAW_KEYBOARD_F9 0x42 +#define RAW_KEYBOARD_F10 0x43 +#define RAW_KEYBOARD_F11 0x44 +#define RAW_KEYBOARD_F12 0x45 +#define RAW_KEYBOARD_PRINT 0x46 +#define RAW_KEYBOARD_SCROLL_LOCK 0x47 +#define RAW_KEYBOARD_PAUSE 0x48 + +#endif + diff --git a/plugins/KeyboardioHID/HID_Source/HID_Reports.h b/plugins/KeyboardioHID/HID_Reports.h similarity index 60% rename from plugins/KeyboardioHID/HID_Source/HID_Reports.h rename to plugins/KeyboardioHID/HID_Reports.h index 5134236c2e..34379b2db7 100644 --- a/plugins/KeyboardioHID/HID_Source/HID_Reports.h +++ b/plugins/KeyboardioHID/HID_Reports.h @@ -33,8 +33,8 @@ THE SOFTWARE. #define RAWHID_USAGE_PAGE 0xFFC0 // recommended: 0xFF00 to 0xFFFF #define RAWHID_USAGE 0x0C00 // recommended: 0x0100 to 0xFFFF -#define RAWHID_TX_SIZE 63 // 1 byte for report ID -#define RAWHID_RX_SIZE 63 // 1 byte for report ID +#define RAWHID_TX_SIZE 15 // 1 byte for report ID +#define RAWHID_RX_SIZE 15 // 1 byte for report ID //================================================================================ //Report Typedefinitions @@ -43,12 +43,12 @@ THE SOFTWARE. typedef union{ // mouse report: 5 buttons, position, wheel uint8_t whole8[4]; - uint16_t whole16[4/2]; - uint32_t whole32[4/4]; + uint16_t whole16[4 / 2]; + uint32_t whole32[4 / 4]; struct{ - uint8_t buttons:5; - uint8_t reserved:3; + uint8_t buttons : 5; + uint8_t reserved : 3; int8_t xAxis; int8_t yAxis; int8_t wheel; @@ -59,8 +59,8 @@ typedef union{ typedef union{ // Low level key report: up to 6 keys and shift, ctrl etc at once uint8_t whole8[8]; - uint16_t whole16[8/2]; - uint32_t whole32[8/4]; + uint16_t whole16[8 / 2]; + uint32_t whole32[8 / 4]; struct{ uint8_t modifiers; @@ -82,8 +82,8 @@ typedef union{ typedef union{ // every usable media key possible. Only one at the same time. uint8_t whole8[8]; - uint16_t whole16[8/2]; - uint32_t whole32[8/4]; + uint16_t whole16[8 / 2]; + uint32_t whole32[8 / 4]; struct{ uint16_t key1; @@ -103,63 +103,58 @@ typedef union{ typedef union { // 32 Buttons, 6 Axis, 2 D-Pads - uint8_t whole8[17]; - uint16_t whole16[17/2]; - uint32_t whole32[17/4]; + uint8_t whole8[15]; + uint16_t whole16[15 / 2]; + uint32_t whole32[15 / 4]; uint32_t buttons; struct{ - uint8_t button1 :1; - uint8_t button2 :1; - uint8_t button3 :1; - uint8_t button4 :1; - uint8_t button5 :1; - uint8_t button6 :1; - uint8_t button7 :1; - uint8_t button8 :1; - - uint8_t button9 :1; - uint8_t button10 :1; - uint8_t button11 :1; - uint8_t button12 :1; - uint8_t button13 :1; - uint8_t button14 :1; - uint8_t button15 :1; - uint8_t button16 :1; - - uint8_t button17 :1; - uint8_t button18 :1; - uint8_t button19 :1; - uint8_t button20 :1; - uint8_t button21 :1; - uint8_t button22 :1; - uint8_t button23 :1; - uint8_t button24 :1; - - uint8_t button25 :1; - uint8_t button26 :1; - uint8_t button27 :1; - uint8_t button28 :1; - uint8_t button29 :1; - uint8_t button30 :1; - uint8_t button31 :1; - uint8_t button32 :1; + uint8_t button1 : 1; + uint8_t button2 : 1; + uint8_t button3 : 1; + uint8_t button4 : 1; + uint8_t button5 : 1; + uint8_t button6 : 1; + uint8_t button7 : 1; + uint8_t button8 : 1; + + uint8_t button9 : 1; + uint8_t button10 : 1; + uint8_t button11 : 1; + uint8_t button12 : 1; + uint8_t button13 : 1; + uint8_t button14 : 1; + uint8_t button15 : 1; + uint8_t button16 : 1; + + uint8_t button17 : 1; + uint8_t button18 : 1; + uint8_t button19 : 1; + uint8_t button20 : 1; + uint8_t button21 : 1; + uint8_t button22 : 1; + uint8_t button23 : 1; + uint8_t button24 : 1; + + uint8_t button25 : 1; + uint8_t button26 : 1; + uint8_t button27 : 1; + uint8_t button28 : 1; + uint8_t button29 : 1; + uint8_t button30 : 1; + uint8_t button31 : 1; + uint8_t button32 : 1; uint16_t xAxis; uint16_t yAxis; - uint16_t zAxis; + uint8_t zAxis; uint16_t rxAxis; uint16_t ryAxis; - uint16_t rzAxis; - - uint8_t dPad1: 4; - uint8_t dPad2: 4; - - // deactivated because windows only supports 7 axis. should be enough. - //uint8_t throttle; - //uint8_t rudder; + uint8_t rzAxis; + uint8_t dPad1 : 4; + uint8_t dPad2 : 4; }; } HID_GamepadReport_Data_t; @@ -167,15 +162,15 @@ typedef union { typedef union{ // 2 Buttons, 2 Axis uint8_t whole8[3]; - uint16_t whole16[3/2]; - uint8_t buttons :2; + uint16_t whole16[3 / 2]; + uint8_t buttons : 2; struct{ - uint16_t button1 :1; - uint16_t button2 :1; - uint16_t xAxis :10; - uint16_t yAxis :10; - uint16_t reserved :2; + uint16_t button1 : 1; + uint16_t button2 : 1; + uint16_t xAxis : 10; + uint16_t yAxis : 10; + uint16_t reserved : 2; }; } HID_JoystickReport_Data_t; @@ -194,15 +189,17 @@ typedef union{ /** Enum for the HID report IDs used in the device. */ typedef enum{ - HID_REPORTID_MouseReport = 0x01, /**< Report ID for the Mouse report within the device. */ - HID_REPORTID_KeyboardReport = 0x02, /**< Report ID for the Keyboard report within the device. */ - HID_REPORTID_RawKeyboardReport = 0x03, /**< Report ID for the Raw Keyboard report within the device. */ - HID_REPORTID_MediaReport = 0x04, /**< Report ID for the Media report within the device. */ - HID_REPORTID_SystemReport = 0x05, /**< Report ID for the Power report within the device. */ - HID_REPORTID_Gamepad1Report = 0x06, /**< Report ID for the Gamepad1 report within the device. */ - HID_REPORTID_Gamepad2Report = 0x07, /**< Report ID for the Gamepad2 report within the device. */ - HID_REPORTID_Joystick1Report = 0x08, /**< Report ID for the Joystick1 report within the device. */ - HID_REPORTID_Joystick2Report = 0x09, /**< Report ID for the Joystick2 report within the device. */ + HID_REPORTID_NotAReport = 0x00, // first entry is always zero for multireports + HID_REPORTID_MouseReport = 0x01, /**< Report ID for the Mouse report within the device. */ + HID_REPORTID_KeyboardReport = 0x02, /**< Report ID for the Keyboard report within the device. */ + HID_REPORTID_RawKeyboardReport = 0x03, /**< Report ID for the Raw Keyboard report within the device. */ + HID_REPORTID_MediaReport = 0x04, /**< Report ID for the Media report within the device. */ + HID_REPORTID_SystemReport = 0x05, /**< Report ID for the Power report within the device. */ + HID_REPORTID_Gamepad1Report = 0x06, /**< Report ID for the Gamepad1 report within the device. */ + HID_REPORTID_Gamepad2Report = 0x07, /**< Report ID for the Gamepad2 report within the device. */ + HID_REPORTID_Joystick1Report = 0x08, /**< Report ID for the Joystick1 report within the device. */ + HID_REPORTID_Joystick2Report = 0x09, /**< Report ID for the Joystick2 report within the device. */ + HID_REPORTID_LastNotAReport, // determinate whats the maximum number of reports -1 } HID_Report_IDs; #endif \ No newline at end of file diff --git a/plugins/KeyboardioHID/HID_Source/HID.h b/plugins/KeyboardioHID/HID_Source/HID.h deleted file mode 100644 index 157000b526..0000000000 --- a/plugins/KeyboardioHID/HID_Source/HID.h +++ /dev/null @@ -1,359 +0,0 @@ -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -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 HID_H -#define HID_H - -#include -#include "HID_Reports.h" - -#ifdef USBCON -#include "Platform.h" -#include "USBAPI.h" -#include "USBDesc.h" - -//================================================================================ -//Settings -//================================================================================ - -// deactive unnecessary stuff for Leonardo/Micro -// reports needs to be <=255 bytes for leonardo/micro! -#define HID_MOUSE_ENABLE 54 -#define HID_KEYBOARD_ENABLE 65-18 //18 for missing led out report = 47 -//#define HID_RAWKEYBOARD_ENABLE 30 -#define HID_MEDIA_ENABLE 25 -#define HID_SYSTEM_ENABLE 24 -#define HID_GAMEPAD1_ENABLE 71 -//#define HID_GAMEPAD2_ENABLE 71 -//#define HID_JOYSTICK1_ENABLE 51 -//#define HID_JOYSTICK2_ENABLE 51 - -#endif - -//================================================================================ -// HID -//================================================================================ - -//NHP Definitions - -// Start Mask -#define NHP_MASK_START 0xC0 //B11|000000 the two MSB bits -#define NHP_MASK_LEAD 0xC0 //B11|000000 -#define NHP_MASK_DATA 0x00 //B0|0000000 only the first MSB is important -#define NHP_MASK_END 0x80 //B10|000000 - -// Content Mask -#define NHP_MASK_LENGTH 0x38 //B00|111|000 -#define NHP_MASK_COMMAND 0x0F //B0000|1111 -#define NHP_MASK_DATA_7BIT 0x7F //B0|1111111 -#define NHP_MASK_DATA_4BIT 0x0F //B0000|1111 -#define NHP_MASK_DATA_3BIT 0x07 //B00000|111 -#define NHP_MASK_ADDRESS 0x3F //B00|111111 - -// Reserved Addresses -#define NHP_ADDRESS_CONTROL 0x01 - -// Reserved Usages -#define NHP_USAGE_ARDUINOHID 0x01 - -// Serial to write Protocol data to. Default: Serial -#define HID_SERIAL Serial - -class HID_{ -public: - HID_(void); - void begin(void); - void end(void); - - // everything public for your own modifications - void sendReport(uint8_t ReportID, const void* HIDReport, uint8_t length); -private: - // simple copy/modification of the NicoHoodProtocol writechecksum function - void NHPwriteChecksum(uint8_t address, uint16_t indata); -}; -extern HID_ HID; - -//================================================================================ -// Mouse -//================================================================================ - -#define MOUSE_LEFT 0x01 -#define MOUSE_RIGHT 0x02 -#define MOUSE_MIDDLE 0x04 -#define MOUSE_PREV 0x08 -#define MOUSE_NEXT 0x10 -#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE | MOUSE_PREV | MOUSE_NEXT) - -class Mouse_{ -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 - void releaseAll(void); - bool isPressed(uint8_t b = MOUSE_LEFT); // check LEFT by default -private: - void buttons(uint8_t b); - HID_MouseReport_Data_t _report; -}; -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 - -//Keyboard fixed/added missing Keys -#define KEY_PRINT 0xCE -#define KEY_SCROLL_LOCK 0xCF -#define KEY_PAUSE 0xD0 - -//Raw Keyboard definitions -#define RAW_KEYBOARD_LEFT_CTRL B00000001 -#define RAW_KEYBOARD_LEFT_SHIFT B00000010 -#define RAW_KEYBOARD_LEFT_ALT B00000100 -#define RAW_KEYBOARD_LEFT_GUI B00001000 -#define RAW_KEYBOARD_RIGHT_CTRL B00010000 -#define RAW_KEYBOARD_RIGHT_SHIFT B00100000 -#define RAW_KEYBOARD_RIGHT_ALT B01000000 -#define RAW_KEYBOARD_RIGHT_GUI B10000000 - -#define RAW_KEYBOARD_UP_ARROW 0x52 -#define RAW_KEYBOARD_DOWN_ARROW 0x51 -#define RAW_KEYBOARD_LEFT_ARROW 0x50 -#define RAW_KEYBOARD_RIGHT_ARROW 0x4F -#define RAW_KEYBOARD_SPACEBAR 0x2C -#define RAW_KEYBOARD_BACKSPACE 0x2A -#define RAW_KEYBOARD_TAB 0x2B -#define RAW_KEYBOARD_RETURN 0x28 -#define RAW_KEYBOARD_ESC 0x29 -#define RAW_KEYBOARD_INSERT 0x49 -#define RAW_KEYBOARD_DELETE 0x4C -#define RAW_KEYBOARD_PAGE_UP 0x4B -#define RAW_KEYBOARD_PAGE_DOWN 0x4E -#define RAW_KEYBOARD_HOME 0x4A -#define RAW_KEYBOARD_END 0x4D -#define RAW_KEYBOARD_CAPS_LOCK 0x39 -#define RAW_KEYBOARD_F1 0x3A -#define RAW_KEYBOARD_F2 0x3B -#define RAW_KEYBOARD_F3 0x3C -#define RAW_KEYBOARD_F4 0x3D -#define RAW_KEYBOARD_F5 0x3E -#define RAW_KEYBOARD_F6 0x3F -#define RAW_KEYBOARD_F7 0x40 -#define RAW_KEYBOARD_F8 0x41 -#define RAW_KEYBOARD_F9 0x42 -#define RAW_KEYBOARD_F10 0x43 -#define RAW_KEYBOARD_F11 0x44 -#define RAW_KEYBOARD_F12 0x45 -#define RAW_KEYBOARD_PRINT 0x46 -#define RAW_KEYBOARD_SCROLL_LOCK 0x47 -#define RAW_KEYBOARD_PAUSE 0x48 - -//Keyboard fixed/added missing Keys -#define KEY_PRINT 0xCE -#define KEY_SCROLL_LOCK 0xCF -#define KEY_PAUSE 0xD0 - -class Keyboard_ : public Print{ -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); -private: - HID_KeyboardReport_Data_t _report; -}; -extern Keyboard_ Keyboard; - -//================================================================================ -// RawHID -//================================================================================ - -class RawHID_ : public Print{ -public: - RawHID_(void); - inline void begin(void){ /*empty*/ } - inline void end(void){ /*empty*/ } - using Print::write; // to get the String version of write - size_t write(uint8_t b); - size_t write(const uint8_t *buffer, size_t size); -}; -extern RawHID_ RawHID; - -//================================================================================ -// Media -//================================================================================ - -#define MEDIA_FAST_FORWARD 0xB3 -#define MEDIA_REWIND 0xB4 -#define MEDIA_NEXT 0xB5 -#define MEDIA_PREVIOUS 0xB6 -#define MEDIA_STOP 0xB7 -#define MEDIA_PLAY_PAUSE 0xCD - -#define MEDIA_VOLUME_MUTE 0xE2 -#define MEDIA_VOLUME_UP 0xE9 -#define MEDIA_VOLUME_DOWN 0xEA - -#define MEDIA_EMAIL_READER 0x18A -#define MEDIA_CALCULATOR 0x192 -#define MEDIA_EXPLORER 0x194 - -#define MEDIA_BROWSER_HOME 0x223 -#define MEDIA_BROWSER_BACK 0x224 -#define MEDIA_BROWSER_FORWARD 0x225 -#define MEDIA_BROWSER_REFRESH 0x227 -#define MEDIA_BROWSER_BOOKMARKS 0x22A - -class Media_{ -public: - Media_(void); - void begin(void); - void end(void); - void write(uint16_t m); - void press(uint16_t m); - void release(uint16_t m); - void releaseAll(void); -private: - HID_MediaReport_Data_t _report; -}; -extern Media_ Media; - -//================================================================================ -// System -//================================================================================ - -#define SYSTEM_POWER_DOWN 0x81 -#define SYSTEM_SLEEP 0x82 -#define SYSTEM_WAKE_UP 0x83 - -class System_{ -public: - System_(void); - void begin(void); - void end(void); - void write(uint8_t s); - void press(uint8_t s); - void release(void); - void releaseAll(void); -}; -extern System_ System; - -//================================================================================ -// Gamepad -//================================================================================ - -class Gamepad_{ -public: - Gamepad_(uint8_t reportID); - void begin(void); - void end(void); - void write(void); - void press(uint8_t b); - void release(uint8_t b); - void releaseAll(void); - inline void buttons(uint32_t b){ _report.buttons = b; } - inline void xAxis(uint16_t a){ _report.xAxis = a; } - inline void yAxis(uint16_t a){ _report.yAxis = a; } - inline void zAxis(uint16_t a){ _report.zAxis = a; } - inline void rxAxis(uint16_t a){ _report.rxAxis = a; } - inline void ryAxis(uint16_t a){ _report.ryAxis = a; } - inline void rzAxis(uint16_t a){ _report.rzAxis = a; } - inline void dPad1(uint8_t d){ _report.dPad1 = d; } - inline void dPad2(uint8_t d){ _report.dPad2 = d; } -private: - HID_GamepadReport_Data_t _report; - uint8_t _reportID; -}; -extern Gamepad_ Gamepad1; -extern Gamepad_ Gamepad2; - -//================================================================================ -// Joystick -//================================================================================ - -class Joystick_{ -public: - Joystick_(uint8_t reportID); - void begin(void); - void end(void); - void write(void); - void press(uint8_t b); - void release(uint8_t b); - void releaseAll(void); - inline void buttons(uint8_t b){ _report.buttons = b; } - inline void xAxis(uint16_t a){ _report.xAxis = a; } - inline void yAxis(uint16_t a){ _report.yAxis = a; } - -private: - HID_JoystickReport_Data_t _report; - uint8_t _reportID; -}; -extern Joystick_ Joystick1; -extern Joystick_ Joystick2; - -#endif - diff --git a/plugins/KeyboardioHID/HID_Source/Readme.md b/plugins/KeyboardioHID/HID_Source/Readme.md deleted file mode 100644 index 5e8d1ef7bc..0000000000 --- a/plugins/KeyboardioHID/HID_Source/Readme.md +++ /dev/null @@ -1,11 +0,0 @@ -HID Source -========== - -**Move and replace** these files to (depending on your version and path): -``` -C:\Arduino\arduino-1.0.5\hardware\arduino\cores\arduino -C:\Arduino\arduino-1.5.6-r2\hardware\arduino\avr\cores\arduino -C:\Arduino\arduino-1.5.7\hardware\arduino\avr\cores\arduino -``` - -Restart the IDE! \ No newline at end of file diff --git a/plugins/KeyboardioHID/HID_Source/USBAPI.h b/plugins/KeyboardioHID/HID_Source/USBAPI.h deleted file mode 100644 index 43faeba6c4..0000000000 --- a/plugins/KeyboardioHID/HID_Source/USBAPI.h +++ /dev/null @@ -1,202 +0,0 @@ -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -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 __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) - -// v1.5.7 or newer -#if ARDUINO >= 157 -struct ring_buffer; - -#if (RAMEND < 1000) -#define SERIAL_BUFFER_SIZE 16 -#else -#define SERIAL_BUFFER_SIZE 64 -#endif - -class Serial_ : public Stream -{ -private: - int peek_buffer; -public: - Serial_() { peek_buffer = -1; }; - void begin(unsigned long); - void begin(unsigned long, uint8_t); - void end(void); - - virtual int available(void); - virtual int peek(void); - virtual int read(void); - virtual void flush(void); - virtual size_t write(uint8_t); - virtual size_t write(const uint8_t*, size_t); - using Print::write; // pull in write(str) and write(buf, size) from Print - operator bool(); - - volatile uint8_t _rx_buffer_head; - volatile uint8_t _rx_buffer_tail; - unsigned char _rx_buffer[SERIAL_BUFFER_SIZE]; -}; -extern Serial_ Serial; - -#define HAVE_CDCSERIAL - -// v1.5.0 - v1.5.6 -#elif ARDUINO >= 150 -struct ring_buffer; - -#if (RAMEND < 1000) -#define SERIAL_BUFFER_SIZE 16 -#else -#define SERIAL_BUFFER_SIZE 64 -#endif - -class Serial_ : public Stream -{ -public: - void begin(unsigned long); - void begin(unsigned long, uint8_t); - 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); - using Print::write; // pull in write(str) and write(buf, size) from Print - operator bool(); - - volatile uint8_t _rx_buffer_head; - volatile uint8_t _rx_buffer_tail; - unsigned char _rx_buffer[SERIAL_BUFFER_SIZE]; -}; -extern Serial_ Serial; - -#define HAVE_CDCSERIAL - -// v1.0.1 - v1.0.x -#elif ARDUINO > 100 -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); - using Print::write; // pull in write(str) and write(buf, size) from Print - operator bool(); -}; -extern Serial_ Serial; -#endif - -//================================================================================ -//================================================================================ -// 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' - -#include "HID.h" - -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/plugins/KeyboardioHID/Keyboard.cpp b/plugins/KeyboardioHID/Keyboard.cpp new file mode 100644 index 0000000000..c9f77f9f4b --- /dev/null +++ b/plugins/KeyboardioHID/Keyboard.cpp @@ -0,0 +1,291 @@ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +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 "Keyboard.h" + +#include "Platform.h" + +//================================================================================ +// Keyboard +//================================================================================ + +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 +}; + + +Keyboard_::Keyboard_(void) +{ +} + +void Keyboard_::begin(void) +{ +#ifndef USBCON + // release all buttons for Hoodloader + releaseAll(); +#endif +} + +void Keyboard_::end(void) +{ + // added here! + releaseAll(); +} + +void Keyboard_::sendReport(KeyReport* keys) +{ + HID_SendReport(HID_REPORTID_KeyboardReport, &_keyReport, sizeof(_keyReport)); +} + +// removed <-- +//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) +{ + // release all keys + memset(&_keyReport, 0x00, sizeof(_keyReport)); + sendReport(&_keyReport); +} + +size_t Keyboard_::write(uint8_t c) +{ + uint8_t p = press(c); // Keydown + release(c); // Keyup + return (p); // just return the result of press() since release() almost always returns 1 +} diff --git a/plugins/KeyboardioHID/Keyboard.h b/plugins/KeyboardioHID/Keyboard.h new file mode 100644 index 0000000000..61ba18d9c4 --- /dev/null +++ b/plugins/KeyboardioHID/Keyboard.h @@ -0,0 +1,151 @@ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +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 KEYBOARD_H +#define KEYBOARD_H + +#include "HID.h" + +//================================================================================ +// HID +//================================================================================ + +void HID_SendReport(uint8_t id, const void* data, int len); + +//================================================================================ +// Keyboard +//================================================================================ + +#ifndef USBCON + +#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 + +//Keyboard fixed/added missing Keys +#define KEY_PRINT 0xCE +#define KEY_SCROLL_LOCK 0xCF +#define KEY_PAUSE 0xD0 + +//Raw Keyboard definitions +#define RAW_KEYBOARD_LEFT_CTRL B00000001 +#define RAW_KEYBOARD_LEFT_SHIFT B00000010 +#define RAW_KEYBOARD_LEFT_ALT B00000100 +#define RAW_KEYBOARD_LEFT_GUI B00001000 +#define RAW_KEYBOARD_RIGHT_CTRL B00010000 +#define RAW_KEYBOARD_RIGHT_SHIFT B00100000 +#define RAW_KEYBOARD_RIGHT_ALT B01000000 +#define RAW_KEYBOARD_RIGHT_GUI B10000000 + +#define RAW_KEYBOARD_UP_ARROW 0x52 +#define RAW_KEYBOARD_DOWN_ARROW 0x51 +#define RAW_KEYBOARD_LEFT_ARROW 0x50 +#define RAW_KEYBOARD_RIGHT_ARROW 0x4F +#define RAW_KEYBOARD_SPACEBAR 0x2C +#define RAW_KEYBOARD_BACKSPACE 0x2A +#define RAW_KEYBOARD_TAB 0x2B +#define RAW_KEYBOARD_RETURN 0x28 +#define RAW_KEYBOARD_ESC 0x29 +#define RAW_KEYBOARD_INSERT 0x49 +#define RAW_KEYBOARD_DELETE 0x4C +#define RAW_KEYBOARD_PAGE_UP 0x4B +#define RAW_KEYBOARD_PAGE_DOWN 0x4E +#define RAW_KEYBOARD_HOME 0x4A +#define RAW_KEYBOARD_END 0x4D +#define RAW_KEYBOARD_CAPS_LOCK 0x39 +#define RAW_KEYBOARD_F1 0x3A +#define RAW_KEYBOARD_F2 0x3B +#define RAW_KEYBOARD_F3 0x3C +#define RAW_KEYBOARD_F4 0x3D +#define RAW_KEYBOARD_F5 0x3E +#define RAW_KEYBOARD_F6 0x3F +#define RAW_KEYBOARD_F7 0x40 +#define RAW_KEYBOARD_F8 0x41 +#define RAW_KEYBOARD_F9 0x42 +#define RAW_KEYBOARD_F10 0x43 +#define RAW_KEYBOARD_F11 0x44 +#define RAW_KEYBOARD_F12 0x45 +#define RAW_KEYBOARD_PRINT 0x46 +#define RAW_KEYBOARD_SCROLL_LOCK 0x47 +#define RAW_KEYBOARD_PAUSE 0x48 + +//Keyboard fixed/added missing Keys +#define KEY_PRINT 0xCE +#define KEY_SCROLL_LOCK 0xCF +#define KEY_PAUSE 0xD0 + +// typedef this report again because we cannot include the USBAPI +typedef HID_KeyboardReport_Data_t KeyReport; + +class Keyboard_ : public Print{ +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); +private: + KeyReport _keyReport; + void sendReport(KeyReport* keys); +}; +extern Keyboard_ Keyboard; + +#endif +#endif + diff --git a/plugins/KeyboardioHID/Media.h b/plugins/KeyboardioHID/Media.h new file mode 100644 index 0000000000..090335862c --- /dev/null +++ b/plugins/KeyboardioHID/Media.h @@ -0,0 +1,112 @@ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +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 MEDIA_H +#define MEDIA_H + +#include "HID.h" + +//================================================================================ +// HID +//================================================================================ + +void HID_SendReport(uint8_t id, const void* data, int len); + +//================================================================================ +// Media +//================================================================================ + +#define MEDIA_FAST_FORWARD 0xB3 +#define MEDIA_REWIND 0xB4 +#define MEDIA_NEXT 0xB5 +#define MEDIA_PREVIOUS 0xB6 +#define MEDIA_STOP 0xB7 +#define MEDIA_PLAY_PAUSE 0xCD + +#define MEDIA_VOLUME_MUTE 0xE2 +#define MEDIA_VOLUME_UP 0xE9 +#define MEDIA_VOLUME_DOWN 0xEA + +#define MEDIA_EMAIL_READER 0x18A +#define MEDIA_CALCULATOR 0x192 +#define MEDIA_EXPLORER 0x194 + +#define MEDIA_BROWSER_HOME 0x223 +#define MEDIA_BROWSER_BACK 0x224 +#define MEDIA_BROWSER_FORWARD 0x225 +#define MEDIA_BROWSER_REFRESH 0x227 +#define MEDIA_BROWSER_BOOKMARKS 0x22A + +class Media_{ +public: + inline Media_(void){ + // empty + } + + inline void begin(void){ + memset(&_report, 0, sizeof(_report)); + HID_SendReport(HID_REPORTID_MediaReport, &_report, sizeof(_report)); + } + + inline void end(void){ + begin(); + } + + inline void write(uint16_t m){ + press(m); + release(m); + } + + inline void press(uint16_t m){ + // search for a free spot + for (int i = 0; i < sizeof(HID_MediaReport_Data_t) / 2; i++) { + if (_report.whole16[i] == 0x00) { + _report.whole16[i] = m; + break; + } + } + HID_SendReport(HID_REPORTID_MediaReport, &_report, sizeof(_report)); + } + + inline void release(uint16_t m){ + // search and release the keypress + for (int i = 0; i < sizeof(HID_MediaReport_Data_t) / 2; i++) { + if (_report.whole16[i] == m) { + _report.whole16[i] = 0x00; + // no break to delete multiple keys + } + } + HID_SendReport(HID_REPORTID_MediaReport, &_report, sizeof(_report)); + } + + inline void releaseAll(void){ + begin(); + } +private: + HID_MediaReport_Data_t _report; +}; +extern Media_ Media; + +#endif + diff --git a/plugins/KeyboardioHID/Mouse.cpp b/plugins/KeyboardioHID/Mouse.cpp new file mode 100644 index 0000000000..5a019856b2 --- /dev/null +++ b/plugins/KeyboardioHID/Mouse.cpp @@ -0,0 +1,95 @@ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +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 "Mouse.h" + +#include "Platform.h" + +//================================================================================ +//================================================================================ +// Mouse + +Mouse_::Mouse_(void) : +_buttons(0) +{ +} + +void Mouse_::begin(void) +{ +#ifndef USBCON + // release all buttons for Hoodloader + _buttons = 0; + move(0, 0, 0); +#endif +} + +void Mouse_::end(void) +{ + // added here! + _buttons = 0; + move(0, 0, 0); +} + +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; +} \ No newline at end of file diff --git a/plugins/KeyboardioHID/Mouse.h b/plugins/KeyboardioHID/Mouse.h new file mode 100644 index 0000000000..f2ee81bc1c --- /dev/null +++ b/plugins/KeyboardioHID/Mouse.h @@ -0,0 +1,69 @@ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +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 MOUSE_H +#define MOUSE_H + +#include "HID.h" + +//================================================================================ +// HID +//================================================================================ + +void HID_SendReport(uint8_t id, const void* data, int len); + +//================================================================================ +// Mouse +//================================================================================ + +#ifndef USBCON + +#define MOUSE_LEFT 0x01 +#define MOUSE_RIGHT 0x02 +#define MOUSE_MIDDLE 0x04 +#define MOUSE_PREV 0x08 +#define MOUSE_NEXT 0x10 +#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE | MOUSE_PREV | MOUSE_NEXT) + +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; +#endif + + +#endif + diff --git a/plugins/KeyboardioHID/RawHID.h b/plugins/KeyboardioHID/RawHID.h new file mode 100644 index 0000000000..c4da346eb9 --- /dev/null +++ b/plugins/KeyboardioHID/RawHID.h @@ -0,0 +1,78 @@ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +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 DEFAULT_H +#define DEFAULT_H + +#include "HID.h" + +//================================================================================ +// HID +//================================================================================ + +void HID_SendReport(uint8_t id, const void* data, int len); + +//================================================================================ +// RawHID +//================================================================================ + +class RawHID_ : public Print{ +public: + inline RawHID_(void){ + // empty + } + + inline void begin(void){ + // empty + } + + inline void end(void){ + // empty + } + + using Print::write; // to get the String version of write + inline size_t write(uint8_t b){ + write(&b, 1); + } + + inline size_t write(const uint8_t *buffer, size_t size){ + size_t bytesleft = size; + // first work through the buffer thats already there + while (bytesleft >= RAWHID_RX_SIZE){ + HID_SendReport(HID_REPORTID_RawKeyboardReport, &buffer[size - bytesleft], RAWHID_RX_SIZE); + bytesleft -= RAWHID_RX_SIZE; + } + // write down the other bytes and fill with zeros + if (bytesleft){ + uint8_t rest[RAWHID_RX_SIZE]; + memcpy(rest, &buffer[size - bytesleft], bytesleft); + memset(&rest[bytesleft], 0, RAWHID_RX_SIZE - bytesleft); + HID_SendReport(HID_REPORTID_RawKeyboardReport, &rest, RAWHID_RX_SIZE); + } + } +}; +extern RawHID_ RawHID; + +#endif + diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index b62e7d9428..90770c3dd9 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -1,32 +1,32 @@ -Arduino HID Project BETA 1.7 -============================ +Arduino HID Project +=================== Dont you always wanted to turn your Arduino in a Generic HID device like a Keyboard or a Gamepad? Disappointed that the Uno doesnt support this at all and the Micro/Leonardo only Mouse + Keyboard? Introducing the Arduino HID Project that **enables enhanced USB functionality to Arduino Uno, Mega, Leonardo, Micro.** No need for extra hardware. You just need one of the Arduinos and an USB cable. -**Main difference is that you can upload new sketches to the Uno/Mega and dont need to reflash the firmware.** +**Main difference is that you can upload new sketches to the Uno/Mega and dont need to reflash the firmware over and over again.** Before you had to upload a sketch, flash the firmware, test, flash the firmware, upload, flash again. Thats all gone! -**For the Leonardo/Micro it is 'just' new device stuff, no need for a bootloader.** +**For the Leonardo/Micro it is 'just' new HID devices, no need for a bootloader.** -[Hoodloader Repository moved here.](https://github.com/NicoHood/Hoodloader) +Note: [Hoodloader Repository moved here.](https://github.com/NicoHood/Hoodloader) Features ======== -Use your **Arduino Uno, Mega, Micro, Leonardo or Micro Pro** as Generic HID Device and still be able to upload sketches how you are used to do. -This project provides a new bootloader (Hoodloader) for the 8u2/16u2 and HID libraries Arduino Uno/Mega and Micro/Leonardo. +Use your **Arduino Uno, Mega, Micro, Leonardo or (Pro)Micro** as Generic HID Device and still be able to upload sketches how you are used to do. +This project provides HID libraries for Arduino Uno/Mega (with a new 16u2 bootloader) and Micro/Leonardo. I also corrected some bugs in the original sources. **Software includes:** * Arduino HID Uno/Mega library * Arduino HID Micro/Leonardo library -* Arduino HID Bootloader (Hoodloader) + driver +* Arduino HID Bootloader (Hoodloader) + driver for Uno/Mega * Arduino as ISP with the 16u2 (Hoodloader only, [more information](https://github.com/NicoHood/Hoodloader)) -* Compatible with Linux/Mac/Windows XP/7/8.1* -* Compatible with IDE 1.0.x - 1.5.7 (newer versions might need an update) +* Compatible with Linux/Mac/Windows XP/7/8.1 +* Compatible with IDE 1.0.x - 1.5.7 **The following devices are supported:** @@ -41,20 +41,26 @@ I also corrected some bugs in the original sources. * [Gamecube to PC adapter](https://github.com/NicoHood/Nintendo) * [Other projects](http://nicohood.wordpress.com/) +Version differences +=================== + +| Arduino Uno/Mega | Arduino Leonardo/(Pro)Micro | +|:---------------------------------------|:-----------------------------------| +| HID via Hoodloader on 16u2 | Uses USB core with main MCU (32u4) | +| Serial0 without HID fully usable | Serial0 fully usable | +| Serial0 with HID at baud 115200 only | Serial0 slow + buggy | +| Serial0 with HID fully usable via USB | | +| Serial0 with HID not usable via extern | | +| Uses less flash (Serial Protocol only) | Uses more flash (full USB core) | +| ISP function | No ISP function | + +Over all the Uno/Mega solution gives you more opportunities except that the Serial0 is limited when you use HID. + Installation Leonardo/Micro/Uno/Mega ==================================== -Download the library and install like you are used to (access the examples, keywords.txt with IDE). -Then **move and replace** all files from "HID_Source" to the folder that matches your Arduino IDE version to one of these paths -(depending on your version): -``` -C:\Arduino\arduino-1.0.5\hardware\arduino\cores\arduino -C:\Arduino\arduino-1.5.6-r2\hardware\arduino\avr\cores\arduino -C:\Arduino\arduino-1.5.7\hardware\arduino\avr\cores\arduino -``` -The installation path may differ to yours. Newer Versions than 1.5.7 may not work. -Restart the IDE! +Download the library and [install it](http://arduino.cc/en/pmwiki.php?n=Guide/Libraries) like you are used to. -**I strongly recommend to install the library like this. Otherwise it wont work.** +**For the whole Project IDE 1.5.7 or higher is recommended!** #### Leonardo/Micro only **Edit HID.h to de/activate usb functions.** @@ -62,37 +68,49 @@ By default Mouse, Keyboard, Media, System, Gamepad1 is activated. Each function will take some flash, so if you want to save flash deactivate everything you dont need. -By default Mouse, Keyboard, Media, System, Gamepad1 is activated. You cannot use more than 255 bytes HID report on the Leonardo/Micro. The number after each definition tells you the size of each report. I have no idea why you cannot use more than 255 bytes (yet), its a bug in the Arduino code. #### Uno/Mega only -To **install the new bootloader** connect your Arduino to your PC via USB and see +To install the new bootloader connect your Arduino to your PC via USB and see [Hoodloader installing instructions](https://github.com/NicoHood/Hoodloader). +No special programmer needed, just an USB cable. **You can always switch back to the original firmware, nothing to break.** -For Arduino Mega2560 I recommend (in general) the IDE 1.5.7 or higher. [See Issue on Github.](https://github.com/arduino/Arduino/issues/1071) -[Or this Issue.)(http://forum.arduino.cc/index.php?topic=126160.0) - Usage ===== You are ready to use the libraries. **Just have a look at the examples and test it out.** They are pretty much self explaining. All examples use a button on pin 8 and show the basic usage of the libraries. The libraries will work for all Arduinos listed above but it will use 2 different HID libraries (automatically). +For Keyboard + Mouse usage also see the [official documentation](http://arduino.cc/en/pmwiki.php?n=Reference/MouseKeyboard). -The HID include and HID.begin() is not needed for **Leonardo/Micro** but I'd recommend -to use it every time so you can port the library from one to another device. +**#include is now needed for every device.** -**On Arduino/Mega you can only use baud 115200 for HID** due to programming reasons. Its not bad anyway -because its the fastest baud and you want fast HID recognition. You still can use any other baud for -normal sketches without but HID wont work. If you try nevertheless it will output Serial crap to the Monitor. -HID.begin() starts the Serial at baud 115200 on Arduino Uno/Mega. Do not call Serial.begin() again. +**On Arduino/Mega you can only use baud 115200 for HID** due to speed/programming reasons. +Use Serial.begin(SERIAL_HID_BAUD); as typedef to start Serial at baud 115200. +Its not bad anyway because its the fastest baud and you want fast HID recognition. +You still can **fully use any other baud** for normal sketches but HID wont work. +If you try nevertheless it will output Serial crap to the monitor. **Always release buttons to not cause any erros.** Replug USB cable to reset the values if anything went wrong. -See [Deactivate HID function](https://github.com/NicoHood/Hoodloader) if you need to fully disable HID again. +On Windows every USB report will reset when you open the lock screen. +See [deactivate HID function (Hoodloader only)](https://github.com/NicoHood/Hoodloader) how to disable HID again. + +For Arduino as ISP usage (optional, Hoodloader only, has nothing to do with HID function) +see [Hoodloader repository](https://github.com/NicoHood/Hoodloader). + +Updating to a newer Version +=========================== +HID library: -For Arduino as ISP usage (optional, has nothing to do with HID function) see [Hoodloader repository](https://github.com/NicoHood/Hoodloader). +To upgrade to v1.8 you need to redownload the ide files, replace the original files and install the library like you are used to. + +Hoodloader: + +Just upload the new hex file and check the HID Project if the HID library code has changed and replace the new files too. +You normally dont need to reinstall the drivers for windows if the changelog dosnt note anything. +Versions below 1.5 might need the new drivers. How it works ============ @@ -101,8 +119,12 @@ Its not that complicated, everything you need is in the main 4 .h/cpp files. For the Uno/Mega you need a special Bootloader. Why? See [Hoodloader repository](https://github.com/NicoHood/Hoodloader). To sum it up: Serial information is grabbed by the "man in the middle, 16u2" and you dont have to worry to get any wrong Serial stuff via USB. +Thatswhy you need a special baud (115200) that both sides can communicate with each other. +Every USB command is send via a special [NicoHood Protocol](https://github.com/NicoHood/NicoHoodProtocol) +that's filtered out by the 16u2. If you use Serial0 for extern devices it cannot filter the signal of course. +You can still use the NHP, just dont use the reserved Address 1. -This library wouldnt be possible without +This project wouldnt be possible without ======================================== * [Lufa 140302 from Dean Camera](http://www.fourwalledcubicle.com/LUFA.php) @@ -120,22 +142,22 @@ This library wouldnt be possible without Ideas for the future ==================== * Add more devices (even more?) -* Add Midi (no more free Endpoints) -* Add Led/SPI support (discarded, not needed, too slow) +* Add Midi (no more free Endpoints, possible on 32u4) * Add HID rumble support (very hard) * Add Xbox Support (too hard) -* Add Report Out function (for Keyboard Leds etc, maybe the 4 pin header?) +* Add Report Out function (for Keyboard Leds etc) Known Bugs ========== +See [Hoodloader repository](https://github.com/NicoHood/Hoodloader) for Hoodloader related Bugs/Issues. + +Opening the examples with doubleclick doesnt work, starting from IDE does. + System Wakeup is currently not working on all versions! System Shutdown is only working on Windows systems. RawHID only works on Uno/Mega. It still has some bugs. -Programming Arduino Mega with ISP doesnt work because of fuses. Burning Bootloader error is fixed with IDE 1.5.7 or higher (avrdude bug)! -See this for more information: http://forum.arduino.cc/index.php?topic=126160.0 - Feel free to open an Issue on Github if you find a bug. Or message me via my [blog](http://nicohood.wordpress.com/)! Known Issues @@ -143,7 +165,7 @@ Known Issues **Do not name your sketch HID.ino, this wont work!** -**Do not use HID in interrupts because it uses the Serial. Your Arduino can crash!** +**Do not use HID in interrupts because it uses Serial (Hoodloader only). Your Arduino can crash!** **If you get a checksum error after uploading please message me and send me the whole project.** Same if your Arduino crashes and dont want to upload sketches anymore (Replug usb fixes this). @@ -151,27 +173,29 @@ These bugs occurred while developing the bootloader and should be fixed. Just in USB can behave weird, so please check your code for errors first. If you cannot find a mistake open a Github issue. **If You have weird Problems especially with controllers, let me know.** -Sometimes the Problem is just that Windows messes up the PID so you might want to compile the hoodloader with a different PID - -HID only works with baud 115200 (on Uno/Mega) because there is no "programming finished" indicator. -If you dont use HID you can still choose the baud of your choice. +Sometimes the problem is just that Windows messes up the PID so you might want to compile the hoodloader with a different PID +or reinstall the drivers. XBMC 13.1 (a Media Center) uses Gamepad input. Its seems to not work and may cause weird errors. Even with a standard Gamepad I have these errors. Just want to mention it here. -Not tested on the 8u2 (should only work without DFU and v1.6 due to size. message me if it works!) +Not tested on the 8u2, lite version should work with flashing via ISP. Not tested on the Due (message me if it works!) -The USB implementation of the Leonardo/Micro is not that good it can cause errors or disconnects with massive Serial information. +The USB implementation of the Leonardo/Micro is not that good it can cause errors or disconnects with massiv Serial input. This has nothing to do with this library! For example Adalight dosnt work well for me, so you better use an Arduino Uno with Hoodloader for Mediacenter control and Ambilight. -Oh and by the way: I also removed some bugs from the official firmware. - Version History =============== ``` +1.8 Beta Release (xx.08.2014) +* Changes in the Hoodloader: + * **Huge improvements**, see [Hoodloader repository](https://github.com/NicoHood/Hoodloader) + * Reworked the whole library, easy installation now + * HID fixes for Media Keys/Ubuntu + 1.7.3 Beta Release (10.08.2014) * Changes in the Hoodloader: * Fixed HID flush bug (1.6 - 1.7.2) diff --git a/plugins/KeyboardioHID/System.h b/plugins/KeyboardioHID/System.h new file mode 100644 index 0000000000..f0501a5dc0 --- /dev/null +++ b/plugins/KeyboardioHID/System.h @@ -0,0 +1,79 @@ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +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 SYSTEM_H +#define SYSTEM_H + +#include "HID.h" + +//================================================================================ +// HID +//================================================================================ + +void HID_SendReport(uint8_t id, const void* data, int len); + +//================================================================================ +// System +//================================================================================ + +#define SYSTEM_POWER_DOWN 0x81 +#define SYSTEM_SLEEP 0x82 +#define SYSTEM_WAKE_UP 0x83 + +class System_{ +public: + inline System_(void){ + // empty + } + + inline void begin(void){ + uint8_t _report = 0; + HID_SendReport(HID_REPORTID_SystemReport, &_report, sizeof(_report)); + } + + inline void end(void){ + begin(); + } + + inline void write(uint8_t s){ + press(s); + release(); + } + + inline void press(uint8_t s){ + HID_SendReport(HID_REPORTID_SystemReport, &s, sizeof(s)); + } + + inline void release(void){ + begin(); + } + + inline void releaseAll(void){ + begin(); + } +}; +extern System_ System; + +#endif + diff --git a/plugins/KeyboardioHID/examples/AdvancedRawHID/AdvancedRawHID.ino b/plugins/KeyboardioHID/examples/AdvancedRawHID/AdvancedRawHID.ino index ed7eee1db2..7c62e7b403 100644 --- a/plugins/KeyboardioHID/examples/AdvancedRawHID/AdvancedRawHID.ino +++ b/plugins/KeyboardioHID/examples/AdvancedRawHID/AdvancedRawHID.ino @@ -10,15 +10,13 @@ Definitions from HID_Reports.h: RAWHID_USAGE_PAGE 0xFFC0 // recommended: 0xFF00 to 0xFFFF RAWHID_USAGE 0x0C00 // recommended: 0x0100 to 0xFFFF - RAWHID_TX_SIZE 63 // 1 byte for report ID - RAWHID_RX_SIZE 63 // 1 byte for report ID + RAWHID_TX_SIZE 15 // 1 byte for report ID + RAWHID_RX_SIZE 15 // 1 byte for report ID */ -// not needed for Leonardo/Micro +// include HID library #include -// for Leonardo/Micro: make sure to activate desired USB functions in HID_Reports.h - const int pinLed = 13; const int pinButton = 8; @@ -26,12 +24,11 @@ void setup() { pinMode(pinLed, OUTPUT); pinMode(pinButton, INPUT_PULLUP); - // Starts Serial at baud 115200. end just ends the Serial - // Make sure to end your special HIDs before, this does not clear them! - // You need this baud for the HID library but still can use other bauds - // without HID functions. - // not needed for Leonado/Micro, Serial will not be set - HID.begin(); + // Starts Serial at baud 115200 otherwise HID wont work on Uno/Mega. + // This is not needed for Leonado/(Pro)Micro but make sure to activate desired USB functions in HID.h + Serial.begin(SERIAL_HID_BAUD); + + // no begin function needed for RawHID } void loop() { diff --git a/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino b/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino index 248d1de07b..a02cdf83b6 100644 --- a/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino +++ b/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino @@ -6,10 +6,11 @@ Gamepad example Press a button and demonstrate Gamepad actions */ -// not needed for Leonardo/Micro +// include HID library #include -// for Leonardo/Micro: make sure to activate desired USB functions in HID_Reports.h +// create a new Gamepad instance (1-4) +Gamepad Gamepad1(1); const int pinLed = 13; const int pinButton = 8; @@ -18,22 +19,13 @@ void setup() { pinMode(pinLed, OUTPUT); pinMode(pinButton, INPUT_PULLUP); - // Starts Serial at baud 115200. end just ends the Serial - // Make sure to end your special HIDs before, this does not clear them! - // You need this baud for the HID library but still can use other bauds - // without HID functions. - // not needed for Leonado/Micro, Serial will not be set - HID.begin(); + // Starts Serial at baud 115200 otherwise HID wont work on Uno/Mega. + // This is not needed for Leonado/(Pro)Micro but make sure to activate desired USB functions in HID.h + Serial.begin(SERIAL_HID_BAUD); // Sends a clean report to the host. This is important because // the 16u2 of the Uno/Mega is not turned off while programming - // so you want to start with a clear report to avoid strange bugs. - // its exactly the same like the end() function. - // You can also unplug the device if anything goes wrong. - // To prevent the 16u2 to send more reports just pull the Serial TX (pin1) low - // or see readme for turning off HID functions. - // If you did anything wrong (keyboard is doing weird stuff) - // just logout (no shutdown needed). + // so you want to start with a clean report to avoid strange bugs after reset. Gamepad1.begin(); } diff --git a/plugins/KeyboardioHID/examples/Joystick/Joystick.ino b/plugins/KeyboardioHID/examples/Joystick/Joystick.ino deleted file mode 100644 index 489969d4ef..0000000000 --- a/plugins/KeyboardioHID/examples/Joystick/Joystick.ino +++ /dev/null @@ -1,79 +0,0 @@ -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -Joystick example -Press a button and demonstrate Joystick actions -*/ - -// not needed for Leonardo/Micro -#include - -// for Leonardo/Micro: make sure to activate desired USB functions in HID_Reports.h - -const int pinLed = 13; -const int pinButton = 8; - -void setup() { - pinMode(pinLed, OUTPUT); - pinMode(pinButton, INPUT_PULLUP); - - // Starts Serial at baud 115200. end just ends the Serial - // Make sure to end your special HIDs before, this does not clear them! - // You need this baud for the HID library but still can use other bauds - // without HID functions. - // not needed for Leonardo/Micro, Serial will not be set - HID.begin(); - - // Sends a clean report to the host. This is important because - // the 16u2 of the Uno/Mega is not turned off while programming - // so you want to start with a clear report to avoid strange bugs. - // its exactly the same like the end() function. - // You can also unplug the device if anything goes wrong. - // To prevent the 16u2 to send more reports just pull the Serial TX (pin1) low - // or see readme for turning off HID functions. - // If you did anything wrong (keyboard is doing weird stuff) - // just logout (no shutdown needed). - Joystick1.begin(); -} - -void loop() { - if (!digitalRead(pinButton)) { - digitalWrite(pinLed, HIGH); - - // press button 1-2 and reset - static uint8_t count = 0; - if (++count == 3) { - count = 0; - Joystick1.releaseAll(); - } - else - Joystick1.press(count); - - // move x/y Axis to a new position (10bit) - Joystick1.xAxis(random(1023)); - Joystick1.yAxis(analogRead(A0)); - - // functions before only set the values - // this writes the report to the host - Joystick1.write(); - - // simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } -} - -/* -Prototypes: - -void begin(void); -void end(void); -void write(void); -void press(uint8_t b); -void release(uint8_t b); -void releaseAll(void); -void xAxis(uint16_t a); -void yAxis(uint16_t a); - -*/ diff --git a/plugins/KeyboardioHID/examples/Keyboard/Keyboard.ino b/plugins/KeyboardioHID/examples/Keyboard/Keyboard.ino index 6c3355f37e..0fa5143585 100644 --- a/plugins/KeyboardioHID/examples/Keyboard/Keyboard.ino +++ b/plugins/KeyboardioHID/examples/Keyboard/Keyboard.ino @@ -3,15 +3,13 @@ Copyright (c) 2014 NicoHood See the readme for credit to other people. Keyboard example - Press a button to write some text to your pc. After 10 button presses it will pres ctrl+alt+del. + Press a button to write some text to your pc. See official documentation for more infos */ -// not needed for Leonardo/Micro +// include HID library #include -// for Leonardo/Micro: make sure to activate desired USB functions in HID_Reports.h - const int pinLed = 13; const int pinButton = 8; @@ -19,22 +17,13 @@ void setup() { pinMode(pinLed, OUTPUT); pinMode(pinButton, INPUT_PULLUP); - // Starts Serial at baud 115200. end just ends the Serial - // Make sure to end your special HIDs before, this does not clear them! - // You need this baud for the HID library but still can use other bauds - // without HID functions. - // not needed for Leonardo/Micro, Serial will not be set - HID.begin(); + // Starts Serial at baud 115200 otherwise HID wont work on Uno/Mega. + // This is not needed for Leonado/(Pro)Micro but make sure to activate desired USB functions in HID.h + Serial.begin(SERIAL_HID_BAUD); // Sends a clean report to the host. This is important because // the 16u2 of the Uno/Mega is not turned off while programming - // so you want to start with a clear report to avoid strange bugs. - // its exactly the same like the end() function. - // You can also unplug the device if anything goes wrong. - // To prevent the 16u2 to send more reports just pull the Serial TX (pin1) low - // or see readme for turning off HID functions. - // If you did anything wrong (keyboard is doing weird stuff) - // just logout (no shutdown needed). + // so you want to start with a clean report to avoid strange bugs after reset. Keyboard.begin(); } @@ -47,16 +36,6 @@ void loop() { Keyboard.println("This message was sent with my Arduino."); Serial.println("Serial port is still working and not glitching out"); - // you can press any key, see list below - static uint8_t count = 0; - if (++count == 10) { - Keyboard.press(KEY_LEFT_CTRL); - Keyboard.press(KEY_LEFT_ALT); - Keyboard.press(KEY_DELETE); - Keyboard.releaseAll(); - count = 0; - } - // simple debounce delay(300); digitalWrite(pinLed, LOW); diff --git a/plugins/KeyboardioHID/examples/Media/Media.ino b/plugins/KeyboardioHID/examples/Media/Media.ino index 86aec501a5..e8065eef67 100644 --- a/plugins/KeyboardioHID/examples/Media/Media.ino +++ b/plugins/KeyboardioHID/examples/Media/Media.ino @@ -6,11 +6,9 @@ Media example Press a button to play/pause music player */ -// not needed for Leonardo/Micro +// include HID library #include -// for Leonardo/Micro: make sure to activate desired USB functions in HID_Reports.h - const int pinLed = 13; const int pinButton = 8; @@ -18,22 +16,13 @@ void setup() { pinMode(pinLed, OUTPUT); pinMode(pinButton, INPUT_PULLUP); - // Starts Serial at baud 115200. end just ends the Serial - // Make sure to end your special HIDs before, this does not clear them! - // You need this baud for the HID library but still can use other bauds - // without HID functions. - // not needed for Leonardo/Micro, Serial will not be set - HID.begin(); + // Starts Serial at baud 115200 otherwise HID wont work on Uno/Mega. + // This is not needed for Leonado/(Pro)Micro but make sure to activate desired USB functions in HID.h + Serial.begin(SERIAL_HID_BAUD); // Sends a clean report to the host. This is important because // the 16u2 of the Uno/Mega is not turned off while programming - // so you want to start with a clear report to avoid strange bugs. - // its exactly the same like the end() function. - // You can also unplug the device if anything goes wrong. - // To prevent the 16u2 to send more reports just pull the Serial TX (pin1) low - // or see readme for turning off HID functions. - // If you did anything wrong (keyboard is doing weird stuff) - // just logout (no shutdown needed). + // so you want to start with a clean report to avoid strange bugs after reset. Media.begin(); } diff --git a/plugins/KeyboardioHID/examples/Mouse/Mouse.ino b/plugins/KeyboardioHID/examples/Mouse/Mouse.ino index 13b218f804..41b7647fc0 100644 --- a/plugins/KeyboardioHID/examples/Mouse/Mouse.ino +++ b/plugins/KeyboardioHID/examples/Mouse/Mouse.ino @@ -6,11 +6,9 @@ Copyright (c) 2014 NicoHood Press a button to click with mouse. See official documentation for more infos */ -// not needed for Leonardo/Micro +// include HID library #include -// for Leonardo/Micro: make sure to activate desired USB functions in HID_Reports.h - const int pinLed = 13; const int pinButton = 8; @@ -18,22 +16,13 @@ void setup() { pinMode(pinLed, OUTPUT); pinMode(pinButton, INPUT_PULLUP); - // Starts Serial at baud 115200. end just ends the Serial - // Make sure to end your special HIDs before, this does not clear them! - // You need this baud for the HID library but still can use other bauds - // without HID functions. - // not needed for Leonardo/Micro, Serial will not be set - HID.begin(); + // Starts Serial at baud 115200 otherwise HID wont work on Uno/Mega. + // This is not needed for Leonado/(Pro)Micro but make sure to activate desired USB functions in HID.h + Serial.begin(SERIAL_HID_BAUD); // Sends a clean report to the host. This is important because // the 16u2 of the Uno/Mega is not turned off while programming - // so you want to start with a clear report to avoid strange bugs. - // its exactly the same like the end() function. - // You can also unplug the device if anything goes wrong. - // To prevent the 16u2 to send more reports just pull the Serial TX (pin1) low - // or see readme for turning off HID functions. - // If you did anything wrong (keyboard is doing weird stuff) - // just logout (no shutdown needed). + // so you want to start with a clean report to avoid strange bugs after reset. Mouse.begin(); } diff --git a/plugins/KeyboardioHID/examples/System/System.ino b/plugins/KeyboardioHID/examples/System/System.ino index c434ca7d7a..7d03b2ebbc 100644 --- a/plugins/KeyboardioHID/examples/System/System.ino +++ b/plugins/KeyboardioHID/examples/System/System.ino @@ -6,11 +6,9 @@ System example Press a button to put pc into standby mode */ -// not needed for Leonardo/Micro +// include HID library #include -// for Leonardo/Micro: make sure to activate desired USB functions in HID_Reports.h - const int pinLed = 13; const int pinButton = 8; @@ -18,22 +16,13 @@ void setup() { pinMode(pinLed, OUTPUT); pinMode(pinButton, INPUT_PULLUP); - // Starts Serial at baud 115200. end just ends the Serial - // Make sure to end your special HIDs before, this does not clear them! - // You need this baud for the HID library but still can use other bauds - // without HID functions. - // not needed for Leonardo/Micro, Serial will not be set - HID.begin(); + // Starts Serial at baud 115200 otherwise HID wont work on Uno/Mega. + // This is not needed for Leonado/(Pro)Micro but make sure to activate desired USB functions in HID.h + Serial.begin(SERIAL_HID_BAUD); // Sends a clean report to the host. This is important because // the 16u2 of the Uno/Mega is not turned off while programming - // so you want to start with a clear report to avoid strange bugs. - // its exactly the same like the end() function. - // You can also unplug the device if anything goes wrong. - // To prevent the 16u2 to send more reports just pull the Serial TX (pin1) low - // or see readme for turning off HID functions. - // If you did anything wrong (keyboard is doing weird stuff) - // just logout (no shutdown needed). + // so you want to start with a clean report to avoid strange bugs after reset. System.begin(); } diff --git a/plugins/KeyboardioHID/keywords.txt b/plugins/KeyboardioHID/keywords.txt index 8d04ebace5..56aad2fba4 100644 --- a/plugins/KeyboardioHID/keywords.txt +++ b/plugins/KeyboardioHID/keywords.txt @@ -41,6 +41,8 @@ Media KEYWORD3 System KEYWORD3 Gamepad1 KEYWORD3 Gamepad2 KEYWORD3 +Gamepad3 KEYWORD3 +Gamepad4 KEYWORD3 Joystick1 KEYWORD3 Joystick2 KEYWORD3 @@ -52,6 +54,9 @@ Joystick2 KEYWORD3 # Constants (LITERAL1) ####################################### +#General +SERIAL_HID_BAUD LITERAL1 + #Mouse MOUSE_LEFT LITERAL1 From 7cc19bd245baf61aff127451ceb0c9a3d27246d5 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Mon, 25 Aug 2014 03:35:18 +0200 Subject: [PATCH 043/602] Removed older versions --- .../Firmwares/Hoodloader1_7_3.hex | 613 ------------------ plugins/KeyboardioHID/Firmwares/Joystick.cpp | 63 -- plugins/KeyboardioHID/Firmwares/Joystick.h | 55 -- ...ino-usbserial-atmega16u2-Mega2560-Rev3.hex | 254 -------- ...uino-usbserial-atmega16u2-MegaADK-Rev3.hex | 254 -------- .../Arduino-usbserial-atmega16u2-Uno-Rev3.hex | 254 -------- plugins/KeyboardioHID/Firmwares/Readme.md | 4 +- plugins/KeyboardioHID/Readme.md | 8 +- 8 files changed, 7 insertions(+), 1498 deletions(-) delete mode 100644 plugins/KeyboardioHID/Firmwares/Hoodloader1_7_3.hex delete mode 100644 plugins/KeyboardioHID/Firmwares/Joystick.cpp delete mode 100644 plugins/KeyboardioHID/Firmwares/Joystick.h delete mode 100644 plugins/KeyboardioHID/Firmwares/OriginalFirmwares/Arduino-usbserial-atmega16u2-Mega2560-Rev3.hex delete mode 100644 plugins/KeyboardioHID/Firmwares/OriginalFirmwares/Arduino-usbserial-atmega16u2-MegaADK-Rev3.hex delete mode 100644 plugins/KeyboardioHID/Firmwares/OriginalFirmwares/Arduino-usbserial-atmega16u2-Uno-Rev3.hex diff --git a/plugins/KeyboardioHID/Firmwares/Hoodloader1_7_3.hex b/plugins/KeyboardioHID/Firmwares/Hoodloader1_7_3.hex deleted file mode 100644 index a5f35cfc18..0000000000 --- a/plugins/KeyboardioHID/Firmwares/Hoodloader1_7_3.hex +++ /dev/null @@ -1,613 +0,0 @@ -:1000000073C100008DC100008BC1000089C10000D8 -:1000100087C1000085C1000083C1000081C10000CC -:100020007FC100007DC100007BC100000C94BC0CAE -:100030000C94680D75C1000073C1000071C100000F -:100040006FC100006DC100006BC1000069C10000FC -:1000500067C1000065C1000063C1000012C200005A -:100060005FC100005DC100005BC1000059C100001C -:1000700057C1000030034100720064007500690040 -:100080006E006F00200048006F006F0064006C007D -:100090006F0061006400650072002000420065008E -:1000A00074006100000012034E00690063006F00DD -:1000B00048006F006F006400000004030904090297 -:1000C0005F00030100C032080B00020202010009B8 -:1000D00004000001020201000524001001042402B2 -:1000E000060524060001070582030800FF09040134 -:1000F00000020A0000000705040240000107058312 -:10010000024000010904020001030000000921115E -:1001100001000122B801070581032000011201102E -:1001200001EF020108EB03686E73010102DC0105B7 -:10013000010902A1010901A100850105091901298F -:10014000051500250195057501810295017503814D -:100150000305010930093109381581257F75089596 -:10016000038106C0C005010906A101850205071922 -:10017000E029E715002501750195088102950175B3 -:1001800008810395067508150025650507190029DE -:1001900065810005081901290595057501910295EC -:1001A0000175039103C006C0FF0A000CA10185037D -:1001B0007508150026FF00953F09018102953F094A -:1001C000029102C0050C0901A1018504150026FF5A -:1001D000FF19002AFFFF950475108100C005010971 -:1001E00080A1018505150026FF00190029FF950152 -:1001F00075088100C005010905A1018506050919D9 -:10020000012920150025017501952081020501A114 -:10021000000930093109320933093409351500273D -:10022000FFFF0000751095068102C005010939091C -:100230003915012508950275048102C005010905DB -:10024000A10185070509190129201500250175015E -:10025000952081020501A1000930093109320933D5 -:1002600009340935150027FFFF0000751095068138 -:1002700002C0093909391501250895027504810262 -:10028000C005010904A1018508A10005091901297A -:100290000215002501750195028102050109300949 -:1002A00031150026FF03750A95028102750295013A -:1002B0008103C0C005010904A1018509A100050948 -:1002C0001901290215002501750195028102050118 -:1002D00009300931150026FF03750A950281027560 -:1002E0000295018103C0C00011241FBECFEFD2E0F0 -:1002F000DEBFCDBF11E0A0E0B1E0E0E1F6E202C078 -:1003000005900D92AE32B107D9F712E0AEE2B1E03E -:1003100001C01D92A634B107E1F7BFD70C940613B4 -:100320006FCE9BB1809589238BB908959BB1982B93 -:100330009BB90895CF93DF9384B7877F84BF28E16B -:100340000FB6F89420936000109260000FBE80E119 -:1003500090E09093CD008093CC00CAECD0E096E082 -:100360009883A8ECB0E082E08C93E9ECF0E0208385 -:10037000539A5A9A5B9A10821C92188298838C9393 -:1003800088E980835B988AB180638AB98BB1806386 -:100390008BB90E94AD0C84E085BD5F9A579A209A74 -:1003A00022982A9ADF91CF9108950895089580E0C8 -:1003B00091E00E94EE1180E191E00E942B0FE2EEAD -:1003C000F0E080818460808308951F93CF93DF9352 -:1003D000EC01E98DE150E23028F4F0E0E55DFE4FFC -:1003E000108101C010E0888D823009F418608A8D78 -:1003F000873031F0883031F0863029F4126003C044 -:10040000146001C016605B9A1092C9001092C80077 -:100410001092CA002C893D894E895F89211581EE91 -:1004200038074105510579F0CA01B90196958795BC -:100430007795679560587B47814E9F4F0E94C71202 -:100440002150310902C020E130E03093CD002093EB -:10045000CC001093CA008C899D89AE89BF89811513 -:10046000914EA105B10511F480E001C082E08093B6 -:10047000C80088E98093C9005B98DF91CF911F91F4 -:1004800008951F920F920FB60F9211242F933F934E -:100490008F939F93AF93BF93EF93FF938091CE0081 -:1004A00090912E019330F9F090913D029430D9F45F -:1004B000EFE2F1E0A081B1818C938081918101967E -:1004C00091838083268137818217930721F4848169 -:1004D0009581918380832FB7F894828593850196C7 -:1004E000938782872FBFFF91EF91BF91AF919F912B -:1004F0008F913F912F910F900FBE0F901F901895E5 -:10050000FC01208920FF02C05F9808955F9A8BB19B -:1005100080638BB9089580E191E00E94041080E02F -:1005200091E00C94B71080910E0190910F0100970B -:1005300029F0019790930F0180930E010895EF9297 -:10054000FF920F931F93CF93DF937B01C901E801C3 -:10055000E091BD01EE2319F14091BE012091BF0150 -:1005600042131DC051E05093FF01F0E0E150FE4FF7 -:100570005083E0ECF1E050E0BF010E94F612809160 -:10058000BD01F70180838091BE018883198210929A -:10059000BD011092BF011092BE0181E001C080E058 -:1005A000DF91CF911F910F91FF90EF900895EF92FF -:1005B000FF920F931F93CF93DF931F92CDB7DEB7B8 -:1005C0007901633081F480E16983ABDE69816093F6 -:1005D000BC01B801C7010F90DF91CF911F910F911E -:1005E000FF90EF905BC70F90DF91CF911F910F911C -:1005F000FF90EF900895109215021092090208954D -:1006000020912E018091240190912501A091260135 -:10061000B09127010097A105B10539F0811532ECA1 -:10062000930731E0A307B10521F41A9B02C082E0D1 -:1006300007C00197A105B10511F483E001C081E075 -:1006400080932E0180912E01281709F44BC023308E -:1006500011F021111DC0EFE2F1E02FB7F8948BE308 -:1006600091E09183808393838283958384838BEB52 -:1006700091E09783868380E890E091878087138656 -:1006800012862FBF1092BB011092BC0180E34EDE98 -:1006900080912E01823041F4AEDF1092BD010895A9 -:1006A00080E091E00E9403128091BD01882331F027 -:1006B0009091BE018091BF01981791F380912E0116 -:1006C000833081F41092300110922F011092320188 -:1006D00010923101109234011092330180E326DE32 -:1006E00022982A9A08950F931F93CF93DF931F9216 -:1006F000CDB7DEB78C0180E191E069830E94C00F25 -:10070000809111018F708093E90049818091E80008 -:1007100080FFFCCF8091200180FF0BC050E0B8012A -:1007200080E191E00F90DF91CF911F910F910C9498 -:10073000500F0F90DF91CF911F910F910895CF929D -:10074000DF92EF92FF920F931F93FA018B010095B6 -:10075000109520E030E0980111270027AB0160E000 -:1007600070E0042B152B262B372B4CE150E097E043 -:1007700068017901042E04C0F694E794D794C794D5 -:100780000A94D2F76C2D683028F0973059F4C08263 -:1007900096E008C0C0829150C11004C04750510972 -:1007A000923031F7492F425013C0DF01A40FB11D21 -:1007B00068017901E894C7F8DD24EE24FF24CC9287 -:1007C000B7E03695279517950795BA95D1F741501B -:1007D0004111EBCF492F50E09A01A3E0220F331FC4 -:1007E000AA95E1F7206C3F6F3081322B3083E40F04 -:1007F000F51F319781508F7380688083892F1F91F7 -:100800000F91FF90EF90DF90CF900895CF93DF93FB -:1008100000D000D000D0CDB7DEB76091BD01662317 -:10082000A1F08091BF01811110C070E07160AE0134 -:100830004F5F5F4F81E083DF682FCE01019653DF6A -:1008400004C080E091E00E9403128091BD018823E2 -:1008500031F09091BE018091BF01981791F31092F1 -:10086000BD011092BF011092BE0126960FB6F894FA -:10087000DEBF0FBECDBFDF91CF9108950F931F93C1 -:10088000982F40911502E42FF0E0E15FFD4F808347 -:10089000809115028F5F80931502892F807C8038AC -:1008A00009F444C0803C09F05FC0292F28732695C5 -:1008B00026952695223008F477C0273079F4492F01 -:1008C0004F7050E060E070E040930A0250930B02DA -:1008D00060930C0270930D0215E00FC0892F877092 -:1008E00090E0A0E0B0E080930A0290930B02A09306 -:1008F0000C02B0930D02122F11508091090288232F -:1009000091F084DF6091150261508FE092E0EBDEA0 -:10091000E0911502F0E0E25FFD4F808180930F02CD -:1009200081E0809315021093090245C0809109026D -:100930008130D1F500910A0210910B0220910C0236 -:1009400030910D02A90166277727222733274027F8 -:100950005127622773274F3F5F4F6105710521F5CE -:10096000892F8F738F5F28C0809109028230E0F059 -:1009700081508093090240910A0250910B026091CC -:100980000C0270910D0227E0440F551F661F771F60 -:100990002A95D1F7492B40930A0250930B0260939A -:1009A0000C0270930D0207C031DF609115028FE0D9 -:1009B00092E099DE20DE80E01F910F910895CF93A1 -:1009C0005DDFC82F811105C07FC080E091E00E94EB -:1009D00003128091BD01882331F02091BE019091D6 -:1009E000BF01291791F3C130A9F590910B02913005 -:1009F00089F50CDF90910A029093BD011092BF011E -:100A00008FE3E0ECF1E0DF01282F1D922A95E9F752 -:100A10009530A9F058F4923081F018F49130C1F477 -:100A20000AC0933091F0943099F407C0983050F098 -:100A30009A3070F409C084E008C088E006C0C09312 -:100A4000BE0140C081E101C083E08093BE013AC095 -:100A5000DDDE38C0882381F16091BF01462F50E070 -:100A60008C2F90E09A012E5F3F4F359527952F5F91 -:100A70003F4F8217930701F5FA01E054FE4F809132 -:100A80000A028083E62FEF5FE093BF018091BE01F1 -:100A90008E1749F0F0E0E054FE4F90910B029083E6 -:100AA0006E5F6093BF019091BF0189130BC080E01E -:100AB00091E00E94031206C0A9DE609115028FE04A -:100AC00092E011DECF9197CDCF910895682F80E10C -:100AD00091E00E946E0F8823E9F080E191E00E948E -:100AE000C00F0E940F0F80E11CDC2FEF81EE94E01D -:100AF000215080409040E1F700C0000080E111DC0F -:100B00002FEF81EE94E0215080409040E1F700C04B -:100B10000000E9CF089580E191E00E94D60F97FD93 -:100B2000FACF0895EF92FF920F931F93CF93DF9325 -:100B30007C0109E311E0C0E0D0E005C0ECDFF80182 -:100B400081938F012196CE15DF05C4F3DF91CF91FC -:100B50001F910F91FF90EF9008959091450180E0D3 -:100B600020914601820F911D9093360180933501AB -:100B70009091470180E020914801820F911D909350 -:100B80003801809337010895CF93C82FC4DF803296 -:100B900039F484E19BDF8C2F99DF80E1CF9196CFF0 -:100BA00085E194DF80912F0190913001019690931F -:100BB000300180932F01CF910895813859F018F4B6 -:100BC000803871F405C0823839F0833949F406C0A1 -:100BD00082E007C081E005C082E103C083E501C077 -:100BE00080E0D2CF98DF803221F484E16FDF80E1B2 -:100BF0006DCF80E296DB2FEF80E792E021508040BE -:100C00009040E1F700C0000080E290DB2FEF80E72A -:100C100092E0215080409040E1F700C0000080E267 -:100C200080DB2FEF80E792E0215080409040E1F799 -:100C300000C0000080E27ADB85E148DF80912F016F -:100C40009091300101969093300180932F01089587 -:100C500083E58CBD8DB58EB508950DB407FEFDCF2F -:100C600008958EBDFADF8EB50895CF93DF9300D03F -:100C70001F92CDB7DEB72B834A836983F2DF698188 -:100C8000862FEFDF4A81842FECDF2B81822F0F909C -:100C90000F900F90DF91CF91E4CFDADF249A2C9A56 -:100CA000219A29982FEF80E792E0215080409040D0 -:100CB000E1F700C000002C982FEF80E792E0215070 -:100CC00080409040E1F700C000002398229A20E085 -:100CD00040E063E58CEAC9DF81E090E09093320167 -:100CE000809331010895462F880F880F880F20E0E8 -:100CF000672F805EBACF0F931F93CF93DF938C0142 -:100D0000C0E0D0E019C0609133017091340180E0FF -:100D1000EADFDCDE609133017091340181E0E3DFD2 -:100D2000D5DE20913301309134012F5F3F4F309356 -:100D30003401209333012296C017D10724F380E1B8 -:100D4000DF91CF911F910F91089584E090E0EADE4A -:100D500020913C0140913B0160913A018091390121 -:100D600084DF12CFD8DE803259F080912F0190912C -:100D7000300101969093300180932F0185E115C0D9 -:100D800084E1A4DE20E040E060E080E36EDF9EDEF0 -:100D900020E041E060E080E368DF98DE20E042E0B0 -:100DA00060E080E362DF92DE80E190CE23982298BB -:100DB000229A2198249810923201109231010895BC -:100DC000CF92DF92EF92FF920F931F93CF93DF9317 -:100DD000D82FC92F7B01CB01A5DE80E2A7DAE9E39A -:100DE000CE2EE1E0DE2E0D2F1C2FE80111C0F60102 -:100DF00021916F014C2F6D2F80EC37DFFFE722E34D -:100E000082E0F15020408040E1F700C000002196D0 -:100E1000CE01801B910B8E159F054CF380E281DA89 -:100E200080E1DF91CF911F910F91FF90EF90DF90C4 -:100E3000CF9008950F931F93CF93DF93C091330109 -:100E4000D0913401209137013091380128173907AA -:100E500024F0CC0FDD1F8C0112C080912F019091E6 -:100E6000300101969093300180932F0181E10EC0F3 -:100E700060E270E0CE01A4DFA096005211090132B9 -:100E80001105B4F7B801CE019BDF80E1DF91CF916E -:100E90001F910F910895EF92FF920F931F93CF939D -:100EA000DF937C010091330110913401000F111F79 -:100EB000E80107C02FEF4C2F6D2F80EAD6DE06DE4B -:100EC0002196CE01801B910B8E159F059CF380E12E -:100ED000DF91CF911F910F91FF90EF9008951F9395 -:100EE000CF93DF9318DED82F16DEC82F14DE182F0D -:100EF00012DE803259F080912F01909130010196DD -:100F00009093300180932F0185E113C03D2F20E0A5 -:100F1000C9018C0F911DEC0184E1D8DD163419F460 -:100F2000CE01E9DE06C0153419F4CE01B4DF01C0EC -:100F300081E1DF91CF911F91C9CDCF93DF9300D095 -:100F4000CDB7DEB7482F80E249839A83EFD920E0FE -:100F500049819A81692F8CE488DE2FEF86E791E042 -:100F6000215080409040E1F700C0000080E20F90E7 -:100F70000F90DF91CF91D5C98091350190913601C5 -:100F800020913301309134018032910511F4207F9A -:100F90000EC08034910511F4207E09C0803891057F -:100FA00011F4207C04C08115914009F42078C90116 -:100FB0000895962F672F242F880F880F880F492FA9 -:100FC000805C53CECF92DF92EF92FF920F931F93EC -:100FD000CF93DF936C01D0DF8C01C0E0D0E029C05B -:100FE000CBDF0817190721F0C801A7DFC5DF8C0187 -:100FF000BEE2EB2EB1E0FB2EEC0EFD1E6091330144 -:1010000070913401F701438580E0D3DF229660912F -:10101000330170913401F701448581E0CADF2091EA -:101020003301309134012F5F3F4F309334012093CF -:101030003301CC15DD05A4F2C8017FDF80E1DF912B -:10104000CF911F910F91FF90EF90DF90CF90089577 -:10105000CF93DF93EC0166DD5EDD803229F484E11D -:1010600035DDCE01AFDF0AC080912F0190913001B4 -:1010700001969093300180932F0185E1DF91CF910C -:1010800025CDCF93DF9347DDD82F80E0C82F43DDF8 -:10109000C80FD11DC13081E0D80764F081E116DDB1 -:1010A00080912F01909130010196909330018093AF -:1010B0002F0122C030DD863421F4CE01DF91CF91A3 -:1010C000C7CF8534A9F4CE01B5DEC82F24DD803228 -:1010D00021F484E1FBDC8C2F0CC080912F019091D6 -:1010E000300101969093300180932F0185E101C07A -:1010F00081E1DF91CF91EACCDF91CF910895CF9339 -:10110000DF938091310190913201892B19F080E2B7 -:1011100008D902C080E20AD980912F019091300154 -:10112000892B19F080E1FDD802C080E1FFD880E171 -:1011300091E03CD797FDAEC08135910509F485C09B -:10114000E4F48134910509F452C054F480339105DC -:1011500099F181339105A9F1809709F089C07EC08A -:101160008534910509F44EC08035910509F44EC0CF -:101170008234910509F07CC03EC08136910509F4A6 -:1011800059C06CF48635910509F45CC08036910530 -:1011900009F44FC08535910509F06AC039C084371C -:1011A000910509F44CC08537910509F454C0843683 -:1011B000910509F05DC040C01092300110922F01DE -:1011C0001EC0A9DC803209F065C084E17FDC81E4C7 -:1011D0007DDC86E57BDC82E579DC80E277DC89E416 -:1011E00075DC83E573DC80E571DC80E150C093DC65 -:1011F000DF91CF91E2CC84E190E094DCAEDCDF9132 -:10120000CF91F0CC85E090E08DDCF9CF46DDF7CFD3 -:1012100082DCC82FD0E0D0933401C09333017BDC53 -:10122000382F20E02C0F3D1F3093340120933301E1 -:10123000E6CF71DC70DCE3CFDF91CF9122CFDF917D -:10124000CF914DCEDF91CF9180CD10923001109291 -:101250002F01ACDDD4CFDF91CF9184CD80912F01D0 -:101260009091300101969093300180932F010EC030 -:1012700080912F01909130010196909330018093DD -:101280002F0149DC803211F482E101C085E1DF9158 -:10129000CF911CCCDF91CF91089510922E018AE05E -:1012A000EFEFF1E0DF011D928A95E9F743D87894DA -:1012B000C3E0FC2E0FE211E0A3D98091FF01811160 -:1012C00001C089B180912E01833011F418DF90C0E4 -:1012D00080E191E06BD6EC0197FD0AC080E121D856 -:1012E000F092BC018091C80085FFFCCFC093CE0076 -:1012F0008FB7F894C0913901D0913A018FBF2097F0 -:1013000019F4A89949C06CC080E20BD8F092BB01D7 -:10131000809111018F708093E9008091E80080FF37 -:10132000F0CFCE01C034D10510F08FE390E0E82E6D -:10133000C0E0D0E02EC080912E01813061F0F80134 -:10134000A281B3818D91B383A28326813781A217B5 -:10135000B30781F40BC0E0913101F091320160815B -:1013600080E191E0BBD5882351F3CBCF2481358137 -:10137000338322839FB7F894228533852150310926 -:10138000338722879FBF90912E01923009F417DB9B -:101390002196EC12D0CFB5CFA89A8091BB018823BB -:1013A00099F081508093BB0181110EC080912E0174 -:1013B000823039F42BDA609115028FE092E093D9F4 -:1013C0001AD980E20E9496018091BC01882341F0E5 -:1013D00081508093BC01811103C080E10E9496017D -:1013E00080912E01823021F480E091E00E9403126E -:1013F00080E191E0C5D513D55FCF292F3327233066 -:101400003105B1F04CF42130310509F439C02230F6 -:10141000310509F03AC007C02132310539F12232D5 -:10142000310549F132C0EFE5F0E08EEB90E031C0DC -:1014300099278130910561F08230910581F0892BE7 -:1014400021F5EAEBF0E0E491F0E08AEB90E021C0D6 -:10145000E6EAF0E0E491F0E086EA90E01AC0E4E722 -:10146000F0E0E491F0E084E790E013C0E9E0F0E020 -:101470008DE091E00EC0E8EBF1E08FE291E009C071 -:10148000E2E1F0E08DE191E004C0E0E0F0E080E036 -:1014900090E0DA018D939C93CF010895680F791F36 -:1014A00009C0FC012191CF013091C80035FFFCCF6C -:1014B0002093CE0086179707A1F70895BF92CF9289 -:1014C000DF92EF92FF920F931F93CF93DF937C01F4 -:1014D0008B01EA01D7D1B82E811132C0209731F0AB -:1014E00028813981021B130BE20EF31EC12CD12C73 -:1014F00022C08091E80085FD14C08091E8008E77BD -:101500008093E800209749F0888199818C0D9D1D7A -:101510009983888325E0B22E13C0B4D1882359F073 -:101520000EC0F70181917F018093F10001501109F4 -:10153000FFEFCF1ADF0A01151105D9F601C0B82E49 -:101540008B2DDF91CF911F910F91FF90EF90DF9046 -:10155000CF90BF9008952091440230914502261704 -:10156000370748F06115710539F42091E8002E77AE -:101570002093E80001C0B9019C0180E034C0909143 -:101580003D02992309F443C0953009F442C090917B -:10159000E80093FD3AC09091E80092FD30C0909130 -:1015A000E80090FF20C08091F20090E0F901821BDA -:1015B000930B05C021912093F100615071099F01A7 -:1015C000280F391F6115710519F02830310590F386 -:1015D00081E02830310509F080E09091E8009E77A5 -:1015E0009093E8009F016115710549F68111C7CFFD -:1015F00006C080913D02882351F0853051F08091E2 -:10160000E80082FFF6CF80E0089581E0089582E04F -:10161000089583E008956115710529F42091E8008B -:101620002B772093E8009C0121C080913D02882304 -:1016300081F1853041F18091E80083FD26C08091E1 -:10164000E80082FFF2CFF90107C08091F100819399 -:101650009F016150710929F09F018091F200811171 -:10166000F4CF8091E8008B778093E80061157105D5 -:10167000E1F68091E80080FD0AC080913D02882358 -:1016800041F08530B1F783E0089581E0089580E06E -:10169000089582E008952091440230914502261772 -:1016A000370748F06115710539F42091E8002E776D -:1016B0002093E80001C0B9019C0180E035C0909101 -:1016C0003D02992309F444C0953009F443C0909138 -:1016D000E80093FD3BC09091E80092FD31C09091ED -:1016E000E80090FF21C08091F20090E0F901821B98 -:1016F000930B06C024912093F1003196615071093B -:101700009C012E0F3F1F6115710519F0283031051E -:1017100088F381E02830310509F080E09091E800FD -:101720009E779093E8009F016115710541F6811144 -:10173000C6CF06C080913D02882351F0853051F01C -:101740008091E80082FFF6CF80E0089581E008955F -:1017500082E0089583E00895982F2CC09093E900CB -:10176000981739F07091EC002091ED005091F00045 -:1017700003C0242F762F50E021FD02C09F5F1AC0C6 -:101780003091EB003E7F3093EB003091ED003D7FD8 -:101790003093ED003091EB0031603093EB007093AB -:1017A000EC002093ED005093F0002091EE0027FD17 -:1017B000E5CF07C0953090F28F708093E90081E00B -:1017C000089580E008950F931F93CF93DF93062F22 -:1017D000EC0110E02EC09881911103C01F5F259687 -:1017E00028C02C81E981FA816B81892F8F70853027 -:1017F00010F080E021C0223010F056E001C052E02D -:1018000028E030E040E003C04F5F220F331F2E1767 -:101810003F07D0F34295407F452B991F9927991F89 -:101820006295660F660F607C692B96DF8111D6CFBB -:10183000E0CF1013D0CF81E0DF91CF911F910F91B6 -:10184000089580913E0287FD05C08091E80080FFE9 -:101850000EC012C08091E80082FD05C080913D025B -:101860008111F8CF08958091E8008B7708C08091AE -:101870003D028111EACF08958091E8008E77809330 -:10188000E80008958091E4009091E50045E62091FC -:10189000EC0020FD1FC023C020913D02222391F0C7 -:1018A000253091F02091EB0025FD10C02091E4003F -:1018B0003091E5002817390751F34150C90139F734 -:1018C00084E0089582E0089583E0089581E008951A -:1018D00080E008952091E80020FFDECFF9CF20912D -:1018E000E80022FFD9CFF4CF41D043D08091D80077 -:1018F0008F778093D8008091D80080688093D8003B -:101900008091D8008F7D8093D80084E089BD86E0E7 -:1019100089BD09B400FEFDCF10923D02109239023C -:1019200010923B0210923A0242E060E080E014DF45 -:101930008091E1008E7F8093E1008091E2008160E0 -:101940008093E2008091E20088608093E2008091C1 -:10195000E0008E7F8093E0000895E3E6F0E0808170 -:101960008E7F808381E080933C02BECF1092E200A4 -:1019700008951092E10008951F920F920FB60F92F2 -:1019800011242F933F934F935F936F937F938F9384 -:101990009F93AF93BF93EF93FF938091E10082FFFA -:1019A0000BC08091E20082FF07C08091E1008B7F35 -:1019B0008093E1000E9493028091E10080FF18C0B3 -:1019C0008091E20080FF14C08091E2008E7F8093BE -:1019D000E2008091E20080618093E2008091D80073 -:1019E00080628093D80019BC10923D020E94D601FB -:1019F0008091E10084FF30C08091E20084FF2CC020 -:101A000084E089BD86E089BD09B400FEFDCF8091E8 -:101A1000D8008F7D8093D8008091E1008F7E8093E5 -:101A2000E1008091E2008F7E8093E2008091E200ED -:101A300081608093E20080913902882311F084E074 -:101A400007C08091E30087FF02C083E001C081E00E -:101A500080933D020E94D5018091E10083FF27C061 -:101A60008091E20083FF23C08091E100877F809313 -:101A7000E10082E080933D02109239028091E10002 -:101A80008E7F8093E1008091E2008E7F8093E20060 -:101A90008091E20080618093E20042E060E080E0BB -:101AA0005BDE8091F00088608093F000B7D1FF91F9 -:101AB000EF91BF91AF919F918F917F916F915F91C6 -:101AC0004F913F912F910F900FBE0F901F9018953F -:101AD0001F920F920FB60F9211242F933F934F93A3 -:101AE0005F936F937F938F939F93AF93BF93CF93A6 -:101AF000EF93FF938091E9008F709091EC0090FF3D -:101B000002C090E801C090E0C92FC82B1092E900F4 -:101B10008091F000877F8093F00078941CD0109221 -:101B2000E9008091F00088608093F000CF70C0934E -:101B3000E900FF91EF91CF91BF91AF919F918F916C -:101B40007F916F915F914F913F912F910F900FBEB9 -:101B50000F901F9018951F93CF93DF93CDB7DEB7EB -:101B6000AC970FB6F894DEBF0FBECDBFEEE3F2E048 -:101B70008091F100819322E0E634F207C9F70E94D8 -:101B80008B028091E80083FF31C180913E029091E9 -:101B90003F02953009F487C038F49130B1F170F00C -:101BA000933009F023C131C0983009F4F3C0993063 -:101BB00009F4FFC0963009F019C19BC0803821F0AC -:101BC000823809F013C108C080913A0290913B021B -:101BD000992389F082600FC0809142029091430264 -:101BE0008F7099278093E9008091EB0085FB88270F -:101BF00080F91092E9009091E800977F9093E800B7 -:101C00008093F1001092F100D0C0882319F0823047 -:101C100009F0ECC08F7121F0823009F0E7C00BC0F1 -:101C200080914002813009F0E1C0933009F080E0FA -:101C300080933B022FC08091400281112BC0809184 -:101C40004202909143028F709927009709F4CEC009 -:101C50008093E9002091EB0020FF1CC020913F02FF -:101C6000233021F48091EB00806212C09091EB0050 -:101C700090619093EB0021E030E001C0220F8A9543 -:101C8000EAF72093EA001092EA008091EB00886066 -:101C90008093EB001092E9008091E800877F8093A9 -:101CA000E800CFDDA3C08111A1C0809140029091D6 -:101CB00041028F779927182F9091E3009078982B05 -:101CC0009093E3008091E800877F8093E800B9DD7E -:101CD0008091E80080FFFCCF8091E30080688093D2 -:101CE000E300112311F083E001C082E080933D0204 -:101CF0007DC08058823008F079C080914002909178 -:101D000041028C3D23E0920771F583E08A838AE2E9 -:101D100089834FB7F894DE01139620E03EE051E24C -:101D2000E32FF0E050935700E49120FF03C0E295C9 -:101D3000EF703F5FEF708E2F90E0EA3010F0C796A3 -:101D400001C0C0968D939D932F5F243149F74FBFFB -:101D50008091E800877F8093E8006AE270E0CE011E -:101D60000196F9DB11C0AE01455D5F4F6091420203 -:101D700044DB0097D9F12091E800277F2093E80009 -:101D8000BC018BA59CA587DC8091E8008B778093B4 -:101D9000E8002CC0803851F58091E800877F80935F -:101DA000E800809139028093F1008091E8008E77FD -:101DB00076CF81111BC0909140029230B8F480918F -:101DC000E800877F8093E800909339023ADD8091A4 -:101DD0003902811104C08091E30087FF02C084E0D2 -:101DE00001C081E080933D020E94D7018091E8000C -:101DF00083FF0AC08091E800877F8093E80080918C -:101E0000EB0080628093EB00AC960FB6F894DEBFD7 -:101E10000FBECDBFDF91CF911F9108950895CF934D -:101E200080913D028823A9F08091E9008F70909104 -:101E3000EC0090FF02C090E801C090E0C92FC82BD1 -:101E40001092E9008091E80083FD85DECF70C09399 -:101E5000E900CF910895CF93DF93EC014096FC0108 -:101E60008BE0DF011D928A95E9F782E08C838987F8 -:101E700083E08E8761E0CE010196A5DC882361F0C6 -:101E800061E0CE0106969FDC882331F061E0CE014F -:101E90000B96DF91CF9197CC80E0DF91CF910895A1 -:101EA0000F931F93FC01CB01BA0120913D02243016 -:101EB00089F40489158926893789012B022B032B84 -:101EC00049F021812F702093E90040E050E01F91FC -:101ED0000F91F4CA82E01F910F910895CF93C62FFE -:101EE00020913D022430F1F4FC0144895589668932 -:101EF0007789452B462B472BA9F081818F708093E2 -:101F0000E9008091E80085FF04C0C093F10080E003 -:101F10000AC08091E8008E778093E800B3DC8823C4 -:101F2000A1F301C082E0CF91089520913D022430B9 -:101F300029F5FC014489558966897789452B462B0B -:101F4000472BE1F081818F708093E9008091F2004E -:101F5000811102C080E008959091E8008091E8002E -:101F60008E778093E80095FDF5CF8CDC811107C05A -:101F70009091E8009E779093E800089582E008959C -:101F800020913D02243089F4FC01448955896689F9 -:101F90007789452B462B472B41F021812F702093C9 -:101FA000E9002091E80020FDC0CF089520913D0276 -:101FB000243019F02FEF3FEF24C0FC0144895589EC -:101FC00066897789452B462B472BA1F386818F7035 -:101FD0008093E9008091E80082FFECCF8091F200CD -:101FE000882321F02091F10030E002C02FEF3FEF75 -:101FF0008091F200811105C08091E8008B77809379 -:10200000E800C90108950895CF93DF93EC01809112 -:10201000E80083FFA9C0888190E0209142023091BE -:1020200043022817390709F09FC080913F0281328F -:1020300061F020F4803209F097C03DC0823209F48B -:102040006EC0833209F090C07FC080913E02813A19 -:1020500009F08AC08091E800877F8093E800809132 -:10206000E80080FFFCCF4C895D896E897F894093B1 -:10207000F100BB27A72F962F852F8093F100CB016E -:10208000AA27BB278093F100472F5527662777277C -:102090004093F100888D8093F100898D8093F10049 -:1020A0008A8D8093F1008091E8008E778093E8001C -:1020B000DF91CF91C6CB80913E02813209F054C0AE -:1020C0008091E800877F8093E80005C080913D0201 -:1020D000882309F449C08091E80082FFF7CF30914E -:1020E000F1002091F1009091F1008091F1003C8B82 -:1020F0002D8B9E8B8F8B8091F100888F8091F100CA -:10210000898F8091F1008A8F8091E8008B7780938E -:10211000E80097DBCE01DF91CF910C94E50180912F -:102120003E02813209F58091E800877F8093E800C4 -:1021300088DB8091400290914102998B888BCE017F -:10214000DF91CF910C94800280913E02813261F444 -:102150008091E800877F8093E80073DB6091400204 -:10216000CE01DF91CF914FCFDF91CF9108956F9244 -:102170007F928F929F92AF92BF92CF92DF92EF9217 -:10218000FF920F931F93CF93DF9300D01F92CDB791 -:10219000DEB77C01ADB6BEB68091E80083FF07C113 -:1021A000F701808190E0209142023091430228178C -:1021B000390709F0FCC080913F02833009F49EC0CA -:1021C00030F4813071F0823009F0F1C0D4C08A302F -:1021D00009F4B9C08B3009F4A2C0893009F0E7C016 -:1021E0004CC080913E02813A09F0E1C08DB69EB6A6 -:1021F0001A82198280914002109141028B83F7016B -:1022000040858DB79EB7841B91090FB6F8949EBF89 -:102210000FBE8DBFCDB6DEB6EFEFCE1ADE0A3601A9 -:1022200050E060E070E0C601EAD1412F41508E01DC -:102230000F5F1F4F9601BE016D5F7F4FC7010E9468 -:102240009F02F701268137812115310529F040854C -:1022500050E0B601C901CAD11092E9008091E800AE -:10226000877F8093E80069817A81C30174D9809166 -:10227000E8008B778093E80039C080913E0281327C -:1022800009F095C08DB69EB60091440210914502AA -:1022900070904002609041028DB79EB7801B910BF9 -:1022A0000FB6F8949EBF0FBE8DBFCDB6DEB6EFEF72 -:1022B000CE1ADE0A8091E800877F8093E800B8019B -:1022C000C601A9D98091E8008E778093E80021E0CB -:1022D000711001C020E030E0021B130B2C0D3D1DDE -:1022E000462D4150672DC7010E94D702882D992D98 -:1022F0000FB6F8949EBF0FBE8DBF59C080913E02AD -:10230000813A09F054C08091E800877F8093E8000B -:102310008091E80080FFFCCFF701818540C080916B -:102320003E02813209F043C08091E800877F8093AC -:10233000E80087DA9091400281E0911101C080E0CD -:10234000F701818734C080913E02813281F580910E -:10235000E800877F8093E80074DA809140029091D2 -:102360004102882736E0969587953A95E1F7F7017F -:10237000958784871CC080913E02813AC1F4809188 -:10238000E800877F8093E8008091E80080FFFCCF21 -:10239000F701848595859695879596958795809381 -:1023A000F1008091E8008E778093E8004ADA0FB65A -:1023B000F894BEBE0FBEADBE0F900F900F90DF9190 -:1023C000CF911F910F91FF90EF90DF90CF90BF9032 -:1023D000AF909F908F907F906F9008959C01275FA2 -:1023E0003F4FF90127E0DF011D922A95E9F721E02F -:1023F000FC01218724EF31E03587248723E0248303 -:1024000061E00196E0C94F925F926F927F928F9246 -:102410009F92AF92BF92CF92DF92EF92FF920F9373 -:102420001F93CF93DF9300D01F92CDB7DEB77C010F -:10243000ADB6BEB680913D02843009F08FC0809168 -:10244000E4009091E500F7012285338528173907CC -:1024500009F484C081818F708093E9008091E80045 -:1024600085FF7CC06DB67EB640858DB79EB7841B58 -:1024700091090FB6F8949EBF0FBE8DBFCDB6DEB6E4 -:10248000EFEFCE1ADE0A1B821A821982460150E053 -:1024900060E070E0C601B3D08E010F5F1F4F960160 -:1024A00040E0BE016D5F7F4FC7010E949F02582E22 -:1024B000F70184859585892B31F001E010E0868550 -:1024C0009785892B11F000E010E0F701C680D780D6 -:1024D000C114D10489F049815A81B601C40179D06F -:1024E00044244394009709F4412CF701408550E0BF -:1024F000B401C6017BD001C0412C89819A81892B0E -:10250000F9F0511004C0411002C000FF19C0F701DA -:10251000848595859787868781818F708093E90070 -:102520008B8181118093F10069817A8140E050E0D4 -:10253000C4010E945E0A8091E8008E778093E800D3 -:102540008091E4009091E500F70193878287862DC2 -:10255000972D0FB6F8949EBF0FBE8DBF0FB6F8949F -:10256000BEBE0FBEADBE0F900F900F90DF91CF910A -:102570001F910F91FF90EF90DF90CF90BF90AF90A1 -:102580009F908F907F906F905F904F900895A1E201 -:102590001A2EAA1BBB1BFD010DC0AA1FBB1FEE1FDD -:1025A000FF1FA217B307E407F50720F0A21BB30B28 -:1025B000E40BF50B661F771F881F991F1A9469F7A4 -:1025C00060957095809590959B01AC01BD01CF0100 -:1025D0000895FB01DC0104C08D910190801921F464 -:1025E00041505040C8F7881B990B0895FB01DC014E -:1025F00002C001900D9241505040D8F70895DC017F -:1026000001C06D9341505040E0F70895F894FFCF1A -:1026100002812000000100003F00000000000000D7 -:102620000083400000010440000001820800000116 -:0E26300000000000000000000000003020004C -:00000001FF diff --git a/plugins/KeyboardioHID/Firmwares/Joystick.cpp b/plugins/KeyboardioHID/Firmwares/Joystick.cpp deleted file mode 100644 index 1985694393..0000000000 --- a/plugins/KeyboardioHID/Firmwares/Joystick.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -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 "Joystick.h" - -//================================================================================ -// Joystick -//================================================================================ - -Joystick_ Joystick1(HID_REPORTID_Joystick1Report); -Joystick_ Joystick2(HID_REPORTID_Joystick2Report); - -Joystick_::Joystick_(uint8_t reportID){ - _reportID = reportID; -} - -void Joystick_::begin(void){ - memset(&_report, 0, sizeof(_report)); - HID_SendReport(_reportID, &_report, sizeof(_report)); -} - -void Joystick_::end(void){ - begin(); -} - -void Joystick_::write(void){ - HID_SendReport(_reportID, &_report, sizeof(_report));; -} - -void Joystick_::press(uint8_t b){ - if (b == 1) _report.button1 = 1; - else if (b == 2) _report.button2 = 1; -} - -void Joystick_::release(uint8_t b){ - if (b == 1) _report.button1 = 0; - else if (b == 2) _report.button2 = 0; -} - -void Joystick_::releaseAll(void){ - _report.button1 = 0; - _report.button2 = 0; -} \ No newline at end of file diff --git a/plugins/KeyboardioHID/Firmwares/Joystick.h b/plugins/KeyboardioHID/Firmwares/Joystick.h deleted file mode 100644 index db0526205e..0000000000 --- a/plugins/KeyboardioHID/Firmwares/Joystick.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -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 JOYSTICK_H -#define JOYSTICK_H - -#include "HID.h" - -//================================================================================ -// Joystick -//================================================================================ - -class Joystick_{ -public: - Joystick_(uint8_t reportID); - void begin(void); - void end(void); - void write(void); - void press(uint8_t b); - void release(uint8_t b); - void releaseAll(void); - inline void buttons(uint8_t b){ _report.buttons = b; } - inline void xAxis(uint16_t a){ _report.xAxis = a; } - inline void yAxis(uint16_t a){ _report.yAxis = a; } - -private: - HID_JoystickReport_Data_t _report; - uint8_t _reportID; -}; -extern Joystick_ Joystick1; -extern Joystick_ Joystick2; - -#endif - diff --git a/plugins/KeyboardioHID/Firmwares/OriginalFirmwares/Arduino-usbserial-atmega16u2-Mega2560-Rev3.hex b/plugins/KeyboardioHID/Firmwares/OriginalFirmwares/Arduino-usbserial-atmega16u2-Mega2560-Rev3.hex deleted file mode 100644 index 6ff3644796..0000000000 --- a/plugins/KeyboardioHID/Firmwares/OriginalFirmwares/Arduino-usbserial-atmega16u2-Mega2560-Rev3.hex +++ /dev/null @@ -1,254 +0,0 @@ -:1000000090C00000A9C00000A7C00000A5C000006B -:10001000A3C00000A1C000009FC000009DC0000060 -:100020009BC0000099C0000097C0000048C40000B9 -:100030000CC4000091C000008FC000008DC0000003 -:100040008BC0000089C0000087C0000085C0000090 -:1000500083C0000081C000007FC0000002C100001A -:100060007BC0000079C0000077C0000075C00000B0 -:1000700073C0000071C000006FC000006DC00000C0 -:100080006BC0000069C0000067C0000065C00000D0 -:1000900063C0000061C000001201100102000008EE -:1000A0004123420001000102DC0109023E0002017D -:1000B00000C0320904000001020201000524000111 -:1000C0001004240206052406000107058203080027 -:1000D000FF09040100020A000000070504024000B5 -:1000E00001070583024000010403090432034100B3 -:1000F00072006400750069006E006F002000280027 -:100100007700770077002E006100720064007500B0 -:1001100069006E006F002E0063006300290000007C -:10012000000011241FBECFEFD2E0DEBFCDBF11E033 -:10013000A0E0B1E0ECEAFFE002C005900D92A6312C -:10014000B107D9F712E0A6E1B1E001C01D92AF32CC -:10015000B107E1F7F1D028C753CF9C01DC01AE57BE -:10016000BF4FED91FC91119741911196FC93EE9345 -:1001700080589F4FE817F90711F42D933C939FB7D0 -:10018000F894F901EC57FF4F8081815080839FBF25 -:10019000842F0895DF92EF92FF920F931F93FC013B -:1001A0008489813019F0823021F405C040E3D42ED7 -:1001B00004C0DD2402C030E2D32E8389823011F4E2 -:1001C00088E0D82A8589873031F0883031F0863050 -:1001D00031F482E003C084E001C086E0D82A1092A6 -:1001E000C9001092C8001092CA00E784F088018903 -:1001F000128980E0E81681EEF80680E0080780E0CA -:10020000180719F420E130E00FC0C801B701969536 -:1002100087957795679560587B47814E9F4FA801DA -:100220009701A0D6215030403093CD002093CC00D0 -:10023000D092CA0080E0E81681EEF80680E0080758 -:1002400080E0180711F082E001C080E08093C800D0 -:1002500088E98093C9001F910F91FF90EF90DF9084 -:1002600008951F920F920FB60F9211242F938F9320 -:100270009F93EF93FF939091CE008EB38430F1F46F -:10028000E0919901F0919A019083E0919901F091A8 -:100290009A01CF01019690939A018093990189590F -:1002A000914021F489E191E0928381839FB7F89492 -:1002B00080919D018F5F80939D019FBFFF91EF9182 -:1002C0009F918F912F910F900FBE0F901F901895B7 -:1002D000FC01858580FF02C05F9808955F9A0895AC -:1002E00080E091E0D5C580E091E088C584B7877F44 -:1002F00084BF28E10FB6F89420936000109260004C -:100300000FBE87E690E09093CD008093CC0086E00E -:100310008093CA001092C8002093C900539A5A9A39 -:100320008AB180638AB98BB180638BB983D284E050 -:1003300085BD5F9A579A08950F931F93CF93DF93CC -:10034000D5DF2FB7F8948EE991E090931F02809348 -:100350001E0290932102809320022FBF2FB7F894A2 -:1003600089E191E090939A018093990190939C0187 -:1003700080939B012FBF7894CEE9D1E003E08FB743 -:10038000F894909122028FBF903809F180E091E0BB -:10039000ABD497FD1CC0E0911E02F0911F02808338 -:1003A000E0911E02F0911F02CF01019690931F026F -:1003B00080931E028E51924011F4D283C1839FB765 -:1003C000F894809122028F5F809322029FBF8FB7A3 -:1003D000F89410919D018FBFA89902C0113678F151 -:1003E000A89A80919D01882361F05D980093160181 -:1003F00008C089E191E0B1DE682F80E091E0DAD4B5 -:1004000011501123B1F780911601882351F080918A -:10041000160181508093160180911601882309F4FA -:100420005D9A80911701882351F0809117018150C6 -:100430008093170180911701882309F45C9A8FB784 -:10044000F894909122028FBF992369F08EE991E090 -:1004500084DE982F8091C80085FFFCCF9093CE005A -:100460005C980093170180E091E095D42AD487CF5F -:10047000DA01923049F0933061F09130F9F4E8E913 -:10048000F0E022E130E01EC0EAEAF0E02EE330E0E6 -:1004900019C0813049F0813018F0823079F408C0F9 -:1004A000E8EEF0E0849107C0ECEEF0E0849103C048 -:1004B000E0E2F1E08491282F30E004C0E0E0F0E0D9 -:1004C00020E030E0ED93FC93C901089528E030E08E -:1004D00040E003C04F5F220F331F28173907D0F3C6 -:1004E000842F8295807F08958093E9008091EB00AE -:1004F00081608093EB001092ED006093EC004093DC -:10050000ED008091EE00881F8827881F08951092C3 -:10051000F40090E09093E9001092F0001092E8004F -:100520001092ED008091EB008E7F8093EB009F5F37 -:10053000953081F708958091270288238CF403C0B9 -:100540008EB38823B1F08091E80082FFF9CF8091CB -:10055000E8008B778093E80008958EB3882349F0F4 -:100560008091E80080FFF9CF8091E8008E7780933A -:10057000E800089594E68091EC0080FF05C080912A -:10058000E80080FF05C023C08091E80082FD1FC005 -:100590008EB3882311F482E008958EB3853011F470 -:1005A00083E008958091EB0085FF02C081E008950B -:1005B0008091E10082FFDFCF8091E1008B7F80930B -:1005C000E100992311F484E008959150D4CF80E0A4 -:1005D00008959C0140912D0250912E024617570715 -:1005E00018F4F90120E038C06115710511F0AB0174 -:1005F000F8CF8091E8008E778093E80040E050E0EB -:10060000F0CF8091E80083FF02C081E008958091DF -:10061000E80082FD2DC08EB3882381F18EB3853032 -:1006200079F18091E80080FF17C09091F20006C038 -:1006300081918093F100415050409F5F41155105D9 -:1006400011F09830A8F320E0983009F421E080916F -:10065000E8008E778093E8004115510591F622233A -:1006600081F606C08EB3882349F08EB3853041F001 -:100670008091E80082FFF6CF80E0089582E008953F -:1006800083E008959C0140912D0250912E0246175F -:10069000570710F490E03BC06115710511F0AB01F4 -:1006A000F9CF8091E8008E778093E80040E050E039 -:1006B000F1CF8091E80083FF02C081E0089580912E -:1006C000E80082FD30C08EB3882399F18EB3853067 -:1006D00091F18091E80080FF1AC08091F20009C07A -:1006E000F9012F5F3F4FE491E093F10041505040FA -:1006F0008F5F4115510511F0883090F390E08830FC -:1007000009F491E08091E8008E778093E80041152C -:10071000510579F6992369F606C08EB3882349F00E -:100720008EB3853041F08091E80082FFF6CF80E003 -:10073000089582E0089583E008959C016115710594 -:1007400029F48091E8008B778093E800F90120C0BC -:100750008091E80083FF02C081E008958EB3882372 -:1007600039F18EB3853031F18091E80082FFF0CF0E -:1007700006C08091F10081936150704021F080911A -:10078000F2008823B1F78091E8008B778093E8002E -:1007900061157105E9F606C08EB3882349F08EB362 -:1007A000853041F08091E80080FFF6CF80E0089529 -:1007B00082E0089583E0089542D044D01EBA10929A -:1007C0002502109224021092230284E089BD89B58B -:1007D000826089BD09B400FEFDCF8091D800982FBA -:1007E0009F779093D80080688093D80080916300B1 -:1007F0008E7F809363008091D8008F7D8093D80096 -:100800008091E0008E7F8093E0008091E1008E7FF8 -:100810008093E1008091E20081608093E20080910A -:10082000E100877F8093E1008091E20088608093FF -:10083000E2000895C1DF81E08093260208951092BE -:10084000E20008951092E10008951F920F920FB6F2 -:100850000F9211241F932F933F934F935F936F93A6 -:100860007F938F939F93AF93BF93EF93FF93E9EEA3 -:10087000F0E0108117701082E0EFF0E08081877F58 -:1008800080837894C3D0F894A9EEB0E01C92E0EF96 -:10089000F0E08081886080831C93FF91EF91BF918D -:1008A000AF919F918F917F916F915F914F913F9108 -:1008B0002F911F910F900FBE0F901F9018951F92B0 -:1008C0000F920FB60F9211242F933F934F935F9384 -:1008D0006F937F938F939F93AF93BF93EF93FF9308 -:1008E0008091E10080FF1BC08091E20080FF17C073 -:1008F0008091E1008E7F8093E1008091E2008E7F05 -:100900008093E2008091E20080618093E200809118 -:10091000D80080628093D80019BC1EBAD1D18091D2 -:10092000E10084FF29C08091E20084FF25C084E0BB -:1009300089BD89B5826089BD09B400FEFDCF809173 -:10094000D8008F7D8093D8008091E1008F7E8093C6 -:10095000E1008091E2008F7E8093E2008091E200CE -:1009600081608093E20080912502882311F481E068 -:1009700001C084E08EBBA4D18091E10083FF27C039 -:100980008091E20083FF23C08091E100877F809304 -:10099000E10082E08EBB109225028091E1008E7F03 -:1009A0008093E1008091E2008E7F8093E20080914D -:1009B000E20080618093E200AADD80E060E042E036 -:1009C00093DD8091F00088608093F00079D1809170 -:1009D000E10082FF0AC08091E20082FF06C08091A0 -:1009E000E1008B7F8093E1006BD1FF91EF91BF918C -:1009F000AF919F918F917F916F915F914F913F91B7 -:100A00002F910F900FBE0F901F9018951F93DF939B -:100A1000CF93CDB7DEB7AC970FB6F894DEBF0FBE5D -:100A2000CDBFE7E2F2E08091F100819322E0EF3266 -:100A3000F207C9F78091270230912802353009F476 -:100A400087C0363040F43130C9F1313070F0333086 -:100A500009F01DC133C0383009F4EFC0393009F452 -:100A6000FEC0363009F013C192C0803821F08238C0 -:100A700009F00DC108C090912302809124028823BF -:100A800099F0926011C080912B0287708093E900E9 -:100A90008091EB0090E025E0969587952A95E1F707 -:100AA000982F91701092E9008091E800877F8093E1 -:100AB000E8009093F1001092F100CAC0882319F069 -:100AC000823009F0E4C090E08F719070009721F0BF -:100AD000029709F0DDC00CC080912902813009F035 -:100AE000D7C010922402333069F5809324022AC0C3 -:100AF00080912902882331F520912B02277009F477 -:100B0000C7C02093E9008091EB0080FFC1C0333063 -:100B100021F48091EB00806213C08091EB00806132 -:100B20008093EB0081E090E002C0880F991F2A9526 -:100B3000E2F78093EA001092EA008091EB0088606F -:100B40008093EB001092E9008091E800877F83C0DA -:100B5000882309F09CC0109129028091E800877FCA -:100B60008093E800E8DC04C08EB3882309F490C0C9 -:100B70008091E80080FFF8CF812F8F7711F492E009 -:100B800001C093E09EBB80688093E30081C08058E1 -:100B9000823008F07CC08091290290912A0223E0E3 -:100BA0008C3D920799F55FB7F894DE0115964EE0FB -:100BB00020E030E061E2E42FF0E0609357008491A0 -:100BC00020FF03C082958F704F5F982F9F70892FF1 -:100BD000805D8A3308F0895F8C9311961C9211977F -:100BE0002F5F3F4F12962431310529F75FBF8AE20C -:100BF0008B8383E08C838091E800877F8093E8007B -:100C0000CE0103966AE270E0E4DC11C060912B0231 -:100C1000AE014F5F5F4F2CDCBC010097C9F18091A2 -:100C2000E800877F8093E80089819A812BDD80919D -:100C3000E8008B778093E8002BC0803841F58091E5 -:100C4000E800877F8093E800809125028093F1007F -:100C50008091E8008E778093E8006DDC19C08823CE -:100C6000B1F490912902923098F48091E800877F46 -:100C70008093E800909325025EDC80912502882312 -:100C800011F483E001C084E08EBB2DDB01C028DBC2 -:100C90008091E80083FF0AC08091EB00806280931E -:100CA000EB008091E800877F8093E800AC960FB658 -:100CB000F894DEBF0FBECDBFCF91DF911F91089595 -:100CC00008951F938EB3882361F01091E90010926C -:100CD000E9008091E80083FF01C098DE177010934F -:100CE000E9001F9108950895FC018EB3843021F529 -:100CF00087859089A189B2890097A105B105E1F0A6 -:100D000085818093E9008091E80082FF15C0809181 -:100D1000F200882319F42FEF3FEF04C08091F10017 -:100D2000282F30E08091F200882341F48091E80080 -:100D30008B778093E80002C02FEF3FEFC901089541 -:100D4000FC018EB3843011F587859089A189B28921 -:100D50000097A105B105D1F081818093E9008091D0 -:100D6000F2008823A9F09091E8008091E8008E7746 -:100D70008093E80095FD0CC0FDDB982F882349F493 -:100D80008091E8008E778093E80003C092E001C074 -:100D900090E0892F0895FC018EB3843051F487854B -:100DA0009089A189B2890097A105B10511F0CF0101 -:100DB000C7CF08951F93FC01162F8EB38430D9F44A -:100DC00087859089A189B2890097A105B10599F01D -:100DD00081818093E9008091E80085FD08C08091C1 -:100DE000E8008E778093E800C5DB882329F4109310 -:100DF000F10080E001C082E01F9108950F931F93DE -:100E0000CF93DF93EC010D96FC0189E0DF011D9289 -:100E10008A95E9F72A813B8109818C81882311F425 -:100E200010E001C014E0C90151DB182B1260802FC3 -:100E300061E8412F59DB882329F12E813F810D8103 -:100E40008885882311F410E001C014E0C9013EDB5D -:100E5000182B1260802F60E8412F46DB882391F029 -:100E60002A853B8509858C85882311F410E001C013 -:100E700014E0C9012BDB182B1260802F61EC412F8D -:100E800033DB01C080E0DF91CF911F910F91089576 -:100E9000CF93DF93EC018091E80083FF60C08881ED -:100EA00090E020912B0230912C022817390709F08D -:100EB00056C080912802813261F0823220F4803263 -:100EC00009F04DC019C0823269F1833209F047C080 -:100ED00038C080912702813A09F041C08091E80032 -:100EE000877F8093E800CE010F9667E070E071DBAA -:100EF0008091E8008B7713C080912702813279F5C9 -:100F00008091E800877F8093E800CE010F9667E02C -:100F100070E013DCCE013ED98091E8008E7780939B -:100F2000E8001DC0809127028132C9F48091E80059 -:100F3000877F8093E800809129028D87CE01C8D9F0 -:100F40000DC080912702813251F48091E800877FA3 -:100F50008093E800CE0160912902C5DEECDADF91D2 -:100F6000CF910895A1E21A2EAA1BBB1BFD010DC053 -:100F7000AA1FBB1FEE1FFF1FA217B307E407F50749 -:100F800020F0A21BB30BE40BF50B661F771F881F25 -:100F9000991F1A9469F760957095809590959B01BB -:0C0FA000AC01BD01CF010895F894FFCF13 -:100FAC0000034000000440000002080000000000A4 -:060FBC000000000000002F -:00000001FF diff --git a/plugins/KeyboardioHID/Firmwares/OriginalFirmwares/Arduino-usbserial-atmega16u2-MegaADK-Rev3.hex b/plugins/KeyboardioHID/Firmwares/OriginalFirmwares/Arduino-usbserial-atmega16u2-MegaADK-Rev3.hex deleted file mode 100644 index 1ca40e2e57..0000000000 --- a/plugins/KeyboardioHID/Firmwares/OriginalFirmwares/Arduino-usbserial-atmega16u2-MegaADK-Rev3.hex +++ /dev/null @@ -1,254 +0,0 @@ -:1000000090C00000A9C00000A7C00000A5C000006B -:10001000A3C00000A1C000009FC000009DC0000060 -:100020009BC0000099C0000097C0000048C40000B9 -:100030000CC4000091C000008FC000008DC0000003 -:100040008BC0000089C0000087C0000085C0000090 -:1000500083C0000081C000007FC0000002C100001A -:100060007BC0000079C0000077C0000075C00000B0 -:1000700073C0000071C000006FC000006DC00000C0 -:100080006BC0000069C0000067C0000065C00000D0 -:1000900063C0000061C000001201100102000008EE -:1000A0004123440001000102DC0109023E0002017B -:1000B00000C0320904000001020201000524000111 -:1000C0001004240206052406000107058203080027 -:1000D000FF09040100020A000000070504024000B5 -:1000E00001070583024000010403090432034100B3 -:1000F00072006400750069006E006F002000280027 -:100100007700770077002E006100720064007500B0 -:1001100069006E006F002E0063006300290000007C -:10012000000011241FBECFEFD2E0DEBFCDBF11E033 -:10013000A0E0B1E0ECEAFFE002C005900D92A6312C -:10014000B107D9F712E0A6E1B1E001C01D92AF32CC -:10015000B107E1F7F1D028C753CF9C01DC01AE57BE -:10016000BF4FED91FC91119741911196FC93EE9345 -:1001700080589F4FE817F90711F42D933C939FB7D0 -:10018000F894F901EC57FF4F8081815080839FBF25 -:10019000842F0895DF92EF92FF920F931F93FC013B -:1001A0008489813019F0823021F405C040E3D42ED7 -:1001B00004C0DD2402C030E2D32E8389823011F4E2 -:1001C00088E0D82A8589873031F0883031F0863050 -:1001D00031F482E003C084E001C086E0D82A1092A6 -:1001E000C9001092C8001092CA00E784F088018903 -:1001F000128980E0E81681EEF80680E0080780E0CA -:10020000180719F420E130E00FC0C801B701969536 -:1002100087957795679560587B47814E9F4FA801DA -:100220009701A0D6215030403093CD002093CC00D0 -:10023000D092CA0080E0E81681EEF80680E0080758 -:1002400080E0180711F082E001C080E08093C800D0 -:1002500088E98093C9001F910F91FF90EF90DF9084 -:1002600008951F920F920FB60F9211242F938F9320 -:100270009F93EF93FF939091CE008EB38430F1F46F -:10028000E0919901F0919A019083E0919901F091A8 -:100290009A01CF01019690939A018093990189590F -:1002A000914021F489E191E0928381839FB7F89492 -:1002B00080919D018F5F80939D019FBFFF91EF9182 -:1002C0009F918F912F910F900FBE0F901F901895B7 -:1002D000FC01858580FF02C05F9808955F9A0895AC -:1002E00080E091E0D5C580E091E088C584B7877F44 -:1002F00084BF28E10FB6F89420936000109260004C -:100300000FBE87E690E09093CD008093CC0086E00E -:100310008093CA001092C8002093C900539A5A9A39 -:100320008AB180638AB98BB180638BB983D284E050 -:1003300085BD5F9A579A08950F931F93CF93DF93CC -:10034000D5DF2FB7F8948EE991E090931F02809348 -:100350001E0290932102809320022FBF2FB7F894A2 -:1003600089E191E090939A018093990190939C0187 -:1003700080939B012FBF7894CEE9D1E003E08FB743 -:10038000F894909122028FBF903809F180E091E0BB -:10039000ABD497FD1CC0E0911E02F0911F02808338 -:1003A000E0911E02F0911F02CF01019690931F026F -:1003B00080931E028E51924011F4D283C1839FB765 -:1003C000F894809122028F5F809322029FBF8FB7A3 -:1003D000F89410919D018FBFA89902C0113678F151 -:1003E000A89A80919D01882361F05D980093160181 -:1003F00008C089E191E0B1DE682F80E091E0DAD4B5 -:1004000011501123B1F780911601882351F080918A -:10041000160181508093160180911601882309F4FA -:100420005D9A80911701882351F0809117018150C6 -:100430008093170180911701882309F45C9A8FB784 -:10044000F894909122028FBF992369F08EE991E090 -:1004500084DE982F8091C80085FFFCCF9093CE005A -:100460005C980093170180E091E095D42AD487CF5F -:10047000DA01923049F0933061F09130F9F4E8E913 -:10048000F0E022E130E01EC0EAEAF0E02EE330E0E6 -:1004900019C0813049F0813018F0823079F408C0F9 -:1004A000E8EEF0E0849107C0ECEEF0E0849103C048 -:1004B000E0E2F1E08491282F30E004C0E0E0F0E0D9 -:1004C00020E030E0ED93FC93C901089528E030E08E -:1004D00040E003C04F5F220F331F28173907D0F3C6 -:1004E000842F8295807F08958093E9008091EB00AE -:1004F00081608093EB001092ED006093EC004093DC -:10050000ED008091EE00881F8827881F08951092C3 -:10051000F40090E09093E9001092F0001092E8004F -:100520001092ED008091EB008E7F8093EB009F5F37 -:10053000953081F708958091270288238CF403C0B9 -:100540008EB38823B1F08091E80082FFF9CF8091CB -:10055000E8008B778093E80008958EB3882349F0F4 -:100560008091E80080FFF9CF8091E8008E7780933A -:10057000E800089594E68091EC0080FF05C080912A -:10058000E80080FF05C023C08091E80082FD1FC005 -:100590008EB3882311F482E008958EB3853011F470 -:1005A00083E008958091EB0085FF02C081E008950B -:1005B0008091E10082FFDFCF8091E1008B7F80930B -:1005C000E100992311F484E008959150D4CF80E0A4 -:1005D00008959C0140912D0250912E024617570715 -:1005E00018F4F90120E038C06115710511F0AB0174 -:1005F000F8CF8091E8008E778093E80040E050E0EB -:10060000F0CF8091E80083FF02C081E008958091DF -:10061000E80082FD2DC08EB3882381F18EB3853032 -:1006200079F18091E80080FF17C09091F20006C038 -:1006300081918093F100415050409F5F41155105D9 -:1006400011F09830A8F320E0983009F421E080916F -:10065000E8008E778093E8004115510591F622233A -:1006600081F606C08EB3882349F08EB3853041F001 -:100670008091E80082FFF6CF80E0089582E008953F -:1006800083E008959C0140912D0250912E0246175F -:10069000570710F490E03BC06115710511F0AB01F4 -:1006A000F9CF8091E8008E778093E80040E050E039 -:1006B000F1CF8091E80083FF02C081E0089580912E -:1006C000E80082FD30C08EB3882399F18EB3853067 -:1006D00091F18091E80080FF1AC08091F20009C07A -:1006E000F9012F5F3F4FE491E093F10041505040FA -:1006F0008F5F4115510511F0883090F390E08830FC -:1007000009F491E08091E8008E778093E80041152C -:10071000510579F6992369F606C08EB3882349F00E -:100720008EB3853041F08091E80082FFF6CF80E003 -:10073000089582E0089583E008959C016115710594 -:1007400029F48091E8008B778093E800F90120C0BC -:100750008091E80083FF02C081E008958EB3882372 -:1007600039F18EB3853031F18091E80082FFF0CF0E -:1007700006C08091F10081936150704021F080911A -:10078000F2008823B1F78091E8008B778093E8002E -:1007900061157105E9F606C08EB3882349F08EB362 -:1007A000853041F08091E80080FFF6CF80E0089529 -:1007B00082E0089583E0089542D044D01EBA10929A -:1007C0002502109224021092230284E089BD89B58B -:1007D000826089BD09B400FEFDCF8091D800982FBA -:1007E0009F779093D80080688093D80080916300B1 -:1007F0008E7F809363008091D8008F7D8093D80096 -:100800008091E0008E7F8093E0008091E1008E7FF8 -:100810008093E1008091E20081608093E20080910A -:10082000E100877F8093E1008091E20088608093FF -:10083000E2000895C1DF81E08093260208951092BE -:10084000E20008951092E10008951F920F920FB6F2 -:100850000F9211241F932F933F934F935F936F93A6 -:100860007F938F939F93AF93BF93EF93FF93E9EEA3 -:10087000F0E0108117701082E0EFF0E08081877F58 -:1008800080837894C3D0F894A9EEB0E01C92E0EF96 -:10089000F0E08081886080831C93FF91EF91BF918D -:1008A000AF919F918F917F916F915F914F913F9108 -:1008B0002F911F910F900FBE0F901F9018951F92B0 -:1008C0000F920FB60F9211242F933F934F935F9384 -:1008D0006F937F938F939F93AF93BF93EF93FF9308 -:1008E0008091E10080FF1BC08091E20080FF17C073 -:1008F0008091E1008E7F8093E1008091E2008E7F05 -:100900008093E2008091E20080618093E200809118 -:10091000D80080628093D80019BC1EBAD1D18091D2 -:10092000E10084FF29C08091E20084FF25C084E0BB -:1009300089BD89B5826089BD09B400FEFDCF809173 -:10094000D8008F7D8093D8008091E1008F7E8093C6 -:10095000E1008091E2008F7E8093E2008091E200CE -:1009600081608093E20080912502882311F481E068 -:1009700001C084E08EBBA4D18091E10083FF27C039 -:100980008091E20083FF23C08091E100877F809304 -:10099000E10082E08EBB109225028091E1008E7F03 -:1009A0008093E1008091E2008E7F8093E20080914D -:1009B000E20080618093E200AADD80E060E042E036 -:1009C00093DD8091F00088608093F00079D1809170 -:1009D000E10082FF0AC08091E20082FF06C08091A0 -:1009E000E1008B7F8093E1006BD1FF91EF91BF918C -:1009F000AF919F918F917F916F915F914F913F91B7 -:100A00002F910F900FBE0F901F9018951F93DF939B -:100A1000CF93CDB7DEB7AC970FB6F894DEBF0FBE5D -:100A2000CDBFE7E2F2E08091F100819322E0EF3266 -:100A3000F207C9F78091270230912802353009F476 -:100A400087C0363040F43130C9F1313070F0333086 -:100A500009F01DC133C0383009F4EFC0393009F452 -:100A6000FEC0363009F013C192C0803821F08238C0 -:100A700009F00DC108C090912302809124028823BF -:100A800099F0926011C080912B0287708093E900E9 -:100A90008091EB0090E025E0969587952A95E1F707 -:100AA000982F91701092E9008091E800877F8093E1 -:100AB000E8009093F1001092F100CAC0882319F069 -:100AC000823009F0E4C090E08F719070009721F0BF -:100AD000029709F0DDC00CC080912902813009F035 -:100AE000D7C010922402333069F5809324022AC0C3 -:100AF00080912902882331F520912B02277009F477 -:100B0000C7C02093E9008091EB0080FFC1C0333063 -:100B100021F48091EB00806213C08091EB00806132 -:100B20008093EB0081E090E002C0880F991F2A9526 -:100B3000E2F78093EA001092EA008091EB0088606F -:100B40008093EB001092E9008091E800877F83C0DA -:100B5000882309F09CC0109129028091E800877FCA -:100B60008093E800E8DC04C08EB3882309F490C0C9 -:100B70008091E80080FFF8CF812F8F7711F492E009 -:100B800001C093E09EBB80688093E30081C08058E1 -:100B9000823008F07CC08091290290912A0223E0E3 -:100BA0008C3D920799F55FB7F894DE0115964EE0FB -:100BB00020E030E061E2E42FF0E0609357008491A0 -:100BC00020FF03C082958F704F5F982F9F70892FF1 -:100BD000805D8A3308F0895F8C9311961C9211977F -:100BE0002F5F3F4F12962431310529F75FBF8AE20C -:100BF0008B8383E08C838091E800877F8093E8007B -:100C0000CE0103966AE270E0E4DC11C060912B0231 -:100C1000AE014F5F5F4F2CDCBC010097C9F18091A2 -:100C2000E800877F8093E80089819A812BDD80919D -:100C3000E8008B778093E8002BC0803841F58091E5 -:100C4000E800877F8093E800809125028093F1007F -:100C50008091E8008E778093E8006DDC19C08823CE -:100C6000B1F490912902923098F48091E800877F46 -:100C70008093E800909325025EDC80912502882312 -:100C800011F483E001C084E08EBB2DDB01C028DBC2 -:100C90008091E80083FF0AC08091EB00806280931E -:100CA000EB008091E800877F8093E800AC960FB658 -:100CB000F894DEBF0FBECDBFCF91DF911F91089595 -:100CC00008951F938EB3882361F01091E90010926C -:100CD000E9008091E80083FF01C098DE177010934F -:100CE000E9001F9108950895FC018EB3843021F529 -:100CF00087859089A189B2890097A105B105E1F0A6 -:100D000085818093E9008091E80082FF15C0809181 -:100D1000F200882319F42FEF3FEF04C08091F10017 -:100D2000282F30E08091F200882341F48091E80080 -:100D30008B778093E80002C02FEF3FEFC901089541 -:100D4000FC018EB3843011F587859089A189B28921 -:100D50000097A105B105D1F081818093E9008091D0 -:100D6000F2008823A9F09091E8008091E8008E7746 -:100D70008093E80095FD0CC0FDDB982F882349F493 -:100D80008091E8008E778093E80003C092E001C074 -:100D900090E0892F0895FC018EB3843051F487854B -:100DA0009089A189B2890097A105B10511F0CF0101 -:100DB000C7CF08951F93FC01162F8EB38430D9F44A -:100DC00087859089A189B2890097A105B10599F01D -:100DD00081818093E9008091E80085FD08C08091C1 -:100DE000E8008E778093E800C5DB882329F4109310 -:100DF000F10080E001C082E01F9108950F931F93DE -:100E0000CF93DF93EC010D96FC0189E0DF011D9289 -:100E10008A95E9F72A813B8109818C81882311F425 -:100E200010E001C014E0C90151DB182B1260802FC3 -:100E300061E8412F59DB882329F12E813F810D8103 -:100E40008885882311F410E001C014E0C9013EDB5D -:100E5000182B1260802F60E8412F46DB882391F029 -:100E60002A853B8509858C85882311F410E001C013 -:100E700014E0C9012BDB182B1260802F61EC412F8D -:100E800033DB01C080E0DF91CF911F910F91089576 -:100E9000CF93DF93EC018091E80083FF60C08881ED -:100EA00090E020912B0230912C022817390709F08D -:100EB00056C080912802813261F0823220F4803263 -:100EC00009F04DC019C0823269F1833209F047C080 -:100ED00038C080912702813A09F041C08091E80032 -:100EE000877F8093E800CE010F9667E070E071DBAA -:100EF0008091E8008B7713C080912702813279F5C9 -:100F00008091E800877F8093E800CE010F9667E02C -:100F100070E013DCCE013ED98091E8008E7780939B -:100F2000E8001DC0809127028132C9F48091E80059 -:100F3000877F8093E800809129028D87CE01C8D9F0 -:100F40000DC080912702813251F48091E800877FA3 -:100F50008093E800CE0160912902C5DEECDADF91D2 -:100F6000CF910895A1E21A2EAA1BBB1BFD010DC053 -:100F7000AA1FBB1FEE1FFF1FA217B307E407F50749 -:100F800020F0A21BB30BE40BF50B661F771F881F25 -:100F9000991F1A9469F760957095809590959B01BB -:0C0FA000AC01BD01CF010895F894FFCF13 -:100FAC0000034000000440000002080000000000A4 -:060FBC000000000000002F -:00000001FF diff --git a/plugins/KeyboardioHID/Firmwares/OriginalFirmwares/Arduino-usbserial-atmega16u2-Uno-Rev3.hex b/plugins/KeyboardioHID/Firmwares/OriginalFirmwares/Arduino-usbserial-atmega16u2-Uno-Rev3.hex deleted file mode 100644 index 711fabfb2d..0000000000 --- a/plugins/KeyboardioHID/Firmwares/OriginalFirmwares/Arduino-usbserial-atmega16u2-Uno-Rev3.hex +++ /dev/null @@ -1,254 +0,0 @@ -:1000000090C00000A9C00000A7C00000A5C000006B -:10001000A3C00000A1C000009FC000009DC0000060 -:100020009BC0000099C0000097C0000048C40000B9 -:100030000CC4000091C000008FC000008DC0000003 -:100040008BC0000089C0000087C0000085C0000090 -:1000500083C0000081C000007FC0000002C100001A -:100060007BC0000079C0000077C0000075C00000B0 -:1000700073C0000071C000006FC000006DC00000C0 -:100080006BC0000069C0000067C0000065C00000D0 -:1000900063C0000061C000001201100102000008EE -:1000A0004123430001000102DC0109023E0002017C -:1000B00000C0320904000001020201000524000111 -:1000C0001004240206052406000107058203080027 -:1000D000FF09040100020A000000070504024000B5 -:1000E00001070583024000010403090432034100B3 -:1000F00072006400750069006E006F002000280027 -:100100007700770077002E006100720064007500B0 -:1001100069006E006F002E0063006300290000007C -:10012000000011241FBECFEFD2E0DEBFCDBF11E033 -:10013000A0E0B1E0ECEAFFE002C005900D92A6312C -:10014000B107D9F712E0A6E1B1E001C01D92AF32CC -:10015000B107E1F7F1D028C753CF9C01DC01AE57BE -:10016000BF4FED91FC91119741911196FC93EE9345 -:1001700080589F4FE817F90711F42D933C939FB7D0 -:10018000F894F901EC57FF4F8081815080839FBF25 -:10019000842F0895DF92EF92FF920F931F93FC013B -:1001A0008489813019F0823021F405C040E3D42ED7 -:1001B00004C0DD2402C030E2D32E8389823011F4E2 -:1001C00088E0D82A8589873031F0883031F0863050 -:1001D00031F482E003C084E001C086E0D82A1092A6 -:1001E000C9001092C8001092CA00E784F088018903 -:1001F000128980E0E81681EEF80680E0080780E0CA -:10020000180719F420E130E00FC0C801B701969536 -:1002100087957795679560587B47814E9F4FA801DA -:100220009701A0D6215030403093CD002093CC00D0 -:10023000D092CA0080E0E81681EEF80680E0080758 -:1002400080E0180711F082E001C080E08093C800D0 -:1002500088E98093C9001F910F91FF90EF90DF9084 -:1002600008951F920F920FB60F9211242F938F9320 -:100270009F93EF93FF939091CE008EB38430F1F46F -:10028000E0919901F0919A019083E0919901F091A8 -:100290009A01CF01019690939A018093990189590F -:1002A000914021F489E191E0928381839FB7F89492 -:1002B00080919D018F5F80939D019FBFFF91EF9182 -:1002C0009F918F912F910F900FBE0F901F901895B7 -:1002D000FC01858580FF02C05F9808955F9A0895AC -:1002E00080E091E0D5C580E091E088C584B7877F44 -:1002F00084BF28E10FB6F89420936000109260004C -:100300000FBE87E690E09093CD008093CC0086E00E -:100310008093CA001092C8002093C900539A5A9A39 -:100320008AB180638AB98BB180638BB983D284E050 -:1003300085BD5F9A579A08950F931F93CF93DF93CC -:10034000D5DF2FB7F8948EE991E090931F02809348 -:100350001E0290932102809320022FBF2FB7F894A2 -:1003600089E191E090939A018093990190939C0187 -:1003700080939B012FBF7894CEE9D1E003E08FB743 -:10038000F894909122028FBF903809F180E091E0BB -:10039000ABD497FD1CC0E0911E02F0911F02808338 -:1003A000E0911E02F0911F02CF01019690931F026F -:1003B00080931E028E51924011F4D283C1839FB765 -:1003C000F894809122028F5F809322029FBF8FB7A3 -:1003D000F89410919D018FBFA89902C0113678F151 -:1003E000A89A80919D01882361F05D980093160181 -:1003F00008C089E191E0B1DE682F80E091E0DAD4B5 -:1004000011501123B1F780911601882351F080918A -:10041000160181508093160180911601882309F4FA -:100420005D9A80911701882351F0809117018150C6 -:100430008093170180911701882309F45C9A8FB784 -:10044000F894909122028FBF992369F08EE991E090 -:1004500084DE982F8091C80085FFFCCF9093CE005A -:100460005C980093170180E091E095D42AD487CF5F -:10047000DA01923049F0933061F09130F9F4E8E913 -:10048000F0E022E130E01EC0EAEAF0E02EE330E0E6 -:1004900019C0813049F0813018F0823079F408C0F9 -:1004A000E8EEF0E0849107C0ECEEF0E0849103C048 -:1004B000E0E2F1E08491282F30E004C0E0E0F0E0D9 -:1004C00020E030E0ED93FC93C901089528E030E08E -:1004D00040E003C04F5F220F331F28173907D0F3C6 -:1004E000842F8295807F08958093E9008091EB00AE -:1004F00081608093EB001092ED006093EC004093DC -:10050000ED008091EE00881F8827881F08951092C3 -:10051000F40090E09093E9001092F0001092E8004F -:100520001092ED008091EB008E7F8093EB009F5F37 -:10053000953081F708958091270288238CF403C0B9 -:100540008EB38823B1F08091E80082FFF9CF8091CB -:10055000E8008B778093E80008958EB3882349F0F4 -:100560008091E80080FFF9CF8091E8008E7780933A -:10057000E800089594E68091EC0080FF05C080912A -:10058000E80080FF05C023C08091E80082FD1FC005 -:100590008EB3882311F482E008958EB3853011F470 -:1005A00083E008958091EB0085FF02C081E008950B -:1005B0008091E10082FFDFCF8091E1008B7F80930B -:1005C000E100992311F484E008959150D4CF80E0A4 -:1005D00008959C0140912D0250912E024617570715 -:1005E00018F4F90120E038C06115710511F0AB0174 -:1005F000F8CF8091E8008E778093E80040E050E0EB -:10060000F0CF8091E80083FF02C081E008958091DF -:10061000E80082FD2DC08EB3882381F18EB3853032 -:1006200079F18091E80080FF17C09091F20006C038 -:1006300081918093F100415050409F5F41155105D9 -:1006400011F09830A8F320E0983009F421E080916F -:10065000E8008E778093E8004115510591F622233A -:1006600081F606C08EB3882349F08EB3853041F001 -:100670008091E80082FFF6CF80E0089582E008953F -:1006800083E008959C0140912D0250912E0246175F -:10069000570710F490E03BC06115710511F0AB01F4 -:1006A000F9CF8091E8008E778093E80040E050E039 -:1006B000F1CF8091E80083FF02C081E0089580912E -:1006C000E80082FD30C08EB3882399F18EB3853067 -:1006D00091F18091E80080FF1AC08091F20009C07A -:1006E000F9012F5F3F4FE491E093F10041505040FA -:1006F0008F5F4115510511F0883090F390E08830FC -:1007000009F491E08091E8008E778093E80041152C -:10071000510579F6992369F606C08EB3882349F00E -:100720008EB3853041F08091E80082FFF6CF80E003 -:10073000089582E0089583E008959C016115710594 -:1007400029F48091E8008B778093E800F90120C0BC -:100750008091E80083FF02C081E008958EB3882372 -:1007600039F18EB3853031F18091E80082FFF0CF0E -:1007700006C08091F10081936150704021F080911A -:10078000F2008823B1F78091E8008B778093E8002E -:1007900061157105E9F606C08EB3882349F08EB362 -:1007A000853041F08091E80080FFF6CF80E0089529 -:1007B00082E0089583E0089542D044D01EBA10929A -:1007C0002502109224021092230284E089BD89B58B -:1007D000826089BD09B400FEFDCF8091D800982FBA -:1007E0009F779093D80080688093D80080916300B1 -:1007F0008E7F809363008091D8008F7D8093D80096 -:100800008091E0008E7F8093E0008091E1008E7FF8 -:100810008093E1008091E20081608093E20080910A -:10082000E100877F8093E1008091E20088608093FF -:10083000E2000895C1DF81E08093260208951092BE -:10084000E20008951092E10008951F920F920FB6F2 -:100850000F9211241F932F933F934F935F936F93A6 -:100860007F938F939F93AF93BF93EF93FF93E9EEA3 -:10087000F0E0108117701082E0EFF0E08081877F58 -:1008800080837894C3D0F894A9EEB0E01C92E0EF96 -:10089000F0E08081886080831C93FF91EF91BF918D -:1008A000AF919F918F917F916F915F914F913F9108 -:1008B0002F911F910F900FBE0F901F9018951F92B0 -:1008C0000F920FB60F9211242F933F934F935F9384 -:1008D0006F937F938F939F93AF93BF93EF93FF9308 -:1008E0008091E10080FF1BC08091E20080FF17C073 -:1008F0008091E1008E7F8093E1008091E2008E7F05 -:100900008093E2008091E20080618093E200809118 -:10091000D80080628093D80019BC1EBAD1D18091D2 -:10092000E10084FF29C08091E20084FF25C084E0BB -:1009300089BD89B5826089BD09B400FEFDCF809173 -:10094000D8008F7D8093D8008091E1008F7E8093C6 -:10095000E1008091E2008F7E8093E2008091E200CE -:1009600081608093E20080912502882311F481E068 -:1009700001C084E08EBBA4D18091E10083FF27C039 -:100980008091E20083FF23C08091E100877F809304 -:10099000E10082E08EBB109225028091E1008E7F03 -:1009A0008093E1008091E2008E7F8093E20080914D -:1009B000E20080618093E200AADD80E060E042E036 -:1009C00093DD8091F00088608093F00079D1809170 -:1009D000E10082FF0AC08091E20082FF06C08091A0 -:1009E000E1008B7F8093E1006BD1FF91EF91BF918C -:1009F000AF919F918F917F916F915F914F913F91B7 -:100A00002F910F900FBE0F901F9018951F93DF939B -:100A1000CF93CDB7DEB7AC970FB6F894DEBF0FBE5D -:100A2000CDBFE7E2F2E08091F100819322E0EF3266 -:100A3000F207C9F78091270230912802353009F476 -:100A400087C0363040F43130C9F1313070F0333086 -:100A500009F01DC133C0383009F4EFC0393009F452 -:100A6000FEC0363009F013C192C0803821F08238C0 -:100A700009F00DC108C090912302809124028823BF -:100A800099F0926011C080912B0287708093E900E9 -:100A90008091EB0090E025E0969587952A95E1F707 -:100AA000982F91701092E9008091E800877F8093E1 -:100AB000E8009093F1001092F100CAC0882319F069 -:100AC000823009F0E4C090E08F719070009721F0BF -:100AD000029709F0DDC00CC080912902813009F035 -:100AE000D7C010922402333069F5809324022AC0C3 -:100AF00080912902882331F520912B02277009F477 -:100B0000C7C02093E9008091EB0080FFC1C0333063 -:100B100021F48091EB00806213C08091EB00806132 -:100B20008093EB0081E090E002C0880F991F2A9526 -:100B3000E2F78093EA001092EA008091EB0088606F -:100B40008093EB001092E9008091E800877F83C0DA -:100B5000882309F09CC0109129028091E800877FCA -:100B60008093E800E8DC04C08EB3882309F490C0C9 -:100B70008091E80080FFF8CF812F8F7711F492E009 -:100B800001C093E09EBB80688093E30081C08058E1 -:100B9000823008F07CC08091290290912A0223E0E3 -:100BA0008C3D920799F55FB7F894DE0115964EE0FB -:100BB00020E030E061E2E42FF0E0609357008491A0 -:100BC00020FF03C082958F704F5F982F9F70892FF1 -:100BD000805D8A3308F0895F8C9311961C9211977F -:100BE0002F5F3F4F12962431310529F75FBF8AE20C -:100BF0008B8383E08C838091E800877F8093E8007B -:100C0000CE0103966AE270E0E4DC11C060912B0231 -:100C1000AE014F5F5F4F2CDCBC010097C9F18091A2 -:100C2000E800877F8093E80089819A812BDD80919D -:100C3000E8008B778093E8002BC0803841F58091E5 -:100C4000E800877F8093E800809125028093F1007F -:100C50008091E8008E778093E8006DDC19C08823CE -:100C6000B1F490912902923098F48091E800877F46 -:100C70008093E800909325025EDC80912502882312 -:100C800011F483E001C084E08EBB2DDB01C028DBC2 -:100C90008091E80083FF0AC08091EB00806280931E -:100CA000EB008091E800877F8093E800AC960FB658 -:100CB000F894DEBF0FBECDBFCF91DF911F91089595 -:100CC00008951F938EB3882361F01091E90010926C -:100CD000E9008091E80083FF01C098DE177010934F -:100CE000E9001F9108950895FC018EB3843021F529 -:100CF00087859089A189B2890097A105B105E1F0A6 -:100D000085818093E9008091E80082FF15C0809181 -:100D1000F200882319F42FEF3FEF04C08091F10017 -:100D2000282F30E08091F200882341F48091E80080 -:100D30008B778093E80002C02FEF3FEFC901089541 -:100D4000FC018EB3843011F587859089A189B28921 -:100D50000097A105B105D1F081818093E9008091D0 -:100D6000F2008823A9F09091E8008091E8008E7746 -:100D70008093E80095FD0CC0FDDB982F882349F493 -:100D80008091E8008E778093E80003C092E001C074 -:100D900090E0892F0895FC018EB3843051F487854B -:100DA0009089A189B2890097A105B10511F0CF0101 -:100DB000C7CF08951F93FC01162F8EB38430D9F44A -:100DC00087859089A189B2890097A105B10599F01D -:100DD00081818093E9008091E80085FD08C08091C1 -:100DE000E8008E778093E800C5DB882329F4109310 -:100DF000F10080E001C082E01F9108950F931F93DE -:100E0000CF93DF93EC010D96FC0189E0DF011D9289 -:100E10008A95E9F72A813B8109818C81882311F425 -:100E200010E001C014E0C90151DB182B1260802FC3 -:100E300061E8412F59DB882329F12E813F810D8103 -:100E40008885882311F410E001C014E0C9013EDB5D -:100E5000182B1260802F60E8412F46DB882391F029 -:100E60002A853B8509858C85882311F410E001C013 -:100E700014E0C9012BDB182B1260802F61EC412F8D -:100E800033DB01C080E0DF91CF911F910F91089576 -:100E9000CF93DF93EC018091E80083FF60C08881ED -:100EA00090E020912B0230912C022817390709F08D -:100EB00056C080912802813261F0823220F4803263 -:100EC00009F04DC019C0823269F1833209F047C080 -:100ED00038C080912702813A09F041C08091E80032 -:100EE000877F8093E800CE010F9667E070E071DBAA -:100EF0008091E8008B7713C080912702813279F5C9 -:100F00008091E800877F8093E800CE010F9667E02C -:100F100070E013DCCE013ED98091E8008E7780939B -:100F2000E8001DC0809127028132C9F48091E80059 -:100F3000877F8093E800809129028D87CE01C8D9F0 -:100F40000DC080912702813251F48091E800877FA3 -:100F50008093E800CE0160912902C5DEECDADF91D2 -:100F6000CF910895A1E21A2EAA1BBB1BFD010DC053 -:100F7000AA1FBB1FEE1FFF1FA217B307E407F50749 -:100F800020F0A21BB30BE40BF50B661F771F881F25 -:100F9000991F1A9469F760957095809590959B01BB -:0C0FA000AC01BD01CF010895F894FFCF13 -:100FAC0000034000000440000002080000000000A4 -:060FBC000000000000002F -:00000001FF diff --git a/plugins/KeyboardioHID/Firmwares/Readme.md b/plugins/KeyboardioHID/Firmwares/Readme.md index bfe6de1e09..2042bd5d1d 100644 --- a/plugins/KeyboardioHID/Firmwares/Readme.md +++ b/plugins/KeyboardioHID/Firmwares/Readme.md @@ -2,4 +2,6 @@ Firmwares ========= [**See installing instructions on the Hoodloader repository**](https://github.com/NicoHood/Hoodloader) -There are also other/older Versions of the Hoodloader and the Lite Version for 8u2. \ No newline at end of file +You can also get the latest Hoodloader version or the dev version from this repository (select dev branch). + +There are also other/older versions of the Hoodloader and the Lite Version for 8u2. The original firmware can also be found there. \ No newline at end of file diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 90770c3dd9..0abf45e7eb 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -34,8 +34,7 @@ I also corrected some bugs in the original sources. * Mouse (5 buttons, move, wheel) * Media Keys (4 keys for music player, webbrowser and more) * System Key (for PC standby/shutdown) -* 2 Gamepads (32 buttons, 6 16bit axis, 2 D-Pads) -* 2 Joysticks (2 buttons, 2 10bit axis) +* 4 Gamepads (32 buttons, 4 16bit axis, 2 8bit axis, 2 D-Pads) **Projects can be found here:** * [Gamecube to PC adapter](https://github.com/NicoHood/Nintendo) @@ -151,8 +150,6 @@ Known Bugs ========== See [Hoodloader repository](https://github.com/NicoHood/Hoodloader) for Hoodloader related Bugs/Issues. -Opening the examples with doubleclick doesnt work, starting from IDE does. - System Wakeup is currently not working on all versions! System Shutdown is only working on Windows systems. @@ -165,6 +162,8 @@ Known Issues **Do not name your sketch HID.ino, this wont work!** +Opening the examples with doubleclick doesnt work, starting from IDE does. + **Do not use HID in interrupts because it uses Serial (Hoodloader only). Your Arduino can crash!** **If you get a checksum error after uploading please message me and send me the whole project.** @@ -195,6 +194,7 @@ Version History * **Huge improvements**, see [Hoodloader repository](https://github.com/NicoHood/Hoodloader) * Reworked the whole library, easy installation now * HID fixes for Media Keys/Ubuntu + * Removed Joystick, added 4 Gamepads 1.7.3 Beta Release (10.08.2014) * Changes in the Hoodloader: From d18b9f840da93f5347b2379e06502c32081aa18b Mon Sep 17 00:00:00 2001 From: NicoHood Date: Mon, 25 Aug 2014 19:06:05 +0200 Subject: [PATCH 044/602] Gamepad fix --- plugins/KeyboardioHID/Gamepad.h | 40 +++-- plugins/KeyboardioHID/HID.cpp | 3 + plugins/KeyboardioHID/HID.h | 3 + plugins/KeyboardioHID/HID_Reports.h | 147 +++++++++--------- plugins/KeyboardioHID/Keyboard.h | 10 +- .../AdvancedRawHID/AdvancedRawHID.ino | 95 ++++------- .../examples/Gamepad/Gamepad.ino | 37 +++-- plugins/KeyboardioHID/keywords.txt | 13 +- 8 files changed, 177 insertions(+), 171 deletions(-) diff --git a/plugins/KeyboardioHID/Gamepad.h b/plugins/KeyboardioHID/Gamepad.h index edb1bdd814..6d51014974 100644 --- a/plugins/KeyboardioHID/Gamepad.h +++ b/plugins/KeyboardioHID/Gamepad.h @@ -37,6 +37,16 @@ void HID_SendReport(uint8_t id, const void* data, int len); // Gamepad //================================================================================ +#define GAMEPAD_DPAD_CENTERED 0 +#define GAMEPAD_DPAD_UP 1 +#define GAMEPAD_DPAD_UP_RIGHT 2 +#define GAMEPAD_DPAD_RIGHT 3 +#define GAMEPAD_DPAD_DOWN_RIGHT 4 +#define GAMEPAD_DPAD_DOWN 5 +#define GAMEPAD_DPAD_DOWN_LEFT 6 +#define GAMEPAD_DPAD_LEFT 7 +#define GAMEPAD_DPAD_UP_LEFT 8 + class Gamepad{ public: inline Gamepad(uint8_t num){ @@ -45,14 +55,14 @@ class Gamepad{ _reportID = HID_REPORTID_Gamepad1Report; break; case 2: - _reportID = HID_REPORTID_Gamepad1Report; - break; - case 3: - _reportID = HID_REPORTID_Gamepad1Report; - break; - case 4: - _reportID = HID_REPORTID_Gamepad1Report; + _reportID = HID_REPORTID_Gamepad2Report; break; + //case 3: + // _reportID = HID_REPORTID_Gamepad3Report; + // break; + //case 4: + // _reportID = HID_REPORTID_Gamepad4Report; + // break; default: _reportID = HID_REPORTID_NotAReport; break; @@ -71,14 +81,14 @@ class Gamepad{ inline void releaseAll(void){ _report.buttons = 0;} inline void buttons(uint32_t b){ _report.buttons = b; } - inline void xAxis(uint16_t a){ _report.xAxis = a; } - inline void yAxis(uint16_t a){ _report.yAxis = a; } - inline void zAxis(uint8_t a){ _report.zAxis = a; } - inline void rxAxis(uint16_t a){ _report.rxAxis = a; } - inline void ryAxis(uint16_t a){ _report.ryAxis = a; } - inline void rzAxis(uint8_t a){ _report.rzAxis = a; } - inline void dPad1(uint8_t d){ _report.dPad1 = d; } - inline void dPad2(uint8_t d){ _report.dPad2 = d; } + inline void xAxis(int16_t a){ _report.xAxis = a; } + inline void yAxis(int16_t a){ _report.yAxis = a; } + inline void zAxis(int8_t a){ _report.zAxis = a; } + inline void rxAxis(int16_t a){ _report.rxAxis = a; } + inline void ryAxis(int16_t a){ _report.ryAxis = a; } + inline void rzAxis(int8_t a){ _report.rzAxis = a; } + inline void dPad1(int8_t d){ _report.dPad1 = d; } + inline void dPad2(int8_t d){ _report.dPad2 = d; } private: HID_GamepadReport_Data_t _report; uint8_t _reportID; diff --git a/plugins/KeyboardioHID/HID.cpp b/plugins/KeyboardioHID/HID.cpp index 77608df4db..a1dc953967 100644 --- a/plugins/KeyboardioHID/HID.cpp +++ b/plugins/KeyboardioHID/HID.cpp @@ -73,6 +73,9 @@ void HID_SendReport(uint8_t id, const void* data, int len) // valid HID reports start at Address 2 NHPwriteChecksum(2 + i / 2, (data1 << 8) | data0); } +#ifdef HID_EXTRADELAY + delay(HID_EXTRADELAY); +#endif } // simple copy/modification of the NicoHoodProtocol writechecksum function diff --git a/plugins/KeyboardioHID/HID.h b/plugins/KeyboardioHID/HID.h index e08e0dc404..a8a14a4574 100644 --- a/plugins/KeyboardioHID/HID.h +++ b/plugins/KeyboardioHID/HID.h @@ -51,6 +51,9 @@ THE SOFTWARE. //#define HID_JOYSTICK1_ENABLE 51 //#define HID_JOYSTICK2_ENABLE 51 +// extra delay for raspberry. Only needed for Hoodloader and slow devices +//#define HID_EXTRADELAY 20 + //================================================================================ // NHP //================================================================================ diff --git a/plugins/KeyboardioHID/HID_Reports.h b/plugins/KeyboardioHID/HID_Reports.h index 34379b2db7..e0b195ded1 100644 --- a/plugins/KeyboardioHID/HID_Reports.h +++ b/plugins/KeyboardioHID/HID_Reports.h @@ -43,12 +43,12 @@ THE SOFTWARE. typedef union{ // mouse report: 5 buttons, position, wheel uint8_t whole8[4]; - uint16_t whole16[4 / 2]; - uint32_t whole32[4 / 4]; + uint16_t whole16[4/2]; + uint32_t whole32[4/4]; struct{ - uint8_t buttons : 5; - uint8_t reserved : 3; + uint8_t buttons:5; + uint8_t reserved:3; int8_t xAxis; int8_t yAxis; int8_t wheel; @@ -59,8 +59,8 @@ typedef union{ typedef union{ // Low level key report: up to 6 keys and shift, ctrl etc at once uint8_t whole8[8]; - uint16_t whole16[8 / 2]; - uint32_t whole32[8 / 4]; + uint16_t whole16[8/2]; + uint32_t whole32[8/4]; struct{ uint8_t modifiers; @@ -82,8 +82,8 @@ typedef union{ typedef union{ // every usable media key possible. Only one at the same time. uint8_t whole8[8]; - uint16_t whole16[8 / 2]; - uint32_t whole32[8 / 4]; + uint16_t whole16[8/2]; + uint32_t whole32[8/4]; struct{ uint16_t key1; @@ -104,57 +104,58 @@ typedef union{ typedef union { // 32 Buttons, 6 Axis, 2 D-Pads uint8_t whole8[15]; - uint16_t whole16[15 / 2]; - uint32_t whole32[15 / 4]; + uint16_t whole16[15/2]; + uint32_t whole32[15/4]; uint32_t buttons; struct{ - uint8_t button1 : 1; - uint8_t button2 : 1; - uint8_t button3 : 1; - uint8_t button4 : 1; - uint8_t button5 : 1; - uint8_t button6 : 1; - uint8_t button7 : 1; - uint8_t button8 : 1; - - uint8_t button9 : 1; - uint8_t button10 : 1; - uint8_t button11 : 1; - uint8_t button12 : 1; - uint8_t button13 : 1; - uint8_t button14 : 1; - uint8_t button15 : 1; - uint8_t button16 : 1; - - uint8_t button17 : 1; - uint8_t button18 : 1; - uint8_t button19 : 1; - uint8_t button20 : 1; - uint8_t button21 : 1; - uint8_t button22 : 1; - uint8_t button23 : 1; - uint8_t button24 : 1; - - uint8_t button25 : 1; - uint8_t button26 : 1; - uint8_t button27 : 1; - uint8_t button28 : 1; - uint8_t button29 : 1; - uint8_t button30 : 1; - uint8_t button31 : 1; - uint8_t button32 : 1; - - uint16_t xAxis; - uint16_t yAxis; - uint8_t zAxis; - - uint16_t rxAxis; - uint16_t ryAxis; - uint8_t rzAxis; - - uint8_t dPad1 : 4; - uint8_t dPad2 : 4; + uint8_t button1 :1; + uint8_t button2 :1; + uint8_t button3 :1; + uint8_t button4 :1; + uint8_t button5 :1; + uint8_t button6 :1; + uint8_t button7 :1; + uint8_t button8 :1; + + uint8_t button9 :1; + uint8_t button10 :1; + uint8_t button11 :1; + uint8_t button12 :1; + uint8_t button13 :1; + uint8_t button14 :1; + uint8_t button15 :1; + uint8_t button16 :1; + + uint8_t button17 :1; + uint8_t button18 :1; + uint8_t button19 :1; + uint8_t button20 :1; + uint8_t button21 :1; + uint8_t button22 :1; + uint8_t button23 :1; + uint8_t button24 :1; + + uint8_t button25 :1; + uint8_t button26 :1; + uint8_t button27 :1; + uint8_t button28 :1; + uint8_t button29 :1; + uint8_t button30 :1; + uint8_t button31 :1; + uint8_t button32 :1; + + int16_t xAxis; + int16_t yAxis; + + int16_t rxAxis; + int16_t ryAxis; + + int8_t zAxis; + int8_t rzAxis; + + uint8_t dPad1: 4; + uint8_t dPad2: 4; }; } HID_GamepadReport_Data_t; @@ -162,15 +163,15 @@ typedef union { typedef union{ // 2 Buttons, 2 Axis uint8_t whole8[3]; - uint16_t whole16[3 / 2]; - uint8_t buttons : 2; + uint16_t whole16[3/2]; + uint8_t buttons :2; struct{ - uint16_t button1 : 1; - uint16_t button2 : 1; - uint16_t xAxis : 10; - uint16_t yAxis : 10; - uint16_t reserved : 2; + uint16_t button1 :1; + uint16_t button2 :1; + uint16_t xAxis :10; + uint16_t yAxis :10; + uint16_t reserved :2; }; } HID_JoystickReport_Data_t; @@ -189,16 +190,16 @@ typedef union{ /** Enum for the HID report IDs used in the device. */ typedef enum{ - HID_REPORTID_NotAReport = 0x00, // first entry is always zero for multireports - HID_REPORTID_MouseReport = 0x01, /**< Report ID for the Mouse report within the device. */ - HID_REPORTID_KeyboardReport = 0x02, /**< Report ID for the Keyboard report within the device. */ - HID_REPORTID_RawKeyboardReport = 0x03, /**< Report ID for the Raw Keyboard report within the device. */ - HID_REPORTID_MediaReport = 0x04, /**< Report ID for the Media report within the device. */ - HID_REPORTID_SystemReport = 0x05, /**< Report ID for the Power report within the device. */ - HID_REPORTID_Gamepad1Report = 0x06, /**< Report ID for the Gamepad1 report within the device. */ - HID_REPORTID_Gamepad2Report = 0x07, /**< Report ID for the Gamepad2 report within the device. */ - HID_REPORTID_Joystick1Report = 0x08, /**< Report ID for the Joystick1 report within the device. */ - HID_REPORTID_Joystick2Report = 0x09, /**< Report ID for the Joystick2 report within the device. */ + HID_REPORTID_NotAReport = 0x00, // first entry is always zero for multireports + HID_REPORTID_MouseReport = 0x01, /**< Report ID for the Mouse report within the device. */ + HID_REPORTID_KeyboardReport = 0x02, /**< Report ID for the Keyboard report within the device. */ + HID_REPORTID_RawKeyboardReport = 0x03, /**< Report ID for the Raw Keyboard report within the device. */ + HID_REPORTID_MediaReport = 0x04, /**< Report ID for the Media report within the device. */ + HID_REPORTID_SystemReport = 0x05, /**< Report ID for the Power report within the device. */ + HID_REPORTID_Gamepad1Report = 0x06, /**< Report ID for the Gamepad1 report within the device. */ + HID_REPORTID_Gamepad2Report = 0x07, /**< Report ID for the Gamepad2 report within the device. */ + HID_REPORTID_Joystick1Report = 0x08, /**< Report ID for the Joystick1 report within the device. */ + HID_REPORTID_Joystick2Report = 0x09, /**< Report ID for the Joystick2 report within the device. */ HID_REPORTID_LastNotAReport, // determinate whats the maximum number of reports -1 } HID_Report_IDs; diff --git a/plugins/KeyboardioHID/Keyboard.h b/plugins/KeyboardioHID/Keyboard.h index 61ba18d9c4..22724dda31 100644 --- a/plugins/KeyboardioHID/Keyboard.h +++ b/plugins/KeyboardioHID/Keyboard.h @@ -37,6 +37,11 @@ void HID_SendReport(uint8_t id, const void* data, int len); // Keyboard //================================================================================ +//Keyboard fixed/added missing Keys +#define KEY_PRINT 0xCE +#define KEY_SCROLL_LOCK 0xCF +#define KEY_PAUSE 0xD0 + #ifndef USBCON #define KEY_LEFT_CTRL 0x80 @@ -76,11 +81,6 @@ void HID_SendReport(uint8_t id, const void* data, int len); #define KEY_F11 0xCC #define KEY_F12 0xCD -//Keyboard fixed/added missing Keys -#define KEY_PRINT 0xCE -#define KEY_SCROLL_LOCK 0xCF -#define KEY_PAUSE 0xD0 - //Raw Keyboard definitions #define RAW_KEYBOARD_LEFT_CTRL B00000001 #define RAW_KEYBOARD_LEFT_SHIFT B00000010 diff --git a/plugins/KeyboardioHID/examples/AdvancedRawHID/AdvancedRawHID.ino b/plugins/KeyboardioHID/examples/AdvancedRawHID/AdvancedRawHID.ino index 7c62e7b403..7905f7dbb1 100644 --- a/plugins/KeyboardioHID/examples/AdvancedRawHID/AdvancedRawHID.ino +++ b/plugins/KeyboardioHID/examples/AdvancedRawHID/AdvancedRawHID.ino @@ -37,7 +37,7 @@ void loop() { // direct without library. Always send RAWHID_RX_SIZE bytes! uint8_t buff[RAWHID_RX_SIZE]; // unitialized, has random values - HID.sendReport(HID_REPORTID_RawKeyboardReport, buff, sizeof(buff)); + HID_SendReport(HID_REPORTID_RawKeyboardReport, buff, sizeof(buff)); // with library memset(&buff, 42, sizeof(buff)); @@ -47,7 +47,7 @@ void loop() { RawHID.write(0xCD); // huge buffer with library, will fill the rest with zeros - uint8_t megabuff[256]; + uint8_t megabuff[64]; for (int i = 0; i < sizeof(megabuff); i++) megabuff[i] = i; RawHID.write(megabuff, sizeof(megabuff)); @@ -68,82 +68,47 @@ void loop() { Expected output: // manual with unintialized buff -recv 63 bytes: -1B B7 0B 88 1F 99 1F 5A 95 A9 F7 80 95 90 95 BC -01 CD 01 08 95 A1 E2 1A 2E AA 1B BB 1B FD 01 0D -C0 AA 1F BB 1F EE 1F FF 1F A2 17 B3 07 E4 07 F5 -07 20 F0 A2 1B B3 0B E4 0B F5 0B 66 1F 77 1F +recv 15 bytes: +01 55 C1 FF 01 01 01 00 00 01 00 00 01 00 20 // filled buff -recv 63 bytes: -2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A -2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A -2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A +recv 15 bytes: 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A // single byte filled with zero -recv 63 bytes: -CD 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +recv 15 bytes: +CD 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // huge buffer filled with zero at the end -recv 63 bytes: -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 1E 1F -20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F -30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E - -recv 63 bytes: -3F 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E -4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E -5F 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E -6F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D - -recv 63 bytes: -7E 7F 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D -8E 8F 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D -9E 9F A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD -AE AF B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC - -recv 63 bytes: -BD BE BF C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC -CD CE CF D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC -DD DE DF E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC -ED EE EF F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB - -recv 63 bytes: -FC FD FE FF 00 00 00 00 00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +recv 15 bytes: +00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E + +recv 15 bytes: +0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D + +recv 15 bytes: +1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C + +recv 15 bytes: +2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B + +recv 15 bytes: +3C 3D 3E 3F 00 00 00 00 00 00 00 00 00 00 00 // print -recv 63 bytes: -48 65 6C 6C 6F 20 57 6F 72 6C 64 00 00 00 00 00 -00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +recv 15 bytes: +48 65 6C 6C 6F 20 57 6F 72 6C 64 00 00 00 00 //\r -recv 63 bytes: -0D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +recv 15 bytes: +0D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 //\n -recv 63 bytes: -0A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +recv 15 bytes: +0A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 //write -recv 63 bytes: -48 65 6C 6C 6F 20 57 6F 72 6C 64 0D 0A 00 00 00 -00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +recv 15 bytes: +48 65 6C 6C 6F 20 57 6F 72 6C 64 0D 0A 00 00 + */ \ No newline at end of file diff --git a/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino b/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino index a02cdf83b6..191b374c9f 100644 --- a/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino +++ b/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino @@ -11,6 +11,7 @@ Press a button and demonstrate Gamepad actions // create a new Gamepad instance (1-4) Gamepad Gamepad1(1); +//Gamepad Gamepad2(2); const int pinLed = 13; const int pinButton = 8; @@ -47,12 +48,13 @@ void loop() { // go through all dPad positions // values: 0-8 (0==centred) - static uint8_t dpad1 = 0; + static uint8_t dpad1 = GAMEPAD_DPAD_CENTERED; Gamepad1.dPad1(dpad1++); - if (dpad1 == 9) dpad1 = 0; - static int8_t dpad2 = 0; + if(dpad1>GAMEPAD_DPAD_UP_LEFT) dpad1 = GAMEPAD_DPAD_CENTERED; + static int8_t dpad2 = GAMEPAD_DPAD_CENTERED; Gamepad1.dPad2(dpad2--); - if (dpad2 == -1) dpad2 = 8; + if(dpad2 Date: Mon, 25 Aug 2014 19:45:38 +0200 Subject: [PATCH 045/602] Gamepad Descriptor Fix --- plugins/KeyboardioHID/HID.cpp | 37 +++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/plugins/KeyboardioHID/HID.cpp b/plugins/KeyboardioHID/HID.cpp index a1dc953967..e0e3d532d8 100644 --- a/plugins/KeyboardioHID/HID.cpp +++ b/plugins/KeyboardioHID/HID.cpp @@ -288,6 +288,7 @@ const u8 _hidReportDescriptor[] = { 0xc0, // END_COLLECTION #endif + #ifdef HID_GAMEPAD1_ENABLE // Gamepad1 0x05, 0x01, // USAGE_PAGE (Generic Desktop) @@ -303,19 +304,25 @@ const u8 _hidReportDescriptor[] = { 0x75, 0x01, // REPORT_SIZE (1) 0x95, 0x20, // REPORT_COUNT (32) 0x81, 0x02, // INPUT (Data,Var,Abs) - // 6 16bit Axis + // 4 16bit Axis 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0xa1, 0x00, // COLLECTION (Physical) 0x09, 0x30, // USAGE (X) 0x09, 0x31, // USAGE (Y) - 0x09, 0x32, // USAGE (Z) 0x09, 0x33, // USAGE (Rx) 0x09, 0x34, // USAGE (Ry) - 0x09, 0x35, // USAGE (Rz) - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x27, 0xff, 0xff, 0x00, 0x00, // LOGICAL_MAXIMUM (65535) + 0x16, 0x00, 0x80, // LOGICAL_MINIMUM (-32768) + 0x26, 0xFF, 0x7F, // LOGICAL_MAXIMUM (32767) 0x75, 0x10, // REPORT_SIZE (16) - 0x95, 0x06, // REPORT_COUNT (6) + 0x95, 0x04, // REPORT_COUNT (4) + 0x81, 0x02, // INPUT (Data,Var,Abs) + // 2 8bit Axis + 0x09, 0x32, // USAGE (Z) + 0x09, 0x35, // USAGE (Rz) + 0x15, 0x80, // LOGICAL_MINIMUM (-128) + 0x25, 0x7F, // LOGICAL_MAXIMUM (127) + 0x75, 0x08, // REPORT_SIZE (8) + 0x95, 0x02, // REPORT_COUNT (2) 0x81, 0x02, // INPUT (Data,Var,Abs) 0xc0, // END_COLLECTION // 2 Hat Switches @@ -356,19 +363,25 @@ const u8 _hidReportDescriptor[] = { 0x75, 0x01, // REPORT_SIZE (1) 0x95, 0x20, // REPORT_COUNT (32) 0x81, 0x02, // INPUT (Data,Var,Abs) - // 6 16bit Axis + // 4 16bit Axis 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0xa1, 0x00, // COLLECTION (Physical) 0x09, 0x30, // USAGE (X) 0x09, 0x31, // USAGE (Y) - 0x09, 0x32, // USAGE (Z) 0x09, 0x33, // USAGE (Rx) 0x09, 0x34, // USAGE (Ry) - 0x09, 0x35, // USAGE (Rz) - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x27, 0xff, 0xff, 0x00, 0x00, // LOGICAL_MAXIMUM (65535) + 0x16, 0x00, 0x80, // LOGICAL_MINIMUM (-32768) + 0x26, 0xFF, 0x7F, // LOGICAL_MAXIMUM (32767) 0x75, 0x10, // REPORT_SIZE (16) - 0x95, 0x06, // REPORT_COUNT (6) + 0x95, 0x04, // REPORT_COUNT (4) + 0x81, 0x02, // INPUT (Data,Var,Abs) + // 2 8bit Axis + 0x09, 0x32, // USAGE (Z) + 0x09, 0x35, // USAGE (Rz) + 0x15, 0x80, // LOGICAL_MINIMUM (-128) + 0x25, 0x7F, // LOGICAL_MAXIMUM (127) + 0x75, 0x08, // REPORT_SIZE (8) + 0x95, 0x02, // REPORT_COUNT (2) 0x81, 0x02, // INPUT (Data,Var,Abs) 0xc0, // END_COLLECTION // 2 Hat Switches From 60f162723c3b6259b94f6c149d5d73745c112035 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Tue, 26 Aug 2014 21:12:30 +0200 Subject: [PATCH 046/602] Gamepad fixes --- plugins/KeyboardioHID/Gamepad.h | 18 +-- plugins/KeyboardioHID/HID.cpp | 119 +++++++++++++++++- plugins/KeyboardioHID/HID.h | 2 + plugins/KeyboardioHID/HID_Reports.h | 6 +- plugins/KeyboardioHID/Readme.md | 19 ++- .../AdvancedGamepad/AdvancedGamepad.ino | 28 ++--- .../AdvancedKeyboard/AdvancedKeyboard.ino | 24 +--- .../examples/Gamepad/Gamepad.ino | 2 + 8 files changed, 163 insertions(+), 55 deletions(-) diff --git a/plugins/KeyboardioHID/Gamepad.h b/plugins/KeyboardioHID/Gamepad.h index 6d51014974..a6f994687c 100644 --- a/plugins/KeyboardioHID/Gamepad.h +++ b/plugins/KeyboardioHID/Gamepad.h @@ -57,12 +57,12 @@ class Gamepad{ case 2: _reportID = HID_REPORTID_Gamepad2Report; break; - //case 3: - // _reportID = HID_REPORTID_Gamepad3Report; - // break; - //case 4: - // _reportID = HID_REPORTID_Gamepad4Report; - // break; + case 3: + _reportID = HID_REPORTID_Gamepad3Report; + break; + case 4: + _reportID = HID_REPORTID_Gamepad4Report; + break; default: _reportID = HID_REPORTID_NotAReport; break; @@ -75,10 +75,10 @@ class Gamepad{ } inline void end(void){ begin(); } - inline void write(void){ HID_SendReport(_reportID, &_report, sizeof(_report));} + inline void write(void){ HID_SendReport(_reportID, &_report, sizeof(_report)); } inline void press(uint8_t b){ _report.buttons |= (uint32_t)1 << (b - 1); } - inline void release(uint8_t b){ _report.buttons &= ~((uint32_t)1 << (b - 1)); } - inline void releaseAll(void){ _report.buttons = 0;} + inline void release(uint8_t b){ _report.buttons &= ~((uint32_t)1 << (b - 1)); } + inline void releaseAll(void){ memset(&_report, 0x00, sizeof(_report)); } inline void buttons(uint32_t b){ _report.buttons = b; } inline void xAxis(int16_t a){ _report.xAxis = a; } diff --git a/plugins/KeyboardioHID/HID.cpp b/plugins/KeyboardioHID/HID.cpp index e0e3d532d8..710581b857 100644 --- a/plugins/KeyboardioHID/HID.cpp +++ b/plugins/KeyboardioHID/HID.cpp @@ -288,7 +288,6 @@ const u8 _hidReportDescriptor[] = { 0xc0, // END_COLLECTION #endif - #ifdef HID_GAMEPAD1_ENABLE // Gamepad1 0x05, 0x01, // USAGE_PAGE (Generic Desktop) @@ -406,6 +405,124 @@ const u8 _hidReportDescriptor[] = { 0xc0, // END_COLLECTION #endif +#ifdef HID_GAMEPAD3_ENABLE + // Gamepad3 + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x04, // USAGE (Joystick) + 0xa1, 0x01, // COLLECTION (Application) + 0x85, HID_REPORTID_Gamepad3Report, // REPORT_ID + // 32 Buttons + 0x05, 0x09, // USAGE_PAGE (Button) + 0x19, 0x01, // USAGE_MINIMUM (Button 1) + 0x29, 0x20, // USAGE_MAXIMUM (Button 32) + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x25, 0x01, // LOGICAL_MAXIMUM (1) + 0x75, 0x01, // REPORT_SIZE (1) + 0x95, 0x20, // REPORT_COUNT (32) + 0x81, 0x02, // INPUT (Data,Var,Abs) + // 4 16bit Axis + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0xa1, 0x00, // COLLECTION (Physical) + 0x09, 0x30, // USAGE (X) + 0x09, 0x31, // USAGE (Y) + 0x09, 0x33, // USAGE (Rx) + 0x09, 0x34, // USAGE (Ry) + 0x16, 0x00, 0x80, // LOGICAL_MINIMUM (-32768) + 0x26, 0xFF, 0x7F, // LOGICAL_MAXIMUM (32767) + 0x75, 0x10, // REPORT_SIZE (16) + 0x95, 0x04, // REPORT_COUNT (4) + 0x81, 0x02, // INPUT (Data,Var,Abs) + // 2 8bit Axis + 0x09, 0x32, // USAGE (Z) + 0x09, 0x35, // USAGE (Rz) + 0x15, 0x80, // LOGICAL_MINIMUM (-128) + 0x25, 0x7F, // LOGICAL_MAXIMUM (127) + 0x75, 0x08, // REPORT_SIZE (8) + 0x95, 0x02, // REPORT_COUNT (2) + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0xc0, // END_COLLECTION + // 2 Hat Switches + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x39, // USAGE (Hat switch) + 0x09, 0x39, // USAGE (Hat switch) + 0x15, 0x01, // LOGICAL_MINIMUM (1) + 0x25, 0x08, // LOGICAL_MAXIMUM (8) + 0x95, 0x02, // REPORT_COUNT (2) + 0x75, 0x04, // REPORT_SIZE (4) + 0x81, 0x02, // INPUT (Data,Var,Abs) + // 8bit Throttle + Rudder + //0x05, 0x02, // USAGE_PAGE (Simulation Controls) + //0xa1, 0x00, // COLLECTION (Physical) + //0x15, 0x00, // LOGICAL_MINIMUM (0) + //0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255) + //0x09, 0xbb, // USAGE (Throttle) + //0x09, 0xba, // USAGE (Rudder) + //0x75, 0x08, // REPORT_SIZE (8) + //0x95, 0x02, // REPORT_COUNT (2) + //0x81, 0x02, // INPUT (Data,Var,Abs) + //0xc0, // END_COLLECTION + 0xc0, // END_COLLECTION +#endif + +#ifdef HID_GAMEPAD4_ENABLE + // Gamepad4 + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x04, // USAGE (Joystick) + 0xa1, 0x01, // COLLECTION (Application) + 0x85, HID_REPORTID_Gamepad4Report, // REPORT_ID + // 32 Buttons + 0x05, 0x09, // USAGE_PAGE (Button) + 0x19, 0x01, // USAGE_MINIMUM (Button 1) + 0x29, 0x20, // USAGE_MAXIMUM (Button 32) + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x25, 0x01, // LOGICAL_MAXIMUM (1) + 0x75, 0x01, // REPORT_SIZE (1) + 0x95, 0x20, // REPORT_COUNT (32) + 0x81, 0x02, // INPUT (Data,Var,Abs) + // 4 16bit Axis + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0xa1, 0x00, // COLLECTION (Physical) + 0x09, 0x30, // USAGE (X) + 0x09, 0x31, // USAGE (Y) + 0x09, 0x33, // USAGE (Rx) + 0x09, 0x34, // USAGE (Ry) + 0x16, 0x00, 0x80, // LOGICAL_MINIMUM (-32768) + 0x26, 0xFF, 0x7F, // LOGICAL_MAXIMUM (32767) + 0x75, 0x10, // REPORT_SIZE (16) + 0x95, 0x04, // REPORT_COUNT (4) + 0x81, 0x02, // INPUT (Data,Var,Abs) + // 2 8bit Axis + 0x09, 0x32, // USAGE (Z) + 0x09, 0x35, // USAGE (Rz) + 0x15, 0x80, // LOGICAL_MINIMUM (-128) + 0x25, 0x7F, // LOGICAL_MAXIMUM (127) + 0x75, 0x08, // REPORT_SIZE (8) + 0x95, 0x02, // REPORT_COUNT (2) + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0xc0, // END_COLLECTION + // 2 Hat Switches + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x39, // USAGE (Hat switch) + 0x09, 0x39, // USAGE (Hat switch) + 0x15, 0x01, // LOGICAL_MINIMUM (1) + 0x25, 0x08, // LOGICAL_MAXIMUM (8) + 0x95, 0x02, // REPORT_COUNT (2) + 0x75, 0x04, // REPORT_SIZE (4) + 0x81, 0x02, // INPUT (Data,Var,Abs) + // 8bit Throttle + Rudder + //0x05, 0x02, // USAGE_PAGE (Simulation Controls) + //0xa1, 0x00, // COLLECTION (Physical) + //0x15, 0x00, // LOGICAL_MINIMUM (0) + //0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255) + //0x09, 0xbb, // USAGE (Throttle) + //0x09, 0xba, // USAGE (Rudder) + //0x75, 0x08, // REPORT_SIZE (8) + //0x95, 0x02, // REPORT_COUNT (2) + //0x81, 0x02, // INPUT (Data,Var,Abs) + //0xc0, // END_COLLECTION + 0xc0, // END_COLLECTION +#endif + #ifdef HID_JOYSTICK1_ENABLE // Joystick1 0x05, 0x01, // USAGE_PAGE (Generic Desktop) diff --git a/plugins/KeyboardioHID/HID.h b/plugins/KeyboardioHID/HID.h index a8a14a4574..6838f1cb20 100644 --- a/plugins/KeyboardioHID/HID.h +++ b/plugins/KeyboardioHID/HID.h @@ -48,6 +48,8 @@ THE SOFTWARE. #define HID_SYSTEM_ENABLE 24 #define HID_GAMEPAD1_ENABLE 71 //#define HID_GAMEPAD2_ENABLE 71 +//#define HID_GAMEPAD3_ENABLE 71 +//#define HID_GAMEPAD4_ENABLE 71 //#define HID_JOYSTICK1_ENABLE 51 //#define HID_JOYSTICK2_ENABLE 51 diff --git a/plugins/KeyboardioHID/HID_Reports.h b/plugins/KeyboardioHID/HID_Reports.h index e0b195ded1..31ca5ad2e4 100644 --- a/plugins/KeyboardioHID/HID_Reports.h +++ b/plugins/KeyboardioHID/HID_Reports.h @@ -198,8 +198,10 @@ typedef enum{ HID_REPORTID_SystemReport = 0x05, /**< Report ID for the Power report within the device. */ HID_REPORTID_Gamepad1Report = 0x06, /**< Report ID for the Gamepad1 report within the device. */ HID_REPORTID_Gamepad2Report = 0x07, /**< Report ID for the Gamepad2 report within the device. */ - HID_REPORTID_Joystick1Report = 0x08, /**< Report ID for the Joystick1 report within the device. */ - HID_REPORTID_Joystick2Report = 0x09, /**< Report ID for the Joystick2 report within the device. */ + HID_REPORTID_Gamepad3Report = 0x08, /**< Report ID for the Gamepad3 report within the device. */ + HID_REPORTID_Gamepad4Report = 0x09, /**< Report ID for the Gamepad4 report within the device. */ + HID_REPORTID_Joystick1Report = 0x10, /**< Report ID for the Joystick1 report within the device. */ + HID_REPORTID_Joystick2Report = 0x11, /**< Report ID for the Joystick2 report within the device. */ HID_REPORTID_LastNotAReport, // determinate whats the maximum number of reports -1 } HID_Report_IDs; diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 0abf45e7eb..a529adacb4 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -9,7 +9,7 @@ No need for extra hardware. You just need one of the Arduinos and an USB cable. **Main difference is that you can upload new sketches to the Uno/Mega and dont need to reflash the firmware over and over again.** Before you had to upload a sketch, flash the firmware, test, flash the firmware, upload, flash again. Thats all gone! -**For the Leonardo/Micro it is 'just' new HID devices, no need for a bootloader.** +**For the Leonardo/Micro it is 'just' new HID devices, no need for a bootloader (like on Uno/Mega).** Note: [Hoodloader Repository moved here.](https://github.com/NicoHood/Hoodloader) @@ -57,11 +57,12 @@ Over all the Uno/Mega solution gives you more opportunities except that the Seri Installation Leonardo/Micro/Uno/Mega ==================================== + +#### Leonardo/Micro only Download the library and [install it](http://arduino.cc/en/pmwiki.php?n=Guide/Libraries) like you are used to. **For the whole Project IDE 1.5.7 or higher is recommended!** -#### Leonardo/Micro only **Edit HID.h to de/activate usb functions.** By default Mouse, Keyboard, Media, System, Gamepad1 is activated. @@ -71,12 +72,18 @@ You cannot use more than 255 bytes HID report on the Leonardo/Micro. The number after each definition tells you the size of each report. I have no idea why you cannot use more than 255 bytes (yet), its a bug in the Arduino code. -#### Uno/Mega only +#### Uno/Mega onl +Download the library and [install it](http://arduino.cc/en/pmwiki.php?n=Guide/Libraries) like you are used to. + +**For the whole Project IDE 1.5.7 or higher is recommended!** + To install the new bootloader connect your Arduino to your PC via USB and see [Hoodloader installing instructions](https://github.com/NicoHood/Hoodloader). No special programmer needed, just an USB cable. **You can always switch back to the original firmware, nothing to break.** +Edit HID.h to add an extra delay for raspberry pi. This is a workaround to fix this for slower PCs. There is still a problem with Raspberry. + Usage ===== You are ready to use the libraries. **Just have a look at the examples and test it out.** They are pretty much self explaining. @@ -103,9 +110,11 @@ Updating to a newer Version =========================== HID library: -To upgrade to v1.8 you need to redownload the ide files, replace the original files and install the library like you are used to. +To upgrade to v1.8 you need to redownload the Arduino IDE files, restore the original files and install the library like you are used to. +You library is now located in sketchbook/libraries/HID/ +Its now way easier to install the library, no need to replace system files. For further releases just replace all files again. -Hoodloader: +Hoodloader (Not needed for Leonardo/Micro): Just upload the new hex file and check the HID Project if the HID library code has changed and replace the new files too. You normally dont need to reinstall the drivers for windows if the changelog dosnt note anything. diff --git a/plugins/KeyboardioHID/examples/AdvancedGamepad/AdvancedGamepad.ino b/plugins/KeyboardioHID/examples/AdvancedGamepad/AdvancedGamepad.ino index 10dba0d62f..bd8eb03192 100644 --- a/plugins/KeyboardioHID/examples/AdvancedGamepad/AdvancedGamepad.ino +++ b/plugins/KeyboardioHID/examples/AdvancedGamepad/AdvancedGamepad.ino @@ -1,15 +1,13 @@ /* -Copyright (c) 2014 NicoHood + Copyright (c) 2014 NicoHood See the readme for credit to other people. Advanced Gamepad example */ -// not needed for Leonardo/Micro +// include HID library #include -// for Leonardo/Micro: make sure to activate desired USB functions in HID_Reports.h - const int pinLed = 13; const int pinButton = 8; @@ -20,24 +18,15 @@ void setup() { pinMode(pinLed, OUTPUT); pinMode(pinButton, INPUT_PULLUP); - // Starts Serial at baud 115200. end just ends the Serial - // Make sure to end your special HIDs before, this does not clear them! - // You need this baud for the HID library but still can use other bauds - // without HID functions. - // not needed for Leonado/Micro, Serial will not be set - HID.begin(); + // Starts Serial at baud 115200 otherwise HID wont work on Uno/Mega. + // This is not needed for Leonado/(Pro)Micro but make sure to activate desired USB functions in HID.h + Serial.begin(SERIAL_HID_BAUD); // Sends a clean report to the host. This is important because // the 16u2 of the Uno/Mega is not turned off while programming - // so you want to start with a clear report to avoid strange bugs. - // its exactly the same like the end() function. - // You can also unplug the device if anything goes wrong. - // To prevent the 16u2 to send more reports just pull the Serial TX (pin1) low - // or see readme for turning off HID functions. - // If you did anything wrong (keyboard is doing weird stuff) - // just logout (no shutdown needed). + // so you want to start with a clean report to avoid strange bugs after reset. memset(&Gamepadreport, 0, sizeof(Gamepadreport)); - HID.sendReport(HID_REPORTID_Gamepad1Report, &Gamepadreport, sizeof(Gamepadreport)); + HID_SendReport(HID_REPORTID_Gamepad1Report, &Gamepadreport, sizeof(Gamepadreport)); } void loop() { @@ -56,7 +45,7 @@ void loop() { // functions before only set the values // this writes the report to the host - HID.sendReport(HID_REPORTID_Gamepad1Report, &Gamepadreport, sizeof(Gamepadreport)); + HID_SendReport(HID_REPORTID_Gamepad1Report, &Gamepadreport, sizeof(Gamepadreport)); // simple debounce delay(300); @@ -64,4 +53,3 @@ void loop() { } } - diff --git a/plugins/KeyboardioHID/examples/AdvancedKeyboard/AdvancedKeyboard.ino b/plugins/KeyboardioHID/examples/AdvancedKeyboard/AdvancedKeyboard.ino index 708ae91055..725f1bea35 100644 --- a/plugins/KeyboardioHID/examples/AdvancedKeyboard/AdvancedKeyboard.ino +++ b/plugins/KeyboardioHID/examples/AdvancedKeyboard/AdvancedKeyboard.ino @@ -5,11 +5,9 @@ Copyright (c) 2014 NicoHood Advanced Keyboard example */ -// not needed for Leonardo/Micro +// include HID library #include -// for Leonardo/Micro: make sure to activate desired USB functions in HID_Reports.h - const int pinLed = 13; const int pinButton = 8; @@ -17,22 +15,13 @@ void setup() { pinMode(pinLed, OUTPUT); pinMode(pinButton, INPUT_PULLUP); - // Starts Serial at baud 115200. end just ends the Serial - // Make sure to end your special HIDs before, this does not clear them! - // You need this baud for the HID library but still can use other bauds - // without HID functions. - // not needed for Leonado/Micro, Serial will not be set - HID.begin(); + // Starts Serial at baud 115200 otherwise HID wont work on Uno/Mega. + // This is not needed for Leonado/(Pro)Micro but make sure to activate desired USB functions in HID.h + Serial.begin(SERIAL_HID_BAUD); // Sends a clean report to the host. This is important because // the 16u2 of the Uno/Mega is not turned off while programming - // so you want to start with a clear report to avoid strange bugs. - // its exactly the same like the end() function. - // You can also unplug the device if anything goes wrong. - // To prevent the 16u2 to send more reports just pull the Serial TX (pin1) low - // or see readme for turning off HID functions. - // If you did anything wrong (keyboard is doing weird stuff) - // just logout (no shutdown needed). + // so you want to start with a clean report to avoid strange bugs after reset. pressRawKeyboard(0, 0); } @@ -59,7 +48,7 @@ void loop() { void pressRawKeyboard(uint8_t modifiers, uint8_t key) { uint8_t keys[8] = { modifiers, 0, key, 0, 0, 0, 0, 0 }; //modifiers, reserved, key[0] - HID.sendReport(HID_REPORTID_KeyboardReport, keys, sizeof(keys)); + HID_SendReport(HID_REPORTID_KeyboardReport, keys, sizeof(keys)); } /* @@ -108,4 +97,3 @@ See Hut1_12v2.pdf Chapter 10 (Page 53) for more Keys RAW_KEYBOARD_SCROLL_LOCK RAW_KEYBOARD_PAUSE */ - diff --git a/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino b/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino index 191b374c9f..44dd2ced6a 100644 --- a/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino +++ b/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino @@ -12,6 +12,8 @@ Press a button and demonstrate Gamepad actions // create a new Gamepad instance (1-4) Gamepad Gamepad1(1); //Gamepad Gamepad2(2); +//Gamepad Gamepad3(3); +//Gamepad Gamepad4(4); const int pinLed = 13; const int pinButton = 8; From e447e9e19a7bd8bf7242c86cc5f9ec5b9984eeed Mon Sep 17 00:00:00 2001 From: NicoHood Date: Tue, 26 Aug 2014 21:33:45 +0200 Subject: [PATCH 047/602] Update 1.8 Release --- plugins/KeyboardioHID/Readme.md | 4 +- .../KeyboardioHID/firmwares/Hoodloader1_8.hex | 642 ++++++++++++++++++ 2 files changed, 645 insertions(+), 1 deletion(-) create mode 100644 plugins/KeyboardioHID/firmwares/Hoodloader1_8.hex diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index a529adacb4..99adc9515d 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -114,6 +114,8 @@ To upgrade to v1.8 you need to redownload the Arduino IDE files, restore the ori You library is now located in sketchbook/libraries/HID/ Its now way easier to install the library, no need to replace system files. For further releases just replace all files again. +**Restart the IDE** + Hoodloader (Not needed for Leonardo/Micro): Just upload the new hex file and check the HID Project if the HID library code has changed and replace the new files too. @@ -198,7 +200,7 @@ so you better use an Arduino Uno with Hoodloader for Mediacenter control and Amb Version History =============== ``` -1.8 Beta Release (xx.08.2014) +1.8 Beta Release (26.08.2014) * Changes in the Hoodloader: * **Huge improvements**, see [Hoodloader repository](https://github.com/NicoHood/Hoodloader) * Reworked the whole library, easy installation now diff --git a/plugins/KeyboardioHID/firmwares/Hoodloader1_8.hex b/plugins/KeyboardioHID/firmwares/Hoodloader1_8.hex new file mode 100644 index 0000000000..d35ec84ce2 --- /dev/null +++ b/plugins/KeyboardioHID/firmwares/Hoodloader1_8.hex @@ -0,0 +1,642 @@ +:1000000099C10000B3C10000B1C10000AFC1000040 +:10001000ADC10000ABC10000A9C10000A7C1000034 +:10002000A5C10000A3C10000A1C100000C94B80D3F +:100030000C94640E9BC1000099C1000097C10000A0 +:1000400095C1000093C1000091C100008FC1000064 +:100050008DC100008BC1000089C1000057C30000A2 +:1000600085C1000083C1000081C100007FC1000084 +:100070007DC100003003410072006400750069001A +:100080006E006F00200048006F006F0064006C007D +:100090006F0061006400650072002000420065008E +:1000A00074006100000012034E00690063006F00DD +:1000B00048006F006F006400000004030904090297 +:1000C0005F00030100C032080B00020202010009B8 +:1000D00004000001020201000524001001042402B2 +:1000E000060524060001070582030800FF09040134 +:1000F00000020A0000000705040240000107058312 +:10010000024000010904020001030000000921115E +:1001100001000122040207058103100001120110F1 +:1001200001EF020108EB03686E80010102DC0105AA +:10013000010902A1010901A100850105091901298F +:10014000051500250195057501810295017503814D +:100150000305010930093109381581257F75089596 +:10016000038106C0C005010906A101850205071922 +:10017000E029E715002501750195088102950175B3 +:1001800008810395067508150025650507190029DE +:1001900065810005081901290595057501910295EC +:1001A0000175039103C006C0FF0A000CA10185037D +:1001B0007508150026FF00950F09018102950F09AA +:1001C000029102C0050C0901A1018504150026FF5A +:1001D0000319002AFF03950475108100C005010969 +:1001E00080A1018505150026FF00190029FF950152 +:1001F00075088100C005010904A1018506050919DA +:10020000012920150025017501952081020501A114 +:1002100000093009310933093416008026FF7F7543 +:100220001095048102093209351580257F750895DE +:10023000028102C005010939093915012508950215 +:1002400075048102C005010904A10185070509198A +:10025000012920150025017501952081020501A1C4 +:1002600000093009310933093416008026FF7F75F3 +:100270001095048102093209351580257F7508958E +:10028000028102C009390939150125089502750452 +:100290008102C005010904A1018508050919012988 +:1002A00020150025017501952081020501A1000995 +:1002B0003009310933093416008026FF7F75109507 +:1002C000048102093209351580257F750895028160 +:1002D00002C005010939093915012508950275047F +:1002E0008102C005010904A1018509050919012937 +:1002F00020150025017501952081020501A1000945 +:100300003009310933093416008026FF7F751095B6 +:10031000048102093209351580257F75089502810F +:1003200002C005010939093915012508950275042E +:100330008102C00011241FBECFEFD2E0DEBFCDBFCF +:1003400011E0A0E0B1E0EAECF7E202C005900D9206 +:10035000AE33B107D9F711E0AEE3B1E001C01D92B1 +:10036000A63FB107E1F773D00C94E31349CEEEE357 +:10037000F1E05FB7F894208131812115310519F042 +:100380004481411104C05FBF2FEF3FEF11C0828154 +:1003900090E0841B910997FF03C06381860F911D34 +:1003A000D901A80FB91F2C91415044835FBF30E0A1 +:1003B000C9010895EEE3F1E04FB7F894208131814F +:1003C0002115310509F41DC0828190E05481851BFF +:1003D0009109019797FF03C05381850F911DD901A2 +:1003E000A80FB91F6C9384819381891308C09281EF +:1003F000911101C0828382818150828302C08F5F0C +:1004000084834FBF089584B7877F84BF88E10FB688 +:10041000F89480936000109260000FBE539A5A9A2D +:1004200080E191E00E94D00A1092CA018AB18063F3 +:100430008AB98BB180638BB90E94A90D84E085BD18 +:100440005F9A579A25982D9A26982E9A089580910A +:10045000CB01807F8093CB011092DB011092DC01F5 +:100460002DD4D1DF789410E213B980E191E00E949D +:10047000B51097FD1BC0409124015091250160915A +:10048000260170912701413051056105710511F474 +:10049000AFD60CC05C989091CA019C609093CA0141 +:1004A0009091C80095FFFCCF8093CE002FB7F894B1 +:1004B00080913E0190913F01892B19F0809142017A +:1004C00001C080E02FBF90E0009719F4A89981C087 +:1004D00002C15D982091CA0123602093CA01209136 +:1004E00011012F702093E9002091E80020FFEECF4A +:1004F0008034910510F08FE390E0F82EC0E0D0E05A +:1005000065C08091240190912501A0912601B091B0 +:1005100027012091E80121110CC082309105A1052D +:10052000B10528F08115924CA140B10511F41D9937 +:1005300043C08091200180FD0AC0222341F08EE358 +:1005400091E015DF8091E80181112DC03EC07FB799 +:10055000F89420913E0130913F012115310541F081 +:1005600040914201442321F050E01416150624F076 +:100570007FBF6FEF7FEF10C08091400190E0841B40 +:10058000950B97FF04C040914101840F911DF90123 +:10059000E80FF91F60817FBF80E191E00E944D105C +:1005A000882369F293CF81508093E8018091CA013A +:1005B00080638093CA0109C08091CA0180638093DF +:1005C000CA018EE391E0D3DEA1D22196FC1299CF2D +:1005D0007DCFA89A9091CA01892F807309F459C0E0 +:1005E000892F82958F708D5F8370282F2295207FB1 +:1005F0009F7C922B9093CA0181114BC0E091DD0149 +:10060000E6FF15C0E695E695E695E770F0E0EE5159 +:10061000FE4F60818EE391E0CDDE8091DD0186FBAF +:10062000882780F99091E801890F8093E8018091F3 +:10063000DD0187FD2AC08695869586958770C0E086 +:10064000D0E0E82EF12C8EE3C82E81E0D82ECE0C1F +:10065000DF1C09C0F601EC0FFD1FEC55FF4F608158 +:100660008EE391E0A7DE2197CE01809590958E15BF +:100670009F0584F38091DD01869586958695877028 +:100680009091E801890F8093E8018DED91E070D69B +:100690000AD29091CA01892F837049F081508370EA +:1006A0009C7F982B9093CA01811101C05D9A909113 +:1006B000CA01892F8C7079F0892F869586958D5F78 +:1006C0008370282F220F220F937F922B9093CA01C1 +:1006D000811101C05C9A80E091E00E94E01280E10B +:1006E00091E00E949F100E940C10BECE08950895C4 +:1006F00080E091E00E94CB1280E191E00E942810FE +:10070000E2EEF0E080818460808308951F920F9272 +:100710000FB60F9211242F933F934F935F938F93B4 +:100720009F93AF93BF93EF93FF934091CE0080913F +:10073000ED018430E9F4EEE3F1E02FB7F894808125 +:1007400091810097A1F054813381531301C00FC0F0 +:100750003281DC01A30FB11D4C93832F8F5F828305 +:100760009381891301C0128284818F5F84832FBF9C +:10077000FF91EF91BF91AF919F918F915F914F91B9 +:100780003F912F910F900FBE0F901F90189580E111 +:1007900091E00E94E31080E091E00C94941180912C +:1007A0000E0190910F01009729F0019790930F018E +:1007B00080930E010895292F332723303105B1F09E +:1007C0004CF42130310509F439C02230310509F0EB +:1007D0003AC007C02132310539F12232310549F1E1 +:1007E00032C0EFE5F0E08EEB90E031C09927813028 +:1007F000910561F08230910581F0892B21F5EAEBBA +:10080000F0E0E491F0E08AEB90E021C0E6EAF0E06D +:10081000E491F0E086EA90E01AC0E4E7F0E0E491C9 +:10082000F0E084E790E013C0E9E0F0E08DE091E0D3 +:100830000EC0E4E0F2E08FE291E009C0E2E1F0E016 +:100840008DE191E004C0E0E0F0E080E090E0DA01CA +:100850008D939C93CF010895FF920F931F93CF9395 +:10086000DF9320E030E050E0640F751FCEE3D1E06D +:100870002CC0FB01E21BF30B31970081FE011FB777 +:10088000F894A081B181109709F41CC0828190E096 +:10089000F4808F199109019797FF03C0F3808F0DA2 +:1008A000911DA80FB91F0C9384819381891308C0EF +:1008B0009281911101C0828382818150828302C022 +:1008C0008F5F84831FBF2F5F3F4F241735078CF244 +:1008D000DF91CF911F910F91FF900895089504C06B +:1008E00080E091E00E94E0128091DC0187FDF8CF6A +:1008F00008958150813130F4E82FF0E0E55DFE4F3E +:100900008081089580E00895EF92FF921F93CF9326 +:10091000DF931F92CDB7DEB7182FE82EF12C21E020 +:10092000E21AF1082091DB018091DC01382F3F773A +:100930000E2C02C0359527950A94E2F720FF36C0A9 +:10094000812FD7DF882391F18983C9DF1F709091B0 +:10095000CB01907F912B9093CB012CEC31E08981DE +:10096000482F50E060E070E0C9010E94DC138091E4 +:10097000DC0180688093DC01B2DF81E090E002C09E +:10098000880F991FEA94E2F7809590952091DB01FA +:100990004091DC01342F3F77822393238093DB0146 +:1009A0009F77842F8078892B8093DC010F90DF91D3 +:1009B000CF911F91FF90EF900895CF938091DB012D +:1009C0002091DC01922F9F77892B31F0C1E08C2F91 +:1009D0009BDFCF5FC231D9F7CF910895CF92DF92DD +:1009E000EF92FF920F931F93CF93DF9300D0CDB779 +:1009F000DEB77B01932F68017091DC01672F60786F +:100A000009F440C0E091CB01EF70E330B1F0F0E0C9 +:100A1000319741E050E002C0440F551FEA95E2F7DC +:100A2000E091DB01F72FFF774E2B5F2B4093DB012B +:100A3000452F4F77462B4093DC018091CB018F707F +:100A400029839A8356DF182FECECF1E0482F50E011 +:100A5000BF012981822F9A810E94D3139091CB01EB +:100A60009F70F7019083F601108311828091DC0161 +:100A70008F778093DC018091CB01807F8093CB01C5 +:100A800081E006C0F7011082F8011182108280E037 +:100A90000F900F90DF91CF911F910F91FF90EF90EA +:100AA000DF90CF9008951F93CF93DF9300D000D0B5 +:100AB00000D0CDB7DEB713DF8091CB01682F6F7008 +:100AC000B1F0807FA1F470E07160AE014F5F5F4FC5 +:100AD00081E024D5182F482FBE016F5F7F4F8EE332 +:100AE00091E0BADE9091E801910F9093E801809136 +:100AF000CB01807F8093CB0126960FB6F894DEBFA2 +:100B00000FBECDBFDF91CF911F910895CF936DEDB3 +:100B100071E0E1D4882309F48AC087FD70C0813078 +:100B2000C1F49091DF019130A1F4D9DEC091DE01D2 +:100B30008091CB018F708093CB01B5DFCF70809116 +:100B4000CB01807F8C2B8093CB018F7009F06FC01D +:100B50006CC02091CB01922F9F7009F450C099274F +:100B600087FD909522952F7030E02E5F3F4F359591 +:100B700027952F5F3F4F8217930709F040C0AFDEE4 +:100B8000C091CB018C2F8F70B4DE2C2F22952F704B +:100B90009091DE013091DF01E22FF0E0E453FE4F4F +:100BA0009083E22FEF5FEF704E2F4295407F909140 +:100BB000CB019F70942B9093CB018E1769F0F0E0DE +:100BC000E453FE4F30832E5F2295207F9091CB011E +:100BD0009F70922B9093CB012091CB0122952F7087 +:100BE00030E090E02817390711F58091DC0180682A +:100BF0008093DC0180E091E0CF910C94E012409171 +:100C0000DD01469546954695477062EE71E08EE3AC +:100C100091E022DE8091DD0186958695869587702C +:100C20009091E801890F8093E801CF913CCFCF915B +:100C30000895682F80E191E00E944D108823D9F03B +:100C400080E191E00E949F100E940C105C982FEFB1 +:100C500081EE94E0215080409040E1F700C0000018 +:100C60005C982FEF81EE94E0215080409040E1F7B6 +:100C700000C00000EBCF089580E191E00E94B51024 +:100C800097FDFACF0895EF92FF920F931F93CF93A2 +:100C9000DF937C0103E411E0C0E0D0E005C0ECDFAD +:100CA000F80181938F012196CE15DF05C4F3DF9102 +:100CB000CF911F910F91FF90EF9008952398229864 +:100CC0002198249820981092C5011092C401109286 +:100CD000C7011092C6011092C9011092C80110926A +:100CE000C301EEE3F1E02FB7F89483E491E0918340 +:100CF0008083128280E8838314822FBF1092E801E0 +:100D00008DED91E035C3CF93C82FB6DF803239F433 +:100D100084E18FDF8C2F8DDF80E1CF918ACF85E159 +:100D200088DF8091C301982F9F5F9F778078892B00 +:100D30008093C301CF9108959FDF803221F484E135 +:100D400078DF80E176CF85E174DF8091C301982F51 +:100D50009F5F9F778078892B8093C30108958138A6 +:100D600059F018F4803871F405C0823839F08339AD +:100D700049F406C082E007C081E005C082E103C0FB +:100D800083E501C080E0BFCF84E190E07CDF9091FB +:100D90004F0180E020915001820F911D9093C70177 +:100DA0008093C6019091510180E020915201820F01 +:100DB000911D9093C9018093C801089583E58CBD6E +:100DC0008DB58EB508950DB407FEFDCF08958EBD87 +:100DD000FADF8EB50895CF93DF9300D01F92CDB781 +:100DE000DEB72B834A836983F2DF6981862FEFDFC9 +:100DF0004A81842FECDF2B81822F0F900F900F9070 +:100E0000DF91CF91E4CF38DF803259F08091C30178 +:100E1000982F9F5F9F778078892B8093C30185E10E +:100E200015C084E106DF20E040E060E080E3D3DF2E +:100E300000DF20E041E060E080E3CDDFFADE20E08B +:100E400042E060E080E3C7DFF4DE80E1F2CE84E0E0 +:100E500090E019DF209146014091450160914401E5 +:100E600080914301B8DF4FCF209A289AA7DF249AB8 +:100E70002C9A219A29982FEF80E792E02150804008 +:100E80009040E1F700C000002C982FEF80E792E03F +:100E9000215080409040E1F700C000002398229A42 +:100EA00020E040E063E58CEA96DFE3ECF1E080814E +:100EB0008068808382DDEEE3F1E08FB7F8941182E1 +:100EC00010821282138214828FBF1092CA018BB1DA +:100ED00080638BB90895962F672F242F492F7BCFDE +:100EE000EF92FF920F931F93CF93DF93C5DE182FDE +:100EF000C3DED82FC1DEC82FBFDE803259F080910B +:100F0000C301982F9F5F9F778078892B8093C301BF +:100F100085E144C0312F20E07901ED0EF11C84E120 +:100F200088DEC63419F51BC06091C4017091C501FB +:100F300040E080E2D0DF7DDE6091C4017091C501A8 +:100F400040E088E2C8DF75DE8091C4019091C50160 +:100F500001969093C5018093C401229602C0C0E01F +:100F6000D0E0CE15DF0504F380E118C0C534A9F444 +:100F70000091C4011091C501000F111FC0E0D0E025 +:100F800008C0BE01600F711F4FEF80EAA4DF51DE81 +:100F90002196CE15DF05ACF3E7CF81E1DF91CF914C +:100FA0001F910F91FF90EF9044CE8091C6019091D8 +:100FB000C7012091C4013091C5018032910511F41F +:100FC000207F0EC08034910511F4207E09C0803846 +:100FD000910511F4207C04C08115914009F420781A +:100FE000C90108955D9A40E0BC018CE474DF2FEFE5 +:100FF00086E791E0215080409040E1F700C000007A +:101000005D980895CF92DF92EF92FF920F931F9316 +:10101000CF93DF937B01CB0136DEC7DF8C01C0E0CD +:10102000D0E029C09EE3C92E91E0D92ECC0EDD1E62 +:101030006091C4017091C501F601458180E44BDFE8 +:1010400022966091C4017091C501F601468188E441 +:1010500042DF2091C4013091C5012F5F3F4F309393 +:10106000C5012093C401A1DF0817190721F0C801A9 +:10107000B9DF9BDF8C01CE15DF05A4F280E1DF91A3 +:10108000CF911F910F91FF90EF90DF90CF90089537 +:101090000F931F93CF93DF93C091C401D091C501EB +:1010A000CC0FDD1F8C0108C060E870E0CE01AADF24 +:1010B000C058DF4F0058110901381105A8F7B801D1 +:1010C000CE01A0DF80E1DF91CF911F910F910895B4 +:1010D000CF92DF92EF92FF920F931F93CF93DF9304 +:1010E0006C018B01CB01CFDD5D9A33E4E32E31E05F +:1010F000F32EC0E0D0E012C0F70141917F01BE01A4 +:101100006C0D7D1D80ECE7DEFFE722E382E0F1500D +:1011100020408040E1F700C000002196C017D107B1 +:101120005CF35D9880E1DF91CF911F910F91FF906B +:10113000EF90DF90CF9008950F931F93CF93DF939D +:10114000C091C401D091C5012091C8013091C9015D +:101150002817390724F0CC0FDD1F8C0113C08091B4 +:10116000C301982F9F5F9F778078892B8093C3015D +:1011700081E10FC060E870E0CE01AADFC058DF4F08 +:101180000058110901381105A8F7B801CE01A0DFF8 +:1011900080E1DF91CF911F910F910895CF93DF935D +:1011A0006BDDD82F80E0C82F67DDC80FD11D64DD4F +:1011B000863419F4CE016CDF04C08534A9F4CE0165 +:1011C000BBDFC82F59DD803221F484E132DD8C2F62 +:1011D0000CC08091C301982F9F5F9F778078892BE7 +:1011E0008093C30185E101C081E1DF91CF9121CDE1 +:1011F000CF93DF932091C30127FF02C05D9801C008 +:101200005D9A2F7711F05C9801C05C9A97FDADC094 +:101210008135910509F483C0E4F48134910509F422 +:1012200053C054F48033910599F181339105B1F1A4 +:10123000809709F088C07DC08534910509F44CC0C1 +:101240008035910509F44CC08234910509F07BC0CA +:101250003FC08136910509F457C06CF4863591057D +:1012600009F45AC08036910509F44DC085359105C1 +:1012700009F069C037C08437910509F44AC0853741 +:10128000910509F453C08436910509F05CC03EC055 +:101290008091C30180788093C3011BC0EDDC803254 +:1012A00009F063C084E1C5DC81E4C3DC86E5C1DC10 +:1012B00082E5BFDC80E2BDDC89E4BBDC83E5B9DC30 +:1012C00080E5B7DC80E14EC0D7DCDF91CF9147CD20 +:1012D0005BDDDF91CF9130CD85E090E0D4DCF9CFBC +:1012E000C3DDF7CFC9DCC82FD0E0D093C501C093D0 +:1012F000C401C2DC382F20E02C0F3D1F3093C50104 +:101300002093C401E6CFB8DCB7DCE3CFDF91CF9107 +:1013100045CFDF91CF91E4CDDF91CF9198CD8091F2 +:10132000C30180788093C301C9DCD3CFDF91CF9113 +:101330006ACD8091C301982F9F5F9F778078892B1A +:101340008093C3010EC08091C301982F9F5F9F7748 +:101350008078892B8093C3018FDC803211F482E185 +:1013600001C085E1DF91CF9164CCDF91CF910895E9 +:10137000FC01208120682F7B208308950F931F9309 +:10138000FB01908196FF0FC0292F26952695269563 +:101390002770DB01A20FB11D15962C912583977C38 +:1013A00098609F7B03C097FF02C0907C90839081E0 +:1013B0009695969596959770DF01A90FB11D159694 +:1013C0008C93292F2F5F2770220F220F220F40812D +:1013D000477C422B4083282F207C342F37702038C5 +:1013E00009F463C0203C09F045C0282F28732695D6 +:1013F00026952695332349F0990F990F990F477C2D +:10140000492B406440839EEF01C090E0223098F465 +:10141000908196FB222720F9892F869586958695BF +:10142000820F8770880F880F880F977C982B9F7B7F +:1014300090839FEF3FC0273059F4082F0F7010E0C2 +:1014400020E030E0018312832383348325E00AC047 +:10145000482F477050E060E070E04183528363831F +:101460007483215027708081887F822B8083992309 +:1014700029F120C0032F10E00230110524F1395F5B +:101480003770487F432B408341815281638174814F +:1014900097E0440F551F661F771F9A95D1F7482B89 +:1014A000418352836383748309C0313071F4982F70 +:1014B0009F739F5F80818068808309C080818F7760 +:1014C000808390E004C09DEFF5CF9CEFF3CF892F90 +:1014D0001F910F9108950F931F93CF93DF93EB010B +:1014E0004DDF1816B4F409811A812B813C81A901C2 +:1014F000662777272227332740275127622773271C +:101500004F3F5F4F6105710521F0888180688883B6 +:101510008BEFDF91CF911F910F910895FA012CE18C +:1015200030E097E0AB01022E02C0569547950A9431 +:10153000E2F7483028F0973059F4408396E008C02D +:1015400040839150411104C027503109923051F726 +:10155000492F42500DC0DF01A40FB11D9B012F7711 +:1015600033272C93660F672F661F770B71954150B9 +:101570004111F1CF492F50E09A0163E0220F331F50 +:101580006A95E1F7206C3F6F3081322B3083E40F96 +:10159000F51F319781508F7380688083892F08955C +:1015A000CF92DF92EF92FF92CF93DF93EC01809185 +:1015B000C30187FD83DB01DACC88DD88EE88FF88F4 +:1015C00082E0C816D104E104F10420F0988D8A8DE0 +:1015D000E98D09C0E0E088E090E0C12C32ECD32E28 +:1015E000EE24E394F12CE150E23028F4F0E0E45CE6 +:1015F000FE4FC08101C0C0E0923009F4C86087305E +:1016000031F0883031F0863029F4C26003C0C46004 +:1016100001C0C6605B9A1092C9001092C800109277 +:10162000CA00C11481EED806E104F10489F0C701B3 +:10163000B601969587957795679560587B47814E5B +:101640009F4FA70196010E94A4132150310902C0A7 +:1016500020E130E03093CD002093CC00C093CA004D +:10166000C11481EED806E104F10411F480E001C058 +:1016700082E08093C80088E98093C9005B98DF917D +:10168000CF91FF90EF90DF90CF900895CF93DF93AD +:10169000EC0193D91E9B03C0888980FF02C05F982C +:1016A00006C05F9A1092CA018BB180638BB9DF913B +:1016B000CF910895BF92CF92DF92EF92FF920F9356 +:1016C0001F93CF93DF937C018B01EA01D7D1B82E12 +:1016D000811132C0209731F028813981021B130B10 +:1016E000E20EF31EC12CD12C22C08091E80085FDB2 +:1016F00014C08091E8008E778093E800209749F02D +:10170000888199818C0D9D1D9983888325E0B22E57 +:1017100013C0B4D1882359F00EC0F70181917F0125 +:101720008093F10001501109FFEFCF1ADF0A011574 +:101730001105D9F601C0B82E8B2DDF91CF911F91E5 +:101740000F91FF90EF90DF90CF90BF900895209180 +:10175000F4013091F5012617370748F0611571053E +:1017600039F42091E8002E772093E80001C0B901F8 +:101770009C0180E034C09091ED01992309F443C0AD +:10178000953009F442C09091E80093FD3AC09091E1 +:10179000E80092FD30C09091E80090FF20C0809159 +:1017A000F20090E0F901821B930B05C02191209378 +:1017B000F100615071099F01280F391F61157105F2 +:1017C00019F02830310590F381E02830310509F017 +:1017D00080E09091E8009E779093E8009F0161156A +:1017E000710549F68111C7CF06C08091ED018823AC +:1017F00051F0853051F08091E80082FFF6CF80E013 +:10180000089581E0089582E0089583E008956115C8 +:10181000710529F42091E8002B772093E8009C01C2 +:1018200021C08091ED01882381F1853041F18091C3 +:10183000E80083FD26C08091E80082FFF2CFF90125 +:1018400007C08091F10081939F016150710929F0D7 +:101850009F018091F2008111F4CF8091E8008B7795 +:101860008093E80061157105E1F68091E80080FD44 +:101870000AC08091ED01882341F08530B1F783E003 +:10188000089581E0089580E0089582E00895209110 +:10189000F4013091F5012617370748F061157105FD +:1018A00039F42091E8002E772093E80001C0B901B7 +:1018B0009C0180E035C09091ED01992309F444C06A +:1018C000953009F443C09091E80093FD3BC090919E +:1018D000E80092FD31C09091E80090FF21C0809116 +:1018E000F20090E0F901821B930B06C02491209333 +:1018F000F1003196615071099C012E0F3F1F611557 +:10190000710519F02830310588F381E02830310560 +:1019100009F080E09091E8009E779093E8009F01A5 +:101920006115710541F68111C6CF06C08091ED01A8 +:10193000882351F0853051F08091E80082FFF6CF86 +:1019400080E0089581E0089582E0089583E008959D +:10195000982F2CC09093E900981739F07091EC0003 +:101960002091ED005091F00003C0242F762F50E01D +:1019700021FD02C09F5F1AC03091EB003E7F309383 +:10198000EB003091ED003D7F3093ED003091EB00A6 +:1019900031603093EB007093EC002093ED00509396 +:1019A000F0002091EE0027FDE5CF07C0953090F2C2 +:1019B0008F708093E90081E0089580E008950F938F +:1019C0001F93CF93DF93062FEC0110E02EC0988178 +:1019D000911103C01F5F259628C02C81E981FA81EF +:1019E0006B81892F8F70853010F080E021C022300C +:1019F00010F056E001C052E028E030E040E003C0C3 +:101A00004F5F220F331F2E173F07D0F34295407FC1 +:101A1000452B991F9927991F6295660F660F607C69 +:101A2000692B96DF8111D6CFE0CF1013D0CF81E0A4 +:101A3000DF91CF911F910F9108958091EE0187FD65 +:101A400005C08091E80080FF0EC012C08091E800C0 +:101A500082FD05C08091ED018111F8CF089580913C +:101A6000E8008B7708C08091ED018111EACF0895DD +:101A70008091E8008E778093E80008958091E400DB +:101A80009091E50045E62091EC0020FD1FC023C0A9 +:101A90002091ED01222391F0253091F02091EB006F +:101AA00025FD10C02091E4003091E500281739078A +:101AB00051F34150C90139F784E0089582E0089557 +:101AC00083E0089581E0089580E008952091E80082 +:101AD00020FFDECFF9CF2091E80022FFD9CFF4CF4D +:101AE00041D043D08091D8008F778093D8008091E7 +:101AF000D80080688093D8008091D8008F7D809333 +:101B0000D80084E089BD86E089BD09B400FEFDCF20 +:101B10001092ED011092E9011092EB011092EA018E +:101B200042E060E080E014DF8091E1008E7F8093EE +:101B3000E1008091E20081608093E2008091E20008 +:101B400088608093E2008091E0008E7F8093E000C7 +:101B50000895E3E6F0E080818E7F808381E08093CA +:101B6000EC01BECF1092E20008951092E1000895BA +:101B70001F920F920FB60F9211242F933F934F9302 +:101B80005F936F937F938F939F93AF93BF93EF93E5 +:101B9000FF938091E10082FF0BC08091E20082FF01 +:101BA00007C08091E1008B7F8093E1000E94CF030A +:101BB0008091E10080FF18C08091E20080FF14C096 +:101BC0008091E2008E7F8093E2008091E20080614C +:101BD0008093E2008091D80080628093D80019BC85 +:101BE0001092ED010E9477038091E10084FF30C0E4 +:101BF0008091E20084FF2CC084E089BD86E089BD2D +:101C000009B400FEFDCF8091D8008F7D8093D8006D +:101C10008091E1008F7E8093E1008091E2008F7ED1 +:101C20008093E2008091E20081608093E2008091E5 +:101C3000E901882311F084E007C08091E30087FF69 +:101C400002C083E001C081E08093ED010E94760331 +:101C50008091E10083FF27C08091E20083FF23C0D1 +:101C60008091E100877F8093E10082E08093ED0125 +:101C70001092E9018091E1008E7F8093E1008091D4 +:101C8000E2008E7F8093E2008091E2008061809389 +:101C9000E20042E060E080E05BDE8091F00088607E +:101CA0008093F000B8D1FF91EF91BF91AF919F91D8 +:101CB0008F917F916F915F914F913F912F910F90F5 +:101CC0000FBE0F901F9018951F920F920FB60F9294 +:101CD00011242F933F934F935F936F937F938F9331 +:101CE0009F93AF93BF93CF93EF93FF938091E900BE +:101CF0008F709091EC0090FF02C090E801C090E0DE +:101D0000C92FC82B1092E9008091F000877F809343 +:101D1000F00078941CD01092E9008091F000886067 +:101D20008093F000CF70C093E900FF91EF91CF91C5 +:101D3000BF91AF919F918F917F916F915F914F91E3 +:101D40003F912F910F900FBE0F901F9018951F93EA +:101D5000CF93DF93CDB7DEB7AC970FB6F894DEBF65 +:101D60000FBECDBFEEEEF1E08091F100819321E056 +:101D7000E63FF207C9F70E94C7038091E80083FF9E +:101D800032C18091EE019091EF01953009F487C046 +:101D900038F49130B1F170F0933009F024C131C0C2 +:101DA000983009F4F4C0993009F400C1963009F074 +:101DB0001AC19BC0803821F0823809F014C108C0D4 +:101DC0008091EA019091EB01992389F082600FC024 +:101DD0008091F2019091F3018F7099278093E9002F +:101DE0008091EB0085FB882780F91092E9009091A3 +:101DF000E800977F9093E8008093F1001092F10043 +:101E0000D1C0882319F0823009F0EDC08F7121F024 +:101E1000823009F0E8C00BC08091F001813009F0F8 +:101E2000E2C0933009F080E08093EB012FC08091F5 +:101E3000F00181112BC08091F2019091F3018F701C +:101E40009927009709F4CFC08093E9002091EB0017 +:101E500020FF1CC02091EF01233021F48091EB0082 +:101E6000806212C09091EB0090619093EB0021E0B2 +:101E700030E001C0220F8A95EAF72093EA00109221 +:101E8000EA008091EB0088608093EB001092E900FB +:101E90008091E800877F8093E800CFDDA4C08111A6 +:101EA000A2C08091F0019091F1018F779927182FAE +:101EB0009091E3009078982B9093E3008091E80054 +:101EC000877F8093E800B9DD8091E80080FFFCCF38 +:101ED0008091E30080688093E300112311F083E098 +:101EE00001C082E08093ED017EC08058823008F00E +:101EF0007AC08091F0019091F1018C3D23E092072E +:101F000071F583E08A838AE289834FB7F894DE0112 +:101F1000139620E03EE051E2E32FF0E050935700AB +:101F2000E49120FF03C0E295EF703F5FEF708E2FCA +:101F300090E0EA3010F0C79601C0C0968D939D9353 +:101F40002F5F243149F74FBF8091E800877F80934E +:101F5000E8006AE270E0CE010196F9DB12C0AE0142 +:101F6000455D5F4F6091F2010E94DB030097D9F15C +:101F70002091E800277F2093E800BC018BA59CA559 +:101F800086DC8091E8008B778093E8002CC0803855 +:101F900051F58091E800877F8093E8008091E90106 +:101FA0008093F1008091E8008E7775CF81111BC07E +:101FB0009091F0019230B8F48091E800877F80938F +:101FC000E8009093E90139DD8091E901811104C0B5 +:101FD0008091E30087FF02C084E001C081E080932C +:101FE000ED010E9478038091E80083FF0AC0809190 +:101FF000E800877F8093E8008091EB008062809307 +:10200000EB00AC960FB6F894DEBF0FBECDBFDF91EC +:10201000CF911F9108950895CF938091ED0188236A +:10202000A9F08091E9008F709091EC0090FF02C0C0 +:1020300090E801C090E0C92FC82B1092E900809170 +:10204000E80083FD84DECF70C093E900CF9108954E +:10205000CF93DF93EC014096FC018BE0DF011D92F2 +:102060008A95E9F782E08C83898783E08E8761E037 +:10207000CE010196A4DC882361F061E0CE010696D2 +:102080009EDC882331F061E0CE010B96DF91CF9189 +:1020900096CC80E0DF91CF910895CF93C62F209109 +:1020A000ED012430F1F4FC01448955896689778972 +:1020B000452B462B472BA9F081818F708093E90037 +:1020C0008091E80085FF04C0C093F10080E00AC061 +:1020D0008091E8008E778093E800D0DC8823A1F31C +:1020E00001C082E0CF9108952091ED01243029F5BF +:1020F000FC014489558966897789452B462B472BF6 +:10210000E1F081818F708093E9008091F20081116C +:1021100002C080E008959091E8008091E8008E77F9 +:102120008093E80095FDF5CFA9DC811107C090915F +:10213000E8009E779093E800089582E0089520914A +:10214000ED01243089F4FC01448955896689778939 +:10215000452B462B472B41F021812F702093E9001E +:102160002091E80020FDC0CF08952091ED0124309A +:1021700019F02FEF3FEF24C0FC014489558966898F +:102180007789452B462B472BA1F386818F7080934F +:10219000E9008091E80082FFECCF8091F200882373 +:1021A00021F02091F10030E002C02FEF3FEF80914D +:1021B000F200811105C08091E8008B778093E800E0 +:1021C000C90108950895CF93DF93EC018091E80051 +:1021D00083FFA7C0888190E02091F2013091F30144 +:1021E0002817390709F09DC08091EF01813261F015 +:1021F00020F4803209F095C03DC0823209F46DC0F0 +:10220000833209F08EC07DC08091EE01813A09F0E1 +:1022100088C08091E800877F8093E8008091E80083 +:1022200080FFFCCF4C895D896E897F894093F100E6 +:10223000BB27A72F962F852F8093F100CB01AA27CC +:10224000BB278093F100472F5527662777274093B8 +:10225000F100888D8093F100898D8093F1008A8D43 +:102260008093F1008091E8008E778093E800DF9101 +:10227000CF91E3CB8091EE01813209F052C0809181 +:10228000E800877F8093E80005C08091ED018823F6 +:1022900009F447C08091E80082FFF7CF3091F10048 +:1022A0002091F1009091F1008091F1003C8B2D8BF9 +:1022B0009E8B8F8B8091F100888F8091F100898FA8 +:1022C0008091F1008A8F8091E8008B778093E800FD +:1022D000B4DBCE01DF91CF9163C98091EE018132F1 +:1022E00001F58091E800877F8093E800A6DB80916C +:1022F000F0019091F101998B888BCE01DF91CF9104 +:10230000C5C98091EE01813261F48091E800877F38 +:102310008093E80092DB6091F001CE01DF91CF91D4 +:1023200051CFDF91CF9108956F927F928F929F92BC +:10233000AF92BF92CF92DF92EF92FF920F931F93D3 +:10234000CF93DF9300D01F92CDB7DEB77C01ADB63F +:10235000BEB68091E80083FF07C1F701808190E05D +:102360002091F2013091F3012817390709F0FCC0E0 +:102370008091EF01833009F49EC030F4813071F018 +:10238000823009F0F1C0D4C08A3009F4B9C08B3072 +:1023900009F4A2C0893009F0E7C04CC08091EE0179 +:1023A000813A09F0E1C08DB69EB61A8219828091F9 +:1023B000F0011091F1018B83F70140858DB79EB735 +:1023C000841B91090FB6F8949EBF0FBE8DBFCDB68A +:1023D000DEB6EFEFCE1ADE0A360150E060E070E0C4 +:1023E000C601EAD1412F41508E010F5F1F4F960168 +:1023F000BE016D5F7F4FC7010E94EE04F701268189 +:1024000037812115310529F0408550E0B601C90119 +:10241000CAD11092E9008091E800877F8093E8009C +:1024200069817A81C30193D98091E8008B77809389 +:10243000E80039C08091EE01813209F095C08DB677 +:102440009EB60091F4011091F5017090F00160903A +:10245000F1018DB79EB7801B910B0FB6F8949EBF0C +:102460000FBE8DBFCDB6DEB6EFEFCE1ADE0A80917D +:10247000E800877F8093E800B801C601C8D9809141 +:10248000E8008E778093E80021E0711001C020E021 +:1024900030E0021B130B2C0D3D1D462D4150672DC6 +:1024A000C7010E946E04882D992D0FB6F8949EBF27 +:1024B0000FBE8DBF59C08091EE01813A09F054C022 +:1024C0008091E800877F8093E8008091E80080FF9A +:1024D000FCCFF701818540C08091EE01813209F087 +:1024E00043C08091E800877F8093E800A6DA90914E +:1024F000F00181E0911101C080E0F701818734C0D3 +:102500008091EE01813281F58091E800877F809390 +:10251000E80093DA8091F0019091F101882736E08C +:10252000969587953A95E1F7F701958784871CC0C2 +:102530008091EE01813AC1F48091E800877F809319 +:10254000E8008091E80080FFFCCFF7018485958545 +:1025500096958795969587958093F1008091E800F0 +:102560008E778093E80069DA0FB6F894BEBE0FBE8E +:10257000ADBE0F900F900F90DF91CF911F910F91F3 +:10258000FF90EF90DF90CF90BF90AF909F908F9093 +:102590007F906F9008959C01275F3F4FF90127E0DE +:1025A000DF011D922A95E9F721E0FC01218724EF44 +:1025B00031E03587248723E0248361E00196FFC959 +:1025C0004F925F926F927F928F929F92AF92BF9243 +:1025D000CF92DF92EF92FF920F931F93CF93DF93EF +:1025E00000D01F92CDB7DEB77C01ADB6BEB68091EC +:1025F000ED01843009F08FC08091E4009091E500F6 +:10260000F701228533852817390709F484C08181B1 +:102610008F708093E9008091E80085FF7CC06DB6E3 +:102620007EB640858DB79EB7841B91090FB6F8948E +:102630009EBF0FBE8DBFCDB6DEB6EFEFCE1ADE0A5F +:102640001B821A821982460150E060E070E0C601E8 +:10265000B3D08E010F5F1F4F960140E0BE016D5F4A +:102660007F4FC7010E94EE04582EF701848595859F +:10267000892B31F001E010E086859785892B11F0D8 +:1026800000E010E0F701C680D780C114D10489F0C2 +:1026900049815A81B601C40179D0442443940097FA +:1026A00009F4412CF701408550E0B401C6017BD00C +:1026B00001C0412C89819A81892BF9F0511004C005 +:1026C000411002C000FF19C0F701848595859787E6 +:1026D000868781818F708093E9008B81811180933F +:1026E000F10069817A8140E050E0C4010E945A0BF8 +:1026F0008091E8008E778093E8008091E4009091CB +:10270000E500F70193878287862D972D0FB6F89401 +:102710009EBF0FBE8DBF0FB6F894BEBE0FBEADBE3E +:102720000F900F900F90DF91CF911F910F91FF901D +:10273000EF90DF90CF90BF90AF909F908F907F9061 +:102740006F905F904F900895A1E21A2EAA1BBB1BB9 +:10275000FD010DC0AA1FBB1FEE1FFF1FA217B3076D +:10276000E407F50720F0A21BB30BE40BF50B661F83 +:10277000771F881F991F1A9469F760957095809547 +:1027800090959B01AC01BD01CF010895FB01DC01D7 +:1027900004C08D910190801921F441505040C8F738 +:1027A000881B990B0895FB01DC0102C001900D927A +:1027B00041505040D8F70895DC0101C06D9341505D +:0A27C0005040E0F70895F894FFCFB1 +:1027CA0002811000000100000F000000000000005C +:1027DA00008340000001044000000182080000015B +:1027EA00000000000000000000000004080F0801BB +:0E27FA000F0F0F0F000000000000030330203F +:00000001FF From 23430ae29ae0cec3aae843c344a3108e976f3b50 Mon Sep 17 00:00:00 2001 From: Nico Date: Fri, 21 Nov 2014 18:37:15 +0100 Subject: [PATCH 048/602] Starting from a clean 1.5.8 USB API --- plugins/KeyboardioHID/CDC.cpp | 211 ++++ .../KeyboardioHID/Firmwares/Hoodloader.inf | 71 -- plugins/KeyboardioHID/Firmwares/Readme.md | 7 - plugins/KeyboardioHID/Gamepad.h | 98 -- plugins/KeyboardioHID/HID.cpp | 991 ++++++++---------- plugins/KeyboardioHID/HID.h | 141 --- plugins/KeyboardioHID/HID_Reports.h | 208 ---- plugins/KeyboardioHID/Keyboard.cpp | 291 ----- plugins/KeyboardioHID/Keyboard.h | 151 --- plugins/KeyboardioHID/Media.h | 112 -- plugins/KeyboardioHID/Mouse.cpp | 95 -- plugins/KeyboardioHID/Mouse.h | 69 -- plugins/KeyboardioHID/RawHID.h | 78 -- plugins/KeyboardioHID/Readme.md | 330 ------ plugins/KeyboardioHID/System.h | 79 -- plugins/KeyboardioHID/USBAPI.h | 244 +++++ plugins/KeyboardioHID/USBCore.cpp | 699 ++++++++++++ plugins/KeyboardioHID/USBCore.h | 303 ++++++ plugins/KeyboardioHID/USBDesc.h | 63 ++ .../AdvancedGamepad/AdvancedGamepad.ino | 55 - .../AdvancedKeyboard/AdvancedKeyboard.ino | 99 -- .../AdvancedRawHID/AdvancedRawHID.ino | 114 -- .../examples/Gamepad/Gamepad.ino | 100 -- .../examples/Keyboard/Keyboard.ino | 88 -- .../KeyboardioHID/examples/Media/Media.ino | 65 -- .../KeyboardioHID/examples/Mouse/Mouse.ino | 52 - plugins/KeyboardioHID/examples/Readme.md | 4 - .../KeyboardioHID/examples/System/System.ino | 48 - .../KeyboardioHID/firmwares/Hoodloader1_8.hex | 642 ------------ plugins/KeyboardioHID/keywords.txt | 196 ---- plugins/KeyboardioHID/wiring_private.h | 71 ++ 31 files changed, 2016 insertions(+), 3759 deletions(-) create mode 100644 plugins/KeyboardioHID/CDC.cpp delete mode 100644 plugins/KeyboardioHID/Firmwares/Hoodloader.inf delete mode 100644 plugins/KeyboardioHID/Firmwares/Readme.md delete mode 100644 plugins/KeyboardioHID/Gamepad.h delete mode 100644 plugins/KeyboardioHID/HID.h delete mode 100644 plugins/KeyboardioHID/HID_Reports.h delete mode 100644 plugins/KeyboardioHID/Keyboard.cpp delete mode 100644 plugins/KeyboardioHID/Keyboard.h delete mode 100644 plugins/KeyboardioHID/Media.h delete mode 100644 plugins/KeyboardioHID/Mouse.cpp delete mode 100644 plugins/KeyboardioHID/Mouse.h delete mode 100644 plugins/KeyboardioHID/RawHID.h delete mode 100644 plugins/KeyboardioHID/Readme.md delete mode 100644 plugins/KeyboardioHID/System.h create mode 100644 plugins/KeyboardioHID/USBAPI.h create mode 100644 plugins/KeyboardioHID/USBCore.cpp create mode 100644 plugins/KeyboardioHID/USBCore.h create mode 100644 plugins/KeyboardioHID/USBDesc.h delete mode 100644 plugins/KeyboardioHID/examples/AdvancedGamepad/AdvancedGamepad.ino delete mode 100644 plugins/KeyboardioHID/examples/AdvancedKeyboard/AdvancedKeyboard.ino delete mode 100644 plugins/KeyboardioHID/examples/AdvancedRawHID/AdvancedRawHID.ino delete mode 100644 plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino delete mode 100644 plugins/KeyboardioHID/examples/Keyboard/Keyboard.ino delete mode 100644 plugins/KeyboardioHID/examples/Media/Media.ino delete mode 100644 plugins/KeyboardioHID/examples/Mouse/Mouse.ino delete mode 100644 plugins/KeyboardioHID/examples/Readme.md delete mode 100644 plugins/KeyboardioHID/examples/System/System.ino delete mode 100644 plugins/KeyboardioHID/firmwares/Hoodloader1_8.hex delete mode 100644 plugins/KeyboardioHID/keywords.txt create mode 100644 plugins/KeyboardioHID/wiring_private.h diff --git a/plugins/KeyboardioHID/CDC.cpp b/plugins/KeyboardioHID/CDC.cpp new file mode 100644 index 0000000000..5d4f2a0808 --- /dev/null +++ b/plugins/KeyboardioHID/CDC.cpp @@ -0,0 +1,211 @@ + + +/* 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 "USBAPI.h" +#include + +#if defined(USBCON) +#ifdef CDC_ENABLED + +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); + } + + if (CDC_SET_CONTROL_LINE_STATE == r) + { + _usbLineInfo.lineState = setup.wValueL; + } + + if (CDC_SET_LINE_CODING == r || CDC_SET_CONTROL_LINE_STATE == r) + { + // 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 + + // We check DTR state to determine if host port is open (bit 0 of lineState). + if (1200 == _usbLineInfo.dwDTERate && (_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; +} + + +void Serial_::begin(unsigned long /* baud_count */) +{ + peek_buffer = -1; +} + +void Serial_::begin(unsigned long /* baud_count */, byte /* config */) +{ + peek_buffer = -1; +} + +void Serial_::end(void) +{ +} + +int Serial_::available(void) +{ + if (peek_buffer >= 0) { + return 1 + USB_Available(CDC_RX); + } + return USB_Available(CDC_RX); +} + +int Serial_::peek(void) +{ + if (peek_buffer < 0) + peek_buffer = USB_Recv(CDC_RX); + return peek_buffer; +} + +int Serial_::read(void) +{ + if (peek_buffer >= 0) { + int c = peek_buffer; + peek_buffer = -1; + return c; + } + return USB_Recv(CDC_RX); +} + +void Serial_::flush(void) +{ + USB_Flush(CDC_TX); +} + +size_t Serial_::write(uint8_t c) +{ + return write(&c, 1); +} + +size_t Serial_::write(const uint8_t *buffer, size_t size) +{ + /* 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,buffer,size); + 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/plugins/KeyboardioHID/Firmwares/Hoodloader.inf b/plugins/KeyboardioHID/Firmwares/Hoodloader.inf deleted file mode 100644 index f2a05a317c..0000000000 --- a/plugins/KeyboardioHID/Firmwares/Hoodloader.inf +++ /dev/null @@ -1,71 +0,0 @@ -;************************************************************ -; Windows USB CDC ACM Setup File -; Copyright (c) 2000 Microsoft Corporation -;************************************************************ - -[DefaultInstall] -CopyINF="Hoodloader.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] -%hoodloader.name%=DriverInstall, USB\VID_03EB&PID_6E68&MI_00 -%hoodloader-lite.name%=DriverInstall, USB\VID_03EB&PID_4E48&MI_00 - -[DeviceList.NTx86] -%hoodloader.name%=DriverInstall, USB\VID_03EB&PID_6E68&MI_00 -%hoodloader-lite.name%=DriverInstall, USB\VID_03EB&PID_4E48&MI_00 - -[DeviceList.NTamd64] -%hoodloader.name%=DriverInstall, USB\VID_03EB&PID_6E68&MI_00 -%hoodloader-lite.name%=DriverInstall, USB\VID_03EB&PID_4E48&MI_00 - -[DeviceList.NTia64] -%hoodloader.name%=DriverInstall, USB\VID_03EB&PID_6E68&MI_00 -%hoodloader-lite.name%=DriverInstall, USB\VID_03EB&PID_4E48&MI_00 - -;------------------------------------------------------------------------------ -; String Definitions -;------------------------------------------------------------------------------ -;Modify these strings to customize your device -;------------------------------------------------------------------------------ -[Strings] -MFGNAME="NicoHood" -hoodloader.name="Arduino Hoodloader" -hoodloader-lite.name="Arduino Hoodloader-Lite" \ No newline at end of file diff --git a/plugins/KeyboardioHID/Firmwares/Readme.md b/plugins/KeyboardioHID/Firmwares/Readme.md deleted file mode 100644 index 2042bd5d1d..0000000000 --- a/plugins/KeyboardioHID/Firmwares/Readme.md +++ /dev/null @@ -1,7 +0,0 @@ -Firmwares -========= -[**See installing instructions on the Hoodloader repository**](https://github.com/NicoHood/Hoodloader) - -You can also get the latest Hoodloader version or the dev version from this repository (select dev branch). - -There are also other/older versions of the Hoodloader and the Lite Version for 8u2. The original firmware can also be found there. \ No newline at end of file diff --git a/plugins/KeyboardioHID/Gamepad.h b/plugins/KeyboardioHID/Gamepad.h deleted file mode 100644 index a6f994687c..0000000000 --- a/plugins/KeyboardioHID/Gamepad.h +++ /dev/null @@ -1,98 +0,0 @@ -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -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 GAMEPAD_H -#define GAMEPAD_H - -#include "HID.h" - -//================================================================================ -// HID -//================================================================================ - -void HID_SendReport(uint8_t id, const void* data, int len); - -//================================================================================ -// Gamepad -//================================================================================ - -#define GAMEPAD_DPAD_CENTERED 0 -#define GAMEPAD_DPAD_UP 1 -#define GAMEPAD_DPAD_UP_RIGHT 2 -#define GAMEPAD_DPAD_RIGHT 3 -#define GAMEPAD_DPAD_DOWN_RIGHT 4 -#define GAMEPAD_DPAD_DOWN 5 -#define GAMEPAD_DPAD_DOWN_LEFT 6 -#define GAMEPAD_DPAD_LEFT 7 -#define GAMEPAD_DPAD_UP_LEFT 8 - -class Gamepad{ -public: - inline Gamepad(uint8_t num){ - switch (num){ - case 1: - _reportID = HID_REPORTID_Gamepad1Report; - break; - case 2: - _reportID = HID_REPORTID_Gamepad2Report; - break; - case 3: - _reportID = HID_REPORTID_Gamepad3Report; - break; - case 4: - _reportID = HID_REPORTID_Gamepad4Report; - break; - default: - _reportID = HID_REPORTID_NotAReport; - break; - } - } - - inline void begin(void){ - memset(&_report, 0, sizeof(_report)); - HID_SendReport(_reportID, &_report, sizeof(_report)); - } - - inline void end(void){ begin(); } - inline void write(void){ HID_SendReport(_reportID, &_report, sizeof(_report)); } - inline void press(uint8_t b){ _report.buttons |= (uint32_t)1 << (b - 1); } - inline void release(uint8_t b){ _report.buttons &= ~((uint32_t)1 << (b - 1)); } - inline void releaseAll(void){ memset(&_report, 0x00, sizeof(_report)); } - - inline void buttons(uint32_t b){ _report.buttons = b; } - inline void xAxis(int16_t a){ _report.xAxis = a; } - inline void yAxis(int16_t a){ _report.yAxis = a; } - inline void zAxis(int8_t a){ _report.zAxis = a; } - inline void rxAxis(int16_t a){ _report.rxAxis = a; } - inline void ryAxis(int16_t a){ _report.ryAxis = a; } - inline void rzAxis(int8_t a){ _report.rzAxis = a; } - inline void dPad1(int8_t d){ _report.dPad1 = d; } - inline void dPad2(int8_t d){ _report.dPad2 = d; } -private: - HID_GamepadReport_Data_t _report; - uint8_t _reportID; -}; - -#endif - diff --git a/plugins/KeyboardioHID/HID.cpp b/plugins/KeyboardioHID/HID.cpp index 710581b857..75c37b24b2 100644 --- a/plugins/KeyboardioHID/HID.cpp +++ b/plugins/KeyboardioHID/HID.cpp @@ -1,595 +1,137 @@ -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -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 "HID.h" - -//================================================================================ -// Mouse -//================================================================================ - -Mouse_ Mouse; - -//================================================================================ -// Keyboard -//================================================================================ -Keyboard_ Keyboard; - -//================================================================================ -// RawHID -//================================================================================ - -RawHID_ RawHID; -//================================================================================ -// Media -//================================================================================ - -Media_ Media; - -//================================================================================ -// System -//================================================================================ - -System_ System; - -//================================================================================ -// HID Uno/Mega -//================================================================================ - -#ifndef USBCON - -void HID_SendReport(uint8_t id, const void* data, int len) -{ - // write the Report via Protocol and checksum. 16bit for each sending - // send control address - NHPwriteChecksum(NHP_ADDRESS_CONTROL, (NHP_USAGE_ARDUINOHID << 8) | id); - const uint8_t* report = (const uint8_t*)data; - for (int i = 0; i < len; i++){ - uint8_t data0 = report[i++]; - uint8_t data1 = 0; - if (i != len) - data1 = report[i]; - // valid HID reports start at Address 2 - NHPwriteChecksum(2 + i / 2, (data1 << 8) | data0); - } -#ifdef HID_EXTRADELAY - delay(HID_EXTRADELAY); -#endif -} - -// simple copy/modification of the NicoHoodProtocol writechecksum function -void NHPwriteChecksum(uint8_t address, uint16_t indata){ - // writes two bytes with its inverse - uint32_t temp = ~indata; - uint32_t data = (temp << 16) | indata; - - // buffer for write operation - uint8_t writebuffer[6]; - - // start with the maximum size of blocks - uint8_t blocks = 7; - - // check for the first 7 bit block that doesnt fit into the first 3 bits - while (blocks > 2){ - uint8_t nextvalue = (data >> (7 * (blocks - 3))); - - if (nextvalue > NHP_MASK_DATA_3BIT){ - // special case for the MSB - if (blocks == 7) { - writebuffer[0] = nextvalue; - blocks--; - } - // this block is too big, write this into the next data block - break; - } - else{ - // write the possible first 3 bits and check again after if zero - writebuffer[0] = nextvalue; - blocks--; - // we have our first bits, stop (nonzero) - if (nextvalue) - break; - } - } +/* 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. +*/ - // write the rest of the data bits - uint8_t datablocks = blocks - 2; - while (datablocks > 0){ - writebuffer[datablocks] = data & NHP_MASK_DATA_7BIT; - data >>= 7; - datablocks--; - } +#include "USBAPI.h" - // write lead + length mask - writebuffer[0] |= NHP_MASK_LEAD | (blocks << 3); +#if defined(USBCON) +#ifdef HID_ENABLED - // write end mask - writebuffer[blocks - 1] = NHP_MASK_END | ((address - 1) & NHP_MASK_ADDRESS); +//#define RAWHID_ENABLED - // write the buffer - HID_SERIAL.write(writebuffer, blocks); -} +// Singletons for mouse and keyboard -#else // #ifdef USBCON +Mouse_ Mouse; +Keyboard_ Keyboard; //================================================================================ -// HID Leonardo/Micro //================================================================================ -#include "Platform.h" -#include "USBAPI.h" -#include "USBDesc.h" - -#ifdef HID_ENABLED +// HID report descriptor -//================================================================================ -//================================================================================ +#define LSB(_x) ((_x) & 0xFF) +#define MSB(_x) ((_x) >> 8) -// HID report descriptor +#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[] = { - -#ifdef HID_MOUSE_ENABLE - // 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, HID_REPORTID_MouseReport,// REPORT_ID - // 5 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) - 0x95, 0x05, // REPORT_COUNT (5) - 0x75, 0x01, // REPORT_SIZE (1) - 0x81, 0x02, // INPUT (Data,Var,Abs) - // reserved - 0x95, 0x01, // REPORT_COUNT (1) - 0x75, 0x03, // REPORT_SIZE (3) - 0x81, 0x03, // INPUT (Cnst,Var,Abs) - // x, y, wheel - 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) - // end - 0xc0, // END_COLLECTION - 0xc0, // END_COLLECTION -#endif - -#ifdef HID_KEYBOARD_ENABLE - // Keyboard - 0x05, 0x01, // USAGE_PAGE (Generic Desktop) - 0x09, 0x06, // USAGE (Keyboard) - 0xa1, 0x01, // COLLECTION (Application) - 0x85, HID_REPORTID_KeyboardReport, // REPORT_ID - 0x05, 0x07, // USAGE_PAGE (Keyboard) - // modifiers + + // 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) + 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) - // reserved byte - 0x95, 0x01, // REPORT_COUNT (1) - 0x75, 0x08, // REPORT_SIZE (8) - 0x81, 0x03, // INPUT (Cnst,Var,Abs) - // Key[6] Array + 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) + 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) - // LEDs for num lock etc - //0x05, 0x08, /* USAGE_PAGE (LEDs) */ - //0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */ - //0x29, 0x05, /* USAGE_MAXIMUM (Kana) */ - //0x95, 0x05, /* REPORT_COUNT (5) */ - //0x75, 0x01, /* REPORT_SIZE (1) */ - //0x91, 0x02, /* OUTPUT (Data,Var,Abs) */ - // Reserved 3 bits - //0x95, 0x01, /* REPORT_COUNT (1) */ - //0x75, 0x03, /* REPORT_SIZE (3) */ - //0x91, 0x03, /* OUTPUT (Cnst,Var,Abs) */ - // end - 0xc0, // END_COLLECTION -#endif + 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application) + 0x81, 0x00, // INPUT (Data,Ary,Abs) + 0xc0, // END_COLLECTION -#ifdef HID_RAWKEYBOARD_ENABLE - // RAW HID +#ifdef 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, HID_REPORTID_RawKeyboardReport, // REPORT_ID - 0x75, 0x08, // report size = 8 bits - 0x15, 0x00, // logical minimum = 0 - 0x26, 0xFF, 0x00, // logical maximum = 255 + 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, RAWHID_TX_SIZE, // report count TX - 0x09, 0x01, // usage - 0x81, 0x02, // Input (array) + 0x95, 64, // report count TX + 0x09, 0x01, // usage + 0x81, 0x02, // Input (array) - 0x95, RAWHID_RX_SIZE, // report count RX - 0x09, 0x02, // usage - 0x91, 0x02, // Output (array) - 0xC0, // end collection -#endif - -#ifdef HID_MEDIA_ENABLE - // Media - 0x05, 0x0C, // usage page (consumer device) - 0x09, 0x01, // usage -- consumer control - 0xA1, 0x01, // collection (application) - 0x85, HID_REPORTID_MediaReport, // report id - //0x05, 0x0C, // usage page (consumer) - - // 4 media Keys - 0x15, 0x00, //logical minimum - 0x26, 0xFF, 0x03, //logical maximum (3ff) - 0x19, 0x00, // usage minimum (0) - 0x2A, 0xFF, 0x03, //usage maximum (3ff) - 0x95, 0x04, //report count (4) - 0x75, 0x10, //report size (16) - - 0x81, 0x00, //input - 0xC0, //end collection -#endif - -#ifdef HID_SYSTEM_ENABLE - // System - 0x05, 0x01, // USAGE_PAGE (Generic Desktop) - 0x09, 0x80, // USAGE (System Control) - 0xa1, 0x01, // COLLECTION (Application) - 0x85, HID_REPORTID_SystemReport, // REPORT_ID - // 1 system key - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255) - 0x19, 0x00, // USAGE_MINIMUM (Undefined) - 0x29, 0xff, // USAGE_MAXIMUM (System Menu Down) - 0x95, 0x01, // REPORT_COUNT (1) - 0x75, 0x08, // REPORT_SIZE (8) - 0x81, 0x00, // INPUT (Data,Ary,Abs) - 0xc0, // END_COLLECTION -#endif - -#ifdef HID_GAMEPAD1_ENABLE - // Gamepad1 - 0x05, 0x01, // USAGE_PAGE (Generic Desktop) - 0x09, 0x04, // USAGE (Joystick) - 0xa1, 0x01, // COLLECTION (Application) - 0x85, HID_REPORTID_Gamepad1Report, // REPORT_ID - // 32 Buttons - 0x05, 0x09, // USAGE_PAGE (Button) - 0x19, 0x01, // USAGE_MINIMUM (Button 1) - 0x29, 0x20, // USAGE_MAXIMUM (Button 32) - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x25, 0x01, // LOGICAL_MAXIMUM (1) - 0x75, 0x01, // REPORT_SIZE (1) - 0x95, 0x20, // REPORT_COUNT (32) - 0x81, 0x02, // INPUT (Data,Var,Abs) - // 4 16bit Axis - 0x05, 0x01, // USAGE_PAGE (Generic Desktop) - 0xa1, 0x00, // COLLECTION (Physical) - 0x09, 0x30, // USAGE (X) - 0x09, 0x31, // USAGE (Y) - 0x09, 0x33, // USAGE (Rx) - 0x09, 0x34, // USAGE (Ry) - 0x16, 0x00, 0x80, // LOGICAL_MINIMUM (-32768) - 0x26, 0xFF, 0x7F, // LOGICAL_MAXIMUM (32767) - 0x75, 0x10, // REPORT_SIZE (16) - 0x95, 0x04, // REPORT_COUNT (4) - 0x81, 0x02, // INPUT (Data,Var,Abs) - // 2 8bit Axis - 0x09, 0x32, // USAGE (Z) - 0x09, 0x35, // USAGE (Rz) - 0x15, 0x80, // LOGICAL_MINIMUM (-128) - 0x25, 0x7F, // LOGICAL_MAXIMUM (127) - 0x75, 0x08, // REPORT_SIZE (8) - 0x95, 0x02, // REPORT_COUNT (2) - 0x81, 0x02, // INPUT (Data,Var,Abs) - 0xc0, // END_COLLECTION - // 2 Hat Switches - 0x05, 0x01, // USAGE_PAGE (Generic Desktop) - 0x09, 0x39, // USAGE (Hat switch) - 0x09, 0x39, // USAGE (Hat switch) - 0x15, 0x01, // LOGICAL_MINIMUM (1) - 0x25, 0x08, // LOGICAL_MAXIMUM (8) - 0x95, 0x02, // REPORT_COUNT (2) - 0x75, 0x04, // REPORT_SIZE (4) - 0x81, 0x02, // INPUT (Data,Var,Abs) - // 8bit Throttle + Rudder - //0x05, 0x02, // USAGE_PAGE (Simulation Controls) - //0xa1, 0x00, // COLLECTION (Physical) - //0x15, 0x00, // LOGICAL_MINIMUM (0) - //0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255) - //0x09, 0xbb, // USAGE (Throttle) - //0x09, 0xba, // USAGE (Rudder) - //0x75, 0x08, // REPORT_SIZE (8) - //0x95, 0x02, // REPORT_COUNT (2) - //0x81, 0x02, // INPUT (Data,Var,Abs) - //0xc0, // END_COLLECTION - 0xc0, // END_COLLECTION -#endif - -#ifdef HID_GAMEPAD2_ENABLE - // Gamepad2 - 0x05, 0x01, // USAGE_PAGE (Generic Desktop) - 0x09, 0x04, // USAGE (Joystick) - 0xa1, 0x01, // COLLECTION (Application) - 0x85, HID_REPORTID_Gamepad2Report, // REPORT_ID - // 32 Buttons - 0x05, 0x09, // USAGE_PAGE (Button) - 0x19, 0x01, // USAGE_MINIMUM (Button 1) - 0x29, 0x20, // USAGE_MAXIMUM (Button 32) - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x25, 0x01, // LOGICAL_MAXIMUM (1) - 0x75, 0x01, // REPORT_SIZE (1) - 0x95, 0x20, // REPORT_COUNT (32) - 0x81, 0x02, // INPUT (Data,Var,Abs) - // 4 16bit Axis - 0x05, 0x01, // USAGE_PAGE (Generic Desktop) - 0xa1, 0x00, // COLLECTION (Physical) - 0x09, 0x30, // USAGE (X) - 0x09, 0x31, // USAGE (Y) - 0x09, 0x33, // USAGE (Rx) - 0x09, 0x34, // USAGE (Ry) - 0x16, 0x00, 0x80, // LOGICAL_MINIMUM (-32768) - 0x26, 0xFF, 0x7F, // LOGICAL_MAXIMUM (32767) - 0x75, 0x10, // REPORT_SIZE (16) - 0x95, 0x04, // REPORT_COUNT (4) - 0x81, 0x02, // INPUT (Data,Var,Abs) - // 2 8bit Axis - 0x09, 0x32, // USAGE (Z) - 0x09, 0x35, // USAGE (Rz) - 0x15, 0x80, // LOGICAL_MINIMUM (-128) - 0x25, 0x7F, // LOGICAL_MAXIMUM (127) - 0x75, 0x08, // REPORT_SIZE (8) - 0x95, 0x02, // REPORT_COUNT (2) - 0x81, 0x02, // INPUT (Data,Var,Abs) - 0xc0, // END_COLLECTION - // 2 Hat Switches - 0x09, 0x39, // USAGE (Hat switch) - 0x09, 0x39, // USAGE (Hat switch) - 0x15, 0x01, // LOGICAL_MINIMUM (1) - 0x25, 0x08, // LOGICAL_MAXIMUM (8) - 0x95, 0x02, // REPORT_COUNT (2) - 0x75, 0x04, // REPORT_SIZE (4) - 0x81, 0x02, // INPUT (Data,Var,Abs) - // 8bit Throttle + Rudder - //0x05, 0x02, // USAGE_PAGE (Simulation Controls) - //0xa1, 0x00, // COLLECTION (Physical) - //0x15, 0x00, // LOGICAL_MINIMUM (0) - //0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255) - //0x09, 0xbb, // USAGE (Throttle) - //0x09, 0xba, // USAGE (Rudder) - //0x75, 0x08, // REPORT_SIZE (8) - //0x95, 0x02, // REPORT_COUNT (2) - //0x81, 0x02, // INPUT (Data,Var,Abs) - //0xc0, // END_COLLECTION - 0xc0, // END_COLLECTION -#endif - -#ifdef HID_GAMEPAD3_ENABLE - // Gamepad3 - 0x05, 0x01, // USAGE_PAGE (Generic Desktop) - 0x09, 0x04, // USAGE (Joystick) - 0xa1, 0x01, // COLLECTION (Application) - 0x85, HID_REPORTID_Gamepad3Report, // REPORT_ID - // 32 Buttons - 0x05, 0x09, // USAGE_PAGE (Button) - 0x19, 0x01, // USAGE_MINIMUM (Button 1) - 0x29, 0x20, // USAGE_MAXIMUM (Button 32) - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x25, 0x01, // LOGICAL_MAXIMUM (1) - 0x75, 0x01, // REPORT_SIZE (1) - 0x95, 0x20, // REPORT_COUNT (32) - 0x81, 0x02, // INPUT (Data,Var,Abs) - // 4 16bit Axis - 0x05, 0x01, // USAGE_PAGE (Generic Desktop) - 0xa1, 0x00, // COLLECTION (Physical) - 0x09, 0x30, // USAGE (X) - 0x09, 0x31, // USAGE (Y) - 0x09, 0x33, // USAGE (Rx) - 0x09, 0x34, // USAGE (Ry) - 0x16, 0x00, 0x80, // LOGICAL_MINIMUM (-32768) - 0x26, 0xFF, 0x7F, // LOGICAL_MAXIMUM (32767) - 0x75, 0x10, // REPORT_SIZE (16) - 0x95, 0x04, // REPORT_COUNT (4) - 0x81, 0x02, // INPUT (Data,Var,Abs) - // 2 8bit Axis - 0x09, 0x32, // USAGE (Z) - 0x09, 0x35, // USAGE (Rz) - 0x15, 0x80, // LOGICAL_MINIMUM (-128) - 0x25, 0x7F, // LOGICAL_MAXIMUM (127) - 0x75, 0x08, // REPORT_SIZE (8) - 0x95, 0x02, // REPORT_COUNT (2) - 0x81, 0x02, // INPUT (Data,Var,Abs) - 0xc0, // END_COLLECTION - // 2 Hat Switches - 0x05, 0x01, // USAGE_PAGE (Generic Desktop) - 0x09, 0x39, // USAGE (Hat switch) - 0x09, 0x39, // USAGE (Hat switch) - 0x15, 0x01, // LOGICAL_MINIMUM (1) - 0x25, 0x08, // LOGICAL_MAXIMUM (8) - 0x95, 0x02, // REPORT_COUNT (2) - 0x75, 0x04, // REPORT_SIZE (4) - 0x81, 0x02, // INPUT (Data,Var,Abs) - // 8bit Throttle + Rudder - //0x05, 0x02, // USAGE_PAGE (Simulation Controls) - //0xa1, 0x00, // COLLECTION (Physical) - //0x15, 0x00, // LOGICAL_MINIMUM (0) - //0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255) - //0x09, 0xbb, // USAGE (Throttle) - //0x09, 0xba, // USAGE (Rudder) - //0x75, 0x08, // REPORT_SIZE (8) - //0x95, 0x02, // REPORT_COUNT (2) - //0x81, 0x02, // INPUT (Data,Var,Abs) - //0xc0, // END_COLLECTION - 0xc0, // END_COLLECTION -#endif - -#ifdef HID_GAMEPAD4_ENABLE - // Gamepad4 - 0x05, 0x01, // USAGE_PAGE (Generic Desktop) - 0x09, 0x04, // USAGE (Joystick) - 0xa1, 0x01, // COLLECTION (Application) - 0x85, HID_REPORTID_Gamepad4Report, // REPORT_ID - // 32 Buttons - 0x05, 0x09, // USAGE_PAGE (Button) - 0x19, 0x01, // USAGE_MINIMUM (Button 1) - 0x29, 0x20, // USAGE_MAXIMUM (Button 32) - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x25, 0x01, // LOGICAL_MAXIMUM (1) - 0x75, 0x01, // REPORT_SIZE (1) - 0x95, 0x20, // REPORT_COUNT (32) - 0x81, 0x02, // INPUT (Data,Var,Abs) - // 4 16bit Axis - 0x05, 0x01, // USAGE_PAGE (Generic Desktop) - 0xa1, 0x00, // COLLECTION (Physical) - 0x09, 0x30, // USAGE (X) - 0x09, 0x31, // USAGE (Y) - 0x09, 0x33, // USAGE (Rx) - 0x09, 0x34, // USAGE (Ry) - 0x16, 0x00, 0x80, // LOGICAL_MINIMUM (-32768) - 0x26, 0xFF, 0x7F, // LOGICAL_MAXIMUM (32767) - 0x75, 0x10, // REPORT_SIZE (16) - 0x95, 0x04, // REPORT_COUNT (4) - 0x81, 0x02, // INPUT (Data,Var,Abs) - // 2 8bit Axis - 0x09, 0x32, // USAGE (Z) - 0x09, 0x35, // USAGE (Rz) - 0x15, 0x80, // LOGICAL_MINIMUM (-128) - 0x25, 0x7F, // LOGICAL_MAXIMUM (127) - 0x75, 0x08, // REPORT_SIZE (8) - 0x95, 0x02, // REPORT_COUNT (2) - 0x81, 0x02, // INPUT (Data,Var,Abs) - 0xc0, // END_COLLECTION - // 2 Hat Switches - 0x05, 0x01, // USAGE_PAGE (Generic Desktop) - 0x09, 0x39, // USAGE (Hat switch) - 0x09, 0x39, // USAGE (Hat switch) - 0x15, 0x01, // LOGICAL_MINIMUM (1) - 0x25, 0x08, // LOGICAL_MAXIMUM (8) - 0x95, 0x02, // REPORT_COUNT (2) - 0x75, 0x04, // REPORT_SIZE (4) - 0x81, 0x02, // INPUT (Data,Var,Abs) - // 8bit Throttle + Rudder - //0x05, 0x02, // USAGE_PAGE (Simulation Controls) - //0xa1, 0x00, // COLLECTION (Physical) - //0x15, 0x00, // LOGICAL_MINIMUM (0) - //0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255) - //0x09, 0xbb, // USAGE (Throttle) - //0x09, 0xba, // USAGE (Rudder) - //0x75, 0x08, // REPORT_SIZE (8) - //0x95, 0x02, // REPORT_COUNT (2) - //0x81, 0x02, // INPUT (Data,Var,Abs) - //0xc0, // END_COLLECTION - 0xc0, // END_COLLECTION -#endif - -#ifdef HID_JOYSTICK1_ENABLE - // Joystick1 - 0x05, 0x01, // USAGE_PAGE (Generic Desktop) - 0x09, 0x04, // USAGE (Joystick) - 0xa1, 0x01, // COLLECTION (Application) - 0x85, HID_REPORTID_Joystick1Report, // REPORT_ID - 0xa1, 0x00, // COLLECTION (Physical) - 0x05, 0x09, // USAGE_PAGE (Button) - 0x19, 0x01, // USAGE_MINIMUM (Button 1) - 0x29, 0x02, // USAGE_MAXIMUM (Button 2) - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x25, 0x01, // LOGICAL_MAXIMUM (1) - 0x75, 0x01, // REPORT_SIZE (1) - 0x95, 0x02, // REPORT_COUNT (2) - 0x81, 0x02, // INPUT (Data,Var,Abs) - 0x05, 0x01, // USAGE_PAGE (Generic Desktop) - 0x09, 0x30, // USAGE (X) - 0x09, 0x31, // USAGE (Y) - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x26, 0xff, 0x03, // LOGICAL_MAXIMUM (1023) - 0x75, 0x0a, // REPORT_SIZE (10) - 0x95, 0x02, // REPORT_COUNT (2) - 0x81, 0x02, // INPUT (Data,Var,Abs) - 0x75, 0x02, // REPORT_SIZE (2) - 0x95, 0x01, // REPORT_COUNT (1) - 0x81, 0x03, // INPUT (Cnst,Var,Abs) - 0xc0, // END_COLLECTION - 0xc0, // END_COLLECTION -#endif - -#ifdef HID_JOYSTICK2_ENABLE - // Joystick2 - 0x05, 0x01, // USAGE_PAGE (Generic Desktop) - 0x09, 0x04, // USAGE (Joystick) - 0xa1, 0x01, // COLLECTION (Application) - 0x85, HID_REPORTID_Joystick2Report, // REPORT_ID - 0xa1, 0x00, // COLLECTION (Physical) - 0x05, 0x09, // USAGE_PAGE (Button) - 0x19, 0x01, // USAGE_MINIMUM (Button 1) - 0x29, 0x02, // USAGE_MAXIMUM (Button 2) - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x25, 0x01, // LOGICAL_MAXIMUM (1) - 0x75, 0x01, // REPORT_SIZE (1) - 0x95, 0x02, // REPORT_COUNT (2) - 0x81, 0x02, // INPUT (Data,Var,Abs) - 0x05, 0x01, // USAGE_PAGE (Generic Desktop) - 0x09, 0x30, // USAGE (X) - 0x09, 0x31, // USAGE (Y) - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x26, 0xff, 0x03, // LOGICAL_MAXIMUM (1023) - 0x75, 0x0a, // REPORT_SIZE (10) - 0x95, 0x02, // REPORT_COUNT (2) - 0x81, 0x02, // INPUT (Data,Var,Abs) - 0x75, 0x02, // REPORT_SIZE (2) - 0x95, 0x01, // REPORT_COUNT (1) - 0x81, 0x03, // INPUT (Cnst,Var,Abs) - 0xc0, // END_COLLECTION - 0xc0, // END_COLLECTION + 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_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) + D_ENDPOINT(USB_ENDPOINT_IN (HID_ENDPOINT_INT),USB_ENDPOINT_TYPE_INTERRUPT,0x40,0x01) }; //================================================================================ @@ -604,19 +146,18 @@ u8 _hid_idle = 1; int WEAK HID_GetInterface(u8* interfaceNum) { interfaceNum[0] += 1; // uses 1 - return USB_SendControl(TRANSFER_PGM, &_hidInterface, sizeof(_hidInterface)); + return USB_SendControl(TRANSFER_PGM,&_hidInterface,sizeof(_hidInterface)); } int WEAK HID_GetDescriptor(int /* i */) { - return USB_SendControl(TRANSFER_PGM, _hidReportDescriptor, sizeof(_hidReportDescriptor)); + 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); + USB_Send(HID_TX | TRANSFER_RELEASE,data,len); } bool WEAK HID_Setup(Setup& setup) @@ -636,7 +177,7 @@ bool WEAK HID_Setup(Setup& setup) return true; } } - + if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType) { if (HID_SET_PROTOCOL == r) @@ -654,6 +195,324 @@ bool WEAK HID_Setup(Setup& setup) return false; } -#endif // #ifdef HID_ENABLED +//================================================================================ +//================================================================================ +// 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 + 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 +#endif /* if defined(USBCON) */ diff --git a/plugins/KeyboardioHID/HID.h b/plugins/KeyboardioHID/HID.h deleted file mode 100644 index 6838f1cb20..0000000000 --- a/plugins/KeyboardioHID/HID.h +++ /dev/null @@ -1,141 +0,0 @@ -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -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 HID_H -#define HID_H - -#include - -// HID Resources -#include "HID_Reports.h" -#include "RawHID.h" -#include "Media.h" -#include "System.h" -#include "Gamepad.h" -#include "Keyboard.h" -#include "Mouse.h" - -//================================================================================ -//Settings -//================================================================================ - -// deactive unnecessary stuff for Leonardo/Micro -// reports needs to be <=255 bytes for leonardo/micro! -#define HID_MOUSE_ENABLE 54 -#define HID_KEYBOARD_ENABLE 65-18 //18 for missing led out report = 47 -//#define HID_RAWKEYBOARD_ENABLE 30 -#define HID_MEDIA_ENABLE 25 -#define HID_SYSTEM_ENABLE 24 -#define HID_GAMEPAD1_ENABLE 71 -//#define HID_GAMEPAD2_ENABLE 71 -//#define HID_GAMEPAD3_ENABLE 71 -//#define HID_GAMEPAD4_ENABLE 71 -//#define HID_JOYSTICK1_ENABLE 51 -//#define HID_JOYSTICK2_ENABLE 51 - -// extra delay for raspberry. Only needed for Hoodloader and slow devices -//#define HID_EXTRADELAY 20 - -//================================================================================ -// NHP -//================================================================================ - -// Start Mask -#define NHP_MASK_START 0xC0 //B11|000000 the two MSB bits -#define NHP_MASK_LEAD 0xC0 //B11|000000 -#define NHP_MASK_DATA 0x00 //B0|0000000 only the first MSB is important -#define NHP_MASK_END 0x80 //B10|000000 - -// Content Mask -#define NHP_MASK_LENGTH 0x38 //B00|111|000 -#define NHP_MASK_COMMAND 0x0F //B0000|1111 -#define NHP_MASK_DATA_7BIT 0x7F //B0|1111111 -#define NHP_MASK_DATA_4BIT 0x0F //B0000|1111 -#define NHP_MASK_DATA_3BIT 0x07 //B00000|111 -#define NHP_MASK_ADDRESS 0x3F //B00|111111 - -// Reserved Addresses -#define NHP_ADDRESS_CONTROL 0x01 - -// Reserved Usages -#define NHP_USAGE_ARDUINOHID 0x01 - -// Serial to write Protocol data to. Default: Serial -#define HID_SERIAL Serial -#define SERIAL_HID_BAUD 115200 - -void NHPwriteChecksum(uint8_t address, uint16_t indata); - -//================================================================================ -// Keyboard Definitions -//================================================================================ - -//Keyboard fixed/added missing Keys -#define KEY_PRINT 0xCE -#define KEY_SCROLL_LOCK 0xCF -#define KEY_PAUSE 0xD0 - -//Raw Keyboard definitions -#define RAW_KEYBOARD_LEFT_CTRL B00000001 -#define RAW_KEYBOARD_LEFT_SHIFT B00000010 -#define RAW_KEYBOARD_LEFT_ALT B00000100 -#define RAW_KEYBOARD_LEFT_GUI B00001000 -#define RAW_KEYBOARD_RIGHT_CTRL B00010000 -#define RAW_KEYBOARD_RIGHT_SHIFT B00100000 -#define RAW_KEYBOARD_RIGHT_ALT B01000000 -#define RAW_KEYBOARD_RIGHT_GUI B10000000 - -#define RAW_KEYBOARD_UP_ARROW 0x52 -#define RAW_KEYBOARD_DOWN_ARROW 0x51 -#define RAW_KEYBOARD_LEFT_ARROW 0x50 -#define RAW_KEYBOARD_RIGHT_ARROW 0x4F -#define RAW_KEYBOARD_SPACEBAR 0x2C -#define RAW_KEYBOARD_BACKSPACE 0x2A -#define RAW_KEYBOARD_TAB 0x2B -#define RAW_KEYBOARD_RETURN 0x28 -#define RAW_KEYBOARD_ESC 0x29 -#define RAW_KEYBOARD_INSERT 0x49 -#define RAW_KEYBOARD_DELETE 0x4C -#define RAW_KEYBOARD_PAGE_UP 0x4B -#define RAW_KEYBOARD_PAGE_DOWN 0x4E -#define RAW_KEYBOARD_HOME 0x4A -#define RAW_KEYBOARD_END 0x4D -#define RAW_KEYBOARD_CAPS_LOCK 0x39 -#define RAW_KEYBOARD_F1 0x3A -#define RAW_KEYBOARD_F2 0x3B -#define RAW_KEYBOARD_F3 0x3C -#define RAW_KEYBOARD_F4 0x3D -#define RAW_KEYBOARD_F5 0x3E -#define RAW_KEYBOARD_F6 0x3F -#define RAW_KEYBOARD_F7 0x40 -#define RAW_KEYBOARD_F8 0x41 -#define RAW_KEYBOARD_F9 0x42 -#define RAW_KEYBOARD_F10 0x43 -#define RAW_KEYBOARD_F11 0x44 -#define RAW_KEYBOARD_F12 0x45 -#define RAW_KEYBOARD_PRINT 0x46 -#define RAW_KEYBOARD_SCROLL_LOCK 0x47 -#define RAW_KEYBOARD_PAUSE 0x48 - -#endif - diff --git a/plugins/KeyboardioHID/HID_Reports.h b/plugins/KeyboardioHID/HID_Reports.h deleted file mode 100644 index 31ca5ad2e4..0000000000 --- a/plugins/KeyboardioHID/HID_Reports.h +++ /dev/null @@ -1,208 +0,0 @@ -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -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 HID_REPORTS_H -#define HID_REPORTS_H - -//================================================================================ -//Definitions -//================================================================================ - -#define LSB(_x) ((_x) & 0xFF) -#define MSB(_x) ((_x) >> 8) - -#define RAWHID_USAGE_PAGE 0xFFC0 // recommended: 0xFF00 to 0xFFFF -#define RAWHID_USAGE 0x0C00 // recommended: 0x0100 to 0xFFFF -#define RAWHID_TX_SIZE 15 // 1 byte for report ID -#define RAWHID_RX_SIZE 15 // 1 byte for report ID - -//================================================================================ -//Report Typedefinitions -//================================================================================ - -typedef union{ - // mouse report: 5 buttons, position, wheel - uint8_t whole8[4]; - uint16_t whole16[4/2]; - uint32_t whole32[4/4]; - - struct{ - uint8_t buttons:5; - uint8_t reserved:3; - int8_t xAxis; - int8_t yAxis; - int8_t wheel; - }; -} HID_MouseReport_Data_t; - - -typedef union{ - // Low level key report: up to 6 keys and shift, ctrl etc at once - uint8_t whole8[8]; - uint16_t whole16[8/2]; - uint32_t whole32[8/4]; - - struct{ - uint8_t modifiers; - uint8_t reserved; - uint8_t keys[6]; - }; -} HID_KeyboardReport_Data_t; - - -typedef union{ - // a 32 byte buffer for rx or tx - uint8_t whole8[RAWHID_TX_SIZE]; - uint16_t whole16[RAWHID_TX_SIZE / 2]; - uint32_t whole32[RAWHID_TX_SIZE / 4]; - uint8_t buff[RAWHID_TX_SIZE]; -} HID_RawKeyboardReport_Data_t; - - -typedef union{ - // every usable media key possible. Only one at the same time. - uint8_t whole8[8]; - uint16_t whole16[8/2]; - uint32_t whole32[8/4]; - - struct{ - uint16_t key1; - uint16_t key2; - uint16_t key3; - uint16_t key4; - }; -} HID_MediaReport_Data_t; - - -typedef union{ - // every usable system control key possible. Only one at the same time. - uint8_t whole8[1]; - uint8_t key; -} HID_SystemReport_Data_t; - - -typedef union { - // 32 Buttons, 6 Axis, 2 D-Pads - uint8_t whole8[15]; - uint16_t whole16[15/2]; - uint32_t whole32[15/4]; - uint32_t buttons; - - struct{ - uint8_t button1 :1; - uint8_t button2 :1; - uint8_t button3 :1; - uint8_t button4 :1; - uint8_t button5 :1; - uint8_t button6 :1; - uint8_t button7 :1; - uint8_t button8 :1; - - uint8_t button9 :1; - uint8_t button10 :1; - uint8_t button11 :1; - uint8_t button12 :1; - uint8_t button13 :1; - uint8_t button14 :1; - uint8_t button15 :1; - uint8_t button16 :1; - - uint8_t button17 :1; - uint8_t button18 :1; - uint8_t button19 :1; - uint8_t button20 :1; - uint8_t button21 :1; - uint8_t button22 :1; - uint8_t button23 :1; - uint8_t button24 :1; - - uint8_t button25 :1; - uint8_t button26 :1; - uint8_t button27 :1; - uint8_t button28 :1; - uint8_t button29 :1; - uint8_t button30 :1; - uint8_t button31 :1; - uint8_t button32 :1; - - int16_t xAxis; - int16_t yAxis; - - int16_t rxAxis; - int16_t ryAxis; - - int8_t zAxis; - int8_t rzAxis; - - uint8_t dPad1: 4; - uint8_t dPad2: 4; - }; -} HID_GamepadReport_Data_t; - - -typedef union{ - // 2 Buttons, 2 Axis - uint8_t whole8[3]; - uint16_t whole16[3/2]; - uint8_t buttons :2; - - struct{ - uint16_t button1 :1; - uint16_t button2 :1; - uint16_t xAxis :10; - uint16_t yAxis :10; - uint16_t reserved :2; - }; -} HID_JoystickReport_Data_t; - - -typedef union{ - HID_MouseReport_Data_t Mouse; - HID_KeyboardReport_Data_t Keyboard; - HID_RawKeyboardReport_Data_t RawKeyboard; - HID_MediaReport_Data_t Media; - HID_GamepadReport_Data_t Gamepad1; - HID_GamepadReport_Data_t Gamepad2; - HID_JoystickReport_Data_t Joystick1; - HID_JoystickReport_Data_t Joystick2; -} HID_HIDReport_Data_t; - - -/** Enum for the HID report IDs used in the device. */ -typedef enum{ - HID_REPORTID_NotAReport = 0x00, // first entry is always zero for multireports - HID_REPORTID_MouseReport = 0x01, /**< Report ID for the Mouse report within the device. */ - HID_REPORTID_KeyboardReport = 0x02, /**< Report ID for the Keyboard report within the device. */ - HID_REPORTID_RawKeyboardReport = 0x03, /**< Report ID for the Raw Keyboard report within the device. */ - HID_REPORTID_MediaReport = 0x04, /**< Report ID for the Media report within the device. */ - HID_REPORTID_SystemReport = 0x05, /**< Report ID for the Power report within the device. */ - HID_REPORTID_Gamepad1Report = 0x06, /**< Report ID for the Gamepad1 report within the device. */ - HID_REPORTID_Gamepad2Report = 0x07, /**< Report ID for the Gamepad2 report within the device. */ - HID_REPORTID_Gamepad3Report = 0x08, /**< Report ID for the Gamepad3 report within the device. */ - HID_REPORTID_Gamepad4Report = 0x09, /**< Report ID for the Gamepad4 report within the device. */ - HID_REPORTID_Joystick1Report = 0x10, /**< Report ID for the Joystick1 report within the device. */ - HID_REPORTID_Joystick2Report = 0x11, /**< Report ID for the Joystick2 report within the device. */ - HID_REPORTID_LastNotAReport, // determinate whats the maximum number of reports -1 -} HID_Report_IDs; - -#endif \ No newline at end of file diff --git a/plugins/KeyboardioHID/Keyboard.cpp b/plugins/KeyboardioHID/Keyboard.cpp deleted file mode 100644 index c9f77f9f4b..0000000000 --- a/plugins/KeyboardioHID/Keyboard.cpp +++ /dev/null @@ -1,291 +0,0 @@ -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -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 "Keyboard.h" - -#include "Platform.h" - -//================================================================================ -// Keyboard -//================================================================================ - -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 -}; - - -Keyboard_::Keyboard_(void) -{ -} - -void Keyboard_::begin(void) -{ -#ifndef USBCON - // release all buttons for Hoodloader - releaseAll(); -#endif -} - -void Keyboard_::end(void) -{ - // added here! - releaseAll(); -} - -void Keyboard_::sendReport(KeyReport* keys) -{ - HID_SendReport(HID_REPORTID_KeyboardReport, &_keyReport, sizeof(_keyReport)); -} - -// removed <-- -//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) -{ - // release all keys - memset(&_keyReport, 0x00, sizeof(_keyReport)); - sendReport(&_keyReport); -} - -size_t Keyboard_::write(uint8_t c) -{ - uint8_t p = press(c); // Keydown - release(c); // Keyup - return (p); // just return the result of press() since release() almost always returns 1 -} diff --git a/plugins/KeyboardioHID/Keyboard.h b/plugins/KeyboardioHID/Keyboard.h deleted file mode 100644 index 22724dda31..0000000000 --- a/plugins/KeyboardioHID/Keyboard.h +++ /dev/null @@ -1,151 +0,0 @@ -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -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 KEYBOARD_H -#define KEYBOARD_H - -#include "HID.h" - -//================================================================================ -// HID -//================================================================================ - -void HID_SendReport(uint8_t id, const void* data, int len); - -//================================================================================ -// Keyboard -//================================================================================ - -//Keyboard fixed/added missing Keys -#define KEY_PRINT 0xCE -#define KEY_SCROLL_LOCK 0xCF -#define KEY_PAUSE 0xD0 - -#ifndef USBCON - -#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 - -//Raw Keyboard definitions -#define RAW_KEYBOARD_LEFT_CTRL B00000001 -#define RAW_KEYBOARD_LEFT_SHIFT B00000010 -#define RAW_KEYBOARD_LEFT_ALT B00000100 -#define RAW_KEYBOARD_LEFT_GUI B00001000 -#define RAW_KEYBOARD_RIGHT_CTRL B00010000 -#define RAW_KEYBOARD_RIGHT_SHIFT B00100000 -#define RAW_KEYBOARD_RIGHT_ALT B01000000 -#define RAW_KEYBOARD_RIGHT_GUI B10000000 - -#define RAW_KEYBOARD_UP_ARROW 0x52 -#define RAW_KEYBOARD_DOWN_ARROW 0x51 -#define RAW_KEYBOARD_LEFT_ARROW 0x50 -#define RAW_KEYBOARD_RIGHT_ARROW 0x4F -#define RAW_KEYBOARD_SPACEBAR 0x2C -#define RAW_KEYBOARD_BACKSPACE 0x2A -#define RAW_KEYBOARD_TAB 0x2B -#define RAW_KEYBOARD_RETURN 0x28 -#define RAW_KEYBOARD_ESC 0x29 -#define RAW_KEYBOARD_INSERT 0x49 -#define RAW_KEYBOARD_DELETE 0x4C -#define RAW_KEYBOARD_PAGE_UP 0x4B -#define RAW_KEYBOARD_PAGE_DOWN 0x4E -#define RAW_KEYBOARD_HOME 0x4A -#define RAW_KEYBOARD_END 0x4D -#define RAW_KEYBOARD_CAPS_LOCK 0x39 -#define RAW_KEYBOARD_F1 0x3A -#define RAW_KEYBOARD_F2 0x3B -#define RAW_KEYBOARD_F3 0x3C -#define RAW_KEYBOARD_F4 0x3D -#define RAW_KEYBOARD_F5 0x3E -#define RAW_KEYBOARD_F6 0x3F -#define RAW_KEYBOARD_F7 0x40 -#define RAW_KEYBOARD_F8 0x41 -#define RAW_KEYBOARD_F9 0x42 -#define RAW_KEYBOARD_F10 0x43 -#define RAW_KEYBOARD_F11 0x44 -#define RAW_KEYBOARD_F12 0x45 -#define RAW_KEYBOARD_PRINT 0x46 -#define RAW_KEYBOARD_SCROLL_LOCK 0x47 -#define RAW_KEYBOARD_PAUSE 0x48 - -//Keyboard fixed/added missing Keys -#define KEY_PRINT 0xCE -#define KEY_SCROLL_LOCK 0xCF -#define KEY_PAUSE 0xD0 - -// typedef this report again because we cannot include the USBAPI -typedef HID_KeyboardReport_Data_t KeyReport; - -class Keyboard_ : public Print{ -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); -private: - KeyReport _keyReport; - void sendReport(KeyReport* keys); -}; -extern Keyboard_ Keyboard; - -#endif -#endif - diff --git a/plugins/KeyboardioHID/Media.h b/plugins/KeyboardioHID/Media.h deleted file mode 100644 index 090335862c..0000000000 --- a/plugins/KeyboardioHID/Media.h +++ /dev/null @@ -1,112 +0,0 @@ -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -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 MEDIA_H -#define MEDIA_H - -#include "HID.h" - -//================================================================================ -// HID -//================================================================================ - -void HID_SendReport(uint8_t id, const void* data, int len); - -//================================================================================ -// Media -//================================================================================ - -#define MEDIA_FAST_FORWARD 0xB3 -#define MEDIA_REWIND 0xB4 -#define MEDIA_NEXT 0xB5 -#define MEDIA_PREVIOUS 0xB6 -#define MEDIA_STOP 0xB7 -#define MEDIA_PLAY_PAUSE 0xCD - -#define MEDIA_VOLUME_MUTE 0xE2 -#define MEDIA_VOLUME_UP 0xE9 -#define MEDIA_VOLUME_DOWN 0xEA - -#define MEDIA_EMAIL_READER 0x18A -#define MEDIA_CALCULATOR 0x192 -#define MEDIA_EXPLORER 0x194 - -#define MEDIA_BROWSER_HOME 0x223 -#define MEDIA_BROWSER_BACK 0x224 -#define MEDIA_BROWSER_FORWARD 0x225 -#define MEDIA_BROWSER_REFRESH 0x227 -#define MEDIA_BROWSER_BOOKMARKS 0x22A - -class Media_{ -public: - inline Media_(void){ - // empty - } - - inline void begin(void){ - memset(&_report, 0, sizeof(_report)); - HID_SendReport(HID_REPORTID_MediaReport, &_report, sizeof(_report)); - } - - inline void end(void){ - begin(); - } - - inline void write(uint16_t m){ - press(m); - release(m); - } - - inline void press(uint16_t m){ - // search for a free spot - for (int i = 0; i < sizeof(HID_MediaReport_Data_t) / 2; i++) { - if (_report.whole16[i] == 0x00) { - _report.whole16[i] = m; - break; - } - } - HID_SendReport(HID_REPORTID_MediaReport, &_report, sizeof(_report)); - } - - inline void release(uint16_t m){ - // search and release the keypress - for (int i = 0; i < sizeof(HID_MediaReport_Data_t) / 2; i++) { - if (_report.whole16[i] == m) { - _report.whole16[i] = 0x00; - // no break to delete multiple keys - } - } - HID_SendReport(HID_REPORTID_MediaReport, &_report, sizeof(_report)); - } - - inline void releaseAll(void){ - begin(); - } -private: - HID_MediaReport_Data_t _report; -}; -extern Media_ Media; - -#endif - diff --git a/plugins/KeyboardioHID/Mouse.cpp b/plugins/KeyboardioHID/Mouse.cpp deleted file mode 100644 index 5a019856b2..0000000000 --- a/plugins/KeyboardioHID/Mouse.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -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 "Mouse.h" - -#include "Platform.h" - -//================================================================================ -//================================================================================ -// Mouse - -Mouse_::Mouse_(void) : -_buttons(0) -{ -} - -void Mouse_::begin(void) -{ -#ifndef USBCON - // release all buttons for Hoodloader - _buttons = 0; - move(0, 0, 0); -#endif -} - -void Mouse_::end(void) -{ - // added here! - _buttons = 0; - move(0, 0, 0); -} - -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; -} \ No newline at end of file diff --git a/plugins/KeyboardioHID/Mouse.h b/plugins/KeyboardioHID/Mouse.h deleted file mode 100644 index f2ee81bc1c..0000000000 --- a/plugins/KeyboardioHID/Mouse.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -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 MOUSE_H -#define MOUSE_H - -#include "HID.h" - -//================================================================================ -// HID -//================================================================================ - -void HID_SendReport(uint8_t id, const void* data, int len); - -//================================================================================ -// Mouse -//================================================================================ - -#ifndef USBCON - -#define MOUSE_LEFT 0x01 -#define MOUSE_RIGHT 0x02 -#define MOUSE_MIDDLE 0x04 -#define MOUSE_PREV 0x08 -#define MOUSE_NEXT 0x10 -#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE | MOUSE_PREV | MOUSE_NEXT) - -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; -#endif - - -#endif - diff --git a/plugins/KeyboardioHID/RawHID.h b/plugins/KeyboardioHID/RawHID.h deleted file mode 100644 index c4da346eb9..0000000000 --- a/plugins/KeyboardioHID/RawHID.h +++ /dev/null @@ -1,78 +0,0 @@ -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -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 DEFAULT_H -#define DEFAULT_H - -#include "HID.h" - -//================================================================================ -// HID -//================================================================================ - -void HID_SendReport(uint8_t id, const void* data, int len); - -//================================================================================ -// RawHID -//================================================================================ - -class RawHID_ : public Print{ -public: - inline RawHID_(void){ - // empty - } - - inline void begin(void){ - // empty - } - - inline void end(void){ - // empty - } - - using Print::write; // to get the String version of write - inline size_t write(uint8_t b){ - write(&b, 1); - } - - inline size_t write(const uint8_t *buffer, size_t size){ - size_t bytesleft = size; - // first work through the buffer thats already there - while (bytesleft >= RAWHID_RX_SIZE){ - HID_SendReport(HID_REPORTID_RawKeyboardReport, &buffer[size - bytesleft], RAWHID_RX_SIZE); - bytesleft -= RAWHID_RX_SIZE; - } - // write down the other bytes and fill with zeros - if (bytesleft){ - uint8_t rest[RAWHID_RX_SIZE]; - memcpy(rest, &buffer[size - bytesleft], bytesleft); - memset(&rest[bytesleft], 0, RAWHID_RX_SIZE - bytesleft); - HID_SendReport(HID_REPORTID_RawKeyboardReport, &rest, RAWHID_RX_SIZE); - } - } -}; -extern RawHID_ RawHID; - -#endif - diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md deleted file mode 100644 index 99adc9515d..0000000000 --- a/plugins/KeyboardioHID/Readme.md +++ /dev/null @@ -1,330 +0,0 @@ -Arduino HID Project -=================== -Dont you always wanted to turn your Arduino in a Generic HID device like a Keyboard or a Gamepad? -Disappointed that the Uno doesnt support this at all and the Micro/Leonardo only Mouse + Keyboard? - -Introducing the Arduino HID Project that **enables enhanced USB functionality to Arduino Uno, Mega, Leonardo, Micro.** -No need for extra hardware. You just need one of the Arduinos and an USB cable. - -**Main difference is that you can upload new sketches to the Uno/Mega and dont need to reflash the firmware over and over again.** -Before you had to upload a sketch, flash the firmware, test, flash the firmware, upload, flash again. Thats all gone! - -**For the Leonardo/Micro it is 'just' new HID devices, no need for a bootloader (like on Uno/Mega).** - -Note: [Hoodloader Repository moved here.](https://github.com/NicoHood/Hoodloader) - -Features -======== -Use your **Arduino Uno, Mega, Micro, Leonardo or (Pro)Micro** as Generic HID Device and still be able to upload sketches how you are used to do. -This project provides HID libraries for Arduino Uno/Mega (with a new 16u2 bootloader) and Micro/Leonardo. -I also corrected some bugs in the original sources. - -**Software includes:** - -* Arduino HID Uno/Mega library -* Arduino HID Micro/Leonardo library -* Arduino HID Bootloader (Hoodloader) + driver for Uno/Mega -* Arduino as ISP with the 16u2 (Hoodloader only, [more information](https://github.com/NicoHood/Hoodloader)) -* Compatible with Linux/Mac/Windows XP/7/8.1 -* Compatible with IDE 1.0.x - 1.5.7 - -**The following devices are supported:** - -* Keyboard (modifiers + 6 keys pressed at the same time) -* Mouse (5 buttons, move, wheel) -* Media Keys (4 keys for music player, webbrowser and more) -* System Key (for PC standby/shutdown) -* 4 Gamepads (32 buttons, 4 16bit axis, 2 8bit axis, 2 D-Pads) - -**Projects can be found here:** -* [Gamecube to PC adapter](https://github.com/NicoHood/Nintendo) -* [Other projects](http://nicohood.wordpress.com/) - -Version differences -=================== - -| Arduino Uno/Mega | Arduino Leonardo/(Pro)Micro | -|:---------------------------------------|:-----------------------------------| -| HID via Hoodloader on 16u2 | Uses USB core with main MCU (32u4) | -| Serial0 without HID fully usable | Serial0 fully usable | -| Serial0 with HID at baud 115200 only | Serial0 slow + buggy | -| Serial0 with HID fully usable via USB | | -| Serial0 with HID not usable via extern | | -| Uses less flash (Serial Protocol only) | Uses more flash (full USB core) | -| ISP function | No ISP function | - -Over all the Uno/Mega solution gives you more opportunities except that the Serial0 is limited when you use HID. - -Installation Leonardo/Micro/Uno/Mega -==================================== - -#### Leonardo/Micro only -Download the library and [install it](http://arduino.cc/en/pmwiki.php?n=Guide/Libraries) like you are used to. - -**For the whole Project IDE 1.5.7 or higher is recommended!** - -**Edit HID.h to de/activate usb functions.** -By default Mouse, Keyboard, Media, System, Gamepad1 is activated. - -Each function will take some flash, -so if you want to save flash deactivate everything you dont need. -You cannot use more than 255 bytes HID report on the Leonardo/Micro. -The number after each definition tells you the size of each report. -I have no idea why you cannot use more than 255 bytes (yet), its a bug in the Arduino code. - -#### Uno/Mega onl -Download the library and [install it](http://arduino.cc/en/pmwiki.php?n=Guide/Libraries) like you are used to. - -**For the whole Project IDE 1.5.7 or higher is recommended!** - -To install the new bootloader connect your Arduino to your PC via USB and see -[Hoodloader installing instructions](https://github.com/NicoHood/Hoodloader). -No special programmer needed, just an USB cable. -**You can always switch back to the original firmware, nothing to break.** - -Edit HID.h to add an extra delay for raspberry pi. This is a workaround to fix this for slower PCs. There is still a problem with Raspberry. - -Usage -===== -You are ready to use the libraries. **Just have a look at the examples and test it out.** They are pretty much self explaining. -All examples use a button on pin 8 and show the basic usage of the libraries. -The libraries will work for all Arduinos listed above but it will use 2 different HID libraries (automatically). -For Keyboard + Mouse usage also see the [official documentation](http://arduino.cc/en/pmwiki.php?n=Reference/MouseKeyboard). - -**#include is now needed for every device.** - -**On Arduino/Mega you can only use baud 115200 for HID** due to speed/programming reasons. -Use Serial.begin(SERIAL_HID_BAUD); as typedef to start Serial at baud 115200. -Its not bad anyway because its the fastest baud and you want fast HID recognition. -You still can **fully use any other baud** for normal sketches but HID wont work. -If you try nevertheless it will output Serial crap to the monitor. - -**Always release buttons to not cause any erros.** Replug USB cable to reset the values if anything went wrong. -On Windows every USB report will reset when you open the lock screen. -See [deactivate HID function (Hoodloader only)](https://github.com/NicoHood/Hoodloader) how to disable HID again. - -For Arduino as ISP usage (optional, Hoodloader only, has nothing to do with HID function) -see [Hoodloader repository](https://github.com/NicoHood/Hoodloader). - -Updating to a newer Version -=========================== -HID library: - -To upgrade to v1.8 you need to redownload the Arduino IDE files, restore the original files and install the library like you are used to. -You library is now located in sketchbook/libraries/HID/ -Its now way easier to install the library, no need to replace system files. For further releases just replace all files again. - -**Restart the IDE** - -Hoodloader (Not needed for Leonardo/Micro): - -Just upload the new hex file and check the HID Project if the HID library code has changed and replace the new files too. -You normally dont need to reinstall the drivers for windows if the changelog dosnt note anything. -Versions below 1.5 might need the new drivers. - -How it works -============ -For the Leonardo/Micro its just a modified version of the HID descriptor and Classes for the new devices. -Its not that complicated, everything you need is in the main 4 .h/cpp files. - -For the Uno/Mega you need a special Bootloader. Why? See [Hoodloader repository](https://github.com/NicoHood/Hoodloader). -To sum it up: Serial information is grabbed by the "man in the middle, 16u2" and you dont have to worry to get any wrong Serial stuff via USB. -Thatswhy you need a special baud (115200) that both sides can communicate with each other. -Every USB command is send via a special [NicoHood Protocol](https://github.com/NicoHood/NicoHoodProtocol) -that's filtered out by the 16u2. If you use Serial0 for extern devices it cannot filter the signal of course. -You can still use the NHP, just dont use the reserved Address 1. - -This project wouldnt be possible without -======================================== - -* [Lufa 140302 from Dean Camera](http://www.fourwalledcubicle.com/LUFA.php) -* [Darran's HID Projects] (https://github.com/harlequin-tech/arduino-usb) -* [Connor's Joystick for the Leonardo](http://www.imaginaryindustries.com/blog/?p=80) -* [Stefan Jones Multimedia Keys Example](http://stefanjones.ca/blog/arduino-leonardo-remote-multimedia-keys/) -* [Athanasios Douitsis Multimedia Keys Example](https://github.com/aduitsis/ardumultimedia) -* [The Original Arduino Sources](https://github.com/arduino/Arduino/tree/master/hardware/arduino/firmwares/atmegaxxu2/arduino-usbserial) -* [USBlyzer](http://www.usblyzer.com/) -* A lot of searching through the web -* The awesome official Arduino IRC chat! -* [The NicoHood Protocol ^.^](https://github.com/NicoHood/NicoHoodProtocol) -* For donations please contact me on my blog :) - -Ideas for the future -==================== -* Add more devices (even more?) -* Add Midi (no more free Endpoints, possible on 32u4) -* Add HID rumble support (very hard) -* Add Xbox Support (too hard) -* Add Report Out function (for Keyboard Leds etc) - -Known Bugs -========== -See [Hoodloader repository](https://github.com/NicoHood/Hoodloader) for Hoodloader related Bugs/Issues. - -System Wakeup is currently not working on all versions! -System Shutdown is only working on Windows systems. - -RawHID only works on Uno/Mega. It still has some bugs. - -Feel free to open an Issue on Github if you find a bug. Or message me via my [blog](http://nicohood.wordpress.com/)! - -Known Issues -============ - -**Do not name your sketch HID.ino, this wont work!** - -Opening the examples with doubleclick doesnt work, starting from IDE does. - -**Do not use HID in interrupts because it uses Serial (Hoodloader only). Your Arduino can crash!** - -**If you get a checksum error after uploading please message me and send me the whole project.** -Same if your Arduino crashes and dont want to upload sketches anymore (Replug usb fixes this). -These bugs occurred while developing the bootloader and should be fixed. Just in case it happens again I noted it here. -USB can behave weird, so please check your code for errors first. If you cannot find a mistake open a Github issue. - -**If You have weird Problems especially with controllers, let me know.** -Sometimes the problem is just that Windows messes up the PID so you might want to compile the hoodloader with a different PID -or reinstall the drivers. - -XBMC 13.1 (a Media Center) uses Gamepad input. Its seems to not work and may cause weird errors. -Even with a standard Gamepad I have these errors. Just want to mention it here. - -Not tested on the 8u2, lite version should work with flashing via ISP. - -Not tested on the Due (message me if it works!) - -The USB implementation of the Leonardo/Micro is not that good it can cause errors or disconnects with massiv Serial input. -This has nothing to do with this library! For example Adalight dosnt work well for me, -so you better use an Arduino Uno with Hoodloader for Mediacenter control and Ambilight. - -Version History -=============== -``` -1.8 Beta Release (26.08.2014) -* Changes in the Hoodloader: - * **Huge improvements**, see [Hoodloader repository](https://github.com/NicoHood/Hoodloader) - * Reworked the whole library, easy installation now - * HID fixes for Media Keys/Ubuntu - * Removed Joystick, added 4 Gamepads - -1.7.3 Beta Release (10.08.2014) -* Changes in the Hoodloader: - * Fixed HID flush bug (1.6 - 1.7.2) - -1.7.2 Beta Release (10.08.2014) -* Changes in the Hoodloader: - * Added Lite version for 8u2 - * Added Versions that show up as Uno/Mega (not recommended) - * Makefile and structure changes - -1.7.1 Beta Release (10.08.2014) -* Changes in the Hoodloader: - * Fixed HID deactivation bug - -1.7 Beta Release (10.08.2014) -* Changes in the Hoodloader: - * Works as ISP now. See the [Hoodloader Repository](https://github.com/NicoHood/Hoodloader) for more information. - * Exceeded 8kb limit. For flashing a 8u2 use v1.6 please! -* Changed Readme text - -1.6 Beta Release (09.08.2014) -* Bugfixes in the Hoodloader: - * Changed HID management (not blocking that much, faster) - * added RawHID in/out (HID to Serial) -* Added RawHID Class and example - -1.5 Beta Release (21.07.2014) -* Moved Hoodloader source to a [separate Github page](https://github.com/NicoHood/Hoodloader) -* Bugfixes in the Hoodloader: - * Firmware is still available here - * Overall a lot of ram improvements, now with a big global union of ram - * Removed USBtoUSART buffer (not needed, saved 128/500 bytes) - * Removed Lite version because of better ram usage not needed - * Separated different modes better to not cause any errors in default mode - * Improved the deactivate option - * Integrated NHP directly - * Replaced LightweightRingbuffer with native Lufa Ringbuffer - * Improved writing to CDC Host - * Fixed a bug in checkNHPProtocol: & needs to be a == - * General structure changes - * Improved stability - * Fixed Arduino as ISP bug - -1.4.1 Beta Release (10.07.2014) -* #define Bugfix in USBAPI.h - -1.4 Beta Release (10.07.2014) -* Bugfixes in the Hoodloader: - * Added Lite Version with less ram usage - * Changed PIDs, edited driver file -* merged v1.0.x and v1.5.x together (both are compatible!) -* added IDE v1.5.7 support -* added Tutorials - -1.3 Beta Release (01.07.2014) -* Bugfixes in the Hoodloader: - * Improved ram usage (you can get even better but that messes up code and increases flash) -* **Important NHP fix inside the HID Class for Uno/Mega** - -1.2 Beta Release (22.06.2014) -* Added 1.0.x/1.5.x support -* Bugfixes in the Hoodloader: - * Sometimes HID Devices weren't updating when using more than 1 Device (set forcewrite to true) - * Fast updates crashed the bootloader (too much ram usage, set CDC buffer from 128b to 100b each) -* Minor file structure changes - -1.1 Beta Release (05.06.2014) -* Added Leonardo/Micro support -* Included NicoHoodProtocol -* Minor fixes - -1.0 Beta Release (03.06.2014) -``` - -Licence and Copyright -===================== -If you use this library for any cool project let me know! - -``` -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -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. -``` - -For Developers -============== -If you deactivate some reports it can occur that windows will cause problems and recognize it as different device. -While developing I had that much trouble that I had to change the PID. No way to repair the broken windows driver settings. -So be careful if you change the source on your own with important PIDs. (Therefore I made a 2nd Lite Version with a different PID and more ram) -Therefore reinstall the divers for any device or just dont touch the HID reports in the Bootloader. -The Leonardo/Micro version worked fine till now. - -See this how to uninstall the drivers: -https://support.microsoft.com/kb/315539 - -The Hootloader was coded with Windows7 and Visual Studio and compiled with a Raspberry Pi. -Lufa version 140302 is included! -**To recompile see instructions in [Hoodloader Repository](https://github.com/NicoHood/Hoodloader).** - -The difference between the Leonardo/Micro and Uno/Mega is that the HID Class is different. All other classes are the same. -The Leonardo/Micro Version uses USBAPI.h and no Serial while the Uno/Mega Version uses Serial. -You can also modify the library to send HID reports to other devices/other serials. -Just modify the HID Class (#define HID_SERIAL Serial). - diff --git a/plugins/KeyboardioHID/System.h b/plugins/KeyboardioHID/System.h deleted file mode 100644 index f0501a5dc0..0000000000 --- a/plugins/KeyboardioHID/System.h +++ /dev/null @@ -1,79 +0,0 @@ -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -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 SYSTEM_H -#define SYSTEM_H - -#include "HID.h" - -//================================================================================ -// HID -//================================================================================ - -void HID_SendReport(uint8_t id, const void* data, int len); - -//================================================================================ -// System -//================================================================================ - -#define SYSTEM_POWER_DOWN 0x81 -#define SYSTEM_SLEEP 0x82 -#define SYSTEM_WAKE_UP 0x83 - -class System_{ -public: - inline System_(void){ - // empty - } - - inline void begin(void){ - uint8_t _report = 0; - HID_SendReport(HID_REPORTID_SystemReport, &_report, sizeof(_report)); - } - - inline void end(void){ - begin(); - } - - inline void write(uint8_t s){ - press(s); - release(); - } - - inline void press(uint8_t s){ - HID_SendReport(HID_REPORTID_SystemReport, &s, sizeof(s)); - } - - inline void release(void){ - begin(); - } - - inline void releaseAll(void){ - begin(); - } -}; -extern System_ System; - -#endif - diff --git a/plugins/KeyboardioHID/USBAPI.h b/plugins/KeyboardioHID/USBAPI.h new file mode 100644 index 0000000000..2fab957f93 --- /dev/null +++ b/plugins/KeyboardioHID/USBAPI.h @@ -0,0 +1,244 @@ +/* + USBAPI.h + Copyright (c) 2005-2014 Arduino. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef __USBAPI__ +#define __USBAPI__ + +#include +#include +#include +#include +#include + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned long u32; + +#include "Arduino.h" + +#if defined(USBCON) + +#include "USBDesc.h" +#include "USBCore.h" + +//================================================================================ +//================================================================================ +// 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) + +struct ring_buffer; + +#if (RAMEND < 1000) +#define SERIAL_BUFFER_SIZE 16 +#else +#define SERIAL_BUFFER_SIZE 64 +#endif + +class Serial_ : public Stream +{ +private: + int peek_buffer; +public: + Serial_() { peek_buffer = -1; }; + void begin(unsigned long); + void begin(unsigned long, uint8_t); + void end(void); + + virtual int available(void); + virtual int peek(void); + virtual int read(void); + virtual void flush(void); + virtual size_t write(uint8_t); + virtual size_t write(const uint8_t*, size_t); + using Print::write; // pull in write(str) and write(buf, size) from Print + operator bool(); + + volatile uint8_t _rx_buffer_head; + volatile uint8_t _rx_buffer_tail; + unsigned char _rx_buffer[SERIAL_BUFFER_SIZE]; +}; +extern Serial_ Serial; + +#define HAVE_CDCSERIAL + +//================================================================================ +//================================================================================ +// 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) */ diff --git a/plugins/KeyboardioHID/USBCore.cpp b/plugins/KeyboardioHID/USBCore.cpp new file mode 100644 index 0000000000..b4f7bed7e8 --- /dev/null +++ b/plugins/KeyboardioHID/USBCore.cpp @@ -0,0 +1,699 @@ + + +/* 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 "USBAPI.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 u8 STRING_PRODUCT[] PROGMEM; +extern const u8 STRING_MANUFACTURER[] PROGMEM; +extern const DeviceDescriptor USB_DeviceDescriptor PROGMEM; +extern const DeviceDescriptor USB_DeviceDescriptorA PROGMEM; + +const u16 STRING_LANGUAGE[2] = { + (3<<8) | (2+2), + 0x0409 // English +}; + +#ifndef USB_PRODUCT +// If no product is provided, use USB IO Board +#define USB_PRODUCT "USB IO Board" +#endif + +const u8 STRING_PRODUCT[] PROGMEM = USB_PRODUCT; + +#if USB_VID == 0x2341 +# if defined(USB_MANUFACTURER) +# undef USB_MANUFACTURER +# endif +# define USB_MANUFACTURER "Arduino LLC" +#elif USB_VID == 0x1b4f +# if defined(USB_MANUFACTURER) +# undef USB_MANUFACTURER +# endif +# define USB_MANUFACTURER "SparkFun" +#elif !defined(USB_MANUFACTURER) +// Fall through to unknown if no manufacturer name was provided in a macro +# define USB_MANUFACTURER "Unknown" +#endif + +const u8 STRING_MANUFACTURER[] PROGMEM = USB_MANUFACTURER; + + +#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< len) + n = len; + { + LockEP lock(ep); + // Frame may have been released by the SOF interrupt handler + if (!ReadWriteAllowed()) + continue; + len -= n; + 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; +} + +// Send a USB descriptor string. The string is stored in PROGMEM as a +// plain ASCII string but is sent out as UTF-16 with the correct 2-byte +// prefix +static bool USB_SendStringDescriptor(const u8*string_P, u8 string_len) { + SendControl(2 + string_len * 2); + SendControl(3); + for(u8 i = 0; i < string_len; i++) { + bool r = SendControl(pgm_read_byte(&string_P[i])); + r &= SendControl(0); // high byte + if(!r) { + return false; + } + } + return true; +} + +// 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 + + 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) { + return USB_SendStringDescriptor(STRING_PRODUCT, strlen(USB_PRODUCT)); + } + else if (setup.wValueL == IMANUFACTURER) { + return USB_SendStringDescriptor(STRING_MANUFACTURER, strlen(USB_MANUFACTURER)); + } + else + return false; + } + + if (desc_addr == 0) + return false; + u8 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<> 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/plugins/KeyboardioHID/USBDesc.h b/plugins/KeyboardioHID/USBDesc.h new file mode 100644 index 0000000000..900713e0f9 --- /dev/null +++ b/plugins/KeyboardioHID/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/plugins/KeyboardioHID/examples/AdvancedGamepad/AdvancedGamepad.ino b/plugins/KeyboardioHID/examples/AdvancedGamepad/AdvancedGamepad.ino deleted file mode 100644 index bd8eb03192..0000000000 --- a/plugins/KeyboardioHID/examples/AdvancedGamepad/AdvancedGamepad.ino +++ /dev/null @@ -1,55 +0,0 @@ -/* - Copyright (c) 2014 NicoHood - See the readme for credit to other people. - - Advanced Gamepad example - */ - -// include HID library -#include - -const int pinLed = 13; -const int pinButton = 8; - -// see HID_Reports.h for all data structures -HID_GamepadReport_Data_t Gamepadreport; - -void setup() { - pinMode(pinLed, OUTPUT); - pinMode(pinButton, INPUT_PULLUP); - - // Starts Serial at baud 115200 otherwise HID wont work on Uno/Mega. - // This is not needed for Leonado/(Pro)Micro but make sure to activate desired USB functions in HID.h - Serial.begin(SERIAL_HID_BAUD); - - // Sends a clean report to the host. This is important because - // the 16u2 of the Uno/Mega is not turned off while programming - // so you want to start with a clean report to avoid strange bugs after reset. - memset(&Gamepadreport, 0, sizeof(Gamepadreport)); - HID_SendReport(HID_REPORTID_Gamepad1Report, &Gamepadreport, sizeof(Gamepadreport)); -} - -void loop() { - if (!digitalRead(pinButton)) { - digitalWrite(pinLed, HIGH); - - // This demo is actually made for advanced users to show them how they can write an own report. - // This might be useful for a Gamepad if you want to edit the values direct on your own. - - // count with buttons binary - static uint32_t count = 0; - Gamepadreport.whole32[0] = count++; - - // move x/y Axis to a new position (16bit) - Gamepadreport.whole16[2] = (random(0xFFFF)); - - // functions before only set the values - // this writes the report to the host - HID_SendReport(HID_REPORTID_Gamepad1Report, &Gamepadreport, sizeof(Gamepadreport)); - - // simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } -} - diff --git a/plugins/KeyboardioHID/examples/AdvancedKeyboard/AdvancedKeyboard.ino b/plugins/KeyboardioHID/examples/AdvancedKeyboard/AdvancedKeyboard.ino deleted file mode 100644 index 725f1bea35..0000000000 --- a/plugins/KeyboardioHID/examples/AdvancedKeyboard/AdvancedKeyboard.ino +++ /dev/null @@ -1,99 +0,0 @@ -/* -Copyright (c) 2014 NicoHood - See the readme for credit to other people. - - Advanced Keyboard example - */ - -// include HID library -#include - -const int pinLed = 13; -const int pinButton = 8; - -void setup() { - pinMode(pinLed, OUTPUT); - pinMode(pinButton, INPUT_PULLUP); - - // Starts Serial at baud 115200 otherwise HID wont work on Uno/Mega. - // This is not needed for Leonado/(Pro)Micro but make sure to activate desired USB functions in HID.h - Serial.begin(SERIAL_HID_BAUD); - - // Sends a clean report to the host. This is important because - // the 16u2 of the Uno/Mega is not turned off while programming - // so you want to start with a clean report to avoid strange bugs after reset. - pressRawKeyboard(0, 0); -} - -void loop() { - if (!digitalRead(pinButton)) { - digitalWrite(pinLed, HIGH); - - // This demo is actually made for advanced users to show them how they can write an own report. - // This might be useful for a Keyboard if you only use one key, - // because the library has a lot of code for simple use - - // press STRG + ALT + DEL on keyboard (see usb documentation) - //pressRawKeyboard(0, 4); //modifiers + 4 - //pressRawKeyboard(0, 29); //modifiers + z - pressRawKeyboard(RAW_KEYBOARD_LEFT_CTRL | RAW_KEYBOARD_LEFT_ALT , RAW_KEYBOARD_DELETE); //modifiers + key - pressRawKeyboard(0, 0); // release! Important - - // simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } -} - -void pressRawKeyboard(uint8_t modifiers, uint8_t key) { - uint8_t keys[8] = { - modifiers, 0, key, 0, 0, 0, 0, 0 }; //modifiers, reserved, key[0] - HID_SendReport(HID_REPORTID_KeyboardReport, keys, sizeof(keys)); -} - -/* -See Hut1_12v2.pdf Chapter 10 (Page 53) for more Keys - (especially a-z, a=0x04 z=29) - Definitions: - - RAW_KEYBOARD_LEFT_CTRL - RAW_KEYBOARD_LEFT_SHIFT - RAW_KEYBOARD_LEFT_ALT - RAW_KEYBOARD_LEFT_GUI - RAW_KEYBOARD_RIGHT_CTRL - RAW_KEYBOARD_RIGHT_SHIFT - RAW_KEYBOARD_RIGHT_ALT - RAW_KEYBOARD_RIGHT_GUI - - RAW_KEYBOARD_UP_ARROW - RAW_KEYBOARD_DOWN_ARROW - RAW_KEYBOARD_LEFT_ARROW - RAW_KEYBOARD_RIGHT_ARROW - RAW_KEYBOARD_SPACEBAR - RAW_KEYBOARD_BACKSPACE - RAW_KEYBOARD_TAB - RAW_KEYBOARD_RETURN - RAW_KEYBOARD_ESC - RAW_KEYBOARD_INSERT - RAW_KEYBOARD_DELETE - RAW_KEYBOARD_PAGE_UP - RAW_KEYBOARD_PAGE_DOWN - RAW_KEYBOARD_HOME - RAW_KEYBOARD_END - RAW_KEYBOARD_CAPS_LOCK - RAW_KEYBOARD_F1 - RAW_KEYBOARD_F2 - RAW_KEYBOARD_F3 - RAW_KEYBOARD_F4 - RAW_KEYBOARD_F5 - RAW_KEYBOARD_F6 - RAW_KEYBOARD_F7 - RAW_KEYBOARD_F8 - RAW_KEYBOARD_F9 - RAW_KEYBOARD_F10 - RAW_KEYBOARD_F11 - RAW_KEYBOARD_F12 - RAW_KEYBOARD_PRINT - RAW_KEYBOARD_SCROLL_LOCK - RAW_KEYBOARD_PAUSE - */ diff --git a/plugins/KeyboardioHID/examples/AdvancedRawHID/AdvancedRawHID.ino b/plugins/KeyboardioHID/examples/AdvancedRawHID/AdvancedRawHID.ino deleted file mode 100644 index 7905f7dbb1..0000000000 --- a/plugins/KeyboardioHID/examples/AdvancedRawHID/AdvancedRawHID.ino +++ /dev/null @@ -1,114 +0,0 @@ -/* - Copyright (c) 2014 NicoHood - See the readme for credit to other people. - - Advanced RawHID example - Shows how to send bytes via raw HID - Press a button to send some example values. - Keep in mind that you can only send full data packets, the rest is filled with zero! - - Definitions from HID_Reports.h: - RAWHID_USAGE_PAGE 0xFFC0 // recommended: 0xFF00 to 0xFFFF - RAWHID_USAGE 0x0C00 // recommended: 0x0100 to 0xFFFF - RAWHID_TX_SIZE 15 // 1 byte for report ID - RAWHID_RX_SIZE 15 // 1 byte for report ID - */ - -// include HID library -#include - -const int pinLed = 13; -const int pinButton = 8; - -void setup() { - pinMode(pinLed, OUTPUT); - pinMode(pinButton, INPUT_PULLUP); - - // Starts Serial at baud 115200 otherwise HID wont work on Uno/Mega. - // This is not needed for Leonado/(Pro)Micro but make sure to activate desired USB functions in HID.h - Serial.begin(SERIAL_HID_BAUD); - - // no begin function needed for RawHID -} - -void loop() { - if (!digitalRead(pinButton)) { - digitalWrite(pinLed, HIGH); - - // direct without library. Always send RAWHID_RX_SIZE bytes! - uint8_t buff[RAWHID_RX_SIZE]; // unitialized, has random values - HID_SendReport(HID_REPORTID_RawKeyboardReport, buff, sizeof(buff)); - - // with library - memset(&buff, 42, sizeof(buff)); - RawHID.write(buff, sizeof(buff)); - - // write a single byte, will fill the rest with zeros - RawHID.write(0xCD); - - // huge buffer with library, will fill the rest with zeros - uint8_t megabuff[64]; - for (int i = 0; i < sizeof(megabuff); i++) - megabuff[i] = i; - RawHID.write(megabuff, sizeof(megabuff)); - - // You can use print too, but better dont use a linefeed - RawHID.println("Hello World"); - - // And compare it to write: - RawHID.write("Hello World\r\n"); - - // simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } -} - -/* -Expected output: - -// manual with unintialized buff -recv 15 bytes: -01 55 C1 FF 01 01 01 00 00 01 00 00 01 00 20 - -// filled buff -recv 15 bytes: -2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A - -// single byte filled with zero -recv 15 bytes: -CD 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - -// huge buffer filled with zero at the end -recv 15 bytes: -00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E - -recv 15 bytes: -0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D - -recv 15 bytes: -1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C - -recv 15 bytes: -2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B - -recv 15 bytes: -3C 3D 3E 3F 00 00 00 00 00 00 00 00 00 00 00 - -// print -recv 15 bytes: -48 65 6C 6C 6F 20 57 6F 72 6C 64 00 00 00 00 - -//\r -recv 15 bytes: -0D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - -//\n -recv 15 bytes: -0A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - -//write -recv 15 bytes: -48 65 6C 6C 6F 20 57 6F 72 6C 64 0D 0A 00 00 - -*/ \ No newline at end of file diff --git a/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino b/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino deleted file mode 100644 index 44dd2ced6a..0000000000 --- a/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino +++ /dev/null @@ -1,100 +0,0 @@ -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -Gamepad example -Press a button and demonstrate Gamepad actions -*/ - -// include HID library -#include - -// create a new Gamepad instance (1-4) -Gamepad Gamepad1(1); -//Gamepad Gamepad2(2); -//Gamepad Gamepad3(3); -//Gamepad Gamepad4(4); - -const int pinLed = 13; -const int pinButton = 8; - -void setup() { - pinMode(pinLed, OUTPUT); - pinMode(pinButton, INPUT_PULLUP); - - // Starts Serial at baud 115200 otherwise HID wont work on Uno/Mega. - // This is not needed for Leonado/(Pro)Micro but make sure to activate desired USB functions in HID.h - Serial.begin(SERIAL_HID_BAUD); - - // Sends a clean report to the host. This is important because - // the 16u2 of the Uno/Mega is not turned off while programming - // so you want to start with a clean report to avoid strange bugs after reset. - Gamepad1.begin(); -} - -void loop() { - if (!digitalRead(pinButton)) { - digitalWrite(pinLed, HIGH); - - // press button 1-32 and reset (34 becaue its written later) - static uint8_t count = 1; - Gamepad1.press(count++); - if (count == 34) { - Gamepad1.releaseAll(); - count = 1; - } - - // move x/y Axis to a new position (16bit) - Gamepad1.xAxis(random(0xFFFF)); - Gamepad1.yAxis(analogRead(A0) << 6); - - // go through all dPad positions - // values: 0-8 (0==centred) - static uint8_t dpad1 = GAMEPAD_DPAD_CENTERED; - Gamepad1.dPad1(dpad1++); - if(dpad1>GAMEPAD_DPAD_UP_LEFT) dpad1 = GAMEPAD_DPAD_CENTERED; - static int8_t dpad2 = GAMEPAD_DPAD_CENTERED; - Gamepad1.dPad2(dpad2--); - if(dpad2 - -const int pinLed = 13; -const int pinButton = 8; - -void setup() { - pinMode(pinLed, OUTPUT); - pinMode(pinButton, INPUT_PULLUP); - - // Starts Serial at baud 115200 otherwise HID wont work on Uno/Mega. - // This is not needed for Leonado/(Pro)Micro but make sure to activate desired USB functions in HID.h - Serial.begin(SERIAL_HID_BAUD); - - // Sends a clean report to the host. This is important because - // the 16u2 of the Uno/Mega is not turned off while programming - // so you want to start with a clean report to avoid strange bugs after reset. - Keyboard.begin(); -} - - -void loop() { - if (!digitalRead(pinButton)) { - digitalWrite(pinLed, HIGH); - - // Same use as the official library, pretty much self explaining - Keyboard.println("This message was sent with my Arduino."); - Serial.println("Serial port is still working and not glitching out"); - - // simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } -} - -/* -Definitions: - - KEY_LEFT_CTRL - KEY_LEFT_SHIFT - KEY_LEFT_ALT - KEY_LEFT_GUI - KEY_RIGHT_CTRL - KEY_RIGHT_SHIFT - KEY_RIGHT_ALT - KEY_RIGHT_GUI - - KEY_UP_ARROW - KEY_DOWN_ARROW - KEY_LEFT_ARROW - KEY_RIGHT_ARROW - KEY_BACKSPACE - KEY_TAB - KEY_RETURN - KEY_ESC - KEY_INSERT - KEY_DELETE - KEY_PAGE_UP - KEY_PAGE_DOWN - KEY_HOME - KEY_END - KEY_CAPS_LOCK - KEY_F1 - KEY_F2 - KEY_F3 - KEY_F4 - KEY_F5 - KEY_F6 - KEY_F7 - KEY_F8 - KEY_F9 - KEY_F10 - KEY_F11 - KEY_F12 - - KEY_PRINT - KEY_SCROLL_LOCK - KEY_PAUSE - */ \ No newline at end of file diff --git a/plugins/KeyboardioHID/examples/Media/Media.ino b/plugins/KeyboardioHID/examples/Media/Media.ino deleted file mode 100644 index e8065eef67..0000000000 --- a/plugins/KeyboardioHID/examples/Media/Media.ino +++ /dev/null @@ -1,65 +0,0 @@ -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -Media example -Press a button to play/pause music player -*/ - -// include HID library -#include - -const int pinLed = 13; -const int pinButton = 8; - -void setup() { - pinMode(pinLed, OUTPUT); - pinMode(pinButton, INPUT_PULLUP); - - // Starts Serial at baud 115200 otherwise HID wont work on Uno/Mega. - // This is not needed for Leonado/(Pro)Micro but make sure to activate desired USB functions in HID.h - Serial.begin(SERIAL_HID_BAUD); - - // Sends a clean report to the host. This is important because - // the 16u2 of the Uno/Mega is not turned off while programming - // so you want to start with a clean report to avoid strange bugs after reset. - Media.begin(); -} - -void loop() { - if (!digitalRead(pinButton)) { - digitalWrite(pinLed, HIGH); - - // See list below for more definitions or the official usb documentation - Media.write(MEDIA_PLAY_PAUSE); - - // simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } -} - -/* -Definitions: - -MEDIA_FAST_FORWARD -MEDIA_REWIND -MEDIA_NEXT -MEDIA_PREVIOUS -MEDIA_STOP -MEDIA_PLAY_PAUSE - -MEDIA_VOLUME_MUTE -MEDIA_VOLUME_UP -MEDIA_VOLUME_DOWN - -MEDIA_EMAIL_READER -MEDIA_CALCULATOR -MEDIA_EXPLORER - -MEDIA_BROWSER_HOME -MEDIA_BROWSER_BACK -MEDIA_BROWSER_FORWARD -MEDIA_BROWSER_REFRESH -MEDIA_BROWSER_BOOKMARKS -*/ diff --git a/plugins/KeyboardioHID/examples/Mouse/Mouse.ino b/plugins/KeyboardioHID/examples/Mouse/Mouse.ino deleted file mode 100644 index 41b7647fc0..0000000000 --- a/plugins/KeyboardioHID/examples/Mouse/Mouse.ino +++ /dev/null @@ -1,52 +0,0 @@ -/* -Copyright (c) 2014 NicoHood - See the readme for credit to other people. - - Mouse example - Press a button to click with mouse. See official documentation for more infos - */ - -// include HID library -#include - -const int pinLed = 13; -const int pinButton = 8; - -void setup() { - pinMode(pinLed, OUTPUT); - pinMode(pinButton, INPUT_PULLUP); - - // Starts Serial at baud 115200 otherwise HID wont work on Uno/Mega. - // This is not needed for Leonado/(Pro)Micro but make sure to activate desired USB functions in HID.h - Serial.begin(SERIAL_HID_BAUD); - - // Sends a clean report to the host. This is important because - // the 16u2 of the Uno/Mega is not turned off while programming - // so you want to start with a clean report to avoid strange bugs after reset. - Mouse.begin(); -} - -void loop() { - if (!digitalRead(pinButton)) { - digitalWrite(pinLed, HIGH); - - // Same use as the official library, pretty much self explaining - Mouse.click(); - Serial.println("Serial port is still working and not glitching out"); - - // simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } -} - -/* -Definitions: - - MOUSE_LEFT - MOUSE_RIGHT - MOUSE_MIDDLE - MOUSE_PREV - MOUSE_NEXT - */ - diff --git a/plugins/KeyboardioHID/examples/Readme.md b/plugins/KeyboardioHID/examples/Readme.md deleted file mode 100644 index 30a01d3b39..0000000000 --- a/plugins/KeyboardioHID/examples/Readme.md +++ /dev/null @@ -1,4 +0,0 @@ -Examples -======== - -Just try these examples once the HID Source is installed. Its pretty much self explaining. \ No newline at end of file diff --git a/plugins/KeyboardioHID/examples/System/System.ino b/plugins/KeyboardioHID/examples/System/System.ino deleted file mode 100644 index 7d03b2ebbc..0000000000 --- a/plugins/KeyboardioHID/examples/System/System.ino +++ /dev/null @@ -1,48 +0,0 @@ -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -System example -Press a button to put pc into standby mode -*/ - -// include HID library -#include - -const int pinLed = 13; -const int pinButton = 8; - -void setup() { - pinMode(pinLed, OUTPUT); - pinMode(pinButton, INPUT_PULLUP); - - // Starts Serial at baud 115200 otherwise HID wont work on Uno/Mega. - // This is not needed for Leonado/(Pro)Micro but make sure to activate desired USB functions in HID.h - Serial.begin(SERIAL_HID_BAUD); - - // Sends a clean report to the host. This is important because - // the 16u2 of the Uno/Mega is not turned off while programming - // so you want to start with a clean report to avoid strange bugs after reset. - System.begin(); -} - -void loop() { - if (!digitalRead(pinButton)) { - digitalWrite(pinLed, HIGH); - - // See list below for more definitions or the official usb documentation - System.write(SYSTEM_SLEEP); - - // simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } -} - -/* -Definitions: - -SYSTEM_POWER_DOWN -SYSTEM_SLEEP -SYSTEM_WAKE_UP -*/ diff --git a/plugins/KeyboardioHID/firmwares/Hoodloader1_8.hex b/plugins/KeyboardioHID/firmwares/Hoodloader1_8.hex deleted file mode 100644 index d35ec84ce2..0000000000 --- a/plugins/KeyboardioHID/firmwares/Hoodloader1_8.hex +++ /dev/null @@ -1,642 +0,0 @@ -:1000000099C10000B3C10000B1C10000AFC1000040 -:10001000ADC10000ABC10000A9C10000A7C1000034 -:10002000A5C10000A3C10000A1C100000C94B80D3F -:100030000C94640E9BC1000099C1000097C10000A0 -:1000400095C1000093C1000091C100008FC1000064 -:100050008DC100008BC1000089C1000057C30000A2 -:1000600085C1000083C1000081C100007FC1000084 -:100070007DC100003003410072006400750069001A -:100080006E006F00200048006F006F0064006C007D -:100090006F0061006400650072002000420065008E -:1000A00074006100000012034E00690063006F00DD -:1000B00048006F006F006400000004030904090297 -:1000C0005F00030100C032080B00020202010009B8 -:1000D00004000001020201000524001001042402B2 -:1000E000060524060001070582030800FF09040134 -:1000F00000020A0000000705040240000107058312 -:10010000024000010904020001030000000921115E -:1001100001000122040207058103100001120110F1 -:1001200001EF020108EB03686E80010102DC0105AA -:10013000010902A1010901A100850105091901298F -:10014000051500250195057501810295017503814D -:100150000305010930093109381581257F75089596 -:10016000038106C0C005010906A101850205071922 -:10017000E029E715002501750195088102950175B3 -:1001800008810395067508150025650507190029DE -:1001900065810005081901290595057501910295EC -:1001A0000175039103C006C0FF0A000CA10185037D -:1001B0007508150026FF00950F09018102950F09AA -:1001C000029102C0050C0901A1018504150026FF5A -:1001D0000319002AFF03950475108100C005010969 -:1001E00080A1018505150026FF00190029FF950152 -:1001F00075088100C005010904A1018506050919DA -:10020000012920150025017501952081020501A114 -:1002100000093009310933093416008026FF7F7543 -:100220001095048102093209351580257F750895DE -:10023000028102C005010939093915012508950215 -:1002400075048102C005010904A10185070509198A -:10025000012920150025017501952081020501A1C4 -:1002600000093009310933093416008026FF7F75F3 -:100270001095048102093209351580257F7508958E -:10028000028102C009390939150125089502750452 -:100290008102C005010904A1018508050919012988 -:1002A00020150025017501952081020501A1000995 -:1002B0003009310933093416008026FF7F75109507 -:1002C000048102093209351580257F750895028160 -:1002D00002C005010939093915012508950275047F -:1002E0008102C005010904A1018509050919012937 -:1002F00020150025017501952081020501A1000945 -:100300003009310933093416008026FF7F751095B6 -:10031000048102093209351580257F75089502810F -:1003200002C005010939093915012508950275042E -:100330008102C00011241FBECFEFD2E0DEBFCDBFCF -:1003400011E0A0E0B1E0EAECF7E202C005900D9206 -:10035000AE33B107D9F711E0AEE3B1E001C01D92B1 -:10036000A63FB107E1F773D00C94E31349CEEEE357 -:10037000F1E05FB7F894208131812115310519F042 -:100380004481411104C05FBF2FEF3FEF11C0828154 -:1003900090E0841B910997FF03C06381860F911D34 -:1003A000D901A80FB91F2C91415044835FBF30E0A1 -:1003B000C9010895EEE3F1E04FB7F894208131814F -:1003C0002115310509F41DC0828190E05481851BFF -:1003D0009109019797FF03C05381850F911DD901A2 -:1003E000A80FB91F6C9384819381891308C09281EF -:1003F000911101C0828382818150828302C08F5F0C -:1004000084834FBF089584B7877F84BF88E10FB688 -:10041000F89480936000109260000FBE539A5A9A2D -:1004200080E191E00E94D00A1092CA018AB18063F3 -:100430008AB98BB180638BB90E94A90D84E085BD18 -:100440005F9A579A25982D9A26982E9A089580910A -:10045000CB01807F8093CB011092DB011092DC01F5 -:100460002DD4D1DF789410E213B980E191E00E949D -:10047000B51097FD1BC0409124015091250160915A -:10048000260170912701413051056105710511F474 -:10049000AFD60CC05C989091CA019C609093CA0141 -:1004A0009091C80095FFFCCF8093CE002FB7F894B1 -:1004B00080913E0190913F01892B19F0809142017A -:1004C00001C080E02FBF90E0009719F4A89981C087 -:1004D00002C15D982091CA0123602093CA01209136 -:1004E00011012F702093E9002091E80020FFEECF4A -:1004F0008034910510F08FE390E0F82EC0E0D0E05A -:1005000065C08091240190912501A0912601B091B0 -:1005100027012091E80121110CC082309105A1052D -:10052000B10528F08115924CA140B10511F41D9937 -:1005300043C08091200180FD0AC0222341F08EE358 -:1005400091E015DF8091E80181112DC03EC07FB799 -:10055000F89420913E0130913F012115310541F081 -:1005600040914201442321F050E01416150624F076 -:100570007FBF6FEF7FEF10C08091400190E0841B40 -:10058000950B97FF04C040914101840F911DF90123 -:10059000E80FF91F60817FBF80E191E00E944D105C -:1005A000882369F293CF81508093E8018091CA013A -:1005B00080638093CA0109C08091CA0180638093DF -:1005C000CA018EE391E0D3DEA1D22196FC1299CF2D -:1005D0007DCFA89A9091CA01892F807309F459C0E0 -:1005E000892F82958F708D5F8370282F2295207FB1 -:1005F0009F7C922B9093CA0181114BC0E091DD0149 -:10060000E6FF15C0E695E695E695E770F0E0EE5159 -:10061000FE4F60818EE391E0CDDE8091DD0186FBAF -:10062000882780F99091E801890F8093E8018091F3 -:10063000DD0187FD2AC08695869586958770C0E086 -:10064000D0E0E82EF12C8EE3C82E81E0D82ECE0C1F -:10065000DF1C09C0F601EC0FFD1FEC55FF4F608158 -:100660008EE391E0A7DE2197CE01809590958E15BF -:100670009F0584F38091DD01869586958695877028 -:100680009091E801890F8093E8018DED91E070D69B -:100690000AD29091CA01892F837049F081508370EA -:1006A0009C7F982B9093CA01811101C05D9A909113 -:1006B000CA01892F8C7079F0892F869586958D5F78 -:1006C0008370282F220F220F937F922B9093CA01C1 -:1006D000811101C05C9A80E091E00E94E01280E10B -:1006E00091E00E949F100E940C10BECE08950895C4 -:1006F00080E091E00E94CB1280E191E00E942810FE -:10070000E2EEF0E080818460808308951F920F9272 -:100710000FB60F9211242F933F934F935F938F93B4 -:100720009F93AF93BF93EF93FF934091CE0080913F -:10073000ED018430E9F4EEE3F1E02FB7F894808125 -:1007400091810097A1F054813381531301C00FC0F0 -:100750003281DC01A30FB11D4C93832F8F5F828305 -:100760009381891301C0128284818F5F84832FBF9C -:10077000FF91EF91BF91AF919F918F915F914F91B9 -:100780003F912F910F900FBE0F901F90189580E111 -:1007900091E00E94E31080E091E00C94941180912C -:1007A0000E0190910F01009729F0019790930F018E -:1007B00080930E010895292F332723303105B1F09E -:1007C0004CF42130310509F439C02230310509F0EB -:1007D0003AC007C02132310539F12232310549F1E1 -:1007E00032C0EFE5F0E08EEB90E031C09927813028 -:1007F000910561F08230910581F0892B21F5EAEBBA -:10080000F0E0E491F0E08AEB90E021C0E6EAF0E06D -:10081000E491F0E086EA90E01AC0E4E7F0E0E491C9 -:10082000F0E084E790E013C0E9E0F0E08DE091E0D3 -:100830000EC0E4E0F2E08FE291E009C0E2E1F0E016 -:100840008DE191E004C0E0E0F0E080E090E0DA01CA -:100850008D939C93CF010895FF920F931F93CF9395 -:10086000DF9320E030E050E0640F751FCEE3D1E06D -:100870002CC0FB01E21BF30B31970081FE011FB777 -:10088000F894A081B181109709F41CC0828190E096 -:10089000F4808F199109019797FF03C0F3808F0DA2 -:1008A000911DA80FB91F0C9384819381891308C0EF -:1008B0009281911101C0828382818150828302C022 -:1008C0008F5F84831FBF2F5F3F4F241735078CF244 -:1008D000DF91CF911F910F91FF900895089504C06B -:1008E00080E091E00E94E0128091DC0187FDF8CF6A -:1008F00008958150813130F4E82FF0E0E55DFE4F3E -:100900008081089580E00895EF92FF921F93CF9326 -:10091000DF931F92CDB7DEB7182FE82EF12C21E020 -:10092000E21AF1082091DB018091DC01382F3F773A -:100930000E2C02C0359527950A94E2F720FF36C0A9 -:10094000812FD7DF882391F18983C9DF1F709091B0 -:10095000CB01907F912B9093CB012CEC31E08981DE -:10096000482F50E060E070E0C9010E94DC138091E4 -:10097000DC0180688093DC01B2DF81E090E002C09E -:10098000880F991FEA94E2F7809590952091DB01FA -:100990004091DC01342F3F77822393238093DB0146 -:1009A0009F77842F8078892B8093DC010F90DF91D3 -:1009B000CF911F91FF90EF900895CF938091DB012D -:1009C0002091DC01922F9F77892B31F0C1E08C2F91 -:1009D0009BDFCF5FC231D9F7CF910895CF92DF92DD -:1009E000EF92FF920F931F93CF93DF9300D0CDB779 -:1009F000DEB77B01932F68017091DC01672F60786F -:100A000009F440C0E091CB01EF70E330B1F0F0E0C9 -:100A1000319741E050E002C0440F551FEA95E2F7DC -:100A2000E091DB01F72FFF774E2B5F2B4093DB012B -:100A3000452F4F77462B4093DC018091CB018F707F -:100A400029839A8356DF182FECECF1E0482F50E011 -:100A5000BF012981822F9A810E94D3139091CB01EB -:100A60009F70F7019083F601108311828091DC0161 -:100A70008F778093DC018091CB01807F8093CB01C5 -:100A800081E006C0F7011082F8011182108280E037 -:100A90000F900F90DF91CF911F910F91FF90EF90EA -:100AA000DF90CF9008951F93CF93DF9300D000D0B5 -:100AB00000D0CDB7DEB713DF8091CB01682F6F7008 -:100AC000B1F0807FA1F470E07160AE014F5F5F4FC5 -:100AD00081E024D5182F482FBE016F5F7F4F8EE332 -:100AE00091E0BADE9091E801910F9093E801809136 -:100AF000CB01807F8093CB0126960FB6F894DEBFA2 -:100B00000FBECDBFDF91CF911F910895CF936DEDB3 -:100B100071E0E1D4882309F48AC087FD70C0813078 -:100B2000C1F49091DF019130A1F4D9DEC091DE01D2 -:100B30008091CB018F708093CB01B5DFCF70809116 -:100B4000CB01807F8C2B8093CB018F7009F06FC01D -:100B50006CC02091CB01922F9F7009F450C099274F -:100B600087FD909522952F7030E02E5F3F4F359591 -:100B700027952F5F3F4F8217930709F040C0AFDEE4 -:100B8000C091CB018C2F8F70B4DE2C2F22952F704B -:100B90009091DE013091DF01E22FF0E0E453FE4F4F -:100BA0009083E22FEF5FEF704E2F4295407F909140 -:100BB000CB019F70942B9093CB018E1769F0F0E0DE -:100BC000E453FE4F30832E5F2295207F9091CB011E -:100BD0009F70922B9093CB012091CB0122952F7087 -:100BE00030E090E02817390711F58091DC0180682A -:100BF0008093DC0180E091E0CF910C94E012409171 -:100C0000DD01469546954695477062EE71E08EE3AC -:100C100091E022DE8091DD0186958695869587702C -:100C20009091E801890F8093E801CF913CCFCF915B -:100C30000895682F80E191E00E944D108823D9F03B -:100C400080E191E00E949F100E940C105C982FEFB1 -:100C500081EE94E0215080409040E1F700C0000018 -:100C60005C982FEF81EE94E0215080409040E1F7B6 -:100C700000C00000EBCF089580E191E00E94B51024 -:100C800097FDFACF0895EF92FF920F931F93CF93A2 -:100C9000DF937C0103E411E0C0E0D0E005C0ECDFAD -:100CA000F80181938F012196CE15DF05C4F3DF9102 -:100CB000CF911F910F91FF90EF9008952398229864 -:100CC0002198249820981092C5011092C401109286 -:100CD000C7011092C6011092C9011092C80110926A -:100CE000C301EEE3F1E02FB7F89483E491E0918340 -:100CF0008083128280E8838314822FBF1092E801E0 -:100D00008DED91E035C3CF93C82FB6DF803239F433 -:100D100084E18FDF8C2F8DDF80E1CF918ACF85E159 -:100D200088DF8091C301982F9F5F9F778078892B00 -:100D30008093C301CF9108959FDF803221F484E135 -:100D400078DF80E176CF85E174DF8091C301982F51 -:100D50009F5F9F778078892B8093C30108958138A6 -:100D600059F018F4803871F405C0823839F08339AD -:100D700049F406C082E007C081E005C082E103C0FB -:100D800083E501C080E0BFCF84E190E07CDF9091FB -:100D90004F0180E020915001820F911D9093C70177 -:100DA0008093C6019091510180E020915201820F01 -:100DB000911D9093C9018093C801089583E58CBD6E -:100DC0008DB58EB508950DB407FEFDCF08958EBD87 -:100DD000FADF8EB50895CF93DF9300D01F92CDB781 -:100DE000DEB72B834A836983F2DF6981862FEFDFC9 -:100DF0004A81842FECDF2B81822F0F900F900F9070 -:100E0000DF91CF91E4CF38DF803259F08091C30178 -:100E1000982F9F5F9F778078892B8093C30185E10E -:100E200015C084E106DF20E040E060E080E3D3DF2E -:100E300000DF20E041E060E080E3CDDFFADE20E08B -:100E400042E060E080E3C7DFF4DE80E1F2CE84E0E0 -:100E500090E019DF209146014091450160914401E5 -:100E600080914301B8DF4FCF209A289AA7DF249AB8 -:100E70002C9A219A29982FEF80E792E02150804008 -:100E80009040E1F700C000002C982FEF80E792E03F -:100E9000215080409040E1F700C000002398229A42 -:100EA00020E040E063E58CEA96DFE3ECF1E080814E -:100EB0008068808382DDEEE3F1E08FB7F8941182E1 -:100EC00010821282138214828FBF1092CA018BB1DA -:100ED00080638BB90895962F672F242F492F7BCFDE -:100EE000EF92FF920F931F93CF93DF93C5DE182FDE -:100EF000C3DED82FC1DEC82FBFDE803259F080910B -:100F0000C301982F9F5F9F778078892B8093C301BF -:100F100085E144C0312F20E07901ED0EF11C84E120 -:100F200088DEC63419F51BC06091C4017091C501FB -:100F300040E080E2D0DF7DDE6091C4017091C501A8 -:100F400040E088E2C8DF75DE8091C4019091C50160 -:100F500001969093C5018093C401229602C0C0E01F -:100F6000D0E0CE15DF0504F380E118C0C534A9F444 -:100F70000091C4011091C501000F111FC0E0D0E025 -:100F800008C0BE01600F711F4FEF80EAA4DF51DE81 -:100F90002196CE15DF05ACF3E7CF81E1DF91CF914C -:100FA0001F910F91FF90EF9044CE8091C6019091D8 -:100FB000C7012091C4013091C5018032910511F41F -:100FC000207F0EC08034910511F4207E09C0803846 -:100FD000910511F4207C04C08115914009F420781A -:100FE000C90108955D9A40E0BC018CE474DF2FEFE5 -:100FF00086E791E0215080409040E1F700C000007A -:101000005D980895CF92DF92EF92FF920F931F9316 -:10101000CF93DF937B01CB0136DEC7DF8C01C0E0CD -:10102000D0E029C09EE3C92E91E0D92ECC0EDD1E62 -:101030006091C4017091C501F601458180E44BDFE8 -:1010400022966091C4017091C501F601468188E441 -:1010500042DF2091C4013091C5012F5F3F4F309393 -:10106000C5012093C401A1DF0817190721F0C801A9 -:10107000B9DF9BDF8C01CE15DF05A4F280E1DF91A3 -:10108000CF911F910F91FF90EF90DF90CF90089537 -:101090000F931F93CF93DF93C091C401D091C501EB -:1010A000CC0FDD1F8C0108C060E870E0CE01AADF24 -:1010B000C058DF4F0058110901381105A8F7B801D1 -:1010C000CE01A0DF80E1DF91CF911F910F910895B4 -:1010D000CF92DF92EF92FF920F931F93CF93DF9304 -:1010E0006C018B01CB01CFDD5D9A33E4E32E31E05F -:1010F000F32EC0E0D0E012C0F70141917F01BE01A4 -:101100006C0D7D1D80ECE7DEFFE722E382E0F1500D -:1011100020408040E1F700C000002196C017D107B1 -:101120005CF35D9880E1DF91CF911F910F91FF906B -:10113000EF90DF90CF9008950F931F93CF93DF939D -:10114000C091C401D091C5012091C8013091C9015D -:101150002817390724F0CC0FDD1F8C0113C08091B4 -:10116000C301982F9F5F9F778078892B8093C3015D -:1011700081E10FC060E870E0CE01AADFC058DF4F08 -:101180000058110901381105A8F7B801CE01A0DFF8 -:1011900080E1DF91CF911F910F910895CF93DF935D -:1011A0006BDDD82F80E0C82F67DDC80FD11D64DD4F -:1011B000863419F4CE016CDF04C08534A9F4CE0165 -:1011C000BBDFC82F59DD803221F484E132DD8C2F62 -:1011D0000CC08091C301982F9F5F9F778078892BE7 -:1011E0008093C30185E101C081E1DF91CF9121CDE1 -:1011F000CF93DF932091C30127FF02C05D9801C008 -:101200005D9A2F7711F05C9801C05C9A97FDADC094 -:101210008135910509F483C0E4F48134910509F422 -:1012200053C054F48033910599F181339105B1F1A4 -:10123000809709F088C07DC08534910509F44CC0C1 -:101240008035910509F44CC08234910509F07BC0CA -:101250003FC08136910509F457C06CF4863591057D -:1012600009F45AC08036910509F44DC085359105C1 -:1012700009F069C037C08437910509F44AC0853741 -:10128000910509F453C08436910509F05CC03EC055 -:101290008091C30180788093C3011BC0EDDC803254 -:1012A00009F063C084E1C5DC81E4C3DC86E5C1DC10 -:1012B00082E5BFDC80E2BDDC89E4BBDC83E5B9DC30 -:1012C00080E5B7DC80E14EC0D7DCDF91CF9147CD20 -:1012D0005BDDDF91CF9130CD85E090E0D4DCF9CFBC -:1012E000C3DDF7CFC9DCC82FD0E0D093C501C093D0 -:1012F000C401C2DC382F20E02C0F3D1F3093C50104 -:101300002093C401E6CFB8DCB7DCE3CFDF91CF9107 -:1013100045CFDF91CF91E4CDDF91CF9198CD8091F2 -:10132000C30180788093C301C9DCD3CFDF91CF9113 -:101330006ACD8091C301982F9F5F9F778078892B1A -:101340008093C3010EC08091C301982F9F5F9F7748 -:101350008078892B8093C3018FDC803211F482E185 -:1013600001C085E1DF91CF9164CCDF91CF910895E9 -:10137000FC01208120682F7B208308950F931F9309 -:10138000FB01908196FF0FC0292F26952695269563 -:101390002770DB01A20FB11D15962C912583977C38 -:1013A00098609F7B03C097FF02C0907C90839081E0 -:1013B0009695969596959770DF01A90FB11D159694 -:1013C0008C93292F2F5F2770220F220F220F40812D -:1013D000477C422B4083282F207C342F37702038C5 -:1013E00009F463C0203C09F045C0282F28732695D6 -:1013F00026952695332349F0990F990F990F477C2D -:10140000492B406440839EEF01C090E0223098F465 -:10141000908196FB222720F9892F869586958695BF -:10142000820F8770880F880F880F977C982B9F7B7F -:1014300090839FEF3FC0273059F4082F0F7010E0C2 -:1014400020E030E0018312832383348325E00AC047 -:10145000482F477050E060E070E04183528363831F -:101460007483215027708081887F822B8083992309 -:1014700029F120C0032F10E00230110524F1395F5B -:101480003770487F432B408341815281638174814F -:1014900097E0440F551F661F771F9A95D1F7482B89 -:1014A000418352836383748309C0313071F4982F70 -:1014B0009F739F5F80818068808309C080818F7760 -:1014C000808390E004C09DEFF5CF9CEFF3CF892F90 -:1014D0001F910F9108950F931F93CF93DF93EB010B -:1014E0004DDF1816B4F409811A812B813C81A901C2 -:1014F000662777272227332740275127622773271C -:101500004F3F5F4F6105710521F0888180688883B6 -:101510008BEFDF91CF911F910F910895FA012CE18C -:1015200030E097E0AB01022E02C0569547950A9431 -:10153000E2F7483028F0973059F4408396E008C02D -:1015400040839150411104C027503109923051F726 -:10155000492F42500DC0DF01A40FB11D9B012F7711 -:1015600033272C93660F672F661F770B71954150B9 -:101570004111F1CF492F50E09A0163E0220F331F50 -:101580006A95E1F7206C3F6F3081322B3083E40F96 -:10159000F51F319781508F7380688083892F08955C -:1015A000CF92DF92EF92FF92CF93DF93EC01809185 -:1015B000C30187FD83DB01DACC88DD88EE88FF88F4 -:1015C00082E0C816D104E104F10420F0988D8A8DE0 -:1015D000E98D09C0E0E088E090E0C12C32ECD32E28 -:1015E000EE24E394F12CE150E23028F4F0E0E45CE6 -:1015F000FE4FC08101C0C0E0923009F4C86087305E -:1016000031F0883031F0863029F4C26003C0C46004 -:1016100001C0C6605B9A1092C9001092C800109277 -:10162000CA00C11481EED806E104F10489F0C701B3 -:10163000B601969587957795679560587B47814E5B -:101640009F4FA70196010E94A4132150310902C0A7 -:1016500020E130E03093CD002093CC00C093CA004D -:10166000C11481EED806E104F10411F480E001C058 -:1016700082E08093C80088E98093C9005B98DF917D -:10168000CF91FF90EF90DF90CF900895CF93DF93AD -:10169000EC0193D91E9B03C0888980FF02C05F982C -:1016A00006C05F9A1092CA018BB180638BB9DF913B -:1016B000CF910895BF92CF92DF92EF92FF920F9356 -:1016C0001F93CF93DF937C018B01EA01D7D1B82E12 -:1016D000811132C0209731F028813981021B130B10 -:1016E000E20EF31EC12CD12C22C08091E80085FDB2 -:1016F00014C08091E8008E778093E800209749F02D -:10170000888199818C0D9D1D9983888325E0B22E57 -:1017100013C0B4D1882359F00EC0F70181917F0125 -:101720008093F10001501109FFEFCF1ADF0A011574 -:101730001105D9F601C0B82E8B2DDF91CF911F91E5 -:101740000F91FF90EF90DF90CF90BF900895209180 -:10175000F4013091F5012617370748F0611571053E -:1017600039F42091E8002E772093E80001C0B901F8 -:101770009C0180E034C09091ED01992309F443C0AD -:10178000953009F442C09091E80093FD3AC09091E1 -:10179000E80092FD30C09091E80090FF20C0809159 -:1017A000F20090E0F901821B930B05C02191209378 -:1017B000F100615071099F01280F391F61157105F2 -:1017C00019F02830310590F381E02830310509F017 -:1017D00080E09091E8009E779093E8009F0161156A -:1017E000710549F68111C7CF06C08091ED018823AC -:1017F00051F0853051F08091E80082FFF6CF80E013 -:10180000089581E0089582E0089583E008956115C8 -:10181000710529F42091E8002B772093E8009C01C2 -:1018200021C08091ED01882381F1853041F18091C3 -:10183000E80083FD26C08091E80082FFF2CFF90125 -:1018400007C08091F10081939F016150710929F0D7 -:101850009F018091F2008111F4CF8091E8008B7795 -:101860008093E80061157105E1F68091E80080FD44 -:101870000AC08091ED01882341F08530B1F783E003 -:10188000089581E0089580E0089582E00895209110 -:10189000F4013091F5012617370748F061157105FD -:1018A00039F42091E8002E772093E80001C0B901B7 -:1018B0009C0180E035C09091ED01992309F444C06A -:1018C000953009F443C09091E80093FD3BC090919E -:1018D000E80092FD31C09091E80090FF21C0809116 -:1018E000F20090E0F901821B930B06C02491209333 -:1018F000F1003196615071099C012E0F3F1F611557 -:10190000710519F02830310588F381E02830310560 -:1019100009F080E09091E8009E779093E8009F01A5 -:101920006115710541F68111C6CF06C08091ED01A8 -:10193000882351F0853051F08091E80082FFF6CF86 -:1019400080E0089581E0089582E0089583E008959D -:10195000982F2CC09093E900981739F07091EC0003 -:101960002091ED005091F00003C0242F762F50E01D -:1019700021FD02C09F5F1AC03091EB003E7F309383 -:10198000EB003091ED003D7F3093ED003091EB00A6 -:1019900031603093EB007093EC002093ED00509396 -:1019A000F0002091EE0027FDE5CF07C0953090F2C2 -:1019B0008F708093E90081E0089580E008950F938F -:1019C0001F93CF93DF93062FEC0110E02EC0988178 -:1019D000911103C01F5F259628C02C81E981FA81EF -:1019E0006B81892F8F70853010F080E021C022300C -:1019F00010F056E001C052E028E030E040E003C0C3 -:101A00004F5F220F331F2E173F07D0F34295407FC1 -:101A1000452B991F9927991F6295660F660F607C69 -:101A2000692B96DF8111D6CFE0CF1013D0CF81E0A4 -:101A3000DF91CF911F910F9108958091EE0187FD65 -:101A400005C08091E80080FF0EC012C08091E800C0 -:101A500082FD05C08091ED018111F8CF089580913C -:101A6000E8008B7708C08091ED018111EACF0895DD -:101A70008091E8008E778093E80008958091E400DB -:101A80009091E50045E62091EC0020FD1FC023C0A9 -:101A90002091ED01222391F0253091F02091EB006F -:101AA00025FD10C02091E4003091E500281739078A -:101AB00051F34150C90139F784E0089582E0089557 -:101AC00083E0089581E0089580E008952091E80082 -:101AD00020FFDECFF9CF2091E80022FFD9CFF4CF4D -:101AE00041D043D08091D8008F778093D8008091E7 -:101AF000D80080688093D8008091D8008F7D809333 -:101B0000D80084E089BD86E089BD09B400FEFDCF20 -:101B10001092ED011092E9011092EB011092EA018E -:101B200042E060E080E014DF8091E1008E7F8093EE -:101B3000E1008091E20081608093E2008091E20008 -:101B400088608093E2008091E0008E7F8093E000C7 -:101B50000895E3E6F0E080818E7F808381E08093CA -:101B6000EC01BECF1092E20008951092E1000895BA -:101B70001F920F920FB60F9211242F933F934F9302 -:101B80005F936F937F938F939F93AF93BF93EF93E5 -:101B9000FF938091E10082FF0BC08091E20082FF01 -:101BA00007C08091E1008B7F8093E1000E94CF030A -:101BB0008091E10080FF18C08091E20080FF14C096 -:101BC0008091E2008E7F8093E2008091E20080614C -:101BD0008093E2008091D80080628093D80019BC85 -:101BE0001092ED010E9477038091E10084FF30C0E4 -:101BF0008091E20084FF2CC084E089BD86E089BD2D -:101C000009B400FEFDCF8091D8008F7D8093D8006D -:101C10008091E1008F7E8093E1008091E2008F7ED1 -:101C20008093E2008091E20081608093E2008091E5 -:101C3000E901882311F084E007C08091E30087FF69 -:101C400002C083E001C081E08093ED010E94760331 -:101C50008091E10083FF27C08091E20083FF23C0D1 -:101C60008091E100877F8093E10082E08093ED0125 -:101C70001092E9018091E1008E7F8093E1008091D4 -:101C8000E2008E7F8093E2008091E2008061809389 -:101C9000E20042E060E080E05BDE8091F00088607E -:101CA0008093F000B8D1FF91EF91BF91AF919F91D8 -:101CB0008F917F916F915F914F913F912F910F90F5 -:101CC0000FBE0F901F9018951F920F920FB60F9294 -:101CD00011242F933F934F935F936F937F938F9331 -:101CE0009F93AF93BF93CF93EF93FF938091E900BE -:101CF0008F709091EC0090FF02C090E801C090E0DE -:101D0000C92FC82B1092E9008091F000877F809343 -:101D1000F00078941CD01092E9008091F000886067 -:101D20008093F000CF70C093E900FF91EF91CF91C5 -:101D3000BF91AF919F918F917F916F915F914F91E3 -:101D40003F912F910F900FBE0F901F9018951F93EA -:101D5000CF93DF93CDB7DEB7AC970FB6F894DEBF65 -:101D60000FBECDBFEEEEF1E08091F100819321E056 -:101D7000E63FF207C9F70E94C7038091E80083FF9E -:101D800032C18091EE019091EF01953009F487C046 -:101D900038F49130B1F170F0933009F024C131C0C2 -:101DA000983009F4F4C0993009F400C1963009F074 -:101DB0001AC19BC0803821F0823809F014C108C0D4 -:101DC0008091EA019091EB01992389F082600FC024 -:101DD0008091F2019091F3018F7099278093E9002F -:101DE0008091EB0085FB882780F91092E9009091A3 -:101DF000E800977F9093E8008093F1001092F10043 -:101E0000D1C0882319F0823009F0EDC08F7121F024 -:101E1000823009F0E8C00BC08091F001813009F0F8 -:101E2000E2C0933009F080E08093EB012FC08091F5 -:101E3000F00181112BC08091F2019091F3018F701C -:101E40009927009709F4CFC08093E9002091EB0017 -:101E500020FF1CC02091EF01233021F48091EB0082 -:101E6000806212C09091EB0090619093EB0021E0B2 -:101E700030E001C0220F8A95EAF72093EA00109221 -:101E8000EA008091EB0088608093EB001092E900FB -:101E90008091E800877F8093E800CFDDA4C08111A6 -:101EA000A2C08091F0019091F1018F779927182FAE -:101EB0009091E3009078982B9093E3008091E80054 -:101EC000877F8093E800B9DD8091E80080FFFCCF38 -:101ED0008091E30080688093E300112311F083E098 -:101EE00001C082E08093ED017EC08058823008F00E -:101EF0007AC08091F0019091F1018C3D23E092072E -:101F000071F583E08A838AE289834FB7F894DE0112 -:101F1000139620E03EE051E2E32FF0E050935700AB -:101F2000E49120FF03C0E295EF703F5FEF708E2FCA -:101F300090E0EA3010F0C79601C0C0968D939D9353 -:101F40002F5F243149F74FBF8091E800877F80934E -:101F5000E8006AE270E0CE010196F9DB12C0AE0142 -:101F6000455D5F4F6091F2010E94DB030097D9F15C -:101F70002091E800277F2093E800BC018BA59CA559 -:101F800086DC8091E8008B778093E8002CC0803855 -:101F900051F58091E800877F8093E8008091E90106 -:101FA0008093F1008091E8008E7775CF81111BC07E -:101FB0009091F0019230B8F48091E800877F80938F -:101FC000E8009093E90139DD8091E901811104C0B5 -:101FD0008091E30087FF02C084E001C081E080932C -:101FE000ED010E9478038091E80083FF0AC0809190 -:101FF000E800877F8093E8008091EB008062809307 -:10200000EB00AC960FB6F894DEBF0FBECDBFDF91EC -:10201000CF911F9108950895CF938091ED0188236A -:10202000A9F08091E9008F709091EC0090FF02C0C0 -:1020300090E801C090E0C92FC82B1092E900809170 -:10204000E80083FD84DECF70C093E900CF9108954E -:10205000CF93DF93EC014096FC018BE0DF011D92F2 -:102060008A95E9F782E08C83898783E08E8761E037 -:10207000CE010196A4DC882361F061E0CE010696D2 -:102080009EDC882331F061E0CE010B96DF91CF9189 -:1020900096CC80E0DF91CF910895CF93C62F209109 -:1020A000ED012430F1F4FC01448955896689778972 -:1020B000452B462B472BA9F081818F708093E90037 -:1020C0008091E80085FF04C0C093F10080E00AC061 -:1020D0008091E8008E778093E800D0DC8823A1F31C -:1020E00001C082E0CF9108952091ED01243029F5BF -:1020F000FC014489558966897789452B462B472BF6 -:10210000E1F081818F708093E9008091F20081116C -:1021100002C080E008959091E8008091E8008E77F9 -:102120008093E80095FDF5CFA9DC811107C090915F -:10213000E8009E779093E800089582E0089520914A -:10214000ED01243089F4FC01448955896689778939 -:10215000452B462B472B41F021812F702093E9001E -:102160002091E80020FDC0CF08952091ED0124309A -:1021700019F02FEF3FEF24C0FC014489558966898F -:102180007789452B462B472BA1F386818F7080934F -:10219000E9008091E80082FFECCF8091F200882373 -:1021A00021F02091F10030E002C02FEF3FEF80914D -:1021B000F200811105C08091E8008B778093E800E0 -:1021C000C90108950895CF93DF93EC018091E80051 -:1021D00083FFA7C0888190E02091F2013091F30144 -:1021E0002817390709F09DC08091EF01813261F015 -:1021F00020F4803209F095C03DC0823209F46DC0F0 -:10220000833209F08EC07DC08091EE01813A09F0E1 -:1022100088C08091E800877F8093E8008091E80083 -:1022200080FFFCCF4C895D896E897F894093F100E6 -:10223000BB27A72F962F852F8093F100CB01AA27CC -:10224000BB278093F100472F5527662777274093B8 -:10225000F100888D8093F100898D8093F1008A8D43 -:102260008093F1008091E8008E778093E800DF9101 -:10227000CF91E3CB8091EE01813209F052C0809181 -:10228000E800877F8093E80005C08091ED018823F6 -:1022900009F447C08091E80082FFF7CF3091F10048 -:1022A0002091F1009091F1008091F1003C8B2D8BF9 -:1022B0009E8B8F8B8091F100888F8091F100898FA8 -:1022C0008091F1008A8F8091E8008B778093E800FD -:1022D000B4DBCE01DF91CF9163C98091EE018132F1 -:1022E00001F58091E800877F8093E800A6DB80916C -:1022F000F0019091F101998B888BCE01DF91CF9104 -:10230000C5C98091EE01813261F48091E800877F38 -:102310008093E80092DB6091F001CE01DF91CF91D4 -:1023200051CFDF91CF9108956F927F928F929F92BC -:10233000AF92BF92CF92DF92EF92FF920F931F93D3 -:10234000CF93DF9300D01F92CDB7DEB77C01ADB63F -:10235000BEB68091E80083FF07C1F701808190E05D -:102360002091F2013091F3012817390709F0FCC0E0 -:102370008091EF01833009F49EC030F4813071F018 -:10238000823009F0F1C0D4C08A3009F4B9C08B3072 -:1023900009F4A2C0893009F0E7C04CC08091EE0179 -:1023A000813A09F0E1C08DB69EB61A8219828091F9 -:1023B000F0011091F1018B83F70140858DB79EB735 -:1023C000841B91090FB6F8949EBF0FBE8DBFCDB68A -:1023D000DEB6EFEFCE1ADE0A360150E060E070E0C4 -:1023E000C601EAD1412F41508E010F5F1F4F960168 -:1023F000BE016D5F7F4FC7010E94EE04F701268189 -:1024000037812115310529F0408550E0B601C90119 -:10241000CAD11092E9008091E800877F8093E8009C -:1024200069817A81C30193D98091E8008B77809389 -:10243000E80039C08091EE01813209F095C08DB677 -:102440009EB60091F4011091F5017090F00160903A -:10245000F1018DB79EB7801B910B0FB6F8949EBF0C -:102460000FBE8DBFCDB6DEB6EFEFCE1ADE0A80917D -:10247000E800877F8093E800B801C601C8D9809141 -:10248000E8008E778093E80021E0711001C020E021 -:1024900030E0021B130B2C0D3D1D462D4150672DC6 -:1024A000C7010E946E04882D992D0FB6F8949EBF27 -:1024B0000FBE8DBF59C08091EE01813A09F054C022 -:1024C0008091E800877F8093E8008091E80080FF9A -:1024D000FCCFF701818540C08091EE01813209F087 -:1024E00043C08091E800877F8093E800A6DA90914E -:1024F000F00181E0911101C080E0F701818734C0D3 -:102500008091EE01813281F58091E800877F809390 -:10251000E80093DA8091F0019091F101882736E08C -:10252000969587953A95E1F7F701958784871CC0C2 -:102530008091EE01813AC1F48091E800877F809319 -:10254000E8008091E80080FFFCCFF7018485958545 -:1025500096958795969587958093F1008091E800F0 -:102560008E778093E80069DA0FB6F894BEBE0FBE8E -:10257000ADBE0F900F900F90DF91CF911F910F91F3 -:10258000FF90EF90DF90CF90BF90AF909F908F9093 -:102590007F906F9008959C01275F3F4FF90127E0DE -:1025A000DF011D922A95E9F721E0FC01218724EF44 -:1025B00031E03587248723E0248361E00196FFC959 -:1025C0004F925F926F927F928F929F92AF92BF9243 -:1025D000CF92DF92EF92FF920F931F93CF93DF93EF -:1025E00000D01F92CDB7DEB77C01ADB6BEB68091EC -:1025F000ED01843009F08FC08091E4009091E500F6 -:10260000F701228533852817390709F484C08181B1 -:102610008F708093E9008091E80085FF7CC06DB6E3 -:102620007EB640858DB79EB7841B91090FB6F8948E -:102630009EBF0FBE8DBFCDB6DEB6EFEFCE1ADE0A5F -:102640001B821A821982460150E060E070E0C601E8 -:10265000B3D08E010F5F1F4F960140E0BE016D5F4A -:102660007F4FC7010E94EE04582EF701848595859F -:10267000892B31F001E010E086859785892B11F0D8 -:1026800000E010E0F701C680D780C114D10489F0C2 -:1026900049815A81B601C40179D0442443940097FA -:1026A00009F4412CF701408550E0B401C6017BD00C -:1026B00001C0412C89819A81892BF9F0511004C005 -:1026C000411002C000FF19C0F701848595859787E6 -:1026D000868781818F708093E9008B81811180933F -:1026E000F10069817A8140E050E0C4010E945A0BF8 -:1026F0008091E8008E778093E8008091E4009091CB -:10270000E500F70193878287862D972D0FB6F89401 -:102710009EBF0FBE8DBF0FB6F894BEBE0FBEADBE3E -:102720000F900F900F90DF91CF911F910F91FF901D -:10273000EF90DF90CF90BF90AF909F908F907F9061 -:102740006F905F904F900895A1E21A2EAA1BBB1BB9 -:10275000FD010DC0AA1FBB1FEE1FFF1FA217B3076D -:10276000E407F50720F0A21BB30BE40BF50B661F83 -:10277000771F881F991F1A9469F760957095809547 -:1027800090959B01AC01BD01CF010895FB01DC01D7 -:1027900004C08D910190801921F441505040C8F738 -:1027A000881B990B0895FB01DC0102C001900D927A -:1027B00041505040D8F70895DC0101C06D9341505D -:0A27C0005040E0F70895F894FFCFB1 -:1027CA0002811000000100000F000000000000005C -:1027DA00008340000001044000000182080000015B -:1027EA00000000000000000000000004080F0801BB -:0E27FA000F0F0F0F000000000000030330203F -:00000001FF diff --git a/plugins/KeyboardioHID/keywords.txt b/plugins/KeyboardioHID/keywords.txt deleted file mode 100644 index 8cf0b01ad2..0000000000 --- a/plugins/KeyboardioHID/keywords.txt +++ /dev/null @@ -1,196 +0,0 @@ -####################################### -# Syntax Coloring Map For HID -####################################### - -####################################### -# Datatypes (KEYWORD1) -####################################### - -####################################### -# Methods and Functions (KEYWORD2) -####################################### - -begin KEYWORD2 -end KEYWORD2 -click KEYWORD2 -move KEYWORD2 -write KEYWORD2 -press KEYWORD2 -isPressed KEYWORD2 -releaseAll KEYWORD2 -buttons KEYWORD2 -xAxis KEYWORD2 -yAxis KEYWORD2 -zAxis KEYWORD2 -rxAxis KEYWORD2 -ryAxis KEYWORD2 -rzAxis KEYWORD2 -dPad1 KEYWORD2 -dPad2 KEYWORD2 -HID_SendReport KEYWORD2 - -####################################### -# Classes (KEYWORD3) -####################################### - -HID KEYWORD3 -Mouse KEYWORD3 -Keyboard KEYWORD3 -RawHID KEYWORD3 -Media KEYWORD3 -System KEYWORD3 -Gamepad1 KEYWORD3 -Gamepad2 KEYWORD3 -Gamepad3 KEYWORD3 -Gamepad4 KEYWORD3 -Joystick1 KEYWORD3 -Joystick2 KEYWORD3 - -####################################### -# Instances (KEYWORD2) -####################################### - -####################################### -# Constants (LITERAL1) -####################################### - -#General -SERIAL_HID_BAUD LITERAL1 - -#Mouse - -MOUSE_LEFT LITERAL1 -MOUSE_RIGHT LITERAL1 -MOUSE_MIDDLE LITERAL1 -MOUSE_PREV LITERAL1 -MOUSE_NEXT LITERAL1 - -#Keyboard - -KEY_LEFT_CTRL LITERAL1 -KEY_LEFT_SHIFT LITERAL1 -KEY_LEFT_ALT LITERAL1 -KEY_LEFT_GUI LITERAL1 -KEY_RIGHT_CTRL LITERAL1 -KEY_RIGHT_SHIFT LITERAL1 -KEY_RIGHT_ALT LITERAL1 -KEY_RIGHT_GUI LITERAL1 - -KEY_UP_ARROW LITERAL1 -KEY_DOWN_ARROW LITERAL1 -KEY_LEFT_ARROW LITERAL1 -KEY_RIGHT_ARROW LITERAL1 -KEY_BACKSPACE LITERAL1 -KEY_TAB LITERAL1 -KEY_RETURN LITERAL1 -KEY_ESC LITERAL1 -KEY_INSERT LITERAL1 -KEY_DELETE LITERAL1 -KEY_PAGE_UP LITERAL1 -KEY_PAGE_DOWN LITERAL1 -KEY_HOME LITERAL1 -KEY_END LITERAL1 -KEY_CAPS_LOCK LITERAL1 -KEY_F1 LITERAL1 -KEY_F2 LITERAL1 -KEY_F3 LITERAL1 -KEY_F4 LITERAL1 -KEY_F5 LITERAL1 -KEY_F6 LITERAL1 -KEY_F7 LITERAL1 -KEY_F8 LITERAL1 -KEY_F9 LITERAL1 -KEY_F10 LITERAL1 -KEY_F11 LITERAL1 -KEY_F12 LITERAL1 - -KEY_PRINT LITERAL1 -KEY_SCROLL_LOCK LITERAL1 -KEY_PAUSE LITERAL1 - -#Raw Keyboard definitions - -RAW_KEYBOARD_LEFT_CTRL LITERAL1 -RAW_KEYBOARD_LEFT_SHIFT LITERAL1 -RAW_KEYBOARD_LEFT_ALT LITERAL1 -RAW_KEYBOARD_LEFT_GUI LITERAL1 -RAW_KEYBOARD_RIGHT_CTRL LITERAL1 -RAW_KEYBOARD_RIGHT_SHIFT LITERAL1 -RAW_KEYBOARD_RIGHT_ALT LITERAL1 -RAW_KEYBOARD_RIGHT_GUI LITERAL1 - -RAW_KEYBOARD_UP_ARROW LITERAL1 -RAW_KEYBOARD_DOWN_ARROW LITERAL1 -RAW_KEYBOARD_LEFT_ARROW LITERAL1 -RAW_KEYBOARD_RIGHT_ARROW LITERAL1 -RAW_KEYBOARD_SPACEBAR LITERAL1 -RAW_KEYBOARD_BACKSPACE LITERAL1 -RAW_KEYBOARD_TAB LITERAL1 -RAW_KEYBOARD_RETURN LITERAL1 -RAW_KEYBOARD_ESC LITERAL1 -RAW_KEYBOARD_INSERT LITERAL1 -RAW_KEYBOARD_DELETE LITERAL1 -RAW_KEYBOARD_PAGE_UP LITERAL1 -RAW_KEYBOARD_PAGE_DOWN LITERAL1 -RAW_KEYBOARD_HOME LITERAL1 -RAW_KEYBOARD_END LITERAL1 -RAW_KEYBOARD_CAPS_LOCK LITERAL1 -RAW_KEYBOARD_F1 LITERAL1 -RAW_KEYBOARD_F2 LITERAL1 -RAW_KEYBOARD_F3 LITERAL1 -RAW_KEYBOARD_F4 LITERAL1 -RAW_KEYBOARD_F5 LITERAL1 -RAW_KEYBOARD_F6 LITERAL1 -RAW_KEYBOARD_F7 LITERAL1 -RAW_KEYBOARD_F8 LITERAL1 -RAW_KEYBOARD_F9 LITERAL1 -RAW_KEYBOARD_F10 LITERAL1 -RAW_KEYBOARD_F11 LITERAL1 -RAW_KEYBOARD_F12 LITERAL1 -RAW_KEYBOARD_PRINT LITERAL1 -RAW_KEYBOARD_SCROLL_LOCK LITERAL1 -RAW_KEYBOARD_PAUSE LITERAL1 - -#RawHID -RAWHID_RX_SIZE LITERAL1 -RAWHID_TX_SIZE LITERAL1 - -#Media - -MEDIA_FAST_FORWARD LITERAL1 -MEDIA_REWIND LITERAL1 -MEDIA_NEXT LITERAL1 -MEDIA_PREVIOUS LITERAL1 -MEDIA_STOP LITERAL1 -MEDIA_PLAY_PAUSE LITERAL1 - -MEDIA_VOLUME_MUTE LITERAL1 -MEDIA_VOLUME_UP LITERAL1 -MEDIA_VOLUME_DOWN LITERAL1 - -MEDIA_EMAIL_READER LITERAL1 -MEDIA_CALCULATOR LITERAL1 -MEDIA_EXPLORER LITERAL1 - -MEDIA_BROWSER_HOME LITERAL1 -MEDIA_BROWSER_BACK LITERAL1 -MEDIA_BROWSER_FORWARD LITERAL1 -MEDIA_BROWSER_REFRESH LITERAL1 -MEDIA_BROWSER_BOOKMARKS LITERAL1 - -#System - -SYSTEM_POWER_DOWN LITERAL1 -SYSTEM_SLEEP LITERAL1 -SYSTEM_WAKE_UP LITERAL1 - -#Gamepad -GAMEPAD_DPAD_CENTERED LITERAL1 -GAMEPAD_DPAD_UP LITERAL1 -GAMEPAD_DPAD_UP_RIGHT LITERAL1 -GAMEPAD_DPAD_RIGHT LITERAL1 -GAMEPAD_DPAD_DOWN_RIGHT LITERAL1 -GAMEPAD_DPAD_DOWN LITERAL1 -GAMEPAD_DPAD_DOWN_LEFT LITERAL1 -GAMEPAD_DPAD_LEFT LITERAL1 -GAMEPAD_DPAD_UP_LEFT LITERAL1 diff --git a/plugins/KeyboardioHID/wiring_private.h b/plugins/KeyboardioHID/wiring_private.h new file mode 100644 index 0000000000..5dc7d4bed4 --- /dev/null +++ b/plugins/KeyboardioHID/wiring_private.h @@ -0,0 +1,71 @@ +/* + 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 +#include +#include +#include + +#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__) || defined(__AVR_ATmega128RFA1__) || defined(__AVR_ATmega256RFR2__) +#define EXTERNAL_NUM_INTERRUPTS 8 +#elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644A__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__) +#define EXTERNAL_NUM_INTERRUPTS 3 +#elif defined(__AVR_ATmega32U4__) +#define EXTERNAL_NUM_INTERRUPTS 5 +#else +#define EXTERNAL_NUM_INTERRUPTS 2 +#endif + +typedef void (*voidFuncPtr)(void); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif From a5d7d2eaf6a4d6560ea13358592107a10a0adf81 Mon Sep 17 00:00:00 2001 From: Nico Date: Fri, 21 Nov 2014 18:37:50 +0100 Subject: [PATCH 049/602] Adding Examples + Readme --- plugins/KeyboardioHID/Readme.md | 330 ++++++++++++++++++ .../AdvancedGamepad/AdvancedGamepad.ino | 53 +++ .../AdvancedKeyboard/AdvancedKeyboard.ino | 98 ++++++ .../AdvancedRawHID/AdvancedRawHID.ino | 109 ++++++ .../examples/Gamepad/Gamepad.ino | 87 +++++ .../examples/Keyboard/Keyboard.ino | 84 +++++ .../KeyboardioHID/examples/Media/Media.ino | 58 +++ .../KeyboardioHID/examples/Mouse/Mouse.ino | 47 +++ plugins/KeyboardioHID/examples/Readme.md | 4 + .../KeyboardioHID/examples/System/System.ino | 41 +++ plugins/KeyboardioHID/keywords.txt | 192 ++++++++++ 11 files changed, 1103 insertions(+) create mode 100644 plugins/KeyboardioHID/Readme.md create mode 100644 plugins/KeyboardioHID/examples/AdvancedGamepad/AdvancedGamepad.ino create mode 100644 plugins/KeyboardioHID/examples/AdvancedKeyboard/AdvancedKeyboard.ino create mode 100644 plugins/KeyboardioHID/examples/AdvancedRawHID/AdvancedRawHID.ino create mode 100644 plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino create mode 100644 plugins/KeyboardioHID/examples/Keyboard/Keyboard.ino create mode 100644 plugins/KeyboardioHID/examples/Media/Media.ino create mode 100644 plugins/KeyboardioHID/examples/Mouse/Mouse.ino create mode 100644 plugins/KeyboardioHID/examples/Readme.md create mode 100644 plugins/KeyboardioHID/examples/System/System.ino create mode 100644 plugins/KeyboardioHID/keywords.txt diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md new file mode 100644 index 0000000000..d5bce3b589 --- /dev/null +++ b/plugins/KeyboardioHID/Readme.md @@ -0,0 +1,330 @@ +Arduino HID Project +=================== +Dont you always wanted to turn your Arduino in a Generic HID device like a Keyboard or a Gamepad? +Disappointed that the Uno doesnt support this at all and the Micro/Leonardo only Mouse + Keyboard? + +Introducing the Arduino HID Project that **enables enhanced USB functionality to Arduino Uno, Mega, Leonardo, Micro.** +No need for extra hardware. You just need one of the Arduinos and an USB cable. + +**Main difference is that you can upload new sketches to the Uno/Mega and dont need to reflash the firmware over and over again.** +Before you had to upload a sketch, flash the firmware, test, flash the firmware, upload, flash again. Thats all gone! + +**For the Leonardo/Micro it is 'just' new HID devices, no need for a bootloader (like on Uno/Mega).** + +Note: [Hoodloader Repository moved here.](https://github.com/NicoHood/Hoodloader) + +Features +======== +Use your **Arduino Uno, Mega, Micro, Leonardo or (Pro)Micro** as Generic HID Device and still be able to upload sketches how you are used to do. +This project provides HID libraries for Arduino Uno/Mega (with a new 16u2 bootloader) and Micro/Leonardo. +I also corrected some bugs in the original sources. + +**Software includes:** + +* Arduino HID Uno/Mega library +* Arduino HID Micro/Leonardo library +* Arduino HID Bootloader (Hoodloader) + driver for Uno/Mega +* Arduino as ISP with the 16u2 (Hoodloader only, [more information](https://github.com/NicoHood/Hoodloader)) +* Compatible with Linux/Mac/Windows XP/7/8.1 +* Compatible with IDE 1.0.x - 1.5.7 + +**The following devices are supported:** + +* Keyboard (modifiers + 6 keys pressed at the same time) +* Mouse (5 buttons, move, wheel) +* Media Keys (4 keys for music player, webbrowser and more) +* System Key (for PC standby/shutdown) +* 4 Gamepads (32 buttons, 4 16bit axis, 2 8bit axis, 2 D-Pads) + +**Projects can be found here:** +* [Gamecube to PC adapter](https://github.com/NicoHood/Nintendo) +* [Other projects](http://nicohood.wordpress.com/) + +Version differences +=================== + +| Arduino Uno/Mega | Arduino Leonardo/(Pro)Micro | +|:---------------------------------------|:-----------------------------------| +| HID via Hoodloader on 16u2 | Uses USB core with main MCU (32u4) | +| Serial0 without HID fully usable | Serial0 fully usable | +| Serial0 with HID at baud 115200 only | Serial0 slow + buggy | +| Serial0 with HID fully usable via USB | | +| Serial0 with HID not usable via extern | | +| Uses less flash (Serial Protocol only) | Uses more flash (full USB core) | +| ISP function | No ISP function | + +Over all the Uno/Mega solution gives you more opportunities except that the Serial0 is limited when you use HID. + +Installation Leonardo/Micro/Uno/Mega +==================================== + +#### Leonardo/Micro only +Download the library and [install it](http://arduino.cc/en/pmwiki.php?n=Guide/Libraries) like you are used to. + +**For the whole Project IDE 1.5.7 or higher is recommended!** + +**Edit HID.h to de/activate usb functions.** +By default Mouse, Keyboard, Media, System, Gamepad1 is activated. + +Each function will take some flash, +so if you want to save flash deactivate everything you dont need. +You cannot use more than 255 bytes HID report on the Leonardo/Micro. +The number after each definition tells you the size of each report. +I have no idea why you cannot use more than 255 bytes (yet), its a bug in the Arduino code. + +#### Uno/Mega only +Download the library and [install it](http://arduino.cc/en/pmwiki.php?n=Guide/Libraries) like you are used to. + +**For the whole Project IDE 1.5.7 or higher is recommended!** + +To install the new bootloader connect your Arduino to your PC via USB and see +[Hoodloader installing instructions](https://github.com/NicoHood/Hoodloader). +No special programmer needed, just an USB cable. +**You can always switch back to the original firmware, nothing to break.** + +Edit HID.h to add an extra delay for raspberry pi. This is a workaround to fix this for slower PCs. There is still a problem with Raspberry. + +Usage +===== +You are ready to use the libraries. **Just have a look at the examples and test it out.** They are pretty much self explaining. +All examples use a button on pin 8 and show the basic usage of the libraries. +The libraries will work for all Arduinos listed above but it will use 2 different HID libraries (automatically). +For Keyboard + Mouse usage also see the [official documentation](http://arduino.cc/en/pmwiki.php?n=Reference/MouseKeyboard). + +**#include is now needed for every device.** + +**On Arduino/Mega you can only use baud 115200 for HID** due to speed/programming reasons. +Use Serial.begin(SERIAL_HID_BAUD); as typedef to start Serial at baud 115200. +Its not bad anyway because its the fastest baud and you want fast HID recognition. +You still can **fully use any other baud** for normal sketches but HID wont work. +If you try nevertheless it will output Serial crap to the monitor. + +**Always release buttons to not cause any erros.** Replug USB cable to reset the values if anything went wrong. +On Windows every USB report will reset when you open the lock screen. +See [deactivate HID function (Hoodloader only)](https://github.com/NicoHood/Hoodloader) how to disable HID again. + +For Arduino as ISP usage (optional, Hoodloader only, has nothing to do with HID function) +see [Hoodloader repository](https://github.com/NicoHood/Hoodloader). + +Updating to a newer Version +=========================== +HID library: + +To upgrade to v1.8 you need to redownload the Arduino IDE files, restore the original files and install the library like you are used to. +You library is now located in sketchbook/libraries/HID/ +Its now way easier to install the library, no need to replace system files. For further releases just replace all files again. + +**Restart the IDE** + +Hoodloader (Not needed for Leonardo/Micro): + +Just upload the new hex file and check the HID Project if the HID library code has changed and replace the new files too. +You normally dont need to reinstall the drivers for windows if the changelog dosnt note anything. +Versions below 1.5 might need the new drivers. + +How it works +============ +For the Leonardo/Micro its just a modified version of the HID descriptor and Classes for the new devices. +Its not that complicated, everything you need is in the main 4 .h/cpp files. + +For the Uno/Mega you need a special Bootloader. Why? See [Hoodloader repository](https://github.com/NicoHood/Hoodloader). +To sum it up: Serial information is grabbed by the "man in the middle, 16u2" and you dont have to worry to get any wrong Serial stuff via USB. +Thatswhy you need a special baud (115200) that both sides can communicate with each other. +Every USB command is send via a special [NicoHood Protocol](https://github.com/NicoHood/NicoHoodProtocol) +that's filtered out by the 16u2. If you use Serial0 for extern devices it cannot filter the signal of course. +You can still use the NHP, just dont use the reserved Address 1. + +This project wouldnt be possible without +======================================== + +* [Lufa 140302 from Dean Camera](http://www.fourwalledcubicle.com/LUFA.php) +* [Darran's HID Projects] (https://github.com/harlequin-tech/arduino-usb) +* [Connor's Joystick for the Leonardo](http://www.imaginaryindustries.com/blog/?p=80) +* [Stefan Jones Multimedia Keys Example](http://stefanjones.ca/blog/arduino-leonardo-remote-multimedia-keys/) +* [Athanasios Douitsis Multimedia Keys Example](https://github.com/aduitsis/ardumultimedia) +* [The Original Arduino Sources](https://github.com/arduino/Arduino/tree/master/hardware/arduino/firmwares/atmegaxxu2/arduino-usbserial) +* [USBlyzer](http://www.usblyzer.com/) +* A lot of searching through the web +* The awesome official Arduino IRC chat! +* [The NicoHood Protocol ^.^](https://github.com/NicoHood/NicoHoodProtocol) +* For donations please contact me on my blog :) + +Ideas for the future +==================== +* Add more devices (even more?) +* Add Midi (no more free Endpoints, possible on 32u4) +* Add HID rumble support (very hard) +* Add Xbox Support (too hard) +* Add Report Out function (for Keyboard Leds etc) + +Known Bugs +========== +See [Hoodloader repository](https://github.com/NicoHood/Hoodloader) for Hoodloader related Bugs/Issues. + +System Wakeup is currently not working on all versions! +System Shutdown is only working on Windows systems. + +RawHID only works on Uno/Mega. It still has some bugs. + +Feel free to open an Issue on Github if you find a bug. Or message me via my [blog](http://nicohood.wordpress.com/)! + +Known Issues +============ + +**Do not name your sketch HID.ino, this wont work!** + +Opening the examples with doubleclick doesnt work, starting from IDE does. + +**Do not use HID in interrupts because it uses Serial (Hoodloader only). Your Arduino can crash!** + +**If you get a checksum error after uploading please message me and send me the whole project.** +Same if your Arduino crashes and dont want to upload sketches anymore (Replug usb fixes this). +These bugs occurred while developing the bootloader and should be fixed. Just in case it happens again I noted it here. +USB can behave weird, so please check your code for errors first. If you cannot find a mistake open a Github issue. + +**If You have weird Problems especially with controllers, let me know.** +Sometimes the problem is just that Windows messes up the PID so you might want to compile the hoodloader with a different PID +or reinstall the drivers. + +XBMC 13.1 (a Media Center) uses Gamepad input. Its seems to not work and may cause weird errors. +Even with a standard Gamepad I have these errors. Just want to mention it here. + +Not tested on the 8u2, lite version should work with flashing via ISP. + +Not tested on the Due (message me if it works!) + +The USB implementation of the Leonardo/Micro is not that good it can cause errors or disconnects with massiv Serial input. +This has nothing to do with this library! For example Adalight dosnt work well for me, +so you better use an Arduino Uno with Hoodloader for Mediacenter control and Ambilight. + +Version History +=============== +``` +1.8 Beta Release (26.08.2014) +* Changes in the Hoodloader: + * **Huge improvements**, see [Hoodloader repository](https://github.com/NicoHood/Hoodloader) + * Reworked the whole library, easy installation now + * HID fixes for Media Keys/Ubuntu + * Removed Joystick, added 4 Gamepads + +1.7.3 Beta Release (10.08.2014) +* Changes in the Hoodloader: + * Fixed HID flush bug (1.6 - 1.7.2) + +1.7.2 Beta Release (10.08.2014) +* Changes in the Hoodloader: + * Added Lite version for 8u2 + * Added Versions that show up as Uno/Mega (not recommended) + * Makefile and structure changes + +1.7.1 Beta Release (10.08.2014) +* Changes in the Hoodloader: + * Fixed HID deactivation bug + +1.7 Beta Release (10.08.2014) +* Changes in the Hoodloader: + * Works as ISP now. See the [Hoodloader Repository](https://github.com/NicoHood/Hoodloader) for more information. + * Exceeded 8kb limit. For flashing a 8u2 use v1.6 please! +* Changed Readme text + +1.6 Beta Release (09.08.2014) +* Bugfixes in the Hoodloader: + * Changed HID management (not blocking that much, faster) + * added RawHID in/out (HID to Serial) +* Added RawHID Class and example + +1.5 Beta Release (21.07.2014) +* Moved Hoodloader source to a [separate Github page](https://github.com/NicoHood/Hoodloader) +* Bugfixes in the Hoodloader: + * Firmware is still available here + * Overall a lot of ram improvements, now with a big global union of ram + * Removed USBtoUSART buffer (not needed, saved 128/500 bytes) + * Removed Lite version because of better ram usage not needed + * Separated different modes better to not cause any errors in default mode + * Improved the deactivate option + * Integrated NHP directly + * Replaced LightweightRingbuffer with native Lufa Ringbuffer + * Improved writing to CDC Host + * Fixed a bug in checkNHPProtocol: & needs to be a == + * General structure changes + * Improved stability + * Fixed Arduino as ISP bug + +1.4.1 Beta Release (10.07.2014) +* #define Bugfix in USBAPI.h + +1.4 Beta Release (10.07.2014) +* Bugfixes in the Hoodloader: + * Added Lite Version with less ram usage + * Changed PIDs, edited driver file +* merged v1.0.x and v1.5.x together (both are compatible!) +* added IDE v1.5.7 support +* added Tutorials + +1.3 Beta Release (01.07.2014) +* Bugfixes in the Hoodloader: + * Improved ram usage (you can get even better but that messes up code and increases flash) +* **Important NHP fix inside the HID Class for Uno/Mega** + +1.2 Beta Release (22.06.2014) +* Added 1.0.x/1.5.x support +* Bugfixes in the Hoodloader: + * Sometimes HID Devices weren't updating when using more than 1 Device (set forcewrite to true) + * Fast updates crashed the bootloader (too much ram usage, set CDC buffer from 128b to 100b each) +* Minor file structure changes + +1.1 Beta Release (05.06.2014) +* Added Leonardo/Micro support +* Included NicoHoodProtocol +* Minor fixes + +1.0 Beta Release (03.06.2014) +``` + +Licence and Copyright +===================== +If you use this library for any cool project let me know! + +``` +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +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. +``` + +For Developers +============== +If you deactivate some reports it can occur that windows will cause problems and recognize it as different device. +While developing I had that much trouble that I had to change the PID. No way to repair the broken windows driver settings. +So be careful if you change the source on your own with important PIDs. (Therefore I made a 2nd Lite Version with a different PID and more ram) +Therefore reinstall the divers for any device or just dont touch the HID reports in the Bootloader. +The Leonardo/Micro version worked fine till now. + +See this how to uninstall the drivers: +https://support.microsoft.com/kb/315539 + +The Hootloader was coded with Windows7 and Visual Studio and compiled with a Raspberry Pi. +Lufa version 140302 is included! +**To recompile see instructions in [Hoodloader Repository](https://github.com/NicoHood/Hoodloader).** + +The difference between the Leonardo/Micro and Uno/Mega is that the HID Class is different. All other classes are the same. +The Leonardo/Micro Version uses USBAPI.h and no Serial while the Uno/Mega Version uses Serial. +You can also modify the library to send HID reports to other devices/other serials. +Just modify the HID Class (#define HID_SERIAL Serial). + diff --git a/plugins/KeyboardioHID/examples/AdvancedGamepad/AdvancedGamepad.ino b/plugins/KeyboardioHID/examples/AdvancedGamepad/AdvancedGamepad.ino new file mode 100644 index 0000000000..eef660d9df --- /dev/null +++ b/plugins/KeyboardioHID/examples/AdvancedGamepad/AdvancedGamepad.ino @@ -0,0 +1,53 @@ +/* + Copyright (c) 2014 NicoHood + See the readme for credit to other people. + + Advanced Gamepad example + */ + +// include HID library +#include + +// see HID_Reports.h for all data structures +HID_GamepadReport_Data_t Gamepadreport; + +const int pinLed = LED_BUILTIN; +const int pinButton = 2; + +// see HID_Reports.h for all data structures +HID_GamepadReport_Data_t Gamepadreport; + +void setup() { + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); + + // Sends a clean report to the host. This is important on any Arduino type. + // Make sure all desired USB functions are activated in USBAPI.h! + memset(&Gamepadreport, 0, sizeof(Gamepadreport)); + HID_SendReport(HID_REPORTID_Gamepad1Report, &Gamepadreport, sizeof(Gamepadreport)); +} + +void loop() { + if (!digitalRead(pinButton)) { + digitalWrite(pinLed, HIGH); + + // This demo is actually made for advanced users to show them how they can write an own report. + // This might be useful for a Gamepad if you want to edit the values direct on your own. + + // count with buttons binary + static uint32_t count = 0; + Gamepadreport.whole32[0] = count++; + + // move x/y Axis to a new position (16bit) + Gamepadreport.whole16[2] = (random(0xFFFF)); + + // functions before only set the values + // this writes the report to the host + HID_SendReport(HID_REPORTID_Gamepad1Report, &Gamepadreport, sizeof(Gamepadreport)); + + // simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } +} + diff --git a/plugins/KeyboardioHID/examples/AdvancedKeyboard/AdvancedKeyboard.ino b/plugins/KeyboardioHID/examples/AdvancedKeyboard/AdvancedKeyboard.ino new file mode 100644 index 0000000000..e6d71cfa8d --- /dev/null +++ b/plugins/KeyboardioHID/examples/AdvancedKeyboard/AdvancedKeyboard.ino @@ -0,0 +1,98 @@ +/* + Copyright (c) 2014 NicoHood + See the readme for credit to other people. + + Advanced Keyboard example + + This demo is actually made for advanced users to show them how they can write an own report. + This might be useful for a Keyboard if you only use one key, + because the library has a lot of code for simple use + */ + +const int pinLed = LED_BUILTIN; +const int pinButton = 2; + +void setup() { + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); + + // Sends a clean report to the host. This is important on any Arduino type. + // Make sure all desired USB functions are activated in USBAPI.h! + pressRawKeyboard(0, 0); +} + +void loop() { + if (!digitalRead(pinButton)) { + digitalWrite(pinLed, HIGH); + + // press normal keys (a-z, A-Z, 0-9) + pressRawKeyboard(0, RAW_KEYBOARD_KEY('a')); //modifiers + a + pressRawKeyboard(0, RAW_KEYBOARD_KEY('Z')); //modifiers + Z + + // press STRG + ALT + DEL on keyboard (see usb documentation for more) + //pressRawKeyboard(RAW_KEYBOARD_LEFT_CTRL | RAW_KEYBOARD_LEFT_ALT , RAW_KEYBOARD_DELETE); //modifiers + key + + // release! Important + pressRawKeyboard(0, 0); + + // simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } +} + +void pressRawKeyboard(uint8_t modifiers, uint8_t key) { + uint8_t keys[8] = { + modifiers, 0, key, 0, 0, 0, 0, 0 + }; //modifiers, reserved, key[0] + HID_SendReport(HID_REPORTID_KeyboardReport, keys, sizeof(keys)); +} + +/* +See Hut1_12v2.pdf Chapter 10 (Page 53) for more Keys + (especially a-z, a=0x04 z=29) + Definitions: + + RAW_KEYBOARD_LEFT_CTRL + RAW_KEYBOARD_LEFT_SHIFT + RAW_KEYBOARD_LEFT_ALT + RAW_KEYBOARD_LEFT_GUI + RAW_KEYBOARD_RIGHT_CTRL + RAW_KEYBOARD_RIGHT_SHIFT + RAW_KEYBOARD_RIGHT_ALT + RAW_KEYBOARD_RIGHT_GUI + + RAW_KEYBOARD_KEY(key) + + RAW_KEYBOARD_UP_ARROW + RAW_KEYBOARD_DOWN_ARROW + RAW_KEYBOARD_LEFT_ARROW + RAW_KEYBOARD_RIGHT_ARROW + RAW_KEYBOARD_SPACEBAR + RAW_KEYBOARD_BACKSPACE + RAW_KEYBOARD_TAB + RAW_KEYBOARD_RETURN + RAW_KEYBOARD_ESC + RAW_KEYBOARD_INSERT + RAW_KEYBOARD_DELETE + RAW_KEYBOARD_PAGE_UP + RAW_KEYBOARD_PAGE_DOWN + RAW_KEYBOARD_HOME + RAW_KEYBOARD_END + RAW_KEYBOARD_CAPS_LOCK + RAW_KEYBOARD_F1 + RAW_KEYBOARD_F2 + RAW_KEYBOARD_F3 + RAW_KEYBOARD_F4 + RAW_KEYBOARD_F5 + RAW_KEYBOARD_F6 + RAW_KEYBOARD_F7 + RAW_KEYBOARD_F8 + RAW_KEYBOARD_F9 + RAW_KEYBOARD_F10 + RAW_KEYBOARD_F11 + RAW_KEYBOARD_F12 + RAW_KEYBOARD_PRINT + RAW_KEYBOARD_SCROLL_LOCK + RAW_KEYBOARD_PAUSE + */ \ No newline at end of file diff --git a/plugins/KeyboardioHID/examples/AdvancedRawHID/AdvancedRawHID.ino b/plugins/KeyboardioHID/examples/AdvancedRawHID/AdvancedRawHID.ino new file mode 100644 index 0000000000..202e3b28ee --- /dev/null +++ b/plugins/KeyboardioHID/examples/AdvancedRawHID/AdvancedRawHID.ino @@ -0,0 +1,109 @@ +/* + Copyright (c) 2014 NicoHood + See the readme for credit to other people. + + Advanced RawHID example + + Shows how to send bytes via raw HID + Press a button to send some example values. + Keep in mind that you can only send full data packets, the rest is filled with zero! + + Definitions from HID_Reports.h: + RAWHID_USAGE_PAGE 0xFFC0 // recommended: 0xFF00 to 0xFFFF + RAWHID_USAGE 0x0C00 // recommended: 0x0100 to 0xFFFF + RAWHID_TX_SIZE 15 // 1 byte for report ID + RAWHID_RX_SIZE 15 // 1 byte for report ID + */ + +const int pinLed = LED_BUILTIN; +const int pinButton = 2; + +void setup() { + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); + + // no begin function needed for RawHID + // Make sure all desired USB functions are activated in USBAPI.h! +} + +void loop() { + if (!digitalRead(pinButton)) { + digitalWrite(pinLed, HIGH); + + // direct without library. Always send RAWHID_RX_SIZE bytes! + uint8_t buff[RAWHID_RX_SIZE]; // unitialized, has random values + HID_SendReport(HID_REPORTID_RawKeyboardReport, buff, sizeof(buff)); + + // with library + memset(&buff, 42, sizeof(buff)); + RawHID.write(buff, sizeof(buff)); + + // write a single byte, will fill the rest with zeros + RawHID.write(0xCD); + + // huge buffer with library, will fill the rest with zeros + uint8_t megabuff[64]; + for (int i = 0; i < sizeof(megabuff); i++) + megabuff[i] = i; + RawHID.write(megabuff, sizeof(megabuff)); + + // You can use print too, but better dont use a linefeed + RawHID.println("Hello World"); + + // And compare it to write: + RawHID.write("Hello World\r\n"); + + // simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } +} + +/* +Expected output: + +// manual with unintialized buff +recv 15 bytes: +01 55 C1 FF 01 01 01 00 00 01 00 00 01 00 20 + +// filled buff +recv 15 bytes: +2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A + +// single byte filled with zero +recv 15 bytes: +CD 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +// huge buffer filled with zero at the end +recv 15 bytes: +00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E + +recv 15 bytes: +0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D + +recv 15 bytes: +1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C + +recv 15 bytes: +2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B + +recv 15 bytes: +3C 3D 3E 3F 00 00 00 00 00 00 00 00 00 00 00 + +// print +recv 15 bytes: +48 65 6C 6C 6F 20 57 6F 72 6C 64 00 00 00 00 + +//\r +recv 15 bytes: +0D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +//\n +recv 15 bytes: +0A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +//write +recv 15 bytes: +48 65 6C 6C 6F 20 57 6F 72 6C 64 0D 0A 00 00 + +*/ \ No newline at end of file diff --git a/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino b/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino new file mode 100644 index 0000000000..cc81ecc506 --- /dev/null +++ b/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino @@ -0,0 +1,87 @@ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +Gamepad example + +Press a button and demonstrate Gamepad actions +*/ + +const int pinLed = LED_BUILTIN; +const int pinButton = 2; + +void setup() { + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); + + // Sends a clean report to the host. This is important on any Arduino type. + // Make sure all desired USB functions are activated in USBAPI.h! + Gamepad.begin(); +} + +void loop() { + if (!digitalRead(pinButton)) { + digitalWrite(pinLed, HIGH); + + // press button 1-32 and reset (34 becaue its written later) + static uint8_t count = 1; + Gamepad.press(count++); + if (count == 34) { + Gamepad.releaseAll(); + count = 1; + } + + // move x/y Axis to a new position (16bit) + Gamepad.xAxis(random(0xFFFF)); + Gamepad.yAxis(analogRead(A0) << 6); + + // go through all dPad positions + // values: 0-8 (0==centred) + static uint8_t dpad1 = GAMEPAD_DPAD_CENTERED; + Gamepad.dPad1(dpad1++); + if(dpad1>GAMEPAD_DPAD_UP_LEFT) dpad1 = GAMEPAD_DPAD_CENTERED; + static int8_t dpad2 = GAMEPAD_DPAD_CENTERED; + Gamepad.dPad2(dpad2--); + if(dpad2 Date: Fri, 21 Nov 2014 18:39:36 +0100 Subject: [PATCH 050/602] Added 16u2 Compatibility + New HID Cores --- plugins/KeyboardioHID/CDC.cpp | 28 +- plugins/KeyboardioHID/HID.cpp | 660 +++++++---------- plugins/KeyboardioHID/USBAPI.h | 951 +++++++++++++++++++++++-- plugins/KeyboardioHID/USBCore.cpp | 219 ++++-- plugins/KeyboardioHID/USBDesc.h | 27 + plugins/KeyboardioHID/wiring_private.h | 4 +- 6 files changed, 1344 insertions(+), 545 deletions(-) diff --git a/plugins/KeyboardioHID/CDC.cpp b/plugins/KeyboardioHID/CDC.cpp index 5d4f2a0808..1c4672fa90 100644 --- a/plugins/KeyboardioHID/CDC.cpp +++ b/plugins/KeyboardioHID/CDC.cpp @@ -16,6 +16,29 @@ ** SOFTWARE. */ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +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 "USBAPI.h" #include @@ -50,8 +73,9 @@ const CDCDescriptor _cdcInterface = // 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) + // edit by NicoHood + D_ENDPOINT(USB_ENDPOINT_OUT(CDC_ENDPOINT_OUT),USB_ENDPOINT_TYPE_BULK,USB_EP_SIZE,0), + D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_IN ),USB_ENDPOINT_TYPE_BULK,USB_EP_SIZE,0) }; int WEAK CDC_GetInterface(u8* interfaceNum) diff --git a/plugins/KeyboardioHID/HID.cpp b/plugins/KeyboardioHID/HID.cpp index 75c37b24b2..27f3150a9b 100644 --- a/plugins/KeyboardioHID/HID.cpp +++ b/plugins/KeyboardioHID/HID.cpp @@ -1,19 +1,42 @@ -/* 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. +/* 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. +*/ + +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +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 "USBAPI.h" @@ -21,117 +44,205 @@ #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) - +#ifdef HID_MOUSE_ENABLED + // 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, HID_REPORTID_MouseReport,// REPORT_ID + // 5 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) + 0x95, 0x05, // REPORT_COUNT (5) + 0x75, 0x01, // REPORT_SIZE (1) + 0x81, 0x02, // INPUT (Data,Var,Abs) + // reserved + 0x95, 0x01, // REPORT_COUNT (1) + 0x75, 0x03, // REPORT_SIZE (3) + 0x81, 0x03, // INPUT (Cnst,Var,Abs) + // x, y, wheel + 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) + // end + 0xc0, // END_COLLECTION + 0xc0, // END_COLLECTION +#endif + +#ifdef HID_KEYBOARD_ENABLED + // Keyboard + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x06, // USAGE (Keyboard) + 0xa1, 0x01, // COLLECTION (Application) + 0x85, HID_REPORTID_KeyboardReport, // REPORT_ID + 0x05, 0x07, // USAGE_PAGE (Keyboard) + // modifiers 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) - + 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) - + 0x81, 0x02, // INPUT (Data,Var,Abs) + // reserved byte + 0x95, 0x01, // REPORT_COUNT (1) + 0x75, 0x08, // REPORT_SIZE (8) + 0x81, 0x03, // INPUT (Cnst,Var,Abs) + // Key[6] Array 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) - + 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 + 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application) + 0x81, 0x00, // INPUT (Data,Ary,Abs) + // LEDs for num lock etc + //0x05, 0x08, /* USAGE_PAGE (LEDs) */ + //0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */ + //0x29, 0x05, /* USAGE_MAXIMUM (Kana) */ + //0x95, 0x05, /* REPORT_COUNT (5) */ + //0x75, 0x01, /* REPORT_SIZE (1) */ + //0x91, 0x02, /* OUTPUT (Data,Var,Abs) */ + // Reserved 3 bits + //0x95, 0x01, /* REPORT_COUNT (1) */ + //0x75, 0x03, /* REPORT_SIZE (3) */ + //0x91, 0x03, /* OUTPUT (Cnst,Var,Abs) */ + // end + 0xc0, // END_COLLECTION +#endif -#ifdef RAWHID_ENABLED - // RAW HID +#ifdef HID_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 + 0xA1, 0x01, // Collection 0x01 + 0x85, HID_REPORTID_RawKeyboardReport, // REPORT_ID + 0x75, 0x08, // report size = 8 bits + 0x15, 0x00, // logical minimum = 0 + 0x26, 0xFF, 0x00, // logical maximum = 255 + + 0x95, RAWHID_TX_SIZE, // report count TX + 0x09, 0x01, // usage + 0x81, 0x02, // Input (array) + + 0x95, RAWHID_RX_SIZE, // report count RX + 0x09, 0x02, // usage + 0x91, 0x02, // Output (array) + 0xC0, // end collection +#endif - 0x95, 64, // report count TX - 0x09, 0x01, // usage - 0x81, 0x02, // Input (array) +#ifdef HID_MEDIA_ENABLED + // Media + 0x05, 0x0C, // usage page (consumer device) + 0x09, 0x01, // usage -- consumer control + 0xA1, 0x01, // collection (application) + 0x85, HID_REPORTID_MediaReport, // report id + //0x05, 0x0C, // usage page (consumer) + + // 4 media Keys + 0x15, 0x00, //logical minimum + 0x26, 0xFF, 0x03, //logical maximum (3ff) + 0x19, 0x00, // usage minimum (0) + 0x2A, 0xFF, 0x03, //usage maximum (3ff) + 0x95, 0x04, //report count (4) + 0x75, 0x10, //report size (16) + + 0x81, 0x00, //input + 0xC0, //end collection +#endif - 0x95, 64, // report count RX - 0x09, 0x02, // usage - 0x91, 0x02, // Output (array) - 0xC0 // end collection +#ifdef HID_SYSTEM_ENABLED + // System + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x80, // USAGE (System Control) + 0xa1, 0x01, // COLLECTION (Application) + 0x85, HID_REPORTID_SystemReport, // REPORT_ID + // 1 system key + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255) + 0x19, 0x00, // USAGE_MINIMUM (Undefined) + 0x29, 0xff, // USAGE_MAXIMUM (System Menu Down) + 0x95, 0x01, // REPORT_COUNT (1) + 0x75, 0x08, // REPORT_SIZE (8) + 0x81, 0x00, // INPUT (Data,Ary,Abs) + 0xc0, // END_COLLECTION +#endif + +#ifdef HID_GAMEPAD_ENABLED + // Gamepad + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x04, // USAGE (Joystick) + 0xa1, 0x01, // COLLECTION (Application) + 0x85, HID_REPORTID_GamepadReport, // REPORT_ID + // 32 Buttons + 0x05, 0x09, // USAGE_PAGE (Button) + 0x19, 0x01, // USAGE_MINIMUM (Button 1) + 0x29, 0x20, // USAGE_MAXIMUM (Button 32) + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x25, 0x01, // LOGICAL_MAXIMUM (1) + 0x75, 0x01, // REPORT_SIZE (1) + 0x95, 0x20, // REPORT_COUNT (32) + 0x81, 0x02, // INPUT (Data,Var,Abs) + // 4 16bit Axis + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0xa1, 0x00, // COLLECTION (Physical) + 0x09, 0x30, // USAGE (X) + 0x09, 0x31, // USAGE (Y) + 0x09, 0x33, // USAGE (Rx) + 0x09, 0x34, // USAGE (Ry) + 0x16, 0x00, 0x80, // LOGICAL_MINIMUM (-32768) + 0x26, 0xFF, 0x7F, // LOGICAL_MAXIMUM (32767) + 0x75, 0x10, // REPORT_SIZE (16) + 0x95, 0x04, // REPORT_COUNT (4) + 0x81, 0x02, // INPUT (Data,Var,Abs) + // 2 8bit Axis + 0x09, 0x32, // USAGE (Z) + 0x09, 0x35, // USAGE (Rz) + 0x15, 0x80, // LOGICAL_MINIMUM (-128) + 0x25, 0x7F, // LOGICAL_MAXIMUM (127) + 0x75, 0x08, // REPORT_SIZE (8) + 0x95, 0x02, // REPORT_COUNT (2) + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0xc0, // END_COLLECTION + // 2 Hat Switches + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x39, // USAGE (Hat switch) + 0x09, 0x39, // USAGE (Hat switch) + 0x15, 0x01, // LOGICAL_MINIMUM (1) + 0x25, 0x08, // LOGICAL_MAXIMUM (8) + 0x95, 0x02, // REPORT_COUNT (2) + 0x75, 0x04, // REPORT_SIZE (4) + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0xc0, // END_COLLECTION #endif }; extern const HIDDescriptor _hidInterface PROGMEM; const HIDDescriptor _hidInterface = { - D_INTERFACE(HID_INTERFACE,1,3,0,0), + 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) + // edit by NicoHood + D_ENDPOINT(USB_ENDPOINT_IN(HID_ENDPOINT_INT), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) }; //================================================================================ @@ -146,18 +257,18 @@ u8 _hid_idle = 1; int WEAK HID_GetInterface(u8* interfaceNum) { interfaceNum[0] += 1; // uses 1 - return USB_SendControl(TRANSFER_PGM,&_hidInterface,sizeof(_hidInterface)); + return USB_SendControl(TRANSFER_PGM, &_hidInterface, sizeof(_hidInterface)); } int WEAK HID_GetDescriptor(int /* i */) { - return USB_SendControl(TRANSFER_PGM,_hidReportDescriptor,sizeof(_hidReportDescriptor)); + 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); + USB_Send(HID_TX | TRANSFER_RELEASE, data, len); } bool WEAK HID_Setup(Setup& setup) @@ -177,7 +288,7 @@ bool WEAK HID_Setup(Setup& setup) return true; } } - + if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType) { if (HID_SET_PROTOCOL == r) @@ -195,324 +306,77 @@ bool WEAK HID_Setup(Setup& setup) return false; } -//================================================================================ -//================================================================================ -// Mouse +#endif -Mouse_::Mouse_(void) : _buttons(0) -{ -} +#else if defined(USE_USB_API) -void Mouse_::begin(void) +// still provide the weak HID_SendReport function to be able to overwrite it externaly +void __attribute__((weak)) HID_SendReport(uint8_t id, const void* data, int len) { + // the user has to overwrite this if no USB Core is used } -void Mouse_::end(void) -{ -} +#endif /* if defined(USBCON) */ -void Mouse_::click(uint8_t b) -{ - _buttons = b; - move(0,0,0); - _buttons = 0; - move(0,0,0); -} +// HID API libs are only included if the device has USB functionality or if the USE_USB_API is needed +#if defined(USBCON) || defined(USE_USB_API) -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); -} +//================================================================================ +// Mouse +//================================================================================ -void Mouse_::buttons(uint8_t b) -{ - if (b != _buttons) - { - _buttons = b; - move(0,0,0); - } -} +#ifdef HID_MOUSE_ENABLED -void Mouse_::press(uint8_t b) -{ - buttons(_buttons | b); -} +// object instance +Mouse_ Mouse; -void Mouse_::release(uint8_t b) -{ - buttons(_buttons & ~b); -} +#endif + +//================================================================================ +// Keyboard +//================================================================================ + +#ifdef HID_KEYBOARD_ENABLED + +// object instance +Keyboard_ Keyboard; + +#endif -bool Mouse_::isPressed(uint8_t b) -{ - if ((b & _buttons) > 0) - return true; - return false; -} //================================================================================ +// Media //================================================================================ -// Keyboard -Keyboard_::Keyboard_(void) -{ -} +#ifdef HID_MEDIA_ENABLED -void Keyboard_::begin(void) -{ -} +// object instance +Media_ Media; -void Keyboard_::end(void) -{ -} +#endif -void Keyboard_::sendReport(KeyReport* keys) -{ - HID_SendReport(2,keys,sizeof(KeyReport)); -} -extern -const uint8_t _asciimap[128] PROGMEM; +//================================================================================ +// System +//================================================================================ -#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 -}; +#ifdef HID_SYSTEAM_ENABLED -uint8_t USBPutChar(uint8_t c); +// object instance +System_ System; -// 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; -} +#endif -// 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; -} +//================================================================================ +// Gamepad +//================================================================================ -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); -} +#ifdef HID_GAMEPAD_ENABLED -size_t Keyboard_::write(uint8_t c) -{ - uint8_t p = press(c); // Keydown - release(c); // Keyup - return p; // just return the result of press() since release() almost always returns 1 -} +// object instance +Gamepad_ Gamepad; #endif -#endif /* if defined(USBCON) */ +#endif // if defined(USBCON) || defined(USE_USB_API) \ No newline at end of file diff --git a/plugins/KeyboardioHID/USBAPI.h b/plugins/KeyboardioHID/USBAPI.h index 2fab957f93..9270655028 100644 --- a/plugins/KeyboardioHID/USBAPI.h +++ b/plugins/KeyboardioHID/USBAPI.h @@ -15,6 +15,29 @@ 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 + */ + +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +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 __USBAPI__ @@ -32,6 +55,89 @@ typedef unsigned long u32; #include "Arduino.h" +#ifdef USBCON +// include needed HID devices +// the more you activate, the more flash it will take +// by default only Mouse + Keyboard are activated +#define HID_MOUSE_ENABLED +#define HID_KEYBOARD_ENABLED +//#define HID_RAWHID_ENABLED +//#define HID_MEDIA_ENABLED +//#define HID_SYSTEM_ENABLED +//#define HID_GAMEPAD_ENABLED + +// calculate HID report size for each device + +#ifdef HID_MOUSE_ENABLED +#define HID_MOUSE_SIZE 54 +#else +#define HID_MOUSE_SIZE 0 +#endif + +#ifdef HID_KEYBOARD_ENABLED +#define HID_KEYBOARD_SIZE (65-18) //18 for missing led out report = 47 +#else +#define HID_KEYBOARD_SIZE 0 +#endif + +#ifdef HID_RAWHID_ENABLED +#define HID_RAWHID_SIZE 30 +#else +#define HID_RAWHID_SIZE 0 +#endif + +#ifdef HID_MEDIA_ENABLED +#define HID_MEDIA_SIZE 25 +#else +#define HID_MEDIA_SIZE 0 +#endif + +#ifdef HID_SYSTEM_ENABLED +#define HID_SYSTEM_SIZE 24 +#else +#define HID_SYSTEM_SIZE 0 +#endif + +#ifdef HID_GAMEPAD_ENABLED +#define HID_GAMEPAD_SIZE 80 +#else +#define HID_GAMEPAD_SIZE 0 +#endif + +// check if usb descriptor isn't too big for USBCore (seems to not work properly then) +#define HID_DESCRIPTOR_SIZE (HID_MOUSE_SIZE + HID_KEYBOARD_SIZE + HID_RAWHID_SIZE + \ +HID_MEDIA_SIZE + HID_SYSTEM_SIZE + HID_GAMEPAD_SIZE + 0) +#if (HID_DESCRIPTOR_SIZE >= 256) +#error Please do not use HID reports >= 256 bytes. Edit USBAPI.h and remove some devices, please. +#endif + +#else // ifdef USBCON + +// still use USE_USB_API sending API to be able to overwrite the HID_SendReport function +#define USE_USB_API + +// activate all API's +#define HID_MOUSE_ENABLED +#define HID_KEYBOARD_ENABLED +#define HID_RAWHID_ENABLED +#define HID_MEDIA_ENABLED +#define HID_SYSTEM_ENABLED +#define HID_GAMEPAD_ENABLED + +#endif + +/** Enum for the HID report IDs used in the device. */ +typedef enum{ + HID_REPORTID_NotAReport = 0x00, /**< first entry is always zero for multireports */ + HID_REPORTID_MouseReport = 0x01, /**< Report ID for the Mouse report within the device. */ + HID_REPORTID_KeyboardReport = 0x02, /**< Report ID for the Keyboard report within the device. */ + HID_REPORTID_RawKeyboardReport = 0x03, /**< Report ID for the Raw Keyboard report within the device. */ + HID_REPORTID_MediaReport = 0x04, /**< Report ID for the Media report within the device. */ + HID_REPORTID_SystemReport = 0x05, /**< Report ID for the Power report within the device. */ + HID_REPORTID_GamepadReport = 0x06, /**< Report ID for the Gamepad report within the device. */ +} HID_Report_IDs; + +// usb core functions #if defined(USBCON) #include "USBDesc.h" @@ -94,33 +200,177 @@ extern Serial_ Serial; //================================================================================ //================================================================================ -// Mouse +// 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); -#define MOUSE_LEFT 1 -#define MOUSE_RIGHT 2 -#define MOUSE_MIDDLE 4 -#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE) +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); + + +#else if defined(USE_USB_API) + +// still provide the weak HID_SendReport function to be able to overwrite it externaly +void HID_SendReport(uint8_t id, const void* data, int len); + +#endif /* if defined(USBCON) */ + +// HID API libs are only included if the device has USB functionality or if the USE_USB_API is needed +#if defined(USBCON) || defined(USE_USB_API) + +//================================================================================ +// Mouse +//================================================================================ + +#ifdef HID_MOUSE_ENABLED + +#define MOUSE_LEFT 0x01 +#define MOUSE_RIGHT 0x02 +#define MOUSE_MIDDLE 0x04 +#define MOUSE_PREV 0x08 +#define MOUSE_NEXT 0x10 +#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE | MOUSE_PREV | MOUSE_NEXT) + +typedef union{ + // mouse report: 5 buttons, position, wheel + uint8_t whole8[4]; + uint16_t whole16[4 / 2]; + uint32_t whole32[4 / 4]; + + struct{ + uint8_t buttons : 5; + uint8_t reserved : 3; + int8_t xAxis; + int8_t yAxis; + int8_t wheel; + }; +} HID_MouseReport_Data_t; class Mouse_ { +public: + inline Mouse_(void) { + // removed this to avoid creating an instance of Mouse if not needed + // the user should call begin first. + //: _buttons(0){ + // empty + } + + inline void begin(void){ + // release all buttons + end(); + } + + inline void end(void){ + _buttons = 0; + move(0, 0, 0); + } + + inline void click(uint8_t b = MOUSE_LEFT){ + _buttons = b; + move(0, 0, 0); + _buttons = 0; + move(0, 0, 0); + } + + inline void move(signed char x, signed char y, signed char wheel = 0){ + u8 m[4]; + m[0] = _buttons; + m[1] = x; + m[2] = y; + m[3] = wheel; + HID_SendReport(1, m, 4); + } + + inline void press(uint8_t b = MOUSE_LEFT){ + // press LEFT by default + buttons(_buttons | b); + } + + inline void release(uint8_t b = MOUSE_LEFT){ + // release LEFT by default + buttons(_buttons & ~b); + } + + inline bool isPressed(uint8_t b = MOUSE_LEFT){ + // check LEFT by default + if ((b & _buttons) > 0) + return true; + return false; + } + 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 + inline void buttons(uint8_t b){ + if (b != _buttons) + { + _buttons = b; + move(0, 0, 0); + } + } }; extern Mouse_ Mouse; +#endif + + //================================================================================ +// Keyboard //================================================================================ -// Keyboard + +#ifdef HID_KEYBOARD_ENABLED + +//Keyboard fixed/added missing Keys +#define KEY_PRINT 0xCE +#define KEY_SCROLL_LOCK 0xCF +#define KEY_PAUSE 0xD0 #define KEY_LEFT_CTRL 0x80 #define KEY_LEFT_SHIFT 0x81 @@ -159,86 +409,645 @@ extern Mouse_ Mouse; #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; +//Raw Keyboard definitions +#define RAW_KEYBOARD_LEFT_CTRL B00000001 +#define RAW_KEYBOARD_LEFT_SHIFT B00000010 +#define RAW_KEYBOARD_LEFT_ALT B00000100 +#define RAW_KEYBOARD_LEFT_GUI B00001000 +#define RAW_KEYBOARD_RIGHT_CTRL B00010000 +#define RAW_KEYBOARD_RIGHT_SHIFT B00100000 +#define RAW_KEYBOARD_RIGHT_ALT B01000000 +#define RAW_KEYBOARD_RIGHT_GUI B10000000 -class Keyboard_ : public Print +#define RAW_KEYBOARD_KEY(key) ((key>='a' && key<='z') ? (0x04 + key-'a') :\ +(key>='A' && key<='Z') ? (0x04 + key-'A') : (key>='1' && key<='9') ? (0x1E + key-'1') : 0x27) + +#define RAW_KEYBOARD_UP_ARROW 0x52 +#define RAW_KEYBOARD_DOWN_ARROW 0x51 +#define RAW_KEYBOARD_LEFT_ARROW 0x50 +#define RAW_KEYBOARD_RIGHT_ARROW 0x4F +#define RAW_KEYBOARD_SPACEBAR 0x2C +#define RAW_KEYBOARD_BACKSPACE 0x2A +#define RAW_KEYBOARD_TAB 0x2B +#define RAW_KEYBOARD_RETURN 0x28 +#define RAW_KEYBOARD_ESC 0x29 +#define RAW_KEYBOARD_INSERT 0x49 +#define RAW_KEYBOARD_DELETE 0x4C +#define RAW_KEYBOARD_PAGE_UP 0x4B +#define RAW_KEYBOARD_PAGE_DOWN 0x4E +#define RAW_KEYBOARD_HOME 0x4A +#define RAW_KEYBOARD_END 0x4D +#define RAW_KEYBOARD_CAPS_LOCK 0x39 +#define RAW_KEYBOARD_F1 0x3A +#define RAW_KEYBOARD_F2 0x3B +#define RAW_KEYBOARD_F3 0x3C +#define RAW_KEYBOARD_F4 0x3D +#define RAW_KEYBOARD_F5 0x3E +#define RAW_KEYBOARD_F6 0x3F +#define RAW_KEYBOARD_F7 0x40 +#define RAW_KEYBOARD_F8 0x41 +#define RAW_KEYBOARD_F9 0x42 +#define RAW_KEYBOARD_F10 0x43 +#define RAW_KEYBOARD_F11 0x44 +#define RAW_KEYBOARD_F12 0x45 +#define RAW_KEYBOARD_PRINT 0x46 +#define RAW_KEYBOARD_SCROLL_LOCK 0x47 +#define RAW_KEYBOARD_PAUSE 0x48 + +#define SHIFT 0x80 +static const uint8_t _asciimap[128] PROGMEM = { -private: - KeyReport _keyReport; - void sendReport(KeyReport* keys); + 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 +}; + +typedef union{ + // Low level key report: up to 6 keys and shift, ctrl etc at once + uint8_t whole8[8]; + uint16_t whole16[8 / 2]; + uint32_t whole32[8 / 4]; + + struct{ + uint8_t modifiers; + uint8_t reserved; + uint8_t keys[6]; + }; +} HID_KeyboardReport_Data_t; + +class Keyboard_ : public Print{ 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); + inline Keyboard_(void){ + // empty + } + + inline void begin(void){ + end(); + } + + inline void end(void){ + // edit by NicoHood + releaseAll(); + } + + inline size_t write(uint8_t c){ + uint8_t p = press(c); // Keydown + release(c); // Keyup + return (p); // just return the result of press() since release() almost always returns 1 + } + + // 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. + inline size_t 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. + inline size_t 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; + } + + inline void releaseAll(void){ + // release all keys + memset(&_keyReport, 0x00, sizeof(_keyReport)); + sendReport(&_keyReport); + } + +private: + HID_KeyboardReport_Data_t _keyReport; + inline void sendReport(HID_KeyboardReport_Data_t* keys){ + HID_SendReport(HID_REPORTID_KeyboardReport, &_keyReport, sizeof(_keyReport)); + } }; extern Keyboard_ Keyboard; -//================================================================================ -//================================================================================ -// Low level API +#endif -typedef struct -{ - uint8_t bmRequestType; - uint8_t bRequest; - uint8_t wValueL; - uint8_t wValueH; - uint16_t wIndex; - uint16_t wLength; -} Setup; //================================================================================ +// RawHID //================================================================================ -// 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); +#ifdef HID_RAWHID_ENABLED + +#define LSB(_x) ((_x) & 0xFF) +#define MSB(_x) ((_x) >> 8) + +//TODO +#define RAWHID_USAGE_PAGE 0xFFC0 // recommended: 0xFF00 to 0xFFFF +#define RAWHID_USAGE 0x0C00 // recommended: 0x0100 to 0xFFFF +#define RAWHID_TX_SIZE 64 //TODO 16? +#define RAWHID_RX_SIZE 64 +//#define RAWHID_TX_SIZE 15 // 1 byte for report ID +//#define RAWHID_RX_SIZE 15 // 1 byte for report ID + +typedef union{ + // a RAWHID_TX_SIZE byte buffer for rx or tx + uint8_t whole8[RAWHID_TX_SIZE]; + uint16_t whole16[RAWHID_TX_SIZE / 2]; + uint32_t whole32[RAWHID_TX_SIZE / 4]; + uint8_t buff[RAWHID_TX_SIZE]; +} HID_RawKeyboardReport_Data_t; + +class RawHID_ : public Print{ +public: + inline RawHID_(void){ + // empty + } + + inline void begin(void){ + // empty + } + + inline void end(void){ + // empty + } + + using Print::write; // to get the String version of write + inline size_t write(uint8_t b){ + write(&b, 1); + } + + inline size_t write(const uint8_t *buffer, size_t size){ + size_t bytesleft = size; + // first work through the buffer thats already there + while (bytesleft >= RAWHID_RX_SIZE){ + HID_SendReport(HID_REPORTID_RawKeyboardReport, &buffer[size - bytesleft], RAWHID_RX_SIZE); + bytesleft -= RAWHID_RX_SIZE; + } + // write down the other bytes and fill with zeros + if (bytesleft){ + uint8_t rest[RAWHID_RX_SIZE]; + memcpy(rest, &buffer[size - bytesleft], bytesleft); + memset(&rest[bytesleft], 0, RAWHID_RX_SIZE - bytesleft); + HID_SendReport(HID_REPORTID_RawKeyboardReport, &rest, RAWHID_RX_SIZE); + } + } +}; +extern RawHID_ RawHID; + +#endif + //================================================================================ +// Media //================================================================================ -// 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); +#ifdef HID_MEDIA_ENABLED + +// Media key definitions, see official USB docs for more +#define MEDIA_FAST_FORWARD 0xB3 +#define MEDIA_REWIND 0xB4 +#define MEDIA_NEXT 0xB5 +#define MEDIA_PREVIOUS 0xB6 +#define MEDIA_STOP 0xB7 +#define MEDIA_PLAY_PAUSE 0xCD + +#define MEDIA_VOLUME_MUTE 0xE2 +#define MEDIA_VOLUME_UP 0xE9 +#define MEDIA_VOLUME_DOWN 0xEA + +#define MEDIA_EMAIL_READER 0x18A +#define MEDIA_CALCULATOR 0x192 +#define MEDIA_EXPLORER 0x194 + +#define MEDIA_BROWSER_HOME 0x223 +#define MEDIA_BROWSER_BACK 0x224 +#define MEDIA_BROWSER_FORWARD 0x225 +#define MEDIA_BROWSER_REFRESH 0x227 +#define MEDIA_BROWSER_BOOKMARKS 0x22A + +typedef union{ + // every usable media key possible, up to 4 keys presses possible + uint8_t whole8[8]; + uint16_t whole16[8 / 2]; + uint32_t whole32[8 / 4]; + + struct{ + uint16_t key1; + uint16_t key2; + uint16_t key3; + uint16_t key4; + }; +} HID_MediaReport_Data_t; + +class Media_{ +public: + inline Media_(void){ + // empty + } + + inline void begin(void){ + // release all buttons + end(); + } + + inline void end(void){ + memset(&_report, 0, sizeof(_report)); + HID_SendReport(HID_REPORTID_MediaReport, &_report, sizeof(_report)); + } + + inline void write(uint16_t m){ + press(m); + release(m); + } + + inline void press(uint16_t m){ + // search for a free spot + for (int i = 0; i < sizeof(HID_MediaReport_Data_t) / 2; i++) { + if (_report.whole16[i] == 0x00) { + _report.whole16[i] = m; + break; + } + } + HID_SendReport(HID_REPORTID_MediaReport, &_report, sizeof(_report)); + } + + inline void release(uint16_t m){ + // search and release the keypress + for (int i = 0; i < sizeof(HID_MediaReport_Data_t) / 2; i++) { + if (_report.whole16[i] == m) { + _report.whole16[i] = 0x00; + // no break to delete multiple keys + } + } + HID_SendReport(HID_REPORTID_MediaReport, &_report, sizeof(_report)); + } + + inline void releaseAll(void){ + begin(); + } +private: + HID_MediaReport_Data_t _report; +}; +extern Media_ Media; + +#endif + //================================================================================ +// System //================================================================================ -// CSC 'Driver' -int CDC_GetInterface(uint8_t* interfaceNum); -int CDC_GetDescriptor(int i); -bool CDC_Setup(Setup& setup); +#ifdef HID_SYSTEM_ENABLED + +#define SYSTEM_POWER_DOWN 0x81 +#define SYSTEM_SLEEP 0x82 +#define SYSTEM_WAKE_UP 0x83 + +typedef union{ + // every usable system control key possible + uint8_t whole8[1]; + uint8_t key; +} HID_SystemReport_Data_t; + +class System_{ +public: + inline System_(void){ + // empty + } + + inline void begin(void){ + // release all buttons + end(); + } + + inline void end(void){ + uint8_t _report = 0; + HID_SendReport(HID_REPORTID_SystemReport, &_report, sizeof(_report)); + } + + inline void write(uint8_t s){ + press(s); + release(); + } + + inline void press(uint8_t s){ + HID_SendReport(HID_REPORTID_SystemReport, &s, sizeof(s)); + } + + inline void release(void){ + begin(); + } + + inline void releaseAll(void){ + begin(); + } +}; +extern System_ System; + +#endif //================================================================================ +// Gamepad //================================================================================ -#define TRANSFER_PGM 0x80 -#define TRANSFER_RELEASE 0x40 -#define TRANSFER_ZERO 0x20 +#ifdef HID_GAMEPAD_ENABLED -int USB_SendControl(uint8_t flags, const void* d, int len); -int USB_RecvControl(void* d, int len); +// Dpad directions +#define GAMEPAD_DPAD_CENTERED 0 +#define GAMEPAD_DPAD_UP 1 +#define GAMEPAD_DPAD_UP_RIGHT 2 +#define GAMEPAD_DPAD_RIGHT 3 +#define GAMEPAD_DPAD_DOWN_RIGHT 4 +#define GAMEPAD_DPAD_DOWN 5 +#define GAMEPAD_DPAD_DOWN_LEFT 6 +#define GAMEPAD_DPAD_LEFT 7 +#define GAMEPAD_DPAD_UP_LEFT 8 -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); +typedef union { + // 32 Buttons, 6 Axis, 2 D-Pads + uint8_t whole8[15]; + uint16_t whole16[15 / 2]; + uint32_t whole32[15 / 4]; + uint32_t buttons; + + struct{ + uint8_t button1 : 1; + uint8_t button2 : 1; + uint8_t button3 : 1; + uint8_t button4 : 1; + uint8_t button5 : 1; + uint8_t button6 : 1; + uint8_t button7 : 1; + uint8_t button8 : 1; + + uint8_t button9 : 1; + uint8_t button10 : 1; + uint8_t button11 : 1; + uint8_t button12 : 1; + uint8_t button13 : 1; + uint8_t button14 : 1; + uint8_t button15 : 1; + uint8_t button16 : 1; + + uint8_t button17 : 1; + uint8_t button18 : 1; + uint8_t button19 : 1; + uint8_t button20 : 1; + uint8_t button21 : 1; + uint8_t button22 : 1; + uint8_t button23 : 1; + uint8_t button24 : 1; + + uint8_t button25 : 1; + uint8_t button26 : 1; + uint8_t button27 : 1; + uint8_t button28 : 1; + uint8_t button29 : 1; + uint8_t button30 : 1; + uint8_t button31 : 1; + uint8_t button32 : 1; + + int16_t xAxis; + int16_t yAxis; + + int16_t rxAxis; + int16_t ryAxis; + + int8_t zAxis; + int8_t rzAxis; + + uint8_t dPad1 : 4; + uint8_t dPad2 : 4; + }; +} HID_GamepadReport_Data_t; + +class Gamepad_{ +public: + inline Gamepad_(void){ + // empty + } + + inline void begin(void){ + // release all buttons + end(); + } + + inline void end(void){ + memset(&_report, 0, sizeof(_report)); + HID_SendReport(HID_REPORTID_GamepadReport, &_report, sizeof(_report)); + } + + inline void write(void){ HID_SendReport(HID_REPORTID_GamepadReport, &_report, sizeof(_report)); } + inline void press(uint8_t b){ _report.buttons |= (uint32_t)1 << (b - 1); } + inline void release(uint8_t b){ _report.buttons &= ~((uint32_t)1 << (b - 1)); } + inline void releaseAll(void){ memset(&_report, 0x00, sizeof(_report)); } + + inline void buttons(uint32_t b){ _report.buttons = b; } + inline void xAxis(int16_t a){ _report.xAxis = a; } + inline void yAxis(int16_t a){ _report.yAxis = a; } + inline void zAxis(int8_t a){ _report.zAxis = a; } + inline void rxAxis(int16_t a){ _report.rxAxis = a; } + inline void ryAxis(int16_t a){ _report.ryAxis = a; } + inline void rzAxis(int8_t a){ _report.rzAxis = a; } + inline void dPad1(int8_t d){ _report.dPad1 = d; } + inline void dPad2(int8_t d){ _report.dPad2 = d; } +private: + HID_GamepadReport_Data_t _report; +}; +extern Gamepad_ Gamepad; #endif -#endif /* if defined(USBCON) */ +#endif // if defined(USBCON) || defined(USE_USB_API) + +#endif /* if defined(__USBAPI__) */ diff --git a/plugins/KeyboardioHID/USBCore.cpp b/plugins/KeyboardioHID/USBCore.cpp index b4f7bed7e8..b95b50fd59 100644 --- a/plugins/KeyboardioHID/USBCore.cpp +++ b/plugins/KeyboardioHID/USBCore.cpp @@ -1,19 +1,42 @@ -/* 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. +/* 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. +*/ + +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +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 "USBAPI.h" @@ -43,7 +66,7 @@ extern const DeviceDescriptor USB_DeviceDescriptor PROGMEM; extern const DeviceDescriptor USB_DeviceDescriptorA PROGMEM; const u16 STRING_LANGUAGE[2] = { - (3<<8) | (2+2), + (3 << 8) | (2 + 2), 0x0409 // English }; @@ -78,12 +101,13 @@ const u8 STRING_MANUFACTURER[] PROGMEM = USB_MANUFACTURER; #define DEVICE_CLASS 0x00 #endif +//TODO warning from USBlyzer with a 16u2 // DEVICE DESCRIPTOR const DeviceDescriptor USB_DeviceDescriptor = - D_DEVICE(0x00,0x00,0x00,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,0,1); +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); +D_DEVICE(DEVICE_CLASS, 0x00, 0x00, 64, USB_VID, USB_PID, 0x100, IMANUFACTURER, IPRODUCT, 0, 1); //================================================================== //================================================================== @@ -92,40 +116,40 @@ volatile u8 _usbConfiguration = 0; static inline void WaitIN(void) { - while (!(UEINTX & (1< Date: Sat, 22 Nov 2014 12:43:36 +0100 Subject: [PATCH 051/602] Added HoodLoader1&2 examples --- .../HoodLoader1_API_Legacy.ino | 163 ++++++++++++++++++ .../HoodLoader2_SerialKeyboard.ino | 52 ++++++ 2 files changed, 215 insertions(+) create mode 100644 plugins/KeyboardioHID/examples/HoodLoader1_API_Legacy/HoodLoader1_API_Legacy.ino create mode 100644 plugins/KeyboardioHID/examples/HoodLoader2_SerialKeyboard/HoodLoader2_SerialKeyboard.ino diff --git a/plugins/KeyboardioHID/examples/HoodLoader1_API_Legacy/HoodLoader1_API_Legacy.ino b/plugins/KeyboardioHID/examples/HoodLoader1_API_Legacy/HoodLoader1_API_Legacy.ino new file mode 100644 index 0000000000..86182a872b --- /dev/null +++ b/plugins/KeyboardioHID/examples/HoodLoader1_API_Legacy/HoodLoader1_API_Legacy.ino @@ -0,0 +1,163 @@ +/* + Copyright (c) 2014 NicoHood + See the readme for credit to other people. + + Keyboard HoodLoader1 API Legacy example + + Legacy Example on how to access the Serial HID API of HoodLoader1. + This methode is outdated, because you can now control the whole + 16u2 with HoodLoader2. It might be still usefull if you want the 328/2560 + keep control of the USB functions. Keep in mind that there is no such thing + as flushing HID reports. If the USB Host is too slow HID reports might be missed. + + You can also adapt the sending method below to send Mouse/Keyboard/Media/System reports. + Gamepads/RawHID have a general problem with the original HoodLoader1 firmware, so please avoid this. + It might be compatible with the new HoodLoader2 port of the protocol later on. + + HID reports are converted into a special Serial Protocol with NHP. + This sketch should only be used with a 328/2560, not a 16u2. + The 16u2 has a HoodLoader1 compatible sketch/firmware loaded and will + listen to the Serial Port for these Protocol packets on baud 115200. + + The HID_SendReport function is implemented weak, so we can overwrite it + in this sketch below. A simple NHP implementation encapsulated the HID reports + into NHP packets with correct addresses and checksums. + + Press a button to write some text to your pc. + See official documentation for more infos + */ + +// Serial to write Protocol data to. Default: Serial +#define HID_SERIAL Serial +#define SERIAL_HID_BAUD 115200 + +// extra delay for raspberry. Only needed for Hoodloader and slow devices +//#define HID_EXTRADELAY 20 + +const int pinLed = 13; +const int pinButton = 8; + +void setup() { + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); + + // Starts Serial at baud 115200 otherwise HID wont work with HoodLoader1. + // This is not needed for Leonado/(Pro)Micro/16u2(HoodLoader2) + Serial.begin(SERIAL_HID_BAUD); + + // Sends a clean report to the host. This is important on any Arduino type. + // Make sure all desired USB functions are activated in USBAPI.h! + Keyboard.begin(); +} + + +void loop() { + if (!digitalRead(pinButton)) { + digitalWrite(pinLed, HIGH); + + // Same use as the official library, pretty much self explaining + Keyboard.println("This message was sent with my Arduino."); + Serial.println("Serial port is still working and not glitching out"); + + // simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } +} + +//================================================================================ +// NHP +//================================================================================ + +// Start Mask +#define NHP_MASK_START 0xC0 //B11|000000 the two MSB bits +#define NHP_MASK_LEAD 0xC0 //B11|000000 +#define NHP_MASK_DATA 0x00 //B0|0000000 only the first MSB is important +#define NHP_MASK_END 0x80 //B10|000000 + +// Content Mask +#define NHP_MASK_LENGTH 0x38 //B00|111|000 +#define NHP_MASK_COMMAND 0x0F //B0000|1111 +#define NHP_MASK_DATA_7BIT 0x7F //B0|1111111 +#define NHP_MASK_DATA_4BIT 0x0F //B0000|1111 +#define NHP_MASK_DATA_3BIT 0x07 //B00000|111 +#define NHP_MASK_ADDRESS 0x3F //B00|111111 + +// Reserved Addresses +#define NHP_ADDRESS_CONTROL 0x01 + +// Reserved Usages +#define NHP_USAGE_ARDUINOHID 0x01 + +// overwrites the HID_SendReport function which is empty/not used on a 328/2560 +void HID_SendReport(uint8_t id, const void* data, int len) +{ + // write the Report via Protocol and checksum. 16bit for each sending + // send control address + NHPwriteChecksum(NHP_ADDRESS_CONTROL, (NHP_USAGE_ARDUINOHID << 8) | id); + const uint8_t* report = (const uint8_t*)data; + for (int i = 0; i < len; i++) { + uint8_t data0 = report[i++]; + uint8_t data1 = 0; + if (i != len) + data1 = report[i]; + // valid HID reports start at Address 2 + NHPwriteChecksum(2 + i / 2, (data1 << 8) | data0); + } +#ifdef HID_EXTRADELAY + delay(HID_EXTRADELAY); +#endif +} + +// simple copy/modification of the NicoHoodProtocol writechecksum function +void NHPwriteChecksum(uint8_t address, uint16_t indata) { + // writes two bytes with its inverse + uint32_t temp = ~indata; + uint32_t data = (temp << 16) | indata; + + // buffer for write operation + uint8_t writebuffer[6]; + + // start with the maximum size of blocks + uint8_t blocks = 7; + + // check for the first 7 bit block that doesnt fit into the first 3 bits + while (blocks > 2) { + uint8_t nextvalue = (data >> (7 * (blocks - 3))); + + if (nextvalue > NHP_MASK_DATA_3BIT) { + // special case for the MSB + if (blocks == 7) { + writebuffer[0] = nextvalue; + blocks--; + } + // this block is too big, write this into the next data block + break; + } + else { + // write the possible first 3 bits and check again after if zero + writebuffer[0] = nextvalue; + blocks--; + // we have our first bits, stop (nonzero) + if (nextvalue) + break; + } + } + + // write the rest of the data bits + uint8_t datablocks = blocks - 2; + while (datablocks > 0) { + writebuffer[datablocks] = data & NHP_MASK_DATA_7BIT; + data >>= 7; + datablocks--; + } + + // write lead + length mask + writebuffer[0] |= NHP_MASK_LEAD | (blocks << 3); + + // write end mask + writebuffer[blocks - 1] = NHP_MASK_END | ((address - 1) & NHP_MASK_ADDRESS); + + // write the buffer + HID_SERIAL.write(writebuffer, blocks); +} diff --git a/plugins/KeyboardioHID/examples/HoodLoader2_SerialKeyboard/HoodLoader2_SerialKeyboard.ino b/plugins/KeyboardioHID/examples/HoodLoader2_SerialKeyboard/HoodLoader2_SerialKeyboard.ino new file mode 100644 index 0000000000..07051d908d --- /dev/null +++ b/plugins/KeyboardioHID/examples/HoodLoader2_SerialKeyboard/HoodLoader2_SerialKeyboard.ino @@ -0,0 +1,52 @@ +/* + Copyright (c) 2014 NicoHood + See the readme for credit to other people. + + HoodLoader2 SerialKeyboard example + + This sketch should demonstate how to program a basic sketch with HoodLoader2. + It was used to demonstrate that Serial and HID is working properly. + + Open the Serial port, type in anything and see that Serial and Keyboard is working. + See official documentation for more infos. + + Use the F() macro to save strings in PROGMEM to keep ram usage low. + */ + +void setup() { + // start + wait for serial debug in/output + while (!Serial); + Serial.begin(115200); + Serial.println(F("Startup")); + + // Sends a clean report to the host. This is important because + // the 16u2 of the Uno/Mega is not turned off while programming + // so you want to start with a clean report to avoid strange bugs after reset. + Keyboard.begin(); +} + + +void loop() { + if (Serial.available()) { + // discard all Serial bytes to avoid multiple sendings + unsigned long currentMillis = millis(); + while (millis() - currentMillis < 100) { + if (Serial.available()) + Serial.write(Serial.read()); + } + + // print an information back to the serial port + Serial.println(); + Serial.println(F("Serial port working. Printing Text in 3 seconds.")); + + // wait 3 seconds and discard all new in bytes to not crash the Arduino + currentMillis = millis(); + while (millis() - currentMillis < 3000) { + if (Serial.available()) + Serial.write(Serial.read()); + } + + // same use as the official library, pretty much self explaining + Keyboard.print(F("This message was sent with my Arduino.")); + } +} \ No newline at end of file From ae001fdc5fe090f0a036b773fd309f5c00d2cda6 Mon Sep 17 00:00:00 2001 From: Nico Date: Sat, 22 Nov 2014 12:59:13 +0100 Subject: [PATCH 052/602] Rearranged examples --- .../AdvancedGamepad/AdvancedGamepad.ino | 0 .../AdvancedKeyboard/AdvancedKeyboard.ino | 0 .../AdvancedRawHID/AdvancedRawHID.ino | 0 .../HoodLoader1_API_Legacy.ino | 2 +- .../HoodLoader2_NoUSB_Blink.ino | 36 +++++++++++++++++++ .../HoodLoader2_SerialKeyboard.ino | 8 +++-- 6 files changed, 42 insertions(+), 4 deletions(-) rename plugins/KeyboardioHID/examples/{ => Advanced}/AdvancedGamepad/AdvancedGamepad.ino (100%) rename plugins/KeyboardioHID/examples/{ => Advanced}/AdvancedKeyboard/AdvancedKeyboard.ino (100%) rename plugins/KeyboardioHID/examples/{ => Advanced}/AdvancedRawHID/AdvancedRawHID.ino (100%) rename plugins/KeyboardioHID/examples/{ => HoodLoader1}/HoodLoader1_API_Legacy/HoodLoader1_API_Legacy.ino (99%) create mode 100644 plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_NoUSB_Blink/HoodLoader2_NoUSB_Blink.ino rename plugins/KeyboardioHID/examples/{ => HoodLoader2}/HoodLoader2_SerialKeyboard/HoodLoader2_SerialKeyboard.ino (87%) diff --git a/plugins/KeyboardioHID/examples/AdvancedGamepad/AdvancedGamepad.ino b/plugins/KeyboardioHID/examples/Advanced/AdvancedGamepad/AdvancedGamepad.ino similarity index 100% rename from plugins/KeyboardioHID/examples/AdvancedGamepad/AdvancedGamepad.ino rename to plugins/KeyboardioHID/examples/Advanced/AdvancedGamepad/AdvancedGamepad.ino diff --git a/plugins/KeyboardioHID/examples/AdvancedKeyboard/AdvancedKeyboard.ino b/plugins/KeyboardioHID/examples/Advanced/AdvancedKeyboard/AdvancedKeyboard.ino similarity index 100% rename from plugins/KeyboardioHID/examples/AdvancedKeyboard/AdvancedKeyboard.ino rename to plugins/KeyboardioHID/examples/Advanced/AdvancedKeyboard/AdvancedKeyboard.ino diff --git a/plugins/KeyboardioHID/examples/AdvancedRawHID/AdvancedRawHID.ino b/plugins/KeyboardioHID/examples/Advanced/AdvancedRawHID/AdvancedRawHID.ino similarity index 100% rename from plugins/KeyboardioHID/examples/AdvancedRawHID/AdvancedRawHID.ino rename to plugins/KeyboardioHID/examples/Advanced/AdvancedRawHID/AdvancedRawHID.ino diff --git a/plugins/KeyboardioHID/examples/HoodLoader1_API_Legacy/HoodLoader1_API_Legacy.ino b/plugins/KeyboardioHID/examples/HoodLoader1/HoodLoader1_API_Legacy/HoodLoader1_API_Legacy.ino similarity index 99% rename from plugins/KeyboardioHID/examples/HoodLoader1_API_Legacy/HoodLoader1_API_Legacy.ino rename to plugins/KeyboardioHID/examples/HoodLoader1/HoodLoader1_API_Legacy/HoodLoader1_API_Legacy.ino index 86182a872b..546a413e1e 100644 --- a/plugins/KeyboardioHID/examples/HoodLoader1_API_Legacy/HoodLoader1_API_Legacy.ino +++ b/plugins/KeyboardioHID/examples/HoodLoader1/HoodLoader1_API_Legacy/HoodLoader1_API_Legacy.ino @@ -66,7 +66,7 @@ void loop() { } //================================================================================ -// NHP +// HoodLoader1 compatible NHP sending API //================================================================================ // Start Mask diff --git a/plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_NoUSB_Blink/HoodLoader2_NoUSB_Blink.ino b/plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_NoUSB_Blink/HoodLoader2_NoUSB_Blink.ino new file mode 100644 index 0000000000..8874a1d1c6 --- /dev/null +++ b/plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_NoUSB_Blink/HoodLoader2_NoUSB_Blink.ino @@ -0,0 +1,36 @@ +/* + Copyright (c) 2014 NicoHood + See the readme for credit to other people. + + HoodLoader2 NoUSB Blink example + + This sketch demonstrates how to use HoodLoader2 without USB Core. + This might be useful to keep ram/flash usage at a very low level. + Select Tools->USB Core->No USB functions to get rid of the USB Core. + + Blinks Leds and shows what workaround is needed to get the timing correct. + You can still use the normal digitalWrite(LED_BUILTIN_TX, LOW); for updating Leds. + Keep in mind that the logic is inverted then! LOW=HIGH and vice versa. + */ + +// workaround for undefined USBCON has to be placed in every sketch +// otherwise the timings wont work correctly +ISR(USB_GEN_vect) +{ + UDINT = 0; +} + +void setup() { + TX_RX_LED_INIT; +} + +void loop() { + TXLED0; + delay(100); + TXLED1; + delay(100); + RXLED0; + delay(100); + RXLED1; + delay(100); +} diff --git a/plugins/KeyboardioHID/examples/HoodLoader2_SerialKeyboard/HoodLoader2_SerialKeyboard.ino b/plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_SerialKeyboard/HoodLoader2_SerialKeyboard.ino similarity index 87% rename from plugins/KeyboardioHID/examples/HoodLoader2_SerialKeyboard/HoodLoader2_SerialKeyboard.ino rename to plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_SerialKeyboard/HoodLoader2_SerialKeyboard.ino index 07051d908d..5aef44609e 100644 --- a/plugins/KeyboardioHID/examples/HoodLoader2_SerialKeyboard/HoodLoader2_SerialKeyboard.ino +++ b/plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_SerialKeyboard/HoodLoader2_SerialKeyboard.ino @@ -4,13 +4,15 @@ HoodLoader2 SerialKeyboard example - This sketch should demonstate how to program a basic sketch with HoodLoader2. + This sketch should demonstrate how to program a basic sketch with HoodLoader2. It was used to demonstrate that Serial and HID is working properly. + The the other examples on how to use the other APIs, it works the same. + + Use the F() macro to save strings in PROGMEM to keep ram usage low. + The 16u2 has very low RAM, so don't try to use that much ram. Open the Serial port, type in anything and see that Serial and Keyboard is working. See official documentation for more infos. - - Use the F() macro to save strings in PROGMEM to keep ram usage low. */ void setup() { From a1e6dd4a3a85a693fe5566e78f013f9cee1f21de Mon Sep 17 00:00:00 2001 From: Nico Date: Sat, 22 Nov 2014 13:09:37 +0100 Subject: [PATCH 053/602] Ignore this Renewed source. Had some Windows problems ;) --- plugins/KeyboardioHID/USBCore.h | 303 -------------------------------- 1 file changed, 303 deletions(-) delete mode 100644 plugins/KeyboardioHID/USBCore.h diff --git a/plugins/KeyboardioHID/USBCore.h b/plugins/KeyboardioHID/USBCore.h deleted file mode 100644 index 8d13806896..0000000000 --- a/plugins/KeyboardioHID/USBCore.h +++ /dev/null @@ -1,303 +0,0 @@ - -// 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 From 52f7d2befaab05df12b9d1a131f03b8f7b7ddbce Mon Sep 17 00:00:00 2001 From: Nico Date: Sat, 22 Nov 2014 14:02:12 +0100 Subject: [PATCH 054/602] Moved examples --- plugins/KeyboardioHID/examples/{ => Basics}/Gamepad/Gamepad.ino | 2 +- .../KeyboardioHID/examples/{ => Basics}/Keyboard/Keyboard.ino | 0 plugins/KeyboardioHID/examples/{ => Basics}/Media/Media.ino | 0 plugins/KeyboardioHID/examples/{ => Basics}/Mouse/Mouse.ino | 0 plugins/KeyboardioHID/examples/{ => Basics}/System/System.ino | 0 5 files changed, 1 insertion(+), 1 deletion(-) rename plugins/KeyboardioHID/examples/{ => Basics}/Gamepad/Gamepad.ino (97%) rename plugins/KeyboardioHID/examples/{ => Basics}/Keyboard/Keyboard.ino (100%) rename plugins/KeyboardioHID/examples/{ => Basics}/Media/Media.ino (100%) rename plugins/KeyboardioHID/examples/{ => Basics}/Mouse/Mouse.ino (100%) rename plugins/KeyboardioHID/examples/{ => Basics}/System/System.ino (100%) diff --git a/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino b/plugins/KeyboardioHID/examples/Basics/Gamepad/Gamepad.ino similarity index 97% rename from plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino rename to plugins/KeyboardioHID/examples/Basics/Gamepad/Gamepad.ino index cc81ecc506..9014e36ac2 100644 --- a/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino +++ b/plugins/KeyboardioHID/examples/Basics/Gamepad/Gamepad.ino @@ -33,7 +33,7 @@ void loop() { // move x/y Axis to a new position (16bit) Gamepad.xAxis(random(0xFFFF)); - Gamepad.yAxis(analogRead(A0) << 6); + Gamepad.yAxis(random(0xFFFF)); // go through all dPad positions // values: 0-8 (0==centred) diff --git a/plugins/KeyboardioHID/examples/Keyboard/Keyboard.ino b/plugins/KeyboardioHID/examples/Basics/Keyboard/Keyboard.ino similarity index 100% rename from plugins/KeyboardioHID/examples/Keyboard/Keyboard.ino rename to plugins/KeyboardioHID/examples/Basics/Keyboard/Keyboard.ino diff --git a/plugins/KeyboardioHID/examples/Media/Media.ino b/plugins/KeyboardioHID/examples/Basics/Media/Media.ino similarity index 100% rename from plugins/KeyboardioHID/examples/Media/Media.ino rename to plugins/KeyboardioHID/examples/Basics/Media/Media.ino diff --git a/plugins/KeyboardioHID/examples/Mouse/Mouse.ino b/plugins/KeyboardioHID/examples/Basics/Mouse/Mouse.ino similarity index 100% rename from plugins/KeyboardioHID/examples/Mouse/Mouse.ino rename to plugins/KeyboardioHID/examples/Basics/Mouse/Mouse.ino diff --git a/plugins/KeyboardioHID/examples/System/System.ino b/plugins/KeyboardioHID/examples/Basics/System/System.ino similarity index 100% rename from plugins/KeyboardioHID/examples/System/System.ino rename to plugins/KeyboardioHID/examples/Basics/System/System.ino From 96512f22794aab108990386b7f04e4c5a2b9ef48 Mon Sep 17 00:00:00 2001 From: Nico Date: Sat, 22 Nov 2014 14:02:34 +0100 Subject: [PATCH 055/602] Added Gamepad Project, PWM Fade example --- .../HoodLoader2_PWM_Fade.ino | 39 +++++++ .../Gamepad_Project/Gamepad_Project.ino | 110 ++++++++++++++++++ 2 files changed, 149 insertions(+) create mode 100644 plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_PWM_Fade/HoodLoader2_PWM_Fade.ino create mode 100644 plugins/KeyboardioHID/examples/Projects/Gamepad_Project/Gamepad_Project.ino diff --git a/plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_PWM_Fade/HoodLoader2_PWM_Fade.ino b/plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_PWM_Fade/HoodLoader2_PWM_Fade.ino new file mode 100644 index 0000000000..0ba22c889f --- /dev/null +++ b/plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_PWM_Fade/HoodLoader2_PWM_Fade.ino @@ -0,0 +1,39 @@ +/* + Copyright (c) 2014 NicoHood + See the readme for credit to other people. + + PWM Fade + + This example shows how to fade an LED on pin 7 + using the analogWrite() function. + + Basically it is a demonstartion that PWM on pin 7 works fine. + You can also deactivate the USB Core for this example, but then you'd + need the workaround. See the other example for this. +*/ + +int led = 7; // the pin that the LED is attached to +int brightness = 0; // how bright the LED is +int fadeAmount = 5; // how many points to fade the LED by + +// the setup routine runs once when you press reset: +void setup() { + // declare pin 9 to be an output: + pinMode(led, OUTPUT); +} + +// the loop routine runs over and over again forever: +void loop() { + // set the brightness of pin 9: + analogWrite(led, 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 == 255) { + fadeAmount = -fadeAmount ; + } + // wait for 30 milliseconds to see the dimming effect + delay(30); +} diff --git a/plugins/KeyboardioHID/examples/Projects/Gamepad_Project/Gamepad_Project.ino b/plugins/KeyboardioHID/examples/Projects/Gamepad_Project/Gamepad_Project.ino new file mode 100644 index 0000000000..f4d17a0c97 --- /dev/null +++ b/plugins/KeyboardioHID/examples/Projects/Gamepad_Project/Gamepad_Project.ino @@ -0,0 +1,110 @@ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +Gamepad example project + +Press physical buttons to press USB Gamepad buttons. +This can be used for a simple SNES Controller. +*/ + +// pin mappings +const int pinButton1 = 2; +const int pinButton2 = 3; +const int pinButton3 = 4; +const int pinButton4 = 5; +const int pinButton5 = 6; +const int pinButton6 = 7; +const int pinButton7 = 8; +const int pinButton8 = 9; +const int pinButton9 = 10; +const int pinButton10 = 18; +const int pinButton11 = 19; +const int pinButton12 = 20; + +void setup() { + // pinsetup + pinMode(pinButton1, INPUT_PULLUP); + pinMode(pinButton2, INPUT_PULLUP); + pinMode(pinButton3, INPUT_PULLUP); + pinMode(pinButton4, INPUT_PULLUP); + pinMode(pinButton5, INPUT_PULLUP); + pinMode(pinButton6, INPUT_PULLUP); + pinMode(pinButton7, INPUT_PULLUP); + pinMode(pinButton8, INPUT_PULLUP); + pinMode(pinButton9, INPUT_PULLUP); + pinMode(pinButton10, INPUT_PULLUP); + pinMode(pinButton11, INPUT_PULLUP); + pinMode(pinButton12, INPUT_PULLUP); + + // Sends a clean report to the host. This is important on any Arduino type. + // Make sure all desired USB functions are activated in USBAPI.h! + Gamepad.begin(); +} + +void loop() { + // check each button and press Gamepad if needed + if (!digitalRead(pinButton1)) + Gamepad.press(1); + else + Gamepad.release(1); + + if (!digitalRead(pinButton2)) + Gamepad.press(2); + else + Gamepad.release(2); + + if (!digitalRead(pinButton3)) + Gamepad.press(3); + else + Gamepad.release(3); + + if (!digitalRead(pinButton4)) + Gamepad.press(4); + else + Gamepad.release(4); + + if (!digitalRead(pinButton5)) + Gamepad.press(5); + else + Gamepad.release(5); + + if (!digitalRead(pinButton6)) + Gamepad.press(6); + else + Gamepad.release(6); + + if (!digitalRead(pinButton7)) + Gamepad.press(7); + else + Gamepad.release(7); + + if (!digitalRead(pinButton8)) + Gamepad.press(8); + else + Gamepad.release(8); + + if (!digitalRead(pinButton9)) + Gamepad.press(9); + else + Gamepad.release(9); + + if (!digitalRead(pinButton10)) + Gamepad.press(10); + else + Gamepad.release(10); + + if (!digitalRead(pinButton11)) + Gamepad.press(11); + else + Gamepad.release(11); + + if (!digitalRead(pinButton12)) + Gamepad.press(12); + else + Gamepad.release(12); + + // write the information to the host now! + Gamepad.write(); +} + From d54cb23cbe12203ac38359ac3f0361c99311b090 Mon Sep 17 00:00:00 2001 From: Nico Date: Sat, 22 Nov 2014 14:03:26 +0100 Subject: [PATCH 056/602] Added Windows Key + Enter definition --- plugins/KeyboardioHID/USBAPI.h | 3 +++ plugins/KeyboardioHID/keywords.txt | 3 +++ 2 files changed, 6 insertions(+) diff --git a/plugins/KeyboardioHID/USBAPI.h b/plugins/KeyboardioHID/USBAPI.h index 9270655028..a0c583bded 100644 --- a/plugins/KeyboardioHID/USBAPI.h +++ b/plugins/KeyboardioHID/USBAPI.h @@ -376,10 +376,12 @@ extern Mouse_ Mouse; #define KEY_LEFT_SHIFT 0x81 #define KEY_LEFT_ALT 0x82 #define KEY_LEFT_GUI 0x83 +#define KEY_LEFT_WINDOWS KEY_LEFT_GUI #define KEY_RIGHT_CTRL 0x84 #define KEY_RIGHT_SHIFT 0x85 #define KEY_RIGHT_ALT 0x86 #define KEY_RIGHT_GUI 0x87 +#define KEY_RIGHT_WINDOWS KEY_RIGHT_GUI #define KEY_UP_ARROW 0xDA #define KEY_DOWN_ARROW 0xD9 @@ -388,6 +390,7 @@ extern Mouse_ Mouse; #define KEY_BACKSPACE 0xB2 #define KEY_TAB 0xB3 #define KEY_RETURN 0xB0 +#define KEY_ENTER KEY_RETURN #define KEY_ESC 0xB1 #define KEY_INSERT 0xD1 #define KEY_DELETE 0xD4 diff --git a/plugins/KeyboardioHID/keywords.txt b/plugins/KeyboardioHID/keywords.txt index d4e7943a54..81da167976 100644 --- a/plugins/KeyboardioHID/keywords.txt +++ b/plugins/KeyboardioHID/keywords.txt @@ -65,10 +65,12 @@ KEY_LEFT_CTRL LITERAL1 KEY_LEFT_SHIFT LITERAL1 KEY_LEFT_ALT LITERAL1 KEY_LEFT_GUI LITERAL1 +KEY_LEFT_WINDOWS LITERAL1 KEY_RIGHT_CTRL LITERAL1 KEY_RIGHT_SHIFT LITERAL1 KEY_RIGHT_ALT LITERAL1 KEY_RIGHT_GUI LITERAL1 +KEY_RIGHT_WINDOWS LITERAL1 KEY_UP_ARROW LITERAL1 KEY_DOWN_ARROW LITERAL1 @@ -77,6 +79,7 @@ KEY_RIGHT_ARROW LITERAL1 KEY_BACKSPACE LITERAL1 KEY_TAB LITERAL1 KEY_RETURN LITERAL1 +KEY_ENTER LITERAL1 KEY_ESC LITERAL1 KEY_INSERT LITERAL1 KEY_DELETE LITERAL1 From 9c0e8e60d0c508e6ada2799d07628a42ab2a073b Mon Sep 17 00:00:00 2001 From: Nico Date: Sat, 22 Nov 2014 14:49:28 +0100 Subject: [PATCH 057/602] USB Descriptor fix Only u2 Series fixed. I am not sure if a fix for u4 is wanted. Just remove the define and its also fixed ;) --- plugins/KeyboardioHID/USBCore.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/USBCore.cpp b/plugins/KeyboardioHID/USBCore.cpp index b95b50fd59..9691dfe5cb 100644 --- a/plugins/KeyboardioHID/USBCore.cpp +++ b/plugins/KeyboardioHID/USBCore.cpp @@ -101,11 +101,23 @@ const u8 STRING_MANUFACTURER[] PROGMEM = USB_MANUFACTURER; #define DEVICE_CLASS 0x00 #endif -//TODO warning from USBlyzer with a 16u2 +// edit by NicoHood +// warning from USBlyzer: IAD is used. Should be EFh (Miscellaneous Device Class). +// Lufa also use these values, so i will use them at least for the u2 boards. Someone should fix this for the u4 series if needed. +#if defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega8U2__) + +// DEVICE DESCRIPTOR +const DeviceDescriptor USB_DeviceDescriptor = +D_DEVICE(0xEF, 0x02, 0x01, 64, USB_VID, USB_PID, 0x100, IMANUFACTURER, IPRODUCT, 0, 1); + +#else + // DEVICE DESCRIPTOR const DeviceDescriptor USB_DeviceDescriptor = D_DEVICE(0x00, 0x00, 0x00, 64, USB_VID, USB_PID, 0x100, IMANUFACTURER, IPRODUCT, 0, 1); +#endif + const DeviceDescriptor USB_DeviceDescriptorA = D_DEVICE(DEVICE_CLASS, 0x00, 0x00, 64, USB_VID, USB_PID, 0x100, IMANUFACTURER, IPRODUCT, 0, 1); From f4433300c3adc3c6f20119117ba9be1150e6e105 Mon Sep 17 00:00:00 2001 From: Nico Date: Sat, 29 Nov 2014 18:51:00 +0100 Subject: [PATCH 058/602] Added Led Out Report, CDC Linestate, Magic Bootkey You can now read the led states of the keyboard, the dtr line of the cdc and the bootkey got fixed to the new hoodloader 2.0.1 --- plugins/KeyboardioHID/CDC.cpp | 104 +++++++--- plugins/KeyboardioHID/HID.cpp | 41 +++- plugins/KeyboardioHID/USBAPI.h | 21 ++ plugins/KeyboardioHID/USBCore.cpp | 5 +- plugins/KeyboardioHID/USBCore.h | 307 +++++++++++++++++++++++++++++ plugins/KeyboardioHID/keywords.txt | 10 +- 6 files changed, 443 insertions(+), 45 deletions(-) create mode 100644 plugins/KeyboardioHID/USBCore.h diff --git a/plugins/KeyboardioHID/CDC.cpp b/plugins/KeyboardioHID/CDC.cpp index 1c4672fa90..d08ba97842 100644 --- a/plugins/KeyboardioHID/CDC.cpp +++ b/plugins/KeyboardioHID/CDC.cpp @@ -1,19 +1,19 @@ -/* 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. +/* 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. */ /* @@ -61,28 +61,34 @@ static volatile LineInfo _usbLineInfo = { 57600, 0x00, 0x00, 0x00, 0x00 }; extern const CDCDescriptor _cdcInterface PROGMEM; const CDCDescriptor _cdcInterface = { - D_IAD(0,2,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,1), + 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), + 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_INTERFACE(CDC_DATA_INTERFACE, 2, CDC_DATA_INTERFACE_CLASS, 0, 0), // edit by NicoHood - D_ENDPOINT(USB_ENDPOINT_OUT(CDC_ENDPOINT_OUT),USB_ENDPOINT_TYPE_BULK,USB_EP_SIZE,0), - D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_IN ),USB_ENDPOINT_TYPE_BULK,USB_EP_SIZE,0) + D_ENDPOINT(USB_ENDPOINT_OUT(CDC_ENDPOINT_OUT), USB_ENDPOINT_TYPE_BULK, USB_EP_SIZE, 0), + D_ENDPOINT(USB_ENDPOINT_IN(CDC_ENDPOINT_IN), USB_ENDPOINT_TYPE_BULK, USB_EP_SIZE, 0) }; int WEAK CDC_GetInterface(u8* interfaceNum) { interfaceNum[0] += 2; // uses 2 - return USB_SendControl(TRANSFER_PGM,&_cdcInterface,sizeof(_cdcInterface)); + return USB_SendControl(TRANSFER_PGM, &_cdcInterface, sizeof(_cdcInterface)); } +// edit by NicoHood +// ensure the address isnt used anywhere else by adding a compiler flag in the makefile lf flag +// -Wl,--section-start=.blkey=0x280 +//TODO where to put that flag? use different position: 0x100 maybe? +// someone has to add the compiler flag to fix this bug: https://github.com/arduino/Arduino/issues/2474 +//volatile uint8_t MagicBootKey __attribute__((section(".blkey"))); bool WEAK CDC_Setup(Setup& setup) { @@ -93,7 +99,7 @@ bool WEAK CDC_Setup(Setup& setup) { if (CDC_GET_LINE_CODING == r) { - USB_SendControl(0,(void*)&_usbLineInfo,7); + USB_SendControl(0, (void*)&_usbLineInfo, 7); return true; } } @@ -102,7 +108,7 @@ bool WEAK CDC_Setup(Setup& setup) { if (CDC_SET_LINE_CODING == r) { - USB_RecvControl((void*)&_usbLineInfo,7); + USB_RecvControl((void*)&_usbLineInfo, 7); } if (CDC_SET_CONTROL_LINE_STATE == r) @@ -120,8 +126,26 @@ bool WEAK CDC_Setup(Setup& setup) // We check DTR state to determine if host port is open (bit 0 of lineState). if (1200 == _usbLineInfo.dwDTERate && (_usbLineInfo.lineState & 0x01) == 0) { + // edit by NicoHood + // change ram pointer to fit the 16u2's ram size and only use a 8bit value +#if defined(__AVR_ATmega32U4__) *(uint16_t *)0x0800 = 0x7777; wdt_enable(WDTO_120MS); +#else + // workaround for this issue: + // https://github.com/arduino/Arduino/issues/2474 + // I didnt change this for the 32u4 to simply not touch their code + cli(); + + //MagicBootKey = 0x77; + *(uint8_t *)0x0280 = 0x77; + + wdt_enable(WDTO_120MS); + + // wait for reset + for (;;); +#endif + } else { @@ -130,9 +154,18 @@ bool WEAK CDC_Setup(Setup& setup) // To avoid spurious resets we set the watchdog to 250ms and eventually // cancel if DTR goes back high. + // edit by NicoHood +#if defined(__AVR_ATmega32U4__) wdt_disable(); wdt_reset(); *(uint16_t *)0x0800 = 0x0; +#else + // not used because of the workaround above + //wdt_disable(); + //wdt_reset(); + //MagicBootKey = 0x0; + //*(uint8_t *)0x0280 = 0x00; +#endif } } return true; @@ -155,6 +188,12 @@ void Serial_::end(void) { } +// edit by NicoHood +uint8_t Serial_::lineState(void) +{ + return _usbLineInfo.lineState; +} + int Serial_::available(void) { if (peek_buffer >= 0) { @@ -192,20 +231,21 @@ size_t Serial_::write(uint8_t c) size_t Serial_::write(const uint8_t *buffer, size_t size) { - /* only try to send bytes if the high-level CDC connection itself + /* 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,buffer,size); + int r = USB_Send(CDC_TX, buffer, size); if (r > 0) { return r; - } else { + } + else { setWriteError(); return 0; } @@ -223,7 +263,7 @@ size_t Serial_::write(const uint8_t *buffer, size_t size) // where the port is configured (lineState != 0) but not quite opened. Serial_::operator bool() { bool result = false; - if (_usbLineInfo.lineState > 0) + if (_usbLineInfo.lineState > 0) result = true; delay(10); return result; diff --git a/plugins/KeyboardioHID/HID.cpp b/plugins/KeyboardioHID/HID.cpp index 27f3150a9b..70f8d60cfe 100644 --- a/plugins/KeyboardioHID/HID.cpp +++ b/plugins/KeyboardioHID/HID.cpp @@ -48,6 +48,11 @@ THE SOFTWARE. //================================================================================ // HID report descriptor +#if defined USBCON && defined(HID_KEYBOARD_ENABLED) && defined(HID_KEYBOARD_LEDS_ENABLED) +// extern accessible led out report +uint8_t hid_keyboard_leds = 0; +#endif + extern const u8 _hidReportDescriptor[] PROGMEM; const u8 _hidReportDescriptor[] = { #ifdef HID_MOUSE_ENABLED @@ -114,17 +119,19 @@ const u8 _hidReportDescriptor[] = { 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated)) 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application) 0x81, 0x00, // INPUT (Data,Ary,Abs) +#ifdef HID_KEYBOARD_LEDS_ENABLED // LEDs for num lock etc - //0x05, 0x08, /* USAGE_PAGE (LEDs) */ - //0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */ - //0x29, 0x05, /* USAGE_MAXIMUM (Kana) */ - //0x95, 0x05, /* REPORT_COUNT (5) */ - //0x75, 0x01, /* REPORT_SIZE (1) */ - //0x91, 0x02, /* OUTPUT (Data,Var,Abs) */ + 0x05, 0x08, /* USAGE_PAGE (LEDs) */ + 0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */ + 0x29, 0x05, /* USAGE_MAXIMUM (Kana) */ + 0x95, 0x05, /* REPORT_COUNT (5) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */ // Reserved 3 bits - //0x95, 0x01, /* REPORT_COUNT (1) */ - //0x75, 0x03, /* REPORT_SIZE (3) */ - //0x91, 0x03, /* OUTPUT (Cnst,Var,Abs) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x03, /* REPORT_SIZE (3) */ + 0x91, 0x03, /* OUTPUT (Cnst,Var,Abs) */ +#endif // end 0xc0, // END_COLLECTION #endif @@ -302,6 +309,22 @@ bool WEAK HID_Setup(Setup& setup) _hid_idle = setup.wValueL; return true; } + + // edit by NicoHood +#if defined USBCON && defined(HID_KEYBOARD_ENABLED) && defined(HID_KEYBOARD_LEDS_ENABLED) + if (HID_SET_REPORT == r) + { + if (setup.wLength == 2) + { + uint8_t data[2]; + if (2 == USB_RecvControl(data, 2)) + { + // write led out report data + hid_keyboard_leds=data[1]; + } + } + } +#endif } return false; } diff --git a/plugins/KeyboardioHID/USBAPI.h b/plugins/KeyboardioHID/USBAPI.h index a0c583bded..d3c9bd317e 100644 --- a/plugins/KeyboardioHID/USBAPI.h +++ b/plugins/KeyboardioHID/USBAPI.h @@ -61,6 +61,8 @@ typedef unsigned long u32; // by default only Mouse + Keyboard are activated #define HID_MOUSE_ENABLED #define HID_KEYBOARD_ENABLED +//#define HID_KEYBOARD_LEDS_ENABLED + //#define HID_RAWHID_ENABLED //#define HID_MEDIA_ENABLED //#define HID_SYSTEM_ENABLED @@ -76,6 +78,15 @@ typedef unsigned long u32; #ifdef HID_KEYBOARD_ENABLED #define HID_KEYBOARD_SIZE (65-18) //18 for missing led out report = 47 + +#if defined USBCON && defined(HID_KEYBOARD_ENABLED) && defined(HID_KEYBOARD_LEDS_ENABLED) +// extern accessible led out report +extern uint8_t hid_keyboard_leds; + +#define LED_NUM_LOCK 0x01 +#define LED_CAPS_LOCK 0x02 +#define LED_SCROLL_LOCK 0x04 +#endif #else #define HID_KEYBOARD_SIZE 0 #endif @@ -181,6 +192,9 @@ class Serial_ : public Stream void begin(unsigned long, uint8_t); void end(void); + // edit by NicoHood + uint8_t lineState(void); + virtual int available(void); virtual int peek(void); virtual int read(void); @@ -369,6 +383,7 @@ extern Mouse_ Mouse; //Keyboard fixed/added missing Keys #define KEY_PRINT 0xCE +#define KEY_NUM_LOCK 0xDB #define KEY_SCROLL_LOCK 0xCF #define KEY_PAUSE 0xD0 @@ -619,6 +634,12 @@ class Keyboard_ : public Print{ releaseAll(); } +#if defined(HID_KEYBOARD_LEDS_ENABLED) + inline uint8_t getLEDs(void){ + return hid_keyboard_leds; + } +#endif + inline size_t write(uint8_t c){ uint8_t p = press(c); // Keydown release(c); // Keyup diff --git a/plugins/KeyboardioHID/USBCore.cpp b/plugins/KeyboardioHID/USBCore.cpp index 9691dfe5cb..7373819728 100644 --- a/plugins/KeyboardioHID/USBCore.cpp +++ b/plugins/KeyboardioHID/USBCore.cpp @@ -104,7 +104,8 @@ const u8 STRING_MANUFACTURER[] PROGMEM = USB_MANUFACTURER; // edit by NicoHood // warning from USBlyzer: IAD is used. Should be EFh (Miscellaneous Device Class). // Lufa also use these values, so i will use them at least for the u2 boards. Someone should fix this for the u4 series if needed. -#if defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega8U2__) +// You have to use this descriptor if you have CDC AND HID at the same time. Otherwise they are quite different. +#if defined(HID_ENABLED) && (defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega8U2__)) // DEVICE DESCRIPTOR const DeviceDescriptor USB_DeviceDescriptor = @@ -742,7 +743,7 @@ void USBDevice_::attach() #ifdef PINDIV PLLCSR = (1 << PINDIV) | (1 << PLLE); #else - // added from paul, no idea for what board this is used for + // added from paul brook, no idea for what board this is used for PLLCSR = (1 << PLLP0) | (1 << PLLE); #endif diff --git a/plugins/KeyboardioHID/USBCore.h b/plugins/KeyboardioHID/USBCore.h new file mode 100644 index 0000000000..7e2239d0ed --- /dev/null +++ b/plugins/KeyboardioHID/USBCore.h @@ -0,0 +1,307 @@ + +// 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 + +// edit by NicoHood +#define CDC_CONTROL_LINE_OUT_DTR (1 << 0) +#define CDC_CONTROL_LINE_OUT_RTS (1 << 1) + +#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/plugins/KeyboardioHID/keywords.txt b/plugins/KeyboardioHID/keywords.txt index 81da167976..ddefd30dad 100644 --- a/plugins/KeyboardioHID/keywords.txt +++ b/plugins/KeyboardioHID/keywords.txt @@ -48,8 +48,9 @@ Gamepad KEYWORD3 # Constants (LITERAL1) ####################################### -#General -SERIAL_HID_BAUD LITERAL1 +#CDC +CDC_CONTROL_LINE_OUT_DTR LITERAL1 +CDC_CONTROL_LINE_OUT_TRS LITERAL1 #Mouse @@ -61,6 +62,10 @@ MOUSE_NEXT LITERAL1 #Keyboard +LED_NUM_LOCK LITERAL1 +LED_CAPS_LOCK LITERAL1 +LED_SCROLL_LOCK LITERAL1 + KEY_LEFT_CTRL LITERAL1 KEY_LEFT_SHIFT LITERAL1 KEY_LEFT_ALT LITERAL1 @@ -102,6 +107,7 @@ KEY_F11 LITERAL1 KEY_F12 LITERAL1 KEY_PRINT LITERAL1 +KEY_NUM_LOCK LITERAL1 KEY_SCROLL_LOCK LITERAL1 KEY_PAUSE LITERAL1 From c131c3e13d4c5b85a1de65bde04e8f7f66c7656f Mon Sep 17 00:00:00 2001 From: Nico Date: Sat, 29 Nov 2014 20:13:52 +0100 Subject: [PATCH 059/602] Huge Readme Update --- plugins/KeyboardioHID/Readme.md | 208 +++++++++++++++----------------- 1 file changed, 99 insertions(+), 109 deletions(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index d5bce3b589..8b38995959 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -1,126 +1,112 @@ -Arduino HID Project -=================== -Dont you always wanted to turn your Arduino in a Generic HID device like a Keyboard or a Gamepad? -Disappointed that the Uno doesnt support this at all and the Micro/Leonardo only Mouse + Keyboard? +Arduino HID Project 2.0 +======================= +This project went through a lot of phases and has now reached an HID library with 3 software solutions. +The idea is to enable enhanced USB functions to almost all 'standard' Arduino boards. +This is done with slightly different methods for different boards. -Introducing the Arduino HID Project that **enables enhanced USB functionality to Arduino Uno, Mega, Leonardo, Micro.** -No need for extra hardware. You just need one of the Arduinos and an USB cable. +**Arduino IDE 1.5.8 is required for the HID Project. -**Main difference is that you can upload new sketches to the Uno/Mega and dont need to reflash the firmware over and over again.** -Before you had to upload a sketch, flash the firmware, test, flash the firmware, upload, flash again. Thats all gone! +**Supported HID devices:** -**For the Leonardo/Micro it is 'just' new HID devices, no need for a bootloader (like on Uno/Mega).** +* Keyboard with Leds out(modifiers + 6 keys pressed at the same time) +* Mouse (5 buttons, move, wheel) +* Media Keys (4 keys for music player, webbrowser and more) +* System Key (for PC standby/shutdown) +* 1 Gamepad (32 buttons, 4 16bit axis, 2 8bit axis, 2 D-Pads) -Note: [Hoodloader Repository moved here.](https://github.com/NicoHood/Hoodloader) +**Supported Arduinos:** +* Uno +* Mega +* Leonardo +* (Pro)Micro +* Any other 8u2/16u/at90usb162/32u2/32u4 compatible board -Features -======== -Use your **Arduino Uno, Mega, Micro, Leonardo or (Pro)Micro** as Generic HID Device and still be able to upload sketches how you are used to do. -This project provides HID libraries for Arduino Uno/Mega (with a new 16u2 bootloader) and Micro/Leonardo. -I also corrected some bugs in the original sources. +| Leonardo/Micro | Uno/Mega HoodLoader2 | Uno/Mega HoodLoader1 | +|:------------------------------------------|:----------------------------|---------------------------------------| +| Uses modified/extended Arduino USB-Core | Same Core as Leonardo/Micro | Coded with Lufa | +| More HID devices (Media, System, Gamepad) | Fully reprogrammable 16u2 | No reprogrammable 16u2 | +| Keyboard Led Out report | Serial0 fully usable | Main MCU sends HID reports on Serial0 | +| System Wakeup fix (soon) | | Serial Protocol filters HID reports | +| Serial Control Line accessible | | Built-in ISP function | -**Software includes:** +The HID project contains HID APIs to generate HID reports and functions to send them to the USB Host. +The API (syntax/usage) of the HID Project is always the same for each solution, you can port code from one device to another very easy. -* Arduino HID Uno/Mega library -* Arduino HID Micro/Leonardo library -* Arduino HID Bootloader (Hoodloader) + driver for Uno/Mega -* Arduino as ISP with the 16u2 (Hoodloader only, [more information](https://github.com/NicoHood/Hoodloader)) -* Compatible with Linux/Mac/Windows XP/7/8.1 -* Compatible with IDE 1.0.x - 1.5.7 +On a Leonardo this function is extended and improved to get more HID devices + some improvements. +[HoodLoader2](https://github.com/NicoHood/HoodLoader2) is a BootLoader for the 16u2 that let's you use it as standalone MCU with the same USB-Core. +[HoodLoader1](https://github.com/NicoHood/HoodLoader) is a 16u2 firmware that filters special HW Serial signals from the main MCU and sends HID signals to the USB Host. -**The following devices are supported:** -* Keyboard (modifiers + 6 keys pressed at the same time) -* Mouse (5 buttons, move, wheel) -* Media Keys (4 keys for music player, webbrowser and more) -* System Key (for PC standby/shutdown) -* 4 Gamepads (32 buttons, 4 16bit axis, 2 8bit axis, 2 D-Pads) +To make things more clear the HID Software is in a separate repository than the HoodLoader (1 & 2) sources and installing instructions. +HoodLoader 1&2 is only used for an Uno/Mega to actually enable USB functions. The 16u2 is normally used for USB-Serial programming of the main MCU but can do way more than that. +To use HoodLoader1&2 you also need the HID Project. For more information and installation instructions see the specific repository. -**Projects can be found here:** -* [Gamecube to PC adapter](https://github.com/NicoHood/Nintendo) -* [Other projects](http://nicohood.wordpress.com/) +HoodLoader1 was the first solution to enable HID functions to the Uno/Mega but HoodLoader2 opens way more options because you can reprogram the whole MCU standalone. +See the repository for more infos about this great new opportunity. HoodLoader1 API is still usable in a specific example. HoodLoader1&2 are not needed/useable with a Leonardo/Micro. -Version differences -=================== +Installation +============ -| Arduino Uno/Mega | Arduino Leonardo/(Pro)Micro | -|:---------------------------------------|:-----------------------------------| -| HID via Hoodloader on 16u2 | Uses USB core with main MCU (32u4) | -| Serial0 without HID fully usable | Serial0 fully usable | -| Serial0 with HID at baud 115200 only | Serial0 slow + buggy | -| Serial0 with HID fully usable via USB | | -| Serial0 with HID not usable via extern | | -| Uses less flash (Serial Protocol only) | Uses more flash (full USB core) | -| ISP function | No ISP function | +Please remove any older HID Project files from your sketchbook and your Arduino core to not run into any problems. -Over all the Uno/Mega solution gives you more opportunities except that the Serial0 is limited when you use HID. +Download the library and [install it](http://arduino.cc/en/pmwiki.php?n=Guide/Libraries) like you are used to (access the examples, keywords.txt with IDE). +Then **move and replace** all .h and .cpp files to the path below. **I strongly recommend to install the library like this. Otherwise it wont work.* -Installation Leonardo/Micro/Uno/Mega -==================================== +``` +C:\Arduino\arduino-1.5.8\hardware\arduino\avr\cores\arduino +``` +The installation path may differ to yours. Please use Arduino IDE 1.5.8 and file an issue if a newer version isn't working. +Restart the IDE. Ensure all drivers are installed. See [this](https://learn.sparkfun.com/tutorials/disabling-driver-signature-on-windows-8/disabling-signed-driver-enforcement-on-windows-8) +on how to install the unsigned HoodLoader2 drivers. -#### Leonardo/Micro only -Download the library and [install it](http://arduino.cc/en/pmwiki.php?n=Guide/Libraries) like you are used to. +If you are using an Arduino Uno/Mega follow the installation instructions of the HoodLoader1 or 2 (no extra hardware needed, just a few cables). +You can grab the latest version + installing instructions of each HoodLoader in its own repository linked above. +Of course the new version [HoodLoader2](https://github.com/NicoHood/HoodLoader2) is recommend and HoodLoader1 API is only for compatibility reasons online. +The old, full HoodLoader1 HID (software)solution (before update 2.0) can be found here: https://github.com/NicoHood/HID/tree/3d8a9b40752a143141b8be4b8f744e203c80b000 -**For the whole Project IDE 1.5.7 or higher is recommended!** -**Edit HID.h to de/activate usb functions.** -By default Mouse, Keyboard, Media, System, Gamepad1 is activated. +How to use +========== -Each function will take some flash, -so if you want to save flash deactivate everything you dont need. -You cannot use more than 255 bytes HID report on the Leonardo/Micro. -The number after each definition tells you the size of each report. -I have no idea why you cannot use more than 255 bytes (yet), its a bug in the Arduino code. +### Micro/Leonardo + HoodLoader2 -#### Uno/Mega only -Download the library and [install it](http://arduino.cc/en/pmwiki.php?n=Guide/Libraries) like you are used to. +**Edit the USBAPI.h you installed to de/activate usb functions.** By default only Mouse and Keyboard is activated. +The more you activate the more flash is used. For the Uno/Mega you have a limited ram/flash size, so please try not to exceed this limit and only use the needed HID devices. +RawHID is currently not working properly. -**For the whole Project IDE 1.5.7 or higher is recommended!** +Try the Basic examples for each HID device. They are pretty much self explaining. -To install the new bootloader connect your Arduino to your PC via USB and see -[Hoodloader installing instructions](https://github.com/NicoHood/Hoodloader). -No special programmer needed, just an USB cable. -**You can always switch back to the original firmware, nothing to break.** +The HoodLoader2 examples are to show some special cases for the 16u2. It shows how to remove the USB functions if needed, +how to optimally use ram since its limited and some ported sketches to reprogram the main MCU or for the missing ISP function. Please check them out. -Edit HID.h to add an extra delay for raspberry pi. This is a workaround to fix this for slower PCs. There is still a problem with Raspberry. -Usage -===== -You are ready to use the libraries. **Just have a look at the examples and test it out.** They are pretty much self explaining. -All examples use a button on pin 8 and show the basic usage of the libraries. -The libraries will work for all Arduinos listed above but it will use 2 different HID libraries (automatically). -For Keyboard + Mouse usage also see the [official documentation](http://arduino.cc/en/pmwiki.php?n=Reference/MouseKeyboard). +### HoodLoader1 -**#include is now needed for every device.** +Try the HoodLoader1 example. It provides the basic Serial protocol API to send HID reports. You have to copy this to every sketch again. -**On Arduino/Mega you can only use baud 115200 for HID** due to speed/programming reasons. -Use Serial.begin(SERIAL_HID_BAUD); as typedef to start Serial at baud 115200. +With HoodLoader1 you can only use baud 115200 for HID due to speed/programming reasons. +Use Serial.begin(115200) in every HoodLoader1 sketch. Its not bad anyway because its the fastest baud and you want fast HID recognition. You still can **fully use any other baud** for normal sketches but HID wont work. If you try nevertheless it will output Serial crap to the monitor. -**Always release buttons to not cause any erros.** Replug USB cable to reset the values if anything went wrong. +Keep in mind that HoodLoader1 has no flush function. If the PC is reading HID too slow it can miss data, like on a Raspberry Pi. +Add a delay to the sending function or just use the newer HoodLoader2. + +Always release buttons to not cause any erros. Replug USB cable to reset the values if anything went wrong. +Keep in mind that with HoodLoader1 the 16u2 is always on, so you need to reset the HID values on every startup with a begin() of each used API. On Windows every USB report will reset when you open the lock screen. -See [deactivate HID function (Hoodloader only)](https://github.com/NicoHood/Hoodloader) how to disable HID again. +See [deactivate HID function (Hoodloader only)](https://github.com/NicoHood/Hoodloader) how to temporary disable HID again. For Arduino as ISP usage (optional, Hoodloader only, has nothing to do with HID function) see [Hoodloader repository](https://github.com/NicoHood/Hoodloader). -Updating to a newer Version -=========================== -HID library: +The sending API is no longer integrated directly in the HID Project since it is now more an extended USB-Core and this has nothing to do with it. +Its more a legacy version to still use HoodLoader1 or to reimplement something similar with HoodLoader2 if you still want full report access for the main MCU. -To upgrade to v1.8 you need to redownload the Arduino IDE files, restore the original files and install the library like you are used to. -You library is now located in sketchbook/libraries/HID/ -Its now way easier to install the library, no need to replace system files. For further releases just replace all files again. +The older, full integrated HID Core can be found here. Keep in mind to remove all newer stuff since it may conflict (a clean arduino core would do it). +https://github.com/NicoHood/HID/tree/3d8a9b40752a143141b8be4b8f744e203c80b000 -**Restart the IDE** - -Hoodloader (Not needed for Leonardo/Micro): - -Just upload the new hex file and check the HID Project if the HID library code has changed and replace the new files too. -You normally dont need to reinstall the drivers for windows if the changelog dosnt note anything. -Versions below 1.5 might need the new drivers. How it works ============ @@ -147,59 +133,63 @@ This project wouldnt be possible without * A lot of searching through the web * The awesome official Arduino IRC chat! * [The NicoHood Protocol ^.^](https://github.com/NicoHood/NicoHoodProtocol) +* See HoodLoader1&2 repository for more credits/links + +**Projects can be found here:** +* [Gamecube to PC adapter](https://github.com/NicoHood/Nintendo) +* [Other projects](http://nicohood.wordpress.com/) * For donations please contact me on my blog :) Ideas for the future ==================== -* Add more devices (even more?) +* Add more devices (even more?, voice device, flight control?) * Add Midi (no more free Endpoints, possible on 32u4) * Add HID rumble support (very hard) -* Add Xbox Support (too hard) -* Add Report Out function (for Keyboard Leds etc) Known Bugs ========== See [Hoodloader repository](https://github.com/NicoHood/Hoodloader) for Hoodloader related Bugs/Issues. -System Wakeup is currently not working on all versions! +System Wakeup is currently not working on all versions! Will be fixed soon! System Shutdown is only working on Windows systems. -RawHID only works on Uno/Mega. It still has some bugs. +RawHID is not working properly, test it at your own risk. Feel free to open an Issue on Github if you find a bug. Or message me via my [blog](http://nicohood.wordpress.com/)! Known Issues ============ -**Do not name your sketch HID.ino, this wont work!** - -Opening the examples with doubleclick doesnt work, starting from IDE does. - -**Do not use HID in interrupts because it uses Serial (Hoodloader only). Your Arduino can crash!** - -**If you get a checksum error after uploading please message me and send me the whole project.** -Same if your Arduino crashes and dont want to upload sketches anymore (Replug usb fixes this). -These bugs occurred while developing the bootloader and should be fixed. Just in case it happens again I noted it here. -USB can behave weird, so please check your code for errors first. If you cannot find a mistake open a Github issue. - **If You have weird Problems especially with controllers, let me know.** Sometimes the problem is just that Windows messes up the PID so you might want to compile the hoodloader with a different PID -or reinstall the drivers. +or reinstall the drivers. With HoodLoader1 we had a lot of problems especially with linux. XBMC 13.1 (a Media Center) uses Gamepad input. Its seems to not work and may cause weird errors. Even with a standard Gamepad I have these errors. Just want to mention it here. -Not tested on the 8u2, lite version should work with flashing via ISP. - -Not tested on the Due (message me if it works!) - The USB implementation of the Leonardo/Micro is not that good it can cause errors or disconnects with massiv Serial input. This has nothing to do with this library! For example Adalight dosnt work well for me, -so you better use an Arduino Uno with Hoodloader for Mediacenter control and Ambilight. +so you better use an Arduino Uno with Hoodloader1 (yes the older one!) for Mediacenter control and Ambilight. + +Do not use HID in interrupts because it uses Serial (Hoodloader1 only). Your Arduino can crash! + +HoodLoader1 only: If you get a checksum error after uploading please message me and send me the whole project. +Same if your Arduino crashes and dont want to upload sketches anymore (Replug usb fixes this). +These bugs occurred while developing the bootloader and should be fixed. Just in case it happens again I noted it here. +USB can behave weird, so please check your code for errors first. If you cannot find a mistake open a Github issue. Version History =============== ``` +2.0 Release (29.11.2014) +* Added HoodLoader2 +* Separated HoodLoader1&2 more +* Added u2 series for USB-Core +* Extended USB core and fixed minor things for the u2 series +* Added Led Out report. +* Added CDC Line state +* Reworked the whole library structure again + 1.8 Beta Release (26.08.2014) * Changes in the Hoodloader: * **Huge improvements**, see [Hoodloader repository](https://github.com/NicoHood/Hoodloader) From 501e23be6a2bb5834ba46e6fa17230adf992152e Mon Sep 17 00:00:00 2001 From: Nico Date: Sat, 29 Nov 2014 20:24:54 +0100 Subject: [PATCH 060/602] Readme --- plugins/KeyboardioHID/Readme.md | 62 ++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 8b38995959..2807e10b1b 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -4,11 +4,11 @@ This project went through a lot of phases and has now reached an HID library wit The idea is to enable enhanced USB functions to almost all 'standard' Arduino boards. This is done with slightly different methods for different boards. -**Arduino IDE 1.5.8 is required for the HID Project. +**Arduino IDE 1.5.8 is required for the HID Project.** **Supported HID devices:** -* Keyboard with Leds out(modifiers + 6 keys pressed at the same time) +* Keyboard with Leds out (modifiers + 6 keys pressed at the same time) * Mouse (5 buttons, move, wheel) * Media Keys (4 keys for music player, webbrowser and more) * System Key (for PC standby/shutdown) @@ -21,46 +21,47 @@ This is done with slightly different methods for different boards. * (Pro)Micro * Any other 8u2/16u/at90usb162/32u2/32u4 compatible board -| Leonardo/Micro | Uno/Mega HoodLoader2 | Uno/Mega HoodLoader1 | -|:------------------------------------------|:----------------------------|---------------------------------------| -| Uses modified/extended Arduino USB-Core | Same Core as Leonardo/Micro | Coded with Lufa | -| More HID devices (Media, System, Gamepad) | Fully reprogrammable 16u2 | No reprogrammable 16u2 | -| Keyboard Led Out report | Serial0 fully usable | Main MCU sends HID reports on Serial0 | -| System Wakeup fix (soon) | | Serial Protocol filters HID reports | -| Serial Control Line accessible | | Built-in ISP function | +| Leonardo/Micro | Uno/Mega HoodLoader2 | Uno/Mega HoodLoader1 | +|:---------------------------|:----------------------------|---------------------------------------| +| Extended Arduino USB-Core | Same Core as Leonardo/Micro | Coded with Lufa | +| More HID devices | Fully reprogrammable 16u2 | No reprogrammable 16u2 | +| Keyboard Led Out report | Serial0 fully usable | Main MCU sends HID reports on Serial0 | +| System Wakeup fix (soon) | | Serial Protocol filters HID reports | +| Serial Control Line access | | Built-in ISP function | The HID project contains HID APIs to generate HID reports and functions to send them to the USB Host. -The API (syntax/usage) of the HID Project is always the same for each solution, you can port code from one device to another very easy. +The API (syntax/usage) of the HID Project is always the same for each solution, **you can port code from one device to another very easy**. -On a Leonardo this function is extended and improved to get more HID devices + some improvements. -[HoodLoader2](https://github.com/NicoHood/HoodLoader2) is a BootLoader for the 16u2 that let's you use it as standalone MCU with the same USB-Core. -[HoodLoader1](https://github.com/NicoHood/HoodLoader) is a 16u2 firmware that filters special HW Serial signals from the main MCU and sends HID signals to the USB Host. +* On a Leonardo this function is extended and improved to get more HID devices + some improvements. +* [HoodLoader2](https://github.com/NicoHood/HoodLoader2) is a BootLoader for the 16u2 that let's you use it as standalone MCU with the same USB-Core. +* [HoodLoader1](https://github.com/NicoHood/HoodLoader) is a 16u2 firmware that filters special HW Serial signals from the main MCU and sends HID signals to the USB Host. To make things more clear the HID Software is in a separate repository than the HoodLoader (1 & 2) sources and installing instructions. -HoodLoader 1&2 is only used for an Uno/Mega to actually enable USB functions. The 16u2 is normally used for USB-Serial programming of the main MCU but can do way more than that. +**HoodLoader 1&2 is only used for an Uno/Mega to actually enable USB functions.** The 16u2 is normally used for USB-Serial programming of the main MCU but can do way more than that. To use HoodLoader1&2 you also need the HID Project. For more information and installation instructions see the specific repository. HoodLoader1 was the first solution to enable HID functions to the Uno/Mega but HoodLoader2 opens way more options because you can reprogram the whole MCU standalone. -See the repository for more infos about this great new opportunity. HoodLoader1 API is still usable in a specific example. HoodLoader1&2 are not needed/useable with a Leonardo/Micro. +See the repository for more infos about this great new opportunity. HoodLoader1 API is still usable in a specific example. HoodLoader1&2 are not needed/compatible with a Leonardo/Micro. Installation ============ -Please remove any older HID Project files from your sketchbook and your Arduino core to not run into any problems. +**Please remove any older HID Project files from your sketchbook and your Arduino core to not run into any problems.** Download the library and [install it](http://arduino.cc/en/pmwiki.php?n=Guide/Libraries) like you are used to (access the examples, keywords.txt with IDE). -Then **move and replace** all .h and .cpp files to the path below. **I strongly recommend to install the library like this. Otherwise it wont work.* +Then **move and replace** all .h and .cpp files to the path below. **I strongly recommend to install the library like this. Otherwise it wont work.** ``` C:\Arduino\arduino-1.5.8\hardware\arduino\avr\cores\arduino ``` -The installation path may differ to yours. Please use Arduino IDE 1.5.8 and file an issue if a newer version isn't working. +The installation path may differ to yours. **Please use Arduino IDE 1.5.8** and file an issue if a newer version isn't working. Restart the IDE. Ensure all drivers are installed. See [this](https://learn.sparkfun.com/tutorials/disabling-driver-signature-on-windows-8/disabling-signed-driver-enforcement-on-windows-8) on how to install the unsigned HoodLoader2 drivers. -If you are using an Arduino Uno/Mega follow the installation instructions of the HoodLoader1 or 2 (no extra hardware needed, just a few cables). +**If you are using an Arduino Uno/Mega follow the installation instructions of the HoodLoader1 or 2** (no extra hardware needed, just a few cables). You can grab the latest version + installing instructions of each HoodLoader in its own repository linked above. + Of course the new version [HoodLoader2](https://github.com/NicoHood/HoodLoader2) is recommend and HoodLoader1 API is only for compatibility reasons online. The old, full HoodLoader1 HID (software)solution (before update 2.0) can be found here: https://github.com/NicoHood/HID/tree/3d8a9b40752a143141b8be4b8f744e203c80b000 @@ -74,45 +75,48 @@ How to use The more you activate the more flash is used. For the Uno/Mega you have a limited ram/flash size, so please try not to exceed this limit and only use the needed HID devices. RawHID is currently not working properly. -Try the Basic examples for each HID device. They are pretty much self explaining. +**Try the Basic examples for each HID device. They are pretty much self explaining.** -The HoodLoader2 examples are to show some special cases for the 16u2. It shows how to remove the USB functions if needed, +**The HoodLoader2 examples are to show some special cases for the 16u2.** It shows how to remove the USB functions if needed, how to optimally use ram since its limited and some ported sketches to reprogram the main MCU or for the missing ISP function. Please check them out. ### HoodLoader1 -Try the HoodLoader1 example. It provides the basic Serial protocol API to send HID reports. You have to copy this to every sketch again. +**Try the HoodLoader1 example. It provides the basic Serial protocol API to send HID reports. You have to copy this to every sketch again.** -With HoodLoader1 you can only use baud 115200 for HID due to speed/programming reasons. +With HoodLoader1 you can **only use baud 115200 for HID** due to speed/programming reasons. Use Serial.begin(115200) in every HoodLoader1 sketch. Its not bad anyway because its the fastest baud and you want fast HID recognition. You still can **fully use any other baud** for normal sketches but HID wont work. If you try nevertheless it will output Serial crap to the monitor. -Keep in mind that HoodLoader1 has no flush function. If the PC is reading HID too slow it can miss data, like on a Raspberry Pi. +Keep in mind that HoodLoader1 has **no flush function**. If the PC is reading HID too slow it can miss data, like on a Raspberry Pi. Add a delay to the sending function or just use the newer HoodLoader2. Always release buttons to not cause any erros. Replug USB cable to reset the values if anything went wrong. -Keep in mind that with HoodLoader1 the 16u2 is always on, so you need to reset the HID values on every startup with a begin() of each used API. +Keep in mind that **with HoodLoader1 the 16u2 is always on**. The 16u2 and its HID reports are not reset if the main MCU is reset. +So you need to reset the HID reports on every startup with a begin() of each used API. On Windows every USB report will reset when you open the lock screen. See [deactivate HID function (Hoodloader only)](https://github.com/NicoHood/Hoodloader) how to temporary disable HID again. -For Arduino as ISP usage (optional, Hoodloader only, has nothing to do with HID function) +For **16u2 as ISP usage** (optional, Hoodloader only, has nothing to do with HID function) see [Hoodloader repository](https://github.com/NicoHood/Hoodloader). The sending API is no longer integrated directly in the HID Project since it is now more an extended USB-Core and this has nothing to do with it. Its more a legacy version to still use HoodLoader1 or to reimplement something similar with HoodLoader2 if you still want full report access for the main MCU. -The older, full integrated HID Core can be found here. Keep in mind to remove all newer stuff since it may conflict (a clean arduino core would do it). +**The older, full integrated HID Core can be found here.** Keep in mind to remove all newer stuff since it may conflict (a clean arduino core would do it). +It is not better than this solution, maybe easier to use since its just more integrated. https://github.com/NicoHood/HID/tree/3d8a9b40752a143141b8be4b8f744e203c80b000 How it works ============ -For the Leonardo/Micro its just a modified version of the HID descriptor and Classes for the new devices. -Its not that complicated, everything you need is in the main 4 .h/cpp files. +For the Leonardo/Micro + HoodLoader2 its a modified version of the HID descriptors and USB-Core. +This changes were made to improve the functions, add more devices and add u2 series compatibility. +HoodLoader1 only: For the Uno/Mega you need a special Bootloader. Why? See [Hoodloader repository](https://github.com/NicoHood/Hoodloader). To sum it up: Serial information is grabbed by the "man in the middle, 16u2" and you dont have to worry to get any wrong Serial stuff via USB. Thatswhy you need a special baud (115200) that both sides can communicate with each other. From 7224b2a6fb47f3dfbb5ef050c71a7adad41472bb Mon Sep 17 00:00:00 2001 From: Nico Date: Sat, 29 Nov 2014 20:27:32 +0100 Subject: [PATCH 061/602] Added USB-Serial function Its now possible to also reprogram the main MCU with the HoodLoader2 in the sketch itself. It might have some bugs/errors since the USB implementation isn't that reliable. --- .../HoodLoader2_USB-Serial.ino | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_USB-Serial/HoodLoader2_USB-Serial.ino diff --git a/plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_USB-Serial/HoodLoader2_USB-Serial.ino b/plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_USB-Serial/HoodLoader2_USB-Serial.ino new file mode 100644 index 0000000000..1dce7ff33c --- /dev/null +++ b/plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_USB-Serial/HoodLoader2_USB-Serial.ino @@ -0,0 +1,51 @@ +/* + Copyright (c) 2014 NicoHood + See the readme for credit to other people. + + HoodLoader2 USB-Serial + + Transferes from USB to HW Serial and vice versa. + It also resets the main MCU on a DTR rise. + */ + +void setup() { + // set main MCU by default active + pinMode(MAIN_MCU_RESET_PIN, OUTPUT); + digitalWrite(MAIN_MCU_RESET_PIN, HIGH); + + // Start USB and HW Serial + Serial.begin(115200); + Serial1.begin(115200); +} + +void loop() { + // USB -> Serial + for (int i = 0; i < USB_EP_SIZE; i++) { + // read maximum one EP_SIZE to not block + if (Serial.available()) + Serial1.write(Serial.read()); + else break; + } + + // Serial -> USB + if (Serial1.available()) { + Serial.flush(); + // send maximum one EP_SIZE to give the usb some time to flush the buffer + uint8_t buff[USB_EP_SIZE-1]; + int i = 0; + for (i = 0; i < USB_EP_SIZE-1; i++) { + if (Serial1.available()) + buff[i] = Serial1.read(); + else break; + } + Serial.write(buff, i); + } + + // reset the main mcu if DTR goes HIGH + static bool lastDTR = 0; + bool newDTR = (Serial.lineState()&CDC_CONTROL_LINE_OUT_DTR) ? 1 : 0; + if (lastDTR ^ newDTR) + digitalWrite(MAIN_MCU_RESET_PIN, lastDTR); + lastDTR = newDTR; +} + From 66e54035988253836a2b91792997c7dcb0d6763f Mon Sep 17 00:00:00 2001 From: Nico Date: Sun, 30 Nov 2014 12:26:45 +0100 Subject: [PATCH 062/602] NO USB Update --- .../HoodLoader2_NoUSB_Blink/HoodLoader2_NoUSB_Blink.ino | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_NoUSB_Blink/HoodLoader2_NoUSB_Blink.ino b/plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_NoUSB_Blink/HoodLoader2_NoUSB_Blink.ino index 8874a1d1c6..4f5fb1a004 100644 --- a/plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_NoUSB_Blink/HoodLoader2_NoUSB_Blink.ino +++ b/plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_NoUSB_Blink/HoodLoader2_NoUSB_Blink.ino @@ -13,12 +13,14 @@ Keep in mind that the logic is inverted then! LOW=HIGH and vice versa. */ +#ifndef USBCON // workaround for undefined USBCON has to be placed in every sketch // otherwise the timings wont work correctly ISR(USB_GEN_vect) { UDINT = 0; } +#endif void setup() { TX_RX_LED_INIT; From 3fceb9c8fb7ce944d85797198368b8453736f121 Mon Sep 17 00:00:00 2001 From: Nico Date: Sun, 30 Nov 2014 14:17:15 +0100 Subject: [PATCH 063/602] Added Header Picture --- plugins/KeyboardioHID/.gitignore | 2 ++ plugins/KeyboardioHID/Readme.md | 6 ++++-- plugins/KeyboardioHID/header.jpg | Bin 0 -> 150263 bytes 3 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 plugins/KeyboardioHID/.gitignore create mode 100644 plugins/KeyboardioHID/header.jpg diff --git a/plugins/KeyboardioHID/.gitignore b/plugins/KeyboardioHID/.gitignore new file mode 100644 index 0000000000..117ca863b4 --- /dev/null +++ b/plugins/KeyboardioHID/.gitignore @@ -0,0 +1,2 @@ +dev/* +*.pdn \ No newline at end of file diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 2807e10b1b..529ef898db 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -1,5 +1,7 @@ -Arduino HID Project 2.0 -======================= +Arduino HID Project 2.0 (Uno/Mega/Leonardo/Micro) +================================================= +![Header Picture](header.jpg) + This project went through a lot of phases and has now reached an HID library with 3 software solutions. The idea is to enable enhanced USB functions to almost all 'standard' Arduino boards. This is done with slightly different methods for different boards. diff --git a/plugins/KeyboardioHID/header.jpg b/plugins/KeyboardioHID/header.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d87032a640a9052d4cd80c2b450a8dc27659d8a1 GIT binary patch literal 150263 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 JJ%|06_&>z+PgDQ^ literal 0 HcmV?d00001 From b1a06b5b327388c8a1031732e8e3e0942e79ea18 Mon Sep 17 00:00:00 2001 From: Nico Date: Sun, 30 Nov 2014 14:18:59 +0100 Subject: [PATCH 064/602] Readme --- plugins/KeyboardioHID/Readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 529ef898db..570fb0d883 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -1,5 +1,5 @@ -Arduino HID Project 2.0 (Uno/Mega/Leonardo/Micro) -================================================= +Arduino HID Project 2.0 +======================= ![Header Picture](header.jpg) This project went through a lot of phases and has now reached an HID library with 3 software solutions. From 6f2790eb3bbfde624395c9b1222fbc1f5572645d Mon Sep 17 00:00:00 2001 From: Nico Date: Sun, 7 Dec 2014 19:46:09 +0100 Subject: [PATCH 065/602] Made outdated version more clear + credits --- plugins/KeyboardioHID/Readme.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 570fb0d883..61daaea1b7 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -65,7 +65,7 @@ on how to install the unsigned HoodLoader2 drivers. You can grab the latest version + installing instructions of each HoodLoader in its own repository linked above. Of course the new version [HoodLoader2](https://github.com/NicoHood/HoodLoader2) is recommend and HoodLoader1 API is only for compatibility reasons online. -The old, full HoodLoader1 HID (software)solution (before update 2.0) can be found here: https://github.com/NicoHood/HID/tree/3d8a9b40752a143141b8be4b8f744e203c80b000 +The old, full HoodLoader1 HID (software)solution (before update 2.0) can be found here: [Outdated HID Project for 1.5.7](https://github.com/NicoHood/HID/tree/3d8a9b40752a143141b8be4b8f744e203c80b000) How to use @@ -110,7 +110,7 @@ Its more a legacy version to still use HoodLoader1 or to reimplement something s **The older, full integrated HID Core can be found here.** Keep in mind to remove all newer stuff since it may conflict (a clean arduino core would do it). It is not better than this solution, maybe easier to use since its just more integrated. -https://github.com/NicoHood/HID/tree/3d8a9b40752a143141b8be4b8f744e203c80b000 +[Outdated HID Project for 1.5.7](https://github.com/NicoHood/HID/tree/3d8a9b40752a143141b8be4b8f744e203c80b000) How it works @@ -136,6 +136,10 @@ This project wouldnt be possible without * [Athanasios Douitsis Multimedia Keys Example](https://github.com/aduitsis/ardumultimedia) * [The Original Arduino Sources](https://github.com/arduino/Arduino/tree/master/hardware/arduino/firmwares/atmegaxxu2/arduino-usbserial) * [USBlyzer](http://www.usblyzer.com/) +* [Mattairtechs 16u2 Lufa USB Core](https://www.mattairtech.com/index.php/development-boards/mt-db-u1.html) +* [Paul Brook's Minimus 32u2 Arduino USB Core](https://github.com/pbrook/minimus-arduino) +* [Paul Stoffregen's Teensy Core](https://github.com/PaulStoffregen/cores) +* [Keyboard Led Out report by hartmut_holgraefe](http://forum.arduino.cc/index.php?topic=173583.0) * A lot of searching through the web * The awesome official Arduino IRC chat! * [The NicoHood Protocol ^.^](https://github.com/NicoHood/NicoHoodProtocol) From 73de292eca536af5a8b1f5b1fdf0fa04c8d24110 Mon Sep 17 00:00:00 2001 From: Nico Date: Mon, 8 Dec 2014 16:59:45 +0100 Subject: [PATCH 066/602] Notice for User HID settings --- plugins/KeyboardioHID/USBAPI.h | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/KeyboardioHID/USBAPI.h b/plugins/KeyboardioHID/USBAPI.h index d3c9bd317e..9cae349d22 100644 --- a/plugins/KeyboardioHID/USBAPI.h +++ b/plugins/KeyboardioHID/USBAPI.h @@ -128,6 +128,7 @@ HID_MEDIA_SIZE + HID_SYSTEM_SIZE + HID_GAMEPAD_SIZE + 0) #define USE_USB_API // activate all API's +// ignore this, this is not the setting for the USB core, its only used for non usb boards to use the APIs #define HID_MOUSE_ENABLED #define HID_KEYBOARD_ENABLED #define HID_RAWHID_ENABLED From b73d19dff3b749e97b6dd0f08df62444edae4671 Mon Sep 17 00:00:00 2001 From: Nico Date: Mon, 8 Dec 2014 17:02:18 +0100 Subject: [PATCH 067/602] Starting from Zero --- plugins/KeyboardioHID/.gitignore | 2 - plugins/KeyboardioHID/CDC.cpp | 275 ----- plugins/KeyboardioHID/HID.cpp | 405 ------- plugins/KeyboardioHID/Readme.md | 330 ----- plugins/KeyboardioHID/USBAPI.h | 1078 ----------------- plugins/KeyboardioHID/USBCore.cpp | 785 ------------ plugins/KeyboardioHID/USBCore.h | 307 ----- plugins/KeyboardioHID/USBDesc.h | 90 -- .../AdvancedGamepad/AdvancedGamepad.ino | 53 - .../AdvancedKeyboard/AdvancedKeyboard.ino | 98 -- .../AdvancedRawHID/AdvancedRawHID.ino | 109 -- .../examples/Basics/Gamepad/Gamepad.ino | 87 -- .../examples/Basics/Keyboard/Keyboard.ino | 84 -- .../examples/Basics/Media/Media.ino | 58 - .../examples/Basics/Mouse/Mouse.ino | 47 - .../examples/Basics/System/System.ino | 41 - .../HoodLoader1_API_Legacy.ino | 163 --- .../HoodLoader2_NoUSB_Blink.ino | 38 - .../HoodLoader2_PWM_Fade.ino | 39 - .../HoodLoader2_SerialKeyboard.ino | 54 - .../HoodLoader2_USB-Serial.ino | 51 - .../Gamepad_Project/Gamepad_Project.ino | 110 -- plugins/KeyboardioHID/examples/Readme.md | 4 - plugins/KeyboardioHID/header.jpg | Bin 150263 -> 0 bytes plugins/KeyboardioHID/keywords.txt | 201 --- plugins/KeyboardioHID/wiring_private.h | 73 -- 26 files changed, 4582 deletions(-) delete mode 100644 plugins/KeyboardioHID/.gitignore delete mode 100644 plugins/KeyboardioHID/CDC.cpp delete mode 100644 plugins/KeyboardioHID/HID.cpp delete mode 100644 plugins/KeyboardioHID/Readme.md delete mode 100644 plugins/KeyboardioHID/USBAPI.h delete mode 100644 plugins/KeyboardioHID/USBCore.cpp delete mode 100644 plugins/KeyboardioHID/USBCore.h delete mode 100644 plugins/KeyboardioHID/USBDesc.h delete mode 100644 plugins/KeyboardioHID/examples/Advanced/AdvancedGamepad/AdvancedGamepad.ino delete mode 100644 plugins/KeyboardioHID/examples/Advanced/AdvancedKeyboard/AdvancedKeyboard.ino delete mode 100644 plugins/KeyboardioHID/examples/Advanced/AdvancedRawHID/AdvancedRawHID.ino delete mode 100644 plugins/KeyboardioHID/examples/Basics/Gamepad/Gamepad.ino delete mode 100644 plugins/KeyboardioHID/examples/Basics/Keyboard/Keyboard.ino delete mode 100644 plugins/KeyboardioHID/examples/Basics/Media/Media.ino delete mode 100644 plugins/KeyboardioHID/examples/Basics/Mouse/Mouse.ino delete mode 100644 plugins/KeyboardioHID/examples/Basics/System/System.ino delete mode 100644 plugins/KeyboardioHID/examples/HoodLoader1/HoodLoader1_API_Legacy/HoodLoader1_API_Legacy.ino delete mode 100644 plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_NoUSB_Blink/HoodLoader2_NoUSB_Blink.ino delete mode 100644 plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_PWM_Fade/HoodLoader2_PWM_Fade.ino delete mode 100644 plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_SerialKeyboard/HoodLoader2_SerialKeyboard.ino delete mode 100644 plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_USB-Serial/HoodLoader2_USB-Serial.ino delete mode 100644 plugins/KeyboardioHID/examples/Projects/Gamepad_Project/Gamepad_Project.ino delete mode 100644 plugins/KeyboardioHID/examples/Readme.md delete mode 100644 plugins/KeyboardioHID/header.jpg delete mode 100644 plugins/KeyboardioHID/keywords.txt delete mode 100644 plugins/KeyboardioHID/wiring_private.h diff --git a/plugins/KeyboardioHID/.gitignore b/plugins/KeyboardioHID/.gitignore deleted file mode 100644 index 117ca863b4..0000000000 --- a/plugins/KeyboardioHID/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -dev/* -*.pdn \ No newline at end of file diff --git a/plugins/KeyboardioHID/CDC.cpp b/plugins/KeyboardioHID/CDC.cpp deleted file mode 100644 index d08ba97842..0000000000 --- a/plugins/KeyboardioHID/CDC.cpp +++ /dev/null @@ -1,275 +0,0 @@ - - -/* 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. -*/ - -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -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 "USBAPI.h" -#include - -#if defined(USBCON) -#ifdef CDC_ENABLED - -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), - // edit by NicoHood - D_ENDPOINT(USB_ENDPOINT_OUT(CDC_ENDPOINT_OUT), USB_ENDPOINT_TYPE_BULK, USB_EP_SIZE, 0), - D_ENDPOINT(USB_ENDPOINT_IN(CDC_ENDPOINT_IN), USB_ENDPOINT_TYPE_BULK, USB_EP_SIZE, 0) -}; - -int WEAK CDC_GetInterface(u8* interfaceNum) -{ - interfaceNum[0] += 2; // uses 2 - return USB_SendControl(TRANSFER_PGM, &_cdcInterface, sizeof(_cdcInterface)); -} -// edit by NicoHood -// ensure the address isnt used anywhere else by adding a compiler flag in the makefile lf flag -// -Wl,--section-start=.blkey=0x280 -//TODO where to put that flag? use different position: 0x100 maybe? -// someone has to add the compiler flag to fix this bug: https://github.com/arduino/Arduino/issues/2474 -//volatile uint8_t MagicBootKey __attribute__((section(".blkey"))); - -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); - } - - if (CDC_SET_CONTROL_LINE_STATE == r) - { - _usbLineInfo.lineState = setup.wValueL; - } - - if (CDC_SET_LINE_CODING == r || CDC_SET_CONTROL_LINE_STATE == r) - { - // 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 - - // We check DTR state to determine if host port is open (bit 0 of lineState). - if (1200 == _usbLineInfo.dwDTERate && (_usbLineInfo.lineState & 0x01) == 0) - { - // edit by NicoHood - // change ram pointer to fit the 16u2's ram size and only use a 8bit value -#if defined(__AVR_ATmega32U4__) - *(uint16_t *)0x0800 = 0x7777; - wdt_enable(WDTO_120MS); -#else - // workaround for this issue: - // https://github.com/arduino/Arduino/issues/2474 - // I didnt change this for the 32u4 to simply not touch their code - cli(); - - //MagicBootKey = 0x77; - *(uint8_t *)0x0280 = 0x77; - - wdt_enable(WDTO_120MS); - - // wait for reset - for (;;); -#endif - - } - 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. - - // edit by NicoHood -#if defined(__AVR_ATmega32U4__) - wdt_disable(); - wdt_reset(); - *(uint16_t *)0x0800 = 0x0; -#else - // not used because of the workaround above - //wdt_disable(); - //wdt_reset(); - //MagicBootKey = 0x0; - //*(uint8_t *)0x0280 = 0x00; -#endif - } - } - return true; - } - return false; -} - - -void Serial_::begin(unsigned long /* baud_count */) -{ - peek_buffer = -1; -} - -void Serial_::begin(unsigned long /* baud_count */, byte /* config */) -{ - peek_buffer = -1; -} - -void Serial_::end(void) -{ -} - -// edit by NicoHood -uint8_t Serial_::lineState(void) -{ - return _usbLineInfo.lineState; -} - -int Serial_::available(void) -{ - if (peek_buffer >= 0) { - return 1 + USB_Available(CDC_RX); - } - return USB_Available(CDC_RX); -} - -int Serial_::peek(void) -{ - if (peek_buffer < 0) - peek_buffer = USB_Recv(CDC_RX); - return peek_buffer; -} - -int Serial_::read(void) -{ - if (peek_buffer >= 0) { - int c = peek_buffer; - peek_buffer = -1; - return c; - } - return USB_Recv(CDC_RX); -} - -void Serial_::flush(void) -{ - USB_Flush(CDC_TX); -} - -size_t Serial_::write(uint8_t c) -{ - return write(&c, 1); -} - -size_t Serial_::write(const uint8_t *buffer, size_t size) -{ - /* 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, buffer, size); - 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/plugins/KeyboardioHID/HID.cpp b/plugins/KeyboardioHID/HID.cpp deleted file mode 100644 index 70f8d60cfe..0000000000 --- a/plugins/KeyboardioHID/HID.cpp +++ /dev/null @@ -1,405 +0,0 @@ - - -/* 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. -*/ - -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -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 "USBAPI.h" - -#if defined(USBCON) -#ifdef HID_ENABLED - -//================================================================================ -//================================================================================ -// HID report descriptor - -#if defined USBCON && defined(HID_KEYBOARD_ENABLED) && defined(HID_KEYBOARD_LEDS_ENABLED) -// extern accessible led out report -uint8_t hid_keyboard_leds = 0; -#endif - -extern const u8 _hidReportDescriptor[] PROGMEM; -const u8 _hidReportDescriptor[] = { -#ifdef HID_MOUSE_ENABLED - // 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, HID_REPORTID_MouseReport,// REPORT_ID - // 5 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) - 0x95, 0x05, // REPORT_COUNT (5) - 0x75, 0x01, // REPORT_SIZE (1) - 0x81, 0x02, // INPUT (Data,Var,Abs) - // reserved - 0x95, 0x01, // REPORT_COUNT (1) - 0x75, 0x03, // REPORT_SIZE (3) - 0x81, 0x03, // INPUT (Cnst,Var,Abs) - // x, y, wheel - 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) - // end - 0xc0, // END_COLLECTION - 0xc0, // END_COLLECTION -#endif - -#ifdef HID_KEYBOARD_ENABLED - // Keyboard - 0x05, 0x01, // USAGE_PAGE (Generic Desktop) - 0x09, 0x06, // USAGE (Keyboard) - 0xa1, 0x01, // COLLECTION (Application) - 0x85, HID_REPORTID_KeyboardReport, // REPORT_ID - 0x05, 0x07, // USAGE_PAGE (Keyboard) - // modifiers - 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) - // reserved byte - 0x95, 0x01, // REPORT_COUNT (1) - 0x75, 0x08, // REPORT_SIZE (8) - 0x81, 0x03, // INPUT (Cnst,Var,Abs) - // Key[6] Array - 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) -#ifdef HID_KEYBOARD_LEDS_ENABLED - // LEDs for num lock etc - 0x05, 0x08, /* USAGE_PAGE (LEDs) */ - 0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */ - 0x29, 0x05, /* USAGE_MAXIMUM (Kana) */ - 0x95, 0x05, /* REPORT_COUNT (5) */ - 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */ - // Reserved 3 bits - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0x75, 0x03, /* REPORT_SIZE (3) */ - 0x91, 0x03, /* OUTPUT (Cnst,Var,Abs) */ -#endif - // end - 0xc0, // END_COLLECTION -#endif - -#ifdef HID_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, HID_REPORTID_RawKeyboardReport, // REPORT_ID - 0x75, 0x08, // report size = 8 bits - 0x15, 0x00, // logical minimum = 0 - 0x26, 0xFF, 0x00, // logical maximum = 255 - - 0x95, RAWHID_TX_SIZE, // report count TX - 0x09, 0x01, // usage - 0x81, 0x02, // Input (array) - - 0x95, RAWHID_RX_SIZE, // report count RX - 0x09, 0x02, // usage - 0x91, 0x02, // Output (array) - 0xC0, // end collection -#endif - -#ifdef HID_MEDIA_ENABLED - // Media - 0x05, 0x0C, // usage page (consumer device) - 0x09, 0x01, // usage -- consumer control - 0xA1, 0x01, // collection (application) - 0x85, HID_REPORTID_MediaReport, // report id - //0x05, 0x0C, // usage page (consumer) - - // 4 media Keys - 0x15, 0x00, //logical minimum - 0x26, 0xFF, 0x03, //logical maximum (3ff) - 0x19, 0x00, // usage minimum (0) - 0x2A, 0xFF, 0x03, //usage maximum (3ff) - 0x95, 0x04, //report count (4) - 0x75, 0x10, //report size (16) - - 0x81, 0x00, //input - 0xC0, //end collection -#endif - -#ifdef HID_SYSTEM_ENABLED - // System - 0x05, 0x01, // USAGE_PAGE (Generic Desktop) - 0x09, 0x80, // USAGE (System Control) - 0xa1, 0x01, // COLLECTION (Application) - 0x85, HID_REPORTID_SystemReport, // REPORT_ID - // 1 system key - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255) - 0x19, 0x00, // USAGE_MINIMUM (Undefined) - 0x29, 0xff, // USAGE_MAXIMUM (System Menu Down) - 0x95, 0x01, // REPORT_COUNT (1) - 0x75, 0x08, // REPORT_SIZE (8) - 0x81, 0x00, // INPUT (Data,Ary,Abs) - 0xc0, // END_COLLECTION -#endif - -#ifdef HID_GAMEPAD_ENABLED - // Gamepad - 0x05, 0x01, // USAGE_PAGE (Generic Desktop) - 0x09, 0x04, // USAGE (Joystick) - 0xa1, 0x01, // COLLECTION (Application) - 0x85, HID_REPORTID_GamepadReport, // REPORT_ID - // 32 Buttons - 0x05, 0x09, // USAGE_PAGE (Button) - 0x19, 0x01, // USAGE_MINIMUM (Button 1) - 0x29, 0x20, // USAGE_MAXIMUM (Button 32) - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x25, 0x01, // LOGICAL_MAXIMUM (1) - 0x75, 0x01, // REPORT_SIZE (1) - 0x95, 0x20, // REPORT_COUNT (32) - 0x81, 0x02, // INPUT (Data,Var,Abs) - // 4 16bit Axis - 0x05, 0x01, // USAGE_PAGE (Generic Desktop) - 0xa1, 0x00, // COLLECTION (Physical) - 0x09, 0x30, // USAGE (X) - 0x09, 0x31, // USAGE (Y) - 0x09, 0x33, // USAGE (Rx) - 0x09, 0x34, // USAGE (Ry) - 0x16, 0x00, 0x80, // LOGICAL_MINIMUM (-32768) - 0x26, 0xFF, 0x7F, // LOGICAL_MAXIMUM (32767) - 0x75, 0x10, // REPORT_SIZE (16) - 0x95, 0x04, // REPORT_COUNT (4) - 0x81, 0x02, // INPUT (Data,Var,Abs) - // 2 8bit Axis - 0x09, 0x32, // USAGE (Z) - 0x09, 0x35, // USAGE (Rz) - 0x15, 0x80, // LOGICAL_MINIMUM (-128) - 0x25, 0x7F, // LOGICAL_MAXIMUM (127) - 0x75, 0x08, // REPORT_SIZE (8) - 0x95, 0x02, // REPORT_COUNT (2) - 0x81, 0x02, // INPUT (Data,Var,Abs) - 0xc0, // END_COLLECTION - // 2 Hat Switches - 0x05, 0x01, // USAGE_PAGE (Generic Desktop) - 0x09, 0x39, // USAGE (Hat switch) - 0x09, 0x39, // USAGE (Hat switch) - 0x15, 0x01, // LOGICAL_MINIMUM (1) - 0x25, 0x08, // LOGICAL_MAXIMUM (8) - 0x95, 0x02, // REPORT_COUNT (2) - 0x75, 0x04, // REPORT_SIZE (4) - 0x81, 0x02, // INPUT (Data,Var,Abs) - 0xc0, // END_COLLECTION -#endif -}; - -extern const HIDDescriptor _hidInterface PROGMEM; -const HIDDescriptor _hidInterface = -{ - D_INTERFACE(HID_INTERFACE, 1, 3, 0, 0), - D_HIDREPORT(sizeof(_hidReportDescriptor)), - // edit by NicoHood - D_ENDPOINT(USB_ENDPOINT_IN(HID_ENDPOINT_INT), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 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; - } - - // edit by NicoHood -#if defined USBCON && defined(HID_KEYBOARD_ENABLED) && defined(HID_KEYBOARD_LEDS_ENABLED) - if (HID_SET_REPORT == r) - { - if (setup.wLength == 2) - { - uint8_t data[2]; - if (2 == USB_RecvControl(data, 2)) - { - // write led out report data - hid_keyboard_leds=data[1]; - } - } - } -#endif - } - return false; -} - -#endif - -#else if defined(USE_USB_API) - -// still provide the weak HID_SendReport function to be able to overwrite it externaly -void __attribute__((weak)) HID_SendReport(uint8_t id, const void* data, int len) -{ - // the user has to overwrite this if no USB Core is used -} - -#endif /* if defined(USBCON) */ - -// HID API libs are only included if the device has USB functionality or if the USE_USB_API is needed -#if defined(USBCON) || defined(USE_USB_API) - -//================================================================================ -// Mouse -//================================================================================ - -#ifdef HID_MOUSE_ENABLED - -// object instance -Mouse_ Mouse; - -#endif - -//================================================================================ -// Keyboard -//================================================================================ - -#ifdef HID_KEYBOARD_ENABLED - -// object instance -Keyboard_ Keyboard; - -#endif - - -//================================================================================ -// Media -//================================================================================ - -#ifdef HID_MEDIA_ENABLED - -// object instance -Media_ Media; - -#endif - - -//================================================================================ -// System -//================================================================================ - -#ifdef HID_SYSTEAM_ENABLED - -// object instance -System_ System; - -#endif - - -//================================================================================ -// Gamepad -//================================================================================ - -#ifdef HID_GAMEPAD_ENABLED - -// object instance -Gamepad_ Gamepad; - -#endif - -#endif // if defined(USBCON) || defined(USE_USB_API) \ No newline at end of file diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md deleted file mode 100644 index 61daaea1b7..0000000000 --- a/plugins/KeyboardioHID/Readme.md +++ /dev/null @@ -1,330 +0,0 @@ -Arduino HID Project 2.0 -======================= -![Header Picture](header.jpg) - -This project went through a lot of phases and has now reached an HID library with 3 software solutions. -The idea is to enable enhanced USB functions to almost all 'standard' Arduino boards. -This is done with slightly different methods for different boards. - -**Arduino IDE 1.5.8 is required for the HID Project.** - -**Supported HID devices:** - -* Keyboard with Leds out (modifiers + 6 keys pressed at the same time) -* Mouse (5 buttons, move, wheel) -* Media Keys (4 keys for music player, webbrowser and more) -* System Key (for PC standby/shutdown) -* 1 Gamepad (32 buttons, 4 16bit axis, 2 8bit axis, 2 D-Pads) - -**Supported Arduinos:** -* Uno -* Mega -* Leonardo -* (Pro)Micro -* Any other 8u2/16u/at90usb162/32u2/32u4 compatible board - -| Leonardo/Micro | Uno/Mega HoodLoader2 | Uno/Mega HoodLoader1 | -|:---------------------------|:----------------------------|---------------------------------------| -| Extended Arduino USB-Core | Same Core as Leonardo/Micro | Coded with Lufa | -| More HID devices | Fully reprogrammable 16u2 | No reprogrammable 16u2 | -| Keyboard Led Out report | Serial0 fully usable | Main MCU sends HID reports on Serial0 | -| System Wakeup fix (soon) | | Serial Protocol filters HID reports | -| Serial Control Line access | | Built-in ISP function | - -The HID project contains HID APIs to generate HID reports and functions to send them to the USB Host. -The API (syntax/usage) of the HID Project is always the same for each solution, **you can port code from one device to another very easy**. - -* On a Leonardo this function is extended and improved to get more HID devices + some improvements. -* [HoodLoader2](https://github.com/NicoHood/HoodLoader2) is a BootLoader for the 16u2 that let's you use it as standalone MCU with the same USB-Core. -* [HoodLoader1](https://github.com/NicoHood/HoodLoader) is a 16u2 firmware that filters special HW Serial signals from the main MCU and sends HID signals to the USB Host. - - -To make things more clear the HID Software is in a separate repository than the HoodLoader (1 & 2) sources and installing instructions. -**HoodLoader 1&2 is only used for an Uno/Mega to actually enable USB functions.** The 16u2 is normally used for USB-Serial programming of the main MCU but can do way more than that. -To use HoodLoader1&2 you also need the HID Project. For more information and installation instructions see the specific repository. - -HoodLoader1 was the first solution to enable HID functions to the Uno/Mega but HoodLoader2 opens way more options because you can reprogram the whole MCU standalone. -See the repository for more infos about this great new opportunity. HoodLoader1 API is still usable in a specific example. HoodLoader1&2 are not needed/compatible with a Leonardo/Micro. - -Installation -============ - -**Please remove any older HID Project files from your sketchbook and your Arduino core to not run into any problems.** - -Download the library and [install it](http://arduino.cc/en/pmwiki.php?n=Guide/Libraries) like you are used to (access the examples, keywords.txt with IDE). -Then **move and replace** all .h and .cpp files to the path below. **I strongly recommend to install the library like this. Otherwise it wont work.** - -``` -C:\Arduino\arduino-1.5.8\hardware\arduino\avr\cores\arduino -``` -The installation path may differ to yours. **Please use Arduino IDE 1.5.8** and file an issue if a newer version isn't working. -Restart the IDE. Ensure all drivers are installed. See [this](https://learn.sparkfun.com/tutorials/disabling-driver-signature-on-windows-8/disabling-signed-driver-enforcement-on-windows-8) -on how to install the unsigned HoodLoader2 drivers. - -**If you are using an Arduino Uno/Mega follow the installation instructions of the HoodLoader1 or 2** (no extra hardware needed, just a few cables). -You can grab the latest version + installing instructions of each HoodLoader in its own repository linked above. - -Of course the new version [HoodLoader2](https://github.com/NicoHood/HoodLoader2) is recommend and HoodLoader1 API is only for compatibility reasons online. -The old, full HoodLoader1 HID (software)solution (before update 2.0) can be found here: [Outdated HID Project for 1.5.7](https://github.com/NicoHood/HID/tree/3d8a9b40752a143141b8be4b8f744e203c80b000) - - -How to use -========== - -### Micro/Leonardo + HoodLoader2 - -**Edit the USBAPI.h you installed to de/activate usb functions.** By default only Mouse and Keyboard is activated. -The more you activate the more flash is used. For the Uno/Mega you have a limited ram/flash size, so please try not to exceed this limit and only use the needed HID devices. -RawHID is currently not working properly. - -**Try the Basic examples for each HID device. They are pretty much self explaining.** - -**The HoodLoader2 examples are to show some special cases for the 16u2.** It shows how to remove the USB functions if needed, -how to optimally use ram since its limited and some ported sketches to reprogram the main MCU or for the missing ISP function. Please check them out. - - -### HoodLoader1 - -**Try the HoodLoader1 example. It provides the basic Serial protocol API to send HID reports. You have to copy this to every sketch again.** - -With HoodLoader1 you can **only use baud 115200 for HID** due to speed/programming reasons. -Use Serial.begin(115200) in every HoodLoader1 sketch. -Its not bad anyway because its the fastest baud and you want fast HID recognition. -You still can **fully use any other baud** for normal sketches but HID wont work. -If you try nevertheless it will output Serial crap to the monitor. - -Keep in mind that HoodLoader1 has **no flush function**. If the PC is reading HID too slow it can miss data, like on a Raspberry Pi. -Add a delay to the sending function or just use the newer HoodLoader2. - -Always release buttons to not cause any erros. Replug USB cable to reset the values if anything went wrong. -Keep in mind that **with HoodLoader1 the 16u2 is always on**. The 16u2 and its HID reports are not reset if the main MCU is reset. -So you need to reset the HID reports on every startup with a begin() of each used API. -On Windows every USB report will reset when you open the lock screen. -See [deactivate HID function (Hoodloader only)](https://github.com/NicoHood/Hoodloader) how to temporary disable HID again. - -For **16u2 as ISP usage** (optional, Hoodloader only, has nothing to do with HID function) -see [Hoodloader repository](https://github.com/NicoHood/Hoodloader). - -The sending API is no longer integrated directly in the HID Project since it is now more an extended USB-Core and this has nothing to do with it. -Its more a legacy version to still use HoodLoader1 or to reimplement something similar with HoodLoader2 if you still want full report access for the main MCU. - -**The older, full integrated HID Core can be found here.** Keep in mind to remove all newer stuff since it may conflict (a clean arduino core would do it). -It is not better than this solution, maybe easier to use since its just more integrated. -[Outdated HID Project for 1.5.7](https://github.com/NicoHood/HID/tree/3d8a9b40752a143141b8be4b8f744e203c80b000) - - -How it works -============ -For the Leonardo/Micro + HoodLoader2 its a modified version of the HID descriptors and USB-Core. -This changes were made to improve the functions, add more devices and add u2 series compatibility. - -HoodLoader1 only: -For the Uno/Mega you need a special Bootloader. Why? See [Hoodloader repository](https://github.com/NicoHood/Hoodloader). -To sum it up: Serial information is grabbed by the "man in the middle, 16u2" and you dont have to worry to get any wrong Serial stuff via USB. -Thatswhy you need a special baud (115200) that both sides can communicate with each other. -Every USB command is send via a special [NicoHood Protocol](https://github.com/NicoHood/NicoHoodProtocol) -that's filtered out by the 16u2. If you use Serial0 for extern devices it cannot filter the signal of course. -You can still use the NHP, just dont use the reserved Address 1. - -This project wouldnt be possible without -======================================== - -* [Lufa 140302 from Dean Camera](http://www.fourwalledcubicle.com/LUFA.php) -* [Darran's HID Projects] (https://github.com/harlequin-tech/arduino-usb) -* [Connor's Joystick for the Leonardo](http://www.imaginaryindustries.com/blog/?p=80) -* [Stefan Jones Multimedia Keys Example](http://stefanjones.ca/blog/arduino-leonardo-remote-multimedia-keys/) -* [Athanasios Douitsis Multimedia Keys Example](https://github.com/aduitsis/ardumultimedia) -* [The Original Arduino Sources](https://github.com/arduino/Arduino/tree/master/hardware/arduino/firmwares/atmegaxxu2/arduino-usbserial) -* [USBlyzer](http://www.usblyzer.com/) -* [Mattairtechs 16u2 Lufa USB Core](https://www.mattairtech.com/index.php/development-boards/mt-db-u1.html) -* [Paul Brook's Minimus 32u2 Arduino USB Core](https://github.com/pbrook/minimus-arduino) -* [Paul Stoffregen's Teensy Core](https://github.com/PaulStoffregen/cores) -* [Keyboard Led Out report by hartmut_holgraefe](http://forum.arduino.cc/index.php?topic=173583.0) -* A lot of searching through the web -* The awesome official Arduino IRC chat! -* [The NicoHood Protocol ^.^](https://github.com/NicoHood/NicoHoodProtocol) -* See HoodLoader1&2 repository for more credits/links - -**Projects can be found here:** -* [Gamecube to PC adapter](https://github.com/NicoHood/Nintendo) -* [Other projects](http://nicohood.wordpress.com/) -* For donations please contact me on my blog :) - -Ideas for the future -==================== -* Add more devices (even more?, voice device, flight control?) -* Add Midi (no more free Endpoints, possible on 32u4) -* Add HID rumble support (very hard) - -Known Bugs -========== -See [Hoodloader repository](https://github.com/NicoHood/Hoodloader) for Hoodloader related Bugs/Issues. - -System Wakeup is currently not working on all versions! Will be fixed soon! -System Shutdown is only working on Windows systems. - -RawHID is not working properly, test it at your own risk. - -Feel free to open an Issue on Github if you find a bug. Or message me via my [blog](http://nicohood.wordpress.com/)! - -Known Issues -============ - -**If You have weird Problems especially with controllers, let me know.** -Sometimes the problem is just that Windows messes up the PID so you might want to compile the hoodloader with a different PID -or reinstall the drivers. With HoodLoader1 we had a lot of problems especially with linux. - -XBMC 13.1 (a Media Center) uses Gamepad input. Its seems to not work and may cause weird errors. -Even with a standard Gamepad I have these errors. Just want to mention it here. - -The USB implementation of the Leonardo/Micro is not that good it can cause errors or disconnects with massiv Serial input. -This has nothing to do with this library! For example Adalight dosnt work well for me, -so you better use an Arduino Uno with Hoodloader1 (yes the older one!) for Mediacenter control and Ambilight. - -Do not use HID in interrupts because it uses Serial (Hoodloader1 only). Your Arduino can crash! - -HoodLoader1 only: If you get a checksum error after uploading please message me and send me the whole project. -Same if your Arduino crashes and dont want to upload sketches anymore (Replug usb fixes this). -These bugs occurred while developing the bootloader and should be fixed. Just in case it happens again I noted it here. -USB can behave weird, so please check your code for errors first. If you cannot find a mistake open a Github issue. - -Version History -=============== -``` -2.0 Release (29.11.2014) -* Added HoodLoader2 -* Separated HoodLoader1&2 more -* Added u2 series for USB-Core -* Extended USB core and fixed minor things for the u2 series -* Added Led Out report. -* Added CDC Line state -* Reworked the whole library structure again - -1.8 Beta Release (26.08.2014) -* Changes in the Hoodloader: - * **Huge improvements**, see [Hoodloader repository](https://github.com/NicoHood/Hoodloader) - * Reworked the whole library, easy installation now - * HID fixes for Media Keys/Ubuntu - * Removed Joystick, added 4 Gamepads - -1.7.3 Beta Release (10.08.2014) -* Changes in the Hoodloader: - * Fixed HID flush bug (1.6 - 1.7.2) - -1.7.2 Beta Release (10.08.2014) -* Changes in the Hoodloader: - * Added Lite version for 8u2 - * Added Versions that show up as Uno/Mega (not recommended) - * Makefile and structure changes - -1.7.1 Beta Release (10.08.2014) -* Changes in the Hoodloader: - * Fixed HID deactivation bug - -1.7 Beta Release (10.08.2014) -* Changes in the Hoodloader: - * Works as ISP now. See the [Hoodloader Repository](https://github.com/NicoHood/Hoodloader) for more information. - * Exceeded 8kb limit. For flashing a 8u2 use v1.6 please! -* Changed Readme text - -1.6 Beta Release (09.08.2014) -* Bugfixes in the Hoodloader: - * Changed HID management (not blocking that much, faster) - * added RawHID in/out (HID to Serial) -* Added RawHID Class and example - -1.5 Beta Release (21.07.2014) -* Moved Hoodloader source to a [separate Github page](https://github.com/NicoHood/Hoodloader) -* Bugfixes in the Hoodloader: - * Firmware is still available here - * Overall a lot of ram improvements, now with a big global union of ram - * Removed USBtoUSART buffer (not needed, saved 128/500 bytes) - * Removed Lite version because of better ram usage not needed - * Separated different modes better to not cause any errors in default mode - * Improved the deactivate option - * Integrated NHP directly - * Replaced LightweightRingbuffer with native Lufa Ringbuffer - * Improved writing to CDC Host - * Fixed a bug in checkNHPProtocol: & needs to be a == - * General structure changes - * Improved stability - * Fixed Arduino as ISP bug - -1.4.1 Beta Release (10.07.2014) -* #define Bugfix in USBAPI.h - -1.4 Beta Release (10.07.2014) -* Bugfixes in the Hoodloader: - * Added Lite Version with less ram usage - * Changed PIDs, edited driver file -* merged v1.0.x and v1.5.x together (both are compatible!) -* added IDE v1.5.7 support -* added Tutorials - -1.3 Beta Release (01.07.2014) -* Bugfixes in the Hoodloader: - * Improved ram usage (you can get even better but that messes up code and increases flash) -* **Important NHP fix inside the HID Class for Uno/Mega** - -1.2 Beta Release (22.06.2014) -* Added 1.0.x/1.5.x support -* Bugfixes in the Hoodloader: - * Sometimes HID Devices weren't updating when using more than 1 Device (set forcewrite to true) - * Fast updates crashed the bootloader (too much ram usage, set CDC buffer from 128b to 100b each) -* Minor file structure changes - -1.1 Beta Release (05.06.2014) -* Added Leonardo/Micro support -* Included NicoHoodProtocol -* Minor fixes - -1.0 Beta Release (03.06.2014) -``` - -Licence and Copyright -===================== -If you use this library for any cool project let me know! - -``` -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -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. -``` - -For Developers -============== -If you deactivate some reports it can occur that windows will cause problems and recognize it as different device. -While developing I had that much trouble that I had to change the PID. No way to repair the broken windows driver settings. -So be careful if you change the source on your own with important PIDs. (Therefore I made a 2nd Lite Version with a different PID and more ram) -Therefore reinstall the divers for any device or just dont touch the HID reports in the Bootloader. -The Leonardo/Micro version worked fine till now. - -See this how to uninstall the drivers: -https://support.microsoft.com/kb/315539 - -The Hootloader was coded with Windows7 and Visual Studio and compiled with a Raspberry Pi. -Lufa version 140302 is included! -**To recompile see instructions in [Hoodloader Repository](https://github.com/NicoHood/Hoodloader).** - -The difference between the Leonardo/Micro and Uno/Mega is that the HID Class is different. All other classes are the same. -The Leonardo/Micro Version uses USBAPI.h and no Serial while the Uno/Mega Version uses Serial. -You can also modify the library to send HID reports to other devices/other serials. -Just modify the HID Class (#define HID_SERIAL Serial). - diff --git a/plugins/KeyboardioHID/USBAPI.h b/plugins/KeyboardioHID/USBAPI.h deleted file mode 100644 index 9cae349d22..0000000000 --- a/plugins/KeyboardioHID/USBAPI.h +++ /dev/null @@ -1,1078 +0,0 @@ -/* - USBAPI.h - Copyright (c) 2005-2014 Arduino. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -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 __USBAPI__ -#define __USBAPI__ - -#include -#include -#include -#include -#include - -typedef unsigned char u8; -typedef unsigned short u16; -typedef unsigned long u32; - -#include "Arduino.h" - -#ifdef USBCON -// include needed HID devices -// the more you activate, the more flash it will take -// by default only Mouse + Keyboard are activated -#define HID_MOUSE_ENABLED -#define HID_KEYBOARD_ENABLED -//#define HID_KEYBOARD_LEDS_ENABLED - -//#define HID_RAWHID_ENABLED -//#define HID_MEDIA_ENABLED -//#define HID_SYSTEM_ENABLED -//#define HID_GAMEPAD_ENABLED - -// calculate HID report size for each device - -#ifdef HID_MOUSE_ENABLED -#define HID_MOUSE_SIZE 54 -#else -#define HID_MOUSE_SIZE 0 -#endif - -#ifdef HID_KEYBOARD_ENABLED -#define HID_KEYBOARD_SIZE (65-18) //18 for missing led out report = 47 - -#if defined USBCON && defined(HID_KEYBOARD_ENABLED) && defined(HID_KEYBOARD_LEDS_ENABLED) -// extern accessible led out report -extern uint8_t hid_keyboard_leds; - -#define LED_NUM_LOCK 0x01 -#define LED_CAPS_LOCK 0x02 -#define LED_SCROLL_LOCK 0x04 -#endif -#else -#define HID_KEYBOARD_SIZE 0 -#endif - -#ifdef HID_RAWHID_ENABLED -#define HID_RAWHID_SIZE 30 -#else -#define HID_RAWHID_SIZE 0 -#endif - -#ifdef HID_MEDIA_ENABLED -#define HID_MEDIA_SIZE 25 -#else -#define HID_MEDIA_SIZE 0 -#endif - -#ifdef HID_SYSTEM_ENABLED -#define HID_SYSTEM_SIZE 24 -#else -#define HID_SYSTEM_SIZE 0 -#endif - -#ifdef HID_GAMEPAD_ENABLED -#define HID_GAMEPAD_SIZE 80 -#else -#define HID_GAMEPAD_SIZE 0 -#endif - -// check if usb descriptor isn't too big for USBCore (seems to not work properly then) -#define HID_DESCRIPTOR_SIZE (HID_MOUSE_SIZE + HID_KEYBOARD_SIZE + HID_RAWHID_SIZE + \ -HID_MEDIA_SIZE + HID_SYSTEM_SIZE + HID_GAMEPAD_SIZE + 0) -#if (HID_DESCRIPTOR_SIZE >= 256) -#error Please do not use HID reports >= 256 bytes. Edit USBAPI.h and remove some devices, please. -#endif - -#else // ifdef USBCON - -// still use USE_USB_API sending API to be able to overwrite the HID_SendReport function -#define USE_USB_API - -// activate all API's -// ignore this, this is not the setting for the USB core, its only used for non usb boards to use the APIs -#define HID_MOUSE_ENABLED -#define HID_KEYBOARD_ENABLED -#define HID_RAWHID_ENABLED -#define HID_MEDIA_ENABLED -#define HID_SYSTEM_ENABLED -#define HID_GAMEPAD_ENABLED - -#endif - -/** Enum for the HID report IDs used in the device. */ -typedef enum{ - HID_REPORTID_NotAReport = 0x00, /**< first entry is always zero for multireports */ - HID_REPORTID_MouseReport = 0x01, /**< Report ID for the Mouse report within the device. */ - HID_REPORTID_KeyboardReport = 0x02, /**< Report ID for the Keyboard report within the device. */ - HID_REPORTID_RawKeyboardReport = 0x03, /**< Report ID for the Raw Keyboard report within the device. */ - HID_REPORTID_MediaReport = 0x04, /**< Report ID for the Media report within the device. */ - HID_REPORTID_SystemReport = 0x05, /**< Report ID for the Power report within the device. */ - HID_REPORTID_GamepadReport = 0x06, /**< Report ID for the Gamepad report within the device. */ -} HID_Report_IDs; - -// usb core functions -#if defined(USBCON) - -#include "USBDesc.h" -#include "USBCore.h" - -//================================================================================ -//================================================================================ -// 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) - -struct ring_buffer; - -#if (RAMEND < 1000) -#define SERIAL_BUFFER_SIZE 16 -#else -#define SERIAL_BUFFER_SIZE 64 -#endif - -class Serial_ : public Stream -{ -private: - int peek_buffer; -public: - Serial_() { peek_buffer = -1; }; - void begin(unsigned long); - void begin(unsigned long, uint8_t); - void end(void); - - // edit by NicoHood - uint8_t lineState(void); - - virtual int available(void); - virtual int peek(void); - virtual int read(void); - virtual void flush(void); - virtual size_t write(uint8_t); - virtual size_t write(const uint8_t*, size_t); - using Print::write; // pull in write(str) and write(buf, size) from Print - operator bool(); - - volatile uint8_t _rx_buffer_head; - volatile uint8_t _rx_buffer_tail; - unsigned char _rx_buffer[SERIAL_BUFFER_SIZE]; -}; -extern Serial_ Serial; - -#define HAVE_CDCSERIAL - -//================================================================================ -//================================================================================ -// 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); - - -#else if defined(USE_USB_API) - -// still provide the weak HID_SendReport function to be able to overwrite it externaly -void HID_SendReport(uint8_t id, const void* data, int len); - -#endif /* if defined(USBCON) */ - -// HID API libs are only included if the device has USB functionality or if the USE_USB_API is needed -#if defined(USBCON) || defined(USE_USB_API) - -//================================================================================ -// Mouse -//================================================================================ - -#ifdef HID_MOUSE_ENABLED - -#define MOUSE_LEFT 0x01 -#define MOUSE_RIGHT 0x02 -#define MOUSE_MIDDLE 0x04 -#define MOUSE_PREV 0x08 -#define MOUSE_NEXT 0x10 -#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE | MOUSE_PREV | MOUSE_NEXT) - -typedef union{ - // mouse report: 5 buttons, position, wheel - uint8_t whole8[4]; - uint16_t whole16[4 / 2]; - uint32_t whole32[4 / 4]; - - struct{ - uint8_t buttons : 5; - uint8_t reserved : 3; - int8_t xAxis; - int8_t yAxis; - int8_t wheel; - }; -} HID_MouseReport_Data_t; - -class Mouse_ -{ -public: - inline Mouse_(void) { - // removed this to avoid creating an instance of Mouse if not needed - // the user should call begin first. - //: _buttons(0){ - // empty - } - - inline void begin(void){ - // release all buttons - end(); - } - - inline void end(void){ - _buttons = 0; - move(0, 0, 0); - } - - inline void click(uint8_t b = MOUSE_LEFT){ - _buttons = b; - move(0, 0, 0); - _buttons = 0; - move(0, 0, 0); - } - - inline void move(signed char x, signed char y, signed char wheel = 0){ - u8 m[4]; - m[0] = _buttons; - m[1] = x; - m[2] = y; - m[3] = wheel; - HID_SendReport(1, m, 4); - } - - inline void press(uint8_t b = MOUSE_LEFT){ - // press LEFT by default - buttons(_buttons | b); - } - - inline void release(uint8_t b = MOUSE_LEFT){ - // release LEFT by default - buttons(_buttons & ~b); - } - - inline bool isPressed(uint8_t b = MOUSE_LEFT){ - // check LEFT by default - if ((b & _buttons) > 0) - return true; - return false; - } - -private: - uint8_t _buttons; - inline void buttons(uint8_t b){ - if (b != _buttons) - { - _buttons = b; - move(0, 0, 0); - } - } -}; -extern Mouse_ Mouse; - -#endif - - -//================================================================================ -// Keyboard -//================================================================================ - -#ifdef HID_KEYBOARD_ENABLED - -//Keyboard fixed/added missing Keys -#define KEY_PRINT 0xCE -#define KEY_NUM_LOCK 0xDB -#define KEY_SCROLL_LOCK 0xCF -#define KEY_PAUSE 0xD0 - -#define KEY_LEFT_CTRL 0x80 -#define KEY_LEFT_SHIFT 0x81 -#define KEY_LEFT_ALT 0x82 -#define KEY_LEFT_GUI 0x83 -#define KEY_LEFT_WINDOWS KEY_LEFT_GUI -#define KEY_RIGHT_CTRL 0x84 -#define KEY_RIGHT_SHIFT 0x85 -#define KEY_RIGHT_ALT 0x86 -#define KEY_RIGHT_GUI 0x87 -#define KEY_RIGHT_WINDOWS KEY_RIGHT_GUI - -#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_ENTER KEY_RETURN -#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 - -//Raw Keyboard definitions -#define RAW_KEYBOARD_LEFT_CTRL B00000001 -#define RAW_KEYBOARD_LEFT_SHIFT B00000010 -#define RAW_KEYBOARD_LEFT_ALT B00000100 -#define RAW_KEYBOARD_LEFT_GUI B00001000 -#define RAW_KEYBOARD_RIGHT_CTRL B00010000 -#define RAW_KEYBOARD_RIGHT_SHIFT B00100000 -#define RAW_KEYBOARD_RIGHT_ALT B01000000 -#define RAW_KEYBOARD_RIGHT_GUI B10000000 - -#define RAW_KEYBOARD_KEY(key) ((key>='a' && key<='z') ? (0x04 + key-'a') :\ -(key>='A' && key<='Z') ? (0x04 + key-'A') : (key>='1' && key<='9') ? (0x1E + key-'1') : 0x27) - -#define RAW_KEYBOARD_UP_ARROW 0x52 -#define RAW_KEYBOARD_DOWN_ARROW 0x51 -#define RAW_KEYBOARD_LEFT_ARROW 0x50 -#define RAW_KEYBOARD_RIGHT_ARROW 0x4F -#define RAW_KEYBOARD_SPACEBAR 0x2C -#define RAW_KEYBOARD_BACKSPACE 0x2A -#define RAW_KEYBOARD_TAB 0x2B -#define RAW_KEYBOARD_RETURN 0x28 -#define RAW_KEYBOARD_ESC 0x29 -#define RAW_KEYBOARD_INSERT 0x49 -#define RAW_KEYBOARD_DELETE 0x4C -#define RAW_KEYBOARD_PAGE_UP 0x4B -#define RAW_KEYBOARD_PAGE_DOWN 0x4E -#define RAW_KEYBOARD_HOME 0x4A -#define RAW_KEYBOARD_END 0x4D -#define RAW_KEYBOARD_CAPS_LOCK 0x39 -#define RAW_KEYBOARD_F1 0x3A -#define RAW_KEYBOARD_F2 0x3B -#define RAW_KEYBOARD_F3 0x3C -#define RAW_KEYBOARD_F4 0x3D -#define RAW_KEYBOARD_F5 0x3E -#define RAW_KEYBOARD_F6 0x3F -#define RAW_KEYBOARD_F7 0x40 -#define RAW_KEYBOARD_F8 0x41 -#define RAW_KEYBOARD_F9 0x42 -#define RAW_KEYBOARD_F10 0x43 -#define RAW_KEYBOARD_F11 0x44 -#define RAW_KEYBOARD_F12 0x45 -#define RAW_KEYBOARD_PRINT 0x46 -#define RAW_KEYBOARD_SCROLL_LOCK 0x47 -#define RAW_KEYBOARD_PAUSE 0x48 - -#define SHIFT 0x80 -static const uint8_t _asciimap[128] PROGMEM = -{ - 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 -}; - -typedef union{ - // Low level key report: up to 6 keys and shift, ctrl etc at once - uint8_t whole8[8]; - uint16_t whole16[8 / 2]; - uint32_t whole32[8 / 4]; - - struct{ - uint8_t modifiers; - uint8_t reserved; - uint8_t keys[6]; - }; -} HID_KeyboardReport_Data_t; - -class Keyboard_ : public Print{ -public: - inline Keyboard_(void){ - // empty - } - - inline void begin(void){ - end(); - } - - inline void end(void){ - // edit by NicoHood - releaseAll(); - } - -#if defined(HID_KEYBOARD_LEDS_ENABLED) - inline uint8_t getLEDs(void){ - return hid_keyboard_leds; - } -#endif - - inline size_t write(uint8_t c){ - uint8_t p = press(c); // Keydown - release(c); // Keyup - return (p); // just return the result of press() since release() almost always returns 1 - } - - // 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. - inline size_t 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. - inline size_t 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; - } - - inline void releaseAll(void){ - // release all keys - memset(&_keyReport, 0x00, sizeof(_keyReport)); - sendReport(&_keyReport); - } - -private: - HID_KeyboardReport_Data_t _keyReport; - inline void sendReport(HID_KeyboardReport_Data_t* keys){ - HID_SendReport(HID_REPORTID_KeyboardReport, &_keyReport, sizeof(_keyReport)); - } -}; -extern Keyboard_ Keyboard; - -#endif - - -//================================================================================ -// RawHID -//================================================================================ - -#ifdef HID_RAWHID_ENABLED - -#define LSB(_x) ((_x) & 0xFF) -#define MSB(_x) ((_x) >> 8) - -//TODO -#define RAWHID_USAGE_PAGE 0xFFC0 // recommended: 0xFF00 to 0xFFFF -#define RAWHID_USAGE 0x0C00 // recommended: 0x0100 to 0xFFFF -#define RAWHID_TX_SIZE 64 //TODO 16? -#define RAWHID_RX_SIZE 64 -//#define RAWHID_TX_SIZE 15 // 1 byte for report ID -//#define RAWHID_RX_SIZE 15 // 1 byte for report ID - -typedef union{ - // a RAWHID_TX_SIZE byte buffer for rx or tx - uint8_t whole8[RAWHID_TX_SIZE]; - uint16_t whole16[RAWHID_TX_SIZE / 2]; - uint32_t whole32[RAWHID_TX_SIZE / 4]; - uint8_t buff[RAWHID_TX_SIZE]; -} HID_RawKeyboardReport_Data_t; - -class RawHID_ : public Print{ -public: - inline RawHID_(void){ - // empty - } - - inline void begin(void){ - // empty - } - - inline void end(void){ - // empty - } - - using Print::write; // to get the String version of write - inline size_t write(uint8_t b){ - write(&b, 1); - } - - inline size_t write(const uint8_t *buffer, size_t size){ - size_t bytesleft = size; - // first work through the buffer thats already there - while (bytesleft >= RAWHID_RX_SIZE){ - HID_SendReport(HID_REPORTID_RawKeyboardReport, &buffer[size - bytesleft], RAWHID_RX_SIZE); - bytesleft -= RAWHID_RX_SIZE; - } - // write down the other bytes and fill with zeros - if (bytesleft){ - uint8_t rest[RAWHID_RX_SIZE]; - memcpy(rest, &buffer[size - bytesleft], bytesleft); - memset(&rest[bytesleft], 0, RAWHID_RX_SIZE - bytesleft); - HID_SendReport(HID_REPORTID_RawKeyboardReport, &rest, RAWHID_RX_SIZE); - } - } -}; -extern RawHID_ RawHID; - -#endif - - -//================================================================================ -// Media -//================================================================================ - -#ifdef HID_MEDIA_ENABLED - -// Media key definitions, see official USB docs for more -#define MEDIA_FAST_FORWARD 0xB3 -#define MEDIA_REWIND 0xB4 -#define MEDIA_NEXT 0xB5 -#define MEDIA_PREVIOUS 0xB6 -#define MEDIA_STOP 0xB7 -#define MEDIA_PLAY_PAUSE 0xCD - -#define MEDIA_VOLUME_MUTE 0xE2 -#define MEDIA_VOLUME_UP 0xE9 -#define MEDIA_VOLUME_DOWN 0xEA - -#define MEDIA_EMAIL_READER 0x18A -#define MEDIA_CALCULATOR 0x192 -#define MEDIA_EXPLORER 0x194 - -#define MEDIA_BROWSER_HOME 0x223 -#define MEDIA_BROWSER_BACK 0x224 -#define MEDIA_BROWSER_FORWARD 0x225 -#define MEDIA_BROWSER_REFRESH 0x227 -#define MEDIA_BROWSER_BOOKMARKS 0x22A - -typedef union{ - // every usable media key possible, up to 4 keys presses possible - uint8_t whole8[8]; - uint16_t whole16[8 / 2]; - uint32_t whole32[8 / 4]; - - struct{ - uint16_t key1; - uint16_t key2; - uint16_t key3; - uint16_t key4; - }; -} HID_MediaReport_Data_t; - -class Media_{ -public: - inline Media_(void){ - // empty - } - - inline void begin(void){ - // release all buttons - end(); - } - - inline void end(void){ - memset(&_report, 0, sizeof(_report)); - HID_SendReport(HID_REPORTID_MediaReport, &_report, sizeof(_report)); - } - - inline void write(uint16_t m){ - press(m); - release(m); - } - - inline void press(uint16_t m){ - // search for a free spot - for (int i = 0; i < sizeof(HID_MediaReport_Data_t) / 2; i++) { - if (_report.whole16[i] == 0x00) { - _report.whole16[i] = m; - break; - } - } - HID_SendReport(HID_REPORTID_MediaReport, &_report, sizeof(_report)); - } - - inline void release(uint16_t m){ - // search and release the keypress - for (int i = 0; i < sizeof(HID_MediaReport_Data_t) / 2; i++) { - if (_report.whole16[i] == m) { - _report.whole16[i] = 0x00; - // no break to delete multiple keys - } - } - HID_SendReport(HID_REPORTID_MediaReport, &_report, sizeof(_report)); - } - - inline void releaseAll(void){ - begin(); - } -private: - HID_MediaReport_Data_t _report; -}; -extern Media_ Media; - -#endif - - -//================================================================================ -// System -//================================================================================ - -#ifdef HID_SYSTEM_ENABLED - -#define SYSTEM_POWER_DOWN 0x81 -#define SYSTEM_SLEEP 0x82 -#define SYSTEM_WAKE_UP 0x83 - -typedef union{ - // every usable system control key possible - uint8_t whole8[1]; - uint8_t key; -} HID_SystemReport_Data_t; - -class System_{ -public: - inline System_(void){ - // empty - } - - inline void begin(void){ - // release all buttons - end(); - } - - inline void end(void){ - uint8_t _report = 0; - HID_SendReport(HID_REPORTID_SystemReport, &_report, sizeof(_report)); - } - - inline void write(uint8_t s){ - press(s); - release(); - } - - inline void press(uint8_t s){ - HID_SendReport(HID_REPORTID_SystemReport, &s, sizeof(s)); - } - - inline void release(void){ - begin(); - } - - inline void releaseAll(void){ - begin(); - } -}; -extern System_ System; - -#endif - -//================================================================================ -// Gamepad -//================================================================================ - -#ifdef HID_GAMEPAD_ENABLED - -// Dpad directions -#define GAMEPAD_DPAD_CENTERED 0 -#define GAMEPAD_DPAD_UP 1 -#define GAMEPAD_DPAD_UP_RIGHT 2 -#define GAMEPAD_DPAD_RIGHT 3 -#define GAMEPAD_DPAD_DOWN_RIGHT 4 -#define GAMEPAD_DPAD_DOWN 5 -#define GAMEPAD_DPAD_DOWN_LEFT 6 -#define GAMEPAD_DPAD_LEFT 7 -#define GAMEPAD_DPAD_UP_LEFT 8 - -typedef union { - // 32 Buttons, 6 Axis, 2 D-Pads - uint8_t whole8[15]; - uint16_t whole16[15 / 2]; - uint32_t whole32[15 / 4]; - uint32_t buttons; - - struct{ - uint8_t button1 : 1; - uint8_t button2 : 1; - uint8_t button3 : 1; - uint8_t button4 : 1; - uint8_t button5 : 1; - uint8_t button6 : 1; - uint8_t button7 : 1; - uint8_t button8 : 1; - - uint8_t button9 : 1; - uint8_t button10 : 1; - uint8_t button11 : 1; - uint8_t button12 : 1; - uint8_t button13 : 1; - uint8_t button14 : 1; - uint8_t button15 : 1; - uint8_t button16 : 1; - - uint8_t button17 : 1; - uint8_t button18 : 1; - uint8_t button19 : 1; - uint8_t button20 : 1; - uint8_t button21 : 1; - uint8_t button22 : 1; - uint8_t button23 : 1; - uint8_t button24 : 1; - - uint8_t button25 : 1; - uint8_t button26 : 1; - uint8_t button27 : 1; - uint8_t button28 : 1; - uint8_t button29 : 1; - uint8_t button30 : 1; - uint8_t button31 : 1; - uint8_t button32 : 1; - - int16_t xAxis; - int16_t yAxis; - - int16_t rxAxis; - int16_t ryAxis; - - int8_t zAxis; - int8_t rzAxis; - - uint8_t dPad1 : 4; - uint8_t dPad2 : 4; - }; -} HID_GamepadReport_Data_t; - -class Gamepad_{ -public: - inline Gamepad_(void){ - // empty - } - - inline void begin(void){ - // release all buttons - end(); - } - - inline void end(void){ - memset(&_report, 0, sizeof(_report)); - HID_SendReport(HID_REPORTID_GamepadReport, &_report, sizeof(_report)); - } - - inline void write(void){ HID_SendReport(HID_REPORTID_GamepadReport, &_report, sizeof(_report)); } - inline void press(uint8_t b){ _report.buttons |= (uint32_t)1 << (b - 1); } - inline void release(uint8_t b){ _report.buttons &= ~((uint32_t)1 << (b - 1)); } - inline void releaseAll(void){ memset(&_report, 0x00, sizeof(_report)); } - - inline void buttons(uint32_t b){ _report.buttons = b; } - inline void xAxis(int16_t a){ _report.xAxis = a; } - inline void yAxis(int16_t a){ _report.yAxis = a; } - inline void zAxis(int8_t a){ _report.zAxis = a; } - inline void rxAxis(int16_t a){ _report.rxAxis = a; } - inline void ryAxis(int16_t a){ _report.ryAxis = a; } - inline void rzAxis(int8_t a){ _report.rzAxis = a; } - inline void dPad1(int8_t d){ _report.dPad1 = d; } - inline void dPad2(int8_t d){ _report.dPad2 = d; } -private: - HID_GamepadReport_Data_t _report; -}; -extern Gamepad_ Gamepad; - -#endif - -#endif // if defined(USBCON) || defined(USE_USB_API) - -#endif /* if defined(__USBAPI__) */ diff --git a/plugins/KeyboardioHID/USBCore.cpp b/plugins/KeyboardioHID/USBCore.cpp deleted file mode 100644 index 7373819728..0000000000 --- a/plugins/KeyboardioHID/USBCore.cpp +++ /dev/null @@ -1,785 +0,0 @@ - - -/* 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. -*/ - -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -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 "USBAPI.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 u8 STRING_PRODUCT[] PROGMEM; -extern const u8 STRING_MANUFACTURER[] PROGMEM; -extern const DeviceDescriptor USB_DeviceDescriptor PROGMEM; -extern const DeviceDescriptor USB_DeviceDescriptorA PROGMEM; - -const u16 STRING_LANGUAGE[2] = { - (3 << 8) | (2 + 2), - 0x0409 // English -}; - -#ifndef USB_PRODUCT -// If no product is provided, use USB IO Board -#define USB_PRODUCT "USB IO Board" -#endif - -const u8 STRING_PRODUCT[] PROGMEM = USB_PRODUCT; - -#if USB_VID == 0x2341 -# if defined(USB_MANUFACTURER) -# undef USB_MANUFACTURER -# endif -# define USB_MANUFACTURER "Arduino LLC" -#elif USB_VID == 0x1b4f -# if defined(USB_MANUFACTURER) -# undef USB_MANUFACTURER -# endif -# define USB_MANUFACTURER "SparkFun" -#elif !defined(USB_MANUFACTURER) -// Fall through to unknown if no manufacturer name was provided in a macro -# define USB_MANUFACTURER "Unknown" -#endif - -const u8 STRING_MANUFACTURER[] PROGMEM = USB_MANUFACTURER; - - -#ifdef CDC_ENABLED -#define DEVICE_CLASS 0x02 -#else -#define DEVICE_CLASS 0x00 -#endif - -// edit by NicoHood -// warning from USBlyzer: IAD is used. Should be EFh (Miscellaneous Device Class). -// Lufa also use these values, so i will use them at least for the u2 boards. Someone should fix this for the u4 series if needed. -// You have to use this descriptor if you have CDC AND HID at the same time. Otherwise they are quite different. -#if defined(HID_ENABLED) && (defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega8U2__)) - -// DEVICE DESCRIPTOR -const DeviceDescriptor USB_DeviceDescriptor = -D_DEVICE(0xEF, 0x02, 0x01, 64, USB_VID, USB_PID, 0x100, IMANUFACTURER, IPRODUCT, 0, 1); - -#else - -// DEVICE DESCRIPTOR -const DeviceDescriptor USB_DeviceDescriptor = -D_DEVICE(0x00, 0x00, 0x00, 64, USB_VID, USB_PID, 0x100, IMANUFACTURER, IPRODUCT, 0, 1); - -#endif - -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; - // edit by NicoHood - return USB_EP_SIZE - 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 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; - { - LockEP lock(ep); - // Frame may have been released by the SOF interrupt handler - if (!ReadWriteAllowed()) - continue; - len -= n; - 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 -// edit by NicoHood -#define EP_SINGLE_16 0x12 - -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); - // edit by NicoHood -#if USB_EP_SIZE == 16 - UECFG1X = EP_SINGLE_16; -#elif USB_EP_SIZE == 64 - UECFG1X = EP_DOUBLE_64; -#else -#error Unsupported value for USB_EP_SIZE -#endif - } - 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; -} - -// Send a USB descriptor string. The string is stored in PROGMEM as a -// plain ASCII string but is sent out as UTF-16 with the correct 2-byte -// prefix -static bool USB_SendStringDescriptor(const u8*string_P, u8 string_len) { - SendControl(2 + string_len * 2); - SendControl(3); - for (u8 i = 0; i < string_len; i++) { - bool r = SendControl(pgm_read_byte(&string_P[i])); - r &= SendControl(0); // high byte - if (!r) { - return false; - } - } - return true; -} - -// 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 - - 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) { - return USB_SendStringDescriptor(STRING_PRODUCT, strlen(USB_PRODUCT)); - } - else if (setup.wValueL == IMANUFACTURER) { - return USB_SendStringDescriptor(STRING_MANUFACTURER, strlen(USB_MANUFACTURER)); - } - else - return false; - } - - if (desc_addr == 0) - return false; - u8 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 -#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_() -{ -} - -// edit by NicoHood -// added from teensy definition by paul stoffregen -#if defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega8U2__) -#define HW_CONFIG() -#define PLL_CONFIG() (PLLCSR = ((1<> 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/plugins/KeyboardioHID/USBDesc.h b/plugins/KeyboardioHID/USBDesc.h deleted file mode 100644 index 75f4558a3b..0000000000 --- a/plugins/KeyboardioHID/USBDesc.h +++ /dev/null @@ -1,90 +0,0 @@ - - -/* 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. -*/ - -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -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. -*/ - -#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 - -// edit by NicoHood -#ifndef USB_EP_SIZE -#define USB_EP_SIZE 64 -#endif -#define IMANUFACTURER 1 -#define IPRODUCT 2 - diff --git a/plugins/KeyboardioHID/examples/Advanced/AdvancedGamepad/AdvancedGamepad.ino b/plugins/KeyboardioHID/examples/Advanced/AdvancedGamepad/AdvancedGamepad.ino deleted file mode 100644 index eef660d9df..0000000000 --- a/plugins/KeyboardioHID/examples/Advanced/AdvancedGamepad/AdvancedGamepad.ino +++ /dev/null @@ -1,53 +0,0 @@ -/* - Copyright (c) 2014 NicoHood - See the readme for credit to other people. - - Advanced Gamepad example - */ - -// include HID library -#include - -// see HID_Reports.h for all data structures -HID_GamepadReport_Data_t Gamepadreport; - -const int pinLed = LED_BUILTIN; -const int pinButton = 2; - -// see HID_Reports.h for all data structures -HID_GamepadReport_Data_t Gamepadreport; - -void setup() { - pinMode(pinLed, OUTPUT); - pinMode(pinButton, INPUT_PULLUP); - - // Sends a clean report to the host. This is important on any Arduino type. - // Make sure all desired USB functions are activated in USBAPI.h! - memset(&Gamepadreport, 0, sizeof(Gamepadreport)); - HID_SendReport(HID_REPORTID_Gamepad1Report, &Gamepadreport, sizeof(Gamepadreport)); -} - -void loop() { - if (!digitalRead(pinButton)) { - digitalWrite(pinLed, HIGH); - - // This demo is actually made for advanced users to show them how they can write an own report. - // This might be useful for a Gamepad if you want to edit the values direct on your own. - - // count with buttons binary - static uint32_t count = 0; - Gamepadreport.whole32[0] = count++; - - // move x/y Axis to a new position (16bit) - Gamepadreport.whole16[2] = (random(0xFFFF)); - - // functions before only set the values - // this writes the report to the host - HID_SendReport(HID_REPORTID_Gamepad1Report, &Gamepadreport, sizeof(Gamepadreport)); - - // simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } -} - diff --git a/plugins/KeyboardioHID/examples/Advanced/AdvancedKeyboard/AdvancedKeyboard.ino b/plugins/KeyboardioHID/examples/Advanced/AdvancedKeyboard/AdvancedKeyboard.ino deleted file mode 100644 index e6d71cfa8d..0000000000 --- a/plugins/KeyboardioHID/examples/Advanced/AdvancedKeyboard/AdvancedKeyboard.ino +++ /dev/null @@ -1,98 +0,0 @@ -/* - Copyright (c) 2014 NicoHood - See the readme for credit to other people. - - Advanced Keyboard example - - This demo is actually made for advanced users to show them how they can write an own report. - This might be useful for a Keyboard if you only use one key, - because the library has a lot of code for simple use - */ - -const int pinLed = LED_BUILTIN; -const int pinButton = 2; - -void setup() { - pinMode(pinLed, OUTPUT); - pinMode(pinButton, INPUT_PULLUP); - - // Sends a clean report to the host. This is important on any Arduino type. - // Make sure all desired USB functions are activated in USBAPI.h! - pressRawKeyboard(0, 0); -} - -void loop() { - if (!digitalRead(pinButton)) { - digitalWrite(pinLed, HIGH); - - // press normal keys (a-z, A-Z, 0-9) - pressRawKeyboard(0, RAW_KEYBOARD_KEY('a')); //modifiers + a - pressRawKeyboard(0, RAW_KEYBOARD_KEY('Z')); //modifiers + Z - - // press STRG + ALT + DEL on keyboard (see usb documentation for more) - //pressRawKeyboard(RAW_KEYBOARD_LEFT_CTRL | RAW_KEYBOARD_LEFT_ALT , RAW_KEYBOARD_DELETE); //modifiers + key - - // release! Important - pressRawKeyboard(0, 0); - - // simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } -} - -void pressRawKeyboard(uint8_t modifiers, uint8_t key) { - uint8_t keys[8] = { - modifiers, 0, key, 0, 0, 0, 0, 0 - }; //modifiers, reserved, key[0] - HID_SendReport(HID_REPORTID_KeyboardReport, keys, sizeof(keys)); -} - -/* -See Hut1_12v2.pdf Chapter 10 (Page 53) for more Keys - (especially a-z, a=0x04 z=29) - Definitions: - - RAW_KEYBOARD_LEFT_CTRL - RAW_KEYBOARD_LEFT_SHIFT - RAW_KEYBOARD_LEFT_ALT - RAW_KEYBOARD_LEFT_GUI - RAW_KEYBOARD_RIGHT_CTRL - RAW_KEYBOARD_RIGHT_SHIFT - RAW_KEYBOARD_RIGHT_ALT - RAW_KEYBOARD_RIGHT_GUI - - RAW_KEYBOARD_KEY(key) - - RAW_KEYBOARD_UP_ARROW - RAW_KEYBOARD_DOWN_ARROW - RAW_KEYBOARD_LEFT_ARROW - RAW_KEYBOARD_RIGHT_ARROW - RAW_KEYBOARD_SPACEBAR - RAW_KEYBOARD_BACKSPACE - RAW_KEYBOARD_TAB - RAW_KEYBOARD_RETURN - RAW_KEYBOARD_ESC - RAW_KEYBOARD_INSERT - RAW_KEYBOARD_DELETE - RAW_KEYBOARD_PAGE_UP - RAW_KEYBOARD_PAGE_DOWN - RAW_KEYBOARD_HOME - RAW_KEYBOARD_END - RAW_KEYBOARD_CAPS_LOCK - RAW_KEYBOARD_F1 - RAW_KEYBOARD_F2 - RAW_KEYBOARD_F3 - RAW_KEYBOARD_F4 - RAW_KEYBOARD_F5 - RAW_KEYBOARD_F6 - RAW_KEYBOARD_F7 - RAW_KEYBOARD_F8 - RAW_KEYBOARD_F9 - RAW_KEYBOARD_F10 - RAW_KEYBOARD_F11 - RAW_KEYBOARD_F12 - RAW_KEYBOARD_PRINT - RAW_KEYBOARD_SCROLL_LOCK - RAW_KEYBOARD_PAUSE - */ \ No newline at end of file diff --git a/plugins/KeyboardioHID/examples/Advanced/AdvancedRawHID/AdvancedRawHID.ino b/plugins/KeyboardioHID/examples/Advanced/AdvancedRawHID/AdvancedRawHID.ino deleted file mode 100644 index 202e3b28ee..0000000000 --- a/plugins/KeyboardioHID/examples/Advanced/AdvancedRawHID/AdvancedRawHID.ino +++ /dev/null @@ -1,109 +0,0 @@ -/* - Copyright (c) 2014 NicoHood - See the readme for credit to other people. - - Advanced RawHID example - - Shows how to send bytes via raw HID - Press a button to send some example values. - Keep in mind that you can only send full data packets, the rest is filled with zero! - - Definitions from HID_Reports.h: - RAWHID_USAGE_PAGE 0xFFC0 // recommended: 0xFF00 to 0xFFFF - RAWHID_USAGE 0x0C00 // recommended: 0x0100 to 0xFFFF - RAWHID_TX_SIZE 15 // 1 byte for report ID - RAWHID_RX_SIZE 15 // 1 byte for report ID - */ - -const int pinLed = LED_BUILTIN; -const int pinButton = 2; - -void setup() { - pinMode(pinLed, OUTPUT); - pinMode(pinButton, INPUT_PULLUP); - - // no begin function needed for RawHID - // Make sure all desired USB functions are activated in USBAPI.h! -} - -void loop() { - if (!digitalRead(pinButton)) { - digitalWrite(pinLed, HIGH); - - // direct without library. Always send RAWHID_RX_SIZE bytes! - uint8_t buff[RAWHID_RX_SIZE]; // unitialized, has random values - HID_SendReport(HID_REPORTID_RawKeyboardReport, buff, sizeof(buff)); - - // with library - memset(&buff, 42, sizeof(buff)); - RawHID.write(buff, sizeof(buff)); - - // write a single byte, will fill the rest with zeros - RawHID.write(0xCD); - - // huge buffer with library, will fill the rest with zeros - uint8_t megabuff[64]; - for (int i = 0; i < sizeof(megabuff); i++) - megabuff[i] = i; - RawHID.write(megabuff, sizeof(megabuff)); - - // You can use print too, but better dont use a linefeed - RawHID.println("Hello World"); - - // And compare it to write: - RawHID.write("Hello World\r\n"); - - // simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } -} - -/* -Expected output: - -// manual with unintialized buff -recv 15 bytes: -01 55 C1 FF 01 01 01 00 00 01 00 00 01 00 20 - -// filled buff -recv 15 bytes: -2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A - -// single byte filled with zero -recv 15 bytes: -CD 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - -// huge buffer filled with zero at the end -recv 15 bytes: -00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E - -recv 15 bytes: -0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D - -recv 15 bytes: -1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C - -recv 15 bytes: -2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B - -recv 15 bytes: -3C 3D 3E 3F 00 00 00 00 00 00 00 00 00 00 00 - -// print -recv 15 bytes: -48 65 6C 6C 6F 20 57 6F 72 6C 64 00 00 00 00 - -//\r -recv 15 bytes: -0D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - -//\n -recv 15 bytes: -0A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - -//write -recv 15 bytes: -48 65 6C 6C 6F 20 57 6F 72 6C 64 0D 0A 00 00 - -*/ \ No newline at end of file diff --git a/plugins/KeyboardioHID/examples/Basics/Gamepad/Gamepad.ino b/plugins/KeyboardioHID/examples/Basics/Gamepad/Gamepad.ino deleted file mode 100644 index 9014e36ac2..0000000000 --- a/plugins/KeyboardioHID/examples/Basics/Gamepad/Gamepad.ino +++ /dev/null @@ -1,87 +0,0 @@ -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -Gamepad example - -Press a button and demonstrate Gamepad actions -*/ - -const int pinLed = LED_BUILTIN; -const int pinButton = 2; - -void setup() { - pinMode(pinLed, OUTPUT); - pinMode(pinButton, INPUT_PULLUP); - - // Sends a clean report to the host. This is important on any Arduino type. - // Make sure all desired USB functions are activated in USBAPI.h! - Gamepad.begin(); -} - -void loop() { - if (!digitalRead(pinButton)) { - digitalWrite(pinLed, HIGH); - - // press button 1-32 and reset (34 becaue its written later) - static uint8_t count = 1; - Gamepad.press(count++); - if (count == 34) { - Gamepad.releaseAll(); - count = 1; - } - - // move x/y Axis to a new position (16bit) - Gamepad.xAxis(random(0xFFFF)); - Gamepad.yAxis(random(0xFFFF)); - - // go through all dPad positions - // values: 0-8 (0==centred) - static uint8_t dpad1 = GAMEPAD_DPAD_CENTERED; - Gamepad.dPad1(dpad1++); - if(dpad1>GAMEPAD_DPAD_UP_LEFT) dpad1 = GAMEPAD_DPAD_CENTERED; - static int8_t dpad2 = GAMEPAD_DPAD_CENTERED; - Gamepad.dPad2(dpad2--); - if(dpad2 2) { - uint8_t nextvalue = (data >> (7 * (blocks - 3))); - - if (nextvalue > NHP_MASK_DATA_3BIT) { - // special case for the MSB - if (blocks == 7) { - writebuffer[0] = nextvalue; - blocks--; - } - // this block is too big, write this into the next data block - break; - } - else { - // write the possible first 3 bits and check again after if zero - writebuffer[0] = nextvalue; - blocks--; - // we have our first bits, stop (nonzero) - if (nextvalue) - break; - } - } - - // write the rest of the data bits - uint8_t datablocks = blocks - 2; - while (datablocks > 0) { - writebuffer[datablocks] = data & NHP_MASK_DATA_7BIT; - data >>= 7; - datablocks--; - } - - // write lead + length mask - writebuffer[0] |= NHP_MASK_LEAD | (blocks << 3); - - // write end mask - writebuffer[blocks - 1] = NHP_MASK_END | ((address - 1) & NHP_MASK_ADDRESS); - - // write the buffer - HID_SERIAL.write(writebuffer, blocks); -} diff --git a/plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_NoUSB_Blink/HoodLoader2_NoUSB_Blink.ino b/plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_NoUSB_Blink/HoodLoader2_NoUSB_Blink.ino deleted file mode 100644 index 4f5fb1a004..0000000000 --- a/plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_NoUSB_Blink/HoodLoader2_NoUSB_Blink.ino +++ /dev/null @@ -1,38 +0,0 @@ -/* - Copyright (c) 2014 NicoHood - See the readme for credit to other people. - - HoodLoader2 NoUSB Blink example - - This sketch demonstrates how to use HoodLoader2 without USB Core. - This might be useful to keep ram/flash usage at a very low level. - Select Tools->USB Core->No USB functions to get rid of the USB Core. - - Blinks Leds and shows what workaround is needed to get the timing correct. - You can still use the normal digitalWrite(LED_BUILTIN_TX, LOW); for updating Leds. - Keep in mind that the logic is inverted then! LOW=HIGH and vice versa. - */ - -#ifndef USBCON -// workaround for undefined USBCON has to be placed in every sketch -// otherwise the timings wont work correctly -ISR(USB_GEN_vect) -{ - UDINT = 0; -} -#endif - -void setup() { - TX_RX_LED_INIT; -} - -void loop() { - TXLED0; - delay(100); - TXLED1; - delay(100); - RXLED0; - delay(100); - RXLED1; - delay(100); -} diff --git a/plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_PWM_Fade/HoodLoader2_PWM_Fade.ino b/plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_PWM_Fade/HoodLoader2_PWM_Fade.ino deleted file mode 100644 index 0ba22c889f..0000000000 --- a/plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_PWM_Fade/HoodLoader2_PWM_Fade.ino +++ /dev/null @@ -1,39 +0,0 @@ -/* - Copyright (c) 2014 NicoHood - See the readme for credit to other people. - - PWM Fade - - This example shows how to fade an LED on pin 7 - using the analogWrite() function. - - Basically it is a demonstartion that PWM on pin 7 works fine. - You can also deactivate the USB Core for this example, but then you'd - need the workaround. See the other example for this. -*/ - -int led = 7; // the pin that the LED is attached to -int brightness = 0; // how bright the LED is -int fadeAmount = 5; // how many points to fade the LED by - -// the setup routine runs once when you press reset: -void setup() { - // declare pin 9 to be an output: - pinMode(led, OUTPUT); -} - -// the loop routine runs over and over again forever: -void loop() { - // set the brightness of pin 9: - analogWrite(led, 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 == 255) { - fadeAmount = -fadeAmount ; - } - // wait for 30 milliseconds to see the dimming effect - delay(30); -} diff --git a/plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_SerialKeyboard/HoodLoader2_SerialKeyboard.ino b/plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_SerialKeyboard/HoodLoader2_SerialKeyboard.ino deleted file mode 100644 index 5aef44609e..0000000000 --- a/plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_SerialKeyboard/HoodLoader2_SerialKeyboard.ino +++ /dev/null @@ -1,54 +0,0 @@ -/* - Copyright (c) 2014 NicoHood - See the readme for credit to other people. - - HoodLoader2 SerialKeyboard example - - This sketch should demonstrate how to program a basic sketch with HoodLoader2. - It was used to demonstrate that Serial and HID is working properly. - The the other examples on how to use the other APIs, it works the same. - - Use the F() macro to save strings in PROGMEM to keep ram usage low. - The 16u2 has very low RAM, so don't try to use that much ram. - - Open the Serial port, type in anything and see that Serial and Keyboard is working. - See official documentation for more infos. - */ - -void setup() { - // start + wait for serial debug in/output - while (!Serial); - Serial.begin(115200); - Serial.println(F("Startup")); - - // Sends a clean report to the host. This is important because - // the 16u2 of the Uno/Mega is not turned off while programming - // so you want to start with a clean report to avoid strange bugs after reset. - Keyboard.begin(); -} - - -void loop() { - if (Serial.available()) { - // discard all Serial bytes to avoid multiple sendings - unsigned long currentMillis = millis(); - while (millis() - currentMillis < 100) { - if (Serial.available()) - Serial.write(Serial.read()); - } - - // print an information back to the serial port - Serial.println(); - Serial.println(F("Serial port working. Printing Text in 3 seconds.")); - - // wait 3 seconds and discard all new in bytes to not crash the Arduino - currentMillis = millis(); - while (millis() - currentMillis < 3000) { - if (Serial.available()) - Serial.write(Serial.read()); - } - - // same use as the official library, pretty much self explaining - Keyboard.print(F("This message was sent with my Arduino.")); - } -} \ No newline at end of file diff --git a/plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_USB-Serial/HoodLoader2_USB-Serial.ino b/plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_USB-Serial/HoodLoader2_USB-Serial.ino deleted file mode 100644 index 1dce7ff33c..0000000000 --- a/plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_USB-Serial/HoodLoader2_USB-Serial.ino +++ /dev/null @@ -1,51 +0,0 @@ -/* - Copyright (c) 2014 NicoHood - See the readme for credit to other people. - - HoodLoader2 USB-Serial - - Transferes from USB to HW Serial and vice versa. - It also resets the main MCU on a DTR rise. - */ - -void setup() { - // set main MCU by default active - pinMode(MAIN_MCU_RESET_PIN, OUTPUT); - digitalWrite(MAIN_MCU_RESET_PIN, HIGH); - - // Start USB and HW Serial - Serial.begin(115200); - Serial1.begin(115200); -} - -void loop() { - // USB -> Serial - for (int i = 0; i < USB_EP_SIZE; i++) { - // read maximum one EP_SIZE to not block - if (Serial.available()) - Serial1.write(Serial.read()); - else break; - } - - // Serial -> USB - if (Serial1.available()) { - Serial.flush(); - // send maximum one EP_SIZE to give the usb some time to flush the buffer - uint8_t buff[USB_EP_SIZE-1]; - int i = 0; - for (i = 0; i < USB_EP_SIZE-1; i++) { - if (Serial1.available()) - buff[i] = Serial1.read(); - else break; - } - Serial.write(buff, i); - } - - // reset the main mcu if DTR goes HIGH - static bool lastDTR = 0; - bool newDTR = (Serial.lineState()&CDC_CONTROL_LINE_OUT_DTR) ? 1 : 0; - if (lastDTR ^ newDTR) - digitalWrite(MAIN_MCU_RESET_PIN, lastDTR); - lastDTR = newDTR; -} - diff --git a/plugins/KeyboardioHID/examples/Projects/Gamepad_Project/Gamepad_Project.ino b/plugins/KeyboardioHID/examples/Projects/Gamepad_Project/Gamepad_Project.ino deleted file mode 100644 index f4d17a0c97..0000000000 --- a/plugins/KeyboardioHID/examples/Projects/Gamepad_Project/Gamepad_Project.ino +++ /dev/null @@ -1,110 +0,0 @@ -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -Gamepad example project - -Press physical buttons to press USB Gamepad buttons. -This can be used for a simple SNES Controller. -*/ - -// pin mappings -const int pinButton1 = 2; -const int pinButton2 = 3; -const int pinButton3 = 4; -const int pinButton4 = 5; -const int pinButton5 = 6; -const int pinButton6 = 7; -const int pinButton7 = 8; -const int pinButton8 = 9; -const int pinButton9 = 10; -const int pinButton10 = 18; -const int pinButton11 = 19; -const int pinButton12 = 20; - -void setup() { - // pinsetup - pinMode(pinButton1, INPUT_PULLUP); - pinMode(pinButton2, INPUT_PULLUP); - pinMode(pinButton3, INPUT_PULLUP); - pinMode(pinButton4, INPUT_PULLUP); - pinMode(pinButton5, INPUT_PULLUP); - pinMode(pinButton6, INPUT_PULLUP); - pinMode(pinButton7, INPUT_PULLUP); - pinMode(pinButton8, INPUT_PULLUP); - pinMode(pinButton9, INPUT_PULLUP); - pinMode(pinButton10, INPUT_PULLUP); - pinMode(pinButton11, INPUT_PULLUP); - pinMode(pinButton12, INPUT_PULLUP); - - // Sends a clean report to the host. This is important on any Arduino type. - // Make sure all desired USB functions are activated in USBAPI.h! - Gamepad.begin(); -} - -void loop() { - // check each button and press Gamepad if needed - if (!digitalRead(pinButton1)) - Gamepad.press(1); - else - Gamepad.release(1); - - if (!digitalRead(pinButton2)) - Gamepad.press(2); - else - Gamepad.release(2); - - if (!digitalRead(pinButton3)) - Gamepad.press(3); - else - Gamepad.release(3); - - if (!digitalRead(pinButton4)) - Gamepad.press(4); - else - Gamepad.release(4); - - if (!digitalRead(pinButton5)) - Gamepad.press(5); - else - Gamepad.release(5); - - if (!digitalRead(pinButton6)) - Gamepad.press(6); - else - Gamepad.release(6); - - if (!digitalRead(pinButton7)) - Gamepad.press(7); - else - Gamepad.release(7); - - if (!digitalRead(pinButton8)) - Gamepad.press(8); - else - Gamepad.release(8); - - if (!digitalRead(pinButton9)) - Gamepad.press(9); - else - Gamepad.release(9); - - if (!digitalRead(pinButton10)) - Gamepad.press(10); - else - Gamepad.release(10); - - if (!digitalRead(pinButton11)) - Gamepad.press(11); - else - Gamepad.release(11); - - if (!digitalRead(pinButton12)) - Gamepad.press(12); - else - Gamepad.release(12); - - // write the information to the host now! - Gamepad.write(); -} - diff --git a/plugins/KeyboardioHID/examples/Readme.md b/plugins/KeyboardioHID/examples/Readme.md deleted file mode 100644 index 30a01d3b39..0000000000 --- a/plugins/KeyboardioHID/examples/Readme.md +++ /dev/null @@ -1,4 +0,0 @@ -Examples -======== - -Just try these examples once the HID Source is installed. Its pretty much self explaining. \ No newline at end of file diff --git a/plugins/KeyboardioHID/header.jpg b/plugins/KeyboardioHID/header.jpg deleted file mode 100644 index d87032a640a9052d4cd80c2b450a8dc27659d8a1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 150263 zcmeFYWmILowkEuBhr+1>ioz)z3U_xYWaIAcu2s0ZYvHnScM5kX+;!vbE+6N7eb4)L zkJCNw{n4ZU+^jLzT3N|Vp3Gz=naRxC!rKPmgOr%07ytqS0-*PP0p2zNCZcZUCIEn} zEPxsS0KfyFAwB_M-rpeJi4Ow*U+-cNQ~;=deusPyWCFb30UzE;?w$VO^xo+oJpX*! z>6_a)(c2h1ePN+zr2htZdj-(S+c}wAn|l}=eKBzVBK2KV+}hm6{L43bCMJ3odX_JY zZbnR;Oa=yw%z(FLfG_|G0t)J%1O*KR1q}lS0|N~Wg8&N$1BZx!goKEIh=_#p0Tl@u z4H*#;6%!Q=9UTJ$0|^xi8xtM-0|o~AKN5j}dgp-@rbxZfcs0m0j7v(aHH|Y+QUo&Ll1ihp>{0 zUv70xZ5JXQd42cHIR%@ck^iPhK;G7cm~qcXN>M6K@j$T4dwvA(NFd+g{0$ETBs2^x z6de3}s4)6J&_Ke#B16OeBND`WEkU9~5koV`QfFE!p7e@U{FWkC$^dn##T8TMo5gn7HRJwqp z5^?f?mx9GipLT98vpT_!du|!x$N7mbzp4tGoMW$z%4=9j`*8geKIRp~6V)lOa$zAm z1#MA-ff}yrwK8}4fzP|rbXJp^y6}#A{@6->6z({$S*6p^z(7H?StR)YhTgr@#04x6d$l zqU9|c`jkhRThl0(pnu#5ip9g%8 zsVA)~QIktsTqaTTPrqRa%lyiI_zCu9$0WL_R~{G1lc-^72fD&LXS=zsa{;>PyT5u~ zM3buAV|qf@+2J2)R`Fc@8V_ku(CEFon4hF384vp%P5o3FQj=RnGTgBzqOPF(t+Gx; zK@{uX5>WOx{~gBi-8bD8sRp2u9okE8!^`OW9Y&LF-^cH7fcY-x&fqK1+ZWR|;J#825ye{q-jXi_%vuMHX`5>*_%` zFsj@fbWtpYzZ0f(LFAlvd|uF(R)LsU@}4lch6ngKwi57QtoX&WuUWcq&y=m31J1{O z9L<1(WVhy|kpHVb=M}cKBF-tyxP9@;vU`af1u5%&^snwj2Y1@W&?HU6;oheelT@{8WL!!|4Cl{wnwLWjV{jyLle8_>9ZWVj zl1I5KB!(iF^DC3R2|(E z?GX32^O`@UQ@OcUjt-B9-@^r&%sF?m&SvY3;CQ7=hf+h^YjFK&O^p`zcpx+9 z@dYSP#un)sX}=%u6Fb75=>0j}BKmQV5c~;irg{70kv93raNVDUQ~I`5G*i@!X*LE& z1}JiZC_2pYZ=EY7Q3>A_{(Lsx90L~+5c!{_NIlv3B4Z)73Y&(TC5*(s5*QnHl8JDOg&Jzt<_n& zLFuWlK>jk?#ku`_r>pAnYK!}6XCw6kbiaDl^(#nc)yCTz6BDKpx7Iw^wAla&6mb(D zY$XPxW~h>2-{U=(j-@yT!)ifC9%n?J6p~U$VRZ>JH(}7a_Bb8I@_nmegh7;TCUDZz z=SU9`mKrgwsnWlMV~TUB+RM5qi`pM{aA$ZErkEW`>5j55>5iUDre!8SB43M;Ps6aPDeWNzL$;p$%!iF7lrp81;21Y*f*KR7fqg`oUpCr zP~gf0IC^Zbt?f5UN?gvyp_WavcqbahJ0fi%+)-VvI@#`7G%mHY>eI}WW0f3l(!qDqW`pJ zo__Lt`}4Fbi!#*>cMD0wa2%hFh;i=?01{_vFrT$sLh0ZQm6J`o_`Hpab7E>nk;*AZ z+}{{UNm{yy5T%Zn7R`<=6E5W|DVgH8SetCGEPcEzlQhMz(jz|*0#?)}!8)v<3Xj6C zz=$EKIV3URG>t34bA;tvEu5IGdi~U0fN?w9x9>uGCpO5e-#Z!97-hkahe%>K5lnEw zn}_=bC?jj#U$SDqAN>N8NssHgMc2gc&L#1u*U7a|%Dow+5)tfYF&=@XajuEe49k!h z5Jzun{|Ix@{=SI>$xJHoLB`LnHjlT}tQ3r-`jcnzAg0?#3r>wbv3EWi`jbp#rW2Zgn4>Td9pbBJqxj1ial99z$f4n2YaGvY!l}X2%k4cI< zS7O?#cTvhc=epXEgtNoxTnO#}A?)F^X*^$%@GpAw47f~pqYZI;_ob(QYfVvM$G5Gx z>5~;!t6l8TIDs%grBt2`!U zCpNVB%3gV}u7Rmzyn-EsIWOJHCLQ&~<(A#AUIru9ni2j**&r6vBfRa(7TAGmKN)8% zb^o7gWB3;O0??V$UNtcc_L&>U9goTL3v{q_*}I|j(L1XR%W%s!Y^}WYR^pcFK{iR@ z-W@Zer}d@i?H^@y6=w^D{nSrm1fiuF~ z;uH50B9lZyYGsL+iZ#TEwd%lHydJKWZc#=oKXw`(Ol;Ono=#b=RnsIt0U_{-?T~yp zuMndWH9wNuQh^~#5-e7x1q-LApOq)na}XQSYGB4#wyR(X zAAVOIFq#-GJ&TPylg%0Rre~GdsH}3M?4@$+fk(WS6JX04K;;i)y#}5YLe{?|6xK*^ z#%A36M|ir%1%$~~lMFJxc_}MJom(#{KLIqY)qDnBZgaz3!kpYM9qg*7z(@!r2Xulam1mQ$X8B@f-()AISKlU@8& zA*7?d{?&Osy<#!t5ZTV9N!x{_0Uup*CQ^XX=G2Bes>eGVHC+k3LVqi6l}shCw;5hI zW)V_6xg^Z@I2yzn8~%8o-doUd-kZoNm|4vaV)Z`@u)Pq=%5D}TdAyx}nD?Jy-U}$TkwH}e5C#Myi}$CPceaWUv~lZf(I5S#SARO9?!FDW}#Gd zI_xVthv8}RD72Lu-OqCmUn9TJ) zK??a#6V0x3ctEI#I_Jh5Y8J5kj`^a%%zZSxAxz(iYX>FMuE}!mSH?)SS%Ir94TejT zYkkz+8=ya=)fIH6+U@Lh^IL9yK<9QpRDiHD=!})p)^pw3Yh6J~0aw9Ib#+(EoRLs& z^yu_43?sDl6W$UYj5cw~c+W8?# zlupf`r$F%c99OO#J-Hn%hR)$;`wCYw$C(l-u`_xN5QgirhRhK`ebmcW_(YkjUpm8a zk*7LKkMa&PQ~||um-qW?Q#x;eq$=mFnGAxg> zDGZaHcg3OKwL~xepkC3DpEW;I4`z>=#U#2WSUxK!FmoOe`!44O6w^D-kL@aFcMkt_ zSZ3J8KTp`?(`^RR50Jxi?D&M1xmQ{#Mo#-%~!`hdy=GPx@fWf@diCgNuN2oUdNs$K4@=)66 z+12oofm!dAlkcj)>|@}>HQcKxp^9&{D*qp%2W+lMc?vU6RTs+W(kG^+Ulkz!1yJ@r z+H)9J*&D#1!uJ>dCAD*Imdu~qieq^q;H_c3p!R<-V>zq8_G!JVbiUil>u%n~4awUb zo(*`A_B}(Y5@9BwI8Wffs+do0%QH5^?!opLn#F1F#f`2Bw=(Cf=@Yi&3&a~BR{UR} zWV~lgkGLzl6klzk4!_-G&To|Xvi}`j&iKDWXLy>&ufFPon0)2rs*qiF+6g25(Bl40 zc&W9T$6IwVY8Le`m4d@p1gj&mSk3M#bH(*)_2gwc?qHhd4@= zuVj7V-T(^CzBZ8;K}SUB_b!p27)q%zG!Pc6q;7Kx4`)kaSR& zCds$uut$h*X0t3s853AZRJ&R7Q!y?t<~c`pHYLJ_*! z30beaSeA|;2IeZmYCfh3(>_tfWO!~?woVq#>zrlQ-&I`RUW|t#^fRDlvDo%Z$aXZ3 zx6NKv6uongbV#xH$VRn~Y^rFxj)?^9tfLrqeiF3Ns7&i12+S4Ia(@G`Bkp=1567-2 zk1T5tCW}a;@q&Tn^qnye2UI(z;Br%nFvSwy!Nj1)I4My*`JDl-1gYiY=m9m%=jOxw zqHK(-`7Yny1d)93?3L%qls->~$3y4U?IcEQ`#os)iNPk`wd2LGeWE5L(RKF9H`|&V zbB&7~bWg27jkIP^>36B96g9`aqj*wime@GbA9;CyK$b;Dzl3meJpRsdb5~~cRg&y1 zsviGA0b}mHYaZcZKiJD>j?s8htoq6ymJfsAS*F5kx||Oc(?QME?+rSeLT7Le;~H1? z+b#p`Y3j0~bCQmTUV>aTM^sr^Vbw`9+*FL&=|>OXGi;fL^8dw$u;Gff&idQs0@sU6ufJZ;#H@2US8cAV`-h z+f6$Z(KJTA+dzA2Z-D&b06Exg(`EH~(!{TA%<-xi%H^4s)ItH9`mef(4a|>}iLz_8 zSz4A~5+^oI5(4DhPIuR>orHa9YYXet&D&1EQaA^k$&KGbr>$Jir~IW;lnhqR8l_!S zozX02NKSLZs6zf%Dh)M#jA6P1ya9q$PD{zN4+RERpk4{>-Tl(nZD?fquEiJPP(J2j{79?$QRt`PY#O(d=t_cc6#+98ae41j5g9(w zxOM?mRpCk3qIUp4{!(!w*w`}jLsWz|GvGPscdUdv!58K+Wsw+J(VZ1;w5o=)N&E*^ z6)wrm%sj&kN#A(Oo~Bwj4I8%1l_zH~Mqm0WuAdP*O31m2OffBKtY*xgxLk<%plE>K zp<{ZUOP@NA5_X%oU%q6wtZ?g%B|Y^i%_jO?80^tLjiVq+rburvw5GTMZU=gJ6jgyy zZ{J2%$yvDdw-{(DsHi_&zaOq`$!PTd1%$;Fwda_w^;+yzR*C0Z4Ue6sUQeUtG0jc) z?WiS5f2&Bm0j$-Dc*uxDZacLw>Iyorf15f$QAJ1clSKO5X0FXj1B0ijzMIan(PERU z&gV~|xz2t#gzB>EbqC%<)AS!ZNYWdy2m>@nC;OB()^vXUY6`6z@P6W~V5mn`>h>&O zod@o7V&*rBFCQKsX5lcW?k2&pmq2R zElROWDndUx`K|N~P&H!QKQ#I2!M3G(wh$}*ICJe>Ypiis(mi(+sFd0Ws5z0j)JhIi z!|&02l0LSWY==ZqH%&56belz;u`{u^aZ~JO{mChBRC-lS*SXmyZLz3jsq?kFu}#?5 z($lwgkplT3=^DxKQhT-ExW@@g#|(c;$a1WRPAcKX(OQ!qKCd&;CzN(OKS_eR6}#%1}D5tmHH~*VPeTW z{E^qo_JD7@=xEJ%kvoZz{np7F#){>XUO6qhGPWfjZjePco_rI!wph-1M5*E2x}wwL zYp%2EeGWm>Zq^Nw^g1YMoc$R6u3A~WoZIF6;bl8H&w3eg=zzhhRydxv3VcpvKazKg zA5Yg#ZrT%!58|^%lCKgci^;UrG#r#N-~k>HS*Q{3k7MDNrFX$O#j4e5QfTP_8;9Vh zCO<_@rc&{2ph~1>dH8?dttVKzCHLk=UpjR=C2N)KL>}p314QeuNHjEnW5;=tSHDs) z>lz!>_G%hQiu00cQdnV-x-no1{0t>9qrY8N##u;4^Zl3`+H%Cb+xPn`@+jV9*RArv zcZ9-6E|sFK8YUV> z@El>~O%bE!MF@FQ9$JFm$st963R*eVp-zrJt!lQ+*gXp}=~Dbq*48QJ1F9a?i2E%z zW^hJ8wVmGh3KCpRB^H#4sn`anW&$H7KH}O6Tn}0H}>+p`7bI~ZveaZrjJ2qs%A}j zSZn$eWP2ZL$(5V%zgyA&&wf|Z&F`GC(Ou5-(r!Rxv&>luZ(|`&l7x`L0yIdv+(S=uQe;c;3*~>(LhE$@hZbsE#7pIw*Y@5? zSClvw|D&(2OuXnDZr*7sQJ@yk%wmz+PPsJOs2`)-nboRU0iNX6QTR%<=Wfbi^;m{f zq6jon0DUr9(|FWSF# z*iKs39%Gymeejyt?PvN~o( zWa$BM46P<9)>-u#*rVCyPD1%Arc|twx)?2bv&ZRNi_^rv7~DGeK3jLecp{Y$3ce6? z(PZ#^;7ew((W+$llA)K7L+FS6P@k4%*5W0Rh;5y1ttr=yFPI$YSv7)SqTomO?PI(( zyAbj3I!6~3Lh(%vI0{K#2vbG8A`EJQU6u1k@#6z-qL#{R8K`o3r^LlyjoF&b*>#M` zx3g5f`Fzs^R=pPp6keFZC~zC+-YwFNC$3nvSeg=Z7_vNAW!3PVJ(Z{`S#zJOFV%T6 zb=91`fxC|Rb7OznXjynZa04VdSd)GCdRp-V0rqr4xyjS&vBgUG)>I!J$hNj`|wWrzxA_JMyB2X2lZEp0a1x=AKg8p zJ)VPnw8aQNa(x?048%(gJ6#?2UNa6Ffxqg`I*@cieA1A9E*Yus2#+CC*P`VQLnwjd zDc8zr%nv__*q?qN*HDeX*9LGz1-9xRP!h4HEqmsKazPQz!K ztGPy;=6j!RON0@J1yABRwcQjdBfOPl&q=u%1PZT9x_=yo>Oa*`ohy@?Gru^G-$@1#RVGiymyQUj!G`=&e08(^aG(sFDO?}rWS zpcoz4#!hKkTc28nifY?ll-G>BhgBJ@P&WPOsig4QsizY@d|+v~K^m}5e&-4xdIPA+ zduLro|HeG$#vu0LDNW8O^>QiBldueO)v21K9k5yL)Ea=+j8$~lzv5&S|XD4LO_BWjJLM8nHHBj zCF15D9f{@(90~q(xpox79Z%?5$t6&n1$a!PY!83j#*mKF(%tBx{=!xfxl z8dPL3rq5`_c64a@J_3UuS9;_|2|#BPx@ncXS#DDZe2c|+eo39S)DoEyX`wmI(63kY zWaP^_wO#Iq*=m*ICQhwkE97?P4)A+P#&!&8<&;yGTuFif5MFNpvE;G&EH_~FFX zf%f;L9Zt>gHdPvX+cZ_9$(}h?LcQt8^QbKYzLYX?`9>|3BM)+lk#1)R zmOhkue&AZ9FBg7w8g;~LNeKqsSZhcN;>GO<>9e|3ikuSCn$~hapRXubwe7k;`2ZcH z4h&t{zo+&vI_>RXW>c3?4C#E$G+QSpQQYj0ZwPdv5nYom<^D5;katc_&I&w9o@%+T zxXWO-o$d(_*t3luDTkTrew8)h@R&WjTj}gnhFuKJUjcLVAAwl2OYOH39?5hiDDz|L zYP7mD+v;Gy*J}wJXok#mo}Of{kF6(b5FY4;{$|DY8_%lyo-yWIspG4AAv1_E#ViIl ziT**N#1LZK$N8jaeGpqi=kAD_;-IuLO~h<-^U2|iwTN4;(qQN4iH6gg%AQeN z&;}+;c!~8x-AFSUn|AAP{@qAhQ}FCZ)|DnQ>MXB`H-Lrq;sdD3yBXTROEP~dL-n`L z#DR*nz?y7JF6vFNyl$dPZF#lkk*(yjaO=#mCIc!pB;~-wfVQKyhr(7RLb!8DmEvYO zeDcLnDNG&c8l=^S*B#YZ{1D;wNqtd!&A6YnPD^lW>q7$qSgX@O1#1mQA3{6(Cc8f^ zSqop<_fhonNcC~T(3wH8Ci*q*xdnu8XfKY^6*oK$DxP+_CLIgH*-__!J@QV9ds%?NroGRQJHO(O;zT=~wO3ynE^xE3xNzbu z89zeYV~D+VBq#u^*ycZ9+wcQZN0#B<8S+pf(3sYnv>}xJLtn_u69+*uOf}^q?DDS8 zr-&LsBB%NR{``tbjPGo#{d0xtx$q){qRN_hTik8jJxnQf5P=(H`f_8@TIBp8;6e8( zN_OMo;A6L0(P5!R$|+T|*@x3;rt?QLN42@v-SC5f#ey9)J+*HDk9ea{RlOETYw~_aiyOQ@UL<(5&uOb@ z`8rbstkXV`!!7V!;XJsP7PVF#LOAHew0#oyN;Fognwbq=aX&5^D+F`Q?hYktXyTm@ z@axphX9w(|-p4Gy0Mqox`kd34Rv9byXahm>ijOa_189dp?yl(yj0Mzoaw85@ANq-9 z#n0a;rJ;wX)-BMYql34KEd>>=%D!p(EZMWQFfqrOF3&7HU>8Kiw#rB!h?`>JNBuZd zz$-J#o+*`f>d@(beL`6wG7p+hfE$osO={6zB7x?;JxhtG9jylnzz$0UntwbXt`|%y z;|yQ3o+0!QBlDRUtZ2$4ZzvwIkc=?OMT<0K4B?+C&1?i>$Fk##;2|@|QnH z-P|5pwLvdN{~0OlpX>VHVfPkC7u!PPP&3YHDYq<)^JpWo<Spk}p>$}E^ zJxlNWZr(OWPls-i0PNyOmbxgvni#E1wR0S=2inzlSaxjHPkgz&m}`bhb(sr=i8TQ! zVkK@3js~BwQ;l!49wQUm3Rzw`mZsWYzaZlF&@Y&q4(K`K_+B zJ=pApH9=l%Ir+Y*ga0yP73gF027rAaSsCIO$NPZ_^_VcCaB1&U!(dBR8vL_CJeoljuZCS{@0TeO9)~UIOa+^aMwpiCx?Xm6e4M33Dl+b0&6;ar zp96Heb>kHWL|&q{@YyBycIM~wbqi&k>@7kn$?R43HxuT#T*v!n6TpSds zjM+Vd60DCZps7sSDpC$fp3pBIN-AscGJP@o&8NuV);`F>Y+rqS11PH$j{f9?YG+>9 z2cUjLbOXV*EB2Ir)AXVz0K!ZR5%UHZpcKhimSE;Q*M3Cse88Bd!52ujZm}_8rrR5( z;DZW1QLbhX6eHw>wcI|}knKBPYS#Z~pE;sQ2O1-aknpuOtZDrTF^@!FfgPA%(@Pc1 z3zkfBN4ytR>C6%PL$2OJs%B@HV^TYiO?&F^-YUT~!?b;F4y{B_UDW42Uk_9wM}Fdb z_L=2p>kxhNKYodsp1_gE0KacH^J=!yL4=ikZME3F07iX|b;CrOBg{I9H!PlJlLfjQd*kU@$&eZ(gDkIP#J17m->@$wj^k45MsJaG>7O!%5PVz z+l}lb~AGsF#Zq~74S@UVcfVwc_c}UwN;q}cbS z7rH3V)WP-`*(=Qq-enuER7(iO+g57lYh>$cGV8D_ucT?)PHQ7q{H`%g=f3mlM-m|P zkTpSL^JrRxveUz%@HLe^Hydxmc*C&sM~nUOlN#2MP6(5)k3%$u`AcVTE|sVSfjJrD zT9yn#>m3KLOql2Mz``dGndnKe$sO;iXe=dk9?GgL`Ip#Sayw&h1PTuhoD|iLP}D8D zC3eR;j!#5r@Tqp!#SGU8(iaa$6THbRkINP78tM2wBO{J(AAytCy47V8gddF5q=X3j zPr(K#lx7X6#IdhT!zHXyXO<1eePAD%j(yD5iV70^qE8!=;Mrx+jmq~d@uH2YL4vx- zb*z=80N+~>?@?KeL|cask9p3g5!MWQ;xUr)v?PJR;^6aJrM2a7bqo9mEM73&K*keI z1L0V+3a+tGklbk#p6SNkOZ{dEJF(}{&w8`2?LYdr_$=DWgG-`?S|@->JV=+KQ1fMq zb7(mpm(%Yfez6o@UQT%d7trQSL9~v3BLJ`;*=CbF{Qcopd}j6c8MC%R6KH=D%&OSm zb9CogaT#~pYnlV?B_we;vARB)>^pv{ltSOQ@EBY`x_X>O5r*yW^Z!W%$FiRR#X@}? zOG>y3#G6CmpQm{=!;y6~w(%4Si-M2PQch$cBYKz(!;)>C-Bo%9!6MW1)Z0NeAlA4svX}n?9xFP4j6L zmZg~ssNbr~my-kCrH3x2Yp`k8;E zQSf2t5#>{C{es&=_l3GWv18sKo^US143}a?wNcerLcum5pL+lEonl2fOYY2KApED* zmU2IIJLL9ykX!rHtaiTIG&F_wHDP)%yAZTVSZ2o!yWXaNbm*`|uAEV^kcc`)a`f|| zn8m&I;UwO?YGPq+{Yt)!y+b;w4-2x{H&$RSM-)GcJg^c4I%DFbG?l&unWja^E!&Q}$$2I91w z-vr4>$IGA2yCB3BYS&%WP54Ovm{+x10T>d3Q~j=FZQr8t!M8RBZc&O4b@BQioy z1Fmq7H_|epIjK6;L1U(q=<2jT6gOC!q~Mx%MN%seP9;k6fTfki}w_==os*fS;vpR6aeZG<+ihUTK_6BlTu=a=yN3V5sEEk_k6;b%N)5PvcV;OQ5q^)vYmV{ zcHSu}i)eh3Spu9pC*=lHqqS=p=J(?)SNbh%HRn=U@DH=I-$pB#WFrPNY?9s=WRgZ0 z#FYn|p|uE-d0JKbwCv9v8f+Sd{J&`DLZ{MkJ~i#Pk6=B!Q$|%s_3mk4iXn8?4B?b9 zI`b;cw5>)MI+B)?ET4~Dd;!$wcR3R8Nv+`#4&2p*#D~Qft-~b`7vM*BYq|6VMyUrU zZskrg8#TmHi`i)^&X}et-($-w7jw)(aP^dv3wC*|U>Wsk&4T>%1{fYSj(Aw@ydy`_ zzH4bE3eFUSb2}1G*l!woMG_kiG~VnuAK;2VlNnW#S$k63E zGj%lP45%)#vwBjZ4(`jId41vYsZna)P4U`rgx=LelK&v;T=my{Wbfbno3pKd+rrl3 z-?H6sY<*JI{PnGT@I?n^>Oy zSThl(J=q6HPFq(il0lPWDGu>iWWDIKqYGJDvyC#!N~qr^gMN)Q1bZlPS>5cf^5&?>8nuHJgNcC$Mv{ahveu#0v zU7b2=NRhv(mi#Pk&5b`8efNIi_jU5aNilxDHTn!E^>SWoU+`i}PB;UHjjgdh^8UTyPl^IOA!p%`VO zkWgEaAqVd8;nFnaCGyX_VX3(ch}xx%&h_9DLcFslepeIRyEN{T?v3L{dYqp>JsUGu zhk{YCDL~*kLyX$^h>+dgWGo1Y*u;j&1YH~MPtjJE#+0~lysph!dYjx@1Wat3!Oqoq zcvg_Ra?9YVqa4;fMds8Tj`75;L)BP&KY>NkDBW-U{Q@!a#b)%OOXBW?J%LxLh-=p2 zAB1|;Y{(AA_>L59K9v7r>XnFHRK(Y>*OtmCwn0pero9wBE?CN+vrYs<`NEgK0Zc$4 z_Td;+`3?5Hp)Pw9sQp1JBB_{~(Y7~8Wy6jXfMwS*>Jp2wub2i;(0#OAOg0NXH_Xy; z(dhL>F?no`rfTin4l0zliO;w6OQ%m(jZB&fRIRsOX?gnR||%Aw>RN zhn{s=U_TG-A#&=x;KVkt6ur0ovwHSBBz>JIbB;E9@2sVXGpJ8pCO zE%)89#7WLxfs_1^>Rgveb@LRj#d+Ff@0MBKo!KtS(D_<$wzY&%%&)EcxKtZXy<10q+JtcSmQ%xwQ$$&WtjD59i>9GWJvV{q0JNsC z)%Cj`1V>;s%Pk=al8a#Q@-k?C?E(J3cJCIbZ++S*GhZ?@32y(Xh0IdKARNlHj6 z4anV{PLA-Gm`XY=GwtBEQrTvLAQTkfk`o;^QdL2A0~qrx9FXi~q`I-p8ZxIUwKYdViW4{dG#dIsB;i2kV`4*hb`xkSgidDn9 z(v~`ls(%sZnx9!&bmwwY}K?VkZAE9Ty0P)np;M`Q5sFY_$K1 z&^#%gNQ*|kj4q4-kMxrnL4OZ1TyKmH`V|I4@Y!5TJM$I+&K`mqBMv9O5!ZSpHo^Ue zxg3gxTKTlI5`TIM^}{(S>g_;oujWW4RaxnJXZHV(UD3d3&**BanI}M5?cTeyF zqegAoiBXXLY&z@6)kp@ztFru|IisV}{E*A6hs@@YJfczK{rNm;w7}_WlU79|{1_Pi zqA+E^eGi}c3j{^o&ag(f+Rmv(;}(T}Cu<|2U5tO%2VJB{_iy+W(#{U5K6ql5+rc5_ zK_f9~A6U-^>c0+5wjvGndYaUz{Sr4`RQ)O|W{!M~7@MTkwLgV~C$E3aF@eus^&;|ts7sw&T z*_;qK4P|m?oocO~j(twtauop`q!ZTC)jtH}G0!%Ov%gaMQl4~x!Ajr_t%DBxZhbXZ z%|_l~aDO){>X_`|A}x!+&9vqA+hK=bq_**97JN<5CLLToFKmVD?9qj@)sd>pU6$wQ zbnqK*FW!AOJn2GX=hMMrI94%pfdbj7R(h4K5Aj(3K7?WhB_bJJnYbyh0s*w@_f9m# zTg+eFO&W4tRuF#WyKDI7{<7e)gR`aP>GZn#qcKmKF*H#Iywr^ZnD-p;k!EO16UqEf}1$mTNq*SCr3aIE{apTRM?&G&(gKUpd;)8(A~;*cX#|htr@y zju@>EyXHv8p>8hkd&BvWd8<__Ew6*}MxcG0!1Vdc!+rInk_>r4p&Mkn>Dl-E$xVw z#;U{f3TMlQtOAN4+`_5N%Y7-i+Fux}O-6E0F5XWG9e=d)4}5GT9P3mEwqNt=rD@T9 z9Zo%*SlbHBG~QzJ^7n^Ah^1hsMW*;LYnVA~(G}%TOmR%w_h*@E+Pe*-d5^g_V{$HV zv=gY|E8epHX}XR#YnixhCgr@U*91}+K27HXI}BQIsMDTSN1zJKV);{EKWiVp;E}e@ z;1R*(I>j}cM2Ez^)~pIxgK?`hFsf@je?xauES$*RooBd4e?(fG)uT?x`|LwV37u2_ zRQz>kvC=>RM}ddvzA<~1$)n)l%UIZk>$Tr$O_JRHiUo=fQ8X{>?)AwOnC~I$$aAb{ zER*qm0^W1ERIJQ2EkgzQkKt$CGRb{yH&<9~TP8VRLl@r$)Y384I0yf%)K;^g!y@_M zcprxiTieD46~_B{y&HdHX-|{e5WG(x8Uy6;No`sew)^bzP@`ey$S4wryv@IQjsW3a zNXUN7f}us@?Zch>Mn&UrzuKqcNG#8+?Pys6oft}0aPTEt+Vv%BAhv2RJQx*v()@Cm zX8)8z{f<*Nud{V)-dXIktZ>23wh6%4Q8yNkYLDvZ3Snp~P2}@{mRCfAJ&|slRkIe7dK~K1 z4f)w7sFy}#XGY@iC}KCS!jc0LV)5l(oK=7EMP!bK=fHGjh=&}zF1jKeIh=!4#<&(5 z4=x_=Ekx=0Fzm0sOIz;Gm*U8EG-`ZW}atM|g~LsG99`@xBNkq5=l;Ifm{*4|RY z7uiqQvyfNND}JoB*appQ{BQ<_bo5u zJkgkgt6o};9J?G(nNBcFHR&F?W(reDE$Hh9*@H6R_-zu^yB0Fr<8a6=5mvhUiWIfE z($gc_U9M8%!< zSlelwoE^xtx)GJI)q$#f-Q9%yQS0<#$q;Upj3D=eS=iccBFP5NFqcweL*4;u18yBp zqA=g^_4+SWiBbMY+7D&Pq3GvXBrxVx?EfEkZy6QG|E2qq0KtM=@Zj$55Zr^iyEN_u zcXzh{!QHy?;MO=n8+UiN9R9P;IrBTSX6CN5?tOJ%^o#1MUR_oD+pBl&y`RsM?1iIM zq6d@C2-9Wq>YJJvSF4KBy~ifGhJ-3LT^!+)sqzaw9eY1rc8ny(QP|CKkFr^|zM1Dk zDIxkFaNp<=e2YNo&R&q(`oX0|r@k44VcrVk{MyxC$2v`B!OU8Mat1m-NI0rm_(>$= zO#S|s%OdAQ$!k)-LMPE6PiD)F`|vG}AEkOp{Ll5+i!=CTN$O1RJg)Se#r0T+)@&qF zQ{nFLui^%)!gCdz{nKB%6m7(Hot{(E?pZW1SRTyw?H*_8Kb?R`^boghe?zaLww6?Z zmBYTtw?t+ImDY@?hCATL=OmbZ?NQA{qEzBEI1Rr^Fhv9GTV9@l8v1a`(DGf-gs!dI zTEVNlKl4y#fs*K}cbKG+h@?vre3gO``^s z*5WdUb$v~-s?J5aqtK^8&v1)LgKAHeU6-bzNj)GLL3K&qnqA8q;(n8{?vq`fI~Bib zPdMY1cTOhY5XMGQueyS6e_3qnaxRppEe+>Dtf9;k|BahW@_Al2i9sx=jn)RHCFTk9c5SQwaP0YuEaR$l9u@ zBgdJ8+y%%z(t1zbau^*r*n$xg(_D#k)T1iNJv};<#wY^AzGZ@_3rpPZ$52n07zH-B ze1a(Z{T!Xd4HZ+1;=t@Th|^%MGQ-!g6vtAjW8}zWi2_$^W_o69Z6rA96L^02*pI~H zRm!KGGdTDiKe=Xr6ZaH}r7js)*SiLbF$%JZ4CZ79nDit_VWsMUw{%A%5o+hZgb2Ef zPD^C_9-_!Z+Xkj;>O0}s=4njF@JfSZ6we}_83!S97G^Q5HgKDgPWW#3YdD#94RfXJ z7wL^b79A=nuU|Sut@`x^ovRFqop}JT5WfTak6ijjK`yS@=2EuO zoKY^D(XH2KzLh}?{@Bi+9Xjb8V7?km99z}7YD-LedUD)AbH2bE`M|tIjpJ7WN+pHG zIaswo@_`xgOu7;f-R&Iad)igrKqwKb{ymwBES{vnxz^m}Np9xIC2pe)8SkL#@cg|- zL9YXh_@@r$9|gq!P6MMw=yB6Vvi^mHz$Ra9V8~yt;Po=_5?Fq#-@B8j9&RH@e!+7S z*s(D)a8cLvtloV(L(md5=sDgnyn?I$5dh7h*8u$|lj-MVXkHoSd+n4c>r@FdckSMm z#$yN;798_&mFJ4gEbD51uW_X-RnsCtg1ySk?5@#0 z9%iPU7~sKHcc)1TiJOn^p{irm2GGlNZwJ6**gFcV1%#a=DW0V7pddoGWa{FYmK-cskDL#i#H0QeF}!M}?@^Rh4<$ z#bWXJN9h7MkrQ5rTwWD-8cPwhOT8^6xS2K;$Ku_#vH5Dy{qc z$(30P^b|LsZ2iNHSl}Lz|)%&{F%>w+x^Se zRc=>L7_mB7#CC79)2#C*hOaC&?s94#FrnXUk%?cR{G%~cF8Dn)$4r4ATTBqRk;0&R zH4$cTRj=|w%OS?xHec7K1?DBm>je`7E8<`(${=CL}^YH zjR~b-{-N^uRdrGYdD3RfalCfr7!E2uYfUEo_OOaTtRFd}h^0!Q31L)lAfnZeXcYzH zcjZdwC#v+Sq|Gygw}&T`=B+j!jYta`+wnZtk~5)xB5O5cEpc=&sg`;n`}PZ}=`&Vp zfs+p2F#Ac~QW@!H;MzIEGkPcO!;t_^op5@qOuy<{0(W<4Vr!3J+l^ci<`>T2-})>x zBXdXNqjl0tIFi326k)cpaUNXVdzJg>X_VjLF5iT9aBOF=BbpH_xnMG%ma6L7b+m(y zxhOqQH}`##ZO_zn{Z*BtAZD8_#RUlbd!r-sGc5}GHH-WUnWK26G zuduWhx*(ZdhHEYn8fy4;|Nxiu|~;MbKJi zqdz!jz{JL2J$hmykXH3whEs-hnorhrI=yLGMEYQH)&kWupSI}_)ka8cFoxC%x18O4 zjNUAg>$Y5JLU%wiBlWL#+=e1u`~JJs=&!NQpEqUhbqR70Gpi1#wm_rWPPfC&JO<>n0}fi zI?KsgmCL)Nwt_?JYYh=pmE&3>0m)f+94V^iuY;XUyQl=HhSMcYp^lFeO zRC*iqxxLM>0$TVjBlpEf$?2;9Xlwp1qsd2j7>0;oSQ>C5#R(Hzbb)-bO1#6X(=YxM zeaLCj-I0SZxbzOO_e;rn zZ}7SdRSjePj#BI2HuWbl8D0e8tXZ7wjz4jMlrYdV%+C*S^${B^YAOZFEu<1ms zf~m)*6TAu0aR@GEA%$(~u4&>qI7yrV%juE23_Ln}XJ9HlBCe&FE!LlM%J$bAd@asL zGw*6WZ;e{v0_Fxe4eA4>z%vY;{A%#n-dT-A3*XSx&)ME(YYgz5L_RF1Qw4MIC1QP} zTa%!>9|d(1d&AEU7~B*~*i-NC#+U6k@)p~aFUG9V5a!@8K!@w`LM4Bnr;ShTeUCQjn}`^8jLou*RcdP zbBAv)xx^Pp0fH0S`>aqA<<56FUNcff-kYrlhU*G@_lhl!YRk8w z^8}k(U!49zF$y`YHPR1}y_uA8OIAk%aEVU(+Iei|F;2xF8#{OboSEScv>4t;X^yy( zCt_9y`|;;mn`X->5L;S}yRTsD!Cjt39`jD|xzQ}Kafou<2p1%h1td1t{ot=(J=4PQ zr(GgJp^HX36Vx}*n+DXKfy0tm4CAQVlEJ)GHu-{t5WcU-{F4(pNSv%tr*S^d;Zs{w z^&n5~cQS7iO-7jq9Lajh>1mdqE2#F_-pdR~@=$9^`J^pXACnLX;xOP#{FvxcjUflk zKxl>)kjUhqgrlwSX~k&6i1g=?u* z3*T+BDdckn`0DKaJbZTA!$`-t6ZuQ9!p4~P0-#esVK{BE-KucXGMWqETQe=qOcM6z%J(9 z+6=zL5>EQcgjj9>uqSP?2oQJ^I9{4#sTpYPf6U=cjXKbtw#DdQt~}e$q(>a9*Bh>y zoid>Ia*eur;I*kxWuuQXaf(`apUCRF+|_`5-tMq&&=U-<|1&1VPonFjpScUqE#m-0 z+d&AsPDyFDJ`uaTR+l}d;|Z`p(d~936u*16X<^r%@L3auqZys4jl;rUc3u1$Or6mS z%pfnaU#WJ)u5`O1YHc7)Az#%42v=~--)Oq46Ik*ScViIyiN`3oSZKPfI!it_`gTs1 zUnt_WsINDyxW(P=&pZh>UCLJxk;%h-q{nedVBonHk%a$74X%tUx~7y8*yZciJodxHq3#5ODk583k|Lm6vfBf@VY%P3p zyEOKmz>xCBDL8P4Z#IobRnh080$Iy!2p$IM-Oo$)+5PHf8+)G&-MaNmtBc!gg=Xlx zXqOU$W^Ku=RE;*svBJ{aD)VPoC*6gl!-e$V^96S4wsGfo6%ZU}bXqZ3;AUP=wi_n8 z>I@@~s|UG{8JBHeXGusxUqYAYgIV+n3J1~!k_nku{HzHNOBrIxz*;@kQ8 zSLJAd16m|vabU}~8@J`TA#_pWX8>>*g_9>yLtZAtU+nD1uvsR?v&@!y8HS0a4?5dw zBr_(30fJmM%|QAJuTjUhCOyJP{Bx`VMLW;vlk`aIR)+heX1t`GObtdlMRVCWs(wfr z!{}m|P%PC4_xAh83E-keb4Wo9ryyxC?5IXUr%SF;&U|X z$b~5=+vN1QRI*4vJ0PxUDeYSvD9x=4=?ugyM1B_5ED+g>t=Cu;E;|essAR%{a{6R$ zF1Sya^h;Kva&la|pUeQSM!hUSJrA+@HdOqXc(h6f`!;5TZuqoh!7}{dn-T3*b^R-g zLi^Z}OCkHOw67L%FyR7?Yv!dZ&tUcHx!L@j@&RECgSDlqA6y>Pqy7CsX)BDrCkCXm zwah~K*Cm%1Yfd_YeKT%U3EONk$Mo#D5df2!9yF*Uq)+K;hD3I0Hf^4Mbp5Vw#A}2C z>i4Ykne%E4Xl52|7k@m=RbKt1! zAQKh1T9ih6Tuh>M4)RvuY04k4p5gmJ*rJh){~~A5Birl!7F|3&*4rA-Sz}sxRGvo{ z%7jDe%}{nGmDH2K2QK_6BC{Nla=s)4+kY?clw_%vEX>ZR7@TJl~?-P{x3Ll#)5SV?XN}-;1UNLVF*@V}nmzDkTouPv>$(!;3fV zU@jSB|3J4JeEEpdnsH&-7~m+b{yv*m&s%XWA;d4?_^>}mqV}@95Qg=~7wTvngN*y; zx;l*U=5S%>AQ?_@6>-zQ$o*3Kw`sb3s#}OEc%9qkQXS`C(z?Sq&TD()zffMwot$IV zBy#1G7f2=3C652|Azlw?_5bxlyaZM-C`Swv;Y8&*a=)HRjb4DdRG^>Zqt}!bR*LB7 z5H~t%WO3TlVo{b~2rL-4SObe;JZEQY?qIjxg)!_O(#M?9ZjZ*9V=*CLl{j{IG4Lrc zNincFSpU!!MwnDQRZ6aRuHNl8l(9w8r%f`Jvr};_3Q=OOf}?Ic@GuxZdI2SA;!q@W z-eIMGc#kl|kIGb{Xahkn?q`I{fFe{#odxNjhi!@sdzfG(*he?)3zx`9Z#EOpg9?GT zsEWZlrx1XNV7^4(DV(fj10flero5>lvn(x?bo@Q1ukcE>VxqQuCfW$$VgV^jkSg}4 zh1HLNxgPIp9D51k2jh|NM}DSl0()u#)MkFoW<}Sbsl`iQ7E&(%-@wrRn`5*2t)5K7 z{T|W>C{#87T~Y4__)mvGj**BCnmZRfu+xKYvJ9?$djC82&h-Ce?=W`d-V~h0U3K9v z5cN-aTIyqJe$}ba=LIgW!FGH4d6Tx?9NzOd!+w!!EfOvg{_MP|kF8UfBRkESH9EY4 zEFhbb=_KSwXcLdCz`)f%V`1Lq#79)NLe=mW3co$Lqy|BG9N-c3{AKKA*9-CbNlE2q zXWIq@G7+L7lY5{=yke8%#35od*sB;ADw)8=5RVQ&i}SIFL4AA|duGpfu6y;V-kSGu zYoETT3)J5#sn}HVvk7+RFcfrk*#+8W{9L)u?=bTN*i?=kc5U&lT|l;k4(G4mcAeI| zohP9bCh#29apOuMCoii?4CiWPjLM43cT!EQ&kF6*@xe@cvorcEq%nHKznT_O>td?} zv`Y}$eV$Wgv#DOHy8X^Bd1F5W$F5+Vxiv@R2**mUOg^PH*e6#_L0PWr z{E5YtG)wK9Rx0|$nCnFQ(ADD{jnFuShJWrL&CE+egnW6wuzXt1rqT_Ba#SOA3VIHR0!dO;oxG=!Fb=srQg0}?# zNUL`z$^k;;!_` z>geBbbPnN1MNYR_<8pWOgye)94m|efO^)6RKW^u6H&5Ol9v2`3&SY{nXu?UZL`NPaiS`*Xnav-qI` zu)N09W*RSY1lZb;JXzw#jJnJ&IZ6w%3&fUt=I5EWKqb;h)o3!4#@!Op((0h6Q+3H< zYr9@hCXWayOWFF(;{+6$l4J-|4WqK&M4Mp%vgar~Q0L`wbh_9DTg+cLby6_%gycgE zrF;}C@jYG;H*|hHYFHK_|1QSVMFWX;S3rm28Dp?HEN>mywi#x6A0p;ZT5Lg73VG@gm?u2Q-+TX@Nh3SH}`CIH<4^Oa|b&vL9+} zOfxez15~nk(qT;DLG>|vU)nl&_pVa7)uJyBcWV*9_*(L7vb!ZbW&M=3zj4tdSbhbX zj-TU2JUiG&x;k*+RP%Lc@2XN4S~golB>RED{6>i;&d)1u15umAuYIC>daplaC7SHA zt&sI)hBFLotE@MCe&e40A}Tk^Q80;FIgzkP21M9f!+LtQ7yt{JkY!^7U0wQgWVjS+ z_S|BrF}sG1>v_>fJWCQLh5t1B`+g$I-ukRGZ6kO_JnP_TFxEh*xM_SJfeh~@9i9JG z1w4PJng4xf)E1Lr+C}b2r~JNAZf%8_fbg{^z9mes`OHbC)yqyZF| z6=%Aqd8>kAB^E1mohd+61WXMZ%(xvAsdA2_Hw2P3Mki|>9h_V3>(W~1NYf^V4uR`~ zVGnj&Ke8)7)?meCXzHRXQr0p|qthlI1ORH$0J??9%M0OL0C)TOoiy0v0vRiagIIvK z@5@cGByrFkUynv^`zqP?LEU1kD+ud*s|>P2lTJc|0byIm&3WUg6qM0v$f~2AyFr&U ze@tK`-TcOxL7X$}G~0YuLaXy=>zD;`C*pK?i436kpzgMOp%8_%ThXS?s0uv_IVs;8 zDBWPZCnuiWKAv3Npw~*3c8i-P#7rce!ENj#-pMWq<|6jnM`1q#t7bU?Aql*s2vK;X zP8dqKC=-8lTAyipY@-BG_lSZ0nu;$b&%V$1?fml#nH<+lc79})$PGvY8gfXig#nVr zKpk7xSu27$DA6@sV5=X6tnm$yMT!P;W}wcYi2OdwT> z>VQhV4E(z^9XC+xoqggBl4!$+cW3xe$kMOy zbYCkdJXdK4SNb-RWqw>D^*FkOTco%saVirkOnC4YidS>U26Nw#&uz44mKm3Ti?G>v zx}8SX49l`qK*>slS}I=zH7QSJ-p4Z)<8+FOi>yy8?he8*Xtk-Qn{~`AM0M~95YnzL8-U^)Pc2AuQI z6}tGJD!b@^aqnog3=@M){P0gVhzI1OHcd*kjy_mfh@3q{fw-)CA;6~K>8IQ}_|A&zb>)q z>O&$ZKBvd}VuqS?^Zp!$+3V;?n$M);^=tdn&CK`gAD2?nAino&TzIrKJMLV_#K8L` zXk(?9i%DZBx#y(z*IIb+cWb?l)#g7dCdwC@lZN_nS2BATWS5pQZ6yUU>6jvPBks17 z7a9)a`h9j%8uwAezIk&F_T)LMr>c;m3Z8`7g!FaUOoBNvl2&I-F9P3))C3e~&v#LQ zzTkVJZu4>2)-;hws)MjWk?>s+6O*-)h^9m4E&ruI*yJ-f;J>q*i9rIX;>ouc1mU$cQ7i{Dlje zRApTIRljetZNwJB*Yw7;yi`gZ(9Tvfd?{BRMMpP36LQW>_6HaFX#CfOFx})QphT3Z z^=#gSYIY;A^ZP*Z9lzz__qwxKEyi{k_-_4~bO4oU(T+g)SR1E1lXtUupT3uG$TC;$ z2@fDI(NSGa$;47KyO?;5%YzzG3>6kmxs&?#eIP1lw$XIX!EWN(c<=_tAC0mY@3cEp+qM49XV{(bsQf`pK-4X{tx6p z(gaBZ?hu>rJo4KQ=?Ptun6WY^kBPeLD1p8nXMMg(VM5Nj8e}#=I*-l?Jo%Re9+Bic zS&y6VhP^1>gbOrUWQ%Kf(HJ+~desg(idaEz;whXqvs-&ttWdoClqVbH*)Oco-(bX5-}v18F3pAF;h=X3O=qa-)KWdMbWTQ#1@UG%CFz zO5M{FKrL`1x`poBfM*m@1{yVK@aUc1V%dC2V!P&0pC{%HDp=oQ>3nfx-{z2>C)M|B zT%@1$75xMBg<@|sT<`xS#jnxj_@`J%UA*yC`pa{Ge_y4CI>zMfSJSh14l_!NfB$;- zzQ%G98~n*^xkVjVlrgEr;}jy1MvSB)Wi23aHtq3SyfU#&}^mndzKS4@D_UGae={ zaFvt++`3~cPeQdR#i~*4jOh%hd*S&D^^yvoP+T+j_3S&fd<<io3e7`I|=7ORtKgXIJ#PE~}AnKjCXk;HQewT$wQuP5@s^Z8)>@ZR}& zq)YgUj)6KMy~m5*k`Xh-69Bc8uI6sRQ?co~M7mg?6Gm~;;vU@?kq-9_2Mrn|5S2Ry z9Eufo;k{cFTvtz<{K4Vsu^b`;pO!>w=Yhj4-%drEZQ2z)_S?dHiEGuhVKg?JRLZ=- z4`~5mI;Wk4-5Fa_*e4+gO+I`6u(;%S5xj_m+86&9YD9UVKD`cyB>bIKl~l=*)>@NE z#%JnxJ;a*uRa;}ZxZVW*_<3*HY?a+x`W+%T>o0f0=#syhaYyf#w%3<*0(wldl$2{A z#T1c1zRP9(Zap{R@_B%LyQF|Ai3iupBli8~Z*0gV2O=IuS;9WrYus%q*lY}plOqXB zxCJ`N+LGxG2ErtyA}FJ!P2QfEpTLH14!!@AmHp!s)kVU>PB52c9&Rn^mKSn??*z&L z5q^^;66d>Ir<>o68Qi|PE$&|F3`F+Q%8-5sE^a7ah4dUidM+GMz#~HvmWQLjjtH&7 z33o&GFW&~amPMfW{Ac^E7N>{vW-gf2W_FZ2hu?U;>$Y}nZ9`69j0xl5M>!y&?Eswr z>Xg32v-cC1t&UGN7^|(eb&#K%RA_0MdIqV{{~%vl+VQrGbnlrJ&)m$qp5V4LHD@9J}K$^|9HZ*Q%OnF}mL~#_E1`*c3r`8&<@m z0Q=mTGi!xBV=Qr!*(ne+ocbFK8gy&<5&FN$#{FYm$(h#^`p7961Hwcw*hXd2aUCAf zSKL==Ha-zp?7ML^AXmuM0-eo+I8&$lioyL<-23M``CB!&P}*dM=MdSh_d-FqNalJ|FfMiFDAdF z(+E&ZTA81nrCw5f|FJ|>uw>no6%76nlYjo!zhx>`(Ee99Sz6}*)y}e=7ZdWVMLU|z zLSKQz_pt0#p8xwQNhtgeK`56pOP4x(V6KsgTA?MSQq$D3-u(fyn6OPzX!G?~RQ3Kw zDS%XV3nDd3$baA8MN5{|`TvM>;rZ`yE)krgmB60&yi@Ya^LzRkIb4ZA>P*a8_`-c) ze;@Ct>&ttn@IEr6Q;Zwc(RpK+p>e|F!N!o&zMd#jT!#Z z72QX`x;J}lSnWiE&0?-;92L_}{Lq6@*9P9$@~`-SXPax6$Mrncf#wMC?L$pFghjX@!B8md^Wr$LKhrEfp*{ zzog+&P*IG zT7g#V8-G+5q}SQm>;_aEEqxNg%$+O#*~NDpee5fDr%w6CPuB{;7tel+&wU{HoD=Ki zsn+S8w$W-k6aU)ux_2MCsRu2waV9w0unjhni%K#nJC}BIzT^E1)k$v5yD?@O=!E<| zUdW#|^t#x$oBLz1^GXNRj;g`eyl;;))q8l0H6PNa<3H&!H`K^QIQ^;%wN1AB0h{17 zGZk`Izy#HWRwD6csMNo8Xml88AkF*j5r_+?iLTZh*5~hBh2v9P$S;DtMavl8MA`S$ z96KnHr`3Y8g%^+7A)ddaDmnecCf>9S4(&YAI}XL3b@<+==qo&1D#U!ygR{_N_3#b0 z7chUxHvzI*VC2&>3n9|)0j1Tr*-{7^Xl_qU&wk;XB&~HK=Qm#j)lO$*0lM^dH9l<{ zCx#iGdI`3raC44Ckg}jl?wTbyTYg(QQR16)pT$$i{zJ&f zl%qObJT3$Zwc<#%gol!jgw7dwOxu^3GGA{>MZL-DeWi3P0TXqKF9(_^jH2h*T4(Z* z<)}-gXRlSXKmP`#P-hVHwVewPMox_08ahx~^*wX6fD=i}LJG>-_Y&jCy6~T-2`h&b zeu4w3i_M;cQ6eF^?JXC4MK8*Nl>%LZ9jgneWL&OrvtY61JN+wb5CU z*1DO~<>$^)**^ewLQ4eZ{aTa9xlFPrB9|A8ot zH^+7~ zPv_Vzrio6rIn}wk+)IZmm%w_>*TyGZ--5?Xt&@kRGLg9mRWaNHbQ8- z)YRTm4P-MQO9FeB!g!jq|a=$I5N`L4I5?yxBZmAWW{V?(K@q+na?(l}PN<-fF zz)sYGaM_45ZGlR$eA1)Pr;CQ>nptbfSM39nUwuWb%i-|z(G_s`b2w9?{0wXWc+w4msj-_6ZP?{#OA_` zZlM()N@Lps;wfX4(Mu3-`cH__A##0(oMX)EK7s+|NZeAxpRl!~vm*0N?&?zU6x{g* zE(*xopvB4Zs!?L#*?<}7(-{ZV+A7E5#chp?C;6s2DhEY^a8yKPzQfL3hq8!Y(R_!1 zm)=|ApH76vo8qN0`Og{=4>}hbGtkyLPMa>@^FuSykFF{e?u&`XcQ$=~z}4B^Z*;r! z*Jn5l-Za=$z41e?gcOYLeaIjJIp9qWY~XeHS1P2B0hF2ZuO15(5Hz$r~E!)<^k+F z+S^v$vJ<+V&lBj+?mjXI@0>+KF15hSf71GqweuHBH;3U%;7DN5o?DTf4z>3|Nu45D z^vGHCWwqCHR;9JJ)5213QU8PS?`oxZRz1Gd$KG5cLBs3v7|PB;PBRbuTi#TB(PNgZYKARMztw%d&y zX-ReKhcI!oYALG#U+ODL1{c?=+n^(Vw-OErsW!@%k%qU{=eAHds=4Pd*xH0Zd9iyB z%oqg?h`B-kpxCc?t45RPVLZU;Rf##*Rf&xHULu=Q%o%VXl6}(iHqp%m@jx;tVoT9Q z!rKIYzw*fs=+isy4na|txQ`c%H<>L`cF89=<-T)XI_LBBY1N!o?l~iE^w+f2V$s8J zgWs9so<*5NvKy_S*Q_{icanF*DRz=Q`t4j&E^j6#U9>)ujQDHp?*V$cVekH>&sq2w zmv?h7nqu+V27WyKv8$rGX;0!C;wTD{#({TjjU?=%uCYDa8z-hnrEkH)?CKai_c_mO z)mbj@5$X`yo>%kS#_n)~wGaOlha=gj5N8~+ofNlQGdZroc$3n%HHvl;juhS$1G;uo zUdB*i_U_{26}xmSjk!mU^P?&`^>c|ETLM-*K7-&gxr zl^BQSo}%i6$YD~^8fbv#T#Hh zk@ja6KYS8z{(Pq3L#L>OS;;Sbrdggv?boT_k=cR}DusPwf8diBUHe}-{)rt&u8b)K!Brb-Qb;Xo}KZF zvaf~hJdk1_?nrlWy^Y|$Cq)piuq>)2M8}1Zrj?XQy7T$Hi}AaK`n>)3*-}&VEE(AG zx83Lh;wm;3-`vwU>-=yxI(faL@j|3q1=*n;vh%54gSfhyEFR@gz*koc>UtOh&wI)$ z%E)REW93Q}I{E^IXdvR23OcNoTc-F!^Us7-b-!>+oLjrw=9K_c%iaJ)# ztwC!mgDa`qg=KkjK-_3EeLyu)&^g%xa_cn9%V&W-V&e{ut<~ZV@X={c_)6H4lso>r z9$hnA`jOt|=i=N!00o*ZG^Jy|GW>|LS}JB#jdbKw@>&@b&asnVwzuCd(O$b|vt3~n z-G6EihxH$Dt^eG%i9R~_&GL7nV_HU;wdd+eM6dI-1AST9ld~6(NH+d$Ex7prb29WM!b=xe0Y|k>v`>!Yv=%laY%k`@msN-q@t$5Fe6^!)KuB)cB{yb~ zj~;xzgs^yuu)|peeRA@lsdj`3LNYR|`4UBnM@N^myWC3VZ{jo8P+|8I59)pT>fgLI zBr5#NsF%X;lYsN(Z$I-bNY-Q_s`Zk8RQ-$6|2!G4M-M#@D)7+$o(3QJGM^7@ziv}y zW7>fKQ*5eY^?$10G1~6L0kxfNHM006%dI(h%IgRJg@TXyUp9^y=9-=VdgFilI-)py z7^nYV2pAB)%S`tBP*BT`qjSgXjT17`$Bq8kF>Zp3^2fJW1MEZ9qcY#ry~(1Gji+xt zRRP3p7L%P|B`LPDwUtE`Ajc7oHeKPayv4)iUnsuhyL{{+mg&O% zQjm_jnk8u}U{(nUB0F06V^O_=nZAOy;*wdA<^yLX>s&fW`sBkWZ8FF09+!!fQ~EMz zQ83*|rUAVd7m-@3x>|=?zN@$rCtXYVTsr4mmg8u$eOa3i&zy89Db>hKj`Lh!Lo4Bk z%l2TKMPbB+0kO@lPmg?u0bf-i;}hCr^jh&4^0=#fIYLgzH3^as*7nlRzfet)xWI~& z)GVgFDb5)E^{6)O5x5?SKY7B~w()5(l}NVuW?nT~Eop`w^FGkHrf}hkC3uRiABNRXpcZum8z<#?IGAtc`2z)5U8V6>{LY;Zmoo`t<{67M^kzSp*z}91KosPg7$lZaUHK8kl8vwo@**viKSo34C5g_k zEDqWIdn0to$-?4sZ6P09H0Dh7rKqs{oC*|K-8zLJ_C}Rxt^`5t4&%LP!tl%JIDqHdI zAn1}u54GQ7-jB7g*i+D4MeI3@yc5b2rd=K%8!sv~SSebUaE?Nb68PI@_EUS?YNqiz z+3W`aWGmVF%n}!>N;T!EQ!9&lEkb8}?` zfXlg{P9pB%krBYBSh1-vBy=;_F6Rtse*SSeR~;4*ENZ6Hq`uX=KyN|1sDZicKINcj z7f*Rda)0M}Ou+h4Mjd0N`2T5ENgZ$L7-h-ErVaJ!sa%tDYu?qj!hsyk~|?Cc*n; z#5QBVgjT&|wnFsdzV!z0f?P6{9C&)G`S!W@A6d%xr} zQKqZE^LDExK$X}tJ%ylea&GM~y}koB0!Yb3V|;*PFpg23uxvb!R44Bm&+UMIxsd)k z>^B!#qk%)>Q0t)%FsDC}Q$p>NM;29&!&=jk1WO6YF7}MzBy}GG*Rz`VITIV@IUD`u z=HC+TTc$GKb0Yi(p>NZVI;t5eX>AOPK-ax#=EYJtlhV7|CIVMhKP!#dg}XX2 z+g&rJ^u;Cin-MdF6x=I+vRw0iUATEp3uHawuNp-HZ0J^(xiWVEC9u7hM;F7sZDVf8 z9^5Hb49MumO0XNt6Xw*;_I&;8uGH*2*LcRKDZ=5WEkUN92FB>OlDYcewho5Dw!7a= zfGS-UA)KxiR{5GegJs8pn0IqD9it`}>kI25*6i5A!xR?0sT_Ty5Q3iKx5SIP;HY=| zjY_A@LH?Y>_qYtScD-Fh9;eiJJwq$C*4WAevth~0`Y1-eD(XKkh!)Zb0b7{3R#d~0 zwmQqV-iuRKIABQZKtr&j`uJHUby;%HjKIpo<6&~sYT-8j8&tGuyW#$5(*Ot8&$dTQ z5#KyyS$!<>Q?8{0=Pe#|JFautsuk$=4=%PYUkQaOst<(_bF0gpPRjb)a8r{LwU(Ld zOcfMET;RPJjDzh0L-Dov@+x(Io1TRx z8>mqi)t7yoi-}RpEqJo~10INq1t0g!dFR{astH+}Mx z)*Ad+pJge>gaiFyzt<#t;{SyTyo-6wM(d_Yf^5OP=x!cEm}zVsLWiaYmP$~znij|L z4B_^9=_7^JiVp4aneD#TaYDCL72r&1792YKPe=NU}ZWn62hav43Q|^}%D(*u$zy7Hr zeiX)mO(&rKh&-BzSoW1|df^-V@9oYa$p+&Cb2ilC!^d4|qEUztyz1n@T+2(x2_2;h$| z4%7zh8uW5Eyyl= z)ag+w_BAiCG1pFOP5UgK1r^7T!-WvzujpBq)}R!}Q2%X%PQX(z-^PpoFVxM60auEO z3IGk4Z)q+Ew{dnkH}xd^%r_vp5oU8esOTkXaSghAdt+loDDSpLc(^nkuJKfP=ls1_ zT< z1b2t-MuWQqm!@%df^jDyff+=qUR*3B`y^F}6EmCN^jRL*9)`Kv2k?2K;o_@aUZJAXBD zAo{!<>Me?fm!TkFK6A# zntE29o{}8yq1k2STs;aNfZp^1ytqShpNB+7t>J#zC#cD%{!1ZO)S@C07#gXX(3}Lq zmpC8Dl0$Rn);-%T+oq8$0;P3NF^_>uCe1}QzkQgzu_}{I4Hk3V&~hzgf4foD<(%pE z#qu9CpxxfY{^<ciF4?%TBI9T$j&>0OU%H(L;G^Oq zAocqWj3)YW>*4FZAJSWki?fUu>IPH6;%$7v)Jy>`U(1GbShwbC z%}5L<=J-~`%+ur7hW-2|gZrmiLz0nF(-o(umY-VP$%U*`e#QNq^tDh|o-aOG5c_yN zM?oZesnL-IF^%>2sO_CHNN@5p8?n4+O_kJ3^$7u1Qx0h??qX_!?gPw&$Yv3!@nYjX z;1|m)yl)WUaiS(w0a#Q0l?`HWCDdp34ELpY!OzOf)phnaRVtX|9}_&n72PS`I>w8f z(AY2Z$a=qB0Y+3XB$ixIF*Ltd#CS%%R;0a zi-Y^z$?c%P#uV8UnX-cN1V;9<(_*1U;{}7<8Gh9*e5BaSvtAF~M1@5Ur_!Jpgttww zZ^NwW>ehT%k~QF|1nhZ7CgsWPccF6K6jkHG^0lFZcUx^a;dS3D{sg+;}#5+(Z6yT_1+O8oQXQ5!e~ZaMsHUj*NRI=W`5Y} z`%1uVlZa|Y;l?xzax6A#iLusQstG_oyr5E1GRybgKV2Mxxr4k(v?<+9tY4*Sy+SX0 zGdb4hk?oAQXiojqWa1j zezcw1Cu`K`%H6hp*u$HG3wAgw^$%Kw1%@TGb@}Ae0Nw0Kg_DrY3ZA5fO~t)f{lZp@ zM4mSCZIegJRvlTwt#8~#a1cHcodo@M5R)5iy?ktl{DQ|dOIKUrw~k6Ycca3c4LD_p zT)z+=az>g$X;omVoRXJX*cYN2KT^2EAhZV!rz!y7mDI_FmE;v_DdMZ4`P_LznwA8# zp_H(l^69U`ej(=xNs#}+4y2*Dp{{AF5A!e z6=@uk-+R3|1Bp(F+uoZQIC*7L)mk`e@1i#G+9$|o0eiKd6u;y3XStVdkp^om&1`Q@v-gxMgCz(u>k*z9^GWV=~pP z)8swoQ5cTOCpjywJdOJ7$OtA--(1fbE6O@{@x&(uwF54R3`ou#--D~KJkA$;iYvX{`+n` zsQqySpHRa?Uc-BBI=y;@jiP?BfoJ(*s-JrhdR8Y4c&Gf92RgdURD?}DSB+7ZFoGR2 zK#(t~YNhb=y~0bJkjHfXi|FSrZE|;zGF|RG~p*d50^#Oa& zZO9ZjNEK?h!m?syq%*^`v;W&w?O*ioEQP!DEewlMghD`r4UYkb^?LWW$xiO|p7MBALeG>>$H>3)QQmmXZYJ{kW z(bT=Rv8Y>RRJHnJKKCl|W1a&UDIkXKtPD53A-tB!y>6GPtEoB?Jm}~Y)a(b5e#^ZC zL)IJKKh}ofMfaWiwgtWMG-ancbJ0U9Lubi=(RxJ1iR_~o{o{ieRYz^4fD zwwINNDv{-)OA+I}>N=V}p2gSG)liEKnh?SU1+uJh7mE)bGO*23B1?FcuIG1}iRa6L zA9a?MCPTh0V)rw>|0WCaUIe&-M;sZ?p?qs1Kg57Yh3+Tu1L%Y(?fV~_Q=t{|v1fGu zppo+SNgZ=$F>U~+_sP@3U!RFG3cT$vggxGNe1abZ3JzCfyg{_|&eFgNBONK^78`IC zr9LQj!g0y4cgdrNtr3X!o>GgJX*!3@k0>XVlw=SUi-W8p{xgsAJfsJqk|;P5jEE!q z{>5kjUUK>fPMp_^Y68P;YOfzG32A7ex37I)zCVWhS$dZPZtV75g=`mQa>l3sjdby} zdde#!&SS@a3Q8z`UF6KvXMksqkp$Q_$Uu=Z6HQgM)FMHZ)P%$^u6%Vg5&NbS?dB~D zHBaF}ej@@Bm3pPbcZe70%&*3f40Rrrd(HeypOYcaIKui_m6Z#K4fhul2R1)DkncBp z_wKkiU!!Av`)R?)qEY`zb5C3VDS`Y$QTOBczYn*U0t5d}f0_NG;QeQ>J2_L+)q`}b z`sI@FSl;tL)1`YqYLM#nHkE8GS@dA4bJr2GdbhPzfTRIl@^s5`_1|gwzt6l+L)o%h z9Q1L?r+-jFfTZnL!~fs*|8-2%lVNQceICXGJG`5&?bF6(l>96 z3gxY0wQCBZLP`}emaU}u>p%l`2NEdWANYOOjc*d9kZaf~X9m85^F`PDN@S@A^JrBY z_!cgbs_Js*IW02Un(8KmcI<(|5&i@&%=m17E!g012wp)x?7DvyNH1K-BFu~xKVoIYXBriC)Tqm23-dE zg6QHR$xdHk$lbjTgocvSV0FZSaDT|)mw@ad2Mohr?RX_y9kI4gMiBkfh!E%P` zfb<&P)%T`1Am2WYAgg0tU+=BRXl zH3v++{alV~(}*Eqt53Y7y~tZRz3FejBi}yslp$rgD;2 z+&q&zIRfS~mt&mE9LF(TxRaXAyywPewHzj?(hm;TOkM88AR;YnU3eVtqYKxsnnU~A zJ~_BYjQ;RV$%(PnKGfKYP990t`L5`x%tc5kF$-KKbg5LDuV$`8?7Aqy!VffK;w#v2WFqIr5NkH%jd&s6brHP~_-#p`m@HXE6cpTV zo51l#ayel(voJ%Kg5`bJsb$M_7T#<$z5_A6*$<~^;#Szj2d=_;{|xwFX*)!lKxyK0 z5;O1DzQR-(rdDg^IR$NHtKz*a`BxY{AFHm#3x^);II?D!eZ4sCd5MO3UWm4qZGHZo zZ*-By9$!N&0JqrN*DqC$^-X(YCis04qdZnqO@mKK?3cUEF3L;HGgLeFr$dF9>B5o? zQ!3_*g;pA8YJLA;*LDVa9xj8wc(2t!Wqpv3RjpxrU(G42PJ$g>xM#7ji0zyIg4e^E z2F{rmZcH~LTB799?-UYo2R_r4M-+x(5VFUkTZ4YcrEwyB?J|X)Hf@rNs#oO&Y?Dsb z&{!e3VT_y)9qJ!6TB94)1G|Y@NBiX=*lpO`<>V%$P`{@#WgsfzO}N;!t=R^`SJUFp z(>ZBGz>x#B>63k^K8c0*_lQ;KwsM$ytiVzDn-qV-KU0ypkEmMHao(OtwRdfhky|I9 zq!6Unv+;)y?9B%8>Ipf}x6Y>VezGEj&b0Wu#1o-nQQ>-EeP0s~FoKdBmXZje2J z0Pak-a2_%V4_cWy-(a~q`Kz6e-IA;xX|oh*Ad8vTx_T!;OC^h%1{d#=r#PHw-uH?ao{rpi zd`~}md8ovf5fz)-jEbX8j*@t85^ zyY(}wGJ)z7C3NEQJvi6NU~Qr--%)Wi!nr+Z0FE2sZ#)NBu2=2-WpqyZacjJDT@M*X zL_)fzRzDrT_;@#`sGf`PdGAwo44hHSNH*O_XKG_OiWWSQ*-ZE1C%B)E@E_u|! zK=CRpGR%vN-t07d@wh^O|L8>`FBrvklga>FcGMmRBn3>yBsyg zw^43#?|t(1_I95WDC)MyHV;l`y*OPqkk9>4WdGFQVzH6_p^?|ZOMxE!5u2kLCev@P zYpH_9mU7-ij~4?i2$t(vCu*X4aj* z4kV5@hS&T^Gz>+IW>15-HGZ{DU-#%z)2T@G76_R6aoBJ!6i%{?8n+3wy&Sl}KUGyN z{t5gYnv!j-WT4?5^1S6k%L><_atLVBHfib1<&k>PplZKD3U}2~1Wn=aic3$-A~UGG zp%eSJ4@M@B6UmW^4PUQ*QK4-2vHRzOYr=Tpq_~Eg>nHv}n%>TyVzgr#j#Zu0b^itb z3I``anTqG2qhzy<53znDyAXSS%!_^FYvSU7J;zI}ver8wNV2{nm9g z0nD^uNu?b|HOuCFwJgdoq%U|q1BQP~+$)k>8&6LUBtUc9^NKKy#Iu|Ayo_mbvCcW*q8r z@Yq*~Af~k(IT~n#iG1kmIjr>nmnrNP^yv|4)3Z5D{F0Hj)7YpCO>REEIwvu5Yh*j0 znWg5@@syTMFkSR@FY81A%b4Fc z7(Jh<<1axVm2mEN4kHIH+uGU^Q`NEy%||m2537XX*9lpgx!_R>|0L77N_tV9Vn>5{ zN?Yq|@rU1o2=XiCYh6q&-@&75Yj4&kV_i_~)zbD#RTViTC4^FbE9yy(ifwynwNJAb z63n)^E9#bxGw3xa&MSGT4IVS&FUW~|V1y+{oC!o5+qQ(}5_zV1B>(=JeLDE{fZf5^ zqrPz%uQ#1%z2)?^PcSzDV)wP_*4PVu`roDVT$8BCQ`5;G?J^=ob0DQxgYWjBc^|ef zmj<8k8NRhmCI;!D5t4h6V#a+kf9732yc1$WjEoGx*Dko1`$N9j*qvR>Km8-ow9oO;V#%2dwwj-7-Dme8 z1vg~)nr&`bf=i~am*)r}_lWJG1+z|6F-MZE=l1@CX2--xd)Kg6ZP12Wnc1^2r*NYc z!!I1hjR$AkJ#!_$*DSR?kd>59Y8NZesyS46p#E7K^lVy|42wxh>7>o%xhOnU6$EdCt`3~3$|Pg(uTqzugfb-&dO+ zR~c;ViPSwc_O+!*=eTK-kwOJ;=<^ZdJwK)rE}f+nl_A`}z3x?imM0!o%#SX;iAij~ z{gpsUSAu$c`H8*ww3j>YaO7Cl9o8kYGU~4OT3{<{nf20*Px-k6l67x+i6gwCw6a_p zm83SL+gU%~WM0J5uZL>Rl51rdq+mq9mQl)UU)1)PfVjNb;N&Aq0-H1~(MJ5quqnYH zmR)MMp8oxadyoV10Oemsb+)L_bYj-8HKnJ-N!LONWeNE z>%L{xba0(Y8tRxV8_N2Ad7<6{cw(>{w(k(Y(P8i5U^w`ML5`E0XU2m9f{*S zqjsj$G=#LXRHcS1$r1U1nJ#j)6DJ+4_3QNZ`(4u|rnsL&*P8P0#%yocHOgt8^(t7E zoF3l<;cT>g0jhJqUF>%GV&2yxIBwuCkv}f$6v+J@V^~E*)RmnvmUdsZ{jdB4qTJOe zsff%8P1h0ToV(knD-EQM5C5Q%`ItY(;WgM?d}thaIWedP%6M6)VLgjXkML*stGE3( zjT>W|Sv@GMES)Hi%kz$hXvjRX3c@wr?o?FMmBaSOQoJCKOi8pFx7F0XOJ8Nzrpb2? zR12a!pD=yzm$bTJ;k_+=xl!qoA(O>8abo;O^*{DuCJHm=yx70ngSxH0_nd!9m>_ap zlSc%+4HsF4#WjUWiq)Ojf)dtSi4Bq!Q~R(cKw}W-_fIOzc=_wXA~q}xFuscF61D1$0P-8@zVS7-D0ZoOK1X4M&fCuC$A|+U_bME6`4@SHsv~2E?00vAov%s zF`y?azvf6t;16W$zkzNEcs?l!#a5(~Nv%ObNDrXqrM0AT|KWJOg#+-z#XWHQq8IQl9DFt4e*yCKmbjG_K$2HLAqDN610ZWZDr$yz%i>sV3Iz^w#M9Mbr;jc{08-X+(^NU}^ zU3Id+Ook?4<;?@M-(@8M#3H}*iV9a}RIna*CT~mD}GC5mZ^$T9r zWpJ&N{ERH@^zQghN|@A3Xcn7+9yv5bb0Z@w++?6lR}ZXZVj1lDMVGf+XQWgKq;{l2 zkKkl$Mg~h>7U~^T5U~+TsEwR^ETA7X_zsIOUWY)zF}STfB-M*sQKyRB1{9Wq=+IPM z_aK?)Se;s`{4(-#)d(Cq%c}~zC?1#7r6ua)xBeaaCFJ3JwlZKyv6ICI6;TN6N+CKv zWUXM*N=Z3iS=OPhgExThHpJ!CgShJX(6-Vm=SHW0(3mtIHMCA3;J$hCw{pJxT^@%* zu@=jgYmz0)5WvolI3DH3hBo)5a0ge7D=QGlEdeUrRG054m*nYFSr>(gni+v z$8M~z$*q>E!r5tvEE;T-&{^u#)x!Co(b<1$4VQn#Eg$+RhfYo?LqP)1R_9n zM4$S-Z`Ibmq)X36@1@SIh6%yWhGmbl-cn6(9X=O$*dK4v!Q)lvleDACR|&3ccMIcc zUNRU2(LJ{Du3KfUq8sFM@-}b~xmh|-H zlKq2XxRL^)TFf;ete#HN5+vx2WP}u>Li=2X%AZi2jz^OI8298oWNY3~gww zSFbu*JrN)831m(pd}m!fs#_~^c9d3s%QELnQP_*9g}~Jj z{qQU!4f!Yg80!Se+VH-pfIXVpkMh7<95x6`=FbqCOrR;&>&mr`G;t@2BoVPn%yB}l zTlJ!|TUbmdc8gL+jWO%@gV%H1XFp{;UZe=54D6D7Amg-|DuhtaN`qiG5fjR+6z_0x z((|OEnw&SW03-5@yO+fdULiMx$Gi!9{EK5}oql@mg7YvWXZ5`l;P3;iTNIoaRBA<{ z(>DXC52~aAq`K0S+Z?z+2x%z+apg!w))PqhMyt0mewfsbWz!NWLO`xF%c4R_ooY%0SWxjOC`+`WWAmvm& z>`-JQmgG&D6VW@)*|0xccXdIIHK^55gebTkEQ~)G&glA)Tf}3EuHV)q%SSgZ=3K`R zn)Le*TZ6HCm`ZF(w{E-*@{oXL?a*p^Y+c-$BKLS^7w(`otQLStqz5NTj}}}L^wCre zV}JfrDWZ%c5mt35%Q|MB1AP)#C24!2B1*b+TP5L-I`#jcfh0~{(aLlpPp=f;fIZr3 zk(56Ca!rj+Q86iRzyWb+nv!flFFI#RN8wQ#{F33=ihehckpbzVBf;`k8pKreR4qP!>DW)y zttP?FD(jaQiqI-j*C{Y;>vL%1y+kHQs;zk;Y|!Zot&3H-Q}b%@z*rcf;4zHG5@3CV6_ckBD3Y-6{!CT_z%SCa=C$$nyC-%;^$_M&@D!>M8|)=-3lM#V3` z`f`m_IDk4L7RR>Cr~jt(lsX6TBsR==H(64RI$bzk(<-4(1dl7qGLIxJHL~S$UawV( z)jeGOub-aEX(?Ly7@e~bPSduXJ(H~CS6pE?Rg&1fBvh<#*1j-PtcuLUlb7JiDLtTH z&%w}{qkob}GpdFEjrS6^qHKkJP1G+znLJykn(NA(8ZM*7+=;z>LmKvnuaRO6d%mvb zCB@(CXCy8E>U7xqY+U^~*W3O#UULEdTO&?-3iBzh_!{AbrwR0*dbDp*?GrHeFpd6U z=}lATs(l$~X_-?Cqeuf`Yc2Bu_b{EH=J% z)-X=8$HfMn`rnmY&zg_?*PQpDUl$Z;{d*9{k`r2S=_N?G5i%Ta zr%2ffgyA(a$czLBylfmaU;uZOo)(ENHisxJ^QVmOZL@x3eUtM-tCD+;kf6+~|6rF^ zi7J_B(K(8enA(7McBa~KQN5tPmT`70((Q9yj4IS}bDjvW))^-DL&sJ2YyybKQ*P{$ z8f1i670-@GYRs9|{o>zyi*yB~eSd92oE>)_FRW3Qr=A$~OmHnv32f7tIGQIBwcx-# zf91#WcUrJz#JYd8mRR6V#ngskmXj1G0Qv(O0FhJFk_{AEQzDiq5oVdEn@J8vEt++Q^z){*d{$c~R;em(e}X!F>U-waHV z9-_9S&Kw~cVD*FrSh$g=yC}alK)@XI(R^xc@awF|Ing!)Y z^w?jrWVRk@+x&x;2Bg8b^{TY(PtjQ+S8NNfxnY)> zv#9&ZX8D4u`Xi!DKZLi^iB>>Lx^>$c?}R-|Bk@plD`y6jsbV-t@uV??zd5TUtRRNs86XoZr{j@PSSMfTGj=TF=|rhD+9rg}nQj|GT|bh|xV{y* ziSzC>otP6Es4|4R=DbPBs6devZt}s@N+#usC+zU1-j=T#_KuYu`6k;@dH1-_nbxig z+_z*sK|$?Ii-C?o#K54dD_@SQiX+>N`C?vZ4zpgvAY~oo%bRo6Xeig%~$O5`L=NihYXl2lk_66_HsU8 zfg7XPiinBMMTrJaykRPl^P7Vl7r)^$c|n}I;oZCc43MNE?4g(N{|E-DG)q-;sJyjT z@y;<^fzv?MXV;rUjqM|@pXj}mM!v7gJy%%tY!3=gJiM-TR@*Qtn~|O-Iqbe4G;!!^ zG}je;MkH?Q`K-xm?Q}aF>ROOSPLy;eKB4X(W2UqB)t`s{gi3I?=$9f->BX;K6tUM) z8NKuM9u@yrH!rvS|0~dE7GHeA!MEy|LjZG6ux~}kRExiSBoeVaPJLu$ ztoU$7{a+~Ytc#-i{MLfoywZjL5IfaN9euG8A!5YWKKNK0D|kNAoD{Iu^$Sqd6;z14Cp-}ORa294zzy;1_lkZAKS zjptMzx*o{j5Q)~k9hKo+BKAi0uE8@fOzyh8^>FJ?!lM@lSO8q3oqsiX2c}-Yje?p9)+>3-8 zoK);C-nyGR&;mvQ_fpe&8JZgngG6nOH$49)UYU~68k&~GA#eOflcuj79)`zmXhVj<*E zwO;IKaWn|8b2lFR!{N#D5;C^1-X=AsgHX)S1c*nkG=WtQ-E>@OkA$(zmlH+WZ3yZ| z8`ti`W!ZSYJ*z|`YM`X%DRs~h8j-ljZ9uknc2fJ`X96wKhLH@ zHK;(T1yT(zyK5fxY&p`f`1`$`WPz$L$W(JeKV81$H9afptsi=tSfvDtSM8!YJ5%I4 z%%ryZDl2;10%RGIy_WLLOJ}9X{m;@rXzp$WA-F_diHeo)6zx+kf_U0e9z}hEj&8UM zCB$Us#lxMtAi^QcYbg*9k^0a|)q@w%xpL93H=n-_-qck>;(NsL`~GOu*R8@cgz<-t zpj$*U1{%E6in~~I z4a#XUI)*b0#@h-UK_3-{D^Hfo76=Sie2##3Utd_pLJU7FIfX;Wk!rBZ&amD%dS_)O zDe<=RnA>wXSIq?-3pICC>$-Id`l&1MPnChNNo&7hyl+`awa%r)NO$*|8<$~c4a^W?OS&!b72fZ{3yW<0%9Ii?2OZ85K zRhq__#zmOabB%2bYp*u98u^yVb~^&8dO-_q?-U4Ky+_wXOdGVDTi@DRuqpGtf8)fw zWj$=MTTfuh_#v%}WpknNIk}__(2+lT_PN#)>lkpiyN|h0^oH!i|;6 zho&k&X4|#ZMdByJXL3vKz~4mA`Pj1$X+9xZsN5Vc)@)pu5y)$*eVNB}jQpX2rmvOS zee}DL4v7(I77F}Hyx(!YvO1&5G{2C4F68SDxT7*L=|GtMUV}52!gjCOs#QoE0jqF^ z<2yO(w%KG2!L{xd?G9q7TbL%O@WW5j1VarU%1Ya|9S`R^?nD(!m_DJ}X6;GN9gMCIR|u%tQ`{25U7eDBH9 zI*pF?sLRq+j3o6lF_X4Gd025Ty;&D@zGBB2U8mk>6q}^jLytCw%TW|fPekK`o zIn5j?p7G8X9v#V-4u2i~LCc*A9u1m4YD<7iN!9j6ZhkiF)`LI10WxsEMtxep>d1nF zs9w@av?*VOa&er5{OHkLxgZ8KI(FXMW(HQ#e=r~X{6k)lECf)Tk>gkz|Nb-%E9cXh z>|r01Tqj|Zn}IdgjEr;N&4$(F$xM4OFKICSqnzC({4qQgR;}3_%L^PAB8Oah^4$%+JJ@Ov~noeZD8`g&y2uA}f&7#BamTIu>XCAml*kch#? zNQxO@wZeC`@;YNf(Yby3tplpxX@*YdkVxg?;5Txiz%SzvuLM6*W2K1uZtGp)bcnyK zMSBBg=&#Z*?&H68EGf-wQq~eFeM`flUeUEkiK!}kg%bXPr50=t0fFjSWnBCX!eSp;JQdW zgwkJ)Dk?ZF!Gy)sx@QE4zA9^KbobWe9pZ2YjQ){FYZQUVyyfR=A1~kgq;&xO)W}9dqdM*p!+xIs1GYQwn3 z7i_O!-er!d<&6iEu4R|nRj$htsFz@ITtwSi+Qd&cP{vv@y?%Fqu~d9e5<5||xCE4} z7d3o6%%S(Vxf~uc`FI`$%D=K*NUgk{tT`joNaz7%Gi*l^gc~7@xhA|krz=iGmj0rb zBAlodd?!R>qk+@YtbDJ=xJ+f4pUx<%_0t#t&pYD2B?>Z}&4sD8f*cHzO=IuyGR?k+ zUzy>&GA+cQ3|#tMOPVdcav0$}jEZ<`Yxjl9(nu??21BC-U=gl{7;!65Nt0bY0ZCa*t!s3i zY4`3k5nt1s&LP~)@FhbelUQB8;qBPphUfMp%x?(`VKIGQNO37fwI2Fh$H1&FjjMPt zQX~CPonDEl{)@;W$jXOnJ7nr}X67^9WToo^yds+kF3$zR&f&%y(5pH`E`S?9ksi!{ zK8;=wuKqd|H%ax8px1jZ_EXbA#@E3fzkKT{GZ(Rrxka*4V$sMbtN^S4mRttl@5FI4 z765VrulPO4u2YLwaGIH8F(PRw@f-M!72qKGs-Lp{j(EY{F9hR|W~T6$mtdjV2=j+J zmA$;DeL3=!RQTC&^06%D+XC*-SKHYX^j@u9&BAs+>_ozMN&#^&^N=G-ztEO!%DbMZ z6uChj+H`(0ap72z0^8JZG8auUR=2FaSz4@m)@tDencs}We3S<5!>*hYHT2T(`5dvD z7n?%4x^W$*=g$mc6*q`m2y9@(w3r`Rah!lr6JE6m5EC;8$&FUO(f24?A93?6&53?2 zORCg`!&=ckh4ta1h?8vL-@@u_XQVusM%-WAb?v4SsZ9BcZtY=ii%i8vtve&i z4E1%o#~O$&!|JBY&qRFYLz^q)^K||}vjx$5NRnfmh=%4k2h7Qu%wb7kQ^YD4MY$0$G03KZwqo<8+)Zhw0>`vCNwQ`Iht z6%Ck9Hw|YQu0%-bX8RRYeM6#E|qf56Z5Vp86nx>f20XrU1V3^$x0SgPmL)764!UpIbeAN#&^>p2_XdECD-lzzp-=QYQrnqV+(H_=Zm zxHxHL>sJrYg}QUBQkfRBJtJg9O4*O2!~l*6s16BDErsi1@ToX%VOxA#8V6*5t~`(_ zJjL6U75mRQ1%S)cj7S431JA_hfuokhMC*z5(TxM;$KWG=c{4!mOgck1og;NqQhLOi zQAW1+@UR-z2;~;@(w|e%>Y1E94b;%`HU{ySVHs6WIBa93*T1{z+^M>@v&9}OsDyFl*{l}3(b%2;Hk^86!)|A8r;D7N9!NMf2OWh3eoBrYvMb^ zE?>4(1{dmmud>g-!6d4P6si;K%anno6!j3fOPwTEkGxxK7dl*9%;{Xy8^@J3`%Cz^ zZxDXt)?l_#$}0M^G|%U;>%q=+-W=G*DLY*6LglZbZ<^@r`?)Re*-MnFULHoq-H6Ah zfaT_ryoiaa`2P)vBGcmh2Tl8>)GGbyK5FLwpx~?M&xB7!Q4i&nzo}+-Z^|+Lg#(s` z_%A?MIRcpAaOArm6e#sq{P8$by*-tNyYUEp16!_DIpTCW?OSF3yy?YJP4){t5clWP z2{Jt$sc{PX?ajsO8O-N?H=YkDKrZBm<9MrEX!GJy$i{3WfZUP@rVd*u|6@7qtq*`; zu|)==1?LuA#2DA<$+y^Al$y!r>m^G+9)R8b{@Sr#>HHb3Ly#YRGdZnnzxD7#%#~0S za|<_Nx}?4vm`wMR@5lYFr%w5Px_l_IlZ=Gj+|8lCMK*ro1Y6=V_%#%1B_ym*{Z7Or zWqO9l8ats%qs&hJvss3e&iK*bk*TbOQtbm`M!R}2Z`_=?bn;jZ_>$5 zO{uiYx%SPk6}0{V@Ma`OU+`zP`Dn~z*fj_3I5f-Y!ClNX1cnQ)yxS2?SxIrF!vMnv zRNt7_y>%3g7sBE`^8AeIUYzM0T!J*t&~=ZV+|5S&&14;_UF-tkCY65W)e=oEqaSO? zr}>yB15bQ9uUb4X{r_Ik+ZnH3SROD`S`s>#2sSfb zzRpD6TGrdQz{c@6=n~K7vooO!m&N2qdXd?CG^tLictc$etqY?dd%J!nK6flqGGZws zMw{jdS9J;VzcdrbQgDV8OAE+(mb1ydB(WG&HP6l2vYBe}3NWOYb>BnO*w6!oddih; z-}cRlA;g=`?GfEr=DxjEEN^=OKuPxf{aPoB17{nCF(|3lhj{1jK+X}8Cu|VId71O%DA_OXdTrw01Swii8GEpyuZkW(2C8Vo! z!P%D7kv-pRWPM!v!*H|JGaOpwn%V6SeA7$msu@!8`GC< zh?D!va|tgn_b%gE0}hUnJQB1!zjf_M;oE7!DM?=~?&;30`dtsX7qvTH!zt}z?8 zg&i{mF3v(LKh{=8oUmMbxD0e5A+^jn0v{6GjXhaiiMI$p$Z5|W*rfv8>;gwY@pR9L z##n@xNyX?YG!}A7C1&?&$(Q5iHOYan4U1k8S(1eclB3yM*qm|Od`^qty$fy3cCJE^ z{6_}E!Nr1z;8x;1ROy9XE$~cGHAvGO`Mq;Dl>9)Pd`$!qaILl_{ci9hyogISPGdMh zr2sj~4Yrxg_a;4S1eyoew5`vP5U*!)zfN{{H-y)^BLoO{L?YOJ4j^Qz$ZfFVwp+V* zRCZEhPGwErw-{#k8Tz$sydM(J1vf?N4;iJoAPjS z?IHSP;t}*6LQ*)eAHUw)ChtDC`B@f)h7(cXLx!UQ9n^BL@+)vW>Tb*Ty2hoR&nD+C z5e^$(>Q|bn#iD)KOzM><`~y-dMH;w9R{8(AjcNQiKj61@dZ?-Lt~};!_Enu@)l1ek zOIqpA-JWb|MU8}Oltg)I?~=@Q`) z%B_ampZ+%S|S1m35i7QlHrets-xny_hGkeEZ zJaF`Lyr~EsIzlUy`u=C!aG;*qn^*A^?1sH2dJBH_Ri3JLlnN`;KPc;(QCCcoMt_#= z>_#Wvm&d zf#oZf*cED*(J#2?8wmo=Qb>TOTQ8#0a)XxF%LKm{{)>a8(LZYQjgL-j$XY)k9Gq6p zu;`s~;l+x(@k!#@t}va;kAvd3TodXgl;fDcLg^8F5r|=*&gwSaxrDq%-0*mS?Y%SUbC?&LohNnliY%+ijBR z&{?oB8bzp4MVI!UygP3GGNC@Kz}uyLHOTX-w-;a}Qbpst2VjBVX6+tra#U>OIz4yc z1x~wc(~IfEr00rCPryoTm`^L6QR|xlCx-(awQ(P ztU7_Uhr6NKm&Gq)2KQCOgCfJh*ej(ibjMqoN}I|ShdDkZ#nN7S+7KNElFd#)IcflG z^_R;%DC>(7Kkfy=rmnt@{K}xJp0s0ZO&c1+1gjHH7IY1&ZZjluy-h2@-@g`30mf;4 z7#+9?PB7jc&2cq$c5`b}H`!e(f&-5zx14f39Ig>=Wv6KrsPo35&a!2L+M$~H3Ct!$ z0peu@a8Kg!kp%n*xcY!MP+uD3<|SLjtkBetxB&Q}T7lWDTGcflT?YBIPBYTTX8H{8 zX0T1Mo5#6ExJJao_Tj@8-yxum&H7NN6oX7wj1_huYdU*6@aJ@|GqcWu#k%{^pSOg)7Q?z|dXJk9d1>6|X%iH(_l_w?$jpw1_2; zG51*djvZ)myvz2R2s((P@VN!o{z{Z82{^hP0hj$rw;NN!y0ops?WNL#+u+k}uFq&n z-YG$x&!3{O4@Tb#v!9{9s26+(4hvZ%t78s{I@Fda!D<9%*y=lBn3azAgGun%8}bV{ zr*M%Uc4L8rp)%IF1QY(NcTK86u%emp+^^p-NtfA&;y>Q_aN)>#w;~YwkG4UUxHSIh zphIua2L@?;?Li&Sbr4NI?U(J`yQ@UQShCCO7YK@Igscplae0@lFOP@OJcz}wNB>)F zaA8~SP=hN{f?9PzJA5**JC){TT)l{bq4@VF~w(PgHryn`EfW#kvb^kAI)Uf>i zdvNAge>Nb1c{#@E(&N5B`QhB}ABx{lxh(&^P_TOG<8AxbcIz2SpuzvH8$Or=Czc8N zo<;|KmgNsnew5pJY!&Dyt0DI-n!hnw(Y1X)?GQM2iV@%7x`7uVe(-hEgSA)3_rGO{ zmQMc(90lL|{vY5dNK|McH$TBr;2~y7Tb@Y^cl8CH1O~552UWe$BZb19GvySop`$B4 zB1a{X;SUkyp1-wkd-ZFSVF2pUglY2UwoBV7F?XBCf<2Xv1E^u_8Ld{alR1x1%safF zJ&r$@px`%UNF&dGa7AgA_$Z!or$NS6 z72nevSr2}^Z71N-e)OJTM$g&UEYwK7JV+fFQ_A%2z`a{g+NpvSLe@lt{{E;Nv9_C+ zqzs*o9qS3#u4c+7pXPogdB|R=vmhSsAT~yAA<6HA_&n03 znKyA?w>io#)v@(7x{q~Q!&UP2mITHqC`9WpxH$8zcPfs24n~d{bPQ9tI|mw(pb<>< zMT#SVttr>Io_MH-pyQbgOwfI|zI@X}Mr*EDL|4YP(=)PMbB=!>tgQZdVCogb$R~Wd z{KJ+J#VQMH=A_EuGdd zUpz+)&wlcYqq$PimpjN>0(JmuxSXKQUx-8g6|~xn!l16qL4UVMU*@V|1#C)3rOnBj z<;h?0BdxI=`BiF24P>9Z4y9V9a!KPBVVxV+CHobr)h6TLA23v4`ON{5aTx}k_AcX} zW>b^Oz*zG6bNoT&lBjXsYdtUakC-rC%5?%71h-%MN|fz9FU1@v{So!PqQlv0`1^Kt@m zMFKTIduQ@-!JtVlC>_aHN-zk0#3#AWvDuD{RrL%oAF_E~?I{;}e3eoT!KRZb+KNB; zF!3qbpY9(D79*cg+mZt!*#*91)^J^^%OqCfG16=J>vCpg;WZ~w5%;f!HuL4lh|E?gZ7f-$hUVUZpJ6a8n(F#P}Xd4}A<4{Uu zlB)7&we`QF73VLfSJvqpkH9^d{J1@hSbHgK2`G12c5SztgHUSv2Rt771Q2q&BzRr? zPFOMZZour7eH}bz_^{)B4`?h75Bx@$|K)1d@+mTbjlp$mjv%V1N7msQLRI&l*c6#H? z$_=8HhkdOwv(T@ZPVj`Ylfj@DX(wJzETG9v1yc>98i74GEj``ZRP5!g4r5zP2AIIt z)P<$$<#L@^%N$*pRo!lXx5r{m8}Fx}Zw0T||1w-pcVJ&qAu}z0N#oA2?yf7fKv=ai zM1C%wEOUGN|Em7XP?4>o%93#S8pHY!%5gToPMuIkwP#4ddmD=vUcsVeWvS)~I4~k7 zj4u708JKH3GV&17tn? zw}s?acBU=Hm``iHs3U&N#g(ACvNPrI-%G#iMzJqWHWeXuFX*m{ zOt9{%=DctZsG{6}jX7eEDZRRYJEK*R(%a&b_rp{kzpAQr`^ZF9LCR`W5J_)aV;g>) zJlQU+Zb@}y_51zkV^X;h9|khqczD}XjJ}M2+0qK0VQ(5{ONWbDL@}XT9mn%w%g)p6 zhEalp4{d@pzbn{%n$1Q}nYi=nZbZ6M+keVSOH>xml3mp~R zAi82L_mbXUed60k*z`F?>w|bbob!nLyJ4-W*5rLX^V3`k;)xk6ypSLo3!&s)I5+-O z*w_+?hWNy%N^sQ_!mlRklz--o;cs676pJk;&Z8xMPtP@QShAWf#&!c<`tXsWW|5A7 z@^FP`UVM=+R|13U(lHZ=jr45agbA?a4wR241t5}Hrg`}v7^)Kk_hZ@3+h)(b1j?cu zQB4z6qXUn!Y;LRg_VXGr!K}-SfMye0R5GYV28qq?#D4s_AfuF2WqGQ?UO{VZCmv2n z4_|BY2#=?su`Q9J<;ojL;O{7%q0s3=;y+KMjlmegGM4S{9UbTRv~U)C(x87399yq4 zzR%<d*R#jo%7FMIQJ)$0<1Rvvg-LJVj~I%lZZ?fg3$CSeZ1^4ez3+C z*w*vg`*TpLM7HuiH0}EX>0f&QnFgNd56Giy zm(D8!MXyV$ekL&nIn0%+Hoej05a+9%C&K&IBdArv zY5DiBZY)vQv|xjoF12$W{CnlM^b0=2lODWM$u?eA-aSfb*$Q&&9|{s!v_g6NdXbA8-K-3DY*ef}&x< zUzQesO_Lvfj-9?AZM-{k9&5ni<$VGVuBZwpVG;&X;&fqROe4=-zYJZ92ht zVqz2DpSXUGmvI&fV%%~P&E^9A;N)L54)yl$&ES7?asQ!gK+DJUbcqfu=eqZ~x6FO< z7h)=nlV8hkE<_D zd%vCWliBKhz1)F{1D!#)P}&*Ps~gOLxTZFDfPA#^U|P(LdfU0zajnPjt4x#yFVFm= zR-8ChpP1Vw%;z5pkq(_*c|dHVzQ*wwN2^kG)zevgsTPMYmWNuf5E1Ly?s3`bTG2>i zoKXRxh>0ygo}uCF!nBY2T(>m=J6vhJ%m77&L`2}YbI{<*D_(aR+o?C7gw3;MHA65) z6$)>(SR{n-UOAwC))6~>BLS|iW9t_fH3G}IEGFzD`wiN~&Np{nj|s^Hz78&_K*si! z?%pJlH4gbz+mj|sm;k@|Hi0b_X{7=KOCCX!Q(YQAv5Tp%>Kr?{NTR8=z2fIzxc2x; z;r3NyYshwv&8{d%LqBO=c=Bk|YzmcQDL#3(&R7PVhi$3!-VBa~qSSPF`z!B5JQ!5T zTN8(5*(-m=pZFv%2Wr)hku}B_9=%-u$@z;-{m}UF9+?>2hzs%7u^T}cT#hM*# zRGC)tcwH$xW4&s=hfj3#lMlGYhy7k>McF}^PM=_GW_%;UIsx^v;z)R7sh@s7@>rbFAXq%D^vkN=9O-&Ce`aTYP2mgAdPTbjH^U{Bn|Bbm&6ki8k5ie|R@xpTA(a zVsDC-SwxMRKfjTjRTYXDD-S6T{;-U{fl5ZlK;ss|7j0cxspC`r_yGuRn11N{8s&UX;vEH|~RH_3+n^TuuE=fTJ6 zKGyMDb$Jd5J^N&;TCxhXe#g!vX%#|0_ZimzQEh6rvH-NCm=V~QpfLb^u+A_r_X3kW zp%lcx@(Ln+={tJ7^*G1=J^#dk!7@(#Mg0Lpqf`poUQnO9qo3f~!j=cuka{QCe4U}{ zPC})2QKgQw2@k8v5X3R84JDN+({%o^^!b|h#Epi|TW$YrN5=$#E;s@JKiwV<* zHw+Fb5X%#lcAiF-3OdeyO3*NI7a^lD?)}w#&SC82!W--LyRp1C1-t2thUEoQcn1D6 z>SoiD7sMXCf#SIE$f~z!D%ieJCV&NX>CxFUUr28Wke6?T60qz7IGbe;2pc@S2?hrI zpt$RwBJ;nj9hJtqh&W*%TONGnm#0kVF0u8dW&4A{Z+KFU{^E$|AB2)gX@De+~n6H zzanNF`46_5MYZC5a$MRhYP5HvTjD;J_ba}aSA2&V=I`jh%YIeG%Bk2T;<>>9{I8%) zlSr-YYRBi?t-)wd4b<1XvCGZ-#{&A`c*LRXWoE8Z{sL#0;#Q{6gkLE+^Pn2XwU<2K9fz`$IzUN#V>DRZAf(Mkpa%TXKDC5q0rI04u^`X!;CZ zH<;=Yb98$2qoPdpB~RTLQF$L3#Gf7eJQv#b{>C4CgDWmF zk;~Q?-u8nU`ENK$ivA-Oi|VZ7nzKT0aEpgKEhWqvy%4V zcr2@Fk(qU6Cs+TDHJejv%euTLq>9zi6hAZs(1^PgD+?2pz+H0YM3^=8_s&ee_>{_B z$wWdXX{(h&ChgsXB4FUG<5g6}5*(>{3OjMen9?n@IfsxuQL{j!7 zywpkEgp_&^dDGo&8AY5w4`@pz`_y45!(PurV=BFNLA^~i1osq5%ItU(EX>1hw(%FQiZ0W`@(jU9}rmE z6dxOO;@Tc&+~UI-)B-%R%Df;OX*J!0M7Zs225E<+Ly1^;Ho+r4BXPEQOfhUqYIqqh zq$q}|0n^rUFj~W9XJ7^a+-+=nu&*n6B5hTAD)SIWNfYCFW<+1LXuDzij+7R_sHDUk zI>6W9-ms3Q@olk)Cq5PKd7)EWvf6u{8hah-Wsq8%YSF%PzWw&nj z{!&Wj#RYzSVJ&C5M7pbntDV&{mbWQ;05b1S|Jd{lUxYbXuMhn={)~P+0Bg7tD2#lg zAQvdJ=q5cWRkHTRpjVGu_TujLvn^{o90*OAc zJ(`A>!G57F`|{H(FRy{MC5=x!z7wwZx7Nkt$@=Pq9pI6UJuIV-Wz?}z&hh$nIE_}P zuiT7)14HjffsvoB*fdxLL6+Njj z6%|jre*Ggr&_qK|_f23k*QRZW(a8)|ERnlUZjH29lYy0? z;}FHMLGcn{cA`zv2ux9LzLXsB!&W^gCOftWC)^$+Y;XqRn4gjZ1Br}1InZT?E3%s> z7zt;6BHIlwdZh^cVy9_xZL8euer&iU-lB8tduJ` zhyP3ncE*AYC-l==pl8d-dvHiwGgst76vce#ayAu5D+xQ{-l5bNe?tbPYJ;f&yna0h zcKtTR!?Vs&DPJv%Lj@O>@E=7ns-eC#FwW(# zYyJ|4FQ0>{uxDMKjA7Az+nQ|wLaE*;Xpxet4=`3^%&D)3Zo=)u5QJzlJ<;7=OLbK% zq=*2CtE9#=3r}UcTv><3=8V6p z5i?u5Qj{-~P5Js+RwR3FU2S1EI4;5fISQvW#}BCB5gUd9ibReDS&4QuO{~Qp+iCSsdhTCjojf>cp#@em+NzjmFkyJ0=@y zALs-t{QQA6xZfcq@h}p~@KIj}cmap{aSEQ4;$mfo{=6ih!l)|!&o`U+vs@f@t zm0%~8(ugg4uO`x2CY%R9Ear)`b#v%#jTDThE-p6Cjhey3Q;8$t6EkB4tWKFh{WnqS zK3bfcuwp2}X?RUnWO(D`RlRc3h2e-?$)G7dd$@n-%uGWfHb9bJjJG{tR9Yps%#>GaftPZB4uQ-bHGYU8ol2jfPiXJk@GCHMzIgA$i&6uoGjp&KflV|W{(#O~CNZy-?(Zc-5Mbu}1i?fVsc#(D4 z$KZq^O197B78#7cF^tCKVLHH6rXIRav?HG@++++COgnwuUjXMXBj=L{PC9ols$KZm zvIR(71s+d*tJO|BUHN^hR9x{J_7tD3uz@z+Dw*@Ub)Qc-idk@pMYn#A*p_Sxs*yGv z7QM2L`Ziiz;VsNIHNoW`2%ZQC;SWNr(NH9x|5s$>Sa67OZSlBW3o?lY{SW4*+W(A_ z%6gZZ{@01wO!fcjveW-hXZ$Et$@ERmDjwN?=WRw;A^&@nG#`7mR@k;G)&;ygEq(tC z-~3YPTekDNMJ5%mm$q62j=>jmb#wZW)@cfNwB^ceZ=0%@c@Q|R^ z($?(_-?m<`pFb^T%9E-#clYo7iImF)w2vZRoJQ?~ z(Eyow5M$w7@mAm6BR?<7W!?RxdSc(@dxq2OdKJd5e5)aG^M~GO#RVgqp|4L2ZtC`w znq{@Bdo@9+`Ysf|`1g2&QLm$W9$}Ga6PMEeQ20$$E=dNei4-@DMUXLq|4^<^svcIH zAp}V!5U1AnwTg9LmgRZ@(GTN9frAe-h&vq|z2koLhM{rbaJOo+@N?d=mlX9*U1yDU6;kVmJ%T>t8ZvQ?}dC4w7KoeC1+Xr22eeCg}L>6A8iISdn}CJ!p2-6?%eHVD(Y zkvZ;TecrW3dz_qPmYq*kGvcLknR8FiADPV_Q~mzF%E)q`%`1WBABxM*r-(gdsl6C_ zY4pvCH(q3Ih#6-&b^=y^D{>lX4eL(y!gM5YMV_Yb-$inm7Gpzzrmd? z1*(52O|1s|MmS`HjYnUf^?^^r74=&+pLbRY(!5fClG1#bP&k~c7USROD%^y`ly>)4Q*pquS#l$i2F;zI=e{Lj$mdVP_us? zjgPy3Xf$xf%EcYzF9a4vJ zbiR&{Ch&$LD3tLkhoOUuD8><(l*crI4m@`LN+u$k8*!R55+5w9b&j(@qglTk%Fznc z-$h49`d~h?TL1E16{B-(_7m< zr*oHBvFfx*lblzOWHpi$SWa<##5o+b()26c30>X z60BLt=8e7L-skj{R8#Kd;1~h_$^oIvZ(Zi)@+3lqXQJz`K?QVBO;ZdHb%j%z3@>pA zxJ5476>KCqG9<*P+`dgSUX=Fhdq1e*6X8ovJu%I{)hk;Nj{!V#zbQzH`@13IAi}(P zGq{>s`q|PKAA&DymK_E~D$PwtJlwBOnyv=A@2S70y3R+!%D_xnk(860+zb=AhYsR8 zLaw@OGOO`PjUvR^yuOT+S*f;A!C;#Kfjau+sPUjZy)r0-}$7b`UDzsmF?I8na@B7KPVb5g9upCga zE>!>?u7C$9b%!bHFpTE!eyAs zdWS1G8nM0a-h9>F5=#TVhw_Xw*rZ2+K0MRaZk;^cw<5!1F#TdTJg@c4iuc9SIP~=M zl6D3hNRicg29fkPRybRx4R`&WE6$oa8%aldqQCP3@1!}52axkHXe(p z`;Q_&H?QhU#4d6QGBV^D$Q_-~R|}6=Q5VD>`>cTSvyn$Lc3jea2vb&YI%xPpI0^5nKLj6Z+^5 zf3$}KFvc6~+nSK1dy6{I^N7i;W(#8?+C2|He|?9)mx*<>Gf9bHZA%r7FL9SmkK>#? z2G7~Q9t*dQiCy54z;{vtKdyuZZuOoSFC7$-gqqq2ip;8b)GT_A>mbEwI;kVNggi8g zvDd;~ZPmvxm;)~*g3~vb@`H)*k0tzB%9S|m-lBDgGm$OywV!$$ju0`l1W(&*~m2{MlpSwoW- z=5TEphAD*4{xq6in)j#jdetH^3{K#z_^p^cPM5z_D>&yA1rXH%UA}hfm_M3%cPhXi z%lamTF7eQgQxV%k;8DlzSD{{NnQWB1ootYfH5M*?2i8f=x3Qv6*k!-!=uE9I)s_)k zR=ODJqC&9r$KLR};B9jEVoGiGr!@kbDG8U%V$>B^oEndn1mx6H%dK%Q)vDM)B9BKs z>5erEq{t4n+2iRBFSV5Tz+F|e4tJGtJrI5BZ(4qjF!~GzEo%A zAaA@|Nj4syFfTcL(#Qz=jErZ#Qa}SPb0my%MqQT=QPey|QnFxObgWiGNeoZfhRvL^6(q0Kt9& zgJWIa2%t4DxXEWpoi$$YYHkhlbN=4M62MfB%O@YMoz^$M&h+9l9CqE$`_7$DacNA^ zX|`G8#IdZixNfVOUZTxIg|<>_*v=c!f&kb1H%Ec>oJEg>d;ffX9UL#Ue%CC;{S>p1 zwVd>K8R2!e;|#ZCod{B3mh0|# zBpL9{3ju$Jjq)*_%Hl?XpuJDrH;Xl6Y!Rg#_U@@dY*)=C%DE=sC37~HXN#{m*$=+C zwc62G!}g`5G&V|1=kA7PJGLX2!Sh2cJ=cu*Yq_C`z&z{wvi+WnL_OT+ zN?xGysH<>&Y>bm3WvJ5{dWq)9@qFvXr&!8$=rf7jmcbjRl`-_7ub|6-N4}lm@_6#> z%pbZyqyci(&?RGx=={h*BGz8SXie<+b=57rX%wQ;Zt4KZP# z$AY&Thdy&Q1T+E#ouI~w^s!B@&-PWScvO;q)Zdx2`LHJkB-*p2k4jzji#Vm04RHk; z%6bxQdL?$B^FB`sdkwYw8nT*^gv%=!jO;6xY$u=s<~mzpiE1^G@3MK*SjT{VJd2NT zbjC46qdSGKQkem?^e5=tI7v%=-SBs%X*#h$n)4AE@u^XON~MueDt8s*9*k~d*Zs}F zTi<~5C~G6? zhA+Go=fu*;&^X&V_!MbIx5Zsg>{7-nzA5T`;2h=W<+C~z-NH9iW_`XTLr{~KO`%^ zYIqS$y9;Yr+GAr()8$6GXYOJQO*fNRDXR%}2?Wklwn+MYTx@hnP>D-dBLr!BMM~&s zt=biARsygY`Y!@dWReebNA+1%1{leZ4lyQfIsQ6@v(IK|YeST8kfk^$e1co!PrZlba<4tJFhia)|IR+=+m<>D$H7rP z^VE)?^t8*UZS{)I@6GA?fKChJUc&Vh`-J-H=L^C5h=NezL?5_=&lFfWpIAtfo}&}3pe|mNP zkkp#Xz*)(f75;3SOjMV6aSv6S9>pP)6p=J6Uf!NDckF3ef-hH zJHiem8ebh64{4_{5984pN#l1IO{K4W@L4RQ>4GyQM^QnS?Bv7eK6^O@r3ifp7%b%N zzk@p|!W6=$iF7G$x)Ojyzic%X(aEb-8x3opN{j!Q~{TBTGGVb7@zyLv&E zcj*SMCm}FzM?!K7x|13tu1&i`p{qg4OO~oC9LAcHa2OWU`4=DkU5e5QTZ4GBiC@05=g9-jQC#5}uvddB;$5h(w!mDTw^MmU(O`V8)0PUY2z)=2vF#UC#;RPZ>9fhy^aWmJssDUQ%_l^gGhSwsZje&R z>TcMUYY|Ut@jDhX>-8%Kfe_TAH@p3)un7kNA{Z#Dff0>3ffcJahXu9_?g$nYBRzKq zDQAUlhsDm*r26=^#!u~)Zf_r83)8}7-W2l@=$N3Flp2^TQ}RL0Uo8Dy!SZU7av~B7 z{EDZVvF9}I4#J_F!c85d;Ck9rfJk-26_#AmU^Nsb^)ipCXUoPk?5)6RcsK{ ztL4YdP*ikgOwo}Sx*r#(LHZAEL#f|J+Fg3_rM}qYBgG!`R@c`hW6xkx$yAomkM0q+ zoxkP%dl^?`P*)f@ma1rf)|mnsr@jgY$USpT!CSptcJIawd@1k5lvoa^nyZU*>{EF^ zY_O%TZVZRSEt$0{wsd*ERau3q5ku)ntX>oj3~OryXn22Rk!@dmuwCM0hjqk~gooUB zvZN44)@@lsW#*y_Rh~CYkm9!4l(r%d=7VSQ^_te~>*{imQd!Mn4f&VCPxoK7bE=7O z?V`lY0(q9+#$C=X{;}vtw0hWyMTH}A^i%!3D?g+~ZO;|12&&?l|7^{1-m6Lmuw+B4 z4rA)YynuSv(4wQrdaiXu4(016RiZaFtR5UStRp94!y?UtbmGn!;vR*dN^&iZ@$%Q2 zywx2FMjE~I;N0NBZtz2VlYxMXyd#s>eU?%nTuR-yX3Pjjm(k&i0;qnY8(WG}OL2D+Psw zmC-3F<(hVu?=T{SC!vQGeSSVS?)v0mgkPnDY)DWuzS_imGms;PWR;89n#Lk9DEhjz zz$#x|l#M3J(;9Hjw(U#}`#|BX#FLQ!Dw|6&FWG8jO@Uq06SA(T>5{?sOD@?9!W+qP zeK46H%1~i7Po~-0ewQq(Cp>hLJj){^i8{v>Pw?*I6G{Jb;do>V;@FmJY{w2erjvl` zydrnzLE_=Anf}(r^udA+wi)MuO$$$mje;X z8Sn5g@pi0!SqOSAMZG}%qaR$zq8ghs0FSp$fTPDmES~1_cq7mwP~yMmB^2eLuTHLh zI~U3q_)z77vSN4ImZjBZJ6ey?c;GV+keF?x<2G`|U3;jsmR{J34#Hq-n09u6El z&3J8Lv}S*1;;a5;5WwCy<4Ao?yOh_8_$J(OK4SYG7RSPU98O&eFNzHloi`7RPDw zQ)#}!Nk$PxgKYUgVVT2M&Lf`2KY*u2Ug%t;tv_^Dy;sQne9$TKd{$_Sy2UT@|Dlwy zGJONkB@i#q6F^OndP{otZpUpZ6@5>p3vi-ugrgR=)ZN>>UIc-)yd45zzQoU)GAaA-lHW2+V zsL)Hcc!~mF2I!oNDUk^0G%}nz250%4RdT*_|FV09;lLFB`xhmv5hDuTm*&7=0^kA8 zH=k&~#hgrR%2&|LZrEmYaj;Q*2h`ILDi15Muo0fnC&DjldDHIDf-5!nLlZ-XvyBwG z=o9YKww{Y&9xcd4gbQ(nCvc~)UQ_CZXP_uz(22Mkuh{U+JF0!C3pgBe_QhRnG(}7F z>sbJBrr*GArrguCspSpPa^zolFb)}dH&5D!C&yH|mktY+D7bx>bXfBf^EqT3Cf=~a z46$~3Xf387@F853wn zx}N2y9ue`Mu}|yAKCdQ`y~%RhpP{Q*XLBC465oo!-eQ=G`fSsaB7he*)VXoNS5Hn$ z_@f0JfT4kpAIa|8M6T#|5czyg7{PUhk}!SsW1WyRnhNu`rN}2FXfHlvkFQAeSI$S3 z;`YR!EZ@l@(*G>^g9n${A26S9P;>c2R+Zo-Mr8TWls$;m!9=O29Y;q?oxEA)zVY3n z1`YV~z*)*+z{s3DX&=mZ6cMsWn{rOegM)+A(U#c+?aIJUPa!_G&hHfVkfAp{Vll7) z3K3SUoYn2k*GqqyA<1333Y;RY=)nQrUCBvW25T&3#XJgwWm{3GMXRQ>-9&zcjW@FutAR3O*On;X-}Zvw{pOY1g( z;QFg3tDpT}7{$EH!jptQ&qjgP(((WE|F0qS&^s@vh`ueUXip*Idg_hGqt|9@q`23& z7#vh5L%p2D_nsO5P{MT#{E4FIj^KF*-Yvq$$(dQStYy~i5=>Xq6gxK@d$zd~XqH23 zfKHH1SnAdEweWOX5GAIixITg9^t75|y0cz`dhR)c&6tW){pacADJ?QjIRlWey*?x?5lnAWKUdyTtJLx05KRJoY-sSh=A1lAr5OT+F5$zZ?J}mC1XBH@Bk^N@p5+SB z%9<`@hVXp^xtl8I*Ilu1j$RRhmKHz$P*g;BdMv85Wi_Ev8%B#LOAuW;358J-b20z9 zO})}xBot|jt2;r^bW_nAvL78Ey*VfkL^hdMmB**nPFhY;0EalG*In%ak9EVo`fks? z-j@(onQIGIA}vcx*$TgaHMDLjOwMJeH6W3A8429_#a=IjUX%sde2{!{ZGX-n1w@tJlO-($4 z2dH5!ndTo)vv{I_mo_)moD7|No-6zF`}k?^?z4qh0kvFivTlZ~ta}Ir!#TZXhI}3V znr)d%Ow~O$9j6k$wmpTioO@yp`IE(aLS5kQ=i0{6uM$}tYQ-f;B7qWUbx6G=%!DDt zC|FR1kQoMY02qmA`?kQ1F+2XD)VAYnLPINlZv!ScYkpw_#|zZyl1W?Asts%u{6it; zr&~AqzIjv!Xi@IHvA-TMS=E;$E6ckLEv+CUcro%l$)RjbF*sK&#An94`v#nLr(vu* z+kb`WLCQV)?rX6@fCQ23F_4ts`zL!a&9_Q4_0qs zbnng7I7=HpAV{Tl*?N-_z?UbAzAOrhXr_wqnXWL>eDYaZ0d2jBu2v9^eMeCx>W%n( z`wzt@6#z@&b&=&Tx!9h~a9x_8`F@2@WS6R+Nc%||2oE_CNXYmu92KUKp4>sZ#jZI` zHEr?>Q!(*tEX~+4-C1!WwjFvq4wcE0_Sqo;lTP=WvF@AVqUSGtLC`iwzpxwolr$N& zDDf7m$4TQ}*g5pPzYqyR3JH?;42uV(21q+^kys$=T5*BF^G!oIK$j23L`4$CKOlBT zp>hR5x=ClcJ@zBP8NmmT}OF?^uVUFmId~U2r}d_9VF}&z(<{k-!Ew z(-;;@%%c9gA&T6SgjH*UJzaW(6VAF-G&RJ}jkZoIc%k`2-CKm^Xa6!XFev$X z8G)@NPFOR;!MENk!nuqmIPG0nn|&311_`#d$W%}`bjXY*{&QFZ*oN4yuu8N72l(Wi2j_GT?Flq`cPJfzS_R{ zo6ev@5#Y>^MT?@Dj^Q}v*9Ps?e?15(pOcSS`1-krtVuKPO}?q5@kk=X%*QLR18kP| zLCE;5<=SUjuFq}Jlq{9gd9@s)X{H9vfY6%makC~SP4?rSQ11(J)$W1vPugzwqnB(p z`xL7m2}$9mbdINiEnPXB*t_I66bLYD__**$B&E(%yx>>wpf{2C0EMp9vL9^|-uX1C zM7}hTkdoH*{0p;M(W;mGLXF=B+JI0wvYy7XzE-l79phy?&4iSx)|pLy_J1fS1isG+ z{pcMT(>rh5-gh_ew(+nU8A_SFV#9_=f>T2b0uA&?O36a%Zp3Tlja@dVd`!TJXH|UJ z!_I_&)IN3HvC4Jj0{Nz{XVRo@>u8E_`8dEJk>W=RyjRI^E|BbaxbT;38_7mBM5XKm z%760fCBg~QYJqS>quo$NA%_RKWGFO|e zQj=J|MCQqN2_Pc##TU4v2rzq=ded=2L){=gIZPvn%AaKpn1wwA;Dul?;=UI6If-4w z#n0IG72O5!0G5|luXI(<&`aGuud7SML0(uYx35aKa(!jIV_}Mrh#Y2kiuZO6W(QCb zFPg7N(&q~pr&j*Li^8t3*$Lhszp!v>RYlE7^QPrky`eP~_PYo)d_Hz^0Q+%8f z&y_9g`Mhza^qq)#yj7epxttXJ8X@i5UG+RdBjo)0khh2o7R_=X=uQWO&3Noi=TD6t z%i-V9k%4-I{XoOlv0k6kF4VpS@ZCMIF6a#^U4aS*E#qA;j5kLMRF@$z6QPw0;*hKN zDK+s2^kh9jo>>wSpwi&r8qRvotPEVL2Aoo#l1*#7n>dNF(qIhYLJ?Z&zl*a+R7Urm zG5isisl`|>O$K@tLf6y`b{I8mP%R(Xq35;ZAI~gs@rSW^5^q809x$b}GQ(;rl-eX4Ym+fS9p637& zCE(VStyZZAG_0H$h{C$ph4i{TP(O>V1~%(D(f^?&DlsLrS_@CfprFW2;qY=XXAImQ zjYhSwxB5l4{6EaSRa9Kvy0wc03GNQT2`+)cCAho0d*Lp@-66QU6b@BL;TnPkm%`m8 zSOOv6VV}15TI-y)+kgFEjMnOAUd>r!j@jSd`(u}WXpv=Ulovm4NmRyglK?A0?f&kl zx`m#Jg@^IOQ;a#wu; z_J;T16bH^)zCuJ!j^(AYT1=>GT0{$LGWw8p0#AG{Jyc_m->;UazVl`>f4izDpBF#7 z0SC6+BaI%jQ&~W;pXFK^?T#rOS>W7CC;3)D-}hia!N9oaZJQzx+o$Bck9Ve0=7Anu zN5qv6OuaG5|9CrW)Wkv^;c(fQw|LKF+WU#|JUGTJ^+yR`oqQ@dQ-ocj=|XWD=x!{_ zw1-TR3Ja<@`B=?voGbk4WY-nW_6~tuOMZzW0dMD}mN3v)`sj|9=E4}HlrYae*u&c) z_zlaZZ{XzE%Kkiis3c&@BBmr>b=$h58_?S@=%R}3>FgX z@{v;JOt1ZhImaTrQwQ6C=9|IeSn?!zr&IsHr4tL_`5PP$)m%}NckZt2BCXBT%ZDl- zbt~YHzGhxVj$s7zJgy>kL=x`D4z$VXICrZ$rBC`7Izh(MTng?<7lMZyBD}Vg`HSi0j{oJ_gq0j`r zuERoo`7dfAkV};4WM=c3a$?ARi9CcrCCQ%n+dVp}bYm{Abr)l_!l%3Rx6;S|Ag(2M z`|J%{;R#038L>b4lE2kPaVJEO?^xo#eafdR^*Klw$bM_1w5}_Q6|Kv5pbiJH@&&=b)x&Cw!B>{TK~&NjI@MX* z3oMh^AkCL9{M{}+U(-F@p=rmrlc*GJvjbp)U8Syr=`IHxhP9IsZgC*6k1^G>n$)-y zZ8|j4GSeSFleO}=iAs~4Mo}M+P#v1yZefh-UUpkjwRw-M9+>5aZMmF#MG&Y-5ywp5 z5JnM3eCml_$BKJ-z6x>TI+nHWzvY~`VIgYIm<`z5hi^qtuIDw(XyE>o# zTjW5RdX!dpS(TE^jPu8ARE-Ly6w=?xtlS3Pg9xcRVPp}Opj5Q+o> z51e<<-Env0Rqp9;8{r19MsfxxP;@3$p!7nh^Jqm#(X5QH5vd8;9dPzEHb*5aj?%&)=LA#Tv0gl>%qv8h0I$@+J-V32t6hbkHG}Ge1dH|d3vTh`6`2uS)uo(o!=we z#@yL&Us<^c*s@7mXivTz(m>Pfty3xJ6U*!4(7l8(dGX#?_{Z(-uRhX-eT1az$tO;y zgePykE-l9g`ubb0Z<^p~c!QGxuT1W=*6Ujw)^&~@n(@46aJ1 zNt{@RyPQ27dzvsZ+__@vxUSpKaxJ&tLMcBYqmcX)$G_Mit1zpSxS>}N;v+OMmhb(; z`N6K{^Du$&PX<-qgR*$&X5-%F`E+H%&{(hn?eH-t&t3Z^=B^4pxniD(YCI)F+ z{McT%fcWlE?;0W{ASfGeI>u#q-fn}T1p&i$V&zc5&Cnrh^b_qT25DUBy*ltAm2I`S z>qbZ$Kcg`vIrN?Hc5xZ&N@)vxH014|>7py3e+n|r7tPG7yo7UsJsm>YbaoNCo;K-v zT-9R&W!{)234Adv-o>~kZYo`qiNM+^RE~AqeLyAUtp}9PH@?beY|xura(;%b;afd5 zIzv_oQ1dCiES|+(rU`sPNob_!jtnre1FUY5`It>%bG14LJo>=I7*`Z%{9`u1#&vaG z2h2+?Le`9W_geawdNxltPj-7}eS5A0Itnt^qK^37hTZMBupuK^Q9JK7HWE+b8117M z${5$&_ZUCQ_YmSbr2~I{pPAdYIBvor>z_#WSOrsLjcH9Gl;oFuZ)}Cvk=B%+APjWS zt<5R!6YW)8Gx&Enp)RC`X)Wd{9kO_#@qbTD;cbROxWwW8KYuC5oZJ{2+HH7&EbZ>6 zF!^6Gi@J5%7p6k{PiwBO#FD93hwo1j>!ExsnRJ_0pc`4{#u#!2E}co*87N?RK(vE& zN+>?uV@gkLt-;-lS|JSSVuQgR#gFa{UkANoB70`wk8Y-HCZ3{HnFTo?fGk>6V|@iz z$+o=$$z&nZ{w3Zgg>u15DZhD+-|VOB+0t=D)#N`-n!xNC&lH)fGQA18yC2QmH zlVkJ(@q{mlFR4+sZ}T(A-kvOK?3;cPFr^}o5 zURI=lBR&Ub;<#wr%oY#-n!G}x3->3;u2dX7T^v3kZw;rOL=I6T;x>AS%JI&~qgIJyqKVZrCo>^oEDZoD7G778Rp7E?iK6+8=< znpq4<0HlR(=dfg}?HqUBYq%iqi@z$Dcc?E>De^j1`;BNBqUfS!yCRHRpN3c0a#i(j z*|6#kYQlQFBPb31Ln<}t$lZshFCeoKK;RXV$nEu2t-L_qafP4OK1y53c0$D5V9hO(PE!C5N#l(EGc zW%5a}t3f(lMUyL?cHW0EU2?$vPhKx3ar8jyvm{;oNK<8tz$2LsTm(5`_dR*bGRE*P zV*5woshX^W!}*PBG_PLv#6nDg{KDfkLiv2!Q<+e9DBUoG6sIwaXW<=5x(e@Hcur^v z(#oZd_{mC}(-mVE@7)a(f%to)ScI7Awc2rEnBYs$)=@PefNz?1noSN(xQlo$y9EDF z;p)nV6ajuc&xZ*nkIQDZQGTp3M>x3kiUN~)EBJj3LC4|cv8u74Cawcvp*^?-ZbRS! zk7pRJ-EbSrOQg?hYstL~Ak5ptDhA=$B?X!Oz)ngngSz{{-*|)f=2qM6LpeoFlQ2VP zv&!91L+F=v*U1woFTG&C8dc>XT>4t3B~KM*_dqtBw6hV4)(A;+tNtl@hcmIq$!2)- zqOiU<$T*HeA-14_u}u^eIXAmO^ADZzE862=1l>gfiN0MvmyJmy(Mq0&Ua0(3!PEw) zS$Rst!92PN$yI}h3}x;5-Chl?Kf@cVL{|xV=MBZXC_j&80>Ta8lFew4bp0uB5C>F4 zHuJe`n`EAef7UBx@V{;z;(ZowwM+ z7T;t#c#TblozoiRhq=}p?)Xn`uGCwlY%h7coQHaR=jG8187v>KTrS4#atRt@KwEzs z0>!G(s%nh#2m*LRgT$^S3jBk)jhZaPR=^#hedkJ?_Y^QP} z__f#geRMn%_K}0NClbTBEW#Nfi3!0T@v}-PzZc7nK$GSI=Ib#(@%T>IMl!>zn4^_4 zWYal2!}90g06c=PhPC`jNG7AA z?9(9rjRU7OKPb@c!01ZC3a2yqgg^J?ce-v;QRnM0&Nc`2TTA?{r*hG+=BZ%A_A|FG z2U;(KtTnaqt+0r_xL!LZaz9}W=|5H`3AGEgO{%5%aAPo}$qti7r%-M|5aCG(unub) z(k8IhF5kJEtFFryTc5|X%V95nogc#!qTnPe1bf|WDB_E9TLhF@_%M8pHtYgmb<)b( zRm9?_aAzu;P&{h1y|~IvVQg#`Y&<5!b7NLCxpv_lsLy{Qi^x#D(eT*9?ofgmul@bb zwIZ8KGXK=ll@&a^F1x_-4;(c^cm5!zC2P*%ba9k%reU7oEX`uv+Q8$bNtBR2M2idz zw_eJgbJ_Z9d5FQNMcP7{pU2AeD=L{)Kl{6ZcBe`8YU(>XWw8u$Inm1dZ}+p_p^E}Z zt+;!`OCXXxnz0{PvP}9gxxmd{aTryf0T2nw@bg(* zDMHQSLQS8$8hi)OeG`cL(iKL8ifjT?FwF#-`Q3A3-e!!IakrGj<05z4|gzePYQ`?^$H+sFi zB9o_D{l;0L_28yV(5Yb7wy@fg9vg+Vli$NCm#ESMdl5^>9e86a8H8T8n9zS_LAiPx zfn%mu6nZw@i1lHi%iTfu&^8e!59n4o?}%I?6+5ludKUN&yU@vNWubz40N#<}dm|qG z+Z!i1&*t$eDIBj=1as(4EBk}l{yK1az4_KbH@j~d`(v+tpy~OzQs+`aX5Y#uY>RVi zFeARN;G@2%)Uj(@_McNw>jt-9c8I0?+L2;3?3v1qE;qW#Q0L(6qRx9u8Y5=fB**aU zNUC+CgKwfKQD5r;G}qHk@ML>5Wh@X{_Vt_N{m1?ab$u|j8FEz#8K)9O{H z1l-4YtW2lDn=Y`=ot7T5g;KxAAryH|^h6Vt(q=b$Coa4?V>rpuqD8WW<`OgZsBbcH z9O*Q!=YyAd2rv)BAd_yCJvPm(}?Cj`x}y)|ah@jKe`!5VhWp zKc#LvVw)a@?5&lS7E$nRo$@?C5Ge@aW?NL(VG+s)a+Y<I;D7UfHDiIcNXCwd3L6 zWM4L@yI_x|U-mu9aFGASh&cLQ{3Z1^>j8g$bUVfF2gmK-2Kx~|I@}6IOXKFl>GZ6l zGqIoKp|ZyfSf;F|9Kpm!`aYbt7^-R($(A|k;VRJwpmde?2~`)7D!yr7AWXRhx=x{2 zB6#pv@)DsKU{SyxZ>0z|WLV|UGKZ~iE1A~pJs`L0EFWV%irW}N3YcRrr;vsSvw#cO z%3fB8VHDHZ1!4&6#I}7?txa?q>DJ+a6k<-??T#d5)#1*{&Z^?R&L)>yPa|pu$4_IK zZ1b}FcH3j@f}FyFx6UB;R*UmT#l|+6+XATx+`P z{8bspBb;C2+w(x`Dfo2Oog$9p$6w*^LAHi_)R>iYZr_j-@8l5pmM?WYP9iY$S{WvL ztc|IR3l>VDCnD__wa^?{8qxwu@Jc-;ANKv&d%}>Jd2b-n6P9K()Sml6=SFVpqN%%W z^Tj*gdAW36*RH|ZItrwQ#dmvnxL3Jm_L(@iGLX1UoNO7Z?2ct#N8acIJ1uFWsn9A~ z+4BMD*Ii>!b^vphf!+$CrUvz6hz(j8wc;t_cj4UBTaIl$a}Hu1DzW)veM#eo+uO%w z<>MufS&_O7^hE?+n~Dvfp6(Zhy9R59nSwRD{h8(v?n#CTt!abtovQ%hz(DcyX&pgM zb?PBE)e)|SPGZcA0~Z3NbFD&Wd_LVU6!Br0t{mmQD1?JK&kx_K*<`4($HnMiYWVp8 zpWfie3B+y)w$t9H=#;XhrP$$_!w#(WOge_r#Fi&K&ub;;uox%Jv z-Ba%5f1OSP5TM1 znOd^v9>#*Siu$zqn9*&X#i@axZeHiLyV_Oyfo5bo)oxdGecUXQV#0NQ+&ab`On$tx znxd%{j3O$hVCN!P1JKL8i!)2;QttIgC;IZlE}LKu#7A_U2yoy>(X%o}Rw(q%id`|# zUC^q>wWk`#Y7jDZoveu21p+E&kbPWbLblF0H$g6PZBs z!qCJ{zXzu`M|+Kv$vI5Ep)JS_ot`IavB040{uRl~dS1Xn(hLLWpb?yGDGNyk%a=O95$M z6H@ox;^eOCt|30j(@4b{VpM0wpwsjw0*Mc6szoVo8v&0k?6;e_98yUM?rW5)0=1yf z*f*2Q;zl8n;-row^=v##b%dt4Wa5qKy7MoH{JV$no4(Xp^=pxdylSxKQ&(u#dpZWP z(q%#Bawp~Kl;%V}s(oOm;T907!X?PVdIE)4lfby`1J8@jxhdgp)NYxNi`1Kq+wA^! zJrrojQ1qCU)=F=ACPiVk?KEE}ZE#A_tAWqy1Zz@nUcnH=6~BpisWl2x+IS|QxY&7W z&?QW&HUt@^MlHw?=yo~Jz4brf{@3~sIl5s}TS-{-ELF(b%p-sl z7dr!cr0>${g?`lKV^+xcqfQ{9n#_UtWr#NCOjW$3FMK+5D?;vIgMs9;ygsJV{hn4mQS`Z;s~|~k-3@iSUhU(g5RhZ?=a{S` z*iqsb0zY{O4FMsJ?%cbP$)bEw7WaaesB{A(_bHRwU8uoCCL*3V)h7Gbyu;{=R`VuZ zbIU$VI%leMeBN_34rY&~qji&_%~(L7N6Y5^1Jq@W0TZ3j1Ei$*Pi9p-T zy#6cXy? zbHfEN!H;g0S~B6@rR40m0h?-W9LEEWSBWI^?yy9=Fvb)uSDFD$W3y&2a`GKkm;vAT z^Ml50jrGCOa`dwiK0unXNOhI9uj;^-y|e3S{zxM*dWejaygjgy)^G6TIpHI%cl0p# z&=)f|5N8>DQVU;xH8SBaq{kyC0ON6|9pI<22NiN^ngkSjk>q}0PKpR145&}@0VwV# z$|K-Z0Tv*+?PeQ-u!0^SITBL(E;-t!ovNc~JL4uDMrJWht)_*15+x-~Y$9lnjmU++ zp$#zQ5?LZgn{QnaZeLdSuB?kQS1Xw zxUu_j?1uNS+tjzI*w{E79o-r-ZzVhDSyf{=Jb`pfumnG&a#$-}xtM>%G@S!Wl6ie# zLPH?cXa}pQko;4^7*ktsP^Tq75b{CE?O=7k8*fv!mX{{s8cq(+j~+bu4qX%U{bWFY z-!VJi+HThVk_$H*YZRqkeQzqk3q5MjnC@$nLg<7Lh!T=WVFStKN1}jdRDo;kB|NWx zkH>}{kO!BXbA+Fnsj55kYMmk4`&oi*??Qw4$5wtoz~lLfzMg|mtzX)&MEvHGHXjeV z4q`H3i;YUofEwP_T!p$O^^bVof$@Cljdk;}qFw->rGm&6m|0i}LxItzHl zE#8yZ-yMHjwo;MCIfY}iW}{{;rYE!BZiM*3-jF8?`ls{+yzaQNd4-hjw#+GWL{qOZ zjy$jI78i8UXwsc?>>l~C=?4l)Vp2zG*}Rc3gOaL3By#?a*yQ)7-K_HxSa7z6A@;G` z@6tWn*PpZz;0m)Yi=gn^EHPH~pT%AvQ!LMWJmXp4^t6*~M-I3npzfN#W2Pxq2qF7j zrThL#`x4a9qEUJVV*n?ZveA^1h{0--%_-@-4mcsRaho}z;tvDOOTGS;tiY**ISn4* zKKe=PL;5Mcy@YI%kW%o+a#V9G`BaR%DK%rWR=`AG%X;9a-;K%)q$hrc6bkqUCT13? zz_;Sy(f|!KTGnJb3CvQwTWvVpX+Jb3wDYp~aO>~rZ~cTd|GR-ZVm^yX(AQ>@!P?-K zh$<{P+&a0#rO-T$!|Jzzg)6^DxTnOHRXU?HRpwqd6mMJR!MAT(ygL(8FS2s(mb_dX zZS2R4JmCIjP|vG+tCCpp>u?si1k?jv?Ceur^h;}(+fkd8V~E%SGg4Jfz6(a!CysFQ z5o}>)F3LOA>YgXuE)%U2uEDAV`}YEMT5sLkzaq2yjAYP6-~8N|8+&q(&`t|XYu{Oq zPUCWGnvIgogKR2UK? zUnIH&kzbjJ3<|(t*A9L%3IUak0{ek1p68 z@_3K(u|>#akzXdc#=YkRJmj>dqsg7CToWm_EaN5#9`|hcZc-6l7qg2v=*B+;Mij{7 z0I)LEKQW1yd_ek_mcINigoO5LzQ+FnJMXLlVs8)T9_|lP+Dm5!&6}O^b6(E%acv6y zuPl1+h~#_2t#fGn)ZnuUr+@D*_y5Nn-3a>+=Ddo1Kjt%e@BRkSw(7I`lbrwCdCEld z_-*L_{~oP~@I+P9Zpj)C9c-?(DvTA*n1)BS1#4G(fa~9DF6R|!SelGQ4Vpe+I&>s$ zYYyKT(0z;5K`tOSlvII!S7p9;cnr>4(4uhI6wfks{_}9}Xinz)Ao&}pm$l?T{yh`o z4t6$k9`N~vvk^a{Yk;{xzuZeDE?$(`?~7SdP6~EU++H0cbGnd}DQ$=_lignocq?mA zJ-Qw*q|{ZQ_}df#`hKymmJs>Ey?0sYl!3$E5)XJO;<)T(M{bZ8`AhsW^JYqijcY`N zLV!_aUs(0v} zl&<=SmBN68&k`aY6!+4}r8XOS(FI6#k@?PBljQB8fO3cfax~<1BdEJeF17{yC{Dsv z+zFWUvKl1pH6_*i{L8iw#fqU_O5Pdvid4REU9*9^6f_Yvof6h=Az$oJPBphQ%EH+> z?&HFmlcdZ@+e!vz{#mQjy*gTsQC!-aqI&8cdc>6P7OB1mg`Q)%B=Gb4Tap=H-uMwp z^s;9oDx8M6C51M4Xkq39BmGiH@$)a4nXuRwM4tKTzC?XyzJoPDgjF44ovKbN&p zG7O#B+#_Ch+F@S`<8jB@PF*E5Nyx_xgHDMbg!`oKus@7z`94edQiytvJPIzOCqZ@= zvc})dZ=AajwQ`W%f59HrMzolx`xNieYo!j);vg~A%C=k~)@Bn&T%Y_pKH%w$p;Y`6 z1e39lDp-FWb9EUNGQ#mTkky9U`sF*zGFB8kH6N3`81 zewH)8+q}h5ql^liMF;(g*6=OPCSgemitJB0t}8hzGj zlktp&dp<>`xDwv=JXLP3dBITY-gGYqqBp5^3g<_9P#x3%ggQ(wfYHa>yI z^^G*2^QDzExY@go4D!j|V|>;?k9`ea@!4XKx2w=OTpobA$Jr)*!=_XC*&yh?kT~AC zPntoV#(ZF8?LoA$S#%9L6P3%3s6pIrVh$yU93S;XPwGCnVCE27m?nyOHxi@P(3sCK zcJrFrVKna$dEL}e6Ui62g~@n1*jFtWXY_QyPs`>{X5Cm#j&H9(&e@`PIrPMwXnbSS z&3Z(1O5O&L3l(kH-*OfCgQC_$C`=GF_WJjc-`(+3>*DW()WwCijYkF#@ub^#PEZ-D zQ(g?EL6n(-^s8yfH58*Zg#bbMZUyTDo&eOrR3vB5JKuS;fg;D<5h2S>?!p;P{~n%H z7=lwqoybobvCrAz-JucBN*W@#-n*Oi`^ZRX8D6XfR_qJS)yc2bQrSZ*$I}j0P9##; zKz>UUPONcs3wb8^Z)9J`);N8P2mgVK_P6^7PCD>fNp^r8K|2L?~b#h02 z_KH33zAp9;O$Xa8Zba9Pd!j4GfbncS1A-4@LSwzPy;C$7T#|QzQtO7hHpd%&*ez6- zQCAn8>+S!*1>5P$a`M#&jjp|^MwC95o~R@D_Is|EP`X2M%-j&5jQYCegUwbu>e65_WR?nOChq8QX%YCff8fMdvyT6=^VXguSX>B=OUVN^OD!Ez42`m(*?!*j zTblv_f6_PxKU2*zmTkquR0iFB=pr~$_K|OFo~Nyq-o078v+dyFa)?UQX(kuvyM?rY z_;vz!R{U(-!7yd2qZtV~A^?RS1twEdD%kDDDW*22_B(!^=Z2pB`joe@04e!U!7CR6@V}Ir1>ip3(cu9Y5A(5l)wO=YGdk z*@d=1ndo82$3%mRn<1_Y0h3KbGS?vuz}#IkT+aZJLJN+6?n}9nnJ13a*!HbwPqWe67FPJI5vt(LU#4&nW<=;L|(1>`AuW)X9pn8a&3X5i#~6NaD|u{9`Zkv(76Kp z^>B{loJ)wLq53%6&!tR%yC8OC2NR;CgN+pr=?>;M-Zt%clBxPRW#PYsa5>?dsA#$7*FRP)vs81T#`&=}GM%GS-92|C z_2+a48;>7<9`(JNpNfdn|J9jgGTI^1O&Mu#)^zen?*(?P9vi&!nR0>Li@Ue&q;gbx zD~t|_NPSb*jcA`v?d*al0--7f{2EC4VUZcpaIqfzz>Fd`u=}^Stwz6^umy~@H$C!X zpg}iIxuB}#E%7c?TTZo!TNg^jGm_e}bQ((%eTckGq<}h{^bzJdG}$KZspAq?^AFrI zfD)=xTzSf);1F846*q}r?R7C01=x8kI{!vFiw%b@?;7;uG&7@1bLE9Vbu=!8bPB zhiCSTm{Xc&3Ymw220a&fLH0|v8b764;REL8dtca+l7VbFo4y{%6xmdIO&bMv6t3c) zyCH@>QzzV~U%Sm$5s@=6_cZRO$-_vg})AkRG-4ky=zy zZFva%J(802f8NCUG*;Fm$uk?vMKsrfHPI4hbfqGbI71)qzPbJG%S$zfwQ{z4*o#?o z4fAFTeUOmHESAass7099Hk}t7*-xc`8~>Qwc|Q{(d%$^m1z@D)h(_#pRjR4*7u5Q~Y;becMvyme?)t@n!u_onn}EE-Su_ zF;<|fV zibbT+Hqtc@!(;EZj~S#STA`i(AHOX5D436inZTKzu$oR?4kk9FQ)EdY!JLdHKK;DO zzX>Av31(s1Z4g+%61NWbO<>zAL=y+q#_=Cg-{S4BgU>dM$Zn;(DWNGs!=UoX!MbHw zz%#7yV zSx#nx5HGef0Qj*eke2AzWyfx3Fa}3Mx`# zb#`rCXp|J(!ou_LtmX$>L7$fS&dVl~D6P(ezB({=WZ8Um6)pAnM!WYj(MDAKM^*GB zM{DmVepEwdD3S>CDr^z56(4 z=^eXOkkNu50~MvPicUe|lmGliGVwHay-d9WZ0`g!lXsVHBAT!qDP{NTc4G}*j-FV} ztoPI_s^n|TEng;%NKGa9(6R({`KL@DHG0oFp`tjRgyyr@#!GxK$$N)ihV~|I|!ZzX$wrW zo|VP3>O*SYg0`{$wd&&Ro>RG>-e?*zx>x@$U2%K6Tm4}(*Ow+Pp)(zFqxuxS_uU`1 zNj{J}7Hf}=hbWc4-iF;mY9CC74l>OC!velEf4Mg0r8d@NL>Zi);iGU&xH?vHB9b;O z5t_k(Cpn>^70;p5@gEnco?@ps=g4aNtpKbQeH6y6^^=upaOJ%X?bS`(_-b*oKb{#! zW@^#v)T;MfoOC5}%s*RRJR|k(dVCgs=y`{5%r-}&H%LiIf0mqS=SLr(`>~e6Y*yNz z_|>qyE1Qla0qf1=6b89gPn-y@z}5LfuzV8MVvKHnitD+qk}jfGwz-zTIEtZ9Lr#s4 zmVz(ch)48d+Vswg(Ng5i8}>)P?LyOhCUNSUrV*oA5>2~%M?SqaH8xM+T@aLrN@okI@YErkRrF8q zx+dpc8|h6Q97=x-iK^JO=K$TZxf)m&d~B>suZ0XnU%c0z)=t&%pPT_}IP6pI+-_#c zj*Td^xO-)^_PE+)+Uh8bVqsALr*>9V@-@+Z)SY_0cpJIc3kwU`ce1!$9Elykv?6n3 z_nF3XxHDF3n+lyF*;E$b(4&)Ro85(e10)CVLjIQiYe=&~)X1}A>#+P$hJdV;^;NmG zYBa;Vvbe5*v4di~JS#hIxK~YPYPBbDGa%!$u=Fg$qypR4FI|o)9e7 zQn4{#BcHpJ6A{g|z_sR3AnNE)WfZ%h((%5OXo!Y+6jz!GVS**Yz5rfF+r!YA=sVy` zV2H656S|@8mJu=@>Guv>ggq8|px!>~~-hQ8K=O6bjZy)DG zY6~7MJ{*tbW7*<_!w`uo$Ex+-YNzQmIiaErU4O9c);CrEub-uz52&wEapCY4vkc&V zr*}fK+b)n|AKxhTmK3-#oE<0f>$2U(m)wVn$w}!sbS|A}78RKaJlYdFIs!`+o3?!U zmQ0Cu<85ARhA#Wf7pFOA?OT?X2Q0I5$IikA86LxKMZ<6pMe8JAmV%1CT?p*VvW3{J zn3moM7vypUCG!JPApzzR9FAg-{j5#`t;Z~);FGLAa14j;q%8}H2{2tLe&8U~t2( z-RFx{>wz;`H7!y-N)W6D*nY_aD&kq+5^uk^iApLEq4CF1!;B+h6NRrP=`@;=?wkT7 zv(As!?yMML-kwELTYjwjcvW?%8YWOoY$@_Sz=?dFZk-#cYEQio^$_>1&OWOM!9&Dh zA)Wiw8{fw@?PJLso`AYMemb<7O}L6C10QMkq}83Ilejt;EQbh9$OBiDNlf3f+vN#@ zM3ssi=NrGfy~d#LM6<0rP5_4?J_K=~;3_(Iy7mf1=`xr-ZEkv9qr#|;ZfOM^@V@5} zU3IPRvr-dof8(~#+I-f>viQ2lH!bx)=LG-r``?8xOY^w=!5^LtdHm5^;qUB;+efGP z-Z-^q)^y_x2!yrV7mOX}9Z)76)F+iyk4kGrQ{^=-u?K7No@jcS>kK_gg^ zio9UMB;k>~kOBmTAR{VyW>Zy=uK}a_*u2-HWh-pbdgwdkY|_*rKbPl^CX<#^b3y1p zII8Y{Oa-juSww58{Fw4ix`>m+3{z=%7{QdXeIlGg>}E6oU-n1mvp`B7Lb73joQag_ z{1%n}neodWjJ?6~lvww2j=WpmqH|Ui8UBNJ)?yrFVhW6d*6A1yN@vb80cm^XMl?TM zhz8@xCzd5*+SbG&c6+=+A)&t0Mr)8o$h0tp!A8%kYeR*C}g%h_ZOD50_JK2>4r&1Vf2bqOT#E5n4UpEexY#5 zg`mn;gTjp=@u*F9$~burWbPww(~1AiA}0wPedF?B_>%u)Rj6Tu`yQ$S<5HPFZnJWM z?!;#`u#C>9@14bOn^Ov^36QC6gT)8bUXkw>uB%@+^7~^~`7A$lem}MjRG+2?0||sX zv%AJ@+`(qJh=^zR1IPBEw!==NV$sOVP%HNCJ?P~lzV6F}0kHW<&KjwOxZKzkcS0TM zc;u6A+dQXGM3MY%nWL`ioN1f$u!HAg0v(#gAGbei{J$R)ftFn#e5yn?6g(6+xsZAa z6BpdKl3DxR;0>&L021*;`8N7S7`qAjW5fDB3o+&Bl0%;y!xtrFBNIn>As_S93%$~W zagF&d8D{g*%l)U*{)uw=G%C&09_6tPkXKs~+Zvu~$+{ zi5zp6Ha-JzpPse{wNa;Lw`Xl9;#$@J#a#H;C}zoraZ$^xJbUrkY&&86WlTkgxoK|l zESU3pbpLgqF(2P?@_(f)s5bnsa~bpfUZRfftGza^FBwW(u71kEh!E5Q?kA-;M@pJ5 zBM36sAE`?6@>b0s_YH(^$T|Ea`r7XasbitU&;QHFvMjeyZnS`tT!bSSnvS*cE zbah_WwshDPHB(wVe=etSGm9MI7Zdoy_WHKG?{(h-^RC*Q*+Q5;v-OqAbgeyVo`cQD zQa*^cCe9ii1%Zmt>W*mBSMTZ7F?Nf26jKNa;Oq7A^s6FRn6^u4=!N6Us4%8{HbD9_ z<3R_|?MLV^x9(4DpQy?GhCq%$tnQ7ak$OwL19bK-D!#sr-MaIYYTeSCE~mR!W8JTy zgkT}%(D&goC6wovQ?`^}^NuMa9P4o)oC(G$Ln@%Vp3byB=wuA zK7*^xaaAoM^7rEP5xlqgd(u7v&D$DrL#wOR1AZTGn@&%u$**<=G zJdo;_QnmbH`fc5U!{=>g9Qf>lVZKUdVLF+^RwpTG&;h3Zj~~;+B05e}p`h45(%jn9 zwBL{cjp&7S7%Q2R?;_+@8D`A_&4xj(5OdpV(>#v419@oJ60LSFJZ0+RQ*;+ol>ROy zLu?Bt%lp)9yZckTZ}$qqJQn++myL`3{Gth1hNW**0Md$GXPx^R4W+ym6WB|oz_7tmoIt+6Iwl(5?zX*3zoq67a zvwN;ySG!Sg{v>N%?4KOU&P#g67AEMer_B9@_lQB({o8djbZi4@zD!5i1$EzTqfm`+ zM2*|jPsG#f3+LDBV=kitPAR}F8Vs!a+(tc}LIqPUc~IbRB$eE@GMYW)xzKs|e5A%T zru7I+26n^*9DT^4?f=$X{VP5<_|5(A91%>YiPi#zTyb=0=Aov5_&QphNF)X0Gc zGero&q?>Dj;^L@l(Dj_u{iSpEXv)$Xu)LXJ3;s0oF6zNqEOls4pXz%=P7X`^^l<%jB5HRWCC93r=;fp2=&=jvbPrE2TbppswNc5rG)D zA_q_$k$~~d@OnkE#hJN6$71s+{M_^w7|?zQ))|$(rVNphaTD5O^{yPF9^16--q;?K zlT-i2nD+Epgs`vO65sgtvuWV&ACwgCEFs`Qn|#j8dPtl) zFilnCgCQKBlMn-6Of%!8i^@Z48qvJs;miXCST0RKqP=IO6blC2~%K1a!k4)atBzT-Jr_D=Ra(ExO$F0j$JBk>=E*8o=7shxycz!)~ag z>4~;bT;{^uDGA|rOXv#l!~cJ{d#j+hzBm0BLV)1z?(Wh!!JPzm2u=fyyM^HHZVB!V zO=H2`T^e_H3zF|)rfTLlQ#I#Yod4XM(^XyTX6@d4uZ!M$z3=mUo|A3msHCqs?kyxV zU)etz-KB~y_>)7*!+s%<{pyFEm}vGpL{rc8ne=y&aOQcO%t#yS*dN%n?`MM?{OPfr zVDs$W-67Vx`&^e=3-6}0GDz8iObUG(I}N5+OiTg;ixTUNB}VMBZK|LSx;^0*Yb*Ad zvomq8(j$m}nU9W9!s<|b*;kfVIe55I58NVaHbFlG^c?8Vt0k$g5masp(o?sV#EV%p zOI4G5*cdpuQ|D|d+)jkbB1sr{4~|Ge%uW0;3{9eP$Ovvy###J4a_=QvQz!3~CPphS zfn}2Kf$P3Mfb@TwZRd8cHCN2~e1+m?Y&F}P*UyBbGWZP|bYJopWtJ_s+Z>|JLNl3a zlMl+6N6}kF0A{M!H-eQ=X)V{IdEXr6+z#kMQ!0N$C7iS?hw;OUQ|Hi8uvgPiqI(hm zmHuVocS4~02R`_kyF;G?_gSX}jS<)zyWy9KHj`2hQ^8?%6nQKsxLv66klW9GbZ949 z<^FKB>Ui?n2aD%M^J0Y~^Xy^ifFk174!`C-NBMGV?CbD@=9AbV>Mz|dsYaNGuxf>l zKDV=h*kh|=3X<2MAhxcx#r@%nvT#JSnk%_dwGZq*jj!a)FOAW!L-mY$#bA=BiqDQw zx8zBqEe18aFKMIwZ(4Cpi)S#(?zS{q6ets8%GE)`KH5uh3J1G!w?vlvSaeo1rD}JZ z+lczy8Jr$>Y%10bh_uw|_fZD5cd4z}2da>o&T*xSO0<)|M^BjoPU(3jvqGvp=w)}2 zkVyQR=f`;QU6!+SoJX1dJdT2YV0PaL%4i7L z#fMBxyK0Q%__F!+1$dBDhEnxQbz~2BgqytT8M@6*Q6DFBn8Zqs0eH7)#@D|%wn|7Q z39aUM`?-@S(%E#)K1=D{Avih)9j~>Y5e5YHo zvkb839`G=?&kN07@P~}~>tS2wr#}dco6)_$|By~>uJ_g3)Yh(vw#xp)!W~fqJCR%JvCyY`##i`-#qyjF^wUg-JqUlDtJrWw)BBJ z1tIEt!Dk~5oOWw%#O^>NiWSXMvU{(m6IZNN!WsQkS`vFd{5~H&G}Yx&id~KF3u6wi z`c`n7dGPHwXz^gk_`~fkNhdeUP>N>2Xl3ZZ{yIr;I*kpHV2v=18##*48ue`ItPQi) zapz#s5Z)N@IpwE9ej;}pEeZ}>4G-1V@PR{OMACn#*NRJfo^$rkPI+j&xh}r2t?s+1=w>wcU z*4kcB8M0?v5K3hNXcY`t*Rd*)&k6YfyNxDuh>g}uEYH<182gnCIenj8F(h3pM`pi> z{R0z1NmmKIX(*YGVPLD9chN)bboY-m3*eVt7}j-4S3D9G5vS7cK05(;8YkO#lPe`;E+tnuROF-Zi()`oig)!J&`u zY_50Ix1J;f28pav^Nf(*;+{^2D6vR*h1yr^u~PArY2(#ch3=8rDt{>e_x7FT_4j0| zRfF%UAMR(a$vbkfl2i_BwStpv!zU@)d2^$U_)E)X6*QiH7dW%j+WyI zp|A@MQ`X?P5<=Py&+$3!;<2cT+1U3^idlI5xE7&xNM!PEu<|Fc!v3vJAyaG0igI*B zHgo5s|F`2hwHm63yBM*>Bh6^%<)7w8%O8ZXS=Cl)K72(tB^Pwo|9+?1IP@FzVbdY0 zg0-DAAwq=e(rvIk+C!za6MZEuZ2ux5SDNptq1uWE_2dBvF(9Le0O3R0sWq~ZbpGqyg^2Kg}b$CrX(i?~SY`@m9?#A+4OrBNn3(FW=%L!TD_OuNTuB}k*7Vz-NmABv# z0%feVVJxWW&~1|XPwh2nSUO1=!vu)sVfpTV>6-M}KT#l?jioRVhK&x4O4Ch*E602i zILMJu)53Dql$pTc8*8@h?k&fzutEs7?Gr}rbv~@VQ2GHIro6pc(7^^7qYOh15lWTL zwpY^mpyrO}F0k`4W&GWpO5<%0h&;dd16s!HBv;I5fKpds|T?(nG*D-vP5=G2iOi% z-~Og0!T#a-uMiX|vtMVm@PNjV2iI`dtog&tgu6eF(3r6(fzgw1*?G77OvND06kZ`A z+*mm}>Z!ET`d366n9oh5!jO+7k?SiEu811@wKQOpee#9j2T4V@g=G3hfKsx&7d2zv zhmUuj!3*Y~M=W~(vF4&n#KLhlvN}}**T4)lM?hL9Vh&Ke%~Rkp+feBiwUyc+&X6tF z=nu>ohQgxsUKk9CeV!Z|>JMc@XC&07_ezu*ir8ea8586K^Y)(49|V-x&H0k?RC^+e zww04IsEQD0&hTTunKWZ{g_Rcf$`wCB^vsDYqV1}2T2aFbHgzl0A!!0fB2NGAp6xYc znEb~f%3vbzV%YC!4e} zUp14LMc;_4(jjr0=x1F~H`*zyAV#7NLxv9Ayflwhmtvev9=ivPr4w@2kYpFKbqNtd zLNI=V_e1*VZ`rxoLrNo&4CYs@o1GyvBAu*if))nkN~r;vi2+gj3mS1Ia2oq0_9? zBf=y1a zpL+=e9vn2BCu7MC&3@alr?BXoE>O+1OLk#Zc4+8N14X-F(=nQ+1k_{-oa|NS*-##p zG<)p$N86w5MjohS10nLKa%^*9p3r!8&T5V@V!MhTIsWQ}63^l_Qnx2(*naAW`?=Fid;FqE+7|N4YT z>0^E&W{bb#u<0!NNHEklHDky>aoc;Ca?4gRr#6Z0(s9 z$d*ZRur=(Gq@GSU4?=R&a{AIC;IVcDPWtRlbwerdV0sHmere%Bh0k}e%oY{Y9auvR z{z+SY!c7R5byVw?#s==ClK#7xhBZ@2{9|X}2$wyfHknp+EV!P_s8*|pvRz-q?Y`xO zIb^(cVfYCvR!H`v@1=p$dg4^2?g>D}TY-BaVJ{-nXtf=eGeJV!`wh?gm<`-5*LD1y2uYIzT@D`(?JP_;>Ahv?t^_<&qq7>;#5d5%%^!}M!6 z&c(Tbap;FfvFU+Do8GJ!G$Hx9SOaaYy6N9DB=PcbHbP_W-Cy@nO&XPP+*ZnT8T7PH z<;BJ1hZJ03WmdYM6luAfQFw^HJpFM$5Ym)m7Y-Y_;*Bx=a7e!{rkU}BkXOF*i+g4` z5f)7+Tav#)#)~&{^bP!w+GhgeZ_IgC9{z6^7tzBoDA!MN)+^bvx$yPcTtn;J6z`n_ zVQm!TtyAe2_cnTlR7SniNd-|yX~J{P-4eEA4Qf6h(MNcr_Gn4J4BxY$|Ci#or;hI(7IXg{cwf(7^*{PE+)n<-Am>GN;Tb#MnhO>l#ADvh zgU67;Wx!QrAB9`jwIH6EZTo-Y-50z9jvOB2oecbikEPbh{_O?QT`Bk7wITg)UwvzK zDS5)O_MQr#h2r*17fY2_bp?pK#$vUaf!TE_FfPw~?kzINnYBjx${iZ{G6rDSLd zS^S%cw8J_xRX+snfCKSH(w=2+p3Uj zj8`=0wsk&ASq{gs$e$LGlP7Nd3`?oAagT1K9g5HV>X%qJ&RdJG9?)oE)ynxHX@^uM zP0#iFkiruT*1J%ndrxPKnxn_yiZzUAm2LyKVEw*<3g_WZ7sz7HVa2)?>u7R3>`>hI zs@Yd7aOtGuj(ni2QhwglW_)zjfuBp-z#c}l;_MW$6^PMICT^~9Oq@Q*`vfk_`({+x>l8NVm8b+O{SlTP5R-CS9!`_H!B=SmgrN^|{hq+pz(KqE_JRhtD{$g?n?PDvehY{~ws6*EE)sED!ce{i5829I~$tGEc(dM#Ocid=rk4z~_B( zq~~KhbMTs8q=VHwuwLIm$kzGRo)@ue>;lMR>%y^UFR512O6+IKMvul%`VUN0`6wWj z7p~)qo-ckxSzrz?exIHpN&z(2I3>4(J<&K~GV%}1Mzbob$XNsJPo_i@DsZc8%U}Zk zaHr2kAJ6&4lf7`J4Trs*rlAQY3H=hf#Ct`5>cx&xa8F4>!~(s((;R_UNGVX1rC^Q# zLj(jM%*%SVb8E@u8vRi8n*jdGkAgWJydBAJCM>*C_qorL#YsOeBi%QLe+H!!eTqeAK@?D(D?b{E)sQ{Fe1O))gMPR{QiWIt`8mp0fRR&qj)z2?^Q zouM<*`KB^+j?ni0o+{+9g>JznYQ8LdEXdW!*C*^b$-R*-rDHgylW+aC^P_gZ|^A< z?s}uO?*e$7ga}c#b+y@0KIucpu4h#a?(q?ZN|s5m1C)a;T2@;PrYpJ*4TK2us_O^w zZu0D27D%f!JjDkDnOOBb_-IsTV}?60**61PMqBxPKX+E7ofXTgf22KEk$F+iRJXwO z{R5df;uJF(QbL!vx`vBWo^pJ?Ke0peHrC?YYYN#;q*A+HIH=N3DQ9h}hy{RfR7P@* zbyyR(@-Euk1*=+>CiJK~sx|5c!f6}&^VgmA4eOinRmU%;#<-`4VZb!6#8zo}5 zEdxqRkwt@jdNwF&D&2s*V;I5jUB>RV!wqA-raNWq%hmRsAzZ?yx;Th>mpR~T+R&A1RxzqY`#?4F6b4{Y~y4W3K46~ty5WwuRg=O18AlWuGzn=BJ-PP|gXldTE z$6I8zuT_s%!=^(pxn<4B+Nm#P(Kp!f#fC>?EZ=)9=tHn?#JoavADZ(9B8i=GF`0=D*^on&AiLhB82dKilhTHTAHDn~}JNL(37Q z#FO0hsN4SzhbfZO(R6ro!A1?%65KM4t&)Uw4ZLf1FiN@bM-`g zpOkbpEtBPd87^&%P6c1Ib@Y|R?J6YUs=(M(Hl@MlZ*Qf$cK9%<;njqZ53JZ;Iq&84 zd1(2+h@gyFOvS=hdj@hYh2~QPBcT#mKT?lSL=_u%90q(I6df6BOv>fi918ALwf~^XI zU9U{71h&3XclplsXa`DZ-luocR#_lG-&mhIdMzzbn8+*|Oy4n*?ctT5JCUn1oYkOYD`foh< zoy_9!x@i0|l}ICpMEJ)8f@@TY1aWZYo5{e^rinv~Sv|e1(r25`#22lq;PZ)7trH@z zhJ$KzkX`(X@C&e&DIA-dN-=?w)Q>a`!thv<$&+$wcC)v5b$2N?m{U(cD~T#>_)Q?? zmc`~>i)?i`G_KXyT3w2M=xTkcnB|dyO{@RhE67H?P^fLlQ}r{t)t4^m9~kRYb=#a` zO*NZUjq+??V5L^Gp#QT_5DQT;#Pwk?i&YkGD=F{Qy|MLeS5KUQxt3YhQjp%>S+zcp zoW;x6JJvs7V^#QNpi9VQj(4Xa$EQDzd>s_+h=`Fmf>`8wRpBkk!N|mW&a^V`ViOQ- zV-tYl*CpBbTwY8M2dW=;+<(xD*NX2@UQhg^MOrQ#@VwAUA6qP}*An*l*v|AuTb)>4 zpbqdi7Dx+FL*qAWI&#xY`<#znV>T9Q#z{PVq1q-S2!XsO6YXm5N4}Z(+wMerl|vB? zK_sFpp6+Yj<&Y$EZ|-h#-$4CnFq&DbS!b#HZ^l*OE+2&_sv&L;pLYK5-&)3x9;4WA z0CD3%Xe=MCm)jtf%Rd5GjKOI|9AwFGa`;XRuCCsOnk~t+f#l$XO^r}-kgej|Bge-~}09xtSF zH`e7@4Yh34u*he+i#bMJx_t|S+AF|Kq2W>)=bh6K6m9%;*EW?{5V+6gXEL{W z!5G&n?s&|2>PHzYJS{CXEbL@B-Vf>&|2nR4Ru<*2jcx#{`JVPf#4agK%vlos)~lAq zfYYvEtB*|F&iKKKE3MH-6)eg$#ptB#5#Wfr1tX@0$-fR%JEnpE2Zonb9D(bGX-0;& zJY?xE@jY8L3!fsG@DHw!e9!j@6pWr2zo?}aR_`BIYJJLP?y*F6 z>z6U^$Mb^wdHTs>tFHPMT+H+1Wwii$o-KCXTlz3`Sb8%_g&wu{k48{2EUmmG^+@}F zIW6OVJ>gM7k~+@+!}S%>cm2-`;0qYkmBQRrs?O_)I!hnxELv!fK>-a!a&+_3;Sprp zr(_vPN+nV|%Y4BT1kwh27D>>!*ggO2_C#sFbsdC;Zw-pc2r(9={NFBvo0Qtkit zGnUEpnJH~eH?DRR&3Jlam|1qEaNLQW5@9L&@KQ=pI2 zu`6arcC35tTssUd>@)MT;Wun@&|4e>>#(Nr+}y$g$j#SA1zC)P`ANZqbNBbk+; zVXU;ELa^!N6V*Yl?~)rdT6lie*4%K;L8{GF;USh5zWGqt!t#lQeK&ncyrQX3MT1BY z8sC>1nI!47dim&(Z|N}RgCb3M(m5Ad6<+f=p+By%fFsBL(>5I}!)erCO9&IKnh8V` zO27h!Qef<7M_gOxX|cN*^gv3k7mY)$oXn*xDNd7GV)&mZ{{vx5EJ zvd4$CeMF2>=Se6B37{R(ku4-%w^7>><+a?`_Z>`*Km*cM_Nh8$XnVY@6{9p#_(JZ6 zBOwh8j;aye_|{*ctmP_xws*sEERb~QhfZm5t;9hogZ;c?%Vh1k5^piW?z%A-Lr)&k z-k;9J+5vqIAD_#=ciHBdxb-x14sTY{OL)8;InO|KwkdShjrSfq*(~xC8%Ah4N9tkq z1OCsT`lj&=ESBV1)Bv`dWfW8i+O2Kv=a$P%xptiU^4;2WAli02Kr^Nt3hkvm{Rd_^ z>Uq+&)CsNxq%;-nB`U05)`!6U~u|r++$6)FRVs-ySL+{wZ>^_ z^Z?NFgM|i7dA0-wQ=``Ei3KeV5o~O|8zHkqjT>2S*0h_%R@s3&>(^>GQ&nC&yNhx5 zd%cBV*Zu|T%Yer<>_(R}21}SN%P*c+EnWjc*oJMmAN6uHN{mE9E?(JH8*7_G&y-cmTq^SPB3LjK z31k_Ni8)t$IkSk$=OR{R)1~@B;>3R&vSOs@_yl%aej?@ia5X0JbUZSPJ{3~cP5~JO z@9N&}yASF|TAeU{A$1{t+Kp!jE^Sm1@JE_jN2*o6*c#^wcbpLl3Cwsq>qnJy^FOa; ziSiatReWdRuH1S2j_tF+UmqU(W?@ngfs#1YO!R?FVd(YLyzo>I637>$s^9Hd?I0Ek zm~oAU<#fdUC3;`PnR9Bo2~&OBz(4{rwt;v!&*^8{7p;@%Ue>*GI=TrNO;O#l*YKro zRi8`fH1>S7owf zm3X?_ie7lJeI_+*y@)vK42j*dXJNBxe_ZU|S?J;u%~Hhy{7~@<0Dr{Bieoun-`}Pdy?&{RD*bPMxw$>(dQ5029?fFKj_6f(~hC z+0yK8bl29stwyc#sqr8TLpp%a0mbiPz^k*ij#XW>116vI&t1IPUcWYlthYFV?_p=H z+)~{HS(p@;I-!d8t`nx!T$nD#XRZTWiZD1l&7NSj!(HK&*AOEggCgWdw9UALoHn@t z=`@;27rU4=*>@?!%pV%V`eH{`tC!c4FIY(gscH{6p&l2n>E}9hU>Wb-iGFS}X>s$* zC6@SVwPrqj7bCF`p@6#1UIk`}E^c;%=e2<(u5N#|#T?i#C$paJRrPG%0KO8a_%32o z#oRLq1jXWMuJCns)oR8{Z@-?720&1ifpUI?y;P|9N9MUg=uQI+Y*1ncMA~%|_O)Tg zk>9TfC;2KpFQscsrL+GOwS`7i`ORuCZy#G%6e#hvi7ZRrdF=gO@uEk~$`7bG?E?@( ztnr4DFx>TQ~_5VcHrVTvTx7?P;6wB{6~PD z=plNhg;B(uhi63w7nqIs(}U8!E6rqN2lnRJ?3ZGbt6d~KD>^bvB!b{h=b@XGj5F;x zC78RI9}6EB-$gxt7Jf!n@&C$~|C=gR`{;`^iLwstwEqW&m{GEMJ=9{T6$-eTG|b2N zlnI)pIIE;N%CcW7T*xkbL2Mk?c6DS|l8r%YFw zG66bdEVR?Y*jy@j%Zupgt)jeNYa!w5*CMvc*OW7F+Vvk`qWQeL^U0#E2|W~AQsJ0)lWC(a2Gcs9d1p!I&GW>$*Vfy8NO~D z1JT_Npy*fjBHMgS4F`ysl$x&<%>iM9$VcZq1?$b{zs$T7oMjt{(BwQ+W0|(ngH^>+ ze8rDSF}^JaX%qK1Z1ywZj$*cUxf=Za5`rhY!<>y>G+p%li&^Olpu@mw%~}yG;$Y|* znc_9Q=9Htp@G~g$(@exWu0)446O@V+Vq`ExB}7e80cqpgR>C2pVXHO13|(We;!PST zS+{SI23EED_2rt3=+fk$WvfOKHeB2iIoofh-`E-%HyW9hCKhdbjNTp?Gt~3hPiWOY zJjzsF>$sQL6LIx)M>F+^>tVeYXPDDO@lmPjWv}UK$j2RSMzIGMXh)J=yX>~Nk8gn1 z)9HOAn8NPsxh0$I)YT}K_@8mclS35s!{u$aB7&bzCi}HMNEn-AD1K)=`ReF#4z7|Q zZFJ#HU^_Kjq2V2?JgOVD%1{|%k!z2s??OmQ&Y^Wx2?jyCMASK9(c0Xz1U5Z zH|r(WS6GVmf*YT zBpVnJEfV8h>o9vlTW)S8R^xlkmehE5GoM>7TV=eE4NeG^;_8lXeFjmt}cI`zjzUAWPf=(sSQl{5e_qp$EuA*wa z*at7f&7JdnkS8>eaqj~756pZ8ax*Mts)I_n+3lTkjDo#BK5|Ddz5Zxkeos z!8e@V`?}z8@{{-6Bacgmm7Lt)>m?G6YZj|*r^QI6v=`x(Czmz~1AY|l+P(!JG5-J-xQJ78YJW#`9SNK;34kR1Zk z6Dvn5)~6>C#z6+IEu9h7uGacUSEs`F1fKRM<4qVGfasPXbz5<5$ynJ7LxH?Ep*cr_ z958z@m!lK_pPYyK5vFy%Z~D1=kRQ5;S2ylf9kXsxPcD_i*F#cT_RNnhRiQd28AyJV6mmW7?ccDyO#$>3IAJ_h^i;IwwHgd6kRW{x(L|=2~|+9>>b#yvE@zXE>IF zs-Xj~UwBqg!fd1IE3XmXWh9GSc!GG^CLhx<;4({xk1W*_(%WG1NfBEo_4$UzFB@&SmI?8V3v;vlv$3-Ynf8(Dp0Oz zKJq+g8~M^u9Y>L;XokG{fd(Erk&+@BGK zgY86}de_veb+_P`MXKgW;1mB+}Gt&w}sVQbq)r<{{88)u)zESjc$@jK59KzPt844cW4NBhm1*)@wCi+jB7yXk`U{ePNl+RRL9oaP`9^NT@^dK>*;FyRilX9irtz35K)rzQ#5AYISF2Ce$W% zhDI9}i^$4MK`P83bCtUK1tVO9HJUbDt*j$9T4gz9PgfM#Z`oxu6Ko{b1z$GF`cW9A ziuUYvSY|%;n1(oN+mUYf=@h%4F65t9$}SnSSW!dOcNx>X*^9ZA6E(h&&e9#zfZHcp z%sKQyUK^{6Gr!iklr+vGu#D2td9~RcBmo5#OmP1W^pyU0pr>uIi%kW10#y*{+*uTh z3u;NbX#i^f=ythP@q4*mmA%(M6|$YZI9DpwSLERhKy`Eux3?S@8qbH=Vj5R*W!r3o z6D10=wdF4&;SNXO>hkAEcby7*=28G9;y3aHB-na{ppM_z>xMAJdPjlHrg-N>QM6#* z2HC&YO&{sMa`55eQ(hxhuz9cFWtRbfj-Q_2QWZICX0HbZ@jA1`=8!L4+p4QL#_7Ot zd5ISs>pQZ-J}}(0AFIU~v080UTL+{huNv##ur3JPe#F~9zMS{rJR5c7;Mch9*5S}{ z)|o2|_mZ&j%Z5_+dxDTFC`+XEDn@bDSBs03gM`N9Pl9-o&?c|jn;~&K!mgvV7Uk>+ zL)xz#iZ=1Pnr+9S~N96~fM(96gonv!!)$b|+8NKnQb+*G)F|mzD~PzvS&IX`S4nisuWe zmL!OmUe_I>?_?lJ3Q1oxdHUVaaz$tCm<_aHYEAj;G*{)>GP=%F4 zV!q-BJ#TF858R=ASDN+`1Ms*TwkmFJ*{kgAecGob6p2lTY&ct+^xT8=U556{0W34n zmY&3gJb$QW$;jJY?^+WS#tQ1dBv7$o`3|PWVnu^i;&coPttVb<1A}Q*4jX7{{((8x z5KTOnvO%iHUY*#*8f)D?HG~=vu(CKd4{GPda!(-*I5*&@$zEBF!)+bpZse;OBd7f| zXPHgDg4hFMk#6pI0GvcQin}z9< zI+nOH{~!M0sxx$f^LC9k_k0NQuPimUta$6KnylU4e_)ipoL|061vI6j!SN*mo|ln+ z>N0#jN^i3JZ*71AdS2oR#g~8% zdj9|BIM#xG+w5gP^`HF*rhiW>vYKGKOUkpuHwb#XsYrfw`Hn4MsW3cwAE;UKcJwfi zH?(@(>1LbZ)BWIrq- z?w4hy)FV($weHPPOK+x!U1HW+aD6))$0zdeTaWp8lZ?7EQPo-VX8cKKj`NVijU#ba zI+0}bYb<5ZyV*)pK}Py!e=;uv#rmn_g&b!w8n;|og^X(&QN1(Gr^)*Txo{a7J}v01 zR;u&U$Z8wb4q#_!eX_B8c7Dbf#PR1tZiLZk@1uKgF;{K(EFM!NPqXz=3<}o*>1YEC zg^W6v*bsltIH$WkH`^I_7Eql#$0&9FymRn)Lc1!4)uHRiK)j7c>_5Lzb}6xd2`{-@ z+EZ)!kZ&H0VS%qyMOcWiBSS>$Ts$jNlD+R}=6o`lAIdE@a|67b)tuKoq;Ls*Lw8Ik@qT4?4NXqtGL&oJ|$xbvON^ z)uu9p(GIbqnRJX#c|1cgtrQpgZf>X}X<9a(jMm&f#>s|Pax%}9*c1Ly--ND*e4u8c z$uhs!{4(edw4S$l4CUKhjqrI4bPy{iWYbqiMoZM1;;c4Xsl5x%?qZ@zY1W_)+ezRL zQ$?Fo&XSp7*t(mT*}j?VJJFLF0!{^a@FH$RNMlWtVFMpVS$V8J$UA!$)BhlU_K^J>PLF*xJE?9C`KL|A%nxMgX^KhYTl-FwdlN z9)90|Z0ffNzOD<6v*@qJw4lD|Y*am_tOPLc_B*bds{qT=jN9N>eWJmQb7e^1>sd_r z^Loy2b;2X;o_h>N{W!{eaoeZeJMiDZw|vp{qA#e%ifjMCxUMuS=uU`j^XtpZjV-b3 z1!xHgNi}0n%_K>;tIpLlIx^7%UOtGI9j&_xIPkXd!MZSfEaPY8_l#vNGo8!|iE%q2 zK3&#2Zkp{fq>HD^K!)-@7g!sW3b>7?V5oPtK?pE zbi7i;$#eGWDwe;4dz%M&i;8Czms`Zx7y5d%7pe3u_0qV7eJ*j>j)hSaXX23c%UCUAngzH}Qt1k`UC&fPO*=KXjV0;LFYUv=a>C|i7VoJ+< z%2M3dboT-wVn~pJ9rr77V<|ZmBl~jHBEHqCJ((MVBwuOA&Bc;&jTyVYp@7SrkWs_N z0TyJ~f)qGB;rKb^Z2{CG@4lWcCTpRJN^K-#OxT7|b&&KLw-LSkzQv->CUiIW^ZSwh zEgy32*b!$De+2!PnT5*O;M%Nt=vlV5eiYi#ebWp8nXX}*bexZ89io!$y&r$?U zeLskqKpVzh=9a1Z-oaak`7&7Eg1lj6}X+LDz- z*D2xE<@SZ#cGr3HF?G}C9n1tK9tf^ zxN4Ix54NH)b)MbGwnQO}Mwy^&dwo%~StI`S>8 zVri{RCX+?HCgn!UngicIH9mQ?GZi~hu+r_bBP~dS!=b@tt@lZ?!%y=UsjpqlE>T{^ zK{DGGaH+N-sRSD?ZJAMFLl*2Q#N4jmOhXGGFfe6HaD=_f(+S2Mhq^nR^hBW+cyP(?C@&UtyF-xO^U&( ztt#JaM9;h}f>=RXS@U*-{6&Mh`GY*i9(|fdvJriWbL!ZW1BwL|w~%OZR8!CSn=h`t zzl9wmI_qb1F#5ldyXK6!1?T;!@@Y2}$R0T+iXuF^^_bI>l(hXQx~M>k^Cj;0{iim6 zdDmiSh}f&-WGzaR&&=3AFh29A#FmP%SNdlUPxE%v3M6i#NOuC(=Zi*Dkt=PaohOF% zQlNJ-wQ#X3>ktQKiF>!qYBSYr0^~VH9MOgEwoG#EAO?`@k!5E`JI@5wL$*BCF2dE% ziN`JEMM8y@;Xd1O4^G&1z*I;uv70agonTJ5YkS`ujyE$C(0Xx&_Nxqgzpwzd>!h<* zKS=B=o=$bSRIvGBsB4}Tuxp=RYi*NPAqTL|wlo9ndvK{DZ6Em>gl?_V0>JHOf4T@N z_}dJpIF0nZo>$8`qkp_uI61=)|5|-%s%GmAi90zt-&Z6UN-3t~RcLoi_&#+#Ck%8D z0BDjkF6I$ebdNH?c1O3fKTw#bGTPT02FC_TOX|k+(tqBi`xQ(zC34)^fbBo#dOBWz z|5*F{cp`I@ZFV;|t3MWwwHxcwy?jxvH&g~N-+=C?; z3~AIrb;`HYMznhLehBTPV$^}=Yv`3O5wX!R{ib%U<8~o!kD2NhLKY_J@K{=Ia8}U= z#-w(0P-_%Bg$u-Y58yBd+T?_7((DOAw%v6>!FOAovT=IlD27NDr6SkTi5r6nlH_N6 z&3Ag1UQyv8&|nG$MPMz^vb}@b9@_AYW}0wV|hyfsWrLntj_6kKKQ=E z!pR*=3r~y8yDGs|Q)`MfQHwI8YZIWDKrcP$KhoEr>~GcYPt8?>_JiDOtuCpLXqLi4 zQh1E6fm2pVz5MvICY_qJ&H3$!gAN>#1vM<~ROVzel_YTn%ZKGz@W+KdY<)WDzKLUvDj3V0UjV4E zzzSj6_)~KnQlxDcp9OB~I&~wSLV48u*8~g^h7R|k$X{Aqi?oRvYV>K-v9J^D^kP$P zCOOh&{FF}W=UheS$lXhdt?i<2R(t`m)(#K!_62fDJpx;d{0DwUct8aSH9-YDK5G2* z35i_lI(Eu-P#@6_i?X&sTcb@=dpNz=RfM2(j1JlO}?{UzG(JvBL&-k$Q%ro_{ZfDUhf-~@D0GLZiM4^5;3091$&W3{<16{GB#)2K0 ziC>mDAza(6EKaCcm}JG6zIh9Uqck?{?~w=NOMPN+%fpDC(uHV^u&bxbrUOrQVKi6F zNI%!c2`m+zzKiL3mKo+TtX0Ot6nyj?0EKm!aKaIF&7W;`mwS4&sVIGdzO_>N*B;Qo zv--p-JexJ0ucV}mpKC_&-nxy4YI<%DX`UVW@pcIGr__o1#LLcx-)x14FqG!Y$rlss zZnld)uO#1sI=%|KG0)#BdWU&&LazIz3tEE@JR%{r_U_Eu-3wzIRWGl;RFW zi$igzxO;IYK#RK*+*;h7;O-JUIHd%4w-DUj3bYhDjQsBZ&RX}y+%zd8`KZxx%nNuRy)mG51cJA?KN?8D$jW?xZnnN{q&VG}vmq zd})TRi@jZyxKZ)=qn;mI)Ehj7`<7TsEh9Z323s=eloTX_oct6BP>t#$OX;d?mg2>1 z1~Aiai&9~~y0ipdGihgp7w3M2)80UQj{Mi|tghjI&hP)HuSCP)FBt`}&3_1lHBIeT zKj!A2{Qn{Bq~p<^mmDWhKJ9!VOjb30m7HpJ1UtuHM;tHy5AXi9Y~IC74<_rc>YF(` z|H(_V_y(74f(Y^B;2n3Cfkm(X-ah0Y_vkVMzogoN{PCWP>=YS$z1*LGgkMdDQH?;~ zk1SWFB==gmt$U>ov+kT^ReEUnH@^7}s(-&atP6?H+dQXL`S5R8DZU?=Z^v(c{oKK; zk_jXA)ZF$d=l-vn%vuP@Q?jLN)K7z}_kVEMQaxOZK&kyvl1f?S)1p$~8Oku-M)EVEFJ z<~ncjcgGY(H}tA|O~WWhP>UclX2`s!XpXUTehF9JdVi5MMDywXoKDX>m2qn^@}xTDO^eUObWg2H(|d-I2zZSErVWRcu?yuz;~$}{b@vir|1g!0Wh1MzfQ8(loe z$fylG!W}xb6qCr&`}<2(FRf%1033^F+nO$aq-fVXKj&NKJ@mZ0dJ+!08{}7w`wD&x z>G4fm;Cl_5P?Q2;6f+D-9?h&Y*W?0y9QOVpD0d*W<#M#S-<)bo5oo?rVCoxSbSbj) z=5`gDC~hv|kvAd%;I$=E!qh`t++AqArF1x)0V=Q5{GzSzCQC%Zc3!1FIfB~bNErGcWRL!~_Q!DkgV3KI@N4YD15-xk$SragJGQ;FJsl~|2^ zFU>8Ot@qQRjLK;FRckCy)9y;K)uXn;I1X_-wl`V-z_bT>ffoFO8HL6j?Lcj z$J~IwPuN+M5-&n(;#?P}h)(XHGhj(}<+qu3bz5&v3HNbK04!v*mDR%zZ;%PxTU%So z-ZoD1a+N47zl=h6|7z*g5XKTx@C!djk2yfv!EF@gu(&seCfqz9aDHOuaESj3%oZ|R zG8orOo`wB6mXNJXiFKE>-8vS9YJj%r>kChG14*=t&-Kq(4=}5wGQmd8z-%>@&YK0+ z1oA8vG~qp(i1j15%_0DaW>3N;JKgw|f8}<&p!V*UK&$VQg0NDUOWQY>`VkM!k*`LJ z&)l!^G!&o*Tz{VFBd(XL<#@@1h}HweXi>-Jl>^a8ZCo_&NzZsM0e7p@N*)2NSqIEFVTrx7#~ykO97*9?TlxzZvP+HsV3u%)TxdTLGhQjuUwP^)3v+b`hajvXt{0=Q6<0lePDj-Va)+gTR6OXdWAASAZq@~W zlT0YMC!1t;pGpAhGaqv<#{^)X{~^R`-KcXiR^6{%-PJHIxd5U#u*yV40?jJn~$pUW#>MQ6n3P-HfXmJ$HHfKz%$)OvX;$!(BebklTSV z1z{6ntAdq@>SJV@^L){mwAepCFdRqC04dfOwNzwIDHm4`FFTgT$Grh_?dxUz9RTKX&fDeB5xM z|IyUc+>X=mgq2?o3kXl)xp4q=REpeV7+&}Qd0KX|Doj6>0yHbPEuMJ6PI=ufV$^9m zK$XwS1FfASWyiKN0ma<44SEeNa)kSi<)on16T;V?)NbSE1JUNuKZHLz8GV+^;f4i0 zuQP6Jd%a=)hsyEcJO|}9Hs78J{jE`>RV@Yboo1Dfh z(NqCO9mL6+$FF>AcJqmpsXvLVnwVH<-{7cMzknT2L83XkGC>>J-`~hK+XWGJrY9U@k9O|Oo8wUuZkFFM zl8Ej|s!>rXL6if@S7#GxLEl1WW675xYG@!c?Qy~&14=`7}yN8Qnsc*pO^XXR^Z zatv4TzV<58%J3d4$WA+I+2D;Bjlp?!6i%^0c%9VzmRzh%ix!lVwrI#Rb!aLWN`n=g>@UGqq~JYhnW_>(8ok9CR#0uS7TCmfN?9 z8NHTO8oj7*)P?k?)*r8AA8IZIS#Uznm%65U4?4dK$Essi7SV59oO3ZJKiy_`q-!f< zd2Wkzx#tR~_RQDpo=;`thdl+ptc|0Wgh$b_xL$_l8HARRk3#ray-*UOcUL$KBdu6%J!g{br7E11A>&$QPjUQ;SPUw+;Rz9mIo zhtE=XU$gLz6E+u@^;~KQYni+5?r=PijJpoV)Yyl|nmwnBK{bpf?8sJnNs7*ro z%n|u8ggUfVvFMGFV(k5+{FT?*R{yA`Z{@b}k_C9#_^~adn4>!oIJhQ&(+U)CK91Nq z!@7S^(1SyhnN0Io>&5FU*oOP3#YsOB_6Vc=F{0N( zXHr9x6sQ;}J>T=!_Zw^&1R&2G$9WYq4H>qPo5ATya{?@-bbaqzPwZM`P?i)!lX0j% z>LFzAie-ptlw4lc2_Kb%QHKo}e_4P8rsEt*Y+VloT~cYWCL>{q>`+{1p(L`xPWi9Q z7|9=Tiy7_HPAVsq|Bv#=u+YI?=A1Kw9h$d(LNz&jf<}m!UD^~bB1s=Z`EP86yFC-O zdh4QGu&|cgi9Wa5s1~}&d{qW9SH8W3blg7$_Mf}=bFV?w6}pAYLBwb3uXjrqZ|_du z?{RNF1SS*MWA|j1+efdOgtuaT{ggUawUtBbgbB95bc&AJ0N4*3$Z^)zZWQ&%&LMB) z*PUcB)`E0pqY8fXk`CS|b-ywYHj_GYD=Ry%NvjZj+R3MNTvKNC@y^%Uk_qf-lWe1EQk}lF4hvh-1i{vu!B^J;u!KnNVIIOY_~*x|Dh30--ph=dZMNrz;A3 zV)BdyfeZNqGdBhq1*OJOz7SzpyiN9rhOQbZ%X&-P&H|K%7njFZ3w|_+@b06NrDxN^$>1vF1WnTIUKw}6gT8t$h zt%-4F?0{=%B{O~>QVR^z`ZG3pLcX9%t$KX2QI%pp3e=^SeSW^0;!Mf9 zj71!UEeC7_CYAYgKH9D={Om^BHa@F`ZlL6_#u+PsE-mv`DDwh8*D{J|GRkmeA{N=%A#6(R;$HaAwcgjhPtcGElZ z5$caGF%ew7iwDMD9k^!OBMD#a1g#y-f&oRPt(j-sN$APKo!=WPf94$;EY|6#(t~?` zoHHIr-gk*(Qt;y+MxK3h@_OVk{@ zlt)PH9f@v5HJ#Armp!XE=yyw>@^sWCAu;^AJ-$T2^)U{>q2M0pwr)m+3h*7GOSxKN ziCME$1uIt#RT?9yM28?h|80)l10yHRdT>A7j#Qz?)Gw(vne#(6=eEDqUDbPMLaN%m zkh~8mojtVooTV6q8wQGV45K^QLyu^?-!;{OpUehMZT#4~5MkCk4%#Gk`Y;F3gONG8 z2IbpPI`O2aQu4~J9CIhGn5+Ytbc4*SRf+lEKU_}W5F#m54$6+8^PGF-f}_eyCxfK` zmA7~lbT*Mu;K!orLb`P@lT#d9oJEpz=dGh6jVywcto%3+_vhKy*emR{3to0jj*K%J zQW)l^jL}aqvN;{ivfgV-Q(;XYTQoVivFxJ?_rDIcDJB8+4>^Z~E4l zF86c4FnndMOf>6K>ipt0ijKL?j}MFFWb%CdMOz=a)2lFZUQ7p*T7)ztpp(Z}ie8wD zdLC-+OSYo`?B2aTVWa-Dz@nUYEibPIm&Y=b^#AIyR7R8h&-lK~EdEb;`~O?tmt65) zhoGYV&7LW#7JSgx4i(quq|AVE@viG;-hq_t0o~loyJYv7r~>8L|73r+e2Ql`vfQU@ z^zbp`8)dSooOzk-S`2a7FB$do^1Db4XAbKcn2Jx2u0Wbma2n@rdD??aUB~N0Uo3rd z##4do3->^i-BnmSqi6^q2qR{_+|h&H7=1(UDIzw7m&}9e-3iu4 zBlq?M({qh(DLpOX$xiRH*~gb(eN|CKDugp@-=)pmh+Gpm%31;47IVUb;;ag+Xr|7r zcyqwarbeB9tEMk|eYl<#+m!|7#Os&-(gT3h(*~yt0qH$KXB3(yc5|8WQcYaXM}AzT z0yY81c>(=7tidlFE!SNYKATwLf0zVuoO2$I*&_H;o`ik{`X+>dO(DdwCYrV7@?aQv zE`qTJraE1Tc|h=^E(A&?Ma%G4$0eI-zSovgoW-^S=%5y_X8S}`)KwZR^dh}fuTeMD z>|NnezNx?O2DCpL16N2o$6W5zPONlZur^pp(e|hY0T&!g06-lNM1kW zlH?DOwJ@J&)|xfx>VuopgLWcO)Ybs5Go}ab2k%PWDexLF?#8`)(S&Ki;))xI$|)xpwSa(fXgNOKb~O zkaDOs)LRjReZcP!N~=JR*d?q&OhwC?azd~7`~e$b&lzs@9qve)A+ zI4}5RkLoG9`yaylWr_-K18KJs+Lyewi+FxC51-R&X3zyUb?i@O1f}0H21M)pok1$z zp=NtoQz;x^mNWFVcN=v)iX*9`=M~m{7wnu$-JD{@wreVB-m;Xc=C&L$M>Myt$_ZR3 zhgIs#ml5}CH+!e1#9_anT0f*!-jbxw$rDCpMuSfW{|L;DL%Yn5YcqwhMAd95k*V#r zZSvFV1jOag<6%AttR;QCMm>VgG_Tty=R!XA!;>x@3ugHaFWZCbQ#^6;rJB!JRl=BQ z5Imw~xDG zIdo}vOZ`Pxb%p!%GB$s#oz1NW(VM5N&06=C^OR9n8}G8iid5fk{}31}x@ifjgX7L)onX2!tkSD)nQ-~a5 zKXEtX>MhU0l?bv#Dq}VYNF`4HY|*d$C%JzJ6=TMO={kYMt92P-bsKd>t|}#5Rzg&w z_u4(mju?ua!hzl{PIlEg%f7ec9RnQSbAU#oE5~U$kpK_|g~@BkEL0}zN@GbX|^ zb2@J17HF($xVmKhwt1`avW(``sV>>4v#UwuNgR3aJ0gZjm4n2-9mk;z z$zW`vFqC$bZ4d)%Crq8(htwHh_eLdms6G`ZHteYsHE$>1*i_%iC*Sw@WMRbqf??{F?w3M(qY4ozRCr&;LJq_89R!R^eIf%{0IFU#2m=Y{MS8o zw&O1t3IbP7-MOl?9+*ji-V*;1!s%8Nd?RJ~P8r-LzKNZ^<@cdBbi z+>3SSLq88E#uV$6KP`ber~O<7gD%5A8WszZn}#n`?CS@(k4_x5A!cqT+RM9Kit-be_Z_n7{wV@l8epKpJocT-n#Ma*1f*E z%$1Mo+*hWHp()h>S{wR0eBt2P6LD8k+aKM!0^5k4JVA3NH4$i!{iH;f!W_wW_bTj{ zYR1Q|qlt3|MG#wCgoIW)BO2ZGmuB8+^jdfQc+~3^?E8g&a(`+TQ_}5V)t&9ESLWg) zD1MZdJ!H`7|zcZYdvLY>J92dQ1n+~ z<>ZV^|Kh&D9J;Nk%$LyX5-fUp8uk6yZJdR#o+Ci4dYnW03+r$?k)F8XZ_{UMjIo-b zUcTtA#SGoM$mY?%gjy*sdR|{V6rUD2FBVssOG#L-`Kjpb2LjBM*FUb4qu?s z3FACl&V?x|OKDrjQZazj zLifiaJSb$B=h|xS?hGM|cmr=5tP)eNY;uMuBQsk_LCNChsU7Or^?pcyo!keC-fmYz z=dyzl-h1Z$+=J0`0c(12wc_q5;!puOHJN^=wg$idT|z)b6LAt6t-1NwO^t zOU({JXn6Yex`!-;#YNaD?F1wy_gz64T&wDsJLPq3@KUwhTl_70!HGOQ(svig;lLDJ zSti4ok^%vs;H+v9)=%^%^Z4Xl0E93Y>$4veeb~nQ5kekIP!RMvi@;PnuF0a-l^7+N z7Ju$^?U6%iRe9=bUK!Prwr!bHe@R^b0b>SX@0bC~8)^zC43Wx9yvf~|%S*>5Su9gs z10xpN&ENo$!pd(C56u!~X|x6e!~;h~kz98)%}PBhAKFYw1AkBR48UUDqmLb_G$#!$ zlhULX6fk-@oUp?dmh+n9%j8tjZ&49?EJ5JTO}JuXL6X&uJgGCl(n5c`_wrHxGdzo3kYd^DUOXen76 zb0Vy3*Kx}<9+>L~t*Rgt(j&ze*#Iebgu2~Kp3gHBztxP@V932ft{yFh;s1TvaL2Se>UJzglon?}Z9<}h3W&3v3kOjoAJ3&? zIw2m%CR|4pZ7&q?OnX3^3_DCpd0==OKFWN3Tv0piTT%FFKwOITxr7vSJXJy+p*k;% zU`=GaN#yv4Dd*ZbKr(y@Gj!<d%=$MwZR?A;@GC?h^2|5 zop)3FG(;o6r1EvAJF$woI^o=Xr)?(TXG;!B?;+=V1J~MaT@QEOHrBrsN-Ub|N)%Gu z^6PEk#SIPj*tIo;EBGY1Q0NEyTcuFj-&FU{>cj>2`H?&f*A&9{nfBi<*NTM;eEZW^Uw4y{Ze2{2xxM60S7u_0HE z0kQ7a<#HS_4kWv1a^lg$OWTOoQ%xO9x+wP|2awF79j}u)l9&&+EGB04CKNP0+ zJ4WE?ar@0Tm6kIE&bfL@4@x@>8X9)U#?yw()M?Ffz8U6lSlKL)&!3b6&Qv_Vew|maZ{L(C| z|I_u>qcgI;t&@2A`wyYZ`Enk;(0;&i@ugt=$;;(gtC+pq%n?8=fR!5lb(K-&=j8>B zT&KyGDEJs!-^l^E6VKG(0;4+YJM{@}OIGHo4lzoqW#$Gf41_b_{*z}uie@cmfcH!O z6OMF{D2OUe(@=4U2W1v032YyVXMU|Y+dh%ar;fp?4#uG0w-T%@5pP@gixF^(uoFKK zkQhNmEuAj}H2d4lV9=#1jSA7b(Q*D?jLG-tpODDQ=JE1UOsB#bNmmDDtQ3gKNgWekDx(%ZT-?83(j9) zB>`rg{lk9jE4R#pH19;esxCE^)th$qUPYsPest62}@d?2jA_Ba9ALrqm4%&9Jl^`#6&#% zWU*DbH?&qx^(V#6LvuB`i7}cwg-rHAmW^t+D|)8A3+9dGKZMTK!%#S#SJQ2niccKX zKAj-+mtJf+98$)yA$k70g=8iyiHIhY(56q9Xr z=qa$9t=PQ*7pI4AsGMTIBOfzftspZyNAemH%Um!x?Q+`1Kz{6sS((RbQxpqp0VD3x*Vo{wV?}rI^T)ie!PmUo z#?ueWzX%mXaJ4z@%M*lJVA%AP^(B;=YZC}4qcpf(tSZIP1p1uWX`~2h&b9krA6rWp z;_T8*)}*sGx?#nqm?KKq)Tio{BL*%%&~gvqG-emfyYE-im4#wXH8L!%6PS!Ini-SKa)OIMbe0I?lT6!3~R zIj~xmtsOa!n&_hPr-r$$8$}`3Hkh zvz#>c zB;S@lQ`T--xA50^MI-CSM1C8HeWtvN{kWII)bVn8j>#}g8FJ=nu@!(N&OSMy|TY(_*n6A{N+@z&^%cQlDohdc}ah3?@3#Nfk`gM6S&@ z4sN3}VEzykTS@?l(w_+FQ)`{_i-~UDGOp9W7;H|Kd;Rg~W)`hq9Vw;@`8g z)04(p^t4o#ox1)k34xegDKdIuc{}q-X5UM% z!hDM3`q=NnDnD1lLQ``u*%H3!m8TF33oQ!+@-M}w0w3OCKyePU83PbwqE)at=~orGhNJN3RY9f$gbya7T*+vuckJlkX^X8LN{WGTxt-&nh24S~__vEM{0g z6>q-V$8N6=`@6LmcE@VvNG8y?k)GJlh41V^wZVn6p5vMAz=^tuboK*F+^eU>If^*e zxN;-edtNmX>l+?$X`%}?mx7a}JKT;-2?8p4a8?<`TL68w}k@!V00hY3I5Yrid9Y4 ze_9QoxyKFHy$>4q5lc@ri0_$8A^m%_kbG3-#99JBwIVKE?ZxsU9LjSWRomO8$o5r8 zsFuE?s03{195(Ml0XF#E45P|KA2QX%*#-2kv`L1@Nf;`crjF47N5+H zDe+J*r~cH6^97EyZK5zVT0(FJXIOYh&#u~{zfiu8Rj*TKu7CZq5hgjuC*mrD=Vct>e7NQS$3Izgp;fZ2oGGzG zMXf6FA?Lq8vc)a>3ULc|`azAlE$Uc#{UmNC12cNpwvJR|uK4nkmX1La!bKL}m?_c- zn1UW1(L~m;lh1ecUpuL7R53|Tr8|!M6?gk1^R$*fmP)FVj*x!r74i+Ft8S(fq2|jV zJqtfkJ`Qe;S|*FlX-CfLuR$g_ALme@h-ZJ#lSpIYadB${Pho=x>|)&=I-nyRCvtN= z%Jk{G>o9874rL!>2SD}95#N4Ae(hmKi1|N+0K&JU8odyI@ADuNhmE1xrwfVwGQfJ^ z98L+Lb0eAfxU$1jD?Ep*FNf~hZBfTmjTJf%$$CY1-?i~qp{;^Q*3Yhw9SMH975YYd zZ<-UIp>1!(s;ReDoK>bgNo{wJB(5&@^gVeUjU(C2So~;S`jSk{tD4=0W7KXg8o(0z zOc>wpSU_|pK*3(%ILh|$*2-lgorSq|W3XA3@~nHWAXQWK!gu_#3PVye*f2^qdWnn^ z3TTU?sSifpR_+Z8nst=}*(I7nBE#!I?^xfjS`#17v)e08Df&e=O4R8^l6j^a9lsfB z6QMJA7ut5FX&wD7qhU`PBJ!eC<4_$-t3$KZwEDLiMkRwv;Dc`je-t`Y>fwPDh1d5m zGZ{NRiJ5O&5Si8+86UyEQX*XZj8FGaCTdkB6zskVS=lxa}n{I&wZo>?p$fq$| z-<=37`uek&J{#aYEEEdp2D;0-QrW=BW<1W19@vIJYm0j1rS*#EaqIUoQEW@>vGVcW z$)qdSw2%xe|!McE!fE)2z^8dkS^iL48yi)R?HO znke6Kk+UM#>1>hzD9cJoHN5@oEq0tmTm0WPI-I=2mHQT%*oI!Uq= zt&Q)+eo>)_0N!OHYJ#p%$3SS%jqG$-H|d4c~`&M7sx z8eF9&fR=TuU}~=Ox+}l<)ha1p>G*F_s*O7u4HrtULVn+{ETV6dE_*^A+f{a`_*wo? z!)dtW`HrrB6=0kNZAO5*W<0HPuKp$rtjVh|5Py}8{>I=>iBW&8Ip zin(kT*yi+Xil-rNZJpkdTQMhe52B^5$pfuvQ7RL>2%5E=A@S~W9-(a`L->F#dx4ns4&sR-fKBG6YIz838B$Snn~qOPD^8;MJ>~PKvxcS$mGX$n5DAH>+1+H7O0| z70MWv|G*D_?M<<2v?=~)HvGT5%jh@g^;hP*O4TvE70jMR3lW-F{7Xh{kc_!RY=)uNR?lm(@*Tb9P)tLcb&acg?NU6mE5*CkTYS z%Wl@0@iTvJy$gtsW`Op>8O;Ku;{7H%cn{2LnMq=G(o+_^Vu3Cn5o&A9u$lS%Z)p(t z_<^d*c>?G0lJO8W65n_qMw)FHi_z55WUr_fQ}4VQKe1LQBFu@EhS6FTf=KzyBL$Dq zA!U29rCdIxMF~OPuO@^_LG({^Jl_PCe(Ns#%nHH8e_Sz0_YgQRq3sJO2uBRa@s!D= zZG`!G>%T2Y&4x-UuDAOS{U-2XuIVCKqaqme8B+z13Ruj&#t9>)J7l3{)kYsN6^lMe zu0xX2Jlwv!3jOpL85W>|LbRh@!@)!)IJ+aWT(DYL7Z{pB@8{T7JY>zCW{3Q8!Rx|L zTEr#rg=TUP357;uc81q1qb~EDpk5M_E!kX3#FK>mlNvu{?-tp-QXlQeS%`gsxDSZP zMPF_C)v~B$u~l29iP47zvZFv;QIkA>qxn^TU zibej)6l1fQI5Vc2_7k*N7GI&VGEH7taBmvSq5qK;V}~dC?aTAhJh9B#KroI8okDy2 zxcyGcKz~eaXQxJNPx2n3O-2%fd;-Uc?(uWYWJa*U@ZpM1rO(lmOwv zsqtfZMW(YLdv|=ppEuw(%D8IF&zPrsFy7!0)7<;Z$#$A-?GT}sGxC_MTs^e;!&;u`ZtUGD z+jV>Gm~~$)v?i823mVZo&vL0^a%#}3DF-NKoo-klqD~NFvH}-w-W*A>*&~iS zAbm1TI7j^6qYBd1?6iYIdl{BR>+Q+63Ouyg^)pz>U;3l&&LW79746g@1<9lJ-HBMp z8&eIy4BPx_;20%2nlfMJ%&!*g<#>N8zY@zyLydKR$-6*TZmu(}v8nP39CrdZ{=B;C zrRjHd`jm3KUSxe4u|FL|6Gy5Qy$Gy{MciQ-ocq>A(Rx_rK5DJ(;1rAH?N6~ao@jE? z3*tBg!kydl9CS!Ey?swqKlHYq99;2?=kOIGB(u(ti)0RqzCTZlPg8AD?Eny1v`Kt! z+D-Tf5%IMe&S^0&T%*tH`HfhJ-=;;bAo$q@Ey?Xrj-MlZUdwvoK02)a$viK-&YL8^ zM}}ks=8jxW>igc)D7igp*L)&xzMQ?IgBPB1%+A`M2{2pv;q50j)c=wt3_jQoYzMwt z3Krp9xx#!d+6#XkoC9FspNnG^vzu1)uEWY*_v~ykcq`r(aW%$ETZ7JQX!w-!hn1LGz-C+ApAfAy@pi`XAF));mY_d#E=vaJC{IK!)p6?4~R-RmnFojnUj~iiQ881 zFxq%`%(wp+nDSOeHix6{UE5YB}J!J;^I^k_t8j>30p3hB=zjBPx zFuZbic|z7*Gn>|_E^Lvi=flO`gaiDLLbmY7;dXlK)9kCqPGc+M8BfpE$Kj21daEi0Lv4FJwbOjbQ)Uu@(Jx?~jg zWt9k;pWGbZVYE+R2n3Sn{h1Cqa7NC*u86v|TY->B?KP(f6#5EXVh6#|ErjwKu#*7N(??77s5DZlmEUTgTOmlz#z|?x9bblg#@YGj3>qwwI| zCd&I3#a2v_yyVz!!P!xb&C6@J4l3Cn94Ucp6((L(avGw#6$|Sd(xZ=pHqCD2&5VkP z^kiK%9Pj&lhtY=6Mbx{GV>KsbJXgE@}P%x#?Bgeh8uXy4NA4FYV6 zyo?1pnui=;lc(fiwY+dbo_k zT?S?2Sy6uJKUV~*^f2-tKSUQ%D7m%K-f1BErZf1G$)Y0PO6jo7JFmzpYPeuH4I~bw z{RK#Ps2+X4^;%u}W!X6w(V`!I8;fV`r04gQ}*4>$o$?M%&V%TVuE5CN` z7>%|wxNb}BCzsx3V+&>c2`Pk#G`Wr}M74#k>e=EWB|t@@SINI#6YmNn$%YaqFAhg- zxsVh5ur18OpV~UJi>6F5r@Nsdrh0d<03uVI!U*ADJeLhir;v4o zM69^tZ$~%l0at`;&g4(j%uX{^Q(R8hYi(mc1T$li1LcM!e`;0`kx()D3hZ@qCgvQTUs_6NSF0wyJbaj&f3pomg zdi*dusL0SVK_*6-J&fv>F-75}EKOqCI^nEfXeg#jYEU|-s37=!DczP|Pek`}E+VAZ zpm<5J>TWcqR{JYqXCW&3J&Y8EJ;jV70_!rHP6%-&>Jwv45m1|W@w?ae%c36hrcBw$ zghYJ#-jM~UK-SQ-vB_+eSm0rqo52K{0Fn*psS%CO3ggW9np-SQ% zw>xO(yvs(-Y-vA!=qf>kjfUSvR1k;}I+cS;)3eSHzl4cZp2zJ9&=6ZaX3*488}D5a z2&Nje&DQr#9OxK24f(4gdQ5{BZ@<>X53uYEL5q$iteZpQJ0VtHJx*|2n(#`0YS?zv zm||}>;STj?l-GqjB2RV_zPmp@=dZ>w-RQJFn_rNk_Q_;Hh{DJB`gAmIljj*OWVs!i zzW4}M=$aZ>5$8XPgJ=G2qX+yvR<4r7xr@F4>FY9a zZJrIj@l#%K+s{z6_A8~f3lQ-EFO%PGC03k1If||cr_xWn?X2bYVoZ{=~4qnKF%&l?8&#{2K+0#P!)f#)VUDNLL>S zK-{hUz*#vW^jApYe~lpi`}hBU8AsG?gLOwgb!`9_9=;iC>*vrbv!eWTH$G|b6X(PT zM6mu|Zh!Y!TmUNgt()IrSzME@`wu~3i^vZH?^qYFLw=fLlcn+>!dNY@sXY`~-hGm_ ztZ}6II;i?E&hU-p$3cI8_g7`%+j!J`Uz=>76G@FWKABz@+5_pGDyXWwK||bqqWi10 zpMH@<{9TML1E6`iCZYT3W2Dztb@I=XeLJ_YRsJG+wS=Q@NuU zlV7BvJLI|{E%j-;TtKd0*bPlP-M#T!u~AgD>yEO4&q^>=SZSVW)HU54E#1!cZdrhS z)(X{|b6w@Mo_CIjOG3vzE|Cm^S5B97)BGS*qEE#^=!c$l`dlaRKjfB8Jhj+iPZW32a*o94Dk-Gq;?bkfn$sa1&W}VPPtz;&ICj zP^?%IdFoG#-IJ11&GSk1f}FeMAO+T5rcg-6Roim0_qu&KH|# z?P=pG&-5kfbji{tM8x0i7r{fn`LYt7y!;o-R`gG0MY5ZxwpoWr124Yv!j>5 zI>OznCEVX~>IKQd)op!4rvcsMq=wBJ>O_@;i$RogQ1f=Kl>RI(^P#qnBz61G=@}xB zHmqy38Px_;X1=yr$1&nhxhsqpel7lSP#&2X!=Uae8wYo1{07;_hmcbe0x`#;cIPzL z1<}swtbqEl+En=*hZwVrLoxp%^Eiv&v^P)XLj+N*_Kri?5fdIVJj&W9T#3@SDNnwy zU&Y}t%QjA&mYHN=RDX!7ze(1zGx!-Gu*G#KP{(h=8uRu|c>i<4dlSL8S|Ar6HA`!+!`$GW$6)`9QalhP@Zv1J7Poy`j_eC;pCe$vTb#Kz{aN zxRq1I0%-)Tgkzbi@ov(+-bm+|6r-%+LLOzrFI~g3YZ+cK3|W6;hB=NR60rQK8hiiw zK*Pi55`oXuCzpF6D)++OEc$~4bO5LU7t_aSt=Jm9L{FXU34)A3`wM5Kw9Djzko4WH zPrkUX5~*WMm4K7PgC^-vn&M!u0lA5GACs1g#7NrDP!MXEU?jHC2#xr=O8x}g7EUid z=@|d{eYLe=I}*2Vc0sfDK*d~2p3+FrKZFSJLy2K6R|9iN2j{Z(zbflAOQc}RJQ#bV zMS=qf@CW}w$D`<~9zZF6JwSTi89>Q=Lvo}wDqHrpj#=h%IcN;Y-y9-Xk~z&TF<-Mk zuYh;f=0!4BMzY4tT+jQw zzvs|p)sa?@lVw~->K)n!_;tf-aJl@b-j2PI@?!NcIN#TN`~JG0Cj9mGUOgkmC5tcr z&gMLx@@Ssp%8n@2x8-(>DG%x-CEqc@$!lXF|6pw zrP&z=ERdZTO7mdZ&j{KJqPy7HZyU#A&%kM2=9w8{OZwVqnj`V(p(3S-{X1f@XVehD zu)U>G^ZWDr&9AcEZHnt%lII+yf*^hR5}F*UKDgoha&uw^#>clrn~M3yI@+~0r4u@< z-}!y*!iFDgH5RBurRcu_it4SpO*_`w&>FpZ>%g9;VZg~(n{NdIO4n=H-%Go8_iSOc ztHl=Yn36DBd>bwjn2sPz27v=z*aUj=I(`a5N7b7MSw z7yf)TVFo#3S**Q0^AdWZfmBfOqutIBd|j&zO5K-xQBX)K8EydW&YZd#WH=}0qqsQfFcW7|@4ZTp{ z9*L?WCr0oa3brrxX{o_g=LO2Vlhof2N*$xBXa(T4WT@h3E*n7Gl+ja0n~-CJdNWH& zR^i5JIT<$3r2eM87N*ESmg|;OIahwkk8Hm!RXb4NL*?Xxv8WOKHy;>9#1=&PFkP)4 zrzXyss|Or2XO^X*2p?C%+tST;A@ody$}#=T9jZYzCth+jRN(!C)=#Bb)KZ}=tfQsz z&U4o8i>(mF=aHLAb8hcY(olGD)KSQ9qWAYxobiAN&v;HOfsjh|-0o^W1#8YWhnq@i zZt}OMSiR?1t#dh^ecK0 zV^tSreWB4*>oE@IuNlLi);>OgpJr}PAFxeGMfq4xNd@8$-#*%poI?ALcx3O{+%Ade zsPp*P(Bb2-Uj9MWeKQEBSf?yR^H3arjUU6JU6o4JhDUkG3X%5X0%Y@AghBwlQa(0o zfo(%%n!hc%)ghjh&oIN68yr(`BjWcCVqr2NIGF2;cRcl&I4__RGoU~a8vMu9a7n9B zF4KSR8@t?7jAyQJZ+yvprvhi*!0xJZ6Oy&N^J6Z>Z%aK=kB;XSrQF=wIzR~m`;AXf z94Ie_Y{SLZwwSt7LScf27o6++CU1)v%0!w{LEwIYoc5r?-WUcheLFW**F_nwgE{Ze z9=A-~S*MPsefh`_8WA4gTbt4}ALSn4(gk0ih~<|cT;ZxEu!mk87E=&MX?v~^FSIeV z2(qs>7;5oH$~0*{OO!eiA3FSFjW;FKs>^BKYJ_C>$}L0rqR!cbH2R@-=YPxZYOuHe zPvrOH#sAU`{cr5F|1Nvyzx%rX35=dUX0`>b#bdRx-uwg3vePEX8xG`&4lHZ{A7?a%5vvu6UByB%l>lR&~baD)0v)-S5tn1lq{Z5Yy4r4p3kV)Ac9De zfgC3kZd%l^Dj-k;vhPvX{B^H1{#rd`G=FO4{4ICyiIDaj<=lh3APF80m9Z4CWCH z!U_U)TtZ>439sDkR{H$r@zMitY6V41*F-x;uRHgwA6^~0scya-b-~Ou9qBv>Q8&S; zNp%oZiRw$X`f1WP*`JVXBI4e*SsItl^RyW4Q8zO~I7m0XZ`kBtxcM4Xcy&GK)K4a7 zt2LMOY_~pUlGZ9rSQ!F=WUtdr7Kco8sPx#{19$sT{V5mWz|DoI2=WKF{W2R6&3f-UX8ao*t#pq`58kyDi6Lme)JR8#i9m+a+MwM!L z>oxszQVV`GaAnt5$VF>F@$wGf;{jIT%=y{=bw$f1Elj@AJ*z<>=6mb6l|ls%#1FmY zuh^i(cQ@Jl^a96CpXhLOcLi>^CS}Qle$Nf-Q1#(RLJSXGq4piG{ z;y9&ynJN;1`^0-oB_=Zv9HGvx99EM^&^vItD_n75uGqY&=BM>1I%1kGqS~vJ5-zi= zpUNd&u2UQ5a&cUcY<9)jQ{$F!$XHhpd|7Wvw{n*;C}Y}jS53U`0b6~tJ|!zJ^gUZ-+-@@DsHq0$8+K2Ogrz< z1S>n}4rYha-860PK6!gomUP!0%|dks85!kS?N3YP1dd6`7T(MO$w`qI=!3VeYi)KJ zmr)+Gk861id#nQW8^2nVReAnFo674YKrC#<;nCmRFfo?A+a3(OuJsq+e>L{;y!v^1 zcAwt(rBmIS%3k-`Al}MXsr#qSvSYT(zk4L}E@H4jAK9^0BU6Ka&*3$PKP+PQZ5W-4b{6BZ6SJ4)CgXyhah%oFIrt!$6w*pIRT?S|d)?nw z&+s~8gh&lWHT`R5(ryJR(WI{9t-_^X0-)$ks3#w`s|1Z9fI{CSakua{vI2be*5So# zwZS^$U-YnFM%z&?{;2DxjEY`KaCO~sYoi$5XC#>(B-1>YS&RKjsJ*xAqtcfu3VxRz ze#|I9h@`a#*gX3UMk~0RC;J2&P{M-Gh$gy`Qe) zp&Ob}vsCYQHik^MD^!AlWQtZ&8d%#}5ryn%xJSYYLBbO}7rwS}Bd_1pO3y)E-qU@;aJld8z25O~UV~=}FnH2;QuB!WBC3*_%Vz3+RoX=oQ?5 zXgjPWMlCCb0g39heQr}!Ap=Vh7J*goFFgTB=!#?N51jp*l&8+kfjX42)4b5x%WfIH z5$V9+>rf^Gd)m7pD7n8pJN-H->67$>QJ#`KjrYc+v^&$iuIsC9mrb>TFQfgM!1(zO zQzbplVpLkct!O#tEy(Awsgib=WQB2|j%7CS$UY$;j%EyfIX`w|gE0#t;QO)(%XOZt zK-NYsGIpTq?k-m$D5 zMI$}gNj-U%9IHeFoR?RP3}8a1O$^5Hb@m*)QFX56r%T%0`ElWx_GR0JhgQ{8A`1Vv z=yJ()2me24gt{;j7wovTs$i*crpOv9jygE~&mg-3JnH>rU)kOHIf=>}RnzU6lTkg@ z&R6cALj(7zo*TQct=z~GgMc7FtIamn{$9;gbgiAOa z7d&KrX}Ejv-GxjMS=QD3vcFnaA;yE0acD|K#4%#$7#;xOSA>~oR!0>kHG7Oz90ClI zZsh5!pkMZ(P>N>ZxUgQWxY!DA%3fC|=P}DuJrBAkftlvVa8D-2f;50LERueM=4f3-iN#9_HfT5htdt_-;yc}Blg3qO z0rzRUhoayEHv986F@Cpi^Jo6Q^{ba4b2PK* zFksJheZb=ws(3xj6i-_6TiFg$7A_X!*J0>-h0`ZJ2M=Kpyu>aUW7+MhAC^96RPEJ| z6x4;aySWRFR0xt(CG=e3IWFQyo&tRp&&F*Y?w9!MAr zPPeXsBlSn|dBZ6eLY^uLgrgo;H`WpGgD*!>cS(0r>Jkym0xUyDFx797hDkJ22w7zH z*p5DwF~54zCR?gk`}r)c-^8aP_088EhoxWI(0a-IjBUx_dhj-^s~4%4qHgXiR;|2o zMe|H%eLB;VR*Tz|i@Az69G-}%E~ouBN(5Q^qIBU9`{^S2xmn1r-4B=cwi_}kL*8Ru zWfg;$vv7tN=oVQFstrzi+X6Ro76U_U!2wjm(t1uZbKJ)H9go#?-JqRJ!YzkPJ(~_l zeU~|#>x8L7FvOug&6g^AUn-$qyA&wo)N&__Na<|CFk7u;-F^S$;yeO4c!l4FZxbuL z&rBuHgU9SMxDdsf>yVpQ&n)}#^j|?m$vsNFT(b6$8dqT1M;`{V!aVvE_Im;g-*a$J z5!sH&y7>@`fo&_3;;U2bhko@9pHA za80+m?}QY0WD6aVy4>VqjE~MEcgFYzTMp$55dy}V>yn2F>LJW`kW+9Qj#}XZ&RQ znHJ(V2gn%3>DI~b^1~Cog4GPmD?g>ri(Bbymb|nNAqAD1w-I(B$E;Oz@t1*QHW6tl zZQ7}32^>E>XrwY+!*6ApP=3|`A{B0@eq2K!sG~ck1xg+N51J7f9Jjh3+6db8t-2(H4B&&Iyb7#Jp8pm>W0+&1<3@5TnX= zI1M9Stdx;dB%yB$55bt#Y_!#RBI?Hmud!_*sAzGo9@it3U)GvYK_`zHM~v`Ae9Q3q zX-cM%>f+a5)kggNu$%XgA!Tn}b=|CK-W)(`-B7eGNjK zevam2F^mn2zdLd=6lW)vt)Z3IOOD=!cz1wI2M+xWr?KYc)?pr_=}WB_vl*D~k>};$ z2g=KW8{tvP?M;xV>MUD*kXjj{p4T%jvQ?Bf^t4W8@#;?Qaqcc`vUEkcxA+MK3lb1$ zj}hU+ojI=RYy=!kFFA`07mD>!aZRxi?x9uaBD2DQS)2SSIPjF5ME%l8-?BhYSac6x zX7i>%_LjZzsn~hly*noy zQ<^Qyp&ZPr?ZM6;4F-_6J0`cK5G^jlB_+SU9!cjlcKh_|O!YO2H8w+^(egIQR*=El z_}D5~*NS=M($9S1kF1H&n>y@y2MmCX__J2aCVpUdECUsPcBfwAepy}3XVS?1p!+RBnM-{P7vA4Fgt8XW(iX<|sM(ViZJJ*Yn5dIj1axMO&KK1L%A#V7p(Ycr zVfK!|Kt4z&9DNYyo8^y4;XURf*&S=}lF)Cnf zC;mO@@z>Qjke6ut?Y~A5C$crwO3((V!BfnCw9(6B@(JFdT(^ObL>4w31R#H03rO04kS zYqa}>>0S~T+k%h{gDu z@k=5#tUmc($S6`n{(MGE3&{7WZO!1>=)|iCmainBUZ`BbLO5aySZcqeI0+ohgC!M- z_<2vpI*qmch&FQn6e7movu=w)W^6m3g z^lgr27pVu27b7ivIF^*WYjEE3%!%>#FU{Tv!etk#>o16cC1VLMlJ*mSM;-Bw*H2~k zBcR>0XHn(BdDi1#9ud!V4rT99dh~Kv-np!b?aPKitr6v0*Amt{+0M>tJCl3M^t!NPg+(@PC)-FdPP~{;`6^>gwpZyo7j&=L+OPiqh0B zwp*4k#wXze=5Z1Dd0_V=5V{=7t+(%zm?jB=ti%&-N$|lSCru;amq0X%c%$JJOpWc1zzkb|O*jx*& zyRaJ{Rr1P-n^#ottXUh&HUzjdJah2s8N9yzOZyd)L%f(X>fE%$-OmEU2fU<~YIzRM zl{~lTy$wv(RQye6=qU_U(E*O(n|6B}BENj!KAYTk!p2{~1^IgH%~t-pNZqI)+ATX` zu%7ajR__3m2yBmgP}GvU(Y7a^5(dcG%iLhyV&*W&H`IVkjDvs`8-@Gubysh$7YZ9 z5d}$tPemAk*30xre1jPjgHc~F{;m3ldc}#WlEh7f)NWWnQWk_#Fk^fFeVX9 z`OAy5EMDMM7nM;ndPeh_I)0Ksp* z1Tu`negUTrivyR7D0-0Fj|2;C@qhUXrB$xZQ#!j48&$%bBV4x0Ng50Z}d_!~WXB|MQjBp?SP35%$62UWTp&n6= zc4S+6#NRk)8GMG}xs7o4N=1REG`h4|oxM~j0Ls;&Layq?Lmcd4%ycCWq3PU>3tqdM zspOAyN&1`@Pqu=&axnKn@FU?bnhbE4fsUq(0D*kn)p-2Yy1nfy@p-|6T2bx?n;OLDR#hl{ ze^vvNcpLvzt50|*uFft_=)u>ddhDpmA1+4dK4CZm4E??J=_xooV^47&r%Ob%SUfX2 zQr92XfiqTwSkJ-5mM>ds%c=d=emEqfqFL-Bma16u@?${@t^#~;6AnG2pIXotiJ_yk zUsd^r;bXMKQ&h;N%S*@lqYlq*4gxZabrne@dje9VZ~uK=Sf-(}nw)ZNxGPYH#P^k+ za&-kVirJ{H%;Ht{_$1r1Yd5gofW9!T&HE2u?QXWo8D!er$AUuwdgPtr5DWK0OXO@- zftB!nlt2?$@;23+PsuxN+35U!i5vayrQtrr{H^_FLN3~68wxA#tXx;#2JrF?sJ_wz z@zTP9`TEj%DM4fqzT8PNMdNv|*TpMjqIO&0+qYy+N^DfkHX zxyl)}N;jBf@$II9p+dmE*{}PL{oWEJcRfx*XPjv;VL79GmoBHwnelGC$8xR`tBw<^ zJ$`@4>M^DpTs8$Xm}Xr%hxbQiIF8?I;r&eX7w7|pRj>dt1(%`9x51NR!x68_QoR~8 z62BQYHZ9z;X9VosK>>m@R_w$OizQw9I(P22#iMgM{*Dbd^duq$8km^)N9A65ZW=@7 z#gb|6ujEUPMv#_mvjl){jOwcrdl9{RJLO{2VeWps-7d}p{Cklefb76RtN@du^$huu(73jr$B0~6YqM_q%xPCiNmVSi`BHPa19)N-_epMW$^$x`zn*RzoOuYf3Apl~WKlWs^# znyt~vXU6!rZ+cQIF`2CP^vxT3a!W5~tlcidw;n0CdjMz)#r?B$bfOF>fKTg6y@x!e zS@np&hunJIC~4^eSz*~a@@`f(7Y3?qX6VQP4k>Os%S-kdc6w1)vj6e*fq(s4{g-tC z*bDlUa8MZg!Qp8V<<{dcpA=uAKL(n~wS^_W&3@qVJ~uj|w8wnDX33Q7^ri<7b&ZZ% zODlX(o2nok5}0h-Gg5){y8%{IOPTmE&{?~;OG*2<=aBVdNUk|5;m8x-Vww1}JP*`o z^3T{DGs6m{Not)koz~u>HVX)wF_dj>uc!ZwoRm0S_H4evG~(JyL-3<$?7N=(fWCQl zU96-il!>lK`|rq}{^6s_VEC0JwmR3AUU|9d<){(}?J#X6zpAWT|0XF#Ggq9uz6Rk; zGkbWA)%^DeXHQ@v%dawM@JLg3`#Bf+3;=4h&DbZ@HQateY+RH2@fprTp{5SOsn$}t z^rS6x^c#$dT0oZ?hWe5lX5h>@cjcz#-?!iTKy)5h_{l-7l;82aszVy>a|`qNjf$C~ z#}6CW0dru+bjP>n*02@{X(j?`?R!q)>C(auhISOkhY3_$FM_v02f8VWA;seqTg$G> z2dU^gG+YcZd4j^ni-T_^+YM?hJYGd{TCj_ck?EdT@(P^Acn-%b_P|EufiLA=i`n5C z>pjo*MzC ziAXR)QOoj<*(_Sf`M3(c66%d|Wqsd6IMb$;o!XH2SQM z6i2dNVG2fNGz%m(A@gDOU3p`Iy`0hE7*65Ft0$#p4?r;g&BSiYA}CcJtpCG6l-MYy zeG&PkdKc^kzY89!d^V+Cgz>7;T!HjnV)U>%bp9QTDnbYW`o?lac4j$dw`jm`QmzS5 zbJL%Z@_6Tl`halg07YS}d%v$2VCmJ})74PXBt?3hV_c$<*(q5+9&j*7W`7{9wSZQVltqnhTH~HyIRq~#z=EIZ6pGDU8 zo5hR+*@})M0RfQJYM2i|PA;uagLAt2lqk`$saJnU!Aig9d=N5{Ql8Ao4B;9*l%&zb|E;g*0(}k;(v0JQg@i^-x5TT6qwB3X0~v_utL1tf2YV;rADQ*!)Oj^ z?esVTVw}3dRwHO6_U6)lVsNRg!K%odP;ay48*H=-81Use6 zx9^@DR!)Gxo<=B9^p*iP)?&T?+udo>^6x9qr>x=g8>GSgSG>Y1cR4|5sI)!nZT(E5g zr3-z(pj-Mbbe+eKdz;ZnYhplBG4loeyUI;C_5hw@tli6BhCp&r(!-}E<3uu5Zx1SZ2}((Y_~_aGwk63#sHeD>HF zf5<5G!7?Q_tT{YHd)s(}y5a2(s*TPoaF&qqZ;W2lHCMQownwVQitwgfuxdcQxm{}8 z1~YT7OY@&-YsxDDe$UMuUNhs)*|NgmN}V-~M-mtEC2gbXYF5{*_BSaC&_}z}kr?VZ ze9TrEcZWHp3&y86rMuvmEzZc?z$`_qW1K+Z%^H~z;NDT!`as6My&GZXqvKRO zhL!LX)MdWle40YkI(!MUwaQWq2>9qp#rySZ`g>Uhk&@jCCj!ALHvy^@?)vtBfA>L- zNWT-lq<9jGYYt@8-^ja98$|Ap9wm*@w%Qm>+(P% zTRsZ$$7ur7bFmMH@-@2YPEi_1nnOInk-SDLBF80Jn$)i*pgZiXNpkJkAU_JEId3GP zct{mDGLygPi44611bcmCV)giu>~HkZcH4fk*#rcIOX-Pxtq(fn$!L-7g)ZJsjWYNc z=Px?l>hjieoFv7j6MwPCwkp?IA3?Gj8#m6TQ>I$ucL^!2!jwyRsNO!nwM69gmEo1o zTG$voJQsA+{9ND|KLMv6Ttt$DTXOp8_suy_#19ATWZdD=4MeK0-?j<7+_*aYZYfO#CAD834rUu!WFG;(ffXSIVe zzY;{lux#Fll|;Y(fLSRfTu#p58DHuYTT!gY|1VVc|A08O4jqjr+3t~Nmls{^#xt;a z%kZwEbC0U@AGF`mVo7nH3skp?-?nH5*fV8=rI&DAi z+sc&fp2+?frjQh$YU6h%o;cGr``RYTDL?Tf{CTSdP=WsEZ|QLDg`eLVyVWcU5+~xG zQu1h=!xh#12vOIdAg*OfvZNkD;|4Bj6$V@Iik_Iqjr3C3_pPJpjexLEM2|&-Y_|}- zLD%=|!k1kksGb-V25WNB9*$|YTUF7KmfMDnjnXPsXB6R%Yuv4JL&JQSy57AKP$8$C zFrNsZTv_aIDmK-!6SZ_tro^d$gG=qKB|G$vH7>WIh zOfz(;IKrT%KeY=LYqv~&RsLvvvwmGF1YW+M06uwVuV@cd2Z zyEIiApLSN$Bk{-Q%6F9&9QybSPfgYmNR8St|6=q@XFS3<>+~+D{DVfkGX{hB;UWNTj4Vr7vqzJsj?g{a3 z&1O5Jqggaa3eVpjD@UCv5(whE(EZr0A{Hb|K;dbX2j*=PbTwSpy0@5dzZB*0Gw=2O z-1xSz)75df6P!hcnI}^pVkAl23pmAKH(J(>8XnN)=7H zj0AdF$y4_N-HsegoUnK`n8>0eMRf18?UW0ydcH?6ZHyf+K|>8Ln2(dCMuVg%sTY6n zA>E^IR0un`RL8Z^ZvkdkW+V3l|taEJF6nz=EsEb#$ zL%1fQqbhP(h?aF*$|?s?BW}NJ&$aKnjeeh;@KN{Jr+?MfIY5P{GI`p9!Z8+8&ZQBB z;QapLCP>*qFbT#e^~%5eUE6bU#XmZ73-*lqQ`cL4W-;yV(QhnH_%67dGMZh)g0a~h zfBZ}!ihvz>&&QZhNRxaLeTz&S6w!p@WE4YJT3Th$Q*X>VZ?I0&tqxA!yb~>U@*hb2 z$T}kYCne2`G&pdlc-hoy8TG+-aAca{+_gv;?fm-roOHQX@%FEVuG2_J@w!t$rA~7! z-zeyutVZe6f%;G@A2=g@XSgD9lkt}@kyQx{q1e?7HD9S_iTWhXVED37c`%i*wlCkQ zXUg>DfTz*{LTO^`_-`uaeKLIi4|eHrY1g^iX+?qK6_u02#bVO^>2qhe!TCNiTgkH~ z!TbKkFUHH|%KY~vMkPQZuZ(l=o(ns(yUfPME#|1i7)U7Xsm{;cePJ&!em&O_Os!@u zz}apC%?H<9iTS>ODI+_MA}AUbk8To$LH@nNr%c;MmH$TfU66?f9T9M| zkT;>ed9FX?y>ja}N{su6)mnbwPs9JxopB(sj&!{K4HQIr@LMfz);Pr7&cv!~70X-r zUME!rr(oGLOn?s&@_iDV#a=xqu>FQAFkVLHcX*@Jv?-`WjnR~o?ZlfH+xkY;@x6i{ zS8s3OS`Utx2{lK zx#@{{{F~)Gqlj!vv~`Rk7wn&Z{D~@?i4+7K*)&7v{MLsC-0#{!0z13lws-d?QMf2Y zbgYf0CB74iA1M0wHF!y7m)^p9@^|8DdrK0$Tn|;2e_Lkopw&g@nJ4l_59~kZER{Od zqUII!9R*|Lh>@@MPF*!9vjQg{2&o*RJ#2B$07EzOhIiE*dE05@=A#yn{ra9rm^f>p zYRh55?}^0&YeI7cR~EZVBTfa-fWbCu3{83fnpjOe(ff%>(7A!6WQj~*jGP=>{Ww&z zl8~NMj>}upoNqT^8*#eo7;vF9KW~1b?TesH`jym?OD)ocSRQ|Fo z%F$iA%ZwH+TU0dL^lBCxsZk>S?oQ?=Ff=j3_2?G~5|(v8n3!h~J{Qi<+|T!?jNNY! z;9I;K@$)-`9enpPVhsSUy<+T=A+)H9z1`*JIP=HUKhj7F+P?*bw9@->tX~JBEKu3` zhDR`1$vCX99*K16s6v!rXfoQF;u7FhpWEHyM!PmY04(aKlga!I4|LtqUI=NXfiJIL`RKF7`5oM&B|KY|EfoJ_xh_bzK5M)-z&JRlzURv!-L*a zvD3r;QDk;X&z7iKk8Di|{4A5uLL{%i7_Q+UQ{B9ApVJK%@;&mjf1*P7Z*8PZoMdin z#&12^Z=&k^8L#*632P-hU2nr=RVyqh~?gFdIWP1&KFWT zp7-f6fw_}-l~fIugsT<%x<_MRPMQ!9=hnd6m5NR8QW^d+TxDs4csVRIciZ z^eI{@Gw!jeFD5Q8V#K+_kNV{)o#gTenMWGVF0_{1`y5KFslM`M!91H(K`GhP+wE*k z=TdonP#-DC6-B2Veoj%lHavOv|cO2q!kCjd!&T*=09#&$#RBO`Wq#_!k#g5VX z8=QSXYDy`H|Lix$50ob+ag9k1sK<`?2gS$DN=P)H7bEN|0E2wuhV^qxak< z;eRp7>S-~{e*u z@N>+33i2V{R!eg=JAdJAS)@~lxsLVzea@t%5s(mcflR}d_2exY&e8i`-rs)EG=on~ zhTZ=|U{eXw5u=g`39}%5U=2C-S5_nRbK(ATYJS|yj76hz?&|%PeaEn5w4raZTlfqa z#dP~K)aOSk;pXbq{Wj0jEl z%518(c$?a6c>mnZUHO|!FOrob1RSXrt?04|ms)EW2ER@qydS)En0Re_Y1ftFPt>>u zHT)GloFfBsUHL63%yrEgnLRtO?%;Yd_Z+Qm+a#0-*ZJ_fW#&%}S(3=cgeODIzcGh( z2*3LmB)<-wMrR$#|hQos9OZB^L!QHKkpSDlR zpwr~=&fBPl$c;(KgS6Gc)G>{Mz%=QJjjwU- zbdJYI5}e)pngzW++d+fy@Lu8svec!@NbQ)W>&X#xcS4nk0(fNZgkhP5)ZI_ud%dVI zAcv8>{;OL1l}Z`WNn&j&*{cqu;PEMHuoXeA(7m7__U@V=@qkVwIQPLtMLLBkBJ9Kvx+VrPrM^T%aMJ9YEzG)9#YFv_4 zk}WfnuerYk<+<`@6zF|F*>X0%!pJ2P@8O7YP9#rvHycMqw}EsXTh`| zYUH^3<I_1CS3Ab(M!SnP6EKbWAw zTOKgtC)j4WF+y^o#+>f>MChUlrn9op z2GIc4*dW7Of}+>tW!FR{Q79KRtXuzC5LFruU(jP7xcC0y?l)LU-azj~37)6brdcezMv-p}rFW*VFhK2e1#8+sRn0ooo0un(BY&=$o>b0|w+(&| z^xV7Z%?O2eUxL3FR?kJ_g)a0Q8`h*OoOmpP1zQi6;Liz;rcrvsl>GKM2m1u{I=ZsQ z+d}Jf;66Y1QjnK^Awm7BdxS_Cg7PJaAUuaQ%{|$^uW)vQ7d_wfYUBh#cI~NWP0kS0 zIM!gQToW8<{ZaCC$Dp;JS39V=R<#uu9ve>aA``+^|2O1#Qri0d$+373Zg*&w-LH}V z9P!F0#N+u_k=l9xoNgCOn_B<^-Zp+qvDpocxz;w>*;d56g@K7b{dx|sqSI0;Ul z_Dt|!cU)F``)~CYq-P)`;ER(bQD)Dy(k%cm1TpSwV{38rG~9JAjF0trar9lh>);kF z)t}5C0lw8->G`(SX7pWJjenJg(|A^MPZJG5@@>HT{14^Ka=M^T1KQJCl5>bcD44Z! zPPUZNS*m&*k6N)uYLYH3+l}A?vYHBe9%sv}(uk%39>K9YdV1Ij`)d+NDLPZ)5bINk zi8JQD)Mzd;3_;mahCtnl`EY1mLlGz+^x9)&!Kh%cg$ZO-Q_tvAD1j6%g_!U(-JtIcP&84G z-8Q}22O0(o=#Qj1uPC~}Ys?u=D?sgVtcKDDt`&z=u9kA#uArJ`A^=G|Es<44vOko7DhplB$7cgf(Vj979^~a zgJgEeph$)#EIIoV36g^dE|PObK++O~Wyu+dOU`M@Ir**ky?eF3@_yg_Hq8JS2?o!H!NbF&Q(e<|>^Dh)(2u*&0-h>xXJg4e`` zAbCQr|NIucKC%~-0)&6Dt(TkSi^9&3DIqb>fk`ktn?UX%{VH@vbER&|mLEeEqcr|x{ z!^lYFU4jTzz&yA6R+ZpjP8qK-k^A5hL`0j^oT7D&IH**&!n$X?sO#Zo#y40^SbEv$ zLJU=9{6>`Q6pc+YEx*MG1VS-11kEZ9WSgoIkzo|Bq;npZ8w|=f51$;d}g8kh=h}W-}Sh z=DNhrAH^w;qH^BdPF0rZn(L{aR_O*>5jySHu#ObY; zLs6ga-c1dSennW0mqOg`kopN3=zU0PpU zn8k-HFLC&fx=uSbmHntRiwZgZOmP{1b;3B(MF@3F)kckFKEqR0&m8ia1@M$;NS6;4c$vv*+w=Hz_^9{} zO_dX29L~C0-Spylp;3!b{;I4F&TW4e_{C#`@Rs2=Vv*;w%=UaD1&REH0@Gt>yvlns zBYa`hZZaW>i$wJbqIV*Yv3peT<0cSTGMS#aGXi!(aI4$8=ef9KM7^vlqXiiQ6T~Cu z2)eJ605qB#Ma0|d!kZL{3ayvowo5?Agh?K^Rp!7#1uMyC8)E~5F4p1_?fSx`%$6fV z@y0Eqci17L8Tr;J0VBD^u)NPe8g2kDzQG}=pPv(^>&2hIgZs+=h@qGmN9T2- zmtu&19AYOc-w4Esreu;AG3*bhZ!*zW;|D7bKqr%Pj>^Xq1@HCP5KWTW&r7gI-!|}L z>L1J9EEEOawQ=XC&_3ZX){#R1)0wSy(Cq?hZ0w56DwQ*lJ9U#zhj zF{}7Wy~NSH@heE*i5Lai4YIMY&>-O4wF%RD%bw_)rHZHKqhZ_X?mgI9d$bNE4vPd9 zbtItlHz&~fC}$pm8YB2$BzvyMpZhBKsBJu?Y(&4olWq6LCu^EJzh)P&sNikE8Ibgb z^f(7z(awvx$W&MzbEo6(Fn@HM!QHS7J+H~=5YzAOC& z7b=fn&<_)#Y?lZ_@^5hn3_ctmj&PWa%ge&!N#FNW_iW;9{5ox1Ix4{~r=wjHtnIFV z@m#G^6k8Vx5|LxRNXgql7t=Jqx^Y>2g>=DIFwI;)1Z{DBJehqsV|q}>bs!Ln+26S3 z8}W`SM=Yh(>0w+MU=g)roqyVWFU`vKHs5C8Wf6c%eta)O#54t>`;fzbKhke96{mTd z5o4e^#hpc=&p8jU33R=SV)~wRJ!aC!IB5hF?sIl~QBm&|$D4{vbA*}B($oX!h>IGT zb6x9A#!An>B1gU$G+iqMqJ3|=qHctP+2Mz=ou0vYwJr6j0WHZ9SKSkdm+F1~4ucBQ z0#6k?kp>KP^J|G3K?^T}mW-s%*39~YOktw?1x^n!{u#8>r!?O$m*`Z}5!kpK9um*H z1}X3IKL^p>pl<9MT^My^Y~Gyh z)58a4i!yvPL`X!ZF>_vUR^YqsCcKH+q<+bgn{*Wos;C`5D8@gRg9K9SPF7N;YZoaU zJ_5VddN7_dvV96f>ZA?yV)DCmf>J1NSxsonmWwh5Wuuh9^>kad&LN0B&zkdWU14;R z)RcwDji~Z%&Ujb%2UZ!}(Q~>}Gq#MFaN^ge478KPQp(cksTcs6t0+P$lPIGlXNB5o6XyYK{k!7=*4+Zm|tfl)SrK1*UcMGMjTjK zZr)3cgCp+01-zb&!a;aHzX;4>6Sxyt3Pz+BFNP#F30yr7)WrU6$v%?9(_t2QOq^H?4D4 z>z4_JySFXN0yIQUCdZ)7()`~z$Q}@cz+5(Xjld>DB_oOpB+Yk!V99j>S*if|qC z@+wAcXm$d}=Mym@wJCUk#{nnAu`!WIbnX@VN}+S&P0lvP%!Sb0n9`_Y9hFjCSFk8s z3m-%S;MEb*1k%lQ%o*)dyXyYHY3LVQz5f`f2sbgt4m7v9=$Iwm&}!z(Jk7))%xhm{ zzlM9~t`u_F;g7jA`3fSYJ%9ySGeN%e4i{22hHAt;n0>(tfXuu?^z&TfVu`nnUu@+4 zZ=*xPQt^7k6RK-^eWnc@p5Jc{<*Fej7Y!}unat{l{Z{N0ySQ@|jx|NH`hS(0-8C&JUQEv!H1e0~DYFk|yE_velGFnc4HIP!L zoC+|`bv(}N@hup(fsab0vem{fA5*PCDy=XDZc|@U(d|~muJ(??OQojMo1mh%oXd6$ zjZHUse5Sp^y3sl_ndZKJBsiww6T00`RCoKq$_`<+3v!}lN+S-t!tlD?ZQ49sm>8mQ(HKU6 z;Lkm^JWhob>b4CnbW6$XoGOE0 zz+|meTzPU8ZEfI3kCn#Sx*pdTg85ackH+nFbh)XkzPlPpv%f6>({TtqxcPQd_3TjC zq&zO;r2sFxTx72l$e{@esUho1?x`_99=!&cGn#ojqiJ2PO)e3ye_&C(stY1%jnj55 zT3OhOz`~a=+$dmuLCk7``z)~dR+pD@6`WT@bDpz{uq*mtX##qCU0YV<^wOBZV8ua0@E_8Z-inuJuOAk2CEH-G_%RKcTJ_2E~ znZQelJhjdQx}TyPzU@yC&CyUNynB252_$KJdpZHEu}$NhA8}cS?2Uk++zXunTV89t zmmu*Vg2~9QY6R_3^C_hT`F^n}(ASZ)_9uNa$6rr|Xy9F;Do%?t$`yN{iYuhs9-`p| z-RTvd!!lUKPT4`m=jkl55flPk%qQoQ{O+1BQsmV2Y2&;gd!0vD=JpE{578Ly`^!Sb z3E`ws&M+nRu*%+SwnFU{#PM#?YKcz6H1iqglyf)^n zNUhc3GdO>dfqGjx;o`;lhUWiUlt?`z8c}IZC2X5SCs`>x;+PPmje0yR95%O}$>i zkpcHS#8>r1d93@B6pk&`H*~Ss4PBIktD>DQgY(#{)7an06TdWQWTj2-rI~$3z}mJW zC8S?5QW!<5U1+V~O^(1sl2qKGq*b794!SSxQ5Qa&n*ckus&$#?cx-pSsipLTZTrGM8@<9@`le4zH!?0Em4)?Clb&eRS} zVVk@AY|;C&hxkliEDU<>G4lgU5c?V&e-f`%731)wb8WaX+*guIU~)NQ&pFBgo|3YL z%6Y>2b_6eAtT<=dD#M&k;rUXm(ldjD5pJY5Pl&^o#jb=gkf>k=zvGje)7f-Q(x3_(ahtfLYkNUE)l))6Sp%|v}!J6mvfoP5_!k#uJYy&845mX`E4 zvInOO5)Rr<&Jr2-D@*G$JvHV*0Kl=}rS_>H0DdC25^X2#^jB5LJ%&b=y4HAy#4`YY z4I*vQjW0B`a)9@BE-E!NzUmE>)Tlt*Q&oCXAikR3>{*x+-}(})HLemDsR#|zQ78n= z6h@s6DK6-FmWo+o#`h z8<-S!AmlD-S#iSHi#&sE%xKgXv3;!dP8FQEh+0{=?4|Gjv~|^f;N)kK<{LRK?Cloj z*XA+FT{!GQry(FVc2=6@S(Rz;7NP-*&ohd|>1um!Mkw3r>nt@(nd9385tA3!p%fFo zc#-7BL>=pRH0qmK+tU$x)WvFajD~;C{Y+u=66PSq!4hggkgraZ@UfDhPPBy8Bx3PR zJnJ*3@nQP1VtMBkZ=loVl*y;e+5?HynrnOBp6^t_U-|~w(XX~}M*8tvTL&MiP<_D( z6N(LF3)!0&kNA4)VR~laSo;$_)(|cdYa>r={lzNoG_^^C-e+ZcxvxZc4ItHz!)er~ z-m^`F3)mc5_fJtvFv`3Y!p2+nlvaR|EKxY8*R|~5plj!`oxB>;q-Bkm^#@u0i8G&) zv8KAy8vB7iuu`gh^y>U}9#3Y90&3%8m^~{uh3MCX6;y&lxgS+qLnmXHJ~`z!zoVc> zQNfp{$zdG+d+|I0sT17YE9t%Q8rwOPA zOBqUu#cZ)KT_~UPp>>K6h%DGfixz9Tl%MTfueyS=P5u7I^C#}Mek$!Z?LIN=A16OG z(iq8y4xVzd1M5q?$=ghPy43&gcjT=Mhw%#9bwj6{Z6-A{q;9A~hWr&(*BS^S1n(XqB!DE7AUCl;?snRVVH+Jxh^S!(-)QpN^c zG$t9Rk2UUpZQbeL60d}PJh@FiNdAfBy_F=s#exT* z$`oJ8wuP@%xCXTf0IWDMQv_7R$K3E>%Ylg9D^RKvSBDoo23se!5O*tEi31y&sMtHn z%`y}7wS~llRGxUkL~7VZwc8Bi1Uo=Hp+v526VXv4Hvy44H=#Pf)&tmAM+MyGyXc8< z)4xJ!(cGyt`FiB}GBO1Um zIFgyWN8~33Rw?T^<*G{A&4&E^d#uj(jOh|~ktVd9=1*a6VvP;uatWonp>z@JS%@Zo zXYv?LuAPBN8O-wEadBqoU1t&cegn>rz<(PFNHUH=J`2NK zf+V!Qf3(VS_ysG$|LO;pB_uTmu%F*Obkwe^s+3#c728W5@e5e~7loo;#xyg3$X`~e{ zY7_kN>W^4Ty{PMiQj1n^GKGKZA!+wpUNj&AXFhqx)FDb1gB!FIupY@is?+pl)u)#s zalzNz`}D4R&(O)QuKqR{p!InX`u3CROPy5a@EIV6V%Fcl0i`5-FB*!GNX;@mMI;Hf zE5q?Id9<@G;d`NgO-2unm{c4S4xdBJQNf?4LkihneZ)Hsr@74GUGiJNrBCjwj`f?j zh6twwdCX|@ZEECVg3N2CmIs)VT8hjT*031tPVeNt=g{US=f@!l@RCuz^Zs@6fl$*Q z`7O?lU2}c>11l6t-Me_qxUV4j4_XI*F@X1vW3GnxZ5!CowD37d(BmrjGR_@Wc{_3j zvQHiCWH0V*Hag{I)F`7N1<1$?eVq2FAa7z$oi{r=#u$)w zIZglFVbeCMdC1TH!=G^#`TcF8p8QQH1RTJ0RD!lKUkvN1D8Y|HA8{GaBC?$IWMpNY z`RdK!vyiag+AB?|Da*M#F;Ys=S!W>ZZd+}*EW*uQ zi45j97vEGDaRqTYeX79@%$JK8v$G1bdS z6)4@Y5)6Et@6jvhoz%?3GI9wIx&^wwS|k1_B)7bz&i_-_$~sLJjmq&C!JC{1H$Mae zlC9UgK3fA!XWmHMe+Omgxy(2i-2ylS5|9C(G?vRPa<^M&M`hO(1$hb&gglgn6_j|E zTGGXk0RAXZs>ab*uQ5vf=TO1V|C9X8zw=}6kNV*^CGXnjN@s_4W7?o?EKDv%pBEP6 zrFvZBn#7Nojx-W**Ru^#h6{#Hj~&A(CU9`8NGqn zhg(g7!K86*EHT``M7sqt%a^k)?1a8Un9Ax)p!WsnGKYDxAjx(A1t@3hXy)#0I($Z= z+3s*Bo7lzurz7nMkL&N&;s4ZU3Q*ZQf(mL?GM;e<(@i^J9Eq;@W_7pMB6S`XQ9h}e!V;Gzc zvt8VnNkjj$R$6~+^#0#%{s|ZV&7XhIjekjYPF|{)0O8jRE@&!+t@4Yu#UaQ}IaV@g zenIX|3JJd7{W5J0qubawrx_K7UcblbJ(pBg4oAXi)U_Q0NX#%gs$BOUWki0ntwR2X JJ%|06_&>z+PgDQ^ diff --git a/plugins/KeyboardioHID/keywords.txt b/plugins/KeyboardioHID/keywords.txt deleted file mode 100644 index ddefd30dad..0000000000 --- a/plugins/KeyboardioHID/keywords.txt +++ /dev/null @@ -1,201 +0,0 @@ -####################################### -# Syntax Coloring Map For HID -####################################### - -####################################### -# Datatypes (KEYWORD1) -####################################### - -####################################### -# Methods and Functions (KEYWORD2) -####################################### - -begin KEYWORD2 -end KEYWORD2 -click KEYWORD2 -move KEYWORD2 -write KEYWORD2 -press KEYWORD2 -isPressed KEYWORD2 -releaseAll KEYWORD2 -buttons KEYWORD2 -xAxis KEYWORD2 -yAxis KEYWORD2 -zAxis KEYWORD2 -rxAxis KEYWORD2 -ryAxis KEYWORD2 -rzAxis KEYWORD2 -dPad1 KEYWORD2 -dPad2 KEYWORD2 -HID_SendReport KEYWORD2 - -####################################### -# Classes (KEYWORD3) -####################################### - -Mouse KEYWORD3 -Keyboard KEYWORD3 -RawHID KEYWORD3 -Media KEYWORD3 -System KEYWORD3 -Gamepad KEYWORD3 - -####################################### -# Instances (KEYWORD2) -####################################### - -####################################### -# Constants (LITERAL1) -####################################### - -#CDC -CDC_CONTROL_LINE_OUT_DTR LITERAL1 -CDC_CONTROL_LINE_OUT_TRS LITERAL1 - -#Mouse - -MOUSE_LEFT LITERAL1 -MOUSE_RIGHT LITERAL1 -MOUSE_MIDDLE LITERAL1 -MOUSE_PREV LITERAL1 -MOUSE_NEXT LITERAL1 - -#Keyboard - -LED_NUM_LOCK LITERAL1 -LED_CAPS_LOCK LITERAL1 -LED_SCROLL_LOCK LITERAL1 - -KEY_LEFT_CTRL LITERAL1 -KEY_LEFT_SHIFT LITERAL1 -KEY_LEFT_ALT LITERAL1 -KEY_LEFT_GUI LITERAL1 -KEY_LEFT_WINDOWS LITERAL1 -KEY_RIGHT_CTRL LITERAL1 -KEY_RIGHT_SHIFT LITERAL1 -KEY_RIGHT_ALT LITERAL1 -KEY_RIGHT_GUI LITERAL1 -KEY_RIGHT_WINDOWS LITERAL1 - -KEY_UP_ARROW LITERAL1 -KEY_DOWN_ARROW LITERAL1 -KEY_LEFT_ARROW LITERAL1 -KEY_RIGHT_ARROW LITERAL1 -KEY_BACKSPACE LITERAL1 -KEY_TAB LITERAL1 -KEY_RETURN LITERAL1 -KEY_ENTER LITERAL1 -KEY_ESC LITERAL1 -KEY_INSERT LITERAL1 -KEY_DELETE LITERAL1 -KEY_PAGE_UP LITERAL1 -KEY_PAGE_DOWN LITERAL1 -KEY_HOME LITERAL1 -KEY_END LITERAL1 -KEY_CAPS_LOCK LITERAL1 -KEY_F1 LITERAL1 -KEY_F2 LITERAL1 -KEY_F3 LITERAL1 -KEY_F4 LITERAL1 -KEY_F5 LITERAL1 -KEY_F6 LITERAL1 -KEY_F7 LITERAL1 -KEY_F8 LITERAL1 -KEY_F9 LITERAL1 -KEY_F10 LITERAL1 -KEY_F11 LITERAL1 -KEY_F12 LITERAL1 - -KEY_PRINT LITERAL1 -KEY_NUM_LOCK LITERAL1 -KEY_SCROLL_LOCK LITERAL1 -KEY_PAUSE LITERAL1 - -#Raw Keyboard definitions - -RAW_KEYBOARD_LEFT_CTRL LITERAL1 -RAW_KEYBOARD_LEFT_SHIFT LITERAL1 -RAW_KEYBOARD_LEFT_ALT LITERAL1 -RAW_KEYBOARD_LEFT_GUI LITERAL1 -RAW_KEYBOARD_RIGHT_CTRL LITERAL1 -RAW_KEYBOARD_RIGHT_SHIFT LITERAL1 -RAW_KEYBOARD_RIGHT_ALT LITERAL1 -RAW_KEYBOARD_RIGHT_GUI LITERAL1 - -RAW_KEYBOARD_KEY LITERAL1 - -RAW_KEYBOARD_UP_ARROW LITERAL1 -RAW_KEYBOARD_DOWN_ARROW LITERAL1 -RAW_KEYBOARD_LEFT_ARROW LITERAL1 -RAW_KEYBOARD_RIGHT_ARROW LITERAL1 -RAW_KEYBOARD_SPACEBAR LITERAL1 -RAW_KEYBOARD_BACKSPACE LITERAL1 -RAW_KEYBOARD_TAB LITERAL1 -RAW_KEYBOARD_RETURN LITERAL1 -RAW_KEYBOARD_ESC LITERAL1 -RAW_KEYBOARD_INSERT LITERAL1 -RAW_KEYBOARD_DELETE LITERAL1 -RAW_KEYBOARD_PAGE_UP LITERAL1 -RAW_KEYBOARD_PAGE_DOWN LITERAL1 -RAW_KEYBOARD_HOME LITERAL1 -RAW_KEYBOARD_END LITERAL1 -RAW_KEYBOARD_CAPS_LOCK LITERAL1 -RAW_KEYBOARD_F1 LITERAL1 -RAW_KEYBOARD_F2 LITERAL1 -RAW_KEYBOARD_F3 LITERAL1 -RAW_KEYBOARD_F4 LITERAL1 -RAW_KEYBOARD_F5 LITERAL1 -RAW_KEYBOARD_F6 LITERAL1 -RAW_KEYBOARD_F7 LITERAL1 -RAW_KEYBOARD_F8 LITERAL1 -RAW_KEYBOARD_F9 LITERAL1 -RAW_KEYBOARD_F10 LITERAL1 -RAW_KEYBOARD_F11 LITERAL1 -RAW_KEYBOARD_F12 LITERAL1 -RAW_KEYBOARD_PRINT LITERAL1 -RAW_KEYBOARD_SCROLL_LOCK LITERAL1 -RAW_KEYBOARD_PAUSE LITERAL1 - -#RawHID -RAWHID_RX_SIZE LITERAL1 -RAWHID_TX_SIZE LITERAL1 - -#Media - -MEDIA_FAST_FORWARD LITERAL1 -MEDIA_REWIND LITERAL1 -MEDIA_NEXT LITERAL1 -MEDIA_PREVIOUS LITERAL1 -MEDIA_STOP LITERAL1 -MEDIA_PLAY_PAUSE LITERAL1 - -MEDIA_VOLUME_MUTE LITERAL1 -MEDIA_VOLUME_UP LITERAL1 -MEDIA_VOLUME_DOWN LITERAL1 - -MEDIA_EMAIL_READER LITERAL1 -MEDIA_CALCULATOR LITERAL1 -MEDIA_EXPLORER LITERAL1 - -MEDIA_BROWSER_HOME LITERAL1 -MEDIA_BROWSER_BACK LITERAL1 -MEDIA_BROWSER_FORWARD LITERAL1 -MEDIA_BROWSER_REFRESH LITERAL1 -MEDIA_BROWSER_BOOKMARKS LITERAL1 - -#System - -SYSTEM_POWER_DOWN LITERAL1 -SYSTEM_SLEEP LITERAL1 -SYSTEM_WAKE_UP LITERAL1 - -#Gamepad -GAMEPAD_DPAD_CENTERED LITERAL1 -GAMEPAD_DPAD_UP LITERAL1 -GAMEPAD_DPAD_UP_RIGHT LITERAL1 -GAMEPAD_DPAD_RIGHT LITERAL1 -GAMEPAD_DPAD_DOWN_RIGHT LITERAL1 -GAMEPAD_DPAD_DOWN LITERAL1 -GAMEPAD_DPAD_DOWN_LEFT LITERAL1 -GAMEPAD_DPAD_LEFT LITERAL1 -GAMEPAD_DPAD_UP_LEFT LITERAL1 diff --git a/plugins/KeyboardioHID/wiring_private.h b/plugins/KeyboardioHID/wiring_private.h deleted file mode 100644 index 4f06421917..0000000000 --- a/plugins/KeyboardioHID/wiring_private.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - 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 -#include -#include -#include - -#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 - -// edit by NicoHood -#if defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega8U2__) \ -|| defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega128RFA1__) || defined(__AVR_ATmega256RFR2__) -#define EXTERNAL_NUM_INTERRUPTS 8 -#elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644A__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__) -#define EXTERNAL_NUM_INTERRUPTS 3 -#elif defined(__AVR_ATmega32U4__) -#define EXTERNAL_NUM_INTERRUPTS 5 -#else -#define EXTERNAL_NUM_INTERRUPTS 2 -#endif - -typedef void (*voidFuncPtr)(void); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif From 6f470198242a941e8ffa2419a28e72d1d60a8c24 Mon Sep 17 00:00:00 2001 From: Nico Date: Mon, 8 Dec 2014 17:04:56 +0100 Subject: [PATCH 068/602] Adding relevant Arduino Core files --- plugins/KeyboardioHID/CDC.cpp | 211 ++++++++ plugins/KeyboardioHID/HID.cpp | 518 ++++++++++++++++++ plugins/KeyboardioHID/USBAPI.h | 244 +++++++++ plugins/KeyboardioHID/USBCore.cpp | 699 +++++++++++++++++++++++++ plugins/KeyboardioHID/USBCore.h | 303 +++++++++++ plugins/KeyboardioHID/USBDesc.h | 63 +++ plugins/KeyboardioHID/wiring_private.h | 71 +++ 7 files changed, 2109 insertions(+) create mode 100644 plugins/KeyboardioHID/CDC.cpp create mode 100644 plugins/KeyboardioHID/HID.cpp create mode 100644 plugins/KeyboardioHID/USBAPI.h create mode 100644 plugins/KeyboardioHID/USBCore.cpp create mode 100644 plugins/KeyboardioHID/USBCore.h create mode 100644 plugins/KeyboardioHID/USBDesc.h create mode 100644 plugins/KeyboardioHID/wiring_private.h diff --git a/plugins/KeyboardioHID/CDC.cpp b/plugins/KeyboardioHID/CDC.cpp new file mode 100644 index 0000000000..5d4f2a0808 --- /dev/null +++ b/plugins/KeyboardioHID/CDC.cpp @@ -0,0 +1,211 @@ + + +/* 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 "USBAPI.h" +#include + +#if defined(USBCON) +#ifdef CDC_ENABLED + +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); + } + + if (CDC_SET_CONTROL_LINE_STATE == r) + { + _usbLineInfo.lineState = setup.wValueL; + } + + if (CDC_SET_LINE_CODING == r || CDC_SET_CONTROL_LINE_STATE == r) + { + // 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 + + // We check DTR state to determine if host port is open (bit 0 of lineState). + if (1200 == _usbLineInfo.dwDTERate && (_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; +} + + +void Serial_::begin(unsigned long /* baud_count */) +{ + peek_buffer = -1; +} + +void Serial_::begin(unsigned long /* baud_count */, byte /* config */) +{ + peek_buffer = -1; +} + +void Serial_::end(void) +{ +} + +int Serial_::available(void) +{ + if (peek_buffer >= 0) { + return 1 + USB_Available(CDC_RX); + } + return USB_Available(CDC_RX); +} + +int Serial_::peek(void) +{ + if (peek_buffer < 0) + peek_buffer = USB_Recv(CDC_RX); + return peek_buffer; +} + +int Serial_::read(void) +{ + if (peek_buffer >= 0) { + int c = peek_buffer; + peek_buffer = -1; + return c; + } + return USB_Recv(CDC_RX); +} + +void Serial_::flush(void) +{ + USB_Flush(CDC_TX); +} + +size_t Serial_::write(uint8_t c) +{ + return write(&c, 1); +} + +size_t Serial_::write(const uint8_t *buffer, size_t size) +{ + /* 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,buffer,size); + 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/plugins/KeyboardioHID/HID.cpp b/plugins/KeyboardioHID/HID.cpp new file mode 100644 index 0000000000..75c37b24b2 --- /dev/null +++ b/plugins/KeyboardioHID/HID.cpp @@ -0,0 +1,518 @@ + + +/* 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 "USBAPI.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 + +#ifdef 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 + release(c); // Keyup + return p; // just return the result of press() since release() almost always returns 1 +} + +#endif + +#endif /* if defined(USBCON) */ diff --git a/plugins/KeyboardioHID/USBAPI.h b/plugins/KeyboardioHID/USBAPI.h new file mode 100644 index 0000000000..2fab957f93 --- /dev/null +++ b/plugins/KeyboardioHID/USBAPI.h @@ -0,0 +1,244 @@ +/* + USBAPI.h + Copyright (c) 2005-2014 Arduino. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef __USBAPI__ +#define __USBAPI__ + +#include +#include +#include +#include +#include + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned long u32; + +#include "Arduino.h" + +#if defined(USBCON) + +#include "USBDesc.h" +#include "USBCore.h" + +//================================================================================ +//================================================================================ +// 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) + +struct ring_buffer; + +#if (RAMEND < 1000) +#define SERIAL_BUFFER_SIZE 16 +#else +#define SERIAL_BUFFER_SIZE 64 +#endif + +class Serial_ : public Stream +{ +private: + int peek_buffer; +public: + Serial_() { peek_buffer = -1; }; + void begin(unsigned long); + void begin(unsigned long, uint8_t); + void end(void); + + virtual int available(void); + virtual int peek(void); + virtual int read(void); + virtual void flush(void); + virtual size_t write(uint8_t); + virtual size_t write(const uint8_t*, size_t); + using Print::write; // pull in write(str) and write(buf, size) from Print + operator bool(); + + volatile uint8_t _rx_buffer_head; + volatile uint8_t _rx_buffer_tail; + unsigned char _rx_buffer[SERIAL_BUFFER_SIZE]; +}; +extern Serial_ Serial; + +#define HAVE_CDCSERIAL + +//================================================================================ +//================================================================================ +// 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) */ diff --git a/plugins/KeyboardioHID/USBCore.cpp b/plugins/KeyboardioHID/USBCore.cpp new file mode 100644 index 0000000000..b4f7bed7e8 --- /dev/null +++ b/plugins/KeyboardioHID/USBCore.cpp @@ -0,0 +1,699 @@ + + +/* 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 "USBAPI.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 u8 STRING_PRODUCT[] PROGMEM; +extern const u8 STRING_MANUFACTURER[] PROGMEM; +extern const DeviceDescriptor USB_DeviceDescriptor PROGMEM; +extern const DeviceDescriptor USB_DeviceDescriptorA PROGMEM; + +const u16 STRING_LANGUAGE[2] = { + (3<<8) | (2+2), + 0x0409 // English +}; + +#ifndef USB_PRODUCT +// If no product is provided, use USB IO Board +#define USB_PRODUCT "USB IO Board" +#endif + +const u8 STRING_PRODUCT[] PROGMEM = USB_PRODUCT; + +#if USB_VID == 0x2341 +# if defined(USB_MANUFACTURER) +# undef USB_MANUFACTURER +# endif +# define USB_MANUFACTURER "Arduino LLC" +#elif USB_VID == 0x1b4f +# if defined(USB_MANUFACTURER) +# undef USB_MANUFACTURER +# endif +# define USB_MANUFACTURER "SparkFun" +#elif !defined(USB_MANUFACTURER) +// Fall through to unknown if no manufacturer name was provided in a macro +# define USB_MANUFACTURER "Unknown" +#endif + +const u8 STRING_MANUFACTURER[] PROGMEM = USB_MANUFACTURER; + + +#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< len) + n = len; + { + LockEP lock(ep); + // Frame may have been released by the SOF interrupt handler + if (!ReadWriteAllowed()) + continue; + len -= n; + 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; +} + +// Send a USB descriptor string. The string is stored in PROGMEM as a +// plain ASCII string but is sent out as UTF-16 with the correct 2-byte +// prefix +static bool USB_SendStringDescriptor(const u8*string_P, u8 string_len) { + SendControl(2 + string_len * 2); + SendControl(3); + for(u8 i = 0; i < string_len; i++) { + bool r = SendControl(pgm_read_byte(&string_P[i])); + r &= SendControl(0); // high byte + if(!r) { + return false; + } + } + return true; +} + +// 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 + + 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) { + return USB_SendStringDescriptor(STRING_PRODUCT, strlen(USB_PRODUCT)); + } + else if (setup.wValueL == IMANUFACTURER) { + return USB_SendStringDescriptor(STRING_MANUFACTURER, strlen(USB_MANUFACTURER)); + } + else + return false; + } + + if (desc_addr == 0) + return false; + u8 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<> 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/plugins/KeyboardioHID/USBDesc.h b/plugins/KeyboardioHID/USBDesc.h new file mode 100644 index 0000000000..900713e0f9 --- /dev/null +++ b/plugins/KeyboardioHID/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/plugins/KeyboardioHID/wiring_private.h b/plugins/KeyboardioHID/wiring_private.h new file mode 100644 index 0000000000..5dc7d4bed4 --- /dev/null +++ b/plugins/KeyboardioHID/wiring_private.h @@ -0,0 +1,71 @@ +/* + 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 +#include +#include +#include + +#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__) || defined(__AVR_ATmega128RFA1__) || defined(__AVR_ATmega256RFR2__) +#define EXTERNAL_NUM_INTERRUPTS 8 +#elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644A__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__) +#define EXTERNAL_NUM_INTERRUPTS 3 +#elif defined(__AVR_ATmega32U4__) +#define EXTERNAL_NUM_INTERRUPTS 5 +#else +#define EXTERNAL_NUM_INTERRUPTS 2 +#endif + +typedef void (*voidFuncPtr)(void); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif From 201a616d1d3f33cbf1cb131b4380376ae6d20540 Mon Sep 17 00:00:00 2001 From: Nico Date: Mon, 8 Dec 2014 17:07:07 +0100 Subject: [PATCH 069/602] Visual Studio auto format I will hit auto format later anyways, so i will do it here to get the nor relevant change first. Doing this with the 2013 version by the way. --- plugins/KeyboardioHID/CDC.cpp | 65 +++--- plugins/KeyboardioHID/HID.cpp | 308 +++++++++++++------------ plugins/KeyboardioHID/USBAPI.h | 6 +- plugins/KeyboardioHID/USBCore.cpp | 139 +++++------ plugins/KeyboardioHID/USBCore.h | 54 ++--- plugins/KeyboardioHID/USBDesc.h | 28 +-- plugins/KeyboardioHID/wiring_private.h | 4 +- 7 files changed, 305 insertions(+), 299 deletions(-) diff --git a/plugins/KeyboardioHID/CDC.cpp b/plugins/KeyboardioHID/CDC.cpp index 5d4f2a0808..c4e4d1a53a 100644 --- a/plugins/KeyboardioHID/CDC.cpp +++ b/plugins/KeyboardioHID/CDC.cpp @@ -1,19 +1,19 @@ -/* 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. +/* 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 "USBAPI.h" @@ -38,26 +38,26 @@ static volatile LineInfo _usbLineInfo = { 57600, 0x00, 0x00, 0x00, 0x00 }; extern const CDCDescriptor _cdcInterface PROGMEM; const CDCDescriptor _cdcInterface = { - D_IAD(0,2,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,1), + 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), + 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) + 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)); + return USB_SendControl(TRANSFER_PGM, &_cdcInterface, sizeof(_cdcInterface)); } bool WEAK CDC_Setup(Setup& setup) @@ -69,7 +69,7 @@ bool WEAK CDC_Setup(Setup& setup) { if (CDC_GET_LINE_CODING == r) { - USB_SendControl(0,(void*)&_usbLineInfo,7); + USB_SendControl(0, (void*)&_usbLineInfo, 7); return true; } } @@ -78,7 +78,7 @@ bool WEAK CDC_Setup(Setup& setup) { if (CDC_SET_LINE_CODING == r) { - USB_RecvControl((void*)&_usbLineInfo,7); + USB_RecvControl((void*)&_usbLineInfo, 7); } if (CDC_SET_CONTROL_LINE_STATE == r) @@ -168,20 +168,21 @@ size_t Serial_::write(uint8_t c) size_t Serial_::write(const uint8_t *buffer, size_t size) { - /* only try to send bytes if the high-level CDC connection itself + /* 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,buffer,size); + int r = USB_Send(CDC_TX, buffer, size); if (r > 0) { return r; - } else { + } + else { setWriteError(); return 0; } @@ -199,7 +200,7 @@ size_t Serial_::write(const uint8_t *buffer, size_t size) // where the port is configured (lineState != 0) but not quite opened. Serial_::operator bool() { bool result = false; - if (_usbLineInfo.lineState > 0) + if (_usbLineInfo.lineState > 0) result = true; delay(10); return result; diff --git a/plugins/KeyboardioHID/HID.cpp b/plugins/KeyboardioHID/HID.cpp index 75c37b24b2..6923607881 100644 --- a/plugins/KeyboardioHID/HID.cpp +++ b/plugins/KeyboardioHID/HID.cpp @@ -1,19 +1,19 @@ -/* 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. +/* 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 "USBAPI.h" @@ -43,66 +43,66 @@ Keyboard_ Keyboard; 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 + 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) - + 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) - + 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) - + 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) - + 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 + 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application) + 0x81, 0x00, // INPUT (Data,Ary,Abs) + 0xc0, // END_COLLECTION #ifdef RAWHID_ENABLED // RAW HID @@ -110,7 +110,7 @@ const u8 _hidReportDescriptor[] = { 0x0A, LSB(RAWHID_USAGE), MSB(RAWHID_USAGE), 0xA1, 0x01, // Collection 0x01 - 0x85, 0x03, // REPORT_ID (3) + 0x85, 0x03, // REPORT_ID (3) 0x75, 0x08, // report size = 8 bits 0x15, 0x00, // logical minimum = 0 0x26, 0xFF, 0x00, // logical maximum = 255 @@ -129,9 +129,9 @@ const u8 _hidReportDescriptor[] = { extern const HIDDescriptor _hidInterface PROGMEM; const HIDDescriptor _hidInterface = { - D_INTERFACE(HID_INTERFACE,1,3,0,0), + 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) + D_ENDPOINT(USB_ENDPOINT_IN(HID_ENDPOINT_INT), USB_ENDPOINT_TYPE_INTERRUPT, 0x40, 0x01) }; //================================================================================ @@ -146,18 +146,18 @@ u8 _hid_idle = 1; int WEAK HID_GetInterface(u8* interfaceNum) { interfaceNum[0] += 1; // uses 1 - return USB_SendControl(TRANSFER_PGM,&_hidInterface,sizeof(_hidInterface)); + return USB_SendControl(TRANSFER_PGM, &_hidInterface, sizeof(_hidInterface)); } int WEAK HID_GetDescriptor(int /* i */) { - return USB_SendControl(TRANSFER_PGM,_hidReportDescriptor,sizeof(_hidReportDescriptor)); + 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); + USB_Send(HID_TX | TRANSFER_RELEASE, data, len); } bool WEAK HID_Setup(Setup& setup) @@ -177,7 +177,7 @@ bool WEAK HID_Setup(Setup& setup) return true; } } - + if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType) { if (HID_SET_PROTOCOL == r) @@ -203,20 +203,20 @@ Mouse_::Mouse_(void) : _buttons(0) { } -void Mouse_::begin(void) +void Mouse_::begin(void) { } -void Mouse_::end(void) +void Mouse_::end(void) { } void Mouse_::click(uint8_t b) { _buttons = b; - move(0,0,0); + move(0, 0, 0); _buttons = 0; - move(0,0,0); + move(0, 0, 0); } void Mouse_::move(signed char x, signed char y, signed char wheel) @@ -226,7 +226,7 @@ void Mouse_::move(signed char x, signed char y, signed char wheel) m[1] = x; m[2] = y; m[3] = wheel; - HID_SendReport(1,m,4); + HID_SendReport(1, m, 4); } void Mouse_::buttons(uint8_t b) @@ -234,11 +234,11 @@ void Mouse_::buttons(uint8_t b) if (b != _buttons) { _buttons = b; - move(0,0,0); + move(0, 0, 0); } } -void Mouse_::press(uint8_t b) +void Mouse_::press(uint8_t b) { buttons(_buttons | b); } @@ -250,7 +250,7 @@ void Mouse_::release(uint8_t b) bool Mouse_::isPressed(uint8_t b) { - if ((b & _buttons) > 0) + if ((b & _buttons) > 0) return true; return false; } @@ -259,21 +259,21 @@ bool Mouse_::isPressed(uint8_t b) //================================================================================ // Keyboard -Keyboard_::Keyboard_(void) +Keyboard_::Keyboard_(void) { } -void Keyboard_::begin(void) +void Keyboard_::begin(void) { } -void Keyboard_::end(void) +void Keyboard_::end(void) { } void Keyboard_::sendReport(KeyReport* keys) { - HID_SendReport(2,keys,sizeof(KeyReport)); + HID_SendReport(2, keys, sizeof(KeyReport)); } extern @@ -316,17 +316,17 @@ const uint8_t _asciimap[128] = 0x00, // US 0x2c, // ' ' - 0x1e|SHIFT, // ! - 0x34|SHIFT, // " - 0x20|SHIFT, // # - 0x21|SHIFT, // $ - 0x22|SHIFT, // % - 0x24|SHIFT, // & + 0x1e | SHIFT, // ! + 0x34 | SHIFT, // " + 0x20 | SHIFT, // # + 0x21 | SHIFT, // $ + 0x22 | SHIFT, // % + 0x24 | SHIFT, // & 0x34, // ' - 0x26|SHIFT, // ( - 0x27|SHIFT, // ) - 0x25|SHIFT, // * - 0x2e|SHIFT, // + + 0x26 | SHIFT, // ( + 0x27 | SHIFT, // ) + 0x25 | SHIFT, // * + 0x2e | SHIFT, // + 0x36, // , 0x2d, // - 0x37, // . @@ -341,44 +341,44 @@ const uint8_t _asciimap[128] = 0x24, // 7 0x25, // 8 0x26, // 9 - 0x33|SHIFT, // : + 0x33 | SHIFT, // : 0x33, // ; - 0x36|SHIFT, // < + 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 + 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, // _ + 0x23 | SHIFT, // ^ + 0x2d | SHIFT, // _ 0x35, // ` 0x04, // a 0x05, // b @@ -406,10 +406,10 @@ const uint8_t _asciimap[128] = 0x1b, // x 0x1c, // y 0x1d, // z - 0x2f|SHIFT, // - 0x31|SHIFT, // | - 0x30|SHIFT, // } - 0x35|SHIFT, // ~ + 0x2f | SHIFT, // + 0x31 | SHIFT, // | + 0x30 | SHIFT, // } + 0x35 | SHIFT, // ~ 0 // DEL }; @@ -419,15 +419,17 @@ uint8_t USBPutChar(uint8_t c); // 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) +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)); + } + else if (k >= 128) { // it's a modifier key + _keyReport.modifiers |= (1 << (k - 128)); k = 0; - } else { // it's a printing key + } + else { // it's a printing key k = pgm_read_byte(_asciimap + k); if (!k) { setWriteError(); @@ -438,14 +440,14 @@ size_t Keyboard_::press(uint8_t k) 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 && + 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++) { + + for (i = 0; i < 6; i++) { if (_keyReport.keys[i] == 0x00) { _keyReport.keys[i] = k; break; @@ -454,7 +456,7 @@ size_t Keyboard_::press(uint8_t k) if (i == 6) { setWriteError(); return 0; - } + } } sendReport(&_keyReport); return 1; @@ -463,15 +465,17 @@ size_t Keyboard_::press(uint8_t k) // 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) +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)); + } + else if (k >= 128) { // it's a modifier key + _keyReport.modifiers &= ~(1 << (k - 128)); k = 0; - } else { // it's a printing key + } + else { // it's a printing key k = pgm_read_byte(_asciimap + k); if (!k) { return 0; @@ -481,10 +485,10 @@ size_t Keyboard_::release(uint8_t k) 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++) { + for (i = 0; i < 6; i++) { if (0 != k && _keyReport.keys[i] == k) { _keyReport.keys[i] = 0x00; } @@ -497,17 +501,17 @@ size_t Keyboard_::release(uint8_t k) void Keyboard_::releaseAll(void) { _keyReport.keys[0] = 0; - _keyReport.keys[1] = 0; + _keyReport.keys[1] = 0; _keyReport.keys[2] = 0; - _keyReport.keys[3] = 0; + _keyReport.keys[3] = 0; _keyReport.keys[4] = 0; - _keyReport.keys[5] = 0; + _keyReport.keys[5] = 0; _keyReport.modifiers = 0; sendReport(&_keyReport); } size_t Keyboard_::write(uint8_t c) -{ +{ uint8_t p = press(c); // Keydown release(c); // Keyup return p; // just return the result of press() since release() almost always returns 1 diff --git a/plugins/KeyboardioHID/USBAPI.h b/plugins/KeyboardioHID/USBAPI.h index 2fab957f93..325d3ea24f 100644 --- a/plugins/KeyboardioHID/USBAPI.h +++ b/plugins/KeyboardioHID/USBAPI.h @@ -15,7 +15,7 @@ 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 __USBAPI__ #define __USBAPI__ @@ -111,7 +111,7 @@ class Mouse_ 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 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 @@ -213,7 +213,7 @@ void HID_SendReport(uint8_t id, const void* data, int len); 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); +bool MSC_Data(uint8_t rx, uint8_t tx); //================================================================================ //================================================================================ diff --git a/plugins/KeyboardioHID/USBCore.cpp b/plugins/KeyboardioHID/USBCore.cpp index b4f7bed7e8..2b3a1e7efc 100644 --- a/plugins/KeyboardioHID/USBCore.cpp +++ b/plugins/KeyboardioHID/USBCore.cpp @@ -1,19 +1,19 @@ -/* 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. +/* 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 "USBAPI.h" @@ -43,7 +43,7 @@ extern const DeviceDescriptor USB_DeviceDescriptor PROGMEM; extern const DeviceDescriptor USB_DeviceDescriptorA PROGMEM; const u16 STRING_LANGUAGE[2] = { - (3<<8) | (2+2), + (3 << 8) | (2 + 2), 0x0409 // English }; @@ -80,10 +80,10 @@ const u8 STRING_MANUFACTURER[] PROGMEM = USB_MANUFACTURER; // DEVICE DESCRIPTOR const DeviceDescriptor USB_DeviceDescriptor = - D_DEVICE(0x00,0x00,0x00,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,0,1); +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); +D_DEVICE(DEVICE_CLASS, 0x00, 0x00, 64, USB_VID, USB_PID, 0x100, IMANUFACTURER, IPRODUCT, 0, 1); //================================================================== //================================================================== @@ -92,40 +92,40 @@ volatile u8 _usbConfiguration = 0; static inline void WaitIN(void) { - while (!(UEINTX & (1< Date: Mon, 8 Dec 2014 18:11:10 +0100 Subject: [PATCH 070/602] Added USB definitions, fixed USB device Descriptor --- plugins/KeyboardioHID/USBCore.cpp | 43 +++++++++++++++++++------------ plugins/KeyboardioHID/USBCore.h | 15 +++++++++++ 2 files changed, 41 insertions(+), 17 deletions(-) diff --git a/plugins/KeyboardioHID/USBCore.cpp b/plugins/KeyboardioHID/USBCore.cpp index 2b3a1e7efc..a44cce485f 100644 --- a/plugins/KeyboardioHID/USBCore.cpp +++ b/plugins/KeyboardioHID/USBCore.cpp @@ -20,13 +20,13 @@ #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 +#define EP_TYPE_CONTROL (0x00) +#define EP_TYPE_BULK_IN ((1< Date: Tue, 9 Dec 2014 16:46:05 +0100 Subject: [PATCH 071/602] Added u2 Series support --- plugins/KeyboardioHID/CDC.cpp | 34 +++++++++++++- plugins/KeyboardioHID/HID.cpp | 3 +- plugins/KeyboardioHID/USBCore.cpp | 61 +++++++++++++++++++++++--- plugins/KeyboardioHID/USBDesc.h | 7 +++ plugins/KeyboardioHID/wiring_private.h | 4 +- 5 files changed, 99 insertions(+), 10 deletions(-) diff --git a/plugins/KeyboardioHID/CDC.cpp b/plugins/KeyboardioHID/CDC.cpp index c4e4d1a53a..79a790bef6 100644 --- a/plugins/KeyboardioHID/CDC.cpp +++ b/plugins/KeyboardioHID/CDC.cpp @@ -50,8 +50,9 @@ const CDCDescriptor _cdcInterface = // 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) + // edit by NicoHood + D_ENDPOINT(USB_ENDPOINT_OUT(CDC_ENDPOINT_OUT), USB_ENDPOINT_TYPE_BULK, USB_EP_SIZE, 0), + D_ENDPOINT(USB_ENDPOINT_IN(CDC_ENDPOINT_IN), USB_ENDPOINT_TYPE_BULK, USB_EP_SIZE, 0) }; int WEAK CDC_GetInterface(u8* interfaceNum) @@ -96,8 +97,28 @@ bool WEAK CDC_Setup(Setup& setup) // We check DTR state to determine if host port is open (bit 0 of lineState). if (1200 == _usbLineInfo.dwDTERate && (_usbLineInfo.lineState & 0x01) == 0) { + // edit by NicoHood + // change ram pointer to fit the 16u2's ram size and only use an 8bit value +#if defined(__AVR_ATmega32U4__) *(uint16_t *)0x0800 = 0x7777; wdt_enable(WDTO_120MS); +#else + // workaround for this issue: + // https://github.com/arduino/Arduino/issues/2474 + // I didn't change this for the 32u4 to simply not touch their code + // the correct way would be to add a compiler flag like this: + // -Wl,--section-start=.blkey=0x280 + //volatile uint8_t MagicBootKey __attribute__((section(".blkey"))); + cli(); + + //MagicBootKey = 0x77; + *(uint8_t *)0x0280 = 0x77; + + wdt_enable(WDTO_120MS); + + // wait for reset + for (;;); +#endif } else { @@ -106,9 +127,18 @@ bool WEAK CDC_Setup(Setup& setup) // To avoid spurious resets we set the watchdog to 250ms and eventually // cancel if DTR goes back high. + // edit by NicoHood +#if defined(__AVR_ATmega32U4__) wdt_disable(); wdt_reset(); *(uint16_t *)0x0800 = 0x0; +#else + // not used because of the workaround above + //wdt_disable(); + //wdt_reset(); + //MagicBootKey = 0x00; + //*(uint8_t *)0x0280 = 0x00; +#endif } } return true; diff --git a/plugins/KeyboardioHID/HID.cpp b/plugins/KeyboardioHID/HID.cpp index 6923607881..b578c4be06 100644 --- a/plugins/KeyboardioHID/HID.cpp +++ b/plugins/KeyboardioHID/HID.cpp @@ -131,7 +131,8 @@ 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) + // edit by NicoHood + D_ENDPOINT(USB_ENDPOINT_IN(HID_ENDPOINT_INT), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) }; //================================================================================ diff --git a/plugins/KeyboardioHID/USBCore.cpp b/plugins/KeyboardioHID/USBCore.cpp index a44cce485f..82aa37272e 100644 --- a/plugins/KeyboardioHID/USBCore.cpp +++ b/plugins/KeyboardioHID/USBCore.cpp @@ -271,7 +271,8 @@ u8 USB_SendSpace(u8 ep) LockEP lock(ep); if (!ReadWriteAllowed()) return 0; - return 64 - FifoByteCount(); + // edit by NicoHood + return USB_EP_SIZE - FifoByteCount(); } // Blocking Send of data to an endpoint @@ -344,6 +345,8 @@ const u8 _initEndpoints[] = #define EP_SINGLE_64 0x32 // EP0 #define EP_DOUBLE_64 0x36 // Other endpoints +// edit by NicoHood +#define EP_SINGLE_16 0x12 static void InitEP(u8 index, u8 type, u8 size) @@ -362,7 +365,14 @@ void InitEndpoints() UENUM = i; UECONX = (1 << EPEN); UECFG0X = pgm_read_byte(_initEndpoints + i); + // edit by NicoHood +#if USB_EP_SIZE == 16 + UECFG1X = EP_SINGLE_16; +#elif USB_EP_SIZE == 64 UECFG1X = EP_DOUBLE_64; +#else +#error Unsupported value for USB_EP_SIZE +#endif } UERST = 0x7E; // And reset them UERST = 0; @@ -666,16 +676,55 @@ USBDevice_::USBDevice_() { } +// edit by NicoHood +// added from teensy definition by paul stoffregen +#if defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega8U2__) +#define HW_CONFIG() +#define PLL_CONFIG() (PLLCSR = ((1< Date: Tue, 9 Dec 2014 17:47:25 +0100 Subject: [PATCH 072/602] Added Serial line encoding functions + events https://github.com/arduino/Arduino/pull/2469 Weak implementation sounds usefull but takes 6 more bytes of flash/ function (12). Even more, if we would also pass the line states but the user can read this with Serial.dtr() for example. https://github.com/arduino/Arduino/pull/1179 Should we inline the Serial.dtr() functuions etc? But then we need to move the line info to the header as well, also the definition. These optional functions only take flash if they are used. Virtual isnt used, because this would take more flash for no reason. Syntax like this: https://www.pjrc.com/teensy/td_serial.html --- plugins/KeyboardioHID/CDC.cpp | 41 +++++++++++++++++++ plugins/KeyboardioHID/HID_Tests/HID_Tests.ino | 35 ++++++++++++++++ plugins/KeyboardioHID/USBAPI.h | 8 ++++ plugins/KeyboardioHID/USBCore.h | 3 ++ 4 files changed, 87 insertions(+) create mode 100644 plugins/KeyboardioHID/HID_Tests/HID_Tests.ino diff --git a/plugins/KeyboardioHID/CDC.cpp b/plugins/KeyboardioHID/CDC.cpp index 79a790bef6..4269118c7b 100644 --- a/plugins/KeyboardioHID/CDC.cpp +++ b/plugins/KeyboardioHID/CDC.cpp @@ -80,11 +80,13 @@ bool WEAK CDC_Setup(Setup& setup) if (CDC_SET_LINE_CODING == r) { USB_RecvControl((void*)&_usbLineInfo, 7); + CDC_LineEncodingEvent(); } if (CDC_SET_CONTROL_LINE_STATE == r) { _usbLineInfo.lineState = setup.wValueL; + CDC_LineStateEvent(); } if (CDC_SET_LINE_CODING == r || CDC_SET_CONTROL_LINE_STATE == r) @@ -146,6 +148,15 @@ bool WEAK CDC_Setup(Setup& setup) return false; } +void WEAK CDC_LineEncodingEvent(void) +{ + // has to be implemented by the user +} + +void WEAK CDC_LineStateEvent(void) +{ + // has to be implemented by the user +} void Serial_::begin(unsigned long /* baud_count */) { @@ -221,6 +232,36 @@ size_t Serial_::write(const uint8_t *buffer, size_t size) return 0; } +uint32_t Serial_::baud(void) +{ + return _usbLineInfo.dwDTERate; +} + +uint8_t Serial_::stopbits(void) +{ + return _usbLineInfo.bCharFormat; +} + +uint8_t Serial_::paritytype(void) +{ + return _usbLineInfo.bParityType; +} + +uint8_t Serial_::numbits(void) +{ + return _usbLineInfo.bDataBits; +} + +bool Serial_::dtr(void) +{ + return (_usbLineInfo.lineState & CDC_CONTROL_LINE_OUT_DTR) ? true : false; +} + +bool Serial_::rts(void) +{ + return (_usbLineInfo.lineState & CDC_CONTROL_LINE_OUT_RTS) ? true : false; +} + // 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 diff --git a/plugins/KeyboardioHID/HID_Tests/HID_Tests.ino b/plugins/KeyboardioHID/HID_Tests/HID_Tests.ino new file mode 100644 index 0000000000..cdba2e4426 --- /dev/null +++ b/plugins/KeyboardioHID/HID_Tests/HID_Tests.ino @@ -0,0 +1,35 @@ +// simply, ugly code to test the new functions + +void setup() { + Serial.begin(1); +} + +uint32_t eventBaud = 0; + +void loop() { + if (Serial.available()) { + while (Serial.read() != -1); + Serial.println("Serial Port working"); + Keyboard.println("Nico is cool"); + delay(3000); + } + + delay(3000); + Serial.println(Serial.dtr()); + Serial.println(Serial.rts()); + Serial.println(Serial.baud()); + Serial.println(Serial.stopbits()); + Serial.println(Serial.paritytype()); + Serial.println(Serial.numbits()); + + if (eventBaud) { + Serial.println("Event"); + Serial.println(eventBaud); + eventBaud = 0; + } +} + +void CDC_LineEncodingEvent(void) +{ + eventBaud = Serial.baud(); +} diff --git a/plugins/KeyboardioHID/USBAPI.h b/plugins/KeyboardioHID/USBAPI.h index 325d3ea24f..049a1336cd 100644 --- a/plugins/KeyboardioHID/USBAPI.h +++ b/plugins/KeyboardioHID/USBAPI.h @@ -82,6 +82,12 @@ class Serial_ : public Stream virtual size_t write(uint8_t); virtual size_t write(const uint8_t*, size_t); using Print::write; // pull in write(str) and write(buf, size) from Print + uint32_t baud(void); + uint8_t stopbits(void); + uint8_t paritytype(void); + uint8_t numbits(void); + bool dtr(void); + bool rts(void); operator bool(); volatile uint8_t _rx_buffer_head; @@ -222,6 +228,8 @@ bool MSC_Data(uint8_t rx, uint8_t tx); int CDC_GetInterface(uint8_t* interfaceNum); int CDC_GetDescriptor(int i); bool CDC_Setup(Setup& setup); +void CDC_LineEncodingEvent(void); +void CDC_LineStateEvent(void); //================================================================================ //================================================================================ diff --git a/plugins/KeyboardioHID/USBCore.h b/plugins/KeyboardioHID/USBCore.h index 5df4d5de4e..4178b75a4a 100644 --- a/plugins/KeyboardioHID/USBCore.h +++ b/plugins/KeyboardioHID/USBCore.h @@ -56,6 +56,9 @@ #define CDC_GET_LINE_CODING 0x21 #define CDC_SET_CONTROL_LINE_STATE 0x22 +#define CDC_CONTROL_LINE_OUT_DTR (1 << 0) +#define CDC_CONTROL_LINE_OUT_RTS (1 << 1) + #define MSC_RESET 0xFF #define MSC_GET_MAX_LUN 0xFE From e16e02186433708215cc61812b5f9b33f8cc675c Mon Sep 17 00:00:00 2001 From: Nico Date: Tue, 9 Dec 2014 18:25:37 +0100 Subject: [PATCH 073/602] Led Out Report, Minor Keyboard + Mouse changes https://github.com/arduino/Arduino/issues/2275#issuecomment-64989558 Added Led Out Report (with definition) Is the getLEDs() name okay? Adds 44 bytes flash if activated Added missing Keyboard + Mouse definitions Changed Mouse HID report a bit Added definitions to en/disable current reports No bigger changes to the HID Api were made --- plugins/KeyboardioHID/HID.cpp | 109 +++++++++++++----- plugins/KeyboardioHID/HID_Tests/HID_Tests.ino | 5 + plugins/KeyboardioHID/USBAPI.h | 61 +++++++++- 3 files changed, 140 insertions(+), 35 deletions(-) diff --git a/plugins/KeyboardioHID/HID.cpp b/plugins/KeyboardioHID/HID.cpp index b578c4be06..65d773ec07 100644 --- a/plugins/KeyboardioHID/HID.cpp +++ b/plugins/KeyboardioHID/HID.cpp @@ -36,32 +36,40 @@ Keyboard_ Keyboard; #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 +#define RAWHID_USAGE_PAGE 0xFFC0 // recommended: 0xFF00 to 0xFFFF +#define RAWHID_USAGE 0x0C00 // recommended: 0x0100 to 0xFFFF +#define RAWHID_TX_SIZE (USB_EP_SIZE-1) +#define RAWHID_RX_SIZE (USB_EP_SIZE-1) + +#if defined USBCON && defined(HID_KEYBOARD_ENABLED) && defined(HID_KEYBOARD_LEDS_ENABLED) +// extern accessible led out report +uint8_t hid_keyboard_leds = 0; +#endif extern const u8 _hidReportDescriptor[] PROGMEM; const u8 _hidReportDescriptor[] = { - - // Mouse +#ifdef HID_MOUSE_ENABLED + // 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) + 0x85, HID_REPORTID_MouseReport,// REPORT_ID + // 5 buttons 0x05, 0x09, // USAGE_PAGE (Button) 0x19, 0x01, // USAGE_MINIMUM (Button 1) - 0x29, 0x03, // USAGE_MAXIMUM (Button 3) + 0x29, 0x05, // USAGE_MAXIMUM (Button 5) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x25, 0x01, // LOGICAL_MAXIMUM (1) - 0x95, 0x03, // REPORT_COUNT (3) + 0x95, 0x05, // REPORT_COUNT (5) 0x75, 0x01, // REPORT_SIZE (1) 0x81, 0x02, // INPUT (Data,Var,Abs) + // reserved 0x95, 0x01, // REPORT_COUNT (1) - 0x75, 0x05, // REPORT_SIZE (5) + 0x75, 0x03, // REPORT_SIZE (3) 0x81, 0x03, // INPUT (Cnst,Var,Abs) + // x, y, wheel 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0x09, 0x30, // USAGE (X) 0x09, 0x31, // USAGE (Y) @@ -71,58 +79,75 @@ const u8 _hidReportDescriptor[] = { 0x75, 0x08, // REPORT_SIZE (8) 0x95, 0x03, // REPORT_COUNT (3) 0x81, 0x06, // INPUT (Data,Var,Rel) + // end 0xc0, // END_COLLECTION 0xc0, // END_COLLECTION +#endif - // Keyboard - 0x05, 0x01, // USAGE_PAGE (Generic Desktop) // 47 +#ifdef HID_KEYBOARD_ENABLED + // Keyboard + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0x09, 0x06, // USAGE (Keyboard) 0xa1, 0x01, // COLLECTION (Application) - 0x85, 0x02, // REPORT_ID (2) + 0x85, HID_REPORTID_KeyboardReport, // REPORT_ID 0x05, 0x07, // USAGE_PAGE (Keyboard) - + // modifiers 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) + // reserved byte 0x95, 0x01, // REPORT_COUNT (1) 0x75, 0x08, // REPORT_SIZE (8) 0x81, 0x03, // INPUT (Cnst,Var,Abs) - + // Key[6] Array 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) +#ifdef HID_KEYBOARD_LEDS_ENABLED + // LEDs for num lock etc + 0x05, 0x08, /* USAGE_PAGE (LEDs) */ + 0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */ + 0x29, 0x05, /* USAGE_MAXIMUM (Kana) */ + 0x95, 0x05, /* REPORT_COUNT (5) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */ + // Reserved 3 bits + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x03, /* REPORT_SIZE (3) */ + 0x91, 0x03, /* OUTPUT (Cnst,Var,Abs) */ +#endif + // end 0xc0, // END_COLLECTION +#endif -#ifdef RAWHID_ENABLED - // RAW HID +#ifdef HID_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 + 0xA1, 0x01, // Collection 0x01 + 0x85, HID_REPORTID_RawKeyboardReport, // REPORT_ID + 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, RAWHID_TX_SIZE, // 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 + 0x95, RAWHID_RX_SIZE, // report count RX + 0x09, 0x02, // usage + 0x91, 0x02, // Output (array) + 0xC0, // end collection #endif }; @@ -192,6 +217,20 @@ bool WEAK HID_Setup(Setup& setup) _hid_idle = setup.wValueL; return true; } + +#if defined(HID_KEYBOARD_ENABLED) && defined(HID_KEYBOARD_LEDS_ENABLED) + if (HID_SET_REPORT == r) + { + //TODO check correct report ID (not needed for now, no other device has an out report) + if (setup.wLength == 2) + { + // write led out report data + uint8_t data[2]; + if (2 == USB_RecvControl(data, 2)) + hid_keyboard_leds = data[1]; + } + } +#endif } return false; } @@ -200,6 +239,8 @@ bool WEAK HID_Setup(Setup& setup) //================================================================================ // Mouse +#ifdef HID_MOUSE_ENABLED + Mouse_::Mouse_(void) : _buttons(0) { } @@ -256,10 +297,14 @@ bool Mouse_::isPressed(uint8_t b) return false; } +#endif + //================================================================================ //================================================================================ // Keyboard +#ifdef HID_KEYBOARD_ENABLED + Keyboard_::Keyboard_(void) { } @@ -520,4 +565,6 @@ size_t Keyboard_::write(uint8_t c) #endif +#endif + #endif /* if defined(USBCON) */ diff --git a/plugins/KeyboardioHID/HID_Tests/HID_Tests.ino b/plugins/KeyboardioHID/HID_Tests/HID_Tests.ino index cdba2e4426..4dcabe28ea 100644 --- a/plugins/KeyboardioHID/HID_Tests/HID_Tests.ino +++ b/plugins/KeyboardioHID/HID_Tests/HID_Tests.ino @@ -15,6 +15,11 @@ void loop() { } delay(3000); + Keyboard.write(KEY_CAPS_LOCK); + Serial.println("Leds"); + Serial.println(Keyboard.getLEDs(), BIN); + + Serial.println("Serial"); Serial.println(Serial.dtr()); Serial.println(Serial.rts()); Serial.println(Serial.baud()); diff --git a/plugins/KeyboardioHID/USBAPI.h b/plugins/KeyboardioHID/USBAPI.h index 049a1336cd..c135e52d6d 100644 --- a/plugins/KeyboardioHID/USBAPI.h +++ b/plugins/KeyboardioHID/USBAPI.h @@ -34,6 +34,29 @@ typedef unsigned long u32; #if defined(USBCON) +// include needed HID devices +// the more you activate, the more flash it will take +// by default only Mouse + Keyboard (without LEDs) are activated +#define HID_MOUSE_ENABLED +#define HID_KEYBOARD_ENABLED +//#define HID_KEYBOARD_LEDS_ENABLED + +//#define HID_RAWHID_ENABLED (currently broken for USB-Core) +//#define HID_MEDIA_ENABLED +//#define HID_SYSTEM_ENABLED +//#define HID_GAMEPAD_ENABLED + +/** Enum for the HID report IDs used in the device. */ +typedef enum{ + HID_REPORTID_NotAReport = 0x00, /**< first entry is always zero for multireports */ + HID_REPORTID_MouseReport = 0x01, /**< Report ID for the Mouse report within the device. */ + HID_REPORTID_KeyboardReport = 0x02, /**< Report ID for the Keyboard report within the device. */ + HID_REPORTID_RawHidReport = 0x03, /**< Report ID for the Raw Hid report within the device. */ + HID_REPORTID_MediaReport = 0x04, /**< Report ID for the Media report within the device. */ + HID_REPORTID_SystemReport = 0x05, /**< Report ID for the Power report within the device. */ + HID_REPORTID_GamepadReport = 0x06, /**< Report ID for the Gamepad report within the device. */ +} HID_Report_IDs; + #include "USBDesc.h" #include "USBCore.h" @@ -102,10 +125,14 @@ 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) +#ifdef HID_MOUSE_ENABLED + +#define MOUSE_LEFT 0x01 +#define MOUSE_RIGHT 0x02 +#define MOUSE_MIDDLE 0x04 +#define MOUSE_PREV 0x08 +#define MOUSE_NEXT 0x10 +#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE | MOUSE_PREV | MOUSE_NEXT) class Mouse_ { @@ -124,18 +151,29 @@ class Mouse_ }; extern Mouse_ Mouse; +#endif + //================================================================================ //================================================================================ // Keyboard +#ifdef HID_KEYBOARD_ENABLED + +#define KEY_PRINT 0xCE +#define KEY_NUM_LOCK 0xDB +#define KEY_SCROLL_LOCK 0xCF +#define KEY_PAUSE 0xD0 + #define KEY_LEFT_CTRL 0x80 #define KEY_LEFT_SHIFT 0x81 #define KEY_LEFT_ALT 0x82 #define KEY_LEFT_GUI 0x83 +#define KEY_LEFT_WINDOWS KEY_LEFT_GUI #define KEY_RIGHT_CTRL 0x84 #define KEY_RIGHT_SHIFT 0x85 #define KEY_RIGHT_ALT 0x86 #define KEY_RIGHT_GUI 0x87 +#define KEY_RIGHT_WINDOWS KEY_RIGHT_GUI #define KEY_UP_ARROW 0xDA #define KEY_DOWN_ARROW 0xD9 @@ -165,6 +203,15 @@ extern Mouse_ Mouse; #define KEY_F11 0xCC #define KEY_F12 0xCD +#define LED_NUM_LOCK 0x01 +#define LED_CAPS_LOCK 0x02 +#define LED_SCROLL_LOCK 0x04 + +#if defined USBCON && defined(HID_KEYBOARD_ENABLED) && defined(HID_KEYBOARD_LEDS_ENABLED) +// extern accessible led out report +extern uint8_t hid_keyboard_leds; +#endif + // Low level key report: up to 6 keys and shift, ctrl etc at once typedef struct { @@ -186,9 +233,15 @@ class Keyboard_ : public Print virtual size_t press(uint8_t k); virtual size_t release(uint8_t k); virtual void releaseAll(void); + +#if defined(HID_KEYBOARD_LEDS_ENABLED) + inline uint8_t getLEDs(void){ return hid_keyboard_leds; } +#endif }; extern Keyboard_ Keyboard; +#endif + //================================================================================ //================================================================================ // Low level API From 4fc964a1152bcc251a1b89b32f846436b7661b4c Mon Sep 17 00:00:00 2001 From: Nico Date: Fri, 26 Dec 2014 21:47:07 +0100 Subject: [PATCH 074/602] Separated CDC, HID and its APIs. Also added Absolute Mouse and changed the structure. Added a better readme for changelog and todo list. --- plugins/KeyboardioHID/Arduino.h | 252 +++++++++++++++ plugins/KeyboardioHID/CDC.cpp | 2 +- plugins/KeyboardioHID/CDC.h | 77 +++++ plugins/KeyboardioHID/HID.cpp | 477 ++--------------------------- plugins/KeyboardioHID/HID.h | 287 +++++++++++++++++ plugins/KeyboardioHID/HIDAPI.h | 28 ++ plugins/KeyboardioHID/Keyboard.cpp | 284 +++++++++++++++++ plugins/KeyboardioHID/Keyboard.h | 110 +++++++ plugins/KeyboardioHID/Mouse.cpp | 88 ++++++ plugins/KeyboardioHID/Mouse.h | 56 ++++ plugins/KeyboardioHID/Readme.md | 54 ++++ plugins/KeyboardioHID/USBAPI.h | 212 ------------- plugins/KeyboardioHID/USBCore.h | 13 + 13 files changed, 1277 insertions(+), 663 deletions(-) create mode 100644 plugins/KeyboardioHID/Arduino.h create mode 100644 plugins/KeyboardioHID/CDC.h create mode 100644 plugins/KeyboardioHID/HID.h create mode 100644 plugins/KeyboardioHID/HIDAPI.h create mode 100644 plugins/KeyboardioHID/Keyboard.cpp create mode 100644 plugins/KeyboardioHID/Keyboard.h create mode 100644 plugins/KeyboardioHID/Mouse.cpp create mode 100644 plugins/KeyboardioHID/Mouse.h create mode 100644 plugins/KeyboardioHID/Readme.md diff --git a/plugins/KeyboardioHID/Arduino.h b/plugins/KeyboardioHID/Arduino.h new file mode 100644 index 0000000000..64d156d467 --- /dev/null +++ b/plugins/KeyboardioHID/Arduino.h @@ -0,0 +1,252 @@ +/* + Arduino.h - Main include file for the Arduino SDK + Copyright (c) 2005-2013 Arduino Team. 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 Arduino_h +#define Arduino_h + +#include +#include +#include +#include + +#include +#include +#include + +#include "binary.h" + +#ifdef __cplusplus +extern "C"{ +#endif + +void yield(void); + +#define HIGH 0x1 +#define LOW 0x0 + +#define INPUT 0x0 +#define OUTPUT 0x1 +#define INPUT_PULLUP 0x2 + +#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 EULER 2.718281828459045235360287471352 + +#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_ATmega1284__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644A__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__) +#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)) + +// avr-libc defines _NOP() since 1.6.2 +#ifndef _NOP +#define _NOP() do { __asm__ volatile ("nop"); } while (0) +#endif + +typedef unsigned int word; + +#define bit(b) (1UL << (b)) + +typedef uint8_t boolean; +typedef uint8_t byte; + +void init(void); +void initVariant(void); + +int atexit(void (*func)()) __attribute__((weak)); + +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 + +#define NOT_AN_INTERRUPT -1 + +#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 TIMER1C 5 +#define TIMER2 6 +#define TIMER2A 7 +#define TIMER2B 8 + +#define TIMER3A 9 +#define TIMER3B 10 +#define TIMER3C 11 +#define TIMER4A 12 +#define TIMER4B 13 +#define TIMER4C 14 +#define TIMER4D 15 +#define TIMER5A 16 +#define TIMER5B 17 +#define TIMER5C 18 + +#ifdef __cplusplus +} // extern "C" +#endif + +#ifdef __cplusplus +#include "WCharacter.h" +#include "WString.h" +#include "HardwareSerial.h" +#include "USBAPI.h" +#include "CDC.h" +#include "HID.h" + +#if defined(HAVE_HWSERIAL0) && defined(HAVE_CDCSERIAL) +#error "Targets with both UART0 and CDC serial not supported" +#endif + +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/plugins/KeyboardioHID/CDC.cpp b/plugins/KeyboardioHID/CDC.cpp index 4269118c7b..9141091667 100644 --- a/plugins/KeyboardioHID/CDC.cpp +++ b/plugins/KeyboardioHID/CDC.cpp @@ -16,7 +16,7 @@ ** SOFTWARE. */ -#include "USBAPI.h" +#include "CDC.h" #include #if defined(USBCON) diff --git a/plugins/KeyboardioHID/CDC.h b/plugins/KeyboardioHID/CDC.h new file mode 100644 index 0000000000..627f69fa5f --- /dev/null +++ b/plugins/KeyboardioHID/CDC.h @@ -0,0 +1,77 @@ +/* +CDC.h +Copyright (c) 2005-2014 Arduino. All right reserved. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef __CDC__ +#define __CDC__ + +#include "Arduino.h" + +#if defined(USBCON) + +#include "USBDesc.h" +#include "USBCore.h" + +//================================================================================ +//================================================================================ +// Serial over CDC (Serial1 is the physical port) + +struct ring_buffer; + +#if (RAMEND < 1000) +#define SERIAL_BUFFER_SIZE 16 +#else +#define SERIAL_BUFFER_SIZE 64 +#endif + +class Serial_ : public Stream +{ +private: + int peek_buffer; +public: + Serial_() { peek_buffer = -1; }; + void begin(unsigned long); + void begin(unsigned long, uint8_t); + void end(void); + + virtual int available(void); + virtual int peek(void); + virtual int read(void); + virtual void flush(void); + virtual size_t write(uint8_t); + virtual size_t write(const uint8_t*, size_t); + using Print::write; // pull in write(str) and write(buf, size) from Print + uint32_t baud(void); + uint8_t stopbits(void); + uint8_t paritytype(void); + uint8_t numbits(void); + bool dtr(void); + bool rts(void); + operator bool(); + + volatile uint8_t _rx_buffer_head; + volatile uint8_t _rx_buffer_tail; + unsigned char _rx_buffer[SERIAL_BUFFER_SIZE]; +}; +extern Serial_ Serial; + +#define HAVE_CDCSERIAL + +#endif /* if defined(USBCON) */ + +#endif \ No newline at end of file diff --git a/plugins/KeyboardioHID/HID.cpp b/plugins/KeyboardioHID/HID.cpp index 65d773ec07..48e3a0e600 100644 --- a/plugins/KeyboardioHID/HID.cpp +++ b/plugins/KeyboardioHID/HID.cpp @@ -16,138 +16,32 @@ ** SOFTWARE. */ -#include "USBAPI.h" +#include "HID.h" + +#define WEAK __attribute__ ((weak)) #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 // recommended: 0xFF00 to 0xFFFF -#define RAWHID_USAGE 0x0C00 // recommended: 0x0100 to 0xFFFF -#define RAWHID_TX_SIZE (USB_EP_SIZE-1) -#define RAWHID_RX_SIZE (USB_EP_SIZE-1) - -#if defined USBCON && defined(HID_KEYBOARD_ENABLED) && defined(HID_KEYBOARD_LEDS_ENABLED) -// extern accessible led out report -uint8_t hid_keyboard_leds = 0; -#endif - extern const u8 _hidReportDescriptor[] PROGMEM; const u8 _hidReportDescriptor[] = { -#ifdef HID_MOUSE_ENABLED - // 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, HID_REPORTID_MouseReport,// REPORT_ID - // 5 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) - 0x95, 0x05, // REPORT_COUNT (5) - 0x75, 0x01, // REPORT_SIZE (1) - 0x81, 0x02, // INPUT (Data,Var,Abs) - // reserved - 0x95, 0x01, // REPORT_COUNT (1) - 0x75, 0x03, // REPORT_SIZE (3) - 0x81, 0x03, // INPUT (Cnst,Var,Abs) - // x, y, wheel - 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) - // end - 0xc0, // END_COLLECTION - 0xc0, // END_COLLECTION -#endif - -#ifdef HID_KEYBOARD_ENABLED - // Keyboard - 0x05, 0x01, // USAGE_PAGE (Generic Desktop) - 0x09, 0x06, // USAGE (Keyboard) - 0xa1, 0x01, // COLLECTION (Application) - 0x85, HID_REPORTID_KeyboardReport, // REPORT_ID - 0x05, 0x07, // USAGE_PAGE (Keyboard) - // modifiers - 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) - // reserved byte - 0x95, 0x01, // REPORT_COUNT (1) - 0x75, 0x08, // REPORT_SIZE (8) - 0x81, 0x03, // INPUT (Cnst,Var,Abs) - // Key[6] Array - 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) + // by default use the standard HID APIs +#ifndef EXTERN_HID_REPORT #ifdef HID_KEYBOARD_LEDS_ENABLED - // LEDs for num lock etc - 0x05, 0x08, /* USAGE_PAGE (LEDs) */ - 0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */ - 0x29, 0x05, /* USAGE_MAXIMUM (Kana) */ - 0x95, 0x05, /* REPORT_COUNT (5) */ - 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */ - // Reserved 3 bits - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0x75, 0x03, /* REPORT_SIZE (3) */ - 0x91, 0x03, /* OUTPUT (Cnst,Var,Abs) */ + HID_REPORT_KEYBOARD_LEDS(HID_REPORTID_KEYBOARD), +#else + HID_REPORT_KEYBOARD_KEYS(HID_REPORTID_KEYBOARD), #endif - // end - 0xc0, // END_COLLECTION -#endif - -#ifdef HID_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, HID_REPORTID_RawKeyboardReport, // REPORT_ID - 0x75, 0x08, // report size = 8 bits - 0x15, 0x00, // logical minimum = 0 - 0x26, 0xFF, 0x00, // logical maximum = 255 - - 0x95, RAWHID_TX_SIZE, // report count TX - 0x09, 0x01, // usage - 0x81, 0x02, // Input (array) - - 0x95, RAWHID_RX_SIZE, // report count RX - 0x09, 0x02, // usage - 0x91, 0x02, // Output (array) - 0xC0, // end collection + HID_REPORT_MOUSE(HID_REPORTID_MOUSE), + HID_REPORT_MOUSE_ABSOLUTE(HID_REPORTID_MOUSE_ABSOLUTE), + //HID_REPORT_RAWHID(HID_REPORTID_RAWHID), + HID_REPORT_CONSUMERCONTROL(HID_REPORTID_CONSUMERCONTROL), + HID_REPORT_SYSTEMCONTROL(HID_REPORTID_SYSTEMCONTROL), +#else + EXTERN_HID_REPORT #endif }; @@ -167,8 +61,6 @@ const HIDDescriptor _hidInterface = u8 _hid_protocol = 1; u8 _hid_idle = 1; -#define WEAK __attribute__ ((weak)) - int WEAK HID_GetInterface(u8* interfaceNum) { interfaceNum[0] += 1; // uses 1 @@ -217,354 +109,39 @@ bool WEAK HID_Setup(Setup& setup) _hid_idle = setup.wValueL; return true; } - -#if defined(HID_KEYBOARD_ENABLED) && defined(HID_KEYBOARD_LEDS_ENABLED) +#if defined(HID_KEYBOARD_LEDS_ENABLED) if (HID_SET_REPORT == r) { //TODO check correct report ID (not needed for now, no other device has an out report) + // maybe make this a general weak implementation to use it for RAW HID later? if (setup.wLength == 2) { // write led out report data uint8_t data[2]; if (2 == USB_RecvControl(data, 2)) - hid_keyboard_leds = data[1]; + HID_SetKeyboardLedReport(data[1]); } + // else TODO check for other devices like RAW HID, not needed for now } #endif } return false; } -//================================================================================ -//================================================================================ -// Mouse - -#ifdef HID_MOUSE_ENABLED - -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); +#if defined(HID_KEYBOARD_LEDS_ENABLED) +void WEAK HID_SetKeyboardLedReport(uint8_t leds){ + // weak function implemented by the Keyboard API + // to not always create the Keyboard object, if it isn't used } - -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; -} - #endif -//================================================================================ -//================================================================================ -// Keyboard - -#ifdef HID_KEYBOARD_ENABLED - -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; - } - } +#endif - // 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; - } - } +#else /* if defined(USBCON) */ - 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) +void WEAK HID_SendReport(u8 id, const void* data, int len) { - uint8_t p = press(c); // Keydown - release(c); // Keyup - return p; // just return the result of press() since release() almost always returns 1 + // empty to let the user use the HIDAPI for different use } -#endif - -#endif - #endif /* if defined(USBCON) */ diff --git a/plugins/KeyboardioHID/HID.h b/plugins/KeyboardioHID/HID.h new file mode 100644 index 0000000000..66a86b27a6 --- /dev/null +++ b/plugins/KeyboardioHID/HID.h @@ -0,0 +1,287 @@ +/* +HID.h +Copyright (c) 2005-2014 Arduino. All right reserved. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef __HID__ +#define __HID__ + +#include "Arduino.h" + +// enable Led out report by default +#ifndef EXTERN_HID_REPORT +#define HID_KEYBOARD_LEDS_ENABLED +#endif + +// HID report IDs +// note by NicoHood: I would not change the current IDs, since it can confuse the OS +// I had several problems if i change the report id and its use. +// It doesnt matter if a device is not presented and there is a lack of IDs (at least number 1 must be represented) +// Report IDs and the report itself can be overwritten by the pins_arduino.h +#ifndef HID_REPORTID_MOUSE +#define HID_REPORTID_MOUSE 1 +#endif +#ifndef HID_REPORTID_KEYBOARD +#define HID_REPORTID_KEYBOARD 2 +#endif +#ifndef HID_REPORTID_RAWHID +#define HID_REPORTID_RAWHID 3 +#endif +#ifndef HID_REPORTID_CONSUMERCONTROL +#define HID_REPORTID_CONSUMERCONTROL 4 +#endif +#ifndef HID_REPORTID_SYSTEMCONTROL +#define HID_REPORTID_SYSTEMCONTROL 5 +#endif +#ifndef HID_REPORTID_GAMEPAD +#define HID_REPORTID_GAMEPAD 5 +#endif +#ifndef HID_REPORTID_MOUSE_ABSOLUTE +#define HID_REPORTID_MOUSE_ABSOLUTE 6 +#endif + +// HID reports +// Report IDs and the report itself can be overwritten by the pins_arduino.h + + +#ifndef HID_REPORT_MOUSE +#define HID_REPORT_MOUSE(report_id) /* Mouse relative */ \ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 54 */ \ + 0x09, 0x02, /* USAGE (Mouse) */ \ + 0xa1, 0x01, /* COLLECTION (Application) */ \ + 0x85, report_id, /* REPORT_ID */ \ +\ + /* 8 Buttons */ \ + 0x05, 0x09, /* USAGE_PAGE (Button) */ \ + 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ \ + 0x29, 0x08, /* USAGE_MAXIMUM (Button 8) */ \ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ \ + 0x95, 0x08, /* REPORT_COUNT (8) */ \ + 0x75, 0x01, /* REPORT_SIZE (1) */ \ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ +\ + /* X, Y, Wheel */ \ + 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) */ \ +\ + /* End */ \ + 0xc0 /* END_COLLECTION */ +#endif + +#ifndef HID_REPORT_MOUSE_ABSOLUTE +#define HID_REPORT_MOUSE_ABSOLUTE(report_id) /* Mouse absolute */ \ + 0x05, 0x01, /* Usage Page (Generic Desktop) */ \ + 0x09, 0x02, /* Usage (Mouse) */ \ + 0xA1, 0x01, /* Collection (Application) */ \ + 0x85, report_id, /* REPORT_ID */ \ + 0x05, 0x01, /* Usage Page (Generic Desktop) */ \ + 0x09, 0x30, /* Usage (X) */ \ + 0x09, 0x31, /* Usage (Y) */ \ + 0x15, 0x00, /* Logical Minimum (0) */ \ + 0x26, 0xFF, 0x7F, /* Logical Maximum (32767) */ \ + 0x75, 0x10, /* Report Size (16), */ \ + 0x95, 0x02, /* Report Count (2), */ \ + 0x81, 0x02, /* Input (Data, Variable, Absolute) */ \ + 0xC0 /* End Collection */ +#endif + +#ifndef HID_REPORT_KEYBOARD_LEDS +#define HID_REPORT_KEYBOARD_LEDS(report_id) /* Keyboard */ \ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 47 */ \ + 0x09, 0x06, /* USAGE (Keyboard) */ \ + 0xa1, 0x01, /* COLLECTION (Application) */ \ + 0x85, report_id, /* REPORT_ID */ \ + 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ \ +\ + /* Keyboard Modifiers (shift, alt, ...) */ \ + 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) */ \ +\ + /* Reserved byte */ \ + 0x95, 0x01, /* REPORT_COUNT (1) */ \ + 0x75, 0x08, /* REPORT_SIZE (8) */ \ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ \ +\ + /* 5 LEDs for num lock etc */ \ + 0x05, 0x08, /* USAGE_PAGE (LEDs) */ \ + 0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */ \ + 0x29, 0x05, /* USAGE_MAXIMUM (Kana) */ \ + 0x95, 0x05, /* REPORT_COUNT (5) */ \ + 0x75, 0x01, /* REPORT_SIZE (1) */ \ + 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */ \ + /* Reserved 3 bits */ \ + 0x95, 0x01, /* REPORT_COUNT (1) */ \ + 0x75, 0x03, /* REPORT_SIZE (3) */ \ + 0x91, 0x03, /* OUTPUT (Cnst,Var,Abs) */ \ +\ + /* 6 Keyboard keys */ \ + 0x95, 0x06, /* REPORT_COUNT (6) */ \ + 0x75, 0x08, /* REPORT_SIZE (8) */ \ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \ + 0x26, 0xE7, 0x00, /* LOGICAL_MAXIMUM (231) */ \ + 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ \ + 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ \ + 0x29, 0xE7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ \ + 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ \ +\ + /* End */ \ + 0xc0 /* END_COLLECTION */ +#endif + +#ifndef HID_REPORT_KEYBOARD_KEYS +#define HID_REPORT_KEYBOARD_KEYS(report_id) /* Keyboard */ \ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 47 */ \ + 0x09, 0x06, /* USAGE (Keyboard) */ \ + 0xa1, 0x01, /* COLLECTION (Application) */ \ + 0x85, report_id, /* REPORT_ID */ \ + 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ \ +\ + /* Keyboard Modifiers (shift, alt, ...) */ \ + 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) */ \ +\ + /* Reserved byte */ \ + 0x95, 0x01, /* REPORT_COUNT (1) */ \ + 0x75, 0x08, /* REPORT_SIZE (8) */ \ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ \ +\ + HID_REPORT_KEYBOARD_LEDS \ + /* 6 Keyboard keys */ \ + 0x95, 0x06, /* REPORT_COUNT (6) */ \ + 0x75, 0x08, /* REPORT_SIZE (8) */ \ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \ + 0x26, 0xE7, 0x00, /* LOGICAL_MAXIMUM (231) */ \ + 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ \ + 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ \ + 0x29, 0xE7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ \ + 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ \ +\ + /* End */ \ + 0xc0 /* END_COLLECTION */ +#endif + +//TODO limit to system keys only? +#ifndef HID_REPORT_SYSTEMCONTROL +#define HID_REPORT_SYSTEMCONTROL(report_id) /* System Control (Power Down, Sleep, Wakeup, ...) */ \ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ \ + 0x09, 0x80, /* USAGE (System Control) */ \ + 0xa1, 0x01, /* COLLECTION (Application) */ \ + 0x85, report_id, /* REPORT_ID */ \ + /* 1 system key */ \ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \ + 0x26, 0xff, 0x00, /* LOGICAL_MAXIMUM (255) */ \ + 0x19, 0x00, /* USAGE_MINIMUM (Undefined) */ \ + 0x29, 0xff, /* USAGE_MAXIMUM (System Menu Down) */ \ + 0x95, 0x01, /* REPORT_COUNT (1) */ \ + 0x75, 0x08, /* REPORT_SIZE (8) */ \ + 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ \ + 0xc0 /* END_COLLECTION */ +#endif + +#ifndef HID_REPORT_CONSUMERCONTROL +#define HID_REPORT_CONSUMERCONTROL(report_id) /* Consumer Control (Sound/Media keys) */ \ + 0x05, 0x0C, /* usage page (consumer device) */ \ + 0x09, 0x01, /* usage -- consumer control */ \ + 0xA1, 0x01, /* collection (application) */ \ + 0x85, report_id, /* report id */ \ + /* 4 Media Keys */ \ + 0x15, 0x00, /* logical minimum */ \ + 0x26, 0xFF, 0x03, /* logical maximum (3ff) */ \ + 0x19, 0x00, /* usage minimum (0) */ \ + 0x2A, 0xFF, 0x03, /* usage maximum (3ff) */ \ + 0x95, 0x04, /* report count (4) */ \ + 0x75, 0x10, /* report size (16) */ \ + 0x81, 0x00, /* input */ \ + 0xC0 /* end collection */ +#endif + +// note by NicoHood: RawHID might never work with multireports, because of OS problems +// therefore we have to make it a single report with no idea. No other HID device will be supported then. +#define RAWHID_USAGE_PAGE 0xFFC0 // recommended: 0xFF00 to 0xFFFF +#define RAWHID_USAGE 0x0C00 // recommended: 0x0100 to 0xFFFF +#define RAWHID_TX_SIZE (USB_EP_SIZE-1) +#define RAWHID_RX_SIZE (USB_EP_SIZE-1) + +#define LSB(_x) ((_x) & 0xFF) +#define MSB(_x) ((_x) >> 8) + +#ifndef HID_REPORT_RAWHID +#define HID_REPORT_RAWHID(report_id) /* RAW HID */ \ + 0x06, LSB(RAWHID_USAGE_PAGE), MSB(RAWHID_USAGE_PAGE), /* 30 */ \ + 0x0A, LSB(RAWHID_USAGE), MSB(RAWHID_USAGE), \ +\ + 0xA1, 0x01, /* Collection 0x01 */ \ + 0x85, report_id, /* REPORT_ID */ \ + 0x75, 0x08, /* report size = 8 bits */ \ + 0x15, 0x00, /* logical minimum = 0 */ \ + 0x26, 0xFF, 0x00, /* logical maximum = 255 */ \ +\ + 0x95, RAWHID_TX_SIZE, /* report count TX */ \ + 0x09, 0x01, /* usage */ \ + 0x81, 0x02, /* Input (array) */ \ +\ + 0x95, RAWHID_RX_SIZE, /* report count RX */ \ + 0x09, 0x02, /* usage */ \ + 0x91, 0x02, /* Output (array) */ \ + 0xC0 /* end collection */ +#endif + +#if defined(USBCON) + +#include "USBDesc.h" +#include "USBCore.h" +#include "HIDAPI.h" + +//================================================================================ +//================================================================================ +// 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); +#if defined(HID_KEYBOARD_LEDS_ENABLED) +void HID_SetKeyboardLedReport(uint8_t leds); +#endif + +#else /* if defined(USBCON) */ + +// (weak) function prototype to let the user use the HIDAPI for different use +// if he include the api himself +void HID_SendReport(uint8_t id, const void* data, int len); + +#endif /* if defined(USBCON) */ + +#endif \ No newline at end of file diff --git a/plugins/KeyboardioHID/HIDAPI.h b/plugins/KeyboardioHID/HIDAPI.h new file mode 100644 index 0000000000..6ce37be301 --- /dev/null +++ b/plugins/KeyboardioHID/HIDAPI.h @@ -0,0 +1,28 @@ +/* +HIDAPI.h +Copyright (c) 2005-2014 Arduino. All right reserved. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef __HIDAPI__ +#define __HIDAPI__ + +// include all HID APIs +#include "Keyboard.h" +#include "Mouse.h" +//TODO + +#endif \ No newline at end of file diff --git a/plugins/KeyboardioHID/Keyboard.cpp b/plugins/KeyboardioHID/Keyboard.cpp new file mode 100644 index 0000000000..2ab5f771fa --- /dev/null +++ b/plugins/KeyboardioHID/Keyboard.cpp @@ -0,0 +1,284 @@ +/* +Keyboard.cpp +Copyright (c) 2005-2014 Arduino. All right reserved. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "Keyboard.h" + +//================================================================================ +//================================================================================ +// Keyboard + +#if defined(HID_KEYBOARD_LEDS_ENABLED) +uint8_t hid_keyboard_leds = 0; +void HID_SetKeyboardLedReport(uint8_t leds){ + hid_keyboard_leds = leds; +} +#endif + +Keyboard_ Keyboard; + +Keyboard_::Keyboard_(void) +{ +} + +void Keyboard_::begin(void) +{ +} + +void Keyboard_::end(void) +{ +} + +void Keyboard_::sendReport(KeyReport* keys) +{ + HID_SendReport(HID_REPORTID_KEYBOARD, 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 +}; + +// 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) +{ + // release all keys + memset(&_keyReport, 0x00, sizeof(_keyReport)); + sendReport(&_keyReport); +} + +size_t Keyboard_::write(uint8_t c) +{ + uint8_t p = press(c); // Keydown + release(c); // Keyup + return p; // just return the result of press() since release() almost always returns 1 +} diff --git a/plugins/KeyboardioHID/Keyboard.h b/plugins/KeyboardioHID/Keyboard.h new file mode 100644 index 0000000000..6406245100 --- /dev/null +++ b/plugins/KeyboardioHID/Keyboard.h @@ -0,0 +1,110 @@ +/* +Keyboard.h +Copyright (c) 2005-2014 Arduino. All right reserved. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef __KEYBOARDAPI__ +#define __KEYBOARDAPI__ + +// to access the HID_SendReport via USBAPI.h, report number and the Print class +#include "Arduino.h" + +//================================================================================ +//================================================================================ +// Keyboard + +#define KEY_PRINT 0xCE +#define KEY_NUM_LOCK 0xDB +#define KEY_SCROLL_LOCK 0xCF +#define KEY_PAUSE 0xD0 + +#define KEY_LEFT_CTRL 0x80 +#define KEY_LEFT_SHIFT 0x81 +#define KEY_LEFT_ALT 0x82 +#define KEY_LEFT_GUI 0x83 +#define KEY_LEFT_WINDOWS KEY_LEFT_GUI +#define KEY_RIGHT_CTRL 0x84 +#define KEY_RIGHT_SHIFT 0x85 +#define KEY_RIGHT_ALT 0x86 +#define KEY_RIGHT_GUI 0x87 +#define KEY_RIGHT_WINDOWS KEY_RIGHT_GUI + +#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 + +#define LED_NUM_LOCK 0x01 +#define LED_CAPS_LOCK 0x02 +#define LED_SCROLL_LOCK 0x04 + +// 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; + +// extern accessible led out report +extern uint8_t hid_keyboard_leds; + +class Keyboard_ : public Print +{ +protected: + KeyReport _keyReport; + void sendReport(KeyReport* keys); +public: + Keyboard_(void); + void begin(void); + void end(void); + size_t write(uint8_t k); + size_t press(uint8_t k); + size_t release(uint8_t k); + void releaseAll(void); + + //TODO +#if defined(HID_KEYBOARD_LEDS_ENABLED) + inline uint8_t getLEDs(void){ return hid_keyboard_leds; } +#endif +}; +extern Keyboard_ Keyboard; + +#endif \ No newline at end of file diff --git a/plugins/KeyboardioHID/Mouse.cpp b/plugins/KeyboardioHID/Mouse.cpp new file mode 100644 index 0000000000..2debe1a06f --- /dev/null +++ b/plugins/KeyboardioHID/Mouse.cpp @@ -0,0 +1,88 @@ +/* +Mouse.cpp +Copyright (c) 2005-2014 Arduino. All right reserved. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "Mouse.h" + +//================================================================================ +//================================================================================ +// Mouse + +Mouse_ 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; +} + +void Mouse_::moveTo(uint16_t x, uint16_t y) +{ + uint32_t pos = ((uint32_t)y << 16) | x; + HID_SendReport(HID_REPORTID_MOUSE_ABSOLUTE, &pos, sizeof(pos)); +} diff --git a/plugins/KeyboardioHID/Mouse.h b/plugins/KeyboardioHID/Mouse.h new file mode 100644 index 0000000000..582f46b176 --- /dev/null +++ b/plugins/KeyboardioHID/Mouse.h @@ -0,0 +1,56 @@ +/* +Mouse.h +Copyright (c) 2005-2014 Arduino. All right reserved. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef __MOUSEAPI__ +#define __MOUSEAPI__ + +// to access the HID_SendReport via USBAPI.h and report number +#include "Arduino.h" + +//================================================================================ +//================================================================================ +// Mouse + +#define MOUSE_LEFT 0x01 +#define MOUSE_RIGHT 0x02 +#define MOUSE_MIDDLE 0x04 +#define MOUSE_PREV 0x08 +#define MOUSE_NEXT 0x10 +#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE | MOUSE_PREV | MOUSE_NEXT) + +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 + + void moveTo(uint16_t x, uint16_t y); +}; +extern Mouse_ Mouse; + +#endif diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md new file mode 100644 index 0000000000..2a3b917b1a --- /dev/null +++ b/plugins/KeyboardioHID/Readme.md @@ -0,0 +1,54 @@ +TODO +==== + +Under Construction. This is a todo list for myself and a feature list so far. + +``` +Keyboard Layout english only? +more usb definitions instead of fixed values, noone understands +someone has to add the keywords.txt definitions as well +keyboard music vol (change descriptor) +keyboard led move to usb function not to keyboard and from keyboard call this function? +weak hidsendreport implement somewhere the prototype? +move HID-Core to a seperate folder? +usb wakeup +keycode/raw for keyboard +magic key fix? +add examples +void Recv(volatile u8* data, u8 count) static inline?? + +Bugs +Mouse Abs only works with system report under special circumstances. +``` + + +``` +(flash numbers might be irrelevant due to a lot of improvements) +* Uses less flash if HID or Serial is not used +* Extended and compacter(flash) HID Report Descriptors +* Fixed USB Device Descriptor +* Added u2 compatibility with smaller USB_EP_SIZE (16u2 etc) +* Added Serial Event for LineEncoding and LineState (+12b flash) +* Added Serial Function to get dtr state, line encoding etc +* Added Keyboard Led Out report to get Led states (for numlock etc, +52b flash, 1b ram) +* Made CDC-Core independent from USB-Core +* Made HID-Core independent from USB-Core +* Made HID-API independent from HID-Core +* Removed not needed virtual functions in Keyboard +* Made HID Reports and its IDs replaceable via pins_Arduino.h +* Added Absolute Mouse +``` + +``` +Include schematic +- Arduino.h + - USBAPI.h -> Arduino.h, USBDESC.h, USBCore.h + - CDC.h -> Arduino.h, USBDESC.h, USBCore.h + - HID.h -> Arduino.h, USBDESC.h, USBCore.h, HID-API + - HID-API -> Keyboard.h, Mouse.h + - Keyboard.h -> Arduino.h + - Mouse.h -> Arduino.h + +HID.h contains all HID configuration. +Each HID-API (like Mouse) includes Arduino.h and gets these settings as well. +``` \ No newline at end of file diff --git a/plugins/KeyboardioHID/USBAPI.h b/plugins/KeyboardioHID/USBAPI.h index c135e52d6d..79cbc3ceaf 100644 --- a/plugins/KeyboardioHID/USBAPI.h +++ b/plugins/KeyboardioHID/USBAPI.h @@ -34,29 +34,6 @@ typedef unsigned long u32; #if defined(USBCON) -// include needed HID devices -// the more you activate, the more flash it will take -// by default only Mouse + Keyboard (without LEDs) are activated -#define HID_MOUSE_ENABLED -#define HID_KEYBOARD_ENABLED -//#define HID_KEYBOARD_LEDS_ENABLED - -//#define HID_RAWHID_ENABLED (currently broken for USB-Core) -//#define HID_MEDIA_ENABLED -//#define HID_SYSTEM_ENABLED -//#define HID_GAMEPAD_ENABLED - -/** Enum for the HID report IDs used in the device. */ -typedef enum{ - HID_REPORTID_NotAReport = 0x00, /**< first entry is always zero for multireports */ - HID_REPORTID_MouseReport = 0x01, /**< Report ID for the Mouse report within the device. */ - HID_REPORTID_KeyboardReport = 0x02, /**< Report ID for the Keyboard report within the device. */ - HID_REPORTID_RawHidReport = 0x03, /**< Report ID for the Raw Hid report within the device. */ - HID_REPORTID_MediaReport = 0x04, /**< Report ID for the Media report within the device. */ - HID_REPORTID_SystemReport = 0x05, /**< Report ID for the Power report within the device. */ - HID_REPORTID_GamepadReport = 0x06, /**< Report ID for the Gamepad report within the device. */ -} HID_Report_IDs; - #include "USBDesc.h" #include "USBCore.h" @@ -76,195 +53,6 @@ class USBDevice_ }; extern USBDevice_ USBDevice; -//================================================================================ -//================================================================================ -// Serial over CDC (Serial1 is the physical port) - -struct ring_buffer; - -#if (RAMEND < 1000) -#define SERIAL_BUFFER_SIZE 16 -#else -#define SERIAL_BUFFER_SIZE 64 -#endif - -class Serial_ : public Stream -{ -private: - int peek_buffer; -public: - Serial_() { peek_buffer = -1; }; - void begin(unsigned long); - void begin(unsigned long, uint8_t); - void end(void); - - virtual int available(void); - virtual int peek(void); - virtual int read(void); - virtual void flush(void); - virtual size_t write(uint8_t); - virtual size_t write(const uint8_t*, size_t); - using Print::write; // pull in write(str) and write(buf, size) from Print - uint32_t baud(void); - uint8_t stopbits(void); - uint8_t paritytype(void); - uint8_t numbits(void); - bool dtr(void); - bool rts(void); - operator bool(); - - volatile uint8_t _rx_buffer_head; - volatile uint8_t _rx_buffer_tail; - unsigned char _rx_buffer[SERIAL_BUFFER_SIZE]; -}; -extern Serial_ Serial; - -#define HAVE_CDCSERIAL - -//================================================================================ -//================================================================================ -// Mouse - -#ifdef HID_MOUSE_ENABLED - -#define MOUSE_LEFT 0x01 -#define MOUSE_RIGHT 0x02 -#define MOUSE_MIDDLE 0x04 -#define MOUSE_PREV 0x08 -#define MOUSE_NEXT 0x10 -#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE | MOUSE_PREV | MOUSE_NEXT) - -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; - -#endif - -//================================================================================ -//================================================================================ -// Keyboard - -#ifdef HID_KEYBOARD_ENABLED - -#define KEY_PRINT 0xCE -#define KEY_NUM_LOCK 0xDB -#define KEY_SCROLL_LOCK 0xCF -#define KEY_PAUSE 0xD0 - -#define KEY_LEFT_CTRL 0x80 -#define KEY_LEFT_SHIFT 0x81 -#define KEY_LEFT_ALT 0x82 -#define KEY_LEFT_GUI 0x83 -#define KEY_LEFT_WINDOWS KEY_LEFT_GUI -#define KEY_RIGHT_CTRL 0x84 -#define KEY_RIGHT_SHIFT 0x85 -#define KEY_RIGHT_ALT 0x86 -#define KEY_RIGHT_GUI 0x87 -#define KEY_RIGHT_WINDOWS KEY_RIGHT_GUI - -#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 - -#define LED_NUM_LOCK 0x01 -#define LED_CAPS_LOCK 0x02 -#define LED_SCROLL_LOCK 0x04 - -#if defined USBCON && defined(HID_KEYBOARD_ENABLED) && defined(HID_KEYBOARD_LEDS_ENABLED) -// extern accessible led out report -extern uint8_t hid_keyboard_leds; -#endif - -// 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); - -#if defined(HID_KEYBOARD_LEDS_ENABLED) - inline uint8_t getLEDs(void){ return hid_keyboard_leds; } -#endif -}; -extern Keyboard_ Keyboard; - -#endif - -//================================================================================ -//================================================================================ -// 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' diff --git a/plugins/KeyboardioHID/USBCore.h b/plugins/KeyboardioHID/USBCore.h index 4178b75a4a..35d850aede 100644 --- a/plugins/KeyboardioHID/USBCore.h +++ b/plugins/KeyboardioHID/USBCore.h @@ -317,5 +317,18 @@ typedef struct #define D_CDCCS(_subtype,_d0,_d1) { 5, 0x24, _subtype, _d0, _d1 } #define D_CDCCS4(_subtype,_d0) { 4, 0x24, _subtype, _d0 } +//================================================================================ +//================================================================================ +// Low level API + +typedef struct +{ + uint8_t bmRequestType; + uint8_t bRequest; + uint8_t wValueL; + uint8_t wValueH; + uint16_t wIndex; + uint16_t wLength; +} Setup; #endif \ No newline at end of file From d0f2b066cc2878e34cef356298f89d879ce51c90 Mon Sep 17 00:00:00 2001 From: Nico Date: Fri, 26 Dec 2014 22:12:24 +0100 Subject: [PATCH 075/602] Added static inline for Recv() Seems to be missing here? --- plugins/KeyboardioHID/USBCore.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/USBCore.cpp b/plugins/KeyboardioHID/USBCore.cpp index 82aa37272e..be38718415 100644 --- a/plugins/KeyboardioHID/USBCore.cpp +++ b/plugins/KeyboardioHID/USBCore.cpp @@ -128,7 +128,7 @@ static inline void ClearOUT(void) UEINTX = ~(1 << RXOUTI); } -void Recv(volatile u8* data, u8 count) +static inline void Recv(volatile u8* data, u8 count) { while (count--) *data++ = UEDATX; From f80e9cfc204ea5f93eae2e88b77171fd59c015ab Mon Sep 17 00:00:00 2001 From: Nico Date: Fri, 26 Dec 2014 22:13:33 +0100 Subject: [PATCH 076/602] Added Consumer + System HID APIs --- plugins/KeyboardioHID/Consumer.cpp | 27 +++++++ plugins/KeyboardioHID/Consumer.h | 113 +++++++++++++++++++++++++++++ plugins/KeyboardioHID/HID.h | 2 + plugins/KeyboardioHID/HIDAPI.h | 3 +- plugins/KeyboardioHID/Readme.md | 3 +- plugins/KeyboardioHID/System.cpp | 26 +++++++ plugins/KeyboardioHID/System.h | 72 ++++++++++++++++++ 7 files changed, 244 insertions(+), 2 deletions(-) create mode 100644 plugins/KeyboardioHID/Consumer.cpp create mode 100644 plugins/KeyboardioHID/Consumer.h create mode 100644 plugins/KeyboardioHID/System.cpp create mode 100644 plugins/KeyboardioHID/System.h diff --git a/plugins/KeyboardioHID/Consumer.cpp b/plugins/KeyboardioHID/Consumer.cpp new file mode 100644 index 0000000000..6c685d97e2 --- /dev/null +++ b/plugins/KeyboardioHID/Consumer.cpp @@ -0,0 +1,27 @@ +/* +Consumer.cpp +Copyright (c) 2005-2014 Arduino. All right reserved. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "Consumer.h" + +//================================================================================ +// Consumer +//================================================================================ + +// object instance +Consumer_ Consumer; \ No newline at end of file diff --git a/plugins/KeyboardioHID/Consumer.h b/plugins/KeyboardioHID/Consumer.h new file mode 100644 index 0000000000..70e3cd0d59 --- /dev/null +++ b/plugins/KeyboardioHID/Consumer.h @@ -0,0 +1,113 @@ +/* +Consumer.h +Copyright (c) 2005-2014 Arduino. All right reserved. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef __CONSUMERAPI__ +#define __CONSUMERAPI__ + +// to access the HID_SendReport via USBAPI.h and report number +#include "Arduino.h" + +//TODO workaround to access the weak sending function +void HID_SendReport(uint8_t id, const void* data, int len); + +//================================================================================ +// Consumer +//================================================================================ + +// Media key definitions, see official USB docs for more +#define MEDIA_FAST_FORWARD 0xB3 +#define MEDIA_REWIND 0xB4 +#define MEDIA_NEXT 0xB5 +#define MEDIA_PREVIOUS 0xB6 +#define MEDIA_STOP 0xB7 +#define MEDIA_PLAY_PAUSE 0xCD + +#define MEDIA_VOLUME_MUTE 0xE2 +#define MEDIA_VOLUME_UP 0xE9 +#define MEDIA_VOLUME_DOWN 0xEA + +#define CONSUMER_EMAIL_READER 0x18A +#define CONSUMER_CALCULATOR 0x192 +#define CONSUMER_EXPLORER 0x194 + +#define CONSUMER_BROWSER_HOME 0x223 +#define CONSUMER_BROWSER_BACK 0x224 +#define CONSUMER_BROWSER_FORWARD 0x225 +#define CONSUMER_BROWSER_REFRESH 0x227 +#define CONSUMER_BROWSER_BOOKMARKS 0x22A + +typedef union{ + // every usable Consumer key possible, up to 4 keys presses possible + uint8_t whole8[8]; + uint16_t whole16[8 / 2]; + uint32_t whole32[8 / 4]; + struct{ + uint16_t key1; + uint16_t key2; + uint16_t key3; + uint16_t key4; + }; +} HID_ConsumerReport_Data_t; + +class Consumer_{ +public: + inline Consumer_(void){ + // empty + } + inline void begin(void){ + // release all buttons + end(); + } + inline void end(void){ + memset(&_report, 0, sizeof(_report)); + HID_SendReport(HID_REPORTID_CONSUMERCONTROL, &_report, sizeof(_report)); + } + inline void write(uint16_t m){ + press(m); + release(m); + } + inline void press(uint16_t m){ + // search for a free spot + for (int i = 0; i < sizeof(HID_ConsumerReport_Data_t) / 2; i++) { + if (_report.whole16[i] == 0x00) { + _report.whole16[i] = m; + break; + } + } + HID_SendReport(HID_REPORTID_CONSUMERCONTROL, &_report, sizeof(_report)); + } + inline void release(uint16_t m){ + // search and release the keypress + for (int i = 0; i < sizeof(HID_ConsumerReport_Data_t) / 2; i++) { + if (_report.whole16[i] == m) { + _report.whole16[i] = 0x00; + // no break to delete multiple keys + } + } + HID_SendReport(HID_REPORTID_CONSUMERCONTROL, &_report, sizeof(_report)); + } + inline void releaseAll(void){ + begin(); + } +private: + HID_ConsumerReport_Data_t _report; +}; +extern Consumer_ Consumer; + +#endif \ No newline at end of file diff --git a/plugins/KeyboardioHID/HID.h b/plugins/KeyboardioHID/HID.h index 66a86b27a6..89dc0f5df8 100644 --- a/plugins/KeyboardioHID/HID.h +++ b/plugins/KeyboardioHID/HID.h @@ -262,6 +262,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "USBDesc.h" #include "USBCore.h" +// only include HIDAPI if we have an USB AVR MCU. +// The use can overwrite HID_SendReport() and manually include the APIs. #include "HIDAPI.h" //================================================================================ diff --git a/plugins/KeyboardioHID/HIDAPI.h b/plugins/KeyboardioHID/HIDAPI.h index 6ce37be301..0acabafba5 100644 --- a/plugins/KeyboardioHID/HIDAPI.h +++ b/plugins/KeyboardioHID/HIDAPI.h @@ -23,6 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // include all HID APIs #include "Keyboard.h" #include "Mouse.h" -//TODO +#include "Consumer.h" +#include "System.h" #endif \ No newline at end of file diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 2a3b917b1a..63dfc1cc8f 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -7,7 +7,6 @@ Under Construction. This is a todo list for myself and a feature list so far. Keyboard Layout english only? more usb definitions instead of fixed values, noone understands someone has to add the keywords.txt definitions as well -keyboard music vol (change descriptor) keyboard led move to usb function not to keyboard and from keyboard call this function? weak hidsendreport implement somewhere the prototype? move HID-Core to a seperate folder? @@ -16,6 +15,8 @@ keycode/raw for keyboard magic key fix? add examples void Recv(volatile u8* data, u8 count) static inline?? +improve workaround for consumer + system weak hid send function prototype +add gamepad Bugs Mouse Abs only works with system report under special circumstances. diff --git a/plugins/KeyboardioHID/System.cpp b/plugins/KeyboardioHID/System.cpp new file mode 100644 index 0000000000..1d1d78d4ca --- /dev/null +++ b/plugins/KeyboardioHID/System.cpp @@ -0,0 +1,26 @@ +/* +System.cpp +Copyright (c) 2005-2014 Arduino. All right reserved. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "System.h" + +//================================================================================ +// System +//================================================================================ + +System_ System; \ No newline at end of file diff --git a/plugins/KeyboardioHID/System.h b/plugins/KeyboardioHID/System.h new file mode 100644 index 0000000000..815b2af3a6 --- /dev/null +++ b/plugins/KeyboardioHID/System.h @@ -0,0 +1,72 @@ +/* +System.h +Copyright (c) 2005-2014 Arduino. All right reserved. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef __SYSTEMAPI__ +#define __SYSTEMAPI__ + +// to access the HID_SendReport via USBAPI.h and report number +#include "Arduino.h" + +//TODO workaround to access the weak sending function +void HID_SendReport(uint8_t id, const void* data, int len); + +//================================================================================ +// System +//================================================================================ + +#define SYSTEM_POWER_DOWN 0x81 +#define SYSTEM_SLEEP 0x82 +#define SYSTEM_WAKE_UP 0x83 + +typedef union{ + // every usable system control key possible + uint8_t whole8[1]; + uint8_t key; +} HID_SystemReport_Data_t; + +class System_{ +public: + inline System_(void){ + // empty + } + inline void begin(void){ + // release all buttons + end(); + } + inline void end(void){ + uint8_t _report = 0; + HID_SendReport(HID_REPORTID_SYSTEMCONTROL, &_report, sizeof(_report)); + } + inline void write(uint8_t s){ + press(s); + release(); + } + inline void press(uint8_t s){ + HID_SendReport(HID_REPORTID_SYSTEMCONTROL, &s, sizeof(s)); + } + inline void release(void){ + begin(); + } + inline void releaseAll(void){ + begin(); + } +}; +extern System_ System; + +#endif \ No newline at end of file From 0542ef30d76965899822c4e73a608401d1805c0d Mon Sep 17 00:00:00 2001 From: Nico Date: Sat, 27 Dec 2014 12:56:19 +0100 Subject: [PATCH 077/602] Improved Mouse + Keyboard functions Also added Keycodes to Keyboard API. --- plugins/KeyboardioHID/Arduino.h | 1 + plugins/KeyboardioHID/HIDTables.h | 677 +++++++++++++++++++++++++++++ plugins/KeyboardioHID/Keyboard.cpp | 140 +++++- plugins/KeyboardioHID/Keyboard.h | 31 +- plugins/KeyboardioHID/Mouse.cpp | 61 --- plugins/KeyboardioHID/Mouse.h | 80 +++- plugins/KeyboardioHID/Readme.md | 8 + 7 files changed, 901 insertions(+), 97 deletions(-) create mode 100644 plugins/KeyboardioHID/HIDTables.h diff --git a/plugins/KeyboardioHID/Arduino.h b/plugins/KeyboardioHID/Arduino.h index 64d156d467..192c6e8135 100644 --- a/plugins/KeyboardioHID/Arduino.h +++ b/plugins/KeyboardioHID/Arduino.h @@ -224,6 +224,7 @@ extern const uint8_t PROGMEM digital_pin_to_timer_PGM[]; #include "USBAPI.h" #include "CDC.h" #include "HID.h" +#include "HIDTables.h" #if defined(HAVE_HWSERIAL0) && defined(HAVE_CDCSERIAL) #error "Targets with both UART0 and CDC serial not supported" diff --git a/plugins/KeyboardioHID/HIDTables.h b/plugins/KeyboardioHID/HIDTables.h new file mode 100644 index 0000000000..8092e1fbf8 --- /dev/null +++ b/plugins/KeyboardioHID/HIDTables.h @@ -0,0 +1,677 @@ +#ifndef __HIDTables__ +#define HID___HIDTables__ + + +// These mappings were extracted and transcribed from +// http://www.usb.org_SLASH_developers_SLASH_devclass_docs_SLASH_Hut1_12v2.pdf +// +// In most cases, I've preserved the "official" USB Implementers forum +// "Usage Name", though I've standardized some abbreviations and spacing +// that were inconsistent in the original specification. Non alpha-numeric +// characters in symbol names were converted into those characters' names. +// +// To match Arduino code style, all hid usage names are fully upper case. +// +// Not every HID usage listed in this file is currently supported by Arduino +// In particular, any System Control or Consumer Control entry that doesn't +// have a comment indicating that it's "HID type OSC" will require additional +// code in the Arduino core to work. +// +// Non-working usages are listed here in the interest of not having to manually +// convert more usage names each and every time our HID stack gets a little bit +// better. +// +// +// -- Jesse Vincent , January 2014 + + + +// System control mappings + +#define HID_SYSTEM_POWER_DOWN 0x81 // HID type OSC +#define HID_SYSTEM_SLEEP 0x82 // HID type OSC +#define HID_SYSTEM_WAKE_UP 0x83 // HID type OSC +#define HID_SYSTEM_CONTEXT_MENU 0x84 // HID type OSC +#define HID_SYSTEM_MAIN_MENU 0x85 // HID type OSC +#define HID_SYSTEM_APP_MENU 0x86 // HID type OSC +#define HID_SYSTEM_MENU_HELP 0x87 // HID type OSC +#define HID_SYSTEM_MENU_EXIT 0x88 // HID type OSC +#define HID_SYSTEM_MENU_SELECT 0x89 // HID type OSC +#define HID_SYSTEM_MENU_RIGHT 0x8A // HID type RTC +#define HID_SYSTEM_MENU_LEFT 0x8B // HID type RTC +#define HID_SYSTEM_MENU_UP 0x8C // HID type RTC +#define HID_SYSTEM_MENU_DOWN 0x8D // HID type RTC +#define HID_SYSTEM_COLD_RESTART 0x8E // HID type OSC +#define HID_SYSTEM_WARM_RESTART 0x8F // HID type OSC +#define HID_D_PAD_UP 0x90 // HID type OOC +#define HID_D_PAD_DOWN 0x91 // HID type OOC +#define HID_D_PAD_RIGHT 0x92 // HID type OOC +#define HID_D_PAD_LEFT 0x93 // HID type OOC +// 0x94-0x9F are reserved +#define HID_SYSTEM_DOCK 0xA0 // HID type OSC +#define HID_SYSTEM_UNDOCK 0xA1 // HID type OSC +#define HID_SYSTEM_SETUP 0xA2 // HID type OSC +#define HID_SYSTEM_BREAK 0xA3 // HID type OSC +#define HID_SYSTEM_DEBUGGER_BREAK 0xA4 // HID type OSC +#define HID_APPLICATION_BREAK 0xA5 // HID type OSC +#define HID_APPLICATION_DEBUGGER_BREAK 0xA6 // HID type OSC +#define HID_SYSTEM_SPEAKER_MUTE 0xA7 // HID type OSC +#define HID_SYSTEM_HIBERNATE 0xA8 // HID type OSC +// 0xA9-0xAF are reserved +#define HID_SYSTEM_DISPLAY_INVERT 0xB0 // HID type OSC +#define HID_SYSTEM_DISPLAY_INTERNAL 0xB1 // HID type OSC +#define HID_SYSTEM_DISPLAY_EXTERNAL 0xB2 // HID type OSC +#define HID_SYSTEM_DISPLAY_BOTH 0xB3 // HID type OSC +#define HID_SYSTEM_DISPLAY_DUAL 0xB4 // HID type OSC +#define HID_SYSTEM_DISPLAY_TOGGLE_INT_SLASH_EXT 0xB5 // HID type OSC +#define HID_SYSTEM_DISPLAY_SWAP_PRIMARY_SLASH_SECONDARY 0xB6 // HID type OSC +#define HID_SYSTEM_DISPLAY_LCD_AUTOSCALE 0xB7 // HID type OSC + +// Keyboard HID mappings + +// Reserved (no_event_indicated) 0x00 +#define HID_KEYBOARD_ERROR_ROLLOVER 0x01 +#define HID_KEYBOARD_POST_FAIL 0x02 +#define HID_KEYBOARD_ERROR_UNDEFINED 0x03 +#define HID_KEYBOARD_A_AND_A 0x04 +#define HID_KEYBOARD_B_AND_B 0x05 +#define HID_KEYBOARD_C_AND_C 0x06 +#define HID_KEYBOARD_D_AND_D 0x07 +#define HID_KEYBOARD_E_AND_E 0x08 +#define HID_KEYBOARD_F_AND_F 0x09 +#define HID_KEYBOARD_G_AND_G 0x0A +#define HID_KEYBOARD_H_AND_H 0x0B +#define HID_KEYBOARD_I_AND_I 0x0C +#define HID_KEYBOARD_J_AND_J 0x0D +#define HID_KEYBOARD_K_AND_K 0x0E +#define HID_KEYBOARD_L_AND_L 0x0F +#define HID_KEYBOARD_M_AND_M 0x10 +#define HID_KEYBOARD_N_AND_N 0x11 +#define HID_KEYBOARD_O_AND_O 0x12 +#define HID_KEYBOARD_P_AND_P 0x13 +#define HID_KEYBOARD_Q_AND_Q 0x14 +#define HID_KEYBOARD_R_AND_R 0x15 +#define HID_KEYBOARD_S_AND_S 0x16 +#define HID_KEYBOARD_T_AND_T 0x17 +#define HID_KEYBOARD_U_AND_U 0x18 +#define HID_KEYBOARD_V_AND_V 0x19 +#define HID_KEYBOARD_W_AND_W 0x1A +#define HID_KEYBOARD_X_AND_X 0x1B +#define HID_KEYBOARD_Y_AND_Y 0x1C +#define HID_KEYBOARD_Z_AND_Z 0x1D +#define HID_KEYBOARD_1_AND_EXCLAMATION_POINT 0x1E +#define HID_KEYBOARD_2_AND_AT 0x1F +#define HID_KEYBOARD_3_AND_POUND 0x20 +#define HID_KEYBOARD_4_AND_DOLLAR 0x21 +#define HID_KEYBOARD_5_AND_PERCENT 0x22 +#define HID_KEYBOARD_6_AND_CARAT 0x23 +#define HID_KEYBOARD_7_AND_AMPERSAND 0x24 +#define HID_KEYBOARD_8_AND_ASTERISK 0x25 +#define HID_KEYBOARD_9_AND_LEFT_PAREN 0x26 +#define HID_KEYBOARD_0_AND_RIGHT_PAREN 0x27 +#define HID_KEYBOARD_ENTER 0x28 // (MARKED AS ENTER_SLASH_RETURN) +#define HID_KEYBOARD_ESCAPE 0x29 +#define HID_KEYBOARD_DELETE 0x2A // (BACKSPACE) +#define HID_KEYBOARD_TAB 0x2B +#define HID_KEYBOARD_SPACEBAR 0x2C +#define HID_KEYBOARD_MINUS_AND_UNDERSCORE 0x2D // (UNDERSCORE) +#define HID_KEYBOARD_EQUALS_AND_PLUS 0x2E +#define HID_KEYBOARD_LEFT_BRACKET_AND_LEFT_CURLY_BRACE 0x2F +#define HID_KEYBOARD_RIGHT_BRACKET_AND_RIGHT_CURLY_BRACE 0x30 +#define HID_KEYBOARD_BACKSLASH_AND_PIPE 0x31 +#define HID_KEYBOARD_NON_US_POUND_AND_TILDE 0x32 +#define HID_KEYBOARD_SEMICOLON_AND_COLON 0x33 +#define HID_KEYBOARD_QUOTE_AND_DOUBLEQUOTE 0x34 +#define HID_KEYBOARD_GRAVE_ACCENT_AND_TILDE 0x35 +#define HID_KEYBOARD_COMMA_AND_LESS_THAN 0x36 +#define HID_KEYBOARD_PERIOD_AND_GREATER_THAN 0x37 +#define HID_KEYBOARD_SLASH_AND_QUESTION_MARK 0x38 +#define HID_KEYBOARD_CAPS_LOCK 0x39 +#define HID_KEYBOARD_F1 0x3A +#define HID_KEYBOARD_F2 0x3B +#define HID_KEYBOARD_F3 0x3C +#define HID_KEYBOARD_F4 0x3D +#define HID_KEYBOARD_F5 0x3E +#define HID_KEYBOARD_F6 0x3F +#define HID_KEYBOARD_F7 0x40 +#define HID_KEYBOARD_F8 0x41 +#define HID_KEYBOARD_F9 0x42 +#define HID_KEYBOARD_F10 0x43 +#define HID_KEYBOARD_F11 0x44 +#define HID_KEYBOARD_F12 0x45 +#define HID_KEYBOARD_PRINTSCREEN 0x46 +#define HID_KEYBOARD_SCROLL_LOCK 0x47 +#define HID_KEYBOARD_PAUSE 0x48 +#define HID_KEYBOARD_INSERT 0x49 +#define HID_KEYBOARD_HOME 0x4A +#define HID_KEYBOARD_PAGE_UP 0x4B +#define HID_KEYBOARD_DELETE_FORWARD 0x4C +#define HID_KEYBOARD_END 0x4D +#define HID_KEYBOARD_PAGE_DOWN 0x4E +#define HID_KEYBOARD_RIGHTARROW 0x4F +#define HID_KEYBOARD_LEFTARROW 0x50 +#define HID_KEYBOARD_DOWNARROW 0x51 +#define HID_KEYBOARD_UPARROW 0x52 +#define HID_KEYPAD_NUM_LOCK_AND_CLEAR 0x53 +#define HID_KEYPAD_DIVIDE 0x54 +#define HID_KEYPAD_MULTIPLY 0x55 +#define HID_KEYPAD_SUBTRACT 0x56 +#define HID_KEYPAD_ADD 0x57 +#define HID_KEYPAD_ENTER 0x58 +#define HID_KEYPAD_1_AND_END 0x59 +#define HID_KEYPAD_2_AND_DOWN_ARROW 0x5A +#define HID_KEYPAD_3_AND_PAGE_DOWN 0x5B +#define HID_KEYPAD_4_AND_LEFT_ARROW 0x5C +#define HID_KEYPAD_5 0x5D +#define HID_KEYPAD_6_AND_RIGHT_ARROW 0x5E +#define HID_KEYPAD_7_AND_HOME 0x5F +#define HID_KEYPAD_8_AND_UP_ARROW 0x60 +#define HID_KEYPAD_9_AND_PAGE_UP 0x61 +#define HID_KEYPAD_0_AND_INSERT 0x62 +#define HID_KEYPAD_PERIOD_AND_DELETE 0x63 +#define HID_KEYBOARD_NON_US_BACKSLASH_AND_PIPE 0x64 +#define HID_KEYBOARD_APPLICATION 0x65 +#define HID_KEYBOARD_POWER 0x66 +#define HID_KEYPAD_EQUALS 0x67 +#define HID_KEYBOARD_F13 0x68 +#define HID_KEYBOARD_F14 0x69 +#define HID_KEYBOARD_F15 0x6A +#define HID_KEYBOARD_F16 0x6B +#define HID_KEYBOARD_F17 0x6C +#define HID_KEYBOARD_F18 0x6D +#define HID_KEYBOARD_F19 0x6E +#define HID_KEYBOARD_F20 0x6F +#define HID_KEYBOARD_F21 0x70 +#define HID_KEYBOARD_F22 0x71 +#define HID_KEYBOARD_F23 0x72 +#define HID_KEYBOARD_F24 0x73 +#define HID_KEYBOARD_EXECUTE 0x74 +#define HID_KEYBOARD_HELP 0x75 +#define HID_KEYBOARD_MENU 0x76 +#define HID_KEYBOARD_SELECT 0x77 +#define HID_KEYBOARD_STOP 0x78 +#define HID_KEYBOARD_AGAIN 0x79 +#define HID_KEYBOARD_UNDO 0x7A +#define HID_KEYBOARD_CUT 0x7B +#define HID_KEYBOARD_COPY 0x7C +#define HID_KEYBOARD_PASTE 0x7D +#define HID_KEYBOARD_FIND 0x7E +#define HID_KEYBOARD_MUTE 0x7F +#define HID_KEYBOARD_VOLUME_UP 0x80 +#define HID_KEYBOARD_VOLUME_DOWN 0x81 +#define HID_KEYBOARD_LOCKING_CAPS_LOCK 0x82 +#define HID_KEYBOARD_LOCKING_NUM_LOCK 0x83 +#define HID_KEYBOARD_LOCKING_SCROLL_LOCK 0x84 +#define HID_KEYPAD_COMMA 0x85 +#define HID_KEYPAD_EQUAL_SIGN 0x86 +#define HID_KEYBOARD_INTERNATIONAL1 0x87 +#define HID_KEYBOARD_INTERNATIONAL2 0x88 +#define HID_KEYBOARD_INTERNATIONAL3 0x89 +#define HID_KEYBOARD_INTERNATIONAL4 0x8A +#define HID_KEYBOARD_INTERNATIONAL5 0x8B +#define HID_KEYBOARD_INTERNATIONAL6 0x8C +#define HID_KEYBOARD_INTERNATIONAL7 0x8D +#define HID_KEYBOARD_INTERNATIONAL8 0x8E +#define HID_KEYBOARD_INTERNATIONAL9 0x8F +#define HID_KEYBOARD_LANG1 0x90 +#define HID_KEYBOARD_LANG2 0x91 +#define HID_KEYBOARD_LANG3 0x92 +#define HID_KEYBOARD_LANG4 0x93 +#define HID_KEYBOARD_LANG5 0x94 +#define HID_KEYBOARD_LANG6 0x95 +#define HID_KEYBOARD_LANG7 0x96 +#define HID_KEYBOARD_LANG8 0x97 +#define HID_KEYBOARD_LANG9 0x98 +#define HID_KEYBOARD_ALTERNATE_ERASE 0x99 +#define HID_KEYBOARD_SYSREQ_SLASH_ATTENTION 0x9A +#define HID_KEYBOARD_CANCEL 0x9B +#define HID_KEYBOARD_CLEAR 0x9C +#define HID_KEYBOARD_PRIOR 0x9D +#define HID_KEYBOARD_RETURN 0x9E +#define HID_KEYBOARD_SEPARATOR 0x9F +#define HID_KEYBOARD_OUT 0xA0 +#define HID_KEYBOARD_OPER 0xA1 +#define HID_KEYBOARD_CLEAR_SLASH_AGAIN 0xA2 +#define HID_KEYBOARD_CRSEL_SLASH_PROPS 0xA3 +#define HID_KEYBOARD_EXSEL 0xA4 +// Reserved 0xA5-AF +#define HID_KEYPAD_00 0xB0 +#define HID_KEYPAD_000 0xB1 +#define HID_THOUSANDS_SEPARATOR 0xB2 +#define HID_DECIMAL_SEPARATOR 0xB3 +#define HID_CURRENCY_UNIT 0xB4 +#define HID_CURRENCY_SUBUNIT 0xB5 +#define HID_KEYPAD_LEFT_PAREN 0xB6 +#define HID_KEYPAD_RIGHT_PAREN 0xB7 +#define HID_KEYPAD_LEFT_CURLY_BRACE 0xB8 +#define HID_KEYPAD_RIGHT_CURLY_BRACE 0xB9 +#define HID_KEYPAD_TAB 0xBA +#define HID_KEYPAD_BACKSPACE 0xBB +#define HID_KEYPAD_A 0xBC +#define HID_KEYPAD_B 0xBD +#define HID_KEYPAD_C 0xBE +#define HID_KEYPAD_D 0xBF +#define HID_KEYPAD_E 0xC0 +#define HID_KEYPAD_F 0xC1 +#define HID_KEYPAD_XOR 0xC2 +#define HID_KEYPAD_CARAT 0xC3 +#define HID_KEYPAD_PERCENT 0xC4 +#define HID_KEYPAD_LESS_THAN 0xC5 +#define HID_KEYPAD_GREATER_THAN 0xC6 +#define HID_KEYPAD_AMPERSAND 0xC7 +#define HID_KEYPAD_DOUBLEAMPERSAND 0xC8 +#define HID_KEYPAD_PIPE 0xC9 +#define HID_KEYPAD_DOUBLEPIPE 0xCA +#define HID_KEYPAD_COLON 0xCB +#define HID_KEYPAD_POUND_SIGN 0xCC +#define HID_KEYPAD_SPACE 0xCD +#define HID_KEYPAD_AT_SIGN 0xCE +#define HID_KEYPAD_EXCLAMATION_POINT 0xCF +#define HID_KEYPAD_MEMORY_STORE 0xD0 +#define HID_KEYPAD_MEMORY_RECALL 0xD1 +#define HID_KEYPAD_MEMORY_CLEAR 0xD2 +#define HID_KEYPAD_MEMORY_ADD 0xD3 +#define HID_KEYPAD_MEMORY_SUBTRACT 0xD4 +#define HID_KEYPAD_MEMORY_MULTIPLY 0xD5 +#define HID_KEYPAD_MEMORY_DIVIDE 0xD6 +#define HID_KEYPAD_PLUS_SLASH_MINUS 0xD7 +#define HID_KEYPAD_CLEAR 0xD8 +#define HID_KEYPAD_CLEAR_ENTRY 0xD9 +#define HID_KEYPAD_BINARY 0xDA +#define HID_KEYPAD_OCTAL 0xDB +#define HID_KEYPAD_DECIMAL 0xDC +#define HID_KEYPAD_HEXADECIMAL 0xDD + +// 0xDE-0xDF - RESERVED +#define HID_KEYBOARD_LEFT_CONTROL 0xE0 +#define HID_KEYBOARD_LEFT_SHIFT 0xE1 +#define HID_KEYBOARD_LEFT_ALT 0xE2 +#define HID_KEYBOARD_LEFT_GUI 0xE3 +#define HID_KEYBOARD_RIGHT_CONTROL 0xE4 +#define HID_KEYBOARD_RIGHT_SHIFT 0xE5 +#define HID_KEYBOARD_RIGHT_ALT 0xE6 +#define HID_KEYBOARD_RIGHT_GUI 0xE7 + + +// Consumer_Page_(0x0C) 0x15 +#define HID_CONSUMER_NUMERIC_KEY_PAD 0x02 // HID type NARY +#define HID_CONSUMER_PROGRAMMABLE_BUTTONS 0x03 // HID type NARY +#define HID_CONSUMER_MICROPHONE_CA 0x04 +#define HID_CONSUMER_HEADPHONE_CA 0x05 +#define HID_CONSUMER_GRAPHIC_EQUALIZER_CA 0x06 +// Reserved 0x07-1F +#define HID_CONSUMER_PLUS_10 0x20 // HID type OSC +#define HID_CONSUMER_PLUS_100 0x21 // HID type OSC +#define HID_CONSUMER_AM_SLASH_PM 0x22 // HID type OSC +// Reserved 0x23-3F +#define HID_CONSUMER_POWER 0x30 // HID type OOC +#define HID_CONSUMER_RESET 0x31 // HID type OSC +#define HID_CONSUMER_SLEEP 0x32 // HID type OSC +#define HID_CONSUMER_SLEEP_AFTER 0x33 // HID type OSC +#define HID_CONSUMER_SLEEP_MODE 0x34 // HID type RTC +#define HID_CONSUMER_ILLUMINATION 0x35 // HID type OOC +#define HID_CONSUMER_FUNCTION_BUTTONS 0x36 // HID type NARY +// Reserved 0x37-3F +#define HID_CONSUMER_MENU 0x40 // HID type OOC +#define HID_CONSUMER_MENU_PICK 0x41 // HID type OSC +#define HID_CONSUMER_MENU_UP 0x42 // HID type OSC +#define HID_CONSUMER_MENU_DOWN 0x43 // HID type OSC +#define HID_CONSUMER_MENU_LEFT 0x44 // HID type OSC +#define HID_CONSUMER_MENU_RIGHT 0x45 // HID type OSC +#define HID_CONSUMER_MENU_ESCAPE 0x46 // HID type OSC +#define HID_CONSUMER_MENU_VALUE_INCREASE 0x47 // HID type OSC +#define HID_CONSUMER_MENU_VALUE_DECREASE 0x48 // HID type OSC +// Reserved 0x49-5F +#define HID_CONSUMER_DATA_ON_SCREEN 0x60 // HID type OOC +#define HID_CONSUMER_CLOSED_CAPTION 0x61 // HID type OOC +#define HID_CONSUMER_CLOSED_CAPTION_SELECT 0x62 // HID type OSC +#define HID_CONSUMER_VCR_SLASH_TV 0x63 // HID type OOC +#define HID_CONSUMER_BROADCAST_MODE 0x64 // HID type OSC +#define HID_CONSUMER_SNAPSHOT 0x65 // HID type OSC +#define HID_CONSUMER_STILL 0x66 // HID type OSC +// Reserved 0x67-7F +#define HID_CONSUMER_SELECTION 0x80 // HID type NARY +#define HID_CONSUMER_ASSIGN_SELECTION 0x81 // HID type OSC +#define HID_CONSUMER_MODE_STEP 0x82 // HID type OSC +#define HID_CONSUMER_RECALL_LAST 0x83 // HID type OSC +#define HID_CONSUMER_ENTER_CHANNEL 0x84 // HID type OSC +#define HID_CONSUMER_ORDER_MOVIE 0x85 // HID type OSC +#define HID_CONSUMER_CHANNEL 0x86 // HID type LC +#define HID_CONSUMER_MEDIA_SELECTION 0x87 // HID type NARY +#define HID_CONSUMER_MEDIA_SELECT_COMPUTER 0x88 // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_TV 0x89 // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_WWW 0x8A // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_DVD 0x8B // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_TELEPHONE 0x8C // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_PROGRAM_GUIDE 0x8D // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_VIDEO_PHONE 0x8E // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_GAMES 0x8F // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_MESSAGES 0x90 // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_CD 0x91 // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_VCR 0x92 // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_TUNER 0x93 // HID type SEL +#define HID_CONSUMER_QUIT 0x94 // HID type OSC +#define HID_CONSUMER_HELP 0x95 // HID type OOC +#define HID_CONSUMER_MEDIA_SELECT_TAPE 0x96 // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_CABLE 0x97 // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_SATELLITE 0x98 // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_SECURITY 0x99 // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_HOME 0x9A // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_CALL 0x9B // HID type SEL +#define HID_CONSUMER_CHANNEL_INCREMENT 0x9C // HID type OSC +#define HID_CONSUMER_CHANNEL_DECREMENT 0x9D // HID type OSC +#define HID_CONSUMER_MEDIA_SELECT_SAP 0x9E // HID type SEL +// Reserved 0x9F +#define HID_CONSUMER_VCR_PLUS 0xA0 // HID type OSC +#define HID_CONSUMER_ONCE 0xA1 // HID type OSC +#define HID_CONSUMER_DAILY 0xA2 // HID type OSC +#define HID_CONSUMER_WEEKLY 0xA3 // HID type OSC +#define HID_CONSUMER_MONTHLY 0xA4 // HID type OSC +// Reserved 0xA5-AF +#define HID_CONSUMER_PLAY 0xB0 // HID type OOC +#define HID_CONSUMER_PAUSE 0xB1 // HID type OOC +#define HID_CONSUMER_RECORD 0xB2 // HID type OOC +#define HID_CONSUMER_FAST_FORWARD 0xB3 // HID type OOC +#define HID_CONSUMER_REWIND 0xB4 // HID type OOC +#define HID_CONSUMER_SCAN_NEXT_TRACK 0xB5 // HID type OSC +#define HID_CONSUMER_SCAN_PREVIOUS_TRACK 0xB6 // HID type OSC +#define HID_CONSUMER_STOP 0xB7 // HID type OSC +#define HID_CONSUMER_EJECT 0xB8 // HID type OSC +#define HID_CONSUMER_RANDOM_PLAY 0xB9 // HID type OOC +#define HID_CONSUMER_SELECT_DISC 0xBA // HID type NARY +#define HID_CONSUMER_ENTER_DISC_MC 0xBB +#define HID_CONSUMER_REPEAT 0xBC // HID type OSC +#define HID_CONSUMER_TRACKING 0xBD // HID type LC +#define HID_CONSUMER_TRACK_NORMAL 0xBE // HID type OSC +#define HID_CONSUMER_SLOW_TRACKING 0xBF // HID type LC +#define HID_CONSUMER_FRAME_FORWARD 0xC0 // HID type RTC +#define HID_CONSUMER_FRAME_BACK 0xC1 // HID type RTC +#define HID_CONSUMER_MARK 0xC2 // HID type OSC +#define HID_CONSUMER_CLEAR_MARK 0xC3 // HID type OSC +#define HID_CONSUMER_REPEAT_FROM_MARK 0xC4 // HID type OOC +#define HID_CONSUMER_RETURN_TO_MARK 0xC5 // HID type OSC +#define HID_CONSUMER_SEARCH_MARK_FORWARD 0xC6 // HID type OSC +#define HID_CONSUMER_SEARCH_MARK_BACKWARDS 0xC7 // HID type OSC +#define HID_CONSUMER_COUNTER_RESET 0xC8 // HID type OSC +#define HID_CONSUMER_SHOW_COUNTER 0xC9 // HID type OSC +#define HID_CONSUMER_TRACKING_INCREMENT 0xCA // HID type RTC +#define HID_CONSUMER_TRACKING_DECREMENT 0xCB // HID type RTC +#define HID_CONSUMER_STOP_SLASH_EJECT 0xCC // HID type OSC +#define HID_CONSUMER_PLAY_SLASH_PAUSE 0xCD // HID type OSC +#define HID_CONSUMER_PLAY_SLASH_SKIP 0xCE // HID type OSC +// Reserved 0xCF-DF +#define HID_CONSUMER_VOLUME 0xE0 // HID type LC +#define HID_CONSUMER_BALANCE 0xE1 // HID type LC +#define HID_CONSUMER_MUTE 0xE2 // HID type OOC +#define HID_CONSUMER_BASS 0xE3 // HID type LC +#define HID_CONSUMER_TREBLE 0xE4 // HID type LC +#define HID_CONSUMER_BASS_BOOST 0xE5 // HID type OOC +#define HID_CONSUMER_SURROUND_MODE 0xE6 // HID type OSC +#define HID_CONSUMER_LOUDNESS 0xE7 // HID type OOC +#define HID_CONSUMER_MPX 0xE8 // HID type OOC +#define HID_CONSUMER_VOLUME_INCREMENT 0xE9 // HID type RTC +#define HID_CONSUMER_VOLUME_DECREMENT 0xEA // HID type RTC +// Reserved 0xEB-EF +#define HID_CONSUMER_SPEED_SELECT 0xF0 // HID type OSC +#define HID_CONSUMER_PLAYBACK_SPEED 0xF1 // HID type NARY +#define HID_CONSUMER_STANDARD_PLAY 0xF2 // HID type SEL +#define HID_CONSUMER_LONG_PLAY 0xF3 // HID type SEL +#define HID_CONSUMER_EXTENDED_PLAY 0xF4 // HID type SEL +#define HID_CONSUMER_SLOW 0xF5 // HID type OSC +// Reserved 0xF6-FF +#define HID_CONSUMER_FAN_ENABLE 0x100 // HID type OOC +#define HID_CONSUMER_FAN_SPEED 0x101 // HID type LC +#define HID_CONSUMER_LIGHT_ENABLE 0x102 // HID type OOC +#define HID_CONSUMER_LIGHT_ILLUMINATION_LEVEL 0x103 // HID type LC +#define HID_CONSUMER_CLIMATE_CONTROL_ENABLE 0x104 // HID type OOC +#define HID_CONSUMER_ROOM_TEMPERATURE 0x105 // HID type LC +#define HID_CONSUMER_SECURITY_ENABLE 0x106 // HID type OOC +#define HID_CONSUMER_FIRE_ALARM 0x107 // HID type OSC +#define HID_CONSUMER_POLICE_ALARM 0x108 // HID type OSC +#define HID_CONSUMER_PROXIMITY 0x109 // HID type LC +#define HID_CONSUMER_MOTION 0x10A // HID type OSC +#define HID_CONSUMER_DURESS_ALARM 0x10B // HID type OSC +#define HID_CONSUMER_HOLDUP_ALARM 0x10C // HID type OSC +#define HID_CONSUMER_MEDICAL_ALARM 0x10D // HID type OSC +// Reserved 0x10E-14F +#define HID_CONSUMER_BALANCE_RIGHT 0x150 // HID type RTC +#define HID_CONSUMER_BALANCE_LEFT 0x151 // HID type RTC +#define HID_CONSUMER_BASS_INCREMENT 0x152 // HID type RTC +#define HID_CONSUMER_BASS_DECREMENT 0x153 // HID type RTC +#define HID_CONSUMER_TREBLE_INCREMENT 0x154 // HID type RTC +#define HID_CONSUMER_TREBLE_DECREMENT 0x155 // HID type RTC +// Reserved 0x156-15F +#define HID_CONSUMER_SPEAKER_SYSTEM 0x160 // HID type CL +#define HID_CONSUMER_CHANNEL_LEFT 0x161 // HID type CL +#define HID_CONSUMER_CHANNEL_RIGHT 0x162 // HID type CL +#define HID_CONSUMER_CHANNEL_CENTER 0x163 // HID type CL +#define HID_CONSUMER_CHANNEL_FRONT 0x164 // HID type CL +#define HID_CONSUMER_CHANNEL_CENTER_FRONT 0x165 // HID type CL +#define HID_CONSUMER_CHANNEL_SIDE 0x166 // HID type CL +#define HID_CONSUMER_CHANNEL_SURROUND 0x167 // HID type CL +#define HID_CONSUMER_CHANNEL_LOW_FREQUENCY_ENHANCEMENT 0x168 // HID type CL +#define HID_CONSUMER_CHANNEL_TOP 0x169 // HID type CL +#define HID_CONSUMER_CHANNEL_UNKNOWN 0x16A // HID type CL +// Reserved 0x16B-16F +#define HID_CONSUMER_SUB-CHANNEL 0x170 // HID type LC +#define HID_CONSUMER_SUB-CHANNEL_INCREMENT 0x171 // HID type OSC +#define HID_CONSUMER_SUB-CHANNEL_DECREMENT 0x172 // HID type OSC +#define HID_CONSUMER_ALTERNATE_AUDIO_INCREMENT 0x173 // HID type OSC +#define HID_CONSUMER_ALTERNATE_AUDIO_DECREMENT 0x174 // HID type OSC +// Reserved 0x175-17F +#define HID_CONSUMER_APPLICATION_LAUNCH_BUTTONS 0x180 // HID type NARY +#define HID_CONSUMER_AL_LAUNCH_BUTTON_CONFIGURATION_TOOL 0x181 // HID type SEL +#define HID_CONSUMER_AL_PROGRAMMABLE_BUTTON_CONFIGURATION 0x182 // HID type SEL +#define HID_CONSUMER_AL_CONSUMER_CONTROL_CONFIGURATION 0x183 // HID type SEL +#define HID_CONSUMER_AL_WORD_PROCESSOR 0x184 // HID type SEL +#define HID_CONSUMER_AL_TEXT_EDITOR 0x185 // HID type SEL +#define HID_CONSUMER_AL_SPREADSHEET 0x186 // HID type SEL +#define HID_CONSUMER_AL_GRAPHICS_EDITOR 0x187 // HID type SEL +#define HID_CONSUMER_AL_PRESENTATION_APP 0x188 // HID type SEL +#define HID_CONSUMER_AL_DATABASE_APP 0x189 // HID type SEL +#define HID_CONSUMER_AL_EMAIL_READER 0x18A // HID type SEL +#define HID_CONSUMER_AL_NEWSREADER 0x18B // HID type SEL +#define HID_CONSUMER_AL_VOICEMAIL 0x18C // HID type SEL +#define HID_CONSUMER_AL_CONTACTS_SLASH_ADDRESS_BOOK 0x18D // HID type SEL +#define HID_CONSUMER_AL_CALENDAR_SLASH_SCHEDULE 0x18E // HID type SEL +#define HID_CONSUMER_AL_TASK_SLASH_PROJECT_MANAGER 0x18F // HID type SEL +#define HID_CONSUMER_AL_LOG_SLASH_JOURNAL_SLASH_TIMECARD 0x190 // HID type SEL +#define HID_CONSUMER_AL_CHECKBOOK_SLASH_FINANCE 0x191 // HID type SEL +#define HID_CONSUMER_AL_CALCULATOR 0x192 // HID type SEL +#define HID_CONSUMER_AL_A_SLASH_V_CAPTURE_SLASH_PLAYBACK 0x193 // HID type SEL +#define HID_CONSUMER_AL_LOCAL_MACHINE_BROWSER 0x194 // HID type SEL +#define HID_CONSUMER_AL_LAN_SLASH_WAN_BROWSER 0x195 // HID type SEL +#define HID_CONSUMER_AL_INTERNET_BROWSER 0x196 // HID type SEL +#define HID_CONSUMER_AL_REMOTE_NETWORKING_SLASH_ISP_CONNECT 0x197 // HID type SEL +#define HID_CONSUMER_AL_NETWORK_CONFERENCE 0x198 // HID type SEL +#define HID_CONSUMER_AL_NETWORK_CHAT 0x199 // HID type SEL +#define HID_CONSUMER_AL_TELEPHONY_SLASH_DIALER 0x19A // HID type SEL +#define HID_CONSUMER_AL_LOGON 0x19B // HID type SEL +#define HID_CONSUMER_AL_LOGOFF 0x19C // HID type SEL +#define HID_CONSUMER_AL_LOGON_SLASH_LOGOFF 0x19D // HID type SEL +#define HID_CONSUMER_AL_TERMINAL_LOCK_SLASH_SCREENSAVER 0x19E // HID type SEL +#define HID_CONSUMER_AL_CONTROL_PANEL 0x19F // HID type SEL +#define HID_CONSUMER_AL_COMMAND_LINE_PROCESSOR_SLASH_RUN 0x1A0 // HID type SEL +#define HID_CONSUMER_AL_PROCESS_SLASH_TASK_MANAGER 0x1A1 // HID type SEL +#define HID_CONSUMER_AL_SELECT_TASK_SLASH_APPLICATION 0x1A2 // HID type SEL +#define HID_CONSUMER_AL_NEXT_TASK_SLASH_APPLICATION 0x1A3 // HID type SEL +#define HID_CONSUMER_AL_PREVIOUS_TASK_SLASH_APPLICATION 0x1A4 // HID type SEL +#define HID_CONSUMER_AL_PREEMPTIVE_HALT_TASK_SLASH_APPLICATION 0x1A5 // HID type SEL +#define HID_CONSUMER_AL_INTEGRATED_HELP_CENTER 0x1A6 // HID type SEL +#define HID_CONSUMER_AL_DOCUMENTS 0x1A7 // HID type SEL +#define HID_CONSUMER_AL_THESAURUS 0x1A8 // HID type SEL +#define HID_CONSUMER_AL_DICTIONARY 0x1A9 // HID type SEL +#define HID_CONSUMER_AL_DESKTOP 0x1AA // HID type SEL +#define HID_CONSUMER_AL_SPELL_CHECK 0x1AB // HID type SEL +#define HID_CONSUMER_AL_GRAMMAR_CHECK 0x1AC // HID type SEL +#define HID_CONSUMER_AL_WIRELESS_STATUS 0x1AD // HID type SEL +#define HID_CONSUMER_AL_KEYBOARD_LAYOUT 0x1AE // HID type SEL +#define HID_CONSUMER_AL_VIRUS_PROTECTION 0x1AF // HID type SEL +#define HID_CONSUMER_AL_ENCRYPTION 0x1B0 // HID type SEL +#define HID_CONSUMER_AL_SCREEN_SAVER 0x1B1 // HID type SEL +#define HID_CONSUMER_AL_ALARMS 0x1B2 // HID type SEL +#define HID_CONSUMER_AL_CLOCK 0x1B3 // HID type SEL +#define HID_CONSUMER_AL_FILE_BROWSER 0x1B4 // HID type SEL +#define HID_CONSUMER_AL_POWER_STATUS 0x1B5 // HID type SEL +#define HID_CONSUMER_AL_IMAGE_BROWSER 0x1B6 // HID type SEL +#define HID_CONSUMER_AL_AUDIO_BROWSER 0x1B7 // HID type SEL +#define HID_CONSUMER_AL_MOVIE_BROWSER 0x1B8 // HID type SEL +#define HID_CONSUMER_AL_DIGITAL_RIGHTS_MANAGER 0x1B9 // HID type SEL +#define HID_CONSUMER_AL_DIGITAL_WALLET 0x1BA // HID type SEL +// _Reserved 0x1BB +#define HID_CONSUMER_AL_INSTANT_MESSAGING 0x1BC // HID type SEL +#define HID_CONSUMER_AL_OEM_FEATURES_SLASH__TIPS_SLASH_TUTORIAL_BROWSER 0x1BD // HID type SEL +#define HID_CONSUMER_AL_OEM_HELP 0x1BE // HID type SEL +#define HID_CONSUMER_AL_ONLINE_COMMUNITY 0x1BF // HID type SEL +#define HID_CONSUMER_AL_ENTERTAINMENT_CONTENT_BROWSER 0x1C0 // HID type SEL +#define HID_CONSUMER_AL_ONLINE_SHOPPING_BROWSER 0x1C1 // HID type SEL +#define HID_CONSUMER_AL_SMARTCARD_INFORMATION_SLASH_HELP 0x1C2 // HID type SEL +#define HID_CONSUMER_AL_MARKET_MONITOR_SLASH_FINANCE_BROWSER 0x1C3 // HID type SEL +#define HID_CONSUMER_AL_CUSTOMIZED_CORPORATE_NEWS_BROWSER 0x1C4 // HID type SEL +#define HID_CONSUMER_AL_ONLINE_ACTIVITY_BROWSER 0x1C5 // HID type SEL +#define HID_CONSUMER_AL_RESEARCH_SLASH_SEARCH_BROWSER 0x1C6 // HID type SEL +#define HID_CONSUMER_AL_AUDIO_PLAYER 0x1C7 // HID type SEL +// Reserved 0x1C8-1FF +#define HID_CONSUMER_GENERIC_GUI_APPLICATION_CONTROLS 0x200 // HID type NARY +#define HID_CONSUMER_AC_NEW 0x201 // HID type SEL +#define HID_CONSUMER_AC_OPEN 0x202 // HID type SEL +#define HID_CONSUMER_AC_CLOSE 0x203 // HID type SEL +#define HID_CONSUMER_AC_EXIT 0x204 // HID type SEL +#define HID_CONSUMER_AC_MAXIMIZE 0x205 // HID type SEL +#define HID_CONSUMER_AC_MINIMIZE 0x206 // HID type SEL +#define HID_CONSUMER_AC_SAVE 0x207 // HID type SEL +#define HID_CONSUMER_AC_PRINT 0x208 // HID type SEL +#define HID_CONSUMER_AC_PROPERTIES 0x209 // HID type SEL +#define HID_CONSUMER_AC_UNDO 0x21A // HID type SEL +#define HID_CONSUMER_AC_COPY 0x21B // HID type SEL +#define HID_CONSUMER_AC_CUT 0x21C // HID type SEL +#define HID_CONSUMER_AC_PASTE 0x21D // HID type SEL +#define HID_CONSUMER_AC_SELECT_ALL 0x21E // HID type SEL +#define HID_CONSUMER_AC_FIND 0x21F // HID type SEL +#define HID_CONSUMER_AC_FIND_AND_REPLACE 0x220 // HID type SEL +#define HID_CONSUMER_AC_SEARCH 0x221 // HID type SEL +#define HID_CONSUMER_AC_GO_TO 0x222 // HID type SEL +#define HID_CONSUMER_AC_HOME 0x223 // HID type SEL +#define HID_CONSUMER_AC_BACK 0x224 // HID type SEL +#define HID_CONSUMER_AC_FORWARD 0x225 // HID type SEL +#define HID_CONSUMER_AC_STOP 0x226 // HID type SEL +#define HID_CONSUMER_AC_REFRESH 0x227 // HID type SEL +#define HID_CONSUMER_AC_PREVIOUS_LINK 0x228 // HID type SEL +#define HID_CONSUMER_AC_NEXT_LINK 0x229 // HID type SEL +#define HID_CONSUMER_AC_BOOKMARKS 0x22A // HID type SEL +#define HID_CONSUMER_AC_HISTORY 0x22B // HID type SEL +#define HID_CONSUMER_AC_SUBSCRIPTIONS 0x22C // HID type SEL +#define HID_CONSUMER_AC_ZOOM_IN 0x22D // HID type SEL +#define HID_CONSUMER_AC_ZOOM_OUT 0x22E // HID type SEL +#define HID_CONSUMER_AC_ZOOM 0x22F // HID type LC +#define HID_CONSUMER_AC_FULL_SCREEN_VIEW 0x230 // HID type SEL +#define HID_CONSUMER_AC_NORMAL_VIEW 0x231 // HID type SEL +#define HID_CONSUMER_AC_VIEW_TOGGLE 0x232 // HID type SEL +#define HID_CONSUMER_AC_SCROLL_UP 0x233 // HID type SEL +#define HID_CONSUMER_AC_SCROLL_DOWN 0x234 // HID type SEL +#define HID_CONSUMER_AC_SCROLL 0x235 // HID type LC +#define HID_CONSUMER_AC_PAN_LEFT 0x236 // HID type SEL +#define HID_CONSUMER_AC_PAN_RIGHT 0x237 // HID type SEL +#define HID_CONSUMER_AC_PAN 0x238 // HID type LC +#define HID_CONSUMER_AC_NEW_WINDOW 0x239 // HID type SEL +#define HID_CONSUMER_AC_TILE_HORIZONTALLY 0x23A // HID type SEL +#define HID_CONSUMER_AC_TILE_VERTICALLY 0x23B // HID type SEL +#define HID_CONSUMER_AC_FORMAT 0x23C // HID type SEL +#define HID_CONSUMER_AC_EDIT 0x23D // HID type SEL +#define HID_CONSUMER_AC_BOLD 0x23E // HID type SEL +#define HID_CONSUMER_AC_ITALICS 0x23F // HID type SEL +#define HID_CONSUMER_AC_UNDERLINE 0x240 // HID type SEL +#define HID_CONSUMER_AC_STRIKETHROUGH 0x241 // HID type SEL +#define HID_CONSUMER_AC_SUBSCRIPT 0x242 // HID type SEL +#define HID_CONSUMER_AC_SUPERSCRIPT 0x243 // HID type SEL +#define HID_CONSUMER_AC_ALL_CAPS 0x244 // HID type SEL +#define HID_CONSUMER_AC_ROTATE 0x245 // HID type SEL +#define HID_CONSUMER_AC_RESIZE 0x246 // HID type SEL +#define HID_CONSUMER_AC_FLIP_HORIZONTAL 0x247 // HID type SEL +#define HID_CONSUMER_AC_FLIP_VERTICAL 0x248 // HID type SEL +#define HID_CONSUMER_AC_MIRROR_HORIZONTAL 0x249 // HID type SEL +#define HID_CONSUMER_AC_MIRROR_VERTICAL 0x24A // HID type SEL +#define HID_CONSUMER_AC_FONT_SELECT 0x24B // HID type SEL +#define HID_CONSUMER_AC_FONT_COLOR 0x24C // HID type SEL +#define HID_CONSUMER_AC_FONT_SIZE 0x24D // HID type SEL +#define HID_CONSUMER_AC_JUSTIFY_LEFT 0x24E // HID type SEL +#define HID_CONSUMER_AC_JUSTIFY_CENTER_H 0x24F // HID type SEL +#define HID_CONSUMER_AC_JUSTIFY_RIGHT 0x250 // HID type SEL +#define HID_CONSUMER_AC_JUSTIFY_BLOCK_H 0x251 // HID type SEL +#define HID_CONSUMER_AC_JUSTIFY_TOP 0x252 // HID type SEL +#define HID_CONSUMER_AC_JUSTIFY_CENTER_V 0x253 // HID type SEL +#define HID_CONSUMER_AC_JUSTIFY_BOTTOM 0x254 // HID type SEL +#define HID_CONSUMER_AC_JUSTIFY_BLOCK_V 0x255 // HID type SEL +#define HID_CONSUMER_AC_INDENT_DECREASE 0x256 // HID type SEL +#define HID_CONSUMER_AC_INDENT_INCREASE 0x257 // HID type SEL +#define HID_CONSUMER_AC_NUMBERED_LIST 0x258 // HID type SEL +#define HID_CONSUMER_AC_RESTART_NUMBERING 0x259 // HID type SEL +#define HID_CONSUMER_AC_BULLETED_LIST 0x25A // HID type SEL +#define HID_CONSUMER_AC_PROMOTE 0x25B // HID type SEL +#define HID_CONSUMER_AC_DEMOTE 0x25C // HID type SEL +#define HID_CONSUMER_AC_YES 0x25D // HID type SEL +#define HID_CONSUMER_AC_NO 0x25E // HID type SEL +#define HID_CONSUMER_AC_CANCEL 0x25F // HID type SEL +#define HID_CONSUMER_AC_CATALOG 0x260 // HID type SEL +#define HID_CONSUMER_AC_BUY_SLASH_CHECKOUT 0x261 // HID type SEL +#define HID_CONSUMER_AC_ADD_TO_CART 0x262 // HID type SEL +#define HID_CONSUMER_AC_EXPAND 0x263 // HID type SEL +#define HID_CONSUMER_AC_EXPAND_ALL 0x264 // HID type SEL +#define HID_CONSUMER_AC_COLLAPSE 0x265 // HID type SEL +#define HID_CONSUMER_AC_COLLAPSE_ALL 0x266 // HID type SEL +#define HID_CONSUMER_AC_PRINT_PREVIEW 0x267 // HID type SEL +#define HID_CONSUMER_AC_PASTE_SPECIAL 0x268 // HID type SEL +#define HID_CONSUMER_AC_INSERT_MODE 0x269 // HID type SEL +#define HID_CONSUMER_AC_DELETE 0x26A // HID type SEL +#define HID_CONSUMER_AC_LOCK 0x26B // HID type SEL +#define HID_CONSUMER_AC_UNLOCK 0x26C // HID type SEL +#define HID_CONSUMER_AC_PROTECT 0x26D // HID type SEL +#define HID_CONSUMER_AC_UNPROTECT 0x26E // HID type SEL +#define HID_CONSUMER_AC_ATTACH_COMMENT 0x26F // HID type SEL +#define HID_CONSUMER_AC_DELETE_COMMENT 0x270 // HID type SEL +#define HID_CONSUMER_AC_VIEW_COMMENT 0x271 // HID type SEL +#define HID_CONSUMER_AC_SELECT_WORD 0x272 // HID type SEL +#define HID_CONSUMER_AC_SELECT_SENTENCE 0x273 // HID type SEL +#define HID_CONSUMER_AC_SELECT_PARAGRAPH 0x274 // HID type SEL +#define HID_CONSUMER_AC_SELECT_COLUMN 0x275 // HID type SEL +#define HID_CONSUMER_AC_SELECT_ROW 0x276 // HID type SEL +#define HID_CONSUMER_AC_SELECT_TABLE 0x277 // HID type SEL +#define HID_CONSUMER_AC_SELECT_OBJECT 0x278 // HID type SEL +#define HID_CONSUMER_AC_REDO_SLASH_REPEAT 0x279 // HID type SEL +#define HID_CONSUMER_AC_SORT 0x27A // HID type SEL +#define HID_CONSUMER_AC_SORT_ASCENDING 0x27B // HID type SEL +#define HID_CONSUMER_AC_SORT_DESCENDING 0x27C // HID type SEL +#define HID_CONSUMER_AC_FILTER 0x27D // HID type SEL +#define HID_CONSUMER_AC_SET_CLOCK 0x27E // HID type SEL +#define HID_CONSUMER_AC_VIEW_CLOCK 0x27F // HID type SEL +#define HID_CONSUMER_AC_SELECT_TIME_ZONE 0x280 // HID type SEL +#define HID_CONSUMER_AC_EDIT_TIME_ZONES 0x281 // HID type SEL +#define HID_CONSUMER_AC_SET_ALARM 0x282 // HID type SEL +#define HID_CONSUMER_AC_CLEAR_ALARM 0x283 // HID type SEL +#define HID_CONSUMER_AC_SNOOZE_ALARM 0x284 // HID type SEL +#define HID_CONSUMER_AC_RESET_ALARM 0x285 // HID type SEL +#define HID_CONSUMER_AC_SYNCHRONIZE 0x286 // HID type SEL +#define HID_CONSUMER_AC_SEND_SLASH_RECEIVE 0x287 // HID type SEL +#define HID_CONSUMER_AC_SEND_TO 0x288 // HID type SEL +#define HID_CONSUMER_AC_REPLY 0x289 // HID type SEL +#define HID_CONSUMER_AC_REPLY_ALL 0x28A // HID type SEL +#define HID_CONSUMER_AC_FORWARD_MSG 0x28B // HID type SEL +#define HID_CONSUMER_AC_SEND 0x28C // HID type SEL +#define HID_CONSUMER_AC_ATTACH_FILE 0x28D // HID type SEL +#define HID_CONSUMER_AC_UPLOAD 0x28E // HID type SEL +#define HID_CONSUMER_AC_DOWNLOAD_(SAVE_TARGET_AS) 0x28F // HID type SEL +#define HID_CONSUMER_AC_SET_BORDERS 0x290 // HID type SEL +#define HID_CONSUMER_AC_INSERT_ROW 0x291 // HID type SEL +#define HID_CONSUMER_AC_INSERT_COLUMN 0x292 // HID type SEL +#define HID_CONSUMER_AC_INSERT_FILE 0x293 // HID type SEL +#define HID_CONSUMER_AC_INSERT_PICTURE 0x294 // HID type SEL +#define HID_CONSUMER_AC_INSERT_OBJECT 0x295 // HID type SEL +#define HID_CONSUMER_AC_INSERT_SYMBOL 0x296 // HID type SEL +#define HID_CONSUMER_AC_SAVE_AND_CLOSE 0x297 // HID type SEL +#define HID_CONSUMER_AC_RENAME 0x298 // HID type SEL +#define HID_CONSUMER_AC_MERGE 0x299 // HID type SEL +#define HID_CONSUMER_AC_SPLIT 0x29A // HID type SEL +#define HID_CONSUMER_AC_DISRIBUTE_HORIZONTALLY 0x29B // HID type SEL +#define HID_CONSUMER_AC_DISTRIBUTE_VERTICALLY 0x29C // HID type SEL + +#endif // __HIDTables__ diff --git a/plugins/KeyboardioHID/Keyboard.cpp b/plugins/KeyboardioHID/Keyboard.cpp index 2ab5f771fa..0ab9d4e281 100644 --- a/plugins/KeyboardioHID/Keyboard.cpp +++ b/plugins/KeyboardioHID/Keyboard.cpp @@ -26,24 +26,13 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #if defined(HID_KEYBOARD_LEDS_ENABLED) uint8_t hid_keyboard_leds = 0; void HID_SetKeyboardLedReport(uint8_t leds){ + // implementation of the weak function in HID.cpp hid_keyboard_leds = leds; } #endif Keyboard_ Keyboard; -Keyboard_::Keyboard_(void) -{ -} - -void Keyboard_::begin(void) -{ -} - -void Keyboard_::end(void) -{ -} - void Keyboard_::sendReport(KeyReport* keys) { HID_SendReport(HID_REPORTID_KEYBOARD, keys, sizeof(KeyReport)); @@ -206,9 +195,9 @@ size_t Keyboard_::press(uint8_t k) setWriteError(); return 0; } - if (k & 0x80) { // it's a capital letter or other character reached with shift + if (k & SHIFT) { // it's a capital letter or other character reached with shift _keyReport.modifiers |= 0x02; // the left shift modifier - k &= 0x7F; + k = k ^ SHIFT; } } @@ -251,9 +240,9 @@ size_t Keyboard_::release(uint8_t k) if (!k) { return 0; } - if (k & 0x80) { // it's a capital letter or other character reached with shift + if (k & SHIFT) { // it's a capital letter or other character reached with shift _keyReport.modifiers &= ~(0x02); // the left shift modifier - k &= 0x7F; + k = k ^ SHIFT; } } @@ -282,3 +271,122 @@ size_t Keyboard_::write(uint8_t c) release(c); // Keyup return p; // just return the result of press() since release() almost always returns 1 } + + +// pressKeycode() 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 releaseKeycode(), releaseAll(), or otherwise clear the report and resend. +size_t Keyboard_::pressKeycode(uint8_t k) +{ + if (!addKeycodeToReport(k)) { + return 0; + } + sendReport(&_keyReport); +} + +size_t Keyboard_::addKeycodeToReport(uint8_t k) +{ + uint8_t index = 0; + uint8_t done = 0; + + if ((k >= HID_KEYBOARD_LEFT_CONTROL) && (k <= HID_KEYBOARD_RIGHT_GUI)) { + // it's a modifier key + _keyReport.modifiers |= (0x01 << (k - HID_KEYBOARD_LEFT_CONTROL)); + } + else { + // it's some other key: + // Add k to the key report only if it's not already present + // and if there is an empty slot. + for (index = 0; index < sizeof(_keyReport.keys); index++) { + if (_keyReport.keys[index] != k) { // is k already in list? + if (0 == _keyReport.keys[index]) { // have we found an empty slot? + _keyReport.keys[index] = k; + done = 1; + break; + } + } + else { + done = 1; + break; + } + + } + + // use separate variable to check if slot was found + // for style reasons - we do not know how the compiler + // handles the for() index when it leaves the loop + if (0 == done) { + setWriteError(); + return 0; + } + } + + return 1; +} + + +// releaseKeycode() 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. +// When send is set to FALSE (= 0) no sendReport() is executed. This comes in +// handy when combining key releases (e.g. SHIFT+A). +size_t Keyboard_::releaseKeycode(uint8_t k) +{ + if (!removeKeycodeFromReport(k)) { + return 0; + } + sendReport(&_keyReport); +} + +size_t Keyboard_::removeKeycodeFromReport(uint8_t k) +{ + uint8_t indexA; + uint8_t indexB; + uint8_t count; + + if ((k >= HID_KEYBOARD_LEFT_CONTROL) && (k <= HID_KEYBOARD_RIGHT_GUI)) { + // it's a modifier key + _keyReport.modifiers = _keyReport.modifiers & (~(0x01 << (k - HID_KEYBOARD_LEFT_CONTROL))); + } + else { + // it's some other key: + // 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 (indexA = 0; indexA < sizeof(_keyReport.keys); indexA++) { + if (_keyReport.keys[indexA] == k) { + _keyReport.keys[indexA] = 0; + } + } + + // finally rearrange the keys list so that the free (= 0x00) are at the + // end of the keys list - some implementations stop for keys at the + // first occurence of an 0x00 in the keys list + // so (0x00)(0x01)(0x00)(0x03)(0x02)(0x00) becomes + // (0x01)(0x03)(0x02)(0x00)(0x00)(0x00) + count = 0; // holds the number of zeros we've found + indexA = 0; + while ((indexA + count) < sizeof(_keyReport.keys)) { + if (0 == _keyReport.keys[indexA]) { + count++; // one more zero + for (indexB = indexA; indexB < sizeof(_keyReport.keys) - count; indexB++) { + _keyReport.keys[indexB] = _keyReport.keys[indexB + 1]; + } + _keyReport.keys[sizeof(_keyReport.keys) - count] = 0; + } + else { + indexA++; // one more non-zero + } + } + } + + return 1; +} + + +size_t Keyboard_::writeKeycode(uint8_t c) +{ + uint8_t p = pressKeycode(c); // Keydown + releaseKeycode(c); // Keyup + return (p); // just return the result of pressKeycode() since release() almost always returns 1 +} \ No newline at end of file diff --git a/plugins/KeyboardioHID/Keyboard.h b/plugins/KeyboardioHID/Keyboard.h index 6406245100..36274a690b 100644 --- a/plugins/KeyboardioHID/Keyboard.h +++ b/plugins/KeyboardioHID/Keyboard.h @@ -23,6 +23,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // to access the HID_SendReport via USBAPI.h, report number and the Print class #include "Arduino.h" +//TODO workaround to access the weak sending function +void HID_SendReport(uint8_t id, const void* data, int len); + //================================================================================ //================================================================================ // Keyboard @@ -84,7 +87,9 @@ typedef struct } KeyReport; // extern accessible led out report +#if defined(HID_KEYBOARD_LEDS_ENABLED) extern uint8_t hid_keyboard_leds; +#endif class Keyboard_ : public Print { @@ -92,15 +97,31 @@ class Keyboard_ : public Print KeyReport _keyReport; void sendReport(KeyReport* keys); public: - Keyboard_(void); - void begin(void); - void end(void); + inline Keyboard_(void){ + // empty + } + + inline void begin(void){ + // edit by NicoHood + end(); + } + + inline void end(void){ + // edit by NicoHood + releaseAll(); + } + size_t write(uint8_t k); size_t press(uint8_t k); - size_t release(uint8_t k); + inline size_t release(uint8_t k); void releaseAll(void); - //TODO + size_t writeKeycode(uint8_t k); + size_t pressKeycode(uint8_t k); + size_t releaseKeycode(uint8_t k); + size_t addKeycodeToReport(uint8_t k); + size_t removeKeycodeFromReport(uint8_t k); + #if defined(HID_KEYBOARD_LEDS_ENABLED) inline uint8_t getLEDs(void){ return hid_keyboard_leds; } #endif diff --git a/plugins/KeyboardioHID/Mouse.cpp b/plugins/KeyboardioHID/Mouse.cpp index 2debe1a06f..f4c2504f25 100644 --- a/plugins/KeyboardioHID/Mouse.cpp +++ b/plugins/KeyboardioHID/Mouse.cpp @@ -25,64 +25,3 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Mouse_ 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; -} - -void Mouse_::moveTo(uint16_t x, uint16_t y) -{ - uint32_t pos = ((uint32_t)y << 16) | x; - HID_SendReport(HID_REPORTID_MOUSE_ABSOLUTE, &pos, sizeof(pos)); -} diff --git a/plugins/KeyboardioHID/Mouse.h b/plugins/KeyboardioHID/Mouse.h index 582f46b176..789428207b 100644 --- a/plugins/KeyboardioHID/Mouse.h +++ b/plugins/KeyboardioHID/Mouse.h @@ -23,15 +23,20 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // to access the HID_SendReport via USBAPI.h and report number #include "Arduino.h" +//TODO workaround to access the weak sending function +void HID_SendReport(uint8_t id, const void* data, int len); + //================================================================================ //================================================================================ // Mouse -#define MOUSE_LEFT 0x01 -#define MOUSE_RIGHT 0x02 -#define MOUSE_MIDDLE 0x04 -#define MOUSE_PREV 0x08 -#define MOUSE_NEXT 0x10 +#define MOUSE_LEFT (1 << 0) +#define MOUSE_RIGHT (1 << 1) +#define MOUSE_MIDDLE (1 << 2) +#define MOUSE_PREV (1 << 3) +#define MOUSE_NEXT (1 << 4) +// actually this mouse report has 8 buttons (for smaller descriptor) +// but the last 3 wont do anything from what I tested #define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE | MOUSE_PREV | MOUSE_NEXT) class Mouse_ @@ -40,16 +45,61 @@ class Mouse_ 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 - - void moveTo(uint16_t x, uint16_t y); + inline Mouse_(void) { + // removed this to avoid creating an instance of Mouse if not needed + // the user should call begin first. + //: _buttons(0){ + // empty + } + + inline void begin(void){ + // release all buttons + end(); + } + + inline void end(void){ + _buttons = 0; + move(0, 0, 0); + } + + inline void click(uint8_t b = MOUSE_LEFT){ + _buttons = b; + move(0, 0, 0); + _buttons = 0; + move(0, 0, 0); + } + + inline void move(signed char x, signed char y, signed char wheel = 0){ + u8 m[4]; + m[0] = _buttons; + m[1] = x; + m[2] = y; + m[3] = wheel; + HID_SendReport(HID_REPORTID_MOUSE, m, 4); + } + + inline void press(uint8_t b = MOUSE_LEFT){ + // press LEFT by default + buttons(_buttons | b); + } + + inline void release(uint8_t b = MOUSE_LEFT){ + // release LEFT by default + buttons(_buttons & ~b); + } + + inline bool isPressed(uint8_t b = MOUSE_LEFT){ + // check LEFT by default + if ((b & _buttons) > 0) + return true; + return false; + } + + inline void moveTo(uint16_t x, uint16_t y){ + // uses different report ID and different HID mouse device! + uint32_t pos = ((uint32_t)y << 16) | x; + HID_SendReport(HID_REPORTID_MOUSE_ABSOLUTE, &pos, sizeof(pos)); + } }; extern Mouse_ Mouse; diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 63dfc1cc8f..f02dab5c2d 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -17,6 +17,8 @@ add examples void Recv(volatile u8* data, u8 count) static inline?? improve workaround for consumer + system weak hid send function prototype add gamepad +check keycode function again? +generalize HID key definitions Bugs Mouse Abs only works with system report under special circumstances. @@ -38,6 +40,12 @@ Mouse Abs only works with system report under special circumstances. * Removed not needed virtual functions in Keyboard * Made HID Reports and its IDs replaceable via pins_Arduino.h * Added Absolute Mouse +* Removed uint8_t USBPutChar(uint8_t c); in HID.cpp +* Made void Recv(volatile u8* data, u8 count) in USBCore.cpp static inline +* HID-APIs sends a clean report on begin() and end() now. +* Removed virtual functions in Keyboard API +* Added Keycode functions in Keyboard API +* Inlined a lot of the HID API functions to save flash ``` ``` From b724a771b99f3f937439bbe757017c831d0ac6c7 Mon Sep 17 00:00:00 2001 From: Nico Date: Sat, 27 Dec 2014 13:27:12 +0100 Subject: [PATCH 078/602] Added Gamepad Still doesnt work with Abs Mouse together --- plugins/KeyboardioHID/Gamepad.cpp | 27 ++++++ plugins/KeyboardioHID/Gamepad.h | 137 ++++++++++++++++++++++++++++++ plugins/KeyboardioHID/HID.cpp | 3 + plugins/KeyboardioHID/HID.h | 52 +++++++++++- plugins/KeyboardioHID/HIDAPI.h | 1 + plugins/KeyboardioHID/Readme.md | 6 +- 6 files changed, 221 insertions(+), 5 deletions(-) create mode 100644 plugins/KeyboardioHID/Gamepad.cpp create mode 100644 plugins/KeyboardioHID/Gamepad.h diff --git a/plugins/KeyboardioHID/Gamepad.cpp b/plugins/KeyboardioHID/Gamepad.cpp new file mode 100644 index 0000000000..4cb9fd04c5 --- /dev/null +++ b/plugins/KeyboardioHID/Gamepad.cpp @@ -0,0 +1,27 @@ +/* +Gamepad.cpp +Copyright (c) 2005-2014 Arduino. All right reserved. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "Gamepad.h" + +//================================================================================ +// Gamepad +//================================================================================ + +// object instance +Gamepad_ Gamepad; \ No newline at end of file diff --git a/plugins/KeyboardioHID/Gamepad.h b/plugins/KeyboardioHID/Gamepad.h new file mode 100644 index 0000000000..e2d91a3c92 --- /dev/null +++ b/plugins/KeyboardioHID/Gamepad.h @@ -0,0 +1,137 @@ +/* +Gamepad.h +Copyright (c) 2005-2014 Arduino. All right reserved. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef __GAMEPADAPI__ +#define __GAMEPADAPI__ + +// to access the HID_SendReport via USBAPI.h and report number +#include "Arduino.h" + +//TODO workaround to access the weak sending function +void HID_SendReport(uint8_t id, const void* data, int len); + +//================================================================================ +// Gamepad +//================================================================================ + +// Dpad directions +#define GAMEPAD_DPAD_CENTERED 0 +#define GAMEPAD_DPAD_UP 1 +#define GAMEPAD_DPAD_UP_RIGHT 2 +#define GAMEPAD_DPAD_RIGHT 3 +#define GAMEPAD_DPAD_DOWN_RIGHT 4 +#define GAMEPAD_DPAD_DOWN 5 +#define GAMEPAD_DPAD_DOWN_LEFT 6 +#define GAMEPAD_DPAD_LEFT 7 +#define GAMEPAD_DPAD_UP_LEFT 8 + +typedef union { + // 32 Buttons, 6 Axis, 2 D-Pads + uint8_t whole8[15]; + uint16_t whole16[15 / 2]; + uint32_t whole32[15 / 4]; + uint32_t buttons; + + struct{ + uint8_t button1 : 1; + uint8_t button2 : 1; + uint8_t button3 : 1; + uint8_t button4 : 1; + uint8_t button5 : 1; + uint8_t button6 : 1; + uint8_t button7 : 1; + uint8_t button8 : 1; + + uint8_t button9 : 1; + uint8_t button10 : 1; + uint8_t button11 : 1; + uint8_t button12 : 1; + uint8_t button13 : 1; + uint8_t button14 : 1; + uint8_t button15 : 1; + uint8_t button16 : 1; + + uint8_t button17 : 1; + uint8_t button18 : 1; + uint8_t button19 : 1; + uint8_t button20 : 1; + uint8_t button21 : 1; + uint8_t button22 : 1; + uint8_t button23 : 1; + uint8_t button24 : 1; + + uint8_t button25 : 1; + uint8_t button26 : 1; + uint8_t button27 : 1; + uint8_t button28 : 1; + uint8_t button29 : 1; + uint8_t button30 : 1; + uint8_t button31 : 1; + uint8_t button32 : 1; + + int16_t xAxis; + int16_t yAxis; + + int16_t rxAxis; + int16_t ryAxis; + + int8_t zAxis; + int8_t rzAxis; + + uint8_t dPad1 : 4; + uint8_t dPad2 : 4; + }; +} HID_GamepadReport_Data_t; + +class Gamepad_{ +public: + inline Gamepad_(void){ + // empty + } + + inline void begin(void){ + // release all buttons + end(); + } + + inline void end(void){ + memset(&_report, 0, sizeof(_report)); + HID_SendReport(HID_REPORTID_GAMEPAD, &_report, sizeof(_report)); + } + + inline void write(void){ HID_SendReport(HID_REPORTID_GAMEPAD, &_report, sizeof(_report)); } + inline void press(uint8_t b){ _report.buttons |= (uint32_t)1 << (b - 1); } + inline void release(uint8_t b){ _report.buttons &= ~((uint32_t)1 << (b - 1)); } + inline void releaseAll(void){ memset(&_report, 0x00, sizeof(_report)); } + + inline void buttons(uint32_t b){ _report.buttons = b; } + inline void xAxis(int16_t a){ _report.xAxis = a; } + inline void yAxis(int16_t a){ _report.yAxis = a; } + inline void zAxis(int8_t a){ _report.zAxis = a; } + inline void rxAxis(int16_t a){ _report.rxAxis = a; } + inline void ryAxis(int16_t a){ _report.ryAxis = a; } + inline void rzAxis(int8_t a){ _report.rzAxis = a; } + inline void dPad1(int8_t d){ _report.dPad1 = d; } + inline void dPad2(int8_t d){ _report.dPad2 = d; } +private: + HID_GamepadReport_Data_t _report; +}; +extern Gamepad_ Gamepad; + +#endif \ No newline at end of file diff --git a/plugins/KeyboardioHID/HID.cpp b/plugins/KeyboardioHID/HID.cpp index 48e3a0e600..082905d4bd 100644 --- a/plugins/KeyboardioHID/HID.cpp +++ b/plugins/KeyboardioHID/HID.cpp @@ -40,6 +40,9 @@ const u8 _hidReportDescriptor[] = { //HID_REPORT_RAWHID(HID_REPORTID_RAWHID), HID_REPORT_CONSUMERCONTROL(HID_REPORTID_CONSUMERCONTROL), HID_REPORT_SYSTEMCONTROL(HID_REPORTID_SYSTEMCONTROL), + //TODO get Gamepad working with the other devices + //HID_REPORT_GAMEPAD(HID_REPORTID_GAMEPAD), + #else EXTERN_HID_REPORT #endif diff --git a/plugins/KeyboardioHID/HID.h b/plugins/KeyboardioHID/HID.h index 89dc0f5df8..74e5dc3832 100644 --- a/plugins/KeyboardioHID/HID.h +++ b/plugins/KeyboardioHID/HID.h @@ -48,10 +48,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define HID_REPORTID_SYSTEMCONTROL 5 #endif #ifndef HID_REPORTID_GAMEPAD -#define HID_REPORTID_GAMEPAD 5 +#define HID_REPORTID_GAMEPAD 6 #endif #ifndef HID_REPORTID_MOUSE_ABSOLUTE -#define HID_REPORTID_MOUSE_ABSOLUTE 6 +#define HID_REPORTID_MOUSE_ABSOLUTE 7 #endif // HID reports @@ -227,6 +227,54 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 0xC0 /* end collection */ #endif +#ifndef HID_REPORT_GAMEPAD +#define HID_REPORT_GAMEPAD(report_id) /* Gamepad with 32 buttons and 6 axis*/ \ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ \ + 0x09, 0x04, /* USAGE (Joystick) */ \ + 0xa1, 0x01, /* COLLECTION (Application) */ \ + 0x85, HID_REPORTID_GAMEPAD, /* REPORT_ID */ \ + /* 32 Buttons */ \ + 0x05, 0x09, /* USAGE_PAGE (Button) */ \ + 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ \ + 0x29, 0x20, /* USAGE_MAXIMUM (Button 32) */ \ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ \ + 0x75, 0x01, /* REPORT_SIZE (1) */ \ + 0x95, 0x20, /* REPORT_COUNT (32) */ \ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ + /* 4 16bit Axis */ \ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ \ + 0xa1, 0x00, /* COLLECTION (Physical) */ \ + 0x09, 0x30, /* USAGE (X) */ \ + 0x09, 0x31, /* USAGE (Y) */ \ + 0x09, 0x33, /* USAGE (Rx) */ \ + 0x09, 0x34, /* USAGE (Ry) */ \ + 0x16, 0x00, 0x80, /* LOGICAL_MINIMUM (-32768) */ \ + 0x26, 0xFF, 0x7F, /* LOGICAL_MAXIMUM (32767) */ \ + 0x75, 0x10, /* REPORT_SIZE (16) */ \ + 0x95, 0x04, /* REPORT_COUNT (4) */ \ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ + /* 2 8bit Axis */ \ + 0x09, 0x32, /* USAGE (Z) */ \ + 0x09, 0x35, /* USAGE (Rz) */ \ + 0x15, 0x80, /* LOGICAL_MINIMUM (-128) */ \ + 0x25, 0x7F, /* LOGICAL_MAXIMUM (127) */ \ + 0x75, 0x08, /* REPORT_SIZE (8) */ \ + 0x95, 0x02, /* REPORT_COUNT (2) */ \ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ + 0xc0, /* END_COLLECTION */ \ + /* 2 Hat Switches */ \ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ \ + 0x09, 0x39, /* USAGE (Hat switch) */ \ + 0x09, 0x39, /* USAGE (Hat switch) */ \ + 0x15, 0x01, /* LOGICAL_MINIMUM (1) */ \ + 0x25, 0x08, /* LOGICAL_MAXIMUM (8) */ \ + 0x95, 0x02, /* REPORT_COUNT (2) */ \ + 0x75, 0x04, /* REPORT_SIZE (4) */ \ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ + 0xc0 /* END_COLLECTION */ +#endif + // note by NicoHood: RawHID might never work with multireports, because of OS problems // therefore we have to make it a single report with no idea. No other HID device will be supported then. #define RAWHID_USAGE_PAGE 0xFFC0 // recommended: 0xFF00 to 0xFFFF diff --git a/plugins/KeyboardioHID/HIDAPI.h b/plugins/KeyboardioHID/HIDAPI.h index 0acabafba5..8526bc5edc 100644 --- a/plugins/KeyboardioHID/HIDAPI.h +++ b/plugins/KeyboardioHID/HIDAPI.h @@ -25,5 +25,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "Mouse.h" #include "Consumer.h" #include "System.h" +#include "Gamepad.h" #endif \ No newline at end of file diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index f02dab5c2d..abb703c0fc 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -9,19 +9,18 @@ more usb definitions instead of fixed values, noone understands someone has to add the keywords.txt definitions as well keyboard led move to usb function not to keyboard and from keyboard call this function? weak hidsendreport implement somewhere the prototype? -move HID-Core to a seperate folder? usb wakeup keycode/raw for keyboard magic key fix? add examples -void Recv(volatile u8* data, u8 count) static inline?? improve workaround for consumer + system weak hid send function prototype -add gamepad check keycode function again? generalize HID key definitions +separate folder for the usb core? Bugs Mouse Abs only works with system report under special circumstances. +Gamepad + Mouse Abs doesnt work ``` @@ -46,6 +45,7 @@ Mouse Abs only works with system report under special circumstances. * Removed virtual functions in Keyboard API * Added Keycode functions in Keyboard API * Inlined a lot of the HID API functions to save flash +* Added Gamepad ``` ``` From 070838f588c9f41c59b7aed71a9264b984f79500 Mon Sep 17 00:00:00 2001 From: Nico Date: Sat, 27 Dec 2014 13:27:22 +0100 Subject: [PATCH 079/602] Added Raw Keyboard definitions --- plugins/KeyboardioHID/Keyboard.h | 45 ++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/plugins/KeyboardioHID/Keyboard.h b/plugins/KeyboardioHID/Keyboard.h index 36274a690b..67c50b6078 100644 --- a/plugins/KeyboardioHID/Keyboard.h +++ b/plugins/KeyboardioHID/Keyboard.h @@ -78,6 +78,51 @@ void HID_SendReport(uint8_t id, const void* data, int len); #define LED_CAPS_LOCK 0x02 #define LED_SCROLL_LOCK 0x04 +//Raw Keyboard definitions +#define RAW_KEYBOARD_LEFT_CTRL (1 << 0) +#define RAW_KEYBOARD_LEFT_SHIFT (1 << 1) +#define RAW_KEYBOARD_LEFT_ALT (1 << 2) +#define RAW_KEYBOARD_LEFT_GUI (1 << 3) +#define RAW_KEYBOARD_RIGHT_CTRL (1 << 4) +#define RAW_KEYBOARD_RIGHT_SHIFT (1 << 5) +#define RAW_KEYBOARD_RIGHT_ALT (1 << 6) +#define RAW_KEYBOARD_RIGHT_GUI (1 << 7) + +#define RAW_KEYBOARD_KEY(key) ((key>='a' && key<='z') ? (0x04 + key-'a') :\ +(key>='A' && key<='Z') ? (0x04 + key-'A') : (key>='1' && key<='9') ? (0x1E + key-'1') : 0x27) + +#define RAW_KEYBOARD_UP_ARROW 0x52 +#define RAW_KEYBOARD_DOWN_ARROW 0x51 +#define RAW_KEYBOARD_LEFT_ARROW 0x50 +#define RAW_KEYBOARD_RIGHT_ARROW 0x4F +#define RAW_KEYBOARD_SPACEBAR 0x2C +#define RAW_KEYBOARD_BACKSPACE 0x2A +#define RAW_KEYBOARD_TAB 0x2B +#define RAW_KEYBOARD_RETURN 0x28 +#define RAW_KEYBOARD_ESC 0x29 +#define RAW_KEYBOARD_INSERT 0x49 +#define RAW_KEYBOARD_DELETE 0x4C +#define RAW_KEYBOARD_PAGE_UP 0x4B +#define RAW_KEYBOARD_PAGE_DOWN 0x4E +#define RAW_KEYBOARD_HOME 0x4A +#define RAW_KEYBOARD_END 0x4D +#define RAW_KEYBOARD_CAPS_LOCK 0x39 +#define RAW_KEYBOARD_F1 0x3A +#define RAW_KEYBOARD_F2 0x3B +#define RAW_KEYBOARD_F3 0x3C +#define RAW_KEYBOARD_F4 0x3D +#define RAW_KEYBOARD_F5 0x3E +#define RAW_KEYBOARD_F6 0x3F +#define RAW_KEYBOARD_F7 0x40 +#define RAW_KEYBOARD_F8 0x41 +#define RAW_KEYBOARD_F9 0x42 +#define RAW_KEYBOARD_F10 0x43 +#define RAW_KEYBOARD_F11 0x44 +#define RAW_KEYBOARD_F12 0x45 +#define RAW_KEYBOARD_PRINT 0x46 +#define RAW_KEYBOARD_SCROLL_LOCK 0x47 +#define RAW_KEYBOARD_PAUSE 0x48 + // Low level key report: up to 6 keys and shift, ctrl etc at once typedef struct { From 2b1f75fc176ee495e544a063fd1d616aed922d68 Mon Sep 17 00:00:00 2001 From: Nico Date: Sat, 27 Dec 2014 13:30:47 +0100 Subject: [PATCH 080/602] Updated Example I know its messy. It was just for me to test things and will be improved over the time. Just FYI --- plugins/KeyboardioHID/HID_Tests/HID_Tests.ino | 40 ----- plugins/KeyboardioHID/hidtests2/hidtests2.ino | 138 ++++++++++++++++++ 2 files changed, 138 insertions(+), 40 deletions(-) delete mode 100644 plugins/KeyboardioHID/HID_Tests/HID_Tests.ino create mode 100644 plugins/KeyboardioHID/hidtests2/hidtests2.ino diff --git a/plugins/KeyboardioHID/HID_Tests/HID_Tests.ino b/plugins/KeyboardioHID/HID_Tests/HID_Tests.ino deleted file mode 100644 index 4dcabe28ea..0000000000 --- a/plugins/KeyboardioHID/HID_Tests/HID_Tests.ino +++ /dev/null @@ -1,40 +0,0 @@ -// simply, ugly code to test the new functions - -void setup() { - Serial.begin(1); -} - -uint32_t eventBaud = 0; - -void loop() { - if (Serial.available()) { - while (Serial.read() != -1); - Serial.println("Serial Port working"); - Keyboard.println("Nico is cool"); - delay(3000); - } - - delay(3000); - Keyboard.write(KEY_CAPS_LOCK); - Serial.println("Leds"); - Serial.println(Keyboard.getLEDs(), BIN); - - Serial.println("Serial"); - Serial.println(Serial.dtr()); - Serial.println(Serial.rts()); - Serial.println(Serial.baud()); - Serial.println(Serial.stopbits()); - Serial.println(Serial.paritytype()); - Serial.println(Serial.numbits()); - - if (eventBaud) { - Serial.println("Event"); - Serial.println(eventBaud); - eventBaud = 0; - } -} - -void CDC_LineEncodingEvent(void) -{ - eventBaud = Serial.baud(); -} diff --git a/plugins/KeyboardioHID/hidtests2/hidtests2.ino b/plugins/KeyboardioHID/hidtests2/hidtests2.ino new file mode 100644 index 0000000000..0573f3ef45 --- /dev/null +++ b/plugins/KeyboardioHID/hidtests2/hidtests2.ino @@ -0,0 +1,138 @@ +void setup() { + // put your setup code here, to run once: + pinMode(7, INPUT_PULLUP); + pinMode(8, INPUT_PULLUP); + pinMode(9, INPUT_PULLUP); + pinMode(10, INPUT_PULLUP); + + // 6374 292 + Keyboard.begin(); + Gamepad.begin(); +} + +uint32_t eventBaud = 0; + +void loop() { + + if (!digitalRead(7)) { + digitalWrite(13, 1); + Mouse.moveTo(1000, 1000); + delay(300); + digitalWrite(13, 0); + } + + if (!digitalRead(8)) { + digitalWrite(13, 1); + Mouse.move(100, 0); + delay(300); + digitalWrite(13, 0); + } + + if (!digitalRead(9)) { + digitalWrite(13, 1); + Mouse.move(-100, 0); + delay(300); + digitalWrite(13, 0); + } + + if (!digitalRead(10)) { + uint8_t k[8] = {0}; + k[1] = 1; + + k[2] = 4; + k[3] = 5; + HID_SendReport(HID_REPORTID_KEYBOARD, &k, sizeof(k)); + Keyboard.releaseAll(); + delay(300); + } + + if (Serial.available()) { + // let the Serial receive all bytes and discard the first bytes + // this is to ensure you only input a single char and no string + char c; + delay(300); + int length = Serial.available(); + while (Serial.available()) + c = Serial.read(); + if (length > 1) { + Serial.println("Please only input a single character or deactivate linefeed!"); + return; + } + + if (c != -1) { + Serial.println(c); + switch (c) { + case 'a': + Keyboard.write('b'); + break; + + case 'p': + Consumer.write(MEDIA_PLAY_PAUSE); + break; + + case 's': + { + // uint8_t k[8] = {0}; + // k[1] = 1 << 4; + // //k[2] = 4; + // HID_SendReport(HID_REPORTID_KEYBOARD, &k, sizeof(k)); + // Keyboard.releaseAll(); + break; + } + + case 'r': + Mouse.move(100, 0); + break; + + case 'l': + Mouse.move(-100, 0); + break; + + case 't': + Mouse.moveTo(1000, 1000); + break; + + case 'c': + case 'C': + Keyboard.write(KEY_CAPS_LOCK); + Serial.println("Leds"); + Serial.println(Keyboard.getLEDs(), BIN); + break; + + case 'k': + Keyboard.print("Testing USB functions xyz"); + break; + + case '\r': + case '\n': + Serial.println("Please only input a single character!"); + break; + + case 'd': + Serial.println("Serial"); + Serial.println(Serial.dtr()); + Serial.println(Serial.rts()); + Serial.println(Serial.baud()); + Serial.println(Serial.stopbits()); + Serial.println(Serial.paritytype()); + Serial.println(Serial.numbits()); + break; + + default: + Serial.println("unknown"); + } + } + } + + + if (eventBaud) { + Serial.println("Event"); + Serial.println(eventBaud); + eventBaud = 0; + } +} + +void CDC_LineEncodingEvent(void) +{ + eventBaud = Serial.baud(); +} From db56400537aa1ed4634f80b908dab63e687ee20f Mon Sep 17 00:00:00 2001 From: Nico Date: Sat, 27 Dec 2014 15:57:58 +0100 Subject: [PATCH 081/602] Added USB wakeup support Had no chance to test it yet. Not sure if u2 Series will work as well. --- plugins/KeyboardioHID/Readme.md | 1 + plugins/KeyboardioHID/USBAPI.h | 1 + plugins/KeyboardioHID/USBCore.cpp | 237 ++++++++++++++++++++++-------- plugins/KeyboardioHID/USBCore.h | 10 +- 4 files changed, 190 insertions(+), 59 deletions(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index abb703c0fc..3d0105678f 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -46,6 +46,7 @@ Gamepad + Mouse Abs doesnt work * Added Keycode functions in Keyboard API * Inlined a lot of the HID API functions to save flash * Added Gamepad +* Added USB Wakeup support ``` ``` diff --git a/plugins/KeyboardioHID/USBAPI.h b/plugins/KeyboardioHID/USBAPI.h index 79cbc3ceaf..a49669c3cc 100644 --- a/plugins/KeyboardioHID/USBAPI.h +++ b/plugins/KeyboardioHID/USBAPI.h @@ -50,6 +50,7 @@ class USBDevice_ void attach(); void detach(); // Serial port goes down too... void poll(); + bool wakeupHost(); // returns false, when wakeup cannot be processed }; extern USBDevice_ USBDevice; diff --git a/plugins/KeyboardioHID/USBCore.cpp b/plugins/KeyboardioHID/USBCore.cpp index be38718415..242c6dc24d 100644 --- a/plugins/KeyboardioHID/USBCore.cpp +++ b/plugins/KeyboardioHID/USBCore.cpp @@ -2,6 +2,8 @@ /* Copyright (c) 2010, Peter Barrett ** +** Sleep/Wakeup/SystemControl support added by Michael Dreher +** ** 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. @@ -98,6 +100,8 @@ D_DEVICE(USB_DEVICE_NO_CLASS, USB_DEVICE_NO_SUB_CLASS, USB_DEVICE_NO_PROTOCOL, 6 //================================================================== volatile u8 _usbConfiguration = 0; +volatile u8 _usbCurrentStatus = 0; // meaning of bits see usb_20.pdf, Figure 9-4. Information Returned by a GetStatus() Request to a Device +volatile u8 _usbSuspendState = 0; // copy of UDINT to check SUSPI and WAKEUPI bits static inline void WaitIN(void) { @@ -563,16 +567,37 @@ ISR(USB_COM_vect) { // Standard Requests u8 r = setup.bRequest; + u16 wValue = (setup.wValueH << 8) | setup.wValueL; if (GET_STATUS == r) { - Send8(0); // TODO - Send8(0); + if (requestType == (REQUEST_DEVICETOHOST | REQUEST_STANDARD | REQUEST_DEVICE)) + { + Send8(_usbCurrentStatus); + Send8(0); + } + else + { + // TODO: handle the HALT state of an endpoint here + // see "Figure 9-6. Information Returned by a GetStatus() Request to an Endpoint" in usb_20.pdf for more information + Send8(0); + Send8(0); + } } else if (CLEAR_FEATURE == r) { + if ((requestType == (REQUEST_HOSTTODEVICE | REQUEST_STANDARD | REQUEST_DEVICE)) + && (wValue == DEVICE_REMOTE_WAKEUP)) + { + _usbCurrentStatus &= ~FEATURE_REMOTE_WAKEUP_ENABLED; + } } else if (SET_FEATURE == r) { + if ((requestType == (REQUEST_HOSTTODEVICE | REQUEST_STANDARD | REQUEST_DEVICE)) + && (wValue == DEVICE_REMOTE_WAKEUP)) + { + _usbCurrentStatus |= FEATURE_REMOTE_WAKEUP_ENABLED; + } } else if (SET_ADDRESS == r) { @@ -629,11 +654,113 @@ void USB_Flush(u8 ep) ReleaseTX(); } +// edit by NicoHood +// added from teensy definition by paul stoffregen +//TODO remove, not needed anymore +#if defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega8U2__) +#define HW_CONFIG() +#define PLL_CONFIG() (PLLCSR = ((1< Date: Sat, 27 Dec 2014 15:58:09 +0100 Subject: [PATCH 082/602] Updated Example --- plugins/KeyboardioHID/hidtests2/hidtests2.ino | 44 +++++++++++++------ 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/plugins/KeyboardioHID/hidtests2/hidtests2.ino b/plugins/KeyboardioHID/hidtests2/hidtests2.ino index 0573f3ef45..7c88e4cb85 100644 --- a/plugins/KeyboardioHID/hidtests2/hidtests2.ino +++ b/plugins/KeyboardioHID/hidtests2/hidtests2.ino @@ -4,6 +4,8 @@ void setup() { pinMode(8, INPUT_PULLUP); pinMode(9, INPUT_PULLUP); pinMode(10, INPUT_PULLUP); + pinMode(11, INPUT_PULLUP); + pinMode(12, INPUT_PULLUP); // 6374 292 Keyboard.begin(); @@ -45,6 +47,18 @@ void loop() { Keyboard.releaseAll(); delay(300); } + if (!digitalRead(11)) { + digitalWrite(13, 1); + System.write(SYSTEM_SLEEP); + delay(300); + digitalWrite(13, 0); + } + if (!digitalRead(12)) { + digitalWrite(13, 1); + USBDevice.wakeupHost(); + delay(300); + digitalWrite(13, 0); + } if (Serial.available()) { // let the Serial receive all bytes and discard the first bytes @@ -70,7 +84,7 @@ void loop() { Consumer.write(MEDIA_PLAY_PAUSE); break; - case 's': + case 'o': { // uint8_t k[8] = {0}; // k[1] = 1 << 4; @@ -80,6 +94,10 @@ void loop() { break; } + case 's': + System.write(SYSTEM_SLEEP); + break; + case 'r': Mouse.move(100, 0); break; @@ -107,24 +125,24 @@ void loop() { case '\n': Serial.println("Please only input a single character!"); break; - - case 'd': - Serial.println("Serial"); - Serial.println(Serial.dtr()); - Serial.println(Serial.rts()); - Serial.println(Serial.baud()); - Serial.println(Serial.stopbits()); - Serial.println(Serial.paritytype()); - Serial.println(Serial.numbits()); - break; + + case 'd': + Serial.println("Serial"); + Serial.println(Serial.dtr()); + Serial.println(Serial.rts()); + Serial.println(Serial.baud()); + Serial.println(Serial.stopbits()); + Serial.println(Serial.paritytype()); + Serial.println(Serial.numbits()); + break; default: Serial.println("unknown"); } } } - - + + if (eventBaud) { Serial.println("Event"); Serial.println(eventBaud); From 9942220ebd1f0f79817151c4307dfa0cb6090b4a Mon Sep 17 00:00:00 2001 From: Nico Date: Sat, 27 Dec 2014 17:15:49 +0100 Subject: [PATCH 083/602] USB Wakeup u2 Series fix Now working with HoodLoader2. Also got the chance to test the features on a PC where USB wakeup is supported. It seems to work now properly. --- plugins/KeyboardioHID/USBCore.cpp | 36 ++++++------------- plugins/KeyboardioHID/hidtests2/hidtests2.ino | 8 ++--- 2 files changed, 14 insertions(+), 30 deletions(-) diff --git a/plugins/KeyboardioHID/USBCore.cpp b/plugins/KeyboardioHID/USBCore.cpp index 242c6dc24d..764a411f82 100644 --- a/plugins/KeyboardioHID/USBCore.cpp +++ b/plugins/KeyboardioHID/USBCore.cpp @@ -654,32 +654,6 @@ void USB_Flush(u8 ep) ReleaseTX(); } -// edit by NicoHood -// added from teensy definition by paul stoffregen -//TODO remove, not needed anymore -#if defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega8U2__) -#define HW_CONFIG() -#define PLL_CONFIG() (PLLCSR = ((1< Date: Sat, 27 Dec 2014 17:37:12 +0100 Subject: [PATCH 084/602] Moved USB-Core into a separate folder --- plugins/KeyboardioHID/{ => arduino}/Arduino.h | 8 ++++---- plugins/KeyboardioHID/{ => arduino/USB-Core}/CDC.cpp | 0 plugins/KeyboardioHID/{ => arduino/USB-Core}/CDC.h | 0 plugins/KeyboardioHID/{ => arduino/USB-Core}/Consumer.cpp | 0 plugins/KeyboardioHID/{ => arduino/USB-Core}/Consumer.h | 0 plugins/KeyboardioHID/{ => arduino/USB-Core}/Gamepad.cpp | 0 plugins/KeyboardioHID/{ => arduino/USB-Core}/Gamepad.h | 0 plugins/KeyboardioHID/{ => arduino/USB-Core}/HID.cpp | 0 plugins/KeyboardioHID/{ => arduino/USB-Core}/HID.h | 0 plugins/KeyboardioHID/{ => arduino/USB-Core}/HIDAPI.h | 0 plugins/KeyboardioHID/{ => arduino/USB-Core}/HIDTables.h | 0 plugins/KeyboardioHID/{ => arduino/USB-Core}/Keyboard.cpp | 0 plugins/KeyboardioHID/{ => arduino/USB-Core}/Keyboard.h | 0 plugins/KeyboardioHID/{ => arduino/USB-Core}/Mouse.cpp | 0 plugins/KeyboardioHID/{ => arduino/USB-Core}/Mouse.h | 0 plugins/KeyboardioHID/{ => arduino/USB-Core}/System.cpp | 0 plugins/KeyboardioHID/{ => arduino/USB-Core}/System.h | 0 plugins/KeyboardioHID/{ => arduino/USB-Core}/USBAPI.h | 0 plugins/KeyboardioHID/{ => arduino/USB-Core}/USBCore.cpp | 0 plugins/KeyboardioHID/{ => arduino/USB-Core}/USBCore.h | 0 plugins/KeyboardioHID/{ => arduino/USB-Core}/USBDesc.h | 0 plugins/KeyboardioHID/{ => arduino}/wiring_private.h | 0 22 files changed, 4 insertions(+), 4 deletions(-) rename plugins/KeyboardioHID/{ => arduino}/Arduino.h (98%) rename plugins/KeyboardioHID/{ => arduino/USB-Core}/CDC.cpp (100%) rename plugins/KeyboardioHID/{ => arduino/USB-Core}/CDC.h (100%) rename plugins/KeyboardioHID/{ => arduino/USB-Core}/Consumer.cpp (100%) rename plugins/KeyboardioHID/{ => arduino/USB-Core}/Consumer.h (100%) rename plugins/KeyboardioHID/{ => arduino/USB-Core}/Gamepad.cpp (100%) rename plugins/KeyboardioHID/{ => arduino/USB-Core}/Gamepad.h (100%) rename plugins/KeyboardioHID/{ => arduino/USB-Core}/HID.cpp (100%) rename plugins/KeyboardioHID/{ => arduino/USB-Core}/HID.h (100%) rename plugins/KeyboardioHID/{ => arduino/USB-Core}/HIDAPI.h (100%) rename plugins/KeyboardioHID/{ => arduino/USB-Core}/HIDTables.h (100%) rename plugins/KeyboardioHID/{ => arduino/USB-Core}/Keyboard.cpp (100%) rename plugins/KeyboardioHID/{ => arduino/USB-Core}/Keyboard.h (100%) rename plugins/KeyboardioHID/{ => arduino/USB-Core}/Mouse.cpp (100%) rename plugins/KeyboardioHID/{ => arduino/USB-Core}/Mouse.h (100%) rename plugins/KeyboardioHID/{ => arduino/USB-Core}/System.cpp (100%) rename plugins/KeyboardioHID/{ => arduino/USB-Core}/System.h (100%) rename plugins/KeyboardioHID/{ => arduino/USB-Core}/USBAPI.h (100%) rename plugins/KeyboardioHID/{ => arduino/USB-Core}/USBCore.cpp (100%) rename plugins/KeyboardioHID/{ => arduino/USB-Core}/USBCore.h (100%) rename plugins/KeyboardioHID/{ => arduino/USB-Core}/USBDesc.h (100%) rename plugins/KeyboardioHID/{ => arduino}/wiring_private.h (100%) diff --git a/plugins/KeyboardioHID/Arduino.h b/plugins/KeyboardioHID/arduino/Arduino.h similarity index 98% rename from plugins/KeyboardioHID/Arduino.h rename to plugins/KeyboardioHID/arduino/Arduino.h index 192c6e8135..8340ca37ef 100644 --- a/plugins/KeyboardioHID/Arduino.h +++ b/plugins/KeyboardioHID/arduino/Arduino.h @@ -221,10 +221,10 @@ extern const uint8_t PROGMEM digital_pin_to_timer_PGM[]; #include "WCharacter.h" #include "WString.h" #include "HardwareSerial.h" -#include "USBAPI.h" -#include "CDC.h" -#include "HID.h" -#include "HIDTables.h" +#include "USB-Core/USBAPI.h" +#include "USB-Core/CDC.h" +#include "USB-Core/HID.h" +#include "USB-Core/HIDTables.h" #if defined(HAVE_HWSERIAL0) && defined(HAVE_CDCSERIAL) #error "Targets with both UART0 and CDC serial not supported" diff --git a/plugins/KeyboardioHID/CDC.cpp b/plugins/KeyboardioHID/arduino/USB-Core/CDC.cpp similarity index 100% rename from plugins/KeyboardioHID/CDC.cpp rename to plugins/KeyboardioHID/arduino/USB-Core/CDC.cpp diff --git a/plugins/KeyboardioHID/CDC.h b/plugins/KeyboardioHID/arduino/USB-Core/CDC.h similarity index 100% rename from plugins/KeyboardioHID/CDC.h rename to plugins/KeyboardioHID/arduino/USB-Core/CDC.h diff --git a/plugins/KeyboardioHID/Consumer.cpp b/plugins/KeyboardioHID/arduino/USB-Core/Consumer.cpp similarity index 100% rename from plugins/KeyboardioHID/Consumer.cpp rename to plugins/KeyboardioHID/arduino/USB-Core/Consumer.cpp diff --git a/plugins/KeyboardioHID/Consumer.h b/plugins/KeyboardioHID/arduino/USB-Core/Consumer.h similarity index 100% rename from plugins/KeyboardioHID/Consumer.h rename to plugins/KeyboardioHID/arduino/USB-Core/Consumer.h diff --git a/plugins/KeyboardioHID/Gamepad.cpp b/plugins/KeyboardioHID/arduino/USB-Core/Gamepad.cpp similarity index 100% rename from plugins/KeyboardioHID/Gamepad.cpp rename to plugins/KeyboardioHID/arduino/USB-Core/Gamepad.cpp diff --git a/plugins/KeyboardioHID/Gamepad.h b/plugins/KeyboardioHID/arduino/USB-Core/Gamepad.h similarity index 100% rename from plugins/KeyboardioHID/Gamepad.h rename to plugins/KeyboardioHID/arduino/USB-Core/Gamepad.h diff --git a/plugins/KeyboardioHID/HID.cpp b/plugins/KeyboardioHID/arduino/USB-Core/HID.cpp similarity index 100% rename from plugins/KeyboardioHID/HID.cpp rename to plugins/KeyboardioHID/arduino/USB-Core/HID.cpp diff --git a/plugins/KeyboardioHID/HID.h b/plugins/KeyboardioHID/arduino/USB-Core/HID.h similarity index 100% rename from plugins/KeyboardioHID/HID.h rename to plugins/KeyboardioHID/arduino/USB-Core/HID.h diff --git a/plugins/KeyboardioHID/HIDAPI.h b/plugins/KeyboardioHID/arduino/USB-Core/HIDAPI.h similarity index 100% rename from plugins/KeyboardioHID/HIDAPI.h rename to plugins/KeyboardioHID/arduino/USB-Core/HIDAPI.h diff --git a/plugins/KeyboardioHID/HIDTables.h b/plugins/KeyboardioHID/arduino/USB-Core/HIDTables.h similarity index 100% rename from plugins/KeyboardioHID/HIDTables.h rename to plugins/KeyboardioHID/arduino/USB-Core/HIDTables.h diff --git a/plugins/KeyboardioHID/Keyboard.cpp b/plugins/KeyboardioHID/arduino/USB-Core/Keyboard.cpp similarity index 100% rename from plugins/KeyboardioHID/Keyboard.cpp rename to plugins/KeyboardioHID/arduino/USB-Core/Keyboard.cpp diff --git a/plugins/KeyboardioHID/Keyboard.h b/plugins/KeyboardioHID/arduino/USB-Core/Keyboard.h similarity index 100% rename from plugins/KeyboardioHID/Keyboard.h rename to plugins/KeyboardioHID/arduino/USB-Core/Keyboard.h diff --git a/plugins/KeyboardioHID/Mouse.cpp b/plugins/KeyboardioHID/arduino/USB-Core/Mouse.cpp similarity index 100% rename from plugins/KeyboardioHID/Mouse.cpp rename to plugins/KeyboardioHID/arduino/USB-Core/Mouse.cpp diff --git a/plugins/KeyboardioHID/Mouse.h b/plugins/KeyboardioHID/arduino/USB-Core/Mouse.h similarity index 100% rename from plugins/KeyboardioHID/Mouse.h rename to plugins/KeyboardioHID/arduino/USB-Core/Mouse.h diff --git a/plugins/KeyboardioHID/System.cpp b/plugins/KeyboardioHID/arduino/USB-Core/System.cpp similarity index 100% rename from plugins/KeyboardioHID/System.cpp rename to plugins/KeyboardioHID/arduino/USB-Core/System.cpp diff --git a/plugins/KeyboardioHID/System.h b/plugins/KeyboardioHID/arduino/USB-Core/System.h similarity index 100% rename from plugins/KeyboardioHID/System.h rename to plugins/KeyboardioHID/arduino/USB-Core/System.h diff --git a/plugins/KeyboardioHID/USBAPI.h b/plugins/KeyboardioHID/arduino/USB-Core/USBAPI.h similarity index 100% rename from plugins/KeyboardioHID/USBAPI.h rename to plugins/KeyboardioHID/arduino/USB-Core/USBAPI.h diff --git a/plugins/KeyboardioHID/USBCore.cpp b/plugins/KeyboardioHID/arduino/USB-Core/USBCore.cpp similarity index 100% rename from plugins/KeyboardioHID/USBCore.cpp rename to plugins/KeyboardioHID/arduino/USB-Core/USBCore.cpp diff --git a/plugins/KeyboardioHID/USBCore.h b/plugins/KeyboardioHID/arduino/USB-Core/USBCore.h similarity index 100% rename from plugins/KeyboardioHID/USBCore.h rename to plugins/KeyboardioHID/arduino/USB-Core/USBCore.h diff --git a/plugins/KeyboardioHID/USBDesc.h b/plugins/KeyboardioHID/arduino/USB-Core/USBDesc.h similarity index 100% rename from plugins/KeyboardioHID/USBDesc.h rename to plugins/KeyboardioHID/arduino/USB-Core/USBDesc.h diff --git a/plugins/KeyboardioHID/wiring_private.h b/plugins/KeyboardioHID/arduino/wiring_private.h similarity index 100% rename from plugins/KeyboardioHID/wiring_private.h rename to plugins/KeyboardioHID/arduino/wiring_private.h From 8a42a414142f332d9c5805b9d4420ae2e59c4532 Mon Sep 17 00:00:00 2001 From: Nico Date: Sat, 27 Dec 2014 17:38:46 +0100 Subject: [PATCH 085/602] Moved Keyboard Led Out Report to HID Core Saves some more flash and is better accessible. --- plugins/KeyboardioHID/arduino/USB-Core/HID.cpp | 13 +++++-------- plugins/KeyboardioHID/arduino/USB-Core/HID.h | 8 +++++--- plugins/KeyboardioHID/arduino/USB-Core/Keyboard.cpp | 8 -------- plugins/KeyboardioHID/arduino/USB-Core/Keyboard.h | 5 ----- 4 files changed, 10 insertions(+), 24 deletions(-) diff --git a/plugins/KeyboardioHID/arduino/USB-Core/HID.cpp b/plugins/KeyboardioHID/arduino/USB-Core/HID.cpp index 082905d4bd..4ac49caeea 100644 --- a/plugins/KeyboardioHID/arduino/USB-Core/HID.cpp +++ b/plugins/KeyboardioHID/arduino/USB-Core/HID.cpp @@ -57,6 +57,10 @@ const HIDDescriptor _hidInterface = D_ENDPOINT(USB_ENDPOINT_IN(HID_ENDPOINT_INT), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) }; +#if defined(HID_KEYBOARD_LEDS_ENABLED) +uint8_t hid_keyboard_leds = 0; +#endif + //================================================================================ //================================================================================ // Driver @@ -122,7 +126,7 @@ bool WEAK HID_Setup(Setup& setup) // write led out report data uint8_t data[2]; if (2 == USB_RecvControl(data, 2)) - HID_SetKeyboardLedReport(data[1]); + hid_keyboard_leds = data[1]; } // else TODO check for other devices like RAW HID, not needed for now } @@ -131,13 +135,6 @@ bool WEAK HID_Setup(Setup& setup) return false; } -#if defined(HID_KEYBOARD_LEDS_ENABLED) -void WEAK HID_SetKeyboardLedReport(uint8_t leds){ - // weak function implemented by the Keyboard API - // to not always create the Keyboard object, if it isn't used -} -#endif - #endif #else /* if defined(USBCON) */ diff --git a/plugins/KeyboardioHID/arduino/USB-Core/HID.h b/plugins/KeyboardioHID/arduino/USB-Core/HID.h index 74e5dc3832..b64fb606e4 100644 --- a/plugins/KeyboardioHID/arduino/USB-Core/HID.h +++ b/plugins/KeyboardioHID/arduino/USB-Core/HID.h @@ -27,6 +27,11 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define HID_KEYBOARD_LEDS_ENABLED #endif +// extern accessible led out report +#if defined(HID_KEYBOARD_LEDS_ENABLED) +extern uint8_t hid_keyboard_leds; +#endif + // HID report IDs // note by NicoHood: I would not change the current IDs, since it can confuse the OS // I had several problems if i change the report id and its use. @@ -322,9 +327,6 @@ 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); -#if defined(HID_KEYBOARD_LEDS_ENABLED) -void HID_SetKeyboardLedReport(uint8_t leds); -#endif #else /* if defined(USBCON) */ diff --git a/plugins/KeyboardioHID/arduino/USB-Core/Keyboard.cpp b/plugins/KeyboardioHID/arduino/USB-Core/Keyboard.cpp index 0ab9d4e281..09732a86f4 100644 --- a/plugins/KeyboardioHID/arduino/USB-Core/Keyboard.cpp +++ b/plugins/KeyboardioHID/arduino/USB-Core/Keyboard.cpp @@ -23,14 +23,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA //================================================================================ // Keyboard -#if defined(HID_KEYBOARD_LEDS_ENABLED) -uint8_t hid_keyboard_leds = 0; -void HID_SetKeyboardLedReport(uint8_t leds){ - // implementation of the weak function in HID.cpp - hid_keyboard_leds = leds; -} -#endif - Keyboard_ Keyboard; void Keyboard_::sendReport(KeyReport* keys) diff --git a/plugins/KeyboardioHID/arduino/USB-Core/Keyboard.h b/plugins/KeyboardioHID/arduino/USB-Core/Keyboard.h index 67c50b6078..a1003e76a0 100644 --- a/plugins/KeyboardioHID/arduino/USB-Core/Keyboard.h +++ b/plugins/KeyboardioHID/arduino/USB-Core/Keyboard.h @@ -131,11 +131,6 @@ typedef struct uint8_t keys[6]; } KeyReport; -// extern accessible led out report -#if defined(HID_KEYBOARD_LEDS_ENABLED) -extern uint8_t hid_keyboard_leds; -#endif - class Keyboard_ : public Print { protected: From 942d9c9de0eeb4867127023bf4297ca97728e032 Mon Sep 17 00:00:00 2001 From: Nico Date: Fri, 2 Jan 2015 11:58:18 +0100 Subject: [PATCH 086/602] Moved new Core into a separate hardware folder Now you can install the core by just adding it to your sketchbook. There is still a bug in boards.txt where the core isnt recognized. Copy it to your local Arduino folder. --- .../KeyboardioHID/hardware/HID/avr/boards.txt | 33 + .../HID/avr/cores/hid}/Arduino.h | 0 .../hardware/HID/avr/cores/hid/Client.h | 45 ++ .../HID/avr/cores/hid/HardwareSerial.cpp | 252 ++++++ .../HID/avr/cores/hid/HardwareSerial.h | 149 ++++ .../HID/avr/cores/hid/HardwareSerial0.cpp | 79 ++ .../HID/avr/cores/hid/HardwareSerial1.cpp | 69 ++ .../HID/avr/cores/hid/HardwareSerial2.cpp | 57 ++ .../HID/avr/cores/hid/HardwareSerial3.cpp | 57 ++ .../avr/cores/hid/HardwareSerial_private.h | 123 +++ .../hardware/HID/avr/cores/hid/IPAddress.cpp | 74 ++ .../hardware/HID/avr/cores/hid/IPAddress.h | 75 ++ .../hardware/HID/avr/cores/hid/Print.cpp | 264 +++++++ .../hardware/HID/avr/cores/hid/Print.h | 84 ++ .../hardware/HID/avr/cores/hid/Printable.h | 40 + .../hardware/HID/avr/cores/hid/Server.h | 30 + .../hardware/HID/avr/cores/hid/Stream.cpp | 270 +++++++ .../hardware/HID/avr/cores/hid/Stream.h | 102 +++ .../hardware/HID/avr/cores/hid/Tone.cpp | 616 +++++++++++++++ .../HID/avr/cores/hid}/USB-Core/CDC.cpp | 0 .../HID/avr/cores/hid}/USB-Core/CDC.h | 0 .../HID/avr/cores/hid}/USB-Core/Consumer.cpp | 0 .../HID/avr/cores/hid}/USB-Core/Consumer.h | 0 .../HID/avr/cores/hid}/USB-Core/Gamepad.cpp | 0 .../HID/avr/cores/hid}/USB-Core/Gamepad.h | 0 .../HID/avr/cores/hid}/USB-Core/HID.cpp | 21 +- .../HID/avr/cores/hid}/USB-Core/HID.h | 16 +- .../HID/avr/cores/hid}/USB-Core/HIDAPI.h | 0 .../HID/avr/cores/hid}/USB-Core/HIDTables.h | 0 .../HID/avr/cores/hid}/USB-Core/Keyboard.cpp | 0 .../HID/avr/cores/hid}/USB-Core/Keyboard.h | 0 .../HID/avr/cores/hid}/USB-Core/Mouse.cpp | 0 .../HID/avr/cores/hid}/USB-Core/Mouse.h | 0 .../HID/avr/cores/hid}/USB-Core/System.cpp | 0 .../HID/avr/cores/hid}/USB-Core/System.h | 0 .../HID/avr/cores/hid}/USB-Core/USBAPI.h | 0 .../HID/avr/cores/hid}/USB-Core/USBCore.cpp | 0 .../HID/avr/cores/hid}/USB-Core/USBCore.h | 0 .../HID/avr/cores/hid}/USB-Core/USBDesc.h | 0 .../hardware/HID/avr/cores/hid/Udp.h | 88 +++ .../hardware/HID/avr/cores/hid/WCharacter.h | 168 ++++ .../hardware/HID/avr/cores/hid/WInterrupts.c | 334 ++++++++ .../hardware/HID/avr/cores/hid/WMath.cpp | 60 ++ .../hardware/HID/avr/cores/hid/WString.cpp | 745 ++++++++++++++++++ .../hardware/HID/avr/cores/hid/WString.h | 224 ++++++ .../hardware/HID/avr/cores/hid/abi.cpp | 35 + .../hardware/HID/avr/cores/hid/binary.h | 534 +++++++++++++ .../hardware/HID/avr/cores/hid/hooks.c | 31 + .../hardware/HID/avr/cores/hid/main.cpp | 49 ++ .../hardware/HID/avr/cores/hid/new.cpp | 36 + .../hardware/HID/avr/cores/hid/new.h | 30 + .../hardware/HID/avr/cores/hid/wiring.c | 325 ++++++++ .../HID/avr/cores/hid/wiring_analog.c | 292 +++++++ .../HID/avr/cores/hid/wiring_digital.c | 181 +++++ .../HID/avr/cores/hid}/wiring_private.h | 0 .../hardware/HID/avr/cores/hid/wiring_pulse.c | 69 ++ .../hardware/HID/avr/cores/hid/wiring_shift.c | 55 ++ .../hardware/HID/avr/platform.txt | 9 + .../hid_descriptors/hid_descriptors.h | 36 + .../HID/avr/variants/leonardo/pins_arduino.h | 361 +++++++++ .../avr/variants/leonardo_hid/pins_arduino.h | 2 + .../HID/avr/variants/micro/pins_arduino.h | 37 + .../HID/avr/variants/micro_hid/pins_arduino.h | 2 + plugins/KeyboardioHID/hidtests2/hidtests2.ino | 15 +- 64 files changed, 6154 insertions(+), 20 deletions(-) create mode 100644 plugins/KeyboardioHID/hardware/HID/avr/boards.txt rename plugins/KeyboardioHID/{arduino => hardware/HID/avr/cores/hid}/Arduino.h (100%) create mode 100644 plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Client.h create mode 100644 plugins/KeyboardioHID/hardware/HID/avr/cores/hid/HardwareSerial.cpp create mode 100644 plugins/KeyboardioHID/hardware/HID/avr/cores/hid/HardwareSerial.h create mode 100644 plugins/KeyboardioHID/hardware/HID/avr/cores/hid/HardwareSerial0.cpp create mode 100644 plugins/KeyboardioHID/hardware/HID/avr/cores/hid/HardwareSerial1.cpp create mode 100644 plugins/KeyboardioHID/hardware/HID/avr/cores/hid/HardwareSerial2.cpp create mode 100644 plugins/KeyboardioHID/hardware/HID/avr/cores/hid/HardwareSerial3.cpp create mode 100644 plugins/KeyboardioHID/hardware/HID/avr/cores/hid/HardwareSerial_private.h create mode 100644 plugins/KeyboardioHID/hardware/HID/avr/cores/hid/IPAddress.cpp create mode 100644 plugins/KeyboardioHID/hardware/HID/avr/cores/hid/IPAddress.h create mode 100644 plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Print.cpp create mode 100644 plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Print.h create mode 100644 plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Printable.h create mode 100644 plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Server.h create mode 100644 plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Stream.cpp create mode 100644 plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Stream.h create mode 100644 plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Tone.cpp rename plugins/KeyboardioHID/{arduino => hardware/HID/avr/cores/hid}/USB-Core/CDC.cpp (100%) rename plugins/KeyboardioHID/{arduino => hardware/HID/avr/cores/hid}/USB-Core/CDC.h (100%) rename plugins/KeyboardioHID/{arduino => hardware/HID/avr/cores/hid}/USB-Core/Consumer.cpp (100%) rename plugins/KeyboardioHID/{arduino => hardware/HID/avr/cores/hid}/USB-Core/Consumer.h (100%) rename plugins/KeyboardioHID/{arduino => hardware/HID/avr/cores/hid}/USB-Core/Gamepad.cpp (100%) rename plugins/KeyboardioHID/{arduino => hardware/HID/avr/cores/hid}/USB-Core/Gamepad.h (100%) rename plugins/KeyboardioHID/{arduino => hardware/HID/avr/cores/hid}/USB-Core/HID.cpp (85%) rename plugins/KeyboardioHID/{arduino => hardware/HID/avr/cores/hid}/USB-Core/HID.h (97%) rename plugins/KeyboardioHID/{arduino => hardware/HID/avr/cores/hid}/USB-Core/HIDAPI.h (100%) rename plugins/KeyboardioHID/{arduino => hardware/HID/avr/cores/hid}/USB-Core/HIDTables.h (100%) rename plugins/KeyboardioHID/{arduino => hardware/HID/avr/cores/hid}/USB-Core/Keyboard.cpp (100%) rename plugins/KeyboardioHID/{arduino => hardware/HID/avr/cores/hid}/USB-Core/Keyboard.h (100%) rename plugins/KeyboardioHID/{arduino => hardware/HID/avr/cores/hid}/USB-Core/Mouse.cpp (100%) rename plugins/KeyboardioHID/{arduino => hardware/HID/avr/cores/hid}/USB-Core/Mouse.h (100%) rename plugins/KeyboardioHID/{arduino => hardware/HID/avr/cores/hid}/USB-Core/System.cpp (100%) rename plugins/KeyboardioHID/{arduino => hardware/HID/avr/cores/hid}/USB-Core/System.h (100%) rename plugins/KeyboardioHID/{arduino => hardware/HID/avr/cores/hid}/USB-Core/USBAPI.h (100%) rename plugins/KeyboardioHID/{arduino => hardware/HID/avr/cores/hid}/USB-Core/USBCore.cpp (100%) rename plugins/KeyboardioHID/{arduino => hardware/HID/avr/cores/hid}/USB-Core/USBCore.h (100%) rename plugins/KeyboardioHID/{arduino => hardware/HID/avr/cores/hid}/USB-Core/USBDesc.h (100%) create mode 100644 plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Udp.h create mode 100644 plugins/KeyboardioHID/hardware/HID/avr/cores/hid/WCharacter.h create mode 100644 plugins/KeyboardioHID/hardware/HID/avr/cores/hid/WInterrupts.c create mode 100644 plugins/KeyboardioHID/hardware/HID/avr/cores/hid/WMath.cpp create mode 100644 plugins/KeyboardioHID/hardware/HID/avr/cores/hid/WString.cpp create mode 100644 plugins/KeyboardioHID/hardware/HID/avr/cores/hid/WString.h create mode 100644 plugins/KeyboardioHID/hardware/HID/avr/cores/hid/abi.cpp create mode 100644 plugins/KeyboardioHID/hardware/HID/avr/cores/hid/binary.h create mode 100644 plugins/KeyboardioHID/hardware/HID/avr/cores/hid/hooks.c create mode 100644 plugins/KeyboardioHID/hardware/HID/avr/cores/hid/main.cpp create mode 100644 plugins/KeyboardioHID/hardware/HID/avr/cores/hid/new.cpp create mode 100644 plugins/KeyboardioHID/hardware/HID/avr/cores/hid/new.h create mode 100644 plugins/KeyboardioHID/hardware/HID/avr/cores/hid/wiring.c create mode 100644 plugins/KeyboardioHID/hardware/HID/avr/cores/hid/wiring_analog.c create mode 100644 plugins/KeyboardioHID/hardware/HID/avr/cores/hid/wiring_digital.c rename plugins/KeyboardioHID/{arduino => hardware/HID/avr/cores/hid}/wiring_private.h (100%) create mode 100644 plugins/KeyboardioHID/hardware/HID/avr/cores/hid/wiring_pulse.c create mode 100644 plugins/KeyboardioHID/hardware/HID/avr/cores/hid/wiring_shift.c create mode 100644 plugins/KeyboardioHID/hardware/HID/avr/platform.txt create mode 100644 plugins/KeyboardioHID/hardware/HID/avr/variants/hid_descriptors/hid_descriptors.h create mode 100644 plugins/KeyboardioHID/hardware/HID/avr/variants/leonardo/pins_arduino.h create mode 100644 plugins/KeyboardioHID/hardware/HID/avr/variants/leonardo_hid/pins_arduino.h create mode 100644 plugins/KeyboardioHID/hardware/HID/avr/variants/micro/pins_arduino.h create mode 100644 plugins/KeyboardioHID/hardware/HID/avr/variants/micro_hid/pins_arduino.h diff --git a/plugins/KeyboardioHID/hardware/HID/avr/boards.txt b/plugins/KeyboardioHID/hardware/HID/avr/boards.txt new file mode 100644 index 0000000000..8866d1b304 --- /dev/null +++ b/plugins/KeyboardioHID/hardware/HID/avr/boards.txt @@ -0,0 +1,33 @@ +############################################################## + +leonardo_extended.name=Arduino Leonardo Extended HID-Core +leonardo_extended.vid.0=0x2341 +leonardo_extended.pid.0=0x0036 +leonardo_extended.vid.1=0x2341 +leonardo_extended.pid.1=0x8036 +leonardo_extended.upload.tool=arduino:avrdude +leonardo_extended.upload.protocol=avr109 +leonardo_extended.upload.maximum_size=28672 +leonardo_extended.upload.maximum_data_size=2560 +leonardo_extended.upload.speed=57600 +leonardo_extended.upload.disable_flushing=true +leonardo_extended.upload.use_1200bps_touch=true +leonardo_extended.upload.wait_for_upload_port=true + +leonardo_extended.bootloader.tool=arduino:avrdude +leonardo_extended.bootloader.low_fuses=0xff +leonardo_extended.bootloader.high_fuses=0xd8 +leonardo_extended.bootloader.extended_fuses=0xcb +leonardo_extended.bootloader.file=arduino:caterina/Caterina-leonardo_extended.hex +leonardo_extended.bootloader.unlock_bits=0x3F +leonardo_extended.bootloader.lock_bits=0x2F + +leonardo_extended.build.mcu=atmega32u4 +leonardo_extended.build.f_cpu=16000000L +leonardo_extended.build.vid=0x2341 +leonardo_extended.build.pid=0x8036 +leonardo_extended.build.usb_product="Arduino Leonardo" +leonardo_extended.build.board=AVR_LEONARDO +leonardo_extended.build.core=arduino:hid +leonardo_extended.build.variant=leonardo_hid +leonardo_extended.build.extra_flags={build.usb_flags} \ No newline at end of file diff --git a/plugins/KeyboardioHID/arduino/Arduino.h b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Arduino.h similarity index 100% rename from plugins/KeyboardioHID/arduino/Arduino.h rename to plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Arduino.h diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Client.h b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Client.h new file mode 100644 index 0000000000..b8e5d935f2 --- /dev/null +++ b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Client.h @@ -0,0 +1,45 @@ +/* + Client.h - Base class that provides Client + 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 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/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/HardwareSerial.cpp b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/HardwareSerial.cpp new file mode 100644 index 0000000000..29a336649e --- /dev/null +++ b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/HardwareSerial.cpp @@ -0,0 +1,252 @@ +/* + 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 + Modified 14 August 2012 by Alarus + Modified 3 December 2013 by Matthijs Kooijman +*/ + +#include +#include +#include +#include +#include "Arduino.h" + +#include "HardwareSerial.h" +#include "HardwareSerial_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(HAVE_HWSERIAL0) || defined(HAVE_HWSERIAL1) || defined(HAVE_HWSERIAL2) || defined(HAVE_HWSERIAL3) + +// SerialEvent functions are weak, so when the user doesn't define them, +// the linker just sets their address to 0 (which is checked below). +// The Serialx_available is just a wrapper around Serialx.available(), +// but we can refer to it weakly so we don't pull in the entire +// HardwareSerial instance if the user doesn't also refer to it. +#if defined(HAVE_HWSERIAL0) + void serialEvent() __attribute__((weak)); + bool Serial0_available() __attribute__((weak)); +#endif + +#if defined(HAVE_HWSERIAL1) + void serialEvent1() __attribute__((weak)); + bool Serial1_available() __attribute__((weak)); +#endif + +#if defined(HAVE_HWSERIAL2) + void serialEvent2() __attribute__((weak)); + bool Serial2_available() __attribute__((weak)); +#endif + +#if defined(HAVE_HWSERIAL3) + void serialEvent3() __attribute__((weak)); + bool Serial3_available() __attribute__((weak)); +#endif + +void serialEventRun(void) +{ +#if defined(HAVE_HWSERIAL0) + if (Serial0_available && serialEvent && Serial0_available()) serialEvent(); +#endif +#if defined(HAVE_HWSERIAL1) + if (Serial1_available && serialEvent1 && Serial1_available()) serialEvent1(); +#endif +#if defined(HAVE_HWSERIAL2) + if (Serial2_available && serialEvent2 && Serial2_available()) serialEvent2(); +#endif +#if defined(HAVE_HWSERIAL3) + if (Serial3_available && serialEvent3 && Serial3_available()) serialEvent3(); +#endif +} + +// Actual interrupt handlers ////////////////////////////////////////////////////////////// + +void HardwareSerial::_tx_udr_empty_irq(void) +{ + // If interrupts are enabled, there must be more data in the output + // buffer. Send the next byte + unsigned char c = _tx_buffer[_tx_buffer_tail]; + _tx_buffer_tail = (_tx_buffer_tail + 1) % SERIAL_TX_BUFFER_SIZE; + + *_udr = c; + + // clear the TXC bit -- "can be cleared by writing a one to its bit + // location". This makes sure flush() won't return until the bytes + // actually got written + sbi(*_ucsra, TXC0); + + if (_tx_buffer_head == _tx_buffer_tail) { + // Buffer empty, so disable interrupts + cbi(*_ucsrb, UDRIE0); + } +} + +// Public Methods ////////////////////////////////////////////////////////////// + +void HardwareSerial::begin(unsigned long baud, byte config) +{ + // Try u2x mode first + uint16_t baud_setting = (F_CPU / 4 / baud - 1) / 2; + *_ucsra = 1 << U2X0; + + // hardcoded exception for 57600 for compatibility with the bootloader + // shipped with the Duemilanove and previous boards and the firmware + // on the 8U2 on the Uno and Mega 2560. Also, The baud_setting cannot + // be > 4095, so switch back to non-u2x mode if the baud rate is too + // low. + if (((F_CPU == 16000000UL) && (baud == 57600)) || (baud_setting >4095)) + { + *_ucsra = 0; + baud_setting = (F_CPU / 8 / baud - 1) / 2; + } + + // assign the baud_setting, a.k.a. ubrr (USART Baud Rate Register) + *_ubrrh = baud_setting >> 8; + *_ubrrl = baud_setting; + + _written = false; + + //set the data bits, parity, and stop bits +#if defined(__AVR_ATmega8__) + config |= 0x80; // select UCSRC register (shared with UBRRH) +#endif + *_ucsrc = config; + + sbi(*_ucsrb, RXEN0); + sbi(*_ucsrb, TXEN0); + sbi(*_ucsrb, RXCIE0); + cbi(*_ucsrb, UDRIE0); +} + +void HardwareSerial::end() +{ + // wait for transmission of outgoing data + while (_tx_buffer_head != _tx_buffer_tail) + ; + + cbi(*_ucsrb, RXEN0); + cbi(*_ucsrb, TXEN0); + cbi(*_ucsrb, RXCIE0); + cbi(*_ucsrb, UDRIE0); + + // clear any received data + _rx_buffer_head = _rx_buffer_tail; +} + +int HardwareSerial::available(void) +{ + return (int)(SERIAL_RX_BUFFER_SIZE + _rx_buffer_head - _rx_buffer_tail) % SERIAL_RX_BUFFER_SIZE; +} + +int HardwareSerial::peek(void) +{ + if (_rx_buffer_head == _rx_buffer_tail) { + return -1; + } else { + return _rx_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[_rx_buffer_tail]; + _rx_buffer_tail = (rx_buffer_index_t)(_rx_buffer_tail + 1) % SERIAL_RX_BUFFER_SIZE; + return c; + } +} + +int HardwareSerial::availableForWrite(void) +{ +#if (SERIAL_TX_BUFFER_SIZE>256) + uint8_t oldSREG = SREG; + cli(); +#endif + tx_buffer_index_t head = _tx_buffer_head; + tx_buffer_index_t tail = _tx_buffer_tail; +#if (SERIAL_TX_BUFFER_SIZE>256) + SREG = oldSREG; +#endif + if (head >= tail) return SERIAL_TX_BUFFER_SIZE - 1 - head + tail; + return tail - head - 1; +} + +void HardwareSerial::flush() +{ + // If we have never written a byte, no need to flush. This special + // case is needed since there is no way to force the TXC (transmit + // complete) bit to 1 during initialization + if (!_written) + return; + + while (bit_is_set(*_ucsrb, UDRIE0) || bit_is_clear(*_ucsra, TXC0)) { + if (bit_is_clear(SREG, SREG_I) && bit_is_set(*_ucsrb, UDRIE0)) + // Interrupts are globally disabled, but the DR empty + // interrupt should be enabled, so poll the DR empty flag to + // prevent deadlock + if (bit_is_set(*_ucsra, UDRE0)) + _tx_udr_empty_irq(); + } + // If we get here, nothing is queued anymore (DRIE is disabled) and + // the hardware finished tranmission (TXC is set). +} + +size_t HardwareSerial::write(uint8_t c) +{ + // If the buffer and the data register is empty, just write the byte + // to the data register and be done. This shortcut helps + // significantly improve the effective datarate at high (> + // 500kbit/s) bitrates, where interrupt overhead becomes a slowdown. + if (_tx_buffer_head == _tx_buffer_tail && bit_is_set(*_ucsra, UDRE0)) { + *_udr = c; + sbi(*_ucsra, TXC0); + return 1; + } + tx_buffer_index_t i = (_tx_buffer_head + 1) % SERIAL_TX_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 + while (i == _tx_buffer_tail) { + if (bit_is_clear(SREG, SREG_I)) { + // Interrupts are disabled, so we'll have to poll the data + // register empty flag ourselves. If it is set, pretend an + // interrupt has happened and call the handler to free up + // space for us. + if(bit_is_set(*_ucsra, UDRE0)) + _tx_udr_empty_irq(); + } else { + // nop, the interrupt handler will free up space for us + } + } + + _tx_buffer[_tx_buffer_head] = c; + _tx_buffer_head = i; + + sbi(*_ucsrb, UDRIE0); + _written = true; + + return 1; +} + + +#endif // whole file diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/HardwareSerial.h b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/HardwareSerial.h new file mode 100644 index 0000000000..935934b195 --- /dev/null +++ b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/HardwareSerial.h @@ -0,0 +1,149 @@ +/* + 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 + Modified 14 August 2012 by Alarus + Modified 3 December 2013 by Matthijs Kooijman +*/ + +#ifndef HardwareSerial_h +#define HardwareSerial_h + +#include + +#include "Stream.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 !(defined(SERIAL_TX_BUFFER_SIZE) && defined(SERIAL_RX_BUFFER_SIZE)) +#if (RAMEND < 1000) +#define SERIAL_TX_BUFFER_SIZE 16 +#define SERIAL_RX_BUFFER_SIZE 16 +#else +#define SERIAL_TX_BUFFER_SIZE 64 +#define SERIAL_RX_BUFFER_SIZE 64 +#endif +#endif +#if (SERIAL_TX_BUFFER_SIZE>256) +typedef uint16_t tx_buffer_index_t; +#else +typedef uint8_t tx_buffer_index_t; +#endif +#if (SERIAL_RX_BUFFER_SIZE>256) +typedef uint16_t rx_buffer_index_t; +#else +typedef uint8_t rx_buffer_index_t; +#endif + +// Define config for Serial.begin(baud, config); +#define SERIAL_5N1 0x00 +#define SERIAL_6N1 0x02 +#define SERIAL_7N1 0x04 +#define SERIAL_8N1 0x06 +#define SERIAL_5N2 0x08 +#define SERIAL_6N2 0x0A +#define SERIAL_7N2 0x0C +#define SERIAL_8N2 0x0E +#define SERIAL_5E1 0x20 +#define SERIAL_6E1 0x22 +#define SERIAL_7E1 0x24 +#define SERIAL_8E1 0x26 +#define SERIAL_5E2 0x28 +#define SERIAL_6E2 0x2A +#define SERIAL_7E2 0x2C +#define SERIAL_8E2 0x2E +#define SERIAL_5O1 0x30 +#define SERIAL_6O1 0x32 +#define SERIAL_7O1 0x34 +#define SERIAL_8O1 0x36 +#define SERIAL_5O2 0x38 +#define SERIAL_6O2 0x3A +#define SERIAL_7O2 0x3C +#define SERIAL_8O2 0x3E + +class HardwareSerial : public Stream +{ + protected: + volatile uint8_t * const _ubrrh; + volatile uint8_t * const _ubrrl; + volatile uint8_t * const _ucsra; + volatile uint8_t * const _ucsrb; + volatile uint8_t * const _ucsrc; + volatile uint8_t * const _udr; + // Has any byte been written to the UART since begin() + bool _written; + + volatile rx_buffer_index_t _rx_buffer_head; + volatile rx_buffer_index_t _rx_buffer_tail; + volatile tx_buffer_index_t _tx_buffer_head; + volatile tx_buffer_index_t _tx_buffer_tail; + + // Don't put any members after these buffers, since only the first + // 32 bytes of this struct can be accessed quickly using the ldd + // instruction. + unsigned char _rx_buffer[SERIAL_RX_BUFFER_SIZE]; + unsigned char _tx_buffer[SERIAL_TX_BUFFER_SIZE]; + + public: + inline HardwareSerial( + volatile uint8_t *ubrrh, volatile uint8_t *ubrrl, + volatile uint8_t *ucsra, volatile uint8_t *ucsrb, + volatile uint8_t *ucsrc, volatile uint8_t *udr); + void begin(unsigned long baud) { begin(baud, SERIAL_8N1); } + void begin(unsigned long, uint8_t); + void end(); + virtual int available(void); + virtual int peek(void); + virtual int read(void); + int availableForWrite(void); + virtual void flush(void); + virtual size_t write(uint8_t); + inline size_t write(unsigned long n) { return write((uint8_t)n); } + inline size_t write(long n) { return write((uint8_t)n); } + inline size_t write(unsigned int n) { return write((uint8_t)n); } + inline size_t write(int n) { return write((uint8_t)n); } + using Print::write; // pull in write(str) and write(buf, size) from Print + operator bool() { return true; } + + // Interrupt handlers - Not intended to be called externally + inline void _rx_complete_irq(void); + void _tx_udr_empty_irq(void); +}; + +#if defined(UBRRH) || defined(UBRR0H) + extern HardwareSerial Serial; + #define HAVE_HWSERIAL0 +#endif +#if defined(UBRR1H) + extern HardwareSerial Serial1; + #define HAVE_HWSERIAL1 +#endif +#if defined(UBRR2H) + extern HardwareSerial Serial2; + #define HAVE_HWSERIAL2 +#endif +#if defined(UBRR3H) + extern HardwareSerial Serial3; + #define HAVE_HWSERIAL3 +#endif + +extern void serialEventRun(void) __attribute__((weak)); + +#endif diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/HardwareSerial0.cpp b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/HardwareSerial0.cpp new file mode 100644 index 0000000000..1146eebab6 --- /dev/null +++ b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/HardwareSerial0.cpp @@ -0,0 +1,79 @@ +/* + HardwareSerial0.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 + Modified 14 August 2012 by Alarus + Modified 3 December 2013 by Matthijs Kooijman +*/ + +#include "Arduino.h" +#include "HardwareSerial.h" +#include "HardwareSerial_private.h" + +// Each HardwareSerial is defined in its own file, sine the linker pulls +// in the entire file when any element inside is used. --gc-sections can +// additionally cause unused symbols to be dropped, but ISRs have the +// "used" attribute so are never dropped and they keep the +// HardwareSerial instance in as well. Putting each instance in its own +// file prevents the linker from pulling in any unused instances in the +// first place. + +#if defined(HAVE_HWSERIAL0) + +#if defined(USART_RX_vect) + ISR(USART_RX_vect) +#elif defined(USART0_RX_vect) + ISR(USART0_RX_vect) +#elif defined(USART_RXC_vect) + ISR(USART_RXC_vect) // ATmega8 +#else + #error "Don't know what the Data Received vector is called for Serial" +#endif + { + Serial._rx_complete_irq(); + } + +#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) +#else + #error "Don't know what the Data Register Empty vector is called for Serial" +#endif +{ + Serial._tx_udr_empty_irq(); +} + +#if defined(UBRRH) && defined(UBRRL) + HardwareSerial Serial(&UBRRH, &UBRRL, &UCSRA, &UCSRB, &UCSRC, &UDR); +#else + HardwareSerial Serial(&UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UCSR0C, &UDR0); +#endif + +// Function that can be weakly referenced by serialEventRun to prevent +// pulling in this file if it's not otherwise used. +bool Serial0_available() { + return Serial.available(); +} + +#endif // HAVE_HWSERIAL0 diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/HardwareSerial1.cpp b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/HardwareSerial1.cpp new file mode 100644 index 0000000000..19625e235d --- /dev/null +++ b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/HardwareSerial1.cpp @@ -0,0 +1,69 @@ +/* + HardwareSerial1.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 + Modified 14 August 2012 by Alarus + Modified 3 December 2013 by Matthijs Kooijman +*/ + +#include "Arduino.h" +#include "HardwareSerial.h" +#include "HardwareSerial_private.h" + +// Each HardwareSerial is defined in its own file, sine the linker pulls +// in the entire file when any element inside is used. --gc-sections can +// additionally cause unused symbols to be dropped, but ISRs have the +// "used" attribute so are never dropped and they keep the +// HardwareSerial instance in as well. Putting each instance in its own +// file prevents the linker from pulling in any unused instances in the +// first place. + +#if defined(HAVE_HWSERIAL1) + +#if defined(UART1_RX_vect) +ISR(UART1_RX_vect) +#elif defined(USART1_RX_vect) +ISR(USART1_RX_vect) +#else +#error "Don't know what the Data Register Empty vector is called for Serial1" +#endif +{ + Serial1._rx_complete_irq(); +} + +#if defined(UART1_UDRE_vect) +ISR(UART1_UDRE_vect) +#elif defined(USART1_UDRE_vect) +ISR(USART1_UDRE_vect) +#else +#error "Don't know what the Data Register Empty vector is called for Serial1" +#endif +{ + Serial1._tx_udr_empty_irq(); +} + +HardwareSerial Serial1(&UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UCSR1C, &UDR1); + +// Function that can be weakly referenced by serialEventRun to prevent +// pulling in this file if it's not otherwise used. +bool Serial1_available() { + return Serial1.available(); +} + +#endif // HAVE_HWSERIAL1 diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/HardwareSerial2.cpp b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/HardwareSerial2.cpp new file mode 100644 index 0000000000..fd334ae15b --- /dev/null +++ b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/HardwareSerial2.cpp @@ -0,0 +1,57 @@ +/* + HardwareSerial2.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 + Modified 14 August 2012 by Alarus + Modified 3 December 2013 by Matthijs Kooijman +*/ + +#include "Arduino.h" +#include "HardwareSerial.h" +#include "HardwareSerial_private.h" + +// Each HardwareSerial is defined in its own file, sine the linker pulls +// in the entire file when any element inside is used. --gc-sections can +// additionally cause unused symbols to be dropped, but ISRs have the +// "used" attribute so are never dropped and they keep the +// HardwareSerial instance in as well. Putting each instance in its own +// file prevents the linker from pulling in any unused instances in the +// first place. + +#if defined(HAVE_HWSERIAL2) + +ISR(USART2_RX_vect) +{ + Serial2._rx_complete_irq(); +} + +ISR(USART2_UDRE_vect) +{ + Serial2._tx_udr_empty_irq(); +} + +HardwareSerial Serial2(&UBRR2H, &UBRR2L, &UCSR2A, &UCSR2B, &UCSR2C, &UDR2); + +// Function that can be weakly referenced by serialEventRun to prevent +// pulling in this file if it's not otherwise used. +bool Serial2_available() { + return Serial2.available(); +} + +#endif // HAVE_HWSERIAL2 diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/HardwareSerial3.cpp b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/HardwareSerial3.cpp new file mode 100644 index 0000000000..a68095b37c --- /dev/null +++ b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/HardwareSerial3.cpp @@ -0,0 +1,57 @@ +/* + HardwareSerial3.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 + Modified 14 August 2012 by Alarus + Modified 3 December 2013 by Matthijs Kooijman +*/ + +#include "Arduino.h" +#include "HardwareSerial.h" +#include "HardwareSerial_private.h" + +// Each HardwareSerial is defined in its own file, sine the linker pulls +// in the entire file when any element inside is used. --gc-sections can +// additionally cause unused symbols to be dropped, but ISRs have the +// "used" attribute so are never dropped and they keep the +// HardwareSerial instance in as well. Putting each instance in its own +// file prevents the linker from pulling in any unused instances in the +// first place. + +#if defined(HAVE_HWSERIAL3) + +ISR(USART3_RX_vect) +{ + Serial3._rx_complete_irq(); +} + +ISR(USART3_UDRE_vect) +{ + Serial3._tx_udr_empty_irq(); +} + +HardwareSerial Serial3(&UBRR3H, &UBRR3L, &UCSR3A, &UCSR3B, &UCSR3C, &UDR3); + +// Function that can be weakly referenced by serialEventRun to prevent +// pulling in this file if it's not otherwise used. +bool Serial3_available() { + return Serial3.available(); +} + +#endif // HAVE_HWSERIAL3 diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/HardwareSerial_private.h b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/HardwareSerial_private.h new file mode 100644 index 0000000000..761a5e559c --- /dev/null +++ b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/HardwareSerial_private.h @@ -0,0 +1,123 @@ +/* + HardwareSerial_private.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 23 November 2006 by David A. Mellis + Modified 28 September 2010 by Mark Sproul + Modified 14 August 2012 by Alarus +*/ + +#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(HAVE_HWSERIAL0) || defined(HAVE_HWSERIAL1) || defined(HAVE_HWSERIAL2) || defined(HAVE_HWSERIAL3) + +// Ensure that the various bit positions we use are available with a 0 +// postfix, so we can always use the values for UART0 for all UARTs. The +// alternative, passing the various values for each UART to the +// HardwareSerial constructor also works, but makes the code bigger and +// slower. +#if !defined(TXC0) +#if defined(TXC) +// Some chips like ATmega8 don't have UPE, only PE. The other bits are +// named as expected. +#if !defined(UPE) && defined(PE) +#define UPE PE +#endif +// On ATmega8, the uart and its bits are not numbered, so there is no TXC0 etc. +#define TXC0 TXC +#define RXEN0 RXEN +#define TXEN0 TXEN +#define RXCIE0 RXCIE +#define UDRIE0 UDRIE +#define U2X0 U2X +#define UPE0 UPE +#define UDRE0 UDRE +#elif defined(TXC1) +// Some devices have uart1 but no uart0 +#define TXC0 TXC1 +#define RXEN0 RXEN1 +#define TXEN0 TXEN1 +#define RXCIE0 RXCIE1 +#define UDRIE0 UDRIE1 +#define U2X0 U2X1 +#define UPE0 UPE1 +#define UDRE0 UDRE1 +#else +#error No UART found in HardwareSerial.cpp +#endif +#endif // !defined TXC0 + +// Check at compiletime that it is really ok to use the bit positions of +// UART0 for the other UARTs as well, in case these values ever get +// changed for future hardware. +#if defined(TXC1) && (TXC1 != TXC0 || RXEN1 != RXEN0 || RXCIE1 != RXCIE0 || \ + UDRIE1 != UDRIE0 || U2X1 != U2X0 || UPE1 != UPE0 || \ + UDRE1 != UDRE0) +#error "Not all bit positions for UART1 are the same as for UART0" +#endif +#if defined(TXC2) && (TXC2 != TXC0 || RXEN2 != RXEN0 || RXCIE2 != RXCIE0 || \ + UDRIE2 != UDRIE0 || U2X2 != U2X0 || UPE2 != UPE0 || \ + UDRE2 != UDRE0) +#error "Not all bit positions for UART2 are the same as for UART0" +#endif +#if defined(TXC3) && (TXC3 != TXC0 || RXEN3 != RXEN0 || RXCIE3 != RXCIE0 || \ + UDRIE3 != UDRIE0 || U3X3 != U3X0 || UPE3 != UPE0 || \ + UDRE3 != UDRE0) +#error "Not all bit positions for UART3 are the same as for UART0" +#endif + +// Constructors //////////////////////////////////////////////////////////////// + +HardwareSerial::HardwareSerial( + volatile uint8_t *ubrrh, volatile uint8_t *ubrrl, + volatile uint8_t *ucsra, volatile uint8_t *ucsrb, + volatile uint8_t *ucsrc, volatile uint8_t *udr) : + _ubrrh(ubrrh), _ubrrl(ubrrl), + _ucsra(ucsra), _ucsrb(ucsrb), _ucsrc(ucsrc), + _udr(udr), + _rx_buffer_head(0), _rx_buffer_tail(0), + _tx_buffer_head(0), _tx_buffer_tail(0) +{ +} + +// Actual interrupt handlers ////////////////////////////////////////////////////////////// + +void HardwareSerial::_rx_complete_irq(void) +{ + if (bit_is_clear(*_ucsra, UPE0)) { + // No Parity error, read byte and store it in the buffer if there is + // room + unsigned char c = *_udr; + rx_buffer_index_t i = (unsigned int)(_rx_buffer_head + 1) % SERIAL_RX_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 != _rx_buffer_tail) { + _rx_buffer[_rx_buffer_head] = c; + _rx_buffer_head = i; + } + } else { + // Parity error, read byte but discard it + *_udr; + }; +} + +#endif // whole file diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/IPAddress.cpp b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/IPAddress.cpp new file mode 100644 index 0000000000..899cbd4eda --- /dev/null +++ b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/IPAddress.cpp @@ -0,0 +1,74 @@ +/* + IPAddress.cpp - Base class that provides IPAddress + 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 +*/ + +#include +#include + +IPAddress::IPAddress() +{ + _address.dword = 0; +} + +IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet) +{ + _address.bytes[0] = first_octet; + _address.bytes[1] = second_octet; + _address.bytes[2] = third_octet; + _address.bytes[3] = fourth_octet; +} + +IPAddress::IPAddress(uint32_t address) +{ + _address.dword = address; +} + +IPAddress::IPAddress(const uint8_t *address) +{ + memcpy(_address.bytes, address, sizeof(_address.bytes)); +} + +IPAddress& IPAddress::operator=(const uint8_t *address) +{ + memcpy(_address.bytes, address, sizeof(_address.bytes)); + return *this; +} + +IPAddress& IPAddress::operator=(uint32_t address) +{ + _address.dword = address; + return *this; +} + +bool IPAddress::operator==(const uint8_t* addr) const +{ + return memcmp(addr, _address.bytes, sizeof(_address.bytes)) == 0; +} + +size_t IPAddress::printTo(Print& p) const +{ + size_t n = 0; + for (int i =0; i < 3; i++) + { + n += p.print(_address.bytes[i], DEC); + n += p.print('.'); + } + n += p.print(_address.bytes[3], DEC); + return n; +} + diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/IPAddress.h b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/IPAddress.h new file mode 100644 index 0000000000..94acdc4566 --- /dev/null +++ b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/IPAddress.h @@ -0,0 +1,75 @@ +/* + IPAddress.h - Base class that provides IPAddress + 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 IPAddress_h +#define IPAddress_h + +#include +#include + +// A class to make it easier to handle and pass around IP addresses + +class IPAddress : public Printable { +private: + union { + uint8_t bytes[4]; // IPv4 address + uint32_t dword; + } _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.bytes; }; + +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() const { return _address.dword; }; + bool operator==(const IPAddress& addr) const { return _address.dword == addr._address.dword; }; + bool operator==(const uint8_t* addr) const; + + // Overloaded index operator to allow getting and setting individual octets of the address + uint8_t operator[](int index) const { return _address.bytes[index]; }; + uint8_t& operator[](int index) { return _address.bytes[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/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Print.cpp b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Print.cpp new file mode 100644 index 0000000000..5df56306e9 --- /dev/null +++ b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Print.cpp @@ -0,0 +1,264 @@ +/* + 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 +#include +#include +#include +#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) +{ + PGM_P p = reinterpret_cast(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) +{ + return write(s.c_str(), s.length()); +} + +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; + + if (isnan(number)) return print("nan"); + if (isinf(number)) return print("inf"); + if (number > 4294967040.0) return print ("ovf"); // constant determined empirically + if (number <-4294967040.0) return print ("ovf"); // constant determined empirically + + // 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 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/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Print.h b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Print.h new file mode 100644 index 0000000000..7b53aa4d17 --- /dev/null +++ b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Print.h @@ -0,0 +1,84 @@ +/* + 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 +#include // 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) { + if (str == NULL) return 0; + return write((const uint8_t *)str, strlen(str)); + } + virtual size_t write(const uint8_t *buffer, size_t size); + size_t write(const char *buffer, size_t size) { + return write((const uint8_t *)buffer, 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/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Printable.h b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Printable.h new file mode 100644 index 0000000000..2a1b2e9f2c --- /dev/null +++ b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/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 + +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/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Server.h b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Server.h new file mode 100644 index 0000000000..69e3e39fe6 --- /dev/null +++ b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Server.h @@ -0,0 +1,30 @@ +/* + Server.h - Base class that provides Server + 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 server_h +#define server_h + +#include "Print.h" + +class Server : public Print { +public: + virtual void begin() =0; +}; + +#endif diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Stream.cpp b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Stream.cpp new file mode 100644 index 0000000000..9c581bee1b --- /dev/null +++ b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/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, (char*)""); +} + +// 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; + int 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/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Stream.h b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Stream.h new file mode 100644 index 0000000000..5cf5ddf017 --- /dev/null +++ b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Stream.h @@ -0,0 +1,102 @@ +/* + 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 +#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 +{ + protected: + 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 + bool find(uint8_t *target) { return find ((char *)target); } + // 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 + bool find(uint8_t *target, size_t length) { return find ((char *)target, length); } + // 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(uint8_t *target, char *terminator) { return findUntil((char *)target, terminator); } + + bool findUntil(char *target, size_t targetLen, char *terminate, size_t termLen); // as above but search ends if the terminate string is found + bool findUntil(uint8_t *target, size_t targetLen, char *terminate, size_t termLen) {return findUntil((char *)target, targetLen, terminate, termLen); } + + + 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 + size_t readBytes( uint8_t *buffer, size_t length) { return readBytes((char *)buffer, length); } + // 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 + size_t readBytesUntil( char terminator, uint8_t *buffer, size_t length) { return readBytesUntil(terminator, (char *)buffer, length); } + // 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/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Tone.cpp b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Tone.cpp new file mode 100644 index 0000000000..9bb6fe721c --- /dev/null +++ b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Tone.cpp @@ -0,0 +1,616 @@ +/* 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 +0008 S Kanemoto 12/06/22 Fixed for Leonardo by @maris_HY +*************************************************/ + +#include +#include +#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 + + +#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) + +#define AVAILABLE_TONE_PINS 1 +#define USE_TIMER2 + +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 +#define USE_TIMER2 + +const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 1 */ }; +static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255 */ }; + +#elif defined(__AVR_ATmega32U4__) + +#define AVAILABLE_TONE_PINS 1 +#define USE_TIMER3 + +const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 3 /*, 1 */ }; +static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255 */ }; + +#else + +#define AVAILABLE_TONE_PINS 1 +#define USE_TIMER2 + +// 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); +} + +#ifdef USE_TIMER0 +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 + + +#ifdef USE_TIMER1 +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 + + +#ifdef USE_TIMER2 +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 + } +} +#endif + + +#ifdef USE_TIMER3 +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 + } +} +#endif + + +#ifdef USE_TIMER4 +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 + } +} +#endif + + +#ifdef USE_TIMER5 +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/plugins/KeyboardioHID/arduino/USB-Core/CDC.cpp b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/CDC.cpp similarity index 100% rename from plugins/KeyboardioHID/arduino/USB-Core/CDC.cpp rename to plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/CDC.cpp diff --git a/plugins/KeyboardioHID/arduino/USB-Core/CDC.h b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/CDC.h similarity index 100% rename from plugins/KeyboardioHID/arduino/USB-Core/CDC.h rename to plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/CDC.h diff --git a/plugins/KeyboardioHID/arduino/USB-Core/Consumer.cpp b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/Consumer.cpp similarity index 100% rename from plugins/KeyboardioHID/arduino/USB-Core/Consumer.cpp rename to plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/Consumer.cpp diff --git a/plugins/KeyboardioHID/arduino/USB-Core/Consumer.h b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/Consumer.h similarity index 100% rename from plugins/KeyboardioHID/arduino/USB-Core/Consumer.h rename to plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/Consumer.h diff --git a/plugins/KeyboardioHID/arduino/USB-Core/Gamepad.cpp b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/Gamepad.cpp similarity index 100% rename from plugins/KeyboardioHID/arduino/USB-Core/Gamepad.cpp rename to plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/Gamepad.cpp diff --git a/plugins/KeyboardioHID/arduino/USB-Core/Gamepad.h b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/Gamepad.h similarity index 100% rename from plugins/KeyboardioHID/arduino/USB-Core/Gamepad.h rename to plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/Gamepad.h diff --git a/plugins/KeyboardioHID/arduino/USB-Core/HID.cpp b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/HID.cpp similarity index 85% rename from plugins/KeyboardioHID/arduino/USB-Core/HID.cpp rename to plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/HID.cpp index 4ac49caeea..26406cd4af 100644 --- a/plugins/KeyboardioHID/arduino/USB-Core/HID.cpp +++ b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/HID.cpp @@ -28,23 +28,12 @@ extern const u8 _hidReportDescriptor[] PROGMEM; const u8 _hidReportDescriptor[] = { - // by default use the standard HID APIs -#ifndef EXTERN_HID_REPORT -#ifdef HID_KEYBOARD_LEDS_ENABLED - HID_REPORT_KEYBOARD_LEDS(HID_REPORTID_KEYBOARD), -#else - HID_REPORT_KEYBOARD_KEYS(HID_REPORTID_KEYBOARD), -#endif - HID_REPORT_MOUSE(HID_REPORTID_MOUSE), - HID_REPORT_MOUSE_ABSOLUTE(HID_REPORTID_MOUSE_ABSOLUTE), - //HID_REPORT_RAWHID(HID_REPORTID_RAWHID), - HID_REPORT_CONSUMERCONTROL(HID_REPORTID_CONSUMERCONTROL), - HID_REPORT_SYSTEMCONTROL(HID_REPORTID_SYSTEMCONTROL), - //TODO get Gamepad working with the other devices - //HID_REPORT_GAMEPAD(HID_REPORTID_GAMEPAD), - -#else + // by default use the standard HID descriptors + // extern descriptors can be passed via pins_Arduino.h +#ifdef EXTERN_HID_REPORT EXTERN_HID_REPORT +#else + DEFAULT_HID_REPORT #endif }; diff --git a/plugins/KeyboardioHID/arduino/USB-Core/HID.h b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/HID.h similarity index 97% rename from plugins/KeyboardioHID/arduino/USB-Core/HID.h rename to plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/HID.h index b64fb606e4..85d21de886 100644 --- a/plugins/KeyboardioHID/arduino/USB-Core/HID.h +++ b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/HID.h @@ -22,9 +22,19 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "Arduino.h" -// enable Led out report by default -#ifndef EXTERN_HID_REPORT -#define HID_KEYBOARD_LEDS_ENABLED +// for the extern HID descriptors +#include "pins_Arduino.h" + +// default HID report descriptor +#ifdef HID_KEYBOARD_LEDS_ENABLED +#define DEFAULT_HID_REPORT \ +HID_REPORT_KEYBOARD_LEDS(HID_REPORTID_KEYBOARD), \ +HID_REPORT_MOUSE(HID_REPORTID_MOUSE) + +#else +#define DEFAULT_HID_REPORT \ +HID_REPORT_KEYBOARD_KEYS(HID_REPORTID_KEYBOARD), \ +HID_REPORT_MOUSE(HID_REPORTID_MOUSE) #endif // extern accessible led out report diff --git a/plugins/KeyboardioHID/arduino/USB-Core/HIDAPI.h b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/HIDAPI.h similarity index 100% rename from plugins/KeyboardioHID/arduino/USB-Core/HIDAPI.h rename to plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/HIDAPI.h diff --git a/plugins/KeyboardioHID/arduino/USB-Core/HIDTables.h b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/HIDTables.h similarity index 100% rename from plugins/KeyboardioHID/arduino/USB-Core/HIDTables.h rename to plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/HIDTables.h diff --git a/plugins/KeyboardioHID/arduino/USB-Core/Keyboard.cpp b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/Keyboard.cpp similarity index 100% rename from plugins/KeyboardioHID/arduino/USB-Core/Keyboard.cpp rename to plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/Keyboard.cpp diff --git a/plugins/KeyboardioHID/arduino/USB-Core/Keyboard.h b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/Keyboard.h similarity index 100% rename from plugins/KeyboardioHID/arduino/USB-Core/Keyboard.h rename to plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/Keyboard.h diff --git a/plugins/KeyboardioHID/arduino/USB-Core/Mouse.cpp b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/Mouse.cpp similarity index 100% rename from plugins/KeyboardioHID/arduino/USB-Core/Mouse.cpp rename to plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/Mouse.cpp diff --git a/plugins/KeyboardioHID/arduino/USB-Core/Mouse.h b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/Mouse.h similarity index 100% rename from plugins/KeyboardioHID/arduino/USB-Core/Mouse.h rename to plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/Mouse.h diff --git a/plugins/KeyboardioHID/arduino/USB-Core/System.cpp b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/System.cpp similarity index 100% rename from plugins/KeyboardioHID/arduino/USB-Core/System.cpp rename to plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/System.cpp diff --git a/plugins/KeyboardioHID/arduino/USB-Core/System.h b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/System.h similarity index 100% rename from plugins/KeyboardioHID/arduino/USB-Core/System.h rename to plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/System.h diff --git a/plugins/KeyboardioHID/arduino/USB-Core/USBAPI.h b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/USBAPI.h similarity index 100% rename from plugins/KeyboardioHID/arduino/USB-Core/USBAPI.h rename to plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/USBAPI.h diff --git a/plugins/KeyboardioHID/arduino/USB-Core/USBCore.cpp b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/USBCore.cpp similarity index 100% rename from plugins/KeyboardioHID/arduino/USB-Core/USBCore.cpp rename to plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/USBCore.cpp diff --git a/plugins/KeyboardioHID/arduino/USB-Core/USBCore.h b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/USBCore.h similarity index 100% rename from plugins/KeyboardioHID/arduino/USB-Core/USBCore.h rename to plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/USBCore.h diff --git a/plugins/KeyboardioHID/arduino/USB-Core/USBDesc.h b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/USBDesc.h similarity index 100% rename from plugins/KeyboardioHID/arduino/USB-Core/USBDesc.h rename to plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/USBDesc.h diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Udp.h b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Udp.h new file mode 100644 index 0000000000..dc5644b9df --- /dev/null +++ b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/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 +#include + +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/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/WCharacter.h b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/WCharacter.h new file mode 100644 index 0000000000..79733b50a5 --- /dev/null +++ b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/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 + +// 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/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/WInterrupts.c b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/WInterrupts.c new file mode 100644 index 0000000000..d3fbf100e3 --- /dev/null +++ b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/WInterrupts.c @@ -0,0 +1,334 @@ +/* -*- 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 +#include +#include +#include +#include + +#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<= 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/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/WString.cpp b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/WString.cpp new file mode 100644 index 0000000000..dcd469d7dd --- /dev/null +++ b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/WString.cpp @@ -0,0 +1,745 @@ +/* + 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; +} + +String::String(const __FlashStringHelper *pstr) +{ + init(); + *this = pstr; +} + +#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[1 + 8 * sizeof(unsigned char)]; + utoa(value, buf, base); + *this = buf; +} + +String::String(int value, unsigned char base) +{ + init(); + char buf[2 + 8 * sizeof(int)]; + itoa(value, buf, base); + *this = buf; +} + +String::String(unsigned int value, unsigned char base) +{ + init(); + char buf[1 + 8 * sizeof(unsigned int)]; + utoa(value, buf, base); + *this = buf; +} + +String::String(long value, unsigned char base) +{ + init(); + char buf[2 + 8 * sizeof(long)]; + ltoa(value, buf, base); + *this = buf; +} + +String::String(unsigned long value, unsigned char base) +{ + init(); + char buf[1 + 8 * sizeof(unsigned long)]; + ultoa(value, buf, base); + *this = buf; +} + +String::String(float value, unsigned char decimalPlaces) +{ + init(); + char buf[33]; + *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf); +} + +String::String(double value, unsigned char decimalPlaces) +{ + init(); + char buf[33]; + *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf); +} + +String::~String() +{ + free(buffer); +} + +/*********************************************/ +/* Memory Management */ +/*********************************************/ + +inline void String::init(void) +{ + buffer = NULL; + capacity = 0; + len = 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; +} + +String & String::copy(const __FlashStringHelper *pstr, unsigned int length) +{ + if (!reserve(length)) { + invalidate(); + return *this; + } + len = length; + strcpy_P(buffer, (PGM_P)pstr); + 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; +} + +String & String::operator = (const __FlashStringHelper *pstr) +{ + if (pstr) copy(pstr, strlen_P((PGM_P)pstr)); + 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[1 + 3 * sizeof(unsigned char)]; + itoa(num, buf, 10); + return concat(buf, strlen(buf)); +} + +unsigned char String::concat(int num) +{ + char buf[2 + 3 * sizeof(int)]; + itoa(num, buf, 10); + return concat(buf, strlen(buf)); +} + +unsigned char String::concat(unsigned int num) +{ + char buf[1 + 3 * sizeof(unsigned int)]; + utoa(num, buf, 10); + return concat(buf, strlen(buf)); +} + +unsigned char String::concat(long num) +{ + char buf[2 + 3 * sizeof(long)]; + ltoa(num, buf, 10); + return concat(buf, strlen(buf)); +} + +unsigned char String::concat(unsigned long num) +{ + char buf[1 + 3 * sizeof(unsigned long)]; + ultoa(num, buf, 10); + return concat(buf, strlen(buf)); +} + +unsigned char String::concat(float num) +{ + char buf[20]; + char* string = dtostrf(num, 4, 2, buf); + return concat(string, strlen(string)); +} + +unsigned char String::concat(double num) +{ + char buf[20]; + char* string = dtostrf(num, 4, 2, buf); + return concat(string, strlen(string)); +} + +unsigned char String::concat(const __FlashStringHelper * str) +{ + if (!str) return 0; + int length = strlen_P((const char *) str); + if (length == 0) return 1; + unsigned int newlen = len + length; + if (!reserve(newlen)) return 0; + strcpy_P(buffer + len, (const char *) str); + len = newlen; + return 1; +} + +/*********************************************/ +/* Concatenate */ +/*********************************************/ + +StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs) +{ + StringSumHelper &a = const_cast(lhs); + if (!a.concat(rhs.buffer, rhs.len)) a.invalidate(); + return a; +} + +StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr) +{ + StringSumHelper &a = const_cast(lhs); + if (!cstr || !a.concat(cstr, strlen(cstr))) a.invalidate(); + return a; +} + +StringSumHelper & operator + (const StringSumHelper &lhs, char c) +{ + StringSumHelper &a = const_cast(lhs); + if (!a.concat(c)) a.invalidate(); + return a; +} + +StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num) +{ + StringSumHelper &a = const_cast(lhs); + if (!a.concat(num)) a.invalidate(); + return a; +} + +StringSumHelper & operator + (const StringSumHelper &lhs, int num) +{ + StringSumHelper &a = const_cast(lhs); + if (!a.concat(num)) a.invalidate(); + return a; +} + +StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num) +{ + StringSumHelper &a = const_cast(lhs); + if (!a.concat(num)) a.invalidate(); + return a; +} + +StringSumHelper & operator + (const StringSumHelper &lhs, long num) +{ + StringSumHelper &a = const_cast(lhs); + if (!a.concat(num)) a.invalidate(); + return a; +} + +StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num) +{ + StringSumHelper &a = const_cast(lhs); + if (!a.concat(num)) a.invalidate(); + return a; +} + +StringSumHelper & operator + (const StringSumHelper &lhs, float num) +{ + StringSumHelper &a = const_cast(lhs); + if (!a.concat(num)) a.invalidate(); + return a; +} + +StringSumHelper & operator + (const StringSumHelper &lhs, double num) +{ + StringSumHelper &a = const_cast(lhs); + if (!a.concat(num)) a.invalidate(); + return a; +} + +StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs) +{ + StringSumHelper &a = const_cast(lhs); + if (!a.concat(rhs)) 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, 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::remove(unsigned int index){ + // Pass the biggest integer as the count. The remove method + // below will take care of truncating it at the end of the + // string. + remove(index, (unsigned int)-1); +} + +void String::remove(unsigned int index, unsigned int count){ + if (index >= len) { return; } + if (count <= 0) { return; } + if (count > len - index) { count = len - index; } + char *writeTo = buffer + index; + len = len - count; + strncpy(writeTo, buffer + index + count,len - index); + buffer[len] = 0; +} + +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; +} + +float String::toFloat(void) const +{ + if (buffer) return float(atof(buffer)); + return 0; +} diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/WString.h b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/WString.h new file mode 100644 index 0000000000..7402430927 --- /dev/null +++ b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/WString.h @@ -0,0 +1,224 @@ +/* + 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 +#include +#include +#include + +// 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(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); + String(const __FlashStringHelper *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); + explicit String(float, unsigned char decimalPlaces=2); + explicit String(double, unsigned char decimalPlaces=2); + ~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); + String & operator = (const __FlashStringHelper *str); + #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); + unsigned char concat(float num); + unsigned char concat(double num); + unsigned char concat(const __FlashStringHelper * str); + + // 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);} + String & operator += (float num) {concat(num); return (*this);} + String & operator += (double num) {concat(num); return (*this);} + String & operator += (const __FlashStringHelper *str){concat(str); 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); + friend StringSumHelper & operator + (const StringSumHelper &lhs, float num); + friend StringSumHelper & operator + (const StringSumHelper &lhs, double num); + friend StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs); + + // 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);} + const char * c_str() const { return buffer; } + + // 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 { return substring(beginIndex, len); }; + 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 remove(unsigned int index); + void remove(unsigned int index, unsigned int count); + void toLowerCase(void); + void toUpperCase(void); + void trim(void); + + // parsing/conversion + long toInt(void) const; + float toFloat(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') +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); + String & copy(const __FlashStringHelper *pstr, 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) {} + StringSumHelper(float num) : String(num) {} + StringSumHelper(double num) : String(num) {} +}; + +#endif // __cplusplus +#endif // String_class_h diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/abi.cpp b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/abi.cpp new file mode 100644 index 0000000000..8d719b8e64 --- /dev/null +++ b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/abi.cpp @@ -0,0 +1,35 @@ +/* + Copyright (c) 2014 Arduino. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include + +extern "C" void __cxa_pure_virtual(void) __attribute__ ((__noreturn__)); +extern "C" void __cxa_deleted_virtual(void) __attribute__ ((__noreturn__)); + +void __cxa_pure_virtual(void) { + // We might want to write some diagnostics to uart in this case + //std::terminate(); + abort(); +} + +void __cxa_deleted_virtual(void) { + // We might want to write some diagnostics to uart in this case + //std::terminate(); + abort(); +} + diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/binary.h b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/binary.h new file mode 100644 index 0000000000..aec4c733d4 --- /dev/null +++ b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/binary.h @@ -0,0 +1,534 @@ +/* + binary.h - Definitions for binary constants + Copyright (c) 2006 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 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/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/hooks.c b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/hooks.c new file mode 100644 index 0000000000..641eabc737 --- /dev/null +++ b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/hooks.c @@ -0,0 +1,31 @@ +/* + Copyright (c) 2012 Arduino. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +/** + * Empty yield() hook. + * + * This function is intended to be used by library writers to build + * libraries or sketches that supports cooperative threads. + * + * Its defined as a weak symbol and it can be redefined to implement a + * real cooperative scheduler. + */ +static void __empty() { + // Empty +} +void yield(void) __attribute__ ((weak, alias("__empty"))); diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/main.cpp b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/main.cpp new file mode 100644 index 0000000000..a60980da57 --- /dev/null +++ b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/main.cpp @@ -0,0 +1,49 @@ +/* + main.cpp - Main loop for Arduino sketches + Copyright (c) 2005-2013 Arduino Team. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include + +//Declared weak in Arduino.h to allow user redefinitions. +int atexit(void (*func)()) { return 0; } + +// Weak empty variant initialization function. +// May be redefined by variant files. +void initVariant() __attribute__((weak)); +void initVariant() { } + +int main(void) +{ + init(); + + initVariant(); + +#if defined(USBCON) + USBDevice.attach(); +#endif + + setup(); + + for (;;) { + loop(); + if (serialEventRun) serialEventRun(); + } + + return 0; +} + diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/new.cpp b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/new.cpp new file mode 100644 index 0000000000..cf6f89c178 --- /dev/null +++ b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/new.cpp @@ -0,0 +1,36 @@ +/* + Copyright (c) 2014 Arduino. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include + +void *operator new(size_t size) { + return malloc(size); +} + +void *operator new[](size_t size) { + return malloc(size); +} + +void operator delete(void * ptr) { + free(ptr); +} + +void operator delete[](void * ptr) { + free(ptr); +} + diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/new.h b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/new.h new file mode 100644 index 0000000000..6e1b68f0da --- /dev/null +++ b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/new.h @@ -0,0 +1,30 @@ +/* + Copyright (c) 2014 Arduino. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef NEW_H +#define NEW_H + +#include + +void * operator new(size_t size); +void * operator new[](size_t size); +void operator delete(void * ptr); +void operator delete[](void * ptr); + +#endif + diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/wiring.c b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/wiring.c new file mode 100644 index 0000000000..5cbe241956 --- /dev/null +++ b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/wiring.c @@ -0,0 +1,325 @@ +/* + 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__) +ISR(TIM0_OVF_vect) +#else +ISR(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) { + yield(); + 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/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/wiring_analog.c b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/wiring_analog.c new file mode 100644 index 0000000000..48a9ef52d5 --- /dev/null +++ b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/wiring_analog.c @@ -0,0 +1,292 @@ +/* + 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(analogPinToChannel) +#if defined(__AVR_ATmega32U4__) + if (pin >= 18) pin -= 18; // allow for channel or pin numbers +#endif + pin = analogPinToChannel(pin); +#elif 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__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644A__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__) + 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(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(TCCR1A) && defined(COM1C1) + case TIMER1C: + // connect pwm to pin on timer 1, channel B + sbi(TCCR1A, COM1C1); + OCR1C = 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/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/wiring_digital.c b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/wiring_digital.c new file mode 100644 index 0000000000..df94cc1c5b --- /dev/null +++ b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/wiring_digital.c @@ -0,0 +1,181 @@ +/* + 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(TCCR1A) && defined(COM1C1) + case TIMER1C: cbi(TCCR1A, COM1C1); 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/plugins/KeyboardioHID/arduino/wiring_private.h b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/wiring_private.h similarity index 100% rename from plugins/KeyboardioHID/arduino/wiring_private.h rename to plugins/KeyboardioHID/hardware/HID/avr/cores/hid/wiring_private.h diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/wiring_pulse.c b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/wiring_pulse.c new file mode 100644 index 0000000000..0d968865d2 --- /dev/null +++ b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/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/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/wiring_shift.c b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/wiring_shift.c new file mode 100644 index 0000000000..cfe786758c --- /dev/null +++ b/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/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/plugins/KeyboardioHID/hardware/HID/avr/platform.txt b/plugins/KeyboardioHID/hardware/HID/avr/platform.txt new file mode 100644 index 0000000000..cf12aa435e --- /dev/null +++ b/plugins/KeyboardioHID/hardware/HID/avr/platform.txt @@ -0,0 +1,9 @@ + +# Arduino AVR Core and platform. +# ------------------------------ + +# For more info: +# https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification + +name=Arduino HID-Core +version=2.1 diff --git a/plugins/KeyboardioHID/hardware/HID/avr/variants/hid_descriptors/hid_descriptors.h b/plugins/KeyboardioHID/hardware/HID/avr/variants/hid_descriptors/hid_descriptors.h new file mode 100644 index 0000000000..787b865d2a --- /dev/null +++ b/plugins/KeyboardioHID/hardware/HID/avr/variants/hid_descriptors/hid_descriptors.h @@ -0,0 +1,36 @@ +// add your custom HID Report Descriptor here. +// you can use the pre defined reports as well +#define EXTERN_HID_REPORT DEFAULT_HID_REPORT + +#define GAMEPAD_HID_REPORT \ +HID_REPORT_KEYBOARD_LEDS(HID_REPORTID_KEYBOARD), \ +HID_REPORT_MOUSE(HID_REPORTID_MOUSE), \ +HID_REPORT_GAMEPAD(HID_REPORTID_GAMEPAD) + +#define EXTENDED_HID_REPORT \ +HID_REPORT_KEYBOARD_LEDS(HID_REPORTID_KEYBOARD), \ +HID_REPORT_MOUSE(HID_REPORTID_MOUSE), \ +HID_REPORT_MOUSE_ABSOLUTE(HID_REPORTID_MOUSE_ABSOLUTE), \ +HID_REPORT_CONSUMERCONTROL(HID_REPORTID_CONSUMERCONTROL), \ +HID_REPORT_SYSTEMCONTROL(HID_REPORTID_SYSTEMCONTROL) + + +// use this to enable the Keyboard Led functions +#define HID_KEYBOARD_LEDS_ENABLED + + +// Keep in mind that changing the ids or reports might confuse your OS +// Then you might need to reinstall all drivers or change the USB PID +// Mouse Abs only works with a System report and without Gamepad +// Gamepads can causes some recognition Problems with some OS +// RAW HID seems to not works properly in a multireport +// Currently available pre defined reports: + +//HID_REPORT_KEYBOARD_LEDS(HID_REPORTID_KEYBOARD), +//HID_REPORT_KEYBOARD_KEYS(HID_REPORTID_KEYBOARD), +//HID_REPORT_MOUSE(HID_REPORTID_MOUSE), +//HID_REPORT_MOUSE_ABSOLUTE(HID_REPORTID_MOUSE_ABSOLUTE), +////HID_REPORT_RAWHID(HID_REPORTID_RAWHID), // not working at the moment +//HID_REPORT_CONSUMERCONTROL(HID_REPORTID_CONSUMERCONTROL), +//HID_REPORT_SYSTEMCONTROL(HID_REPORTID_SYSTEMCONTROL), +//HID_REPORT_GAMEPAD(HID_REPORTID_GAMEPAD), \ No newline at end of file diff --git a/plugins/KeyboardioHID/hardware/HID/avr/variants/leonardo/pins_arduino.h b/plugins/KeyboardioHID/hardware/HID/avr/variants/leonardo/pins_arduino.h new file mode 100644 index 0000000000..fd75373c12 --- /dev/null +++ b/plugins/KeyboardioHID/hardware/HID/avr/variants/leonardo/pins_arduino.h @@ -0,0 +1,361 @@ +/* + 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 + +// Workaround for wrong definitions in "iom32u4.h". +// This should be fixed in the AVR toolchain. +#undef UHCON +#undef UHINT +#undef UHIEN +#undef UHADDR +#undef UHFNUM +#undef UHFNUML +#undef UHFNUMH +#undef UHFLEN +#undef UPINRQX +#undef UPINTX +#undef UPNUM +#undef UPRST +#undef UPCONX +#undef UPCFG0X +#undef UPCFG1X +#undef UPSTAX +#undef UPCFG2X +#undef UPIENX +#undef UPDATX +#undef TCCR2A +#undef WGM20 +#undef WGM21 +#undef COM2B0 +#undef COM2B1 +#undef COM2A0 +#undef COM2A1 +#undef TCCR2B +#undef CS20 +#undef CS21 +#undef CS22 +#undef WGM22 +#undef FOC2B +#undef FOC2A +#undef TCNT2 +#undef TCNT2_0 +#undef TCNT2_1 +#undef TCNT2_2 +#undef TCNT2_3 +#undef TCNT2_4 +#undef TCNT2_5 +#undef TCNT2_6 +#undef TCNT2_7 +#undef OCR2A +#undef OCR2_0 +#undef OCR2_1 +#undef OCR2_2 +#undef OCR2_3 +#undef OCR2_4 +#undef OCR2_5 +#undef OCR2_6 +#undef OCR2_7 +#undef OCR2B +#undef OCR2_0 +#undef OCR2_1 +#undef OCR2_2 +#undef OCR2_3 +#undef OCR2_4 +#undef OCR2_5 +#undef OCR2_6 +#undef OCR2_7 + +#define NUM_DIGITAL_PINS 30 +#define NUM_ANALOG_INPUTS 12 + +#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; +#define LED_BUILTIN 13 + +// 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) ) ) + +#define digitalPinToInterrupt(p) ((p) == 0 ? 2 : ((p) == 1 ? 3 : ((p) == 2 ? 1 : ((p) == 3 ? 0 : ((p) == 7 ? 4 : NOT_AN_INTERRUPT))))) + +#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[] = { + 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[] = { + _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[] = { + 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, + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, + + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, +}; + +const uint8_t PROGMEM analog_pin_to_channel_PGM[] = { + 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 */ + +// These serial port names are intended to allow libraries and architecture-neutral +// sketches to automatically default to the correct port name for a particular type +// of use. For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN, +// the first hardware serial port whose RX/TX pins are not dedicated to another use. +// +// SERIAL_PORT_MONITOR Port which normally prints to the Arduino Serial Monitor +// +// SERIAL_PORT_USBVIRTUAL Port which is USB virtual serial +// +// SERIAL_PORT_LINUXBRIDGE Port which connects to a Linux system via Bridge library +// +// SERIAL_PORT_HARDWARE Hardware serial port, physical RX & TX pins. +// +// SERIAL_PORT_HARDWARE_OPEN Hardware serial ports which are open for use. Their RX & TX +// pins are NOT connected to anything by default. +#define SERIAL_PORT_MONITOR Serial +#define SERIAL_PORT_USBVIRTUAL Serial +#define SERIAL_PORT_HARDWARE Serial1 +#define SERIAL_PORT_HARDWARE_OPEN Serial1 + +#endif /* Pins_Arduino_h */ diff --git a/plugins/KeyboardioHID/hardware/HID/avr/variants/leonardo_hid/pins_arduino.h b/plugins/KeyboardioHID/hardware/HID/avr/variants/leonardo_hid/pins_arduino.h new file mode 100644 index 0000000000..6de11a9ac1 --- /dev/null +++ b/plugins/KeyboardioHID/hardware/HID/avr/variants/leonardo_hid/pins_arduino.h @@ -0,0 +1,2 @@ +#include "../leonardo/pins_arduino.h" +#include "../hid_descriptors/hid_descriptors.h" \ No newline at end of file diff --git a/plugins/KeyboardioHID/hardware/HID/avr/variants/micro/pins_arduino.h b/plugins/KeyboardioHID/hardware/HID/avr/variants/micro/pins_arduino.h new file mode 100644 index 0000000000..ea8e42dd23 --- /dev/null +++ b/plugins/KeyboardioHID/hardware/HID/avr/variants/micro/pins_arduino.h @@ -0,0 +1,37 @@ +/* + 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 "../leonardo/pins_arduino.h" + +#undef TXLED0 +#undef TXLED1 +#undef RXLED0 +#undef RXLED1 +#undef TX_RX_LED_INIT + +#define TXLED0 PORTD &= ~(1<<5) +#define TXLED1 PORTD |= (1<<5) +#define RXLED0 PORTB &= ~(1<<0) +#define RXLED1 PORTB |= (1<<0) +#define TX_RX_LED_INIT DDRD |= (1<<5), DDRB |= (1<<0), TXLED0, RXLED0 \ No newline at end of file diff --git a/plugins/KeyboardioHID/hardware/HID/avr/variants/micro_hid/pins_arduino.h b/plugins/KeyboardioHID/hardware/HID/avr/variants/micro_hid/pins_arduino.h new file mode 100644 index 0000000000..5eb21b9e8b --- /dev/null +++ b/plugins/KeyboardioHID/hardware/HID/avr/variants/micro_hid/pins_arduino.h @@ -0,0 +1,2 @@ +#include "../micro/pins_arduino.h" +#include "../hid_descriptors/hid_descriptors.h" \ No newline at end of file diff --git a/plugins/KeyboardioHID/hidtests2/hidtests2.ino b/plugins/KeyboardioHID/hidtests2/hidtests2.ino index 00df6a0242..9f2af89bb6 100644 --- a/plugins/KeyboardioHID/hidtests2/hidtests2.ino +++ b/plugins/KeyboardioHID/hidtests2/hidtests2.ino @@ -7,9 +7,10 @@ void setup() { pinMode(2, INPUT_PULLUP); pinMode(3, INPUT_PULLUP); - // 6374 292 + // 7052 279 Keyboard.begin(); Gamepad.begin(); + hid_keyboard_leds = 0; //test to access it from here } uint32_t eventBaud = 0; @@ -126,6 +127,18 @@ void loop() { Serial.println("Please only input a single character!"); break; + case 'g': { + // press button 1-32 and reset (34 becaue its written later) + static uint8_t count = 1; + Gamepad.press(count++); + if (count == 34) { + Gamepad.releaseAll(); + count = 1; + } + Gamepad.write(); + } + break; + case 'd': Serial.println("Serial"); Serial.println(Serial.dtr()); From cb61ba5b0093dd706395008c99c55207cbdae134 Mon Sep 17 00:00:00 2001 From: Nico Date: Fri, 2 Jan 2015 12:01:45 +0100 Subject: [PATCH 087/602] Readme update --- plugins/KeyboardioHID/Readme.md | 39 ++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 3d0105678f..e21c55e2f0 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -4,23 +4,27 @@ TODO Under Construction. This is a todo list for myself and a feature list so far. ``` -Keyboard Layout english only? -more usb definitions instead of fixed values, noone understands -someone has to add the keywords.txt definitions as well -keyboard led move to usb function not to keyboard and from keyboard call this function? -weak hidsendreport implement somewhere the prototype? -usb wakeup -keycode/raw for keyboard -magic key fix? +Keyboard Layout for different Languages +Clean up USB Core code from fixed values. Use better understandable definitions +Magic key fix for 32u4? + +Add Keywords.txt definitions add examples -improve workaround for consumer + system weak hid send function prototype -check keycode function again? -generalize HID key definitions -separate folder for the usb core? +keycode/raw for keyboard +Check Keyboard keycode function again? +Generalize HID key definitions via HIDTables for example? +Add custom HID reports example +add copyright + +update Burning via ISP (advanced) +Test with Android phone +update no usb workaround notice (no longer needed for hoodloader2, but for leonardo) + Bugs Mouse Abs only works with system report under special circumstances. -Gamepad + Mouse Abs doesnt work +Gamepad + Mouse Abs doesnt work (fix Gamepad) +Fix HID_SendReport() prototype workaround in HID-APIs ``` @@ -47,6 +51,8 @@ Gamepad + Mouse Abs doesnt work * Inlined a lot of the HID API functions to save flash * Added Gamepad * Added USB Wakeup support +* Separated USB-Core in its own folder +* Added HID Tables ``` ``` @@ -56,9 +62,12 @@ Include schematic - CDC.h -> Arduino.h, USBDESC.h, USBCore.h - HID.h -> Arduino.h, USBDESC.h, USBCore.h, HID-API - HID-API -> Keyboard.h, Mouse.h - - Keyboard.h -> Arduino.h - - Mouse.h -> Arduino.h + - Keyboard.h -> Arduino.h + - Mouse.h -> Arduino.h + - [Other APIs].h -> Arduino.h + - HIDTables.h HID.h contains all HID configuration. Each HID-API (like Mouse) includes Arduino.h and gets these settings as well. +The pins_Arduino.h can overwrite each HID descriptor or define complete new one. ``` \ No newline at end of file From 4240bbb041ee1d3ff65706fb1750c60e162c9a6b Mon Sep 17 00:00:00 2001 From: Nico Date: Fri, 2 Jan 2015 14:53:53 +0100 Subject: [PATCH 088/602] Moved Core again --- plugins/KeyboardioHID/Readme.md | 13 + .../{hardware/HID => }/avr/boards.txt | 36 +- .../HID => }/avr/cores/hid/Arduino.h | 0 .../{hardware/HID => }/avr/cores/hid/Client.h | 0 .../HID => }/avr/cores/hid/HardwareSerial.cpp | 0 .../HID => }/avr/cores/hid/HardwareSerial.h | 0 .../avr/cores/hid/HardwareSerial0.cpp | 0 .../avr/cores/hid/HardwareSerial1.cpp | 0 .../avr/cores/hid/HardwareSerial2.cpp | 0 .../avr/cores/hid/HardwareSerial3.cpp | 0 .../avr/cores/hid/HardwareSerial_private.h | 0 .../HID => }/avr/cores/hid/IPAddress.cpp | 0 .../HID => }/avr/cores/hid/IPAddress.h | 0 .../HID => }/avr/cores/hid/Print.cpp | 0 .../{hardware/HID => }/avr/cores/hid/Print.h | 0 .../HID => }/avr/cores/hid/Printable.h | 0 .../{hardware/HID => }/avr/cores/hid/Server.h | 0 .../HID => }/avr/cores/hid/Stream.cpp | 0 .../{hardware/HID => }/avr/cores/hid/Stream.h | 0 .../{hardware/HID => }/avr/cores/hid/Tone.cpp | 0 .../HID => }/avr/cores/hid/USB-Core/CDC.cpp | 0 .../HID => }/avr/cores/hid/USB-Core/CDC.h | 0 .../avr/cores/hid/USB-Core/Consumer.cpp | 0 .../avr/cores/hid/USB-Core/Consumer.h | 0 .../avr/cores/hid/USB-Core/Gamepad.cpp | 0 .../HID => }/avr/cores/hid/USB-Core/Gamepad.h | 0 .../HID => }/avr/cores/hid/USB-Core/HID.cpp | 0 .../HID => }/avr/cores/hid/USB-Core/HID.h | 0 .../HID => }/avr/cores/hid/USB-Core/HIDAPI.h | 0 .../avr/cores/hid/USB-Core/HIDTables.h | 0 .../avr/cores/hid/USB-Core/Keyboard.cpp | 0 .../avr/cores/hid/USB-Core/Keyboard.h | 0 .../HID => }/avr/cores/hid/USB-Core/Mouse.cpp | 0 .../HID => }/avr/cores/hid/USB-Core/Mouse.h | 0 .../avr/cores/hid/USB-Core/System.cpp | 0 .../HID => }/avr/cores/hid/USB-Core/System.h | 0 .../HID => }/avr/cores/hid/USB-Core/USBAPI.h | 0 .../avr/cores/hid/USB-Core/USBCore.cpp | 0 .../HID => }/avr/cores/hid/USB-Core/USBCore.h | 0 .../HID => }/avr/cores/hid/USB-Core/USBDesc.h | 0 .../{hardware/HID => }/avr/cores/hid/Udp.h | 0 .../HID => }/avr/cores/hid/WCharacter.h | 0 .../HID => }/avr/cores/hid/WInterrupts.c | 0 .../HID => }/avr/cores/hid/WMath.cpp | 0 .../HID => }/avr/cores/hid/WString.cpp | 0 .../HID => }/avr/cores/hid/WString.h | 0 .../{hardware/HID => }/avr/cores/hid/abi.cpp | 0 .../{hardware/HID => }/avr/cores/hid/binary.h | 0 .../{hardware/HID => }/avr/cores/hid/hooks.c | 0 .../{hardware/HID => }/avr/cores/hid/main.cpp | 0 .../{hardware/HID => }/avr/cores/hid/new.cpp | 0 .../{hardware/HID => }/avr/cores/hid/new.h | 0 .../{hardware/HID => }/avr/cores/hid/wiring.c | 0 .../HID => }/avr/cores/hid/wiring_analog.c | 0 .../HID => }/avr/cores/hid/wiring_digital.c | 0 .../HID => }/avr/cores/hid/wiring_private.h | 0 .../HID => }/avr/cores/hid/wiring_pulse.c | 0 .../HID => }/avr/cores/hid/wiring_shift.c | 0 .../{hardware/HID => }/avr/platform.txt | 4 +- .../hid_descriptors/hid_descriptors.h | 0 .../avr/variants/leonardo_hid/pins_arduino.h | 22 ++ .../avr/variants/micro_hid/pins_arduino.h | 22 ++ .../{ => examples}/hidtests2/hidtests2.ino | 0 .../HID/avr/variants/leonardo/pins_arduino.h | 361 ------------------ .../avr/variants/leonardo_hid/pins_arduino.h | 2 - .../HID/avr/variants/micro/pins_arduino.h | 37 -- .../HID/avr/variants/micro_hid/pins_arduino.h | 2 - 67 files changed, 94 insertions(+), 405 deletions(-) rename plugins/KeyboardioHID/{hardware/HID => }/avr/boards.txt (53%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/Arduino.h (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/Client.h (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/HardwareSerial.cpp (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/HardwareSerial.h (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/HardwareSerial0.cpp (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/HardwareSerial1.cpp (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/HardwareSerial2.cpp (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/HardwareSerial3.cpp (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/HardwareSerial_private.h (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/IPAddress.cpp (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/IPAddress.h (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/Print.cpp (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/Print.h (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/Printable.h (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/Server.h (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/Stream.cpp (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/Stream.h (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/Tone.cpp (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/USB-Core/CDC.cpp (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/USB-Core/CDC.h (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/USB-Core/Consumer.cpp (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/USB-Core/Consumer.h (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/USB-Core/Gamepad.cpp (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/USB-Core/Gamepad.h (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/USB-Core/HID.cpp (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/USB-Core/HID.h (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/USB-Core/HIDAPI.h (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/USB-Core/HIDTables.h (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/USB-Core/Keyboard.cpp (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/USB-Core/Keyboard.h (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/USB-Core/Mouse.cpp (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/USB-Core/Mouse.h (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/USB-Core/System.cpp (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/USB-Core/System.h (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/USB-Core/USBAPI.h (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/USB-Core/USBCore.cpp (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/USB-Core/USBCore.h (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/USB-Core/USBDesc.h (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/Udp.h (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/WCharacter.h (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/WInterrupts.c (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/WMath.cpp (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/WString.cpp (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/WString.h (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/abi.cpp (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/binary.h (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/hooks.c (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/main.cpp (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/new.cpp (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/new.h (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/wiring.c (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/wiring_analog.c (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/wiring_digital.c (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/wiring_private.h (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/wiring_pulse.c (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/cores/hid/wiring_shift.c (100%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/platform.txt (55%) rename plugins/KeyboardioHID/{hardware/HID => }/avr/variants/hid_descriptors/hid_descriptors.h (100%) create mode 100644 plugins/KeyboardioHID/avr/variants/leonardo_hid/pins_arduino.h create mode 100644 plugins/KeyboardioHID/avr/variants/micro_hid/pins_arduino.h rename plugins/KeyboardioHID/{ => examples}/hidtests2/hidtests2.ino (100%) delete mode 100644 plugins/KeyboardioHID/hardware/HID/avr/variants/leonardo/pins_arduino.h delete mode 100644 plugins/KeyboardioHID/hardware/HID/avr/variants/leonardo_hid/pins_arduino.h delete mode 100644 plugins/KeyboardioHID/hardware/HID/avr/variants/micro/pins_arduino.h delete mode 100644 plugins/KeyboardioHID/hardware/HID/avr/variants/micro_hid/pins_arduino.h diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index e21c55e2f0..7dbb0ccf97 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -1,3 +1,15 @@ +Installation +============ + +put these files into *sketchbook/hardware/HID/* + +at the moment you have to move +the cores/hid folder into your Arduino installation because of a bug in the ide. +This Core is ment to use with 1.5.8 or newer Arduino IDE + +You can compile all HID APIs +but this doesnt mean that you can use them if no hid descriptor is set correctly. + TODO ==== @@ -25,6 +37,7 @@ Bugs Mouse Abs only works with system report under special circumstances. Gamepad + Mouse Abs doesnt work (fix Gamepad) Fix HID_SendReport() prototype workaround in HID-APIs +Core selection in boards.txt is not working ``` diff --git a/plugins/KeyboardioHID/hardware/HID/avr/boards.txt b/plugins/KeyboardioHID/avr/boards.txt similarity index 53% rename from plugins/KeyboardioHID/hardware/HID/avr/boards.txt rename to plugins/KeyboardioHID/avr/boards.txt index 8866d1b304..ff9f9f9542 100644 --- a/plugins/KeyboardioHID/hardware/HID/avr/boards.txt +++ b/plugins/KeyboardioHID/avr/boards.txt @@ -1,6 +1,6 @@ ############################################################## -leonardo_extended.name=Arduino Leonardo Extended HID-Core +leonardo_extended.name=Arduino Leonardo Custom HID leonardo_extended.vid.0=0x2341 leonardo_extended.pid.0=0x0036 leonardo_extended.vid.1=0x2341 @@ -30,4 +30,36 @@ leonardo_extended.build.usb_product="Arduino Leonardo" leonardo_extended.build.board=AVR_LEONARDO leonardo_extended.build.core=arduino:hid leonardo_extended.build.variant=leonardo_hid -leonardo_extended.build.extra_flags={build.usb_flags} \ No newline at end of file +leonardo_extended.build.extra_flags={build.usb_flags} + +############################################################## + +micro.name=Arduino Micro Custom HID +micro.upload.tool=arduino:avrdude +micro.upload.protocol=avr109 +micro.upload.maximum_size=28672 +micro.upload.maximum_data_size=2560 +micro.upload.speed=57600 +micro.upload.disable_flushing=true +micro.upload.use_1200bps_touch=true +micro.upload.wait_for_upload_port=true + +micro.bootloader.tool=arduino:avrdude +micro.bootloader.low_fuses=0xff +micro.bootloader.high_fuses=0xd8 +micro.bootloader.extended_fuses=0xcb +micro.bootloader.file=arduino:caterina/Caterina-Micro.hex +micro.bootloader.unlock_bits=0x3F +micro.bootloader.lock_bits=0x2F + +micro.build.mcu=atmega32u4 +micro.build.f_cpu=16000000L +micro.build.vid=0x2341 +micro.build.pid=0x8037 +micro.build.usb_product="Arduino Micro" +micro.build.board=AVR_MICRO +micro.build.core=arduino:hid +micro.build.variant=micro_hid +micro.build.extra_flags={build.usb_flags} + +############################################################## \ No newline at end of file diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Arduino.h b/plugins/KeyboardioHID/avr/cores/hid/Arduino.h similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Arduino.h rename to plugins/KeyboardioHID/avr/cores/hid/Arduino.h diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Client.h b/plugins/KeyboardioHID/avr/cores/hid/Client.h similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Client.h rename to plugins/KeyboardioHID/avr/cores/hid/Client.h diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/HardwareSerial.cpp b/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.cpp similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/HardwareSerial.cpp rename to plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.cpp diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/HardwareSerial.h b/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.h similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/HardwareSerial.h rename to plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.h diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/HardwareSerial0.cpp b/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial0.cpp similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/HardwareSerial0.cpp rename to plugins/KeyboardioHID/avr/cores/hid/HardwareSerial0.cpp diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/HardwareSerial1.cpp b/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial1.cpp similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/HardwareSerial1.cpp rename to plugins/KeyboardioHID/avr/cores/hid/HardwareSerial1.cpp diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/HardwareSerial2.cpp b/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial2.cpp similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/HardwareSerial2.cpp rename to plugins/KeyboardioHID/avr/cores/hid/HardwareSerial2.cpp diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/HardwareSerial3.cpp b/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial3.cpp similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/HardwareSerial3.cpp rename to plugins/KeyboardioHID/avr/cores/hid/HardwareSerial3.cpp diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/HardwareSerial_private.h b/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial_private.h similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/HardwareSerial_private.h rename to plugins/KeyboardioHID/avr/cores/hid/HardwareSerial_private.h diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/IPAddress.cpp b/plugins/KeyboardioHID/avr/cores/hid/IPAddress.cpp similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/IPAddress.cpp rename to plugins/KeyboardioHID/avr/cores/hid/IPAddress.cpp diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/IPAddress.h b/plugins/KeyboardioHID/avr/cores/hid/IPAddress.h similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/IPAddress.h rename to plugins/KeyboardioHID/avr/cores/hid/IPAddress.h diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Print.cpp b/plugins/KeyboardioHID/avr/cores/hid/Print.cpp similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Print.cpp rename to plugins/KeyboardioHID/avr/cores/hid/Print.cpp diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Print.h b/plugins/KeyboardioHID/avr/cores/hid/Print.h similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Print.h rename to plugins/KeyboardioHID/avr/cores/hid/Print.h diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Printable.h b/plugins/KeyboardioHID/avr/cores/hid/Printable.h similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Printable.h rename to plugins/KeyboardioHID/avr/cores/hid/Printable.h diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Server.h b/plugins/KeyboardioHID/avr/cores/hid/Server.h similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Server.h rename to plugins/KeyboardioHID/avr/cores/hid/Server.h diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Stream.cpp b/plugins/KeyboardioHID/avr/cores/hid/Stream.cpp similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Stream.cpp rename to plugins/KeyboardioHID/avr/cores/hid/Stream.cpp diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Stream.h b/plugins/KeyboardioHID/avr/cores/hid/Stream.h similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Stream.h rename to plugins/KeyboardioHID/avr/cores/hid/Stream.h diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Tone.cpp b/plugins/KeyboardioHID/avr/cores/hid/Tone.cpp similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Tone.cpp rename to plugins/KeyboardioHID/avr/cores/hid/Tone.cpp diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/CDC.cpp b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/CDC.cpp similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/CDC.cpp rename to plugins/KeyboardioHID/avr/cores/hid/USB-Core/CDC.cpp diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/CDC.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/CDC.h similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/CDC.h rename to plugins/KeyboardioHID/avr/cores/hid/USB-Core/CDC.h diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/Consumer.cpp b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Consumer.cpp similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/Consumer.cpp rename to plugins/KeyboardioHID/avr/cores/hid/USB-Core/Consumer.cpp diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/Consumer.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Consumer.h similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/Consumer.h rename to plugins/KeyboardioHID/avr/cores/hid/USB-Core/Consumer.h diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/Gamepad.cpp b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.cpp similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/Gamepad.cpp rename to plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.cpp diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/Gamepad.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.h similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/Gamepad.h rename to plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.h diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/HID.cpp b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.cpp similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/HID.cpp rename to plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.cpp diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/HID.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/HID.h rename to plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/HIDAPI.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HIDAPI.h similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/HIDAPI.h rename to plugins/KeyboardioHID/avr/cores/hid/USB-Core/HIDAPI.h diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/HIDTables.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HIDTables.h similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/HIDTables.h rename to plugins/KeyboardioHID/avr/cores/hid/USB-Core/HIDTables.h diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/Keyboard.cpp b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.cpp similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/Keyboard.cpp rename to plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.cpp diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/Keyboard.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/Keyboard.h rename to plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/Mouse.cpp b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.cpp similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/Mouse.cpp rename to plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.cpp diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/Mouse.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.h similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/Mouse.h rename to plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.h diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/System.cpp b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.cpp similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/System.cpp rename to plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.cpp diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/System.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.h similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/System.h rename to plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.h diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/USBAPI.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBAPI.h similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/USBAPI.h rename to plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBAPI.h diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/USBCore.cpp b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBCore.cpp similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/USBCore.cpp rename to plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBCore.cpp diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/USBCore.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBCore.h similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/USBCore.h rename to plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBCore.h diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/USBDesc.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBDesc.h similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/USB-Core/USBDesc.h rename to plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBDesc.h diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Udp.h b/plugins/KeyboardioHID/avr/cores/hid/Udp.h similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/Udp.h rename to plugins/KeyboardioHID/avr/cores/hid/Udp.h diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/WCharacter.h b/plugins/KeyboardioHID/avr/cores/hid/WCharacter.h similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/WCharacter.h rename to plugins/KeyboardioHID/avr/cores/hid/WCharacter.h diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/WInterrupts.c b/plugins/KeyboardioHID/avr/cores/hid/WInterrupts.c similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/WInterrupts.c rename to plugins/KeyboardioHID/avr/cores/hid/WInterrupts.c diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/WMath.cpp b/plugins/KeyboardioHID/avr/cores/hid/WMath.cpp similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/WMath.cpp rename to plugins/KeyboardioHID/avr/cores/hid/WMath.cpp diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/WString.cpp b/plugins/KeyboardioHID/avr/cores/hid/WString.cpp similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/WString.cpp rename to plugins/KeyboardioHID/avr/cores/hid/WString.cpp diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/WString.h b/plugins/KeyboardioHID/avr/cores/hid/WString.h similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/WString.h rename to plugins/KeyboardioHID/avr/cores/hid/WString.h diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/abi.cpp b/plugins/KeyboardioHID/avr/cores/hid/abi.cpp similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/abi.cpp rename to plugins/KeyboardioHID/avr/cores/hid/abi.cpp diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/binary.h b/plugins/KeyboardioHID/avr/cores/hid/binary.h similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/binary.h rename to plugins/KeyboardioHID/avr/cores/hid/binary.h diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/hooks.c b/plugins/KeyboardioHID/avr/cores/hid/hooks.c similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/hooks.c rename to plugins/KeyboardioHID/avr/cores/hid/hooks.c diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/main.cpp b/plugins/KeyboardioHID/avr/cores/hid/main.cpp similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/main.cpp rename to plugins/KeyboardioHID/avr/cores/hid/main.cpp diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/new.cpp b/plugins/KeyboardioHID/avr/cores/hid/new.cpp similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/new.cpp rename to plugins/KeyboardioHID/avr/cores/hid/new.cpp diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/new.h b/plugins/KeyboardioHID/avr/cores/hid/new.h similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/new.h rename to plugins/KeyboardioHID/avr/cores/hid/new.h diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/wiring.c b/plugins/KeyboardioHID/avr/cores/hid/wiring.c similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/wiring.c rename to plugins/KeyboardioHID/avr/cores/hid/wiring.c diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/wiring_analog.c b/plugins/KeyboardioHID/avr/cores/hid/wiring_analog.c similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/wiring_analog.c rename to plugins/KeyboardioHID/avr/cores/hid/wiring_analog.c diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/wiring_digital.c b/plugins/KeyboardioHID/avr/cores/hid/wiring_digital.c similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/wiring_digital.c rename to plugins/KeyboardioHID/avr/cores/hid/wiring_digital.c diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/wiring_private.h b/plugins/KeyboardioHID/avr/cores/hid/wiring_private.h similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/wiring_private.h rename to plugins/KeyboardioHID/avr/cores/hid/wiring_private.h diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/wiring_pulse.c b/plugins/KeyboardioHID/avr/cores/hid/wiring_pulse.c similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/wiring_pulse.c rename to plugins/KeyboardioHID/avr/cores/hid/wiring_pulse.c diff --git a/plugins/KeyboardioHID/hardware/HID/avr/cores/hid/wiring_shift.c b/plugins/KeyboardioHID/avr/cores/hid/wiring_shift.c similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/cores/hid/wiring_shift.c rename to plugins/KeyboardioHID/avr/cores/hid/wiring_shift.c diff --git a/plugins/KeyboardioHID/hardware/HID/avr/platform.txt b/plugins/KeyboardioHID/avr/platform.txt similarity index 55% rename from plugins/KeyboardioHID/hardware/HID/avr/platform.txt rename to plugins/KeyboardioHID/avr/platform.txt index cf12aa435e..8887bd75a4 100644 --- a/plugins/KeyboardioHID/hardware/HID/avr/platform.txt +++ b/plugins/KeyboardioHID/avr/platform.txt @@ -4,6 +4,8 @@ # For more info: # https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification +# https://github.com/arduino/Arduino/wiki/Arduino-Hardware-Cores-migration-guide-from-1.0-to-1.6 -name=Arduino HID-Core +# https://github.com/NicoHood +name=Arduino Custom HID-Core version=2.1 diff --git a/plugins/KeyboardioHID/hardware/HID/avr/variants/hid_descriptors/hid_descriptors.h b/plugins/KeyboardioHID/avr/variants/hid_descriptors/hid_descriptors.h similarity index 100% rename from plugins/KeyboardioHID/hardware/HID/avr/variants/hid_descriptors/hid_descriptors.h rename to plugins/KeyboardioHID/avr/variants/hid_descriptors/hid_descriptors.h diff --git a/plugins/KeyboardioHID/avr/variants/leonardo_hid/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/leonardo_hid/pins_arduino.h new file mode 100644 index 0000000000..77655bda39 --- /dev/null +++ b/plugins/KeyboardioHID/avr/variants/leonardo_hid/pins_arduino.h @@ -0,0 +1,22 @@ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. +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 <../../variants/leonardo/pins_arduino.h> +#include "../hid_descriptors/hid_descriptors.h" \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/variants/micro_hid/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/micro_hid/pins_arduino.h new file mode 100644 index 0000000000..4dc36e2023 --- /dev/null +++ b/plugins/KeyboardioHID/avr/variants/micro_hid/pins_arduino.h @@ -0,0 +1,22 @@ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. +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 <../../variants/micro/pins_arduino.h> +#include "../hid_descriptors/hid_descriptors.h" \ No newline at end of file diff --git a/plugins/KeyboardioHID/hidtests2/hidtests2.ino b/plugins/KeyboardioHID/examples/hidtests2/hidtests2.ino similarity index 100% rename from plugins/KeyboardioHID/hidtests2/hidtests2.ino rename to plugins/KeyboardioHID/examples/hidtests2/hidtests2.ino diff --git a/plugins/KeyboardioHID/hardware/HID/avr/variants/leonardo/pins_arduino.h b/plugins/KeyboardioHID/hardware/HID/avr/variants/leonardo/pins_arduino.h deleted file mode 100644 index fd75373c12..0000000000 --- a/plugins/KeyboardioHID/hardware/HID/avr/variants/leonardo/pins_arduino.h +++ /dev/null @@ -1,361 +0,0 @@ -/* - 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 - -// Workaround for wrong definitions in "iom32u4.h". -// This should be fixed in the AVR toolchain. -#undef UHCON -#undef UHINT -#undef UHIEN -#undef UHADDR -#undef UHFNUM -#undef UHFNUML -#undef UHFNUMH -#undef UHFLEN -#undef UPINRQX -#undef UPINTX -#undef UPNUM -#undef UPRST -#undef UPCONX -#undef UPCFG0X -#undef UPCFG1X -#undef UPSTAX -#undef UPCFG2X -#undef UPIENX -#undef UPDATX -#undef TCCR2A -#undef WGM20 -#undef WGM21 -#undef COM2B0 -#undef COM2B1 -#undef COM2A0 -#undef COM2A1 -#undef TCCR2B -#undef CS20 -#undef CS21 -#undef CS22 -#undef WGM22 -#undef FOC2B -#undef FOC2A -#undef TCNT2 -#undef TCNT2_0 -#undef TCNT2_1 -#undef TCNT2_2 -#undef TCNT2_3 -#undef TCNT2_4 -#undef TCNT2_5 -#undef TCNT2_6 -#undef TCNT2_7 -#undef OCR2A -#undef OCR2_0 -#undef OCR2_1 -#undef OCR2_2 -#undef OCR2_3 -#undef OCR2_4 -#undef OCR2_5 -#undef OCR2_6 -#undef OCR2_7 -#undef OCR2B -#undef OCR2_0 -#undef OCR2_1 -#undef OCR2_2 -#undef OCR2_3 -#undef OCR2_4 -#undef OCR2_5 -#undef OCR2_6 -#undef OCR2_7 - -#define NUM_DIGITAL_PINS 30 -#define NUM_ANALOG_INPUTS 12 - -#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; -#define LED_BUILTIN 13 - -// 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) ) ) - -#define digitalPinToInterrupt(p) ((p) == 0 ? 2 : ((p) == 1 ? 3 : ((p) == 2 ? 1 : ((p) == 3 ? 0 : ((p) == 7 ? 4 : NOT_AN_INTERRUPT))))) - -#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[] = { - 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[] = { - _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[] = { - 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, - NOT_ON_TIMER, - NOT_ON_TIMER, - NOT_ON_TIMER, - NOT_ON_TIMER, - - NOT_ON_TIMER, - NOT_ON_TIMER, - NOT_ON_TIMER, - NOT_ON_TIMER, - NOT_ON_TIMER, - NOT_ON_TIMER, - NOT_ON_TIMER, - NOT_ON_TIMER, - NOT_ON_TIMER, - NOT_ON_TIMER, -}; - -const uint8_t PROGMEM analog_pin_to_channel_PGM[] = { - 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 */ - -// These serial port names are intended to allow libraries and architecture-neutral -// sketches to automatically default to the correct port name for a particular type -// of use. For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN, -// the first hardware serial port whose RX/TX pins are not dedicated to another use. -// -// SERIAL_PORT_MONITOR Port which normally prints to the Arduino Serial Monitor -// -// SERIAL_PORT_USBVIRTUAL Port which is USB virtual serial -// -// SERIAL_PORT_LINUXBRIDGE Port which connects to a Linux system via Bridge library -// -// SERIAL_PORT_HARDWARE Hardware serial port, physical RX & TX pins. -// -// SERIAL_PORT_HARDWARE_OPEN Hardware serial ports which are open for use. Their RX & TX -// pins are NOT connected to anything by default. -#define SERIAL_PORT_MONITOR Serial -#define SERIAL_PORT_USBVIRTUAL Serial -#define SERIAL_PORT_HARDWARE Serial1 -#define SERIAL_PORT_HARDWARE_OPEN Serial1 - -#endif /* Pins_Arduino_h */ diff --git a/plugins/KeyboardioHID/hardware/HID/avr/variants/leonardo_hid/pins_arduino.h b/plugins/KeyboardioHID/hardware/HID/avr/variants/leonardo_hid/pins_arduino.h deleted file mode 100644 index 6de11a9ac1..0000000000 --- a/plugins/KeyboardioHID/hardware/HID/avr/variants/leonardo_hid/pins_arduino.h +++ /dev/null @@ -1,2 +0,0 @@ -#include "../leonardo/pins_arduino.h" -#include "../hid_descriptors/hid_descriptors.h" \ No newline at end of file diff --git a/plugins/KeyboardioHID/hardware/HID/avr/variants/micro/pins_arduino.h b/plugins/KeyboardioHID/hardware/HID/avr/variants/micro/pins_arduino.h deleted file mode 100644 index ea8e42dd23..0000000000 --- a/plugins/KeyboardioHID/hardware/HID/avr/variants/micro/pins_arduino.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - 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 "../leonardo/pins_arduino.h" - -#undef TXLED0 -#undef TXLED1 -#undef RXLED0 -#undef RXLED1 -#undef TX_RX_LED_INIT - -#define TXLED0 PORTD &= ~(1<<5) -#define TXLED1 PORTD |= (1<<5) -#define RXLED0 PORTB &= ~(1<<0) -#define RXLED1 PORTB |= (1<<0) -#define TX_RX_LED_INIT DDRD |= (1<<5), DDRB |= (1<<0), TXLED0, RXLED0 \ No newline at end of file diff --git a/plugins/KeyboardioHID/hardware/HID/avr/variants/micro_hid/pins_arduino.h b/plugins/KeyboardioHID/hardware/HID/avr/variants/micro_hid/pins_arduino.h deleted file mode 100644 index 5eb21b9e8b..0000000000 --- a/plugins/KeyboardioHID/hardware/HID/avr/variants/micro_hid/pins_arduino.h +++ /dev/null @@ -1,2 +0,0 @@ -#include "../micro/pins_arduino.h" -#include "../hid_descriptors/hid_descriptors.h" \ No newline at end of file From 9ddb38784b257bdbfc4d9931ff780224b4288cd9 Mon Sep 17 00:00:00 2001 From: Nico Date: Fri, 2 Jan 2015 16:23:27 +0100 Subject: [PATCH 089/602] Added Examples --- plugins/KeyboardioHID/Readme.md | 3 + .../hid_descriptors/hid_descriptors.h | 33 +++- .../AdvancedGamepad/AdvancedGamepad.ino | 53 ++++++ .../AdvancedKeyboard/AdvancedKeyboard.ino | 98 ++++++++++ .../AdvancedRawHID/AdvancedRawHID.ino | 109 +++++++++++ .../HoodLoader1_API_Legacy.ino | 163 +++++++++++++++++ .../HoodLoader2_PWM_Fade.ino | 39 ++++ .../HoodLoader2_SerialKeyboard.ino | 54 ++++++ .../HoodLoader2_USB-Serial.ino | 51 ++++++ .../Gamepad_Project/Gamepad_Project.ino | 113 ++++++++++++ plugins/KeyboardioHID/examples/Readme.md | 4 + .../examples/hidtests2/hidtests2.ino | 169 ------------------ 12 files changed, 714 insertions(+), 175 deletions(-) create mode 100644 plugins/KeyboardioHID/examples/Advanced/AdvancedGamepad/AdvancedGamepad.ino create mode 100644 plugins/KeyboardioHID/examples/Advanced/AdvancedKeyboard/AdvancedKeyboard.ino create mode 100644 plugins/KeyboardioHID/examples/Advanced/AdvancedRawHID/AdvancedRawHID.ino create mode 100644 plugins/KeyboardioHID/examples/HoodLoader1/HoodLoader1_API_Legacy/HoodLoader1_API_Legacy.ino create mode 100644 plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_PWM_Fade/HoodLoader2_PWM_Fade.ino create mode 100644 plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_SerialKeyboard/HoodLoader2_SerialKeyboard.ino create mode 100644 plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_USB-Serial/HoodLoader2_USB-Serial.ino create mode 100644 plugins/KeyboardioHID/examples/Projects/Gamepad_Project/Gamepad_Project.ino create mode 100644 plugins/KeyboardioHID/examples/Readme.md delete mode 100644 plugins/KeyboardioHID/examples/hidtests2/hidtests2.ino diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 7dbb0ccf97..304c28f132 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -38,6 +38,9 @@ Mouse Abs only works with system report under special circumstances. Gamepad + Mouse Abs doesnt work (fix Gamepad) Fix HID_SendReport() prototype workaround in HID-APIs Core selection in boards.txt is not working + +Do not name the Arduino Sketch 'Mouse.ino' or 'Keyboard.ino' etc. +Your Arduino IDE will output errors then if you double click the file and try to compile. ``` diff --git a/plugins/KeyboardioHID/avr/variants/hid_descriptors/hid_descriptors.h b/plugins/KeyboardioHID/avr/variants/hid_descriptors/hid_descriptors.h index 787b865d2a..529adecb5e 100644 --- a/plugins/KeyboardioHID/avr/variants/hid_descriptors/hid_descriptors.h +++ b/plugins/KeyboardioHID/avr/variants/hid_descriptors/hid_descriptors.h @@ -1,11 +1,28 @@ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. +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. +*/ + // add your custom HID Report Descriptor here. // you can use the pre defined reports as well -#define EXTERN_HID_REPORT DEFAULT_HID_REPORT - -#define GAMEPAD_HID_REPORT \ -HID_REPORT_KEYBOARD_LEDS(HID_REPORTID_KEYBOARD), \ -HID_REPORT_MOUSE(HID_REPORTID_MOUSE), \ -HID_REPORT_GAMEPAD(HID_REPORTID_GAMEPAD) +//#define EXTERN_HID_REPORT DEFAULT_HID_REPORT +#define EXTERN_HID_REPORT EXTENDED_HID_REPORT +//#define EXTERN_HID_REPORT GAMEPAD_HID_REPORT #define EXTENDED_HID_REPORT \ HID_REPORT_KEYBOARD_LEDS(HID_REPORTID_KEYBOARD), \ @@ -14,6 +31,10 @@ HID_REPORT_MOUSE_ABSOLUTE(HID_REPORTID_MOUSE_ABSOLUTE), \ HID_REPORT_CONSUMERCONTROL(HID_REPORTID_CONSUMERCONTROL), \ HID_REPORT_SYSTEMCONTROL(HID_REPORTID_SYSTEMCONTROL) +#define GAMEPAD_HID_REPORT \ +HID_REPORT_KEYBOARD_LEDS(HID_REPORTID_KEYBOARD), \ +HID_REPORT_MOUSE(HID_REPORTID_MOUSE), \ +HID_REPORT_GAMEPAD(HID_REPORTID_GAMEPAD) // use this to enable the Keyboard Led functions #define HID_KEYBOARD_LEDS_ENABLED diff --git a/plugins/KeyboardioHID/examples/Advanced/AdvancedGamepad/AdvancedGamepad.ino b/plugins/KeyboardioHID/examples/Advanced/AdvancedGamepad/AdvancedGamepad.ino new file mode 100644 index 0000000000..eef660d9df --- /dev/null +++ b/plugins/KeyboardioHID/examples/Advanced/AdvancedGamepad/AdvancedGamepad.ino @@ -0,0 +1,53 @@ +/* + Copyright (c) 2014 NicoHood + See the readme for credit to other people. + + Advanced Gamepad example + */ + +// include HID library +#include + +// see HID_Reports.h for all data structures +HID_GamepadReport_Data_t Gamepadreport; + +const int pinLed = LED_BUILTIN; +const int pinButton = 2; + +// see HID_Reports.h for all data structures +HID_GamepadReport_Data_t Gamepadreport; + +void setup() { + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); + + // Sends a clean report to the host. This is important on any Arduino type. + // Make sure all desired USB functions are activated in USBAPI.h! + memset(&Gamepadreport, 0, sizeof(Gamepadreport)); + HID_SendReport(HID_REPORTID_Gamepad1Report, &Gamepadreport, sizeof(Gamepadreport)); +} + +void loop() { + if (!digitalRead(pinButton)) { + digitalWrite(pinLed, HIGH); + + // This demo is actually made for advanced users to show them how they can write an own report. + // This might be useful for a Gamepad if you want to edit the values direct on your own. + + // count with buttons binary + static uint32_t count = 0; + Gamepadreport.whole32[0] = count++; + + // move x/y Axis to a new position (16bit) + Gamepadreport.whole16[2] = (random(0xFFFF)); + + // functions before only set the values + // this writes the report to the host + HID_SendReport(HID_REPORTID_Gamepad1Report, &Gamepadreport, sizeof(Gamepadreport)); + + // simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } +} + diff --git a/plugins/KeyboardioHID/examples/Advanced/AdvancedKeyboard/AdvancedKeyboard.ino b/plugins/KeyboardioHID/examples/Advanced/AdvancedKeyboard/AdvancedKeyboard.ino new file mode 100644 index 0000000000..e6d71cfa8d --- /dev/null +++ b/plugins/KeyboardioHID/examples/Advanced/AdvancedKeyboard/AdvancedKeyboard.ino @@ -0,0 +1,98 @@ +/* + Copyright (c) 2014 NicoHood + See the readme for credit to other people. + + Advanced Keyboard example + + This demo is actually made for advanced users to show them how they can write an own report. + This might be useful for a Keyboard if you only use one key, + because the library has a lot of code for simple use + */ + +const int pinLed = LED_BUILTIN; +const int pinButton = 2; + +void setup() { + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); + + // Sends a clean report to the host. This is important on any Arduino type. + // Make sure all desired USB functions are activated in USBAPI.h! + pressRawKeyboard(0, 0); +} + +void loop() { + if (!digitalRead(pinButton)) { + digitalWrite(pinLed, HIGH); + + // press normal keys (a-z, A-Z, 0-9) + pressRawKeyboard(0, RAW_KEYBOARD_KEY('a')); //modifiers + a + pressRawKeyboard(0, RAW_KEYBOARD_KEY('Z')); //modifiers + Z + + // press STRG + ALT + DEL on keyboard (see usb documentation for more) + //pressRawKeyboard(RAW_KEYBOARD_LEFT_CTRL | RAW_KEYBOARD_LEFT_ALT , RAW_KEYBOARD_DELETE); //modifiers + key + + // release! Important + pressRawKeyboard(0, 0); + + // simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } +} + +void pressRawKeyboard(uint8_t modifiers, uint8_t key) { + uint8_t keys[8] = { + modifiers, 0, key, 0, 0, 0, 0, 0 + }; //modifiers, reserved, key[0] + HID_SendReport(HID_REPORTID_KeyboardReport, keys, sizeof(keys)); +} + +/* +See Hut1_12v2.pdf Chapter 10 (Page 53) for more Keys + (especially a-z, a=0x04 z=29) + Definitions: + + RAW_KEYBOARD_LEFT_CTRL + RAW_KEYBOARD_LEFT_SHIFT + RAW_KEYBOARD_LEFT_ALT + RAW_KEYBOARD_LEFT_GUI + RAW_KEYBOARD_RIGHT_CTRL + RAW_KEYBOARD_RIGHT_SHIFT + RAW_KEYBOARD_RIGHT_ALT + RAW_KEYBOARD_RIGHT_GUI + + RAW_KEYBOARD_KEY(key) + + RAW_KEYBOARD_UP_ARROW + RAW_KEYBOARD_DOWN_ARROW + RAW_KEYBOARD_LEFT_ARROW + RAW_KEYBOARD_RIGHT_ARROW + RAW_KEYBOARD_SPACEBAR + RAW_KEYBOARD_BACKSPACE + RAW_KEYBOARD_TAB + RAW_KEYBOARD_RETURN + RAW_KEYBOARD_ESC + RAW_KEYBOARD_INSERT + RAW_KEYBOARD_DELETE + RAW_KEYBOARD_PAGE_UP + RAW_KEYBOARD_PAGE_DOWN + RAW_KEYBOARD_HOME + RAW_KEYBOARD_END + RAW_KEYBOARD_CAPS_LOCK + RAW_KEYBOARD_F1 + RAW_KEYBOARD_F2 + RAW_KEYBOARD_F3 + RAW_KEYBOARD_F4 + RAW_KEYBOARD_F5 + RAW_KEYBOARD_F6 + RAW_KEYBOARD_F7 + RAW_KEYBOARD_F8 + RAW_KEYBOARD_F9 + RAW_KEYBOARD_F10 + RAW_KEYBOARD_F11 + RAW_KEYBOARD_F12 + RAW_KEYBOARD_PRINT + RAW_KEYBOARD_SCROLL_LOCK + RAW_KEYBOARD_PAUSE + */ \ No newline at end of file diff --git a/plugins/KeyboardioHID/examples/Advanced/AdvancedRawHID/AdvancedRawHID.ino b/plugins/KeyboardioHID/examples/Advanced/AdvancedRawHID/AdvancedRawHID.ino new file mode 100644 index 0000000000..202e3b28ee --- /dev/null +++ b/plugins/KeyboardioHID/examples/Advanced/AdvancedRawHID/AdvancedRawHID.ino @@ -0,0 +1,109 @@ +/* + Copyright (c) 2014 NicoHood + See the readme for credit to other people. + + Advanced RawHID example + + Shows how to send bytes via raw HID + Press a button to send some example values. + Keep in mind that you can only send full data packets, the rest is filled with zero! + + Definitions from HID_Reports.h: + RAWHID_USAGE_PAGE 0xFFC0 // recommended: 0xFF00 to 0xFFFF + RAWHID_USAGE 0x0C00 // recommended: 0x0100 to 0xFFFF + RAWHID_TX_SIZE 15 // 1 byte for report ID + RAWHID_RX_SIZE 15 // 1 byte for report ID + */ + +const int pinLed = LED_BUILTIN; +const int pinButton = 2; + +void setup() { + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); + + // no begin function needed for RawHID + // Make sure all desired USB functions are activated in USBAPI.h! +} + +void loop() { + if (!digitalRead(pinButton)) { + digitalWrite(pinLed, HIGH); + + // direct without library. Always send RAWHID_RX_SIZE bytes! + uint8_t buff[RAWHID_RX_SIZE]; // unitialized, has random values + HID_SendReport(HID_REPORTID_RawKeyboardReport, buff, sizeof(buff)); + + // with library + memset(&buff, 42, sizeof(buff)); + RawHID.write(buff, sizeof(buff)); + + // write a single byte, will fill the rest with zeros + RawHID.write(0xCD); + + // huge buffer with library, will fill the rest with zeros + uint8_t megabuff[64]; + for (int i = 0; i < sizeof(megabuff); i++) + megabuff[i] = i; + RawHID.write(megabuff, sizeof(megabuff)); + + // You can use print too, but better dont use a linefeed + RawHID.println("Hello World"); + + // And compare it to write: + RawHID.write("Hello World\r\n"); + + // simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } +} + +/* +Expected output: + +// manual with unintialized buff +recv 15 bytes: +01 55 C1 FF 01 01 01 00 00 01 00 00 01 00 20 + +// filled buff +recv 15 bytes: +2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A + +// single byte filled with zero +recv 15 bytes: +CD 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +// huge buffer filled with zero at the end +recv 15 bytes: +00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E + +recv 15 bytes: +0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D + +recv 15 bytes: +1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C + +recv 15 bytes: +2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B + +recv 15 bytes: +3C 3D 3E 3F 00 00 00 00 00 00 00 00 00 00 00 + +// print +recv 15 bytes: +48 65 6C 6C 6F 20 57 6F 72 6C 64 00 00 00 00 + +//\r +recv 15 bytes: +0D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +//\n +recv 15 bytes: +0A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +//write +recv 15 bytes: +48 65 6C 6C 6F 20 57 6F 72 6C 64 0D 0A 00 00 + +*/ \ No newline at end of file diff --git a/plugins/KeyboardioHID/examples/HoodLoader1/HoodLoader1_API_Legacy/HoodLoader1_API_Legacy.ino b/plugins/KeyboardioHID/examples/HoodLoader1/HoodLoader1_API_Legacy/HoodLoader1_API_Legacy.ino new file mode 100644 index 0000000000..546a413e1e --- /dev/null +++ b/plugins/KeyboardioHID/examples/HoodLoader1/HoodLoader1_API_Legacy/HoodLoader1_API_Legacy.ino @@ -0,0 +1,163 @@ +/* + Copyright (c) 2014 NicoHood + See the readme for credit to other people. + + Keyboard HoodLoader1 API Legacy example + + Legacy Example on how to access the Serial HID API of HoodLoader1. + This methode is outdated, because you can now control the whole + 16u2 with HoodLoader2. It might be still usefull if you want the 328/2560 + keep control of the USB functions. Keep in mind that there is no such thing + as flushing HID reports. If the USB Host is too slow HID reports might be missed. + + You can also adapt the sending method below to send Mouse/Keyboard/Media/System reports. + Gamepads/RawHID have a general problem with the original HoodLoader1 firmware, so please avoid this. + It might be compatible with the new HoodLoader2 port of the protocol later on. + + HID reports are converted into a special Serial Protocol with NHP. + This sketch should only be used with a 328/2560, not a 16u2. + The 16u2 has a HoodLoader1 compatible sketch/firmware loaded and will + listen to the Serial Port for these Protocol packets on baud 115200. + + The HID_SendReport function is implemented weak, so we can overwrite it + in this sketch below. A simple NHP implementation encapsulated the HID reports + into NHP packets with correct addresses and checksums. + + Press a button to write some text to your pc. + See official documentation for more infos + */ + +// Serial to write Protocol data to. Default: Serial +#define HID_SERIAL Serial +#define SERIAL_HID_BAUD 115200 + +// extra delay for raspberry. Only needed for Hoodloader and slow devices +//#define HID_EXTRADELAY 20 + +const int pinLed = 13; +const int pinButton = 8; + +void setup() { + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); + + // Starts Serial at baud 115200 otherwise HID wont work with HoodLoader1. + // This is not needed for Leonado/(Pro)Micro/16u2(HoodLoader2) + Serial.begin(SERIAL_HID_BAUD); + + // Sends a clean report to the host. This is important on any Arduino type. + // Make sure all desired USB functions are activated in USBAPI.h! + Keyboard.begin(); +} + + +void loop() { + if (!digitalRead(pinButton)) { + digitalWrite(pinLed, HIGH); + + // Same use as the official library, pretty much self explaining + Keyboard.println("This message was sent with my Arduino."); + Serial.println("Serial port is still working and not glitching out"); + + // simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } +} + +//================================================================================ +// HoodLoader1 compatible NHP sending API +//================================================================================ + +// Start Mask +#define NHP_MASK_START 0xC0 //B11|000000 the two MSB bits +#define NHP_MASK_LEAD 0xC0 //B11|000000 +#define NHP_MASK_DATA 0x00 //B0|0000000 only the first MSB is important +#define NHP_MASK_END 0x80 //B10|000000 + +// Content Mask +#define NHP_MASK_LENGTH 0x38 //B00|111|000 +#define NHP_MASK_COMMAND 0x0F //B0000|1111 +#define NHP_MASK_DATA_7BIT 0x7F //B0|1111111 +#define NHP_MASK_DATA_4BIT 0x0F //B0000|1111 +#define NHP_MASK_DATA_3BIT 0x07 //B00000|111 +#define NHP_MASK_ADDRESS 0x3F //B00|111111 + +// Reserved Addresses +#define NHP_ADDRESS_CONTROL 0x01 + +// Reserved Usages +#define NHP_USAGE_ARDUINOHID 0x01 + +// overwrites the HID_SendReport function which is empty/not used on a 328/2560 +void HID_SendReport(uint8_t id, const void* data, int len) +{ + // write the Report via Protocol and checksum. 16bit for each sending + // send control address + NHPwriteChecksum(NHP_ADDRESS_CONTROL, (NHP_USAGE_ARDUINOHID << 8) | id); + const uint8_t* report = (const uint8_t*)data; + for (int i = 0; i < len; i++) { + uint8_t data0 = report[i++]; + uint8_t data1 = 0; + if (i != len) + data1 = report[i]; + // valid HID reports start at Address 2 + NHPwriteChecksum(2 + i / 2, (data1 << 8) | data0); + } +#ifdef HID_EXTRADELAY + delay(HID_EXTRADELAY); +#endif +} + +// simple copy/modification of the NicoHoodProtocol writechecksum function +void NHPwriteChecksum(uint8_t address, uint16_t indata) { + // writes two bytes with its inverse + uint32_t temp = ~indata; + uint32_t data = (temp << 16) | indata; + + // buffer for write operation + uint8_t writebuffer[6]; + + // start with the maximum size of blocks + uint8_t blocks = 7; + + // check for the first 7 bit block that doesnt fit into the first 3 bits + while (blocks > 2) { + uint8_t nextvalue = (data >> (7 * (blocks - 3))); + + if (nextvalue > NHP_MASK_DATA_3BIT) { + // special case for the MSB + if (blocks == 7) { + writebuffer[0] = nextvalue; + blocks--; + } + // this block is too big, write this into the next data block + break; + } + else { + // write the possible first 3 bits and check again after if zero + writebuffer[0] = nextvalue; + blocks--; + // we have our first bits, stop (nonzero) + if (nextvalue) + break; + } + } + + // write the rest of the data bits + uint8_t datablocks = blocks - 2; + while (datablocks > 0) { + writebuffer[datablocks] = data & NHP_MASK_DATA_7BIT; + data >>= 7; + datablocks--; + } + + // write lead + length mask + writebuffer[0] |= NHP_MASK_LEAD | (blocks << 3); + + // write end mask + writebuffer[blocks - 1] = NHP_MASK_END | ((address - 1) & NHP_MASK_ADDRESS); + + // write the buffer + HID_SERIAL.write(writebuffer, blocks); +} diff --git a/plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_PWM_Fade/HoodLoader2_PWM_Fade.ino b/plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_PWM_Fade/HoodLoader2_PWM_Fade.ino new file mode 100644 index 0000000000..0ba22c889f --- /dev/null +++ b/plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_PWM_Fade/HoodLoader2_PWM_Fade.ino @@ -0,0 +1,39 @@ +/* + Copyright (c) 2014 NicoHood + See the readme for credit to other people. + + PWM Fade + + This example shows how to fade an LED on pin 7 + using the analogWrite() function. + + Basically it is a demonstartion that PWM on pin 7 works fine. + You can also deactivate the USB Core for this example, but then you'd + need the workaround. See the other example for this. +*/ + +int led = 7; // the pin that the LED is attached to +int brightness = 0; // how bright the LED is +int fadeAmount = 5; // how many points to fade the LED by + +// the setup routine runs once when you press reset: +void setup() { + // declare pin 9 to be an output: + pinMode(led, OUTPUT); +} + +// the loop routine runs over and over again forever: +void loop() { + // set the brightness of pin 9: + analogWrite(led, 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 == 255) { + fadeAmount = -fadeAmount ; + } + // wait for 30 milliseconds to see the dimming effect + delay(30); +} diff --git a/plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_SerialKeyboard/HoodLoader2_SerialKeyboard.ino b/plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_SerialKeyboard/HoodLoader2_SerialKeyboard.ino new file mode 100644 index 0000000000..5aef44609e --- /dev/null +++ b/plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_SerialKeyboard/HoodLoader2_SerialKeyboard.ino @@ -0,0 +1,54 @@ +/* + Copyright (c) 2014 NicoHood + See the readme for credit to other people. + + HoodLoader2 SerialKeyboard example + + This sketch should demonstrate how to program a basic sketch with HoodLoader2. + It was used to demonstrate that Serial and HID is working properly. + The the other examples on how to use the other APIs, it works the same. + + Use the F() macro to save strings in PROGMEM to keep ram usage low. + The 16u2 has very low RAM, so don't try to use that much ram. + + Open the Serial port, type in anything and see that Serial and Keyboard is working. + See official documentation for more infos. + */ + +void setup() { + // start + wait for serial debug in/output + while (!Serial); + Serial.begin(115200); + Serial.println(F("Startup")); + + // Sends a clean report to the host. This is important because + // the 16u2 of the Uno/Mega is not turned off while programming + // so you want to start with a clean report to avoid strange bugs after reset. + Keyboard.begin(); +} + + +void loop() { + if (Serial.available()) { + // discard all Serial bytes to avoid multiple sendings + unsigned long currentMillis = millis(); + while (millis() - currentMillis < 100) { + if (Serial.available()) + Serial.write(Serial.read()); + } + + // print an information back to the serial port + Serial.println(); + Serial.println(F("Serial port working. Printing Text in 3 seconds.")); + + // wait 3 seconds and discard all new in bytes to not crash the Arduino + currentMillis = millis(); + while (millis() - currentMillis < 3000) { + if (Serial.available()) + Serial.write(Serial.read()); + } + + // same use as the official library, pretty much self explaining + Keyboard.print(F("This message was sent with my Arduino.")); + } +} \ No newline at end of file diff --git a/plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_USB-Serial/HoodLoader2_USB-Serial.ino b/plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_USB-Serial/HoodLoader2_USB-Serial.ino new file mode 100644 index 0000000000..1dce7ff33c --- /dev/null +++ b/plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_USB-Serial/HoodLoader2_USB-Serial.ino @@ -0,0 +1,51 @@ +/* + Copyright (c) 2014 NicoHood + See the readme for credit to other people. + + HoodLoader2 USB-Serial + + Transferes from USB to HW Serial and vice versa. + It also resets the main MCU on a DTR rise. + */ + +void setup() { + // set main MCU by default active + pinMode(MAIN_MCU_RESET_PIN, OUTPUT); + digitalWrite(MAIN_MCU_RESET_PIN, HIGH); + + // Start USB and HW Serial + Serial.begin(115200); + Serial1.begin(115200); +} + +void loop() { + // USB -> Serial + for (int i = 0; i < USB_EP_SIZE; i++) { + // read maximum one EP_SIZE to not block + if (Serial.available()) + Serial1.write(Serial.read()); + else break; + } + + // Serial -> USB + if (Serial1.available()) { + Serial.flush(); + // send maximum one EP_SIZE to give the usb some time to flush the buffer + uint8_t buff[USB_EP_SIZE-1]; + int i = 0; + for (i = 0; i < USB_EP_SIZE-1; i++) { + if (Serial1.available()) + buff[i] = Serial1.read(); + else break; + } + Serial.write(buff, i); + } + + // reset the main mcu if DTR goes HIGH + static bool lastDTR = 0; + bool newDTR = (Serial.lineState()&CDC_CONTROL_LINE_OUT_DTR) ? 1 : 0; + if (lastDTR ^ newDTR) + digitalWrite(MAIN_MCU_RESET_PIN, lastDTR); + lastDTR = newDTR; +} + diff --git a/plugins/KeyboardioHID/examples/Projects/Gamepad_Project/Gamepad_Project.ino b/plugins/KeyboardioHID/examples/Projects/Gamepad_Project/Gamepad_Project.ino new file mode 100644 index 0000000000..e3418d73ba --- /dev/null +++ b/plugins/KeyboardioHID/examples/Projects/Gamepad_Project/Gamepad_Project.ino @@ -0,0 +1,113 @@ +/* + Copyright (c) 2014 NicoHood + See the readme for credit to other people. + + Gamepad example project + + Press physical buttons to press USB Gamepad buttons. + This can be used for a simple SNES Controller. + + Make sure the Gamepad report is set in: + sketchbook/hardware/HID/avr/variants/hid_descriptors/hid_descriptors.h +*/ + +// pin mappings +const int pinButton1 = 2; +const int pinButton2 = 3; +const int pinButton3 = 4; +const int pinButton4 = 5; +const int pinButton5 = 6; +const int pinButton6 = 7; +const int pinButton7 = 8; +const int pinButton8 = 9; +const int pinButton9 = 10; +const int pinButton10 = 18; +const int pinButton11 = 19; +const int pinButton12 = 20; + +void setup() { + // pinsetup + pinMode(pinButton1, INPUT_PULLUP); + pinMode(pinButton2, INPUT_PULLUP); + pinMode(pinButton3, INPUT_PULLUP); + pinMode(pinButton4, INPUT_PULLUP); + pinMode(pinButton5, INPUT_PULLUP); + pinMode(pinButton6, INPUT_PULLUP); + pinMode(pinButton7, INPUT_PULLUP); + pinMode(pinButton8, INPUT_PULLUP); + pinMode(pinButton9, INPUT_PULLUP); + pinMode(pinButton10, INPUT_PULLUP); + pinMode(pinButton11, INPUT_PULLUP); + pinMode(pinButton12, INPUT_PULLUP); + + // Sends a clean report to the host. This is important on any Arduino type. + // Make sure all desired USB functions are activated in USBAPI.h! + Gamepad.begin(); +} + +void loop() { + // check each button and press Gamepad if needed + if (!digitalRead(pinButton1)) + Gamepad.press(1); + else + Gamepad.release(1); + + if (!digitalRead(pinButton2)) + Gamepad.press(2); + else + Gamepad.release(2); + + if (!digitalRead(pinButton3)) + Gamepad.press(3); + else + Gamepad.release(3); + + if (!digitalRead(pinButton4)) + Gamepad.press(4); + else + Gamepad.release(4); + + if (!digitalRead(pinButton5)) + Gamepad.press(5); + else + Gamepad.release(5); + + if (!digitalRead(pinButton6)) + Gamepad.press(6); + else + Gamepad.release(6); + + if (!digitalRead(pinButton7)) + Gamepad.press(7); + else + Gamepad.release(7); + + if (!digitalRead(pinButton8)) + Gamepad.press(8); + else + Gamepad.release(8); + + if (!digitalRead(pinButton9)) + Gamepad.press(9); + else + Gamepad.release(9); + + if (!digitalRead(pinButton10)) + Gamepad.press(10); + else + Gamepad.release(10); + + if (!digitalRead(pinButton11)) + Gamepad.press(11); + else + Gamepad.release(11); + + if (!digitalRead(pinButton12)) + Gamepad.press(12); + else + Gamepad.release(12); + + // write the information to the host now! + Gamepad.write(); +} + diff --git a/plugins/KeyboardioHID/examples/Readme.md b/plugins/KeyboardioHID/examples/Readme.md new file mode 100644 index 0000000000..30a01d3b39 --- /dev/null +++ b/plugins/KeyboardioHID/examples/Readme.md @@ -0,0 +1,4 @@ +Examples +======== + +Just try these examples once the HID Source is installed. Its pretty much self explaining. \ No newline at end of file diff --git a/plugins/KeyboardioHID/examples/hidtests2/hidtests2.ino b/plugins/KeyboardioHID/examples/hidtests2/hidtests2.ino deleted file mode 100644 index 9f2af89bb6..0000000000 --- a/plugins/KeyboardioHID/examples/hidtests2/hidtests2.ino +++ /dev/null @@ -1,169 +0,0 @@ -void setup() { - // put your setup code here, to run once: - pinMode(7, INPUT_PULLUP); - pinMode(8, INPUT_PULLUP); - pinMode(9, INPUT_PULLUP); - pinMode(10, INPUT_PULLUP); - pinMode(2, INPUT_PULLUP); - pinMode(3, INPUT_PULLUP); - - // 7052 279 - Keyboard.begin(); - Gamepad.begin(); - hid_keyboard_leds = 0; //test to access it from here -} - -uint32_t eventBaud = 0; - -void loop() { - - if (!digitalRead(7)) { - digitalWrite(13, 1); - Mouse.moveTo(1000, 1000); - delay(300); - digitalWrite(13, 0); - } - - if (!digitalRead(8)) { - digitalWrite(13, 1); - Mouse.move(100, 0); - delay(300); - digitalWrite(13, 0); - } - - if (!digitalRead(9)) { - digitalWrite(13, 1); - Mouse.move(-100, 0); - delay(300); - digitalWrite(13, 0); - } - - if (!digitalRead(10)) { - uint8_t k[8] = {0}; - k[1] = 1; - - k[2] = 4; - k[3] = 5; - HID_SendReport(HID_REPORTID_KEYBOARD, &k, sizeof(k)); - Keyboard.releaseAll(); - delay(300); - } - if (!digitalRead(2)) { - digitalWrite(13, 1); - System.write(SYSTEM_SLEEP); - delay(300); - digitalWrite(13, 0); - } - if (!digitalRead(3)) { - digitalWrite(13, 1); - USBDevice.wakeupHost(); - delay(300); - digitalWrite(13, 0); - } - - if (Serial.available()) { - // let the Serial receive all bytes and discard the first bytes - // this is to ensure you only input a single char and no string - char c; - delay(300); - int length = Serial.available(); - while (Serial.available()) - c = Serial.read(); - if (length > 1) { - Serial.println("Please only input a single character or deactivate linefeed!"); - return; - } - - if (c != -1) { - Serial.println(c); - switch (c) { - case 'a': - Keyboard.write('b'); - break; - - case 'p': - Consumer.write(MEDIA_PLAY_PAUSE); - break; - - case 'o': - { - // uint8_t k[8] = {0}; - // k[1] = 1 << 4; - // //k[2] = 4; - // HID_SendReport(HID_REPORTID_KEYBOARD, &k, sizeof(k)); - // Keyboard.releaseAll(); - break; - } - - case 's': - System.write(SYSTEM_SLEEP); - break; - - case 'r': - Mouse.move(100, 0); - break; - - case 'l': - Mouse.move(-100, 0); - break; - - case 't': - Mouse.moveTo(1000, 1000); - break; - - case 'c': - case 'C': - Keyboard.write(KEY_CAPS_LOCK); - Serial.println("Leds"); - Serial.println(Keyboard.getLEDs(), BIN); - break; - - case 'k': - Keyboard.print("Testing USB functions xyz"); - break; - - case '\r': - case '\n': - Serial.println("Please only input a single character!"); - break; - - case 'g': { - // press button 1-32 and reset (34 becaue its written later) - static uint8_t count = 1; - Gamepad.press(count++); - if (count == 34) { - Gamepad.releaseAll(); - count = 1; - } - Gamepad.write(); - } - break; - - case 'd': - Serial.println("Serial"); - Serial.println(Serial.dtr()); - Serial.println(Serial.rts()); - Serial.println(Serial.baud()); - Serial.println(Serial.stopbits()); - Serial.println(Serial.paritytype()); - Serial.println(Serial.numbits()); - break; - - default: - Serial.println("unknown"); - } - } - } - - - if (eventBaud) { - Serial.println("Event"); - Serial.println(eventBaud); - eventBaud = 0; - } -} - -void CDC_LineEncodingEvent(void) -{ - eventBaud = Serial.baud(); -} From ab8e006cd9282e34ea0b548b6854243137afe940 Mon Sep 17 00:00:00 2001 From: Nico Date: Fri, 2 Jan 2015 16:59:05 +0100 Subject: [PATCH 090/602] HID Report fix --- .../avr/cores/hid/USB-Core/HID.h | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h index 85d21de886..b6820a8b5d 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h @@ -25,18 +25,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // for the extern HID descriptors #include "pins_Arduino.h" -// default HID report descriptor -#ifdef HID_KEYBOARD_LEDS_ENABLED -#define DEFAULT_HID_REPORT \ -HID_REPORT_KEYBOARD_LEDS(HID_REPORTID_KEYBOARD), \ -HID_REPORT_MOUSE(HID_REPORTID_MOUSE) - -#else -#define DEFAULT_HID_REPORT \ -HID_REPORT_KEYBOARD_KEYS(HID_REPORTID_KEYBOARD), \ -HID_REPORT_MOUSE(HID_REPORTID_MOUSE) -#endif - // extern accessible led out report #if defined(HID_KEYBOARD_LEDS_ENABLED) extern uint8_t hid_keyboard_leds; @@ -192,7 +180,6 @@ extern uint8_t hid_keyboard_leds; 0x75, 0x08, /* REPORT_SIZE (8) */ \ 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ \ \ - HID_REPORT_KEYBOARD_LEDS \ /* 6 Keyboard keys */ \ 0x95, 0x06, /* REPORT_COUNT (6) */ \ 0x75, 0x08, /* REPORT_SIZE (8) */ \ @@ -321,6 +308,18 @@ extern uint8_t hid_keyboard_leds; 0xC0 /* end collection */ #endif +// default HID report descriptor +#ifdef HID_KEYBOARD_LEDS_ENABLED +#define DEFAULT_HID_REPORT \ +HID_REPORT_KEYBOARD_LEDS(HID_REPORTID_KEYBOARD), \ +HID_REPORT_MOUSE(HID_REPORTID_MOUSE) + +#else +#define DEFAULT_HID_REPORT \ +HID_REPORT_KEYBOARD_KEYS(HID_REPORTID_KEYBOARD), \ +HID_REPORT_MOUSE(HID_REPORTID_MOUSE) +#endif + #if defined(USBCON) #include "USBDesc.h" From d6ffca653587be83cf1d941b0c24bfd7d4b3f9a8 Mon Sep 17 00:00:00 2001 From: Nico Date: Fri, 2 Jan 2015 16:59:24 +0100 Subject: [PATCH 091/602] USB-Serial Update --- plugins/KeyboardioHID/Readme.md | 1 + .../USB-Serial/USB-Serial.ino} | 34 +++++++++++++------ 2 files changed, 24 insertions(+), 11 deletions(-) rename plugins/KeyboardioHID/examples/{HoodLoader2/HoodLoader2_USB-Serial/HoodLoader2_USB-Serial.ino => Projects/USB-Serial/USB-Serial.ino} (57%) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 304c28f132..8bc3fbaf85 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -69,6 +69,7 @@ Your Arduino IDE will output errors then if you double click the file and try to * Added USB Wakeup support * Separated USB-Core in its own folder * Added HID Tables +* USB-Serial now fully reprogrammable ``` ``` diff --git a/plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_USB-Serial/HoodLoader2_USB-Serial.ino b/plugins/KeyboardioHID/examples/Projects/USB-Serial/USB-Serial.ino similarity index 57% rename from plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_USB-Serial/HoodLoader2_USB-Serial.ino rename to plugins/KeyboardioHID/examples/Projects/USB-Serial/USB-Serial.ino index 1dce7ff33c..5c8dbacd64 100644 --- a/plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_USB-Serial/HoodLoader2_USB-Serial.ino +++ b/plugins/KeyboardioHID/examples/Projects/USB-Serial/USB-Serial.ino @@ -2,16 +2,21 @@ Copyright (c) 2014 NicoHood See the readme for credit to other people. - HoodLoader2 USB-Serial + USB-Serial Transferes from USB to HW Serial and vice versa. It also resets the main MCU on a DTR rise. */ +// define the reset pin to reset the destination MCU. +// this definition is made for HoodLoader2 (pin 20) +// but you still can use it with any other USB MCU or pin +const int resetPin = MAIN_MCU_RESET_PIN; + void setup() { // set main MCU by default active - pinMode(MAIN_MCU_RESET_PIN, OUTPUT); - digitalWrite(MAIN_MCU_RESET_PIN, HIGH); + pinMode(resetPin, OUTPUT); + digitalWrite(resetPin, HIGH); // Start USB and HW Serial Serial.begin(115200); @@ -31,21 +36,28 @@ void loop() { if (Serial1.available()) { Serial.flush(); // send maximum one EP_SIZE to give the usb some time to flush the buffer - uint8_t buff[USB_EP_SIZE-1]; + uint8_t buff[USB_EP_SIZE - 1]; int i = 0; - for (i = 0; i < USB_EP_SIZE-1; i++) { + for (i = 0; i < USB_EP_SIZE - 1; i++) { if (Serial1.available()) buff[i] = Serial1.read(); else break; } Serial.write(buff, i); } +} - // reset the main mcu if DTR goes HIGH - static bool lastDTR = 0; - bool newDTR = (Serial.lineState()&CDC_CONTROL_LINE_OUT_DTR) ? 1 : 0; - if (lastDTR ^ newDTR) - digitalWrite(MAIN_MCU_RESET_PIN, lastDTR); - lastDTR = newDTR; +void CDC_LineEncodingEvent(void) +{ + // start HW Serial with new baud rate + Serial1.end(); + Serial1.begin(Serial.baud()); } +void CDC_LineStateEvent(void) { + // reset the main mcu if DTR goes HIGH + if (Serial.dtr()) + digitalWrite(resetPin, LOW); + else + digitalWrite(resetPin, HIGH); +} From 464d6621cf7deab0a94a373ef911e80aade7f1eb Mon Sep 17 00:00:00 2001 From: Nico Date: Fri, 2 Jan 2015 16:59:33 +0100 Subject: [PATCH 092/602] Example fixes --- .../AdvancedGamepad/AdvancedGamepad.ino | 11 +- .../AdvancedKeyboard/AdvancedKeyboard.ino | 3 +- .../AdvancedRawHID/AdvancedRawHID.ino | 5 +- .../HID_Basic/HID_Consumer/HID_Consumer.ino | 48 +++++ .../HID_Basic/HID_Gamepad/HID_Gamepad.ino | 86 +++++++++ .../HID_Basic/HID_Keyboard/HID_Keyboard.ino | 86 +++++++++ .../HID_Basic/HID_Mouse/HID_Mouse.ino | 72 ++++++++ .../HID_Basic/HID_System/HID_System.ino | 51 ++++++ .../Gamepad_Project/Gamepad_Project.ino | 1 - .../examples/Projects/HID_Test/HID_Test.ino | 169 ++++++++++++++++++ .../HoodLoader1_API_Legacy.ino | 0 .../HoodLoader2_PWM_Fade.ino | 0 .../HoodLoader2_SerialKeyboard.ino | 0 13 files changed, 520 insertions(+), 12 deletions(-) rename plugins/KeyboardioHID/examples/{Advanced => HID_Advanced}/AdvancedGamepad/AdvancedGamepad.ino (80%) rename plugins/KeyboardioHID/examples/{Advanced => HID_Advanced}/AdvancedKeyboard/AdvancedKeyboard.ino (94%) rename plugins/KeyboardioHID/examples/{Advanced => HID_Advanced}/AdvancedRawHID/AdvancedRawHID.ino (93%) create mode 100644 plugins/KeyboardioHID/examples/HID_Basic/HID_Consumer/HID_Consumer.ino create mode 100644 plugins/KeyboardioHID/examples/HID_Basic/HID_Gamepad/HID_Gamepad.ino create mode 100644 plugins/KeyboardioHID/examples/HID_Basic/HID_Keyboard/HID_Keyboard.ino create mode 100644 plugins/KeyboardioHID/examples/HID_Basic/HID_Mouse/HID_Mouse.ino create mode 100644 plugins/KeyboardioHID/examples/HID_Basic/HID_System/HID_System.ino create mode 100644 plugins/KeyboardioHID/examples/Projects/HID_Test/HID_Test.ino rename plugins/KeyboardioHID/examples/{HoodLoader1 => Projects}/HoodLoader1_API_Legacy/HoodLoader1_API_Legacy.ino (100%) rename plugins/KeyboardioHID/examples/{HoodLoader2 => Projects}/HoodLoader2_PWM_Fade/HoodLoader2_PWM_Fade.ino (100%) rename plugins/KeyboardioHID/examples/{HoodLoader2 => Projects}/HoodLoader2_SerialKeyboard/HoodLoader2_SerialKeyboard.ino (100%) diff --git a/plugins/KeyboardioHID/examples/Advanced/AdvancedGamepad/AdvancedGamepad.ino b/plugins/KeyboardioHID/examples/HID_Advanced/AdvancedGamepad/AdvancedGamepad.ino similarity index 80% rename from plugins/KeyboardioHID/examples/Advanced/AdvancedGamepad/AdvancedGamepad.ino rename to plugins/KeyboardioHID/examples/HID_Advanced/AdvancedGamepad/AdvancedGamepad.ino index eef660d9df..04cee3e5f5 100644 --- a/plugins/KeyboardioHID/examples/Advanced/AdvancedGamepad/AdvancedGamepad.ino +++ b/plugins/KeyboardioHID/examples/HID_Advanced/AdvancedGamepad/AdvancedGamepad.ino @@ -3,11 +3,11 @@ See the readme for credit to other people. Advanced Gamepad example + + Make sure the Gamepad report is set in: + sketchbook/hardware/HID/avr/variants/hid_descriptors/hid_descriptors.h */ -// include HID library -#include - // see HID_Reports.h for all data structures HID_GamepadReport_Data_t Gamepadreport; @@ -22,9 +22,8 @@ void setup() { pinMode(pinButton, INPUT_PULLUP); // Sends a clean report to the host. This is important on any Arduino type. - // Make sure all desired USB functions are activated in USBAPI.h! memset(&Gamepadreport, 0, sizeof(Gamepadreport)); - HID_SendReport(HID_REPORTID_Gamepad1Report, &Gamepadreport, sizeof(Gamepadreport)); + HID_SendReport(HID_REPORTID_GAMEPAD, &Gamepadreport, sizeof(Gamepadreport)); } void loop() { @@ -43,7 +42,7 @@ void loop() { // functions before only set the values // this writes the report to the host - HID_SendReport(HID_REPORTID_Gamepad1Report, &Gamepadreport, sizeof(Gamepadreport)); + HID_SendReport(HID_REPORTID_GAMEPAD, &Gamepadreport, sizeof(Gamepadreport)); // simple debounce delay(300); diff --git a/plugins/KeyboardioHID/examples/Advanced/AdvancedKeyboard/AdvancedKeyboard.ino b/plugins/KeyboardioHID/examples/HID_Advanced/AdvancedKeyboard/AdvancedKeyboard.ino similarity index 94% rename from plugins/KeyboardioHID/examples/Advanced/AdvancedKeyboard/AdvancedKeyboard.ino rename to plugins/KeyboardioHID/examples/HID_Advanced/AdvancedKeyboard/AdvancedKeyboard.ino index e6d71cfa8d..8e8d5bb47f 100644 --- a/plugins/KeyboardioHID/examples/Advanced/AdvancedKeyboard/AdvancedKeyboard.ino +++ b/plugins/KeyboardioHID/examples/HID_Advanced/AdvancedKeyboard/AdvancedKeyboard.ino @@ -17,7 +17,6 @@ void setup() { pinMode(pinButton, INPUT_PULLUP); // Sends a clean report to the host. This is important on any Arduino type. - // Make sure all desired USB functions are activated in USBAPI.h! pressRawKeyboard(0, 0); } @@ -45,7 +44,7 @@ void pressRawKeyboard(uint8_t modifiers, uint8_t key) { uint8_t keys[8] = { modifiers, 0, key, 0, 0, 0, 0, 0 }; //modifiers, reserved, key[0] - HID_SendReport(HID_REPORTID_KeyboardReport, keys, sizeof(keys)); + HID_SendReport(HID_REPORTID_KEYBOARD, keys, sizeof(keys)); } /* diff --git a/plugins/KeyboardioHID/examples/Advanced/AdvancedRawHID/AdvancedRawHID.ino b/plugins/KeyboardioHID/examples/HID_Advanced/AdvancedRawHID/AdvancedRawHID.ino similarity index 93% rename from plugins/KeyboardioHID/examples/Advanced/AdvancedRawHID/AdvancedRawHID.ino rename to plugins/KeyboardioHID/examples/HID_Advanced/AdvancedRawHID/AdvancedRawHID.ino index 202e3b28ee..ffadce7a26 100644 --- a/plugins/KeyboardioHID/examples/Advanced/AdvancedRawHID/AdvancedRawHID.ino +++ b/plugins/KeyboardioHID/examples/HID_Advanced/AdvancedRawHID/AdvancedRawHID.ino @@ -2,7 +2,7 @@ Copyright (c) 2014 NicoHood See the readme for credit to other people. - Advanced RawHID example + Advanced RawHID example (currently not available) Shows how to send bytes via raw HID Press a button to send some example values. @@ -23,7 +23,6 @@ void setup() { pinMode(pinButton, INPUT_PULLUP); // no begin function needed for RawHID - // Make sure all desired USB functions are activated in USBAPI.h! } void loop() { @@ -32,7 +31,7 @@ void loop() { // direct without library. Always send RAWHID_RX_SIZE bytes! uint8_t buff[RAWHID_RX_SIZE]; // unitialized, has random values - HID_SendReport(HID_REPORTID_RawKeyboardReport, buff, sizeof(buff)); + HID_SendReport(HID_REPORTID_RAWHID, buff, sizeof(buff)); // with library memset(&buff, 42, sizeof(buff)); diff --git a/plugins/KeyboardioHID/examples/HID_Basic/HID_Consumer/HID_Consumer.ino b/plugins/KeyboardioHID/examples/HID_Basic/HID_Consumer/HID_Consumer.ino new file mode 100644 index 0000000000..186f6e1ef9 --- /dev/null +++ b/plugins/KeyboardioHID/examples/HID_Basic/HID_Consumer/HID_Consumer.ino @@ -0,0 +1,48 @@ +/* + Copyright (c) 2014 NicoHood + See the readme for credit to other people. + + Consumer example (former Media example) + + Press a button to play/pause music player + See HID Project documentation for more Consumer keys. + + Make sure the Consumer report is set in: + sketchbook/hardware/HID/avr/variants/hid_descriptors/hid_descriptors.h + +// basic Media key definitions, see HID Project and official USB docs for more +#define MEDIA_FAST_FORWARD 0xB3 +#define MEDIA_REWIND 0xB4 +#define MEDIA_NEXT 0xB5 +#define MEDIA_PREVIOUS 0xB6 +#define MEDIA_STOP 0xB7 +#define MEDIA_PLAY_PAUSE 0xCD + +#define MEDIA_VOLUME_MUTE 0xE2 +#define MEDIA_VOLUME_UP 0xE9 +#define MEDIA_VOLUME_DOWN 0xEA +*/ + +const int pinLed = LED_BUILTIN; +const int pinButton = 2; + +void setup() { + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); + + // Sends a clean report to the host. This is important on any Arduino type. + Consumer.begin(); +} + +void loop() { + if (!digitalRead(pinButton)) { + digitalWrite(pinLed, HIGH); + + // See list above for more definitions or the official usb documentation + Consumer.write(MEDIA_PLAY_PAUSE); + + // simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } +} diff --git a/plugins/KeyboardioHID/examples/HID_Basic/HID_Gamepad/HID_Gamepad.ino b/plugins/KeyboardioHID/examples/HID_Basic/HID_Gamepad/HID_Gamepad.ino new file mode 100644 index 0000000000..b72887d818 --- /dev/null +++ b/plugins/KeyboardioHID/examples/HID_Basic/HID_Gamepad/HID_Gamepad.ino @@ -0,0 +1,86 @@ +/* + Copyright (c) 2014 NicoHood + See the readme for credit to other people. + + Gamepad example + + Press a button and demonstrate Gamepad actions + + Make sure the Gamepad report is set in: + sketchbook/hardware/HID/avr/variants/hid_descriptors/hid_descriptors.h + + Function prototypes: + void begin(void); + void end(void); + void write(void); + void press(uint8_t b); + void release(uint8_t b); + void releaseAll(void); + void buttons(uint32_t b); + void xAxis(int16_t a); + void yAxis(int16_t a); + void rxAxis(int16_t a); + void ryAxis(int16_t a); + void zAxis(int8_t a); + void rzAxis(int8_t a); + void dPad1(int8_t d); + void dPad2(int8_t d); + + Definitions: + GAMEPAD_DPAD_CENTERED 0 + GAMEPAD_DPAD_UP 1 + GAMEPAD_DPAD_UP_RIGHT 2 + GAMEPAD_DPAD_RIGHT 3 + GAMEPAD_DPAD_DOWN_RIGHT 4 + GAMEPAD_DPAD_DOWN 5 + GAMEPAD_DPAD_DOWN_LEFT 6 + GAMEPAD_DPAD_LEFT 7 + GAMEPAD_DPAD_UP_LEFT 8 + */ + +const int pinLed = LED_BUILTIN; +const int pinButton = 2; + +void setup() { + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); + + // Sends a clean report to the host. This is important on any Arduino type. + Gamepad.begin(); +} + +void loop() { + if (!digitalRead(pinButton)) { + digitalWrite(pinLed, HIGH); + + // press button 1-32 and reset (34 becaue its written later) + static uint8_t count = 1; + Gamepad.press(count++); + if (count == 34) { + Gamepad.releaseAll(); + count = 1; + } + + // move x/y Axis to a new position (16bit) + Gamepad.xAxis(random(0xFFFF)); + Gamepad.yAxis(random(0xFFFF)); + + // go through all dPad positions + // values: 0-8 (0==centred) + static uint8_t dpad1 = GAMEPAD_DPAD_CENTERED; + Gamepad.dPad1(dpad1++); + if(dpad1>GAMEPAD_DPAD_UP_LEFT) dpad1 = GAMEPAD_DPAD_CENTERED; + static int8_t dpad2 = GAMEPAD_DPAD_CENTERED; + Gamepad.dPad2(dpad2--); + if(dpad2 1) { + Serial.println("Please only input a single character or deactivate linefeed!"); + return; + } + + if (c != -1) { + Serial.println(c); + switch (c) { + case 'a': + Keyboard.write('b'); + break; + + case 'p': + Consumer.write(MEDIA_PLAY_PAUSE); + break; + + case 'o': + { + // uint8_t k[8] = {0}; + // k[1] = 1 << 4; + // //k[2] = 4; + // HID_SendReport(HID_REPORTID_KEYBOARD, &k, sizeof(k)); + // Keyboard.releaseAll(); + break; + } + + case 's': + System.write(SYSTEM_SLEEP); + break; + + case 'r': + Mouse.move(100, 0); + break; + + case 'l': + Mouse.move(-100, 0); + break; + + case 't': + Mouse.moveTo(1000, 1000); + break; + + case 'c': + case 'C': + Keyboard.write(KEY_CAPS_LOCK); + Serial.println("Leds"); + Serial.println(Keyboard.getLEDs(), BIN); + break; + + case 'k': + Keyboard.print("Testing USB functions xyz"); + break; + + case '\r': + case '\n': + Serial.println("Please only input a single character!"); + break; + + case 'g': { + // press button 1-32 and reset (34 becaue its written later) + static uint8_t count = 1; + Gamepad.press(count++); + if (count == 34) { + Gamepad.releaseAll(); + count = 1; + } + Gamepad.write(); + } + break; + + case 'd': + Serial.println("Serial"); + Serial.println(Serial.dtr()); + Serial.println(Serial.rts()); + Serial.println(Serial.baud()); + Serial.println(Serial.stopbits()); + Serial.println(Serial.paritytype()); + Serial.println(Serial.numbits()); + break; + + default: + Serial.println("unknown"); + } + } + } + + + if (eventBaud) { + Serial.println("Event"); + Serial.println(eventBaud); + eventBaud = 0; + } +} + +void CDC_LineEncodingEvent(void) +{ + eventBaud = Serial.baud(); +} diff --git a/plugins/KeyboardioHID/examples/HoodLoader1/HoodLoader1_API_Legacy/HoodLoader1_API_Legacy.ino b/plugins/KeyboardioHID/examples/Projects/HoodLoader1_API_Legacy/HoodLoader1_API_Legacy.ino similarity index 100% rename from plugins/KeyboardioHID/examples/HoodLoader1/HoodLoader1_API_Legacy/HoodLoader1_API_Legacy.ino rename to plugins/KeyboardioHID/examples/Projects/HoodLoader1_API_Legacy/HoodLoader1_API_Legacy.ino diff --git a/plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_PWM_Fade/HoodLoader2_PWM_Fade.ino b/plugins/KeyboardioHID/examples/Projects/HoodLoader2_PWM_Fade/HoodLoader2_PWM_Fade.ino similarity index 100% rename from plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_PWM_Fade/HoodLoader2_PWM_Fade.ino rename to plugins/KeyboardioHID/examples/Projects/HoodLoader2_PWM_Fade/HoodLoader2_PWM_Fade.ino diff --git a/plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_SerialKeyboard/HoodLoader2_SerialKeyboard.ino b/plugins/KeyboardioHID/examples/Projects/HoodLoader2_SerialKeyboard/HoodLoader2_SerialKeyboard.ino similarity index 100% rename from plugins/KeyboardioHID/examples/HoodLoader2/HoodLoader2_SerialKeyboard/HoodLoader2_SerialKeyboard.ino rename to plugins/KeyboardioHID/examples/Projects/HoodLoader2_SerialKeyboard/HoodLoader2_SerialKeyboard.ino From 2c58bc3134a32cfdd7b5684221863056b1696620 Mon Sep 17 00:00:00 2001 From: Nico Date: Fri, 2 Jan 2015 17:28:13 +0100 Subject: [PATCH 093/602] USB-Serial fix --- .../KeyboardioHID/examples/Projects/USB-Serial/USB-Serial.ino | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/KeyboardioHID/examples/Projects/USB-Serial/USB-Serial.ino b/plugins/KeyboardioHID/examples/Projects/USB-Serial/USB-Serial.ino index 5c8dbacd64..5d8ac8c718 100644 --- a/plugins/KeyboardioHID/examples/Projects/USB-Serial/USB-Serial.ino +++ b/plugins/KeyboardioHID/examples/Projects/USB-Serial/USB-Serial.ino @@ -18,9 +18,8 @@ void setup() { pinMode(resetPin, OUTPUT); digitalWrite(resetPin, HIGH); - // Start USB and HW Serial + // Start USB Serial Serial.begin(115200); - Serial1.begin(115200); } void loop() { From 333769ac36015366ae54759ad2c2905b79687fa8 Mon Sep 17 00:00:00 2001 From: Nico Date: Fri, 2 Jan 2015 17:36:29 +0100 Subject: [PATCH 094/602] Copyright update --- plugins/KeyboardioHID/Readme.md | 34 +++++++++++++++--- plugins/KeyboardioHID/avr/cores/hid/Arduino.h | 20 +++++++++++ .../avr/cores/hid/USB-Core/CDC.cpp | 25 +++++++++++-- .../avr/cores/hid/USB-Core/CDC.h | 23 ++++++++++++ .../avr/cores/hid/USB-Core/Consumer.cpp | 30 +++++++++------- .../avr/cores/hid/USB-Core/Consumer.h | 30 +++++++++------- .../avr/cores/hid/USB-Core/Gamepad.cpp | 30 +++++++++------- .../avr/cores/hid/USB-Core/Gamepad.h | 36 ++++++++++--------- .../avr/cores/hid/USB-Core/HID.cpp | 25 +++++++++++-- .../avr/cores/hid/USB-Core/HID.h | 23 ++++++++++++ .../avr/cores/hid/USB-Core/HIDAPI.h | 30 +++++++++------- .../avr/cores/hid/USB-Core/Keyboard.cpp | 23 ++++++++++++ .../avr/cores/hid/USB-Core/Keyboard.h | 23 ++++++++++++ .../avr/cores/hid/USB-Core/Mouse.cpp | 23 ++++++++++++ .../avr/cores/hid/USB-Core/Mouse.h | 23 ++++++++++++ .../avr/cores/hid/USB-Core/System.cpp | 30 +++++++++------- .../avr/cores/hid/USB-Core/System.h | 30 +++++++++------- .../avr/cores/hid/USB-Core/USBAPI.h | 20 +++++++++++ .../avr/cores/hid/USB-Core/USBCore.cpp | 22 ++++++++++-- .../avr/cores/hid/USB-Core/USBCore.h | 21 ++++++++++- .../avr/cores/hid/USB-Core/USBDesc.h | 25 +++++++++++-- .../avr/cores/hid/wiring_private.h | 20 +++++++++++ .../hid_descriptors/hid_descriptors.h | 3 ++ .../avr/variants/leonardo_hid/pins_arduino.h | 3 ++ .../avr/variants/micro_hid/pins_arduino.h | 3 ++ 25 files changed, 467 insertions(+), 108 deletions(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 8bc3fbaf85..72481650fe 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -21,12 +21,10 @@ Clean up USB Core code from fixed values. Use better understandable definitions Magic key fix for 32u4? Add Keywords.txt definitions -add examples keycode/raw for keyboard Check Keyboard keycode function again? Generalize HID key definitions via HIDTables for example? Add custom HID reports example -add copyright update Burning via ISP (advanced) Test with Android phone @@ -45,14 +43,13 @@ Your Arduino IDE will output errors then if you double click the file and try to ``` -(flash numbers might be irrelevant due to a lot of improvements) * Uses less flash if HID or Serial is not used * Extended and compacter(flash) HID Report Descriptors * Fixed USB Device Descriptor * Added u2 compatibility with smaller USB_EP_SIZE (16u2 etc) -* Added Serial Event for LineEncoding and LineState (+12b flash) +* Added Serial Event for LineEncoding and LineState * Added Serial Function to get dtr state, line encoding etc -* Added Keyboard Led Out report to get Led states (for numlock etc, +52b flash, 1b ram) +* Added Keyboard Led Out report to get Led states (for numlock etc) * Made CDC-Core independent from USB-Core * Made HID-Core independent from USB-Core * Made HID-API independent from HID-Core @@ -87,4 +84,31 @@ Include schematic HID.h contains all HID configuration. Each HID-API (like Mouse) includes Arduino.h and gets these settings as well. The pins_Arduino.h can overwrite each HID descriptor or define complete new one. +``` + +Licence and Copyright +===================== +If you use this library for any cool project let me know! + +``` +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +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/plugins/KeyboardioHID/avr/cores/hid/Arduino.h b/plugins/KeyboardioHID/avr/cores/hid/Arduino.h index 8340ca37ef..e8575a3fe0 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/Arduino.h +++ b/plugins/KeyboardioHID/avr/cores/hid/Arduino.h @@ -17,6 +17,26 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. +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 Arduino_h #define Arduino_h diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/CDC.cpp b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/CDC.cpp index 9141091667..e846f0b8f2 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/CDC.cpp +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/CDC.cpp @@ -1,5 +1,3 @@ - - /* Copyright (c) 2011, Peter Barrett ** ** Permission to use, copy, modify, and/or distribute this software for @@ -16,6 +14,29 @@ ** SOFTWARE. */ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +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 "CDC.h" #include diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/CDC.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/CDC.h index 627f69fa5f..f58bc0ddd6 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/CDC.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/CDC.h @@ -17,6 +17,29 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +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 __CDC__ #define __CDC__ diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Consumer.cpp b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Consumer.cpp index 6c685d97e2..051fdda148 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Consumer.cpp +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Consumer.cpp @@ -1,20 +1,24 @@ /* -Consumer.cpp -Copyright (c) 2005-2014 Arduino. All right reserved. +Copyright (c) 2014 NicoHood +See the readme for credit to other people. -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. +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: -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. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. -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 +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 "Consumer.h" diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Consumer.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Consumer.h index 70e3cd0d59..22617ab63c 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Consumer.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Consumer.h @@ -1,20 +1,24 @@ /* -Consumer.h -Copyright (c) 2005-2014 Arduino. All right reserved. +Copyright (c) 2014 NicoHood +See the readme for credit to other people. -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. +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: -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. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. -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 +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 __CONSUMERAPI__ diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.cpp b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.cpp index 4cb9fd04c5..6a86a7c456 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.cpp +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.cpp @@ -1,20 +1,24 @@ /* -Gamepad.cpp -Copyright (c) 2005-2014 Arduino. All right reserved. +Copyright (c) 2014 NicoHood +See the readme for credit to other people. -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. +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: -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. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. -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 +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 "Gamepad.h" diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.h index e2d91a3c92..03f9c08ab3 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.h @@ -1,20 +1,24 @@ /* -Gamepad.h -Copyright (c) 2005-2014 Arduino. All right reserved. - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +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 __GAMEPADAPI__ diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.cpp b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.cpp index 26406cd4af..587c0167fe 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.cpp +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.cpp @@ -1,5 +1,3 @@ - - /* Copyright (c) 2011, Peter Barrett ** ** Permission to use, copy, modify, and/or distribute this software for @@ -16,6 +14,29 @@ ** SOFTWARE. */ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +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 "HID.h" #define WEAK __attribute__ ((weak)) diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h index b6820a8b5d..238ac799a3 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h @@ -17,6 +17,29 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +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 __HID__ #define __HID__ diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HIDAPI.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HIDAPI.h index 8526bc5edc..4ca593da06 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HIDAPI.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HIDAPI.h @@ -1,20 +1,24 @@ /* -HIDAPI.h -Copyright (c) 2005-2014 Arduino. All right reserved. +Copyright (c) 2014 NicoHood +See the readme for credit to other people. -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. +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: -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. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. -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 +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 __HIDAPI__ diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.cpp b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.cpp index 09732a86f4..148f1e3490 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.cpp +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.cpp @@ -17,6 +17,29 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +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 "Keyboard.h" //================================================================================ diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h index a1003e76a0..ade9f9004f 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h @@ -17,6 +17,29 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +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 __KEYBOARDAPI__ #define __KEYBOARDAPI__ diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.cpp b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.cpp index f4c2504f25..779d58f349 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.cpp +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.cpp @@ -17,6 +17,29 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +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 "Mouse.h" //================================================================================ diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.h index 789428207b..8fabdca613 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.h @@ -17,6 +17,29 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +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 __MOUSEAPI__ #define __MOUSEAPI__ diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.cpp b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.cpp index 1d1d78d4ca..afc6c7f2fe 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.cpp +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.cpp @@ -1,20 +1,24 @@ /* -System.cpp -Copyright (c) 2005-2014 Arduino. All right reserved. +Copyright (c) 2014 NicoHood +See the readme for credit to other people. -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. +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: -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. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. -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 +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 "System.h" diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.h index 815b2af3a6..fd1b7dd47c 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.h @@ -1,20 +1,24 @@ /* -System.h -Copyright (c) 2005-2014 Arduino. All right reserved. +Copyright (c) 2014 NicoHood +See the readme for credit to other people. -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. +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: -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. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. -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 +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 __SYSTEMAPI__ diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBAPI.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBAPI.h index a49669c3cc..44bad6f3be 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBAPI.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBAPI.h @@ -17,6 +17,26 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. +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 __USBAPI__ #define __USBAPI__ diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBCore.cpp b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBCore.cpp index 764a411f82..30318273e3 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBCore.cpp +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBCore.cpp @@ -1,5 +1,3 @@ - - /* Copyright (c) 2010, Peter Barrett ** ** Sleep/Wakeup/SystemControl support added by Michael Dreher @@ -18,6 +16,26 @@ ** SOFTWARE. */ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. +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 "USBAPI.h" #if defined(USBCON) diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBCore.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBCore.h index 267900c3c5..f1ed5890f9 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBCore.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBCore.h @@ -1,4 +1,3 @@ - // Copyright (c) 2010, Peter Barrett /* ** Permission to use, copy, modify, and/or distribute this software for @@ -15,6 +14,26 @@ ** SOFTWARE. */ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. +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 __USBCORE_H__ #define __USBCORE_H__ diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBDesc.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBDesc.h index 93e90486c2..a7c33889b8 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBDesc.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBDesc.h @@ -1,5 +1,3 @@ - - /* Copyright (c) 2011, Peter Barrett ** ** Permission to use, copy, modify, and/or distribute this software for @@ -16,6 +14,29 @@ ** SOFTWARE. */ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +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. +*/ + #define CDC_ENABLED #define HID_ENABLED diff --git a/plugins/KeyboardioHID/avr/cores/hid/wiring_private.h b/plugins/KeyboardioHID/avr/cores/hid/wiring_private.h index 97e547efd9..35f644b11b 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/wiring_private.h +++ b/plugins/KeyboardioHID/avr/cores/hid/wiring_private.h @@ -22,6 +22,26 @@ $Id: wiring.h 239 2007-01-12 17:58:39Z mellis $ */ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. +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 WiringPrivate_h #define WiringPrivate_h diff --git a/plugins/KeyboardioHID/avr/variants/hid_descriptors/hid_descriptors.h b/plugins/KeyboardioHID/avr/variants/hid_descriptors/hid_descriptors.h index 529adecb5e..7b7f371b6c 100644 --- a/plugins/KeyboardioHID/avr/variants/hid_descriptors/hid_descriptors.h +++ b/plugins/KeyboardioHID/avr/variants/hid_descriptors/hid_descriptors.h @@ -1,14 +1,17 @@ /* Copyright (c) 2014 NicoHood See the readme for credit to other people. + 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 diff --git a/plugins/KeyboardioHID/avr/variants/leonardo_hid/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/leonardo_hid/pins_arduino.h index 77655bda39..adf6c2a368 100644 --- a/plugins/KeyboardioHID/avr/variants/leonardo_hid/pins_arduino.h +++ b/plugins/KeyboardioHID/avr/variants/leonardo_hid/pins_arduino.h @@ -1,14 +1,17 @@ /* Copyright (c) 2014 NicoHood See the readme for credit to other people. + 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 diff --git a/plugins/KeyboardioHID/avr/variants/micro_hid/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/micro_hid/pins_arduino.h index 4dc36e2023..eecbe30681 100644 --- a/plugins/KeyboardioHID/avr/variants/micro_hid/pins_arduino.h +++ b/plugins/KeyboardioHID/avr/variants/micro_hid/pins_arduino.h @@ -1,14 +1,17 @@ /* Copyright (c) 2014 NicoHood See the readme for credit to other people. + 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 From 7631be5c3734fe1cabfc14211e6eff97d3689936 Mon Sep 17 00:00:00 2001 From: Nico Date: Fri, 2 Jan 2015 18:28:14 +0100 Subject: [PATCH 095/602] Better Readme --- plugins/KeyboardioHID/Readme.md | 294 +++++++++++++++++- .../hid_descriptors/hid_descriptors.h | 16 +- plugins/KeyboardioHID/header.jpg | Bin 0 -> 150263 bytes plugins/KeyboardioHID/keywords.txt | 201 ++++++++++++ 4 files changed, 490 insertions(+), 21 deletions(-) create mode 100644 plugins/KeyboardioHID/header.jpg create mode 100644 plugins/KeyboardioHID/keywords.txt diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 72481650fe..4fb056b64e 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -1,14 +1,141 @@ +Arduino HID Project 2.1 +======================= +![Header Picture](header.jpg) + +This project went through a lot of phases and has now reached a new Arduino USB-Core +with a lot of new functions like extended HID. It also supports HoodLoader1+2. +The idea is to enable enhanced USB functions to almost all 'standard' Arduino boards. +This is done with slightly different methods for different boards. + +**Supported Arduinos (IDE 1.5.8 or higher!):** +* Uno (with HoodLoader1 or 2) +* Mega (with HoodLoader1 or 2) +* Leonardo +* (Pro)Micro +* Any other 8u2/16u/at90usb162/32u2/32u4 compatible board + +**Main features of the new USB-Core:** + +* New HID devices(list below) +* HID reports are easier to modify now +* USB Wakeup +* Smaller flash/ram usage +* More Serial functions +* u2 Series support (HL2) +* HoodLoader1 compatible legacy example + +**There are many more additions and fixes in this USB Core. See change log for more details.** + +**Supported HID devices:** + +* Keyboard with Leds out (modifiers + 6 keys pressed at the same time) +* Mouse (5 buttons, move, wheel) + Absolute Mouse +* Media Keys (4 keys for music player, webbrowser and more) +* System Key (for PC standby/shutdown) +* Gamepad (32 buttons, 4 16bit axis, 2 8bit axis, 2 D-Pads) + +The HID project contains HID APIs to generate HID reports and functions to send them to the USB Host. +The API (syntax/usage) of the HID Project is always the same for each solution, **you can port code from one device to another very easy**. + +* On a Leonardo this function is extended and improved to get more HID devices + some improvements. +* [HoodLoader2](https://github.com/NicoHood/HoodLoader2) is a BootLoader for the 16u2 that let's you use it as standalone MCU with the same USB-Core. +* [HoodLoader1](https://github.com/NicoHood/HoodLoader) is a 16u2 firmware that filters special HW Serial signals from the main MCU and sends HID signals to the USB Host. + +To make things more clear the HID Software is in a separate repository than the HoodLoader (1 & 2) sources and installing instructions. +**HoodLoader 1&2 is only used for an Uno/Mega to actually enable USB functions.** The 16u2 is normally used for USB-Serial programming of the main MCU but can do way more than that. +To use HoodLoader1&2 you also need the HID Project. For more information and installation instructions see the specific repository. + +HoodLoader1 was the first solution to enable HID functions to the Uno/Mega but HoodLoader2 opens way more options because you can reprogram the whole MCU standalone. +See the repository for more infos about this great new opportunity. HoodLoader1 API is still usable in a specific example. HoodLoader1&2 are not needed/compatible with a Leonardo/Micro. + + Installation ============ -put these files into *sketchbook/hardware/HID/* +Put all files from *avr/* into *sketchbook/hardware/HID/avr*. +Make sure you use Arduino IDE 1.5.8 or newer. + +At the moment you have to move the cores/hid folder into your Arduino installation +*arduino-1.6.0/hardware/arduino/avr/cores/hid* because of a bug in the IDE. + +If you like to, you can add the keywords to your Arduino IDE so that words like 'Gamepad' are highlighted. +(TODO) + +How to use +========== + +### Micro/Leonardo + HoodLoader2 + +**You can compile all HID APIs but this doesnt mean that you can use them if no hid descriptor is set correctly.** +Edit the *sketchbook/hardware/HID/avr/variants/hid_descriptors/hid_descriptors.h* to use the extended HID core. +At the moment you have 3 options: Default, Gamepad or Extended. Extended should work for anything expect Gamepads. +See the bug section below to find out more about working hid reports. Not all of them are playing well together. + +Have a closer look at these lines: +``` cpp +// use this to enable the Keyboard Led functions +#define HID_KEYBOARD_LEDS_ENABLED + +// add your custom HID Report Descriptor here. +// you can use the pre defined reports as well +//#define EXTERN_HID_REPORT DEFAULT_HID_REPORT +#define EXTERN_HID_REPORT EXTENDED_HID_REPORT +//#define EXTERN_HID_REPORT GAMEPAD_HID_REPORT +``` + +You can also add your own descriptor with your own APIs. +Use the void HID_SendReport(uint8_t id, const void* data, int len); function to send hid reports. + +See *Project/USB-Serial* for a fully usable USB-Serial bridge and how to use the new Serial functions. +In the CDC.h you can also see the new Control Line functions for advanced users. + +**Try the Basic HID examples for each HID device. They are pretty much self explaining. +You can also see the *Projects/HID_Test* for an all in one example.** + +### HoodLoader1 + +**Try the HoodLoader1 example. It provides the basic Serial protocol API to send HID reports. You have to copy this to every sketch again.** + +With HoodLoader1 you can **only use baud 115200 for HID** due to speed/programming reasons. +Use Serial.begin(115200) in every HoodLoader1 sketch. +Its not bad anyway because its the fastest baud and you want fast HID recognition. +You still can **fully use any other baud** for normal sketches but HID wont work. +If you try nevertheless it will output Serial crap to the monitor. + +Keep in mind that HoodLoader1 has **no flush function**. If the PC is reading HID too slow it can miss data, like on a Raspberry Pi. +Add a delay to the sending function or just use the newer HoodLoader2. +Do not use HID in interrupts because it uses Serial. Your Arduino can crash! -at the moment you have to move -the cores/hid folder into your Arduino installation because of a bug in the ide. -This Core is ment to use with 1.5.8 or newer Arduino IDE +Always release buttons to not cause any erros. Replug USB cable to reset the values if anything went wrong. +Keep in mind that **with HoodLoader1 the 16u2 is always on**. The 16u2 and its HID reports are not reset if the main MCU is reset. +So you need to reset the HID reports on every startup with a begin() of each used API. +On Windows every USB report will reset when you open the lock screen. +See [deactivate HID function (Hoodloader only)](https://github.com/NicoHood/Hoodloader) how to temporary disable HID again. + +For **16u2 as ISP usage** (optional, Hoodloader only, has nothing to do with HID function) +see [Hoodloader repository](https://github.com/NicoHood/Hoodloader). + +The sending API is no longer integrated directly in the HID Project since it is now more an extended USB-Core and this has nothing to do with it. +Its more a legacy version to still use HoodLoader1 or to reimplement something similar with HoodLoader2 if you still want full report access for the main MCU. + +**The older, full integrated HID Core can be found here.** Keep in mind to remove all newer stuff since it may conflict (a clean arduino core would do it). +It is not better than this solution, maybe easier to use since its just more integrated. +[Outdated HID Project for 1.5.7](https://github.com/NicoHood/HID/tree/3d8a9b40752a143141b8be4b8f744e203c80b000) + + +How it works +============ +For the Leonardo/Micro + HoodLoader2 its a modified version of the HID descriptors and USB-Core. +This changes were made to improve the functions, add more devices and add u2 series compatibility. + +HoodLoader1 only: +For the Uno/Mega you need a special Bootloader. Why? See [Hoodloader repository](https://github.com/NicoHood/Hoodloader). +To sum it up: Serial information is grabbed by the "man in the middle, 16u2" and you dont have to worry to get any wrong Serial stuff via USB. +Thatswhy you need a special baud (115200) that both sides can communicate with each other. +Every USB command is send via a special [NicoHood Protocol](https://github.com/NicoHood/NicoHoodProtocol) +that's filtered out by the 16u2. If you use Serial0 for extern devices it cannot filter the signal of course. +You can still use the NHP, just dont use the reserved Address 1. -You can compile all HID APIs -but this doesnt mean that you can use them if no hid descriptor is set correctly. TODO ==== @@ -20,29 +147,43 @@ Keyboard Layout for different Languages Clean up USB Core code from fixed values. Use better understandable definitions Magic key fix for 32u4? -Add Keywords.txt definitions +Add/update Keywords.txt definitions keycode/raw for keyboard Check Keyboard keycode function again? Generalize HID key definitions via HIDTables for example? Add custom HID reports example +add keyboard led example update Burning via ISP (advanced) Test with Android phone update no usb workaround notice (no longer needed for hoodloader2, but for leonardo) +``` -Bugs -Mouse Abs only works with system report under special circumstances. -Gamepad + Mouse Abs doesnt work (fix Gamepad) -Fix HID_SendReport() prototype workaround in HID-APIs -Core selection in boards.txt is not working - -Do not name the Arduino Sketch 'Mouse.ino' or 'Keyboard.ino' etc. +Known Bugs +========== +* See Hoodloader1+2 repositories for HoodLoader1+2 related Bugs/Issues. +* Mouse Abs only works with system report under special circumstances. +* Gamepad + Mouse Abs doesnt work together +* Fix HID_SendReport() prototype workaround in HID-APIs +* Core selection in boards.txt is not working +* Do not name the Arduino Sketch 'Mouse.ino' or 'Keyboard.ino' etc. Your Arduino IDE will output errors then if you double click the file and try to compile. -``` +* RawHID is not working properly, test it at your own risk. +* Feel free to open an Issue on Github if you find a bug. Or message me via my [blog](http://nicohood.wordpress.com/)! +* All OS have some problems with Gamepads. Dont use more than one device for Linux and be careful when you change the descriptor. +* XBMC 13.1 (a Media Center) uses Gamepad input. Its seems to not work and may cause weird errors. +Even with a standard Gamepad I have these errors. Just want to mention it here. +* The Serial may disconnect if you have too much throughput. This is a general bug of the Arduino Core, +which might be fixed. For example Adalight dosnt work well for me, +so you better use an Arduino Uno with Hoodloader1 (yes the older one!) for Mediacenter control and Ambilight. +Version History +=============== ``` +2.1 Release (xx.01.2015) +* Reworked the whole USB-Core from scratch * Uses less flash if HID or Serial is not used * Extended and compacter(flash) HID Report Descriptors * Fixed USB Device Descriptor @@ -67,8 +208,131 @@ Your Arduino IDE will output errors then if you double click the file and try to * Separated USB-Core in its own folder * Added HID Tables * USB-Serial now fully reprogrammable + +2.0 Release (29.11.2014) +* Added HoodLoader2 +* Separated HoodLoader1&2 more +* Added u2 series for USB-Core +* Extended USB core and fixed minor things for the u2 series +* Added Led Out report. +* Added CDC Line state +* Reworked the whole library structure again + +1.8 Beta Release (26.08.2014) +* Changes in the Hoodloader: + * **Huge improvements**, see [Hoodloader repository](https://github.com/NicoHood/Hoodloader) + * Reworked the whole library, easy installation now + * HID fixes for Media Keys/Ubuntu + * Removed Joystick, added 4 Gamepads + +1.7.3 Beta Release (10.08.2014) +* Changes in the Hoodloader: + * Fixed HID flush bug (1.6 - 1.7.2) + +1.7.2 Beta Release (10.08.2014) +* Changes in the Hoodloader: + * Added Lite version for 8u2 + * Added Versions that show up as Uno/Mega (not recommended) + * Makefile and structure changes + +1.7.1 Beta Release (10.08.2014) +* Changes in the Hoodloader: + * Fixed HID deactivation bug + +1.7 Beta Release (10.08.2014) +* Changes in the Hoodloader: + * Works as ISP now. See the [Hoodloader Repository](https://github.com/NicoHood/Hoodloader) for more information. + * Exceeded 8kb limit. For flashing a 8u2 use v1.6 please! +* Changed Readme text + +1.6 Beta Release (09.08.2014) +* Bugfixes in the Hoodloader: + * Changed HID management (not blocking that much, faster) + * added RawHID in/out (HID to Serial) +* Added RawHID Class and example + +1.5 Beta Release (21.07.2014) +* Moved Hoodloader source to a [separate Github page](https://github.com/NicoHood/Hoodloader) +* Bugfixes in the Hoodloader: + * Firmware is still available here + * Overall a lot of ram improvements, now with a big global union of ram + * Removed USBtoUSART buffer (not needed, saved 128/500 bytes) + * Removed Lite version because of better ram usage not needed + * Separated different modes better to not cause any errors in default mode + * Improved the deactivate option + * Integrated NHP directly + * Replaced LightweightRingbuffer with native Lufa Ringbuffer + * Improved writing to CDC Host + * Fixed a bug in checkNHPProtocol: & needs to be a == + * General structure changes + * Improved stability + * Fixed Arduino as ISP bug + +1.4.1 Beta Release (10.07.2014) +* #define Bugfix in USBAPI.h + +1.4 Beta Release (10.07.2014) +* Bugfixes in the Hoodloader: + * Added Lite Version with less ram usage + * Changed PIDs, edited driver file +* merged v1.0.x and v1.5.x together (both are compatible!) +* added IDE v1.5.7 support +* added Tutorials + +1.3 Beta Release (01.07.2014) +* Bugfixes in the Hoodloader: + * Improved ram usage (you can get even better but that messes up code and increases flash) +* **Important NHP fix inside the HID Class for Uno/Mega** + +1.2 Beta Release (22.06.2014) +* Added 1.0.x/1.5.x support +* Bugfixes in the Hoodloader: + * Sometimes HID Devices weren't updating when using more than 1 Device (set forcewrite to true) + * Fast updates crashed the bootloader (too much ram usage, set CDC buffer from 128b to 100b each) +* Minor file structure changes + +1.1 Beta Release (05.06.2014) +* Added Leonardo/Micro support +* Included NicoHoodProtocol +* Minor fixes + +1.0 Beta Release (03.06.2014) ``` +Useful Links/Credits +==================== + +* [LUFA from Dean Camera](http://www.fourwalledcubicle.com/LUFA.php) +* [Darran's HID Projects] (https://github.com/harlequin-tech/arduino-usb) +* [Connor's Joystick for the Leonardo](http://www.imaginaryindustries.com/blog/?p=80) +* [Stefan Jones Multimedia Keys Example](http://stefanjones.ca/blog/arduino-leonardo-remote-multimedia-keys/) +* [Athanasios Douitsis Multimedia Keys Example](https://github.com/aduitsis/ardumultimedia) +* [The Original Arduino Sources](https://github.com/arduino/Arduino/tree/master/hardware/arduino/firmwares/atmegaxxu2/arduino-usbserial) +* [USBlyzer](http://www.usblyzer.com/) +* [Mattairtechs 16u2 Lufa USB Core](https://www.mattairtech.com/index.php/development-boards/mt-db-u1.html) +* [Paul Brook's Minimus 32u2 Arduino USB Core](https://github.com/pbrook/minimus-arduino) +* [Paul Stoffregen's Teensy Core](https://github.com/PaulStoffregen/cores) +* [Keyboard Led Out report by hartmut_holgraefe](http://forum.arduino.cc/index.php?topic=173583.0) +* [Github Pull Request with a lot of new functions](https://github.com/arduino/Arduino/pull/1803) +* A lot of searching through the web +* The awesome official Arduino IRC chat! +* [The NicoHood Protocol ^.^](https://github.com/NicoHood/NicoHoodProtocol) +* See HoodLoader1&2 repository for more credits/links +* [Hackaday post about HoodLoader2](hackaday.com/2014/11/30/using-the-second-microcontroller-on-an-arduino) +* [Gamecube to PC adapter](https://github.com/NicoHood/Nintendo) +* See http://nicohood.wordpress.com/ for more tutorials, projects and contact. +* For donations please contact me on my blog :) + +For Developers +============== +If you deactivate some reports it can occur that windows will cause problems and recognize it as different device. +While developing I had that much trouble that I had to change the PID. No way to repair the broken windows driver settings. +So be careful if you change the source on your own with important PIDs. +Therefore reinstall the divers for any device or just dont touch the HID reports. + +See this how to uninstall the drivers: +https://support.microsoft.com/kb/315539 + ``` Include schematic - Arduino.h diff --git a/plugins/KeyboardioHID/avr/variants/hid_descriptors/hid_descriptors.h b/plugins/KeyboardioHID/avr/variants/hid_descriptors/hid_descriptors.h index 7b7f371b6c..72809e5fe8 100644 --- a/plugins/KeyboardioHID/avr/variants/hid_descriptors/hid_descriptors.h +++ b/plugins/KeyboardioHID/avr/variants/hid_descriptors/hid_descriptors.h @@ -21,12 +21,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -// add your custom HID Report Descriptor here. -// you can use the pre defined reports as well -//#define EXTERN_HID_REPORT DEFAULT_HID_REPORT -#define EXTERN_HID_REPORT EXTENDED_HID_REPORT -//#define EXTERN_HID_REPORT GAMEPAD_HID_REPORT - #define EXTENDED_HID_REPORT \ HID_REPORT_KEYBOARD_LEDS(HID_REPORTID_KEYBOARD), \ HID_REPORT_MOUSE(HID_REPORTID_MOUSE), \ @@ -39,9 +33,19 @@ HID_REPORT_KEYBOARD_LEDS(HID_REPORTID_KEYBOARD), \ HID_REPORT_MOUSE(HID_REPORTID_MOUSE), \ HID_REPORT_GAMEPAD(HID_REPORTID_GAMEPAD) +//================================================================================ +// Settings +//================================================================================ + // use this to enable the Keyboard Led functions #define HID_KEYBOARD_LEDS_ENABLED +// add your custom HID Report Descriptor here. +// you can use the pre defined reports as well +//#define EXTERN_HID_REPORT DEFAULT_HID_REPORT +#define EXTERN_HID_REPORT EXTENDED_HID_REPORT +//#define EXTERN_HID_REPORT GAMEPAD_HID_REPORT + // Keep in mind that changing the ids or reports might confuse your OS // Then you might need to reinstall all drivers or change the USB PID diff --git a/plugins/KeyboardioHID/header.jpg b/plugins/KeyboardioHID/header.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d87032a640a9052d4cd80c2b450a8dc27659d8a1 GIT binary patch literal 150263 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 JJ%|06_&>z+PgDQ^ literal 0 HcmV?d00001 diff --git a/plugins/KeyboardioHID/keywords.txt b/plugins/KeyboardioHID/keywords.txt new file mode 100644 index 0000000000..ddefd30dad --- /dev/null +++ b/plugins/KeyboardioHID/keywords.txt @@ -0,0 +1,201 @@ +####################################### +# Syntax Coloring Map For HID +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +begin KEYWORD2 +end KEYWORD2 +click KEYWORD2 +move KEYWORD2 +write KEYWORD2 +press KEYWORD2 +isPressed KEYWORD2 +releaseAll KEYWORD2 +buttons KEYWORD2 +xAxis KEYWORD2 +yAxis KEYWORD2 +zAxis KEYWORD2 +rxAxis KEYWORD2 +ryAxis KEYWORD2 +rzAxis KEYWORD2 +dPad1 KEYWORD2 +dPad2 KEYWORD2 +HID_SendReport KEYWORD2 + +####################################### +# Classes (KEYWORD3) +####################################### + +Mouse KEYWORD3 +Keyboard KEYWORD3 +RawHID KEYWORD3 +Media KEYWORD3 +System KEYWORD3 +Gamepad KEYWORD3 + +####################################### +# Instances (KEYWORD2) +####################################### + +####################################### +# Constants (LITERAL1) +####################################### + +#CDC +CDC_CONTROL_LINE_OUT_DTR LITERAL1 +CDC_CONTROL_LINE_OUT_TRS LITERAL1 + +#Mouse + +MOUSE_LEFT LITERAL1 +MOUSE_RIGHT LITERAL1 +MOUSE_MIDDLE LITERAL1 +MOUSE_PREV LITERAL1 +MOUSE_NEXT LITERAL1 + +#Keyboard + +LED_NUM_LOCK LITERAL1 +LED_CAPS_LOCK LITERAL1 +LED_SCROLL_LOCK LITERAL1 + +KEY_LEFT_CTRL LITERAL1 +KEY_LEFT_SHIFT LITERAL1 +KEY_LEFT_ALT LITERAL1 +KEY_LEFT_GUI LITERAL1 +KEY_LEFT_WINDOWS LITERAL1 +KEY_RIGHT_CTRL LITERAL1 +KEY_RIGHT_SHIFT LITERAL1 +KEY_RIGHT_ALT LITERAL1 +KEY_RIGHT_GUI LITERAL1 +KEY_RIGHT_WINDOWS LITERAL1 + +KEY_UP_ARROW LITERAL1 +KEY_DOWN_ARROW LITERAL1 +KEY_LEFT_ARROW LITERAL1 +KEY_RIGHT_ARROW LITERAL1 +KEY_BACKSPACE LITERAL1 +KEY_TAB LITERAL1 +KEY_RETURN LITERAL1 +KEY_ENTER LITERAL1 +KEY_ESC LITERAL1 +KEY_INSERT LITERAL1 +KEY_DELETE LITERAL1 +KEY_PAGE_UP LITERAL1 +KEY_PAGE_DOWN LITERAL1 +KEY_HOME LITERAL1 +KEY_END LITERAL1 +KEY_CAPS_LOCK LITERAL1 +KEY_F1 LITERAL1 +KEY_F2 LITERAL1 +KEY_F3 LITERAL1 +KEY_F4 LITERAL1 +KEY_F5 LITERAL1 +KEY_F6 LITERAL1 +KEY_F7 LITERAL1 +KEY_F8 LITERAL1 +KEY_F9 LITERAL1 +KEY_F10 LITERAL1 +KEY_F11 LITERAL1 +KEY_F12 LITERAL1 + +KEY_PRINT LITERAL1 +KEY_NUM_LOCK LITERAL1 +KEY_SCROLL_LOCK LITERAL1 +KEY_PAUSE LITERAL1 + +#Raw Keyboard definitions + +RAW_KEYBOARD_LEFT_CTRL LITERAL1 +RAW_KEYBOARD_LEFT_SHIFT LITERAL1 +RAW_KEYBOARD_LEFT_ALT LITERAL1 +RAW_KEYBOARD_LEFT_GUI LITERAL1 +RAW_KEYBOARD_RIGHT_CTRL LITERAL1 +RAW_KEYBOARD_RIGHT_SHIFT LITERAL1 +RAW_KEYBOARD_RIGHT_ALT LITERAL1 +RAW_KEYBOARD_RIGHT_GUI LITERAL1 + +RAW_KEYBOARD_KEY LITERAL1 + +RAW_KEYBOARD_UP_ARROW LITERAL1 +RAW_KEYBOARD_DOWN_ARROW LITERAL1 +RAW_KEYBOARD_LEFT_ARROW LITERAL1 +RAW_KEYBOARD_RIGHT_ARROW LITERAL1 +RAW_KEYBOARD_SPACEBAR LITERAL1 +RAW_KEYBOARD_BACKSPACE LITERAL1 +RAW_KEYBOARD_TAB LITERAL1 +RAW_KEYBOARD_RETURN LITERAL1 +RAW_KEYBOARD_ESC LITERAL1 +RAW_KEYBOARD_INSERT LITERAL1 +RAW_KEYBOARD_DELETE LITERAL1 +RAW_KEYBOARD_PAGE_UP LITERAL1 +RAW_KEYBOARD_PAGE_DOWN LITERAL1 +RAW_KEYBOARD_HOME LITERAL1 +RAW_KEYBOARD_END LITERAL1 +RAW_KEYBOARD_CAPS_LOCK LITERAL1 +RAW_KEYBOARD_F1 LITERAL1 +RAW_KEYBOARD_F2 LITERAL1 +RAW_KEYBOARD_F3 LITERAL1 +RAW_KEYBOARD_F4 LITERAL1 +RAW_KEYBOARD_F5 LITERAL1 +RAW_KEYBOARD_F6 LITERAL1 +RAW_KEYBOARD_F7 LITERAL1 +RAW_KEYBOARD_F8 LITERAL1 +RAW_KEYBOARD_F9 LITERAL1 +RAW_KEYBOARD_F10 LITERAL1 +RAW_KEYBOARD_F11 LITERAL1 +RAW_KEYBOARD_F12 LITERAL1 +RAW_KEYBOARD_PRINT LITERAL1 +RAW_KEYBOARD_SCROLL_LOCK LITERAL1 +RAW_KEYBOARD_PAUSE LITERAL1 + +#RawHID +RAWHID_RX_SIZE LITERAL1 +RAWHID_TX_SIZE LITERAL1 + +#Media + +MEDIA_FAST_FORWARD LITERAL1 +MEDIA_REWIND LITERAL1 +MEDIA_NEXT LITERAL1 +MEDIA_PREVIOUS LITERAL1 +MEDIA_STOP LITERAL1 +MEDIA_PLAY_PAUSE LITERAL1 + +MEDIA_VOLUME_MUTE LITERAL1 +MEDIA_VOLUME_UP LITERAL1 +MEDIA_VOLUME_DOWN LITERAL1 + +MEDIA_EMAIL_READER LITERAL1 +MEDIA_CALCULATOR LITERAL1 +MEDIA_EXPLORER LITERAL1 + +MEDIA_BROWSER_HOME LITERAL1 +MEDIA_BROWSER_BACK LITERAL1 +MEDIA_BROWSER_FORWARD LITERAL1 +MEDIA_BROWSER_REFRESH LITERAL1 +MEDIA_BROWSER_BOOKMARKS LITERAL1 + +#System + +SYSTEM_POWER_DOWN LITERAL1 +SYSTEM_SLEEP LITERAL1 +SYSTEM_WAKE_UP LITERAL1 + +#Gamepad +GAMEPAD_DPAD_CENTERED LITERAL1 +GAMEPAD_DPAD_UP LITERAL1 +GAMEPAD_DPAD_UP_RIGHT LITERAL1 +GAMEPAD_DPAD_RIGHT LITERAL1 +GAMEPAD_DPAD_DOWN_RIGHT LITERAL1 +GAMEPAD_DPAD_DOWN LITERAL1 +GAMEPAD_DPAD_DOWN_LEFT LITERAL1 +GAMEPAD_DPAD_LEFT LITERAL1 +GAMEPAD_DPAD_UP_LEFT LITERAL1 From 81fcd26182eb313005b4cbc994dc376f894024e8 Mon Sep 17 00:00:00 2001 From: Nico Date: Fri, 2 Jan 2015 19:58:02 +0100 Subject: [PATCH 096/602] Updated Keyboard Led example --- plugins/KeyboardioHID/Readme.md | 58 ++++++------ .../HID_Basic/HID_Keyboard/HID_Keyboard.ino | 89 ++++++++++-------- .../HID_Keyboard_Led/HID_Keyboard_Led.ino | 94 +++++++++++++++++++ .../examples/Projects/HID_Test/HID_Test.ino | 2 +- 4 files changed, 172 insertions(+), 71 deletions(-) create mode 100644 plugins/KeyboardioHID/examples/HID_Basic/HID_Keyboard_Led/HID_Keyboard_Led.ino diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 4fb056b64e..de8b3ada34 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -5,7 +5,6 @@ Arduino HID Project 2.1 This project went through a lot of phases and has now reached a new Arduino USB-Core with a lot of new functions like extended HID. It also supports HoodLoader1+2. The idea is to enable enhanced USB functions to almost all 'standard' Arduino boards. -This is done with slightly different methods for different boards. **Supported Arduinos (IDE 1.5.8 or higher!):** * Uno (with HoodLoader1 or 2) @@ -18,13 +17,13 @@ This is done with slightly different methods for different boards. * New HID devices(list below) * HID reports are easier to modify now +* HID APIs are external usable now * USB Wakeup * Smaller flash/ram usage * More Serial functions -* u2 Series support (HL2) -* HoodLoader1 compatible legacy example - -**There are many more additions and fixes in this USB Core. See change log for more details.** +* u2 Series support (with [HoodLoader2](https://github.com/NicoHood/HoodLoader2)) +* [HoodLoader1](https://github.com/NicoHood/HoodLoader) compatible legacy example +* See change log for more additions and fixes **Supported HID devices:** @@ -34,26 +33,14 @@ This is done with slightly different methods for different boards. * System Key (for PC standby/shutdown) * Gamepad (32 buttons, 4 16bit axis, 2 8bit axis, 2 D-Pads) -The HID project contains HID APIs to generate HID reports and functions to send them to the USB Host. -The API (syntax/usage) of the HID Project is always the same for each solution, **you can port code from one device to another very easy**. - -* On a Leonardo this function is extended and improved to get more HID devices + some improvements. -* [HoodLoader2](https://github.com/NicoHood/HoodLoader2) is a BootLoader for the 16u2 that let's you use it as standalone MCU with the same USB-Core. -* [HoodLoader1](https://github.com/NicoHood/HoodLoader) is a 16u2 firmware that filters special HW Serial signals from the main MCU and sends HID signals to the USB Host. - -To make things more clear the HID Software is in a separate repository than the HoodLoader (1 & 2) sources and installing instructions. -**HoodLoader 1&2 is only used for an Uno/Mega to actually enable USB functions.** The 16u2 is normally used for USB-Serial programming of the main MCU but can do way more than that. -To use HoodLoader1&2 you also need the HID Project. For more information and installation instructions see the specific repository. - -HoodLoader1 was the first solution to enable HID functions to the Uno/Mega but HoodLoader2 opens way more options because you can reprogram the whole MCU standalone. -See the repository for more infos about this great new opportunity. HoodLoader1 API is still usable in a specific example. HoodLoader1&2 are not needed/compatible with a Leonardo/Micro. - - Installation ============ -Put all files from *avr/* into *sketchbook/hardware/HID/avr*. -Make sure you use Arduino IDE 1.5.8 or newer. +For Arduino Uno/Mega first install [HoodLoader2](https://github.com/NicoHood/HoodLoader2) on your 16u2 + the needed software files. +[HoodLoader1](https://github.com/NicoHood/HoodLoader) is only supported for legacy but will get a new use soon! + +Installation has changed over the time. Put all files from *avr/* into *sketchbook/hardware/HID/avr*. +Make sure you use Arduino IDE 1.5.8 or newer. You don't have to modify the original Arduino-Core any more. At the moment you have to move the cores/hid folder into your Arduino installation *arduino-1.6.0/hardware/arduino/avr/cores/hid* because of a bug in the IDE. @@ -66,7 +53,7 @@ How to use ### Micro/Leonardo + HoodLoader2 -**You can compile all HID APIs but this doesnt mean that you can use them if no hid descriptor is set correctly.** +**You can compile all HID APIs but this doesn't mean that you can use them if no hid descriptor is set correctly.** Edit the *sketchbook/hardware/HID/avr/variants/hid_descriptors/hid_descriptors.h* to use the extended HID core. At the moment you have 3 options: Default, Gamepad or Extended. Extended should work for anything expect Gamepads. See the bug section below to find out more about working hid reports. Not all of them are playing well together. @@ -88,6 +75,7 @@ Use the void HID_SendReport(uint8_t id, const void* data, int len); function to See *Project/USB-Serial* for a fully usable USB-Serial bridge and how to use the new Serial functions. In the CDC.h you can also see the new Control Line functions for advanced users. +Keep in mind that the USB_ENDPOINTs for the u2 Series are set to 16 bytes, so the Serial buffer is also smaller (normally 64b). **Try the Basic HID examples for each HID device. They are pretty much self explaining. You can also see the *Projects/HID_Test* for an all in one example.** @@ -128,13 +116,28 @@ How it works For the Leonardo/Micro + HoodLoader2 its a modified version of the HID descriptors and USB-Core. This changes were made to improve the functions, add more devices and add u2 series compatibility. +The HID project contains HID APIs to generate HID reports and functions to send them to the USB Host. +The API (syntax/usage) of the HID Project is always the same for each solution, **you can port code from one device to another very easy**. + +* On a Leonardo this function is extended and improved to get more HID devices + some improvements. +* [HoodLoader2](https://github.com/NicoHood/HoodLoader2) is a BootLoader for the 16u2 that let's you use it as standalone MCU with the same USB-Core. +* [HoodLoader1](https://github.com/NicoHood/HoodLoader) is a 16u2 firmware that filters special HW Serial signals from the main MCU and sends HID signals to the USB Host. + +To make things more clear the HID Software is in a separate repository than the HoodLoader (1 & 2) sources and installing instructions. +**HoodLoader 1&2 is only used for an Uno/Mega to actually enable USB functions.** The 16u2 is normally used for USB-Serial programming of the main MCU but can do way more than that. +To use HoodLoader1&2 you also need the HID Project. For more information and installation instructions see the specific repository. + +HoodLoader1 was the first solution to enable HID functions to the Uno/Mega but HoodLoader2 opens way more options because you can reprogram the whole MCU standalone. +See the repository for more infos about this great new opportunity. HoodLoader1 API is still usable in a specific example. HoodLoader1&2 are not needed/compatible with a Leonardo/Micro. + + HoodLoader1 only: -For the Uno/Mega you need a special Bootloader. Why? See [Hoodloader repository](https://github.com/NicoHood/Hoodloader). +For the Uno/Mega you need a special Bootloader(actually firmware in this case). Why? See [Hoodloader repository](https://github.com/NicoHood/Hoodloader). To sum it up: Serial information is grabbed by the "man in the middle, 16u2" and you dont have to worry to get any wrong Serial stuff via USB. Thatswhy you need a special baud (115200) that both sides can communicate with each other. Every USB command is send via a special [NicoHood Protocol](https://github.com/NicoHood/NicoHoodProtocol) that's filtered out by the 16u2. If you use Serial0 for extern devices it cannot filter the signal of course. -You can still use the NHP, just dont use the reserved Address 1. +You can still use the NHP, just don't use the reserved Address 1. TODO @@ -151,12 +154,9 @@ Add/update Keywords.txt definitions keycode/raw for keyboard Check Keyboard keycode function again? Generalize HID key definitions via HIDTables for example? -Add custom HID reports example -add keyboard led example update Burning via ISP (advanced) -Test with Android phone -update no usb workaround notice (no longer needed for hoodloader2, but for leonardo) +Test with Android phone (HL1) ``` diff --git a/plugins/KeyboardioHID/examples/HID_Basic/HID_Keyboard/HID_Keyboard.ino b/plugins/KeyboardioHID/examples/HID_Basic/HID_Keyboard/HID_Keyboard.ino index 9497e1359c..62f06aba57 100644 --- a/plugins/KeyboardioHID/examples/HID_Basic/HID_Keyboard/HID_Keyboard.ino +++ b/plugins/KeyboardioHID/examples/HID_Basic/HID_Keyboard/HID_Keyboard.ino @@ -43,44 +43,51 @@ void loop() { /* Definitions: - KEY_LEFT_CTRL - KEY_LEFT_SHIFT - KEY_LEFT_ALT - KEY_LEFT_GUI - KEY_RIGHT_CTRL - KEY_RIGHT_SHIFT - KEY_RIGHT_ALT - KEY_RIGHT_GUI - - KEY_UP_ARROW - KEY_DOWN_ARROW - KEY_LEFT_ARROW - KEY_RIGHT_ARROW - KEY_BACKSPACE - KEY_TAB - KEY_RETURN - KEY_ESC - KEY_INSERT - KEY_DELETE - KEY_PAGE_UP - KEY_PAGE_DOWN - KEY_HOME - KEY_END - KEY_CAPS_LOCK - KEY_F1 - KEY_F2 - KEY_F3 - KEY_F4 - KEY_F5 - KEY_F6 - KEY_F7 - KEY_F8 - KEY_F9 - KEY_F10 - KEY_F11 - KEY_F12 - - KEY_PRINT - KEY_SCROLL_LOCK - KEY_PAUSE - */ \ No newline at end of file +#define KEY_PRINT 0xCE +#define KEY_NUM_LOCK 0xDB +#define KEY_SCROLL_LOCK 0xCF +#define KEY_PAUSE 0xD0 + +#define KEY_LEFT_CTRL 0x80 +#define KEY_LEFT_SHIFT 0x81 +#define KEY_LEFT_ALT 0x82 +#define KEY_LEFT_GUI 0x83 +#define KEY_LEFT_WINDOWS KEY_LEFT_GUI +#define KEY_RIGHT_CTRL 0x84 +#define KEY_RIGHT_SHIFT 0x85 +#define KEY_RIGHT_ALT 0x86 +#define KEY_RIGHT_GUI 0x87 +#define KEY_RIGHT_WINDOWS KEY_RIGHT_GUI + +#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 + +#define LED_NUM_LOCK 0x01 +#define LED_CAPS_LOCK 0x02 +#define LED_SCROLL_LOCK 0x04 + */ diff --git a/plugins/KeyboardioHID/examples/HID_Basic/HID_Keyboard_Led/HID_Keyboard_Led.ino b/plugins/KeyboardioHID/examples/HID_Basic/HID_Keyboard_Led/HID_Keyboard_Led.ino new file mode 100644 index 0000000000..0d5dcf2223 --- /dev/null +++ b/plugins/KeyboardioHID/examples/HID_Basic/HID_Keyboard_Led/HID_Keyboard_Led.ino @@ -0,0 +1,94 @@ +/* + Copyright (c) 2014 NicoHood + See the readme for credit to other people. + + Keyboard Led example + + Press a button to toogle caps lock. + Caps lock state is represented by the onboard led. + See official and HID Project documentation for more infos + + Make sure the Keyboard report + LEDs! is set in: + sketchbook/hardware/HID/avr/variants/hid_descriptors/hid_descriptors.h +*/ + +const int pinLed = LED_BUILTIN; +const int pinButton = 2; + +void setup() { + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); + + // Sends a clean report to the host. This is important on any Arduino type. + Keyboard.begin(); +} + + +void loop() { + // update Led equal to the caps lock state + // keep in mind on HoodLoader2 high&low are inverted (like this) + if (Keyboard.getLeds()&LED_CAPS_LOCK) + digitalWrite(pinLed, LOW); + else + digitalWrite(pinLed, HIGH); + + if (!digitalRead(pinButton)) { + // trigger caps lock + Keyboard.write(KEY_CAPS_LOCK); + + // simple debounce + delay(500); + } +} + +/* +Definitions: + +#define KEY_PRINT 0xCE +#define KEY_NUM_LOCK 0xDB +#define KEY_SCROLL_LOCK 0xCF +#define KEY_PAUSE 0xD0 + +#define KEY_LEFT_CTRL 0x80 +#define KEY_LEFT_SHIFT 0x81 +#define KEY_LEFT_ALT 0x82 +#define KEY_LEFT_GUI 0x83 +#define KEY_LEFT_WINDOWS KEY_LEFT_GUI +#define KEY_RIGHT_CTRL 0x84 +#define KEY_RIGHT_SHIFT 0x85 +#define KEY_RIGHT_ALT 0x86 +#define KEY_RIGHT_GUI 0x87 +#define KEY_RIGHT_WINDOWS KEY_RIGHT_GUI + +#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 + +#define LED_NUM_LOCK 0x01 +#define LED_CAPS_LOCK 0x02 +#define LED_SCROLL_LOCK 0x04 + */ diff --git a/plugins/KeyboardioHID/examples/Projects/HID_Test/HID_Test.ino b/plugins/KeyboardioHID/examples/Projects/HID_Test/HID_Test.ino index 9f2af89bb6..d542767461 100644 --- a/plugins/KeyboardioHID/examples/Projects/HID_Test/HID_Test.ino +++ b/plugins/KeyboardioHID/examples/Projects/HID_Test/HID_Test.ino @@ -115,7 +115,7 @@ void loop() { case 'C': Keyboard.write(KEY_CAPS_LOCK); Serial.println("Leds"); - Serial.println(Keyboard.getLEDs(), BIN); + Serial.println(Keyboard.getLeds(), BIN); break; case 'k': From 6111347ba3f96d5855fec131af2baab22cc78135 Mon Sep 17 00:00:00 2001 From: Nico Date: Fri, 2 Jan 2015 19:58:49 +0100 Subject: [PATCH 097/602] Updated Keyboard Led function name --- plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h index ade9f9004f..11ab19fd30 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h @@ -186,7 +186,7 @@ class Keyboard_ : public Print size_t removeKeycodeFromReport(uint8_t k); #if defined(HID_KEYBOARD_LEDS_ENABLED) - inline uint8_t getLEDs(void){ return hid_keyboard_leds; } + inline uint8_t getLeds(void){ return hid_keyboard_leds; } #endif }; extern Keyboard_ Keyboard; From b7322cf7ddae5e8cf746e02d5f280883645d6777 Mon Sep 17 00:00:00 2001 From: Nico Date: Fri, 2 Jan 2015 20:13:44 +0100 Subject: [PATCH 098/602] Arduino 1.6 rc1 Core update Just a small HW Serial update --- plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.cpp | 2 +- plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.cpp b/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.cpp index 29a336649e..41935e3205 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.cpp +++ b/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.cpp @@ -152,7 +152,7 @@ void HardwareSerial::end() int HardwareSerial::available(void) { - return (int)(SERIAL_RX_BUFFER_SIZE + _rx_buffer_head - _rx_buffer_tail) % SERIAL_RX_BUFFER_SIZE; + return ((unsigned int)(SERIAL_RX_BUFFER_SIZE + _rx_buffer_head - _rx_buffer_tail)) % SERIAL_RX_BUFFER_SIZE; } int HardwareSerial::peek(void) diff --git a/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.h b/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.h index 935934b195..7dc2aa98c4 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.h +++ b/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.h @@ -32,6 +32,8 @@ // 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. +// NOTE: a "power of 2" buffer size is reccomended to dramatically +// optimize all the modulo operations for ring buffers. #if !(defined(SERIAL_TX_BUFFER_SIZE) && defined(SERIAL_RX_BUFFER_SIZE)) #if (RAMEND < 1000) #define SERIAL_TX_BUFFER_SIZE 16 From 546890aed242d284c9817ed3f13a59bc397ca81f Mon Sep 17 00:00:00 2001 From: Nico Date: Fri, 2 Jan 2015 20:13:49 +0100 Subject: [PATCH 099/602] Readme --- plugins/KeyboardioHID/Readme.md | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index de8b3ada34..22edc96f43 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -38,9 +38,10 @@ Installation For Arduino Uno/Mega first install [HoodLoader2](https://github.com/NicoHood/HoodLoader2) on your 16u2 + the needed software files. [HoodLoader1](https://github.com/NicoHood/HoodLoader) is only supported for legacy but will get a new use soon! +For Arduino Micro/Leonardo ignore this step. Installation has changed over the time. Put all files from *avr/* into *sketchbook/hardware/HID/avr*. -Make sure you use Arduino IDE 1.5.8 or newer. You don't have to modify the original Arduino-Core any more. +Make sure you use Arduino IDE 1.5.8 or newer. You don't have to modify the original core any more. At the moment you have to move the cores/hid folder into your Arduino installation *arduino-1.6.0/hardware/arduino/avr/cores/hid* because of a bug in the IDE. @@ -73,14 +74,17 @@ Have a closer look at these lines: You can also add your own descriptor with your own APIs. Use the void HID_SendReport(uint8_t id, const void* data, int len); function to send hid reports. -See *Project/USB-Serial* for a fully usable USB-Serial bridge and how to use the new Serial functions. -In the CDC.h you can also see the new Control Line functions for advanced users. -Keep in mind that the USB_ENDPOINTs for the u2 Series are set to 16 bytes, so the Serial buffer is also smaller (normally 64b). +**Select your Arduino board under *Tools->Board->Arduino Leonardo/Micro Custom HID* to use the new HID-Core. +If you select the normal Leonardo/Micro entry you will automatically use the standard Arduino Core.** **Try the Basic HID examples for each HID device. They are pretty much self explaining. You can also see the *Projects/HID_Test* for an all in one example.** -### HoodLoader1 +See *Project/USB-Serial* for a fully usable USB-Serial bridge and how to use the new Serial functions. +In the CDC.h you can also see the new Control Line functions for advanced users. +Keep in mind that the USB_ENDPOINTs for the u2 Series are set to 16 bytes, so the Serial buffer is also smaller (normally 64b). + +### HoodLoader1 (legacy, new stuff coming soon) **Try the HoodLoader1 example. It provides the basic Serial protocol API to send HID reports. You have to copy this to every sketch again.** @@ -157,6 +161,7 @@ Generalize HID key definitions via HIDTables for example? update Burning via ISP (advanced) Test with Android phone (HL1) +"Emulate" HL1 protocol ``` From 8db4e5d77d5a8fac0a6dfab48ef1cdfe5fc6ff77 Mon Sep 17 00:00:00 2001 From: Nico Date: Fri, 2 Jan 2015 20:23:17 +0100 Subject: [PATCH 100/602] original keywords.txt --- plugins/KeyboardioHID/keywords.txt | 415 +++++++++++++++-------------- 1 file changed, 219 insertions(+), 196 deletions(-) diff --git a/plugins/KeyboardioHID/keywords.txt b/plugins/KeyboardioHID/keywords.txt index ddefd30dad..d77a4b10ce 100644 --- a/plugins/KeyboardioHID/keywords.txt +++ b/plugins/KeyboardioHID/keywords.txt @@ -1,201 +1,224 @@ -####################################### -# Syntax Coloring Map For HID -####################################### +# LITERAL1 specifies constants + +HIGH LITERAL1 Constants +LOW LITERAL1 Constants +INPUT LITERAL1 Constants +INPUT_PULLUP LITERAL1 Constants +OUTPUT LITERAL1 Constants +DEC LITERAL1 Serial_Print +BIN LITERAL1 Serial_Print +HEX LITERAL1 Serial_Print +OCT LITERAL1 Serial_Print +PI LITERAL1 +HALF_PI LITERAL1 +TWO_PI LITERAL1 +LSBFIRST LITERAL1 ShiftOut +MSBFIRST LITERAL1 ShiftOut +CHANGE LITERAL1 AttachInterrupt +FALLING LITERAL1 AttachInterrupt +RISING LITERAL1 AttachInterrupt +DEFAULT LITERAL1 AnalogReference +EXTERNAL LITERAL1 AnalogReference +INTERNAL LITERAL1 AnalogReference +INTERNAL1V1 LITERAL1 AnalogReference +INTERNAL2V56 LITERAL1 AnalogReference + +# KEYWORD1 specifies datatypes and C/C++ keywords + +boolean KEYWORD1 BooleanVariables +break KEYWORD1 Break +byte KEYWORD1 Byte +case KEYWORD1 SwitchCase +char KEYWORD1 Char +class KEYWORD1 +const KEYWORD1 Const +continue KEYWORD1 Continue +default KEYWORD1 SwitchCase +do KEYWORD1 DoWhile +double KEYWORD1 Double +else KEYWORD1 Else +false KEYWORD1 Constants +float KEYWORD1 Float +for KEYWORD1 For +if KEYWORD1 If +int KEYWORD1 Int +long KEYWORD1 Long +new KEYWORD1 +null KEYWORD1 +private KEYWORD1 +protected KEYWORD1 +public KEYWORD1 +register KEYWORD1 +return KEYWORD1 Return +short KEYWORD1 +signed KEYWORD1 +static KEYWORD1 Static +String KEYWORD1 String +switch KEYWORD1 SwitchCase +this KEYWORD1 +throw KEYWORD1 +try KEYWORD1 +true KEYWORD1 +unsigned KEYWORD1 +void KEYWORD1 Void +while KEYWORD1 While +word KEYWORD1 Word + +# operators aren't highlighted, but may have documentation + ++= IncrementCompound ++ Arithmetic +[] arrayaccess += assign +& BitwiseAnd +| BitwiseAnd +, +// Comments +?: +{} Braces +-- Increment +/ Arithmetic +/* Comments +. dot +== +< greaterthan +<= greaterthanorequalto +++ Increment +!= inequality +<< Bitshift +< lessthan +<= lessthanorequalto +&& Boolean +! Boolean +|| Boolean +- Arithmetic +% Modulo +* Arithmetic +() parentheses +>> Bitshift +; SemiColon +-= IncrementCompound + +# these are datatypes, but we've also defined functions to cast to them + +boolean KEYWORD2 boolean_ +byte KEYWORD2 byte_ +char KEYWORD2 char_ +float KEYWORD2 float_ +int KEYWORD2 int_ +long KEYWORD2 long_ +word KEYWORD2 word_ + +# KEYWORD2 specifies methods and functions + +abs KEYWORD2 Abs +acos KEYWORD2 ACos +asin KEYWORD2 ASin +atan KEYWORD2 ATan +atan2 KEYWORD2 ATan2 +ceil KEYWORD2 Ceil +constrain KEYWORD2 Constrain +cos KEYWORD2 Cos +degrees KEYWORD2 +exp KEYWORD2 Exp +floor KEYWORD2 Floor +log KEYWORD2 Log +map KEYWORD2 Map +max KEYWORD2 Max +min KEYWORD2 Min +radians KEYWORD2 +random KEYWORD2 Random +randomSeed KEYWORD2 RandomSeed +round KEYWORD2 +sin KEYWORD2 Sin +sq KEYWORD2 Sq +sqrt KEYWORD2 Sqrt +tan KEYWORD2 Tan +pow KEYWORD2 Pow + +bitRead KEYWORD2 BitRead +bitWrite KEYWORD2 BitWrite +bitSet KEYWORD2 BitSet +bitClear KEYWORD2 BitClear +bit KEYWORD2 Bit +highByte KEYWORD2 HighByte +lowByte KEYWORD2 LowByte + +analogReference KEYWORD2 AnalogReference +analogRead KEYWORD2 AnalogRead +analogWrite KEYWORD2 AnalogWrite +attachInterrupt KEYWORD2 AttachInterrupt +detachInterrupt KEYWORD2 DetachInterrupt +delay KEYWORD2 Delay +delayMicroseconds KEYWORD2 DelayMicroseconds +digitalWrite KEYWORD2 DigitalWrite +digitalRead KEYWORD2 DigitalRead +interrupts KEYWORD2 +millis KEYWORD2 Millis +micros KEYWORD2 Micros +noInterrupts KEYWORD2 NoInterrupts +noTone KEYWORD2 NoTone +pinMode KEYWORD2 PinMode +pulseIn KEYWORD2 PulseIn +shiftIn KEYWORD2 ShiftIn +shiftOut KEYWORD2 ShiftOut +tone KEYWORD2 Tone +yield KEYWORD2 Yield + +Serial KEYWORD3 Serial +Serial1 KEYWORD3 Serial +Serial2 KEYWORD3 Serial +Serial3 KEYWORD3 Serial +SerialUSB KEYWORD3 Serial +begin KEYWORD2 Serial_Begin +end KEYWORD2 Serial_End +peek KEYWORD2 Serial_Peek +read KEYWORD2 Serial_Read +print KEYWORD2 Serial_Print +println KEYWORD2 Serial_Println +available KEYWORD2 Serial_Available +availableForWrite KEYWORD2 +flush KEYWORD2 Serial_Flush +setTimeout KEYWORD2 +find KEYWORD2 +findUntil KEYWORD2 +parseInt KEYWORD2 +parseFloat KEYWORD2 +readBytes KEYWORD2 +readBytesUntil KEYWORD2 +readString KEYWORD2 +readStringUntil KEYWORD2 +trim KEYWORD2 +toUpperCase KEYWORD2 +toLowerCase KEYWORD2 +charAt KEYWORD2 +compareTo KEYWORD2 +concat KEYWORD2 +endsWith KEYWORD2 +startsWith KEYWORD2 +equals KEYWORD2 +equalsIgnoreCase KEYWORD2 +getBytes KEYWORD2 +indexOf KEYWORD2 +lastIndexOf KEYWORD2 +length KEYWORD2 +replace KEYWORD2 +setCharAt KEYWORD2 +substring KEYWORD2 +toCharArray KEYWORD2 +toInt KEYWORD2 + +# USB-related keywords -####################################### -# Datatypes (KEYWORD1) -####################################### - -####################################### -# Methods and Functions (KEYWORD2) -####################################### - -begin KEYWORD2 -end KEYWORD2 +Keyboard KEYWORD3 +Mouse KEYWORD3 +press KEYWORD2 +release KEYWORD2 +releaseAll KEYWORD2 +accept KEYWORD2 click KEYWORD2 move KEYWORD2 -write KEYWORD2 -press KEYWORD2 isPressed KEYWORD2 -releaseAll KEYWORD2 -buttons KEYWORD2 -xAxis KEYWORD2 -yAxis KEYWORD2 -zAxis KEYWORD2 -rxAxis KEYWORD2 -ryAxis KEYWORD2 -rzAxis KEYWORD2 -dPad1 KEYWORD2 -dPad2 KEYWORD2 -HID_SendReport KEYWORD2 - -####################################### -# Classes (KEYWORD3) -####################################### - -Mouse KEYWORD3 -Keyboard KEYWORD3 -RawHID KEYWORD3 -Media KEYWORD3 -System KEYWORD3 -Gamepad KEYWORD3 - -####################################### -# Instances (KEYWORD2) -####################################### - -####################################### -# Constants (LITERAL1) -####################################### - -#CDC -CDC_CONTROL_LINE_OUT_DTR LITERAL1 -CDC_CONTROL_LINE_OUT_TRS LITERAL1 - -#Mouse - -MOUSE_LEFT LITERAL1 -MOUSE_RIGHT LITERAL1 -MOUSE_MIDDLE LITERAL1 -MOUSE_PREV LITERAL1 -MOUSE_NEXT LITERAL1 - -#Keyboard - -LED_NUM_LOCK LITERAL1 -LED_CAPS_LOCK LITERAL1 -LED_SCROLL_LOCK LITERAL1 - -KEY_LEFT_CTRL LITERAL1 -KEY_LEFT_SHIFT LITERAL1 -KEY_LEFT_ALT LITERAL1 -KEY_LEFT_GUI LITERAL1 -KEY_LEFT_WINDOWS LITERAL1 -KEY_RIGHT_CTRL LITERAL1 -KEY_RIGHT_SHIFT LITERAL1 -KEY_RIGHT_ALT LITERAL1 -KEY_RIGHT_GUI LITERAL1 -KEY_RIGHT_WINDOWS LITERAL1 - -KEY_UP_ARROW LITERAL1 -KEY_DOWN_ARROW LITERAL1 -KEY_LEFT_ARROW LITERAL1 -KEY_RIGHT_ARROW LITERAL1 -KEY_BACKSPACE LITERAL1 -KEY_TAB LITERAL1 -KEY_RETURN LITERAL1 -KEY_ENTER LITERAL1 -KEY_ESC LITERAL1 -KEY_INSERT LITERAL1 -KEY_DELETE LITERAL1 -KEY_PAGE_UP LITERAL1 -KEY_PAGE_DOWN LITERAL1 -KEY_HOME LITERAL1 -KEY_END LITERAL1 -KEY_CAPS_LOCK LITERAL1 -KEY_F1 LITERAL1 -KEY_F2 LITERAL1 -KEY_F3 LITERAL1 -KEY_F4 LITERAL1 -KEY_F5 LITERAL1 -KEY_F6 LITERAL1 -KEY_F7 LITERAL1 -KEY_F8 LITERAL1 -KEY_F9 LITERAL1 -KEY_F10 LITERAL1 -KEY_F11 LITERAL1 -KEY_F12 LITERAL1 - -KEY_PRINT LITERAL1 -KEY_NUM_LOCK LITERAL1 -KEY_SCROLL_LOCK LITERAL1 -KEY_PAUSE LITERAL1 - -#Raw Keyboard definitions - -RAW_KEYBOARD_LEFT_CTRL LITERAL1 -RAW_KEYBOARD_LEFT_SHIFT LITERAL1 -RAW_KEYBOARD_LEFT_ALT LITERAL1 -RAW_KEYBOARD_LEFT_GUI LITERAL1 -RAW_KEYBOARD_RIGHT_CTRL LITERAL1 -RAW_KEYBOARD_RIGHT_SHIFT LITERAL1 -RAW_KEYBOARD_RIGHT_ALT LITERAL1 -RAW_KEYBOARD_RIGHT_GUI LITERAL1 - -RAW_KEYBOARD_KEY LITERAL1 - -RAW_KEYBOARD_UP_ARROW LITERAL1 -RAW_KEYBOARD_DOWN_ARROW LITERAL1 -RAW_KEYBOARD_LEFT_ARROW LITERAL1 -RAW_KEYBOARD_RIGHT_ARROW LITERAL1 -RAW_KEYBOARD_SPACEBAR LITERAL1 -RAW_KEYBOARD_BACKSPACE LITERAL1 -RAW_KEYBOARD_TAB LITERAL1 -RAW_KEYBOARD_RETURN LITERAL1 -RAW_KEYBOARD_ESC LITERAL1 -RAW_KEYBOARD_INSERT LITERAL1 -RAW_KEYBOARD_DELETE LITERAL1 -RAW_KEYBOARD_PAGE_UP LITERAL1 -RAW_KEYBOARD_PAGE_DOWN LITERAL1 -RAW_KEYBOARD_HOME LITERAL1 -RAW_KEYBOARD_END LITERAL1 -RAW_KEYBOARD_CAPS_LOCK LITERAL1 -RAW_KEYBOARD_F1 LITERAL1 -RAW_KEYBOARD_F2 LITERAL1 -RAW_KEYBOARD_F3 LITERAL1 -RAW_KEYBOARD_F4 LITERAL1 -RAW_KEYBOARD_F5 LITERAL1 -RAW_KEYBOARD_F6 LITERAL1 -RAW_KEYBOARD_F7 LITERAL1 -RAW_KEYBOARD_F8 LITERAL1 -RAW_KEYBOARD_F9 LITERAL1 -RAW_KEYBOARD_F10 LITERAL1 -RAW_KEYBOARD_F11 LITERAL1 -RAW_KEYBOARD_F12 LITERAL1 -RAW_KEYBOARD_PRINT LITERAL1 -RAW_KEYBOARD_SCROLL_LOCK LITERAL1 -RAW_KEYBOARD_PAUSE LITERAL1 - -#RawHID -RAWHID_RX_SIZE LITERAL1 -RAWHID_TX_SIZE LITERAL1 - -#Media - -MEDIA_FAST_FORWARD LITERAL1 -MEDIA_REWIND LITERAL1 -MEDIA_NEXT LITERAL1 -MEDIA_PREVIOUS LITERAL1 -MEDIA_STOP LITERAL1 -MEDIA_PLAY_PAUSE LITERAL1 - -MEDIA_VOLUME_MUTE LITERAL1 -MEDIA_VOLUME_UP LITERAL1 -MEDIA_VOLUME_DOWN LITERAL1 - -MEDIA_EMAIL_READER LITERAL1 -MEDIA_CALCULATOR LITERAL1 -MEDIA_EXPLORER LITERAL1 - -MEDIA_BROWSER_HOME LITERAL1 -MEDIA_BROWSER_BACK LITERAL1 -MEDIA_BROWSER_FORWARD LITERAL1 -MEDIA_BROWSER_REFRESH LITERAL1 -MEDIA_BROWSER_BOOKMARKS LITERAL1 - -#System - -SYSTEM_POWER_DOWN LITERAL1 -SYSTEM_SLEEP LITERAL1 -SYSTEM_WAKE_UP LITERAL1 -#Gamepad -GAMEPAD_DPAD_CENTERED LITERAL1 -GAMEPAD_DPAD_UP LITERAL1 -GAMEPAD_DPAD_UP_RIGHT LITERAL1 -GAMEPAD_DPAD_RIGHT LITERAL1 -GAMEPAD_DPAD_DOWN_RIGHT LITERAL1 -GAMEPAD_DPAD_DOWN LITERAL1 -GAMEPAD_DPAD_DOWN_LEFT LITERAL1 -GAMEPAD_DPAD_LEFT LITERAL1 -GAMEPAD_DPAD_UP_LEFT LITERAL1 +setup KEYWORD3 Setup +loop KEYWORD3 Loop From 4daabb59b5e42ea67464df27d97fe296dd99848d Mon Sep 17 00:00:00 2001 From: Nico Date: Fri, 2 Jan 2015 20:27:29 +0100 Subject: [PATCH 101/602] Added new keywords.txt definitions --- plugins/KeyboardioHID/Readme.md | 5 ++--- plugins/KeyboardioHID/keywords.txt | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 22edc96f43..999a3ce7bb 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -46,8 +46,8 @@ Make sure you use Arduino IDE 1.5.8 or newer. You don't have to modify the origi At the moment you have to move the cores/hid folder into your Arduino installation *arduino-1.6.0/hardware/arduino/avr/cores/hid* because of a bug in the IDE. -If you like to, you can add the keywords to your Arduino IDE so that words like 'Gamepad' are highlighted. -(TODO) +If you like to, you can add the keywords.txt to your Arduino IDE so that words like 'Gamepad' are highlighted. +Replace the file in *arduino-1.6.0/lib/keywords.txt* with the *keywords.txt* provided in this project. How to use ========== @@ -154,7 +154,6 @@ Keyboard Layout for different Languages Clean up USB Core code from fixed values. Use better understandable definitions Magic key fix for 32u4? -Add/update Keywords.txt definitions keycode/raw for keyboard Check Keyboard keycode function again? Generalize HID key definitions via HIDTables for example? diff --git a/plugins/KeyboardioHID/keywords.txt b/plugins/KeyboardioHID/keywords.txt index d77a4b10ce..69801d48be 100644 --- a/plugins/KeyboardioHID/keywords.txt +++ b/plugins/KeyboardioHID/keywords.txt @@ -210,15 +210,39 @@ toInt KEYWORD2 # USB-related keywords +USBDevice KEYWORD3 Keyboard KEYWORD3 Mouse KEYWORD3 +RawHID KEYWORD3 +System KEYWORD3 +Consumer KEYWORD3 +Gamepad KEYWORD3 press KEYWORD2 release KEYWORD2 releaseAll KEYWORD2 accept KEYWORD2 click KEYWORD2 move KEYWORD2 +moveTo KEYWORD2 isPressed KEYWORD2 +getLeds KEYWORD2 +buttons KEYWORD2 +xAxis KEYWORD2 +yAxis KEYWORD2 +zAxis KEYWORD2 +rxAxis KEYWORD2 +ryAxis KEYWORD2 +rzAxis KEYWORD2 +dPad1 KEYWORD2 +dPad2 KEYWORD2 +HID_SendReport KEYWORD2 +wakeupHost KEYWORD2 +baud KEYWORD2 +stopbits KEYWORD2 +paritytype KEYWORD2 +numbits KEYWORD2 +dtr KEYWORD2 +rts KEYWORD2 setup KEYWORD3 Setup loop KEYWORD3 Loop From 1f4b52c6d972f8cb6d745bd3ea455ea1c5f539e9 Mon Sep 17 00:00:00 2001 From: Nico Date: Fri, 2 Jan 2015 20:27:47 +0100 Subject: [PATCH 102/602] minor format fix --- plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBAPI.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBAPI.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBAPI.h index 44bad6f3be..f6ac2f365c 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBAPI.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBAPI.h @@ -90,8 +90,8 @@ bool MSC_Data(uint8_t rx, uint8_t tx); int CDC_GetInterface(uint8_t* interfaceNum); int CDC_GetDescriptor(int i); bool CDC_Setup(Setup& setup); -void CDC_LineEncodingEvent(void); -void CDC_LineStateEvent(void); +void CDC_LineEncodingEvent(void); +void CDC_LineStateEvent(void); //================================================================================ //================================================================================ From 52492290be7b0ed551afc56df313b5d5206b20ac Mon Sep 17 00:00:00 2001 From: Nico Date: Fri, 2 Jan 2015 20:30:36 +0100 Subject: [PATCH 103/602] Added Keycodes in keywords.txt --- plugins/KeyboardioHID/Readme.md | 2 +- plugins/KeyboardioHID/keywords.txt | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 999a3ce7bb..e375815d49 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -155,7 +155,7 @@ Clean up USB Core code from fixed values. Use better understandable definitions Magic key fix for 32u4? keycode/raw for keyboard -Check Keyboard keycode function again? +Check Keyboard keycode function again? + add example Generalize HID key definitions via HIDTables for example? update Burning via ISP (advanced) diff --git a/plugins/KeyboardioHID/keywords.txt b/plugins/KeyboardioHID/keywords.txt index 69801d48be..e5f61058c7 100644 --- a/plugins/KeyboardioHID/keywords.txt +++ b/plugins/KeyboardioHID/keywords.txt @@ -226,6 +226,11 @@ move KEYWORD2 moveTo KEYWORD2 isPressed KEYWORD2 getLeds KEYWORD2 +pressKeycode KEYWORD2 +releaseKeycode KEYWORD2 +writeKeycode KEYWORD2 +addKeycodeToReport KEYWORD2 +removeKeycodeFromReport KEYWORD2 buttons KEYWORD2 xAxis KEYWORD2 yAxis KEYWORD2 From 5a24a4ba6bbf43e095b11f0480bbf2183f4b9592 Mon Sep 17 00:00:00 2001 From: Nico Date: Fri, 2 Jan 2015 20:33:20 +0100 Subject: [PATCH 104/602] Update Readme.md --- plugins/KeyboardioHID/Readme.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 61daaea1b7..f7745e93ac 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -6,6 +6,9 @@ This project went through a lot of phases and has now reached an HID library wit The idea is to enable enhanced USB functions to almost all 'standard' Arduino boards. This is done with slightly different methods for different boards. +###The new 2.1 is ready to test here, need feedback: +https://github.com/NicoHood/HID/tree/Official-Integration + **Arduino IDE 1.5.8 is required for the HID Project.** **Supported HID devices:** From b75347be449c7e8c85614e951fce0d2627973b05 Mon Sep 17 00:00:00 2001 From: Nico Date: Sat, 3 Jan 2015 14:54:10 +0100 Subject: [PATCH 105/602] Added Installation picture --- plugins/KeyboardioHID/Readme.md | 5 ++++- plugins/KeyboardioHID/installation.png | Bin 0 -> 28170 bytes 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 plugins/KeyboardioHID/installation.png diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index e375815d49..465ba746cf 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -46,6 +46,9 @@ Make sure you use Arduino IDE 1.5.8 or newer. You don't have to modify the origi At the moment you have to move the cores/hid folder into your Arduino installation *arduino-1.6.0/hardware/arduino/avr/cores/hid* because of a bug in the IDE. +**Your sketchbook folder should look like this:** +![Installation Picture](installation.png) + If you like to, you can add the keywords.txt to your Arduino IDE so that words like 'Gamepad' are highlighted. Replace the file in *arduino-1.6.0/lib/keywords.txt* with the *keywords.txt* provided in this project. @@ -147,7 +150,7 @@ You can still use the NHP, just don't use the reserved Address 1. TODO ==== -Under Construction. This is a todo list for myself and a feature list so far. +Under Construction. This is a todo list for myself. ``` Keyboard Layout for different Languages diff --git a/plugins/KeyboardioHID/installation.png b/plugins/KeyboardioHID/installation.png new file mode 100644 index 0000000000000000000000000000000000000000..13dd8339df2fa98e5e77b66f74c94fbbebf0a01f GIT binary patch literal 28170 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 Date: Sat, 3 Jan 2015 19:00:08 +0100 Subject: [PATCH 106/602] Easy USB-Core selection HoodLoader2 needs an update as well. --- plugins/KeyboardioHID/Readme.md | 50 +++--- plugins/KeyboardioHID/avr/boards.txt | 146 +++++++++++------- .../avr/cores/hid/USB-Core/HID.h | 50 +++++- plugins/KeyboardioHID/avr/platform.txt | 3 +- .../pins_arduino.h} | 46 +++--- .../variants/leonardo_gamepad/pins_arduino.h | 45 ++++++ .../avr/variants/leonardo_hid/pins_arduino.h | 25 ++- .../variants/leonardo_no_usb/pins_arduino.h | 28 ++++ .../avr/variants/micro_custom/pins_arduino.h | 64 ++++++++ .../avr/variants/micro_gamepad/pins_arduino.h | 45 ++++++ .../avr/variants/micro_hid/pins_arduino.h | 25 ++- .../avr/variants/micro_no_usb/pins_arduino.h | 28 ++++ plugins/KeyboardioHID/board.png | Bin 0 -> 27786 bytes plugins/KeyboardioHID/usb-core.png | Bin 0 -> 18162 bytes 14 files changed, 447 insertions(+), 108 deletions(-) rename plugins/KeyboardioHID/avr/variants/{hid_descriptors/hid_descriptors.h => leonardo_custom/pins_arduino.h} (64%) create mode 100644 plugins/KeyboardioHID/avr/variants/leonardo_gamepad/pins_arduino.h create mode 100644 plugins/KeyboardioHID/avr/variants/leonardo_no_usb/pins_arduino.h create mode 100644 plugins/KeyboardioHID/avr/variants/micro_custom/pins_arduino.h create mode 100644 plugins/KeyboardioHID/avr/variants/micro_gamepad/pins_arduino.h create mode 100644 plugins/KeyboardioHID/avr/variants/micro_no_usb/pins_arduino.h create mode 100644 plugins/KeyboardioHID/board.png create mode 100644 plugins/KeyboardioHID/usb-core.png diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 465ba746cf..1ca38f82eb 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -37,6 +37,7 @@ Installation ============ For Arduino Uno/Mega first install [HoodLoader2](https://github.com/NicoHood/HoodLoader2) on your 16u2 + the needed software files. +Make sure your HoodLoader2 software is up to date when you also update the HID-Project files. [HoodLoader1](https://github.com/NicoHood/HoodLoader) is only supported for legacy but will get a new use soon! For Arduino Micro/Leonardo ignore this step. @@ -57,30 +58,33 @@ How to use ### Micro/Leonardo + HoodLoader2 +**1. Select the new board via *Tools->Board->Arduino Leonardo HID-Project* for example.** +For HoodLoader2 select the HoodLoader 16u2 MCU. Ensure HoodLoader2 Software is up to date. + +![Board Selection Picture](board.png) + +**2. Select the USB-Core you want to use. You have 5 options here:** + +* Extended (Keyboard+Leds, Mouse+Absolute, Consumer, System) +* Gamepad (Keyboard+Leds, Mouse, Gamepad) +* Custom (Your custom configuration, see below) +* Default Core (Standard Arduino Core) +* No USB Core (No USB functions available, saves ram + flash) + +![USB-Core Selection Picture](usb-core.png) + +To create a custom HID report descriptor you can edit the file in *avr/variants/leonardo_custom/pins_arduino.h*. +Same for Micro and HoodLoader2. Not all HID reports are playing well together on all OS so I made these pre selections. +With the custom report you can try it out yourself. Everything you need should be in the pins_arduino.h file. + **You can compile all HID APIs but this doesn't mean that you can use them if no hid descriptor is set correctly.** Edit the *sketchbook/hardware/HID/avr/variants/hid_descriptors/hid_descriptors.h* to use the extended HID core. At the moment you have 3 options: Default, Gamepad or Extended. Extended should work for anything expect Gamepads. See the bug section below to find out more about working hid reports. Not all of them are playing well together. +Use the void HID_SendReport(uint8_t id, const void* data, int len); function to send hid reports with your custom HID-APIs. -Have a closer look at these lines: -``` cpp -// use this to enable the Keyboard Led functions -#define HID_KEYBOARD_LEDS_ENABLED - -// add your custom HID Report Descriptor here. -// you can use the pre defined reports as well -//#define EXTERN_HID_REPORT DEFAULT_HID_REPORT -#define EXTERN_HID_REPORT EXTENDED_HID_REPORT -//#define EXTERN_HID_REPORT GAMEPAD_HID_REPORT -``` - -You can also add your own descriptor with your own APIs. -Use the void HID_SendReport(uint8_t id, const void* data, int len); function to send hid reports. - -**Select your Arduino board under *Tools->Board->Arduino Leonardo/Micro Custom HID* to use the new HID-Core. -If you select the normal Leonardo/Micro entry you will automatically use the standard Arduino Core.** -**Try the Basic HID examples for each HID device. They are pretty much self explaining. +**3. Try the Basic HID examples for each HID device. They are pretty much self explaining. You can also see the *Projects/HID_Test* for an all in one example.** See *Project/USB-Serial* for a fully usable USB-Serial bridge and how to use the new Serial functions. @@ -215,6 +219,7 @@ Version History * Separated USB-Core in its own folder * Added HID Tables * USB-Serial now fully reprogrammable +* Easy USB-Core selection via Tools->USB-Core 2.0 Release (29.11.2014) * Added HoodLoader2 @@ -345,11 +350,10 @@ Include schematic - Arduino.h - USBAPI.h -> Arduino.h, USBDESC.h, USBCore.h - CDC.h -> Arduino.h, USBDESC.h, USBCore.h - - HID.h -> Arduino.h, USBDESC.h, USBCore.h, HID-API - - HID-API -> Keyboard.h, Mouse.h - - Keyboard.h -> Arduino.h - - Mouse.h -> Arduino.h - - [Other APIs].h -> Arduino.h + - HID.h -> Arduino.h, USBDESC.h, USBCore.h, HID-APIs(Keyboard.h, Mouse.h, etc) + - Keyboard.h -> Arduino.h + - Mouse.h -> Arduino.h + - [Other APIs].h -> Arduino.h - HIDTables.h HID.h contains all HID configuration. diff --git a/plugins/KeyboardioHID/avr/boards.txt b/plugins/KeyboardioHID/avr/boards.txt index ff9f9f9542..d03c5957ff 100644 --- a/plugins/KeyboardioHID/avr/boards.txt +++ b/plugins/KeyboardioHID/avr/boards.txt @@ -1,65 +1,103 @@ +#HID Project board definition file + +menu.usbcore=USB Core + ############################################################## -leonardo_extended.name=Arduino Leonardo Custom HID -leonardo_extended.vid.0=0x2341 -leonardo_extended.pid.0=0x0036 -leonardo_extended.vid.1=0x2341 -leonardo_extended.pid.1=0x8036 -leonardo_extended.upload.tool=arduino:avrdude -leonardo_extended.upload.protocol=avr109 -leonardo_extended.upload.maximum_size=28672 -leonardo_extended.upload.maximum_data_size=2560 -leonardo_extended.upload.speed=57600 -leonardo_extended.upload.disable_flushing=true -leonardo_extended.upload.use_1200bps_touch=true -leonardo_extended.upload.wait_for_upload_port=true +leonardoExtended.name=Arduino Leonardo HID-Project +leonardoExtended.vid.0=0x2341 +leonardoExtended.pid.0=0x0036 +leonardoExtended.vid.1=0x2341 +leonardoExtended.pid.1=0x8036 +leonardoExtended.upload.tool=arduino:avrdude +leonardoExtended.upload.protocol=avr109 +leonardoExtended.upload.maximum_size=28672 +leonardoExtended.upload.maximum_data_size=2560 +leonardoExtended.upload.speed=57600 +leonardoExtended.upload.disable_flushing=true +leonardoExtended.upload.use_1200bps_touch=true +leonardoExtended.upload.wait_for_upload_port=true -leonardo_extended.bootloader.tool=arduino:avrdude -leonardo_extended.bootloader.low_fuses=0xff -leonardo_extended.bootloader.high_fuses=0xd8 -leonardo_extended.bootloader.extended_fuses=0xcb -leonardo_extended.bootloader.file=arduino:caterina/Caterina-leonardo_extended.hex -leonardo_extended.bootloader.unlock_bits=0x3F -leonardo_extended.bootloader.lock_bits=0x2F +leonardoExtended.bootloader.tool=arduino:avrdude +leonardoExtended.bootloader.low_fuses=0xff +leonardoExtended.bootloader.high_fuses=0xd8 +leonardoExtended.bootloader.extended_fuses=0xcb +leonardoExtended.bootloader.file=arduino:caterina/Caterina-leonardo.hex +leonardoExtended.bootloader.unlock_bits=0x3F +leonardoExtended.bootloader.lock_bits=0x2F -leonardo_extended.build.mcu=atmega32u4 -leonardo_extended.build.f_cpu=16000000L -leonardo_extended.build.vid=0x2341 -leonardo_extended.build.pid=0x8036 -leonardo_extended.build.usb_product="Arduino Leonardo" -leonardo_extended.build.board=AVR_LEONARDO -leonardo_extended.build.core=arduino:hid -leonardo_extended.build.variant=leonardo_hid -leonardo_extended.build.extra_flags={build.usb_flags} +leonardoExtended.build.mcu=atmega32u4 +leonardoExtended.build.f_cpu=16000000L +leonardoExtended.build.vid=0x2341 +leonardoExtended.build.pid=0x8036 +leonardoExtended.build.usb_product="Arduino Leonardo" +leonardoExtended.build.board=AVR_LEONARDO +leonardoExtended.build.extra_flags={build.usb_flags} + +#USB core selection +#HID Project needs to be installed https://github.com/NicoHood/HID +#TODO change to HID:hid +leonardoExtended.menu.usbcore.hid=Serial + Extended HID +leonardoExtended.menu.usbcore.hid.build.variant=leonardo_hid +leonardoExtended.menu.usbcore.hid.build.core=arduino:hid +leonardoExtended.menu.usbcore.gamepad=Serial + Gamepad HID +leonardoExtended.menu.usbcore.gamepad.build.variant=leonardo_gamepad +leonardoExtended.menu.usbcore.gamepad.build.core=arduino:hid +leonardoExtended.menu.usbcore.custom=Serial + Custom HID +leonardoExtended.menu.usbcore.custom.build.variant=leonardo_custom +leonardoExtended.menu.usbcore.custom.build.core=arduino:hid +leonardoExtended.menu.usbcore.USB_CORE=Default Core +leonardoExtended.menu.usbcore.USB_CORE.build.variant=arduino:leonardo +leonardoExtended.menu.usbcore.USB_CORE.build.core=arduino:arduino +leonardoExtended.menu.usbcore.NO_USB=No USB functions +leonardoExtended.menu.usbcore.NO_USB.build.variant=leonardo_no_usb +leonardoExtended.menu.usbcore.NO_USB.build.core=arduino:hid ############################################################## -micro.name=Arduino Micro Custom HID -micro.upload.tool=arduino:avrdude -micro.upload.protocol=avr109 -micro.upload.maximum_size=28672 -micro.upload.maximum_data_size=2560 -micro.upload.speed=57600 -micro.upload.disable_flushing=true -micro.upload.use_1200bps_touch=true -micro.upload.wait_for_upload_port=true +microExtended.name=Arduino Micro HID-Project +microExtended.upload.tool=arduino:avrdude +microExtended.upload.protocol=avr109 +microExtended.upload.maximum_size=28672 +microExtended.upload.maximum_data_size=2560 +microExtended.upload.speed=57600 +microExtended.upload.disable_flushing=true +microExtended.upload.use_1200bps_touch=true +microExtended.upload.wait_for_upload_port=true + +microExtended.bootloader.tool=arduino:avrdude +microExtended.bootloader.low_fuses=0xff +microExtended.bootloader.high_fuses=0xd8 +microExtended.bootloader.extended_fuses=0xcb +microExtended.bootloader.file=arduino:caterina/Caterina-Micro.hex +microExtended.bootloader.unlock_bits=0x3F +microExtended.bootloader.lock_bits=0x2F -micro.bootloader.tool=arduino:avrdude -micro.bootloader.low_fuses=0xff -micro.bootloader.high_fuses=0xd8 -micro.bootloader.extended_fuses=0xcb -micro.bootloader.file=arduino:caterina/Caterina-Micro.hex -micro.bootloader.unlock_bits=0x3F -micro.bootloader.lock_bits=0x2F +microExtended.build.mcu=atmega32u4 +microExtended.build.f_cpu=16000000L +microExtended.build.vid=0x2341 +microExtended.build.pid=0x8037 +microExtended.build.usb_product="Arduino Micro" +microExtended.build.board=AVR_MICRO +microExtended.build.extra_flags={build.usb_flags} -micro.build.mcu=atmega32u4 -micro.build.f_cpu=16000000L -micro.build.vid=0x2341 -micro.build.pid=0x8037 -micro.build.usb_product="Arduino Micro" -micro.build.board=AVR_MICRO -micro.build.core=arduino:hid -micro.build.variant=micro_hid -micro.build.extra_flags={build.usb_flags} +#USB core selection +#HID Project needs to be installed https://github.com/NicoHood/HID +#TODO change to HID:hid +microExtended.menu.usbcore.hid=Serial + Extended HID +microExtended.menu.usbcore.hid.build.variant=micro_hid +microExtended.menu.usbcore.hid.build.core=arduino:hid +microExtended.menu.usbcore.gamepad=Serial + Gamepad HID +microExtended.menu.usbcore.gamepad.build.variant=micro_gamepad +microExtended.menu.usbcore.gamepad.build.core=arduino:hid +microExtended.menu.usbcore.custom=Serial + Custom HID +microExtended.menu.usbcore.custom.build.variant=micro_custom +microExtended.menu.usbcore.custom.build.core=arduino:hid +microExtended.menu.usbcore.USB_CORE=Default Core +microExtended.menu.usbcore.USB_CORE.build.variant=arduino:micro +microExtended.menu.usbcore.USB_CORE.build.core=arduino:arduino +microExtended.menu.usbcore.NO_USB=No USB functions +microExtended.menu.usbcore.NO_USB.build.variant=micro_no_usb +microExtended.menu.usbcore.NO_USB.build.core=arduino:hid ############################################################## \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h index 238ac799a3..2606e5a95e 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h @@ -45,8 +45,8 @@ THE SOFTWARE. #include "Arduino.h" -// for the extern HID descriptors -#include "pins_Arduino.h" +// for the extern HID descriptors + settings +#include "pins_arduino.h" // extern accessible led out report #if defined(HID_KEYBOARD_LEDS_ENABLED) @@ -80,6 +80,49 @@ extern uint8_t hid_keyboard_leds; #define HID_REPORTID_MOUSE_ABSOLUTE 7 #endif +// only include HIDAPIs if we have an USB AVR MCU. +// only enable specific APIs to throw an error if the hid report wasn't set +// The user can overwrite HID_SendReport() and manually include the APIs for a non USB AVR +// the include has to be done after the report IDs! + +#ifdef HID_ENABLE_ALL_APIS +// include all HID APIs +#define HID_MOUSE_API_ENABLE +#define HID_KEYBOARD_API_ENABLE +#define HID_CONSUMER_API_ENABLE +#define HID_SYSTEM_API_ENABLE +#define HID_GAMEPAD_API_ENABLE + +#elif !defined(EXTERN_HID_REPORT) +// by default enable mouse + keyboard api +#define HID_MOUSE_API_ENABLE +#define HID_KEYBOARD_API_ENABLE +#endif + +#ifdef USBCON + +#ifdef HID_MOUSE_API_ENABLE +#include "Mouse.h" +#endif + +#ifdef HID_KEYBOARD_API_ENABLE +#include "Keyboard.h" +#endif + +#ifdef HID_CONSUMER_API_ENABLE +#include "Consumer.h" +#endif + +#ifdef HID_SYSTEM_API_ENABLE +#include "System.h" +#endif + +#ifdef HID_GAMEPAD_API_ENABLE +#include "Gamepad.h" +#endif + +#endif + // HID reports // Report IDs and the report itself can be overwritten by the pins_arduino.h @@ -347,9 +390,6 @@ HID_REPORT_MOUSE(HID_REPORTID_MOUSE) #include "USBDesc.h" #include "USBCore.h" -// only include HIDAPI if we have an USB AVR MCU. -// The use can overwrite HID_SendReport() and manually include the APIs. -#include "HIDAPI.h" //================================================================================ //================================================================================ diff --git a/plugins/KeyboardioHID/avr/platform.txt b/plugins/KeyboardioHID/avr/platform.txt index 8887bd75a4..c1dae047af 100644 --- a/plugins/KeyboardioHID/avr/platform.txt +++ b/plugins/KeyboardioHID/avr/platform.txt @@ -7,5 +7,6 @@ # https://github.com/arduino/Arduino/wiki/Arduino-Hardware-Cores-migration-guide-from-1.0-to-1.6 # https://github.com/NicoHood -name=Arduino Custom HID-Core + +name=HID Project USB-Core version=2.1 diff --git a/plugins/KeyboardioHID/avr/variants/hid_descriptors/hid_descriptors.h b/plugins/KeyboardioHID/avr/variants/leonardo_custom/pins_arduino.h similarity index 64% rename from plugins/KeyboardioHID/avr/variants/hid_descriptors/hid_descriptors.h rename to plugins/KeyboardioHID/avr/variants/leonardo_custom/pins_arduino.h index 72809e5fe8..5fed3ae274 100644 --- a/plugins/KeyboardioHID/avr/variants/hid_descriptors/hid_descriptors.h +++ b/plugins/KeyboardioHID/avr/variants/leonardo_custom/pins_arduino.h @@ -21,38 +21,38 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#define EXTENDED_HID_REPORT \ -HID_REPORT_KEYBOARD_LEDS(HID_REPORTID_KEYBOARD), \ -HID_REPORT_MOUSE(HID_REPORTID_MOUSE), \ -HID_REPORT_MOUSE_ABSOLUTE(HID_REPORTID_MOUSE_ABSOLUTE), \ -HID_REPORT_CONSUMERCONTROL(HID_REPORTID_CONSUMERCONTROL), \ -HID_REPORT_SYSTEMCONTROL(HID_REPORTID_SYSTEMCONTROL) - -#define GAMEPAD_HID_REPORT \ -HID_REPORT_KEYBOARD_LEDS(HID_REPORTID_KEYBOARD), \ -HID_REPORT_MOUSE(HID_REPORTID_MOUSE), \ -HID_REPORT_GAMEPAD(HID_REPORTID_GAMEPAD) +// include the standard leonardo board definition file +#include <../../variants/leonardo/pins_arduino.h> //================================================================================ -// Settings +// HID Settings //================================================================================ // use this to enable the Keyboard Led functions #define HID_KEYBOARD_LEDS_ENABLED -// add your custom HID Report Descriptor here. -// you can use the pre defined reports as well -//#define EXTERN_HID_REPORT DEFAULT_HID_REPORT -#define EXTERN_HID_REPORT EXTENDED_HID_REPORT -//#define EXTERN_HID_REPORT GAMEPAD_HID_REPORT +// add your custom report here: +#define EXTERN_HID_REPORT \ +HID_REPORT_KEYBOARD_LEDS(HID_REPORTID_KEYBOARD), \ +HID_REPORT_MOUSE(HID_REPORTID_MOUSE) +// activate your custom HID-APIs here: +#define HID_MOUSE_API_ENABLE +#define HID_KEYBOARD_API_ENABLE +//#define HID_CONSUMER_API_ENABLE +//#define HID_SYSTEM_API_ENABLE +//#define HID_GAMEPAD_API_ENABLE -// Keep in mind that changing the ids or reports might confuse your OS -// Then you might need to reinstall all drivers or change the USB PID -// Mouse Abs only works with a System report and without Gamepad -// Gamepads can causes some recognition Problems with some OS -// RAW HID seems to not works properly in a multireport -// Currently available pre defined reports: +/* +You can use the pre defined reports as well. +Keep in mind that changing the ids or reports might confuse your OS. +Then you might need to reinstall all drivers or change the USB PID. +Mouse Abs only works with a System report together. +Gamepad and Mouse Abs dont work together. +Gamepads can causes some recognition problems with some OS. +RAW HID seems to not works properly in a multireport. +Currently available pre defined reports : +*/ //HID_REPORT_KEYBOARD_LEDS(HID_REPORTID_KEYBOARD), //HID_REPORT_KEYBOARD_KEYS(HID_REPORTID_KEYBOARD), diff --git a/plugins/KeyboardioHID/avr/variants/leonardo_gamepad/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/leonardo_gamepad/pins_arduino.h new file mode 100644 index 0000000000..738c80eff5 --- /dev/null +++ b/plugins/KeyboardioHID/avr/variants/leonardo_gamepad/pins_arduino.h @@ -0,0 +1,45 @@ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +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 the standard leonardo board definition file +#include <../../variants/leonardo/pins_arduino.h> + +//================================================================================ +// HID Settings +//================================================================================ + +// use this to enable the Keyboard Led functions +#define HID_KEYBOARD_LEDS_ENABLED + +#define GAMEPAD_HID_REPORT \ +HID_REPORT_KEYBOARD_LEDS(HID_REPORTID_KEYBOARD), \ +HID_REPORT_MOUSE(HID_REPORTID_MOUSE), \ +HID_REPORT_GAMEPAD(HID_REPORTID_GAMEPAD) + +// add your custom report here: +#define EXTERN_HID_REPORT GAMEPAD_HID_REPORT + +// activate your custom HID-APIs here: +#define HID_MOUSE_API_ENABLE +#define HID_KEYBOARD_API_ENABLE +#define HID_GAMEPAD_API_ENABLE \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/variants/leonardo_hid/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/leonardo_hid/pins_arduino.h index adf6c2a368..4d8fbc42c8 100644 --- a/plugins/KeyboardioHID/avr/variants/leonardo_hid/pins_arduino.h +++ b/plugins/KeyboardioHID/avr/variants/leonardo_hid/pins_arduino.h @@ -21,5 +21,28 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +// include the standard leonardo board definition file #include <../../variants/leonardo/pins_arduino.h> -#include "../hid_descriptors/hid_descriptors.h" \ No newline at end of file + +//================================================================================ +// HID Settings +//================================================================================ + +// use this to enable the Keyboard Led functions +#define HID_KEYBOARD_LEDS_ENABLED + +#define EXTENDED_HID_REPORT \ +HID_REPORT_KEYBOARD_LEDS(HID_REPORTID_KEYBOARD), \ +HID_REPORT_MOUSE(HID_REPORTID_MOUSE), \ +HID_REPORT_MOUSE_ABSOLUTE(HID_REPORTID_MOUSE_ABSOLUTE), \ +HID_REPORT_CONSUMERCONTROL(HID_REPORTID_CONSUMERCONTROL), \ +HID_REPORT_SYSTEMCONTROL(HID_REPORTID_SYSTEMCONTROL) + +// add your custom report here: +#define EXTERN_HID_REPORT EXTENDED_HID_REPORT + +// activate your custom HID-APIs here: +#define HID_MOUSE_API_ENABLE +#define HID_KEYBOARD_API_ENABLE +#define HID_CONSUMER_API_ENABLE +#define HID_SYSTEM_API_ENABLE diff --git a/plugins/KeyboardioHID/avr/variants/leonardo_no_usb/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/leonardo_no_usb/pins_arduino.h new file mode 100644 index 0000000000..53dfb82032 --- /dev/null +++ b/plugins/KeyboardioHID/avr/variants/leonardo_no_usb/pins_arduino.h @@ -0,0 +1,28 @@ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +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 the standard leonardo board definition file +#include <../../variants/leonardo/pins_arduino.h> + +// deactivate usb functions +#undef USBCON diff --git a/plugins/KeyboardioHID/avr/variants/micro_custom/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/micro_custom/pins_arduino.h new file mode 100644 index 0000000000..4e7ff4c602 --- /dev/null +++ b/plugins/KeyboardioHID/avr/variants/micro_custom/pins_arduino.h @@ -0,0 +1,64 @@ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +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 the standard micro board definition file +#include <../../variants/micro/pins_arduino.h> + +//================================================================================ +// HID Settings +//================================================================================ + +// use this to enable the Keyboard Led functions +#define HID_KEYBOARD_LEDS_ENABLED + +// add your custom report here: +#define EXTERN_HID_REPORT \ +HID_REPORT_KEYBOARD_LEDS(HID_REPORTID_KEYBOARD), \ +HID_REPORT_MOUSE(HID_REPORTID_MOUSE) + +// activate your custom HID-APIs here: +#define HID_MOUSE_API_ENABLE +#define HID_KEYBOARD_API_ENABLE +//#define HID_CONSUMER_API_ENABLE +//#define HID_SYSTEM_API_ENABLE +//#define HID_GAMEPAD_API_ENABLE + +/* +You can use the pre defined reports as well. +Keep in mind that changing the ids or reports might confuse your OS. +Then you might need to reinstall all drivers or change the USB PID. +Mouse Abs only works with a System report together. +Gamepad and Mouse Abs dont work together. +Gamepads can causes some recognition problems with some OS. +RAW HID seems to not works properly in a multireport. +Currently available pre defined reports : +*/ + +//HID_REPORT_KEYBOARD_LEDS(HID_REPORTID_KEYBOARD), +//HID_REPORT_KEYBOARD_KEYS(HID_REPORTID_KEYBOARD), +//HID_REPORT_MOUSE(HID_REPORTID_MOUSE), +//HID_REPORT_MOUSE_ABSOLUTE(HID_REPORTID_MOUSE_ABSOLUTE), +////HID_REPORT_RAWHID(HID_REPORTID_RAWHID), // not working at the moment +//HID_REPORT_CONSUMERCONTROL(HID_REPORTID_CONSUMERCONTROL), +//HID_REPORT_SYSTEMCONTROL(HID_REPORTID_SYSTEMCONTROL), +//HID_REPORT_GAMEPAD(HID_REPORTID_GAMEPAD), \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/variants/micro_gamepad/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/micro_gamepad/pins_arduino.h new file mode 100644 index 0000000000..54a65b74a7 --- /dev/null +++ b/plugins/KeyboardioHID/avr/variants/micro_gamepad/pins_arduino.h @@ -0,0 +1,45 @@ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +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 the standard micro board definition file +#include <../../variants/micro/pins_arduino.h> + +//================================================================================ +// HID Settings +//================================================================================ + +// use this to enable the Keyboard Led functions +#define HID_KEYBOARD_LEDS_ENABLED + +#define GAMEPAD_HID_REPORT \ +HID_REPORT_KEYBOARD_LEDS(HID_REPORTID_KEYBOARD), \ +HID_REPORT_MOUSE(HID_REPORTID_MOUSE), \ +HID_REPORT_GAMEPAD(HID_REPORTID_GAMEPAD) + +// add your custom report here: +#define EXTERN_HID_REPORT GAMEPAD_HID_REPORT + +// activate your custom HID-APIs here: +#define HID_MOUSE_API_ENABLE +#define HID_KEYBOARD_API_ENABLE +#define HID_GAMEPAD_API_ENABLE \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/variants/micro_hid/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/micro_hid/pins_arduino.h index eecbe30681..b687abdf0a 100644 --- a/plugins/KeyboardioHID/avr/variants/micro_hid/pins_arduino.h +++ b/plugins/KeyboardioHID/avr/variants/micro_hid/pins_arduino.h @@ -21,5 +21,28 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +// include the standard micro board definition file #include <../../variants/micro/pins_arduino.h> -#include "../hid_descriptors/hid_descriptors.h" \ No newline at end of file + +//================================================================================ +// HID Settings +//================================================================================ + +// use this to enable the Keyboard Led functions +#define HID_KEYBOARD_LEDS_ENABLED + +#define EXTENDED_HID_REPORT \ +HID_REPORT_KEYBOARD_LEDS(HID_REPORTID_KEYBOARD), \ +HID_REPORT_MOUSE(HID_REPORTID_MOUSE), \ +HID_REPORT_MOUSE_ABSOLUTE(HID_REPORTID_MOUSE_ABSOLUTE), \ +HID_REPORT_CONSUMERCONTROL(HID_REPORTID_CONSUMERCONTROL), \ +HID_REPORT_SYSTEMCONTROL(HID_REPORTID_SYSTEMCONTROL) + +// add your custom report here: +#define EXTERN_HID_REPORT EXTENDED_HID_REPORT + +// activate your custom HID-APIs here: +#define HID_MOUSE_API_ENABLE +#define HID_KEYBOARD_API_ENABLE +#define HID_CONSUMER_API_ENABLE +#define HID_SYSTEM_API_ENABLE \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/variants/micro_no_usb/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/micro_no_usb/pins_arduino.h new file mode 100644 index 0000000000..43f444c010 --- /dev/null +++ b/plugins/KeyboardioHID/avr/variants/micro_no_usb/pins_arduino.h @@ -0,0 +1,28 @@ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +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 the standard micro board definition file +#include <../../variants/micro/pins_arduino.h> + +// deactivate usb functions +#undef USBCON diff --git a/plugins/KeyboardioHID/board.png b/plugins/KeyboardioHID/board.png new file mode 100644 index 0000000000000000000000000000000000000000..7ceebc06a547288c080e167729c7d905368c679f GIT binary patch literal 27786 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 literal 0 HcmV?d00001 From 0345fb4ebb2a2aff1dc7151f2309d4e4874b8502 Mon Sep 17 00:00:00 2001 From: Nico Date: Sat, 3 Jan 2015 19:14:36 +0100 Subject: [PATCH 107/602] Fixed HID_SendReport() prototype workaround --- plugins/KeyboardioHID/Readme.md | 13 +-- .../avr/cores/hid/USB-Core/Consumer.h | 3 - .../avr/cores/hid/USB-Core/Gamepad.h | 3 - .../avr/cores/hid/USB-Core/HID.h | 87 ++++++++++--------- .../avr/cores/hid/USB-Core/Keyboard.h | 3 - .../avr/cores/hid/USB-Core/Mouse.h | 3 - .../avr/cores/hid/USB-Core/System.h | 3 - 7 files changed, 47 insertions(+), 68 deletions(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 1ca38f82eb..005e36d9eb 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -59,7 +59,7 @@ How to use ### Micro/Leonardo + HoodLoader2 **1. Select the new board via *Tools->Board->Arduino Leonardo HID-Project* for example.** -For HoodLoader2 select the HoodLoader 16u2 MCU. Ensure HoodLoader2 Software is up to date. +For HoodLoader2 select the 16u2 MCU. Ensure HoodLoader2 board definition files are up to date. ![Board Selection Picture](board.png) @@ -73,17 +73,10 @@ For HoodLoader2 select the HoodLoader 16u2 MCU. Ensure HoodLoader2 Software is u ![USB-Core Selection Picture](usb-core.png) -To create a custom HID report descriptor you can edit the file in *avr/variants/leonardo_custom/pins_arduino.h*. +To create a **custom HID report descriptor** you can edit the file in *avr/variants/leonardo_custom/pins_arduino.h*. Same for Micro and HoodLoader2. Not all HID reports are playing well together on all OS so I made these pre selections. With the custom report you can try it out yourself. Everything you need should be in the pins_arduino.h file. -**You can compile all HID APIs but this doesn't mean that you can use them if no hid descriptor is set correctly.** -Edit the *sketchbook/hardware/HID/avr/variants/hid_descriptors/hid_descriptors.h* to use the extended HID core. -At the moment you have 3 options: Default, Gamepad or Extended. Extended should work for anything expect Gamepads. -See the bug section below to find out more about working hid reports. Not all of them are playing well together. -Use the void HID_SendReport(uint8_t id, const void* data, int len); function to send hid reports with your custom HID-APIs. - - **3. Try the Basic HID examples for each HID device. They are pretty much self explaining. You can also see the *Projects/HID_Test* for an all in one example.** @@ -168,6 +161,7 @@ Generalize HID key definitions via HIDTables for example? update Burning via ISP (advanced) Test with Android phone (HL1) "Emulate" HL1 protocol +test no usb function with leonardo (usb workaround?) ``` @@ -176,7 +170,6 @@ Known Bugs * See Hoodloader1+2 repositories for HoodLoader1+2 related Bugs/Issues. * Mouse Abs only works with system report under special circumstances. * Gamepad + Mouse Abs doesnt work together -* Fix HID_SendReport() prototype workaround in HID-APIs * Core selection in boards.txt is not working * Do not name the Arduino Sketch 'Mouse.ino' or 'Keyboard.ino' etc. Your Arduino IDE will output errors then if you double click the file and try to compile. diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Consumer.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Consumer.h index 22617ab63c..1cc9dae750 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Consumer.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Consumer.h @@ -27,9 +27,6 @@ THE SOFTWARE. // to access the HID_SendReport via USBAPI.h and report number #include "Arduino.h" -//TODO workaround to access the weak sending function -void HID_SendReport(uint8_t id, const void* data, int len); - //================================================================================ // Consumer //================================================================================ diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.h index 03f9c08ab3..3bd4b5d62d 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.h @@ -27,9 +27,6 @@ THE SOFTWARE. // to access the HID_SendReport via USBAPI.h and report number #include "Arduino.h" -//TODO workaround to access the weak sending function -void HID_SendReport(uint8_t id, const void* data, int len); - //================================================================================ // Gamepad //================================================================================ diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h index 2606e5a95e..79a3fbedb6 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h @@ -80,49 +80,6 @@ extern uint8_t hid_keyboard_leds; #define HID_REPORTID_MOUSE_ABSOLUTE 7 #endif -// only include HIDAPIs if we have an USB AVR MCU. -// only enable specific APIs to throw an error if the hid report wasn't set -// The user can overwrite HID_SendReport() and manually include the APIs for a non USB AVR -// the include has to be done after the report IDs! - -#ifdef HID_ENABLE_ALL_APIS -// include all HID APIs -#define HID_MOUSE_API_ENABLE -#define HID_KEYBOARD_API_ENABLE -#define HID_CONSUMER_API_ENABLE -#define HID_SYSTEM_API_ENABLE -#define HID_GAMEPAD_API_ENABLE - -#elif !defined(EXTERN_HID_REPORT) -// by default enable mouse + keyboard api -#define HID_MOUSE_API_ENABLE -#define HID_KEYBOARD_API_ENABLE -#endif - -#ifdef USBCON - -#ifdef HID_MOUSE_API_ENABLE -#include "Mouse.h" -#endif - -#ifdef HID_KEYBOARD_API_ENABLE -#include "Keyboard.h" -#endif - -#ifdef HID_CONSUMER_API_ENABLE -#include "Consumer.h" -#endif - -#ifdef HID_SYSTEM_API_ENABLE -#include "System.h" -#endif - -#ifdef HID_GAMEPAD_API_ENABLE -#include "Gamepad.h" -#endif - -#endif - // HID reports // Report IDs and the report itself can be overwritten by the pins_arduino.h @@ -408,4 +365,48 @@ void HID_SendReport(uint8_t id, const void* data, int len); #endif /* if defined(USBCON) */ + +// only include HIDAPIs if we have an USB AVR MCU. +// only enable specific APIs to throw an error if the hid report wasn't set +// The user can overwrite HID_SendReport() and manually include the APIs for a non USB AVR +// the include has to be done at the end so that the HID-APIs see the report ids and the send prototype. + +#ifdef HID_ENABLE_ALL_APIS +// include all HID APIs +#define HID_MOUSE_API_ENABLE +#define HID_KEYBOARD_API_ENABLE +#define HID_CONSUMER_API_ENABLE +#define HID_SYSTEM_API_ENABLE +#define HID_GAMEPAD_API_ENABLE + +#elif !defined(EXTERN_HID_REPORT) +// by default enable mouse + keyboard api +#define HID_MOUSE_API_ENABLE +#define HID_KEYBOARD_API_ENABLE +#endif + +#ifdef USBCON + +#ifdef HID_MOUSE_API_ENABLE +#include "Mouse.h" +#endif + +#ifdef HID_KEYBOARD_API_ENABLE +#include "Keyboard.h" +#endif + +#ifdef HID_CONSUMER_API_ENABLE +#include "Consumer.h" +#endif + +#ifdef HID_SYSTEM_API_ENABLE +#include "System.h" +#endif + +#ifdef HID_GAMEPAD_API_ENABLE +#include "Gamepad.h" +#endif + +#endif + #endif \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h index 11ab19fd30..5f405a545c 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h @@ -46,9 +46,6 @@ THE SOFTWARE. // to access the HID_SendReport via USBAPI.h, report number and the Print class #include "Arduino.h" -//TODO workaround to access the weak sending function -void HID_SendReport(uint8_t id, const void* data, int len); - //================================================================================ //================================================================================ // Keyboard diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.h index 8fabdca613..05e48c95ff 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.h @@ -46,9 +46,6 @@ THE SOFTWARE. // to access the HID_SendReport via USBAPI.h and report number #include "Arduino.h" -//TODO workaround to access the weak sending function -void HID_SendReport(uint8_t id, const void* data, int len); - //================================================================================ //================================================================================ // Mouse diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.h index fd1b7dd47c..b47f148c0a 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.h @@ -27,9 +27,6 @@ THE SOFTWARE. // to access the HID_SendReport via USBAPI.h and report number #include "Arduino.h" -//TODO workaround to access the weak sending function -void HID_SendReport(uint8_t id, const void* data, int len); - //================================================================================ // System //================================================================================ From 8c54856874f4384907044935768cbbcb679a4e2a Mon Sep 17 00:00:00 2001 From: Nico Date: Sat, 3 Jan 2015 19:20:52 +0100 Subject: [PATCH 108/602] Improved changelog --- plugins/KeyboardioHID/Readme.md | 36 +++++++++++++++++---------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 005e36d9eb..bf6928047b 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -77,8 +77,8 @@ To create a **custom HID report descriptor** you can edit the file in *avr/varia Same for Micro and HoodLoader2. Not all HID reports are playing well together on all OS so I made these pre selections. With the custom report you can try it out yourself. Everything you need should be in the pins_arduino.h file. -**3. Try the Basic HID examples for each HID device. They are pretty much self explaining. -You can also see the *Projects/HID_Test* for an all in one example.** +**3. Try the Basic HID examples for each HID device. They are pretty much self explaining.** +You can also see the *Projects/HID_Test* for an all in one example. See *Project/USB-Serial* for a fully usable USB-Serial bridge and how to use the new Serial functions. In the CDC.h you can also see the new Control Line functions for advanced users. @@ -224,40 +224,40 @@ Version History * Reworked the whole library structure again 1.8 Beta Release (26.08.2014) -* Changes in the Hoodloader: - * **Huge improvements**, see [Hoodloader repository](https://github.com/NicoHood/Hoodloader) +* Changes in the Hoodloader1: + * **Huge improvements**, see Hoodloader1 repository * Reworked the whole library, easy installation now * HID fixes for Media Keys/Ubuntu * Removed Joystick, added 4 Gamepads 1.7.3 Beta Release (10.08.2014) -* Changes in the Hoodloader: +* Changes in the Hoodloader1: * Fixed HID flush bug (1.6 - 1.7.2) 1.7.2 Beta Release (10.08.2014) -* Changes in the Hoodloader: +* Changes in the Hoodloader1: * Added Lite version for 8u2 * Added Versions that show up as Uno/Mega (not recommended) * Makefile and structure changes 1.7.1 Beta Release (10.08.2014) -* Changes in the Hoodloader: +* Changes in the Hoodloader1: * Fixed HID deactivation bug 1.7 Beta Release (10.08.2014) -* Changes in the Hoodloader: - * Works as ISP now. See the [Hoodloader Repository](https://github.com/NicoHood/Hoodloader) for more information. +* Changes in the Hoodloader1: + * Works as ISP now. See Hoodloader1 Repository for more information. * Exceeded 8kb limit. For flashing a 8u2 use v1.6 please! * Changed Readme text 1.6 Beta Release (09.08.2014) -* Bugfixes in the Hoodloader: +* Bugfixes in the Hoodloader1: * Changed HID management (not blocking that much, faster) * added RawHID in/out (HID to Serial) * Added RawHID Class and example 1.5 Beta Release (21.07.2014) -* Moved Hoodloader source to a [separate Github page](https://github.com/NicoHood/Hoodloader) +* Moved Hoodloader1 source to a separate Github page * Bugfixes in the Hoodloader: * Firmware is still available here * Overall a lot of ram improvements, now with a big global union of ram @@ -277,7 +277,7 @@ Version History * #define Bugfix in USBAPI.h 1.4 Beta Release (10.07.2014) -* Bugfixes in the Hoodloader: +* Bugfixes in the Hoodloader1: * Added Lite Version with less ram usage * Changed PIDs, edited driver file * merged v1.0.x and v1.5.x together (both are compatible!) @@ -285,15 +285,17 @@ Version History * added Tutorials 1.3 Beta Release (01.07.2014) -* Bugfixes in the Hoodloader: - * Improved ram usage (you can get even better but that messes up code and increases flash) +* Bugfixes in the Hoodloader1: + * Improved ram usage * **Important NHP fix inside the HID Class for Uno/Mega** 1.2 Beta Release (22.06.2014) * Added 1.0.x/1.5.x support -* Bugfixes in the Hoodloader: - * Sometimes HID Devices weren't updating when using more than 1 Device (set forcewrite to true) - * Fast updates crashed the bootloader (too much ram usage, set CDC buffer from 128b to 100b each) +* Bugfixes in the Hoodloader1: + * Sometimes HID Devices weren't updating + when using more than 1 Device (set forcewrite to true) + * Fast updates crashed the bootloader + (too much ram usage, set CDC buffer from 128b to 100b each) * Minor file structure changes 1.1 Beta Release (05.06.2014) From 48ec9138ae543ce53f153d165eef3a3a81e06abf Mon Sep 17 00:00:00 2001 From: Nico Date: Thu, 8 Jan 2015 17:44:04 +0100 Subject: [PATCH 109/602] Added Raw HID, made Custom reports more easy Also added a new picture and a keyboard + mouse report definition --- plugins/KeyboardioHID/Readme.md | 2 + plugins/KeyboardioHID/avr/boards.txt | 68 ++++++++++++++- .../avr/cores/hid/USB-Core/HID.cpp | 25 +++++- .../avr/cores/hid/USB-Core/HID.h | 60 +++++++++---- .../avr/cores/hid/USB-Core/Keyboard.h | 14 +++- .../avr/cores/hid/USB-Core/Mouse.h | 13 +++ .../avr/cores/hid/USB-Core/RawHID.cpp | 30 +++++++ .../avr/cores/hid/USB-Core/RawHID.h | 79 ++++++++++++++++++ .../variants/leonardo_custom/pins_arduino.h | 52 +++++++++++- .../variants/leonardo_gamepad/pins_arduino.h | 24 ++---- .../avr/variants/leonardo_hid/pins_arduino.h | 27 ++---- .../avr/variants/micro_custom/pins_arduino.h | 52 +++++++++++- .../avr/variants/micro_gamepad/pins_arduino.h | 24 ++---- .../avr/variants/micro_hid/pins_arduino.h | 27 ++---- .../HoodLoader1_API_Legacy.ino | 2 + plugins/KeyboardioHID/hid-core.png | Bin 0 -> 34248 bytes 16 files changed, 405 insertions(+), 94 deletions(-) create mode 100644 plugins/KeyboardioHID/avr/cores/hid/USB-Core/RawHID.cpp create mode 100644 plugins/KeyboardioHID/avr/cores/hid/USB-Core/RawHID.h create mode 100644 plugins/KeyboardioHID/hid-core.png diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index bf6928047b..5cf7295ec6 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -46,6 +46,7 @@ Make sure you use Arduino IDE 1.5.8 or newer. You don't have to modify the origi At the moment you have to move the cores/hid folder into your Arduino installation *arduino-1.6.0/hardware/arduino/avr/cores/hid* because of a bug in the IDE. +![HID Folder Picture](hid-core.png) **Your sketchbook folder should look like this:** ![Installation Picture](installation.png) @@ -208,6 +209,7 @@ Version History * Added Keycode functions in Keyboard API * Inlined a lot of the HID API functions to save flash * Added Gamepad +* Added RawHID API (but RawHID itself isnt working still) * Added USB Wakeup support * Separated USB-Core in its own folder * Added HID Tables diff --git a/plugins/KeyboardioHID/avr/boards.txt b/plugins/KeyboardioHID/avr/boards.txt index d03c5957ff..43f101d930 100644 --- a/plugins/KeyboardioHID/avr/boards.txt +++ b/plugins/KeyboardioHID/avr/boards.txt @@ -100,4 +100,70 @@ microExtended.menu.usbcore.NO_USB=No USB functions microExtended.menu.usbcore.NO_USB.build.variant=micro_no_usb microExtended.menu.usbcore.NO_USB.build.core=arduino:hid -############################################################## \ No newline at end of file +############################################################## + +uno.name=Arduino Uno HID-Project + +uno.vid.0=0x2341 +uno.pid.0=0x0043 +uno.vid.1=0x2341 +uno.pid.1=0x0001 + +uno.upload.tool=arduino:avrdude +uno.upload.protocol=arduino +uno.upload.maximum_size=32256 +uno.upload.maximum_data_size=2048 +uno.upload.speed=115200 + +uno.bootloader.tool=arduino:avrdude +uno.bootloader.low_fuses=0xFF +uno.bootloader.high_fuses=0xDE +uno.bootloader.extended_fuses=0x05 +uno.bootloader.unlock_bits=0x3F +uno.bootloader.lock_bits=0x0F +uno.bootloader.file=arduino:optiboot/optiboot_atmega328.hex + +uno.build.mcu=atmega328p +uno.build.f_cpu=16000000L +uno.build.board=AVR_UNO +uno.build.core=arduino:hid +uno.build.variant=arduino:standard + +############################################################## + + +mega.name=Arduino Mega 2560 HID-Project + +mega.vid.0=0x2341 +mega.pid.0=0x0010 +mega.vid.1=0x2341 +mega.pid.1=0x0042 + +mega.upload.tool=arduino:avrdude +mega.upload.maximum_data_size=8192 + +mega.bootloader.tool=arduino:avrdude +mega.bootloader.low_fuses=0xFF +mega.bootloader.unlock_bits=0x3F +mega.bootloader.lock_bits=0x0F + +mega.build.f_cpu=16000000L +mega.build.core=arduino:hid +mega.build.variant=arduino:mega +# default board may be overridden by the cpu menu +mega.build.board=AVR_MEGA2560 + +## Arduino Mega w/ ATmega2560 +## ------------------------- + +mega.upload.protocol=wiring +mega.upload.maximum_size=253952 +mega.upload.speed=115200 + +mega.bootloader.high_fuses=0xD8 +mega.bootloader.extended_fuses=0xFD +mega.bootloader.file=arduino:stk500v2/stk500boot_v2_mega2560.hex + +mega.build.mcu=atmega2560 +mega.build.board=AVR_MEGA2560 + diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.cpp b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.cpp index 587c0167fe..dac5d618a2 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.cpp +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.cpp @@ -54,7 +54,30 @@ const u8 _hidReportDescriptor[] = { #ifdef EXTERN_HID_REPORT EXTERN_HID_REPORT #else - DEFAULT_HID_REPORT + // use the hid descriptors of the selected hid devices +#ifdef HID_KEYBOARD_LEDS_ENABLE //TODO move keyboard below mouse? + HID_REPORT_KEYBOARD_LEDS(HID_REPORTID_KEYBOARD), +#elif defined(HID_KEYBOARD_KEYS_ENABLE) + HID_REPORT_KEYBOARD_KEYS(HID_REPORTID_KEYBOARD), +#endif +#if defined(HID_MOUSE_ENABLE) + HID_REPORT_MOUSE(HID_REPORTID_MOUSE), +#endif +#if defined(HID_MOUSE_ABSOLUTE_ENABLE) + HID_REPORT_MOUSE_ABSOLUTE(HID_REPORTID_MOUSE_ABSOLUTE), +#endif +#ifdef HID_RAWHID_ENABLE + HID_REPORT_RAWHID(HID_REPORTID_RAWHID), // not working at the moment +#endif +#ifdef HID_CONSUMER_ENABLE + HID_REPORT_CONSUMERCONTROL(HID_REPORTID_CONSUMERCONTROL), +#endif +#ifdef HID_SYSTEM_ENABLE + HID_REPORT_SYSTEMCONTROL(HID_REPORTID_SYSTEMCONTROL), +#endif +#ifdef HID_GAMEPAD_ENABLE + HID_REPORT_GAMEPAD(HID_REPORTID_GAMEPAD), +#endif #endif }; diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h index 79a3fbedb6..020f2eca68 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h @@ -48,6 +48,36 @@ THE SOFTWARE. // for the extern HID descriptors + settings #include "pins_arduino.h" +#ifndef EXTERN_HID_REPORT +// by default enable mouse + keyboard api +#define HID_MOUSE_ENABLE +#define HID_KEYBOARD_KEYS_ENABLE +#endif + +#ifdef HID_KEYBOARD_LEDS_ENABLE +// enable the Keyboard Led functions if the led report is selected +#define HID_KEYBOARD_LEDS_ENABLED +#endif + +#if defined(HID_MOUSE_ENABLE) || defined(HID_MOUSE_ABSOLUTE_ENABLE) +#define HID_MOUSE_API_ENABLE +#endif +#if defined(HID_KEYBOARD_LEDS_ENABLE) || defined(HID_KEYBOARD_KEYS_ENABLE) +#define HID_KEYBOARD_API_ENABLE +#endif +#ifdef HID_RAWHID_ENABLE +#define HID_RAWHID_API_ENABLE +#endif +#ifdef HID_CONSUMER_ENABLE +#define HID_CONSUMER_API_ENABLE +#endif +#ifdef HID_SYSTEM_ENABLE +#define HID_SYSTEM_API_ENABLE +#endif +#ifdef HID_GAMEPAD_ENABLE +#define HID_GAMEPAD_API_ENABLE +#endif + // extern accessible led out report #if defined(HID_KEYBOARD_LEDS_ENABLED) extern uint8_t hid_keyboard_leds; @@ -302,10 +332,18 @@ extern uint8_t hid_keyboard_leds; // note by NicoHood: RawHID might never work with multireports, because of OS problems // therefore we have to make it a single report with no idea. No other HID device will be supported then. +#ifndef RAWHID_USAGE_PAGE #define RAWHID_USAGE_PAGE 0xFFC0 // recommended: 0xFF00 to 0xFFFF +#endif +#ifndef RAWHID_USAGE #define RAWHID_USAGE 0x0C00 // recommended: 0x0100 to 0xFFFF +#endif +#ifndef RAWHID_TX_SIZE #define RAWHID_TX_SIZE (USB_EP_SIZE-1) +#endif +#ifndef RAWHID_RX_SIZE #define RAWHID_RX_SIZE (USB_EP_SIZE-1) +#endif #define LSB(_x) ((_x) & 0xFF) #define MSB(_x) ((_x) >> 8) @@ -331,18 +369,6 @@ extern uint8_t hid_keyboard_leds; 0xC0 /* end collection */ #endif -// default HID report descriptor -#ifdef HID_KEYBOARD_LEDS_ENABLED -#define DEFAULT_HID_REPORT \ -HID_REPORT_KEYBOARD_LEDS(HID_REPORTID_KEYBOARD), \ -HID_REPORT_MOUSE(HID_REPORTID_MOUSE) - -#else -#define DEFAULT_HID_REPORT \ -HID_REPORT_KEYBOARD_KEYS(HID_REPORTID_KEYBOARD), \ -HID_REPORT_MOUSE(HID_REPORTID_MOUSE) -#endif - #if defined(USBCON) #include "USBDesc.h" @@ -375,14 +401,10 @@ void HID_SendReport(uint8_t id, const void* data, int len); // include all HID APIs #define HID_MOUSE_API_ENABLE #define HID_KEYBOARD_API_ENABLE +#define HID_RAWHID_API_ENABLE #define HID_CONSUMER_API_ENABLE #define HID_SYSTEM_API_ENABLE #define HID_GAMEPAD_API_ENABLE - -#elif !defined(EXTERN_HID_REPORT) -// by default enable mouse + keyboard api -#define HID_MOUSE_API_ENABLE -#define HID_KEYBOARD_API_ENABLE #endif #ifdef USBCON @@ -395,6 +417,10 @@ void HID_SendReport(uint8_t id, const void* data, int len); #include "Keyboard.h" #endif +#ifdef HID_RAWHID_API_ENABLE +#include "RawHID.h" +#endif + #ifdef HID_CONSUMER_API_ENABLE #include "Consumer.h" #endif diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h index 5f405a545c..1bf159d4ad 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h @@ -143,13 +143,25 @@ THE SOFTWARE. #define RAW_KEYBOARD_SCROLL_LOCK 0x47 #define RAW_KEYBOARD_PAUSE 0x48 +typedef union{ + // Low level key report: up to 6 keys and shift, ctrl etc at once + uint8_t whole8[8]; + uint16_t whole16[8 / 2]; + uint32_t whole32[8 / 4]; + struct{ + uint8_t modifiers; + uint8_t reserved; + uint8_t keys[6]; + }; +} HID_KeyboardReport_Data_t; + // 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; +} KeyReport; //TODO typedef union above class Keyboard_ : public Print { diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.h index 05e48c95ff..ce57999afd 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.h @@ -59,6 +59,19 @@ THE SOFTWARE. // but the last 3 wont do anything from what I tested #define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE | MOUSE_PREV | MOUSE_NEXT) +typedef union{ + // mouse report: 8 buttons, position, wheel + uint8_t whole8[4]; + uint16_t whole16[4 / 2]; + uint32_t whole32[4 / 4]; + struct{ + uint8_t buttons; + int8_t xAxis; + int8_t yAxis; + int8_t wheel; + }; +} HID_MouseReport_Data_t; + class Mouse_ { private: diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/RawHID.cpp b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/RawHID.cpp new file mode 100644 index 0000000000..b5a168740a --- /dev/null +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/RawHID.cpp @@ -0,0 +1,30 @@ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +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 "RawHID.h" + +//================================================================================ +// RawHID +//================================================================================ + +RawHID_ RawHID; \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/RawHID.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/RawHID.h new file mode 100644 index 0000000000..bd31630f6b --- /dev/null +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/RawHID.h @@ -0,0 +1,79 @@ +/* +Copyright (c) 2014 NicoHood +See the readme for credit to other people. + +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 __RAWHIDAPI__ +#define __RAWHIDAPI__ + +// to access the HID_SendReport via USBAPI.h and report number +#include "Arduino.h" + +//================================================================================ +// RawHID +//================================================================================ + +typedef union{ +// a RAWHID_TX_SIZE byte buffer for rx or tx +uint8_t whole8[RAWHID_TX_SIZE]; +uint16_t whole16[RAWHID_TX_SIZE / 2]; +uint32_t whole32[RAWHID_TX_SIZE / 4]; +uint8_t buff[RAWHID_TX_SIZE]; +} HID_RawKeyboardReport_Data_t; + +class RawHID_ : public Print{ +public: + inline RawHID_(void){ + // empty + } + + inline void begin(void){ + // empty + } + + inline void end(void){ + // empty + } + + using Print::write; // to get the String version of write + inline size_t write(uint8_t b){ + write(&b, 1); + } + + inline size_t write(const uint8_t *buffer, size_t size){ + size_t bytesleft = size; + // first work through the buffer thats already there + while (bytesleft >= RAWHID_RX_SIZE){ + HID_SendReport(HID_REPORTID_RAWHID, &buffer[size - bytesleft], RAWHID_RX_SIZE); + bytesleft -= RAWHID_RX_SIZE; + } + // write down the other bytes and fill with zeros + if (bytesleft){ + uint8_t rest[RAWHID_RX_SIZE]; + memcpy(rest, &buffer[size - bytesleft], bytesleft); + memset(&rest[bytesleft], 0, RAWHID_RX_SIZE - bytesleft); + HID_SendReport(HID_REPORTID_RAWHID, &rest, RAWHID_RX_SIZE); + } + } +}; +extern RawHID_ RawHID; + +#endif \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/variants/leonardo_custom/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/leonardo_custom/pins_arduino.h index 5fed3ae274..c198ad0be0 100644 --- a/plugins/KeyboardioHID/avr/variants/leonardo_custom/pins_arduino.h +++ b/plugins/KeyboardioHID/avr/variants/leonardo_custom/pins_arduino.h @@ -28,20 +28,60 @@ THE SOFTWARE. // HID Settings //================================================================================ +/* +You have two options to enable/disbale hid functions: + +The nearly full automatic way which enables the specific hid report for you, +enables the specific hid api and also enables the keyboard led function if needed. + +The fully customizable variant where you can create your very own HID report. +You still can use the predefined hid reports or add you very own ones. +You have to enable the specific hid apis on your own then, also the keyboard led function. +*/ + +#define HID_AUTOMATIC +#define HID_CUSTOM_SETTINGS + +//================================================================================ +// Automatic +//================================================================================ + +#ifdef HID_AUTOMATIC +// pre selected hid reports with autoinclude of the api +#define HID_MOUSE_ENABLE // normal mouse with buttons + wheel +//#define HID_MOUSE_ABSOLUTE_ENABLE // only works with system and without gamepad +#define HID_KEYBOARD_LEDS_ENABLE // leds OR keys +//#define HID_KEYBOARD_KEYS_ENABLE +//#define HID_RAWHID_ENABLE // currently not working +//#define HID_CONSUMER_ENABLE +//#define HID_SYSTEM_ENABLE +//#define HID_GAMEPAD_ENABLE // only works without mouse absolute + +//================================================================================ +// Custom Settings +//================================================================================ + +#elif defined(HID_CUSTOM_SETTINGS) + +// default setting here shows a mouse + keyboard with no led function +// like in IDE 1.0.6/1.5.8 or lower + // use this to enable the Keyboard Led functions -#define HID_KEYBOARD_LEDS_ENABLED +//#define HID_KEYBOARD_LEDS_ENABLED // add your custom report here: #define EXTERN_HID_REPORT \ -HID_REPORT_KEYBOARD_LEDS(HID_REPORTID_KEYBOARD), \ +HID_REPORT_KEYBOARD_KEYS(HID_REPORTID_KEYBOARD), \ HID_REPORT_MOUSE(HID_REPORTID_MOUSE) // activate your custom HID-APIs here: #define HID_MOUSE_API_ENABLE #define HID_KEYBOARD_API_ENABLE +//#define HID_RAWHID_API_ENABLE //#define HID_CONSUMER_API_ENABLE //#define HID_SYSTEM_API_ENABLE //#define HID_GAMEPAD_API_ENABLE +//#define HID_ENABLE_ALL_APIS // enables all of the ones above /* You can use the pre defined reports as well. @@ -58,7 +98,11 @@ Currently available pre defined reports : //HID_REPORT_KEYBOARD_KEYS(HID_REPORTID_KEYBOARD), //HID_REPORT_MOUSE(HID_REPORTID_MOUSE), //HID_REPORT_MOUSE_ABSOLUTE(HID_REPORTID_MOUSE_ABSOLUTE), -////HID_REPORT_RAWHID(HID_REPORTID_RAWHID), // not working at the moment +//HID_REPORT_RAWHID(HID_REPORTID_RAWHID), //HID_REPORT_CONSUMERCONTROL(HID_REPORTID_CONSUMERCONTROL), //HID_REPORT_SYSTEMCONTROL(HID_REPORTID_SYSTEMCONTROL), -//HID_REPORT_GAMEPAD(HID_REPORTID_GAMEPAD), \ No newline at end of file +//HID_REPORT_GAMEPAD(HID_REPORTID_GAMEPAD), + +#else +#error Please select automatic or custom hid report in the pins_arduino.h! +#endif \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/variants/leonardo_gamepad/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/leonardo_gamepad/pins_arduino.h index 738c80eff5..85a19e2a89 100644 --- a/plugins/KeyboardioHID/avr/variants/leonardo_gamepad/pins_arduino.h +++ b/plugins/KeyboardioHID/avr/variants/leonardo_gamepad/pins_arduino.h @@ -28,18 +28,12 @@ THE SOFTWARE. // HID Settings //================================================================================ -// use this to enable the Keyboard Led functions -#define HID_KEYBOARD_LEDS_ENABLED - -#define GAMEPAD_HID_REPORT \ -HID_REPORT_KEYBOARD_LEDS(HID_REPORTID_KEYBOARD), \ -HID_REPORT_MOUSE(HID_REPORTID_MOUSE), \ -HID_REPORT_GAMEPAD(HID_REPORTID_GAMEPAD) - -// add your custom report here: -#define EXTERN_HID_REPORT GAMEPAD_HID_REPORT - -// activate your custom HID-APIs here: -#define HID_MOUSE_API_ENABLE -#define HID_KEYBOARD_API_ENABLE -#define HID_GAMEPAD_API_ENABLE \ No newline at end of file +// pre selected hid reports with autoinclude of the api +#define HID_MOUSE_ENABLE // normal mouse with buttons + wheel +//#define HID_MOUSE_ABSOLUTE_ENABLE // only works with system and without gamepad +#define HID_KEYBOARD_LEDS_ENABLE // leds OR keys +//#define HID_KEYBOARD_KEYS_ENABLE +//#define HID_RAWHID_ENABLE // currently not working +//#define HID_CONSUMER_ENABLE +//#define HID_SYSTEM_ENABLE +#define HID_GAMEPAD_ENABLE // only works without mouse absolute diff --git a/plugins/KeyboardioHID/avr/variants/leonardo_hid/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/leonardo_hid/pins_arduino.h index 4d8fbc42c8..22545bf75b 100644 --- a/plugins/KeyboardioHID/avr/variants/leonardo_hid/pins_arduino.h +++ b/plugins/KeyboardioHID/avr/variants/leonardo_hid/pins_arduino.h @@ -28,21 +28,12 @@ THE SOFTWARE. // HID Settings //================================================================================ -// use this to enable the Keyboard Led functions -#define HID_KEYBOARD_LEDS_ENABLED - -#define EXTENDED_HID_REPORT \ -HID_REPORT_KEYBOARD_LEDS(HID_REPORTID_KEYBOARD), \ -HID_REPORT_MOUSE(HID_REPORTID_MOUSE), \ -HID_REPORT_MOUSE_ABSOLUTE(HID_REPORTID_MOUSE_ABSOLUTE), \ -HID_REPORT_CONSUMERCONTROL(HID_REPORTID_CONSUMERCONTROL), \ -HID_REPORT_SYSTEMCONTROL(HID_REPORTID_SYSTEMCONTROL) - -// add your custom report here: -#define EXTERN_HID_REPORT EXTENDED_HID_REPORT - -// activate your custom HID-APIs here: -#define HID_MOUSE_API_ENABLE -#define HID_KEYBOARD_API_ENABLE -#define HID_CONSUMER_API_ENABLE -#define HID_SYSTEM_API_ENABLE +// pre selected hid reports with autoinclude of the api +#define HID_MOUSE_ENABLE // normal mouse with buttons + wheel +#define HID_MOUSE_ABSOLUTE_ENABLE // only works with system and without gamepad +#define HID_KEYBOARD_LEDS_ENABLE // leds OR keys +//#define HID_KEYBOARD_KEYS_ENABLE +//#define HID_RAWHID_ENABLE // currently not working +#define HID_CONSUMER_ENABLE +#define HID_SYSTEM_ENABLE +//#define HID_GAMEPAD_ENABLE // only works without mouse absolute diff --git a/plugins/KeyboardioHID/avr/variants/micro_custom/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/micro_custom/pins_arduino.h index 4e7ff4c602..1b6241f37e 100644 --- a/plugins/KeyboardioHID/avr/variants/micro_custom/pins_arduino.h +++ b/plugins/KeyboardioHID/avr/variants/micro_custom/pins_arduino.h @@ -28,20 +28,60 @@ THE SOFTWARE. // HID Settings //================================================================================ +/* +You have two options to enable/disbale hid functions: + +The nearly full automatic way which enables the specific hid report for you, +enables the specific hid api and also enables the keyboard led function if needed. + +The fully customizable variant where you can create your very own HID report. +You still can use the predefined hid reports or add you very own ones. +You have to enable the specific hid apis on your own then, also the keyboard led function. +*/ + +#define HID_AUTOMATIC +#define HID_CUSTOM_SETTINGS + +//================================================================================ +// Automatic +//================================================================================ + +#ifdef HID_AUTOMATIC +// pre selected hid reports with autoinclude of the api +#define HID_MOUSE_ENABLE // normal mouse with buttons + wheel +//#define HID_MOUSE_ABSOLUTE_ENABLE // only works with system and without gamepad +#define HID_KEYBOARD_LEDS_ENABLE // leds OR keys +//#define HID_KEYBOARD_KEYS_ENABLE +//#define HID_RAWHID_ENABLE // currently not working +//#define HID_CONSUMER_ENABLE +//#define HID_SYSTEM_ENABLE +//#define HID_GAMEPAD_ENABLE // only works without mouse absolute + +//================================================================================ +// Custom Settings +//================================================================================ + +#elif defined(HID_CUSTOM_SETTINGS) + +// default setting here shows a mouse + keyboard with no led function +// like in IDE 1.0.6/1.5.8 or lower + // use this to enable the Keyboard Led functions -#define HID_KEYBOARD_LEDS_ENABLED +//#define HID_KEYBOARD_LEDS_ENABLED // add your custom report here: #define EXTERN_HID_REPORT \ -HID_REPORT_KEYBOARD_LEDS(HID_REPORTID_KEYBOARD), \ +HID_REPORT_KEYBOARD_KEYS(HID_REPORTID_KEYBOARD), \ HID_REPORT_MOUSE(HID_REPORTID_MOUSE) // activate your custom HID-APIs here: #define HID_MOUSE_API_ENABLE #define HID_KEYBOARD_API_ENABLE +//#define HID_RAWHID_API_ENABLE //#define HID_CONSUMER_API_ENABLE //#define HID_SYSTEM_API_ENABLE //#define HID_GAMEPAD_API_ENABLE +//#define HID_ENABLE_ALL_APIS // enables all of the ones above /* You can use the pre defined reports as well. @@ -58,7 +98,11 @@ Currently available pre defined reports : //HID_REPORT_KEYBOARD_KEYS(HID_REPORTID_KEYBOARD), //HID_REPORT_MOUSE(HID_REPORTID_MOUSE), //HID_REPORT_MOUSE_ABSOLUTE(HID_REPORTID_MOUSE_ABSOLUTE), -////HID_REPORT_RAWHID(HID_REPORTID_RAWHID), // not working at the moment +//HID_REPORT_RAWHID(HID_REPORTID_RAWHID), //HID_REPORT_CONSUMERCONTROL(HID_REPORTID_CONSUMERCONTROL), //HID_REPORT_SYSTEMCONTROL(HID_REPORTID_SYSTEMCONTROL), -//HID_REPORT_GAMEPAD(HID_REPORTID_GAMEPAD), \ No newline at end of file +//HID_REPORT_GAMEPAD(HID_REPORTID_GAMEPAD), + +#else +#error Please select automatic or custom hid report in the pins_arduino.h! +#endif \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/variants/micro_gamepad/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/micro_gamepad/pins_arduino.h index 54a65b74a7..18a34979a6 100644 --- a/plugins/KeyboardioHID/avr/variants/micro_gamepad/pins_arduino.h +++ b/plugins/KeyboardioHID/avr/variants/micro_gamepad/pins_arduino.h @@ -28,18 +28,12 @@ THE SOFTWARE. // HID Settings //================================================================================ -// use this to enable the Keyboard Led functions -#define HID_KEYBOARD_LEDS_ENABLED - -#define GAMEPAD_HID_REPORT \ -HID_REPORT_KEYBOARD_LEDS(HID_REPORTID_KEYBOARD), \ -HID_REPORT_MOUSE(HID_REPORTID_MOUSE), \ -HID_REPORT_GAMEPAD(HID_REPORTID_GAMEPAD) - -// add your custom report here: -#define EXTERN_HID_REPORT GAMEPAD_HID_REPORT - -// activate your custom HID-APIs here: -#define HID_MOUSE_API_ENABLE -#define HID_KEYBOARD_API_ENABLE -#define HID_GAMEPAD_API_ENABLE \ No newline at end of file +// pre selected hid reports with autoinclude of the api +#define HID_MOUSE_ENABLE // normal mouse with buttons + wheel +//#define HID_MOUSE_ABSOLUTE_ENABLE // only works with system and without gamepad +#define HID_KEYBOARD_LEDS_ENABLE // leds OR keys +//#define HID_KEYBOARD_KEYS_ENABLE +//#define HID_RAWHID_ENABLE // currently not working +//#define HID_CONSUMER_ENABLE +//#define HID_SYSTEM_ENABLE +#define HID_GAMEPAD_ENABLE // only works without mouse absolute diff --git a/plugins/KeyboardioHID/avr/variants/micro_hid/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/micro_hid/pins_arduino.h index b687abdf0a..18ec7e144a 100644 --- a/plugins/KeyboardioHID/avr/variants/micro_hid/pins_arduino.h +++ b/plugins/KeyboardioHID/avr/variants/micro_hid/pins_arduino.h @@ -28,21 +28,12 @@ THE SOFTWARE. // HID Settings //================================================================================ -// use this to enable the Keyboard Led functions -#define HID_KEYBOARD_LEDS_ENABLED - -#define EXTENDED_HID_REPORT \ -HID_REPORT_KEYBOARD_LEDS(HID_REPORTID_KEYBOARD), \ -HID_REPORT_MOUSE(HID_REPORTID_MOUSE), \ -HID_REPORT_MOUSE_ABSOLUTE(HID_REPORTID_MOUSE_ABSOLUTE), \ -HID_REPORT_CONSUMERCONTROL(HID_REPORTID_CONSUMERCONTROL), \ -HID_REPORT_SYSTEMCONTROL(HID_REPORTID_SYSTEMCONTROL) - -// add your custom report here: -#define EXTERN_HID_REPORT EXTENDED_HID_REPORT - -// activate your custom HID-APIs here: -#define HID_MOUSE_API_ENABLE -#define HID_KEYBOARD_API_ENABLE -#define HID_CONSUMER_API_ENABLE -#define HID_SYSTEM_API_ENABLE \ No newline at end of file +// pre selected hid reports with autoinclude of the api +#define HID_MOUSE_ENABLE // normal mouse with buttons + wheel +#define HID_MOUSE_ABSOLUTE_ENABLE // only works with system and without gamepad +#define HID_KEYBOARD_LEDS_ENABLE // leds OR keys +//#define HID_KEYBOARD_KEYS_ENABLE +//#define HID_RAWHID_ENABLE // currently not working +#define HID_CONSUMER_ENABLE +#define HID_SYSTEM_ENABLE +//#define HID_GAMEPAD_ENABLE // only works without mouse absolute diff --git a/plugins/KeyboardioHID/examples/Projects/HoodLoader1_API_Legacy/HoodLoader1_API_Legacy.ino b/plugins/KeyboardioHID/examples/Projects/HoodLoader1_API_Legacy/HoodLoader1_API_Legacy.ino index 546a413e1e..b8f4fe90e8 100644 --- a/plugins/KeyboardioHID/examples/Projects/HoodLoader1_API_Legacy/HoodLoader1_API_Legacy.ino +++ b/plugins/KeyboardioHID/examples/Projects/HoodLoader1_API_Legacy/HoodLoader1_API_Legacy.ino @@ -27,6 +27,8 @@ See official documentation for more infos */ +#include "USB-Core/Keyboard.h" + // Serial to write Protocol data to. Default: Serial #define HID_SERIAL Serial #define SERIAL_HID_BAUD 115200 diff --git a/plugins/KeyboardioHID/hid-core.png b/plugins/KeyboardioHID/hid-core.png new file mode 100644 index 0000000000000000000000000000000000000000..4d3d0ce7c2641f710307c621b3e60bbcc31c874a GIT binary patch literal 34248 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 Date: Thu, 8 Jan 2015 22:18:22 +0100 Subject: [PATCH 110/602] Dev HoodLoader2 link added --- plugins/KeyboardioHID/Readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 5cf7295ec6..6ff2a97f85 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -37,6 +37,7 @@ Installation ============ For Arduino Uno/Mega first install [HoodLoader2](https://github.com/NicoHood/HoodLoader2) on your 16u2 + the needed software files. +Temporary use this dev version of the HoodLoader2: https://github.com/NicoHood/HoodLoader2/tree/dev Make sure your HoodLoader2 software is up to date when you also update the HID-Project files. [HoodLoader1](https://github.com/NicoHood/HoodLoader) is only supported for legacy but will get a new use soon! For Arduino Micro/Leonardo ignore this step. From 35da4b06d0d91e8baeb23a2773267ca87dc4c8b4 Mon Sep 17 00:00:00 2001 From: Nico Date: Fri, 9 Jan 2015 18:00:36 +0100 Subject: [PATCH 111/602] Fixed hid core installation It is no longer needed to manually move the hid core to your arduino installation due to a fix in platform.txt --- plugins/KeyboardioHID/Readme.md | 7 +- plugins/KeyboardioHID/avr/boards.txt | 22 +- plugins/KeyboardioHID/avr/platform.txt | 96 +++++ .../avr/variants/leonardo/pins_arduino.h | 361 ++++++++++++++++++ .../variants/leonardo_custom/pins_arduino.h | 2 +- .../variants/leonardo_gamepad/pins_arduino.h | 2 +- .../avr/variants/leonardo_hid/pins_arduino.h | 2 +- .../variants/leonardo_no_usb/pins_arduino.h | 2 +- .../avr/variants/micro/pins_arduino.h | 37 ++ .../avr/variants/micro_custom/pins_arduino.h | 2 +- .../avr/variants/micro_gamepad/pins_arduino.h | 2 +- .../avr/variants/micro_hid/pins_arduino.h | 2 +- .../avr/variants/micro_no_usb/pins_arduino.h | 2 +- plugins/KeyboardioHID/board.png | Bin 27786 -> 27753 bytes plugins/KeyboardioHID/hid-core.png | Bin 34248 -> 0 bytes 15 files changed, 514 insertions(+), 25 deletions(-) create mode 100644 plugins/KeyboardioHID/avr/variants/leonardo/pins_arduino.h create mode 100644 plugins/KeyboardioHID/avr/variants/micro/pins_arduino.h delete mode 100644 plugins/KeyboardioHID/hid-core.png diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 6ff2a97f85..6dfbddfe3f 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -42,12 +42,9 @@ Make sure your HoodLoader2 software is up to date when you also update the HID-P [HoodLoader1](https://github.com/NicoHood/HoodLoader) is only supported for legacy but will get a new use soon! For Arduino Micro/Leonardo ignore this step. -Installation has changed over the time. Put all files from *avr/* into *sketchbook/hardware/HID/avr*. +Installation has changed over the time. Make sure you use Arduino IDE 1.5.8 or newer. You don't have to modify the original core any more. - -At the moment you have to move the cores/hid folder into your Arduino installation -*arduino-1.6.0/hardware/arduino/avr/cores/hid* because of a bug in the IDE. -![HID Folder Picture](hid-core.png) +Put all files into *sketchbook/hardware/HID/*. **You have to rename the folder HID-master to HID.** **Your sketchbook folder should look like this:** ![Installation Picture](installation.png) diff --git a/plugins/KeyboardioHID/avr/boards.txt b/plugins/KeyboardioHID/avr/boards.txt index 43f101d930..f1c22bfb87 100644 --- a/plugins/KeyboardioHID/avr/boards.txt +++ b/plugins/KeyboardioHID/avr/boards.txt @@ -36,22 +36,21 @@ leonardoExtended.build.extra_flags={build.usb_flags} #USB core selection #HID Project needs to be installed https://github.com/NicoHood/HID -#TODO change to HID:hid leonardoExtended.menu.usbcore.hid=Serial + Extended HID leonardoExtended.menu.usbcore.hid.build.variant=leonardo_hid -leonardoExtended.menu.usbcore.hid.build.core=arduino:hid +leonardoExtended.menu.usbcore.hid.build.core=HID:hid leonardoExtended.menu.usbcore.gamepad=Serial + Gamepad HID leonardoExtended.menu.usbcore.gamepad.build.variant=leonardo_gamepad -leonardoExtended.menu.usbcore.gamepad.build.core=arduino:hid +leonardoExtended.menu.usbcore.gamepad.build.core=HID:hid leonardoExtended.menu.usbcore.custom=Serial + Custom HID leonardoExtended.menu.usbcore.custom.build.variant=leonardo_custom -leonardoExtended.menu.usbcore.custom.build.core=arduino:hid +leonardoExtended.menu.usbcore.custom.build.core=HID:hid leonardoExtended.menu.usbcore.USB_CORE=Default Core leonardoExtended.menu.usbcore.USB_CORE.build.variant=arduino:leonardo leonardoExtended.menu.usbcore.USB_CORE.build.core=arduino:arduino leonardoExtended.menu.usbcore.NO_USB=No USB functions leonardoExtended.menu.usbcore.NO_USB.build.variant=leonardo_no_usb -leonardoExtended.menu.usbcore.NO_USB.build.core=arduino:hid +leonardoExtended.menu.usbcore.NO_USB.build.core=HID:hid ############################################################## @@ -83,22 +82,21 @@ microExtended.build.extra_flags={build.usb_flags} #USB core selection #HID Project needs to be installed https://github.com/NicoHood/HID -#TODO change to HID:hid microExtended.menu.usbcore.hid=Serial + Extended HID microExtended.menu.usbcore.hid.build.variant=micro_hid -microExtended.menu.usbcore.hid.build.core=arduino:hid +microExtended.menu.usbcore.hid.build.core=HID:hid microExtended.menu.usbcore.gamepad=Serial + Gamepad HID microExtended.menu.usbcore.gamepad.build.variant=micro_gamepad -microExtended.menu.usbcore.gamepad.build.core=arduino:hid +microExtended.menu.usbcore.gamepad.build.core=HID:hid microExtended.menu.usbcore.custom=Serial + Custom HID microExtended.menu.usbcore.custom.build.variant=micro_custom -microExtended.menu.usbcore.custom.build.core=arduino:hid +microExtended.menu.usbcore.custom.build.core=HID:hid microExtended.menu.usbcore.USB_CORE=Default Core microExtended.menu.usbcore.USB_CORE.build.variant=arduino:micro microExtended.menu.usbcore.USB_CORE.build.core=arduino:arduino microExtended.menu.usbcore.NO_USB=No USB functions microExtended.menu.usbcore.NO_USB.build.variant=micro_no_usb -microExtended.menu.usbcore.NO_USB.build.core=arduino:hid +microExtended.menu.usbcore.NO_USB.build.core=HID:hid ############################################################## @@ -126,7 +124,7 @@ uno.bootloader.file=arduino:optiboot/optiboot_atmega328.hex uno.build.mcu=atmega328p uno.build.f_cpu=16000000L uno.build.board=AVR_UNO -uno.build.core=arduino:hid +uno.build.core=HID:hid uno.build.variant=arduino:standard ############################################################## @@ -148,7 +146,7 @@ mega.bootloader.unlock_bits=0x3F mega.bootloader.lock_bits=0x0F mega.build.f_cpu=16000000L -mega.build.core=arduino:hid +mega.build.core=HID:hid mega.build.variant=arduino:mega # default board may be overridden by the cpu menu mega.build.board=AVR_MEGA2560 diff --git a/plugins/KeyboardioHID/avr/platform.txt b/plugins/KeyboardioHID/avr/platform.txt index c1dae047af..051ea4549d 100644 --- a/plugins/KeyboardioHID/avr/platform.txt +++ b/plugins/KeyboardioHID/avr/platform.txt @@ -10,3 +10,99 @@ name=HID Project USB-Core version=2.1 + + +# AVR compile variables +# --------------------- + +# Default "compiler.path" is correct, change only if you want to overidde the initial value +compiler.path={runtime.ide.path}/hardware/tools/avr/bin/ +compiler.c.cmd=avr-gcc +compiler.c.flags=-c -g -Os -w -ffunction-sections -fdata-sections -MMD +# -w flag added to avoid printing a wrong warning http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59396 +# This is fixed in gcc 4.8.3 and will be removed as soon as we update the toolchain +compiler.c.elf.flags=-w -Os -Wl,--gc-sections +compiler.c.elf.cmd=avr-gcc +compiler.S.flags=-c -g -x assembler-with-cpp +compiler.cpp.cmd=avr-g++ +compiler.cpp.flags=-c -g -Os -w -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD +compiler.ar.cmd=avr-ar +compiler.ar.flags=rcs +compiler.objcopy.cmd=avr-objcopy +compiler.objcopy.eep.flags=-O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 +compiler.elf2hex.flags=-O ihex -R .eeprom +compiler.elf2hex.cmd=avr-objcopy +compiler.ldflags= +compiler.size.cmd=avr-size + +# This can be overriden in boards.txt +build.extra_flags= + +# These can be overridden in platform.local.txt +compiler.c.extra_flags= +compiler.c.elf.extra_flags= +compiler.S.extra_flags= +compiler.cpp.extra_flags= +compiler.ar.extra_flags= +compiler.objcopy.eep.extra_flags= +compiler.elf2hex.extra_flags= + +# AVR compile patterns +# -------------------- + +## Compile c files +recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" + +## Compile c++ files +recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" + +## Compile S files +recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.S.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.S.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" + +## Create archives +recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{build.path}/{archive_file}" "{object_file}" + +## Combine gc-sections, archives, and objects +recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mmcu={build.mcu} {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" {object_files} "{build.path}/{archive_file}" "-L{build.path}" -lm + +## Create eeprom +recipe.objcopy.eep.pattern="{compiler.path}{compiler.objcopy.cmd}" {compiler.objcopy.eep.flags} {compiler.objcopy.eep.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.eep" + +## Create hex +recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.flags} {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.hex" + +## Compute size +recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf" +recipe.size.regex=^(?:\.text|\.data|\.bootloader)\s+([0-9]+).* +recipe.size.regex.data=^(?:\.data|\.bss|\.noinit)\s+([0-9]+).* +recipe.size.regex.eeprom=^(?:\.eeprom)\s+([0-9]+).* + + +# AVR Uploader/Programmers tools +# ------------------------------ + +tools.avrdude.cmd.path={runtime.ide.path}/hardware/tools/avr/bin/avrdude +tools.avrdude.config.path={runtime.ide.path}/hardware/tools/avr/etc/avrdude.conf + +tools.avrdude.upload.params.verbose=-v +tools.avrdude.upload.params.quiet=-q -q +tools.avrdude.upload.pattern="{cmd.path}" "-C{config.path}" {upload.verbose} -p{build.mcu} -c{upload.protocol} -P{serial.port} -b{upload.speed} -D "-Uflash:w:{build.path}/{build.project_name}.hex:i" + +tools.avrdude.program.params.verbose=-v +tools.avrdude.program.params.quiet=-q -q +tools.avrdude.program.pattern="{cmd.path}" "-C{config.path}" {program.verbose} -p{build.mcu} -c{protocol} {program.extra_params} "-Uflash:w:{build.path}/{build.project_name}.hex:i" + +tools.avrdude.erase.params.verbose=-v +tools.avrdude.erase.params.quiet=-q -q +tools.avrdude.erase.pattern="{cmd.path}" "-C{config.path}" {erase.verbose} -p{build.mcu} -c{protocol} {program.extra_params} -e -Ulock:w:{bootloader.unlock_bits}:m -Uefuse:w:{bootloader.extended_fuses}:m -Uhfuse:w:{bootloader.high_fuses}:m -Ulfuse:w:{bootloader.low_fuses}:m + +tools.avrdude.bootloader.params.verbose=-v +tools.avrdude.bootloader.params.quiet=-q -q +tools.avrdude.bootloader.pattern="{cmd.path}" "-C{config.path}" {bootloader.verbose} -p{build.mcu} -c{protocol} {program.extra_params} "-Uflash:w:{runtime.platform.path}/bootloaders/{bootloader.file}:i" -Ulock:w:{bootloader.lock_bits}:m + + +# USB Default Flags +# Default blank usb manufacturer will be filled it at compile time +# - from numeric vendor ID, set to Unknown otherwise +build.usb_manufacturer= +build.usb_flags=-DUSB_VID={build.vid} -DUSB_PID={build.pid} '-DUSB_MANUFACTURER={build.usb_manufacturer}' '-DUSB_PRODUCT={build.usb_product}' diff --git a/plugins/KeyboardioHID/avr/variants/leonardo/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/leonardo/pins_arduino.h new file mode 100644 index 0000000000..fd75373c12 --- /dev/null +++ b/plugins/KeyboardioHID/avr/variants/leonardo/pins_arduino.h @@ -0,0 +1,361 @@ +/* + 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 + +// Workaround for wrong definitions in "iom32u4.h". +// This should be fixed in the AVR toolchain. +#undef UHCON +#undef UHINT +#undef UHIEN +#undef UHADDR +#undef UHFNUM +#undef UHFNUML +#undef UHFNUMH +#undef UHFLEN +#undef UPINRQX +#undef UPINTX +#undef UPNUM +#undef UPRST +#undef UPCONX +#undef UPCFG0X +#undef UPCFG1X +#undef UPSTAX +#undef UPCFG2X +#undef UPIENX +#undef UPDATX +#undef TCCR2A +#undef WGM20 +#undef WGM21 +#undef COM2B0 +#undef COM2B1 +#undef COM2A0 +#undef COM2A1 +#undef TCCR2B +#undef CS20 +#undef CS21 +#undef CS22 +#undef WGM22 +#undef FOC2B +#undef FOC2A +#undef TCNT2 +#undef TCNT2_0 +#undef TCNT2_1 +#undef TCNT2_2 +#undef TCNT2_3 +#undef TCNT2_4 +#undef TCNT2_5 +#undef TCNT2_6 +#undef TCNT2_7 +#undef OCR2A +#undef OCR2_0 +#undef OCR2_1 +#undef OCR2_2 +#undef OCR2_3 +#undef OCR2_4 +#undef OCR2_5 +#undef OCR2_6 +#undef OCR2_7 +#undef OCR2B +#undef OCR2_0 +#undef OCR2_1 +#undef OCR2_2 +#undef OCR2_3 +#undef OCR2_4 +#undef OCR2_5 +#undef OCR2_6 +#undef OCR2_7 + +#define NUM_DIGITAL_PINS 30 +#define NUM_ANALOG_INPUTS 12 + +#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; +#define LED_BUILTIN 13 + +// 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) ) ) + +#define digitalPinToInterrupt(p) ((p) == 0 ? 2 : ((p) == 1 ? 3 : ((p) == 2 ? 1 : ((p) == 3 ? 0 : ((p) == 7 ? 4 : NOT_AN_INTERRUPT))))) + +#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[] = { + 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[] = { + _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[] = { + 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, + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, + + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, + NOT_ON_TIMER, +}; + +const uint8_t PROGMEM analog_pin_to_channel_PGM[] = { + 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 */ + +// These serial port names are intended to allow libraries and architecture-neutral +// sketches to automatically default to the correct port name for a particular type +// of use. For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN, +// the first hardware serial port whose RX/TX pins are not dedicated to another use. +// +// SERIAL_PORT_MONITOR Port which normally prints to the Arduino Serial Monitor +// +// SERIAL_PORT_USBVIRTUAL Port which is USB virtual serial +// +// SERIAL_PORT_LINUXBRIDGE Port which connects to a Linux system via Bridge library +// +// SERIAL_PORT_HARDWARE Hardware serial port, physical RX & TX pins. +// +// SERIAL_PORT_HARDWARE_OPEN Hardware serial ports which are open for use. Their RX & TX +// pins are NOT connected to anything by default. +#define SERIAL_PORT_MONITOR Serial +#define SERIAL_PORT_USBVIRTUAL Serial +#define SERIAL_PORT_HARDWARE Serial1 +#define SERIAL_PORT_HARDWARE_OPEN Serial1 + +#endif /* Pins_Arduino_h */ diff --git a/plugins/KeyboardioHID/avr/variants/leonardo_custom/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/leonardo_custom/pins_arduino.h index c198ad0be0..b6c714dbd0 100644 --- a/plugins/KeyboardioHID/avr/variants/leonardo_custom/pins_arduino.h +++ b/plugins/KeyboardioHID/avr/variants/leonardo_custom/pins_arduino.h @@ -22,7 +22,7 @@ THE SOFTWARE. */ // include the standard leonardo board definition file -#include <../../variants/leonardo/pins_arduino.h> +#include "../leonardo/pins_arduino.h" //================================================================================ // HID Settings diff --git a/plugins/KeyboardioHID/avr/variants/leonardo_gamepad/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/leonardo_gamepad/pins_arduino.h index 85a19e2a89..75b7638a37 100644 --- a/plugins/KeyboardioHID/avr/variants/leonardo_gamepad/pins_arduino.h +++ b/plugins/KeyboardioHID/avr/variants/leonardo_gamepad/pins_arduino.h @@ -22,7 +22,7 @@ THE SOFTWARE. */ // include the standard leonardo board definition file -#include <../../variants/leonardo/pins_arduino.h> +#include "../leonardo/pins_arduino.h" //================================================================================ // HID Settings diff --git a/plugins/KeyboardioHID/avr/variants/leonardo_hid/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/leonardo_hid/pins_arduino.h index 22545bf75b..7378bca813 100644 --- a/plugins/KeyboardioHID/avr/variants/leonardo_hid/pins_arduino.h +++ b/plugins/KeyboardioHID/avr/variants/leonardo_hid/pins_arduino.h @@ -22,7 +22,7 @@ THE SOFTWARE. */ // include the standard leonardo board definition file -#include <../../variants/leonardo/pins_arduino.h> +#include "../leonardo/pins_arduino.h" //================================================================================ // HID Settings diff --git a/plugins/KeyboardioHID/avr/variants/leonardo_no_usb/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/leonardo_no_usb/pins_arduino.h index 53dfb82032..7d84c5c093 100644 --- a/plugins/KeyboardioHID/avr/variants/leonardo_no_usb/pins_arduino.h +++ b/plugins/KeyboardioHID/avr/variants/leonardo_no_usb/pins_arduino.h @@ -22,7 +22,7 @@ THE SOFTWARE. */ // include the standard leonardo board definition file -#include <../../variants/leonardo/pins_arduino.h> +#include "../leonardo/pins_arduino.h" // deactivate usb functions #undef USBCON diff --git a/plugins/KeyboardioHID/avr/variants/micro/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/micro/pins_arduino.h new file mode 100644 index 0000000000..ea8e42dd23 --- /dev/null +++ b/plugins/KeyboardioHID/avr/variants/micro/pins_arduino.h @@ -0,0 +1,37 @@ +/* + 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 "../leonardo/pins_arduino.h" + +#undef TXLED0 +#undef TXLED1 +#undef RXLED0 +#undef RXLED1 +#undef TX_RX_LED_INIT + +#define TXLED0 PORTD &= ~(1<<5) +#define TXLED1 PORTD |= (1<<5) +#define RXLED0 PORTB &= ~(1<<0) +#define RXLED1 PORTB |= (1<<0) +#define TX_RX_LED_INIT DDRD |= (1<<5), DDRB |= (1<<0), TXLED0, RXLED0 \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/variants/micro_custom/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/micro_custom/pins_arduino.h index 1b6241f37e..912bb5190e 100644 --- a/plugins/KeyboardioHID/avr/variants/micro_custom/pins_arduino.h +++ b/plugins/KeyboardioHID/avr/variants/micro_custom/pins_arduino.h @@ -22,7 +22,7 @@ THE SOFTWARE. */ // include the standard micro board definition file -#include <../../variants/micro/pins_arduino.h> +#include "../micro/pins_arduino.h" //================================================================================ // HID Settings diff --git a/plugins/KeyboardioHID/avr/variants/micro_gamepad/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/micro_gamepad/pins_arduino.h index 18a34979a6..dcbd43af14 100644 --- a/plugins/KeyboardioHID/avr/variants/micro_gamepad/pins_arduino.h +++ b/plugins/KeyboardioHID/avr/variants/micro_gamepad/pins_arduino.h @@ -22,7 +22,7 @@ THE SOFTWARE. */ // include the standard micro board definition file -#include <../../variants/micro/pins_arduino.h> +#include "../micro/pins_arduino.h" //================================================================================ // HID Settings diff --git a/plugins/KeyboardioHID/avr/variants/micro_hid/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/micro_hid/pins_arduino.h index 18ec7e144a..6b8fdcfb79 100644 --- a/plugins/KeyboardioHID/avr/variants/micro_hid/pins_arduino.h +++ b/plugins/KeyboardioHID/avr/variants/micro_hid/pins_arduino.h @@ -22,7 +22,7 @@ THE SOFTWARE. */ // include the standard micro board definition file -#include <../../variants/micro/pins_arduino.h> +#include "../micro/pins_arduino.h" //================================================================================ // HID Settings diff --git a/plugins/KeyboardioHID/avr/variants/micro_no_usb/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/micro_no_usb/pins_arduino.h index 43f444c010..8cbee830bc 100644 --- a/plugins/KeyboardioHID/avr/variants/micro_no_usb/pins_arduino.h +++ b/plugins/KeyboardioHID/avr/variants/micro_no_usb/pins_arduino.h @@ -22,7 +22,7 @@ THE SOFTWARE. */ // include the standard micro board definition file -#include <../../variants/micro/pins_arduino.h> +#include "../micro/pins_arduino.h" // deactivate usb functions #undef USBCON diff --git a/plugins/KeyboardioHID/board.png b/plugins/KeyboardioHID/board.png index 7ceebc06a547288c080e167729c7d905368c679f..a370b2197177b256674bfab76cf9a6578889a282 100644 GIT binary patch delta 23083 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 Cz|B|y delta 23105 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 Date: Sat, 10 Jan 2015 00:21:17 +0100 Subject: [PATCH 112/602] Advanced Gamepad example fix --- plugins/KeyboardioHID/Readme.md | 1 + .../examples/HID_Advanced/AdvancedGamepad/AdvancedGamepad.ino | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 6dfbddfe3f..e4ce199c25 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -161,6 +161,7 @@ update Burning via ISP (advanced) Test with Android phone (HL1) "Emulate" HL1 protocol test no usb function with leonardo (usb workaround?) +test gamepad under linux, maybe remove keyboard? ``` diff --git a/plugins/KeyboardioHID/examples/HID_Advanced/AdvancedGamepad/AdvancedGamepad.ino b/plugins/KeyboardioHID/examples/HID_Advanced/AdvancedGamepad/AdvancedGamepad.ino index 04cee3e5f5..629332023e 100644 --- a/plugins/KeyboardioHID/examples/HID_Advanced/AdvancedGamepad/AdvancedGamepad.ino +++ b/plugins/KeyboardioHID/examples/HID_Advanced/AdvancedGamepad/AdvancedGamepad.ino @@ -8,9 +8,6 @@ sketchbook/hardware/HID/avr/variants/hid_descriptors/hid_descriptors.h */ -// see HID_Reports.h for all data structures -HID_GamepadReport_Data_t Gamepadreport; - const int pinLed = LED_BUILTIN; const int pinButton = 2; From a67d60dc48928853897d0ddf80b329f56dc0bd2a Mon Sep 17 00:00:00 2001 From: Nico Date: Sun, 11 Jan 2015 00:58:00 +0100 Subject: [PATCH 113/602] Added more pictures to troubleshoot --- plugins/KeyboardioHID/Readme.md | 40 ++++++++++++++++-- .../HID_Basic/HID_Gamepad/HID_Gamepad.ino | 14 +++--- plugins/KeyboardioHID/gamepad.png | Bin 0 -> 13043 bytes plugins/KeyboardioHID/remove-device.png | Bin 0 -> 28040 bytes 4 files changed, 43 insertions(+), 11 deletions(-) create mode 100644 plugins/KeyboardioHID/gamepad.png create mode 100644 plugins/KeyboardioHID/remove-device.png diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index e4ce199c25..35f82fa0ec 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -36,14 +36,15 @@ The idea is to enable enhanced USB functions to almost all 'standard' Arduino bo Installation ============ -For Arduino Uno/Mega first install [HoodLoader2](https://github.com/NicoHood/HoodLoader2) on your 16u2 + the needed software files. -Temporary use this dev version of the HoodLoader2: https://github.com/NicoHood/HoodLoader2/tree/dev +HID-Project only works with the new Arduino IDE 1.5.8 or newer. +I recommend you to use the new [IDE 1.6 rc1](https://groups.google.com/a/arduino.cc/d/msg/developers/2_GD40Sl6FA/OLWZMwaLJ3IJ). + +For Arduino Uno/Mega first install [HoodLoader2 dev](https://github.com/NicoHood/HoodLoader2/tree/dev) on your 16u2 + the needed software files. Make sure your HoodLoader2 software is up to date when you also update the HID-Project files. [HoodLoader1](https://github.com/NicoHood/HoodLoader) is only supported for legacy but will get a new use soon! For Arduino Micro/Leonardo ignore this step. -Installation has changed over the time. -Make sure you use Arduino IDE 1.5.8 or newer. You don't have to modify the original core any more. +Installation has changed over the time. You don't have to modify the original core any more. Put all files into *sketchbook/hardware/HID/*. **You have to rename the folder HID-master to HID.** **Your sketchbook folder should look like this:** @@ -59,6 +60,8 @@ How to use **1. Select the new board via *Tools->Board->Arduino Leonardo HID-Project* for example.** For HoodLoader2 select the 16u2 MCU. Ensure HoodLoader2 board definition files are up to date. +The Uno and Mega entry is just for advanced users who want to use the HID-APIs but normally you'd +need the new HoodLoader2 (16u2) board definition files. ![Board Selection Picture](board.png) @@ -114,6 +117,34 @@ It is not better than this solution, maybe easier to use since its just more int [Outdated HID Project for 1.5.7](https://github.com/NicoHood/HID/tree/3d8a9b40752a143141b8be4b8f744e203c80b000) +### Midi support? +Some people have asked me about Midi support. It is not planned to integrate Midi into the HID-Project USB-Core since it is very complicated to do so. +But I will work on a new Midi firmware for the 16u2 that supports of course Midi (HoodLoader2 only). A firmware is something like a pre-compiled sketch. With the difference +that I wont use the Arduino IDE to create this firmware. I will use Lufa and a makefile to compile this firmware. This is more efficient. + +When the firmware is done you may upload it via avr-dude as described on the HoodLoader2 github page. Then you are able to start the midi with a simple reset +or start the bootloader (HoodLoader2) again with a double reset like you are used to. Then you can reprogram your 328 again. + +So be patient, I have a lot of new stuff planned and Midi will come. But you are able to flash other firmwares like HIDuino. Maybe thats all you need. +Install HoodLoader2 and flash the hex file. If it works please leave me some info. + +Troubleshoot +============ + +Switching the HID-Core might confuse the OS since the USB device changes completely from one second to the other. +Therefore go to Printers and Devices on Windows and select remove. Reconnect your Arduino and maybe remove it again if its not working properly. +Alternatively you can also restart your PC or use another USB PID (in the boards.txt) to see if its a Windows problem or not. +If you change the USB PID the CDC Driver wont be loaded but you can always reupload a sketch in bootloader mode. + +![remove usb device](remove-device.png) + +Gamepads had several problems over the time. The first thing I'd like to mention is that the calibration windows only updates if you focus it. +Windows only supports gamepads with up to 7 axis and 32 buttons and has problems with more than one Gamepad in a multireport. +Linux has problems when gamepads are in multi reports with a system device for example. It may occur that it display immense axis/buttons or none at all. +![gamepad](gamepad.png) + +If you have any other problem, open an issue on github or contact me on my blog. + How it works ============ For the Leonardo/Micro + HoodLoader2 its a modified version of the HID descriptors and USB-Core. @@ -162,6 +193,7 @@ Test with Android phone (HL1) "Emulate" HL1 protocol test no usb function with leonardo (usb workaround?) test gamepad under linux, maybe remove keyboard? +remove dev HL2 link ``` diff --git a/plugins/KeyboardioHID/examples/HID_Basic/HID_Gamepad/HID_Gamepad.ino b/plugins/KeyboardioHID/examples/HID_Basic/HID_Gamepad/HID_Gamepad.ino index b72887d818..eeadb3fbfb 100644 --- a/plugins/KeyboardioHID/examples/HID_Basic/HID_Gamepad/HID_Gamepad.ino +++ b/plugins/KeyboardioHID/examples/HID_Basic/HID_Gamepad/HID_Gamepad.ino @@ -1,14 +1,14 @@ /* Copyright (c) 2014 NicoHood See the readme for credit to other people. - + Gamepad example - + Press a button and demonstrate Gamepad actions - + Make sure the Gamepad report is set in: sketchbook/hardware/HID/avr/variants/hid_descriptors/hid_descriptors.h - + Function prototypes: void begin(void); void end(void); @@ -69,10 +69,10 @@ void loop() { // values: 0-8 (0==centred) static uint8_t dpad1 = GAMEPAD_DPAD_CENTERED; Gamepad.dPad1(dpad1++); - if(dpad1>GAMEPAD_DPAD_UP_LEFT) dpad1 = GAMEPAD_DPAD_CENTERED; + if (dpad1 > GAMEPAD_DPAD_UP_LEFT) dpad1 = GAMEPAD_DPAD_CENTERED; static int8_t dpad2 = GAMEPAD_DPAD_CENTERED; Gamepad.dPad2(dpad2--); - if(dpad2jdYwo#b`K{lYdnZy|Ri5}7)in?ZM69SFqX`1x z} zk5h>yAiU!)tLLueWbN){=4u6UHnVed=XA7kzsJYP&B<>S%4-Dz@mea%NNGPe!Q_yx zLuWjuxI*q-k-PpfMEzQb1`GZd;=vkbJxZzKq)}E(@5$8?$xb_w2Q1b%z$;es%6wWF zCG#XkDg!9vo=N5%h*Dl^inRgtE~Ba~{1!Bi__1PUZAM{~=GBe*1Cvcy&B44)p6{^4 z@qFXXnZG2gq17L0a@=?*-0I)5Gb^}r7SI?k`GXHP_>nusFe+d#QjPxlmCnT_w@Tl+ zMf%KWTx8gzdvRoml%Ha4Ij`wa;|2@K$yjR(<~J}ugI>X3xG{$vS}$}L|KmSc2@x8cnco5S0lNr+Z6mSwa2Fo<>w}=Y_sdw*liVG@{nM#}m7!zP)3!rD<|mFV@6U|1?4BJ4?lte6o=%M(GYlux&cabb_#bZ^=%t#i$2&$Mc78zT_THiq3x@)8%XlUFu^B+{`gOgWQ^Y zKGoQwaOr&UasVHdui{6{WT)+x?Wyu@mKZ_u9ba_nppfXmivva@-cT*V z4|+4ifuALG2+dt}q+&!|UR6cII0VxN;&*f~ecfyeZmVx)DNHFgc*7Jz+N~AHXYELA zPS=-{(+^>QOZya>*@rGtjvi8Q5A8GJyKT}Ma7yg-{1~v0MiPFyQz@n@1@(zL?qq5? zJ75Y3>(38Pe{iD0+x|YQ!#CBu$ynEYCd+%HJ2&x~MboBram0t&^3C(O!G(?vV|xbo zC}xEri)~Np#cAh_(wbKpY%RP6Rx)gPjYi&yUFi=YP|DC*!Lsy-!4gLxu(0LGIW+O_^M^IF!fk8c^}QTB*dKes^Xd zm0UkSzr=MMWlbLD8U9Dv>X||B9<>S1pkV15vxnsiXKi_BaXY&>kQ%b>wL#)piR;l zZ2|QwBdSxW^*VH)k>@af)#afwB*bCm#56@`b*OCiX=NcL^zhpmb?VZun&sFh2!8mx zd$YGXc#Tda46lCVGSsy#j(!RluqKmcOc6DvX*^mYel1=?h)AvQLqu=P1{T~jA;+@PF5afS5VmP+(VRb!I$BM_-bLd zm<|Eytr-^PE%p}%&zGw-!XDHWWqho#cVri(`up?U0MsMq0nC4Wf#)Q6So9Ym!ovPKHx}>nJN|qj1_nQ!?K-{=>;vrd)m%}+ zkYjNW$d*oz8uVKF859&m5)8)yiQpp%K^483mQBwS213D(1rpD zT|G54?8HPH4|YMnmR-&TBpm$Zm`#p1$TV+zhG;_vJ1-}rW}oE>8WOImrx4%&M zhe&v1J@nV@khcOL)q(rvLo=T^57^QzN^FGccY7JezcnoG|6-76K#RMwQEjrR(C2pP zq0in5_&>hc+x_5S7-AlE>%uq1@Y8L4uDG>5`n#?cw)XV)qh)Sl*z)q^f+AC+5S+RZ)1U$7f=)AWGtY>@H+um=>)yR8eO-q+q?b4(bwU1D;i>aRM zI0YPWDR9cVDK=|6b!e~=1r-ClY)vzO%B~aloA4g%5PZ0-(Gf)jj9)~g&&yVKqj>co z3@3XT7Jj7maSdL-`W$ay=NJI@)0N&9^B|>+qe(cO-J7J%T4rqi&?H$)EKbw79!)vG zZ!$?lrvVudgVSF9V^#hS7rhU~y2MWWvKznTc>PH53GdGFnwJ(o>1U`_A=X{~PN`yB zo{#jr@wXVY`twN~jBdY)R}_6=Kn<+4{^evXg6nSD7rG@Tz8>)@3APy;dngl*8WfbB z2ChbUl)$S7XwFlCT)ar1bRc~&wHL`l4vXEM7a#*NuKE_J&Fnh$lM)N4>s>q`GygJk z|Mx;W6za$AiWu0@DeKiUUG>z{gHmwNh~u&_Nk>iVU~wWuZ`D$;=9li-4;cp0`y={d z@G%O5roeHwij1{ZO8qogHbfw|fJlwAzTa`u^kWiBz4cFX1efn)vmu1CM!Q9>tSkj* z*nn!4s~%eTz2&M=&376%`plV<)|U^pR*>F8;|&7C0fSw4Lv%JJyZUn9z{jjyckr$> z7-W8H{jO)w;Xxz9vRt_nyQosZ%xKSGk?uY&a!YXbs)^ANeU6BU7AwRuiT~(jGJKQf z!|JW)-8@kFSg+&h&3McsK`R1XPyU2dm>SV9whA)_CQ)ts`|&sZoX!fFd1zufel(q+ z_(m{_?VmO8NYP5HSjw<|Otq7^L!Fz&md0UkX;WdZH>jxEIfZ;U%NzDsL|nAyI#P|3 z{exHczzTeB@#Gfe@GxrjVPZ}4+Ne_aB=>2EwNd-M2Z~y>r0$>0s)E54onF&n$MyuT zihEMS7D{;-I1V3XXPOq7J9HIvKlw>Nmu*_jhD-LsI$O0KQ8kiswZb4u&9_?fh9mhl z{j6C%f!2MFK59OT#(GS*<)u~4Q49^yUBbfEmY4LuL>M?TaHbe~H2JK%H5Ahi#-^m= zvJAj<)!oiehFXUNGFTjWier3SP9A+ngMOB%T6DHZUE#A`+?gRrETt?9GvWn z3Q3X6(LXf`8yoa<$u#4uv5XjEFI^EJ^BD6l%y6HytZFUBD`g-Rv>Eo)w2}iS6KANl z==c`*I>#Xe`~!g6=bj)eESyqBd&48m1v?VP7qcU%eteKgtD>aM9VjG*%2$rzI-C+c zmC>Xdn&#wiJh$wKaUd7&-~7TGW4#tVK~#|OP};#-@nKzL#!?1nR-dsU^r&&~AT*9h zBd0|2Q=*(}x`stS6ww!J=(c+}p5q5yH)wUBc~c_+E0YUMDqe7;#ea|x6Q1K)L z+fYR^CHQBol!Bq9Sc`2R^|(T33#y5dI)?sZuDa(Ibz}Y#pKPU=5%sqFIMX5yCw25? zOwx;=EnjRKp zP#e{D(ra?Dmlkoi9!*(Q#^0yV;3Z7(6w(dy%-OIMmu5^Nb7)2^kDKXKV0a2@J-?iB zDL=>Q@pNZNn$RW}kCE9b8*+Qma|5MRAF_B(Xjeo_=M~x&Hwfn!(dJ2OEcn4n%)~as zlJiE&^wd39N-*1;%*G7*mhr?IXOwfyL}yv=V z`G86~6zXI!yjlFoTVU7wV+&2FC@=qv)A+5DdRMP~W2qBY<=9hp`balCT%uGQzV4Ck1s|Ky}iQCm4)6(8Eg#@DyRI_G~`ycBnaGHt|`TIr3F2+`}Rc$df&xuzUk@V` zCO^V|W(L@yQCot2{#+{qEipeGNps?=JYhVa=)7n=VmllrEac^riMz%i54Kxg7F-dv z6caG+u$AY9(y`J~KyJlQSlsLpD-Eva4gD2H{$%DAkAJR)ja2NWLTb3jtK#-}$|3sF zDVfRFQ;`k%gWov7;v`x8R}Y7(kJQQ(vaU+nlKY?k z7+rJYpDk`)G~p-~p&FR>*;u7I7D=-@YZo_*hR*Z&#<|^rM6bcGC5LztPY&=Oc(AjH zv*aW}UC>@M!QWfx4N;#@VK zuqQoh9AC11O_%m*6ylh}bGBQ&Us})l)=ieu(bvxZqnon!8W((sT|Avmhz;Uq8s-$o z_l38j=o&ulfSDe{viRC_Th&5>EuI~Y)>df9lPySLr*~;C)p{ILxMDZF(1FW3NysAVoQsG<5Tv_5#Tmv%4K5x5Z?Kn8M#G`@%VuUFYTV^-rxdaQ z*5NsJ8=MANX@r!WY6$gp7O8$J4)YlF)~A+Q5R^MkiaAEOgxq;YWAwGPz#^7|+uMBW z36oB(l4lgT^JDsOFx5LHrYYTb1YN&m0705($U@F~S0jbPwkn?cwY4#go zNHP+CI8Uy#bG9I>{^|4%+XMbPbfDKaMXCj=OTV{AlQfxDc~yBd9O#+xoLvU32M55Q z+~D@R{e~Ln2yH)AqL{309q33L0VrGWR4;2f-Ssfcw~R$~jc&lNE>OZvp$aVMO9WaE z34jrUKv-7#Upc;K_sPQC-J`W_(zCN|($kT-yJtI%lDn~UcTZ8<@%|o%J*`d0X$z>+ z$aBOol54vKv%Rf$mOhvF3qF_kQ?1eIe02`e^8VN@Z(;7ZVa~s`_BhUT`m`%=;j}0Z zeYzT0cg$Aj6}bP_YhgdRaq6sW&MVOTaLNhOa%j=m`g6H4Jka6rSNzr)QWAZdb9d%+ z?r?|BcW3)@!1KfIyQtI8jb4H0#*K9*3(bH*v})VANtbX&iQXf?1W1BMBzkB{JcwcJ z+49|or|GC)T%m2kco0#GXHc{=oxoRznY`%Gz!`suHq`JPJv2q{$6|-5*@3{IOB9}K z7cxVhW%(_7AcQ?N-D z2=`)9pp_ta4$pf5kSoB0LA1CKJdpbpAg-hL0okMQKMOH2?UHApdzWFD7$DIT@GdMu z-tbTB_c!SeDAbmeBl2!v83?o>G%@&jRt5WJXmWY9o%W*ya_P z@?{C}HIt4lQ!q?JtNZE(2m&G0L-RO$T8KM5tGyqV(_{4_t?un}J|?&l6>rE*-lw!G z(d{@vaQGz{=36}z$04B+K{(~rCTr)1Su36?WOtS6kmLP*M0HZoXHX~(M3irSI{R&6 zRp%OoH}ScSp}m|%7;9Kd30uXWO+B$a-o^dQG%VZ_;4jxGd}DpGQWPQV%ebVC*`A6P z)(#@HC0AkP9M7PayQs1(-09S|_@(QPMVeOKy=@X;h2kVrqVA>Id{6f@s3!@KND9Ek z?=BWW4blOuloe#cZLfhspHN_?9-pg-g$1B4j6x7vVf`#uu#t0$75J9fZi0l-`i|P8kq3DVfD4#UsQ9 zD1Lp)QChTUe>M#zCmv>E-e`HhNmNVXDQFD^RpKN-=zz8^t8>W zthp$Qg)e4S85qpxF3E#c?bG=z@tG`PBAFB~@cxKoulJLL+g#U@X5)C5Ui5Vs7zk%9 z3X~B4)^YC(i$?DGI}ZK=9*Z-1nMrcpHSjC}{K8$BJ1b%jhs)~v3>EBRt=7)L?+5JC z0ouNnj${81-PyNAcTL0VvN_cRX$AYfc0=W$J3lEXWuV_ zgfBAbZ$oG)&S+Asj)+Paj;2#OJVW+yv0+CrEctPASFTIvG>kkS_B+sOw6<^4_?@S= z-{LnC@E8vmSTlSa4b7pSCodAglcqQ1hJ{j$BB?RFMVgkxFWvt|^xb>&w=OK9#j_F2 z=;8TJ69(zFxAXSRM95;2!eTzZjM0&wFn0$1&Tg@rJ2Ihd5CYw5MMrtc@9isQ9Oc=A z&VS@0LONLx(Fr-KM6GT0MaUYvSV?q1)v14n_*zEaH%I5FX~-nnGNHDcm-E{n9xk2; z&irkldasE&0mQY_1bip?cq7rInumVfrGEa6Qc-?YW<2V(z+d?6gD@FLmGC0IAZ?s~ zt%!drgn#RMpvClmJ3TZ2R-Tohg$r_ceG>pZ5aC~g-d`f&--X%D@VS<0<7O9K5)<#$ z?bx!$Xte8Vbq#eL0=u$WEuuBW8*w6gxS*#K?OItpb#@kR_|NN&z=BWA*Rf- z(j~4IyQ`?3_3}VvCJ0sujGINEB_6=wTVs*%sy^k+7eX;UF=8uo#W-*Fj#%F&Q>EHJ zPzKN^W>B4%3-mfc0yZRmqv6YIJKd$X^zrq1W$6Z0cUY3oA~FtBc*Tmkn?OODKJNvb z95UqZK8dBQy7~PkBKdyLogEF_$XCus3f#8L`IT%~>)g(e#ocSpYi6|ceAgvX>R$2< zd$@#B3t9`a${RV3ppn11J?<4mD?eRcC`2RvJ{%ia2-_xx>H5!LUfPL-R)g>xQRJ8yITdIGL z-k&$OzYDYD;a@A8-9GCs1S=^z-yS^A?|VGElS!0fO#iC4+^l18jH@k%WYfh2DPS}@ zyE=N(UU3`rw$pK|*-NT3Kg)bca8GV|cJUj;Q|VO#n+b;Iiyc&J0TgZ$H#BuAh~lb% z=Ne~k)k^Uz*wv&gr*egRZ|l5s-2&`un08P<?^3r+5nG-(OKyY(ZqR93^dX|J zwgpEX`gw-$&6yqiRKErN{*1kqaupFuuA+5w**Q?G#ajnmBqvlv=0+4QBA955p#s+W z(?KudN9^syZ#E8Eg?u6M7xN3gJ>BS6Y29yH_%a zX77aB=IxcK5%oq?@oOxP*7AMiDmL$ZUf|kaEc2R(%T$q&`6fvUAsM|tWoC_lT~R$7 z{Q}ERaC@$wyYP4zVj||4*CiB3h%cEsV8r-3bi!Q{J;gUdX{|`i@bisfbTdD3J!gP& zy}!$TH-=ibh^@)PZuIuqQGF}M&mETL>{Lq!3ZI?DMTVGiI_EdY0S{(oFvtJXuq@xM;T z^imdDfaz@#;)Wu!r9=c6TnYX~NP!1oD-MJti>FFOMO}|1($s#bV409lFGK(07Ww@f zl!YZ%5_|8-%0|c#u&_RUz^gEZ`wZIk!vR_yFIKtbsiDvVhj2B03n9{riTNQ@eQO-Y zirMLD7@T~f9NtHgi82u=2@;rjM>|+8^ML#k`6K-o*IvVCqnl*p&bc}RhVj#tcmi&5!`tcDJ`1u9m=j87=o-rC-lui_2uS`&^+)vApy z(98H}zDJ{!0w^-N2C17-C%mYAO++GYC8tr(#Y zb`7j)Z{V_`$}b|5sFV)$-whT*sjd12UNI|H$g$ zg%Qkb8o7X}Rk6(dDGUzjfLtP|Q$4-Oo8myWRVLguH|4h&JefTd_# zl?<$fR{hE-M3pY!7$VqE7o1p-;O0Yq1T%zNqgpRR5lxluJOtP&gvq>6Wu!gRl3evY zZTVULN;kiu1D9+KL={bCh#ZtrjGd^!x;GptS9lx~5}8Ef>-Fje3)ttC9J!TTqfk^T z^lv(eS+%$YEC8zk{TKdiL#3Tn4a)Shpk%9Lv2MRboyvbF%g%F%BI|8Qz5|$w$rKDL zeyLG$N~1)EF0=|R<(`qMVB&inuu2oa!c9v6s0WTFiN zd>j18E)oE{PUR7#^&*E=;(wF0f68PYKpST?(AJOp&x&ol7~a=o4ptZ|y{J@-Ue-~X zye4H~FGHyo2;h6hs*X@|jUvW}FVq%Y0KSb{eTjTJm9+7W0|#5-*_|j78|iQ@)r;Bk z2*k49h>P{bkDgit!*uNG=!7u^Bsq`8;=ilHKQE}KO5psKhqkE&iHOrVlF^s-?}hmE zvr|*(o~AZFTSRv7|NLDW#GprA{=|T3=@H@j4C*;GkNatULL6l3s3*VTv78UR{g zT2(uK>A8pdcF(6N1#!I)dkoJz1;wB)+ZIvVOr zyM)81#JUwL34m-QDUbDxLG!&Bs4rVpL<^*Cfy)NhzcF_>`@Z4*)MF?~#Hir-)Oy^r zoZpSxRd3&(I|=5)A0m{qdmk42l)jv?6fUNh)j6*sr)MP>E>9VTCQL2OtrKN1T)@Bi zfQ<#1G~HA!o0OGGnUyG%>9d&hnQ$ynu;O!hQmY*8a@@!+x5yDymGUZh|< ze&3V+TfhQ8Seq*&)vX;mx~x|tsy5xR6~P$_Z%`t?v9Gx`XZcdc+WmQoS$(s5#)fwz zxO!iOTdLaIibReC!VE?%n%4kWqgG-xg|aoV;~zOFGNFJ>00p0PVJUe&k#y{8zxD_^ zXAwcnr~uq3-|}LK_4+_T8)HEL3nhO&8gPh%T>f~b@Eu`Tt#!0Jf9qOpvu;B^e5`O> zfPfsY&%s7YeDK$FpN^Wn))IWGC{%R17wOht5|}mOnNQC^3b-UMB~x zKk4HN*zEM|@AaQ55~{f#xUs6qCdGdIW!n)@Wl*ua?e- z_~=s+0w>T>PGSSAS`b2*+TK{h8wdcp)#@TQC1h`36#gaa>vdsxuL3Vf$a>TimV_E^zs&k`E;so zMU`Y&kyRs{Ec`unx8Y2LWf^_-W*1j9eC#ee*}wSZuboxw0ujXpJiLHIF&#O z3t?fuHy|BY>}$#*kEag$o+C)Psjls}4luvXi&>w5S>pz3dB|eX7|O%s2e?K7-$`;c zkPjI8tW!AhKX=drHH;Fp&NQu&P1>&@xV(%a1Q-Y~WdvEgUJ(`If*Hq@X=cWvIaqqG zjVq(}Qz(b)g~IuJFjW0iQKCk#jRsIxGPMnCK6YR7vV}HvY^g4J0-&J(eq=2*qjoNY zH<^{&&bQH(bK>lx3VrzRC~j+A@Cs`4?+2?sa@~xSavw4^)}F1Q(W!132K_WKGy;_l zi7OJTQAoMbrg8gRj8bzUvKzlI6`h_~WtK#_mj&oE?qh-L+>c@8`Wn1&p?|Dj-mN z6^`<-(rN`g^!2Pdu4F_V8~WLbb1W|dUih=|15YcGKcmj`51T{~wl!V@>YERBp{9pj z3>L{m48~ai-Eghf%ShBR!XM9bRz1@~oqrzFcT~C*W8b092dTc!n44ow+NTA2ob{S2>O1*3V@Q zeE$fv+4eB0XhHJD_utG!`^n_hkrGf{jodz^=S`dJgs-^lXXp|s3T5mx@8l1$t%E3_^}_OH44pIE>JYww~NLaFxN z_lvD(2VOG~c4ddSDRhwuuQy@qa8(c4Z7lCmC#`lFOH<+i3tFZY2}yhZpdX*gp;yCe zaywYwUKDq-9<|m~*xzZ(DC!R4!Q(hx`WNvK`wP$!Zh*6xYtSiLCD6wgs^VOLP7jKG z$&j*e9cV-W@Fh@=VZQ*L3pV`U9%leX);E&E^FLzeZ;ZI3XUKDENbSV(lSzcQ=Ie83)1=E?mJf?5N|%$eO_Tkv@_ zgKMSaVFg$NB*6}Mv}0+?>T%2~jX049`qIKhX|9v^`;=fXe~Yz32$tD4zyV}I^yszv zd*1_3RlIR{;etU-4R&JO)UAbe#;UG8tjnvtzjmB94?1dRfEcm_XxeT9!iYb{fMktzj#BEZL}6!;<53WVcLs z)EXgz>n1I0=0Zib3Q`>r^Ye+WMLwjcn!aPzHow_;X6=RLL#u1ngIieO0PN(cj!goJ zP8O|u0UiQuZUCde@XIR%6!BgLFU(hD4`i$V=HA^gXy&VOBvTHias(vpg%}KQFiCI- z7y>}1LIe2+=CJn1&^`IByd2KcF7PBIv7-yXnm>veI9c0SF{hB*3GMt=rhpjd$ zgd_a1Oh=?vAmngn#oB!7Af$O9TP7pqY7(?EBNAQIKWNk#w(DMeklCa68UT%AH%QHT zTJ<-x_5(PL$_!oZKxPJ}pOxCqS!myKx)3FRsUb)ZF(2*o|QasB*vD=Z6I~9 zwRs6kv4D*{7<(E7iu3=~Ww!tT7m6MuTBJnUBvyQ^YzKgj7to^q=jS(nZ*c)e{_&)z zx4j&Agr^!Zt^W8D&;$)a0+s!*ujv5?nST;~KHUEKjjcH>+brb7ZGm&`HXeQ*A;rA0 zQ+fw>f@;>%`Ld>tv>9da##umD9O@kB49uRs7jV8oVgc=gK4EO5}a<5veQln+O*7{<>g;l*2*xa>@D?Jkpe(S~6ygnwIFeb$*X z6eP-KdhjEGX4nmu6w}BUb9*R)>&qQv_i(Z2YRfpotVjH2ucgGPozLyf_$xl!Wvd?V z1rkEpKYP8~Tf)9a*vfo)P{qfgQPH$iY1>9Z;uh9dkPM;9>zv=dFxxOm8`%q)ez;}C zXZy9}zD740OeI^TIktsJU^R16FyqZjn(N!N<*#O~0e1|%fpPG14%LUXzW7P-WggF2 z8{)>qe?8+?-9)fw#B%?B7RE4Z?=6`C`}eB$zFo?y+RR~q(0cdcwix7zZVNOsT#m~k z-JxswN@YO`Uk^jb@@Lcuuo$SgnvjUp-S0a^unuvjB(m`)AYm(?k#dauACkOaTrcI) zGINHWYZ>mBBnvB~SPD%-x5Bz1+J9k8?*$F2HB2>PWeI z>O7u0hv#^WSq4r&-_i7yp1Ea7?vy#^z0L;b=*7Pp~-Y7i#U!`#8_uXR_5 zZua8($PRP=sY(6sUy;42Jxe(7r;00``ZAWLxAY;>_pV3m5&yeaasPNnw-W`tjGJHf eeEsV=DRf&~!|s*jB=DaUkfN-rOvU48A^!)Hkjo?h literal 0 HcmV?d00001 diff --git a/plugins/KeyboardioHID/remove-device.png b/plugins/KeyboardioHID/remove-device.png new file mode 100644 index 0000000000000000000000000000000000000000..3ad5407956868af8ba54c4999f36f20e5666be0a GIT binary patch literal 28040 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 OCnNdnG5V3goBspJ$zzcK literal 0 HcmV?d00001 From 32765c1e6532b9274fcdd8cc3f781f582bdc433f Mon Sep 17 00:00:00 2001 From: Nico Date: Sun, 11 Jan 2015 01:01:08 +0100 Subject: [PATCH 114/602] Moved pictures into picture folder --- plugins/KeyboardioHID/Readme.md | 15 ++++++++------- plugins/KeyboardioHID/{ => pictures}/board.png | Bin plugins/KeyboardioHID/{ => pictures}/gamepad.png | Bin plugins/KeyboardioHID/{ => pictures}/header.jpg | Bin .../{ => pictures}/installation.png | Bin .../{ => pictures}/remove-device.png | Bin .../KeyboardioHID/{ => pictures}/usb-core.png | Bin 7 files changed, 8 insertions(+), 7 deletions(-) rename plugins/KeyboardioHID/{ => pictures}/board.png (100%) rename plugins/KeyboardioHID/{ => pictures}/gamepad.png (100%) rename plugins/KeyboardioHID/{ => pictures}/header.jpg (100%) rename plugins/KeyboardioHID/{ => pictures}/installation.png (100%) rename plugins/KeyboardioHID/{ => pictures}/remove-device.png (100%) rename plugins/KeyboardioHID/{ => pictures}/usb-core.png (100%) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 35f82fa0ec..1e45f36e08 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -1,6 +1,6 @@ Arduino HID Project 2.1 ======================= -![Header Picture](header.jpg) +![Header Picture](pictures/header.jpg) This project went through a lot of phases and has now reached a new Arduino USB-Core with a lot of new functions like extended HID. It also supports HoodLoader1+2. @@ -48,7 +48,7 @@ Installation has changed over the time. You don't have to modify the original co Put all files into *sketchbook/hardware/HID/*. **You have to rename the folder HID-master to HID.** **Your sketchbook folder should look like this:** -![Installation Picture](installation.png) +![Installation Picture](pictures/installation.png) If you like to, you can add the keywords.txt to your Arduino IDE so that words like 'Gamepad' are highlighted. Replace the file in *arduino-1.6.0/lib/keywords.txt* with the *keywords.txt* provided in this project. @@ -63,7 +63,7 @@ For HoodLoader2 select the 16u2 MCU. Ensure HoodLoader2 board definition files a The Uno and Mega entry is just for advanced users who want to use the HID-APIs but normally you'd need the new HoodLoader2 (16u2) board definition files. -![Board Selection Picture](board.png) +![Board Selection Picture](pictures/board.png) **2. Select the USB-Core you want to use. You have 5 options here:** @@ -73,7 +73,7 @@ need the new HoodLoader2 (16u2) board definition files. * Default Core (Standard Arduino Core) * No USB Core (No USB functions available, saves ram + flash) -![USB-Core Selection Picture](usb-core.png) +![USB-Core Selection Picture](pictures/usb-core.png) To create a **custom HID report descriptor** you can edit the file in *avr/variants/leonardo_custom/pins_arduino.h*. Same for Micro and HoodLoader2. Not all HID reports are playing well together on all OS so I made these pre selections. @@ -136,14 +136,15 @@ Therefore go to Printers and Devices on Windows and select remove. Reconnect you Alternatively you can also restart your PC or use another USB PID (in the boards.txt) to see if its a Windows problem or not. If you change the USB PID the CDC Driver wont be loaded but you can always reupload a sketch in bootloader mode. -![remove usb device](remove-device.png) +![remove usb device](pictures/remove-device.png) Gamepads had several problems over the time. The first thing I'd like to mention is that the calibration windows only updates if you focus it. Windows only supports gamepads with up to 7 axis and 32 buttons and has problems with more than one Gamepad in a multireport. Linux has problems when gamepads are in multi reports with a system device for example. It may occur that it display immense axis/buttons or none at all. -![gamepad](gamepad.png) -If you have any other problem, open an issue on github or contact me on my blog. +![gamepad](pictures/gamepad.png) + +**If you have any other problem, open an issue on github or contact me on my blog.** How it works ============ diff --git a/plugins/KeyboardioHID/board.png b/plugins/KeyboardioHID/pictures/board.png similarity index 100% rename from plugins/KeyboardioHID/board.png rename to plugins/KeyboardioHID/pictures/board.png diff --git a/plugins/KeyboardioHID/gamepad.png b/plugins/KeyboardioHID/pictures/gamepad.png similarity index 100% rename from plugins/KeyboardioHID/gamepad.png rename to plugins/KeyboardioHID/pictures/gamepad.png diff --git a/plugins/KeyboardioHID/header.jpg b/plugins/KeyboardioHID/pictures/header.jpg similarity index 100% rename from plugins/KeyboardioHID/header.jpg rename to plugins/KeyboardioHID/pictures/header.jpg diff --git a/plugins/KeyboardioHID/installation.png b/plugins/KeyboardioHID/pictures/installation.png similarity index 100% rename from plugins/KeyboardioHID/installation.png rename to plugins/KeyboardioHID/pictures/installation.png diff --git a/plugins/KeyboardioHID/remove-device.png b/plugins/KeyboardioHID/pictures/remove-device.png similarity index 100% rename from plugins/KeyboardioHID/remove-device.png rename to plugins/KeyboardioHID/pictures/remove-device.png diff --git a/plugins/KeyboardioHID/usb-core.png b/plugins/KeyboardioHID/pictures/usb-core.png similarity index 100% rename from plugins/KeyboardioHID/usb-core.png rename to plugins/KeyboardioHID/pictures/usb-core.png From a63b5bae0c09b55fe01d75241a5090971e851365 Mon Sep 17 00:00:00 2001 From: Nico Date: Sun, 11 Jan 2015 12:08:01 +0100 Subject: [PATCH 115/602] Fix when no specific descriptors are set --- plugins/KeyboardioHID/Readme.md | 6 +++--- plugins/KeyboardioHID/avr/boards.txt | 16 ++++------------ .../KeyboardioHID/avr/cores/hid/USB-Core/HID.h | 4 +++- 3 files changed, 10 insertions(+), 16 deletions(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 1e45f36e08..64d0a68071 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -131,16 +131,17 @@ Install HoodLoader2 and flash the hex file. If it works please leave me some inf Troubleshoot ============ -Switching the HID-Core might confuse the OS since the USB device changes completely from one second to the other. +**Switching the HID-Core** might confuse the OS since the USB device changes completely from one second to the other. Therefore go to Printers and Devices on Windows and select remove. Reconnect your Arduino and maybe remove it again if its not working properly. Alternatively you can also restart your PC or use another USB PID (in the boards.txt) to see if its a Windows problem or not. If you change the USB PID the CDC Driver wont be loaded but you can always reupload a sketch in bootloader mode. ![remove usb device](pictures/remove-device.png) -Gamepads had several problems over the time. The first thing I'd like to mention is that the calibration windows only updates if you focus it. +**Gamepads** had several problems over the time. The first thing I'd like to mention is that the calibration windows only updates if you focus it. Windows only supports gamepads with up to 7 axis and 32 buttons and has problems with more than one Gamepad in a multireport. Linux has problems when gamepads are in multi reports with a system device for example. It may occur that it display immense axis/buttons or none at all. +The current gamepad setting was tested under windows and ubuntu and seems to work. Feel free to extend the gamepad report at your own risk. ![gamepad](pictures/gamepad.png) @@ -193,7 +194,6 @@ update Burning via ISP (advanced) Test with Android phone (HL1) "Emulate" HL1 protocol test no usb function with leonardo (usb workaround?) -test gamepad under linux, maybe remove keyboard? remove dev HL2 link ``` diff --git a/plugins/KeyboardioHID/avr/boards.txt b/plugins/KeyboardioHID/avr/boards.txt index f1c22bfb87..1b8b4099b6 100644 --- a/plugins/KeyboardioHID/avr/boards.txt +++ b/plugins/KeyboardioHID/avr/boards.txt @@ -28,6 +28,7 @@ leonardoExtended.bootloader.lock_bits=0x2F leonardoExtended.build.mcu=atmega32u4 leonardoExtended.build.f_cpu=16000000L +leonardoExtended.build.core=HID:hid leonardoExtended.build.vid=0x2341 leonardoExtended.build.pid=0x8036 leonardoExtended.build.usb_product="Arduino Leonardo" @@ -38,19 +39,14 @@ leonardoExtended.build.extra_flags={build.usb_flags} #HID Project needs to be installed https://github.com/NicoHood/HID leonardoExtended.menu.usbcore.hid=Serial + Extended HID leonardoExtended.menu.usbcore.hid.build.variant=leonardo_hid -leonardoExtended.menu.usbcore.hid.build.core=HID:hid leonardoExtended.menu.usbcore.gamepad=Serial + Gamepad HID leonardoExtended.menu.usbcore.gamepad.build.variant=leonardo_gamepad -leonardoExtended.menu.usbcore.gamepad.build.core=HID:hid leonardoExtended.menu.usbcore.custom=Serial + Custom HID leonardoExtended.menu.usbcore.custom.build.variant=leonardo_custom -leonardoExtended.menu.usbcore.custom.build.core=HID:hid leonardoExtended.menu.usbcore.USB_CORE=Default Core -leonardoExtended.menu.usbcore.USB_CORE.build.variant=arduino:leonardo -leonardoExtended.menu.usbcore.USB_CORE.build.core=arduino:arduino +leonardoExtended.menu.usbcore.USB_CORE.build.variant=leonardo leonardoExtended.menu.usbcore.NO_USB=No USB functions leonardoExtended.menu.usbcore.NO_USB.build.variant=leonardo_no_usb -leonardoExtended.menu.usbcore.NO_USB.build.core=HID:hid ############################################################## @@ -74,6 +70,7 @@ microExtended.bootloader.lock_bits=0x2F microExtended.build.mcu=atmega32u4 microExtended.build.f_cpu=16000000L +microExtended.build.core=HID:hid microExtended.build.vid=0x2341 microExtended.build.pid=0x8037 microExtended.build.usb_product="Arduino Micro" @@ -84,19 +81,14 @@ microExtended.build.extra_flags={build.usb_flags} #HID Project needs to be installed https://github.com/NicoHood/HID microExtended.menu.usbcore.hid=Serial + Extended HID microExtended.menu.usbcore.hid.build.variant=micro_hid -microExtended.menu.usbcore.hid.build.core=HID:hid microExtended.menu.usbcore.gamepad=Serial + Gamepad HID microExtended.menu.usbcore.gamepad.build.variant=micro_gamepad -microExtended.menu.usbcore.gamepad.build.core=HID:hid microExtended.menu.usbcore.custom=Serial + Custom HID microExtended.menu.usbcore.custom.build.variant=micro_custom -microExtended.menu.usbcore.custom.build.core=HID:hid microExtended.menu.usbcore.USB_CORE=Default Core -microExtended.menu.usbcore.USB_CORE.build.variant=arduino:micro -microExtended.menu.usbcore.USB_CORE.build.core=arduino:arduino +microExtended.menu.usbcore.USB_CORE.build.variant=micro microExtended.menu.usbcore.NO_USB=No USB functions microExtended.menu.usbcore.NO_USB.build.variant=micro_no_usb -microExtended.menu.usbcore.NO_USB.build.core=HID:hid ############################################################## diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h index 020f2eca68..2d652e967f 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h @@ -48,7 +48,9 @@ THE SOFTWARE. // for the extern HID descriptors + settings #include "pins_arduino.h" -#ifndef EXTERN_HID_REPORT +#if !defined(EXTERN_HID_REPORT) && !defined(HID_MOUSE_ENABLE) && !defined(HID_KEYBOARD_KEYS_ENABLE) \ +&& !defined(HID_KEYBOARD_LEDS_ENABLE) && !defined(HID_MOUSE_ABSOLUTE_ENABLE) && !defined(HID_RAWHID_ENABLE) \ +&& !defined(HID_CONSUMER_ENABLE) && !defined(HID_SYSTEM_ENABLE) && !defined(HID_GAMEPAD_ENABLE) // by default enable mouse + keyboard api #define HID_MOUSE_ENABLE #define HID_KEYBOARD_KEYS_ENABLE From da1cc5863362f93f0a74cbc59abac8da9c9389f1 Mon Sep 17 00:00:00 2001 From: Nico Date: Sun, 11 Jan 2015 12:55:18 +0100 Subject: [PATCH 116/602] Added NoUsb workaround for Leo/Micro devices Had to add this workaround again since the Leo/Micro bootloader is coded different than the HL2 which fixes this problem. --- plugins/KeyboardioHID/Readme.md | 21 ++++++++++++- .../Leonardo_Micro_NoUSB_Blink.ino | 31 +++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 plugins/KeyboardioHID/examples/Projects/Leonardo_Micro_NoUSB_Blink/Leonardo_Micro_NoUSB_Blink.ino diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 64d0a68071..9886e62c2c 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -86,6 +86,22 @@ See *Project/USB-Serial* for a fully usable USB-Serial bridge and how to use the In the CDC.h you can also see the new Control Line functions for advanced users. Keep in mind that the USB_ENDPOINTs for the u2 Series are set to 16 bytes, so the Serial buffer is also smaller (normally 64b). +**If you don't want to use the USB-Core** you can also choose under *Tools/USB Core* "No USB functions" to get rid of the USB stuff +and save the ram for other stuff if you don't need it. You also don't need the HID Project essentially if you don't want to use the USB functions. +Due to a bad Leonardo/Micro bootloader you need to add an add an ISR into every sketch as workaround. +**This is not needed for HoodLoader2 devices**, since the bootloader does a true watchdog reset on reprogramming and not a simple application jump +(the usb clock is then still on and breaks any delay functions). +Checkout the 'Leonardo_Micro_NoUSB_Blink' example. + +```cpp +// workaround for undefined USBCON has to be placed in every sketch +// otherwise the timings wont work correctly +ISR(USB_GEN_vect) +{ + UDINT = 0; +} +``` + ### HoodLoader1 (legacy, new stuff coming soon) **Try the HoodLoader1 example. It provides the basic Serial protocol API to send HID reports. You have to copy this to every sketch again.** @@ -131,6 +147,10 @@ Install HoodLoader2 and flash the hex file. If it works please leave me some inf Troubleshoot ============ +**Any random weird problem** is mostly solved by a pc reboot or a port switching. Try another (USB2.0) port if you have any problems with your device. +You might also try it on another pc to see if your OS mixes up drivers. Once I had a problem with my USB-Hub, so ensure to connect it directly. +You could also try a different/shorter USB cable. + **Switching the HID-Core** might confuse the OS since the USB device changes completely from one second to the other. Therefore go to Printers and Devices on Windows and select remove. Reconnect your Arduino and maybe remove it again if its not working properly. Alternatively you can also restart your PC or use another USB PID (in the boards.txt) to see if its a Windows problem or not. @@ -193,7 +213,6 @@ Generalize HID key definitions via HIDTables for example? update Burning via ISP (advanced) Test with Android phone (HL1) "Emulate" HL1 protocol -test no usb function with leonardo (usb workaround?) remove dev HL2 link ``` diff --git a/plugins/KeyboardioHID/examples/Projects/Leonardo_Micro_NoUSB_Blink/Leonardo_Micro_NoUSB_Blink.ino b/plugins/KeyboardioHID/examples/Projects/Leonardo_Micro_NoUSB_Blink/Leonardo_Micro_NoUSB_Blink.ino new file mode 100644 index 0000000000..8309b2613f --- /dev/null +++ b/plugins/KeyboardioHID/examples/Projects/Leonardo_Micro_NoUSB_Blink/Leonardo_Micro_NoUSB_Blink.ino @@ -0,0 +1,31 @@ +/* + Copyright (c) 2014 NicoHood + See the readme for credit to other people. + + Leonardo_Micro_NoUSB_Blink + + Blinks Led and shows what workaround is needed to fix the timing. + This is not needed for HoodLoader2 devices any more. +*/ + + +// workaround for undefined USBCON has to be placed in every sketch +// otherwise the timings wont work correctly +ISR(USB_GEN_vect) +{ + UDINT = 0; +} + +// the setup function runs once when you press reset or power the board +void setup() { + // initialize digital pin 13 as an output. + pinMode(13, OUTPUT); +} + +// the loop function runs over and over again forever +void loop() { + digitalWrite(13, HIGH); // turn the LED on (HIGH is the voltage level) + delay(1000); // wait for a second + digitalWrite(13, LOW); // turn the LED off by making the voltage LOW + delay(1000); // wait for a second +} From d3ed466c665c3f099a7d484d0d2083650a6b9b33 Mon Sep 17 00:00:00 2001 From: Nico Date: Sun, 11 Jan 2015 13:57:58 +0100 Subject: [PATCH 117/602] Arduino as ISP fix --- plugins/KeyboardioHID/Readme.md | 14 + plugins/KeyboardioHID/avr/programmers.txt | 8 + .../Projects/ArduinoISP/ArduinoISP.ino | 554 ++++++++++++++++++ 3 files changed, 576 insertions(+) create mode 100644 plugins/KeyboardioHID/avr/programmers.txt create mode 100644 plugins/KeyboardioHID/examples/Projects/ArduinoISP/ArduinoISP.ino diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 9886e62c2c..61e8056035 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -144,6 +144,19 @@ or start the bootloader (HoodLoader2) again with a double reset like you are use So be patient, I have a lot of new stuff planned and Midi will come. But you are able to flash other firmwares like HIDuino. Maybe thats all you need. Install HoodLoader2 and flash the hex file. If it works please leave me some info. +* https://github.com/ddiakopoulos/hiduino +* http://hunt.net.nz/users/darran/weblog/5b7f8/Arduino_UNO_USB_MIDI_firmware.html + +### Arduino as ISP +You want to use your Leonardo/Micro as ISP as well? Here is a simple fix (not working with HoodLoader2 currently): +Select the Leonardo board and upload the Arduino as ISP sketch from this project to your Leonardo. +Select the board you want to flash and under *Tools->Programmer->Arduino as ISP (Leonardo)*. +Ensure the correct Serial port is selected, wires are also correct and hit burn bootloader. + +A fix for the u2 Series is in work. Optional you could use HoodLoader1 firmware as ISP. +The only thing I changed was the reset pin to pin 10 instead of SS +and the upload protocol from stk500v1 to arduino to avoid any CDC Serial dtr state problems. + Troubleshoot ============ @@ -266,6 +279,7 @@ Version History * Added HID Tables * USB-Serial now fully reprogrammable * Easy USB-Core selection via Tools->USB-Core +* Added Arduino as ISP fix for 32u4 (u2 Series doesn't work at the moment) 2.0 Release (29.11.2014) * Added HoodLoader2 diff --git a/plugins/KeyboardioHID/avr/programmers.txt b/plugins/KeyboardioHID/avr/programmers.txt new file mode 100644 index 0000000000..4aa9d6e5c0 --- /dev/null +++ b/plugins/KeyboardioHID/avr/programmers.txt @@ -0,0 +1,8 @@ +arduinoispleo.name=Arduino as ISP (Leonardo) +arduinoispleo.communication=serial +arduinoispleo.protocol=arduino +arduinoispleo.speed=19200 +arduinoispleo.program.protocol=arduino +arduinoispleo.program.speed=19200 +arduinoispleo.program.tool=avrdude +arduinoispleo.program.extra_params=-P{serial.port} -b{program.speed} \ No newline at end of file diff --git a/plugins/KeyboardioHID/examples/Projects/ArduinoISP/ArduinoISP.ino b/plugins/KeyboardioHID/examples/Projects/ArduinoISP/ArduinoISP.ino new file mode 100644 index 0000000000..0766ebae9f --- /dev/null +++ b/plugins/KeyboardioHID/examples/Projects/ArduinoISP/ArduinoISP.ino @@ -0,0 +1,554 @@ +// ArduinoISP version 04m3 +// Copyright (c) 2008-2011 Randall Bohn +// If you require a license, see +// http://www.opensource.org/licenses/bsd-license.php +// +// This sketch turns the Arduino into a AVRISP +// using the following arduino pins: +// +// pin name: not-mega: mega(1280 and 2560) +// slave reset: 10: 53 +// MOSI: 11: 51 +// MISO: 12: 50 +// SCK: 13: 52 +// +// Put an LED (with resistor) on the following pins: +// 9: Heartbeat - shows the programmer is running +// 8: Error - Lights up if something goes wrong (use red if that makes sense) +// 7: Programming - In communication with the slave +// +// 23 July 2011 Randall Bohn +// -Address Arduino issue 509 :: Portability of ArduinoISP +// http://code.google.com/p/arduino/issues/detail?id=509 +// +// October 2010 by Randall Bohn +// - Write to EEPROM > 256 bytes +// - Better use of LEDs: +// -- Flash LED_PMODE on each flash commit +// -- Flash LED_PMODE while writing EEPROM (both give visual feedback of writing progress) +// - Light LED_ERR whenever we hit a STK_NOSYNC. Turn it off when back in sync. +// - Use pins_arduino.h (should also work on Arduino Mega) +// +// October 2009 by David A. Mellis +// - Added support for the read signature command +// +// February 2009 by Randall Bohn +// - Added support for writing to EEPROM (what took so long?) +// Windows users should consider WinAVR's avrdude instead of the +// avrdude included with Arduino software. +// +// January 2008 by Randall Bohn +// - Thanks to Amplificar for helping me with the STK500 protocol +// - The AVRISP/STK500 (mk I) protocol is used in the arduino bootloader +// - The SPI functions herein were developed for the AVR910_ARD programmer +// - More information at http://code.google.com/p/mega-isp + +#include "pins_arduino.h" +#define RESET 10 + +#define LED_HB 9 +#define LED_ERR 8 +#define LED_PMODE 7 +#define PROG_FLICKER true + +#define HWVER 2 +#define SWMAJ 1 +#define SWMIN 18 + +// STK Definitions +#define STK_OK 0x10 +#define STK_FAILED 0x11 +#define STK_UNKNOWN 0x12 +#define STK_INSYNC 0x14 +#define STK_NOSYNC 0x15 +#define CRC_EOP 0x20 //ok it is a space... + +void pulse(int pin, int times); + +void setup() { + Serial.begin(19200); + pinMode(LED_PMODE, OUTPUT); + pulse(LED_PMODE, 2); + pinMode(LED_ERR, OUTPUT); + pulse(LED_ERR, 2); + pinMode(LED_HB, OUTPUT); + pulse(LED_HB, 2); +} + +int error = 0; +int pmode = 0; +// address for reading and writing, set by 'U' command +int here; +uint8_t buff[256]; // global block storage + +#define beget16(addr) (*addr * 256 + *(addr+1) ) +typedef struct param { + uint8_t devicecode; + uint8_t revision; + uint8_t progtype; + uint8_t parmode; + uint8_t polling; + uint8_t selftimed; + uint8_t lockbytes; + uint8_t fusebytes; + int flashpoll; + int eeprompoll; + int pagesize; + int eepromsize; + int flashsize; +} +parameter; + +parameter param; + +// this provides a heartbeat on pin 9, so you can tell the software is running. +uint8_t hbval = 128; +int8_t hbdelta = 8; +void heartbeat() { + if (hbval > 192) hbdelta = -hbdelta; + if (hbval < 32) hbdelta = -hbdelta; + hbval += hbdelta; + analogWrite(LED_HB, hbval); + delay(20); +} + + +void loop(void) { + // is pmode active? + if (pmode) digitalWrite(LED_PMODE, HIGH); + else digitalWrite(LED_PMODE, LOW); + // is there an error? + if (error) digitalWrite(LED_ERR, HIGH); + else digitalWrite(LED_ERR, LOW); + + // light the heartbeat LED + heartbeat(); + if (Serial.available()) { + avrisp(); + } +} + +uint8_t getch() { + while (!Serial.available()); + return Serial.read(); +} +void fill(int n) { + for (int x = 0; x < n; x++) { + buff[x] = getch(); + } +} + +#define PTIME 30 +void pulse(int pin, int times) { + do { + digitalWrite(pin, HIGH); + delay(PTIME); + digitalWrite(pin, LOW); + delay(PTIME); + } + while (times--); +} + +void prog_lamp(int state) { + if (PROG_FLICKER) + digitalWrite(LED_PMODE, state); +} + +void spi_init() { + uint8_t x; + SPCR = 0x53; + x = SPSR; + x = SPDR; +} + +void spi_wait() { + do { + } + while (!(SPSR & (1 << SPIF))); +} + +uint8_t spi_send(uint8_t b) { + uint8_t reply; + SPDR = b; + spi_wait(); + reply = SPDR; + return reply; +} + +uint8_t spi_transaction(uint8_t a, uint8_t b, uint8_t c, uint8_t d) { + uint8_t n; + spi_send(a); + n = spi_send(b); + //if (n != a) error = -1; + n = spi_send(c); + return spi_send(d); +} + +void empty_reply() { + if (CRC_EOP == getch()) { + Serial.print((char)STK_INSYNC); + Serial.print((char)STK_OK); + } + else { + error++; + Serial.print((char)STK_NOSYNC); + } +} + +void breply(uint8_t b) { + if (CRC_EOP == getch()) { + Serial.print((char)STK_INSYNC); + Serial.print((char)b); + Serial.print((char)STK_OK); + } + else { + error++; + Serial.print((char)STK_NOSYNC); + } +} + +void get_version(uint8_t c) { + switch (c) { + case 0x80: + breply(HWVER); + break; + case 0x81: + breply(SWMAJ); + break; + case 0x82: + breply(SWMIN); + break; + case 0x93: + breply('S'); // serial programmer + break; + default: + breply(0); + } +} + +void set_parameters() { + // call this after reading paramter packet into buff[] + param.devicecode = buff[0]; + param.revision = buff[1]; + param.progtype = buff[2]; + param.parmode = buff[3]; + param.polling = buff[4]; + param.selftimed = buff[5]; + param.lockbytes = buff[6]; + param.fusebytes = buff[7]; + param.flashpoll = buff[8]; + // ignore buff[9] (= buff[8]) + // following are 16 bits (big endian) + param.eeprompoll = beget16(&buff[10]); + param.pagesize = beget16(&buff[12]); + param.eepromsize = beget16(&buff[14]); + + // 32 bits flashsize (big endian) + param.flashsize = buff[16] * 0x01000000 + + buff[17] * 0x00010000 + + buff[18] * 0x00000100 + + buff[19]; + +} + +void start_pmode() { + spi_init(); + // following delays may not work on all targets... + pinMode(RESET, OUTPUT); + digitalWrite(RESET, HIGH); + pinMode(SCK, OUTPUT); + digitalWrite(SCK, LOW); + delay(50); + digitalWrite(RESET, LOW); + delay(50); + pinMode(MISO, INPUT); + pinMode(MOSI, OUTPUT); + spi_transaction(0xAC, 0x53, 0x00, 0x00); + pmode = 1; +} + +void end_pmode() { + pinMode(MISO, INPUT); + pinMode(MOSI, INPUT); + pinMode(SCK, INPUT); + pinMode(RESET, INPUT); + pmode = 0; +} + +void universal() { + int w; + uint8_t ch; + + fill(4); + ch = spi_transaction(buff[0], buff[1], buff[2], buff[3]); + breply(ch); +} + +void flash(uint8_t hilo, int addr, uint8_t data) { + spi_transaction(0x40 + 8 * hilo, + addr >> 8 & 0xFF, + addr & 0xFF, + data); +} +void commit(int addr) { + if (PROG_FLICKER) prog_lamp(LOW); + spi_transaction(0x4C, (addr >> 8) & 0xFF, addr & 0xFF, 0); + if (PROG_FLICKER) { + delay(PTIME); + prog_lamp(HIGH); + } +} + +//#define _current_page(x) (here & 0xFFFFE0) +int current_page(int addr) { + if (param.pagesize == 32) return here & 0xFFFFFFF0; + if (param.pagesize == 64) return here & 0xFFFFFFE0; + if (param.pagesize == 128) return here & 0xFFFFFFC0; + if (param.pagesize == 256) return here & 0xFFFFFF80; + return here; +} + + +void write_flash(int length) { + fill(length); + if (CRC_EOP == getch()) { + Serial.print((char) STK_INSYNC); + Serial.print((char) write_flash_pages(length)); + } + else { + error++; + Serial.print((char) STK_NOSYNC); + } +} + +uint8_t write_flash_pages(int length) { + int x = 0; + int page = current_page(here); + while (x < length) { + if (page != current_page(here)) { + commit(page); + page = current_page(here); + } + flash(LOW, here, buff[x++]); + flash(HIGH, here, buff[x++]); + here++; + } + + commit(page); + + return STK_OK; +} + +#define EECHUNK (32) +uint8_t write_eeprom(int length) { + // here is a word address, get the byte address + int start = here * 2; + int remaining = length; + if (length > param.eepromsize) { + error++; + return STK_FAILED; + } + while (remaining > EECHUNK) { + write_eeprom_chunk(start, EECHUNK); + start += EECHUNK; + remaining -= EECHUNK; + } + write_eeprom_chunk(start, remaining); + return STK_OK; +} +// write (length) bytes, (start) is a byte address +uint8_t write_eeprom_chunk(int start, int length) { + // this writes byte-by-byte, + // page writing may be faster (4 bytes at a time) + fill(length); + prog_lamp(LOW); + for (int x = 0; x < length; x++) { + int addr = start + x; + spi_transaction(0xC0, (addr >> 8) & 0xFF, addr & 0xFF, buff[x]); + delay(45); + } + prog_lamp(HIGH); + return STK_OK; +} + +void program_page() { + char result = (char) STK_FAILED; + int length = 256 * getch(); + length += getch(); + char memtype = getch(); + // flash memory @here, (length) bytes + if (memtype == 'F') { + write_flash(length); + return; + } + if (memtype == 'E') { + result = (char)write_eeprom(length); + if (CRC_EOP == getch()) { + Serial.print((char) STK_INSYNC); + Serial.print(result); + } + else { + error++; + Serial.print((char) STK_NOSYNC); + } + return; + } + Serial.print((char)STK_FAILED); + return; +} + +uint8_t flash_read(uint8_t hilo, int addr) { + return spi_transaction(0x20 + hilo * 8, + (addr >> 8) & 0xFF, + addr & 0xFF, + 0); +} + +char flash_read_page(int length) { + for (int x = 0; x < length; x += 2) { + uint8_t low = flash_read(LOW, here); + Serial.print((char) low); + uint8_t high = flash_read(HIGH, here); + Serial.print((char) high); + here++; + } + return STK_OK; +} + +char eeprom_read_page(int length) { + // here again we have a word address + int start = here * 2; + for (int x = 0; x < length; x++) { + int addr = start + x; + uint8_t ee = spi_transaction(0xA0, (addr >> 8) & 0xFF, addr & 0xFF, 0xFF); + Serial.print((char) ee); + } + return STK_OK; +} + +void read_page() { + char result = (char)STK_FAILED; + int length = 256 * getch(); + length += getch(); + char memtype = getch(); + if (CRC_EOP != getch()) { + error++; + Serial.print((char) STK_NOSYNC); + return; + } + Serial.print((char) STK_INSYNC); + if (memtype == 'F') result = flash_read_page(length); + if (memtype == 'E') result = eeprom_read_page(length); + Serial.print(result); + return; +} + +void read_signature() { + if (CRC_EOP != getch()) { + error++; + Serial.print((char) STK_NOSYNC); + return; + } + Serial.print((char) STK_INSYNC); + uint8_t high = spi_transaction(0x30, 0x00, 0x00, 0x00); + Serial.print((char) high); + uint8_t middle = spi_transaction(0x30, 0x00, 0x01, 0x00); + Serial.print((char) middle); + uint8_t low = spi_transaction(0x30, 0x00, 0x02, 0x00); + Serial.print((char) low); + Serial.print((char) STK_OK); +} +////////////////////////////////////////// +////////////////////////////////////////// + + +//////////////////////////////////// +//////////////////////////////////// +int avrisp() { + uint8_t data, low, high; + uint8_t ch = getch(); + switch (ch) { + case '0': // signon + error = 0; + empty_reply(); + break; + case '1': + if (getch() == CRC_EOP) { + Serial.print((char) STK_INSYNC); + Serial.print("AVR ISP"); + Serial.print((char) STK_OK); + } + break; + case 'A': + get_version(getch()); + break; + case 'B': + fill(20); + set_parameters(); + empty_reply(); + break; + case 'E': // extended parameters - ignore for now + fill(5); + empty_reply(); + break; + + case 'P': + start_pmode(); + empty_reply(); + break; + case 'U': // set address (word) + here = getch(); + here += 256 * getch(); + empty_reply(); + break; + + case 0x60: //STK_PROG_FLASH + low = getch(); + high = getch(); + empty_reply(); + break; + case 0x61: //STK_PROG_DATA + data = getch(); + empty_reply(); + break; + + case 0x64: //STK_PROG_PAGE + program_page(); + break; + + case 0x74: //STK_READ_PAGE 't' + read_page(); + break; + + case 'V': //0x56 + universal(); + break; + case 'Q': //0x51 + error = 0; + end_pmode(); + empty_reply(); + break; + + case 0x75: //STK_READ_SIGN 'u' + read_signature(); + break; + + // expecting a command, not CRC_EOP + // this is how we can get back in sync + case CRC_EOP: + error++; + Serial.print((char) STK_NOSYNC); + break; + + // anything else we will return STK_UNKNOWN + default: + error++; + if (CRC_EOP == getch()) + Serial.print((char)STK_UNKNOWN); + else + Serial.print((char)STK_NOSYNC); + } +} + + + From 04da3e87f20d4f3a6eef67922314bd9514bb14ca Mon Sep 17 00:00:00 2001 From: Nico Date: Sun, 11 Jan 2015 15:01:35 +0100 Subject: [PATCH 118/602] Fixed minor custom hid definition --- plugins/KeyboardioHID/Readme.md | 2 +- .../KeyboardioHID/avr/variants/leonardo_custom/pins_arduino.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 61e8056035..854381c41c 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -223,7 +223,7 @@ keycode/raw for keyboard Check Keyboard keycode function again? + add example Generalize HID key definitions via HIDTables for example? -update Burning via ISP (advanced) +update Burning via ISP for HL2 Test with Android phone (HL1) "Emulate" HL1 protocol remove dev HL2 link diff --git a/plugins/KeyboardioHID/avr/variants/leonardo_custom/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/leonardo_custom/pins_arduino.h index b6c714dbd0..c50913ae8c 100644 --- a/plugins/KeyboardioHID/avr/variants/leonardo_custom/pins_arduino.h +++ b/plugins/KeyboardioHID/avr/variants/leonardo_custom/pins_arduino.h @@ -40,7 +40,7 @@ You have to enable the specific hid apis on your own then, also the keyboard led */ #define HID_AUTOMATIC -#define HID_CUSTOM_SETTINGS +//#define HID_CUSTOM_SETTINGS //================================================================================ // Automatic From 32213f06c58cd49fb46e3ef68091ff838cc2b7bb Mon Sep 17 00:00:00 2001 From: Nico Date: Sun, 11 Jan 2015 15:04:15 +0100 Subject: [PATCH 119/602] gamepad report id fix --- plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h index 2d652e967f..c996420ef8 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h @@ -289,7 +289,7 @@ extern uint8_t hid_keyboard_leds; 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ \ 0x09, 0x04, /* USAGE (Joystick) */ \ 0xa1, 0x01, /* COLLECTION (Application) */ \ - 0x85, HID_REPORTID_GAMEPAD, /* REPORT_ID */ \ + 0x85, report_id, /* REPORT_ID */ \ /* 32 Buttons */ \ 0x05, 0x09, /* USAGE_PAGE (Button) */ \ 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ \ From b274cd0c2eb68e9c227e00828060deaac7a3aca9 Mon Sep 17 00:00:00 2001 From: Nico Date: Sun, 11 Jan 2015 15:36:08 +0100 Subject: [PATCH 120/602] Added custom gamepad example --- plugins/KeyboardioHID/Readme.md | 1 + .../variants/leonardo_custom/pins_arduino.h | 47 +++++++++++++++++++ .../avr/variants/micro_custom/pins_arduino.h | 47 +++++++++++++++++++ 3 files changed, 95 insertions(+) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 854381c41c..d4f44a990f 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -388,6 +388,7 @@ Useful Links/Credits * [Paul Stoffregen's Teensy Core](https://github.com/PaulStoffregen/cores) * [Keyboard Led Out report by hartmut_holgraefe](http://forum.arduino.cc/index.php?topic=173583.0) * [Github Pull Request with a lot of new functions](https://github.com/arduino/Arduino/pull/1803) +* [Arduino ISP fix](https://petervanhoyweghen.wordpress.com/2012/09/16/arduinoisp-on-the-leonardo/) * A lot of searching through the web * The awesome official Arduino IRC chat! * [The NicoHood Protocol ^.^](https://github.com/NicoHood/NicoHoodProtocol) diff --git a/plugins/KeyboardioHID/avr/variants/leonardo_custom/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/leonardo_custom/pins_arduino.h index c50913ae8c..111d4f90c9 100644 --- a/plugins/KeyboardioHID/avr/variants/leonardo_custom/pins_arduino.h +++ b/plugins/KeyboardioHID/avr/variants/leonardo_custom/pins_arduino.h @@ -83,6 +83,53 @@ HID_REPORT_MOUSE(HID_REPORTID_MOUSE) //#define HID_GAMEPAD_API_ENABLE //#define HID_ENABLE_ALL_APIS // enables all of the ones above + +//// 2nd example with a custom Joystick report (the Gamepad API wont work anymor since the report is different) +//#define EXTERN_HID_REPORT \ /* Gamepad with 32 buttons and 10 axis*/ \ +//0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ \ +//0x09, 0x04, /* USAGE (Joystick) */ \ +//0xa1, 0x01, /* COLLECTION (Application) */ \ +//0x85, HID_REPORTID_GAMEPAD, /* REPORT_ID */ \ +///* 32 Buttons */ \ +//0x05, 0x09, /* USAGE_PAGE (Button) */ \ +//0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ \ +//0x29, 0x20, /* USAGE_MAXIMUM (Button 32) */ \ +//0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \ +//0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ \ +//0x75, 0x01, /* REPORT_SIZE (1) */ \ +//0x95, 0x20, /* REPORT_COUNT (32) */ \ +//0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ +///* 10 8bit Axis */ \ +//0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ \ +//0xa1, 0x00, /* COLLECTION (Physical) */ \ +//0x09, 0x30, /* USAGE (X) */ \ +//0x09, 0x31, /* USAGE (Y) */ \ +//0x09, 0x33, /* USAGE (Rx) */ \ +//0x09, 0x34, /* USAGE (Ry) */ \ +//0x09, 0x32, /* USAGE (Z) */ \ +//0x09, 0x35, /* USAGE (Rz) */ \ +//0x09, 0x36, /* Usage (Slider) */ \ +//0x09, 0x36, /* Usage (Slider) */ \ +//0x09, 0x36, /* Usage (Slider) */ \ +//0x09, 0x36, /* Usage (Slider) */ \ +//0x15, 0x80, /* LOGICAL_MINIMUM (-128) */ \ +//0x25, 0x7F, /* LOGICAL_MAXIMUM (127) */ \ +//0x75, 0x08, /* REPORT_SIZE (8) */ \ +//0x95, 0x0A, /* REPORT_COUNT (10) */ \ +//0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ +//0xc0, /* END_COLLECTION */ \ +//0xc0 /* END_COLLECTION */ +// +//// activate your custom HID-APIs here: +////#define HID_MOUSE_API_ENABLE +////#define HID_KEYBOARD_API_ENABLE +////#define HID_RAWHID_API_ENABLE +////#define HID_CONSUMER_API_ENABLE +////#define HID_SYSTEM_API_ENABLE +////#define HID_GAMEPAD_API_ENABLE +////#define HID_ENABLE_ALL_APIS // enables all of the ones above + + /* You can use the pre defined reports as well. Keep in mind that changing the ids or reports might confuse your OS. diff --git a/plugins/KeyboardioHID/avr/variants/micro_custom/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/micro_custom/pins_arduino.h index 912bb5190e..59045af4ec 100644 --- a/plugins/KeyboardioHID/avr/variants/micro_custom/pins_arduino.h +++ b/plugins/KeyboardioHID/avr/variants/micro_custom/pins_arduino.h @@ -83,6 +83,53 @@ HID_REPORT_MOUSE(HID_REPORTID_MOUSE) //#define HID_GAMEPAD_API_ENABLE //#define HID_ENABLE_ALL_APIS // enables all of the ones above + +//// 2nd example with a custom Joystick report (the Gamepad API wont work anymor since the report is different) +//#define EXTERN_HID_REPORT \ /* Gamepad with 32 buttons and 10 axis*/ \ +//0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ \ +//0x09, 0x04, /* USAGE (Joystick) */ \ +//0xa1, 0x01, /* COLLECTION (Application) */ \ +//0x85, HID_REPORTID_GAMEPAD, /* REPORT_ID */ \ +///* 32 Buttons */ \ +//0x05, 0x09, /* USAGE_PAGE (Button) */ \ +//0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ \ +//0x29, 0x20, /* USAGE_MAXIMUM (Button 32) */ \ +//0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \ +//0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ \ +//0x75, 0x01, /* REPORT_SIZE (1) */ \ +//0x95, 0x20, /* REPORT_COUNT (32) */ \ +//0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ +///* 10 8bit Axis */ \ +//0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ \ +//0xa1, 0x00, /* COLLECTION (Physical) */ \ +//0x09, 0x30, /* USAGE (X) */ \ +//0x09, 0x31, /* USAGE (Y) */ \ +//0x09, 0x33, /* USAGE (Rx) */ \ +//0x09, 0x34, /* USAGE (Ry) */ \ +//0x09, 0x32, /* USAGE (Z) */ \ +//0x09, 0x35, /* USAGE (Rz) */ \ +//0x09, 0x36, /* Usage (Slider) */ \ +//0x09, 0x36, /* Usage (Slider) */ \ +//0x09, 0x36, /* Usage (Slider) */ \ +//0x09, 0x36, /* Usage (Slider) */ \ +//0x15, 0x80, /* LOGICAL_MINIMUM (-128) */ \ +//0x25, 0x7F, /* LOGICAL_MAXIMUM (127) */ \ +//0x75, 0x08, /* REPORT_SIZE (8) */ \ +//0x95, 0x0A, /* REPORT_COUNT (10) */ \ +//0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ +//0xc0, /* END_COLLECTION */ \ +//0xc0 /* END_COLLECTION */ +// +//// activate your custom HID-APIs here: +////#define HID_MOUSE_API_ENABLE +////#define HID_KEYBOARD_API_ENABLE +////#define HID_RAWHID_API_ENABLE +////#define HID_CONSUMER_API_ENABLE +////#define HID_SYSTEM_API_ENABLE +////#define HID_GAMEPAD_API_ENABLE +////#define HID_ENABLE_ALL_APIS // enables all of the ones above + + /* You can use the pre defined reports as well. Keep in mind that changing the ids or reports might confuse your OS. From f7eaf830c1134867af32c20b74581517f5e9e4eb Mon Sep 17 00:00:00 2001 From: Nico Date: Sun, 11 Jan 2015 18:14:59 +0100 Subject: [PATCH 121/602] Made installation more clear --- plugins/KeyboardioHID/Readme.md | 6 +++++- plugins/KeyboardioHID/pictures/board.png | Bin 27753 -> 46451 bytes 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index d4f44a990f..9a628330c1 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -48,15 +48,19 @@ Installation has changed over the time. You don't have to modify the original co Put all files into *sketchbook/hardware/HID/*. **You have to rename the folder HID-master to HID.** **Your sketchbook folder should look like this:** + ![Installation Picture](pictures/installation.png) +Ensure that under File->Preferences the correct sketchbook folder is selected. **Restart the IDE.** + + If you like to, you can add the keywords.txt to your Arduino IDE so that words like 'Gamepad' are highlighted. Replace the file in *arduino-1.6.0/lib/keywords.txt* with the *keywords.txt* provided in this project. How to use ========== -### Micro/Leonardo + HoodLoader2 +### Micro/Leonardo & HoodLoader2 **1. Select the new board via *Tools->Board->Arduino Leonardo HID-Project* for example.** For HoodLoader2 select the 16u2 MCU. Ensure HoodLoader2 board definition files are up to date. diff --git a/plugins/KeyboardioHID/pictures/board.png b/plugins/KeyboardioHID/pictures/board.png index a370b2197177b256674bfab76cf9a6578889a282..a3dd47cb1333fe31949cf4917aa146b3471bb3d3 100644 GIT binary patch literal 46451 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 dlKcC^UrlyD6oXKR;50wA_ literal 27753 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 From f12d97efee1bcfddf63dfb3683ec3d9a0b3257e6 Mon Sep 17 00:00:00 2001 From: Nico Date: Sun, 11 Jan 2015 22:52:22 +0100 Subject: [PATCH 122/602] Update Readme.md --- plugins/KeyboardioHID/Readme.md | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 9a628330c1..24a870f64c 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -36,24 +36,27 @@ The idea is to enable enhanced USB functions to almost all 'standard' Arduino bo Installation ============ +##### 1. Grab the newest Arduino release HID-Project only works with the new Arduino IDE 1.5.8 or newer. I recommend you to use the new [IDE 1.6 rc1](https://groups.google.com/a/arduino.cc/d/msg/developers/2_GD40Sl6FA/OLWZMwaLJ3IJ). +##### 2. Install HoodLoader2 (Arduino Uno/Mega only) For Arduino Uno/Mega first install [HoodLoader2 dev](https://github.com/NicoHood/HoodLoader2/tree/dev) on your 16u2 + the needed software files. Make sure your HoodLoader2 software is up to date when you also update the HID-Project files. [HoodLoader1](https://github.com/NicoHood/HoodLoader) is only supported for legacy but will get a new use soon! For Arduino Micro/Leonardo ignore this step. +##### 3. Install the HID core files Installation has changed over the time. You don't have to modify the original core any more. Put all files into *sketchbook/hardware/HID/*. **You have to rename the folder HID-master to HID.** +Ensure that under 'File->Preferences' the correct sketchbook folder is selected. **Restart the IDE.** + **Your sketchbook folder should look like this:** ![Installation Picture](pictures/installation.png) -Ensure that under File->Preferences the correct sketchbook folder is selected. **Restart the IDE.** - - +##### 4. Add the keyword.txt for highlights (optional) If you like to, you can add the keywords.txt to your Arduino IDE so that words like 'Gamepad' are highlighted. Replace the file in *arduino-1.6.0/lib/keywords.txt* with the *keywords.txt* provided in this project. @@ -62,15 +65,15 @@ How to use ### Micro/Leonardo & HoodLoader2 -**1. Select the new board via *Tools->Board->Arduino Leonardo HID-Project* for example.** -For HoodLoader2 select the 16u2 MCU. Ensure HoodLoader2 board definition files are up to date. +##### 1. Select the new board via *Tools->Board->Arduino Leonardo HID-Project* for example. +For HoodLoader2 select the 16u2 MCU, for Leonardo/Micro the specific entry. +Ensure HoodLoader2 board definition files are up to date and installed. The Uno and Mega entry is just for advanced users who want to use the HID-APIs but normally you'd need the new HoodLoader2 (16u2) board definition files. ![Board Selection Picture](pictures/board.png) -**2. Select the USB-Core you want to use. You have 5 options here:** - +##### 2. Select the USB-Core you want to use. You have 5 options here: * Extended (Keyboard+Leds, Mouse+Absolute, Consumer, System) * Gamepad (Keyboard+Leds, Mouse, Gamepad) * Custom (Your custom configuration, see below) @@ -83,15 +86,17 @@ To create a **custom HID report descriptor** you can edit the file in *avr/varia Same for Micro and HoodLoader2. Not all HID reports are playing well together on all OS so I made these pre selections. With the custom report you can try it out yourself. Everything you need should be in the pins_arduino.h file. -**3. Try the Basic HID examples for each HID device. They are pretty much self explaining.** +##### 3. Try the Basic HID examples for each HID device. +They are pretty much self explaining. You can also see the *Projects/HID_Test* for an all in one example. See *Project/USB-Serial* for a fully usable USB-Serial bridge and how to use the new Serial functions. In the CDC.h you can also see the new Control Line functions for advanced users. Keep in mind that the USB_ENDPOINTs for the u2 Series are set to 16 bytes, so the Serial buffer is also smaller (normally 64b). -**If you don't want to use the USB-Core** you can also choose under *Tools/USB Core* "No USB functions" to get rid of the USB stuff -and save the ram for other stuff if you don't need it. You also don't need the HID Project essentially if you don't want to use the USB functions. +##### 4. Deactivate USB-Core to save flash and ram (optional) +If you don't want to use the USB-Core you can also choose under *Tools/USB Core* "No USB functions" to get rid of the USB stuff and save the ram for other stuff if you don't need it. You also don't need the HID Project essentially if you don't want to use the USB functions. + Due to a bad Leonardo/Micro bootloader you need to add an add an ISR into every sketch as workaround. **This is not needed for HoodLoader2 devices**, since the bootloader does a true watchdog reset on reprogramming and not a simple application jump (the usb clock is then still on and breaks any delay functions). @@ -453,4 +458,4 @@ 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 +``` From 1a580a27bda896652e85e43c5a868f6116ba1337 Mon Sep 17 00:00:00 2001 From: Nico Date: Sun, 11 Jan 2015 23:10:14 +0100 Subject: [PATCH 123/602] Added HelloWorld example --- plugins/KeyboardioHID/Readme.md | 10 ++++-- .../examples/HelloWorld/HelloWorld.ino | 34 ++++++++++++++++++ plugins/KeyboardioHID/pictures/example.png | Bin 0 -> 21346 bytes 3 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 plugins/KeyboardioHID/examples/HelloWorld/HelloWorld.ino create mode 100644 plugins/KeyboardioHID/pictures/example.png diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 24a870f64c..bd7f7a50cb 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -87,15 +87,19 @@ Same for Micro and HoodLoader2. Not all HID reports are playing well together on With the custom report you can try it out yourself. Everything you need should be in the pins_arduino.h file. ##### 3. Try the Basic HID examples for each HID device. -They are pretty much self explaining. -You can also see the *Projects/HID_Test* for an all in one example. + +![example Picture](pictures/example.png) + +You may want to start with the HelloWorld and HID_Basic examples. They are pretty much self explaining. +Ensure that always the correct HID-Core is selected. See *Project/USB-Serial* for a fully usable USB-Serial bridge and how to use the new Serial functions. In the CDC.h you can also see the new Control Line functions for advanced users. Keep in mind that the USB_ENDPOINTs for the u2 Series are set to 16 bytes, so the Serial buffer is also smaller (normally 64b). ##### 4. Deactivate USB-Core to save flash and ram (optional) -If you don't want to use the USB-Core you can also choose under *Tools/USB Core* "No USB functions" to get rid of the USB stuff and save the ram for other stuff if you don't need it. You also don't need the HID Project essentially if you don't want to use the USB functions. +If you don't want to use the USB-Core you can also choose under *Tools/USB Core* "No USB functions" to get rid of the USB stuff +and save the ram for other stuff if you don't need it. You also don't need the HID Project essentially if you don't want to use the USB functions. Due to a bad Leonardo/Micro bootloader you need to add an add an ISR into every sketch as workaround. **This is not needed for HoodLoader2 devices**, since the bootloader does a true watchdog reset on reprogramming and not a simple application jump diff --git a/plugins/KeyboardioHID/examples/HelloWorld/HelloWorld.ino b/plugins/KeyboardioHID/examples/HelloWorld/HelloWorld.ino new file mode 100644 index 0000000000..eaa964bc7b --- /dev/null +++ b/plugins/KeyboardioHID/examples/HelloWorld/HelloWorld.ino @@ -0,0 +1,34 @@ +/* + Copyright (c) 2014 NicoHood + See the readme for credit to other people. + + Hello World Keyboard Beginner example + + Press a button to write some text to your pc. + See official and HID Project documentation for more information. +*/ + +const int pinLed = LED_BUILTIN; +const int pinButton = 2; + +void setup() { + // hardware setup + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); + + // Sends a clean report to the host. This is important on any Arduino type. + Keyboard.begin(); +} + +void loop() { + if (digitalRead(pinButton) == LOW) { + digitalWrite(pinLed, HIGH); + + // Same use as the official library, pretty much self explaining + Keyboard.println("Hello World"); + + // simple debounce + delay(500); + digitalWrite(pinLed, LOW); + } +} diff --git a/plugins/KeyboardioHID/pictures/example.png b/plugins/KeyboardioHID/pictures/example.png new file mode 100644 index 0000000000000000000000000000000000000000..949047fb8dfae1186b8a131158003fe4aba683ab GIT binary patch literal 21346 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 literal 0 HcmV?d00001 From 0696ffc1d7c03fec7fc6068d795e14c717a0bcb5 Mon Sep 17 00:00:00 2001 From: Nico Date: Sun, 11 Jan 2015 23:11:43 +0100 Subject: [PATCH 124/602] Removed outdated notice in examples --- .../HID_Advanced/AdvancedGamepad/AdvancedGamepad.ino | 5 +---- .../examples/HID_Basic/HID_Consumer/HID_Consumer.ino | 3 --- .../examples/HID_Basic/HID_Gamepad/HID_Gamepad.ino | 3 --- .../examples/HID_Basic/HID_Keyboard/HID_Keyboard.ino | 3 --- .../examples/HID_Basic/HID_Keyboard_Led/HID_Keyboard_Led.ino | 3 --- .../KeyboardioHID/examples/HID_Basic/HID_Mouse/HID_Mouse.ino | 3 --- .../examples/HID_Basic/HID_System/HID_System.ino | 3 --- 7 files changed, 1 insertion(+), 22 deletions(-) diff --git a/plugins/KeyboardioHID/examples/HID_Advanced/AdvancedGamepad/AdvancedGamepad.ino b/plugins/KeyboardioHID/examples/HID_Advanced/AdvancedGamepad/AdvancedGamepad.ino index 629332023e..0aeb3df2df 100644 --- a/plugins/KeyboardioHID/examples/HID_Advanced/AdvancedGamepad/AdvancedGamepad.ino +++ b/plugins/KeyboardioHID/examples/HID_Advanced/AdvancedGamepad/AdvancedGamepad.ino @@ -3,10 +3,7 @@ See the readme for credit to other people. Advanced Gamepad example - - Make sure the Gamepad report is set in: - sketchbook/hardware/HID/avr/variants/hid_descriptors/hid_descriptors.h - */ +*/ const int pinLed = LED_BUILTIN; const int pinButton = 2; diff --git a/plugins/KeyboardioHID/examples/HID_Basic/HID_Consumer/HID_Consumer.ino b/plugins/KeyboardioHID/examples/HID_Basic/HID_Consumer/HID_Consumer.ino index 186f6e1ef9..f00ddc9b57 100644 --- a/plugins/KeyboardioHID/examples/HID_Basic/HID_Consumer/HID_Consumer.ino +++ b/plugins/KeyboardioHID/examples/HID_Basic/HID_Consumer/HID_Consumer.ino @@ -7,9 +7,6 @@ Press a button to play/pause music player See HID Project documentation for more Consumer keys. - Make sure the Consumer report is set in: - sketchbook/hardware/HID/avr/variants/hid_descriptors/hid_descriptors.h - // basic Media key definitions, see HID Project and official USB docs for more #define MEDIA_FAST_FORWARD 0xB3 #define MEDIA_REWIND 0xB4 diff --git a/plugins/KeyboardioHID/examples/HID_Basic/HID_Gamepad/HID_Gamepad.ino b/plugins/KeyboardioHID/examples/HID_Basic/HID_Gamepad/HID_Gamepad.ino index eeadb3fbfb..89007aed9e 100644 --- a/plugins/KeyboardioHID/examples/HID_Basic/HID_Gamepad/HID_Gamepad.ino +++ b/plugins/KeyboardioHID/examples/HID_Basic/HID_Gamepad/HID_Gamepad.ino @@ -6,9 +6,6 @@ Press a button and demonstrate Gamepad actions - Make sure the Gamepad report is set in: - sketchbook/hardware/HID/avr/variants/hid_descriptors/hid_descriptors.h - Function prototypes: void begin(void); void end(void); diff --git a/plugins/KeyboardioHID/examples/HID_Basic/HID_Keyboard/HID_Keyboard.ino b/plugins/KeyboardioHID/examples/HID_Basic/HID_Keyboard/HID_Keyboard.ino index 62f06aba57..d15e684f76 100644 --- a/plugins/KeyboardioHID/examples/HID_Basic/HID_Keyboard/HID_Keyboard.ino +++ b/plugins/KeyboardioHID/examples/HID_Basic/HID_Keyboard/HID_Keyboard.ino @@ -6,9 +6,6 @@ Press a button to write some text to your pc. See official and HID Project documentation for more infos - - Make sure the Keyboard report is set in (by default it is): - sketchbook/hardware/HID/avr/variants/hid_descriptors/hid_descriptors.h */ const int pinLed = LED_BUILTIN; diff --git a/plugins/KeyboardioHID/examples/HID_Basic/HID_Keyboard_Led/HID_Keyboard_Led.ino b/plugins/KeyboardioHID/examples/HID_Basic/HID_Keyboard_Led/HID_Keyboard_Led.ino index 0d5dcf2223..3aa8134f82 100644 --- a/plugins/KeyboardioHID/examples/HID_Basic/HID_Keyboard_Led/HID_Keyboard_Led.ino +++ b/plugins/KeyboardioHID/examples/HID_Basic/HID_Keyboard_Led/HID_Keyboard_Led.ino @@ -7,9 +7,6 @@ Press a button to toogle caps lock. Caps lock state is represented by the onboard led. See official and HID Project documentation for more infos - - Make sure the Keyboard report + LEDs! is set in: - sketchbook/hardware/HID/avr/variants/hid_descriptors/hid_descriptors.h */ const int pinLed = LED_BUILTIN; diff --git a/plugins/KeyboardioHID/examples/HID_Basic/HID_Mouse/HID_Mouse.ino b/plugins/KeyboardioHID/examples/HID_Basic/HID_Mouse/HID_Mouse.ino index fa24b935b2..d5cf16bb90 100644 --- a/plugins/KeyboardioHID/examples/HID_Basic/HID_Mouse/HID_Mouse.ino +++ b/plugins/KeyboardioHID/examples/HID_Basic/HID_Mouse/HID_Mouse.ino @@ -7,9 +7,6 @@ Press a button to click, move, moveTo the mouse. See official documentation for more infos - Make sure the Absolute Mouse report is set in: - sketchbook/hardware/HID/avr/variants/hid_descriptors/hid_descriptors.h - Mouse Key definitions: MOUSE_LEFT MOUSE_RIGHT diff --git a/plugins/KeyboardioHID/examples/HID_Basic/HID_System/HID_System.ino b/plugins/KeyboardioHID/examples/HID_Basic/HID_System/HID_System.ino index b4f8588691..1e8db5335e 100644 --- a/plugins/KeyboardioHID/examples/HID_Basic/HID_System/HID_System.ino +++ b/plugins/KeyboardioHID/examples/HID_Basic/HID_System/HID_System.ino @@ -5,9 +5,6 @@ System example Press a button to put pc into sleep/shut it down or wake it up again. - - Make sure the System report is set in: - sketchbook/hardware/HID/avr/variants/hid_descriptors/hid_descriptors.h */ const int pinLed = LED_BUILTIN; From f8a19383c5003836746aab25ced790a89a9e751e Mon Sep 17 00:00:00 2001 From: Nico Date: Mon, 12 Jan 2015 10:20:18 +0100 Subject: [PATCH 125/602] Update Readme.md Added Content menu --- plugins/KeyboardioHID/Readme.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index bd7f7a50cb..3a60edb9e8 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -6,6 +6,21 @@ This project went through a lot of phases and has now reached a new Arduino USB- with a lot of new functions like extended HID. It also supports HoodLoader1+2. The idea is to enable enhanced USB functions to almost all 'standard' Arduino boards. +##### Content +* [Features](https://github.com/NicoHood/HID/tree/Official-Integration#features) +* [Installation](https://github.com/NicoHood/HID/tree/Official-Integration#installation) +* [How to use](https://github.com/NicoHood/HID/tree/Official-Integration#how-to-use) +* [Troubleshoot](https://github.com/NicoHood/HID/tree/Official-Integration#troubleshoot) +* [How it works](https://github.com/NicoHood/HID/tree/Official-Integration#how-it-works) +* [Known bugs](https://github.com/NicoHood/HID/tree/Official-Integration#known-bugs) +* [Version history](https://github.com/NicoHood/HID/tree/Official-Integration#version-history) +* [Useful links and credits](https://github.com/NicoHood/HID/tree/Official-Integration#useful-linkscredits) +* [Developer information](https://github.com/NicoHood/HID/tree/Official-Integration#for-developers) +* [License and copyright](https://github.com/NicoHood/HID/tree/Official-Integration#licence-and-copyright) + +Features +======== + **Supported Arduinos (IDE 1.5.8 or higher!):** * Uno (with HoodLoader1 or 2) * Mega (with HoodLoader1 or 2) From b5424d68ef3bf6f96dc9ab0559f7a7b7aafd3655 Mon Sep 17 00:00:00 2001 From: Nico Date: Mon, 12 Jan 2015 17:28:54 +0100 Subject: [PATCH 126/602] readme --- plugins/KeyboardioHID/Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 3a60edb9e8..864475e68b 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -267,13 +267,13 @@ Known Bugs * Do not name the Arduino Sketch 'Mouse.ino' or 'Keyboard.ino' etc. Your Arduino IDE will output errors then if you double click the file and try to compile. * RawHID is not working properly, test it at your own risk. -* Feel free to open an Issue on Github if you find a bug. Or message me via my [blog](http://nicohood.wordpress.com/)! * All OS have some problems with Gamepads. Dont use more than one device for Linux and be careful when you change the descriptor. * XBMC 13.1 (a Media Center) uses Gamepad input. Its seems to not work and may cause weird errors. Even with a standard Gamepad I have these errors. Just want to mention it here. * The Serial may disconnect if you have too much throughput. This is a general bug of the Arduino Core, which might be fixed. For example Adalight dosnt work well for me, so you better use an Arduino Uno with Hoodloader1 (yes the older one!) for Mediacenter control and Ambilight. +* Feel free to open an Issue on Github if you find a bug. Or message me via my [blog](http://nicohood.wordpress.com/)! Version History From ef8caf1ca99f0281f47a75afd9958625e9435c29 Mon Sep 17 00:00:00 2001 From: Nico Date: Thu, 15 Jan 2015 11:41:02 +0100 Subject: [PATCH 127/602] Update Readme.md --- plugins/KeyboardioHID/Readme.md | 40 +++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 864475e68b..95a701956b 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -160,8 +160,23 @@ Its more a legacy version to still use HoodLoader1 or to reimplement something s It is not better than this solution, maybe easier to use since its just more integrated. [Outdated HID Project for 1.5.7](https://github.com/NicoHood/HID/tree/3d8a9b40752a143141b8be4b8f744e203c80b000) +### Arduino as ISP +You want to use your Leonardo/Micro as ISP as well? Here is a simple fix (not working with HoodLoader2 currently): +Select the Leonardo board and upload the Arduino as ISP sketch from this project to your Leonardo. +Select the board you want to flash and under *Tools->Programmer->Arduino as ISP (Leonardo)*. +Ensure the correct Serial port is selected, wires are also correct and hit burn bootloader. + +A fix for the u2 Series is in work. Optional you could use HoodLoader1 firmware as ISP. +The only thing I changed was the reset pin to pin 10 instead of SS +and the upload protocol from stk500v1 to arduino to avoid any CDC Serial dtr state problems. -### Midi support? +Troubleshoot/FAQ +================ + +##### Error: Selected board depends on 'HID' core (not installed) +See [issue #9](https://github.com/NicoHood/HID/issues/9). + +##### Midi support? Some people have asked me about Midi support. It is not planned to integrate Midi into the HID-Project USB-Core since it is very complicated to do so. But I will work on a new Midi firmware for the 16u2 that supports of course Midi (HoodLoader2 only). A firmware is something like a pre-compiled sketch. With the difference that I wont use the Arduino IDE to create this firmware. I will use Lufa and a makefile to compile this firmware. This is more efficient. @@ -174,32 +189,23 @@ Install HoodLoader2 and flash the hex file. If it works please leave me some inf * https://github.com/ddiakopoulos/hiduino * http://hunt.net.nz/users/darran/weblog/5b7f8/Arduino_UNO_USB_MIDI_firmware.html +* Also see [issue #2](https://github.com/NicoHood/HID/issues/2) -### Arduino as ISP -You want to use your Leonardo/Micro as ISP as well? Here is a simple fix (not working with HoodLoader2 currently): -Select the Leonardo board and upload the Arduino as ISP sketch from this project to your Leonardo. -Select the board you want to flash and under *Tools->Programmer->Arduino as ISP (Leonardo)*. -Ensure the correct Serial port is selected, wires are also correct and hit burn bootloader. - -A fix for the u2 Series is in work. Optional you could use HoodLoader1 firmware as ISP. -The only thing I changed was the reset pin to pin 10 instead of SS -and the upload protocol from stk500v1 to arduino to avoid any CDC Serial dtr state problems. - -Troubleshoot -============ - -**Any random weird problem** is mostly solved by a pc reboot or a port switching. Try another (USB2.0) port if you have any problems with your device. +##### Any random weird problem +is mostly solved by a pc reboot or a port switching. Try another (USB2.0) port if you have any problems with your device. You might also try it on another pc to see if your OS mixes up drivers. Once I had a problem with my USB-Hub, so ensure to connect it directly. You could also try a different/shorter USB cable. -**Switching the HID-Core** might confuse the OS since the USB device changes completely from one second to the other. +##### Switching the HID-Core +might confuse the OS since the USB device changes completely from one second to the other. Therefore go to Printers and Devices on Windows and select remove. Reconnect your Arduino and maybe remove it again if its not working properly. Alternatively you can also restart your PC or use another USB PID (in the boards.txt) to see if its a Windows problem or not. If you change the USB PID the CDC Driver wont be loaded but you can always reupload a sketch in bootloader mode. ![remove usb device](pictures/remove-device.png) -**Gamepads** had several problems over the time. The first thing I'd like to mention is that the calibration windows only updates if you focus it. +##### Gamepads +had several problems over the time. The first thing I'd like to mention is that the calibration windows only updates if you focus it. Windows only supports gamepads with up to 7 axis and 32 buttons and has problems with more than one Gamepad in a multireport. Linux has problems when gamepads are in multi reports with a system device for example. It may occur that it display immense axis/buttons or none at all. The current gamepad setting was tested under windows and ubuntu and seems to work. Feel free to extend the gamepad report at your own risk. From ac821099c52835a341bba3048eda6c9df280388b Mon Sep 17 00:00:00 2001 From: Nico Date: Fri, 16 Jan 2015 19:34:07 +0100 Subject: [PATCH 128/602] added preferences picture --- plugins/KeyboardioHID/pictures/preferences.png | Bin 0 -> 18484 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 plugins/KeyboardioHID/pictures/preferences.png diff --git a/plugins/KeyboardioHID/pictures/preferences.png b/plugins/KeyboardioHID/pictures/preferences.png new file mode 100644 index 0000000000000000000000000000000000000000..44247e166e205d8e691c25f60307953b3cf69369 GIT binary patch literal 18484 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 SjlI+dATI-!E_(g$^Zx*oku;+K literal 0 HcmV?d00001 From ea0ef14afb8ef9b1cad658da5eef55ea795cb5de Mon Sep 17 00:00:00 2001 From: Nico Date: Sat, 17 Jan 2015 10:21:54 +0100 Subject: [PATCH 129/602] Moved USB_EP_SIZE definition This was needed in order to use the HID_Core without an USB AVR to still use the HID APIs --- plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBAPI.h | 7 +++++++ plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBDesc.h | 7 ------- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBAPI.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBAPI.h index f6ac2f365c..fe0156731e 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBAPI.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBAPI.h @@ -52,6 +52,13 @@ typedef unsigned long u32; #include "Arduino.h" +// edit by NicoHood +// this definitions is usefull if you want to reduce the EP_SIZE to 16 +// at the moment only 64 and 16 as EP_SIZE for all EPs are supported except the control endpoint +#ifndef USB_EP_SIZE +#define USB_EP_SIZE 64 +#endif + #if defined(USBCON) #include "USBDesc.h" diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBDesc.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBDesc.h index a7c33889b8..d787f3ee72 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBDesc.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBDesc.h @@ -79,13 +79,6 @@ THE SOFTWARE. #define HID_TX HID_ENDPOINT_INT #endif -// edit by NicoHood -// this definitions is usefull if you want to reduce the EP_SIZE to 16 -// at the moment only 64 and 16 as EP_SIZE for all EPs are supported except the control endpoint -#ifndef USB_EP_SIZE -#define USB_EP_SIZE 64 -#endif - #define IMANUFACTURER 1 #define IPRODUCT 2 From 0d5dd30647a639b08b0e99aace51c803f35acc9f Mon Sep 17 00:00:00 2001 From: Nico Date: Sat, 17 Jan 2015 11:01:34 +0100 Subject: [PATCH 130/602] Improved USB-Serial Now the buffer can even shrink down to 2 bytes. Not sure why 1 bytes gives problems. Also a buffer with USB_EP_SIZE is now also possible. --- plugins/KeyboardioHID/Readme.md | 1 + .../KeyboardioHID/examples/Projects/USB-Serial/USB-Serial.ino | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 95a701956b..ca00482391 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -314,6 +314,7 @@ Version History * USB-Serial now fully reprogrammable * Easy USB-Core selection via Tools->USB-Core * Added Arduino as ISP fix for 32u4 (u2 Series doesn't work at the moment) +* Updated USB-Serial 2.0 Release (29.11.2014) * Added HoodLoader2 diff --git a/plugins/KeyboardioHID/examples/Projects/USB-Serial/USB-Serial.ino b/plugins/KeyboardioHID/examples/Projects/USB-Serial/USB-Serial.ino index 5d8ac8c718..1c9e7eb9e4 100644 --- a/plugins/KeyboardioHID/examples/Projects/USB-Serial/USB-Serial.ino +++ b/plugins/KeyboardioHID/examples/Projects/USB-Serial/USB-Serial.ino @@ -33,11 +33,10 @@ void loop() { // Serial -> USB if (Serial1.available()) { - Serial.flush(); // send maximum one EP_SIZE to give the usb some time to flush the buffer uint8_t buff[USB_EP_SIZE - 1]; int i = 0; - for (i = 0; i < USB_EP_SIZE - 1; i++) { + for (i = 0; i < sizeof(buff); i++) { if (Serial1.available()) buff[i] = Serial1.read(); else break; From fcb33f303467e5c687ce8719d18248bb0c7edb5c Mon Sep 17 00:00:00 2001 From: Nico Date: Sat, 17 Jan 2015 14:53:10 +0100 Subject: [PATCH 131/602] Fixed Consumer/System-Control names Also added Absolute Mouse Report --- .../avr/cores/hid/USB-Core/Consumer.h | 8 ++++---- .../KeyboardioHID/avr/cores/hid/USB-Core/HID.h | 16 ++++++++-------- .../KeyboardioHID/avr/cores/hid/USB-Core/Mouse.h | 13 ++++++++++++- .../avr/cores/hid/USB-Core/System.h | 2 +- .../avr/variants/leonardo_custom/pins_arduino.h | 12 ++++++------ .../avr/variants/leonardo_gamepad/pins_arduino.h | 4 ++-- .../avr/variants/leonardo_hid/pins_arduino.h | 4 ++-- .../avr/variants/micro_custom/pins_arduino.h | 12 ++++++------ .../avr/variants/micro_gamepad/pins_arduino.h | 4 ++-- .../avr/variants/micro_hid/pins_arduino.h | 4 ++-- 10 files changed, 45 insertions(+), 34 deletions(-) diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Consumer.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Consumer.h index 1cc9dae750..3397f523d2 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Consumer.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Consumer.h @@ -64,7 +64,7 @@ typedef union{ uint16_t key3; uint16_t key4; }; -} HID_ConsumerReport_Data_t; +} HID_ConsumerControlReport_Data_t; class Consumer_{ public: @@ -85,7 +85,7 @@ class Consumer_{ } inline void press(uint16_t m){ // search for a free spot - for (int i = 0; i < sizeof(HID_ConsumerReport_Data_t) / 2; i++) { + for (int i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { if (_report.whole16[i] == 0x00) { _report.whole16[i] = m; break; @@ -95,7 +95,7 @@ class Consumer_{ } inline void release(uint16_t m){ // search and release the keypress - for (int i = 0; i < sizeof(HID_ConsumerReport_Data_t) / 2; i++) { + for (int i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { if (_report.whole16[i] == m) { _report.whole16[i] = 0x00; // no break to delete multiple keys @@ -107,7 +107,7 @@ class Consumer_{ begin(); } private: - HID_ConsumerReport_Data_t _report; + HID_ConsumerControlReport_Data_t _report; }; extern Consumer_ Consumer; diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h index c996420ef8..d2db12f0ab 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h @@ -70,11 +70,11 @@ THE SOFTWARE. #ifdef HID_RAWHID_ENABLE #define HID_RAWHID_API_ENABLE #endif -#ifdef HID_CONSUMER_ENABLE -#define HID_CONSUMER_API_ENABLE +#ifdef HID_CONSUMERCONTROL_ENABLE +#define HID_CONSUMERCONTROL_API_ENABLE #endif -#ifdef HID_SYSTEM_ENABLE -#define HID_SYSTEM_API_ENABLE +#ifdef HID_SYSTEMCONTROL_ENABLE +#define HID_SYSTEMCONTROL_API_ENABLE #endif #ifdef HID_GAMEPAD_ENABLE #define HID_GAMEPAD_API_ENABLE @@ -404,8 +404,8 @@ void HID_SendReport(uint8_t id, const void* data, int len); #define HID_MOUSE_API_ENABLE #define HID_KEYBOARD_API_ENABLE #define HID_RAWHID_API_ENABLE -#define HID_CONSUMER_API_ENABLE -#define HID_SYSTEM_API_ENABLE +#define HID_CONSUMERCONTROL_API_ENABLE +#define HID_SYSTEMCONTROL_API_ENABLE #define HID_GAMEPAD_API_ENABLE #endif @@ -423,11 +423,11 @@ void HID_SendReport(uint8_t id, const void* data, int len); #include "RawHID.h" #endif -#ifdef HID_CONSUMER_API_ENABLE +#ifdef HID_CONSUMERCONTROL_API_ENABLE #include "Consumer.h" #endif -#ifdef HID_SYSTEM_API_ENABLE +#ifdef HID_SYSTEMCONTROL_API_ENABLE #include "System.h" #endif diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.h index ce57999afd..23462edf2a 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.h @@ -72,6 +72,17 @@ typedef union{ }; } HID_MouseReport_Data_t; +typedef union{ + // mouse absolute report: 2 absolute axis + uint8_t whole8[4]; + uint16_t whole16[4 / 2]; + uint32_t whole32[4 / 4]; + struct{ + int16_t xAxis; + int16_t yAxis; + }; +} HID_MouseAbsoluteReport_Data_t; + class Mouse_ { private: @@ -128,7 +139,7 @@ class Mouse_ return false; } - inline void moveTo(uint16_t x, uint16_t y){ + inline void moveTo(int16_t x, int16_t y){ // uses different report ID and different HID mouse device! uint32_t pos = ((uint32_t)y << 16) | x; HID_SendReport(HID_REPORTID_MOUSE_ABSOLUTE, &pos, sizeof(pos)); diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.h index b47f148c0a..5c0a2d0624 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.h @@ -39,7 +39,7 @@ typedef union{ // every usable system control key possible uint8_t whole8[1]; uint8_t key; -} HID_SystemReport_Data_t; +} HID_SystemControlReport_Data_t; class System_{ public: diff --git a/plugins/KeyboardioHID/avr/variants/leonardo_custom/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/leonardo_custom/pins_arduino.h index 111d4f90c9..ede4dff60b 100644 --- a/plugins/KeyboardioHID/avr/variants/leonardo_custom/pins_arduino.h +++ b/plugins/KeyboardioHID/avr/variants/leonardo_custom/pins_arduino.h @@ -53,8 +53,8 @@ You have to enable the specific hid apis on your own then, also the keyboard led #define HID_KEYBOARD_LEDS_ENABLE // leds OR keys //#define HID_KEYBOARD_KEYS_ENABLE //#define HID_RAWHID_ENABLE // currently not working -//#define HID_CONSUMER_ENABLE -//#define HID_SYSTEM_ENABLE +//#define HID_CONSUMERCONTROL_ENABLE +//#define HID_SYSTEMCONTROL_ENABLE //#define HID_GAMEPAD_ENABLE // only works without mouse absolute //================================================================================ @@ -78,8 +78,8 @@ HID_REPORT_MOUSE(HID_REPORTID_MOUSE) #define HID_MOUSE_API_ENABLE #define HID_KEYBOARD_API_ENABLE //#define HID_RAWHID_API_ENABLE -//#define HID_CONSUMER_API_ENABLE -//#define HID_SYSTEM_API_ENABLE +//#define HID_CONSUMERCONTROL_API_ENABLE +//#define HID_SYSTEMCONTROL_API_ENABLE //#define HID_GAMEPAD_API_ENABLE //#define HID_ENABLE_ALL_APIS // enables all of the ones above @@ -124,8 +124,8 @@ HID_REPORT_MOUSE(HID_REPORTID_MOUSE) ////#define HID_MOUSE_API_ENABLE ////#define HID_KEYBOARD_API_ENABLE ////#define HID_RAWHID_API_ENABLE -////#define HID_CONSUMER_API_ENABLE -////#define HID_SYSTEM_API_ENABLE +////#define HID_CONSUMERCONTROL_API_ENABLE +////#define HID_SYSTEMCONTROL_API_ENABLE ////#define HID_GAMEPAD_API_ENABLE ////#define HID_ENABLE_ALL_APIS // enables all of the ones above diff --git a/plugins/KeyboardioHID/avr/variants/leonardo_gamepad/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/leonardo_gamepad/pins_arduino.h index 75b7638a37..6898e24167 100644 --- a/plugins/KeyboardioHID/avr/variants/leonardo_gamepad/pins_arduino.h +++ b/plugins/KeyboardioHID/avr/variants/leonardo_gamepad/pins_arduino.h @@ -34,6 +34,6 @@ THE SOFTWARE. #define HID_KEYBOARD_LEDS_ENABLE // leds OR keys //#define HID_KEYBOARD_KEYS_ENABLE //#define HID_RAWHID_ENABLE // currently not working -//#define HID_CONSUMER_ENABLE -//#define HID_SYSTEM_ENABLE +//#define HID_CONSUMERCONTROL_ENABLE +//#define HID_SYSTEMCONTROL_ENABLE #define HID_GAMEPAD_ENABLE // only works without mouse absolute diff --git a/plugins/KeyboardioHID/avr/variants/leonardo_hid/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/leonardo_hid/pins_arduino.h index 7378bca813..8f1f8f3ea6 100644 --- a/plugins/KeyboardioHID/avr/variants/leonardo_hid/pins_arduino.h +++ b/plugins/KeyboardioHID/avr/variants/leonardo_hid/pins_arduino.h @@ -34,6 +34,6 @@ THE SOFTWARE. #define HID_KEYBOARD_LEDS_ENABLE // leds OR keys //#define HID_KEYBOARD_KEYS_ENABLE //#define HID_RAWHID_ENABLE // currently not working -#define HID_CONSUMER_ENABLE -#define HID_SYSTEM_ENABLE +#define HID_CONSUMERCONTROL_ENABLE +#define HID_SYSTEMCONTROL_ENABLE //#define HID_GAMEPAD_ENABLE // only works without mouse absolute diff --git a/plugins/KeyboardioHID/avr/variants/micro_custom/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/micro_custom/pins_arduino.h index 59045af4ec..d6a3af8169 100644 --- a/plugins/KeyboardioHID/avr/variants/micro_custom/pins_arduino.h +++ b/plugins/KeyboardioHID/avr/variants/micro_custom/pins_arduino.h @@ -53,8 +53,8 @@ You have to enable the specific hid apis on your own then, also the keyboard led #define HID_KEYBOARD_LEDS_ENABLE // leds OR keys //#define HID_KEYBOARD_KEYS_ENABLE //#define HID_RAWHID_ENABLE // currently not working -//#define HID_CONSUMER_ENABLE -//#define HID_SYSTEM_ENABLE +//#define HID_CONSUMERCONTROL_ENABLE +//#define HID_SYSTEMCONTROL_ENABLE //#define HID_GAMEPAD_ENABLE // only works without mouse absolute //================================================================================ @@ -78,8 +78,8 @@ HID_REPORT_MOUSE(HID_REPORTID_MOUSE) #define HID_MOUSE_API_ENABLE #define HID_KEYBOARD_API_ENABLE //#define HID_RAWHID_API_ENABLE -//#define HID_CONSUMER_API_ENABLE -//#define HID_SYSTEM_API_ENABLE +//#define HID_CONSUMERCONTROL_API_ENABLE +//#define HID_SYSTEMCONTROL_API_ENABLE //#define HID_GAMEPAD_API_ENABLE //#define HID_ENABLE_ALL_APIS // enables all of the ones above @@ -124,8 +124,8 @@ HID_REPORT_MOUSE(HID_REPORTID_MOUSE) ////#define HID_MOUSE_API_ENABLE ////#define HID_KEYBOARD_API_ENABLE ////#define HID_RAWHID_API_ENABLE -////#define HID_CONSUMER_API_ENABLE -////#define HID_SYSTEM_API_ENABLE +////#define HID_CONSUMERCONTROL_API_ENABLE +////#define HID_SYSTEMCONTROL_API_ENABLE ////#define HID_GAMEPAD_API_ENABLE ////#define HID_ENABLE_ALL_APIS // enables all of the ones above diff --git a/plugins/KeyboardioHID/avr/variants/micro_gamepad/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/micro_gamepad/pins_arduino.h index dcbd43af14..d2cbea429a 100644 --- a/plugins/KeyboardioHID/avr/variants/micro_gamepad/pins_arduino.h +++ b/plugins/KeyboardioHID/avr/variants/micro_gamepad/pins_arduino.h @@ -34,6 +34,6 @@ THE SOFTWARE. #define HID_KEYBOARD_LEDS_ENABLE // leds OR keys //#define HID_KEYBOARD_KEYS_ENABLE //#define HID_RAWHID_ENABLE // currently not working -//#define HID_CONSUMER_ENABLE -//#define HID_SYSTEM_ENABLE +//#define HID_CONSUMERCONTROL_ENABLE +//#define HID_SYSTEMCONTROL_ENABLE #define HID_GAMEPAD_ENABLE // only works without mouse absolute diff --git a/plugins/KeyboardioHID/avr/variants/micro_hid/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/micro_hid/pins_arduino.h index 6b8fdcfb79..32e49b0d5c 100644 --- a/plugins/KeyboardioHID/avr/variants/micro_hid/pins_arduino.h +++ b/plugins/KeyboardioHID/avr/variants/micro_hid/pins_arduino.h @@ -34,6 +34,6 @@ THE SOFTWARE. #define HID_KEYBOARD_LEDS_ENABLE // leds OR keys //#define HID_KEYBOARD_KEYS_ENABLE //#define HID_RAWHID_ENABLE // currently not working -#define HID_CONSUMER_ENABLE -#define HID_SYSTEM_ENABLE +#define HID_CONSUMERCONTROL_ENABLE +#define HID_SYSTEMCONTROL_ENABLE //#define HID_GAMEPAD_ENABLE // only works without mouse absolute From 31c79df24ac2d41454580798b19b07f4f8555364 Mon Sep 17 00:00:00 2001 From: Nico Date: Sun, 18 Jan 2015 13:44:07 +0100 Subject: [PATCH 132/602] Added Wiki link --- plugins/KeyboardioHID/Readme.md | 317 ++---------------- .../KeyboardioHID/{pictures => }/header.jpg | Bin plugins/KeyboardioHID/pictures/board.png | Bin 46451 -> 0 bytes plugins/KeyboardioHID/pictures/example.png | Bin 21346 -> 0 bytes plugins/KeyboardioHID/pictures/gamepad.png | Bin 13043 -> 0 bytes .../KeyboardioHID/pictures/installation.png | Bin 28170 -> 0 bytes .../KeyboardioHID/pictures/preferences.png | Bin 18484 -> 0 bytes .../KeyboardioHID/pictures/remove-device.png | Bin 28040 -> 0 bytes plugins/KeyboardioHID/pictures/usb-core.png | Bin 18162 -> 0 bytes 9 files changed, 30 insertions(+), 287 deletions(-) rename plugins/KeyboardioHID/{pictures => }/header.jpg (100%) delete mode 100644 plugins/KeyboardioHID/pictures/board.png delete mode 100644 plugins/KeyboardioHID/pictures/example.png delete mode 100644 plugins/KeyboardioHID/pictures/gamepad.png delete mode 100644 plugins/KeyboardioHID/pictures/installation.png delete mode 100644 plugins/KeyboardioHID/pictures/preferences.png delete mode 100644 plugins/KeyboardioHID/pictures/remove-device.png delete mode 100644 plugins/KeyboardioHID/pictures/usb-core.png diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index ca00482391..07a023b11c 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -1,247 +1,17 @@ Arduino HID Project 2.1 ======================= -![Header Picture](pictures/header.jpg) +![Header Picture](header.jpg) This project went through a lot of phases and has now reached a new Arduino USB-Core with a lot of new functions like extended HID. It also supports HoodLoader1+2. The idea is to enable enhanced USB functions to almost all 'standard' Arduino boards. -##### Content -* [Features](https://github.com/NicoHood/HID/tree/Official-Integration#features) -* [Installation](https://github.com/NicoHood/HID/tree/Official-Integration#installation) -* [How to use](https://github.com/NicoHood/HID/tree/Official-Integration#how-to-use) -* [Troubleshoot](https://github.com/NicoHood/HID/tree/Official-Integration#troubleshoot) -* [How it works](https://github.com/NicoHood/HID/tree/Official-Integration#how-it-works) -* [Known bugs](https://github.com/NicoHood/HID/tree/Official-Integration#known-bugs) -* [Version history](https://github.com/NicoHood/HID/tree/Official-Integration#version-history) -* [Useful links and credits](https://github.com/NicoHood/HID/tree/Official-Integration#useful-linkscredits) -* [Developer information](https://github.com/NicoHood/HID/tree/Official-Integration#for-developers) -* [License and copyright](https://github.com/NicoHood/HID/tree/Official-Integration#licence-and-copyright) - -Features -======== - -**Supported Arduinos (IDE 1.5.8 or higher!):** -* Uno (with HoodLoader1 or 2) -* Mega (with HoodLoader1 or 2) -* Leonardo -* (Pro)Micro -* Any other 8u2/16u/at90usb162/32u2/32u4 compatible board - -**Main features of the new USB-Core:** - -* New HID devices(list below) -* HID reports are easier to modify now -* HID APIs are external usable now -* USB Wakeup -* Smaller flash/ram usage -* More Serial functions -* u2 Series support (with [HoodLoader2](https://github.com/NicoHood/HoodLoader2)) -* [HoodLoader1](https://github.com/NicoHood/HoodLoader) compatible legacy example -* See change log for more additions and fixes - -**Supported HID devices:** - -* Keyboard with Leds out (modifiers + 6 keys pressed at the same time) -* Mouse (5 buttons, move, wheel) + Absolute Mouse -* Media Keys (4 keys for music player, webbrowser and more) -* System Key (for PC standby/shutdown) -* Gamepad (32 buttons, 4 16bit axis, 2 8bit axis, 2 D-Pads) - -Installation -============ - -##### 1. Grab the newest Arduino release -HID-Project only works with the new Arduino IDE 1.5.8 or newer. -I recommend you to use the new [IDE 1.6 rc1](https://groups.google.com/a/arduino.cc/d/msg/developers/2_GD40Sl6FA/OLWZMwaLJ3IJ). - -##### 2. Install HoodLoader2 (Arduino Uno/Mega only) -For Arduino Uno/Mega first install [HoodLoader2 dev](https://github.com/NicoHood/HoodLoader2/tree/dev) on your 16u2 + the needed software files. -Make sure your HoodLoader2 software is up to date when you also update the HID-Project files. -[HoodLoader1](https://github.com/NicoHood/HoodLoader) is only supported for legacy but will get a new use soon! -For Arduino Micro/Leonardo ignore this step. - -##### 3. Install the HID core files -Installation has changed over the time. You don't have to modify the original core any more. -Put all files into *sketchbook/hardware/HID/*. **You have to rename the folder HID-master to HID.** - -Ensure that under 'File->Preferences' the correct sketchbook folder is selected. **Restart the IDE.** - -**Your sketchbook folder should look like this:** - -![Installation Picture](pictures/installation.png) - -##### 4. Add the keyword.txt for highlights (optional) -If you like to, you can add the keywords.txt to your Arduino IDE so that words like 'Gamepad' are highlighted. -Replace the file in *arduino-1.6.0/lib/keywords.txt* with the *keywords.txt* provided in this project. - -How to use -========== - -### Micro/Leonardo & HoodLoader2 - -##### 1. Select the new board via *Tools->Board->Arduino Leonardo HID-Project* for example. -For HoodLoader2 select the 16u2 MCU, for Leonardo/Micro the specific entry. -Ensure HoodLoader2 board definition files are up to date and installed. -The Uno and Mega entry is just for advanced users who want to use the HID-APIs but normally you'd -need the new HoodLoader2 (16u2) board definition files. - -![Board Selection Picture](pictures/board.png) - -##### 2. Select the USB-Core you want to use. You have 5 options here: -* Extended (Keyboard+Leds, Mouse+Absolute, Consumer, System) -* Gamepad (Keyboard+Leds, Mouse, Gamepad) -* Custom (Your custom configuration, see below) -* Default Core (Standard Arduino Core) -* No USB Core (No USB functions available, saves ram + flash) - -![USB-Core Selection Picture](pictures/usb-core.png) - -To create a **custom HID report descriptor** you can edit the file in *avr/variants/leonardo_custom/pins_arduino.h*. -Same for Micro and HoodLoader2. Not all HID reports are playing well together on all OS so I made these pre selections. -With the custom report you can try it out yourself. Everything you need should be in the pins_arduino.h file. - -##### 3. Try the Basic HID examples for each HID device. - -![example Picture](pictures/example.png) - -You may want to start with the HelloWorld and HID_Basic examples. They are pretty much self explaining. -Ensure that always the correct HID-Core is selected. - -See *Project/USB-Serial* for a fully usable USB-Serial bridge and how to use the new Serial functions. -In the CDC.h you can also see the new Control Line functions for advanced users. -Keep in mind that the USB_ENDPOINTs for the u2 Series are set to 16 bytes, so the Serial buffer is also smaller (normally 64b). - -##### 4. Deactivate USB-Core to save flash and ram (optional) -If you don't want to use the USB-Core you can also choose under *Tools/USB Core* "No USB functions" to get rid of the USB stuff -and save the ram for other stuff if you don't need it. You also don't need the HID Project essentially if you don't want to use the USB functions. - -Due to a bad Leonardo/Micro bootloader you need to add an add an ISR into every sketch as workaround. -**This is not needed for HoodLoader2 devices**, since the bootloader does a true watchdog reset on reprogramming and not a simple application jump -(the usb clock is then still on and breaks any delay functions). -Checkout the 'Leonardo_Micro_NoUSB_Blink' example. - -```cpp -// workaround for undefined USBCON has to be placed in every sketch -// otherwise the timings wont work correctly -ISR(USB_GEN_vect) -{ - UDINT = 0; -} -``` - -### HoodLoader1 (legacy, new stuff coming soon) - -**Try the HoodLoader1 example. It provides the basic Serial protocol API to send HID reports. You have to copy this to every sketch again.** - -With HoodLoader1 you can **only use baud 115200 for HID** due to speed/programming reasons. -Use Serial.begin(115200) in every HoodLoader1 sketch. -Its not bad anyway because its the fastest baud and you want fast HID recognition. -You still can **fully use any other baud** for normal sketches but HID wont work. -If you try nevertheless it will output Serial crap to the monitor. - -Keep in mind that HoodLoader1 has **no flush function**. If the PC is reading HID too slow it can miss data, like on a Raspberry Pi. -Add a delay to the sending function or just use the newer HoodLoader2. -Do not use HID in interrupts because it uses Serial. Your Arduino can crash! - -Always release buttons to not cause any erros. Replug USB cable to reset the values if anything went wrong. -Keep in mind that **with HoodLoader1 the 16u2 is always on**. The 16u2 and its HID reports are not reset if the main MCU is reset. -So you need to reset the HID reports on every startup with a begin() of each used API. -On Windows every USB report will reset when you open the lock screen. -See [deactivate HID function (Hoodloader only)](https://github.com/NicoHood/Hoodloader) how to temporary disable HID again. - -For **16u2 as ISP usage** (optional, Hoodloader only, has nothing to do with HID function) -see [Hoodloader repository](https://github.com/NicoHood/Hoodloader). - -The sending API is no longer integrated directly in the HID Project since it is now more an extended USB-Core and this has nothing to do with it. -Its more a legacy version to still use HoodLoader1 or to reimplement something similar with HoodLoader2 if you still want full report access for the main MCU. - -**The older, full integrated HID Core can be found here.** Keep in mind to remove all newer stuff since it may conflict (a clean arduino core would do it). -It is not better than this solution, maybe easier to use since its just more integrated. -[Outdated HID Project for 1.5.7](https://github.com/NicoHood/HID/tree/3d8a9b40752a143141b8be4b8f744e203c80b000) - -### Arduino as ISP -You want to use your Leonardo/Micro as ISP as well? Here is a simple fix (not working with HoodLoader2 currently): -Select the Leonardo board and upload the Arduino as ISP sketch from this project to your Leonardo. -Select the board you want to flash and under *Tools->Programmer->Arduino as ISP (Leonardo)*. -Ensure the correct Serial port is selected, wires are also correct and hit burn bootloader. - -A fix for the u2 Series is in work. Optional you could use HoodLoader1 firmware as ISP. -The only thing I changed was the reset pin to pin 10 instead of SS -and the upload protocol from stk500v1 to arduino to avoid any CDC Serial dtr state problems. - -Troubleshoot/FAQ -================ - -##### Error: Selected board depends on 'HID' core (not installed) -See [issue #9](https://github.com/NicoHood/HID/issues/9). - -##### Midi support? -Some people have asked me about Midi support. It is not planned to integrate Midi into the HID-Project USB-Core since it is very complicated to do so. -But I will work on a new Midi firmware for the 16u2 that supports of course Midi (HoodLoader2 only). A firmware is something like a pre-compiled sketch. With the difference -that I wont use the Arduino IDE to create this firmware. I will use Lufa and a makefile to compile this firmware. This is more efficient. - -When the firmware is done you may upload it via avr-dude as described on the HoodLoader2 github page. Then you are able to start the midi with a simple reset -or start the bootloader (HoodLoader2) again with a double reset like you are used to. Then you can reprogram your 328 again. - -So be patient, I have a lot of new stuff planned and Midi will come. But you are able to flash other firmwares like HIDuino. Maybe thats all you need. -Install HoodLoader2 and flash the hex file. If it works please leave me some info. - -* https://github.com/ddiakopoulos/hiduino -* http://hunt.net.nz/users/darran/weblog/5b7f8/Arduino_UNO_USB_MIDI_firmware.html -* Also see [issue #2](https://github.com/NicoHood/HID/issues/2) - -##### Any random weird problem -is mostly solved by a pc reboot or a port switching. Try another (USB2.0) port if you have any problems with your device. -You might also try it on another pc to see if your OS mixes up drivers. Once I had a problem with my USB-Hub, so ensure to connect it directly. -You could also try a different/shorter USB cable. - -##### Switching the HID-Core -might confuse the OS since the USB device changes completely from one second to the other. -Therefore go to Printers and Devices on Windows and select remove. Reconnect your Arduino and maybe remove it again if its not working properly. -Alternatively you can also restart your PC or use another USB PID (in the boards.txt) to see if its a Windows problem or not. -If you change the USB PID the CDC Driver wont be loaded but you can always reupload a sketch in bootloader mode. - -![remove usb device](pictures/remove-device.png) - -##### Gamepads -had several problems over the time. The first thing I'd like to mention is that the calibration windows only updates if you focus it. -Windows only supports gamepads with up to 7 axis and 32 buttons and has problems with more than one Gamepad in a multireport. -Linux has problems when gamepads are in multi reports with a system device for example. It may occur that it display immense axis/buttons or none at all. -The current gamepad setting was tested under windows and ubuntu and seems to work. Feel free to extend the gamepad report at your own risk. - -![gamepad](pictures/gamepad.png) - -**If you have any other problem, open an issue on github or contact me on my blog.** - -How it works -============ -For the Leonardo/Micro + HoodLoader2 its a modified version of the HID descriptors and USB-Core. -This changes were made to improve the functions, add more devices and add u2 series compatibility. - -The HID project contains HID APIs to generate HID reports and functions to send them to the USB Host. -The API (syntax/usage) of the HID Project is always the same for each solution, **you can port code from one device to another very easy**. - -* On a Leonardo this function is extended and improved to get more HID devices + some improvements. -* [HoodLoader2](https://github.com/NicoHood/HoodLoader2) is a BootLoader for the 16u2 that let's you use it as standalone MCU with the same USB-Core. -* [HoodLoader1](https://github.com/NicoHood/HoodLoader) is a 16u2 firmware that filters special HW Serial signals from the main MCU and sends HID signals to the USB Host. - -To make things more clear the HID Software is in a separate repository than the HoodLoader (1 & 2) sources and installing instructions. -**HoodLoader 1&2 is only used for an Uno/Mega to actually enable USB functions.** The 16u2 is normally used for USB-Serial programming of the main MCU but can do way more than that. -To use HoodLoader1&2 you also need the HID Project. For more information and installation instructions see the specific repository. - -HoodLoader1 was the first solution to enable HID functions to the Uno/Mega but HoodLoader2 opens way more options because you can reprogram the whole MCU standalone. -See the repository for more infos about this great new opportunity. HoodLoader1 API is still usable in a specific example. HoodLoader1&2 are not needed/compatible with a Leonardo/Micro. - +Wiki +==== -HoodLoader1 only: -For the Uno/Mega you need a special Bootloader(actually firmware in this case). Why? See [Hoodloader repository](https://github.com/NicoHood/Hoodloader). -To sum it up: Serial information is grabbed by the "man in the middle, 16u2" and you dont have to worry to get any wrong Serial stuff via USB. -Thatswhy you need a special baud (115200) that both sides can communicate with each other. -Every USB command is send via a special [NicoHood Protocol](https://github.com/NicoHood/NicoHoodProtocol) -that's filtered out by the 16u2. If you use Serial0 for extern devices it cannot filter the signal of course. -You can still use the NHP, just don't use the reserved Address 1. +All documentation moved to the [wiki page](https://github.com/NicoHood/HID/wiki). +An offline version will be available soon. TODO ==== @@ -281,6 +51,30 @@ which might be fixed. For example Adalight dosnt work well for me, so you better use an Arduino Uno with Hoodloader1 (yes the older one!) for Mediacenter control and Ambilight. * Feel free to open an Issue on Github if you find a bug. Or message me via my [blog](http://nicohood.wordpress.com/)! +Useful Links/Credits +==================== + +* [LUFA from Dean Camera](http://www.fourwalledcubicle.com/LUFA.php) +* [Darran's HID Projects] (https://github.com/harlequin-tech/arduino-usb) +* [Connor's Joystick for the Leonardo](http://www.imaginaryindustries.com/blog/?p=80) +* [Stefan Jones Multimedia Keys Example](http://stefanjones.ca/blog/arduino-leonardo-remote-multimedia-keys/) +* [Athanasios Douitsis Multimedia Keys Example](https://github.com/aduitsis/ardumultimedia) +* [The Original Arduino Sources](https://github.com/arduino/Arduino/tree/master/hardware/arduino/firmwares/atmegaxxu2/arduino-usbserial) +* [USBlyzer](http://www.usblyzer.com/) +* [Mattairtechs 16u2 Lufa USB Core](https://www.mattairtech.com/index.php/development-boards/mt-db-u1.html) +* [Paul Brook's Minimus 32u2 Arduino USB Core](https://github.com/pbrook/minimus-arduino) +* [Paul Stoffregen's Teensy Core](https://github.com/PaulStoffregen/cores) +* [Keyboard Led Out report by hartmut_holgraefe](http://forum.arduino.cc/index.php?topic=173583.0) +* [Github Pull Request with a lot of new functions](https://github.com/arduino/Arduino/pull/1803) +* [Arduino ISP fix](https://petervanhoyweghen.wordpress.com/2012/09/16/arduinoisp-on-the-leonardo/) +* A lot of searching through the web +* The awesome official Arduino IRC chat! +* [The NicoHood Protocol ^.^](https://github.com/NicoHood/NicoHoodProtocol) +* See HoodLoader1&2 repository for more credits/links +* [Hackaday post about HoodLoader2](hackaday.com/2014/11/30/using-the-second-microcontroller-on-an-arduino) +* [Gamecube to PC adapter](https://github.com/NicoHood/Nintendo) +* See http://nicohood.wordpress.com/ for more tutorials, projects and contact. +* For donations please contact me on my blog :) Version History =============== @@ -408,63 +202,12 @@ Version History 1.0 Beta Release (03.06.2014) ``` -Useful Links/Credits -==================== - -* [LUFA from Dean Camera](http://www.fourwalledcubicle.com/LUFA.php) -* [Darran's HID Projects] (https://github.com/harlequin-tech/arduino-usb) -* [Connor's Joystick for the Leonardo](http://www.imaginaryindustries.com/blog/?p=80) -* [Stefan Jones Multimedia Keys Example](http://stefanjones.ca/blog/arduino-leonardo-remote-multimedia-keys/) -* [Athanasios Douitsis Multimedia Keys Example](https://github.com/aduitsis/ardumultimedia) -* [The Original Arduino Sources](https://github.com/arduino/Arduino/tree/master/hardware/arduino/firmwares/atmegaxxu2/arduino-usbserial) -* [USBlyzer](http://www.usblyzer.com/) -* [Mattairtechs 16u2 Lufa USB Core](https://www.mattairtech.com/index.php/development-boards/mt-db-u1.html) -* [Paul Brook's Minimus 32u2 Arduino USB Core](https://github.com/pbrook/minimus-arduino) -* [Paul Stoffregen's Teensy Core](https://github.com/PaulStoffregen/cores) -* [Keyboard Led Out report by hartmut_holgraefe](http://forum.arduino.cc/index.php?topic=173583.0) -* [Github Pull Request with a lot of new functions](https://github.com/arduino/Arduino/pull/1803) -* [Arduino ISP fix](https://petervanhoyweghen.wordpress.com/2012/09/16/arduinoisp-on-the-leonardo/) -* A lot of searching through the web -* The awesome official Arduino IRC chat! -* [The NicoHood Protocol ^.^](https://github.com/NicoHood/NicoHoodProtocol) -* See HoodLoader1&2 repository for more credits/links -* [Hackaday post about HoodLoader2](hackaday.com/2014/11/30/using-the-second-microcontroller-on-an-arduino) -* [Gamecube to PC adapter](https://github.com/NicoHood/Nintendo) -* See http://nicohood.wordpress.com/ for more tutorials, projects and contact. -* For donations please contact me on my blog :) - -For Developers -============== -If you deactivate some reports it can occur that windows will cause problems and recognize it as different device. -While developing I had that much trouble that I had to change the PID. No way to repair the broken windows driver settings. -So be careful if you change the source on your own with important PIDs. -Therefore reinstall the divers for any device or just dont touch the HID reports. - -See this how to uninstall the drivers: -https://support.microsoft.com/kb/315539 - -``` -Include schematic -- Arduino.h - - USBAPI.h -> Arduino.h, USBDESC.h, USBCore.h - - CDC.h -> Arduino.h, USBDESC.h, USBCore.h - - HID.h -> Arduino.h, USBDESC.h, USBCore.h, HID-APIs(Keyboard.h, Mouse.h, etc) - - Keyboard.h -> Arduino.h - - Mouse.h -> Arduino.h - - [Other APIs].h -> Arduino.h - - HIDTables.h - -HID.h contains all HID configuration. -Each HID-API (like Mouse) includes Arduino.h and gets these settings as well. -The pins_Arduino.h can overwrite each HID descriptor or define complete new one. -``` - Licence and Copyright ===================== If you use this library for any cool project let me know! ``` -Copyright (c) 2014 NicoHood +Copyright (c) 2014-2015 NicoHood See the readme for credit to other people. Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/plugins/KeyboardioHID/pictures/header.jpg b/plugins/KeyboardioHID/header.jpg similarity index 100% rename from plugins/KeyboardioHID/pictures/header.jpg rename to plugins/KeyboardioHID/header.jpg diff --git a/plugins/KeyboardioHID/pictures/board.png b/plugins/KeyboardioHID/pictures/board.png deleted file mode 100644 index a3dd47cb1333fe31949cf4917aa146b3471bb3d3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 46451 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 dlKcC^UrlyD6oXKR;50wA_ diff --git a/plugins/KeyboardioHID/pictures/example.png b/plugins/KeyboardioHID/pictures/example.png deleted file mode 100644 index 949047fb8dfae1186b8a131158003fe4aba683ab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21346 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 diff --git a/plugins/KeyboardioHID/pictures/gamepad.png b/plugins/KeyboardioHID/pictures/gamepad.png deleted file mode 100644 index 3dbef39fa2071ab50ae8d2abc7ddc6bc8ba71e48..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13043 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 diff --git a/plugins/KeyboardioHID/pictures/installation.png b/plugins/KeyboardioHID/pictures/installation.png deleted file mode 100644 index 13dd8339df2fa98e5e77b66f74c94fbbebf0a01f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28170 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 SjlI+dATI-!E_(g$^Zx*oku;+K diff --git a/plugins/KeyboardioHID/pictures/remove-device.png b/plugins/KeyboardioHID/pictures/remove-device.png deleted file mode 100644 index 3ad5407956868af8ba54c4999f36f20e5666be0a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28040 zcmbTdWmH_-(k=|aod|9Tgy8P(5G=Sh8fcs*xO;#gfdIiJxVtrJ9D=*M1$PMUcO`qD zbN0F88{fU}{lREf%Um^UmOS-Ttx)B6GFa%u=x}gwSh8;=RpH>Cc)-EIOQAji-Z{gZ zZU$c99aUw-;mU?ccYq5-b1_9RIJn9vj5}i_;2Q12TOCI@IP8w!fAHOQ1*X88gicc0 zPHJ{$POiodV7L#)mJlaq2-xW*Co?NE7dVI=3_S>^)9w@b#~Tpc144MsIR@J?AproJ&)!VcZ*~iCai>>Hy@B92euip5@rXF z*>uCb03ymd?G@Zvub5mND|T464V*ZXY5e|y=eBbJv3((Y&H zFlw7*GV7xD?Jqv#>9$&${n=$rC6q~G>^CfdbUse9%LWnbFa9`E4R)V2qiKPE?k-F_ z@Qvx1etoiHv@$%usW79e4%jO@*P^tPRJ2Zk=;C`bJw$r`hFFK;lB#g*#j0h{ z$g+zCSJ{Kt{q@46=P&m-!iZINCRh-w%bLbJEbh#XVbAly1xsw;A=W)#!fsX`VpTfaM>tv zF|?um`PuqV`HmenEhqn&tDmLj5gML%gsyWxX0gGBV{#~kiZ`RE^UKPRUJ9Mz?5=_1 zFXg3h1{|TIqbl9Z=@)q~%D~?@Xi)7maqnSBQJeT$;yx4D<8ZpaZr-!9V}g+~!)TkH z!dKAe?&@G!Gj0-wD}&2gEtU&Xn;fIC7Dc@{hgSKUm#AJSJ;V=x?^0Dv93}5|FN*#S z&f>I$~IW{%F&DW-i72JU0=+F-#E$FuF9#D8bdg2W!85z=VSAl1dvTq|2FYo z>##w_lDqpTk(U}=wIWACH%*|<(VAQMSF4SOgb@prWuQL98rHjgeq@e3W0m!zQm;`Kb1MCkO}B zg7cep&;jkr!ob4PanCaJZQmGKgq_v{6o2nQ4VwkYPLyvlmuoY$(+^VG= ztUU!!G6rI|3`5X?`j|*c{^-QuPVueeGuc|6oy91trS&~a@V%a&tYjNGxJ`ks44OvV zQRPt%c^j3fTxHrN`Cws96al-e$u1jBR2Kiq@MSkw7?I0(5r#*KWCm7UwDL}T57U?o zA4CjvpZi;lfEf>r;a@?0LA_oBoei&|nirf&o%S|29?Ko^gQWEQ*-Nb3>I*;-cOBDA zx#(DYDrKtkLxX17a`X`)nk{|jh+0O(WEysH&nOP|hBcl&d;VpK}|j_6Us(6LX~Q5>>g3OvXP^?lBm+q3;`RqX_Z|ra!S*8fO>(ub7PTSL}-z4g3>_F}t>b`VvCf(%cs%*``32}OsD~bFC46PK5|Oo zQi&Rv^0UDp6e2!ej}P|^^ck33rpszZImU{CKgzKJ2Hs=3;lCwC9~SuWR-pyb=DW7G zrpQS~MrLbkdu-?FDPR*B87b^>_NgX?a^xwj<0b100Y>jHZ+I6XzLXtXk1sBg5fSaI zuC7WWAi27_7WjLNJrOe_C;*vGu@1t5@XW2P8D@TN4yNSDA(cqp-rkaskk~EMixs^_ z(9fW93K4r7ht7*jij9pP@_IOnySG91y z7PCU!*2*fTK-vQNb5OYMs}B~5a0-DoDPf4jRhiFK7Ta~>Z3 z05{$N&pFMHj*iaH%X6!@#(ed+DTd>!tE=0+_h;brGZPPr6+`N1M>HZf?Rf2Hp)~fE zt*ii&ot4!SjE=C2pAP%(xHUC36=PdT+$1QLQ1~R|s^9S8R|Gl;1gesF!dmHjo#4y1 zdnWnR8!{_%g7bKc(@v*2tquG&ojoC}wn{GH3ElQS3+h2LAkesQAa@8-MTkeguOOZG8z zEG)1~FFqjpRI4i{Gc&UqthC^kE?K(Fpb5QP$U!XMe-KDqRiM_hZ5KDU`r_hnn~`l7 zCb;vov@}x*j1f^8S2M44dt+i&qAFtrw=(dEt=@$-U@QpSOeMR^y@ zI|}I^-@}iuQ_~1CaBBDnB|xu0iyO!jd@4){`Fz;T(D&Sl4eR)TOs^|Rim7@aXt1J! z^^dUeTT)ZCO-)T_iiTYK7#Mxd&d&UYG#$)01;VUi39j+)NU?nP=J=yn9OybZ_v`^gf zw;b?%F&=)5!BjHp5)^P0v--^I`WHCQKQ}iQ4f3W#18FLuQ2>?!&wJ#vx?m8DMC-Wr zRVS3a4iy{QjM%TVZB_x{n5P<=l@&nrk%zZBfeUM#z(Xv_b0IVot&ZHNnaNMCj^!vr zxg({n0zQ1ZqjzAylztYi8ljyaK)~GZmUf0+%_tpT`>6xN_dp3OP9yFlvWAsd2B~2gb2LMdL4F)uuhw$W^WSiRY5R!&|5DgVr?jT(389FuR7CVV^dRIoVROH zA{hyhh8;orBXG%VDI?LCuaK?v5|Pi|_rYF8YKU1;cO=I-Fy;@ukTh=LKAsCxk_)m~ z9T^uH7$g$#MO8EMu+PNH>#l{nq#SxeV6P&}`kAPl6}+j6&DF@P7LY_PTGwf`)oN1( z+nDNjGl2L2wm}s2pAX*Y^msb5sQ;o4|#W>Ot#^Ai^h)a;1tgL_6egpomU%wIqu+t5oaK+S{ zRzrGwMA4#HTJihLw0>xb`UQOEd7Goc^DiFb?|C*q^So(OdK2`#4e;w zQSBA23M<6e@nCLqKgcRfl$16&+6e;%oGd%dB&s0bJnfKaT0CCG=;55AqkVl#;VW8X zW#zl%dFBZX%eK5k5Wf;>{%O!z4}P^!%#CowKZM8XN^sZUeri^MRNnu*b>NG?I@$`^ zlSmAi5Jf+oRW?79jEyinh84q=aF%8xudXws47ikmmwpujY8`LGLn6%sJyFS&Fedz- zCW#RSvd6XCpJ}$Yw4)5oGu+VT5dcQoGLrKez(_tmBie2a7|qPekGDrHv9{RAqf7{T zhpQzY!v)lg;?>~x(9B{hv8Qp5S-xfllLw2Z$P>D88PQQtP|P5@bqB>KFzW~S`e$Uk z>@rs{^mA1XMU3GqZtBqaR`lD*9HBW9)KKs8a$Q{|0ZlDpEnYIXONq6lI` z#lQ#*cLy+x8{(Iv!S(3qr&VHxV%iu1EZ@K2tFi4C9=mf4%peCd{0)EJa{YoeCjtmT6rNiL zYERP9f;`PMiy!EUO3UhKf}tRUU=fVOJ=@&gm9+@Jjfx$($2+@O^TM0EK4hd6WPtUO z|F@(BeaaG8VjYY9FTGwk_<2=oe9^_8D^vFO_a8BE6Y~pS1oBdE@Eha_Cb(&*F4YgE zAq>KW8>n#_RKqBZ7Yj`b>esq zw0ncF&`$&%KuRZF;z};{@8@)cKJOc_%l|+kK{RDPkW0$E*NF73LNtmgvhKV6sEbA3 zfJGcqvh70sNg$4}UsFZzMNl_oV-n;35M11XN7FF!ty_>1h7cSQ6eGM2u(DrfLyP_5 zBB;?aJWZ^I_I@_jSqJEGadAlcZa81Q|MGBi`(mpIcxY*9=>V9lv3(&uh^oq!ooI!A zc!4n}o>k&1VGp5>YMgN85HC3pN)Xwp{gKYG8$N@`OAQJEF(BBXT# zm^}knFpfPV4>)uP0lw|pcIoo9=G%GOso2`n;Rb{isk9IwD9 zMqL`e*vGM7l@lxCC0rx$|2xCKSw(Z|XSDVAy@kdNbn7*e{Mzos&zXSE>N$fhG}ZfasS$&E!~`fAl`) zwhK;gdv-oWxwjsxk5!1*+`SI2KG5%5y{9`9Jj5iuBV#~_d4e^>jHZhu$y2#t)j32i z4|6bsO$aXNFrP?Z%Q>R*q02>Y z?Jz@v{dbtj9({t$4L3 z{OrC4={$@tRzBoJH@1zFi~UCEV)!ty+tu-^KA!T_2}9kOznEJ`3>gRfzm_x20ewXA zvc*MYd$~R_hGrS|QrfSv$0-2N9-ANS+-v!-Yq}V@;u?z^??_!S4 zL;0_wj!@_?qU`^#rjv#&f1jV7jQjFs<#5ws>F2(Ce>FLztYUU_7OlbUGd1#GwVy;@ z*>?`Ea#gzwqVjA7htsKpfBIK3u8Ydx3pTK0xvywqY_^1tfiUNabM!N{ zJ?>twz3R=*MmdeJ%M!l*8OmH$xxBH;jlOv$w-?zzJ`Trdn_k#_LLxt!YALFsiG{kt z*aHn62qWMT=)D>J*9h+2$iUC$YTpIrp5uMy@wF#>9JIXpG(SR~U%60J*_h=)Ba?r3 z_r!pJj;$23`s_5fBb}vIAB@THEReY8E89->8DezD^Zq1>ypC#X(iqN*cUorq^4NiF z7KDpKY+B4MBh_bKm+~%)#mr8=>yroSOJw@XwxC&)SVJ1nqKk_Q-^?sQJh%1@j@Jj9 z^@!!|k@H@eD4O};$Eyw1?sqA93+)~#D7TSAbS#64Mf1o<9d@3s?2o@(M%hZin>`vDig)kcETsx2 z&NF}(-@JZ(h4e9wu6tQ{=6-cF@&tqvI96s0Jv>$zJQh_2aUo>Ym>xOC;#hAW3qzqfIpX4KM!VIwd01;`Q`;?4% zDK5)p)I~GM2`lC&W_aTkzm1a8djZaQr*X(8q97uDF`I$0ggwCPBwsK}8vnRn(7j4J zx?*hJgKnsJ^(Hu}@diYsL68T3I!Vwd_>szy@{*J}CX%#z#0#JRxm;S6iTJ{5VUgB zLp(>oygbt+%v`p*@{`I0*gNj$Fw=aen+jRb?fDo7Q6)RHp-V0E`WG%yl2fM3;PLNc zI%b7=``pqP@;=z4k*j&1cQtiKm5Drfub-^fcE{qpp_#u$dA*C@&Q(^aj{(2PT^m*M zkau@oF85IN>d?0&%GVO)0y@%%_6+%Yb6l|Oi9%J_rpp_iB(Cd>Stu}-roV$W(uDk$ltSuWY66h7%8Vcmg2aLo z9j)Q7&v8o~(ncs80eP&lTzY(P8vP|ivdn+`Iq7J0_{q>AD#r5DIKm9tVynWqG7zeX z-t&6=pR1d?%L`3A2{A3r(Z|E(KLQ{;N6hexKJ^WVdbh(YG-WruO=V(3Jh2>nB1YNm zO?}1X_A!vyDhU-W>OuWE88!Vi^~|yuY|my>7ONubZ&ztT&lkvYP1?;v1u4(t(!7!D z!E|wRb{~n^=HBF)u zh}5rKMIQv&HKw_AN~cC(r^i5EN#DCO@eF`+$HHzN=NYtG%O9;J?skVc^u+}>n^Uet zcz)c2ZRH#e;qEmHc@1Qm*rFlEi>(b_%F}N)nUi+Y^ScBTB^hK3`k(K6Xr4jAk^-t) zszouoQjkHFzz>k|%4y*|1!70$AB~67p@r$xyKRSTGtl&{OtMrMUfge{& z*wFBkEc+L`I;y^QnYQe@eMQX4%jL%giD(+m?5#~*)9 z?K>NS>w{}q9$AIizY8#wx6StQvG7DqOUWriecOL0z=)@6(+gzk$X zMtTG^GA(|rQr@o4`bxD`4Ry^O!y@ST&EMVKIo2dd+1OG4P@PUlPIIH9MBl!wtR8x_ z&Gl_I#x~tt=XL8R*djT9gnQK&b6nt)XoeqIq^-4>rl99*yLB#Z&p0Ok ztiO&^S%Cgt7cVCsVOP`T&w@P^?^TF@YR^^Wyk=$I)nvAp!sQctXM!kJBg!b(amrv9 z3-8R3(25l4rHE?^1Ag+!pl4Q`>MO&pW;1a03my>G+GW6CiXSbpc3H7`VM8%eqZ8CUA>CKQs8uW4F}kd3o3og7bK_7S$a^5nD|xhKu*# zUt(fn^7i)Tfh@qSWdTc|@_}9l!s6tWp`X0`v`pT=e-DsggqHy8TG2{v&K2;IzGs$_ zXrfdP0AK3}jl@DiLT&XGT}|$%Zvd5j{8B9iX!JWkzcw`7Jb5zyEXJYyM-Ib_K@*ed z9_#~DClbqx0gmBBsTd}_$@t=Qce6M!*X&n}iJEnu;#urQ;)DJDtgI|zVq$=>Jo#Oh z|5N1XEP#bAHqNYMm_GEfJAGGtdQnG^R>E}9(Q);2{Z-z)hF@NX1&UJsOo2{eNuWgy>&q^Jn{6AgGX#Hy$3Bvvb(Z4Xmh$oyCp3xg~+SJ%}?7eN0tHt)T~DAW13Ij@`mJQA%i8)~(cuagq2ALb;JD@*Cl zpz9N#5;8NA@io>HEV_%N$9VDC!OBq7ECPqRx5$7UT8!JOnW$-LO>a+*R#sL5gkk+% zXLlzG@~!X1WHVB6^Yu-B;B?uJJM=5}Vi9BiZm8Pu37#)Yp$VwSI!TdBZ)?Ynj=Nb} zryp^KA3}Yp-81pGN&itBWzl?D*$_a6pPZZkrYYoecLkUh&|)|_L4)@f7P<3S4J^Ni zb>SZ^0!eE|msHlnV)8)5(rM}>gOTD+brameApGKw_A~sSkyA}xsR6B&|2Rhh#L>|) zPL5jdsK=3?56ya^zMi)QuEkJE07H;I(q(Z>>RkLwX}(ox!Gys&Va!}PK1oJZx={$+ z0n==@HG_5W`he1+pSUxlY2QD+>FK1csHmu!*&DrIhf7TuN;?$3cWkVzxWxGQgwIG{ zJd-Bgkw}2hQCBjEz7slNCXTG2tsSj6GB&fG0q4N7H^)@P<;Ol622*mN)MeEX)!75=$Cds;mdw(>o-a0L~^|TJ*5)Lf18rGoLMcT zcCk@99sU0pMgE~*v|apY93WhdV*DdU{L?4?goJmKL38cQt;qSeVo9%G7r+>7t- zai%gMkBt9i6}wYYa{|=h87AiG~DUZUAxL+l}CHBFBN&=p%dGWl(HPocFr=+ z1Qv2HHPj6`I40AqH3*tcan%b@@*ew|(2MAja&O?rP`7&d3RbjHvHq#NOb8hn!r-vp z{$Werf#DkkBH~!clOIkDFEID$i{8d%h);@ZQ)AESQv*^LOj2tirON7h@pV4N3U{GTUAIZ>ML`odbR=~3JS*y+`7ylzfa z)=%bB3tF^FX3BUfG7bG6NKv+~j+L)iXe+()Bmv9lnYxf zO8$tTSwpT?-W##)$J^&VNkWLA5ysfO)W9OE`Y2@hKNe4^YT0TT1SHaru+O2gkH@Er zf~8@bO-ioUNYcPLBEr(1tYquZQuZxxYw7<{o@CCL-#9uDf>E6@Xsw9%_wS%bg4c)3 zzR0D`C#x5>%M>^6%Q`a9mtYAF%bX~hX(kI<#|=J#jH#OH6MG`uKYsK{o%n-pCXg^x z7KuO7j4?SPxN^(Nevl^~#r|VklJr=-rN4p1fK&Kg;h)I->1{6jA5HuRY*5A_r)mOe z{6GHr?{)v}(*NGzZ=~?Yrv7IOg~ARFC_;OSXSY(C#xq$dWoIWjBwZ|kfUbb|-&<*d zr6tyP2;fV06(y zT@@i==?m$}p1X5U3ciCI#+5QXZt?n`YYte+v46_yUk`Rk~D>6blmaMKJBmW z8+Y*S1@k+9;nzPV#i0bvCFAkB3wZwQnVPDq>*1X9VTqKyyu6Z<(z|!>*TJDr zhrtu&5|`(({zn#m=ZeXam?G{XOuu3Jfr1C=;dE(%i(pSguKv6`42{Z#U_WkCoe4kq|e`E{(#Mou8a6Hn`e- zP(I!n&(}}Y&&oETq@;ZI>=_IOYwzfAJz9!QP8MckQ_)s`hDT(mqeJmD$!#^Oy1{$} z?bMOEY-vf@KVEan<>Fmk-No$%g|NA0LYmsh#6)Uh;`^=jHIiufC8j-CM@sNXmLgPN zNN6-P6h9Jzf06FVNI6YD^pN7d(|AhOUn*^Ib$HWG<^Q!!qhJcSb+~bK7Te1gk8iG|)=#78% zff>o4%>J~HbEPJx7J?@cReVdXe!ft+_uW8SFH3z20GCk)O>^_pIK?y3(W65{W!7tJ z2M1*6Qnqj3zV*a9H2y{z!o0^*kssmswBse%GHWmQ^0p$iIBOw7=4z;t8 zHuF)HD@!r2XfXd2?paZ7J<=vY6Gblc-EKLW!<<=w_vZFWx{C%(ZJq$ua@IN*UKt!* z0Wg@Xdr)AAxxKTZuCe=a&t%_C@W@QPKHJn0fu2W4k;NoRha;38Kau9n*80jlfqhKI zuk71mk#`%Lat@JxRx;bIWecn4tl4hU8N`{oaATh!gY8pB6YK{cGsb+v2AcF5b~_VC z1=r0@42>23Z)&*-H(Czi9mDmm=B#fytg@jP`Z$!<0EH};l@|98^c9s9D7<}(iHgcd zN5{lWw}WtVOY^2|`MW37*XV=O89k%d+VhyAV(X0AlQkOE7_}%0p2q{Iw{fO18ylN} zfkDOY`Pnfdyu@@yM#jVh=k9}}WhYnw+EeiQ(T@;dg5?vum<`S@&asBy4mUbb-?aKu z)kQw|sLZ-!X}QO88hwP>?rm2%UT*JGkT$sAMpQqJT%G$@o}@r`#pk`TYcc{xcHB;Quc3gHdHdgVFmR9_n zm0Meyo9m2=IJ>+&Kka(o^*M#dP7DmpJLspe^S;i>$$3pf1Ffj2$jr>lFSj!V)D&R7 z_x0rpP-{d)3=EW{-rb2aFzk^DxNL6V*Voqr{|x+0l@j+7my+ttl}{ieC7qj}FE=0y zhdF>B{j<~4;ejG7H#cmpo6+U2X8G<%=jqm>t!RjY}V#Cm*Da0Pk3_}W%^WCZ^_G1UQ=7^ z3^aFHScVrn5aKHq7lo98b_jxlqO2@@KK&kvC@f>4`N7{Gh+)>=5(w%~z~BuZA9yr0 zG-bHw9mLSg%BRVnl@!h{F8r%KZ*OE|fO*5cm2Ev`Wv`Q;)YW#)Ko~mzaOoG`U&qqI z&T;#Omeu0JhXNp^toH)F!bq|MGQdvzhK6dZYQiJle)`;db`c79N{3AEd3Z|R z^IWC?bhNTk=KtygQ;D@0G{SlwC0N%3g;cQV;i!K4vG-(JN(9kRwjkwax8A4TVEO`U z%L3vlkpR3L50-AxeFKA};L?n_Q|Yz%%$I`9;YG7*pYzh$n!c62pirJkIABfr54xB< z+pDXw6>Q3&ht`xC%;MtXZ|?6qTpd5v{=&`86=e|Qy!+PGj)Kvmty~W54I~3;X=(L| zxc!p-){Kn({r$N)e(fu9Zxb~&Ymk6NeoISBK|y^+L49eHkcfzgpr9ZZ7Z!elP?L8> zd=R&UL`Q`%G7(LF4xQDWhsRA;*$?fs77I%-)O=W2Mkb-j)A#lw#ZDq1Q0&;={-k2Z zNQudJ^*Vsa=cIG0KS7VauXyh(lfi>ZdYh~)b?Ji4nJEx`WFFz_xpOlxo%&yw7nM~u z3@>$9w-q)`y~^#|geTk6MNWfl^aN?5``6NZzDkLhIG7!+r?MsulAbhsF|khY zqE+sC?h4T+FAsckjT90rEhQ;Q!S8f;It+Dpzv1QQO&4@`xW$g#eecL<23iDgAI z<_jgz%r?U}EXh0f-H-vo>F+W)Z_0MC^+-xFJE=1)xvOkx)w&j4>h0T4)zyv;st&rk z{4c%tahtqLY-qTAe2iL9 zQmhuhg%>tg7dh0G7w_MeIS+vGn|s&9&;(aeBa4M=jCUy5se&#)cDJKrBe9uV?(2N# z>sS!(?qi?Dt~B^l)Y)p>qyi5!W+ny(1Uq2(%HIP61O4wyDBxo6^%#Mwzs;WL&^YbfTt{9H*wHPQ_2%UK;x^ zd3606lcH()*a)jCn{T8M;}l!#>bPW4&9qJzE1{H(B4c>53TQ`-!1^UBms}8Z^^B#%`I)R zGdi9+m_H_K{qaLm+pYfd=Rvg7*an~3`|;t1{r$8TTw%pp?~gp`JtO-?tAA5SID10!c*s>p`jro(>*gU z;O6N`@Z!bQ)z#eGTyRjZ3N%`Pzb*X3dx^q=`qwnjmwa48OjHb191SHUPxeU&akVux z;?mNv!r%Vln6sX4ZF^~?oga|1x4Y+<0TO$KIypUEURHzaXgaQ;`?hy%WN4jSpZXHu&VjCv{G6Rn)xqu8 zl14cx69v7hrfh3%H&Yi)Zr=R`K8%X@9v-le5R?KQT3WXcA8@Cl6$eYPJ`duK0J!D$ z20*pQ0K_$B)795Uu!;z9F8U_&HSQb>0KBrYy&D^ND~q9_dl{>VGc$Jq0VO4*A55j( zr63Sy&QF1p#t0=*)*#*a5E<#Ch3^>svj9PF*x-T{KMG7)1Eb})IOKCpTRb>87s|6hK4!;bzZZ@045Qp$5TWL(WOj8H+Qp(@D9Fw&WQ?BkNZsR#Y0^8ZCWCBB7D zmA!J@V$p^A1U4jmt17H6wa%!l1)4*zX*v5k7a2raScQd`=KF64k~jd^26P#69yD=A z=B8$UPe=<03Swf6gP?ZH4X#H|w+33gZ-+hue$tD9uOKT6bQ>7x=z4p4;M^|(aO2e7 z-7PlYevOn1-r)Q0uBgaF)j>5lI9Q>}L{DE-QetCg7Zn=H=dnK%nbzQPIA`KGI@HfY z`-)FOCHwf|qEgrnOI%S=5vU+T&d*kcdK6b$zF_YVvNbF&U7 zCleQhWOuy(-T*y1Z1My~g6-|?fg%Q7N?*&>SK6a3U5Li@K-lxw*T7N}WwBE?ta~0r z73imuf74~pcP=`HeG@tC+I;W2eSy83pQ2E>d)yMlYw$oXYh7{bTyeMn07jsJ7$QAu z;Bb6`MO$8Ag-A@i7uWY|Y^-Ep0D!+UiQ3wk^e@8N+Fl*Ar9M`$24xF+oS|yQ+n=0N z=rPmfrs}GzFU-y+CC7Md^u+LGI@zyqHtOKOZIQvjbcroJ#c(Ke(;|kG;=4WKjNPn)a?fv|@yS~1^x(Z)B zR#jD1&{F^y0V}74orN1A{@0i4$M!&(;U)6t)q}oH8T3S4uoUMMFn>3eq zH+!xkHqZ*#hm)9&+$1qo0$(@+ z3QjvaKc5gm{1sd1cY=kE*gk$afkG&A_CGo9H{%Dl1G}0pw0|{U+;km5k3P7ZMuaLA zTJKxzY#(hC1q7MNdm6esdwV%Ziz?TLBt!*fb66aW<@OUW>%n>IfaWD-WT3TmlT%Zg z>gwD)P&lA(Qc=RlQ2sH<%+By}5Ck=Ph4}>FPAZ|$7N=QkX6g`ZvZe3VmnX62-d^{{ zT!H|wQd>q7lm{kE`Y5@QXBbalh;4O8{$+OFjfO9cBJ3A)@n>QP` za@uU&ot>T@9_=M^^8HqOUytv^6F&9y7+yZOTpdSOZ!r#~R)@(dlq+*4OxC1TxAq@awYl`%bNJ6qS%Wb!+`d%wd@NywlDxAQ#@}PKptK|LjF*$mxlzC6%NeuLl zz9hOZ$H!8LQvk#!R%!H}g{Az{F{-vue0}lu&-ro1OH#g*hZpt7K0U>F8dK^ecB`G#GTbb6V7Co=g>AET?PEjQ(tJ)PY zzK(iB!{{V_DiY{GU0osaA~Kd6d+VuXTUb~qC@2gt(ArqpHuf648%boqkf*YOEUX_0l#5nrIkjzH7>q%#u| zb=-;U&Qh~~#c^#FKTx4*1G&X|VIX1vm^21BnBVBs)!sQMXb0%)0?7v*9i5>Vk4me1 zg_2!RkQARhIz1Z8dTQm%mwOc8fw?K}8viw_>@1@;^kRcAJo}{uMTdJ7^`4goK$+#F zpzz*74j3;h;1MZ*$-vORwDgLay0$sfa(}K?CW>542=(DOnkr*HFeFmju%7f=s*diW zw)X6^Z#rPhBhMkam#l@abF;#A=5{A-b-<;*Z%Yi7)lJpK-)cwX+kH|Jm9)2{o-KX; zZ#MNeN|S^+qYY}`@5X;WC14}>W;a@GfGpkszESTs`-)#Ux2P`Ey&A6|!N*t4PQ_Bu zNv|(1G3VotuPa}amD5TOs6|8`*JuX%<@$fVUt?rs)YsE9BAT0;TAG{$q9x`tfK{%4 zT!Gh96NN5&w=7OB3NW(sb8#VPHnl0^J=@*elfNeu-Niva-&kMYT;Jq^)_qpe3o!uZ zbn)Xg0njnTT!wXyRS^OBRA^|ZKiL){BGA~cJ-z$)1GWnb zRP66DQmW!Q!1}H;I35#u^D)1OaaulojS&A;^X}ae%-h`UEV(N4;25pAdh6g6Lta*m z33#BW@DIQAyYcsC%+`4Cho|Ab&dE=b;lU*N^=qf!xn(p&`girq7BI7u<^8NJ*O z7(h^Ou&p&kLZasUj5LcE-MRQ247qqO+2pw@ivVwfyIY6HblcJi5T=*XmjD)_KjDDc zpk}e*lBZ(7wN=#Id~17qdoYFPXt@O^>gQ6EXONUslFsY|1!B%)y|S|Mm+ESHQ&aVK z5Fa&1jM{-FUlD4q^XVqfmfMG0p_W4dYx|{nme+ht(3-Gj&r}0T%Po`DZHh12sp?bF z)0~=1-U-(m6p)XwgB_B$!_3H|>4|qAeC|0i=4&tF>^vBf)?aA;piV%M$_bG%_r99t zVSNrX-#$UOf}UEwf#M*h$MAm62Oaw5IeZuV2mHWS9rb*y@m{f}c&Pui0o@vyykQ0h zR#=Sw#1X#R=JD`O`kJhvKRvb}HcRki*Vbxpu!rs=m%XWa2{dY%4@2JZG}e45orH|Y z7C@l1w4cJm!=sem%F5C)GY)K#Y6@VFx8?0gP9 z!sc>xeV+f#_u=rCqJ%~7okFiBw{zTdUH;bO_nXdS!;C}n?iZY9lUQ+13q`x0Jw7!^ zJmQOH8}WKAml@@*ZYtxC*A90JB(breapalT8|qgmU8%fa$GP^0SS2VQ%;Qg6EZ3Cb zNNGW4@g2v%I?X2hi{gE-!H zsqOw<5a+;x{OpA&tA!snTj!uHdd-`)*WvNQNgS6V1@rwG2C*})hYMSV+D#j4O7Fha zo*iEdGcej&?7R^@z$`3BVZXxG zbJkZ@R?cdi7>ZBxmA>>@j)Xc^;7Jt8rk^TZ6*sLC@KXO7^{jT%&43<3p99VwIK% zkUce*J7`T~R!+%J4Ezhb<`%A&EJ}K&qdWI}MG7zXwxRJ3nzNdqgBz%@hsmiq(35?- z_^ULB8wpE`rYJ3yQs1nktu7}lIa}Gpda9to-eqj9DiAFs*Lt!WmqHBmyYGGYl0G9c zqVwfk_`z%4;DGIQ*-#%34Ju1g`NMy;sv`=WF$(uRzi7|7jI?hYD7iGBb!`<-HCLN% z%mHc|OlmM1TDW%H9Poq;>Cq1lX8QEWm->CSc&~k1X4taY{mo_0z$HRap|rr#0+Q`B zNU)E=u+kn=w0-rpb>)LAj$QF7w~C4uFs~CE6Qif6C)V^kkz#-2wgJM8Q-azw*T#|ybbx*}?bnQAV;Ym5v|)OvV?#&^;ilh#Fo=+2rV{>3pRS&lFvo~ccE2)(ZL8n&NT z{I;+Ac<9Q~Qfqr&42o|$-fgEY-el6_w|mF}68KOWiVmy!l9ybE<5nAgA~##E@vd}D zrlKHVSV7_VP3ISR9o+*>_W@O>^427Cx&pU_6gMtd>=gT?cw|QuxTbbTZYNm>_NN@e z53jxl#l_Vg%u;_A)2bS@)nmDplrf#k(YTCh=)S?PwfP7;$Bwc)*q#4=ITAK$4G?k` z#s|9_1Z_XsdN0>!Fv*AMy6fF5(+d6Rj_cl zRpvor!hj`Qp^p~1OHb92qIK+1Cj6}W>ot^EfPn_;h>j^s&J|Mmi+>r)z}YtblV<^7 zL!Z;yikd!?sYBn#&DP*SkuqQ3Ti9i@@AW~sXjA{Rjb6=N=WhoytdDqh96;?zz?d#T zQH9DWh{CDBmpFFpI1q5fXC-D+e>*nJq*wppfME~nbN%^qsfmKPuC0l{DP(JE$e$Q2 zZz)B_7-aqRASjLrElEQY+h>dP{{DH`Gx_Tri#{JD7~>1IDf}=YrT(>)SKo#U{!AIr`p# z0=^;=<$_3R*MEf>vpJ{!kHGxw-ucx}{H=@}AsQPI?)k^fZjo|dyW5*fU%ktv3$3O5 z!(1LHU_bG3EG^YG=hop`W%~7JK}g}6ti-rHH* zA|ds@nh4ThX-1E_nNJJp!A_>|;Y&8u#)j$N?|M2WlY&g z=N(Vw|Ns9_DavdbS;br8*g9rNLPpv1*fKJXj6-%3va(mQ_ctq19KYlDnY*nC;neY8q~G#*y7H|&bi^TOJw?xi;F0#hVSKs+}Bm}Vm zGX%Da=rvmDp0GHmtJUw+`y=&?IVWaD0Rc--kJ=v>>*iGE$-I{ND7 z?1R3_CM*DG1S(wI4_mKxopl^OC?;I{gN4sVaoWykt0I9T8=7aJ zB*OU5G>d8>nq)~=lP%hD%vX(Zk9av=wcnOWgDO&WiZ0P{NO&VVYO~WXxB6gzZ#J)z z-@U@J-c<912V%g=S#!MoVL;6NBx+YYI$8e8Ti&qPq$;u?xdv-H&*tDw+ znp=G2G&uFvySwKGIQ2IhTVlqYJ&p;M#>Ng-I*g?|h2Vz^Ur_O$!xhI}lDnY=LCByF zCsRA|3XZ$66iT>E)90ry^SyG^V}zHkYBBC#@QqKZ+&ai4lc-CRiK5Jg^)Qq%iQxUt z=Tw4=(Il^8l-DNcbKP4j*PV0^Si623%NwGSv(d4rihCoNe|O2Wr#g)T@i0H?&UlHni%e%44lazEZZF z#d47au82Ypwmt;|W9V+(0oefdq&c(Zv}|qA$DNs@>abyqA9IAAd*>tf(#XnC1zw*W zsh=H12}q?2e=ZQE`YUE6t@RJgs%}rTR1?gI>>6Cu8Fgf=+1D<$6UeLJuP$S{pI67r z+S9_c*CnVKLgzcPRsJ~u)!K1gWUf0MJi+-iHNRlP>)^iU|*L<76EgDhDS zt$}YYlE5BzT8o#?tty z?aGKLC;Z55+tO42c(ExIn(w|b)!3=$V!YI9zb#HFkZOvV=uve{u)10Ou<$?WtHgwIS<=!YtHH)0_ziu|GF zps)N(nVY7-eI|!7sk@?kMFl43$#bs8^~GS*c9TjEjSj%TsIwm@`=13}$0-R* zI-IfIKj;}a9E%gHgb%&65%6}8dpML0(S`>hf&TK+=7*n=5E~&WbOy9({D#&3q}YFN zSe=2^e>S+3dd1U|y*LW8=tXp#^5Ck1AnElSZvjskQ7)&2IKD9s+W*v?BBqz_|Bot-c3g|n1PAGS3;-_OpnTc8rwt+=_=I!53z z+xlFOx5Iq2dL$vow0Do*b3fH0;@ZOq#3ellBV5@_UTbMyc4d|L3XVIOVIv*$0KFdGinMP)DVioa3+2 z!OaMmb$NhW{f{=*Rtx19=Na1NT^~$e{+(Ros8V6bWbM~T>#Qt0R{n^E>VjgEY1zIX zAt=FHHtQ`^^!SFJtHM#Ss+eMnc7|qhEA65gmLJcj?rU*w9Yp+dO3W*X2|7xE^aXvlB9O6ZsWX+EILSaa7-vnhdK)IOQU>%AIC$T!;4WDGO-X zW0fX{iarZii-M^s5|Mvk%KL)2^0KOrOW-m^u}1BPIE*X2H^)62-mqgfSMRlaojM}u zOXS5KiOlnV_Lqo7b+7{Cye$gj&PG3F6SClugW z<#3NKI&s2g)frUqe(!Rep_uaOm@f*8eT>1w{>0~#{7cP}ooum9CCSKKL8j~s{x90+ z88#`boAVxL;{W;No(1(bjr&4TnP{)@&t}8Es^Tlmeg4AuO*7yT3C>CS zch*CuL>9(7c%S?y#9U`k5Ax3_F$woTvAlL33i+jH?h7p$OQCDJ*&3bubCpJK44nM8l)BXIZD z6BCiJq=tY+$6FrHTS3kIar58`5*hX5LA4pBF#0KFl;(!zqh$uo^tgrpVDW8IIJ*-e zx;ceDT>!&LZy#EtmalsV{asN+xvGZ2~^>ocp@7LalebEyF(5MrC zzTF+Y z_GgRP7jbcUTzqB1Aq7Tfrm~8>m8ut?pR1OhUG(iNjR>_h*FB;^z3H`kh-(4Ftm*Js zgf4I~6Hypxa}R)aFHhFMNN!irReL$^ypLI-ec*?OLYh`^DK2?CRw7AhVfo+#84dgnHlX90A zCI2vG?7515LEL81=jEoC5j_oKj~=6B6a>{3M*6EYC>|p$-D^wJ(!T4{;McsPexSm4 zqSZY})4Dhobd$_)SBy?;C{8TD*BD`}($kAT*+tb10XdYQ<#GaAUJ^t39dv@*-GY) z{w`uiBmy?X6TmG6-o}3YS}t51(^+16+ForunSv~@nI<7WTGDK&QRr=}8WO1K^}IOW z-*Rvs)RPEmWJdk6ya>WC+DmJ#yZuOJrs;(L`ZIKDU?-cXmV~delObGo035oN3%8SY z(8pcxLpLzz^?vF$=M=g-(5{My-!0!X$t6_Zw_+pRp(*@I`Y-ZnHAEyo>AD`8lGqd( zR|JP0ppApBD&h37%Uwf5`((_>L=lzU(#VNm6 z%{%RdJh~-oLu2C~U5ecqxUOu>SQ81KSM&Z`#B-cS* z-^vRjYR;Na>=d#zG0Y2vapu$@#^>z=_Lu{3(a)5OsTILbzP2>Cqlk3Gls7i2#++7z zv9@UloEV+;NljbR>Cn!YJ}$qrFuSF#<#I@;0jQntraZYU%?Aqe?9X`De~NvZV}+#E zFFN`!MUN+nWxj6|BK7-5frfW#>HZ+O#LkLZpeqv+vW?lb18$%y?U4xA;~j}0ZXnTm zWD?>RW22&C4;$Uw6)GKF@+5OORA~Be+Pd%Rxmo>bFO-2Nf2@_ipe!Y1g(0XIBP%X` zsH?T2OW9!Y3}u^_jDy}Sk{hipe;XZDzP3JAazM7azL$MPa8g&Fg+BsXkxlT|n(h?t{@wNqPEHF+gm~IxtPQ1e z!OihxUf(@#V(SeZq*O2zcn>jACCBvxjW%O*zn*=TH;Wfai=Dd;-mtU1gczTWMQ@Io z?+@1`T4}i#m>!?p@Ja2TonkWoY|R<;5JMRR2z<(*^*29%k39UNzV!; zDhtCuL;3fRe%mW*V7W*e; zxLi$x)e=^3g@N1k(6Lkm^Nt@3Kvl;!R!txaTf?3*jw>CvqlT$19~I)feq2zwqW!>RI|VoEm!w-CmEDztd@dkj zsfW~R=9@+9`&eqN7#nf%iex zf_W+S1uYYHCu`6{tS{Lyg&eqm_x`nQACloDbcrhE&|H1VMZkBs8K`4U$L%doo8DhB zMYOInY)9YI)qC5QH=KrT9Ckq2$P=5+o>kO*Kf4o!iIxtIf#+>5ycz5(Rzz)mSJTYu zws}U*N8Xp0&dnVgN7tKIna=X|a3nH0o9h=Zs!z`qA)iMgJ(iIh*-wluZpwK) zeW!b2iSoL4oTNDJ)`JQMqPQKWyV8UnrAJsb=n%h&0hgi8H(8~0%wu^%>@7)~yS!ov zCTX^ZF$c%=%AJ?gu(rO}Kket1UpF?<1y%Ct9vE!DOrv1l*>D#`U@0H@2Ndi`l?8Z% z{?rGLqCr=KJtc?%=?_#QnOZ7IprHKnisCUkOG=C ziQtc`s$oM}953GIxXQk}bJjQU$-sykR=*f+r7WrfyXx3QJ-TD1Wqid$&Vq)tAOx-C zbcI%BYyKeXEhSif0s90n^o7Ue!%E|k%Jwwm$Pa944UIQMDo$AL_=4fFmhu58>|?2l zj271N9FZn&x{{<9xg54TpCoK|EY4dmxRf#_f0KLZU>%iO&!_;VaNgXY!`k_ObZEU7 z?4=^Z64KZflqNMxqV51qlUP+;w4KK-Ut*}fvC<$|p~*z0fH3%?_)lqLb%0t7D3X4? z*U$Cg+lstR(YF11JSoySJY?cAPv(1!(_Noq9rIN`N#m3B-;(UlsP+1K9US=@{$`vM zWu#>vK>%;ei2mn9RD-}t4+x4?a z``NM@#7N2MVVcBaOmGZ_w#a7olEjaJOZO3V(JW3D_f-&XjwDs4?JuXsA(^+{ahiQ^ zYgR;x(LbhV@+Q9Y{gdb7!((aESAIS3`pa`HV##_;hXi(-EWbRh{?x8a;g~QEvck8 z!h^SZZsQhec)px8+(9?qCzV#?Nzp-RNd({BNmg~FppAwn-;y4=G)%ahTjp(GYX5K1 ziys`dcWaP-QSJAoJD83sKD1C!Jpkv%_N)<^S^nYlZx z_Z@8*tlw7PL}?FNK^Iy2eUVCB?MmEDr-yA;XOp|LS+iI7iu0z8-u}e9tmCDmi;!&n z3sZy=sd3p{fvU)0MLUMca_Lu!nz1}2#k5L;l2<0tED!FnH}&zpLEh$ptiFyNqWP_H z&l?Fm$6S5b8t$a;WRdQ<7Hvt|$fV=^a%}1`&Z+MQ0j0))uF3)bd(AsJq%C8PneV?o z^A-s(*J_&F8k0A@n{2IV-PFf@9&`J_ec?-{d}k4K)}#*|sHYvLtBg~ojX4C=lN}z7 z6V151sRH}*ep>E_8W{>|(iK`c+Ns!Vp+~Bw3~N>{J91gLYZ@5ES=#r&M)*URE{$|I z`!)#?M5FKZAN$n5T96wFX6OuUmQoq8?IxWcdT4zA#rF{W&8)9&J=SL9eFw9NzR_cV z^czD{(SoG5QTtbgj~cCO52bh9aaal5l^~x~ziO;sdgH7 zO`2=8NuipGikdpg{au5jqr=<+5Bh}#_#D5}*@VXZ3=#QHz}ogiH7p;_Yfs3-!^4>N z5Zw_>(q3LJSrU*roequ?ttjRSUcVM_b#)S}dHuiB&k!YzM~@zT0)Kcur5aCF;icLU zp@dwdU*WZYfIl-h0QpDSv4WPi1~-HgyZ=ClOF&geXKH2TIz9c`)biBK3@sfU9evWv z^;B!!grel+>>}l`*vPB5$Z08WOfD~epO}WbHZQbk#mhOa`uIpzS9>K^hrQ5ZN^sY3 z_6s%pwbBInDn!SDXwH7^^VhF^mhQ)Rf`a7$m@O}NM#!32!VXK;*9$ENhDU^vD5S^( zYtG4JQFI0!R!nIgxB&%6XxsCFs+E_MqUbNEETOac!P!iTX>EL0G_L zI;NL21UF5qs{Z#94ZPCq}Q43U51y(*ctu-`uC%UfO1M2`xN(whW zXMS?>mDhZEdDgVF2?dx;DJ2aJdRp4=3k$SYuOcQsr+j|>kdu>>UjtK7A*8^Wzd2{U zWU<7^VAQ6diI4wSSYU5NXDcYEIXlN@u3h}@A5YI58LLIL=Or*@n8^6cR9AaUXot=N zw`fH+^Ad0`D6}L!y%>v4EzBv$VDc-ovU1AHQ&R4Th)ASl16UKCoBM`|Gm12s7YY^O z;JCxbF**P3`XL#O&&=BXWp@ zPs``Q1ZY(@qXBO{}TNL6Vm8jHmiAzd7{EIdyiK7)(f$-2nO z9(+riMZ-m#LXt)g8Z>}lfT^;q?C#yaKs_g6swpEvb=3y=JeJPcBxVBJ=CeIXFm!U~ zz~f=UU|k7JMG@Z{gGaGP^YgLU*%08Q1Ps=ao7I0Xv#AOTgO%gOi#}R$S_@QhirHwT z&m7tGlr*_E=C3o@HTn4Y$u4{Z5cSeTSXh`)#x*P4$bg2bYGjhWqMEJ>fW5Y%P$-!7 zrF{=S#(SiqT;zuJ4xtxzs%>2Tvfd-+cG~LYZpOfv3W418X^5(wT%YON9>`qVefMww zU2qWQv&}*l@vyS8GBMp$Pc=}~#Hm9pMude3@bQ(EyLos&9UbEZ1P0c|AP};eIDnwn z>V?`GDk+(&s{``ML`_XnQc~sxRW97{f})kXyM&#ctcl6ZcjS)ZGkagYRJraNgnpXq zSP^^qqj%vGOU?^G9&tU9H0c99MqlhS$!SHzwg1j%&e;vgB)r3plcLS+hM`t3uR8_d zq#;2ZtSY4Mb>`Z~2hWi7yhKmm`c3t|=YBcw?#D;hGXTNESrqy^psW@z1qU^^bFOb~ zJe8LxBnx@@^5y?NH8wF%&&)viF{)}1R+I%`SU-G#Ek9XaG zo|m{Lzu#I3cC*rihuwg|36E>gCHLEQU>I5cU7X7AF~@Q-?B3VQ&?!~b<-CkpTz3RT zxLIbpnS^a@)|Rec*G))hf7%{QLIRxgK>sD96LmY9?rD2FQ^rhzHqgY~qPwNc8kLg+g3=lE9gpF{o{m~53p+Ct^tjF^5KyCqg#dV7 z7Y3T!of!@P%l;Vn*z)}RSI&DEa=gC<2FkIbkkq#(CxQ(pCjk=;gAFvR@HMrsu;+;k z3lZdxdwg{jX#Bc0AI(CokGb0;WCT?7ltHyWk>A5c&#qjZ^2H`vVOFH5tqoP z35s8vIh$KLfU-Bx-~SvpFt5hHaN(h#m{?6=VGeLcW@JQ_qCFh876D`fc6!p%j6cUf zp#k7JU^4hJuOztL=5S|3P#{6bor9e>E6+X|WmBAHR+gO3%Ff$4z}eL}Yow_ukekrc z-Tg?S9>k@=N8lYZEHv|FdkKL+oT;2-eQ$EHy|cEma$Ffph|>rU)xHuDdM<`~te#sc z(-t9j6S~UPqy3y%MnXMR-k6uSJ6t!(?$D0?85gfg$m5W9T^!+|9a)e^;@y9W>*7Bj z-3lCNMUR&QBeFUrrI_y*JCr!?4DcgNXQI9|X6+pi4Cxhp0?cS}G3&j1ioN%WKG_El z1{#DBLcW#mbO1KKUUE{_p}5_L2#|Zx>T{i1!(SShbSfRK4GeBG@F2@{z6}YV@3yvD zV9iI$J$rVJe{Ni86`nZS+E%&^p+U_@Rup~=PfR4`cpn@X9~%o8yIiC?F=TvPZ^~dsHiv6=pFxTBsCdk0GlEv@kbBVA@K;qSmc+~cbax8=MCW^P6U z$v}{9O{*)LR10xm-n_vz1Z0fD0LoTG#(nYEcoPN}KJ?}HEVQhhiu#hRVz@rlK<}}& zp2FDVj`t{_HOGf@P-Cc9OIwLLCe&zdg7^_QCezl|*0K6nQqn$IFMVSx1YtON2yB$Z zT(+`P3b}#ywy=;J3hl$;@Z@1>*+3umpeA|Zv-l#v566hGpJe0B$N}c`m`YcICgu$2 zeJA4g^06DNj1Zh%d&_c)e6waKT1|t8DM}_^8t_E+q$zN+0`I^brkAF#V`+Xal7N0B z^k@p{Bsx_7yg{zOg^3|SsNjeDLPkst&*ALHjHjv!}4}HN$O1-ytmpG^{wg0}&6H`V`-1+5e5qYz{irH*AMR)OV>eE+{9bJKz%HsNy zhF5#ezPmt7*Rw#rtfs8AI}_rkk>_r9QkT&w!cVX)!*-BcY1Rm{FG}XQ`aiF6zHw!dy3~neaBDpTcsadX*j$?B z)ZsH*JrcB^1MkE`K|{Qx;j(}D*WE-Qx5;!G!&R;&$7k8V4V~>>ZHz6+*xVwNdEAe^ z!&SP$Z2NO1@TL}ZKG0E>x06v*F)}TW*LbO8WZ|w->Ayy|`S*duSy&)pcZ~WuW@mHL-SMZ$zGiTkkNqds;&0P=qtROW9z>lIfD>n>cxG3J@I41Vy1XhWcKfa7O;$#_lDoO z&DRBkX?VKX&E{;rAMp?)owjx z&26`v8m3Wmz@7U#CeOoqJs^ghL+j$w#Kq)E$<|rU3nZLz{Pgl|eOx9+_qmPHZOa#_ON_Xg$ti=WP1I457~22e0wZGR8~@(dxUt+UGA^uVJ%As%O10 zpO<6V0bvUaRYXDpy2qwd;nLhv0-y)dM1Ykk)QljG=8o0Z+zyD!$fZ^nseS98uKjat zem2DdI1kCams9!?IloGM%W{n_+tM7umJ{^!3BqA>#PjGVW`wM2d%d&Z zNVjq!o`(MgQNoY>*X{CLgS(gKBQ zjyWYIRm|iJIQ2X`F9VJ6^%zQt0!0;OT(4-gP-<;_RUsJ)sCp3B ziB!ojL&|f!5Q8o=r_(10U6sM8w~SdF?kBi&E`61>MJLDf`iB!)oi*cYQ&j&WdDz`^ zvSa-FC?71uc$G2O0?YA96#sA~0n&o{(`LXm6`rYx?(U+Ehs7dzX?BM)d0a2OB(4D5 z0X#5%C>aK)+^%CKKN1r1pgw;qx_)h69*W2KT`i#T9mJNjV|C7&qqc<1o7-fHPa%RVg`Wg9UexXKXjUtecr@SKLjnKH;9j}tpt z82^LeZ43h#2%Qg-;U>4rK68ut`38++Luz9M+AKqyX*cvfQWDQz<}vy89U5=vH$Nf? zfd$(yPeors@T)(+CI*gE&wl>@zFc#*JO`I^yS)4Lms(2hk&ffjEvlDVnfA{+z=zWQ OCnNdnG5V3goBspJ$zzcK diff --git a/plugins/KeyboardioHID/pictures/usb-core.png b/plugins/KeyboardioHID/pictures/usb-core.png deleted file mode 100644 index 6cf0c599cab3e9988846a6910b5fa5c9f7ef2d98..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18162 zcmeHvby$>L*Y7=y3=IlMN+^obNGh#}NQ)pKjdXX{5Q0dlbV#R2cb9Z`cX#Iib8gh< zeV*^V&N<)t&VS!^eSa{_+_Ue!*IxHpzqQtH?>&C6rA2Wt$uI!`z!7`(;tc?xfNxQh z(69f+w6t-9{~*?HM4tmW-FMc&4>$CmNj(FA{9vpLEmZI`hQ+IQ)&PLpc>M=yG0)He zFOt}ZDA~xF>)F_AS?K~6T83se%x1ba)EvyL%$&L(*mMElrMB3MXYvl}Tivhz)`lD1n-GOBZ$;=zk~qY&CTBxOH%KaRsc`R^cv#d2 z1sZGTRr}rMjr^>`@&UD_`FY@aYr}0V(>f}WR_0OM3Ei=3tjOG^>C~R5D^cwF-7Zxt z)jN|>Cvj(&ha=nUJ&xT`jw{`K$diTbN(Lkv02C}NwuPiif8%jIKQ!JVfu2GDptDEu zYQS9?w$^v!mA3m{6Y+!9V*ncfG(%nlIxzmedOW7D;d=D;`l`f7vOT5#WQ@gp!g zel`C0H*luM@T{B)qX(Z8z^fBc2RwaAWU@4r5>6ZtesZC~b73tgkT=yQJ>y9<^pVW6 zLKV5yogxuTn;--I$m5n=Ljb>`1jN3?Afo_(8G3oqStRkhYC`6~Skx7zxXqrm}lv=t8#AD)!W&al8u(Sb%o zfqa6O-QF)bd3?Z$<$#yl)g*`J%ZCceSW-9t8RL7Lq$skeHfnh|ZP)Rk&#V7P6Mv7z|+Yxu21 zCC2IE3A>e-2WE}C;ngSMOJR)|BN#B%;fu@zug1N1!k2vttiHYS_?yLF9I8ye>5BHe z!J&u?3G$;5mZgc4=;!+2RE2RZj~eaWNbO*x0J5$E@Vi-O(aBg_}^VggdurVr{zRPwZ$zj};i@2tJblu@0eDM=}su~gfwJHg3L0b$9L z3ablQiH+7tAu7GsMkXC$niLkK(eulk^r03*p1~VpXL6u?9FyJAn9fq!I5!69X#&-n zk0O&&3O#;KHOt`^{UGYW?&y>yjgBZO+Eh|7j3MmK5J+3UH5|?*I$*Qi@Yd5~-AGre z%Eaa-r{|PUK}RT7}= zi-AGJZv0kZxJnC2gNH^)hXixAzRKuT~VWs5&>AM zmS;Un#?OgjN2U!Sls}GoNdl+7oGNzq{h6~i5(4@Ls{4v@%VYO5h1bSd540u>nFmnA zf>Ilrlphx3c(>eA3_Cp@s&GSXD@|G0r{>gNOYl+%E_Y1OEgmnB)e6)+!t5(Lryuf) z%_m;HXY^BB?3Yh}UOCEHu=h_#c050m*uUy#Hn$|WZC|-Ywe*e31+Hw$7*;SVJX_FU z@|IUoXw0O6&H2up(1MZP2u{dRvZ;iGnC>MeTmNU=6{pR6$90nOlv=vEW{vTQR?-~Q zfdjvhlZmP3Ae=br zbd!3$J#+Jp7b39RYLv=Km-jy z#{*xv>V4LG8jfPUo?wquaJh|yi{-KGpn{(nXu^#E1lY# zr^RC#?7aOPTDDAVI}2zlOvYrd*9q(~n%jx(5lF>PU1SPp^3`C1XKG~^% z@k?%_8_?Y-i&g=M{p!Fj7bh2u;HA`#yL;K`5nfw7D)A(#w4cs~?(#?$X>F)9Uhsi? z^-Y$m27ir{M&i?voA&4048->0kKrtn2OcA1YYj1inP*P@G8YXrGpAkd3Zz!i9Y7M5 z=#jh)|2^+su6|b7>o+A$b%2ZJ`i_f=y-FtY>O{!9cQ2{fvNLV>%+8Lt!s%(FbvWfH z^&e=bk1+nc6I7L#N5%Scnri^q)a#p<8n9=oVKVfRsWDw5-mw}G<|GyRb{ZgpSGfN% zK+J&jxdE>cojT-34>wa`{C7p-(6y#YZXExS^~xpOX7ZsJ&p36#ZVO9ZWy8I&zO=?j zQy{Ijb}L%c<{(;w!?pJ58cto!lMHuw>=kChg4WBz?J}Y4TX%~niuquy3*V@6eNc6s z++oygEHp(M@6aA$8@}|{z=c}0$yD!Xh;P{C;>Rv?z?ae9xV~62rt$8z8?+*UW84>a z5-!($w)G;$4QurS@63+T1@BY0B)%TomSsCaO8qj24izD{qB&MQa`@Pwz&66oxghot zJ|4OTTBjC3Yv4vb*Q;6*cvJZ~(+5ao${H;yM*Of-5$WyP1}azdO`-@~vsW4lf_+CV zhCG$tP2@AEC5)^$bPdtx_?1eL?FT*LtD8L&w|Mw4X3v zkN}G~FxK28qQ|*OLwZI+&{0>}lY_&GPWF?a@F|4nTM_G(w?)y9=x^ef02^5hVES5- z&-ze0@`$f;7b>HS*FN6taZ~hrB=0i^zHyyn?b` zx^KY|a&l5B_TgGiy>@Fhre!NvH3;W%O2zqwDdu!kXr!X7eoABDt{Dw#&8T(O61Ub&_+aF=OXaNYylE{r_wT$h8U2+2z{ zvyc1BiceSGy*8@gr&iAs+arweyRxxD{c@3^C{In+4WtA{+TAtK`TC4t&yvZIEHvl! z))TWq?FxChY6)?9X}SRs^%W6+1P{S#on2$R;}kPGRRk}w6aDvKVrXP^5|LJg`$FLm zgZs|R7ScaMi7=w8|0b+=%3nD9V%T{q^pUySH}^PH{csU1F8b*HNJ9pq56RM?zFDCb zYOO8(CJ!=>s0kFm<`k_8u+2tSCQo~jZIGYz-Au1E`E_&Q;Tc(z2I%g`Ub;&f)3@i(LSmCQTC*%bNvvPxdUbu0}axC8GpXyK) zzZ2$o7R@!ZvElAxrK{eT@reGjHhD8(Qus0NTY2V={8uk>xJIH&?)Q?2tq<<6D%3t( zDQ~7pvdCoWSH==yYpRQ=yg$fII@Q+`VGbgY~9w9u~aMBluB#9-PD!w=n-wy z1I8oDK_v~9JceWUi8W^WjuN`%TQ_=UmJ&s3Q3r`8q@Lai8`vKG%la(Z+^t)t1j2=8 z=-m$ zf##>1459Mv8N8HI(ftN zIRd4rWfIw5({C6`q#`0LZG~Cok}Akz`|IgdA_I;eM7^5JAov$r{iu?eA^SpmCRe(J z5G}omTDv0NCc12;a-pRsIwgP!*5%Fhjf<~KHNmk;~u*dLj_p*&?#V$glSr}oc)LPH7^{J!Vk zB2=aaPMyo8&c3}7m)lIrr9wxS3r6ZYNxxbeCu@_4+{V}^Bz0f0zz``+249=1w`c50 zX~8u%6|NmrpI@EWomkDO2TD-EHpUXzvn>MF4B~yCVVdX2amYz}8qeAQV3TS^hpl<9 z^){v2fkCD>Bp|aMyY5Pqp#+WCeIjKoaX%@+L8X~b7H>K&pTe&C6i?X`S#U9qb~VnQ zT523|$*)`&h-nv|GrPMrfg@Hf1{*jr-8|SKT{CEyt1s|?FqX5zA9Kb+2wi7*;bJh? zvEq@uKqF(jLdjLhh7vWgwwb0D3@%3B&dH-83%dGJbA57=d@%*~r9*Mrtz8@JaMH6ekfBpVAeN!|WW) z(8JL{NjWnh7vspQ{*xMHQn$~DI*5xdAxDI`uh(L7Pj>o%qC@7`6l|EN}5Tk{~wt9+7~2PBRLapy22Od?&eH5TR*J!2i*? zQ3s(2L+79cEFpv%_?43o$qr7+5oWW>feDo6FMGcCDcbo{(rrDkWFYvR=Dd)#mXR%L zkOZ?G&p$mGZPR^Hh|Jv50vKw~v&d}wWy8xnKdY18D~z?7=#Rv%|7G+dgq$bW0}{e| zp>y*BW|A-e41vjuXitq0omu=*ak!tysH~M1-Up`7g53Ao81dw+m$r59kT7JvuH$B(k_%16;s^=Y) zf(7G%pG6N29~IXqlw4`m5>>d?TeNzYOyhiDw0fmtpR^A^mHvA6Ov#V{iNV}bLTt?e z5-4j&8S-V_%cdD+*(t>qH{z!$*}Srja0p{kMtS|T_m;v@StSn_EztWuNLm%YCm|I?8Ua= zTsC3@=(=~gB`kE=^xjhpmNOgjrptsU7l)Cjz1qxQ`1+$e+l?fFf!Ae+OH57bx$})^ z4EuGwX=yf&a862c2UhsscFRh;P=jJYI?+}1%~4O1?)}6AsaiYE=b>MC3h#=km|MV;+j_Sp4Q3 zUhzev8@xKhY?fm@9Vu;Ll{q(>Y~lmbUu~j`cBPG3F)IwCQ!q#@8hIPEGO18jQ4O~6 zER0g$_|sVq#G48Qu}nl5I{L-xi}H^f*#n83wD07L-OyDvK;7r0+;Hw&81N1(rd5*K z4bEp9;W*PwFZN=|vd_*L*T142b2OQ~u601Hz}5yPC?-6l;)hK~1^(b4E1a;i&=k?B zR;q;nZQ&Zg>w)o%TB&4cUUnULpUQiH2e+^e#D+!85n~G2vmR%*f8kEus-q0-FU%n! z;ooV~{0ncO$t(P%Ai(|(%$kQ)4-2bcyLBHJ$liW&ndq%@(eBx(*{c*xCC9R8x~*uS zmB%lXHi&j$YTw0YIlLXwYPHbW-Ibm zdZ{i}7EX|UH^|*D)B9e3?49N!(MsTmah@3=KnlO zbz#H&$%pH{ZA4JD!Kjk4Iaz)%ny(ECH9G2WxuKE!5209kr!^AB;EC9?#Uoe8K^-zK zM|K!NE_)}bAr&cn>2@AZyls>MnR3pYB$w9YXn9=e$uMsbTXrc|Tnr!)G~IeSIrpn^ zt1ht>H@Va{_u3wPRs^*At(T+pjR<=qfBcSKpbbnVsm&a_1{zVa#zLxG7W;(VPZ|1a zY8{8jrK|T{Bd{l&SYXtx*6xoZ&5>6!5@Xs_S0`UBVY4&u_g@v%gvz|Ex1KqD9(l-d zd``iOslB1Y3f-MikJ>NBJXRrzuAO5$cay5u>-=7!rdivjRg>GcIl5z)zTZXkZN^w$ zu+cUtUT-0ESI5Y8#f_i;N(dEO6EsDYq#!C&9v^mKu8-VpIf?~2CugsgIdROCpijkS zp3rfyF=h_Aoaqtoy(H>wjJWjvK}WmS&W@J4S$`78)V4Ey%``Exe!pijCR88EX~C+(Gz~Dd8KhZLyipV_*WSXh)(- z!6opD*5EN*?Kx8>lc?N5?`U5MOU_vbUY&V+aKhH(ZkNrYc)b(ClR^t;nWy{&5%di)`mc7jGot zNgZ$Z#W4bTbb?&&_!>%lM`qe8u?qL|B8_on+*Jp;+TOK)bjMc>$X{K_nDgzfFgtG6 z$Vj|&X~;h4Z4%r@*~57EY&{vzgQa}&>$z`TgoazWnGM@#$f}y)O!ma9YOk^YM4F3K zIe&XGmwT;6%3*arNN9vz*2q7H=O6a-)o8;zwBw0pvYFBmE z1kp*+;QKh~^9gmX>%6kGB5Eyf2V;=;)t4`V{^_ZDh7o=3ni@mtNyZfwgJ+Ayc&*b| zlhP__mC3feYRaFkG@ib4zChK>b9pk?RvN}u%Qn?ztKT`7mYcot&WJY(IX@o!^5Jke zXAX;TYkYJrQfQzafW7>MXV{ci->kbN&=^i6Qf+gp3S8tQlp5U8m*afL$!Dhem%11e z{Up=+c^g!w^m%+1S=1(r{o6w|AHAyJk`IXR_jO*2Wd3qLB6i*+RKHW!Jz#sz+p&`F zpsUR?CMYdF?OX1{G=xsLKh_pZ^NL=kl9t|DuI{g~BeC@W+!5~1tsI<`x|HY%Z;aa^ zhU?VPbmQJ*B@~ZZC%m(QUotQZqOkKApMNEws7>F)eqp(!FJI&wjJVrv&*r6MpjsO{ zx(~IrCivHkBC$;X&yr+iMI#e}nja>xV&>OGmC;8@c_kmSB1{IQJa5m}1$0N(ES|RH zPM`+rQ-9h5%XTWa7nWvZX(L`1gWX(%BY3p!uN(2?H~Rk}tTym)c;pje#s=G&x1-Ah zMUk4L#7~@|_t7>=m>>S|bbFqMols?vA$Qojuy*m+0d`UvZksf{zM5RdwG{(kS?<`m ze7906aVectCKqik<6Ucio|_VjR)@2kpC<5E*Z@m@dn(?GboVr8!bseklgA>P$^p;Z z8B!7t6ds08rF>;MSz;i!SEPNw_LB;QTXKd-zPrTr$JfK){5_LVN1Rbl6nnSmv=Jz8 zrPX`#%$(s1s1zFXuMou+009C}e|b|#J6G!Oy@=LJGeIC!| zMK098n@N}gXt;MyFIEI|$x#E_q^ysI&Z|?B;lC2Z>p4U%aRMij$nurA0aFQWwng!d zdM~ux+N<*z^O~`@6*@|@^Ts*l&89r61wptID8#DvQ?~dW80VY%g3epTBhyYB+4u-q z_H;S{a1A(+d-}Az$F=(b>aXPf*DM%wA(QUNORZcR4qBR&p$hFMHmkj+rBllx%s0p9 zaRv7LWbW`AT~R%L7JWq^!*{p-oBcFhpmUcTAcGXhI4+0 zgvDxaqKxah9P?P~L60CZ5zlqihuo~!6hYLR94tUzuN}<4JcD910W!1%H-0~Q#$?E( z{fsN(WM?GM^VbN$cb?uevmB7(J`46wrIRqOIa`id@(}YdZ((NXS!$x^;+jXYv&|n* zm`5nyt&nv=XY9E&FJB_^Q!B6(W!^0l*OI^iDVjt2p8!l0gpv*eV4tz_O0xFx*sD=3 z=S6TcfED&WU|WgjfO<_7V+X{Y=zxV2(X+S?UYp8?HnRR{=fBIkU-nl{T6c`{x1Ig} zWm;a40E}M+(XY{drF4HKR@g9B+TScR7)kzbwhyLtAzIk8KmCq|!oCh25%A;zc3o=5 zXiiF)Y??iB{4K#$BZ0uLaQYA&uMG}M=sN%DQLNUCLS#Bg0(i&TPdgH;JIsBd5w)oV z{&qc2$l+kwV*vdY^yc*Wa4999!)rN^D7?-PulqrVQO~VcEO%u=nrd0@FMMLMwpLV3 z?X5D~m9xvv)&gcNVbrP?^{CMW{{RaPAh-s(@HJ;=qC|add751{>V?RgbS0WPK*(|m z8R51TQG=M;F>3ext$$D>q;t20`ZkjBpefJ0>Np&Ix#5~QT~SY3p|4J6s+~)1aHg35 z#=HPcpk|Mo6fQFkE(*vWZ;ln_=O>awNb3INzaft`AdxzIKW0u`nQWwIJ3f`y6SAu> zLdO5@0xWyt3XCV1HN+~K%?YxyiWPyh1SLN_kGsE9l3#OYg#oNY|LXPcRQG?IRb!OL zY4Lyz!M%sF=HF`S0ZoUJZ6_aHZFZQ&cKOQoOsxj@wO!Q#X^nc=v#nofc&JG^$1+_ZQwxD`I^b2SksAOJ=GtHpDe#o=mSVK&jDJ`Tb$RVY)=hi|!F-w`8IpReKecH3P4` z($Y?@x{;^j1P@{C@YM<&-*u;5iIFYr9OUc1>@P{7&N{aqP`;`DL8I;EL+-K?rg6~Z zr`!s3KV6AM?0`zsG=b)E`%DYsYh1K!pZB&~40h0V_)mB3CmR&->{K0GZJ^dZ9RQB6 z;zivS?1!fh2Lx%p3UMW)q?OW@>Ee|NTI zs}Y~{0UNmYk_&Jod+Um+Q7O>=j!QcZadH)krb~^`K#Aub08-ZC$*E&xJqEC$8EU05 z3YYidGo$3V^7S%)u1S^Z8#lx9A(5VG4;`n#XP~14Wqr1!tEpsYR=8g171Ys$OV@pO z@{RfBlG^$5n|G`;sJ=<1dvZ zjaUMqt~mo%nTqLU`Xbw!olFNkitf_(uQ!v{>X>WZ%rxu=H$-ez?eo;SUFH}v4%{{h zZqhfoxmoSBYt5h92+E=g&C9Pzq_Q!Uae+qq=dMLX#H2DrVhw6oHwE6>-V1i;udtPc zk@W*Fq()4aP>d@tVqMY%K!J_UD4*8?wgZJ@mYuF7{uo;_JqaV+jseJL;y8S(I)lmu$$SqY7@o7joQ zrTI>*Ay8d~y7*STv>5A$)!B#qwQ}5$%o(ht_BSGpM@F&p;kIE@if#)YQ3dmvZy#h1 zFtU|qO1@7I3cwl1PGHkbV}%QlwgdEndd^x+u9JL;A9K4;$DU0bd@!gdf*M%hh6Z+; zL--A&JuBlTuoEKiJcQS5RVwSgD;6}@bk5w86+SFL?NT&Z2$hDu;?2{8W^|jyZg1Rp2BnRb;Db7I*agTwX7>_oyvtEO>2A3h#QAkFahI(;z?c zO|*Y~#FTJ8S@wfxJU0K?LH?QZQ&|$BcrfMMR*4ZEj14|+Yy5Qxi?Qm$MRgk0{Nkw8t_EfGweAiB1M<-RgqPs!-GR_8ibN{T zN@x1HI!Vjz99pD5fhgo@UID$CIUxx#IT7Sex z!3w9G_3?KLQ627 z9#DU~y29;!^N|a<{+bisF+EKdQ%A?w}i-7z~t)#vHFwVBNOKLTL}EzZ1XGpsYwyar|swKCIsU=>v)MY+E8;q zSzCJ{CFjYlYjL>YtlPBJ_;ptibxTN$N#3xHcPyQhIh|6fiw`l8eOvjNg5IE^zK61+ zdZg2WVYRLdrs=-^sWM?|b^Uva`|-?1>!b{hrYE)$uuRWMoNuP$>0fSQaV)MrRhr+U zaiEvhs6I5eb@P3ti?#6PYFL+l?uJL(9ru8%S#rDynLXXUcF*`SV^bz4^dqz-b}n=~ z`9YJ0p^`~}vdlsxnf|LeIX-2@;T^?Z*+O(hRm%@A!wm{!M5$a4AG+^9v~6Uof<(p_ zR^m&(abG-6-^s-z5Ge#INc({sBY7r*MZ^{s+2RH)OF0Z<`s2*|q%h5N@gHb?#bxA- z!g8APWmpmhSYC8ZYKDrOFBmFY%z_iu6`l`nbtgUjOv)iPtcB&~Um$#Eiy=F1 zCzZC1_hP;d2EMD>w$0^rIn6Uu@^NXFPl&MHBN(A_v{Va?5V7$CY^bN)PqwGLNa2m@ zjmH(m&-}zVHQMU4HQ54*9d$F4dYqETA6o7;mm%^{$1I$K6~q0G&DrI@-Lug#(X=BN zI=wxmhj~B>-)POD^WDSKm~^;kMxGY?Uv)1~Asqcow~Sf%ENfYItIjv)%+(OhXzqv| z!ILhQm%_H|1IXj!j+*0bsxS&y^GkfGp|5xv#{_2cg&IhIXr;Z&%CLQ_v|8#yK?ids zVjG-Lfjja_f|-tZ^QD^;*=;b1*puO|2=d=Z`e71_+S?k(?+hmKFfQO(?)-WaBZqoh z&5z9lCgO6Y48~QzwEN7{BnUdY2g1caNOE#jFDRre!AZ=9e;*tS)}cKhtus!S5p(9h z^a{a`<2jojVL`T}tGm9Ne<)~Oe=u_;fw9>0P@vj~9xDmgZ58k8U=M+O;Tc$aHDHht zw6RceH}EQ`L-!!6_IxoPA;9Eucv+HiBPqA$K=dyTsuEscz0$4S613(c!hAkbdv#Rt z*nf!)2;mU4CWuf}dN=k2E5XYnXXU7P9-osq$JAu`eR$n%^gzV|WM%A#)t8A+!#)Oj z#9M6O0~v+UviU1FNIEK>@3*%*9gKTD7ORBU%k*wJ1P9tz%XvE z)f6d4ggzW+zUlk9Br9L!JohD$oa1?@pLF~upY<|<9P-@iW03X>?;1#Vqy9Q;ymMA* zDu(f5AG5AS&#gX6KQ2>NNV}l>q!xKe!TSkKg*6F+e(YrB9r65~VGfoDn7IW)a#uXZ zeUo4V^X&{{EjeCfoh^;ba^a-CVFx>`^pN$h|u!teCy)GE$>;A z*L8?e@*n!v-rGXNC|1u6GR)YwmL@lYnp~;bL#2v2Lk+C1nI0xT z`=D|90W5ShxG_Pb0(?9+9G|UMI~zt#0N$eJr&0Pf7rru6wy9t-k2)B-M{iBuAZO z{Y;?RgY~uiH^~&fF1UGn(zmYPf(p4B<2r4t1uo(o{hV<-SpT*xJZnBhzD(1g0lj_A zkxJ|jX0f=R^h`5V5{bW5`<=}>TS>-Q}GEp*g{PqPA0FNoxI zK={+R@g~gT{BSMUWszn--AsinWPj^gN{B1`B@FI^<6&(*%q`4>b0PN!l1Grs^sLn;u=%Jk2B z_)lW52e_-K3>Li(mq#NrE(cvX{SO*Zh&8OcIL!v;zS`Q15|zzXY~+NTrbej$=X`z!qvoXcRFa=^!&gkXHcJ(;r#sE1B$i?P`d0si?{_<>NNz{HvH;y z^kPRdxdnk8-lqJYGWGcIfR_ zm$lRgu&|5EBd)Bv;fqUgKA0}B^fizVd2v8>-s@{tHV2z30h7`5)nt6W<5BG^ri2m- zaCws-s?pPpDw$OX2D-57T>J>rfs^(E5gvMp+x+8lHhpD*T-$vVkuPvKhirA~OgNbE zn}Wc!V)OkFnKMTioqyg3n8l3i$<}p2iAfd`_$rIvYVl)PlN9&Vq9Aj48e=v{nV7qs zucfEfm1;*stn9zPO-{aqlpko_DxG1@eQuL{dQ&M5F=N%iv@NWe_?tF?K;f|@S5Cvs z%Es+lI}E(qvdb!3gZKDL5(*Mpa+5$t(%D8>&(k_JFYO75A`R5?8N&0qXfw<%-$<&c z1$FE>Xggz8n-#LXktX*y^Z2dy7sZ~!9N`sHXdu1ulXc_(T(wVPiVoLvj8h*Gc*VT(RwX695x7ywJs@s7a7Fam02>_hN5BVBYEp9IBc5U_KGXbUusCcUYS&he zW#WK~d|uhdo!Z7w8%)X+0GFs9g52apN9a6--GnffJtmotaa6LF>(|Mu-o zaoV+DW81eUN|c#TX*2s?T-?p06kgC0z3vvw@#4hy<{2{~CM=-&{K;7B(0d}!-R=R@ zAhob^y0<`5cb&Xy3PF2o%++niBmB(J6NtNccdD>hs%}CfuM<~nb3hBbm-sz^0%N_- zX-WD3)!D1el(VWwr>{GZ--XVi#>SNw7{^{WxGRob?U3jbMMm$x+VpsPvTCF`2GRmB z5Cj{^;cGcLArspahq?nAQmP7}ViO@9DKSfX8kv zE!OVp!K!!`Cyx4oCw3%`*f`7t^V7UVcv}QkOLE}eCWAC&|T?_2k8RS$(M?smcfw|*7K+EMi@>5rZC4_c`%;t%N z@JO+7vXrH=hu{4*^bXCo`ri#D-UE6A#|{#oIi^Na>8VgEJ@+r8)4)Hu=5;ZUr)Eath`$|IzriI$@JHKG=8^jplu#L@7T519*Tus% zdb%;n-(!)oO~A;Oa=VP)kCIy|?~~Uc)du)M)>9fx%Ept2usxA>kADVM%;-q`WSL&R zk#mON)U`H^J1V@cO|Sv0_YP3jn628x-r=9Tt6TsQ@2!n<11QOL7XjM9GdVk%9;RRL zW&bHf`K4|&zME~B+QW6kh`{S^+omAqLOOf3I{|9n*EUL`6-U+oy44s6^HF#EBL8k} zw@uuYX^c>cxM*RyBj~v=W2{U8RMy`#w8QflJ(UCq%w16=rKJb~M zM8Kq7L=|sR)%S#KiuvO{8#`CZcz${N78dv@u3hN~>@~-XlYLIHrixxtSrej+ax{#v z77uJ|$HcxB=Xqq@QZiK!IDuqSEXg!r@`GZmiA^&LJ4_r$4UdK9Tb7(Y30#xGHhiq8 z7FGUfK+=ffu^E<5qjWn2jIq}c3c;z9Tk9)1BZ{QGQ!@Mh$LTtK$RR^^&M=||cX&D{ zbF)eMJMAT9N9uP}9Ah)yKNI;A#+^bI|B_snn2dzY19DMf%5Z*z9?At~jXie`yd zYIIt}P;vDsGLu$vUD~sy;FN*#735#GPr2n2R-*DV=S`ATxHT4m!ngq-2w|6{9ad0?>}E#5 zIj2;D9`&maV+N93Ow&q+nD^g&VndXYe(%I#?Fg-eYyG}`_5#cq5u1g!+WXfuW{1L8 z5pq-Um-)#&%0I>i>tjNs{Ox5*Wo7k{+mQ@|!K5W*pof_B1Km#+0Bn+9qFC5xdc-P}?Fqq5okoNh4&r)aTER46SS4Xl5j$3MtFfCL8C z^LeDuCtz~7U5j*^0?*9tUsv-c%>cFMf2`~ucOLzS7ev*_h&pwYkykj|ZDTgfuXVa< zg0;gpTe0T+D^>xQRTfkyTW z$erHWh5$dW8CXzUiYU&A`M6Mol{`@>t6Qa5eu!85z2Ssoe&wYdj@%y?<29~s6bKX= zrS#*QWW?BtDi=$wRe!u1T)Sg>*2f{`JQ%*dt9v9hBkAR{@px;j`}KDM^7r4=FDaQy zu}HZjlz5h3;w3sh!$8p|BLTf>@jl9;cZqL}AqPM(L91jZGw`^>Z40Kx=uNN@<7w@Y zR8Ca+s3I@x7Ci{3)&))`&&8v378Ww)qg&tN23-7j3;>V7$6cghXDdUDWvBEoy2~g( zxpm0?Rt`ZB*UzrD@$EP5_l>!t>D4^wSkxb5gUbxSZ69u+a7{U3BTnyCrIxlkcVo$G zZC5$n?A2_&APN@yIct30?^{at+V5+fQiZf@%icBgztL0hqkOKN`mW*L+qr^9I0O*- zAd4-;>e_!ITB(&e_(YXhp|i|96SW(^LDKZwD$qWjvNQNb)qlivV9~2!T-ZQ0uOgC^ z3?DpuLyxTuroykTo(!j;F!N~9!T)y zKm}tecxnefv8N~Gi(PgguMinx06bCIFTrxT>nq6TdS1k=2HpZF-7Crkxq1N5@jN~P zcbx)o$=;ecY)}oKF~r-2bdxmgg1A7yqHP8Te#{fX)Xcidqnme_6Av@e+?}c;ao?KqxjI?VhEt=cMY|F4p?5pupe6nq%1e( zrVTj&^!IL$86)p>1Bat)SKv<&Ja;y5SF@pp_9mwxpa3J>u0PIc?ItXtMdAbvP$Jn% zceRmM2jwy$FA6bBRs?YQjragSQ_cWyE7u=aAMm8)r34RhJ{;$F-ir4k0|y3ooB!J( z&tEbWJb)!E06^YP6F*25IPLH_@bo|72FES08Z{u6I8(e z;i&5`EqH>elqCGmPR0KBY#Pc1b=b^r0oS@OI@x>f2)el>gPU@|pGdgQ2_(U9XPKx0 zc;~+x=YK&Z{d#~4=^a35`Inkgy8s6)bb#9WzpAbRPS`HFxhVSGqQ&b|xduu9FRx_d zKxdIMzNvB7MU)+($+i>8KE3#4MCj8bmzaJA^4roUmLyLm^?Zw%w={X$@f9r!cp3d( zejDGP5|4VDi@`2{3-z5)eO;ko%PIA)AtksmAe$Zoi!1RNj!^p0z5$~BQmE4XM>Vq7 zx9ZcI-3PvPKV<&Tov9MGb#2V=H-Ax!6?$WLPwI~pm8SJfbC@9Jun z+)y5O{uxVkGvk;1bY~X2GOigkyMw-}v$ypsHh7oqWK23fCh2fgU!}{Du-wB2Ox5RP z23k~z9lFBCD(V+te5jnT`Ns} z_^~X9qAPgl(0~6(uu;=e3or=zj(ns>+bOYW&|!0f8JD|Sb(-Koa)Cu5r9)Dp1xNd7 z*K4y^1`cOn$V?*uY(HTJZGMzrB8E0_zoE zl*nKKSE&_zr-}H7o4wK&bUIw^V5xOk9|Vv70-DdkE8t!_hTN)Ot*{I?djt@hS-CZz xu00q0$Wn8fbfXXl?1=69H(aKski{eF2xJ7{M4%cH2M4bMVj|Kna-M5?{x5E?*jE4m From b38b0e448872e58e4d4c6e5ae294a4c7521caef6 Mon Sep 17 00:00:00 2001 From: Nico Date: Sun, 18 Jan 2015 13:59:10 +0100 Subject: [PATCH 133/602] Moved bugs and links to the wiki --- plugins/KeyboardioHID/Readme.md | 43 --------------------------------- 1 file changed, 43 deletions(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 07a023b11c..20fb0f953b 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -33,49 +33,6 @@ Test with Android phone (HL1) remove dev HL2 link ``` - -Known Bugs -========== -* See Hoodloader1+2 repositories for HoodLoader1+2 related Bugs/Issues. -* Mouse Abs only works with system report under special circumstances. -* Gamepad + Mouse Abs doesnt work together -* Core selection in boards.txt is not working -* Do not name the Arduino Sketch 'Mouse.ino' or 'Keyboard.ino' etc. -Your Arduino IDE will output errors then if you double click the file and try to compile. -* RawHID is not working properly, test it at your own risk. -* All OS have some problems with Gamepads. Dont use more than one device for Linux and be careful when you change the descriptor. -* XBMC 13.1 (a Media Center) uses Gamepad input. Its seems to not work and may cause weird errors. -Even with a standard Gamepad I have these errors. Just want to mention it here. -* The Serial may disconnect if you have too much throughput. This is a general bug of the Arduino Core, -which might be fixed. For example Adalight dosnt work well for me, -so you better use an Arduino Uno with Hoodloader1 (yes the older one!) for Mediacenter control and Ambilight. -* Feel free to open an Issue on Github if you find a bug. Or message me via my [blog](http://nicohood.wordpress.com/)! - -Useful Links/Credits -==================== - -* [LUFA from Dean Camera](http://www.fourwalledcubicle.com/LUFA.php) -* [Darran's HID Projects] (https://github.com/harlequin-tech/arduino-usb) -* [Connor's Joystick for the Leonardo](http://www.imaginaryindustries.com/blog/?p=80) -* [Stefan Jones Multimedia Keys Example](http://stefanjones.ca/blog/arduino-leonardo-remote-multimedia-keys/) -* [Athanasios Douitsis Multimedia Keys Example](https://github.com/aduitsis/ardumultimedia) -* [The Original Arduino Sources](https://github.com/arduino/Arduino/tree/master/hardware/arduino/firmwares/atmegaxxu2/arduino-usbserial) -* [USBlyzer](http://www.usblyzer.com/) -* [Mattairtechs 16u2 Lufa USB Core](https://www.mattairtech.com/index.php/development-boards/mt-db-u1.html) -* [Paul Brook's Minimus 32u2 Arduino USB Core](https://github.com/pbrook/minimus-arduino) -* [Paul Stoffregen's Teensy Core](https://github.com/PaulStoffregen/cores) -* [Keyboard Led Out report by hartmut_holgraefe](http://forum.arduino.cc/index.php?topic=173583.0) -* [Github Pull Request with a lot of new functions](https://github.com/arduino/Arduino/pull/1803) -* [Arduino ISP fix](https://petervanhoyweghen.wordpress.com/2012/09/16/arduinoisp-on-the-leonardo/) -* A lot of searching through the web -* The awesome official Arduino IRC chat! -* [The NicoHood Protocol ^.^](https://github.com/NicoHood/NicoHoodProtocol) -* See HoodLoader1&2 repository for more credits/links -* [Hackaday post about HoodLoader2](hackaday.com/2014/11/30/using-the-second-microcontroller-on-an-arduino) -* [Gamecube to PC adapter](https://github.com/NicoHood/Nintendo) -* See http://nicohood.wordpress.com/ for more tutorials, projects and contact. -* For donations please contact me on my blog :) - Version History =============== ``` From 7ce185a6895334c0f5af3fe55058e128642c14cf Mon Sep 17 00:00:00 2001 From: Nico Date: Sat, 24 Jan 2015 22:12:21 +0100 Subject: [PATCH 134/602] Removed HID_Test example Does not compile with the current settings, more a leftover from developing. --- plugins/KeyboardioHID/.gitignore | 2 + .../examples/Projects/HID_Test/HID_Test.ino | 169 ------------------ 2 files changed, 2 insertions(+), 169 deletions(-) create mode 100644 plugins/KeyboardioHID/.gitignore delete mode 100644 plugins/KeyboardioHID/examples/Projects/HID_Test/HID_Test.ino diff --git a/plugins/KeyboardioHID/.gitignore b/plugins/KeyboardioHID/.gitignore new file mode 100644 index 0000000000..117ca863b4 --- /dev/null +++ b/plugins/KeyboardioHID/.gitignore @@ -0,0 +1,2 @@ +dev/* +*.pdn \ No newline at end of file diff --git a/plugins/KeyboardioHID/examples/Projects/HID_Test/HID_Test.ino b/plugins/KeyboardioHID/examples/Projects/HID_Test/HID_Test.ino deleted file mode 100644 index d542767461..0000000000 --- a/plugins/KeyboardioHID/examples/Projects/HID_Test/HID_Test.ino +++ /dev/null @@ -1,169 +0,0 @@ -void setup() { - // put your setup code here, to run once: - pinMode(7, INPUT_PULLUP); - pinMode(8, INPUT_PULLUP); - pinMode(9, INPUT_PULLUP); - pinMode(10, INPUT_PULLUP); - pinMode(2, INPUT_PULLUP); - pinMode(3, INPUT_PULLUP); - - // 7052 279 - Keyboard.begin(); - Gamepad.begin(); - hid_keyboard_leds = 0; //test to access it from here -} - -uint32_t eventBaud = 0; - -void loop() { - - if (!digitalRead(7)) { - digitalWrite(13, 1); - Mouse.moveTo(1000, 1000); - delay(300); - digitalWrite(13, 0); - } - - if (!digitalRead(8)) { - digitalWrite(13, 1); - Mouse.move(100, 0); - delay(300); - digitalWrite(13, 0); - } - - if (!digitalRead(9)) { - digitalWrite(13, 1); - Mouse.move(-100, 0); - delay(300); - digitalWrite(13, 0); - } - - if (!digitalRead(10)) { - uint8_t k[8] = {0}; - k[1] = 1; - - k[2] = 4; - k[3] = 5; - HID_SendReport(HID_REPORTID_KEYBOARD, &k, sizeof(k)); - Keyboard.releaseAll(); - delay(300); - } - if (!digitalRead(2)) { - digitalWrite(13, 1); - System.write(SYSTEM_SLEEP); - delay(300); - digitalWrite(13, 0); - } - if (!digitalRead(3)) { - digitalWrite(13, 1); - USBDevice.wakeupHost(); - delay(300); - digitalWrite(13, 0); - } - - if (Serial.available()) { - // let the Serial receive all bytes and discard the first bytes - // this is to ensure you only input a single char and no string - char c; - delay(300); - int length = Serial.available(); - while (Serial.available()) - c = Serial.read(); - if (length > 1) { - Serial.println("Please only input a single character or deactivate linefeed!"); - return; - } - - if (c != -1) { - Serial.println(c); - switch (c) { - case 'a': - Keyboard.write('b'); - break; - - case 'p': - Consumer.write(MEDIA_PLAY_PAUSE); - break; - - case 'o': - { - // uint8_t k[8] = {0}; - // k[1] = 1 << 4; - // //k[2] = 4; - // HID_SendReport(HID_REPORTID_KEYBOARD, &k, sizeof(k)); - // Keyboard.releaseAll(); - break; - } - - case 's': - System.write(SYSTEM_SLEEP); - break; - - case 'r': - Mouse.move(100, 0); - break; - - case 'l': - Mouse.move(-100, 0); - break; - - case 't': - Mouse.moveTo(1000, 1000); - break; - - case 'c': - case 'C': - Keyboard.write(KEY_CAPS_LOCK); - Serial.println("Leds"); - Serial.println(Keyboard.getLeds(), BIN); - break; - - case 'k': - Keyboard.print("Testing USB functions xyz"); - break; - - case '\r': - case '\n': - Serial.println("Please only input a single character!"); - break; - - case 'g': { - // press button 1-32 and reset (34 becaue its written later) - static uint8_t count = 1; - Gamepad.press(count++); - if (count == 34) { - Gamepad.releaseAll(); - count = 1; - } - Gamepad.write(); - } - break; - - case 'd': - Serial.println("Serial"); - Serial.println(Serial.dtr()); - Serial.println(Serial.rts()); - Serial.println(Serial.baud()); - Serial.println(Serial.stopbits()); - Serial.println(Serial.paritytype()); - Serial.println(Serial.numbits()); - break; - - default: - Serial.println("unknown"); - } - } - } - - - if (eventBaud) { - Serial.println("Event"); - Serial.println(eventBaud); - eventBaud = 0; - } -} - -void CDC_LineEncodingEvent(void) -{ - eventBaud = Serial.baud(); -} From 41771bb9666ec4dff2db4c659d0de5d032db25d1 Mon Sep 17 00:00:00 2001 From: Nico Date: Sat, 24 Jan 2015 22:12:54 +0100 Subject: [PATCH 135/602] Arduino as ISP 16u2 fix --- plugins/KeyboardioHID/Readme.md | 15 +- .../Projects/ArduinoISP/ArduinoISP.ino | 330 +++++++++--------- 2 files changed, 173 insertions(+), 172 deletions(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 20fb0f953b..ff70085fc9 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -13,6 +13,13 @@ All documentation moved to the [wiki page](https://github.com/NicoHood/HID/wiki) An offline version will be available soon. +Contact +======= + +You can contact me on my wordpress blog in the contact section. + +www.nicohood.de + TODO ==== @@ -31,12 +38,14 @@ update Burning via ISP for HL2 Test with Android phone (HL1) "Emulate" HL1 protocol remove dev HL2 link + +HL2 usb hub fix (try with a bare cdc bootloader?) ``` Version History =============== ``` -2.1 Release (xx.01.2015) +2.1 Release (28.01.2015) * Reworked the whole USB-Core from scratch * Uses less flash if HID or Serial is not used * Extended and compacter(flash) HID Report Descriptors @@ -64,8 +73,8 @@ Version History * Added HID Tables * USB-Serial now fully reprogrammable * Easy USB-Core selection via Tools->USB-Core -* Added Arduino as ISP fix for 32u4 (u2 Series doesn't work at the moment) -* Updated USB-Serial +* Added Arduino as ISP fix for 32u4 and 16u2 +* Moved documentation to the wiki 2.0 Release (29.11.2014) * Added HoodLoader2 diff --git a/plugins/KeyboardioHID/examples/Projects/ArduinoISP/ArduinoISP.ino b/plugins/KeyboardioHID/examples/Projects/ArduinoISP/ArduinoISP.ino index 0766ebae9f..03a39d70f7 100644 --- a/plugins/KeyboardioHID/examples/Projects/ArduinoISP/ArduinoISP.ino +++ b/plugins/KeyboardioHID/examples/Projects/ArduinoISP/ArduinoISP.ino @@ -1,16 +1,16 @@ // ArduinoISP version 04m3 // Copyright (c) 2008-2011 Randall Bohn -// If you require a license, see +// If you require a license, see // http://www.opensource.org/licenses/bsd-license.php // // This sketch turns the Arduino into a AVRISP // using the following arduino pins: // // pin name: not-mega: mega(1280 and 2560) -// slave reset: 10: 53 -// MOSI: 11: 51 -// MISO: 12: 50 -// SCK: 13: 52 +// slave reset: 10: 53 +// MOSI: 11: 51 +// MISO: 12: 50 +// SCK: 13: 52 // // Put an LED (with resistor) on the following pins: // 9: Heartbeat - shows the programmer is running @@ -31,7 +31,7 @@ // // October 2009 by David A. Mellis // - Added support for the read signature command -// +// // February 2009 by Randall Bohn // - Added support for writing to EEPROM (what took so long?) // Windows users should consider WinAVR's avrdude instead of the @@ -40,11 +40,17 @@ // January 2008 by Randall Bohn // - Thanks to Amplificar for helping me with the STK500 protocol // - The AVRISP/STK500 (mk I) protocol is used in the arduino bootloader -// - The SPI functions herein were developed for the AVR910_ARD programmer +// - The SPI functions herein were developed for the AVR910_ARD programmer // - More information at http://code.google.com/p/mega-isp +#include "SPI.h" #include "pins_arduino.h" + +#ifdef ARDUINO_HOODLOADER2 +#define RESET 4 +#else #define RESET 10 +#endif #define LED_HB 9 #define LED_ERR 8 @@ -67,16 +73,21 @@ void pulse(int pin, int times); void setup() { Serial.begin(19200); + SPI.setDataMode(0); + SPI.setBitOrder(MSBFIRST); + // Clock Div can be 2,4,8,16,32,64, or 128 + SPI.setClockDivider(SPI_CLOCK_DIV128); pinMode(LED_PMODE, OUTPUT); pulse(LED_PMODE, 2); pinMode(LED_ERR, OUTPUT); pulse(LED_ERR, 2); pinMode(LED_HB, OUTPUT); pulse(LED_HB, 2); + } -int error = 0; -int pmode = 0; +int error=0; +int pmode=0; // address for reading and writing, set by 'U' command int here; uint8_t buff[256]; // global block storage @@ -91,34 +102,34 @@ typedef struct param { uint8_t selftimed; uint8_t lockbytes; uint8_t fusebytes; - int flashpoll; - int eeprompoll; - int pagesize; - int eepromsize; - int flashsize; -} + uint8_t flashpoll; + uint16_t eeprompoll; + uint16_t pagesize; + uint16_t eepromsize; + uint32_t flashsize; +} parameter; parameter param; // this provides a heartbeat on pin 9, so you can tell the software is running. -uint8_t hbval = 128; -int8_t hbdelta = 8; +uint8_t hbval=128; +int8_t hbdelta=8; void heartbeat() { if (hbval > 192) hbdelta = -hbdelta; if (hbval < 32) hbdelta = -hbdelta; hbval += hbdelta; analogWrite(LED_HB, hbval); - delay(20); + delay(40); } void loop(void) { // is pmode active? - if (pmode) digitalWrite(LED_PMODE, HIGH); + if (pmode) digitalWrite(LED_PMODE, HIGH); else digitalWrite(LED_PMODE, LOW); // is there an error? - if (error) digitalWrite(LED_ERR, HIGH); + if (error) digitalWrite(LED_ERR, HIGH); else digitalWrite(LED_ERR, LOW); // light the heartbeat LED @@ -129,7 +140,7 @@ void loop(void) { } uint8_t getch() { - while (!Serial.available()); + while(!Serial.available()); return Serial.read(); } void fill(int n) { @@ -145,7 +156,7 @@ void pulse(int pin, int times) { delay(PTIME); digitalWrite(pin, LOW); delay(PTIME); - } + } while (times--); } @@ -154,41 +165,20 @@ void prog_lamp(int state) { digitalWrite(LED_PMODE, state); } -void spi_init() { - uint8_t x; - SPCR = 0x53; - x = SPSR; - x = SPDR; -} - -void spi_wait() { - do { - } - while (!(SPSR & (1 << SPIF))); -} - -uint8_t spi_send(uint8_t b) { - uint8_t reply; - SPDR = b; - spi_wait(); - reply = SPDR; - return reply; -} - uint8_t spi_transaction(uint8_t a, uint8_t b, uint8_t c, uint8_t d) { uint8_t n; - spi_send(a); - n = spi_send(b); + SPI.transfer(a); + n=SPI.transfer(b); //if (n != a) error = -1; - n = spi_send(c); - return spi_send(d); + n=SPI.transfer(c); + return SPI.transfer(d); } void empty_reply() { if (CRC_EOP == getch()) { Serial.print((char)STK_INSYNC); Serial.print((char)STK_OK); - } + } else { error++; Serial.print((char)STK_NOSYNC); @@ -200,7 +190,7 @@ void breply(uint8_t b) { Serial.print((char)STK_INSYNC); Serial.print((char)b); Serial.print((char)STK_OK); - } + } else { error++; Serial.print((char)STK_NOSYNC); @@ -208,21 +198,21 @@ void breply(uint8_t b) { } void get_version(uint8_t c) { - switch (c) { - case 0x80: - breply(HWVER); - break; - case 0x81: - breply(SWMAJ); - break; - case 0x82: - breply(SWMIN); - break; - case 0x93: - breply('S'); // serial programmer - break; - default: - breply(0); + switch(c) { + case 0x80: + breply(HWVER); + break; + case 0x81: + breply(SWMAJ); + break; + case 0x82: + breply(SWMIN); + break; + case 0x93: + breply('S'); // serial programmer + break; + default: + breply(0); } } @@ -236,7 +226,7 @@ void set_parameters() { param.selftimed = buff[5]; param.lockbytes = buff[6]; param.fusebytes = buff[7]; - param.flashpoll = buff[8]; + param.flashpoll = buff[8]; // ignore buff[9] (= buff[8]) // following are 16 bits (big endian) param.eeprompoll = beget16(&buff[10]); @@ -245,32 +235,26 @@ void set_parameters() { // 32 bits flashsize (big endian) param.flashsize = buff[16] * 0x01000000 - + buff[17] * 0x00010000 - + buff[18] * 0x00000100 - + buff[19]; + + buff[17] * 0x00010000 + + buff[18] * 0x00000100 + + buff[19]; } void start_pmode() { - spi_init(); - // following delays may not work on all targets... - pinMode(RESET, OUTPUT); + SPI.begin(); digitalWrite(RESET, HIGH); - pinMode(SCK, OUTPUT); + pinMode(RESET, OUTPUT); digitalWrite(SCK, LOW); - delay(50); + delay(20); digitalWrite(RESET, LOW); - delay(50); - pinMode(MISO, INPUT); - pinMode(MOSI, OUTPUT); spi_transaction(0xAC, 0x53, 0x00, 0x00); pmode = 1; } void end_pmode() { - pinMode(MISO, INPUT); - pinMode(MOSI, INPUT); - pinMode(SCK, INPUT); + SPI.end(); + digitalWrite(RESET, HIGH); pinMode(RESET, INPUT); pmode = 0; } @@ -285,10 +269,10 @@ void universal() { } void flash(uint8_t hilo, int addr, uint8_t data) { - spi_transaction(0x40 + 8 * hilo, - addr >> 8 & 0xFF, - addr & 0xFF, - data); + spi_transaction(0x40+8*hilo, + addr>>8 & 0xFF, + addr & 0xFF, + data); } void commit(int addr) { if (PROG_FLICKER) prog_lamp(LOW); @@ -314,7 +298,7 @@ void write_flash(int length) { if (CRC_EOP == getch()) { Serial.print((char) STK_INSYNC); Serial.print((char) write_flash_pages(length)); - } + } else { error++; Serial.print((char) STK_NOSYNC); @@ -363,11 +347,11 @@ uint8_t write_eeprom_chunk(int start, int length) { fill(length); prog_lamp(LOW); for (int x = 0; x < length; x++) { - int addr = start + x; - spi_transaction(0xC0, (addr >> 8) & 0xFF, addr & 0xFF, buff[x]); + int addr = start+x; + spi_transaction(0xC0, (addr>>8) & 0xFF, addr & 0xFF, buff[x]); delay(45); } - prog_lamp(HIGH); + prog_lamp(HIGH); return STK_OK; } @@ -386,7 +370,7 @@ void program_page() { if (CRC_EOP == getch()) { Serial.print((char) STK_INSYNC); Serial.print(result); - } + } else { error++; Serial.print((char) STK_NOSYNC); @@ -399,13 +383,13 @@ void program_page() { uint8_t flash_read(uint8_t hilo, int addr) { return spi_transaction(0x20 + hilo * 8, - (addr >> 8) & 0xFF, - addr & 0xFF, - 0); + (addr >> 8) & 0xFF, + addr & 0xFF, + 0); } char flash_read_page(int length) { - for (int x = 0; x < length; x += 2) { + for (int x = 0; x < length; x+=2) { uint8_t low = flash_read(LOW, here); Serial.print((char) low); uint8_t high = flash_read(HIGH, here); @@ -464,91 +448,99 @@ void read_signature() { //////////////////////////////////// //////////////////////////////////// -int avrisp() { +int avrisp() { uint8_t data, low, high; uint8_t ch = getch(); switch (ch) { - case '0': // signon - error = 0; - empty_reply(); - break; - case '1': - if (getch() == CRC_EOP) { - Serial.print((char) STK_INSYNC); - Serial.print("AVR ISP"); - Serial.print((char) STK_OK); - } - break; - case 'A': - get_version(getch()); - break; - case 'B': - fill(20); - set_parameters(); - empty_reply(); - break; - case 'E': // extended parameters - ignore for now - fill(5); - empty_reply(); - break; - - case 'P': - start_pmode(); - empty_reply(); - break; - case 'U': // set address (word) - here = getch(); - here += 256 * getch(); - empty_reply(); - break; - - case 0x60: //STK_PROG_FLASH - low = getch(); - high = getch(); - empty_reply(); - break; - case 0x61: //STK_PROG_DATA - data = getch(); - empty_reply(); - break; - - case 0x64: //STK_PROG_PAGE - program_page(); - break; - - case 0x74: //STK_READ_PAGE 't' - read_page(); - break; - - case 'V': //0x56 - universal(); - break; - case 'Q': //0x51 - error = 0; - end_pmode(); - empty_reply(); - break; - - case 0x75: //STK_READ_SIGN 'u' - read_signature(); - break; - - // expecting a command, not CRC_EOP - // this is how we can get back in sync - case CRC_EOP: + case '0': // signon + error = 0; + empty_reply(); + break; + case '1': + if (getch() == CRC_EOP) { + Serial.print((char) STK_INSYNC); + Serial.print("AVR ISP"); + Serial.print((char) STK_OK); + } else { error++; Serial.print((char) STK_NOSYNC); - break; + } + break; + case 'A': + get_version(getch()); + break; + case 'B': + fill(20); + set_parameters(); + empty_reply(); + break; + case 'E': // extended parameters - ignore for now + fill(5); + empty_reply(); + break; + + case 'P': + if (pmode) { + pulse(LED_ERR, 3); + } else { + start_pmode(); + } + empty_reply(); + break; + case 'U': // set address (word) + here = getch(); + here += 256 * getch(); + empty_reply(); + break; + + case 0x60: //STK_PROG_FLASH + low = getch(); + high = getch(); + empty_reply(); + break; + case 0x61: //STK_PROG_DATA + data = getch(); + empty_reply(); + break; + + case 0x64: //STK_PROG_PAGE + program_page(); + break; + + case 0x74: //STK_READ_PAGE 't' + read_page(); + break; + + case 'V': //0x56 + universal(); + break; + case 'Q': //0x51 + error=0; + end_pmode(); + empty_reply(); + break; + + case 0x75: //STK_READ_SIGN 'u' + read_signature(); + break; + + // expecting a command, not CRC_EOP + // this is how we can get back in sync + case CRC_EOP: + error++; + Serial.print((char) STK_NOSYNC); + break; - // anything else we will return STK_UNKNOWN - default: - error++; - if (CRC_EOP == getch()) - Serial.print((char)STK_UNKNOWN); - else - Serial.print((char)STK_NOSYNC); + // anything else we will return STK_UNKNOWN + default: + error++; + if (CRC_EOP == getch()) + Serial.print((char)STK_UNKNOWN); + else + Serial.print((char)STK_NOSYNC); } } + From 1697b0b454107af75fa19cebcef42d9ea2b86694 Mon Sep 17 00:00:00 2001 From: Nico Date: Sat, 24 Jan 2015 22:51:38 +0100 Subject: [PATCH 136/602] Added Arduino Libraries to avoid compiling errors Also included the SoftSerial fix by matthijskooijman https://github.com/arduino/Arduino/pull/2032 --- plugins/KeyboardioHID/Readme.md | 1 + .../avr/libraries/EEPROM/EEPROM.cpp | 50 ++ .../avr/libraries/EEPROM/EEPROM.h | 35 ++ .../examples/eeprom_clear/eeprom_clear.ino | 23 + .../examples/eeprom_read/eeprom_read.ino | 43 ++ .../examples/eeprom_write/eeprom_write.ino | 38 ++ .../avr/libraries/EEPROM/keywords.txt | 18 + .../avr/libraries/EEPROM/library.properties | 8 + .../KeyboardioHID/avr/libraries/SPI/SPI.cpp | 193 +++++++ plugins/KeyboardioHID/avr/libraries/SPI/SPI.h | 324 +++++++++++ .../BarometricPressureSensor.ino | 143 +++++ .../DigitalPotControl/DigitalPotControl.ino | 71 +++ .../avr/libraries/SPI/keywords.txt | 36 ++ .../avr/libraries/SPI/library.properties | 8 + .../SoftwareSerial/SoftwareSerial.cpp | 486 ++++++++++++++++ .../libraries/SoftwareSerial/SoftwareSerial.h | 120 ++++ .../SoftwareSerialExample.ino | 55 ++ .../TwoPortReceive/TwoPortReceive.ino | 93 ++++ .../avr/libraries/SoftwareSerial/keywords.txt | 30 + .../SoftwareSerial/library.properties | 8 + .../KeyboardioHID/avr/libraries/Wire/Wire.cpp | 303 ++++++++++ .../KeyboardioHID/avr/libraries/Wire/Wire.h | 80 +++ .../SFRRanger_reader/SFRRanger_reader.ino | 87 +++ .../digital_potentiometer.ino | 39 ++ .../examples/master_reader/master_reader.ino | 32 ++ .../examples/master_writer/master_writer.ino | 31 ++ .../slave_receiver/slave_receiver.ino | 38 ++ .../examples/slave_sender/slave_sender.ino | 32 ++ .../avr/libraries/Wire/keywords.txt | 32 ++ .../avr/libraries/Wire/library.properties | 8 + .../avr/libraries/Wire/utility/twi.c | 527 ++++++++++++++++++ .../avr/libraries/Wire/utility/twi.h | 53 ++ 32 files changed, 3045 insertions(+) create mode 100644 plugins/KeyboardioHID/avr/libraries/EEPROM/EEPROM.cpp create mode 100644 plugins/KeyboardioHID/avr/libraries/EEPROM/EEPROM.h create mode 100644 plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_clear/eeprom_clear.ino create mode 100644 plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_read/eeprom_read.ino create mode 100644 plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_write/eeprom_write.ino create mode 100644 plugins/KeyboardioHID/avr/libraries/EEPROM/keywords.txt create mode 100644 plugins/KeyboardioHID/avr/libraries/EEPROM/library.properties create mode 100644 plugins/KeyboardioHID/avr/libraries/SPI/SPI.cpp create mode 100644 plugins/KeyboardioHID/avr/libraries/SPI/SPI.h create mode 100644 plugins/KeyboardioHID/avr/libraries/SPI/examples/BarometricPressureSensor/BarometricPressureSensor.ino create mode 100644 plugins/KeyboardioHID/avr/libraries/SPI/examples/DigitalPotControl/DigitalPotControl.ino create mode 100644 plugins/KeyboardioHID/avr/libraries/SPI/keywords.txt create mode 100644 plugins/KeyboardioHID/avr/libraries/SPI/library.properties create mode 100644 plugins/KeyboardioHID/avr/libraries/SoftwareSerial/SoftwareSerial.cpp create mode 100644 plugins/KeyboardioHID/avr/libraries/SoftwareSerial/SoftwareSerial.h create mode 100644 plugins/KeyboardioHID/avr/libraries/SoftwareSerial/examples/SoftwareSerialExample/SoftwareSerialExample.ino create mode 100644 plugins/KeyboardioHID/avr/libraries/SoftwareSerial/examples/TwoPortReceive/TwoPortReceive.ino create mode 100644 plugins/KeyboardioHID/avr/libraries/SoftwareSerial/keywords.txt create mode 100644 plugins/KeyboardioHID/avr/libraries/SoftwareSerial/library.properties create mode 100644 plugins/KeyboardioHID/avr/libraries/Wire/Wire.cpp create mode 100644 plugins/KeyboardioHID/avr/libraries/Wire/Wire.h create mode 100644 plugins/KeyboardioHID/avr/libraries/Wire/examples/SFRRanger_reader/SFRRanger_reader.ino create mode 100644 plugins/KeyboardioHID/avr/libraries/Wire/examples/digital_potentiometer/digital_potentiometer.ino create mode 100644 plugins/KeyboardioHID/avr/libraries/Wire/examples/master_reader/master_reader.ino create mode 100644 plugins/KeyboardioHID/avr/libraries/Wire/examples/master_writer/master_writer.ino create mode 100644 plugins/KeyboardioHID/avr/libraries/Wire/examples/slave_receiver/slave_receiver.ino create mode 100644 plugins/KeyboardioHID/avr/libraries/Wire/examples/slave_sender/slave_sender.ino create mode 100644 plugins/KeyboardioHID/avr/libraries/Wire/keywords.txt create mode 100644 plugins/KeyboardioHID/avr/libraries/Wire/library.properties create mode 100644 plugins/KeyboardioHID/avr/libraries/Wire/utility/twi.c create mode 100644 plugins/KeyboardioHID/avr/libraries/Wire/utility/twi.h diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index ff70085fc9..741a4a93da 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -75,6 +75,7 @@ Version History * Easy USB-Core selection via Tools->USB-Core * Added Arduino as ISP fix for 32u4 and 16u2 * Moved documentation to the wiki +* Added AVR libraries to the core with the better SoftSerial 2.0 Release (29.11.2014) * Added HoodLoader2 diff --git a/plugins/KeyboardioHID/avr/libraries/EEPROM/EEPROM.cpp b/plugins/KeyboardioHID/avr/libraries/EEPROM/EEPROM.cpp new file mode 100644 index 0000000000..dfa1deb560 --- /dev/null +++ b/plugins/KeyboardioHID/avr/libraries/EEPROM/EEPROM.cpp @@ -0,0 +1,50 @@ +/* + EEPROM.cpp - EEPROM library + Copyright (c) 2006 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 +*/ + +/****************************************************************************** + * Includes + ******************************************************************************/ + +#include +#include "Arduino.h" +#include "EEPROM.h" + +/****************************************************************************** + * Definitions + ******************************************************************************/ + +/****************************************************************************** + * Constructors + ******************************************************************************/ + +/****************************************************************************** + * User API + ******************************************************************************/ + +uint8_t EEPROMClass::read(int address) +{ + return eeprom_read_byte((unsigned char *) address); +} + +void EEPROMClass::write(int address, uint8_t value) +{ + eeprom_write_byte((unsigned char *) address, value); +} + +EEPROMClass EEPROM; diff --git a/plugins/KeyboardioHID/avr/libraries/EEPROM/EEPROM.h b/plugins/KeyboardioHID/avr/libraries/EEPROM/EEPROM.h new file mode 100644 index 0000000000..aa2b577268 --- /dev/null +++ b/plugins/KeyboardioHID/avr/libraries/EEPROM/EEPROM.h @@ -0,0 +1,35 @@ +/* + EEPROM.h - EEPROM library + Copyright (c) 2006 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 EEPROM_h +#define EEPROM_h + +#include + +class EEPROMClass +{ + public: + uint8_t read(int); + void write(int, uint8_t); +}; + +extern EEPROMClass EEPROM; + +#endif + diff --git a/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_clear/eeprom_clear.ino b/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_clear/eeprom_clear.ino new file mode 100644 index 0000000000..b18ff2ca3e --- /dev/null +++ b/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_clear/eeprom_clear.ino @@ -0,0 +1,23 @@ +/* + * EEPROM Clear + * + * Sets all of the bytes of the EEPROM to 0. + * This example code is in the public domain. + + */ + +#include + +void setup() +{ + // write a 0 to all 512 bytes of the EEPROM + for (int i = 0; i < 512; i++) + EEPROM.write(i, 0); + + // turn the LED on when we're done + digitalWrite(13, HIGH); +} + +void loop() +{ +} diff --git a/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_read/eeprom_read.ino b/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_read/eeprom_read.ino new file mode 100644 index 0000000000..ebf79d683f --- /dev/null +++ b/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_read/eeprom_read.ino @@ -0,0 +1,43 @@ +/* + * EEPROM Read + * + * Reads the value of each byte of the EEPROM and prints it + * to the computer. + * This example code is in the public domain. + */ + +#include + +// start reading from the first byte (address 0) of the EEPROM +int address = 0; +byte value; + +void setup() +{ + // initialize serial and wait for port to open: + Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for Leonardo only + } +} + +void loop() +{ + // read a byte from the current address of the EEPROM + value = EEPROM.read(address); + + Serial.print(address); + Serial.print("\t"); + Serial.print(value, DEC); + Serial.println(); + + // advance to the next address of the EEPROM + address = address + 1; + + // there are only 512 bytes of EEPROM, from 0 to 511, so if we're + // on address 512, wrap around to address 0 + if (address == 512) + address = 0; + + delay(500); +} diff --git a/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_write/eeprom_write.ino b/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_write/eeprom_write.ino new file mode 100644 index 0000000000..c047887083 --- /dev/null +++ b/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_write/eeprom_write.ino @@ -0,0 +1,38 @@ +/* + * EEPROM Write + * + * Stores values read from analog input 0 into the EEPROM. + * These values will stay in the EEPROM when the board is + * turned off and may be retrieved later by another sketch. + */ + +#include + +// the current address in the EEPROM (i.e. which byte +// we're going to write to next) +int addr = 0; + +void setup() +{ +} + +void loop() +{ + // need to divide by 4 because analog inputs range from + // 0 to 1023 and each byte of the EEPROM can only hold a + // value from 0 to 255. + int val = analogRead(0) / 4; + + // write the value to the appropriate byte of the EEPROM. + // these values will remain there when the board is + // turned off. + EEPROM.write(addr, val); + + // advance to the next address. there are 512 bytes in + // the EEPROM, so go back to 0 when we hit 512. + addr = addr + 1; + if (addr == 512) + addr = 0; + + delay(100); +} diff --git a/plugins/KeyboardioHID/avr/libraries/EEPROM/keywords.txt b/plugins/KeyboardioHID/avr/libraries/EEPROM/keywords.txt new file mode 100644 index 0000000000..d3218fe2ac --- /dev/null +++ b/plugins/KeyboardioHID/avr/libraries/EEPROM/keywords.txt @@ -0,0 +1,18 @@ +####################################### +# Syntax Coloring Map For Ultrasound +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +EEPROM KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +####################################### +# Constants (LITERAL1) +####################################### + diff --git a/plugins/KeyboardioHID/avr/libraries/EEPROM/library.properties b/plugins/KeyboardioHID/avr/libraries/EEPROM/library.properties new file mode 100644 index 0000000000..796f7cb877 --- /dev/null +++ b/plugins/KeyboardioHID/avr/libraries/EEPROM/library.properties @@ -0,0 +1,8 @@ +name=EEPROM +version=1.0 +author=Arduino +maintainer=Arduino +sentence=Enables reading and writing to the permanent board storage. For all Arduino boards BUT Arduino DUE. +paragraph= +url=http://arduino.cc/en/Reference/EEPROM +architectures=avr diff --git a/plugins/KeyboardioHID/avr/libraries/SPI/SPI.cpp b/plugins/KeyboardioHID/avr/libraries/SPI/SPI.cpp new file mode 100644 index 0000000000..077b6a38db --- /dev/null +++ b/plugins/KeyboardioHID/avr/libraries/SPI/SPI.cpp @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2010 by Cristian Maglie + * Copyright (c) 2014 by Paul Stoffregen (Transaction API) + * Copyright (c) 2014 by Matthijs Kooijman (SPISettings AVR) + * Copyright (c) 2014 by Andrew J. Kroll (atomicity fixes) + * SPI Master library for arduino. + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either the GNU General Public License version 2 + * or the GNU Lesser General Public License version 2.1, both as + * published by the Free Software Foundation. + */ + +#include "SPI.h" + +SPIClass SPI; + +uint8_t SPIClass::initialized = 0; +uint8_t SPIClass::interruptMode = 0; +uint8_t SPIClass::interruptMask = 0; +uint8_t SPIClass::interruptSave = 0; +#ifdef SPI_TRANSACTION_MISMATCH_LED +uint8_t SPIClass::inTransactionFlag = 0; +#endif + +void SPIClass::begin() +{ + uint8_t sreg = SREG; + noInterrupts(); // Protect from a scheduler and prevent transactionBegin + if (!initialized) { + // Set SS to high so a connected chip will be "deselected" by default + digitalWrite(SS, HIGH); + + // When the SS pin is set as OUTPUT, it can be used as + // a general purpose output port (it doesn't influence + // SPI operations). + pinMode(SS, OUTPUT); + + // Warning: if the SS pin ever becomes a LOW INPUT then SPI + // automatically switches to Slave, so the data direction of + // the SS pin MUST be kept as OUTPUT. + SPCR |= _BV(MSTR); + SPCR |= _BV(SPE); + + // Set direction register for SCK and MOSI pin. + // MISO pin automatically overrides to INPUT. + // By doing this AFTER enabling SPI, we avoid accidentally + // clocking in a single bit since the lines go directly + // from "input" to SPI control. + // http://code.google.com/p/arduino/issues/detail?id=888 + pinMode(SCK, OUTPUT); + pinMode(MOSI, OUTPUT); + } + initialized++; // reference count + SREG = sreg; +} + +void SPIClass::end() { + uint8_t sreg = SREG; + noInterrupts(); // Protect from a scheduler and prevent transactionBegin + // Decrease the reference counter + if (initialized) + initialized--; + // If there are no more references disable SPI + if (!initialized) { + SPCR &= ~_BV(SPE); + interruptMode = 0; + #ifdef SPI_TRANSACTION_MISMATCH_LED + inTransactionFlag = 0; + #endif + } + SREG = sreg; +} + +// mapping of interrupt numbers to bits within SPI_AVR_EIMSK +#if defined(__AVR_ATmega32U4__) + #define SPI_INT0_MASK (1< + * Copyright (c) 2014 by Paul Stoffregen (Transaction API) + * Copyright (c) 2014 by Matthijs Kooijman (SPISettings AVR) + * Copyright (c) 2014 by Andrew J. Kroll (atomicity fixes) + * SPI Master library for arduino. + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either the GNU General Public License version 2 + * or the GNU Lesser General Public License version 2.1, both as + * published by the Free Software Foundation. + */ + +#ifndef _SPI_H_INCLUDED +#define _SPI_H_INCLUDED + +#include + +// SPI_HAS_TRANSACTION means SPI has beginTransaction(), endTransaction(), +// usingInterrupt(), and SPISetting(clock, bitOrder, dataMode) +#define SPI_HAS_TRANSACTION 1 + +// SPI_HAS_NOTUSINGINTERRUPT means that SPI has notUsingInterrupt() method +#define SPI_HAS_NOTUSINGINTERRUPT 1 + +// SPI_ATOMIC_VERSION means that SPI has atomicity fixes and what version. +// This way when there is a bug fix you can check this define to alert users +// of your code if it uses better version of this library. +// This also implies everything that SPI_HAS_TRANSACTION as documented above is +// available too. +#define SPI_ATOMIC_VERSION 1 + +// Uncomment this line to add detection of mismatched begin/end transactions. +// A mismatch occurs if other libraries fail to use SPI.endTransaction() for +// each SPI.beginTransaction(). Connect an LED to this pin. The LED will turn +// on if any mismatch is ever detected. +//#define SPI_TRANSACTION_MISMATCH_LED 5 + +#ifndef LSBFIRST +#define LSBFIRST 0 +#endif +#ifndef MSBFIRST +#define MSBFIRST 1 +#endif + +#define SPI_CLOCK_DIV4 0x00 +#define SPI_CLOCK_DIV16 0x01 +#define SPI_CLOCK_DIV64 0x02 +#define SPI_CLOCK_DIV128 0x03 +#define SPI_CLOCK_DIV2 0x04 +#define SPI_CLOCK_DIV8 0x05 +#define SPI_CLOCK_DIV32 0x06 + +#define SPI_MODE0 0x00 +#define SPI_MODE1 0x04 +#define SPI_MODE2 0x08 +#define SPI_MODE3 0x0C + +#define SPI_MODE_MASK 0x0C // CPOL = bit 3, CPHA = bit 2 on SPCR +#define SPI_CLOCK_MASK 0x03 // SPR1 = bit 1, SPR0 = bit 0 on SPCR +#define SPI_2XCLOCK_MASK 0x01 // SPI2X = bit 0 on SPSR + +// define SPI_AVR_EIMSK for AVR boards with external interrupt pins +#if defined(EIMSK) + #define SPI_AVR_EIMSK EIMSK +#elif defined(GICR) + #define SPI_AVR_EIMSK GICR +#elif defined(GIMSK) + #define SPI_AVR_EIMSK GIMSK +#endif + +class SPISettings { +public: + SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) { + if (__builtin_constant_p(clock)) { + init_AlwaysInline(clock, bitOrder, dataMode); + } else { + init_MightInline(clock, bitOrder, dataMode); + } + } + SPISettings() { + init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0); + } +private: + void init_MightInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) { + init_AlwaysInline(clock, bitOrder, dataMode); + } + void init_AlwaysInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) + __attribute__((__always_inline__)) { + // Clock settings are defined as follows. Note that this shows SPI2X + // inverted, so the bits form increasing numbers. Also note that + // fosc/64 appears twice + // SPR1 SPR0 ~SPI2X Freq + // 0 0 0 fosc/2 + // 0 0 1 fosc/4 + // 0 1 0 fosc/8 + // 0 1 1 fosc/16 + // 1 0 0 fosc/32 + // 1 0 1 fosc/64 + // 1 1 0 fosc/64 + // 1 1 1 fosc/128 + + // We find the fastest clock that is less than or equal to the + // given clock rate. The clock divider that results in clock_setting + // is 2 ^^ (clock_div + 1). If nothing is slow enough, we'll use the + // slowest (128 == 2 ^^ 7, so clock_div = 6). + uint8_t clockDiv; + + // When the clock is known at compiletime, use this if-then-else + // cascade, which the compiler knows how to completely optimize + // away. When clock is not known, use a loop instead, which generates + // shorter code. + if (__builtin_constant_p(clock)) { + if (clock >= F_CPU / 2) { + clockDiv = 0; + } else if (clock >= F_CPU / 4) { + clockDiv = 1; + } else if (clock >= F_CPU / 8) { + clockDiv = 2; + } else if (clock >= F_CPU / 16) { + clockDiv = 3; + } else if (clock >= F_CPU / 32) { + clockDiv = 4; + } else if (clock >= F_CPU / 64) { + clockDiv = 5; + } else { + clockDiv = 6; + } + } else { + uint32_t clockSetting = F_CPU / 2; + clockDiv = 0; + while (clockDiv < 6 && clock < clockSetting) { + clockSetting /= 2; + clockDiv++; + } + } + + // Compensate for the duplicate fosc/64 + if (clockDiv == 6) + clockDiv = 7; + + // Invert the SPI2X bit + clockDiv ^= 0x1; + + // Pack into the SPISettings class + spcr = _BV(SPE) | _BV(MSTR) | ((bitOrder == LSBFIRST) ? _BV(DORD) : 0) | + (dataMode & SPI_MODE_MASK) | ((clockDiv >> 1) & SPI_CLOCK_MASK); + spsr = clockDiv & SPI_2XCLOCK_MASK; + } + uint8_t spcr; + uint8_t spsr; + friend class SPIClass; +}; + + +class SPIClass { +public: + // Initialize the SPI library + static void begin(); + + // If SPI is used from within an interrupt, this function registers + // that interrupt with the SPI library, so beginTransaction() can + // prevent conflicts. The input interruptNumber is the number used + // with attachInterrupt. If SPI is used from a different interrupt + // (eg, a timer), interruptNumber should be 255. + static void usingInterrupt(uint8_t interruptNumber); + // And this does the opposite. + static void notUsingInterrupt(uint8_t interruptNumber); + // Note: the usingInterrupt and notUsingInterrupt functions should + // not to be called from ISR context or inside a transaction. + // For details see: + // https://github.com/arduino/Arduino/pull/2381 + // https://github.com/arduino/Arduino/pull/2449 + + // Before using SPI.transfer() or asserting chip select pins, + // this function is used to gain exclusive access to the SPI bus + // and configure the correct settings. + inline static void beginTransaction(SPISettings settings) { + if (interruptMode > 0) { + uint8_t sreg = SREG; + noInterrupts(); + + #ifdef SPI_AVR_EIMSK + if (interruptMode == 1) { + interruptSave = SPI_AVR_EIMSK; + SPI_AVR_EIMSK &= ~interruptMask; + SREG = sreg; + } else + #endif + { + interruptSave = sreg; + } + } + + #ifdef SPI_TRANSACTION_MISMATCH_LED + if (inTransactionFlag) { + pinMode(SPI_TRANSACTION_MISMATCH_LED, OUTPUT); + digitalWrite(SPI_TRANSACTION_MISMATCH_LED, HIGH); + } + inTransactionFlag = 1; + #endif + + SPCR = settings.spcr; + SPSR = settings.spsr; + } + + // Write to the SPI bus (MOSI pin) and also receive (MISO pin) + inline static uint8_t transfer(uint8_t data) { + SPDR = data; + /* + * The following NOP introduces a small delay that can prevent the wait + * loop form iterating when running at the maximum speed. This gives + * about 10% more speed, even if it seems counter-intuitive. At lower + * speeds it is unnoticed. + */ + asm volatile("nop"); + while (!(SPSR & _BV(SPIF))) ; // wait + return SPDR; + } + inline static uint16_t transfer16(uint16_t data) { + union { uint16_t val; struct { uint8_t lsb; uint8_t msb; }; } in, out; + in.val = data; + if (!(SPCR & _BV(DORD))) { + SPDR = in.msb; + asm volatile("nop"); // See transfer(uint8_t) function + while (!(SPSR & _BV(SPIF))) ; + out.msb = SPDR; + SPDR = in.lsb; + asm volatile("nop"); + while (!(SPSR & _BV(SPIF))) ; + out.lsb = SPDR; + } else { + SPDR = in.lsb; + asm volatile("nop"); + while (!(SPSR & _BV(SPIF))) ; + out.lsb = SPDR; + SPDR = in.msb; + asm volatile("nop"); + while (!(SPSR & _BV(SPIF))) ; + out.msb = SPDR; + } + return out.val; + } + inline static void transfer(void *buf, size_t count) { + if (count == 0) return; + uint8_t *p = (uint8_t *)buf; + SPDR = *p; + while (--count > 0) { + uint8_t out = *(p + 1); + while (!(SPSR & _BV(SPIF))) ; + uint8_t in = SPDR; + SPDR = out; + *p++ = in; + } + while (!(SPSR & _BV(SPIF))) ; + *p = SPDR; + } + // After performing a group of transfers and releasing the chip select + // signal, this function allows others to access the SPI bus + inline static void endTransaction(void) { + #ifdef SPI_TRANSACTION_MISMATCH_LED + if (!inTransactionFlag) { + pinMode(SPI_TRANSACTION_MISMATCH_LED, OUTPUT); + digitalWrite(SPI_TRANSACTION_MISMATCH_LED, HIGH); + } + inTransactionFlag = 0; + #endif + + if (interruptMode > 0) { + #ifdef SPI_AVR_EIMSK + uint8_t sreg = SREG; + #endif + noInterrupts(); + #ifdef SPI_AVR_EIMSK + if (interruptMode == 1) { + SPI_AVR_EIMSK = interruptSave; + SREG = sreg; + } else + #endif + { + SREG = interruptSave; + } + } + } + + // Disable the SPI bus + static void end(); + + // This function is deprecated. New applications should use + // beginTransaction() to configure SPI settings. + inline static void setBitOrder(uint8_t bitOrder) { + if (bitOrder == LSBFIRST) SPCR |= _BV(DORD); + else SPCR &= ~(_BV(DORD)); + } + // This function is deprecated. New applications should use + // beginTransaction() to configure SPI settings. + inline static void setDataMode(uint8_t dataMode) { + SPCR = (SPCR & ~SPI_MODE_MASK) | dataMode; + } + // This function is deprecated. New applications should use + // beginTransaction() to configure SPI settings. + inline static void setClockDivider(uint8_t clockDiv) { + SPCR = (SPCR & ~SPI_CLOCK_MASK) | (clockDiv & SPI_CLOCK_MASK); + SPSR = (SPSR & ~SPI_2XCLOCK_MASK) | ((clockDiv >> 2) & SPI_2XCLOCK_MASK); + } + // These undocumented functions should not be used. SPI.transfer() + // polls the hardware flag which is automatically cleared as the + // AVR responds to SPI's interrupt + inline static void attachInterrupt() { SPCR |= _BV(SPIE); } + inline static void detachInterrupt() { SPCR &= ~_BV(SPIE); } + +private: + static uint8_t initialized; + static uint8_t interruptMode; // 0=none, 1=mask, 2=global + static uint8_t interruptMask; // which interrupts to mask + static uint8_t interruptSave; // temp storage, to restore state + #ifdef SPI_TRANSACTION_MISMATCH_LED + static uint8_t inTransactionFlag; + #endif +}; + +extern SPIClass SPI; + +#endif diff --git a/plugins/KeyboardioHID/avr/libraries/SPI/examples/BarometricPressureSensor/BarometricPressureSensor.ino b/plugins/KeyboardioHID/avr/libraries/SPI/examples/BarometricPressureSensor/BarometricPressureSensor.ino new file mode 100644 index 0000000000..8104fcbc25 --- /dev/null +++ b/plugins/KeyboardioHID/avr/libraries/SPI/examples/BarometricPressureSensor/BarometricPressureSensor.ino @@ -0,0 +1,143 @@ +/* + SCP1000 Barometric Pressure Sensor Display + + Shows the output of a Barometric Pressure Sensor on a + Uses the SPI library. For details on the sensor, see: + http://www.sparkfun.com/commerce/product_info.php?products_id=8161 + http://www.vti.fi/en/support/obsolete_products/pressure_sensors/ + + This sketch adapted from Nathan Seidle's SCP1000 example for PIC: + http://www.sparkfun.com/datasheets/Sensors/SCP1000-Testing.zip + + Circuit: + SCP1000 sensor attached to pins 6, 7, 10 - 13: + DRDY: pin 6 + CSB: pin 7 + MOSI: pin 11 + MISO: pin 12 + SCK: pin 13 + + created 31 July 2010 + modified 14 August 2010 + by Tom Igoe + */ + +// the sensor communicates using SPI, so include the library: +#include + +//Sensor's memory register addresses: +const int PRESSURE = 0x1F; //3 most significant bits of pressure +const int PRESSURE_LSB = 0x20; //16 least significant bits of pressure +const int TEMPERATURE = 0x21; //16 bit temperature reading +const byte READ = 0b11111100; // SCP1000's read command +const byte WRITE = 0b00000010; // SCP1000's write command + +// pins used for the connection with the sensor +// the other you need are controlled by the SPI library): +const int dataReadyPin = 6; +const int chipSelectPin = 7; + +void setup() { + Serial.begin(9600); + + // start the SPI library: + SPI.begin(); + + // initalize the data ready and chip select pins: + pinMode(dataReadyPin, INPUT); + pinMode(chipSelectPin, OUTPUT); + + //Configure SCP1000 for low noise configuration: + writeRegister(0x02, 0x2D); + writeRegister(0x01, 0x03); + writeRegister(0x03, 0x02); + // give the sensor time to set up: + delay(100); +} + +void loop() { + //Select High Resolution Mode + writeRegister(0x03, 0x0A); + + // don't do anything until the data ready pin is high: + if (digitalRead(dataReadyPin) == HIGH) { + //Read the temperature data + int tempData = readRegister(0x21, 2); + + // convert the temperature to celsius and display it: + float realTemp = (float)tempData / 20.0; + Serial.print("Temp[C]="); + Serial.print(realTemp); + + + //Read the pressure data highest 3 bits: + byte pressure_data_high = readRegister(0x1F, 1); + pressure_data_high &= 0b00000111; //you only needs bits 2 to 0 + + //Read the pressure data lower 16 bits: + unsigned int pressure_data_low = readRegister(0x20, 2); + //combine the two parts into one 19-bit number: + long pressure = ((pressure_data_high << 16) | pressure_data_low) / 4; + + // display the temperature: + Serial.println("\tPressure [Pa]=" + String(pressure)); + } +} + +//Read from or write to register from the SCP1000: +unsigned int readRegister(byte thisRegister, int bytesToRead ) { + byte inByte = 0; // incoming byte from the SPI + unsigned int result = 0; // result to return + Serial.print(thisRegister, BIN); + Serial.print("\t"); + // SCP1000 expects the register name in the upper 6 bits + // of the byte. So shift the bits left by two bits: + thisRegister = thisRegister << 2; + // now combine the address and the command into one byte + byte dataToSend = thisRegister & READ; + Serial.println(thisRegister, BIN); + // take the chip select low to select the device: + digitalWrite(chipSelectPin, LOW); + // send the device the register you want to read: + SPI.transfer(dataToSend); + // send a value of 0 to read the first byte returned: + result = SPI.transfer(0x00); + // decrement the number of bytes left to read: + bytesToRead--; + // if you still have another byte to read: + if (bytesToRead > 0) { + // shift the first byte left, then get the second byte: + result = result << 8; + inByte = SPI.transfer(0x00); + // combine the byte you just got with the previous one: + result = result | inByte; + // decrement the number of bytes left to read: + bytesToRead--; + } + // take the chip select high to de-select: + digitalWrite(chipSelectPin, HIGH); + // return the result: + return(result); +} + + +//Sends a write command to SCP1000 + +void writeRegister(byte thisRegister, byte thisValue) { + + // SCP1000 expects the register address in the upper 6 bits + // of the byte. So shift the bits left by two bits: + thisRegister = thisRegister << 2; + // now combine the register address and the command into one byte: + byte dataToSend = thisRegister | WRITE; + + // take the chip select low to select the device: + digitalWrite(chipSelectPin, LOW); + + SPI.transfer(dataToSend); //Send register location + SPI.transfer(thisValue); //Send value to record into register + + // take the chip select high to de-select: + digitalWrite(chipSelectPin, HIGH); +} + diff --git a/plugins/KeyboardioHID/avr/libraries/SPI/examples/DigitalPotControl/DigitalPotControl.ino b/plugins/KeyboardioHID/avr/libraries/SPI/examples/DigitalPotControl/DigitalPotControl.ino new file mode 100644 index 0000000000..b135a74f4e --- /dev/null +++ b/plugins/KeyboardioHID/avr/libraries/SPI/examples/DigitalPotControl/DigitalPotControl.ino @@ -0,0 +1,71 @@ +/* + Digital Pot Control + + This example controls an Analog Devices AD5206 digital potentiometer. + The AD5206 has 6 potentiometer channels. Each channel's pins are labeled + A - connect this to voltage + W - this is the pot's wiper, which changes when you set it + B - connect this to ground. + + The AD5206 is SPI-compatible,and to command it, you send two bytes, + one with the channel number (0 - 5) and one with the resistance value for the + channel (0 - 255). + + The circuit: + * All A pins of AD5206 connected to +5V + * All B pins of AD5206 connected to ground + * An LED and a 220-ohm resisor in series connected from each W pin to ground + * CS - to digital pin 10 (SS pin) + * SDI - to digital pin 11 (MOSI pin) + * CLK - to digital pin 13 (SCK pin) + + created 10 Aug 2010 + by Tom Igoe + + Thanks to Heather Dewey-Hagborg for the original tutorial, 2005 + +*/ + + +// inslude the SPI library: +#include + + +// set pin 10 as the slave select for the digital pot: +const int slaveSelectPin = 10; + +void setup() { + // set the slaveSelectPin as an output: + pinMode (slaveSelectPin, OUTPUT); + // initialize SPI: + SPI.begin(); +} + +void loop() { + // go through the six channels of the digital pot: + for (int channel = 0; channel < 6; channel++) { + // change the resistance on this channel from min to max: + for (int level = 0; level < 255; level++) { + digitalPotWrite(channel, level); + delay(10); + } + // wait a second at the top: + delay(100); + // change the resistance on this channel from max to min: + for (int level = 0; level < 255; level++) { + digitalPotWrite(channel, 255 - level); + delay(10); + } + } + +} + +void digitalPotWrite(int address, int value) { + // take the SS pin low to select the chip: + digitalWrite(slaveSelectPin, LOW); + // send in the address and value via SPI: + SPI.transfer(address); + SPI.transfer(value); + // take the SS pin high to de-select the chip: + digitalWrite(slaveSelectPin, HIGH); +} diff --git a/plugins/KeyboardioHID/avr/libraries/SPI/keywords.txt b/plugins/KeyboardioHID/avr/libraries/SPI/keywords.txt new file mode 100644 index 0000000000..fa7616581a --- /dev/null +++ b/plugins/KeyboardioHID/avr/libraries/SPI/keywords.txt @@ -0,0 +1,36 @@ +####################################### +# Syntax Coloring Map SPI +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +SPI KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### +begin KEYWORD2 +end KEYWORD2 +transfer KEYWORD2 +setBitOrder KEYWORD2 +setDataMode KEYWORD2 +setClockDivider KEYWORD2 + + +####################################### +# Constants (LITERAL1) +####################################### +SPI_CLOCK_DIV4 LITERAL1 +SPI_CLOCK_DIV16 LITERAL1 +SPI_CLOCK_DIV64 LITERAL1 +SPI_CLOCK_DIV128 LITERAL1 +SPI_CLOCK_DIV2 LITERAL1 +SPI_CLOCK_DIV8 LITERAL1 +SPI_CLOCK_DIV32 LITERAL1 +SPI_CLOCK_DIV64 LITERAL1 +SPI_MODE0 LITERAL1 +SPI_MODE1 LITERAL1 +SPI_MODE2 LITERAL1 +SPI_MODE3 LITERAL1 \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/libraries/SPI/library.properties b/plugins/KeyboardioHID/avr/libraries/SPI/library.properties new file mode 100644 index 0000000000..6f1ae2016d --- /dev/null +++ b/plugins/KeyboardioHID/avr/libraries/SPI/library.properties @@ -0,0 +1,8 @@ +name=SPI +version=1.0 +author=Arduino +maintainer=Arduino +sentence=Enables the communication with devices that use the Serial Peripheral Interface (SPI) Bus. For all Arduino boards, BUT Arduino DUE. +paragraph= +url=http://arduino.cc/en/Reference/SPI +architectures=avr diff --git a/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/SoftwareSerial.cpp b/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/SoftwareSerial.cpp new file mode 100644 index 0000000000..b28e6e4223 --- /dev/null +++ b/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/SoftwareSerial.cpp @@ -0,0 +1,486 @@ +/* +SoftwareSerial.cpp (formerly NewSoftSerial.cpp) - +Multi-instance software serial library for Arduino/Wiring +-- Interrupt-driven receive and other improvements by ladyada +(http://ladyada.net) +-- Tuning, circular buffer, derivation from class Print/Stream, +multi-instance support, porting to 8MHz processors, +various optimizations, PROGMEM delay tables, inverse logic and +direct port writing by Mikal Hart (http://www.arduiniana.org) +-- Pin change interrupt macros by Paul Stoffregen (http://www.pjrc.com) +-- 20MHz processor support by Garrett Mace (http://www.macetech.com) +-- ATmega1280/2560 support by Brett Hagman (http://www.roguerobotics.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 + +The latest version of this library can always be found at +http://arduiniana.org. +*/ + +// When set, _DEBUG co-opts pins 11 and 13 for debugging with an +// oscilloscope or logic analyzer. Beware: it also slightly modifies +// the bit times, so don't rely on it too much at high baud rates +#define _DEBUG 0 +#define _DEBUG_PIN1 11 +#define _DEBUG_PIN2 13 +// +// Includes +// +#include +#include +#include +#include +#include + +// +// Statics +// +SoftwareSerial *SoftwareSerial::active_object = 0; +char SoftwareSerial::_receive_buffer[_SS_MAX_RX_BUFF]; +volatile uint8_t SoftwareSerial::_receive_buffer_tail = 0; +volatile uint8_t SoftwareSerial::_receive_buffer_head = 0; + +// +// Debugging +// +// This function generates a brief pulse +// for debugging or measuring on an oscilloscope. +inline void DebugPulse(uint8_t pin, uint8_t count) +{ +#if _DEBUG + volatile uint8_t *pport = portOutputRegister(digitalPinToPort(pin)); + + uint8_t val = *pport; + while (count--) + { + *pport = val | digitalPinToBitMask(pin); + *pport = val; + } +#endif +} + +// +// Private methods +// + +/* static */ +inline void SoftwareSerial::tunedDelay(uint16_t delay) { + _delay_loop_2(delay); +} + +// This function sets the current object as the "listening" +// one and returns true if it replaces another +bool SoftwareSerial::listen() +{ + if (!_rx_delay_stopbit) + return false; + + if (active_object != this) + { + if (active_object) + active_object->stopListening(); + + _buffer_overflow = false; + _receive_buffer_head = _receive_buffer_tail = 0; + active_object = this; + + setRxIntMsk(true); + return true; + } + + return false; +} + +// Stop listening. Returns true if we were actually listening. +bool SoftwareSerial::stopListening() +{ + if (active_object == this) + { + setRxIntMsk(false); + active_object = NULL; + return true; + } + return false; +} + +// +// The receive routine called by the interrupt handler +// +void SoftwareSerial::recv() +{ + +#if GCC_VERSION < 40302 + // Work-around for avr-gcc 4.3.0 OSX version bug + // Preserve the registers that the compiler misses + // (courtesy of Arduino forum user *etracer*) + asm volatile( + "push r18 \n\t" + "push r19 \n\t" + "push r20 \n\t" + "push r21 \n\t" + "push r22 \n\t" + "push r23 \n\t" + "push r26 \n\t" + "push r27 \n\t" + ::); +#endif + + uint8_t d = 0; + + // If RX line is high, then we don't see any start bit + // so interrupt is probably not for us + if (_inverse_logic ? rx_pin_read() : !rx_pin_read()) + { + // Disable further interrupts during reception, this prevents + // triggering another interrupt directly after we return, which can + // cause problems at higher baudrates. + setRxIntMsk(false); + + // Wait approximately 1/2 of a bit width to "center" the sample + tunedDelay(_rx_delay_centering); + DebugPulse(_DEBUG_PIN2, 1); + + // Read each of the 8 bits + for (uint8_t i = 8; i > 0; --i) + { + tunedDelay(_rx_delay_intrabit); + d >>= 1; + DebugPulse(_DEBUG_PIN2, 1); + if (rx_pin_read()) + d |= 0x80; + } + + if (_inverse_logic) + d = ~d; + + // if buffer full, set the overflow flag and return + uint8_t next = (_receive_buffer_tail + 1) % _SS_MAX_RX_BUFF; + if (next != _receive_buffer_head) + { + // save new data in buffer: tail points to where byte goes + _receive_buffer[_receive_buffer_tail] = d; // save new byte + _receive_buffer_tail = next; + } + else + { + DebugPulse(_DEBUG_PIN1, 1); + _buffer_overflow = true; + } + + // skip the stop bit + tunedDelay(_rx_delay_stopbit); + DebugPulse(_DEBUG_PIN1, 1); + + // Re-enable interrupts when we're sure to be inside the stop bit + setRxIntMsk(true); + + } + +#if GCC_VERSION < 40302 + // Work-around for avr-gcc 4.3.0 OSX version bug + // Restore the registers that the compiler misses + asm volatile( + "pop r27 \n\t" + "pop r26 \n\t" + "pop r23 \n\t" + "pop r22 \n\t" + "pop r21 \n\t" + "pop r20 \n\t" + "pop r19 \n\t" + "pop r18 \n\t" + ::); +#endif +} + +uint8_t SoftwareSerial::rx_pin_read() +{ + return *_receivePortRegister & _receiveBitMask; +} + +// +// Interrupt handling +// + +/* static */ +inline void SoftwareSerial::handle_interrupt() +{ + if (active_object) + { + active_object->recv(); + } +} + +#if defined(PCINT0_vect) +ISR(PCINT0_vect) +{ + SoftwareSerial::handle_interrupt(); +} +#endif + +#if defined(PCINT1_vect) +ISR(PCINT1_vect, ISR_ALIASOF(PCINT0_vect)); +#endif + +#if defined(PCINT2_vect) +ISR(PCINT2_vect, ISR_ALIASOF(PCINT0_vect)); +#endif + +#if defined(PCINT3_vect) +ISR(PCINT3_vect, ISR_ALIASOF(PCINT0_vect)); +#endif + +// +// Constructor +// +SoftwareSerial::SoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic /* = false */) : +_rx_delay_centering(0), +_rx_delay_intrabit(0), +_rx_delay_stopbit(0), +_tx_delay(0), +_buffer_overflow(false), +_inverse_logic(inverse_logic) +{ + setTX(transmitPin); + setRX(receivePin); +} + +// +// Destructor +// +SoftwareSerial::~SoftwareSerial() +{ + end(); +} + +void SoftwareSerial::setTX(uint8_t tx) +{ + pinMode(tx, OUTPUT); + digitalWrite(tx, HIGH); + _transmitBitMask = digitalPinToBitMask(tx); + uint8_t port = digitalPinToPort(tx); + _transmitPortRegister = portOutputRegister(port); +} + +void SoftwareSerial::setRX(uint8_t rx) +{ + pinMode(rx, INPUT); + if (!_inverse_logic) + digitalWrite(rx, HIGH); // pullup for normal logic! + _receivePin = rx; + _receiveBitMask = digitalPinToBitMask(rx); + uint8_t port = digitalPinToPort(rx); + _receivePortRegister = portInputRegister(port); +} + +uint16_t SoftwareSerial::subtract_cap(uint16_t num, uint16_t sub) { + if (num > sub) + return num - sub; + else + return 1; +} + +// +// Public methods +// + +void SoftwareSerial::begin(long speed) +{ + _rx_delay_centering = _rx_delay_intrabit = _rx_delay_stopbit = _tx_delay = 0; + + // Precalculate the various delays, in number of 4-cycle delays + uint16_t bit_delay = (F_CPU / speed) / 4; + + // 12 (gcc 4.8.2) or 13 (gcc 4.3.2) cycles from start bit to first bit, + // 15 (gcc 4.8.2) or 16 (gcc 4.3.2) cycles between bits, + // 12 (gcc 4.8.2) or 14 (gcc 4.3.2) cycles from last bit to stop bit + // These are all close enough to just use 15 cycles, since the inter-bit + // timings are the most critical (deviations stack 8 times) + _tx_delay = subtract_cap(bit_delay, 15 / 4); + + // Only setup rx when we have a valid PCINT for this pin + if (digitalPinToPCICR(_receivePin)) { +#if GCC_VERSION > 40800 + // Timings counted from gcc 4.8.2 output. This works up to 115200 on + // 16Mhz and 57600 on 8Mhz. + // + // When the start bit occurs, there are 3 or 4 cycles before the + // interrupt flag is set, 4 cycles before the PC is set to the right + // interrupt vector address and the old PC is pushed on the stack, + // and then 75 cycles of instructions (including the RJMP in the + // ISR vector table) until the first delay. After the delay, there + // are 17 more cycles until the pin value is read (excluding the + // delay in the loop). + // We want to have a total delay of 1.5 bit time. Inside the loop, + // we already wait for 1 bit time - 23 cycles, so here we wait for + // 0.5 bit time - (71 + 18 - 22) cycles. + _rx_delay_centering = subtract_cap(bit_delay / 2, (4 + 4 + 75 + 17 - 23) / 4); + + // There are 23 cycles in each loop iteration (excluding the delay) + _rx_delay_intrabit = subtract_cap(bit_delay, 23 / 4); + + // There are 37 cycles from the last bit read to the start of + // stopbit delay and 11 cycles from the delay until the interrupt + // mask is enabled again (which _must_ happen during the stopbit). + // This delay aims at 3/4 of a bit time, meaning the end of the + // delay will be at 1/4th of the stopbit. This allows some extra + // time for ISR cleanup, which makes 115200 baud at 16Mhz work more + // reliably + _rx_delay_stopbit = subtract_cap(bit_delay * 3 / 4, (37 + 11) / 4); +#else // Timings counted from gcc 4.3.2 output + // Note that this code is a _lot_ slower, mostly due to bad register + // allocation choices of gcc. This works up to 57600 on 16Mhz and + // 38400 on 8Mhz. + _rx_delay_centering = subtract_cap(bit_delay / 2, (4 + 4 + 97 + 29 - 11) / 4); + _rx_delay_intrabit = subtract_cap(bit_delay, 11 / 4); + _rx_delay_stopbit = subtract_cap(bit_delay * 3 / 4, (44 + 17) / 4); +#endif + + + // Enable the PCINT for the entire port here, but never disable it + // (others might also need it, so we disable the interrupt by using + // the per-pin PCMSK register). + *digitalPinToPCICR(_receivePin) |= _BV(digitalPinToPCICRbit(_receivePin)); + // Precalculate the pcint mask register and value, so setRxIntMask + // can be used inside the ISR without costing too much time. + _pcint_maskreg = digitalPinToPCMSK(_receivePin); + _pcint_maskvalue = _BV(digitalPinToPCMSKbit(_receivePin)); + + tunedDelay(_tx_delay); // if we were low this establishes the end + } + +#if _DEBUG + pinMode(_DEBUG_PIN1, OUTPUT); + pinMode(_DEBUG_PIN2, OUTPUT); +#endif + + listen(); +} + +void SoftwareSerial::setRxIntMsk(bool enable) +{ + if (enable) + *_pcint_maskreg |= _pcint_maskvalue; + else + *_pcint_maskreg &= ~_pcint_maskvalue; +} + +void SoftwareSerial::end() +{ + stopListening(); +} + + +// Read data from buffer +int SoftwareSerial::read() +{ + if (!isListening()) + return -1; + + // Empty buffer? + if (_receive_buffer_head == _receive_buffer_tail) + return -1; + + // Read from "head" + uint8_t d = _receive_buffer[_receive_buffer_head]; // grab next byte + _receive_buffer_head = (_receive_buffer_head + 1) % _SS_MAX_RX_BUFF; + return d; +} + +int SoftwareSerial::available() +{ + if (!isListening()) + return 0; + + return (_receive_buffer_tail + _SS_MAX_RX_BUFF - _receive_buffer_head) % _SS_MAX_RX_BUFF; +} + +size_t SoftwareSerial::write(uint8_t b) +{ + if (_tx_delay == 0) { + setWriteError(); + return 0; + } + + // By declaring these as local variables, the compiler will put them + // in registers _before_ disabling interrupts and entering the + // critical timing sections below, which makes it a lot easier to + // verify the cycle timings + volatile uint8_t *reg = _transmitPortRegister; + uint8_t reg_mask = _transmitBitMask; + uint8_t inv_mask = ~_transmitBitMask; + uint8_t oldSREG = SREG; + bool inv = _inverse_logic; + uint16_t delay = _tx_delay; + + if (inv) + b = ~b; + + cli(); // turn off interrupts for a clean txmit + + // Write the start bit + if (inv) + *reg |= reg_mask; + else + *reg &= inv_mask; + + tunedDelay(delay); + + // Write each of the 8 bits + for (uint8_t i = 8; i > 0; --i) + { + if (b & 1) // choose bit + *reg |= reg_mask; // send 1 + else + *reg &= inv_mask; // send 0 + + tunedDelay(delay); + b >>= 1; + } + + // restore pin to natural state + if (inv) + *reg &= inv_mask; + else + *reg |= reg_mask; + + SREG = oldSREG; // turn interrupts back on + tunedDelay(_tx_delay); + + return 1; +} + +void SoftwareSerial::flush() +{ + if (!isListening()) + return; + + uint8_t oldSREG = SREG; + cli(); + _receive_buffer_head = _receive_buffer_tail = 0; + SREG = oldSREG; +} + +int SoftwareSerial::peek() +{ + if (!isListening()) + return -1; + + // Empty buffer? + if (_receive_buffer_head == _receive_buffer_tail) + return -1; + + // Read from "head" + return _receive_buffer[_receive_buffer_head]; +} diff --git a/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/SoftwareSerial.h b/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/SoftwareSerial.h new file mode 100644 index 0000000000..a3f155d626 --- /dev/null +++ b/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/SoftwareSerial.h @@ -0,0 +1,120 @@ +/* +SoftwareSerial.h (formerly NewSoftSerial.h) - +Multi-instance software serial library for Arduino/Wiring +-- Interrupt-driven receive and other improvements by ladyada +(http://ladyada.net) +-- Tuning, circular buffer, derivation from class Print/Stream, +multi-instance support, porting to 8MHz processors, +various optimizations, PROGMEM delay tables, inverse logic and +direct port writing by Mikal Hart (http://www.arduiniana.org) +-- Pin change interrupt macros by Paul Stoffregen (http://www.pjrc.com) +-- 20MHz processor support by Garrett Mace (http://www.macetech.com) +-- ATmega1280/2560 support by Brett Hagman (http://www.roguerobotics.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 + +The latest version of this library can always be found at +http://arduiniana.org. +*/ + +#ifndef SoftwareSerial_h +#define SoftwareSerial_h + +#include +#include + +/****************************************************************************** +* Definitions +******************************************************************************/ + +#define _SS_MAX_RX_BUFF 64 // RX buffer size +#ifndef GCC_VERSION +#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) +#endif + +class SoftwareSerial : public Stream +{ +private: + // per object data + uint8_t _receivePin; + uint8_t _receiveBitMask; + volatile uint8_t *_receivePortRegister; + uint8_t _transmitBitMask; + volatile uint8_t *_transmitPortRegister; + volatile uint8_t *_pcint_maskreg; + uint8_t _pcint_maskvalue; + + // Expressed as 4-cycle delays (must never be 0!) + uint16_t _rx_delay_centering; + uint16_t _rx_delay_intrabit; + uint16_t _rx_delay_stopbit; + uint16_t _tx_delay; + + uint16_t _buffer_overflow : 1; + uint16_t _inverse_logic : 1; + + // static data + static char _receive_buffer[_SS_MAX_RX_BUFF]; + static volatile uint8_t _receive_buffer_tail; + static volatile uint8_t _receive_buffer_head; + static SoftwareSerial *active_object; + + // private methods + void recv() __attribute__((__always_inline__)); + uint8_t rx_pin_read(); + void tx_pin_write(uint8_t pin_state) __attribute__((__always_inline__)); + void setTX(uint8_t transmitPin); + void setRX(uint8_t receivePin); + void setRxIntMsk(bool enable) __attribute__((__always_inline__)); + + // Return num - sub, or 1 if the result would be < 1 + static uint16_t subtract_cap(uint16_t num, uint16_t sub); + + // private static method for timing + static inline void tunedDelay(uint16_t delay); + +public: + // public methods + SoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic = false); + ~SoftwareSerial(); + void begin(long speed); + bool listen(); + void end(); + bool isListening() { return this == active_object; } + bool stopListening(); + bool overflow() { bool ret = _buffer_overflow; if (ret) _buffer_overflow = false; return ret; } + int peek(); + + virtual size_t write(uint8_t byte); + virtual int read(); + virtual int available(); + virtual void flush(); + + using Print::write; + + // public only for easy access by interrupt handlers + static inline void handle_interrupt() __attribute__((__always_inline__)); +}; + +// Arduino 0012 workaround +#undef int +#undef char +#undef long +#undef byte +#undef float +#undef abs +#undef round + +#endif diff --git a/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/examples/SoftwareSerialExample/SoftwareSerialExample.ino b/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/examples/SoftwareSerialExample/SoftwareSerialExample.ino new file mode 100644 index 0000000000..f659133010 --- /dev/null +++ b/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/examples/SoftwareSerialExample/SoftwareSerialExample.ino @@ -0,0 +1,55 @@ +/* + Software serial multple serial test + + Receives from the hardware serial, sends to software serial. + Receives from software serial, sends to hardware serial. + + The circuit: + * RX is digital pin 10 (connect to TX of other device) + * TX is digital pin 11 (connect to RX of other device) + + Note: + Not all pins on the Mega and Mega 2560 support change interrupts, + so only the following can be used for RX: + 10, 11, 12, 13, 50, 51, 52, 53, 62, 63, 64, 65, 66, 67, 68, 69 + + Not all pins on the Leonardo support change interrupts, + so only the following can be used for RX: + 8, 9, 10, 11, 14 (MISO), 15 (SCK), 16 (MOSI). + + created back in the mists of time + modified 25 May 2012 + by Tom Igoe + based on Mikal Hart's example + + This example code is in the public domain. + + */ +#include + +SoftwareSerial mySerial(10, 11); // RX, TX + +void setup() +{ + // Open serial communications and wait for port to open: + Serial.begin(57600); + while (!Serial) { + ; // wait for serial port to connect. Needed for Leonardo only + } + + + Serial.println("Goodnight moon!"); + + // set the data rate for the SoftwareSerial port + mySerial.begin(4800); + mySerial.println("Hello, world?"); +} + +void loop() // run over and over +{ + if (mySerial.available()) + Serial.write(mySerial.read()); + if (Serial.available()) + mySerial.write(Serial.read()); +} + diff --git a/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/examples/TwoPortReceive/TwoPortReceive.ino b/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/examples/TwoPortReceive/TwoPortReceive.ino new file mode 100644 index 0000000000..95881a6c41 --- /dev/null +++ b/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/examples/TwoPortReceive/TwoPortReceive.ino @@ -0,0 +1,93 @@ +/* + Software serial multple serial test + + Receives from the two software serial ports, + sends to the hardware serial port. + + In order to listen on a software port, you call port.listen(). + When using two software serial ports, you have to switch ports + by listen()ing on each one in turn. Pick a logical time to switch + ports, like the end of an expected transmission, or when the + buffer is empty. This example switches ports when there is nothing + more to read from a port + + The circuit: + Two devices which communicate serially are needed. + * First serial device's TX attached to digital pin 2, RX to pin 3 + * Second serial device's TX attached to digital pin 4, RX to pin 5 + + Note: + Not all pins on the Mega and Mega 2560 support change interrupts, + so only the following can be used for RX: + 10, 11, 12, 13, 50, 51, 52, 53, 62, 63, 64, 65, 66, 67, 68, 69 + + Not all pins on the Leonardo support change interrupts, + so only the following can be used for RX: + 8, 9, 10, 11, 14 (MISO), 15 (SCK), 16 (MOSI). + + created 18 Apr. 2011 + modified 25 May 2012 + by Tom Igoe + based on Mikal Hart's twoPortRXExample + + This example code is in the public domain. + + */ + +#include +// software serial #1: TX = digital pin 10, RX = digital pin 11 +SoftwareSerial portOne(10, 11); + +// software serial #2: TX = digital pin 8, RX = digital pin 9 +// on the Mega, use other pins instead, since 8 and 9 don't work on the Mega +SoftwareSerial portTwo(8, 9); + +void setup() +{ + // Open serial communications and wait for port to open: + Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for Leonardo only + } + + + // Start each software serial port + portOne.begin(9600); + portTwo.begin(9600); +} + +void loop() +{ + // By default, the last intialized port is listening. + // when you want to listen on a port, explicitly select it: + portOne.listen(); + Serial.println("Data from port one:"); + // while there is data coming in, read it + // and send to the hardware serial port: + while (portOne.available() > 0) { + char inByte = portOne.read(); + Serial.write(inByte); + } + + // blank line to separate data from the two ports: + Serial.println(); + + // Now listen on the second port + portTwo.listen(); + // while there is data coming in, read it + // and send to the hardware serial port: + Serial.println("Data from port two:"); + while (portTwo.available() > 0) { + char inByte = portTwo.read(); + Serial.write(inByte); + } + + // blank line to separate data from the two ports: + Serial.println(); +} + + + + + + diff --git a/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/keywords.txt b/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/keywords.txt new file mode 100644 index 0000000000..aaea17c202 --- /dev/null +++ b/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/keywords.txt @@ -0,0 +1,30 @@ +####################################### +# Syntax Coloring Map for SoftwareSerial +# (formerly NewSoftSerial) +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +SoftwareSerial KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +begin KEYWORD2 +end KEYWORD2 +read KEYWORD2 +write KEYWORD2 +available KEYWORD2 +isListening KEYWORD2 +overflow KEYWORD2 +flush KEYWORD2 +listen KEYWORD2 +peek KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### + diff --git a/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/library.properties b/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/library.properties new file mode 100644 index 0000000000..a69b54df06 --- /dev/null +++ b/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/library.properties @@ -0,0 +1,8 @@ +name=SoftwareSerial +version=1.0 +author=Arduino +maintainer=Arduino +sentence=Enables serial communication on digital pins. For all Arduino boards, BUT Arduino DUE. +paragraph= +url=http://arduino.cc/en/Reference/SoftwareSerial +architectures=avr diff --git a/plugins/KeyboardioHID/avr/libraries/Wire/Wire.cpp b/plugins/KeyboardioHID/avr/libraries/Wire/Wire.cpp new file mode 100644 index 0000000000..553add7822 --- /dev/null +++ b/plugins/KeyboardioHID/avr/libraries/Wire/Wire.cpp @@ -0,0 +1,303 @@ +/* + TwoWire.cpp - TWI/I2C library for Wiring & Arduino + 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 2012 by Todd Krein (todd@krein.org) to implement repeated starts +*/ + +extern "C" { + #include + #include + #include + #include "twi.h" +} + +#include "Wire.h" + +// Initialize Class Variables ////////////////////////////////////////////////// + +uint8_t TwoWire::rxBuffer[BUFFER_LENGTH]; +uint8_t TwoWire::rxBufferIndex = 0; +uint8_t TwoWire::rxBufferLength = 0; + +uint8_t TwoWire::txAddress = 0; +uint8_t TwoWire::txBuffer[BUFFER_LENGTH]; +uint8_t TwoWire::txBufferIndex = 0; +uint8_t TwoWire::txBufferLength = 0; + +uint8_t TwoWire::transmitting = 0; +void (*TwoWire::user_onRequest)(void); +void (*TwoWire::user_onReceive)(int); + +// Constructors //////////////////////////////////////////////////////////////// + +TwoWire::TwoWire() +{ +} + +// Public Methods ////////////////////////////////////////////////////////////// + +void TwoWire::begin(void) +{ + rxBufferIndex = 0; + rxBufferLength = 0; + + txBufferIndex = 0; + txBufferLength = 0; + + twi_init(); +} + +void TwoWire::begin(uint8_t address) +{ + twi_setAddress(address); + twi_attachSlaveTxEvent(onRequestService); + twi_attachSlaveRxEvent(onReceiveService); + begin(); +} + +void TwoWire::begin(int address) +{ + begin((uint8_t)address); +} + +void TwoWire::setClock(uint32_t frequency) +{ + TWBR = ((F_CPU / frequency) - 16) / 2; +} + +uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop) +{ + // clamp to buffer length + if(quantity > BUFFER_LENGTH){ + quantity = BUFFER_LENGTH; + } + // perform blocking read into buffer + uint8_t read = twi_readFrom(address, rxBuffer, quantity, sendStop); + // set rx buffer iterator vars + rxBufferIndex = 0; + rxBufferLength = read; + + return read; +} + +uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity) +{ + return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true); +} + +uint8_t TwoWire::requestFrom(int address, int quantity) +{ + return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true); +} + +uint8_t TwoWire::requestFrom(int address, int quantity, int sendStop) +{ + return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)sendStop); +} + +void TwoWire::beginTransmission(uint8_t address) +{ + // indicate that we are transmitting + transmitting = 1; + // set address of targeted slave + txAddress = address; + // reset tx buffer iterator vars + txBufferIndex = 0; + txBufferLength = 0; +} + +void TwoWire::beginTransmission(int address) +{ + beginTransmission((uint8_t)address); +} + +// +// Originally, 'endTransmission' was an f(void) function. +// It has been modified to take one parameter indicating +// whether or not a STOP should be performed on the bus. +// Calling endTransmission(false) allows a sketch to +// perform a repeated start. +// +// WARNING: Nothing in the library keeps track of whether +// the bus tenure has been properly ended with a STOP. It +// is very possible to leave the bus in a hung state if +// no call to endTransmission(true) is made. Some I2C +// devices will behave oddly if they do not see a STOP. +// +uint8_t TwoWire::endTransmission(uint8_t sendStop) +{ + // transmit buffer (blocking) + int8_t ret = twi_writeTo(txAddress, txBuffer, txBufferLength, 1, sendStop); + // reset tx buffer iterator vars + txBufferIndex = 0; + txBufferLength = 0; + // indicate that we are done transmitting + transmitting = 0; + return ret; +} + +// This provides backwards compatibility with the original +// definition, and expected behaviour, of endTransmission +// +uint8_t TwoWire::endTransmission(void) +{ + return endTransmission(true); +} + +// must be called in: +// slave tx event callback +// or after beginTransmission(address) +size_t TwoWire::write(uint8_t data) +{ + if(transmitting){ + // in master transmitter mode + // don't bother if buffer is full + if(txBufferLength >= BUFFER_LENGTH){ + setWriteError(); + return 0; + } + // put byte in tx buffer + txBuffer[txBufferIndex] = data; + ++txBufferIndex; + // update amount in buffer + txBufferLength = txBufferIndex; + }else{ + // in slave send mode + // reply to master + twi_transmit(&data, 1); + } + return 1; +} + +// must be called in: +// slave tx event callback +// or after beginTransmission(address) +size_t TwoWire::write(const uint8_t *data, size_t quantity) +{ + if(transmitting){ + // in master transmitter mode + for(size_t i = 0; i < quantity; ++i){ + write(data[i]); + } + }else{ + // in slave send mode + // reply to master + twi_transmit(data, quantity); + } + return quantity; +} + +// must be called in: +// slave rx event callback +// or after requestFrom(address, numBytes) +int TwoWire::available(void) +{ + return rxBufferLength - rxBufferIndex; +} + +// must be called in: +// slave rx event callback +// or after requestFrom(address, numBytes) +int TwoWire::read(void) +{ + int value = -1; + + // get each successive byte on each call + if(rxBufferIndex < rxBufferLength){ + value = rxBuffer[rxBufferIndex]; + ++rxBufferIndex; + } + + return value; +} + +// must be called in: +// slave rx event callback +// or after requestFrom(address, numBytes) +int TwoWire::peek(void) +{ + int value = -1; + + if(rxBufferIndex < rxBufferLength){ + value = rxBuffer[rxBufferIndex]; + } + + return value; +} + +void TwoWire::flush(void) +{ + // XXX: to be implemented. +} + +// behind the scenes function that is called when data is received +void TwoWire::onReceiveService(uint8_t* inBytes, int numBytes) +{ + // don't bother if user hasn't registered a callback + if(!user_onReceive){ + return; + } + // don't bother if rx buffer is in use by a master requestFrom() op + // i know this drops data, but it allows for slight stupidity + // meaning, they may not have read all the master requestFrom() data yet + if(rxBufferIndex < rxBufferLength){ + return; + } + // copy twi rx buffer into local read buffer + // this enables new reads to happen in parallel + for(uint8_t i = 0; i < numBytes; ++i){ + rxBuffer[i] = inBytes[i]; + } + // set rx iterator vars + rxBufferIndex = 0; + rxBufferLength = numBytes; + // alert user program + user_onReceive(numBytes); +} + +// behind the scenes function that is called when data is requested +void TwoWire::onRequestService(void) +{ + // don't bother if user hasn't registered a callback + if(!user_onRequest){ + return; + } + // reset tx buffer iterator vars + // !!! this will kill any pending pre-master sendTo() activity + txBufferIndex = 0; + txBufferLength = 0; + // alert user program + user_onRequest(); +} + +// sets function called on slave write +void TwoWire::onReceive( void (*function)(int) ) +{ + user_onReceive = function; +} + +// sets function called on slave read +void TwoWire::onRequest( void (*function)(void) ) +{ + user_onRequest = function; +} + +// Preinstantiate Objects ////////////////////////////////////////////////////// + +TwoWire Wire = TwoWire(); + diff --git a/plugins/KeyboardioHID/avr/libraries/Wire/Wire.h b/plugins/KeyboardioHID/avr/libraries/Wire/Wire.h new file mode 100644 index 0000000000..732bdc314e --- /dev/null +++ b/plugins/KeyboardioHID/avr/libraries/Wire/Wire.h @@ -0,0 +1,80 @@ +/* + TwoWire.h - TWI/I2C library for Arduino & 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 2012 by Todd Krein (todd@krein.org) to implement repeated starts +*/ + +#ifndef TwoWire_h +#define TwoWire_h + +#include +#include "Stream.h" + +#define BUFFER_LENGTH 32 + +class TwoWire : public Stream +{ + private: + static uint8_t rxBuffer[]; + static uint8_t rxBufferIndex; + static uint8_t rxBufferLength; + + static uint8_t txAddress; + static uint8_t txBuffer[]; + static uint8_t txBufferIndex; + static uint8_t txBufferLength; + + static uint8_t transmitting; + static void (*user_onRequest)(void); + static void (*user_onReceive)(int); + static void onRequestService(void); + static void onReceiveService(uint8_t*, int); + public: + TwoWire(); + void begin(); + void begin(uint8_t); + void begin(int); + void setClock(uint32_t); + void beginTransmission(uint8_t); + void beginTransmission(int); + uint8_t endTransmission(void); + uint8_t endTransmission(uint8_t); + uint8_t requestFrom(uint8_t, uint8_t); + uint8_t requestFrom(uint8_t, uint8_t, uint8_t); + uint8_t requestFrom(int, int); + uint8_t requestFrom(int, int, int); + virtual size_t write(uint8_t); + virtual size_t write(const uint8_t *, size_t); + virtual int available(void); + virtual int read(void); + virtual int peek(void); + virtual void flush(void); + void onReceive( void (*)(int) ); + void onRequest( void (*)(void) ); + + inline size_t write(unsigned long n) { return write((uint8_t)n); } + inline size_t write(long n) { return write((uint8_t)n); } + inline size_t write(unsigned int n) { return write((uint8_t)n); } + inline size_t write(int n) { return write((uint8_t)n); } + using Print::write; +}; + +extern TwoWire Wire; + +#endif + diff --git a/plugins/KeyboardioHID/avr/libraries/Wire/examples/SFRRanger_reader/SFRRanger_reader.ino b/plugins/KeyboardioHID/avr/libraries/Wire/examples/SFRRanger_reader/SFRRanger_reader.ino new file mode 100644 index 0000000000..d97a9e3cf8 --- /dev/null +++ b/plugins/KeyboardioHID/avr/libraries/Wire/examples/SFRRanger_reader/SFRRanger_reader.ino @@ -0,0 +1,87 @@ +// I2C SRF10 or SRF08 Devantech Ultrasonic Ranger Finder +// by Nicholas Zambetti +// and James Tichenor + +// Demonstrates use of the Wire library reading data from the +// Devantech Utrasonic Rangers SFR08 and SFR10 + +// Created 29 April 2006 + +// This example code is in the public domain. + + +#include + +void setup() +{ + Wire.begin(); // join i2c bus (address optional for master) + Serial.begin(9600); // start serial communication at 9600bps +} + +int reading = 0; + +void loop() +{ + // step 1: instruct sensor to read echoes + Wire.beginTransmission(112); // transmit to device #112 (0x70) + // the address specified in the datasheet is 224 (0xE0) + // but i2c adressing uses the high 7 bits so it's 112 + Wire.write(byte(0x00)); // sets register pointer to the command register (0x00) + Wire.write(byte(0x50)); // command sensor to measure in "inches" (0x50) + // use 0x51 for centimeters + // use 0x52 for ping microseconds + Wire.endTransmission(); // stop transmitting + + // step 2: wait for readings to happen + delay(70); // datasheet suggests at least 65 milliseconds + + // step 3: instruct sensor to return a particular echo reading + Wire.beginTransmission(112); // transmit to device #112 + Wire.write(byte(0x02)); // sets register pointer to echo #1 register (0x02) + Wire.endTransmission(); // stop transmitting + + // step 4: request reading from sensor + Wire.requestFrom(112, 2); // request 2 bytes from slave device #112 + + // step 5: receive reading from sensor + if (2 <= Wire.available()) // if two bytes were received + { + reading = Wire.read(); // receive high byte (overwrites previous reading) + reading = reading << 8; // shift high byte to be high 8 bits + reading |= Wire.read(); // receive low byte as lower 8 bits + Serial.println(reading); // print the reading + } + + delay(250); // wait a bit since people have to read the output :) +} + + +/* + +// The following code changes the address of a Devantech Ultrasonic Range Finder (SRF10 or SRF08) +// usage: changeAddress(0x70, 0xE6); + +void changeAddress(byte oldAddress, byte newAddress) +{ + Wire.beginTransmission(oldAddress); + Wire.write(byte(0x00)); + Wire.write(byte(0xA0)); + Wire.endTransmission(); + + Wire.beginTransmission(oldAddress); + Wire.write(byte(0x00)); + Wire.write(byte(0xAA)); + Wire.endTransmission(); + + Wire.beginTransmission(oldAddress); + Wire.write(byte(0x00)); + Wire.write(byte(0xA5)); + Wire.endTransmission(); + + Wire.beginTransmission(oldAddress); + Wire.write(byte(0x00)); + Wire.write(newAddress); + Wire.endTransmission(); +} + +*/ diff --git a/plugins/KeyboardioHID/avr/libraries/Wire/examples/digital_potentiometer/digital_potentiometer.ino b/plugins/KeyboardioHID/avr/libraries/Wire/examples/digital_potentiometer/digital_potentiometer.ino new file mode 100644 index 0000000000..4d1580a61e --- /dev/null +++ b/plugins/KeyboardioHID/avr/libraries/Wire/examples/digital_potentiometer/digital_potentiometer.ino @@ -0,0 +1,39 @@ +// I2C Digital Potentiometer +// by Nicholas Zambetti +// and Shawn Bonkowski + +// Demonstrates use of the Wire library +// Controls AD5171 digital potentiometer via I2C/TWI + +// Created 31 March 2006 + +// This example code is in the public domain. + +// This example code is in the public domain. + + +#include + +void setup() +{ + Wire.begin(); // join i2c bus (address optional for master) +} + +byte val = 0; + +void loop() +{ + Wire.beginTransmission(44); // transmit to device #44 (0x2c) + // device address is specified in datasheet + Wire.write(byte(0x00)); // sends instruction byte + Wire.write(val); // sends potentiometer value byte + Wire.endTransmission(); // stop transmitting + + val++; // increment value + if (val == 64) // if reached 64th position (max) + { + val = 0; // start over from lowest value + } + delay(500); +} + diff --git a/plugins/KeyboardioHID/avr/libraries/Wire/examples/master_reader/master_reader.ino b/plugins/KeyboardioHID/avr/libraries/Wire/examples/master_reader/master_reader.ino new file mode 100644 index 0000000000..74f0155f8e --- /dev/null +++ b/plugins/KeyboardioHID/avr/libraries/Wire/examples/master_reader/master_reader.ino @@ -0,0 +1,32 @@ +// Wire Master Reader +// by Nicholas Zambetti + +// Demonstrates use of the Wire library +// Reads data from an I2C/TWI slave device +// Refer to the "Wire Slave Sender" example for use with this + +// Created 29 March 2006 + +// This example code is in the public domain. + + +#include + +void setup() +{ + Wire.begin(); // join i2c bus (address optional for master) + Serial.begin(9600); // start serial for output +} + +void loop() +{ + Wire.requestFrom(2, 6); // request 6 bytes from slave device #2 + + while (Wire.available()) // slave may send less than requested + { + char c = Wire.read(); // receive a byte as character + Serial.print(c); // print the character + } + + delay(500); +} diff --git a/plugins/KeyboardioHID/avr/libraries/Wire/examples/master_writer/master_writer.ino b/plugins/KeyboardioHID/avr/libraries/Wire/examples/master_writer/master_writer.ino new file mode 100644 index 0000000000..482e922379 --- /dev/null +++ b/plugins/KeyboardioHID/avr/libraries/Wire/examples/master_writer/master_writer.ino @@ -0,0 +1,31 @@ +// Wire Master Writer +// by Nicholas Zambetti + +// Demonstrates use of the Wire library +// Writes data to an I2C/TWI slave device +// Refer to the "Wire Slave Receiver" example for use with this + +// Created 29 March 2006 + +// This example code is in the public domain. + + +#include + +void setup() +{ + Wire.begin(); // join i2c bus (address optional for master) +} + +byte x = 0; + +void loop() +{ + Wire.beginTransmission(4); // transmit to device #4 + Wire.write("x is "); // sends five bytes + Wire.write(x); // sends one byte + Wire.endTransmission(); // stop transmitting + + x++; + delay(500); +} diff --git a/plugins/KeyboardioHID/avr/libraries/Wire/examples/slave_receiver/slave_receiver.ino b/plugins/KeyboardioHID/avr/libraries/Wire/examples/slave_receiver/slave_receiver.ino new file mode 100644 index 0000000000..15eff9a545 --- /dev/null +++ b/plugins/KeyboardioHID/avr/libraries/Wire/examples/slave_receiver/slave_receiver.ino @@ -0,0 +1,38 @@ +// Wire Slave Receiver +// by Nicholas Zambetti + +// Demonstrates use of the Wire library +// Receives data as an I2C/TWI slave device +// Refer to the "Wire Master Writer" example for use with this + +// Created 29 March 2006 + +// This example code is in the public domain. + + +#include + +void setup() +{ + Wire.begin(4); // join i2c bus with address #4 + Wire.onReceive(receiveEvent); // register event + Serial.begin(9600); // start serial for output +} + +void loop() +{ + delay(100); +} + +// function that executes whenever data is received from master +// this function is registered as an event, see setup() +void receiveEvent(int howMany) +{ + while (1 < Wire.available()) // loop through all but the last + { + char c = Wire.read(); // receive byte as a character + Serial.print(c); // print the character + } + int x = Wire.read(); // receive byte as an integer + Serial.println(x); // print the integer +} diff --git a/plugins/KeyboardioHID/avr/libraries/Wire/examples/slave_sender/slave_sender.ino b/plugins/KeyboardioHID/avr/libraries/Wire/examples/slave_sender/slave_sender.ino new file mode 100644 index 0000000000..4437ab1521 --- /dev/null +++ b/plugins/KeyboardioHID/avr/libraries/Wire/examples/slave_sender/slave_sender.ino @@ -0,0 +1,32 @@ +// Wire Slave Sender +// by Nicholas Zambetti + +// Demonstrates use of the Wire library +// Sends data as an I2C/TWI slave device +// Refer to the "Wire Master Reader" example for use with this + +// Created 29 March 2006 + +// This example code is in the public domain. + + +#include + +void setup() +{ + Wire.begin(2); // join i2c bus with address #2 + Wire.onRequest(requestEvent); // register event +} + +void loop() +{ + delay(100); +} + +// function that executes whenever data is requested by master +// this function is registered as an event, see setup() +void requestEvent() +{ + Wire.write("hello "); // respond with message of 6 bytes + // as expected by master +} diff --git a/plugins/KeyboardioHID/avr/libraries/Wire/keywords.txt b/plugins/KeyboardioHID/avr/libraries/Wire/keywords.txt new file mode 100644 index 0000000000..ff31475920 --- /dev/null +++ b/plugins/KeyboardioHID/avr/libraries/Wire/keywords.txt @@ -0,0 +1,32 @@ +####################################### +# Syntax Coloring Map For Wire +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +begin KEYWORD2 +setClock KEYWORD2 +beginTransmission KEYWORD2 +endTransmission KEYWORD2 +requestFrom KEYWORD2 +send KEYWORD2 +receive KEYWORD2 +onReceive KEYWORD2 +onRequest KEYWORD2 + +####################################### +# Instances (KEYWORD2) +####################################### + +Wire KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### + diff --git a/plugins/KeyboardioHID/avr/libraries/Wire/library.properties b/plugins/KeyboardioHID/avr/libraries/Wire/library.properties new file mode 100644 index 0000000000..3246a75098 --- /dev/null +++ b/plugins/KeyboardioHID/avr/libraries/Wire/library.properties @@ -0,0 +1,8 @@ +name=Wire +version=1.0 +author=Arduino +maintainer=Arduino +sentence=Allows the communication between devices or sensors connected via Two Wire Interface Bus. For all Arduino boards, BUT Arduino DUE. +paragraph= +url=http://arduino.cc/en/Reference/Wire +architectures=avr diff --git a/plugins/KeyboardioHID/avr/libraries/Wire/utility/twi.c b/plugins/KeyboardioHID/avr/libraries/Wire/utility/twi.c new file mode 100644 index 0000000000..201d7d1bbb --- /dev/null +++ b/plugins/KeyboardioHID/avr/libraries/Wire/utility/twi.c @@ -0,0 +1,527 @@ +/* + twi.c - TWI/I2C library for Wiring & Arduino + 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 2012 by Todd Krein (todd@krein.org) to implement repeated starts +*/ + +#include +#include +#include +#include +#include +#include +#include "Arduino.h" // for digitalWrite + +#ifndef cbi +#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) +#endif + +#ifndef sbi +#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) +#endif + +#include "pins_arduino.h" +#include "twi.h" + +static volatile uint8_t twi_state; +static volatile uint8_t twi_slarw; +static volatile uint8_t twi_sendStop; // should the transaction end with a stop +static volatile uint8_t twi_inRepStart; // in the middle of a repeated start + +static void (*twi_onSlaveTransmit)(void); +static void (*twi_onSlaveReceive)(uint8_t*, int); + +static uint8_t twi_masterBuffer[TWI_BUFFER_LENGTH]; +static volatile uint8_t twi_masterBufferIndex; +static volatile uint8_t twi_masterBufferLength; + +static uint8_t twi_txBuffer[TWI_BUFFER_LENGTH]; +static volatile uint8_t twi_txBufferIndex; +static volatile uint8_t twi_txBufferLength; + +static uint8_t twi_rxBuffer[TWI_BUFFER_LENGTH]; +static volatile uint8_t twi_rxBufferIndex; + +static volatile uint8_t twi_error; + +/* + * Function twi_init + * Desc readys twi pins and sets twi bitrate + * Input none + * Output none + */ +void twi_init(void) +{ + // initialize state + twi_state = TWI_READY; + twi_sendStop = true; // default value + twi_inRepStart = false; + + // activate internal pullups for twi. + digitalWrite(SDA, 1); + digitalWrite(SCL, 1); + + // initialize twi prescaler and bit rate + cbi(TWSR, TWPS0); + cbi(TWSR, TWPS1); + TWBR = ((F_CPU / TWI_FREQ) - 16) / 2; + + /* twi bit rate formula from atmega128 manual pg 204 + SCL Frequency = CPU Clock Frequency / (16 + (2 * TWBR)) + note: TWBR should be 10 or higher for master mode + It is 72 for a 16mhz Wiring board with 100kHz TWI */ + + // enable twi module, acks, and twi interrupt + TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA); +} + +/* + * Function twi_slaveInit + * Desc sets slave address and enables interrupt + * Input none + * Output none + */ +void twi_setAddress(uint8_t address) +{ + // set twi slave address (skip over TWGCE bit) + TWAR = address << 1; +} + +/* + * Function twi_readFrom + * Desc attempts to become twi bus master and read a + * series of bytes from a device on the bus + * Input address: 7bit i2c device address + * data: pointer to byte array + * length: number of bytes to read into array + * sendStop: Boolean indicating whether to send a stop at the end + * Output number of bytes read + */ +uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length, uint8_t sendStop) +{ + uint8_t i; + + // ensure data will fit into buffer + if(TWI_BUFFER_LENGTH < length){ + return 0; + } + + // wait until twi is ready, become master receiver + while(TWI_READY != twi_state){ + continue; + } + twi_state = TWI_MRX; + twi_sendStop = sendStop; + // reset error state (0xFF.. no error occured) + twi_error = 0xFF; + + // initialize buffer iteration vars + twi_masterBufferIndex = 0; + twi_masterBufferLength = length-1; // This is not intuitive, read on... + // On receive, the previously configured ACK/NACK setting is transmitted in + // response to the received byte before the interrupt is signalled. + // Therefor we must actually set NACK when the _next_ to last byte is + // received, causing that NACK to be sent in response to receiving the last + // expected byte of data. + + // build sla+w, slave device address + w bit + twi_slarw = TW_READ; + twi_slarw |= address << 1; + + if (true == twi_inRepStart) { + // if we're in the repeated start state, then we've already sent the start, + // (@@@ we hope), and the TWI statemachine is just waiting for the address byte. + // We need to remove ourselves from the repeated start state before we enable interrupts, + // since the ISR is ASYNC, and we could get confused if we hit the ISR before cleaning + // up. Also, don't enable the START interrupt. There may be one pending from the + // repeated start that we sent outselves, and that would really confuse things. + twi_inRepStart = false; // remember, we're dealing with an ASYNC ISR + TWDR = twi_slarw; + TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE); // enable INTs, but not START + } + else + // send start condition + TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA); + + // wait for read operation to complete + while(TWI_MRX == twi_state){ + continue; + } + + if (twi_masterBufferIndex < length) + length = twi_masterBufferIndex; + + // copy twi buffer to data + for(i = 0; i < length; ++i){ + data[i] = twi_masterBuffer[i]; + } + + return length; +} + +/* + * Function twi_writeTo + * Desc attempts to become twi bus master and write a + * series of bytes to a device on the bus + * Input address: 7bit i2c device address + * data: pointer to byte array + * length: number of bytes in array + * wait: boolean indicating to wait for write or not + * sendStop: boolean indicating whether or not to send a stop at the end + * Output 0 .. success + * 1 .. length to long for buffer + * 2 .. address send, NACK received + * 3 .. data send, NACK received + * 4 .. other twi error (lost bus arbitration, bus error, ..) + */ +uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait, uint8_t sendStop) +{ + uint8_t i; + + // ensure data will fit into buffer + if(TWI_BUFFER_LENGTH < length){ + return 1; + } + + // wait until twi is ready, become master transmitter + while(TWI_READY != twi_state){ + continue; + } + twi_state = TWI_MTX; + twi_sendStop = sendStop; + // reset error state (0xFF.. no error occured) + twi_error = 0xFF; + + // initialize buffer iteration vars + twi_masterBufferIndex = 0; + twi_masterBufferLength = length; + + // copy data to twi buffer + for(i = 0; i < length; ++i){ + twi_masterBuffer[i] = data[i]; + } + + // build sla+w, slave device address + w bit + twi_slarw = TW_WRITE; + twi_slarw |= address << 1; + + // if we're in a repeated start, then we've already sent the START + // in the ISR. Don't do it again. + // + if (true == twi_inRepStart) { + // if we're in the repeated start state, then we've already sent the start, + // (@@@ we hope), and the TWI statemachine is just waiting for the address byte. + // We need to remove ourselves from the repeated start state before we enable interrupts, + // since the ISR is ASYNC, and we could get confused if we hit the ISR before cleaning + // up. Also, don't enable the START interrupt. There may be one pending from the + // repeated start that we sent outselves, and that would really confuse things. + twi_inRepStart = false; // remember, we're dealing with an ASYNC ISR + TWDR = twi_slarw; + TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE); // enable INTs, but not START + } + else + // send start condition + TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE) | _BV(TWSTA); // enable INTs + + // wait for write operation to complete + while(wait && (TWI_MTX == twi_state)){ + continue; + } + + if (twi_error == 0xFF) + return 0; // success + else if (twi_error == TW_MT_SLA_NACK) + return 2; // error: address send, nack received + else if (twi_error == TW_MT_DATA_NACK) + return 3; // error: data send, nack received + else + return 4; // other twi error +} + +/* + * Function twi_transmit + * Desc fills slave tx buffer with data + * must be called in slave tx event callback + * Input data: pointer to byte array + * length: number of bytes in array + * Output 1 length too long for buffer + * 2 not slave transmitter + * 0 ok + */ +uint8_t twi_transmit(const uint8_t* data, uint8_t length) +{ + uint8_t i; + + // ensure data will fit into buffer + if(TWI_BUFFER_LENGTH < length){ + return 1; + } + + // ensure we are currently a slave transmitter + if(TWI_STX != twi_state){ + return 2; + } + + // set length and copy data into tx buffer + twi_txBufferLength = length; + for(i = 0; i < length; ++i){ + twi_txBuffer[i] = data[i]; + } + + return 0; +} + +/* + * Function twi_attachSlaveRxEvent + * Desc sets function called before a slave read operation + * Input function: callback function to use + * Output none + */ +void twi_attachSlaveRxEvent( void (*function)(uint8_t*, int) ) +{ + twi_onSlaveReceive = function; +} + +/* + * Function twi_attachSlaveTxEvent + * Desc sets function called before a slave write operation + * Input function: callback function to use + * Output none + */ +void twi_attachSlaveTxEvent( void (*function)(void) ) +{ + twi_onSlaveTransmit = function; +} + +/* + * Function twi_reply + * Desc sends byte or readys receive line + * Input ack: byte indicating to ack or to nack + * Output none + */ +void twi_reply(uint8_t ack) +{ + // transmit master read ready signal, with or without ack + if(ack){ + TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA); + }else{ + TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT); + } +} + +/* + * Function twi_stop + * Desc relinquishes bus master status + * Input none + * Output none + */ +void twi_stop(void) +{ + // send stop condition + TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTO); + + // wait for stop condition to be exectued on bus + // TWINT is not set after a stop condition! + while(TWCR & _BV(TWSTO)){ + continue; + } + + // update twi state + twi_state = TWI_READY; +} + +/* + * Function twi_releaseBus + * Desc releases bus control + * Input none + * Output none + */ +void twi_releaseBus(void) +{ + // release bus + TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT); + + // update twi state + twi_state = TWI_READY; +} + +ISR(TWI_vect) +{ + switch(TW_STATUS){ + // All Master + case TW_START: // sent start condition + case TW_REP_START: // sent repeated start condition + // copy device address and r/w bit to output register and ack + TWDR = twi_slarw; + twi_reply(1); + break; + + // Master Transmitter + case TW_MT_SLA_ACK: // slave receiver acked address + case TW_MT_DATA_ACK: // slave receiver acked data + // if there is data to send, send it, otherwise stop + if(twi_masterBufferIndex < twi_masterBufferLength){ + // copy data to output register and ack + TWDR = twi_masterBuffer[twi_masterBufferIndex++]; + twi_reply(1); + }else{ + if (twi_sendStop) + twi_stop(); + else { + twi_inRepStart = true; // we're gonna send the START + // don't enable the interrupt. We'll generate the start, but we + // avoid handling the interrupt until we're in the next transaction, + // at the point where we would normally issue the start. + TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ; + twi_state = TWI_READY; + } + } + break; + case TW_MT_SLA_NACK: // address sent, nack received + twi_error = TW_MT_SLA_NACK; + twi_stop(); + break; + case TW_MT_DATA_NACK: // data sent, nack received + twi_error = TW_MT_DATA_NACK; + twi_stop(); + break; + case TW_MT_ARB_LOST: // lost bus arbitration + twi_error = TW_MT_ARB_LOST; + twi_releaseBus(); + break; + + // Master Receiver + case TW_MR_DATA_ACK: // data received, ack sent + // put byte into buffer + twi_masterBuffer[twi_masterBufferIndex++] = TWDR; + case TW_MR_SLA_ACK: // address sent, ack received + // ack if more bytes are expected, otherwise nack + if(twi_masterBufferIndex < twi_masterBufferLength){ + twi_reply(1); + }else{ + twi_reply(0); + } + break; + case TW_MR_DATA_NACK: // data received, nack sent + // put final byte into buffer + twi_masterBuffer[twi_masterBufferIndex++] = TWDR; + if (twi_sendStop) + twi_stop(); + else { + twi_inRepStart = true; // we're gonna send the START + // don't enable the interrupt. We'll generate the start, but we + // avoid handling the interrupt until we're in the next transaction, + // at the point where we would normally issue the start. + TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ; + twi_state = TWI_READY; + } + break; + case TW_MR_SLA_NACK: // address sent, nack received + twi_stop(); + break; + // TW_MR_ARB_LOST handled by TW_MT_ARB_LOST case + + // Slave Receiver + case TW_SR_SLA_ACK: // addressed, returned ack + case TW_SR_GCALL_ACK: // addressed generally, returned ack + case TW_SR_ARB_LOST_SLA_ACK: // lost arbitration, returned ack + case TW_SR_ARB_LOST_GCALL_ACK: // lost arbitration, returned ack + // enter slave receiver mode + twi_state = TWI_SRX; + // indicate that rx buffer can be overwritten and ack + twi_rxBufferIndex = 0; + twi_reply(1); + break; + case TW_SR_DATA_ACK: // data received, returned ack + case TW_SR_GCALL_DATA_ACK: // data received generally, returned ack + // if there is still room in the rx buffer + if(twi_rxBufferIndex < TWI_BUFFER_LENGTH){ + // put byte in buffer and ack + twi_rxBuffer[twi_rxBufferIndex++] = TWDR; + twi_reply(1); + }else{ + // otherwise nack + twi_reply(0); + } + break; + case TW_SR_STOP: // stop or repeated start condition received + // put a null char after data if there's room + if(twi_rxBufferIndex < TWI_BUFFER_LENGTH){ + twi_rxBuffer[twi_rxBufferIndex] = '\0'; + } + // sends ack and stops interface for clock stretching + twi_stop(); + // callback to user defined callback + twi_onSlaveReceive(twi_rxBuffer, twi_rxBufferIndex); + // since we submit rx buffer to "wire" library, we can reset it + twi_rxBufferIndex = 0; + // ack future responses and leave slave receiver state + twi_releaseBus(); + break; + case TW_SR_DATA_NACK: // data received, returned nack + case TW_SR_GCALL_DATA_NACK: // data received generally, returned nack + // nack back at master + twi_reply(0); + break; + + // Slave Transmitter + case TW_ST_SLA_ACK: // addressed, returned ack + case TW_ST_ARB_LOST_SLA_ACK: // arbitration lost, returned ack + // enter slave transmitter mode + twi_state = TWI_STX; + // ready the tx buffer index for iteration + twi_txBufferIndex = 0; + // set tx buffer length to be zero, to verify if user changes it + twi_txBufferLength = 0; + // request for txBuffer to be filled and length to be set + // note: user must call twi_transmit(bytes, length) to do this + twi_onSlaveTransmit(); + // if they didn't change buffer & length, initialize it + if(0 == twi_txBufferLength){ + twi_txBufferLength = 1; + twi_txBuffer[0] = 0x00; + } + // transmit first byte from buffer, fall + case TW_ST_DATA_ACK: // byte sent, ack returned + // copy data to output register + TWDR = twi_txBuffer[twi_txBufferIndex++]; + // if there is more to send, ack, otherwise nack + if(twi_txBufferIndex < twi_txBufferLength){ + twi_reply(1); + }else{ + twi_reply(0); + } + break; + case TW_ST_DATA_NACK: // received nack, we are done + case TW_ST_LAST_DATA: // received ack, but we are done already! + // ack future responses + twi_reply(1); + // leave slave receiver state + twi_state = TWI_READY; + break; + + // All + case TW_NO_INFO: // no state information + break; + case TW_BUS_ERROR: // bus error, illegal stop/start + twi_error = TW_BUS_ERROR; + twi_stop(); + break; + } +} + diff --git a/plugins/KeyboardioHID/avr/libraries/Wire/utility/twi.h b/plugins/KeyboardioHID/avr/libraries/Wire/utility/twi.h new file mode 100644 index 0000000000..6526593394 --- /dev/null +++ b/plugins/KeyboardioHID/avr/libraries/Wire/utility/twi.h @@ -0,0 +1,53 @@ +/* + twi.h - TWI/I2C library for Wiring & Arduino + 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 +*/ + +#ifndef twi_h +#define twi_h + + #include + + //#define ATMEGA8 + + #ifndef TWI_FREQ + #define TWI_FREQ 100000L + #endif + + #ifndef TWI_BUFFER_LENGTH + #define TWI_BUFFER_LENGTH 32 + #endif + + #define TWI_READY 0 + #define TWI_MRX 1 + #define TWI_MTX 2 + #define TWI_SRX 3 + #define TWI_STX 4 + + void twi_init(void); + void twi_setAddress(uint8_t); + uint8_t twi_readFrom(uint8_t, uint8_t*, uint8_t, uint8_t); + uint8_t twi_writeTo(uint8_t, uint8_t*, uint8_t, uint8_t, uint8_t); + uint8_t twi_transmit(const uint8_t*, uint8_t); + void twi_attachSlaveRxEvent( void (*)(uint8_t*, int) ); + void twi_attachSlaveTxEvent( void (*)(void) ); + void twi_reply(uint8_t); + void twi_stop(void); + void twi_releaseBus(void); + +#endif + From 4faee5959022615fdb26d5d8b3a2677bb4131f29 Mon Sep 17 00:00:00 2001 From: Nico Date: Sat, 24 Jan 2015 23:47:51 +0100 Subject: [PATCH 137/602] todo --- plugins/KeyboardioHID/Readme.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 741a4a93da..a7c061d3cf 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -34,10 +34,8 @@ keycode/raw for keyboard Check Keyboard keycode function again? + add example Generalize HID key definitions via HIDTables for example? -update Burning via ISP for HL2 Test with Android phone (HL1) -"Emulate" HL1 protocol -remove dev HL2 link +HID-Bridge + Firmwares (planned for 2.2) HL2 usb hub fix (try with a bare cdc bootloader?) ``` From a9e2b8d9a973b4cfbdf76ef3cfefb4fe4848ac94 Mon Sep 17 00:00:00 2001 From: Nico Date: Wed, 28 Jan 2015 10:22:33 +0100 Subject: [PATCH 138/602] Readme --- plugins/KeyboardioHID/Readme.md | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index a7c061d3cf..219100ec1b 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -6,12 +6,28 @@ This project went through a lot of phases and has now reached a new Arduino USB- with a lot of new functions like extended HID. It also supports HoodLoader1+2. The idea is to enable enhanced USB functions to almost all 'standard' Arduino boards. + +Download +======== + +You have 3 versions you can download: +* The master includes all fixes to the current stable release. Download it by clicking download at the right. +Use the [online Wiki](https://github.com/NicoHood/HID/wiki) to get the newest documentation. +* Download an offline version in [releases](https://github.com/NicoHood/HID/releases). +It's a snapshot of the current stable release but might have missed some updates that the current master branch has included. +This also includes an offline version of the wiki. Offline versions will be available after some time when the official release is out. +* Select [branch 'dev'](https://github.com/NicoHood/HID/tree/dev) to test the bleeding edge of this software. It might now work at all or has a lot of debugging stuff in it. +If the dev version gets near to a new release a note will be placed here, that you can test the new dev beta. +Currently there is no beta available. + + Wiki ==== All documentation moved to the [wiki page](https://github.com/NicoHood/HID/wiki). -An offline version will be available soon. +An offline snapshot is available in [releases](https://github.com/NicoHood/HID/releases). + Contact ======= @@ -20,6 +36,7 @@ You can contact me on my wordpress blog in the contact section. www.nicohood.de + TODO ==== @@ -40,6 +57,7 @@ HID-Bridge + Firmwares (planned for 2.2) HL2 usb hub fix (try with a bare cdc bootloader?) ``` + Version History =============== ``` @@ -167,6 +185,7 @@ Version History 1.0 Beta Release (03.06.2014) ``` + Licence and Copyright ===================== If you use this library for any cool project let me know! From a5ab0abe8c880104304a491b6a8a743d361baa68 Mon Sep 17 00:00:00 2001 From: Nico Date: Wed, 28 Jan 2015 10:25:09 +0100 Subject: [PATCH 139/602] Readme --- plugins/KeyboardioHID/Readme.md | 7 ------- 1 file changed, 7 deletions(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 40e557cc77..219100ec1b 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -6,13 +6,6 @@ This project went through a lot of phases and has now reached a new Arduino USB- with a lot of new functions like extended HID. It also supports HoodLoader1+2. The idea is to enable enhanced USB functions to almost all 'standard' Arduino boards. -<<<<<<< HEAD -======= -###The new 2.1 is ready to test here, need feedback: -https://github.com/NicoHood/HID/tree/Official-Integration - -**Arduino IDE 1.5.8 is required for the HID Project.** ->>>>>>> origin/master Download ======== From 8bf2da2ab59bc8bcb746738dc266854212b32b28 Mon Sep 17 00:00:00 2001 From: The Gitter Badger Date: Mon, 2 Feb 2015 17:50:20 +0000 Subject: [PATCH 140/602] Added Gitter badge --- plugins/KeyboardioHID/Readme.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 219100ec1b..8dabf84441 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -1,5 +1,7 @@ Arduino HID Project 2.1 ======================= + +[![Join the chat at https://gitter.im/NicoHood/HID](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/NicoHood/HID?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) ![Header Picture](header.jpg) This project went through a lot of phases and has now reached a new Arduino USB-Core From ca4024847bfc5c0ef3908510a7cad0d22dea3b66 Mon Sep 17 00:00:00 2001 From: Nico Date: Mon, 2 Feb 2015 20:36:12 +0100 Subject: [PATCH 141/602] Correct undefined Serial Buffer Size https://github.com/arduino/Arduino/pull/2597 --- plugins/KeyboardioHID/.gitignore | 3 +-- plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.h | 9 +++++++-- plugins/KeyboardioHID/avr/cores/hid/USB-Core/CDC.h | 5 +++++ 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/plugins/KeyboardioHID/.gitignore b/plugins/KeyboardioHID/.gitignore index 117ca863b4..432031f828 100644 --- a/plugins/KeyboardioHID/.gitignore +++ b/plugins/KeyboardioHID/.gitignore @@ -1,2 +1 @@ -dev/* -*.pdn \ No newline at end of file +dev/* \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.h b/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.h index 7dc2aa98c4..203008d97a 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.h +++ b/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.h @@ -34,12 +34,17 @@ // location from which to read. // NOTE: a "power of 2" buffer size is reccomended to dramatically // optimize all the modulo operations for ring buffers. -#if !(defined(SERIAL_TX_BUFFER_SIZE) && defined(SERIAL_RX_BUFFER_SIZE)) +#if !(defined(SERIAL_TX_BUFFER_SIZE) #if (RAMEND < 1000) #define SERIAL_TX_BUFFER_SIZE 16 -#define SERIAL_RX_BUFFER_SIZE 16 #else #define SERIAL_TX_BUFFER_SIZE 64 +#endif +#endif +#if !defined(SERIAL_RX_BUFFER_SIZE)) +#if (RAMEND < 1000) +#define SERIAL_RX_BUFFER_SIZE 16 +#else #define SERIAL_RX_BUFFER_SIZE 64 #endif #endif diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/CDC.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/CDC.h index f58bc0ddd6..99b62faa31 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/CDC.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/CDC.h @@ -56,11 +56,16 @@ THE SOFTWARE. struct ring_buffer; +#ifndef SERIAL_BUFFER_SIZE #if (RAMEND < 1000) #define SERIAL_BUFFER_SIZE 16 #else #define SERIAL_BUFFER_SIZE 64 #endif +#endif +#if (SERIAL_BUFFER_SIZE>256) +#error Please lower the CDC Buffer size +#endif class Serial_ : public Stream { From 26d4273335a54bb2aa8ef83449a3568dd960daef Mon Sep 17 00:00:00 2001 From: Nico Date: Mon, 2 Feb 2015 21:33:13 +0100 Subject: [PATCH 142/602] Serial fix --- plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.h b/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.h index 203008d97a..7f4f162d68 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.h +++ b/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.h @@ -34,14 +34,14 @@ // location from which to read. // NOTE: a "power of 2" buffer size is reccomended to dramatically // optimize all the modulo operations for ring buffers. -#if !(defined(SERIAL_TX_BUFFER_SIZE) +#if !defined(SERIAL_TX_BUFFER_SIZE) #if (RAMEND < 1000) #define SERIAL_TX_BUFFER_SIZE 16 #else #define SERIAL_TX_BUFFER_SIZE 64 #endif #endif -#if !defined(SERIAL_RX_BUFFER_SIZE)) +#if !defined(SERIAL_RX_BUFFER_SIZE) #if (RAMEND < 1000) #define SERIAL_RX_BUFFER_SIZE 16 #else From da782b38a41bfd2c712bb327b7c5c23689668141 Mon Sep 17 00:00:00 2001 From: Nico Date: Tue, 3 Feb 2015 19:05:30 +0100 Subject: [PATCH 143/602] Fixed bug which occured after another "fix" --- plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.h b/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.h index 203008d97a..7f4f162d68 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.h +++ b/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.h @@ -34,14 +34,14 @@ // location from which to read. // NOTE: a "power of 2" buffer size is reccomended to dramatically // optimize all the modulo operations for ring buffers. -#if !(defined(SERIAL_TX_BUFFER_SIZE) +#if !defined(SERIAL_TX_BUFFER_SIZE) #if (RAMEND < 1000) #define SERIAL_TX_BUFFER_SIZE 16 #else #define SERIAL_TX_BUFFER_SIZE 64 #endif #endif -#if !defined(SERIAL_RX_BUFFER_SIZE)) +#if !defined(SERIAL_RX_BUFFER_SIZE) #if (RAMEND < 1000) #define SERIAL_RX_BUFFER_SIZE 16 #else From 1ed04da1808949746f909f4b74f979df2f4a8a3e Mon Sep 17 00:00:00 2001 From: Nico Date: Tue, 10 Feb 2015 18:48:23 +0100 Subject: [PATCH 144/602] added keywords file --- .../avr/libraries/HID_Bridge/keywords.txt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 plugins/KeyboardioHID/avr/libraries/HID_Bridge/keywords.txt diff --git a/plugins/KeyboardioHID/avr/libraries/HID_Bridge/keywords.txt b/plugins/KeyboardioHID/avr/libraries/HID_Bridge/keywords.txt new file mode 100644 index 0000000000..f46bacc375 --- /dev/null +++ b/plugins/KeyboardioHID/avr/libraries/HID_Bridge/keywords.txt @@ -0,0 +1,18 @@ +####################################### +# Syntax Coloring Map For Ultrasound +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +Gamepad KEYWORD3 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +####################################### +# Constants (LITERAL1) +####################################### + From d94fa96100e53bbec1ddc6c860ae3c5a02f41705 Mon Sep 17 00:00:00 2001 From: Nico Date: Tue, 10 Feb 2015 18:50:06 +0100 Subject: [PATCH 145/602] Minor updates --- plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.h index 3bd4b5d62d..418efb054e 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.h @@ -95,8 +95,8 @@ typedef union { int8_t zAxis; int8_t rzAxis; - uint8_t dPad1 : 4; - uint8_t dPad2 : 4; + uint8_t dPad1 : 4; + uint8_t dPad2 : 4; }; } HID_GamepadReport_Data_t; @@ -130,7 +130,7 @@ class Gamepad_{ inline void rzAxis(int8_t a){ _report.rzAxis = a; } inline void dPad1(int8_t d){ _report.dPad1 = d; } inline void dPad2(int8_t d){ _report.dPad2 = d; } -private: + HID_GamepadReport_Data_t _report; }; extern Gamepad_ Gamepad; From dd01e2f3753047596b5faa62ea7b9f1aaef0cbbf Mon Sep 17 00:00:00 2001 From: Nico Date: Tue, 10 Feb 2015 19:25:48 +0100 Subject: [PATCH 146/602] gitignore --- plugins/KeyboardioHID/.gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/.gitignore b/plugins/KeyboardioHID/.gitignore index 432031f828..436221a38e 100644 --- a/plugins/KeyboardioHID/.gitignore +++ b/plugins/KeyboardioHID/.gitignore @@ -1 +1,2 @@ -dev/* \ No newline at end of file +dev/* +*.zip \ No newline at end of file From 4e4116ecbe1214c473cf2fe2952139fc57401482 Mon Sep 17 00:00:00 2001 From: Nico Date: Wed, 11 Feb 2015 07:52:57 +0100 Subject: [PATCH 147/602] Added F() makro to Keyboard example --- .../examples/HID_Basic/HID_Keyboard/HID_Keyboard.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/KeyboardioHID/examples/HID_Basic/HID_Keyboard/HID_Keyboard.ino b/plugins/KeyboardioHID/examples/HID_Basic/HID_Keyboard/HID_Keyboard.ino index d15e684f76..83566d83d5 100644 --- a/plugins/KeyboardioHID/examples/HID_Basic/HID_Keyboard/HID_Keyboard.ino +++ b/plugins/KeyboardioHID/examples/HID_Basic/HID_Keyboard/HID_Keyboard.ino @@ -28,8 +28,8 @@ void loop() { digitalWrite(pinLed, HIGH); // Same use as the official library, pretty much self explaining - Keyboard.println("This message was sent with my Arduino."); - Serial.println("Serial port is still working and not glitching out"); + Keyboard.println(F("This message was sent with my Arduino.")); + Serial.println(F("Serial port is still working and not glitching out")); // simple debounce delay(300); From 282e5d239f3b94dae72ff0fd063061b727798293 Mon Sep 17 00:00:00 2001 From: Nico Date: Wed, 11 Feb 2015 15:37:02 +0100 Subject: [PATCH 148/602] fix issue #12 https://github.com/NicoHood/HID/issues/12 --- plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h index 1bf159d4ad..f1666501d9 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h @@ -185,7 +185,7 @@ class Keyboard_ : public Print size_t write(uint8_t k); size_t press(uint8_t k); - inline size_t release(uint8_t k); + size_t release(uint8_t k); void releaseAll(void); size_t writeKeycode(uint8_t k); From cebec81210d38bc4821598366c29b6cad7d9c7cb Mon Sep 17 00:00:00 2001 From: Nico Date: Wed, 11 Feb 2015 15:39:15 +0100 Subject: [PATCH 149/602] fix issue #12 https://github.com/NicoHood/HID/issues/12 --- plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h index 1bf159d4ad..2b4a370f21 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h @@ -185,7 +185,7 @@ class Keyboard_ : public Print size_t write(uint8_t k); size_t press(uint8_t k); - inline size_t release(uint8_t k); + size_t release(uint8_t k); void releaseAll(void); size_t writeKeycode(uint8_t k); @@ -200,4 +200,4 @@ class Keyboard_ : public Print }; extern Keyboard_ Keyboard; -#endif \ No newline at end of file +#endif From 4f65ba59da06d9bfea35e123b75784e060a37d84 Mon Sep 17 00:00:00 2001 From: Nico Date: Wed, 11 Feb 2015 16:14:24 +0100 Subject: [PATCH 150/602] made gamepad report private again people (like me!) should rather use advanced gamepad for such things --- plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.h | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.h index 418efb054e..3a9682f775 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.h @@ -131,6 +131,7 @@ class Gamepad_{ inline void dPad1(int8_t d){ _report.dPad1 = d; } inline void dPad2(int8_t d){ _report.dPad2 = d; } +private: HID_GamepadReport_Data_t _report; }; extern Gamepad_ Gamepad; From 408bb8dbde7881b34de6c1430b588f59280b151d Mon Sep 17 00:00:00 2001 From: Nico Date: Wed, 11 Feb 2015 16:55:39 +0100 Subject: [PATCH 151/602] Readme --- plugins/KeyboardioHID/Readme.md | 6 +- plugins/KeyboardioHID/avr/boards.txt | 67 ---- .../avr/cores/hid/USB-Core/Gamepad.h | 1 - .../avr/cores/hid/USB-Core/HID.cpp | 2 +- .../avr/cores/hid/USB-Core/HID.h | 15 +- .../avr/cores/hid/USB-Core/Keyboard.h | 2 +- .../avr/cores/hid/USB-Core/Mouse.h | 3 +- .../avr/libraries/HIDBridge/HIDBridge.cpp | 121 ++++++++ .../avr/libraries/HIDBridge/HIDBridge.h | 65 ++++ .../avr/libraries/HIDBridge/NHP.h | 288 ++++++++++++++++++ .../avr/libraries/HIDBridge/keywords.txt | 22 ++ plugins/KeyboardioHID/avr/platform.txt | 2 +- .../variants/leonardo_custom/pins_arduino.h | 2 + .../avr/variants/micro_custom/pins_arduino.h | 2 + 14 files changed, 518 insertions(+), 80 deletions(-) create mode 100644 plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.cpp create mode 100644 plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.h create mode 100644 plugins/KeyboardioHID/avr/libraries/HIDBridge/NHP.h create mode 100644 plugins/KeyboardioHID/avr/libraries/HIDBridge/keywords.txt diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 8dabf84441..4812d027ca 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -1,4 +1,4 @@ -Arduino HID Project 2.1 +Arduino HID Project 2.2 ======================= [![Join the chat at https://gitter.im/NicoHood/HID](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/NicoHood/HID?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) @@ -63,6 +63,10 @@ HL2 usb hub fix (try with a bare cdc bootloader?) Version History =============== ``` +2.2 Release (xx.xx.2015) +* added HID-Bridge +* added colour highlighting (through HID-Bridge library) + 2.1 Release (28.01.2015) * Reworked the whole USB-Core from scratch * Uses less flash if HID or Serial is not used diff --git a/plugins/KeyboardioHID/avr/boards.txt b/plugins/KeyboardioHID/avr/boards.txt index 1b8b4099b6..b874a87deb 100644 --- a/plugins/KeyboardioHID/avr/boards.txt +++ b/plugins/KeyboardioHID/avr/boards.txt @@ -90,70 +90,3 @@ microExtended.menu.usbcore.USB_CORE.build.variant=micro microExtended.menu.usbcore.NO_USB=No USB functions microExtended.menu.usbcore.NO_USB.build.variant=micro_no_usb -############################################################## - -uno.name=Arduino Uno HID-Project - -uno.vid.0=0x2341 -uno.pid.0=0x0043 -uno.vid.1=0x2341 -uno.pid.1=0x0001 - -uno.upload.tool=arduino:avrdude -uno.upload.protocol=arduino -uno.upload.maximum_size=32256 -uno.upload.maximum_data_size=2048 -uno.upload.speed=115200 - -uno.bootloader.tool=arduino:avrdude -uno.bootloader.low_fuses=0xFF -uno.bootloader.high_fuses=0xDE -uno.bootloader.extended_fuses=0x05 -uno.bootloader.unlock_bits=0x3F -uno.bootloader.lock_bits=0x0F -uno.bootloader.file=arduino:optiboot/optiboot_atmega328.hex - -uno.build.mcu=atmega328p -uno.build.f_cpu=16000000L -uno.build.board=AVR_UNO -uno.build.core=HID:hid -uno.build.variant=arduino:standard - -############################################################## - - -mega.name=Arduino Mega 2560 HID-Project - -mega.vid.0=0x2341 -mega.pid.0=0x0010 -mega.vid.1=0x2341 -mega.pid.1=0x0042 - -mega.upload.tool=arduino:avrdude -mega.upload.maximum_data_size=8192 - -mega.bootloader.tool=arduino:avrdude -mega.bootloader.low_fuses=0xFF -mega.bootloader.unlock_bits=0x3F -mega.bootloader.lock_bits=0x0F - -mega.build.f_cpu=16000000L -mega.build.core=HID:hid -mega.build.variant=arduino:mega -# default board may be overridden by the cpu menu -mega.build.board=AVR_MEGA2560 - -## Arduino Mega w/ ATmega2560 -## ------------------------- - -mega.upload.protocol=wiring -mega.upload.maximum_size=253952 -mega.upload.speed=115200 - -mega.bootloader.high_fuses=0xD8 -mega.bootloader.extended_fuses=0xFD -mega.bootloader.file=arduino:stk500v2/stk500boot_v2_mega2560.hex - -mega.build.mcu=atmega2560 -mega.build.board=AVR_MEGA2560 - diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.h index 3a9682f775..418efb054e 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.h @@ -131,7 +131,6 @@ class Gamepad_{ inline void dPad1(int8_t d){ _report.dPad1 = d; } inline void dPad2(int8_t d){ _report.dPad2 = d; } -private: HID_GamepadReport_Data_t _report; }; extern Gamepad_ Gamepad; diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.cpp b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.cpp index dac5d618a2..60f0840a6c 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.cpp +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.cpp @@ -91,7 +91,7 @@ const HIDDescriptor _hidInterface = }; #if defined(HID_KEYBOARD_LEDS_ENABLED) -uint8_t hid_keyboard_leds = 0; +volatile uint8_t hid_keyboard_leds = 0; #endif //================================================================================ diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h index d2db12f0ab..a7d8782439 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h @@ -61,10 +61,14 @@ THE SOFTWARE. #define HID_KEYBOARD_LEDS_ENABLED #endif -#if defined(HID_MOUSE_ENABLE) || defined(HID_MOUSE_ABSOLUTE_ENABLE) +#if defined(HID_MOUSE_ENABLE) || defined(HID_MOUSE_ABSOLUTE_API_ENABLE) #define HID_MOUSE_API_ENABLE #endif +#if defined(HID_MOUSE_ABSOLUTE_ENABLE) +#define HID_MOUSE_ABSOLUTE_API_ENABLE +#endif #if defined(HID_KEYBOARD_LEDS_ENABLE) || defined(HID_KEYBOARD_KEYS_ENABLE) +#define HID_KEYBOARD_ENABLE #define HID_KEYBOARD_API_ENABLE #endif #ifdef HID_RAWHID_ENABLE @@ -82,7 +86,7 @@ THE SOFTWARE. // extern accessible led out report #if defined(HID_KEYBOARD_LEDS_ENABLED) -extern uint8_t hid_keyboard_leds; +extern volatile uint8_t hid_keyboard_leds; #endif // HID report IDs @@ -402,6 +406,7 @@ void HID_SendReport(uint8_t id, const void* data, int len); #ifdef HID_ENABLE_ALL_APIS // include all HID APIs #define HID_MOUSE_API_ENABLE +#define HID_MOUSE_ABSOLUTE_API_ENABLE #define HID_KEYBOARD_API_ENABLE #define HID_RAWHID_API_ENABLE #define HID_CONSUMERCONTROL_API_ENABLE @@ -409,8 +414,6 @@ void HID_SendReport(uint8_t id, const void* data, int len); #define HID_GAMEPAD_API_ENABLE #endif -#ifdef USBCON - #ifdef HID_MOUSE_API_ENABLE #include "Mouse.h" #endif @@ -434,7 +437,5 @@ void HID_SendReport(uint8_t id, const void* data, int len); #ifdef HID_GAMEPAD_API_ENABLE #include "Gamepad.h" #endif - +#define kkk #endif - -#endif \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h index f1666501d9..1bf159d4ad 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h @@ -185,7 +185,7 @@ class Keyboard_ : public Print size_t write(uint8_t k); size_t press(uint8_t k); - size_t release(uint8_t k); + inline size_t release(uint8_t k); void releaseAll(void); size_t writeKeycode(uint8_t k); diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.h index 23462edf2a..507607a178 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.h @@ -138,12 +138,13 @@ class Mouse_ return true; return false; } - +#ifdef HID_MOUSE_ABSOLUTE_API_ENABLE inline void moveTo(int16_t x, int16_t y){ // uses different report ID and different HID mouse device! uint32_t pos = ((uint32_t)y << 16) | x; HID_SendReport(HID_REPORTID_MOUSE_ABSOLUTE, &pos, sizeof(pos)); } +#endif }; extern Mouse_ Mouse; diff --git a/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.cpp b/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.cpp new file mode 100644 index 0000000000..ee9a237afd --- /dev/null +++ b/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.cpp @@ -0,0 +1,121 @@ +/* +Copyright (c) 2015 NicoHood +See the readme for credit to other people. + +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 "HIDBridge.h" + +//================================================================================ +// HIDBridge +//================================================================================ + +HIDBridge_ HIDBridge; + +HIDBridge_::HIDBridge_(void){ + // empty +} + +bool HIDBridge_::begin(void) +{ + +} + +void HIDBridge_::err(uint8_t error) +{ + +} + +void HIDBridge_::task(void) +{ + static NHP_Read_Data_t n = { 0 }; + uint8_t error = 0x00; + + while (Serial.available()) { + if (NHPread(Serial.read(), &n)) { + if (n.mode == NHP_ADDRESS) { + switch (n.address) { + case 0: + // received a control address command + if (n.data == 0) { + isReady = true; + return; + } + else + error = 3; + break; + default: + error = 1; + break; + + } + } + else if (n.mode == NHP_COMMAND) { + + } + else { + error = 2; + } + + } + } + + if (error) + err(error); +} + +bool HIDBridge_::ready(void) +{ + //if (!hidReady) { + // // try to wait for a new request/acknowledge + // uint32_t currentMillis = millis(); + // while (!hidReady) { + // readHIDReady(); + // if ((millis() - currentMillis) > 1000) { + // errorHID(0); + // return; + // } + // } + //} +} + +// overwrites the HID_SendReport function which is empty/not used on a 328/2560 +void HID_SendReport(uint8_t reportID, const void* data, int len) +{ + // check if we got a request/acknowledge + if (!HIDBridge.ready()){ + HIDBridge.err(0); + return; + } + + // begin transfer with reportID as command + Serial.write(NHPwriteCommand(reportID)); + + // send data in 4 byte packets with the address of the reportID + // the rest (if any, e.g. with 2 byte) is filled with random bytes + NHP_Write_Data_t n; + for (int i = 0; i < len; i += 4) { + NHPwriteAddress(reportID, UINT32_AT_OFFSET(data, i), &n); + Serial.write(n.writeBuffer, n.writeLength); + } + + // end transfer with zero command + Serial.write(NHPwriteCommand(0)); +} \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.h b/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.h new file mode 100644 index 0000000000..9874342045 --- /dev/null +++ b/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.h @@ -0,0 +1,65 @@ +/* +Copyright (c) 2015 NicoHood +See the readme for credit to other people. + +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 HIDBRIDGE_H +#define HIDBRIDGE_H + +#include +#include "NHP.h" + +//================================================================================ +// Settings +//================================================================================ + + +//================================================================================ +// Definitions +//================================================================================ + +//================================================================================ +// HIDBridge +//================================================================================ + + +class HIDBridge_{ +public: + HIDBridge_(void); + + bool begin(void); + + bool ready(void); + bool isReady; + void task(void); + void err(uint8_t error); + + inline void write(void){} // TODO +}; + +extern HIDBridge_ HIDBridge; + +//================================================================================ +// Function prototypes +//================================================================================ + + +#endif // include guard \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/libraries/HIDBridge/NHP.h b/plugins/KeyboardioHID/avr/libraries/HIDBridge/NHP.h new file mode 100644 index 0000000000..99e8eeeb74 --- /dev/null +++ b/plugins/KeyboardioHID/avr/libraries/HIDBridge/NHP.h @@ -0,0 +1,288 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 NHP_H +#define NHP_H + +#include //uint_t definitions +#include //bool type + + +//================================================================================ +//Settings +//================================================================================ + +// empty + +//================================================================================ +//Definitions +//================================================================================ + +// Header Masks +#define NHP_HEADER_MASK 0xC0 // B11|000000 the two MSB bits determine the block type +#define NHP_HEADER_LEAD 0xC0 // B11|000000 11 MSB +#define NHP_HEADER_DATA_A 0x00 // B00|000000 0X MSB only the first MSB is important +#define NHP_HEADER_DATA_B 0x40 // B01|000000 0X MSB only the first MSB is important +#define NHP_HEADER_END 0x80 // B10|000000 01 MSB + +// Lead +#define NHP_LENGTH_MASK 0x38 // B00|111|000 +#define NHP_LENGTH_OFFSET 3 +#define NHP_COMMAND_MASK 0x0F // B0000|1111 // 4bit command(0-15) in lead block + +// Data +#define NHP_DATA_7BIT_MASK 0x7F // B0|1111111 // data in data block +#define NHP_DATA_4BIT_MASK 0x0F // B0000|1111 // data in lead (32 bit special MSB case) +#define NHP_DATA_3BIT_MASK 0x07 // B00000|111 // data in lead + +// End +#define NHP_ADDRESS_MASK 0x3F // B00|111111 // 6 bit address (0-63) in end block + +// mode indicators +#define NHP_IN_PROGRESS 0 +#define NHP_ADDRESS 1 +#define NHP_COMMAND 2 +#define NHP_RESET 3 + +// errorLevels +#define NHP_ERR_NONE 0 +#define NHP_ERR_LEAD 1 +#define NHP_ERR_DATA 2 +#define NHP_ERR_END 3 + +// buffer sizes +#define NHP_BUFFER_SIZE 6 +#define NHP_READ_BUFFER_SIZE NHP_BUFFER_SIZE +#define NHP_WRITE_BUFFER_SIZE NHP_BUFFER_SIZE + +// definition to convert an uint8_t array to an uint16_t/uint32_t at any position (thx timeage!) +#define UINT16_AT_OFFSET(p_to_8, offset) ((uint16_t)*((const uint16_t *)((p_to_8)+(offset)))) +#define UINT32_AT_OFFSET(p_to_8, offset) ((uint32_t)*((const uint32_t *)((p_to_8)+(offset)))) + +// protocol data for temporary variables +typedef union { + struct { //TODO change order to save flash? + // buffer for read operations + uint8_t readBuffer[NHP_READ_BUFFER_SIZE]; + + // in progress reading data variables + uint8_t readLength : 3; // 0-6 (7 invalid) + uint8_t mode : 2; // in progress, address, command, reset on error (except lead) + uint8_t blocks : 3; // 0-7 + // 2nd byte + uint8_t errorLevel : 2; // no err, lead err, data err, end err + uint8_t address : 6; // 6 bit address (0-63) + union{ + // temporary + final data + uint32_t data; + uint32_t data32; + uint16_t data16[sizeof(data) / sizeof(uint16_t)]; + uint8_t data8[sizeof(data)]; + uint8_t command : 4; + }; + }; + uint8_t raw[sizeof(uint8_t) + sizeof(uint8_t) + sizeof(uint32_t) + sizeof(readBuffer)]; +} NHP_Read_Data_t; + +// protocol data for temporary variables +typedef union { + struct{ + // buffer for write operations + uint8_t writeBuffer[NHP_WRITE_BUFFER_SIZE]; + uint8_t writeLength; + }; + + uint8_t raw[sizeof(writeBuffer) + sizeof(uint8_t)]; +} NHP_Write_Data_t; + +//================================================================================ +// Protocol Function Prototypes +//================================================================================ + +static bool NHPread(uint8_t input, NHP_Read_Data_t* protocol) { + // get old protocol states and save into temporary variables (better compiler optimization) + uint8_t readLength = protocol->readLength; + uint8_t mode; + uint8_t blocks = protocol->blocks; + uint8_t errorLevel = protocol->errorLevel; + uint32_t data = protocol->data; + uint8_t address; + bool newInput = false; + + // completely reset the protocol after sucessfull reading/error last time + if (protocol->mode) { + blocks = 0; + readLength = 0; + } + // check if previous reading had a lead error, copy that lead byte to the beginning + else if (errorLevel == NHP_ERR_LEAD) { + protocol->readBuffer[0] = protocol->readBuffer[readLength]; + readLength = 1; + } + + // write new byte input to the buffer + protocol->readBuffer[readLength++] = input; + + // reset mode and errorLevel to the default (no error, no input) + errorLevel = NHP_ERR_NONE; + mode = NHP_IN_PROGRESS; + + // check the header(lead/data/end) indicator + uint8_t header = input & NHP_HEADER_MASK; + + if (header == NHP_HEADER_LEAD) + { + if (blocks) { + // we were still reading! Log an error but continue reading with this new lead + // set indicator to move this lead byte to the beginning next reading + errorLevel = NHP_ERR_LEAD; + // write the buffer without the new lead, move it next reading + readLength--; + } + + // read command indicator or block length + blocks = (input >> NHP_LENGTH_OFFSET) & (NHP_LENGTH_MASK >> NHP_LENGTH_OFFSET); + + if (blocks == 0 || blocks == 1) { + // save command in data variable + data = input & NHP_COMMAND_MASK; + // return command indicator, reset next reading + mode = NHP_COMMAND; + newInput = true; + } + // address data + else if (blocks == 7) { + // save block length + first 4 data bits (special 32 bit case) + data = input & NHP_DATA_4BIT_MASK; + blocks -= 2; + } + else { + // save block length + first 3 data bits + data = input & NHP_DATA_3BIT_MASK; + blocks--; + } + } + + else if (header == NHP_HEADER_END) + { + // reset next reading on both: valid input or error + if (blocks == 1){ + // valid input, save the address + address = input & NHP_ADDRESS_MASK; + mode = NHP_ADDRESS; + newInput = true; + } + else{ + // too early for an end, reset next time + errorLevel = NHP_ERR_END; + mode = NHP_RESET; + } + } + + else if (header == NHP_HEADER_DATA_A || header == NHP_HEADER_DATA_B) + { + if (blocks >= 2) { + // get next 7 bits of data + blocks--; + data <<= 7; + // normally dont need & NHP_DATA_7BIT_MASK because the MSB bit is zero + data |= (input & NHP_DATA_7BIT_MASK); + } + else { + // log an error, expecting a lead or end byte + errorLevel = NHP_ERR_DATA; + mode = NHP_RESET; + } + } + + // save temporary values to the data struct + protocol->blocks = blocks; + protocol->mode = mode; + protocol->readLength = readLength; + protocol->address = address; + protocol->errorLevel = errorLevel; + protocol->data = data; + + // return if we have a new address or command + return newInput; +} + +//================================================================================ +// Write NHP +//================================================================================ + +static uint8_t NHPwriteCommand(uint8_t command) { + // write lead mask 11 + length 00|0 or 00|1 including the last bit for the 4 bit command + // return the command with protocol around + return NHP_HEADER_LEAD | (command & NHP_COMMAND_MASK); +} + +static void NHPwriteAddress(uint8_t address, uint32_t data, NHP_Write_Data_t* protocol) { + // start with the maximum size of blocks (6+1 for special MSB case) + uint8_t blocks = 7; + + // check for the first 7 bit block that doesnt fit into the first 3 bits + while (blocks > 2) { + uint8_t nextvalue = (data >> (7 * (blocks - 3))); + if (nextvalue > NHP_DATA_3BIT_MASK) { + // data won't fit into the first 3 bits, wee need an extra block for them + // don't write them to the lead block, keep the data for the data blocks + if (blocks == 7) { + // special case for the MSB where we still want to write + // the 'too big' value into the lead block + protocol->writeBuffer[0] = nextvalue; + blocks = 6; + } + break; + } + else { + // write the possible first 3 bits and check again if the value is zero + // this also ensures that the first byte is always initialized + protocol->writeBuffer[0] = nextvalue; + blocks--; + + // we have our first bits, stop + if (nextvalue) + break; + } + } + + // write the rest of the data blocks + uint8_t datablocks = blocks - 2; + while (datablocks > 0) { + protocol->writeBuffer[datablocks] = data & NHP_DATA_7BIT_MASK; + data >>= 7; + datablocks--; + } + + // add lead 11 + length to the first 3 (or 4 for special MSB case) data bits + protocol->writeBuffer[0] |= NHP_HEADER_LEAD | (blocks << NHP_LENGTH_OFFSET); + + // write end 10 + address + protocol->writeBuffer[blocks - 1] = NHP_HEADER_END | (address & NHP_ADDRESS_MASK); + + // save the number of blocks + protocol->writeLength = blocks; +} + +#endif \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/libraries/HIDBridge/keywords.txt b/plugins/KeyboardioHID/avr/libraries/HIDBridge/keywords.txt new file mode 100644 index 0000000000..6ff0971148 --- /dev/null +++ b/plugins/KeyboardioHID/avr/libraries/HIDBridge/keywords.txt @@ -0,0 +1,22 @@ +####################################### +# Syntax Coloring Map For HID-Bridge +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +Gamepad KEYWORD3 + +####################################### +# Instances (KEYWORD2) +####################################### + +####################################### +# Constants (LITERAL1) +####################################### + diff --git a/plugins/KeyboardioHID/avr/platform.txt b/plugins/KeyboardioHID/avr/platform.txt index 051ea4549d..d88615971e 100644 --- a/plugins/KeyboardioHID/avr/platform.txt +++ b/plugins/KeyboardioHID/avr/platform.txt @@ -9,7 +9,7 @@ # https://github.com/NicoHood name=HID Project USB-Core -version=2.1 +version=2.2 # AVR compile variables diff --git a/plugins/KeyboardioHID/avr/variants/leonardo_custom/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/leonardo_custom/pins_arduino.h index ede4dff60b..8901811bb0 100644 --- a/plugins/KeyboardioHID/avr/variants/leonardo_custom/pins_arduino.h +++ b/plugins/KeyboardioHID/avr/variants/leonardo_custom/pins_arduino.h @@ -76,6 +76,7 @@ HID_REPORT_MOUSE(HID_REPORTID_MOUSE) // activate your custom HID-APIs here: #define HID_MOUSE_API_ENABLE +//#define HID_MOUSE_ABSOLUTE_API_ENABLE #define HID_KEYBOARD_API_ENABLE //#define HID_RAWHID_API_ENABLE //#define HID_CONSUMERCONTROL_API_ENABLE @@ -122,6 +123,7 @@ HID_REPORT_MOUSE(HID_REPORTID_MOUSE) // //// activate your custom HID-APIs here: ////#define HID_MOUSE_API_ENABLE +////#define HID_MOUSE_ABSOLUTE_API_ENABLE ////#define HID_KEYBOARD_API_ENABLE ////#define HID_RAWHID_API_ENABLE ////#define HID_CONSUMERCONTROL_API_ENABLE diff --git a/plugins/KeyboardioHID/avr/variants/micro_custom/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/micro_custom/pins_arduino.h index d6a3af8169..d83b4efac0 100644 --- a/plugins/KeyboardioHID/avr/variants/micro_custom/pins_arduino.h +++ b/plugins/KeyboardioHID/avr/variants/micro_custom/pins_arduino.h @@ -76,6 +76,7 @@ HID_REPORT_MOUSE(HID_REPORTID_MOUSE) // activate your custom HID-APIs here: #define HID_MOUSE_API_ENABLE +//#define HID_MOUSE_ABSOLUTE_API_ENABLE #define HID_KEYBOARD_API_ENABLE //#define HID_RAWHID_API_ENABLE //#define HID_CONSUMERCONTROL_API_ENABLE @@ -122,6 +123,7 @@ HID_REPORT_MOUSE(HID_REPORTID_MOUSE) // //// activate your custom HID-APIs here: ////#define HID_MOUSE_API_ENABLE +////#define HID_MOUSE_ABSOLUTE_API_ENABLE ////#define HID_KEYBOARD_API_ENABLE ////#define HID_RAWHID_API_ENABLE ////#define HID_CONSUMERCONTROL_API_ENABLE From 5f0eb9552cc7c48fb620ef65fe234ddc3fd0bfa4 Mon Sep 17 00:00:00 2001 From: Nico Date: Wed, 11 Feb 2015 16:58:07 +0100 Subject: [PATCH 152/602] Added the fixes again had some problems with last commit --- plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.h | 1 + plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.h index 418efb054e..3a9682f775 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.h @@ -131,6 +131,7 @@ class Gamepad_{ inline void dPad1(int8_t d){ _report.dPad1 = d; } inline void dPad2(int8_t d){ _report.dPad2 = d; } +private: HID_GamepadReport_Data_t _report; }; extern Gamepad_ Gamepad; diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h index 1bf159d4ad..f1666501d9 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h @@ -185,7 +185,7 @@ class Keyboard_ : public Print size_t write(uint8_t k); size_t press(uint8_t k); - inline size_t release(uint8_t k); + size_t release(uint8_t k); void releaseAll(void); size_t writeKeycode(uint8_t k); From 248b715e02e58c918b2785e713dcf5fe33419f2a Mon Sep 17 00:00:00 2001 From: Nico Date: Wed, 11 Feb 2015 17:24:14 +0100 Subject: [PATCH 153/602] remove test --- plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h index a7d8782439..418898075f 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h @@ -437,5 +437,5 @@ void HID_SendReport(uint8_t id, const void* data, int len); #ifdef HID_GAMEPAD_API_ENABLE #include "Gamepad.h" #endif -#define kkk + #endif From b8dc98633c61538059ee7119f5c2c0908be6388b Mon Sep 17 00:00:00 2001 From: Nico Date: Wed, 11 Feb 2015 19:19:57 +0100 Subject: [PATCH 154/602] corrected weak hid sending function --- plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.cpp b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.cpp index 60f0840a6c..d661d1557f 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.cpp +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.cpp @@ -112,7 +112,7 @@ 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) +void WEAK HID_SendReport(uint8_t id, const void* data, int len) { USB_Send(HID_TX, &id, 1); USB_Send(HID_TX | TRANSFER_RELEASE, data, len); From 27ed2917614f80749312b81222cc480003788456 Mon Sep 17 00:00:00 2001 From: Nico Date: Sat, 14 Feb 2015 12:37:35 +0100 Subject: [PATCH 155/602] Minor fixes + HIDBridge * increased HW Serial1 RX buffer size from 16 to 32 (TX still 16) * removed fixed size in report buffers * used HID_KeyboardReport_Data_t now in Keyboard API HID Bridge works for transmitting --- plugins/KeyboardioHID/Readme.md | 3 + .../avr/cores/hid/HardwareSerial.h | 2 +- .../avr/cores/hid/USB-Core/Consumer.h | 8 +- .../avr/cores/hid/USB-Core/Gamepad.h | 6 +- .../avr/cores/hid/USB-Core/Keyboard.cpp | 4 +- .../avr/cores/hid/USB-Core/Keyboard.h | 18 +--- .../avr/cores/hid/USB-Core/Mouse.h | 12 +-- .../avr/cores/hid/USB-Core/RawHID.h | 6 +- .../avr/cores/hid/USB-Core/System.h | 2 +- .../avr/libraries/HIDBridge/HIDBridge.cpp | 94 ++++++++++++++----- .../avr/libraries/HIDBridge/HIDBridge.h | 18 +++- 11 files changed, 114 insertions(+), 59 deletions(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 4812d027ca..47f64b89cd 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -65,7 +65,10 @@ Version History ``` 2.2 Release (xx.xx.2015) * added HID-Bridge +* increased HW Serial1 RX buffer size from 16 to 32 (TX still 16) * added colour highlighting (through HID-Bridge library) +* removed fixed size in report buffers +* used HID_KeyboardReport_Data_t now in Keyboard API 2.1 Release (28.01.2015) * Reworked the whole USB-Core from scratch diff --git a/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.h b/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.h index 7f4f162d68..71ad331519 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.h +++ b/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.h @@ -43,7 +43,7 @@ #endif #if !defined(SERIAL_RX_BUFFER_SIZE) #if (RAMEND < 1000) -#define SERIAL_RX_BUFFER_SIZE 16 +#define SERIAL_RX_BUFFER_SIZE 32 #else #define SERIAL_RX_BUFFER_SIZE 64 #endif diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Consumer.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Consumer.h index 3397f523d2..84fc0828ae 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Consumer.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Consumer.h @@ -55,9 +55,9 @@ THE SOFTWARE. typedef union{ // every usable Consumer key possible, up to 4 keys presses possible - uint8_t whole8[8]; - uint16_t whole16[8 / 2]; - uint32_t whole32[8 / 4]; + uint8_t whole8[]; + uint16_t whole16[]; + uint32_t whole32[]; struct{ uint16_t key1; uint16_t key2; @@ -104,7 +104,7 @@ class Consumer_{ HID_SendReport(HID_REPORTID_CONSUMERCONTROL, &_report, sizeof(_report)); } inline void releaseAll(void){ - begin(); + end(); } private: HID_ConsumerControlReport_Data_t _report; diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.h index 3a9682f775..7c3927b73c 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.h @@ -44,9 +44,9 @@ THE SOFTWARE. typedef union { // 32 Buttons, 6 Axis, 2 D-Pads - uint8_t whole8[15]; - uint16_t whole16[15 / 2]; - uint32_t whole32[15 / 4]; + uint8_t whole8[]; + uint16_t whole16[]; + uint32_t whole32[]; uint32_t buttons; struct{ diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.cpp b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.cpp index 148f1e3490..8f2c935cdf 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.cpp +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.cpp @@ -48,9 +48,9 @@ THE SOFTWARE. Keyboard_ Keyboard; -void Keyboard_::sendReport(KeyReport* keys) +void Keyboard_::sendReport(HID_KeyboardReport_Data_t* keys) { - HID_SendReport(HID_REPORTID_KEYBOARD, keys, sizeof(KeyReport)); + HID_SendReport(HID_REPORTID_KEYBOARD, keys, sizeof(HID_KeyboardReport_Data_t)); } extern diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h index f1666501d9..156fc3aa82 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h @@ -145,9 +145,9 @@ THE SOFTWARE. typedef union{ // Low level key report: up to 6 keys and shift, ctrl etc at once - uint8_t whole8[8]; - uint16_t whole16[8 / 2]; - uint32_t whole32[8 / 4]; + uint8_t whole8[]; + uint16_t whole16[]; + uint32_t whole32[]; struct{ uint8_t modifiers; uint8_t reserved; @@ -155,19 +155,11 @@ typedef union{ }; } HID_KeyboardReport_Data_t; -// 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; //TODO typedef union above - class Keyboard_ : public Print { protected: - KeyReport _keyReport; - void sendReport(KeyReport* keys); + HID_KeyboardReport_Data_t _keyReport; + void sendReport(HID_KeyboardReport_Data_t* keys); public: inline Keyboard_(void){ // empty diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.h index 507607a178..fa5b2559cc 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.h @@ -61,9 +61,9 @@ THE SOFTWARE. typedef union{ // mouse report: 8 buttons, position, wheel - uint8_t whole8[4]; - uint16_t whole16[4 / 2]; - uint32_t whole32[4 / 4]; + uint8_t whole8[]; + uint16_t whole16[]; + uint32_t whole32[]; struct{ uint8_t buttons; int8_t xAxis; @@ -74,9 +74,9 @@ typedef union{ typedef union{ // mouse absolute report: 2 absolute axis - uint8_t whole8[4]; - uint16_t whole16[4 / 2]; - uint32_t whole32[4 / 4]; + uint8_t whole8[]; + uint16_t whole16[]; + uint32_t whole32[]; struct{ int16_t xAxis; int16_t yAxis; diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/RawHID.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/RawHID.h index bd31630f6b..f77a36880f 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/RawHID.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/RawHID.h @@ -33,9 +33,9 @@ THE SOFTWARE. typedef union{ // a RAWHID_TX_SIZE byte buffer for rx or tx -uint8_t whole8[RAWHID_TX_SIZE]; -uint16_t whole16[RAWHID_TX_SIZE / 2]; -uint32_t whole32[RAWHID_TX_SIZE / 4]; +uint8_t whole8[]; +uint16_t whole16[]; +uint32_t whole32[]; uint8_t buff[RAWHID_TX_SIZE]; } HID_RawKeyboardReport_Data_t; diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.h index 5c0a2d0624..c8f3a8e280 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.h @@ -37,7 +37,7 @@ THE SOFTWARE. typedef union{ // every usable system control key possible - uint8_t whole8[1]; + uint8_t whole8[]; uint8_t key; } HID_SystemControlReport_Data_t; diff --git a/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.cpp b/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.cpp index ee9a237afd..6f0347636f 100644 --- a/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.cpp +++ b/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.cpp @@ -43,64 +43,107 @@ void HIDBridge_::err(uint8_t error) } -void HIDBridge_::task(void) +void HIDBridge_::readSerial(void) { static NHP_Read_Data_t n = { 0 }; uint8_t error = 0x00; + // read as long as the Serial is available + // but do not block forever + rx_buffer_index_t i = 0; //TODO availabel -> read -1 while (Serial.available()) { - if (NHPread(Serial.read(), &n)) { + // read in new Serial byte and process with NHP protocol + uint8_t b = Serial.read(); + bool newInput = NHPread(b, &n); + + // proceed new valid NHP input + if (newInput) { if (n.mode == NHP_ADDRESS) { switch (n.address) { - case 0: // received a control address command - if (n.data == 0) { + case HIDBRIDGE_ADDRESS_CONTROL: + // acknowledge/request + if (n.data == HIDBRIDGE_CONTROL_ISREADY) isReady = true; - return; - } + + // pause + else if (n.data == HIDBRIDGE_CONTROL_NOTREADY) + isReady = false; + + // not else - error = 3; + err(HID_BRIDGE_ERR_CONTROL); + break; + // received HID out report TODO default: - error = 1; + err(HID_BRIDGE_ERR_ADDRESS); break; - } } - else if (n.mode == NHP_COMMAND) { - - } - else { - error = 2; + // received HID out report TODO + else if (n.mode == NHP_COMMAND) { + error = 4; } + } + // NHP reading error + else if (n.errorLevel) { + error = 2; } + + // do not block forever + if (++i >= SERIAL_RX_BUFFER_SIZE) + break; } - if (error) + if (error){ err(error); + isReady = false; // revert + } } -bool HIDBridge_::ready(void) + +bool HIDBridge_::waitForReady(void) { - //if (!hidReady) { + + uint32_t currentMillis = millis(); + do{ + // check for new state information + // maybe the host sended a pause signal + readSerial(); + + // check for timeout //TODO move 1 up? + if ((millis() - currentMillis) > HIDBRIDGE_TX_TIMEOUT) { + err(1); + return false; + } + } + // try to wait for a new request/acknowledge + while (!isReady) + + return isReady; + + //if (!isReady) { //TODO remove? // // try to wait for a new request/acknowledge // uint32_t currentMillis = millis(); - // while (!hidReady) { - // readHIDReady(); - // if ((millis() - currentMillis) > 1000) { - // errorHID(0); - // return; + // while (!isReady) { + // readSerial(); + // // check for timeout //TODO move 1 up? + // if ((millis() - currentMillis) > HIDBRIDGE_TX_TIMEOUT) { + // err(1); + // return false; // } // } //} + //return true; } // overwrites the HID_SendReport function which is empty/not used on a 328/2560 void HID_SendReport(uint8_t reportID, const void* data, int len) { - // check if we got a request/acknowledge - if (!HIDBridge.ready()){ + // check the latest request/acknowledge, pause, error + if (!HIDBridge.waitForReady()){ HIDBridge.err(0); return; } @@ -118,4 +161,7 @@ void HID_SendReport(uint8_t reportID, const void* data, int len) // end transfer with zero command Serial.write(NHPwriteCommand(0)); + + // need a request/acknowledge next time again + HIDBridge.isReady = false; } \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.h b/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.h index 9874342045..bdf1ba4ee6 100644 --- a/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.h +++ b/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.h @@ -36,6 +36,20 @@ THE SOFTWARE. // Definitions //================================================================================ +#define HIDBRIDGE_TX_TIMEOUT 1000 + +#define HIDBRIDGE_ADDRESS_CONTROL 0 + +#define HIDBRIDGE_CONTROL_ISREADY 0 +#define HIDBRIDGE_CONTROL_NOTREADY 1 + +#define HID_BRIDGE_ERR_TIMEOUT 0 +#define HID_BRIDGE_ERR_NHP_ERR 1 +#define HID_BRIDGE_ERR_COMMAND 2 +#define HID_BRIDGE_ERR_ADDRESS 3 +#define HID_BRIDGE_ERR_CONTROL 4 + + //================================================================================ // HIDBridge //================================================================================ @@ -46,8 +60,8 @@ class HIDBridge_{ HIDBridge_(void); bool begin(void); - - bool ready(void); + void readSerial(void); + bool waitForReady(void); bool isReady; void task(void); void err(uint8_t error); From b49965dbc22e175dadcf28db0c346299f3c03f85 Mon Sep 17 00:00:00 2001 From: Nico Date: Mon, 16 Feb 2015 16:07:31 +0100 Subject: [PATCH 156/602] HID Bridge update --- plugins/KeyboardioHID/avr/boards.txt | 4 - .../avr/libraries/HIDBridge/HIDBridge.cpp | 117 +++++++++--------- .../avr/libraries/HIDBridge/HIDBridge.h | 33 +++-- 3 files changed, 83 insertions(+), 71 deletions(-) diff --git a/plugins/KeyboardioHID/avr/boards.txt b/plugins/KeyboardioHID/avr/boards.txt index b874a87deb..02bc59b0da 100644 --- a/plugins/KeyboardioHID/avr/boards.txt +++ b/plugins/KeyboardioHID/avr/boards.txt @@ -5,10 +5,6 @@ menu.usbcore=USB Core ############################################################## leonardoExtended.name=Arduino Leonardo HID-Project -leonardoExtended.vid.0=0x2341 -leonardoExtended.pid.0=0x0036 -leonardoExtended.vid.1=0x2341 -leonardoExtended.pid.1=0x8036 leonardoExtended.upload.tool=arduino:avrdude leonardoExtended.upload.protocol=avr109 leonardoExtended.upload.maximum_size=28672 diff --git a/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.cpp b/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.cpp index 6f0347636f..9f59045565 100644 --- a/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.cpp +++ b/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.cpp @@ -33,135 +33,134 @@ HIDBridge_::HIDBridge_(void){ // empty } -bool HIDBridge_::begin(void) +bool HIDBridge_::begin(Stream &s) { + begin((Stream*)&s); +} +bool HIDBridge_::begin(Stream* s) +{ + HIDStream = s; } + void HIDBridge_::err(uint8_t error) { - + if (!debug) + return; + debug->println("Softserial"); + debug->println(error); } void HIDBridge_::readSerial(void) { - static NHP_Read_Data_t n = { 0 }; - uint8_t error = 0x00; - // read as long as the Serial is available // but do not block forever - rx_buffer_index_t i = 0; //TODO availabel -> read -1 - while (Serial.available()) { - // read in new Serial byte and process with NHP protocol - uint8_t b = Serial.read(); - bool newInput = NHPread(b, &n); + for (rx_buffer_index_t i = 0; i < SERIAL_RX_BUFFER_SIZE; i++){ + // read in new Serial byte + int b = Serial.read(); + if (b < 0) + break; + + // process with NHP protocol + bool newInput = NHPread(b, &nhp_read); // proceed new valid NHP input if (newInput) { - if (n.mode == NHP_ADDRESS) { - switch (n.address) { + if (nhp_read.mode == NHP_ADDRESS) { + switch (nhp_read.address) { // received a control address command case HIDBRIDGE_ADDRESS_CONTROL: // acknowledge/request - if (n.data == HIDBRIDGE_CONTROL_ISREADY) + if (nhp_read.data == HIDBRIDGE_CONTROL_ISREADY) isReady = true; // pause - else if (n.data == HIDBRIDGE_CONTROL_NOTREADY) + else if (nhp_read.data == HIDBRIDGE_CONTROL_NOTREADY) isReady = false; // not else - err(HID_BRIDGE_ERR_CONTROL); + err(HIDBRIDGE_ERR_CONTROL); break; // received HID out report TODO default: - err(HID_BRIDGE_ERR_ADDRESS); + err(HIDBRIDGE_ERR_ADDRESS); break; } } // received HID out report TODO - else if (n.mode == NHP_COMMAND) { - error = 4; + else if (nhp_read.mode == NHP_COMMAND) { + err(HIDBRIDGE_ERR_COMMAND); } } // NHP reading error - else if (n.errorLevel) { - error = 2; + else if (nhp_read.errorLevel) { + err(HIDBRIDGE_ERR_NHP_ERR); + // do not change isReady state because of a possible full buffer + // which causes NHP corruption } - - // do not block forever - if (++i >= SERIAL_RX_BUFFER_SIZE) - break; - } - - if (error){ - err(error); - isReady = false; // revert } } bool HIDBridge_::waitForReady(void) { - + // try to wait for a new request/acknowledge uint32_t currentMillis = millis(); do{ // check for new state information // maybe the host sended a pause signal readSerial(); - // check for timeout //TODO move 1 up? + // check for timeout if ((millis() - currentMillis) > HIDBRIDGE_TX_TIMEOUT) { - err(1); - return false; + err(HIDBRIDGE_ERR_TIMEOUT); + break; } - } - // try to wait for a new request/acknowledge - while (!isReady) + } while (!isReady); //TODO andn no error in readSerial? return isReady; - - //if (!isReady) { //TODO remove? - // // try to wait for a new request/acknowledge - // uint32_t currentMillis = millis(); - // while (!isReady) { - // readSerial(); - // // check for timeout //TODO move 1 up? - // if ((millis() - currentMillis) > HIDBRIDGE_TX_TIMEOUT) { - // err(1); - // return false; - // } - // } - //} - //return true; } -// overwrites the HID_SendReport function which is empty/not used on a 328/2560 -void HID_SendReport(uint8_t reportID, const void* data, int len) +void HIDBridge_::SendReport(uint8_t reportID, const void* data, int len) { - // check the latest request/acknowledge, pause, error - if (!HIDBridge.waitForReady()){ - HIDBridge.err(0); + // check if stream pointer is set + if (!HIDStream){ + err(HIDBRIDGE_ERR_NO_SPTR); + return; + } + + // check the latest request/acknowledge,a pause, error + if (!waitForReady()){ + err(HIDBRIDGE_ERR_NOT_RDY); return; } // begin transfer with reportID as command - Serial.write(NHPwriteCommand(reportID)); + HIDStream->write(NHPwriteCommand(reportID)); // send data in 4 byte packets with the address of the reportID // the rest (if any, e.g. with 2 byte) is filled with random bytes NHP_Write_Data_t n; for (int i = 0; i < len; i += 4) { NHPwriteAddress(reportID, UINT32_AT_OFFSET(data, i), &n); - Serial.write(n.writeBuffer, n.writeLength); + HIDStream->write(n.writeBuffer, n.writeLength); } // end transfer with zero command - Serial.write(NHPwriteCommand(0)); + HIDStream->write(NHPwriteCommand(0)); // need a request/acknowledge next time again - HIDBridge.isReady = false; + isReady = false; + + err(42); +} + +// overwrites the HID_SendReport function which is empty/not used on a 328/2560 +void HID_SendReport(uint8_t reportID, const void* data, int len) +{ + HIDBridge.SendReport(reportID, data, len); } \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.h b/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.h index bdf1ba4ee6..07e49525f1 100644 --- a/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.h +++ b/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.h @@ -25,6 +25,7 @@ THE SOFTWARE. #define HIDBRIDGE_H #include +#include #include "NHP.h" //================================================================================ @@ -38,16 +39,20 @@ THE SOFTWARE. #define HIDBRIDGE_TX_TIMEOUT 1000 +#define HIDBRIDGE_BAUD 2000000 + #define HIDBRIDGE_ADDRESS_CONTROL 0 #define HIDBRIDGE_CONTROL_ISREADY 0 #define HIDBRIDGE_CONTROL_NOTREADY 1 -#define HID_BRIDGE_ERR_TIMEOUT 0 -#define HID_BRIDGE_ERR_NHP_ERR 1 -#define HID_BRIDGE_ERR_COMMAND 2 -#define HID_BRIDGE_ERR_ADDRESS 3 -#define HID_BRIDGE_ERR_CONTROL 4 +#define HIDBRIDGE_ERR_TIMEOUT 0 +#define HIDBRIDGE_ERR_NHP_ERR 1 +#define HIDBRIDGE_ERR_COMMAND 2 +#define HIDBRIDGE_ERR_ADDRESS 3 +#define HIDBRIDGE_ERR_CONTROL 4 +#define HIDBRIDGE_ERR_NOT_RDY 5 +#define HIDBRIDGE_ERR_NO_SPTR 6 //================================================================================ @@ -58,15 +63,27 @@ THE SOFTWARE. class HIDBridge_{ public: HIDBridge_(void); - - bool begin(void); + inline void debugStream(Stream* s){ + debug = s; + } + bool begin(Stream &s); + bool begin(Stream* s); void readSerial(void); bool waitForReady(void); bool isReady; void task(void); void err(uint8_t error); - inline void write(void){} // TODO + // public to access via HID_SendReport + void SendReport(uint8_t reportID, const void* data, int len); + +private: + Stream* debug; + Stream* HIDStream; //TODO template? + + NHP_Read_Data_t nhp_read; + + }; extern HIDBridge_ HIDBridge; From 0a632f4c211778bcd019aafdae7a3d84b92a1d46 Mon Sep 17 00:00:00 2001 From: Nico Date: Tue, 17 Feb 2015 08:22:00 +0100 Subject: [PATCH 157/602] Arduino as ISP fix for 328 Now it should work with 32u4, 16u2 and 328 and probably others as well --- .../KeyboardioHID/examples/Projects/ArduinoISP/ArduinoISP.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/examples/Projects/ArduinoISP/ArduinoISP.ino b/plugins/KeyboardioHID/examples/Projects/ArduinoISP/ArduinoISP.ino index 03a39d70f7..5a9266e2a3 100644 --- a/plugins/KeyboardioHID/examples/Projects/ArduinoISP/ArduinoISP.ino +++ b/plugins/KeyboardioHID/examples/Projects/ArduinoISP/ArduinoISP.ino @@ -120,7 +120,7 @@ void heartbeat() { if (hbval < 32) hbdelta = -hbdelta; hbval += hbdelta; analogWrite(LED_HB, hbval); - delay(40); + delay(20); } From 5fa0766364ca269234a94d33de06c26395bb6204 Mon Sep 17 00:00:00 2001 From: Nico Date: Tue, 17 Feb 2015 08:22:26 +0100 Subject: [PATCH 158/602] Update Readme.md --- plugins/KeyboardioHID/Readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 47f64b89cd..e50d94b4d0 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -69,6 +69,7 @@ Version History * added colour highlighting (through HID-Bridge library) * removed fixed size in report buffers * used HID_KeyboardReport_Data_t now in Keyboard API +* Arduino as ISP fix for 328 2.1 Release (28.01.2015) * Reworked the whole USB-Core from scratch From 8aefd474bba919274162340abcafde1d8c5ab546 Mon Sep 17 00:00:00 2001 From: Nico Date: Tue, 17 Feb 2015 20:13:24 +0100 Subject: [PATCH 159/602] Moved Keywords.txt to HIDBridge installing is now not needed anymore --- .../avr/libraries/HIDBridge/keywords.txt | 39 +++ .../avr/libraries/HID_Bridge/keywords.txt | 18 -- plugins/KeyboardioHID/keywords.txt | 253 ------------------ 3 files changed, 39 insertions(+), 271 deletions(-) delete mode 100644 plugins/KeyboardioHID/avr/libraries/HID_Bridge/keywords.txt delete mode 100644 plugins/KeyboardioHID/keywords.txt diff --git a/plugins/KeyboardioHID/avr/libraries/HIDBridge/keywords.txt b/plugins/KeyboardioHID/avr/libraries/HIDBridge/keywords.txt index 6ff0971148..897337075b 100644 --- a/plugins/KeyboardioHID/avr/libraries/HIDBridge/keywords.txt +++ b/plugins/KeyboardioHID/avr/libraries/HIDBridge/keywords.txt @@ -10,7 +10,46 @@ # Methods and Functions (KEYWORD2) ####################################### +#USB-related keywords + +USBDevice KEYWORD3 +Keyboard KEYWORD3 +Mouse KEYWORD3 +RawHID KEYWORD3 +System KEYWORD3 +Consumer KEYWORD3 Gamepad KEYWORD3 +press KEYWORD2 +release KEYWORD2 +releaseAll KEYWORD2 +accept KEYWORD2 +click KEYWORD2 +move KEYWORD2 +moveTo KEYWORD2 +isPressed KEYWORD2 +getLeds KEYWORD2 +pressKeycode KEYWORD2 +releaseKeycode KEYWORD2 +writeKeycode KEYWORD2 +addKeycodeToReport KEYWORD2 +removeKeycodeFromReport KEYWORD2 +buttons KEYWORD2 +xAxis KEYWORD2 +yAxis KEYWORD2 +zAxis KEYWORD2 +rxAxis KEYWORD2 +ryAxis KEYWORD2 +rzAxis KEYWORD2 +dPad1 KEYWORD2 +dPad2 KEYWORD2 +HID_SendReport KEYWORD2 +wakeupHost KEYWORD2 +baud KEYWORD2 +stopbits KEYWORD2 +paritytype KEYWORD2 +numbits KEYWORD2 +dtr KEYWORD2 +rts KEYWORD2 ####################################### # Instances (KEYWORD2) diff --git a/plugins/KeyboardioHID/avr/libraries/HID_Bridge/keywords.txt b/plugins/KeyboardioHID/avr/libraries/HID_Bridge/keywords.txt deleted file mode 100644 index f46bacc375..0000000000 --- a/plugins/KeyboardioHID/avr/libraries/HID_Bridge/keywords.txt +++ /dev/null @@ -1,18 +0,0 @@ -####################################### -# Syntax Coloring Map For Ultrasound -####################################### - -####################################### -# Datatypes (KEYWORD1) -####################################### - -Gamepad KEYWORD3 - -####################################### -# Methods and Functions (KEYWORD2) -####################################### - -####################################### -# Constants (LITERAL1) -####################################### - diff --git a/plugins/KeyboardioHID/keywords.txt b/plugins/KeyboardioHID/keywords.txt deleted file mode 100644 index e5f61058c7..0000000000 --- a/plugins/KeyboardioHID/keywords.txt +++ /dev/null @@ -1,253 +0,0 @@ -# LITERAL1 specifies constants - -HIGH LITERAL1 Constants -LOW LITERAL1 Constants -INPUT LITERAL1 Constants -INPUT_PULLUP LITERAL1 Constants -OUTPUT LITERAL1 Constants -DEC LITERAL1 Serial_Print -BIN LITERAL1 Serial_Print -HEX LITERAL1 Serial_Print -OCT LITERAL1 Serial_Print -PI LITERAL1 -HALF_PI LITERAL1 -TWO_PI LITERAL1 -LSBFIRST LITERAL1 ShiftOut -MSBFIRST LITERAL1 ShiftOut -CHANGE LITERAL1 AttachInterrupt -FALLING LITERAL1 AttachInterrupt -RISING LITERAL1 AttachInterrupt -DEFAULT LITERAL1 AnalogReference -EXTERNAL LITERAL1 AnalogReference -INTERNAL LITERAL1 AnalogReference -INTERNAL1V1 LITERAL1 AnalogReference -INTERNAL2V56 LITERAL1 AnalogReference - -# KEYWORD1 specifies datatypes and C/C++ keywords - -boolean KEYWORD1 BooleanVariables -break KEYWORD1 Break -byte KEYWORD1 Byte -case KEYWORD1 SwitchCase -char KEYWORD1 Char -class KEYWORD1 -const KEYWORD1 Const -continue KEYWORD1 Continue -default KEYWORD1 SwitchCase -do KEYWORD1 DoWhile -double KEYWORD1 Double -else KEYWORD1 Else -false KEYWORD1 Constants -float KEYWORD1 Float -for KEYWORD1 For -if KEYWORD1 If -int KEYWORD1 Int -long KEYWORD1 Long -new KEYWORD1 -null KEYWORD1 -private KEYWORD1 -protected KEYWORD1 -public KEYWORD1 -register KEYWORD1 -return KEYWORD1 Return -short KEYWORD1 -signed KEYWORD1 -static KEYWORD1 Static -String KEYWORD1 String -switch KEYWORD1 SwitchCase -this KEYWORD1 -throw KEYWORD1 -try KEYWORD1 -true KEYWORD1 -unsigned KEYWORD1 -void KEYWORD1 Void -while KEYWORD1 While -word KEYWORD1 Word - -# operators aren't highlighted, but may have documentation - -+= IncrementCompound -+ Arithmetic -[] arrayaccess -= assign -& BitwiseAnd -| BitwiseAnd -, -// Comments -?: -{} Braces --- Increment -/ Arithmetic -/* Comments -. dot -== -< greaterthan -<= greaterthanorequalto -++ Increment -!= inequality -<< Bitshift -< lessthan -<= lessthanorequalto -&& Boolean -! Boolean -|| Boolean -- Arithmetic -% Modulo -* Arithmetic -() parentheses ->> Bitshift -; SemiColon --= IncrementCompound - -# these are datatypes, but we've also defined functions to cast to them - -boolean KEYWORD2 boolean_ -byte KEYWORD2 byte_ -char KEYWORD2 char_ -float KEYWORD2 float_ -int KEYWORD2 int_ -long KEYWORD2 long_ -word KEYWORD2 word_ - -# KEYWORD2 specifies methods and functions - -abs KEYWORD2 Abs -acos KEYWORD2 ACos -asin KEYWORD2 ASin -atan KEYWORD2 ATan -atan2 KEYWORD2 ATan2 -ceil KEYWORD2 Ceil -constrain KEYWORD2 Constrain -cos KEYWORD2 Cos -degrees KEYWORD2 -exp KEYWORD2 Exp -floor KEYWORD2 Floor -log KEYWORD2 Log -map KEYWORD2 Map -max KEYWORD2 Max -min KEYWORD2 Min -radians KEYWORD2 -random KEYWORD2 Random -randomSeed KEYWORD2 RandomSeed -round KEYWORD2 -sin KEYWORD2 Sin -sq KEYWORD2 Sq -sqrt KEYWORD2 Sqrt -tan KEYWORD2 Tan -pow KEYWORD2 Pow - -bitRead KEYWORD2 BitRead -bitWrite KEYWORD2 BitWrite -bitSet KEYWORD2 BitSet -bitClear KEYWORD2 BitClear -bit KEYWORD2 Bit -highByte KEYWORD2 HighByte -lowByte KEYWORD2 LowByte - -analogReference KEYWORD2 AnalogReference -analogRead KEYWORD2 AnalogRead -analogWrite KEYWORD2 AnalogWrite -attachInterrupt KEYWORD2 AttachInterrupt -detachInterrupt KEYWORD2 DetachInterrupt -delay KEYWORD2 Delay -delayMicroseconds KEYWORD2 DelayMicroseconds -digitalWrite KEYWORD2 DigitalWrite -digitalRead KEYWORD2 DigitalRead -interrupts KEYWORD2 -millis KEYWORD2 Millis -micros KEYWORD2 Micros -noInterrupts KEYWORD2 NoInterrupts -noTone KEYWORD2 NoTone -pinMode KEYWORD2 PinMode -pulseIn KEYWORD2 PulseIn -shiftIn KEYWORD2 ShiftIn -shiftOut KEYWORD2 ShiftOut -tone KEYWORD2 Tone -yield KEYWORD2 Yield - -Serial KEYWORD3 Serial -Serial1 KEYWORD3 Serial -Serial2 KEYWORD3 Serial -Serial3 KEYWORD3 Serial -SerialUSB KEYWORD3 Serial -begin KEYWORD2 Serial_Begin -end KEYWORD2 Serial_End -peek KEYWORD2 Serial_Peek -read KEYWORD2 Serial_Read -print KEYWORD2 Serial_Print -println KEYWORD2 Serial_Println -available KEYWORD2 Serial_Available -availableForWrite KEYWORD2 -flush KEYWORD2 Serial_Flush -setTimeout KEYWORD2 -find KEYWORD2 -findUntil KEYWORD2 -parseInt KEYWORD2 -parseFloat KEYWORD2 -readBytes KEYWORD2 -readBytesUntil KEYWORD2 -readString KEYWORD2 -readStringUntil KEYWORD2 -trim KEYWORD2 -toUpperCase KEYWORD2 -toLowerCase KEYWORD2 -charAt KEYWORD2 -compareTo KEYWORD2 -concat KEYWORD2 -endsWith KEYWORD2 -startsWith KEYWORD2 -equals KEYWORD2 -equalsIgnoreCase KEYWORD2 -getBytes KEYWORD2 -indexOf KEYWORD2 -lastIndexOf KEYWORD2 -length KEYWORD2 -replace KEYWORD2 -setCharAt KEYWORD2 -substring KEYWORD2 -toCharArray KEYWORD2 -toInt KEYWORD2 - -# USB-related keywords - -USBDevice KEYWORD3 -Keyboard KEYWORD3 -Mouse KEYWORD3 -RawHID KEYWORD3 -System KEYWORD3 -Consumer KEYWORD3 -Gamepad KEYWORD3 -press KEYWORD2 -release KEYWORD2 -releaseAll KEYWORD2 -accept KEYWORD2 -click KEYWORD2 -move KEYWORD2 -moveTo KEYWORD2 -isPressed KEYWORD2 -getLeds KEYWORD2 -pressKeycode KEYWORD2 -releaseKeycode KEYWORD2 -writeKeycode KEYWORD2 -addKeycodeToReport KEYWORD2 -removeKeycodeFromReport KEYWORD2 -buttons KEYWORD2 -xAxis KEYWORD2 -yAxis KEYWORD2 -zAxis KEYWORD2 -rxAxis KEYWORD2 -ryAxis KEYWORD2 -rzAxis KEYWORD2 -dPad1 KEYWORD2 -dPad2 KEYWORD2 -HID_SendReport KEYWORD2 -wakeupHost KEYWORD2 -baud KEYWORD2 -stopbits KEYWORD2 -paritytype KEYWORD2 -numbits KEYWORD2 -dtr KEYWORD2 -rts KEYWORD2 - -setup KEYWORD3 Setup -loop KEYWORD3 Loop From 7a80b3d6d2c304b4df79c08f472eeebdc6ac44bc Mon Sep 17 00:00:00 2001 From: Nico Date: Tue, 17 Feb 2015 20:15:23 +0100 Subject: [PATCH 160/602] Updated HIDBridge and NHP --- .../avr/libraries/HIDBridge/HIDBridge.cpp | 102 +++++---- .../avr/libraries/HIDBridge/HIDBridge.h | 83 +++++-- .../avr/libraries/HIDBridge/NHP.c | 195 +++++++++++++++++ .../avr/libraries/HIDBridge/NHP.h | 202 +++--------------- 4 files changed, 356 insertions(+), 226 deletions(-) create mode 100644 plugins/KeyboardioHID/avr/libraries/HIDBridge/NHP.c diff --git a/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.cpp b/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.cpp index 9f59045565..438b649c3c 100644 --- a/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.cpp +++ b/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.cpp @@ -24,23 +24,33 @@ THE SOFTWARE. #include "HIDBridge.h" //================================================================================ -// HIDBridge +// HIDBridge TX //================================================================================ +#ifdef HIDBRIDGE_TX + HIDBridge_ HIDBridge; HIDBridge_::HIDBridge_(void){ // empty } -bool HIDBridge_::begin(Stream &s) +void HIDBridge_::begin(void) { - begin((Stream*)&s); + // start the serial at our own baud rate + HIDBRIDGE_TX_SERIAL.begin(HIDBRIDGE_BAUD); + + // wait for the first request to see if usb device is connected + available(); } -bool HIDBridge_::begin(Stream* s) +void HIDBridge_::end(void) { - HIDStream = s; + // end the serial transmission and reset our helper values + HIDBRIDGE_TX_SERIAL.end(); + nhp_read.mode = NHP_RESET; + isReady = false; + isConnected = false; } @@ -48,48 +58,60 @@ void HIDBridge_::err(uint8_t error) { if (!debug) return; - debug->println("Softserial"); + debug->print("Bridge Err TX: "); debug->println(error); } -void HIDBridge_::readSerial(void) +void HIDBridge_::read(void) { // read as long as the Serial is available // but do not block forever for (rx_buffer_index_t i = 0; i < SERIAL_RX_BUFFER_SIZE; i++){ + // read in new Serial byte - int b = Serial.read(); + int b = HIDBRIDGE_TX_SERIAL.read(); if (b < 0) break; // process with NHP protocol - bool newInput = NHPread(b, &nhp_read); + bool newInput = readNHP(b, &nhp_read); // proceed new valid NHP input if (newInput) { + + // NHP address contains control data or out report data if (nhp_read.mode == NHP_ADDRESS) { - switch (nhp_read.address) { - // received a control address command - case HIDBRIDGE_ADDRESS_CONTROL: + + // received a control address command + if (nhp_read.address == HIDBRIDGE_ADDRESS_CONTROL) { // acknowledge/request - if (nhp_read.data == HIDBRIDGE_CONTROL_ISREADY) + if (nhp_read.data == HIDBRIDGE_CONTROL_ISREADY){ isReady = true; + isConnected = true; + } // pause - else if (nhp_read.data == HIDBRIDGE_CONTROL_NOTREADY) + else if (nhp_read.data == HIDBRIDGE_CONTROL_NOTREADY){ isReady = false; + isConnected = true; + } - // not + // usb device detached + else if (nhp_read.data == HIDBRIDGE_CONTROL_NOTCONNECTED){ + isReady = false; + isConnected = false; + } + + // not defined control command else err(HIDBRIDGE_ERR_CONTROL); + } - break; - // received HID out report TODO - default: + // received HID out report TODO + else err(HIDBRIDGE_ERR_ADDRESS); - break; - } } + // received HID out report TODO else if (nhp_read.mode == NHP_COMMAND) { err(HIDBRIDGE_ERR_COMMAND); @@ -106,52 +128,46 @@ void HIDBridge_::readSerial(void) } -bool HIDBridge_::waitForReady(void) +bool HIDBridge_::available(void) { // try to wait for a new request/acknowledge uint32_t currentMillis = millis(); do{ // check for new state information // maybe the host sended a pause signal - readSerial(); + read(); - // check for timeout - if ((millis() - currentMillis) > HIDBRIDGE_TX_TIMEOUT) { + // check for timeout, do not wait longer if usb device is not connected + if (!isConnected || (millis() - currentMillis) > HIDBRIDGE_TX_TIMEOUT) { err(HIDBRIDGE_ERR_TIMEOUT); break; } - } while (!isReady); //TODO andn no error in readSerial? + } while (!isReady); return isReady; } void HIDBridge_::SendReport(uint8_t reportID, const void* data, int len) { - // check if stream pointer is set - if (!HIDStream){ - err(HIDBRIDGE_ERR_NO_SPTR); - return; - } - - // check the latest request/acknowledge,a pause, error - if (!waitForReady()){ + // check the latest request/acknowledge, pause or error + if (!available()){ err(HIDBRIDGE_ERR_NOT_RDY); return; } // begin transfer with reportID as command - HIDStream->write(NHPwriteCommand(reportID)); + HIDBRIDGE_TX_SERIAL.write(writeNHPCommand(reportID)); // send data in 4 byte packets with the address of the reportID // the rest (if any, e.g. with 2 byte) is filled with random bytes NHP_Write_Data_t n; for (int i = 0; i < len; i += 4) { - NHPwriteAddress(reportID, UINT32_AT_OFFSET(data, i), &n); - HIDStream->write(n.writeBuffer, n.writeLength); + writeNHPAddress(reportID, UINT32_AT_OFFSET(data, i), &n); + HIDBRIDGE_TX_SERIAL.write(n.writeBuffer, n.writeLength); } // end transfer with zero command - HIDStream->write(NHPwriteCommand(0)); + HIDBRIDGE_TX_SERIAL.write(writeNHPCommand(0)); // need a request/acknowledge next time again isReady = false; @@ -163,4 +179,14 @@ void HIDBridge_::SendReport(uint8_t reportID, const void* data, int len) void HID_SendReport(uint8_t reportID, const void* data, int len) { HIDBridge.SendReport(reportID, data, len); -} \ No newline at end of file +} + +#endif // #ifdef HIDBRIDGE_TX + +//================================================================================ +// HIDBridge RX +//================================================================================ + +#ifdef HIDBRIDGE_RX + +#endif // #ifdef HIDBRIDGE_RX \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.h b/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.h index 07e49525f1..b3aaf7db0d 100644 --- a/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.h +++ b/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.h @@ -25,18 +25,31 @@ THE SOFTWARE. #define HIDBRIDGE_H #include -#include #include "NHP.h" //================================================================================ // Settings //================================================================================ +#define HIDBRIDGE_TX_SERIAL Serial + +#ifdef HOODLOADER2 +#define HIDBRIDGE_RX +#else +#define HIDBRIDGE_TX +#endif //================================================================================ // Definitions //================================================================================ +#if defined(HIDBRIDGE_RX) && defined(HIDBRIDGE_TX) +#error Cannot send and receive at the same time +// also because it will create the instance of the class +// even if its not used, so we dont separate the TX and RX class names +// function names are kept similar +#endif + #define HIDBRIDGE_TX_TIMEOUT 1000 #define HIDBRIDGE_BAUD 2000000 @@ -45,6 +58,7 @@ THE SOFTWARE. #define HIDBRIDGE_CONTROL_ISREADY 0 #define HIDBRIDGE_CONTROL_NOTREADY 1 +#define HIDBRIDGE_CONTROL_NOTCONNECTED 1 #define HIDBRIDGE_ERR_TIMEOUT 0 #define HIDBRIDGE_ERR_NHP_ERR 1 @@ -52,41 +66,82 @@ THE SOFTWARE. #define HIDBRIDGE_ERR_ADDRESS 3 #define HIDBRIDGE_ERR_CONTROL 4 #define HIDBRIDGE_ERR_NOT_RDY 5 -#define HIDBRIDGE_ERR_NO_SPTR 6 //================================================================================ -// HIDBridge +// HIDBridge TX //================================================================================ - +#ifdef HIDBRIDGE_TX class HIDBridge_{ public: HIDBridge_(void); + + // user functions + void begin(void); + void end(void); + + // advanced user functions + void read(void); + bool available(void); + + // public to access via HID_SendReport + void SendReport(uint8_t reportID, const void* data, int len); + + // debug + void err(uint8_t error); inline void debugStream(Stream* s){ debug = s; } - bool begin(Stream &s); - bool begin(Stream* s); - void readSerial(void); - bool waitForReady(void); + Stream* debug; + +private: bool isReady; - void task(void); - void err(uint8_t error); + bool isConnected; + + // temporary NHP protocol read data + NHP_Read_Data_t nhp_read; +}; + +extern HIDBridge_ HIDBridge; +#endif + +//================================================================================ +// HIDBridge RX +//================================================================================ + +#ifdef HIDBRIDGE_RX +class HIDBridge_{ +public: + HIDBridge_(void); + + // user functions + void begin(void); + void end(void); + + // advanced user functions + void read(void); + bool available(void); // public to access via HID_SendReport void SendReport(uint8_t reportID, const void* data, int len); -private: + // debug + void err(uint8_t error); + inline void debugStream(Stream* s){ + debug = s; + } Stream* debug; - Stream* HIDStream; //TODO template? - - NHP_Read_Data_t nhp_read; +private: + bool isReady; + // temporary NHP protocol read data + NHP_Read_Data_t nhp_read; }; extern HIDBridge_ HIDBridge; +#endif //================================================================================ // Function prototypes diff --git a/plugins/KeyboardioHID/avr/libraries/HIDBridge/NHP.c b/plugins/KeyboardioHID/avr/libraries/HIDBridge/NHP.c new file mode 100644 index 0000000000..d2560fc901 --- /dev/null +++ b/plugins/KeyboardioHID/avr/libraries/HIDBridge/NHP.c @@ -0,0 +1,195 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 "NHP.h" + +//================================================================================ +// Read NHP +//================================================================================ + +bool readNHP(uint8_t input, NHP_Read_Data_t* protocol) { + // get old protocol states and save into temporary variables (better compiler optimization) + uint8_t readLength = protocol->readLength; + uint8_t mode; + uint8_t blocks = protocol->blocks; + uint8_t errorLevel = protocol->errorLevel; + uint32_t data = protocol->data; + uint8_t address; + bool newInput = false; + + // completely reset the protocol after sucessfull reading/error last time + if (protocol->mode) { + blocks = 0; + readLength = 0; + } + // check if previous reading had a lead error, copy that lead byte to the beginning + else if (errorLevel == NHP_ERR_LEAD) { + protocol->readBuffer[0] = protocol->readBuffer[readLength]; + readLength = 1; + } + + // write new byte input to the buffer + protocol->readBuffer[readLength++] = input; + + // reset mode and errorLevel to the default (no error, no input) + errorLevel = NHP_ERR_NONE; + mode = NHP_IN_PROGRESS; + + // check the header(lead/data/end) indicator + uint8_t header = input & NHP_HEADER_MASK; + + if (header == NHP_HEADER_LEAD) + { + if (blocks) { + // we were still reading! Log an error but continue reading with this new lead + // set indicator to move this lead byte to the beginning next reading + errorLevel = NHP_ERR_LEAD; + // write the buffer without the new lead, move it next reading + readLength--; + } + + // read command indicator or block length + blocks = (input >> NHP_LENGTH_OFFSET) & (NHP_LENGTH_MASK >> NHP_LENGTH_OFFSET); + + if (blocks == NHP_LENGTH_COMMAND_0 || blocks == NHP_LENGTH_COMMAND_1) { + // save command in data variable + data = input & NHP_COMMAND_MASK; + // return command indicator, reset next reading + mode = NHP_COMMAND; + newInput = true; + } + // address data + else if (blocks == NHP_LENGTH_HIGH_MSB31) { + // save block length + first 4 data bits (special 32 bit case) + data = input & NHP_DATA_4BIT_MASK; + blocks -= 2; + } + else { + // save block length + first 3 data bits + data = input & NHP_DATA_3BIT_MASK; + blocks--; + } + } + + else if (header == NHP_HEADER_END) + { + // reset next reading on both: valid input or error + if (blocks == 1){ + // valid input, save the address + address = input & NHP_ADDRESS_MASK; + mode = NHP_ADDRESS; + newInput = true; + } + else{ + // too early for an end, reset next time + errorLevel = NHP_ERR_END; + mode = NHP_RESET; + } + } + + else if (header == NHP_HEADER_DATA_A || header == NHP_HEADER_DATA_B) + { + if (blocks > 1) { + // get next 7 bits of data + blocks--; + data <<= NHP_DATA_7BIT; + // normally dont need & NHP_DATA_7BIT_MASK because the MSB bit is zero + data |= (input & NHP_DATA_7BIT_MASK); + } + else { + // log an error, expecting a lead or end byte + errorLevel = NHP_ERR_DATA; + mode = NHP_RESET; + } + } + + // save temporary values to the data struct + protocol->blocks = blocks; + protocol->mode = mode; + protocol->readLength = readLength; + protocol->address = address; + protocol->errorLevel = errorLevel; + protocol->data = data; + + // return if we have a new address or command + return newInput; +} + +//================================================================================ +// Write NHP +//================================================================================ + +uint8_t writeNHPCommand(uint8_t command) { + // write lead mask 11 + length 00|0 or 00|1 including the last bit for the 4 bit command + // return the command with protocol around + return NHP_HEADER_LEAD | (command & NHP_COMMAND_MASK); +} + +void writeNHPAddress(uint8_t address, uint32_t data, NHP_Write_Data_t* protocol) { + // start with the maximum size of blocks (6+1 for special MSB case) + uint8_t blocks = 7; + + // check for the first 7 bit block that doesnt fit into the first 3 bits + while (blocks > 2) { + // get the next 7 bit data block, starting from MSB to LSB + uint8_t nextvalue = (data >> (7 * (blocks - 3))); + if (nextvalue > NHP_DATA_3BIT_MASK) { + // data won't fit into the first 3 bits, wee need an extra block for them + // don't write them to the lead block, keep the data for the data blocks + if (blocks == 7) { + // special case for the MSB where we still want to write + // the 'too big' value into the lead block + protocol->writeBuffer[0] = nextvalue; + blocks = 6; + } + break; + } + else { + // write the possible first 3 bits and check again if the value is zero + // this also ensures that the first byte is always initialized + protocol->writeBuffer[0] = nextvalue; + blocks--; + + // we have our first bits, stop + if (nextvalue) + break; + } + } + + // write the rest of the data blocks + uint8_t datablocks = blocks - 2; + while (datablocks > 0) { + protocol->writeBuffer[datablocks] = data & NHP_DATA_7BIT_MASK; + data >>= 7; + datablocks--; + } + + // add lead 11 + length to the first 3 (or 4 for special MSB case) data bits + protocol->writeBuffer[0] |= NHP_HEADER_LEAD | (blocks << NHP_LENGTH_OFFSET); + + // write end 10 + address + protocol->writeBuffer[blocks - 1] = NHP_HEADER_END | (address & NHP_ADDRESS_MASK); + + // save the number of blocks + protocol->writeLength = blocks; +} \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/libraries/HIDBridge/NHP.h b/plugins/KeyboardioHID/avr/libraries/HIDBridge/NHP.h index 99e8eeeb74..71e29f9140 100644 --- a/plugins/KeyboardioHID/avr/libraries/HIDBridge/NHP.h +++ b/plugins/KeyboardioHID/avr/libraries/HIDBridge/NHP.h @@ -24,10 +24,14 @@ THE SOFTWARE. #ifndef NHP_H #define NHP_H + +#ifdef __cplusplus +extern "C"{ +#endif + #include //uint_t definitions #include //bool type - //================================================================================ //Settings //================================================================================ @@ -48,9 +52,13 @@ THE SOFTWARE. // Lead #define NHP_LENGTH_MASK 0x38 // B00|111|000 #define NHP_LENGTH_OFFSET 3 +#define NHP_LENGTH_COMMAND_0 0 // length 0 indicates a command +#define NHP_LENGTH_COMMAND_1 1 // length 1 indicates a command +#define NHP_LENGTH_HIGH_MSB31 7 // length 7 indicates MSB 31 is high (1) #define NHP_COMMAND_MASK 0x0F // B0000|1111 // 4bit command(0-15) in lead block // Data +#define NHP_DATA_7BIT 7 // data blocks contain 7 bit of information #define NHP_DATA_7BIT_MASK 0x7F // B0|1111111 // data in data block #define NHP_DATA_4BIT_MASK 0x0F // B0000|1111 // data in lead (32 bit special MSB case) #define NHP_DATA_3BIT_MASK 0x07 // B00000|111 // data in lead @@ -79,9 +87,13 @@ THE SOFTWARE. #define UINT16_AT_OFFSET(p_to_8, offset) ((uint16_t)*((const uint16_t *)((p_to_8)+(offset)))) #define UINT32_AT_OFFSET(p_to_8, offset) ((uint32_t)*((const uint32_t *)((p_to_8)+(offset)))) -// protocol data for temporary variables +//================================================================================ +// Typedefs +//================================================================================ + +// protocol read data for temporary variables typedef union { - struct { //TODO change order to save flash? + struct { // buffer for read operations uint8_t readBuffer[NHP_READ_BUFFER_SIZE]; @@ -96,15 +108,15 @@ typedef union { // temporary + final data uint32_t data; uint32_t data32; - uint16_t data16[sizeof(data) / sizeof(uint16_t)]; - uint8_t data8[sizeof(data)]; + uint16_t data16[sizeof(uint32_t) / sizeof(uint16_t)]; + uint8_t data8[sizeof(uint32_t) / sizeof(uint8_t)]; uint8_t command : 4; }; }; - uint8_t raw[sizeof(uint8_t) + sizeof(uint8_t) + sizeof(uint32_t) + sizeof(readBuffer)]; + uint8_t raw[NHP_READ_BUFFER_SIZE + sizeof(uint8_t) + sizeof(uint8_t) + sizeof(uint32_t)]; } NHP_Read_Data_t; -// protocol data for temporary variables +// protocol write data for temporary variables typedef union { struct{ // buffer for write operations @@ -112,177 +124,19 @@ typedef union { uint8_t writeLength; }; - uint8_t raw[sizeof(writeBuffer) + sizeof(uint8_t)]; + uint8_t raw[NHP_WRITE_BUFFER_SIZE + sizeof(uint8_t)]; } NHP_Write_Data_t; //================================================================================ -// Protocol Function Prototypes -//================================================================================ - -static bool NHPread(uint8_t input, NHP_Read_Data_t* protocol) { - // get old protocol states and save into temporary variables (better compiler optimization) - uint8_t readLength = protocol->readLength; - uint8_t mode; - uint8_t blocks = protocol->blocks; - uint8_t errorLevel = protocol->errorLevel; - uint32_t data = protocol->data; - uint8_t address; - bool newInput = false; - - // completely reset the protocol after sucessfull reading/error last time - if (protocol->mode) { - blocks = 0; - readLength = 0; - } - // check if previous reading had a lead error, copy that lead byte to the beginning - else if (errorLevel == NHP_ERR_LEAD) { - protocol->readBuffer[0] = protocol->readBuffer[readLength]; - readLength = 1; - } - - // write new byte input to the buffer - protocol->readBuffer[readLength++] = input; - - // reset mode and errorLevel to the default (no error, no input) - errorLevel = NHP_ERR_NONE; - mode = NHP_IN_PROGRESS; - - // check the header(lead/data/end) indicator - uint8_t header = input & NHP_HEADER_MASK; - - if (header == NHP_HEADER_LEAD) - { - if (blocks) { - // we were still reading! Log an error but continue reading with this new lead - // set indicator to move this lead byte to the beginning next reading - errorLevel = NHP_ERR_LEAD; - // write the buffer without the new lead, move it next reading - readLength--; - } - - // read command indicator or block length - blocks = (input >> NHP_LENGTH_OFFSET) & (NHP_LENGTH_MASK >> NHP_LENGTH_OFFSET); - - if (blocks == 0 || blocks == 1) { - // save command in data variable - data = input & NHP_COMMAND_MASK; - // return command indicator, reset next reading - mode = NHP_COMMAND; - newInput = true; - } - // address data - else if (blocks == 7) { - // save block length + first 4 data bits (special 32 bit case) - data = input & NHP_DATA_4BIT_MASK; - blocks -= 2; - } - else { - // save block length + first 3 data bits - data = input & NHP_DATA_3BIT_MASK; - blocks--; - } - } - - else if (header == NHP_HEADER_END) - { - // reset next reading on both: valid input or error - if (blocks == 1){ - // valid input, save the address - address = input & NHP_ADDRESS_MASK; - mode = NHP_ADDRESS; - newInput = true; - } - else{ - // too early for an end, reset next time - errorLevel = NHP_ERR_END; - mode = NHP_RESET; - } - } - - else if (header == NHP_HEADER_DATA_A || header == NHP_HEADER_DATA_B) - { - if (blocks >= 2) { - // get next 7 bits of data - blocks--; - data <<= 7; - // normally dont need & NHP_DATA_7BIT_MASK because the MSB bit is zero - data |= (input & NHP_DATA_7BIT_MASK); - } - else { - // log an error, expecting a lead or end byte - errorLevel = NHP_ERR_DATA; - mode = NHP_RESET; - } - } - - // save temporary values to the data struct - protocol->blocks = blocks; - protocol->mode = mode; - protocol->readLength = readLength; - protocol->address = address; - protocol->errorLevel = errorLevel; - protocol->data = data; - - // return if we have a new address or command - return newInput; -} - -//================================================================================ -// Write NHP +// Function Prototypes //================================================================================ -static uint8_t NHPwriteCommand(uint8_t command) { - // write lead mask 11 + length 00|0 or 00|1 including the last bit for the 4 bit command - // return the command with protocol around - return NHP_HEADER_LEAD | (command & NHP_COMMAND_MASK); -} - -static void NHPwriteAddress(uint8_t address, uint32_t data, NHP_Write_Data_t* protocol) { - // start with the maximum size of blocks (6+1 for special MSB case) - uint8_t blocks = 7; - - // check for the first 7 bit block that doesnt fit into the first 3 bits - while (blocks > 2) { - uint8_t nextvalue = (data >> (7 * (blocks - 3))); - if (nextvalue > NHP_DATA_3BIT_MASK) { - // data won't fit into the first 3 bits, wee need an extra block for them - // don't write them to the lead block, keep the data for the data blocks - if (blocks == 7) { - // special case for the MSB where we still want to write - // the 'too big' value into the lead block - protocol->writeBuffer[0] = nextvalue; - blocks = 6; - } - break; - } - else { - // write the possible first 3 bits and check again if the value is zero - // this also ensures that the first byte is always initialized - protocol->writeBuffer[0] = nextvalue; - blocks--; - - // we have our first bits, stop - if (nextvalue) - break; - } - } - - // write the rest of the data blocks - uint8_t datablocks = blocks - 2; - while (datablocks > 0) { - protocol->writeBuffer[datablocks] = data & NHP_DATA_7BIT_MASK; - data >>= 7; - datablocks--; - } - - // add lead 11 + length to the first 3 (or 4 for special MSB case) data bits - protocol->writeBuffer[0] |= NHP_HEADER_LEAD | (blocks << NHP_LENGTH_OFFSET); - - // write end 10 + address - protocol->writeBuffer[blocks - 1] = NHP_HEADER_END | (address & NHP_ADDRESS_MASK); +bool readNHP(uint8_t input, NHP_Read_Data_t* protocol); +uint8_t writeNHPCommand(uint8_t command); +void writeNHPAddress(uint8_t address, uint32_t data, NHP_Write_Data_t* protocol); - // save the number of blocks - protocol->writeLength = blocks; -} +#ifdef __cplusplus +} // extern "C" +#endif -#endif \ No newline at end of file +#endif // include guard \ No newline at end of file From 9039c5a4f5df76841d224f2c0cb956d263b152bd Mon Sep 17 00:00:00 2001 From: Nico Date: Tue, 17 Feb 2015 20:26:14 +0100 Subject: [PATCH 161/602] Applied last SoftSerial fix --- .../avr/libraries/SoftwareSerial/SoftwareSerial.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/SoftwareSerial.cpp b/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/SoftwareSerial.cpp index b28e6e4223..8ccbbb4f6a 100644 --- a/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/SoftwareSerial.cpp +++ b/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/SoftwareSerial.cpp @@ -266,8 +266,12 @@ SoftwareSerial::~SoftwareSerial() void SoftwareSerial::setTX(uint8_t tx) { + // First write, then set output. If we do this the other way around, + // the pin would be output low for a short while before switching to + // output hihg. Now, it is input with pullup for a short while, which + // is fine. With inverse logic, either order is fine. + digitalWrite(tx, _inverse_logic ? LOW : HIGH); pinMode(tx, OUTPUT); - digitalWrite(tx, HIGH); _transmitBitMask = digitalPinToBitMask(tx); uint8_t port = digitalPinToPort(tx); _transmitPortRegister = portOutputRegister(port); From 3ef42f9d23b461be430a629bd4495370b7fec070 Mon Sep 17 00:00:00 2001 From: Nico Date: Wed, 18 Feb 2015 09:53:08 +0100 Subject: [PATCH 162/602] Update Readme.md --- plugins/KeyboardioHID/Readme.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index e50d94b4d0..e94915399e 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -54,9 +54,7 @@ Check Keyboard keycode function again? + add example Generalize HID key definitions via HIDTables for example? Test with Android phone (HL1) -HID-Bridge + Firmwares (planned for 2.2) - -HL2 usb hub fix (try with a bare cdc bootloader?) +improve keywords.txt ``` @@ -64,12 +62,13 @@ Version History =============== ``` 2.2 Release (xx.xx.2015) -* added HID-Bridge +* added HID-Bridge between 16u2 and 328/2560 * increased HW Serial1 RX buffer size from 16 to 32 (TX still 16) * added colour highlighting (through HID-Bridge library) * removed fixed size in report buffers * used HID_KeyboardReport_Data_t now in Keyboard API * Arduino as ISP fix for 328 +* Upload verification on USB hubs fix for HL2.0.4 2.1 Release (28.01.2015) * Reworked the whole USB-Core from scratch From cff4551a7771a5a184bd4a3467490c16d06396a5 Mon Sep 17 00:00:00 2001 From: Nico Date: Fri, 20 Feb 2015 10:52:46 +0100 Subject: [PATCH 163/602] Update Readme.md --- plugins/KeyboardioHID/Readme.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index e94915399e..2d0ddf8b0d 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -8,6 +8,8 @@ This project went through a lot of phases and has now reached a new Arduino USB- with a lot of new functions like extended HID. It also supports HoodLoader1+2. The idea is to enable enhanced USB functions to almost all 'standard' Arduino boards. +See the [wiki](https://github.com/NicoHood/HID/wiki/Features) for more information about features etc. + Download ======== @@ -69,6 +71,7 @@ Version History * used HID_KeyboardReport_Data_t now in Keyboard API * Arduino as ISP fix for 328 * Upload verification on USB hubs fix for HL2.0.4 +* No USB workaround for Leonardo integrated into variants 2.1 Release (28.01.2015) * Reworked the whole USB-Core from scratch From 4b9fa617e0dcb0ff6db37bc9b9a8bf1621777a6d Mon Sep 17 00:00:00 2001 From: Nico Date: Fri, 20 Feb 2015 14:33:11 +0100 Subject: [PATCH 164/602] Added Runbootloader example Alternative way to the USB-Serial Bridge --- .../HoodLoader2_RunBootloader.ino | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 plugins/KeyboardioHID/examples/Projects/HoodLoader2_RunBootloader/HoodLoader2_RunBootloader.ino diff --git a/plugins/KeyboardioHID/examples/Projects/HoodLoader2_RunBootloader/HoodLoader2_RunBootloader.ino b/plugins/KeyboardioHID/examples/Projects/HoodLoader2_RunBootloader/HoodLoader2_RunBootloader.ino new file mode 100644 index 0000000000..fc6bd37383 --- /dev/null +++ b/plugins/KeyboardioHID/examples/Projects/HoodLoader2_RunBootloader/HoodLoader2_RunBootloader.ino @@ -0,0 +1,33 @@ +/* + Copyright (c) 2015 NicoHood + See the readme for credit to other people. + + HoodLoader2 Run Bootloader example + + Starts Bootloader mode. + This is useful if you only want to use + the USB-Serial bridge again. + + You could delete the program with avrdude, + but this sketch is way simpler to upload. + + It forces a watchdog reset, + meaning the bootloader is started completely indipendant. +*/ + +#include + +void setup() { + // close interrupts + cli(); + + // write magic key to ram + *(uint8_t *)0x0280 = 0x77; + + // watchdog reset + wdt_enable(WDTO_120MS); +} + +void loop() { + // wait for reset +} From 88c80f96f5b275e99a94d246d1a8a6ff88c83c2c Mon Sep 17 00:00:00 2001 From: Nico Date: Fri, 20 Feb 2015 14:43:22 +0100 Subject: [PATCH 165/602] Updated USB-Serial Made it a little prettier --- .../Projects/USB-Serial/USB-Serial.ino | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/plugins/KeyboardioHID/examples/Projects/USB-Serial/USB-Serial.ino b/plugins/KeyboardioHID/examples/Projects/USB-Serial/USB-Serial.ino index 1c9e7eb9e4..9f6d757c26 100644 --- a/plugins/KeyboardioHID/examples/Projects/USB-Serial/USB-Serial.ino +++ b/plugins/KeyboardioHID/examples/Projects/USB-Serial/USB-Serial.ino @@ -24,29 +24,29 @@ void setup() { void loop() { // USB -> Serial - for (int i = 0; i < USB_EP_SIZE; i++) { + uint8_t i; + for (i = 0; i < USB_EP_SIZE; i++) { // read maximum one EP_SIZE to not block - if (Serial.available()) - Serial1.write(Serial.read()); - else break; + int b = Serial.read(); + if (b < 0) + break; + Serial1.write(b); } // Serial -> USB - if (Serial1.available()) { - // send maximum one EP_SIZE to give the usb some time to flush the buffer - uint8_t buff[USB_EP_SIZE - 1]; - int i = 0; - for (i = 0; i < sizeof(buff); i++) { - if (Serial1.available()) - buff[i] = Serial1.read(); - else break; - } - Serial.write(buff, i); + uint8_t buff[USB_EP_SIZE]; + for (i = 0; i < sizeof(buff); i++) { + // read maximum one EP_SIZE to not block + int b = Serial1.read(); + if (b < 0) + break; + buff[i] = b; } + // send maximum one EP_SIZE to give the usb some time to flush the buffer + Serial.write(buff, i); } -void CDC_LineEncodingEvent(void) -{ +void CDC_LineEncodingEvent(void) { // start HW Serial with new baud rate Serial1.end(); Serial1.begin(Serial.baud()); From 720b06dd823ec065a93c4ce2b57e542023a77af8 Mon Sep 17 00:00:00 2001 From: Nico Date: Fri, 20 Feb 2015 14:43:50 +0100 Subject: [PATCH 166/602] Updated HID-Bridge Now works for USB and IO AVR. Still not complete. --- .../avr/libraries/HIDBridge/HIDBridge.cpp | 336 ++++++++++++++---- .../avr/libraries/HIDBridge/HIDBridge.h | 114 +++--- 2 files changed, 331 insertions(+), 119 deletions(-) diff --git a/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.cpp b/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.cpp index 438b649c3c..99c32aa7e8 100644 --- a/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.cpp +++ b/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.cpp @@ -23,12 +23,6 @@ THE SOFTWARE. #include "HIDBridge.h" -//================================================================================ -// HIDBridge TX -//================================================================================ - -#ifdef HIDBRIDGE_TX - HIDBridge_ HIDBridge; HIDBridge_::HIDBridge_(void){ @@ -38,19 +32,23 @@ HIDBridge_::HIDBridge_(void){ void HIDBridge_::begin(void) { // start the serial at our own baud rate - HIDBRIDGE_TX_SERIAL.begin(HIDBRIDGE_BAUD); + HIDBRIDGE_SERIAL.begin(HIDBRIDGE_BAUD); + + rxReady = true; + txReady = false; //move to end? - // wait for the first request to see if usb device is connected + // wait for/send the first request to see if usb device is connected available(); } void HIDBridge_::end(void) { // end the serial transmission and reset our helper values - HIDBRIDGE_TX_SERIAL.end(); + HIDBRIDGE_SERIAL.end(); nhp_read.mode = NHP_RESET; - isReady = false; + rxReady = false; //TODO isConnected = false; + //TODO reset more stuff } @@ -58,73 +56,97 @@ void HIDBridge_::err(uint8_t error) { if (!debug) return; - debug->print("Bridge Err TX: "); + debug->print("err"); debug->println(error); } + +void HIDBridge_::writeState(void) { + // send the current state to the other mcu + NHP_Write_Data_t n; + writeNHPAddress(HIDBRIDGE_CONTROL_ADDRESS, rxReady, &n); + HIDBRIDGE_SERIAL.write(n.writeBuffer, n.writeLength); + + // save new timeout + writeTimeout = millis(); +} + +void HIDBridge_::task(void){ + //TODO implement Serialevent strong for this task? +#ifdef HIDBRIDGE_RX + // if hid request timed out, send a new one + // this is important if the main mcu gets a reset or misses an acknowledge + uint32_t currentMillis = millis(); + if ((currentMillis - writeTimeout) > HIDBRIDGE_TX_TIMEOUT) { + writeState(); + // do not write timeout value, will be written in the function above +#ifdef USB_DEBUG + debug->println("ack 1s"); +#endif + } +#endif + + // read in new controls or data + read(); +} + void HIDBridge_::read(void) { + // check for read timeout only if really needed + if (!nhp_read.mode){ + if (millis() - readTimeout > HIDBRIDGE_RX_TIMEOUT) { + // reset reportID and NHP if we have a timeout + reportID = 0; + nhp_read.mode = NHP_RESET; + err(HIDBRIDGE_ERR_READ_TO); + } + } + // read as long as the Serial is available // but do not block forever - for (rx_buffer_index_t i = 0; i < SERIAL_RX_BUFFER_SIZE; i++){ + rx_buffer_index_t i; + for (i = 0; i < SERIAL_RX_BUFFER_SIZE; i++){ // read in new Serial byte - int b = HIDBRIDGE_TX_SERIAL.read(); + int b = HIDBRIDGE_SERIAL.read(); if (b < 0) break; // process with NHP protocol - bool newInput = readNHP(b, &nhp_read); - - // proceed new valid NHP input - if (newInput) { - - // NHP address contains control data or out report data - if (nhp_read.mode == NHP_ADDRESS) { - - // received a control address command - if (nhp_read.address == HIDBRIDGE_ADDRESS_CONTROL) { - // acknowledge/request - if (nhp_read.data == HIDBRIDGE_CONTROL_ISREADY){ - isReady = true; - isConnected = true; - } - - // pause - else if (nhp_read.data == HIDBRIDGE_CONTROL_NOTREADY){ - isReady = false; - isConnected = true; - } - - // usb device detached - else if (nhp_read.data == HIDBRIDGE_CONTROL_NOTCONNECTED){ - isReady = false; - isConnected = false; - } - - // not defined control command - else - err(HIDBRIDGE_ERR_CONTROL); - } + if (readNHP(b, &nhp_read)) { - // received HID out report TODO - else - err(HIDBRIDGE_ERR_ADDRESS); - } + // command indicates a new hidReport (command==reportID) or the end (command==0) + if (nhp_read.mode == NHP_COMMAND) + proceedCommand(); - // received HID out report TODO - else if (nhp_read.mode == NHP_COMMAND) { - err(HIDBRIDGE_ERR_COMMAND); - } + // NHP address contains control data or hid in/out report data + else if (nhp_read.mode == NHP_ADDRESS) + proceedAddress(); } // NHP reading error else if (nhp_read.errorLevel) { - err(HIDBRIDGE_ERR_NHP_ERR); - // do not change isReady state because of a possible full buffer + // ASCII + if (b < 128) { + // possible main mcu reset + if (!b) + err(HIDBRIDGE_ERR_MCU_RST); + else { //TODO different errors? + err(HIDBRIDGE_ERR_SERIALB); + } + } + else + err(HIDBRIDGE_ERR_SERIALB); + + // do not change rxReady state because of a possible full buffer // which causes NHP corruption + err(HIDBRIDGE_ERR_NHP_ERR); } - } + } // end of for reading loop + + // save new time + if (i) + readTimeout = millis(); } @@ -142,11 +164,172 @@ bool HIDBridge_::available(void) err(HIDBRIDGE_ERR_TIMEOUT); break; } - } while (!isReady); + } while (!txReady); + + return txReady; +} + + +void HIDBridge_::proceedCommand(void){ +#ifdef DEBUG + debug->print("c"); + debug->println(nhp_read.command); +#endif + +#ifdef HIDBRIDGE_RX + // proceed a possible end flag + if (nhp_read.command == HIDBRIDGE_COMMAND_END) { + + // we've got a correct USB protocol received. Write it to the host now. + if (reportID && (recvLength == reportLength)) { + rxReady = false; //TODO not needed? +#ifdef USB_DEBUG + // debug print HID reports + debug->print("USBk "); + debug->print(reportID, DEC); + for (uint8_t i = 0; i < reportLength; i++) { + debug->print(", 0x"); + debug->print(hidReport[i], HEX); + } + debug->println(); +#endif + HID_SendReport(reportID, hidReport, reportLength); + + // acknowledge signal + rxReady = true; + writeState(); + } + // log an error + else + err(HIDBRIDGE_ERR_CMD_END); + + // reset reportID in any case + reportID = 0; + } + + // proceed a possible new reportID lead + else { + // flag an error if we have a pending report + if (reportID) + err(HIDBRIDGE_ERR_CMD_RID); + + // determine the new report length + switch (nhp_read.command) { //TODO progmem lookup table +#ifdef HID_MOUSE_ENABLE + case HID_REPORTID_MOUSE: + reportLength = sizeof(HID_MouseReport_Data_t); + break; +#endif + +#ifdef HID_MOUSE_ABSOLUTE_ENABLE + case HID_REPORTID_MOUSE_ABSOLUTE: + reportLength = sizeof(HID_MouseAbsoluteReport_Data_t); + break; +#endif + +#ifdef HID_KEYBOARD_ENABLE + case HID_REPORTID_KEYBOARD: + reportLength = sizeof(HID_KeyboardReport_Data_t); + break; +#endif + +#ifdef HID_CONSUMERCONTROL_ENABLE + case HID_REPORTID_CONSUMERCONTROL: + reportLength = sizeof(HID_ConsumerControlReport_Data_t); + break; +#endif + +#ifdef HID_SYSTEMCONTROL_ENABLE + case HID_REPORTID_SYSTEMCONTROL: + reportLength = sizeof(HID_SystemControlReport_Data_t); + break; +#endif + +#ifdef HID_GAMEPAD_ENABLE + case HID_REPORTID_GAMEPAD: + reportLength = sizeof(HID_GamepadReport_Data_t); + break; +#endif + + default: + // error + reportLength = 0; + break; + } + + if (reportLength) { + // save new report properties + reportID = nhp_read.command; + recvLength = 0; + } + else { + // new reportID is not supported + //TODO recv length =0? + reportID = 0; + err(HIDBRIDGE_ERR_COMMAND); + } + } +#else // ifdef HIDBRIDGE_RX + err(HIDBRIDGE_ERR_COMMAND); +#endif +} + + +void HIDBridge_::proceedAddress(void){ +#ifdef DEBUG + debug->print("a"); + debug->print(nhp_read.address); + debug->print(", "); + debug->println(nhp_read.data, HEX); +#endif + + // received a control address + if (nhp_read.address == HIDBRIDGE_CONTROL_ADDRESS) { + reportID = 0; + + // acknowledge/request + if (nhp_read.data == HIDBRIDGE_CONTROL_READY){ + txReady = true; + isConnected = true; + } - return isReady; + // pause + else if (nhp_read.data == HIDBRIDGE_CONTROL_NOTREADY){ + txReady = false; + isConnected = true; + } + + // usb device detached + else if (nhp_read.data == HIDBRIDGE_CONTROL_NOTCONNECTED){ + txReady = false; + isConnected = false; + } + + // not defined control command + else + err(HIDBRIDGE_ERR_CONTROL); + } +#ifdef HIDBRIDGE_RX + // received correct reportID (in/out) + else if (reportID && (reportID == nhp_read.address) && (recvLength < reportLength)) { + for (uint8_t i = 0; i < 4; i++) { + // save hidReport + hidReport[recvLength++] = nhp_read.data8[i]; + + // abort if report finished + if (recvLength == reportLength) + break; + } + } +#endif + // received wrong data: lead command missing/wrong reportID/report too long + else { + reportID = 0; + err(HIDBRIDGE_ERR_ADDRESS); + } } + void HIDBridge_::SendReport(uint8_t reportID, const void* data, int len) { // check the latest request/acknowledge, pause or error @@ -156,37 +339,50 @@ void HIDBridge_::SendReport(uint8_t reportID, const void* data, int len) } // begin transfer with reportID as command - HIDBRIDGE_TX_SERIAL.write(writeNHPCommand(reportID)); + HIDBRIDGE_SERIAL.write(writeNHPCommand(reportID)); // send data in 4 byte packets with the address of the reportID // the rest (if any, e.g. with 2 byte) is filled with random bytes NHP_Write_Data_t n; for (int i = 0; i < len; i += 4) { writeNHPAddress(reportID, UINT32_AT_OFFSET(data, i), &n); - HIDBRIDGE_TX_SERIAL.write(n.writeBuffer, n.writeLength); + HIDBRIDGE_SERIAL.write(n.writeBuffer, n.writeLength); } // end transfer with zero command - HIDBRIDGE_TX_SERIAL.write(writeNHPCommand(0)); + HIDBRIDGE_SERIAL.write(writeNHPCommand(0)); // need a request/acknowledge next time again - isReady = false; + txReady = false; err(42); } +//================================================================================ +// Strong function implementations +//================================================================================ + +// IO MCU only +#ifdef HIDBRIDGE_IO +#ifdef HIDBRIDGE_TX // overwrites the HID_SendReport function which is empty/not used on a 328/2560 void HID_SendReport(uint8_t reportID, const void* data, int len) { HIDBridge.SendReport(reportID, data, len); } +#endif +#endif // #ifdef HIDBRIDGE_IO -#endif // #ifdef HIDBRIDGE_TX - -//================================================================================ -// HIDBridge RX -//================================================================================ -#ifdef HIDBRIDGE_RX - -#endif // #ifdef HIDBRIDGE_RX \ No newline at end of file +#ifdef HIDBRIDGE_USE_SERIAL_EVENT +/* +SerialEvent occurs whenever a new data comes in the +hardware serial RX. This routine is run between each +time loop() runs, so using delay inside loop can delay +response. Multiple bytes of data may be available. +*/ +void HIDBRIDGE_SERIAL_EVENT(void) { + HIDBridge.task(); + Serial.println("kk"); +} +#endif diff --git a/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.h b/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.h index b3aaf7db0d..089d680c20 100644 --- a/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.h +++ b/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.h @@ -31,11 +31,32 @@ THE SOFTWARE. // Settings //================================================================================ -#define HIDBRIDGE_TX_SERIAL Serial +//TODO replace with USB and IO +#define HIDBRIDGE_SERIAL SERIAL_PORT_HARDWARE -#ifdef HOODLOADER2 -#define HIDBRIDGE_RX +#define HIDBRIDGE_BAUD 2000000 // transfer at highest possible baud + +// use Arduino builtin serialEvent() function to call the HIDBridge task? +#define HIDBRIDGE_USE_SERIAL_EVENT + +//#define DEBUG +#define USB_DEBUG + +// which MCU should act as USB or IO part? +#ifdef USBCON +#define HIDBRIDGE_USB #else +#define HIDBRIDGE_IO +#endif + +// define if the MCU can do RX, TX or both +// minimal setup: USB RX, IO TX +#ifdef HIDBRIDGE_USB +#define HIDBRIDGE_RX +//#define HIDBRIDGE_TX +#endif +#ifdef HIDBRIDGE_IO +//#define HIDBRIDGE_RX #define HIDBRIDGE_TX #endif @@ -43,22 +64,28 @@ THE SOFTWARE. // Definitions //================================================================================ -#if defined(HIDBRIDGE_RX) && defined(HIDBRIDGE_TX) +#if defined(HIDBRIDGE_USB) && defined(HIDBRIDGE_IO) #error Cannot send and receive at the same time // also because it will create the instance of the class // even if its not used, so we dont separate the TX and RX class names // function names are kept similar #endif -#define HIDBRIDGE_TX_TIMEOUT 1000 +#define HIDBRIDGE_SERIAL_EVENT_WRAPPER_Serial serialEvent +#define HIDBRIDGE_SERIAL_EVENT_WRAPPER_Serial1 serialEvent1 +#define HIDBRIDGE_SERIAL_EVENT HIDBRIDGE_SERIAL_EVENT_WRAPPER_ ## Serial1 + + +#define HIDBRIDGE_TX_TIMEOUT 800 // should be smaller than RX +#define HIDBRIDGE_RX_TIMEOUT 1000 -#define HIDBRIDGE_BAUD 2000000 +#define HIDBRIDGE_CONTROL_ADDRESS 0x00 +#define HIDBRIDGE_CONTROL_NOTREADY 0 +#define HIDBRIDGE_CONTROL_READY 1 +#define HIDBRIDGE_CONTROL_NOTCONNECTED 2 -#define HIDBRIDGE_ADDRESS_CONTROL 0 +#define HIDBRIDGE_COMMAND_END 0 -#define HIDBRIDGE_CONTROL_ISREADY 0 -#define HIDBRIDGE_CONTROL_NOTREADY 1 -#define HIDBRIDGE_CONTROL_NOTCONNECTED 1 #define HIDBRIDGE_ERR_TIMEOUT 0 #define HIDBRIDGE_ERR_NHP_ERR 1 @@ -66,13 +93,18 @@ THE SOFTWARE. #define HIDBRIDGE_ERR_ADDRESS 3 #define HIDBRIDGE_ERR_CONTROL 4 #define HIDBRIDGE_ERR_NOT_RDY 5 +#define HIDBRIDGE_ERR_READ_TO 6 +#define HIDBRIDGE_ERR_CMD_END 7 +#define HIDBRIDGE_ERR_CMD_RID 8 +#define HIDBRIDGE_ERR_MCU_RST 9 +#define HIDBRIDGE_ERR_SERIALB 10 //================================================================================ -// HIDBridge TX +// HIDBridge //================================================================================ -#ifdef HIDBRIDGE_TX + class HIDBridge_{ public: HIDBridge_(void); @@ -81,6 +113,8 @@ class HIDBridge_{ void begin(void); void end(void); + void task(void); + // advanced user functions void read(void); bool available(void); @@ -90,58 +124,40 @@ class HIDBridge_{ // debug void err(uint8_t error); + void writeState(void); + inline void debugStream(Stream* s){ debug = s; } Stream* debug; -private: - bool isReady; - bool isConnected; - - // temporary NHP protocol read data - NHP_Read_Data_t nhp_read; -}; -extern HIDBridge_ HIDBridge; -#endif -//================================================================================ -// HIDBridge RX -//================================================================================ - -#ifdef HIDBRIDGE_RX -class HIDBridge_{ -public: - HIDBridge_(void); - - // user functions - void begin(void); - void end(void); - - // advanced user functions - void read(void); - bool available(void); - - // public to access via HID_SendReport - void SendReport(uint8_t reportID, const void* data, int len); - - // debug - void err(uint8_t error); - inline void debugStream(Stream* s){ - debug = s; - } - Stream* debug; + bool txReady; + bool rxReady; + private: - bool isReady; + + // inlined functions to clear the code + // used in read(), not public accessible + inline void proceedAddress(void); //TODO change to always inline? + inline void proceedCommand(void); + + bool isConnected; + uint32_t readTimeout; + uint32_t writeTimeout; + uint8_t recvLength; + uint8_t reportID; + uint8_t reportLength; + uint8_t hidReport[USB_EP_SIZE - 1]; // temporary NHP protocol read data NHP_Read_Data_t nhp_read; }; extern HIDBridge_ HIDBridge; -#endif + //================================================================================ // Function prototypes From cef9f368449db93de33685509cc01c2bb572c85b Mon Sep 17 00:00:00 2001 From: Nico Date: Fri, 20 Feb 2015 14:45:25 +0100 Subject: [PATCH 167/602] Added No USB workaround to pins.h Due to a bad Leonardo Bootloader this is the only way (i know) to fix this bug right now. It no longer needs to be included in the sketch anymore, this will be compiled automatically now. --- .../variants/leonardo_no_usb/no_usb_isr.cpp | 11 +++++++ .../avr/variants/micro_no_usb/no_usb_isr.cpp | 11 +++++++ .../Leonardo_Micro_NoUSB_Blink.ino | 31 ------------------- 3 files changed, 22 insertions(+), 31 deletions(-) create mode 100644 plugins/KeyboardioHID/avr/variants/leonardo_no_usb/no_usb_isr.cpp create mode 100644 plugins/KeyboardioHID/avr/variants/micro_no_usb/no_usb_isr.cpp delete mode 100644 plugins/KeyboardioHID/examples/Projects/Leonardo_Micro_NoUSB_Blink/Leonardo_Micro_NoUSB_Blink.ino diff --git a/plugins/KeyboardioHID/avr/variants/leonardo_no_usb/no_usb_isr.cpp b/plugins/KeyboardioHID/avr/variants/leonardo_no_usb/no_usb_isr.cpp new file mode 100644 index 0000000000..eec342f6a9 --- /dev/null +++ b/plugins/KeyboardioHID/avr/variants/leonardo_no_usb/no_usb_isr.cpp @@ -0,0 +1,11 @@ +#include +#include + +// workaround for undefined USBCON has to be placed in every sketch +// otherwise the timings wont work correctly +// this is only needed for Leonardo/Micro boards and not for HoodLoader2 +// due to a better bootloader reset (usb clock does not run after programming) +ISR(USB_GEN_vect) +{ + UDINT = 0; +} \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/variants/micro_no_usb/no_usb_isr.cpp b/plugins/KeyboardioHID/avr/variants/micro_no_usb/no_usb_isr.cpp new file mode 100644 index 0000000000..eec342f6a9 --- /dev/null +++ b/plugins/KeyboardioHID/avr/variants/micro_no_usb/no_usb_isr.cpp @@ -0,0 +1,11 @@ +#include +#include + +// workaround for undefined USBCON has to be placed in every sketch +// otherwise the timings wont work correctly +// this is only needed for Leonardo/Micro boards and not for HoodLoader2 +// due to a better bootloader reset (usb clock does not run after programming) +ISR(USB_GEN_vect) +{ + UDINT = 0; +} \ No newline at end of file diff --git a/plugins/KeyboardioHID/examples/Projects/Leonardo_Micro_NoUSB_Blink/Leonardo_Micro_NoUSB_Blink.ino b/plugins/KeyboardioHID/examples/Projects/Leonardo_Micro_NoUSB_Blink/Leonardo_Micro_NoUSB_Blink.ino deleted file mode 100644 index 8309b2613f..0000000000 --- a/plugins/KeyboardioHID/examples/Projects/Leonardo_Micro_NoUSB_Blink/Leonardo_Micro_NoUSB_Blink.ino +++ /dev/null @@ -1,31 +0,0 @@ -/* - Copyright (c) 2014 NicoHood - See the readme for credit to other people. - - Leonardo_Micro_NoUSB_Blink - - Blinks Led and shows what workaround is needed to fix the timing. - This is not needed for HoodLoader2 devices any more. -*/ - - -// workaround for undefined USBCON has to be placed in every sketch -// otherwise the timings wont work correctly -ISR(USB_GEN_vect) -{ - UDINT = 0; -} - -// the setup function runs once when you press reset or power the board -void setup() { - // initialize digital pin 13 as an output. - pinMode(13, OUTPUT); -} - -// the loop function runs over and over again forever -void loop() { - digitalWrite(13, HIGH); // turn the LED on (HIGH is the voltage level) - delay(1000); // wait for a second - digitalWrite(13, LOW); // turn the LED off by making the voltage LOW - delay(1000); // wait for a second -} From 21091e432b426048d3826a1a2c4a5d3e2b4e63d8 Mon Sep 17 00:00:00 2001 From: Nico Date: Tue, 24 Feb 2015 07:45:46 +0100 Subject: [PATCH 168/602] Added better USB PID costumization --- plugins/KeyboardioHID/avr/boards.txt | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/plugins/KeyboardioHID/avr/boards.txt b/plugins/KeyboardioHID/avr/boards.txt index 02bc59b0da..978a88da42 100644 --- a/plugins/KeyboardioHID/avr/boards.txt +++ b/plugins/KeyboardioHID/avr/boards.txt @@ -26,7 +26,7 @@ leonardoExtended.build.mcu=atmega32u4 leonardoExtended.build.f_cpu=16000000L leonardoExtended.build.core=HID:hid leonardoExtended.build.vid=0x2341 -leonardoExtended.build.pid=0x8036 +#leonardoExtended.build.pid=0x8036 leonardoExtended.build.usb_product="Arduino Leonardo" leonardoExtended.build.board=AVR_LEONARDO leonardoExtended.build.extra_flags={build.usb_flags} @@ -35,14 +35,19 @@ leonardoExtended.build.extra_flags={build.usb_flags} #HID Project needs to be installed https://github.com/NicoHood/HID leonardoExtended.menu.usbcore.hid=Serial + Extended HID leonardoExtended.menu.usbcore.hid.build.variant=leonardo_hid +leonardoExtended.menu.usbcore.hid.build.pid=0x8036 leonardoExtended.menu.usbcore.gamepad=Serial + Gamepad HID leonardoExtended.menu.usbcore.gamepad.build.variant=leonardo_gamepad +leonardoExtended.menu.usbcore.gamepad.build.pid=0x8036 leonardoExtended.menu.usbcore.custom=Serial + Custom HID leonardoExtended.menu.usbcore.custom.build.variant=leonardo_custom +leonardoExtended.menu.usbcore.custom.build.pid=0x8036 leonardoExtended.menu.usbcore.USB_CORE=Default Core leonardoExtended.menu.usbcore.USB_CORE.build.variant=leonardo +leonardoExtended.menu.usbcore.USB_CORE.build.pid=0x8036 leonardoExtended.menu.usbcore.NO_USB=No USB functions leonardoExtended.menu.usbcore.NO_USB.build.variant=leonardo_no_usb +leonardoExtended.menu.usbcore.NO_USB.build.pid=0x8036 ############################################################## @@ -68,7 +73,7 @@ microExtended.build.mcu=atmega32u4 microExtended.build.f_cpu=16000000L microExtended.build.core=HID:hid microExtended.build.vid=0x2341 -microExtended.build.pid=0x8037 +#microExtended.build.pid=0x8037 microExtended.build.usb_product="Arduino Micro" microExtended.build.board=AVR_MICRO microExtended.build.extra_flags={build.usb_flags} @@ -77,12 +82,17 @@ microExtended.build.extra_flags={build.usb_flags} #HID Project needs to be installed https://github.com/NicoHood/HID microExtended.menu.usbcore.hid=Serial + Extended HID microExtended.menu.usbcore.hid.build.variant=micro_hid +microExtended.menu.usbcore.hid.pid=0x8037 microExtended.menu.usbcore.gamepad=Serial + Gamepad HID microExtended.menu.usbcore.gamepad.build.variant=micro_gamepad +microExtended.menu.usbcore.gamepad.pid=0x8037 microExtended.menu.usbcore.custom=Serial + Custom HID microExtended.menu.usbcore.custom.build.variant=micro_custom +microExtended.menu.usbcore.custom.pid=0x8037 microExtended.menu.usbcore.USB_CORE=Default Core microExtended.menu.usbcore.USB_CORE.build.variant=micro +microExtended.menu.usbcore.USB_CORE.pid=0x8037 microExtended.menu.usbcore.NO_USB=No USB functions microExtended.menu.usbcore.NO_USB.build.variant=micro_no_usb +microExtended.menu.usbcore.NO_USB.pid=0x8037 From 286d90551580f81804ef446de027fcc090525c27 Mon Sep 17 00:00:00 2001 From: Nico Date: Sat, 28 Feb 2015 10:42:41 +0100 Subject: [PATCH 169/602] Integrated System wakeup into API --- plugins/KeyboardioHID/Readme.md | 1 + plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.h | 7 ++++++- .../examples/HID_Basic/HID_System/HID_System.ino | 4 ++-- plugins/KeyboardioHID/examples/Readme.md | 4 ---- 4 files changed, 9 insertions(+), 7 deletions(-) delete mode 100644 plugins/KeyboardioHID/examples/Readme.md diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 2d0ddf8b0d..cee132e208 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -72,6 +72,7 @@ Version History * Arduino as ISP fix for 328 * Upload verification on USB hubs fix for HL2.0.4 * No USB workaround for Leonardo integrated into variants +* Changed USB Wakeup in System API 2.1 Release (28.01.2015) * Reworked the whole USB-Core from scratch diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.h index c8f3a8e280..03dca7dcc9 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.h @@ -59,7 +59,12 @@ class System_{ release(); } inline void press(uint8_t s){ - HID_SendReport(HID_REPORTID_SYSTEMCONTROL, &s, sizeof(s)); +#ifdef USBCON + if (s == SYSTEM_WAKE_UP) + USBDevice.wakeupHost(); + else +#endif + HID_SendReport(HID_REPORTID_SYSTEMCONTROL, &s, sizeof(s)); } inline void release(void){ begin(); diff --git a/plugins/KeyboardioHID/examples/HID_Basic/HID_System/HID_System.ino b/plugins/KeyboardioHID/examples/HID_Basic/HID_System/HID_System.ino index 1e8db5335e..0531cb255d 100644 --- a/plugins/KeyboardioHID/examples/HID_Basic/HID_System/HID_System.ino +++ b/plugins/KeyboardioHID/examples/HID_Basic/HID_System/HID_System.ino @@ -39,10 +39,10 @@ void loop() { // tries to wake up the PC // this might fail on some PCs where USB wakeup isnt supported - USBDevice.wakeupHost(); + System.write(SYSTEM_WAKE_UP); // simple debounce delay(300); digitalWrite(pinLed, LOW); } -} +} \ No newline at end of file diff --git a/plugins/KeyboardioHID/examples/Readme.md b/plugins/KeyboardioHID/examples/Readme.md deleted file mode 100644 index 30a01d3b39..0000000000 --- a/plugins/KeyboardioHID/examples/Readme.md +++ /dev/null @@ -1,4 +0,0 @@ -Examples -======== - -Just try these examples once the HID Source is installed. Its pretty much self explaining. \ No newline at end of file From d50d79f5712e2eb06af312670c207bedad40d193 Mon Sep 17 00:00:00 2001 From: Nico Date: Sun, 1 Mar 2015 14:23:49 +0100 Subject: [PATCH 170/602] Fix issue #16 --- .../KeyboardioHID/avr/cores/hid/USB-Core/System.cpp | 11 ++++++++++- plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.h | 9 +-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.cpp b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.cpp index afc6c7f2fe..b4fb6ae471 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.cpp +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.cpp @@ -27,4 +27,13 @@ THE SOFTWARE. // System //================================================================================ -System_ System; \ No newline at end of file +System_ System; + +void System_::press(uint8_t s){ +#ifdef USBCON + if (s == SYSTEM_WAKE_UP) + USBDevice.wakeupHost(); + else +#endif + HID_SendReport(HID_REPORTID_SYSTEMCONTROL, &s, sizeof(s)); +} \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.h index 03dca7dcc9..7e57389053 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.h @@ -58,14 +58,7 @@ class System_{ press(s); release(); } - inline void press(uint8_t s){ -#ifdef USBCON - if (s == SYSTEM_WAKE_UP) - USBDevice.wakeupHost(); - else -#endif - HID_SendReport(HID_REPORTID_SYSTEMCONTROL, &s, sizeof(s)); - } + void press(uint8_t s); inline void release(void){ begin(); } From 7fe7b06993608bd94fbb3b380fa283806d9f412d Mon Sep 17 00:00:00 2001 From: Nico Date: Tue, 17 Mar 2015 21:10:59 +0100 Subject: [PATCH 171/602] fix issue #14 --- .../KeyboardioHID/avr/variants/micro_gamepad/pins_arduino.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/KeyboardioHID/avr/variants/micro_gamepad/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/micro_gamepad/pins_arduino.h index d2cbea429a..2bf0c34db8 100644 --- a/plugins/KeyboardioHID/avr/variants/micro_gamepad/pins_arduino.h +++ b/plugins/KeyboardioHID/avr/variants/micro_gamepad/pins_arduino.h @@ -29,9 +29,9 @@ THE SOFTWARE. //================================================================================ // pre selected hid reports with autoinclude of the api -#define HID_MOUSE_ENABLE // normal mouse with buttons + wheel +//#define HID_MOUSE_ENABLE // normal mouse with buttons + wheel //#define HID_MOUSE_ABSOLUTE_ENABLE // only works with system and without gamepad -#define HID_KEYBOARD_LEDS_ENABLE // leds OR keys +//#define HID_KEYBOARD_LEDS_ENABLE // leds OR keys //#define HID_KEYBOARD_KEYS_ENABLE //#define HID_RAWHID_ENABLE // currently not working //#define HID_CONSUMERCONTROL_ENABLE From 20e331d03ff70472ceba28229be8f398705c137d Mon Sep 17 00:00:00 2001 From: Nico Date: Tue, 17 Mar 2015 21:11:28 +0100 Subject: [PATCH 172/602] fix issue #14 --- .../avr/variants/leonardo_gamepad/pins_arduino.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/KeyboardioHID/avr/variants/leonardo_gamepad/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/leonardo_gamepad/pins_arduino.h index 6898e24167..3924ea93a6 100644 --- a/plugins/KeyboardioHID/avr/variants/leonardo_gamepad/pins_arduino.h +++ b/plugins/KeyboardioHID/avr/variants/leonardo_gamepad/pins_arduino.h @@ -29,9 +29,9 @@ THE SOFTWARE. //================================================================================ // pre selected hid reports with autoinclude of the api -#define HID_MOUSE_ENABLE // normal mouse with buttons + wheel +//#define HID_MOUSE_ENABLE // normal mouse with buttons + wheel //#define HID_MOUSE_ABSOLUTE_ENABLE // only works with system and without gamepad -#define HID_KEYBOARD_LEDS_ENABLE // leds OR keys +//#define HID_KEYBOARD_LEDS_ENABLE // leds OR keys //#define HID_KEYBOARD_KEYS_ENABLE //#define HID_RAWHID_ENABLE // currently not working //#define HID_CONSUMERCONTROL_ENABLE From ef4a3db5e280057faa7eb11a7815bb2f5f6cb48e Mon Sep 17 00:00:00 2001 From: Nico Date: Fri, 20 Mar 2015 20:32:21 +0100 Subject: [PATCH 173/602] Delete .gitignore --- plugins/KeyboardioHID/.gitignore | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 plugins/KeyboardioHID/.gitignore diff --git a/plugins/KeyboardioHID/.gitignore b/plugins/KeyboardioHID/.gitignore deleted file mode 100644 index 436221a38e..0000000000 --- a/plugins/KeyboardioHID/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -dev/* -*.zip \ No newline at end of file From b3c24546d4fc66a21fd80e453cf36c90b0708669 Mon Sep 17 00:00:00 2001 From: Nico Date: Mon, 30 Mar 2015 17:01:25 +0200 Subject: [PATCH 174/602] Added Menu Key definition Opens context menus like a right mouse click. --- plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h index d2357891d3..41c5c6c625 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h @@ -54,6 +54,7 @@ THE SOFTWARE. #define KEY_NUM_LOCK 0xDB #define KEY_SCROLL_LOCK 0xCF #define KEY_PAUSE 0xD0 +#define KEY_MENU 0xED // 0x65 in the official docs #define KEY_LEFT_CTRL 0x80 #define KEY_LEFT_SHIFT 0x81 From 15603a107abd30edb0c854cb4074bc7777b39ac7 Mon Sep 17 00:00:00 2001 From: Nico Date: Mon, 30 Mar 2015 17:01:54 +0200 Subject: [PATCH 175/602] Fix Issue #15 --- plugins/KeyboardioHID/avr/boards.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/KeyboardioHID/avr/boards.txt b/plugins/KeyboardioHID/avr/boards.txt index 978a88da42..4645d70ab6 100644 --- a/plugins/KeyboardioHID/avr/boards.txt +++ b/plugins/KeyboardioHID/avr/boards.txt @@ -82,17 +82,17 @@ microExtended.build.extra_flags={build.usb_flags} #HID Project needs to be installed https://github.com/NicoHood/HID microExtended.menu.usbcore.hid=Serial + Extended HID microExtended.menu.usbcore.hid.build.variant=micro_hid -microExtended.menu.usbcore.hid.pid=0x8037 +microExtended.menu.usbcore.hid.build.pid=0x8037 microExtended.menu.usbcore.gamepad=Serial + Gamepad HID microExtended.menu.usbcore.gamepad.build.variant=micro_gamepad -microExtended.menu.usbcore.gamepad.pid=0x8037 +microExtended.menu.usbcore.gamepad.build.pid=0x8037 microExtended.menu.usbcore.custom=Serial + Custom HID microExtended.menu.usbcore.custom.build.variant=micro_custom -microExtended.menu.usbcore.custom.pid=0x8037 +microExtended.menu.usbcore.custom.build.pid=0x8037 microExtended.menu.usbcore.USB_CORE=Default Core microExtended.menu.usbcore.USB_CORE.build.variant=micro -microExtended.menu.usbcore.USB_CORE.pid=0x8037 +microExtended.menu.usbcore.USB_CORE.build.pid=0x8037 microExtended.menu.usbcore.NO_USB=No USB functions microExtended.menu.usbcore.NO_USB.build.variant=micro_no_usb -microExtended.menu.usbcore.NO_USB.pid=0x8037 +microExtended.menu.usbcore.NO_USB.build.pid=0x8037 From 27bfc05a830f726a59465200e3615d8e7317b640 Mon Sep 17 00:00:00 2001 From: Nico Date: Mon, 30 Mar 2015 17:51:09 +0200 Subject: [PATCH 176/602] Fixed compiler path for mac Due to PR here: https://github.com/sparkfun/SF32u4_boards/pull/14 --- plugins/KeyboardioHID/avr/platform.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/avr/platform.txt b/plugins/KeyboardioHID/avr/platform.txt index d88615971e..9261ceb91b 100644 --- a/plugins/KeyboardioHID/avr/platform.txt +++ b/plugins/KeyboardioHID/avr/platform.txt @@ -16,7 +16,7 @@ version=2.2 # --------------------- # Default "compiler.path" is correct, change only if you want to overidde the initial value -compiler.path={runtime.ide.path}/hardware/tools/avr/bin/ +compiler.path={runtime.tools.avr-gcc.path}/bin/ compiler.c.cmd=avr-gcc compiler.c.flags=-c -g -Os -w -ffunction-sections -fdata-sections -MMD # -w flag added to avoid printing a wrong warning http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59396 From 181f8f7f76c9f440ae96ca598727d40ccb7c0c09 Mon Sep 17 00:00:00 2001 From: Nico Date: Wed, 1 Apr 2015 17:03:46 +0200 Subject: [PATCH 177/602] Revert "Fixed compiler path for mac" This reverts commit 27bfc05a830f726a59465200e3615d8e7317b640. --- plugins/KeyboardioHID/avr/platform.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/avr/platform.txt b/plugins/KeyboardioHID/avr/platform.txt index 9261ceb91b..d88615971e 100644 --- a/plugins/KeyboardioHID/avr/platform.txt +++ b/plugins/KeyboardioHID/avr/platform.txt @@ -16,7 +16,7 @@ version=2.2 # --------------------- # Default "compiler.path" is correct, change only if you want to overidde the initial value -compiler.path={runtime.tools.avr-gcc.path}/bin/ +compiler.path={runtime.ide.path}/hardware/tools/avr/bin/ compiler.c.cmd=avr-gcc compiler.c.flags=-c -g -Os -w -ffunction-sections -fdata-sections -MMD # -w flag added to avoid printing a wrong warning http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59396 From c2a9e27043c7210a0c2e841184dc4c0908ef4d73 Mon Sep 17 00:00:00 2001 From: Nico Date: Thu, 2 Apr 2015 15:12:58 +0200 Subject: [PATCH 178/602] Update Readme.md --- plugins/KeyboardioHID/Readme.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 8dabf84441..e557e11791 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -12,6 +12,8 @@ The idea is to enable enhanced USB functions to almost all 'standard' Arduino bo Download ======== +###Download the current dev version for 1.6.2 compatibility. The master currently only works with 1.6.1 and the dev only with 1.6.2 due to internal IDE changes. + You have 3 versions you can download: * The master includes all fixes to the current stable release. Download it by clicking download at the right. Use the [online Wiki](https://github.com/NicoHood/HID/wiki) to get the newest documentation. From 69a7998248c4b581f19abc21182081903ab337a0 Mon Sep 17 00:00:00 2001 From: Nico Date: Thu, 2 Apr 2015 16:10:42 +0200 Subject: [PATCH 179/602] Revert "Revert "Fixed compiler path for mac"" This reverts commit 181f8f7f76c9f440ae96ca598727d40ccb7c0c09. --- plugins/KeyboardioHID/avr/platform.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/avr/platform.txt b/plugins/KeyboardioHID/avr/platform.txt index d88615971e..9261ceb91b 100644 --- a/plugins/KeyboardioHID/avr/platform.txt +++ b/plugins/KeyboardioHID/avr/platform.txt @@ -16,7 +16,7 @@ version=2.2 # --------------------- # Default "compiler.path" is correct, change only if you want to overidde the initial value -compiler.path={runtime.ide.path}/hardware/tools/avr/bin/ +compiler.path={runtime.tools.avr-gcc.path}/bin/ compiler.c.cmd=avr-gcc compiler.c.flags=-c -g -Os -w -ffunction-sections -fdata-sections -MMD # -w flag added to avoid printing a wrong warning http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59396 From b50e775c4df86cb7cfd6ed0f1ec09268a543dc22 Mon Sep 17 00:00:00 2001 From: Nico Date: Sat, 4 Apr 2015 20:21:59 +0200 Subject: [PATCH 180/602] Added wiki link --- .../examples/HID_Basic/HID_Consumer/HID_Consumer.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/KeyboardioHID/examples/HID_Basic/HID_Consumer/HID_Consumer.ino b/plugins/KeyboardioHID/examples/HID_Basic/HID_Consumer/HID_Consumer.ino index f00ddc9b57..f74192f280 100644 --- a/plugins/KeyboardioHID/examples/HID_Basic/HID_Consumer/HID_Consumer.ino +++ b/plugins/KeyboardioHID/examples/HID_Basic/HID_Consumer/HID_Consumer.ino @@ -6,6 +6,7 @@ Press a button to play/pause music player See HID Project documentation for more Consumer keys. + https://github.com/NicoHood/HID/wiki/Consumer-API#key-definitions // basic Media key definitions, see HID Project and official USB docs for more #define MEDIA_FAST_FORWARD 0xB3 From 6d889ca65246ff7369684db94ee227b21608bf5e Mon Sep 17 00:00:00 2001 From: Nico Date: Sat, 4 Apr 2015 20:55:18 +0200 Subject: [PATCH 181/602] Consumer Fixes --- plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.cpp | 2 +- plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h | 2 +- plugins/KeyboardioHID/avr/variants/micro_custom/pins_arduino.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.cpp b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.cpp index d661d1557f..7ec2a409aa 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.cpp +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.cpp @@ -69,7 +69,7 @@ const u8 _hidReportDescriptor[] = { #ifdef HID_RAWHID_ENABLE HID_REPORT_RAWHID(HID_REPORTID_RAWHID), // not working at the moment #endif -#ifdef HID_CONSUMER_ENABLE +#ifdef HID_CONSUMERCONTROL_ENABLE HID_REPORT_CONSUMERCONTROL(HID_REPORTID_CONSUMERCONTROL), #endif #ifdef HID_SYSTEM_ENABLE diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h index 418898075f..1ce2518320 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h @@ -50,7 +50,7 @@ THE SOFTWARE. #if !defined(EXTERN_HID_REPORT) && !defined(HID_MOUSE_ENABLE) && !defined(HID_KEYBOARD_KEYS_ENABLE) \ && !defined(HID_KEYBOARD_LEDS_ENABLE) && !defined(HID_MOUSE_ABSOLUTE_ENABLE) && !defined(HID_RAWHID_ENABLE) \ -&& !defined(HID_CONSUMER_ENABLE) && !defined(HID_SYSTEM_ENABLE) && !defined(HID_GAMEPAD_ENABLE) +&& !defined(HID_CONSUMERCONTROL_ENABLE) && !defined(HID_SYSTEM_ENABLE) && !defined(HID_GAMEPAD_ENABLE) // by default enable mouse + keyboard api #define HID_MOUSE_ENABLE #define HID_KEYBOARD_KEYS_ENABLE diff --git a/plugins/KeyboardioHID/avr/variants/micro_custom/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/micro_custom/pins_arduino.h index d83b4efac0..987774fcec 100644 --- a/plugins/KeyboardioHID/avr/variants/micro_custom/pins_arduino.h +++ b/plugins/KeyboardioHID/avr/variants/micro_custom/pins_arduino.h @@ -40,7 +40,7 @@ You have to enable the specific hid apis on your own then, also the keyboard led */ #define HID_AUTOMATIC -#define HID_CUSTOM_SETTINGS +//#define HID_CUSTOM_SETTINGS //================================================================================ // Automatic From 1b0e4854534a08b9c9f797b533550df81b39f420 Mon Sep 17 00:00:00 2001 From: Nico Date: Sat, 4 Apr 2015 20:55:29 +0200 Subject: [PATCH 182/602] Consumer Custom test --- .../KeyboardioHID/avr/variants/micro_custom/pins_arduino.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/KeyboardioHID/avr/variants/micro_custom/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/micro_custom/pins_arduino.h index 987774fcec..37aa6fbdd0 100644 --- a/plugins/KeyboardioHID/avr/variants/micro_custom/pins_arduino.h +++ b/plugins/KeyboardioHID/avr/variants/micro_custom/pins_arduino.h @@ -48,12 +48,13 @@ You have to enable the specific hid apis on your own then, also the keyboard led #ifdef HID_AUTOMATIC // pre selected hid reports with autoinclude of the api -#define HID_MOUSE_ENABLE // normal mouse with buttons + wheel +//#define HID_MOUSE_ENABLE // normal mouse with buttons + wheel //#define HID_MOUSE_ABSOLUTE_ENABLE // only works with system and without gamepad -#define HID_KEYBOARD_LEDS_ENABLE // leds OR keys +//#define HID_KEYBOARD_LEDS_ENABLE // leds OR keys //#define HID_KEYBOARD_KEYS_ENABLE //#define HID_RAWHID_ENABLE // currently not working -//#define HID_CONSUMERCONTROL_ENABLE +#define HID_CONSUMERCONTROL_ENABLE +#define HID_REPORTID_CONSUMERCONTROL 1 //#define HID_SYSTEMCONTROL_ENABLE //#define HID_GAMEPAD_ENABLE // only works without mouse absolute From cd72484e45555c7304c0b11b5dbe0351c0cc3f98 Mon Sep 17 00:00:00 2001 From: Nico Date: Sat, 4 Apr 2015 21:04:53 +0200 Subject: [PATCH 183/602] Revert "Consumer Custom test" This reverts commit 1b0e4854534a08b9c9f797b533550df81b39f420. --- .../KeyboardioHID/avr/variants/micro_custom/pins_arduino.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/plugins/KeyboardioHID/avr/variants/micro_custom/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/micro_custom/pins_arduino.h index 37aa6fbdd0..987774fcec 100644 --- a/plugins/KeyboardioHID/avr/variants/micro_custom/pins_arduino.h +++ b/plugins/KeyboardioHID/avr/variants/micro_custom/pins_arduino.h @@ -48,13 +48,12 @@ You have to enable the specific hid apis on your own then, also the keyboard led #ifdef HID_AUTOMATIC // pre selected hid reports with autoinclude of the api -//#define HID_MOUSE_ENABLE // normal mouse with buttons + wheel +#define HID_MOUSE_ENABLE // normal mouse with buttons + wheel //#define HID_MOUSE_ABSOLUTE_ENABLE // only works with system and without gamepad -//#define HID_KEYBOARD_LEDS_ENABLE // leds OR keys +#define HID_KEYBOARD_LEDS_ENABLE // leds OR keys //#define HID_KEYBOARD_KEYS_ENABLE //#define HID_RAWHID_ENABLE // currently not working -#define HID_CONSUMERCONTROL_ENABLE -#define HID_REPORTID_CONSUMERCONTROL 1 +//#define HID_CONSUMERCONTROL_ENABLE //#define HID_SYSTEMCONTROL_ENABLE //#define HID_GAMEPAD_ENABLE // only works without mouse absolute From 88b88a9e21bf4e726bc3833875d9db3ea9d879e8 Mon Sep 17 00:00:00 2001 From: Nico Date: Mon, 6 Apr 2015 15:37:49 +0200 Subject: [PATCH 184/602] Readme update --- plugins/KeyboardioHID/Readme.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index cee132e208..ad3d1f610d 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -73,6 +73,8 @@ Version History * Upload verification on USB hubs fix for HL2.0.4 * No USB workaround for Leonardo integrated into variants * Changed USB Wakeup in System API +* Consumer Key fix (issue #3) +* Gamepad fix (issue #14) 2.1 Release (28.01.2015) * Reworked the whole USB-Core from scratch From 82b72176ae87f88a138516ad67fcd91f8405ae90 Mon Sep 17 00:00:00 2001 From: Nico Date: Sat, 11 Apr 2015 09:31:23 +0200 Subject: [PATCH 185/602] Moved and improved examples --- .../Consumer/Consumer.ino} | 14 +-- .../Gamepad/Gamepad.ino} | 32 +------ .../Gamepad_Advanced/Gamepad_Advanced.ino} | 0 .../examples/HID/Keyboard/Keyboard.ino | 39 ++++++++ .../Keyboard_Advanced/Keyboard_Advanced.ino} | 0 .../Keyboard_Led/Keyboard_Led.ino} | 0 .../HID_Mouse.ino => HID/Mouse/Mouse.ino} | 0 .../RawHID_Advanced/RawHID_Advanced.ino} | 4 +- .../HID_System.ino => HID/System/System.ino} | 4 +- .../HID_Basic/HID_Keyboard/HID_Keyboard.ino | 90 ------------------- .../examples/HelloWorld/HelloWorld.ino | 1 + 11 files changed, 49 insertions(+), 135 deletions(-) rename plugins/KeyboardioHID/examples/{HID_Basic/HID_Consumer/HID_Consumer.ino => HID/Consumer/Consumer.ino} (64%) rename plugins/KeyboardioHID/examples/{HID_Basic/HID_Gamepad/HID_Gamepad.ino => HID/Gamepad/Gamepad.ino} (65%) rename plugins/KeyboardioHID/examples/{HID_Advanced/AdvancedGamepad/AdvancedGamepad.ino => HID/Gamepad_Advanced/Gamepad_Advanced.ino} (100%) create mode 100644 plugins/KeyboardioHID/examples/HID/Keyboard/Keyboard.ino rename plugins/KeyboardioHID/examples/{HID_Advanced/AdvancedKeyboard/AdvancedKeyboard.ino => HID/Keyboard_Advanced/Keyboard_Advanced.ino} (100%) rename plugins/KeyboardioHID/examples/{HID_Basic/HID_Keyboard_Led/HID_Keyboard_Led.ino => HID/Keyboard_Led/Keyboard_Led.ino} (100%) rename plugins/KeyboardioHID/examples/{HID_Basic/HID_Mouse/HID_Mouse.ino => HID/Mouse/Mouse.ino} (100%) rename plugins/KeyboardioHID/examples/{HID_Advanced/AdvancedRawHID/AdvancedRawHID.ino => HID/RawHID_Advanced/RawHID_Advanced.ino} (97%) rename plugins/KeyboardioHID/examples/{HID_Basic/HID_System/HID_System.ino => HID/System/System.ino} (91%) delete mode 100644 plugins/KeyboardioHID/examples/HID_Basic/HID_Keyboard/HID_Keyboard.ino diff --git a/plugins/KeyboardioHID/examples/HID_Basic/HID_Consumer/HID_Consumer.ino b/plugins/KeyboardioHID/examples/HID/Consumer/Consumer.ino similarity index 64% rename from plugins/KeyboardioHID/examples/HID_Basic/HID_Consumer/HID_Consumer.ino rename to plugins/KeyboardioHID/examples/HID/Consumer/Consumer.ino index f74192f280..12bc93780e 100644 --- a/plugins/KeyboardioHID/examples/HID_Basic/HID_Consumer/HID_Consumer.ino +++ b/plugins/KeyboardioHID/examples/HID/Consumer/Consumer.ino @@ -6,19 +6,7 @@ Press a button to play/pause music player See HID Project documentation for more Consumer keys. - https://github.com/NicoHood/HID/wiki/Consumer-API#key-definitions - -// basic Media key definitions, see HID Project and official USB docs for more -#define MEDIA_FAST_FORWARD 0xB3 -#define MEDIA_REWIND 0xB4 -#define MEDIA_NEXT 0xB5 -#define MEDIA_PREVIOUS 0xB6 -#define MEDIA_STOP 0xB7 -#define MEDIA_PLAY_PAUSE 0xCD - -#define MEDIA_VOLUME_MUTE 0xE2 -#define MEDIA_VOLUME_UP 0xE9 -#define MEDIA_VOLUME_DOWN 0xEA + https://github.com/NicoHood/HID/wiki/Consumer-API */ const int pinLed = LED_BUILTIN; diff --git a/plugins/KeyboardioHID/examples/HID_Basic/HID_Gamepad/HID_Gamepad.ino b/plugins/KeyboardioHID/examples/HID/Gamepad/Gamepad.ino similarity index 65% rename from plugins/KeyboardioHID/examples/HID_Basic/HID_Gamepad/HID_Gamepad.ino rename to plugins/KeyboardioHID/examples/HID/Gamepad/Gamepad.ino index 89007aed9e..54c4bc4ad8 100644 --- a/plugins/KeyboardioHID/examples/HID_Basic/HID_Gamepad/HID_Gamepad.ino +++ b/plugins/KeyboardioHID/examples/HID/Gamepad/Gamepad.ino @@ -5,34 +5,8 @@ Gamepad example Press a button and demonstrate Gamepad actions - - Function prototypes: - void begin(void); - void end(void); - void write(void); - void press(uint8_t b); - void release(uint8_t b); - void releaseAll(void); - void buttons(uint32_t b); - void xAxis(int16_t a); - void yAxis(int16_t a); - void rxAxis(int16_t a); - void ryAxis(int16_t a); - void zAxis(int8_t a); - void rzAxis(int8_t a); - void dPad1(int8_t d); - void dPad2(int8_t d); - - Definitions: - GAMEPAD_DPAD_CENTERED 0 - GAMEPAD_DPAD_UP 1 - GAMEPAD_DPAD_UP_RIGHT 2 - GAMEPAD_DPAD_RIGHT 3 - GAMEPAD_DPAD_DOWN_RIGHT 4 - GAMEPAD_DPAD_DOWN 5 - GAMEPAD_DPAD_DOWN_LEFT 6 - GAMEPAD_DPAD_LEFT 7 - GAMEPAD_DPAD_UP_LEFT 8 + See HID Project documentation for more infos + https://github.com/NicoHood/HID/wiki/Gamepad-API */ const int pinLed = LED_BUILTIN; @@ -50,7 +24,7 @@ void loop() { if (!digitalRead(pinButton)) { digitalWrite(pinLed, HIGH); - // press button 1-32 and reset (34 becaue its written later) + // press button 1-32 and reset (34 because its written later) static uint8_t count = 1; Gamepad.press(count++); if (count == 34) { diff --git a/plugins/KeyboardioHID/examples/HID_Advanced/AdvancedGamepad/AdvancedGamepad.ino b/plugins/KeyboardioHID/examples/HID/Gamepad_Advanced/Gamepad_Advanced.ino similarity index 100% rename from plugins/KeyboardioHID/examples/HID_Advanced/AdvancedGamepad/AdvancedGamepad.ino rename to plugins/KeyboardioHID/examples/HID/Gamepad_Advanced/Gamepad_Advanced.ino diff --git a/plugins/KeyboardioHID/examples/HID/Keyboard/Keyboard.ino b/plugins/KeyboardioHID/examples/HID/Keyboard/Keyboard.ino new file mode 100644 index 0000000000..ee076b24f8 --- /dev/null +++ b/plugins/KeyboardioHID/examples/HID/Keyboard/Keyboard.ino @@ -0,0 +1,39 @@ +/* + Copyright (c) 2014 NicoHood + See the readme for credit to other people. + + Keyboard example + + Press a button to write some text to your pc. + See official and HID Project documentation for more infos + https://github.com/NicoHood/HID/wiki/Keyboard-API +*/ + +const int pinLed = LED_BUILTIN; +const int pinButton = 2; + +void setup() { + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); + + // Starts Serial debug output + Serial.begin(115200); + + // Sends a clean report to the host. This is important on any Arduino type. + Keyboard.begin(); +} + + +void loop() { + if (!digitalRead(pinButton)) { + digitalWrite(pinLed, HIGH); + + // Same use as the official library, pretty much self explaining + Keyboard.println(F("This message was sent with my Arduino.")); + Serial.println(F("Serial port is still working and not glitching out")); + + // simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } +} diff --git a/plugins/KeyboardioHID/examples/HID_Advanced/AdvancedKeyboard/AdvancedKeyboard.ino b/plugins/KeyboardioHID/examples/HID/Keyboard_Advanced/Keyboard_Advanced.ino similarity index 100% rename from plugins/KeyboardioHID/examples/HID_Advanced/AdvancedKeyboard/AdvancedKeyboard.ino rename to plugins/KeyboardioHID/examples/HID/Keyboard_Advanced/Keyboard_Advanced.ino diff --git a/plugins/KeyboardioHID/examples/HID_Basic/HID_Keyboard_Led/HID_Keyboard_Led.ino b/plugins/KeyboardioHID/examples/HID/Keyboard_Led/Keyboard_Led.ino similarity index 100% rename from plugins/KeyboardioHID/examples/HID_Basic/HID_Keyboard_Led/HID_Keyboard_Led.ino rename to plugins/KeyboardioHID/examples/HID/Keyboard_Led/Keyboard_Led.ino diff --git a/plugins/KeyboardioHID/examples/HID_Basic/HID_Mouse/HID_Mouse.ino b/plugins/KeyboardioHID/examples/HID/Mouse/Mouse.ino similarity index 100% rename from plugins/KeyboardioHID/examples/HID_Basic/HID_Mouse/HID_Mouse.ino rename to plugins/KeyboardioHID/examples/HID/Mouse/Mouse.ino diff --git a/plugins/KeyboardioHID/examples/HID_Advanced/AdvancedRawHID/AdvancedRawHID.ino b/plugins/KeyboardioHID/examples/HID/RawHID_Advanced/RawHID_Advanced.ino similarity index 97% rename from plugins/KeyboardioHID/examples/HID_Advanced/AdvancedRawHID/AdvancedRawHID.ino rename to plugins/KeyboardioHID/examples/HID/RawHID_Advanced/RawHID_Advanced.ino index ffadce7a26..494094759e 100644 --- a/plugins/KeyboardioHID/examples/HID_Advanced/AdvancedRawHID/AdvancedRawHID.ino +++ b/plugins/KeyboardioHID/examples/HID/RawHID_Advanced/RawHID_Advanced.ino @@ -2,7 +2,7 @@ Copyright (c) 2014 NicoHood See the readme for credit to other people. - Advanced RawHID example (currently not available) + Advanced RawHID example (currently not available/broken) Shows how to send bytes via raw HID Press a button to send some example values. @@ -105,4 +105,4 @@ recv 15 bytes: recv 15 bytes: 48 65 6C 6C 6F 20 57 6F 72 6C 64 0D 0A 00 00 -*/ \ No newline at end of file +*/ diff --git a/plugins/KeyboardioHID/examples/HID_Basic/HID_System/HID_System.ino b/plugins/KeyboardioHID/examples/HID/System/System.ino similarity index 91% rename from plugins/KeyboardioHID/examples/HID_Basic/HID_System/HID_System.ino rename to plugins/KeyboardioHID/examples/HID/System/System.ino index 0531cb255d..f4faf239f8 100644 --- a/plugins/KeyboardioHID/examples/HID_Basic/HID_System/HID_System.ino +++ b/plugins/KeyboardioHID/examples/HID/System/System.ino @@ -5,6 +5,8 @@ System example Press a button to put pc into sleep/shut it down or wake it up again. + See HID Project documentation for more infos + https://github.com/NicoHood/HID/wiki/System-API */ const int pinLed = LED_BUILTIN; @@ -45,4 +47,4 @@ void loop() { delay(300); digitalWrite(pinLed, LOW); } -} \ No newline at end of file +} diff --git a/plugins/KeyboardioHID/examples/HID_Basic/HID_Keyboard/HID_Keyboard.ino b/plugins/KeyboardioHID/examples/HID_Basic/HID_Keyboard/HID_Keyboard.ino deleted file mode 100644 index 83566d83d5..0000000000 --- a/plugins/KeyboardioHID/examples/HID_Basic/HID_Keyboard/HID_Keyboard.ino +++ /dev/null @@ -1,90 +0,0 @@ -/* - Copyright (c) 2014 NicoHood - See the readme for credit to other people. - - Keyboard example - - Press a button to write some text to your pc. - See official and HID Project documentation for more infos -*/ - -const int pinLed = LED_BUILTIN; -const int pinButton = 2; - -void setup() { - pinMode(pinLed, OUTPUT); - pinMode(pinButton, INPUT_PULLUP); - - // Starts Serial debug output - Serial.begin(115200); - - // Sends a clean report to the host. This is important on any Arduino type. - Keyboard.begin(); -} - - -void loop() { - if (!digitalRead(pinButton)) { - digitalWrite(pinLed, HIGH); - - // Same use as the official library, pretty much self explaining - Keyboard.println(F("This message was sent with my Arduino.")); - Serial.println(F("Serial port is still working and not glitching out")); - - // simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } -} - -/* -Definitions: - -#define KEY_PRINT 0xCE -#define KEY_NUM_LOCK 0xDB -#define KEY_SCROLL_LOCK 0xCF -#define KEY_PAUSE 0xD0 - -#define KEY_LEFT_CTRL 0x80 -#define KEY_LEFT_SHIFT 0x81 -#define KEY_LEFT_ALT 0x82 -#define KEY_LEFT_GUI 0x83 -#define KEY_LEFT_WINDOWS KEY_LEFT_GUI -#define KEY_RIGHT_CTRL 0x84 -#define KEY_RIGHT_SHIFT 0x85 -#define KEY_RIGHT_ALT 0x86 -#define KEY_RIGHT_GUI 0x87 -#define KEY_RIGHT_WINDOWS KEY_RIGHT_GUI - -#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 - -#define LED_NUM_LOCK 0x01 -#define LED_CAPS_LOCK 0x02 -#define LED_SCROLL_LOCK 0x04 - */ diff --git a/plugins/KeyboardioHID/examples/HelloWorld/HelloWorld.ino b/plugins/KeyboardioHID/examples/HelloWorld/HelloWorld.ino index eaa964bc7b..187908d571 100644 --- a/plugins/KeyboardioHID/examples/HelloWorld/HelloWorld.ino +++ b/plugins/KeyboardioHID/examples/HelloWorld/HelloWorld.ino @@ -6,6 +6,7 @@ Press a button to write some text to your pc. See official and HID Project documentation for more information. + https://github.com/NicoHood/HID/wiki */ const int pinLed = LED_BUILTIN; From 938a2c7890a50761622cc9c109aea4a903e23ea5 Mon Sep 17 00:00:00 2001 From: Nico Date: Sat, 11 Apr 2015 09:31:32 +0200 Subject: [PATCH 186/602] Added Keycode example --- .../HID/Keyboard_Keycode/Keyboard_Keycode.ino | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 plugins/KeyboardioHID/examples/HID/Keyboard_Keycode/Keyboard_Keycode.ino diff --git a/plugins/KeyboardioHID/examples/HID/Keyboard_Keycode/Keyboard_Keycode.ino b/plugins/KeyboardioHID/examples/HID/Keyboard_Keycode/Keyboard_Keycode.ino new file mode 100644 index 0000000000..d195dcd2f9 --- /dev/null +++ b/plugins/KeyboardioHID/examples/HID/Keyboard_Keycode/Keyboard_Keycode.ino @@ -0,0 +1,56 @@ +/* + Copyright (c) 2014 NicoHood + See the readme for credit to other people. + + Keyboard Keycode example + + Press a button to write some text to your pc. + This example is made for advanced users, to add specific keys to the HID report. + See official and HID Project and USB docs documentation for more infos + https://github.com/NicoHood/HID/wiki/Keyboard-API + http://www.usb.org/developers/hidpage/Hut1_12v2.pdf +*/ + +const int pinLed = LED_BUILTIN; +const int pinButton = 2; + +void setup() { + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); + + // Sends a clean report to the host. This is important on any Arduino type. + Keyboard.begin(); +} + +void loop() { + if (!digitalRead(pinButton)) { + digitalWrite(pinLed, HIGH); + + // the "normal" way + //Keyboard.println("Test"); + + // press 'a' via normal API + //Keyboard.write('a'); + + // press 'a' via keycodes + Keyboard.writeKeycode(0x04); + + // press the contect menu button via normal API + //Keyboard.write(KEY_MENU); + + // press the context menu button via keycodes (right mouse click) + //Keyboard.writeKeycode(0x65); + + // You can also try some specific keys that do not work on every OS + /* + #define HID_KEYBOARD_MUTE 0x7F + #define HID_KEYBOARD_VOLUME_UP 0x80 + #define HID_KEYBOARD_VOLUME_DOWN 0x81 + */ + //Keyboard.writeKeycode(0x7F); + + // simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } +} From d5793da3c6d72cc7150ca295b04315e5467d7ff0 Mon Sep 17 00:00:00 2001 From: Nico Date: Sun, 12 Apr 2015 12:51:23 +0200 Subject: [PATCH 187/602] Update 2.2 --- plugins/KeyboardioHID/Readme.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index ad3d1f610d..86b5a6a90a 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -51,8 +51,7 @@ Keyboard Layout for different Languages Clean up USB Core code from fixed values. Use better understandable definitions Magic key fix for 32u4? -keycode/raw for keyboard -Check Keyboard keycode function again? + add example +Check Keyboard keycode function again Generalize HID key definitions via HIDTables for example? Test with Android phone (HL1) @@ -63,8 +62,8 @@ improve keywords.txt Version History =============== ``` -2.2 Release (xx.xx.2015) -* added HID-Bridge between 16u2 and 328/2560 +2.2 Release (12.04.2015) +* added experimental, not finished nor documented HID-Bridge between 16u2 and 328/2560 * increased HW Serial1 RX buffer size from 16 to 32 (TX still 16) * added colour highlighting (through HID-Bridge library) * removed fixed size in report buffers @@ -75,6 +74,7 @@ Version History * Changed USB Wakeup in System API * Consumer Key fix (issue #3) * Gamepad fix (issue #14) +* Added Keycode example 2.1 Release (28.01.2015) * Reworked the whole USB-Core from scratch From bfc20c9f87ff42d22e9217b95d7840e19b9dd90d Mon Sep 17 00:00:00 2001 From: Nico Date: Sun, 12 Apr 2015 12:54:57 +0200 Subject: [PATCH 188/602] removed 1.6.2 note --- plugins/KeyboardioHID/Readme.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index f5ffc09c09..86b5a6a90a 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -14,8 +14,6 @@ See the [wiki](https://github.com/NicoHood/HID/wiki/Features) for more informati Download ======== -###Download the current dev version for 1.6.2 compatibility. The master currently only works with 1.6.1 and the dev only with 1.6.2 due to internal IDE changes. - You have 3 versions you can download: * The master includes all fixes to the current stable release. Download it by clicking download at the right. Use the [online Wiki](https://github.com/NicoHood/HID/wiki) to get the newest documentation. From 48ad3bab0e9e50096d7c45a8e00ef4bb9f5f0388 Mon Sep 17 00:00:00 2001 From: Nico Date: Tue, 14 Apr 2015 19:16:59 +0200 Subject: [PATCH 189/602] Updated Readme and credits --- plugins/KeyboardioHID/Readme.md | 4 +++- .../variants/leonardo_no_usb/no_usb_isr.cpp | 23 +++++++++++++++++++ .../avr/variants/micro_no_usb/no_usb_isr.cpp | 23 +++++++++++++++++++ 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 86b5a6a90a..a9367f6c7d 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -1,4 +1,4 @@ -Arduino HID Project 2.2 +Arduino HID Project 2.3 ======================= [![Join the chat at https://gitter.im/NicoHood/HID](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/NicoHood/HID?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) @@ -62,6 +62,8 @@ improve keywords.txt Version History =============== ``` +2.3 Release (xx.xx.2015) + 2.2 Release (12.04.2015) * added experimental, not finished nor documented HID-Bridge between 16u2 and 328/2560 * increased HW Serial1 RX buffer size from 16 to 32 (TX still 16) diff --git a/plugins/KeyboardioHID/avr/variants/leonardo_no_usb/no_usb_isr.cpp b/plugins/KeyboardioHID/avr/variants/leonardo_no_usb/no_usb_isr.cpp index eec342f6a9..5c5f42242f 100644 --- a/plugins/KeyboardioHID/avr/variants/leonardo_no_usb/no_usb_isr.cpp +++ b/plugins/KeyboardioHID/avr/variants/leonardo_no_usb/no_usb_isr.cpp @@ -1,3 +1,26 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 #include diff --git a/plugins/KeyboardioHID/avr/variants/micro_no_usb/no_usb_isr.cpp b/plugins/KeyboardioHID/avr/variants/micro_no_usb/no_usb_isr.cpp index eec342f6a9..5c5f42242f 100644 --- a/plugins/KeyboardioHID/avr/variants/micro_no_usb/no_usb_isr.cpp +++ b/plugins/KeyboardioHID/avr/variants/micro_no_usb/no_usb_isr.cpp @@ -1,3 +1,26 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 #include From 3e1fac7182298e10b4aae7d90689d7bfdf752d3e Mon Sep 17 00:00:00 2001 From: Nico Date: Tue, 14 Apr 2015 19:21:52 +0200 Subject: [PATCH 190/602] Minor Keyboard API fix --- plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.cpp b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.cpp index 8f2c935cdf..66bcd997b2 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.cpp +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.cpp @@ -50,7 +50,7 @@ Keyboard_ Keyboard; void Keyboard_::sendReport(HID_KeyboardReport_Data_t* keys) { - HID_SendReport(HID_REPORTID_KEYBOARD, keys, sizeof(HID_KeyboardReport_Data_t)); + HID_SendReport(HID_REPORTID_KEYBOARD, keys, sizeof(keys)); } extern From 2c5317f4769ddb7e24cd513b6adf17063d1278c1 Mon Sep 17 00:00:00 2001 From: Nico Date: Sun, 19 Apr 2015 18:30:05 +0200 Subject: [PATCH 191/602] Mouse fix --- plugins/KeyboardioHID/Readme.md | 1 + plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.h | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 86b5a6a90a..213f18681b 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -75,6 +75,7 @@ Version History * Consumer Key fix (issue #3) * Gamepad fix (issue #14) * Added Keycode example +* Mouse press + release fix 2.1 Release (28.01.2015) * Reworked the whole USB-Core from scratch diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.h index fa5b2559cc..0ec0a1b3d8 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.h @@ -87,7 +87,12 @@ class Mouse_ { private: uint8_t _buttons; - void buttons(uint8_t b); + inline void buttons(uint8_t b){ + if (b != _buttons){ + _buttons = b; + move(0, 0, 0); + } + } public: inline Mouse_(void) { // removed this to avoid creating an instance of Mouse if not needed From 12c092b0e16db8717e9977e56b529a4c21e7a01e Mon Sep 17 00:00:00 2001 From: Nico Date: Mon, 20 Apr 2015 14:28:24 +0200 Subject: [PATCH 192/602] Example Compile error fix https://github.com/arduino/Arduino/issues/2997 --- .../{Consumer/Consumer.ino => Consumer_Basic/Consumer_Basic.ino} | 0 .../HID/{Gamepad/Gamepad.ino => Gamepad_Basic/Gamepad_Basic.ino} | 0 .../{Keyboard/Keyboard.ino => Keyboard_Basic/Keyboard_Basic.ino} | 0 .../examples/HID/{Mouse/Mouse.ino => Mouse_Basic/Mouse_Basic.ino} | 0 .../HID/{System/System.ino => System_Basic/System_Basic.ino} | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename plugins/KeyboardioHID/examples/HID/{Consumer/Consumer.ino => Consumer_Basic/Consumer_Basic.ino} (100%) rename plugins/KeyboardioHID/examples/HID/{Gamepad/Gamepad.ino => Gamepad_Basic/Gamepad_Basic.ino} (100%) rename plugins/KeyboardioHID/examples/HID/{Keyboard/Keyboard.ino => Keyboard_Basic/Keyboard_Basic.ino} (100%) rename plugins/KeyboardioHID/examples/HID/{Mouse/Mouse.ino => Mouse_Basic/Mouse_Basic.ino} (100%) rename plugins/KeyboardioHID/examples/HID/{System/System.ino => System_Basic/System_Basic.ino} (100%) diff --git a/plugins/KeyboardioHID/examples/HID/Consumer/Consumer.ino b/plugins/KeyboardioHID/examples/HID/Consumer_Basic/Consumer_Basic.ino similarity index 100% rename from plugins/KeyboardioHID/examples/HID/Consumer/Consumer.ino rename to plugins/KeyboardioHID/examples/HID/Consumer_Basic/Consumer_Basic.ino diff --git a/plugins/KeyboardioHID/examples/HID/Gamepad/Gamepad.ino b/plugins/KeyboardioHID/examples/HID/Gamepad_Basic/Gamepad_Basic.ino similarity index 100% rename from plugins/KeyboardioHID/examples/HID/Gamepad/Gamepad.ino rename to plugins/KeyboardioHID/examples/HID/Gamepad_Basic/Gamepad_Basic.ino diff --git a/plugins/KeyboardioHID/examples/HID/Keyboard/Keyboard.ino b/plugins/KeyboardioHID/examples/HID/Keyboard_Basic/Keyboard_Basic.ino similarity index 100% rename from plugins/KeyboardioHID/examples/HID/Keyboard/Keyboard.ino rename to plugins/KeyboardioHID/examples/HID/Keyboard_Basic/Keyboard_Basic.ino diff --git a/plugins/KeyboardioHID/examples/HID/Mouse/Mouse.ino b/plugins/KeyboardioHID/examples/HID/Mouse_Basic/Mouse_Basic.ino similarity index 100% rename from plugins/KeyboardioHID/examples/HID/Mouse/Mouse.ino rename to plugins/KeyboardioHID/examples/HID/Mouse_Basic/Mouse_Basic.ino diff --git a/plugins/KeyboardioHID/examples/HID/System/System.ino b/plugins/KeyboardioHID/examples/HID/System_Basic/System_Basic.ino similarity index 100% rename from plugins/KeyboardioHID/examples/HID/System/System.ino rename to plugins/KeyboardioHID/examples/HID/System_Basic/System_Basic.ino From 2d1ed679b2b7f4bfdb1d70e0f31d0c01091f6de7 Mon Sep 17 00:00:00 2001 From: Nico Date: Mon, 20 Apr 2015 14:34:15 +0200 Subject: [PATCH 193/602] Example Compile error fix https://github.com/arduino/Arduino/issues/2997 --- .../{Consumer/Consumer.ino => Consumer_Basic/Consumer_Basic.ino} | 0 .../HID/{Gamepad/Gamepad.ino => Gamepad_Basic/Gamepad_Basic.ino} | 0 .../{Keyboard/Keyboard.ino => Keyboard_Basic/Keyboard_Basic.ino} | 0 .../examples/HID/{Mouse/Mouse.ino => Mouse_Basic/Mouse_Basic.ino} | 0 .../HID/{System/System.ino => System_Basic/System_Basic.ino} | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename plugins/KeyboardioHID/examples/HID/{Consumer/Consumer.ino => Consumer_Basic/Consumer_Basic.ino} (100%) rename plugins/KeyboardioHID/examples/HID/{Gamepad/Gamepad.ino => Gamepad_Basic/Gamepad_Basic.ino} (100%) rename plugins/KeyboardioHID/examples/HID/{Keyboard/Keyboard.ino => Keyboard_Basic/Keyboard_Basic.ino} (100%) rename plugins/KeyboardioHID/examples/HID/{Mouse/Mouse.ino => Mouse_Basic/Mouse_Basic.ino} (100%) rename plugins/KeyboardioHID/examples/HID/{System/System.ino => System_Basic/System_Basic.ino} (100%) diff --git a/plugins/KeyboardioHID/examples/HID/Consumer/Consumer.ino b/plugins/KeyboardioHID/examples/HID/Consumer_Basic/Consumer_Basic.ino similarity index 100% rename from plugins/KeyboardioHID/examples/HID/Consumer/Consumer.ino rename to plugins/KeyboardioHID/examples/HID/Consumer_Basic/Consumer_Basic.ino diff --git a/plugins/KeyboardioHID/examples/HID/Gamepad/Gamepad.ino b/plugins/KeyboardioHID/examples/HID/Gamepad_Basic/Gamepad_Basic.ino similarity index 100% rename from plugins/KeyboardioHID/examples/HID/Gamepad/Gamepad.ino rename to plugins/KeyboardioHID/examples/HID/Gamepad_Basic/Gamepad_Basic.ino diff --git a/plugins/KeyboardioHID/examples/HID/Keyboard/Keyboard.ino b/plugins/KeyboardioHID/examples/HID/Keyboard_Basic/Keyboard_Basic.ino similarity index 100% rename from plugins/KeyboardioHID/examples/HID/Keyboard/Keyboard.ino rename to plugins/KeyboardioHID/examples/HID/Keyboard_Basic/Keyboard_Basic.ino diff --git a/plugins/KeyboardioHID/examples/HID/Mouse/Mouse.ino b/plugins/KeyboardioHID/examples/HID/Mouse_Basic/Mouse_Basic.ino similarity index 100% rename from plugins/KeyboardioHID/examples/HID/Mouse/Mouse.ino rename to plugins/KeyboardioHID/examples/HID/Mouse_Basic/Mouse_Basic.ino diff --git a/plugins/KeyboardioHID/examples/HID/System/System.ino b/plugins/KeyboardioHID/examples/HID/System_Basic/System_Basic.ino similarity index 100% rename from plugins/KeyboardioHID/examples/HID/System/System.ino rename to plugins/KeyboardioHID/examples/HID/System_Basic/System_Basic.ino From f30e12256a67a1f9a4d567bdde6b3a50618c1284 Mon Sep 17 00:00:00 2001 From: Nico Date: Fri, 24 Apr 2015 18:06:32 +0200 Subject: [PATCH 194/602] Update Keyboard_Led.ino --- .../HID/Keyboard_Led/Keyboard_Led.ino | 57 +------------------ 1 file changed, 3 insertions(+), 54 deletions(-) diff --git a/plugins/KeyboardioHID/examples/HID/Keyboard_Led/Keyboard_Led.ino b/plugins/KeyboardioHID/examples/HID/Keyboard_Led/Keyboard_Led.ino index 3aa8134f82..273d484358 100644 --- a/plugins/KeyboardioHID/examples/HID/Keyboard_Led/Keyboard_Led.ino +++ b/plugins/KeyboardioHID/examples/HID/Keyboard_Led/Keyboard_Led.ino @@ -1,5 +1,5 @@ /* - Copyright (c) 2014 NicoHood + Copyright (c) 2014-2015 NicoHood See the readme for credit to other people. Keyboard Led example @@ -7,6 +7,7 @@ Press a button to toogle caps lock. Caps lock state is represented by the onboard led. See official and HID Project documentation for more infos + https://github.com/NicoHood/HID/wiki/Keyboard-API */ const int pinLed = LED_BUILTIN; @@ -24,7 +25,7 @@ void setup() { void loop() { // update Led equal to the caps lock state // keep in mind on HoodLoader2 high&low are inverted (like this) - if (Keyboard.getLeds()&LED_CAPS_LOCK) + if (Keyboard.getLeds() & LED_CAPS_LOCK) digitalWrite(pinLed, LOW); else digitalWrite(pinLed, HIGH); @@ -37,55 +38,3 @@ void loop() { delay(500); } } - -/* -Definitions: - -#define KEY_PRINT 0xCE -#define KEY_NUM_LOCK 0xDB -#define KEY_SCROLL_LOCK 0xCF -#define KEY_PAUSE 0xD0 - -#define KEY_LEFT_CTRL 0x80 -#define KEY_LEFT_SHIFT 0x81 -#define KEY_LEFT_ALT 0x82 -#define KEY_LEFT_GUI 0x83 -#define KEY_LEFT_WINDOWS KEY_LEFT_GUI -#define KEY_RIGHT_CTRL 0x84 -#define KEY_RIGHT_SHIFT 0x85 -#define KEY_RIGHT_ALT 0x86 -#define KEY_RIGHT_GUI 0x87 -#define KEY_RIGHT_WINDOWS KEY_RIGHT_GUI - -#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 - -#define LED_NUM_LOCK 0x01 -#define LED_CAPS_LOCK 0x02 -#define LED_SCROLL_LOCK 0x04 - */ From 06df69cc4f552ff8e9420a5bcb484fec7561bc52 Mon Sep 17 00:00:00 2001 From: Nico Date: Mon, 27 Apr 2015 15:00:20 +0200 Subject: [PATCH 195/602] Removed documentation in the example itself --- .../HID/Keyboard_Led/Keyboard_Led.ino | 55 +------------------ 1 file changed, 2 insertions(+), 53 deletions(-) diff --git a/plugins/KeyboardioHID/examples/HID/Keyboard_Led/Keyboard_Led.ino b/plugins/KeyboardioHID/examples/HID/Keyboard_Led/Keyboard_Led.ino index 3aa8134f82..960ca7f715 100644 --- a/plugins/KeyboardioHID/examples/HID/Keyboard_Led/Keyboard_Led.ino +++ b/plugins/KeyboardioHID/examples/HID/Keyboard_Led/Keyboard_Led.ino @@ -7,6 +7,7 @@ Press a button to toogle caps lock. Caps lock state is represented by the onboard led. See official and HID Project documentation for more infos + https://github.com/NicoHood/HID/wiki/Keyboard-API */ const int pinLed = LED_BUILTIN; @@ -36,56 +37,4 @@ void loop() { // simple debounce delay(500); } -} - -/* -Definitions: - -#define KEY_PRINT 0xCE -#define KEY_NUM_LOCK 0xDB -#define KEY_SCROLL_LOCK 0xCF -#define KEY_PAUSE 0xD0 - -#define KEY_LEFT_CTRL 0x80 -#define KEY_LEFT_SHIFT 0x81 -#define KEY_LEFT_ALT 0x82 -#define KEY_LEFT_GUI 0x83 -#define KEY_LEFT_WINDOWS KEY_LEFT_GUI -#define KEY_RIGHT_CTRL 0x84 -#define KEY_RIGHT_SHIFT 0x85 -#define KEY_RIGHT_ALT 0x86 -#define KEY_RIGHT_GUI 0x87 -#define KEY_RIGHT_WINDOWS KEY_RIGHT_GUI - -#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 - -#define LED_NUM_LOCK 0x01 -#define LED_CAPS_LOCK 0x02 -#define LED_SCROLL_LOCK 0x04 - */ +} \ No newline at end of file From eb00d12e9f1e4ac934b27961e3e1586cdd4e2f0d Mon Sep 17 00:00:00 2001 From: NicoHood Date: Wed, 20 May 2015 17:00:13 +0200 Subject: [PATCH 196/602] Added Simple HID-Bridge example Since I dont have any time to produce any relyable Bridge, here is a simple example. --- .../HID-Bridge_IO/HID-Bridge_IO.ino | 22 ++++++++++++ .../HID-Bridge_USB/HID-Bridge_USB.ino | 34 +++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 plugins/KeyboardioHID/examples/Projects/HID-Bridge/HID-Bridge_IO/HID-Bridge_IO.ino create mode 100644 plugins/KeyboardioHID/examples/Projects/HID-Bridge/HID-Bridge_USB/HID-Bridge_USB.ino diff --git a/plugins/KeyboardioHID/examples/Projects/HID-Bridge/HID-Bridge_IO/HID-Bridge_IO.ino b/plugins/KeyboardioHID/examples/Projects/HID-Bridge/HID-Bridge_IO/HID-Bridge_IO.ino new file mode 100644 index 0000000000..32ce692e6a --- /dev/null +++ b/plugins/KeyboardioHID/examples/Projects/HID-Bridge/HID-Bridge_IO/HID-Bridge_IO.ino @@ -0,0 +1,22 @@ +/* + Copyright (c) 2014-2015 NicoHood + See the readme for credit to other people. + + Serial HID-Bridge I/O + Select Arduino Uno/Mega HID-Bridge as board. + + After upload make sure the 16u2 sketch runs, not the HoodLoader2 bootloader. +*/ + +void setup() { + // start the Serial which is connected with the 16u2. + // make sure both baud rates are the same + // you can go up to 2000000 for very fast data transmission + Serial.begin(115200); +} + +void loop() { + // send random letters to the USB MCU + Serial.write(random('a', 'z')); + delay(1000); +} diff --git a/plugins/KeyboardioHID/examples/Projects/HID-Bridge/HID-Bridge_USB/HID-Bridge_USB.ino b/plugins/KeyboardioHID/examples/Projects/HID-Bridge/HID-Bridge_USB/HID-Bridge_USB.ino new file mode 100644 index 0000000000..3073f8d899 --- /dev/null +++ b/plugins/KeyboardioHID/examples/Projects/HID-Bridge/HID-Bridge_USB/HID-Bridge_USB.ino @@ -0,0 +1,34 @@ +/* + Copyright (c) 2014-2015 NicoHood + See the readme for credit to other people. + + Serial HID-Bridge USB + Select Arduino Uno/Mega HID-Bridge as board. + + After upload make sure the 16u2 sketch runs, not the HoodLoader2 bootloader. +*/ + +void setup() { + // start the Serial1 which is connected with the 16u2. + // make sure both baud rates are the same + // you can go up to 2000000 for very fast data transmission + Serial1.begin(115200); + + // Sends a clean report to the host. This is important on any Arduino type. + Keyboard.begin(); + + // start the USB Serial for debugging + Serial.begin(115200); +} + +void loop() { + // check if any Serial data from the I/O MCU was received + char c = Serial1.read(); + + // if it's a character, print it! + if (c >= 'a' && c <= 'z') { + Serial.print(F("USB: ")); + Serial.println(c); + Keyboard.println(c); + } +} From 8bf34fc55dfc7a8d350135a03416303a807e3111 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Mon, 25 May 2015 18:17:01 +0200 Subject: [PATCH 197/602] Minor fixes Updated platforms.txt Added a few consumer definitions --- .../avr/cores/hid/USB-Core/Consumer.h | 26 +++++++++++------- plugins/KeyboardioHID/avr/platform.txt | 27 ++++++++++++------- .../HID/Keyboard_Basic/Keyboard_Basic.ino | 2 +- 3 files changed, 35 insertions(+), 20 deletions(-) diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Consumer.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Consumer.h index 84fc0828ae..5c5433f1ed 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Consumer.h +++ b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Consumer.h @@ -36,12 +36,18 @@ THE SOFTWARE. #define MEDIA_REWIND 0xB4 #define MEDIA_NEXT 0xB5 #define MEDIA_PREVIOUS 0xB6 +#define MEDIA_PREV MEDIA_PREVIOUS #define MEDIA_STOP 0xB7 #define MEDIA_PLAY_PAUSE 0xCD #define MEDIA_VOLUME_MUTE 0xE2 #define MEDIA_VOLUME_UP 0xE9 #define MEDIA_VOLUME_DOWN 0xEA +#define MEDIA_VOL_MUTE MEDIA_VOLUME_MUTE +#define MEDIA_VOL_UP MEDIA_VOLUME_UP +#define MEDIA_VOL_DOWN MEDIA_VOLUME_DOWN + +#define CONSUMER_SCREENSAVER 0x19e #define CONSUMER_EMAIL_READER 0x18A #define CONSUMER_CALCULATOR 0x192 @@ -53,12 +59,12 @@ THE SOFTWARE. #define CONSUMER_BROWSER_REFRESH 0x227 #define CONSUMER_BROWSER_BOOKMARKS 0x22A -typedef union{ +typedef union { // every usable Consumer key possible, up to 4 keys presses possible uint8_t whole8[]; uint16_t whole16[]; uint32_t whole32[]; - struct{ + struct { uint16_t key1; uint16_t key2; uint16_t key3; @@ -66,24 +72,24 @@ typedef union{ }; } HID_ConsumerControlReport_Data_t; -class Consumer_{ +class Consumer_ { public: - inline Consumer_(void){ + inline Consumer_(void) { // empty } - inline void begin(void){ + inline void begin(void) { // release all buttons end(); } - inline void end(void){ + inline void end(void) { memset(&_report, 0, sizeof(_report)); HID_SendReport(HID_REPORTID_CONSUMERCONTROL, &_report, sizeof(_report)); } - inline void write(uint16_t m){ + inline void write(uint16_t m) { press(m); release(m); } - inline void press(uint16_t m){ + inline void press(uint16_t m) { // search for a free spot for (int i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { if (_report.whole16[i] == 0x00) { @@ -93,7 +99,7 @@ class Consumer_{ } HID_SendReport(HID_REPORTID_CONSUMERCONTROL, &_report, sizeof(_report)); } - inline void release(uint16_t m){ + inline void release(uint16_t m) { // search and release the keypress for (int i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { if (_report.whole16[i] == m) { @@ -103,7 +109,7 @@ class Consumer_{ } HID_SendReport(HID_REPORTID_CONSUMERCONTROL, &_report, sizeof(_report)); } - inline void releaseAll(void){ + inline void releaseAll(void) { end(); } private: diff --git a/plugins/KeyboardioHID/avr/platform.txt b/plugins/KeyboardioHID/avr/platform.txt index 9261ceb91b..c03586d8ec 100644 --- a/plugins/KeyboardioHID/avr/platform.txt +++ b/plugins/KeyboardioHID/avr/platform.txt @@ -15,17 +15,23 @@ version=2.2 # AVR compile variables # --------------------- +compiler.warning_flags=-w +compiler.warning_flags.none=-w +compiler.warning_flags.default= +compiler.warning_flags.more=-Wall +compiler.warning_flags.all=-Wall -Wextra + # Default "compiler.path" is correct, change only if you want to overidde the initial value compiler.path={runtime.tools.avr-gcc.path}/bin/ compiler.c.cmd=avr-gcc -compiler.c.flags=-c -g -Os -w -ffunction-sections -fdata-sections -MMD +compiler.c.flags=-c -g -Os {compiler.warning_flags} -ffunction-sections -fdata-sections -MMD # -w flag added to avoid printing a wrong warning http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59396 # This is fixed in gcc 4.8.3 and will be removed as soon as we update the toolchain -compiler.c.elf.flags=-w -Os -Wl,--gc-sections +compiler.c.elf.flags={compiler.warning_flags} -Os -Wl,--gc-sections compiler.c.elf.cmd=avr-gcc compiler.S.flags=-c -g -x assembler-with-cpp compiler.cpp.cmd=avr-g++ -compiler.cpp.flags=-c -g -Os -w -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD +compiler.cpp.flags=-c -g -Os {compiler.warning_flags} -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD compiler.ar.cmd=avr-ar compiler.ar.flags=rcs compiler.objcopy.cmd=avr-objcopy @@ -65,12 +71,14 @@ recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compil ## Combine gc-sections, archives, and objects recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mmcu={build.mcu} {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" {object_files} "{build.path}/{archive_file}" "-L{build.path}" -lm -## Create eeprom +## Create output files (.eep and .hex) recipe.objcopy.eep.pattern="{compiler.path}{compiler.objcopy.cmd}" {compiler.objcopy.eep.flags} {compiler.objcopy.eep.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.eep" - -## Create hex recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.flags} {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.hex" +## Save hex +recipe.output.tmp_file={build.project_name}.hex +recipe.output.save_file={build.project_name}.{build.variant}.hex + ## Compute size recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf" recipe.size.regex=^(?:\.text|\.data|\.bootloader)\s+([0-9]+).* @@ -81,8 +89,9 @@ recipe.size.regex.eeprom=^(?:\.eeprom)\s+([0-9]+).* # AVR Uploader/Programmers tools # ------------------------------ -tools.avrdude.cmd.path={runtime.ide.path}/hardware/tools/avr/bin/avrdude -tools.avrdude.config.path={runtime.ide.path}/hardware/tools/avr/etc/avrdude.conf +tools.avrdude.path={runtime.tools.avrdude.path} +tools.avrdude.cmd.path={path}/bin/avrdude +tools.avrdude.config.path={path}/etc/avrdude.conf tools.avrdude.upload.params.verbose=-v tools.avrdude.upload.params.quiet=-q -q @@ -104,5 +113,5 @@ tools.avrdude.bootloader.pattern="{cmd.path}" "-C{config.path}" {bootloader.verb # USB Default Flags # Default blank usb manufacturer will be filled it at compile time # - from numeric vendor ID, set to Unknown otherwise -build.usb_manufacturer= +build.usb_manufacturer="Unknown" build.usb_flags=-DUSB_VID={build.vid} -DUSB_PID={build.pid} '-DUSB_MANUFACTURER={build.usb_manufacturer}' '-DUSB_PRODUCT={build.usb_product}' diff --git a/plugins/KeyboardioHID/examples/HID/Keyboard_Basic/Keyboard_Basic.ino b/plugins/KeyboardioHID/examples/HID/Keyboard_Basic/Keyboard_Basic.ino index ee076b24f8..afba459a38 100644 --- a/plugins/KeyboardioHID/examples/HID/Keyboard_Basic/Keyboard_Basic.ino +++ b/plugins/KeyboardioHID/examples/HID/Keyboard_Basic/Keyboard_Basic.ino @@ -1,5 +1,5 @@ /* - Copyright (c) 2014 NicoHood + Copyright (c) 2014-2015 NicoHood See the readme for credit to other people. Keyboard example From fdb77a50dc4691438ac10eb08d8f75640a64c592 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Mon, 25 May 2015 18:55:44 +0200 Subject: [PATCH 198/602] Updated Libraries --- .../avr/libraries/EEPROM/EEPROM.cpp | 50 -- .../avr/libraries/EEPROM/EEPROM.h | 127 +++- .../avr/libraries/EEPROM/README.md | 139 +++++ .../examples/eeprom_clear/eeprom_clear.ino | 24 +- .../EEPROM/examples/eeprom_crc/eeprom_crc.ino | 50 ++ .../EEPROM/examples/eeprom_get/eeprom_get.ino | 66 ++ .../eeprom_iteration/eeprom_iteration.ino | 57 ++ .../EEPROM/examples/eeprom_put/eeprom_put.ino | 56 ++ .../examples/eeprom_read/eeprom_read.ino | 24 +- .../examples/eeprom_update/eeprom_update.ino | 69 ++ .../examples/eeprom_write/eeprom_write.ino | 50 +- .../avr/libraries/EEPROM/keywords.txt | 6 +- .../avr/libraries/EEPROM/library.properties | 7 +- .../KeyboardioHID/avr/libraries/SPI/SPI.cpp | 12 +- plugins/KeyboardioHID/avr/libraries/SPI/SPI.h | 2 +- .../avr/libraries/SPI/library.properties | 3 +- .../SoftwareSerial/SoftwareSerial.cpp | 588 +++++++++--------- .../libraries/SoftwareSerial/SoftwareSerial.h | 125 ++-- .../SoftwareSerial/library.properties | 3 +- .../examples/master_reader/master_reader.ino | 2 +- .../examples/master_writer/master_writer.ino | 2 +- .../slave_receiver/slave_receiver.ino | 2 +- .../examples/slave_sender/slave_sender.ino | 2 +- .../avr/libraries/Wire/library.properties | 3 +- 24 files changed, 1015 insertions(+), 454 deletions(-) delete mode 100644 plugins/KeyboardioHID/avr/libraries/EEPROM/EEPROM.cpp create mode 100644 plugins/KeyboardioHID/avr/libraries/EEPROM/README.md create mode 100644 plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_crc/eeprom_crc.ino create mode 100644 plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_get/eeprom_get.ino create mode 100644 plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_iteration/eeprom_iteration.ino create mode 100644 plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_put/eeprom_put.ino create mode 100644 plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_update/eeprom_update.ino diff --git a/plugins/KeyboardioHID/avr/libraries/EEPROM/EEPROM.cpp b/plugins/KeyboardioHID/avr/libraries/EEPROM/EEPROM.cpp deleted file mode 100644 index dfa1deb560..0000000000 --- a/plugins/KeyboardioHID/avr/libraries/EEPROM/EEPROM.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* - EEPROM.cpp - EEPROM library - Copyright (c) 2006 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 -*/ - -/****************************************************************************** - * Includes - ******************************************************************************/ - -#include -#include "Arduino.h" -#include "EEPROM.h" - -/****************************************************************************** - * Definitions - ******************************************************************************/ - -/****************************************************************************** - * Constructors - ******************************************************************************/ - -/****************************************************************************** - * User API - ******************************************************************************/ - -uint8_t EEPROMClass::read(int address) -{ - return eeprom_read_byte((unsigned char *) address); -} - -void EEPROMClass::write(int address, uint8_t value) -{ - eeprom_write_byte((unsigned char *) address, value); -} - -EEPROMClass EEPROM; diff --git a/plugins/KeyboardioHID/avr/libraries/EEPROM/EEPROM.h b/plugins/KeyboardioHID/avr/libraries/EEPROM/EEPROM.h index aa2b577268..cde75dba9a 100644 --- a/plugins/KeyboardioHID/avr/libraries/EEPROM/EEPROM.h +++ b/plugins/KeyboardioHID/avr/libraries/EEPROM/EEPROM.h @@ -1,6 +1,7 @@ /* EEPROM.h - EEPROM library - Copyright (c) 2006 David A. Mellis. All right reserved. + Original Copyright (c) 2006 David A. Mellis. All right reserved. + New version by Christopher Andrews 2015. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -21,15 +22,125 @@ #define EEPROM_h #include +#include +#include -class EEPROMClass -{ - public: - uint8_t read(int); - void write(int, uint8_t); +/*** + EERef class. + + This object references an EEPROM cell. + Its purpose is to mimic a typical byte of RAM, however its storage is the EEPROM. + This class has an overhead of two bytes, similar to storing a pointer to an EEPROM cell. +***/ + +struct EERef{ + + EERef( const int index ) + : index( index ) {} + + //Access/read members. + uint8_t operator*() const { return eeprom_read_byte( (uint8_t*) index ); } + operator const uint8_t() const { return **this; } + + //Assignment/write members. + EERef &operator=( const EERef &ref ) { return *this = *ref; } + EERef &operator=( uint8_t in ) { return eeprom_write_byte( (uint8_t*) index, in ), *this; } + EERef &operator +=( uint8_t in ) { return *this = **this + in; } + EERef &operator -=( uint8_t in ) { return *this = **this - in; } + EERef &operator *=( uint8_t in ) { return *this = **this * in; } + EERef &operator /=( uint8_t in ) { return *this = **this / in; } + EERef &operator ^=( uint8_t in ) { return *this = **this ^ in; } + EERef &operator %=( uint8_t in ) { return *this = **this % in; } + EERef &operator &=( uint8_t in ) { return *this = **this & in; } + EERef &operator |=( uint8_t in ) { return *this = **this | in; } + EERef &operator <<=( uint8_t in ) { return *this = **this << in; } + EERef &operator >>=( uint8_t in ) { return *this = **this >> in; } + + EERef &update( uint8_t in ) { return in != *this ? *this = in : *this; } + + /** Prefix increment/decrement **/ + EERef& operator++() { return *this += 1; } + EERef& operator--() { return *this -= 1; } + + /** Postfix increment/decrement **/ + uint8_t operator++ (int){ + uint8_t ret = **this; + return ++(*this), ret; + } + + uint8_t operator-- (int){ + uint8_t ret = **this; + return --(*this), ret; + } + + int index; //Index of current EEPROM cell. +}; + +/*** + EEPtr class. + + This object is a bidirectional pointer to EEPROM cells represented by EERef objects. + Just like a normal pointer type, this can be dereferenced and repositioned using + increment/decrement operators. +***/ + +struct EEPtr{ + + EEPtr( const int index ) + : index( index ) {} + + operator const int() const { return index; } + EEPtr &operator=( int in ) { return index = in, *this; } + + //Iterator functionality. + bool operator!=( const EEPtr &ptr ) { return index != ptr.index; } + EERef operator*() { return index; } + + /** Prefix & Postfix increment/decrement **/ + EEPtr& operator++() { return ++index, *this; } + EEPtr& operator--() { return --index, *this; } + EEPtr operator++ (int) { return index++; } + EEPtr operator-- (int) { return index--; } + + int index; //Index of current EEPROM cell. }; -extern EEPROMClass EEPROM; +/*** + EEPROMClass class. + + This object represents the entire EEPROM space. + It wraps the functionality of EEPtr and EERef into a basic interface. + This class is also 100% backwards compatible with earlier Arduino core releases. +***/ -#endif +struct EEPROMClass{ + + //Basic user access methods. + EERef operator[]( const int idx ) { return idx; } + uint8_t read( int idx ) { return EERef( idx ); } + void write( int idx, uint8_t val ) { (EERef( idx )) = val; } + void update( int idx, uint8_t val ) { EERef( idx ).update( val ); } + + //STL and C++11 iteration capability. + EEPtr begin() { return 0x00; } + EEPtr end() { return length(); } //Standards requires this to be the item after the last valid entry. The returned pointer is invalid. + uint16_t length() { return E2END + 1; } + + //Functionality to 'get' and 'put' objects to and from EEPROM. + template< typename T > T &get( int idx, T &t ){ + EEPtr e = idx; + uint8_t *ptr = (uint8_t*) &t; + for( int count = sizeof(T) ; count ; --count, ++e ) *ptr++ = *e; + return t; + } + + template< typename T > const T &put( int idx, const T &t ){ + EEPtr e = idx; + const uint8_t *ptr = (const uint8_t*) &t; + for( int count = sizeof(T) ; count ; --count, ++e ) (*e).update( *ptr++ ); + return t; + } +}; +static EEPROMClass EEPROM; +#endif \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/libraries/EEPROM/README.md b/plugins/KeyboardioHID/avr/libraries/EEPROM/README.md new file mode 100644 index 0000000000..a62413613d --- /dev/null +++ b/plugins/KeyboardioHID/avr/libraries/EEPROM/README.md @@ -0,0 +1,139 @@ +## **EEPROM Library V2.0** for Arduino + +**Written by:** _Christopher Andrews_. + +### **What is the EEPROM library.** + +Th EEPROM library provides an easy to use interface to interact with the internal non-volatile storage found in AVR based Arduino boards. This library will work on many AVR devices like ATtiny and ATmega chips. + +### **How to use it** +The EEPROM library is included in your IDE download. To add its functionality to your sketch you'll need to reference the library header file. You do this by adding an include directive to the top of your sketch. + +```Arduino +#include + +void setup(){ + +} + +void loop(){ + +} + +``` + +The library provides a global variable named `EEPROM`, you use this variable to access the library functions. The methods provided in the EEPROM class are listed below. + +You can view all the examples [here](examples/). + +### **Library functions** + +#### **`EEPROM.read( address )`** [[_example_]](examples/eeprom_read/eeprom_read.ino) + +This function allows you to read a single byte of data from the eeprom. +Its only parameter is an `int` which should be set to the address you wish to read. + +The function returns an `unsigned char` containing the value read. + +#### **`EEPROM.write( address, value )`** [[_example_]](examples/eeprom_write/eeprom_write.ino) + +The `write()` method allows you to write a single byte of data to the EEPROM. +Two parameters are needed. The first is an `int` containing the address that is to be written, and the second is a the data to be written (`unsigned char`). + +This function does not return any value. + +#### **`EEPROM.update( address, value )`** [[_example_]](examples/eeprom_update/eeprom_update.ino) + +This function is similar to `EEPROM.write()` however this method will only write data if the cell contents pointed to by `address` is different to `value`. This method can help prevent unnecessary wear on the EEPROM cells. + +This function does not return any value. + +#### **`EEPROM.get( address, object )`** [[_example_]](examples/eeprom_get/eeprom_get.ino) + +This function will retrieve any object from the EEPROM. +Two parameters are needed to call this function. The first is an `int` containing the address that is to be written, and the second is the object you would like to read. + +This function returns a reference to the `object` passed in. It does not need to be used and is only returned for conveience. + +#### **`EEPROM.put( address, object )`** [[_example_]](examples/eeprom_put/eeprom_put.ino) + +This function will write any object to the EEPROM. +Two parameters are needed to call this function. The first is an `int` containing the address that is to be written, and the second is the object you would like to write. + +This function uses the _update_ method to write its data, and therefore only rewrites changed cells. + +This function returns a reference to the `object` passed in. It does not need to be used and is only returned for conveience. + +#### **Subscript operator: `EEPROM[address]`** [[_example_]](examples/eeprom_crc/eeprom_crc.ino) + +This operator allows using the identifier `EEPROM` like an array. +EEPROM cells can be read _and_ **_written_** directly using this method. + +This operator returns a reference to the EEPROM cell. + +```c++ +unsigned char val; + +//Read first EEPROM cell. +val = EEPROM[ 0 ]; + +//Write first EEPROM cell. +EEPROM[ 0 ] = val; + +//Compare contents +if( val == EEPROM[ 0 ] ){ + //Do something... +} +``` + +#### **`EEPROM.length()`** + +This function returns an `unsigned int` containing the number of cells in the EEPROM. + +--- + +### **Advanced features** + +This library uses a component based approach to provide its functionality. This means you can also use these components to design a customized approach. Two background classes are available for use: `EERef` & `EEPtr`. + +#### **`EERef` class** + +This object references an EEPROM cell. +Its purpose is to mimic a typical byte of RAM, however its storage is the EEPROM. +This class has an overhead of two bytes, similar to storing a pointer to an EEPROM cell. + +```C++ +EERef ref = EEPROM[ 10 ]; //Create a reference to 11th cell. + +ref = 4; //write to EEPROM cell. + +unsigned char val = ref; //Read referenced cell. +``` + +#### **`EEPtr` class** + +This object is a bidirectional pointer to EEPROM cells represented by `EERef` objects. +Just like a normal pointer type, this type can be dereferenced and repositioned using +increment/decrement operators. + +```C++ +EEPtr ptr = 10; //Create a pointer to 11th cell. + +*ptr = 4; //dereference and write to EEPROM cell. + +unsigned char val = *ptr; //dereference and read. + +ptr++; //Move to next EEPROM cell. +``` + +#### **`EEPROM.begin()`** + +This function returns an `EEPtr` pointing to the first cell in the EEPROM. +This is useful for STL objects, custom iteration and C++11 style ranged for loops. + +#### **`EEPROM.end()`** + +This function returns an `EEPtr` pointing at the location after the last EEPROM cell. +Used with `begin()` to provide custom iteration. + +**Note:** The `EEPtr` returned is invalid as it is out of range. Infact the hardware causes wrapping of the address (overflow) and `EEPROM.end()` actually references the first EEPROM cell. diff --git a/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_clear/eeprom_clear.ino b/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_clear/eeprom_clear.ino index b18ff2ca3e..49eb5fe55b 100644 --- a/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_clear/eeprom_clear.ino +++ b/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_clear/eeprom_clear.ino @@ -2,22 +2,34 @@ * EEPROM Clear * * Sets all of the bytes of the EEPROM to 0. + * Please see eeprom_iteration for a more in depth + * look at how to traverse the EEPROM. + * * This example code is in the public domain. - */ #include void setup() { - // write a 0 to all 512 bytes of the EEPROM - for (int i = 0; i < 512; i++) + + /*** + Iterate through each byte of the EEPROM storage. + + Larger AVR processors have larger EEPROM sizes, E.g: + - Arduno Duemilanove: 512b EEPROM storage. + - Arduino Uno: 1kb EEPROM storage. + - Arduino Mega: 4kb EEPROM storage. + + Rather than hard-coding the length, you should use the pre-provided length function. + This will make your code portable to all AVR processors. + ***/ + + for ( int i = 0 ; i < EEPROM.length() ; i++ ) EEPROM.write(i, 0); // turn the LED on when we're done digitalWrite(13, HIGH); } -void loop() -{ -} +void loop(){ /** Empty loop. **/ } diff --git a/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_crc/eeprom_crc.ino b/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_crc/eeprom_crc.ino new file mode 100644 index 0000000000..8461d566a2 --- /dev/null +++ b/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_crc/eeprom_crc.ino @@ -0,0 +1,50 @@ +/*** + Written by Christopher Andrews. + CRC algorithm generated by pycrc, MIT licence ( https://github.com/tpircher/pycrc ). + + A CRC is a simple way of checking whether data has changed or become corrupted. + This example calculates a CRC value directly on the EEPROM values. + The purpose of this example is to highlight how the EEPROM object can be used just like an array. +***/ + +#include +#include + +void setup(){ + + //Start serial + Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for Leonardo only + } + + //Print length of data to run CRC on. + Serial.print( "EEPROM length: " ); + Serial.println( EEPROM.length() ); + + //Print the result of calling eeprom_crc() + Serial.print( "CRC32 of EEPROM data: 0x" ); + Serial.println( eeprom_crc(), HEX ); + Serial.print( "\n\nDone!" ); +} + +void loop(){ /* Empty loop */ } + +unsigned long eeprom_crc( void ){ + + const unsigned long crc_table[16] = { + 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, + 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, + 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, + 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c + }; + + unsigned long crc = ~0L; + + for( int index = 0 ; index < EEPROM.length() ; ++index ){ + crc = crc_table[( crc ^ EEPROM[index] ) & 0x0f] ^ (crc >> 4); + crc = crc_table[( crc ^ ( EEPROM[index] >> 4 )) & 0x0f] ^ (crc >> 4); + crc = ~crc; + } + return crc; +} \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_get/eeprom_get.ino b/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_get/eeprom_get.ino new file mode 100644 index 0000000000..662099990c --- /dev/null +++ b/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_get/eeprom_get.ino @@ -0,0 +1,66 @@ +/*** + eeprom_get example. + + This shows how to use the EEPROM.get() method. + + To pre-set the EEPROM data, run the example sketch eeprom_put. + This sketch will run without it, however, the values shown + will be shown from what ever is already on the EEPROM. + + This may cause the serial object to print out a large string + of garbage if there is no null character inside one of the strings + loaded. + + Written by Christopher Andrews 2015 + Released under MIT licence. +***/ + +#include + +void setup(){ + + float f = 0.00f; //Variable to store data read from EEPROM. + int eeAddress = 0; //EEPROM address to start reading from + + Serial.begin( 9600 ); + while (!Serial) { + ; // wait for serial port to connect. Needed for Leonardo only + } + Serial.print( "Read float from EEPROM: " ); + + //Get the float data from the EEPROM at position 'eeAddress' + EEPROM.get( eeAddress, f ); + Serial.println( f, 3 ); //This may print 'ovf, nan' if the data inside the EEPROM is not a valid float. + + /*** + As get also returns a reference to 'f', you can use it inline. + E.g: Serial.print( EEPROM.get( eeAddress, f ) ); + ***/ + + /*** + Get can be used with custom structures too. + I have separated this into an extra function. + ***/ + + secondTest(); //Run the next test. +} + +struct MyObject{ + float field1; + byte field2; + char name[10]; +}; + +void secondTest(){ + int eeAddress = sizeof(float); //Move address to the next byte after float 'f'. + + MyObject customVar; //Variable to store custom object read from EEPROM. + EEPROM.get( eeAddress, customVar ); + + Serial.println( "Read custom object from EEPROM: " ); + Serial.println( customVar.field1 ); + Serial.println( customVar.field2 ); + Serial.println( customVar.name ); +} + +void loop(){ /* Empty loop */ } \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_iteration/eeprom_iteration.ino b/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_iteration/eeprom_iteration.ino new file mode 100644 index 0000000000..650c90a75f --- /dev/null +++ b/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_iteration/eeprom_iteration.ino @@ -0,0 +1,57 @@ +/*** + eeprom_iteration example. + + A set of example snippets highlighting the + simplest methods for traversing the EEPROM. + + Running this sketch is not necessary, this is + simply highlighting certain programming methods. + + Written by Christopher Andrews 2015 + Released under MIT licence. +***/ + +#include + +void setup() { + + /*** + Iterate the EEPROM using a for loop. + ***/ + + for( int index = 0 ; index < EEPROM.length() ; index++ ){ + + //Add one to each cell in the EEPROM + EEPROM[ index ] += 1; + } + + /*** + Iterate the EEPROM using a while loop. + ***/ + + int index = 0; + + while( index < EEPROM.length() ){ + + //Add one to each cell in the EEPROM + EEPROM[ index ] += 1; + index++; + } + + /*** + Iterate the EEPROM using a do-while loop. + ***/ + + int idx = 0; //Used 'idx' to avoid name conflict with 'index' above. + + do{ + + //Add one to each cell in the EEPROM + EEPROM[ idx ] += 1; + idx++; + }while( idx < EEPROM.length() ); + + +} //End of setup function. + +void loop(){} \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_put/eeprom_put.ino b/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_put/eeprom_put.ino new file mode 100644 index 0000000000..186cf95bdc --- /dev/null +++ b/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_put/eeprom_put.ino @@ -0,0 +1,56 @@ +/*** + eeprom_put example. + + This shows how to use the EEPROM.put() method. + Also, this sketch will pre-set the EEPROM data for the + example sketch eeprom_get. + + Note, unlike the single byte version EEPROM.write(), + the put method will use update semantics. As in a byte + will only be written to the EEPROM if the data is actually + different. + + Written by Christopher Andrews 2015 + Released under MIT licence. +***/ + +#include + +struct MyObject{ + float field1; + byte field2; + char name[10]; +}; + +void setup(){ + + Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for Leonardo only + } + + float f = 123.456f; //Variable to store in EEPROM. + int eeAddress = 0; //Location we want the data to be put. + + + //One simple call, with the address first and the object second. + EEPROM.put( eeAddress, f ); + + Serial.println("Written float data type!"); + + /** Put is designed for use with custom structures also. **/ + + //Data to store. + MyObject customVar = { + 3.14f, + 65, + "Working!" + }; + + eeAddress += sizeof(float); //Move address to the next byte after float 'f'. + + EEPROM.put( eeAddress, customVar ); + Serial.print( "Written custom data type! \n\nView the example sketch eeprom_get to see how you can retrieve the values!" ); +} + +void loop(){ /* Empty loop */ } \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_read/eeprom_read.ino b/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_read/eeprom_read.ino index ebf79d683f..68c4ffc745 100644 --- a/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_read/eeprom_read.ino +++ b/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_read/eeprom_read.ino @@ -31,13 +31,27 @@ void loop() Serial.print(value, DEC); Serial.println(); - // advance to the next address of the EEPROM + /*** + Advance to the next address, when at the end restart at the beginning. + + Larger AVR processors have larger EEPROM sizes, E.g: + - Arduno Duemilanove: 512b EEPROM storage. + - Arduino Uno: 1kb EEPROM storage. + - Arduino Mega: 4kb EEPROM storage. + + Rather than hard-coding the length, you should use the pre-provided length function. + This will make your code portable to all AVR processors. + ***/ address = address + 1; - - // there are only 512 bytes of EEPROM, from 0 to 511, so if we're - // on address 512, wrap around to address 0 - if (address == 512) + if(address == EEPROM.length()) address = 0; + + /*** + As the EEPROM sizes are powers of two, wrapping (preventing overflow) of an + EEPROM address is also doable by a bitwise and of the length - 1. + + ++address &= EEPROM.length() - 1; + ***/ delay(500); } diff --git a/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_update/eeprom_update.ino b/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_update/eeprom_update.ino new file mode 100644 index 0000000000..831056fd7d --- /dev/null +++ b/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_update/eeprom_update.ino @@ -0,0 +1,69 @@ +/*** + EEPROM Update method + + Stores values read from analog input 0 into the EEPROM. + These values will stay in the EEPROM when the board is + turned off and may be retrieved later by another sketch. + + If a value has not changed in the EEPROM, it is not overwritten + which would reduce the life span of the EEPROM unnecessarily. + + Released using MIT licence. + ***/ + +#include + +/** the current address in the EEPROM (i.e. which byte we're going to write to next) **/ +int address = 0; + +void setup(){ /** EMpty setup **/ } + +void loop() +{ + /*** + need to divide by 4 because analog inputs range from + 0 to 1023 and each byte of the EEPROM can only hold a + value from 0 to 255. + ***/ + int val = analogRead(0) / 4; + + /*** + Update the particular EEPROM cell. + these values will remain there when the board is + turned off. + ***/ + EEPROM.update(address, val); + + /*** + The function EEPROM.update(address, val) is equivalent to the following: + + if( EEPROM.read(address) != val ){ + EEPROM.write(address, val); + } + ***/ + + + /*** + Advance to the next address, when at the end restart at the beginning. + + Larger AVR processors have larger EEPROM sizes, E.g: + - Arduno Duemilanove: 512b EEPROM storage. + - Arduino Uno: 1kb EEPROM storage. + - Arduino Mega: 4kb EEPROM storage. + + Rather than hard-coding the length, you should use the pre-provided length function. + This will make your code portable to all AVR processors. + ***/ + address = address + 1; + if(address == EEPROM.length()) + address = 0; + + /*** + As the EEPROM sizes are powers of two, wrapping (preventing overflow) of an + EEPROM address is also doable by a bitwise and of the length - 1. + + ++address &= EEPROM.length() - 1; + ***/ + + delay(100); +} diff --git a/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_write/eeprom_write.ino b/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_write/eeprom_write.ino index c047887083..f07446c5a5 100644 --- a/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_write/eeprom_write.ino +++ b/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_write/eeprom_write.ino @@ -8,31 +8,51 @@ #include -// the current address in the EEPROM (i.e. which byte -// we're going to write to next) -int addr = 0; +/** the current address in the EEPROM (i.e. which byte we're going to write to next) **/ +int addr = 0; -void setup() -{ -} +void setup(){ /** Empty setup. **/} void loop() { - // need to divide by 4 because analog inputs range from - // 0 to 1023 and each byte of the EEPROM can only hold a - // value from 0 to 255. + /*** + Need to divide by 4 because analog inputs range from + 0 to 1023 and each byte of the EEPROM can only hold a + value from 0 to 255. + ***/ + int val = analogRead(0) / 4; - // write the value to the appropriate byte of the EEPROM. - // these values will remain there when the board is - // turned off. + /*** + Write the value to the appropriate byte of the EEPROM. + these values will remain there when the board is + turned off. + ***/ + EEPROM.write(addr, val); - // advance to the next address. there are 512 bytes in - // the EEPROM, so go back to 0 when we hit 512. + /*** + Advance to the next address, when at the end restart at the beginning. + + Larger AVR processors have larger EEPROM sizes, E.g: + - Arduno Duemilanove: 512b EEPROM storage. + - Arduino Uno: 1kb EEPROM storage. + - Arduino Mega: 4kb EEPROM storage. + + Rather than hard-coding the length, you should use the pre-provided length function. + This will make your code portable to all AVR processors. + ***/ addr = addr + 1; - if (addr == 512) + if(addr == EEPROM.length()) addr = 0; + + /*** + As the EEPROM sizes are powers of two, wrapping (preventing overflow) of an + EEPROM address is also doable by a bitwise and of the length - 1. + + ++addr &= EEPROM.length() - 1; + ***/ + delay(100); } diff --git a/plugins/KeyboardioHID/avr/libraries/EEPROM/keywords.txt b/plugins/KeyboardioHID/avr/libraries/EEPROM/keywords.txt index d3218fe2ac..2cabc0b062 100644 --- a/plugins/KeyboardioHID/avr/libraries/EEPROM/keywords.txt +++ b/plugins/KeyboardioHID/avr/libraries/EEPROM/keywords.txt @@ -1,5 +1,5 @@ ####################################### -# Syntax Coloring Map For Ultrasound +# Syntax Coloring Map For EEPROM ####################################### ####################################### @@ -7,11 +7,15 @@ ####################################### EEPROM KEYWORD1 +EERef KEYWORD1 +EEPtr KEYWORD2 ####################################### # Methods and Functions (KEYWORD2) ####################################### +update KEYWORD2 + ####################################### # Constants (LITERAL1) ####################################### diff --git a/plugins/KeyboardioHID/avr/libraries/EEPROM/library.properties b/plugins/KeyboardioHID/avr/libraries/EEPROM/library.properties index 796f7cb877..21437ffdf6 100644 --- a/plugins/KeyboardioHID/avr/libraries/EEPROM/library.properties +++ b/plugins/KeyboardioHID/avr/libraries/EEPROM/library.properties @@ -1,8 +1,9 @@ name=EEPROM -version=1.0 -author=Arduino +version=2.0 +author=Arduino, Christopher Andrews maintainer=Arduino sentence=Enables reading and writing to the permanent board storage. For all Arduino boards BUT Arduino DUE. paragraph= -url=http://arduino.cc/en/Reference/EEPROM +url=http://www.arduino.cc/en/Reference/EEPROM architectures=avr + diff --git a/plugins/KeyboardioHID/avr/libraries/SPI/SPI.cpp b/plugins/KeyboardioHID/avr/libraries/SPI/SPI.cpp index 077b6a38db..af14e07b12 100644 --- a/plugins/KeyboardioHID/avr/libraries/SPI/SPI.cpp +++ b/plugins/KeyboardioHID/avr/libraries/SPI/SPI.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 by Cristian Maglie + * Copyright (c) 2010 by Cristian Maglie * Copyright (c) 2014 by Paul Stoffregen (Transaction API) * Copyright (c) 2014 by Matthijs Kooijman (SPISettings AVR) * Copyright (c) 2014 by Andrew J. Kroll (atomicity fixes) @@ -29,7 +29,15 @@ void SPIClass::begin() noInterrupts(); // Protect from a scheduler and prevent transactionBegin if (!initialized) { // Set SS to high so a connected chip will be "deselected" by default - digitalWrite(SS, HIGH); + uint8_t port = digitalPinToPort(SS); + uint8_t bit = digitalPinToBitMask(SS); + volatile uint8_t *reg = portModeRegister(port); + + // if the SS pin is not already configured as an output + // then set it high (to enable the internal pull-up resistor) + if(!(*reg & bit)){ + digitalWrite(SS, HIGH); + } // When the SS pin is set as OUTPUT, it can be used as // a general purpose output port (it doesn't influence diff --git a/plugins/KeyboardioHID/avr/libraries/SPI/SPI.h b/plugins/KeyboardioHID/avr/libraries/SPI/SPI.h index cee618c80d..5206a09184 100644 --- a/plugins/KeyboardioHID/avr/libraries/SPI/SPI.h +++ b/plugins/KeyboardioHID/avr/libraries/SPI/SPI.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 by Cristian Maglie + * Copyright (c) 2010 by Cristian Maglie * Copyright (c) 2014 by Paul Stoffregen (Transaction API) * Copyright (c) 2014 by Matthijs Kooijman (SPISettings AVR) * Copyright (c) 2014 by Andrew J. Kroll (atomicity fixes) diff --git a/plugins/KeyboardioHID/avr/libraries/SPI/library.properties b/plugins/KeyboardioHID/avr/libraries/SPI/library.properties index 6f1ae2016d..2964aecfe5 100644 --- a/plugins/KeyboardioHID/avr/libraries/SPI/library.properties +++ b/plugins/KeyboardioHID/avr/libraries/SPI/library.properties @@ -4,5 +4,6 @@ author=Arduino maintainer=Arduino sentence=Enables the communication with devices that use the Serial Peripheral Interface (SPI) Bus. For all Arduino boards, BUT Arduino DUE. paragraph= -url=http://arduino.cc/en/Reference/SPI +url=http://www.arduino.cc/en/Reference/SPI architectures=avr + diff --git a/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/SoftwareSerial.cpp b/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/SoftwareSerial.cpp index 8ccbbb4f6a..b4e4529513 100644 --- a/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/SoftwareSerial.cpp +++ b/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/SoftwareSerial.cpp @@ -1,12 +1,12 @@ /* -SoftwareSerial.cpp (formerly NewSoftSerial.cpp) - +SoftwareSerial.cpp (formerly NewSoftSerial.cpp) - Multi-instance software serial library for Arduino/Wiring -- Interrupt-driven receive and other improvements by ladyada -(http://ladyada.net) + (http://ladyada.net) -- Tuning, circular buffer, derivation from class Print/Stream, -multi-instance support, porting to 8MHz processors, -various optimizations, PROGMEM delay tables, inverse logic and -direct port writing by Mikal Hart (http://www.arduiniana.org) + multi-instance support, porting to 8MHz processors, + various optimizations, PROGMEM delay tables, inverse logic and + direct port writing by Mikal Hart (http://www.arduiniana.org) -- Pin change interrupt macros by Paul Stoffregen (http://www.pjrc.com) -- 20MHz processor support by Garrett Mace (http://www.macetech.com) -- ATmega1280/2560 support by Brett Hagman (http://www.roguerobotics.com/) @@ -48,7 +48,7 @@ The latest version of this library can always be found at // Statics // SoftwareSerial *SoftwareSerial::active_object = 0; -char SoftwareSerial::_receive_buffer[_SS_MAX_RX_BUFF]; +char SoftwareSerial::_receive_buffer[_SS_MAX_RX_BUFF]; volatile uint8_t SoftwareSerial::_receive_buffer_tail = 0; volatile uint8_t SoftwareSerial::_receive_buffer_head = 0; @@ -60,14 +60,14 @@ volatile uint8_t SoftwareSerial::_receive_buffer_head = 0; inline void DebugPulse(uint8_t pin, uint8_t count) { #if _DEBUG - volatile uint8_t *pport = portOutputRegister(digitalPinToPort(pin)); - - uint8_t val = *pport; - while (count--) - { - *pport = val | digitalPinToBitMask(pin); - *pport = val; - } + volatile uint8_t *pport = portOutputRegister(digitalPinToPort(pin)); + + uint8_t val = *pport; + while (count--) + { + *pport = val | digitalPinToBitMask(pin); + *pport = val; + } #endif } @@ -75,44 +75,44 @@ inline void DebugPulse(uint8_t pin, uint8_t count) // Private methods // -/* static */ -inline void SoftwareSerial::tunedDelay(uint16_t delay) { - _delay_loop_2(delay); +/* static */ +inline void SoftwareSerial::tunedDelay(uint16_t delay) { + _delay_loop_2(delay); } // This function sets the current object as the "listening" // one and returns true if it replaces another bool SoftwareSerial::listen() { - if (!_rx_delay_stopbit) - return false; + if (!_rx_delay_stopbit) + return false; - if (active_object != this) - { - if (active_object) - active_object->stopListening(); + if (active_object != this) + { + if (active_object) + active_object->stopListening(); - _buffer_overflow = false; - _receive_buffer_head = _receive_buffer_tail = 0; - active_object = this; + _buffer_overflow = false; + _receive_buffer_head = _receive_buffer_tail = 0; + active_object = this; - setRxIntMsk(true); - return true; - } + setRxIntMsk(true); + return true; + } - return false; + return false; } // Stop listening. Returns true if we were actually listening. bool SoftwareSerial::stopListening() { - if (active_object == this) - { - setRxIntMsk(false); - active_object = NULL; - return true; - } - return false; + if (active_object == this) + { + setRxIntMsk(false); + active_object = NULL; + return true; + } + return false; } // @@ -122,91 +122,91 @@ void SoftwareSerial::recv() { #if GCC_VERSION < 40302 - // Work-around for avr-gcc 4.3.0 OSX version bug - // Preserve the registers that the compiler misses - // (courtesy of Arduino forum user *etracer*) - asm volatile( - "push r18 \n\t" - "push r19 \n\t" - "push r20 \n\t" - "push r21 \n\t" - "push r22 \n\t" - "push r23 \n\t" - "push r26 \n\t" - "push r27 \n\t" - ::); +// Work-around for avr-gcc 4.3.0 OSX version bug +// Preserve the registers that the compiler misses +// (courtesy of Arduino forum user *etracer*) + asm volatile( + "push r18 \n\t" + "push r19 \n\t" + "push r20 \n\t" + "push r21 \n\t" + "push r22 \n\t" + "push r23 \n\t" + "push r26 \n\t" + "push r27 \n\t" + ::); #endif - uint8_t d = 0; - - // If RX line is high, then we don't see any start bit - // so interrupt is probably not for us - if (_inverse_logic ? rx_pin_read() : !rx_pin_read()) - { - // Disable further interrupts during reception, this prevents - // triggering another interrupt directly after we return, which can - // cause problems at higher baudrates. - setRxIntMsk(false); - - // Wait approximately 1/2 of a bit width to "center" the sample - tunedDelay(_rx_delay_centering); - DebugPulse(_DEBUG_PIN2, 1); - - // Read each of the 8 bits - for (uint8_t i = 8; i > 0; --i) - { - tunedDelay(_rx_delay_intrabit); - d >>= 1; - DebugPulse(_DEBUG_PIN2, 1); - if (rx_pin_read()) - d |= 0x80; - } - - if (_inverse_logic) - d = ~d; - - // if buffer full, set the overflow flag and return - uint8_t next = (_receive_buffer_tail + 1) % _SS_MAX_RX_BUFF; - if (next != _receive_buffer_head) - { - // save new data in buffer: tail points to where byte goes - _receive_buffer[_receive_buffer_tail] = d; // save new byte - _receive_buffer_tail = next; - } - else - { - DebugPulse(_DEBUG_PIN1, 1); - _buffer_overflow = true; - } - - // skip the stop bit - tunedDelay(_rx_delay_stopbit); - DebugPulse(_DEBUG_PIN1, 1); - - // Re-enable interrupts when we're sure to be inside the stop bit - setRxIntMsk(true); - - } + uint8_t d = 0; + + // If RX line is high, then we don't see any start bit + // so interrupt is probably not for us + if (_inverse_logic ? rx_pin_read() : !rx_pin_read()) + { + // Disable further interrupts during reception, this prevents + // triggering another interrupt directly after we return, which can + // cause problems at higher baudrates. + setRxIntMsk(false); + + // Wait approximately 1/2 of a bit width to "center" the sample + tunedDelay(_rx_delay_centering); + DebugPulse(_DEBUG_PIN2, 1); + + // Read each of the 8 bits + for (uint8_t i=8; i > 0; --i) + { + tunedDelay(_rx_delay_intrabit); + d >>= 1; + DebugPulse(_DEBUG_PIN2, 1); + if (rx_pin_read()) + d |= 0x80; + } + + if (_inverse_logic) + d = ~d; + + // if buffer full, set the overflow flag and return + uint8_t next = (_receive_buffer_tail + 1) % _SS_MAX_RX_BUFF; + if (next != _receive_buffer_head) + { + // save new data in buffer: tail points to where byte goes + _receive_buffer[_receive_buffer_tail] = d; // save new byte + _receive_buffer_tail = next; + } + else + { + DebugPulse(_DEBUG_PIN1, 1); + _buffer_overflow = true; + } + + // skip the stop bit + tunedDelay(_rx_delay_stopbit); + DebugPulse(_DEBUG_PIN1, 1); + + // Re-enable interrupts when we're sure to be inside the stop bit + setRxIntMsk(true); + + } #if GCC_VERSION < 40302 - // Work-around for avr-gcc 4.3.0 OSX version bug - // Restore the registers that the compiler misses - asm volatile( - "pop r27 \n\t" - "pop r26 \n\t" - "pop r23 \n\t" - "pop r22 \n\t" - "pop r21 \n\t" - "pop r20 \n\t" - "pop r19 \n\t" - "pop r18 \n\t" - ::); +// Work-around for avr-gcc 4.3.0 OSX version bug +// Restore the registers that the compiler misses + asm volatile( + "pop r27 \n\t" + "pop r26 \n\t" + "pop r23 \n\t" + "pop r22 \n\t" + "pop r21 \n\t" + "pop r20 \n\t" + "pop r19 \n\t" + "pop r18 \n\t" + ::); #endif } uint8_t SoftwareSerial::rx_pin_read() { - return *_receivePortRegister & _receiveBitMask; + return *_receivePortRegister & _receiveBitMask; } // @@ -216,16 +216,16 @@ uint8_t SoftwareSerial::rx_pin_read() /* static */ inline void SoftwareSerial::handle_interrupt() { - if (active_object) - { - active_object->recv(); - } + if (active_object) + { + active_object->recv(); + } } #if defined(PCINT0_vect) ISR(PCINT0_vect) { - SoftwareSerial::handle_interrupt(); + SoftwareSerial::handle_interrupt(); } #endif @@ -244,16 +244,16 @@ ISR(PCINT3_vect, ISR_ALIASOF(PCINT0_vect)); // // Constructor // -SoftwareSerial::SoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic /* = false */) : -_rx_delay_centering(0), -_rx_delay_intrabit(0), -_rx_delay_stopbit(0), -_tx_delay(0), -_buffer_overflow(false), -_inverse_logic(inverse_logic) +SoftwareSerial::SoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic /* = false */) : + _rx_delay_centering(0), + _rx_delay_intrabit(0), + _rx_delay_stopbit(0), + _tx_delay(0), + _buffer_overflow(false), + _inverse_logic(inverse_logic) { - setTX(transmitPin); - setRX(receivePin); + setTX(transmitPin); + setRX(receivePin); } // @@ -261,38 +261,38 @@ _inverse_logic(inverse_logic) // SoftwareSerial::~SoftwareSerial() { - end(); + end(); } void SoftwareSerial::setTX(uint8_t tx) { - // First write, then set output. If we do this the other way around, - // the pin would be output low for a short while before switching to - // output hihg. Now, it is input with pullup for a short while, which - // is fine. With inverse logic, either order is fine. - digitalWrite(tx, _inverse_logic ? LOW : HIGH); - pinMode(tx, OUTPUT); - _transmitBitMask = digitalPinToBitMask(tx); - uint8_t port = digitalPinToPort(tx); - _transmitPortRegister = portOutputRegister(port); + // First write, then set output. If we do this the other way around, + // the pin would be output low for a short while before switching to + // output hihg. Now, it is input with pullup for a short while, which + // is fine. With inverse logic, either order is fine. + digitalWrite(tx, _inverse_logic ? LOW : HIGH); + pinMode(tx, OUTPUT); + _transmitBitMask = digitalPinToBitMask(tx); + uint8_t port = digitalPinToPort(tx); + _transmitPortRegister = portOutputRegister(port); } void SoftwareSerial::setRX(uint8_t rx) { - pinMode(rx, INPUT); - if (!_inverse_logic) - digitalWrite(rx, HIGH); // pullup for normal logic! - _receivePin = rx; - _receiveBitMask = digitalPinToBitMask(rx); - uint8_t port = digitalPinToPort(rx); - _receivePortRegister = portInputRegister(port); + pinMode(rx, INPUT); + if (!_inverse_logic) + digitalWrite(rx, HIGH); // pullup for normal logic! + _receivePin = rx; + _receiveBitMask = digitalPinToBitMask(rx); + uint8_t port = digitalPinToPort(rx); + _receivePortRegister = portInputRegister(port); } uint16_t SoftwareSerial::subtract_cap(uint16_t num, uint16_t sub) { - if (num > sub) - return num - sub; - else - return 1; + if (num > sub) + return num - sub; + else + return 1; } // @@ -301,190 +301,190 @@ uint16_t SoftwareSerial::subtract_cap(uint16_t num, uint16_t sub) { void SoftwareSerial::begin(long speed) { - _rx_delay_centering = _rx_delay_intrabit = _rx_delay_stopbit = _tx_delay = 0; - - // Precalculate the various delays, in number of 4-cycle delays - uint16_t bit_delay = (F_CPU / speed) / 4; - - // 12 (gcc 4.8.2) or 13 (gcc 4.3.2) cycles from start bit to first bit, - // 15 (gcc 4.8.2) or 16 (gcc 4.3.2) cycles between bits, - // 12 (gcc 4.8.2) or 14 (gcc 4.3.2) cycles from last bit to stop bit - // These are all close enough to just use 15 cycles, since the inter-bit - // timings are the most critical (deviations stack 8 times) - _tx_delay = subtract_cap(bit_delay, 15 / 4); - - // Only setup rx when we have a valid PCINT for this pin - if (digitalPinToPCICR(_receivePin)) { -#if GCC_VERSION > 40800 - // Timings counted from gcc 4.8.2 output. This works up to 115200 on - // 16Mhz and 57600 on 8Mhz. - // - // When the start bit occurs, there are 3 or 4 cycles before the - // interrupt flag is set, 4 cycles before the PC is set to the right - // interrupt vector address and the old PC is pushed on the stack, - // and then 75 cycles of instructions (including the RJMP in the - // ISR vector table) until the first delay. After the delay, there - // are 17 more cycles until the pin value is read (excluding the - // delay in the loop). - // We want to have a total delay of 1.5 bit time. Inside the loop, - // we already wait for 1 bit time - 23 cycles, so here we wait for - // 0.5 bit time - (71 + 18 - 22) cycles. - _rx_delay_centering = subtract_cap(bit_delay / 2, (4 + 4 + 75 + 17 - 23) / 4); - - // There are 23 cycles in each loop iteration (excluding the delay) - _rx_delay_intrabit = subtract_cap(bit_delay, 23 / 4); - - // There are 37 cycles from the last bit read to the start of - // stopbit delay and 11 cycles from the delay until the interrupt - // mask is enabled again (which _must_ happen during the stopbit). - // This delay aims at 3/4 of a bit time, meaning the end of the - // delay will be at 1/4th of the stopbit. This allows some extra - // time for ISR cleanup, which makes 115200 baud at 16Mhz work more - // reliably - _rx_delay_stopbit = subtract_cap(bit_delay * 3 / 4, (37 + 11) / 4); -#else // Timings counted from gcc 4.3.2 output - // Note that this code is a _lot_ slower, mostly due to bad register - // allocation choices of gcc. This works up to 57600 on 16Mhz and - // 38400 on 8Mhz. - _rx_delay_centering = subtract_cap(bit_delay / 2, (4 + 4 + 97 + 29 - 11) / 4); - _rx_delay_intrabit = subtract_cap(bit_delay, 11 / 4); - _rx_delay_stopbit = subtract_cap(bit_delay * 3 / 4, (44 + 17) / 4); -#endif - - - // Enable the PCINT for the entire port here, but never disable it - // (others might also need it, so we disable the interrupt by using - // the per-pin PCMSK register). - *digitalPinToPCICR(_receivePin) |= _BV(digitalPinToPCICRbit(_receivePin)); - // Precalculate the pcint mask register and value, so setRxIntMask - // can be used inside the ISR without costing too much time. - _pcint_maskreg = digitalPinToPCMSK(_receivePin); - _pcint_maskvalue = _BV(digitalPinToPCMSKbit(_receivePin)); - - tunedDelay(_tx_delay); // if we were low this establishes the end - } + _rx_delay_centering = _rx_delay_intrabit = _rx_delay_stopbit = _tx_delay = 0; + + // Precalculate the various delays, in number of 4-cycle delays + uint16_t bit_delay = (F_CPU / speed) / 4; + + // 12 (gcc 4.8.2) or 13 (gcc 4.3.2) cycles from start bit to first bit, + // 15 (gcc 4.8.2) or 16 (gcc 4.3.2) cycles between bits, + // 12 (gcc 4.8.2) or 14 (gcc 4.3.2) cycles from last bit to stop bit + // These are all close enough to just use 15 cycles, since the inter-bit + // timings are the most critical (deviations stack 8 times) + _tx_delay = subtract_cap(bit_delay, 15 / 4); + + // Only setup rx when we have a valid PCINT for this pin + if (digitalPinToPCICR(_receivePin)) { + #if GCC_VERSION > 40800 + // Timings counted from gcc 4.8.2 output. This works up to 115200 on + // 16Mhz and 57600 on 8Mhz. + // + // When the start bit occurs, there are 3 or 4 cycles before the + // interrupt flag is set, 4 cycles before the PC is set to the right + // interrupt vector address and the old PC is pushed on the stack, + // and then 75 cycles of instructions (including the RJMP in the + // ISR vector table) until the first delay. After the delay, there + // are 17 more cycles until the pin value is read (excluding the + // delay in the loop). + // We want to have a total delay of 1.5 bit time. Inside the loop, + // we already wait for 1 bit time - 23 cycles, so here we wait for + // 0.5 bit time - (71 + 18 - 22) cycles. + _rx_delay_centering = subtract_cap(bit_delay / 2, (4 + 4 + 75 + 17 - 23) / 4); + + // There are 23 cycles in each loop iteration (excluding the delay) + _rx_delay_intrabit = subtract_cap(bit_delay, 23 / 4); + + // There are 37 cycles from the last bit read to the start of + // stopbit delay and 11 cycles from the delay until the interrupt + // mask is enabled again (which _must_ happen during the stopbit). + // This delay aims at 3/4 of a bit time, meaning the end of the + // delay will be at 1/4th of the stopbit. This allows some extra + // time for ISR cleanup, which makes 115200 baud at 16Mhz work more + // reliably + _rx_delay_stopbit = subtract_cap(bit_delay * 3 / 4, (37 + 11) / 4); + #else // Timings counted from gcc 4.3.2 output + // Note that this code is a _lot_ slower, mostly due to bad register + // allocation choices of gcc. This works up to 57600 on 16Mhz and + // 38400 on 8Mhz. + _rx_delay_centering = subtract_cap(bit_delay / 2, (4 + 4 + 97 + 29 - 11) / 4); + _rx_delay_intrabit = subtract_cap(bit_delay, 11 / 4); + _rx_delay_stopbit = subtract_cap(bit_delay * 3 / 4, (44 + 17) / 4); + #endif + + + // Enable the PCINT for the entire port here, but never disable it + // (others might also need it, so we disable the interrupt by using + // the per-pin PCMSK register). + *digitalPinToPCICR(_receivePin) |= _BV(digitalPinToPCICRbit(_receivePin)); + // Precalculate the pcint mask register and value, so setRxIntMask + // can be used inside the ISR without costing too much time. + _pcint_maskreg = digitalPinToPCMSK(_receivePin); + _pcint_maskvalue = _BV(digitalPinToPCMSKbit(_receivePin)); + + tunedDelay(_tx_delay); // if we were low this establishes the end + } #if _DEBUG - pinMode(_DEBUG_PIN1, OUTPUT); - pinMode(_DEBUG_PIN2, OUTPUT); + pinMode(_DEBUG_PIN1, OUTPUT); + pinMode(_DEBUG_PIN2, OUTPUT); #endif - listen(); + listen(); } void SoftwareSerial::setRxIntMsk(bool enable) { - if (enable) - *_pcint_maskreg |= _pcint_maskvalue; - else - *_pcint_maskreg &= ~_pcint_maskvalue; + if (enable) + *_pcint_maskreg |= _pcint_maskvalue; + else + *_pcint_maskreg &= ~_pcint_maskvalue; } void SoftwareSerial::end() { - stopListening(); + stopListening(); } // Read data from buffer int SoftwareSerial::read() { - if (!isListening()) - return -1; + if (!isListening()) + return -1; - // Empty buffer? - if (_receive_buffer_head == _receive_buffer_tail) - return -1; + // Empty buffer? + if (_receive_buffer_head == _receive_buffer_tail) + return -1; - // Read from "head" - uint8_t d = _receive_buffer[_receive_buffer_head]; // grab next byte - _receive_buffer_head = (_receive_buffer_head + 1) % _SS_MAX_RX_BUFF; - return d; + // Read from "head" + uint8_t d = _receive_buffer[_receive_buffer_head]; // grab next byte + _receive_buffer_head = (_receive_buffer_head + 1) % _SS_MAX_RX_BUFF; + return d; } int SoftwareSerial::available() { - if (!isListening()) - return 0; + if (!isListening()) + return 0; - return (_receive_buffer_tail + _SS_MAX_RX_BUFF - _receive_buffer_head) % _SS_MAX_RX_BUFF; + return (_receive_buffer_tail + _SS_MAX_RX_BUFF - _receive_buffer_head) % _SS_MAX_RX_BUFF; } size_t SoftwareSerial::write(uint8_t b) { - if (_tx_delay == 0) { - setWriteError(); - return 0; - } - - // By declaring these as local variables, the compiler will put them - // in registers _before_ disabling interrupts and entering the - // critical timing sections below, which makes it a lot easier to - // verify the cycle timings - volatile uint8_t *reg = _transmitPortRegister; - uint8_t reg_mask = _transmitBitMask; - uint8_t inv_mask = ~_transmitBitMask; - uint8_t oldSREG = SREG; - bool inv = _inverse_logic; - uint16_t delay = _tx_delay; - - if (inv) - b = ~b; - - cli(); // turn off interrupts for a clean txmit - - // Write the start bit - if (inv) - *reg |= reg_mask; - else - *reg &= inv_mask; - - tunedDelay(delay); - - // Write each of the 8 bits - for (uint8_t i = 8; i > 0; --i) - { - if (b & 1) // choose bit - *reg |= reg_mask; // send 1 - else - *reg &= inv_mask; // send 0 - - tunedDelay(delay); - b >>= 1; - } - - // restore pin to natural state - if (inv) - *reg &= inv_mask; - else - *reg |= reg_mask; - - SREG = oldSREG; // turn interrupts back on - tunedDelay(_tx_delay); - - return 1; + if (_tx_delay == 0) { + setWriteError(); + return 0; + } + + // By declaring these as local variables, the compiler will put them + // in registers _before_ disabling interrupts and entering the + // critical timing sections below, which makes it a lot easier to + // verify the cycle timings + volatile uint8_t *reg = _transmitPortRegister; + uint8_t reg_mask = _transmitBitMask; + uint8_t inv_mask = ~_transmitBitMask; + uint8_t oldSREG = SREG; + bool inv = _inverse_logic; + uint16_t delay = _tx_delay; + + if (inv) + b = ~b; + + cli(); // turn off interrupts for a clean txmit + + // Write the start bit + if (inv) + *reg |= reg_mask; + else + *reg &= inv_mask; + + tunedDelay(delay); + + // Write each of the 8 bits + for (uint8_t i = 8; i > 0; --i) + { + if (b & 1) // choose bit + *reg |= reg_mask; // send 1 + else + *reg &= inv_mask; // send 0 + + tunedDelay(delay); + b >>= 1; + } + + // restore pin to natural state + if (inv) + *reg &= inv_mask; + else + *reg |= reg_mask; + + SREG = oldSREG; // turn interrupts back on + tunedDelay(_tx_delay); + + return 1; } void SoftwareSerial::flush() { - if (!isListening()) - return; + if (!isListening()) + return; - uint8_t oldSREG = SREG; - cli(); - _receive_buffer_head = _receive_buffer_tail = 0; - SREG = oldSREG; + uint8_t oldSREG = SREG; + cli(); + _receive_buffer_head = _receive_buffer_tail = 0; + SREG = oldSREG; } int SoftwareSerial::peek() { - if (!isListening()) - return -1; + if (!isListening()) + return -1; - // Empty buffer? - if (_receive_buffer_head == _receive_buffer_tail) - return -1; + // Empty buffer? + if (_receive_buffer_head == _receive_buffer_tail) + return -1; - // Read from "head" - return _receive_buffer[_receive_buffer_head]; + // Read from "head" + return _receive_buffer[_receive_buffer_head]; } diff --git a/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/SoftwareSerial.h b/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/SoftwareSerial.h index a3f155d626..680e40db1f 100644 --- a/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/SoftwareSerial.h +++ b/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/SoftwareSerial.h @@ -1,12 +1,12 @@ /* -SoftwareSerial.h (formerly NewSoftSerial.h) - +SoftwareSerial.h (formerly NewSoftSerial.h) - Multi-instance software serial library for Arduino/Wiring -- Interrupt-driven receive and other improvements by ladyada -(http://ladyada.net) + (http://ladyada.net) -- Tuning, circular buffer, derivation from class Print/Stream, -multi-instance support, porting to 8MHz processors, -various optimizations, PROGMEM delay tables, inverse logic and -direct port writing by Mikal Hart (http://www.arduiniana.org) + multi-instance support, porting to 8MHz processors, + various optimizations, PROGMEM delay tables, inverse logic and + direct port writing by Mikal Hart (http://www.arduiniana.org) -- Pin change interrupt macros by Paul Stoffregen (http://www.pjrc.com) -- 20MHz processor support by Garrett Mace (http://www.macetech.com) -- ATmega1280/2560 support by Brett Hagman (http://www.roguerobotics.com/) @@ -47,65 +47,66 @@ The latest version of this library can always be found at class SoftwareSerial : public Stream { private: - // per object data - uint8_t _receivePin; - uint8_t _receiveBitMask; - volatile uint8_t *_receivePortRegister; - uint8_t _transmitBitMask; - volatile uint8_t *_transmitPortRegister; - volatile uint8_t *_pcint_maskreg; - uint8_t _pcint_maskvalue; - - // Expressed as 4-cycle delays (must never be 0!) - uint16_t _rx_delay_centering; - uint16_t _rx_delay_intrabit; - uint16_t _rx_delay_stopbit; - uint16_t _tx_delay; - - uint16_t _buffer_overflow : 1; - uint16_t _inverse_logic : 1; - - // static data - static char _receive_buffer[_SS_MAX_RX_BUFF]; - static volatile uint8_t _receive_buffer_tail; - static volatile uint8_t _receive_buffer_head; - static SoftwareSerial *active_object; - - // private methods - void recv() __attribute__((__always_inline__)); - uint8_t rx_pin_read(); - void tx_pin_write(uint8_t pin_state) __attribute__((__always_inline__)); - void setTX(uint8_t transmitPin); - void setRX(uint8_t receivePin); - void setRxIntMsk(bool enable) __attribute__((__always_inline__)); - - // Return num - sub, or 1 if the result would be < 1 - static uint16_t subtract_cap(uint16_t num, uint16_t sub); - - // private static method for timing - static inline void tunedDelay(uint16_t delay); + // per object data + uint8_t _receivePin; + uint8_t _receiveBitMask; + volatile uint8_t *_receivePortRegister; + uint8_t _transmitBitMask; + volatile uint8_t *_transmitPortRegister; + volatile uint8_t *_pcint_maskreg; + uint8_t _pcint_maskvalue; + + // Expressed as 4-cycle delays (must never be 0!) + uint16_t _rx_delay_centering; + uint16_t _rx_delay_intrabit; + uint16_t _rx_delay_stopbit; + uint16_t _tx_delay; + + uint16_t _buffer_overflow:1; + uint16_t _inverse_logic:1; + + // static data + static char _receive_buffer[_SS_MAX_RX_BUFF]; + static volatile uint8_t _receive_buffer_tail; + static volatile uint8_t _receive_buffer_head; + static SoftwareSerial *active_object; + + // private methods + void recv() __attribute__((__always_inline__)); + uint8_t rx_pin_read(); + void tx_pin_write(uint8_t pin_state) __attribute__((__always_inline__)); + void setTX(uint8_t transmitPin); + void setRX(uint8_t receivePin); + void setRxIntMsk(bool enable) __attribute__((__always_inline__)); + + // Return num - sub, or 1 if the result would be < 1 + static uint16_t subtract_cap(uint16_t num, uint16_t sub); + + // private static method for timing + static inline void tunedDelay(uint16_t delay); public: - // public methods - SoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic = false); - ~SoftwareSerial(); - void begin(long speed); - bool listen(); - void end(); - bool isListening() { return this == active_object; } - bool stopListening(); - bool overflow() { bool ret = _buffer_overflow; if (ret) _buffer_overflow = false; return ret; } - int peek(); - - virtual size_t write(uint8_t byte); - virtual int read(); - virtual int available(); - virtual void flush(); - - using Print::write; - - // public only for easy access by interrupt handlers - static inline void handle_interrupt() __attribute__((__always_inline__)); + // public methods + SoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic = false); + ~SoftwareSerial(); + void begin(long speed); + bool listen(); + void end(); + bool isListening() { return this == active_object; } + bool stopListening(); + bool overflow() { bool ret = _buffer_overflow; if (ret) _buffer_overflow = false; return ret; } + int peek(); + + virtual size_t write(uint8_t byte); + virtual int read(); + virtual int available(); + virtual void flush(); + operator bool() { return true; } + + using Print::write; + + // public only for easy access by interrupt handlers + static inline void handle_interrupt() __attribute__((__always_inline__)); }; // Arduino 0012 workaround diff --git a/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/library.properties b/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/library.properties index a69b54df06..37eb04b3dc 100644 --- a/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/library.properties +++ b/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/library.properties @@ -4,5 +4,6 @@ author=Arduino maintainer=Arduino sentence=Enables serial communication on digital pins. For all Arduino boards, BUT Arduino DUE. paragraph= -url=http://arduino.cc/en/Reference/SoftwareSerial +url=http://www.arduino.cc/en/Reference/SoftwareSerial architectures=avr + diff --git a/plugins/KeyboardioHID/avr/libraries/Wire/examples/master_reader/master_reader.ino b/plugins/KeyboardioHID/avr/libraries/Wire/examples/master_reader/master_reader.ino index 74f0155f8e..2d2419b323 100644 --- a/plugins/KeyboardioHID/avr/libraries/Wire/examples/master_reader/master_reader.ino +++ b/plugins/KeyboardioHID/avr/libraries/Wire/examples/master_reader/master_reader.ino @@ -20,7 +20,7 @@ void setup() void loop() { - Wire.requestFrom(2, 6); // request 6 bytes from slave device #2 + Wire.requestFrom(8, 6); // request 6 bytes from slave device #8 while (Wire.available()) // slave may send less than requested { diff --git a/plugins/KeyboardioHID/avr/libraries/Wire/examples/master_writer/master_writer.ino b/plugins/KeyboardioHID/avr/libraries/Wire/examples/master_writer/master_writer.ino index 482e922379..9933cc2cdd 100644 --- a/plugins/KeyboardioHID/avr/libraries/Wire/examples/master_writer/master_writer.ino +++ b/plugins/KeyboardioHID/avr/libraries/Wire/examples/master_writer/master_writer.ino @@ -21,7 +21,7 @@ byte x = 0; void loop() { - Wire.beginTransmission(4); // transmit to device #4 + Wire.beginTransmission(8); // transmit to device #8 Wire.write("x is "); // sends five bytes Wire.write(x); // sends one byte Wire.endTransmission(); // stop transmitting diff --git a/plugins/KeyboardioHID/avr/libraries/Wire/examples/slave_receiver/slave_receiver.ino b/plugins/KeyboardioHID/avr/libraries/Wire/examples/slave_receiver/slave_receiver.ino index 15eff9a545..53df27449f 100644 --- a/plugins/KeyboardioHID/avr/libraries/Wire/examples/slave_receiver/slave_receiver.ino +++ b/plugins/KeyboardioHID/avr/libraries/Wire/examples/slave_receiver/slave_receiver.ino @@ -14,7 +14,7 @@ void setup() { - Wire.begin(4); // join i2c bus with address #4 + Wire.begin(8); // join i2c bus with address #8 Wire.onReceive(receiveEvent); // register event Serial.begin(9600); // start serial for output } diff --git a/plugins/KeyboardioHID/avr/libraries/Wire/examples/slave_sender/slave_sender.ino b/plugins/KeyboardioHID/avr/libraries/Wire/examples/slave_sender/slave_sender.ino index 4437ab1521..26b9e52608 100644 --- a/plugins/KeyboardioHID/avr/libraries/Wire/examples/slave_sender/slave_sender.ino +++ b/plugins/KeyboardioHID/avr/libraries/Wire/examples/slave_sender/slave_sender.ino @@ -14,7 +14,7 @@ void setup() { - Wire.begin(2); // join i2c bus with address #2 + Wire.begin(8); // join i2c bus with address #8 Wire.onRequest(requestEvent); // register event } diff --git a/plugins/KeyboardioHID/avr/libraries/Wire/library.properties b/plugins/KeyboardioHID/avr/libraries/Wire/library.properties index 3246a75098..0805847431 100644 --- a/plugins/KeyboardioHID/avr/libraries/Wire/library.properties +++ b/plugins/KeyboardioHID/avr/libraries/Wire/library.properties @@ -4,5 +4,6 @@ author=Arduino maintainer=Arduino sentence=Allows the communication between devices or sensors connected via Two Wire Interface Bus. For all Arduino boards, BUT Arduino DUE. paragraph= -url=http://arduino.cc/en/Reference/Wire +url=http://www.arduino.cc/en/Reference/Wire architectures=avr + From 46ee89dadbb56b8035b0c0586c6b6443d6547e29 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Mon, 25 May 2015 19:17:29 +0200 Subject: [PATCH 199/602] Updated Arduino Core files Updated to a nightly between 1.6.4 and 1.6.5 --- plugins/KeyboardioHID/Readme.md | 5 + plugins/KeyboardioHID/avr/cores/hid/Arduino.h | 2 +- .../avr/cores/hid/HardwareSerial.h | 2 +- .../KeyboardioHID/avr/cores/hid/Stream.cpp | 107 +++++++++---- plugins/KeyboardioHID/avr/cores/hid/Stream.h | 11 ++ plugins/KeyboardioHID/avr/cores/hid/Tone.cpp | 24 +-- plugins/KeyboardioHID/avr/cores/hid/wiring.c | 151 +++++++++++++----- .../avr/cores/hid/wiring_private.h | 2 +- .../avr/cores/hid/wiring_pulse.c | 24 ++- 9 files changed, 240 insertions(+), 88 deletions(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 88104cdf54..6c1b0a8ee2 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -63,6 +63,11 @@ Version History =============== ``` 2.3 Release (xx.xx.2015) +* Updated Libraries +* Updated Arduino Core +* Added Minor Consumer definitions +* Fixed platforms.txt +* SERIAL_RX_BUFFER_SIZE reverted to 16 (TODO add -D to build option) 2.2 Release (12.04.2015) * added experimental, not finished nor documented HID-Bridge between 16u2 and 328/2560 diff --git a/plugins/KeyboardioHID/avr/cores/hid/Arduino.h b/plugins/KeyboardioHID/avr/cores/hid/Arduino.h index e8575a3fe0..df7990a503 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/Arduino.h +++ b/plugins/KeyboardioHID/avr/cores/hid/Arduino.h @@ -134,7 +134,7 @@ typedef unsigned int word; #define bit(b) (1UL << (b)) -typedef uint8_t boolean; +typedef bool boolean; typedef uint8_t byte; void init(void); diff --git a/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.h b/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.h index 71ad331519..7f4f162d68 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.h +++ b/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.h @@ -43,7 +43,7 @@ #endif #if !defined(SERIAL_RX_BUFFER_SIZE) #if (RAMEND < 1000) -#define SERIAL_RX_BUFFER_SIZE 32 +#define SERIAL_RX_BUFFER_SIZE 16 #else #define SERIAL_RX_BUFFER_SIZE 64 #endif diff --git a/plugins/KeyboardioHID/avr/cores/hid/Stream.cpp b/plugins/KeyboardioHID/avr/cores/hid/Stream.cpp index 9c581bee1b..b31942f293 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/Stream.cpp +++ b/plugins/KeyboardioHID/avr/cores/hid/Stream.cpp @@ -18,6 +18,8 @@ Created July 2011 parsing functions based on TextFinder library by Michael Margolis + + findMulti/findUntil routines written by Jim Leonard/Xuth */ #include "Arduino.h" @@ -75,7 +77,7 @@ void Stream::setTimeout(unsigned long timeout) // sets the maximum number of mi // find returns true if the target string is found bool Stream::find(char *target) { - return findUntil(target, (char*)""); + return findUntil(target, strlen(target), NULL, 0); } // reads data from the stream until the target string of given length is found @@ -96,32 +98,13 @@ bool Stream::findUntil(char *target, char *terminator) // 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; + if (terminator == NULL) { + MultiTarget t[1] = {{target, targetLen, 0}}; + return findMulti(t, 1) == 0 ? true : false; + } else { + MultiTarget t[2] = {{target, targetLen, 0}, {terminator, termLen, 0}}; + return findMulti(t, 2) == 0 ? true : false; } - return false; } @@ -137,7 +120,7 @@ long Stream::parseInt() // this allows format characters (typically commas) in values to be ignored long Stream::parseInt(char skipChar) { - boolean isNegative = false; + bool isNegative = false; long value = 0; int c; @@ -173,10 +156,10 @@ float Stream::parseFloat() // 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; + bool isNegative = false; + bool isFraction = false; long value = 0; - int c; + char c; float fraction = 1.0; c = peekNextDigit(); @@ -268,3 +251,67 @@ String Stream::readStringUntil(char terminator) return ret; } +int Stream::findMulti( struct Stream::MultiTarget *targets, int tCount) { + // any zero length target string automatically matches and would make + // a mess of the rest of the algorithm. + for (struct MultiTarget *t = targets; t < targets+tCount; ++t) { + if (t->len <= 0) + return t - targets; + } + + while (1) { + int c = timedRead(); + if (c < 0) + return -1; + + for (struct MultiTarget *t = targets; t < targets+tCount; ++t) { + // the simple case is if we match, deal with that first. + if (c == t->str[t->index]) { + if (++t->index == t->len) + return t - targets; + else + continue; + } + + // if not we need to walk back and see if we could have matched further + // down the stream (ie '1112' doesn't match the first position in '11112' + // but it will match the second position so we can't just reset the current + // index to 0 when we find a mismatch. + if (t->index == 0) + continue; + + int origIndex = t->index; + do { + --t->index; + // first check if current char works against the new current index + if (c != t->str[t->index]) + continue; + + // if it's the only char then we're good, nothing more to check + if (t->index == 0) { + t->index++; + break; + } + + // otherwise we need to check the rest of the found string + int diff = origIndex - t->index; + size_t i; + for (i = 0; i < t->index; ++i) { + if (t->str[i] != t->str[i + diff]) + break; + } + + // if we successfully got through the previous loop then our current + // index is good. + if (i == t->index) { + t->index++; + break; + } + + // otherwise we just try the next index + } while (t->index); + } + } + // unreachable + return -1; +} diff --git a/plugins/KeyboardioHID/avr/cores/hid/Stream.h b/plugins/KeyboardioHID/avr/cores/hid/Stream.h index 5cf5ddf017..a8101320c9 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/Stream.h +++ b/plugins/KeyboardioHID/avr/cores/hid/Stream.h @@ -97,6 +97,17 @@ class Stream : public Print // this allows format characters (typically commas) in values to be ignored float parseFloat(char skipChar); // as above but the given skipChar is ignored + + struct MultiTarget { + const char *str; // string you're searching for + size_t len; // length of string you're searching for + size_t index; // index used by the search routine. + }; + + // This allows you to search for an arbitrary number of strings. + // Returns index of the target that is found first or -1 if timeout occurs. + int findMulti(struct MultiTarget *targets, int tCount); }; + #endif diff --git a/plugins/KeyboardioHID/avr/cores/hid/Tone.cpp b/plugins/KeyboardioHID/avr/cores/hid/Tone.cpp index 9bb6fe721c..7216219750 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/Tone.cpp +++ b/plugins/KeyboardioHID/avr/cores/hid/Tone.cpp @@ -30,6 +30,8 @@ Version Modified By Date Comments 0006 D Mellis 09/12/29 Replaced objects with functions 0007 M Sproul 10/08/29 Changed #ifdefs from cpu to register 0008 S Kanemoto 12/06/22 Fixed for Leonardo by @maris_HY +0009 J Reucker 15/04/10 Issue #292 Fixed problems with ATmega8 (thanks to Pete62) +0010 jipp 15/04/13 added additional define check #2923 *************************************************/ #include @@ -151,7 +153,7 @@ static int8_t toneBegin(uint8_t _pin) // whereas 16 bit timers are set to either ck/1 or ck/64 prescalar switch (_timer) { - #if defined(TCCR0A) && defined(TCCR0B) + #if defined(TCCR0A) && defined(TCCR0B) && defined(WGM01) case 0: // 8 bit timer TCCR0A = 0; @@ -296,13 +298,13 @@ void tone(uint8_t _pin, unsigned int frequency, unsigned long duration) #if defined(TCCR0B) if (_timer == 0) { - TCCR0B = prescalarbits; + TCCR0B = (TCCR0B & 0b11111000) | prescalarbits; } else #endif #if defined(TCCR2B) { - TCCR2B = prescalarbits; + TCCR2B = (TCCR2B & 0b11111000) | prescalarbits; } #else { @@ -389,7 +391,7 @@ void tone(uint8_t _pin, unsigned int frequency, unsigned long duration) break; #endif -#if defined(TIMSK3) +#if defined(OCR3A) && defined(TIMSK3) && defined(OCIE3A) case 3: OCR3A = ocr; timer3_toggle_count = toggle_count; @@ -397,7 +399,7 @@ void tone(uint8_t _pin, unsigned int frequency, unsigned long duration) break; #endif -#if defined(TIMSK4) +#if defined(OCR4A) && defined(TIMSK4) && defined(OCIE4A) case 4: OCR4A = ocr; timer4_toggle_count = toggle_count; @@ -454,21 +456,21 @@ void disableTimer(uint8_t _timer) #endif break; -#if defined(TIMSK3) +#if defined(TIMSK3) && defined(OCIE3A) case 3: - TIMSK3 = 0; + bitWrite(TIMSK3, OCIE3A, 0); break; #endif -#if defined(TIMSK4) +#if defined(TIMSK4) && defined(OCIE4A) case 4: - TIMSK4 = 0; + bitWrite(TIMSK4, OCIE4A, 0); break; #endif -#if defined(TIMSK5) +#if defined(TIMSK5) && defined(OCIE5A) case 5: - TIMSK5 = 0; + bitWrite(TIMSK5, OCIE5A, 0); break; #endif } diff --git a/plugins/KeyboardioHID/avr/cores/hid/wiring.c b/plugins/KeyboardioHID/avr/cores/hid/wiring.c index 5cbe241956..6cb22c0032 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/wiring.c +++ b/plugins/KeyboardioHID/avr/cores/hid/wiring.c @@ -92,7 +92,6 @@ unsigned long micros() { #error TIMER 0 not defined #endif - #ifdef TIFR0 if ((TIFR0 & _BV(TOV0)) && (t < 255)) m++; @@ -119,65 +118,118 @@ void delay(unsigned long ms) } } -/* Delay for the given number of microseconds. Assumes a 8 or 16 MHz clock. */ +/* Delay for the given number of microseconds. Assumes a 1, 8, 12, 16, 20 or 24 MHz clock. */ void delayMicroseconds(unsigned int us) { + // call = 4 cycles + 2 to 4 cycles to init us(2 for constant delay, 4 for variable) + // 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 +#if F_CPU >= 24000000L + // for the 24 MHz clock for the aventurous ones, trying to overclock + + // zero delay fix + if (!us) return; // = 3 cycles, (4 when true) + + // the following loop takes a 1/6 of a microsecond (4 cycles) + // per iteration, so execute it six times for each microsecond of + // delay requested. + us *= 6; // x6 us, = 7 cycles + + // account for the time taken in the preceeding commands. + // we just burned 22 (24) cycles above, remove 5, (5*4=20) + // us is at least 6 so we can substract 5 + us -= 5; //=2 cycles + +#elif 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. + // for a one-microsecond delay, simply return. the overhead + // of the function call takes 18 (20) cycles, which is 1us __asm__ __volatile__ ( "nop" "\n\t" - "nop"); //just waiting 2 cycle - if (--us == 0) - return; + "nop" "\n\t" + "nop" "\n\t" + "nop"); //just waiting 4 cycles + if (us <= 1) return; // = 3 cycles, (4 when true) // 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 + us = (us << 2) + us; // x5 us, = 7 cycles // account for the time taken in the preceeding commands. - us -= 2; + // we just burned 26 (28) cycles above, remove 7, (7*4=28) + // us is at least 10 so we can substract 7 + us -= 7; // 2 cycles #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; + // of the function call takes 14 (16) cycles, which is 1us + if (us <= 1) return; // = 3 cycles, (4 when true) - // the following loop takes a quarter of a microsecond (4 cycles) + // the following loop takes 1/4 of a microsecond (4 cycles) // per iteration, so execute it four times for each microsecond of // delay requested. - us <<= 2; + us <<= 2; // x4 us, = 4 cycles // account for the time taken in the preceeding commands. - us -= 2; -#else - // for the 8 MHz internal clock on the ATmega168 + // we just burned 19 (21) cycles above, remove 5, (5*4=20) + // us is at least 8 so we can substract 5 + us -= 5; // = 2 cycles, + +#elif F_CPU >= 12000000L + // for the 12 MHz clock if somebody is working with USB + + // for a 1 microsecond delay, simply return. the overhead + // of the function call takes 14 (16) cycles, which is 1.5us + if (us <= 1) return; // = 3 cycles, (4 when true) - // 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 1/3 of a microsecond (4 cycles) + // per iteration, so execute it three times for each microsecond of + // delay requested. + us = (us << 1) + us; // x3 us, = 5 cycles + + // account for the time taken in the preceeding commands. + // we just burned 20 (22) cycles above, remove 5, (5*4=20) + // us is at least 6 so we can substract 5 + us -= 5; //2 cycles + +#elif F_CPU >= 8000000L + // for the 8 MHz internal clock - // the following loop takes half of a microsecond (4 cycles) + // for a 1 and 2 microsecond delay, simply return. the overhead + // of the function call takes 14 (16) cycles, which is 2us + if (us <= 2) return; // = 3 cycles, (4 when true) + + // the following loop takes 1/2 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--; + us <<= 1; //x2 us, = 2 cycles + + // account for the time taken in the preceeding commands. + // we just burned 17 (19) cycles above, remove 4, (4*4=16) + // us is at least 6 so we can substract 4 + us -= 4; // = 2 cycles + +#else + // for the 1 MHz internal clock (default settings for common Atmega microcontrollers) + + // the overhead of the function calls is 14 (16) cycles + if (us <= 16) return; //= 3 cycles, (4 when true) + if (us <= 25) return; //= 3 cycles, (4 when true), (must be at least 25 if we want to substract 22) + + // compensate for the time taken by the preceeding and next commands (about 22 cycles) + us -= 22; // = 2 cycles + // the following loop takes 4 microseconds (4 cycles) + // per iteration, so execute it us/4 times + // us is at least 4, divided by 4 gives us 1 (no zero delay bug) + us >>= 2; // us div 4, = 4 cycles + + #endif // busy wait @@ -185,6 +237,7 @@ void delayMicroseconds(unsigned int us) "1: sbiw %0,1" "\n\t" // 2 cycles "brne 1b" : "=w" (us) : "0" (us) // 2 cycles ); + // return = 4 cycles } void init() @@ -199,7 +252,7 @@ void init() #if defined(TCCR0A) && defined(WGM01) sbi(TCCR0A, WGM01); sbi(TCCR0A, WGM00); -#endif +#endif // set timer 0 prescale factor to 64 #if defined(__AVR_ATmega128__) @@ -302,14 +355,32 @@ void init() #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); - + // set a2d prescaler so we are inside the desired 50-200 KHz range. + #if F_CPU >= 16000000 // 16 MHz / 128 = 125 KHz + sbi(ADCSRA, ADPS2); + sbi(ADCSRA, ADPS1); + sbi(ADCSRA, ADPS0); + #elif F_CPU >= 8000000 // 8 MHz / 64 = 125 KHz + sbi(ADCSRA, ADPS2); + sbi(ADCSRA, ADPS1); + cbi(ADCSRA, ADPS0); + #elif F_CPU >= 4000000 // 4 MHz / 32 = 125 KHz + sbi(ADCSRA, ADPS2); + cbi(ADCSRA, ADPS1); + sbi(ADCSRA, ADPS0); + #elif F_CPU >= 2000000 // 2 MHz / 16 = 125 KHz + sbi(ADCSRA, ADPS2); + cbi(ADCSRA, ADPS1); + cbi(ADCSRA, ADPS0); + #elif F_CPU >= 1000000 // 1 MHz / 8 = 125 KHz + cbi(ADCSRA, ADPS2); + sbi(ADCSRA, ADPS1); + sbi(ADCSRA, ADPS0); + #else // 128 kHz / 2 = 64 KHz -> This is the closest you can get, the prescaler is 2 + cbi(ADCSRA, ADPS2); + cbi(ADCSRA, ADPS1); + sbi(ADCSRA, ADPS0); + #endif // enable a2d conversions sbi(ADCSRA, ADEN); #endif diff --git a/plugins/KeyboardioHID/avr/cores/hid/wiring_private.h b/plugins/KeyboardioHID/avr/cores/hid/wiring_private.h index 35f644b11b..e37ec4dce7 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/wiring_private.h +++ b/plugins/KeyboardioHID/avr/cores/hid/wiring_private.h @@ -84,7 +84,7 @@ extern "C"{ #define EXTERNAL_NUM_INTERRUPTS 2 #endif - typedef void(*voidFuncPtr)(void); +typedef void (*voidFuncPtr)(void); #ifdef __cplusplus } // extern "C" diff --git a/plugins/KeyboardioHID/avr/cores/hid/wiring_pulse.c b/plugins/KeyboardioHID/avr/cores/hid/wiring_pulse.c index 0d968865d2..830c45408a 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/wiring_pulse.c +++ b/plugins/KeyboardioHID/avr/cores/hid/wiring_pulse.c @@ -61,9 +61,25 @@ unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout) 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 + // convert the reading to microseconds. There will be some error introduced by // the interrupt handlers. - return clockCyclesToMicroseconds(width * 21 + 16); + + // Conversion constants are compiler-dependent, different compiler versions + // have different levels of optimization. +#if __GNUC__==4 && __GNUC_MINOR__==3 && __GNUC_PATCHLEVEL__==2 + // avr-gcc 4.3.2 + return clockCyclesToMicroseconds(width * 21 + 16); +#elif __GNUC__==4 && __GNUC_MINOR__==8 && __GNUC_PATCHLEVEL__==1 + // avr-gcc 4.8.1 + return clockCyclesToMicroseconds(width * 24 + 16); +#elif __GNUC__<=4 && __GNUC_MINOR__<=3 + // avr-gcc <=4.3.x + #warning "pulseIn() results may not be accurate" + return clockCyclesToMicroseconds(width * 21 + 16); +#else + // avr-gcc >4.3.x + #warning "pulseIn() results may not be accurate" + return clockCyclesToMicroseconds(width * 24 + 16); +#endif + } From decc02b82a2f66f6328d7e499bdba161e68f410e Mon Sep 17 00:00:00 2001 From: per1234 Date: Wed, 27 May 2015 14:38:37 -0700 Subject: [PATCH 200/602] Add platforms index file Adds Boards Manager install support. --- .../package_NicoHood_HID_index.json | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 plugins/KeyboardioHID/package_NicoHood_HID_index.json diff --git a/plugins/KeyboardioHID/package_NicoHood_HID_index.json b/plugins/KeyboardioHID/package_NicoHood_HID_index.json new file mode 100644 index 0000000000..d1722971a3 --- /dev/null +++ b/plugins/KeyboardioHID/package_NicoHood_HID_index.json @@ -0,0 +1,45 @@ +{ + "packages": [ + { + "name": "HID", + "maintainer": "NicoHood", + "websiteURL": "https://github.com/NicoHood/HID", + "email": "", + "help": { + "online": "" + }, + "platforms": [ + { + "name": "HID Project", + "architecture": "avr", + "version": "2.2", + "category": "HID", + "help": { + "online": "" + }, + "url": "https://github.com/NicoHood/HID/releases/download/2.2/2.2-boards_manager.zip", + "archiveFileName": "2.2-boards_manager.zip", + "checksum": "SHA-256:9c86ee28a7ce9fe33e8b07ec643316131e0031b0d22e63bb398902a5fdadbca9", + "size": "351303", + "boards": [ + {"name": "Arduino Leonardo"}, + {"name": "Arduino Micro"} + ], + "toolsDependencies": [ + { + "packager": "arduino", + "name": "avr-gcc", + "version": "4.8.1-arduino5" + }, + { + "packager": "arduino", + "name": "avrdude", + "version": "6.0.1-arduino5" + } + ] + } + ], + "tools": [] + } + ] +} From 350298169456d258ab6aa3b4fc208448168aeb77 Mon Sep 17 00:00:00 2001 From: Nico Date: Fri, 29 May 2015 19:30:03 +0200 Subject: [PATCH 201/602] Removed Gitter Chat --- plugins/KeyboardioHID/Readme.md | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 6c1b0a8ee2..f231a0ad7f 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -1,7 +1,6 @@ Arduino HID Project 2.3 ======================= -[![Join the chat at https://gitter.im/NicoHood/HID](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/NicoHood/HID?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) ![Header Picture](header.jpg) This project went through a lot of phases and has now reached a new Arduino USB-Core From 6100eccbfba9b49be8dad9e77245283c066ad227 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Mon, 13 Jul 2015 11:18:24 +0200 Subject: [PATCH 202/602] 1.6.6 platforms fix --- plugins/KeyboardioHID/avr/platform.txt | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/plugins/KeyboardioHID/avr/platform.txt b/plugins/KeyboardioHID/avr/platform.txt index c03586d8ec..e482e9238a 100644 --- a/plugins/KeyboardioHID/avr/platform.txt +++ b/plugins/KeyboardioHID/avr/platform.txt @@ -11,7 +11,6 @@ name=HID Project USB-Core version=2.2 - # AVR compile variables # --------------------- @@ -69,18 +68,18 @@ recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.S.flags} -mmcu={b recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{build.path}/{archive_file}" "{object_file}" ## Combine gc-sections, archives, and objects -recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mmcu={build.mcu} {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" {object_files} "{build.path}/{archive_file}" "-L{build.path}" -lm +recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mmcu={build.mcu} {compiler.c.elf.extra_flags} -o "{build.path}/sketch/{build.project_name}.elf" {object_files} "{build.path}/{archive_file}" "-L{build.path}" -lm ## Create output files (.eep and .hex) -recipe.objcopy.eep.pattern="{compiler.path}{compiler.objcopy.cmd}" {compiler.objcopy.eep.flags} {compiler.objcopy.eep.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.eep" -recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.flags} {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.hex" +recipe.objcopy.eep.pattern="{compiler.path}{compiler.objcopy.cmd}" {compiler.objcopy.eep.flags} {compiler.objcopy.eep.extra_flags} "{build.path}/sketch/{build.project_name}.elf" "{build.path}/sketch/{build.project_name}.eep" +recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.flags} {compiler.elf2hex.extra_flags} "{build.path}/sketch/{build.project_name}.elf" "{build.path}/sketch/{build.project_name}.hex" ## Save hex recipe.output.tmp_file={build.project_name}.hex recipe.output.save_file={build.project_name}.{build.variant}.hex ## Compute size -recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf" +recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/sketch/{build.project_name}.elf" recipe.size.regex=^(?:\.text|\.data|\.bootloader)\s+([0-9]+).* recipe.size.regex.data=^(?:\.data|\.bss|\.noinit)\s+([0-9]+).* recipe.size.regex.eeprom=^(?:\.eeprom)\s+([0-9]+).* @@ -95,11 +94,11 @@ tools.avrdude.config.path={path}/etc/avrdude.conf tools.avrdude.upload.params.verbose=-v tools.avrdude.upload.params.quiet=-q -q -tools.avrdude.upload.pattern="{cmd.path}" "-C{config.path}" {upload.verbose} -p{build.mcu} -c{upload.protocol} -P{serial.port} -b{upload.speed} -D "-Uflash:w:{build.path}/{build.project_name}.hex:i" +tools.avrdude.upload.pattern="{cmd.path}" "-C{config.path}" {upload.verbose} -p{build.mcu} -c{upload.protocol} -P{serial.port} -b{upload.speed} -D "-Uflash:w:{build.path}/sketch/{build.project_name}.hex:i" tools.avrdude.program.params.verbose=-v tools.avrdude.program.params.quiet=-q -q -tools.avrdude.program.pattern="{cmd.path}" "-C{config.path}" {program.verbose} -p{build.mcu} -c{protocol} {program.extra_params} "-Uflash:w:{build.path}/{build.project_name}.hex:i" +tools.avrdude.program.pattern="{cmd.path}" "-C{config.path}" {program.verbose} -p{build.mcu} -c{protocol} {program.extra_params} "-Uflash:w:{build.path}/sketch/{build.project_name}.hex:i" tools.avrdude.erase.params.verbose=-v tools.avrdude.erase.params.quiet=-q -q From 8d89a76ca70e73ba00874ff2658f2dabd57960f5 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 9 Aug 2015 14:39:42 +0200 Subject: [PATCH 203/602] Switched to Library with version 2.4 for IDE 1.6.6 --- plugins/KeyboardioHID/.development | 0 plugins/KeyboardioHID/Readme.md | 388 ++++---- plugins/KeyboardioHID/avr/boards.txt | 98 -- plugins/KeyboardioHID/avr/cores/hid/Arduino.h | 273 ------ plugins/KeyboardioHID/avr/cores/hid/Client.h | 45 - .../avr/cores/hid/HardwareSerial.cpp | 252 ----- .../avr/cores/hid/HardwareSerial.h | 156 ---- .../avr/cores/hid/HardwareSerial0.cpp | 79 -- .../avr/cores/hid/HardwareSerial1.cpp | 69 -- .../avr/cores/hid/HardwareSerial2.cpp | 57 -- .../avr/cores/hid/HardwareSerial3.cpp | 57 -- .../avr/cores/hid/HardwareSerial_private.h | 123 --- .../KeyboardioHID/avr/cores/hid/IPAddress.cpp | 74 -- .../KeyboardioHID/avr/cores/hid/IPAddress.h | 75 -- plugins/KeyboardioHID/avr/cores/hid/Print.cpp | 264 ------ plugins/KeyboardioHID/avr/cores/hid/Print.h | 84 -- .../KeyboardioHID/avr/cores/hid/Printable.h | 40 - plugins/KeyboardioHID/avr/cores/hid/Server.h | 30 - .../KeyboardioHID/avr/cores/hid/Stream.cpp | 317 ------- plugins/KeyboardioHID/avr/cores/hid/Stream.h | 113 --- plugins/KeyboardioHID/avr/cores/hid/Tone.cpp | 618 ------------ .../avr/cores/hid/USB-Core/CDC.cpp | 304 ------ .../avr/cores/hid/USB-Core/CDC.h | 105 --- .../avr/cores/hid/USB-Core/HID.cpp | 180 ---- .../avr/cores/hid/USB-Core/HID.h | 441 --------- .../avr/cores/hid/USB-Core/HIDAPI.h | 34 - .../avr/cores/hid/USB-Core/HIDTables.h | 677 -------------- .../avr/cores/hid/USB-Core/Keyboard.cpp | 407 -------- .../avr/cores/hid/USB-Core/Keyboard.h | 196 ---- .../avr/cores/hid/USB-Core/Mouse.cpp | 50 - .../avr/cores/hid/USB-Core/Mouse.h | 156 ---- .../avr/cores/hid/USB-Core/RawHID.cpp | 30 - .../avr/cores/hid/USB-Core/RawHID.h | 79 -- .../avr/cores/hid/USB-Core/USBAPI.h | 121 --- .../avr/cores/hid/USB-Core/USBCore.cpp | 881 ------------------ .../avr/cores/hid/USB-Core/USBCore.h | 361 ------- .../avr/cores/hid/USB-Core/USBDesc.h | 84 -- plugins/KeyboardioHID/avr/cores/hid/Udp.h | 88 -- .../KeyboardioHID/avr/cores/hid/WCharacter.h | 168 ---- .../KeyboardioHID/avr/cores/hid/WInterrupts.c | 334 ------- plugins/KeyboardioHID/avr/cores/hid/WMath.cpp | 60 -- .../KeyboardioHID/avr/cores/hid/WString.cpp | 745 --------------- plugins/KeyboardioHID/avr/cores/hid/WString.h | 224 ----- plugins/KeyboardioHID/avr/cores/hid/abi.cpp | 35 - plugins/KeyboardioHID/avr/cores/hid/binary.h | 534 ----------- plugins/KeyboardioHID/avr/cores/hid/hooks.c | 31 - plugins/KeyboardioHID/avr/cores/hid/main.cpp | 49 - plugins/KeyboardioHID/avr/cores/hid/new.cpp | 36 - plugins/KeyboardioHID/avr/cores/hid/new.h | 30 - plugins/KeyboardioHID/avr/cores/hid/wiring.c | 396 -------- .../avr/cores/hid/wiring_analog.c | 292 ------ .../avr/cores/hid/wiring_digital.c | 181 ---- .../avr/cores/hid/wiring_private.h | 93 -- .../avr/cores/hid/wiring_pulse.c | 85 -- .../avr/cores/hid/wiring_shift.c | 55 -- .../avr/libraries/EEPROM/EEPROM.h | 146 --- .../avr/libraries/EEPROM/README.md | 139 --- .../examples/eeprom_clear/eeprom_clear.ino | 35 - .../EEPROM/examples/eeprom_crc/eeprom_crc.ino | 50 - .../EEPROM/examples/eeprom_get/eeprom_get.ino | 66 -- .../eeprom_iteration/eeprom_iteration.ino | 57 -- .../EEPROM/examples/eeprom_put/eeprom_put.ino | 56 -- .../examples/eeprom_read/eeprom_read.ino | 57 -- .../examples/eeprom_update/eeprom_update.ino | 69 -- .../examples/eeprom_write/eeprom_write.ino | 58 -- .../avr/libraries/EEPROM/keywords.txt | 22 - .../avr/libraries/EEPROM/library.properties | 9 - .../avr/libraries/HIDBridge/HIDBridge.cpp | 388 -------- .../avr/libraries/HIDBridge/HIDBridge.h | 167 ---- .../avr/libraries/HIDBridge/NHP.c | 195 ---- .../avr/libraries/HIDBridge/NHP.h | 142 --- .../KeyboardioHID/avr/libraries/SPI/SPI.cpp | 201 ---- plugins/KeyboardioHID/avr/libraries/SPI/SPI.h | 324 ------- .../BarometricPressureSensor.ino | 143 --- .../DigitalPotControl/DigitalPotControl.ino | 71 -- .../avr/libraries/SPI/keywords.txt | 36 - .../avr/libraries/SPI/library.properties | 9 - .../SoftwareSerial/SoftwareSerial.cpp | 490 ---------- .../libraries/SoftwareSerial/SoftwareSerial.h | 121 --- .../SoftwareSerialExample.ino | 55 -- .../TwoPortReceive/TwoPortReceive.ino | 93 -- .../avr/libraries/SoftwareSerial/keywords.txt | 30 - .../SoftwareSerial/library.properties | 9 - .../KeyboardioHID/avr/libraries/Wire/Wire.cpp | 303 ------ .../KeyboardioHID/avr/libraries/Wire/Wire.h | 80 -- .../SFRRanger_reader/SFRRanger_reader.ino | 87 -- .../digital_potentiometer.ino | 39 - .../examples/master_reader/master_reader.ino | 32 - .../examples/master_writer/master_writer.ino | 31 - .../slave_receiver/slave_receiver.ino | 38 - .../examples/slave_sender/slave_sender.ino | 32 - .../avr/libraries/Wire/keywords.txt | 32 - .../avr/libraries/Wire/library.properties | 9 - .../avr/libraries/Wire/utility/twi.c | 527 ----------- .../avr/libraries/Wire/utility/twi.h | 53 -- plugins/KeyboardioHID/avr/platform.txt | 116 --- plugins/KeyboardioHID/avr/programmers.txt | 8 - .../avr/variants/leonardo/pins_arduino.h | 361 ------- .../variants/leonardo_custom/pins_arduino.h | 157 ---- .../variants/leonardo_gamepad/pins_arduino.h | 39 - .../avr/variants/leonardo_hid/pins_arduino.h | 39 - .../variants/leonardo_no_usb/no_usb_isr.cpp | 34 - .../variants/leonardo_no_usb/pins_arduino.h | 28 - .../avr/variants/micro/pins_arduino.h | 37 - .../avr/variants/micro_custom/pins_arduino.h | 157 ---- .../avr/variants/micro_gamepad/pins_arduino.h | 39 - .../avr/variants/micro_hid/pins_arduino.h | 39 - .../avr/variants/micro_no_usb/no_usb_isr.cpp | 34 - .../avr/variants/micro_no_usb/pins_arduino.h | 28 - .../Consumer.ino} | 13 +- .../examples/Gamepad/Gamepad.ino | 65 ++ .../HID/Gamepad_Advanced/Gamepad_Advanced.ino | 46 - .../HID/Gamepad_Basic/Gamepad_Basic.ino | 57 -- .../Keyboard_Advanced/Keyboard_Advanced.ino | 97 -- .../HID/Keyboard_Basic/Keyboard_Basic.ino | 39 - .../HID/Keyboard_Keycode/Keyboard_Keycode.ino | 56 -- .../HID/Keyboard_Led/Keyboard_Led.ino | 40 - .../examples/HID/Mouse_Basic/Mouse_Basic.ino | 69 -- .../HID/RawHID_Advanced/RawHID_Advanced.ino | 108 --- .../examples/HelloWorld/HelloWorld.ino | 35 - .../Projects/ArduinoISP/ArduinoISP.ino | 546 ----------- .../Gamepad_Project/Gamepad_Project.ino | 112 --- .../HID-Bridge_IO/HID-Bridge_IO.ino | 22 - .../HID-Bridge_USB/HID-Bridge_USB.ino | 34 - .../HoodLoader1_API_Legacy.ino | 165 ---- .../HoodLoader2_PWM_Fade.ino | 39 - .../HoodLoader2_RunBootloader.ino | 33 - .../HoodLoader2_SerialKeyboard.ino | 54 -- .../Projects/USB-Serial/USB-Serial.ino | 61 -- .../System_Basic.ino => System/System.ino} | 19 +- .../libraries/HIDBridge => }/keywords.txt | 4 +- plugins/KeyboardioHID/library.properties | 9 + .../cores/hid/USB-Core => src}/Consumer.cpp | 8 +- .../cores/hid/USB-Core => src}/Consumer.h | 59 +- .../cores/hid/USB-Core => src}/Gamepad.cpp | 8 +- .../{avr/cores/hid/USB-Core => src}/Gamepad.h | 81 +- plugins/KeyboardioHID/src/HID-Project.h | 0 .../cores/hid/USB-Core => src}/System.cpp | 10 +- .../{avr/cores/hid/USB-Core => src}/System.h | 49 +- 139 files changed, 475 insertions(+), 17834 deletions(-) create mode 100644 plugins/KeyboardioHID/.development delete mode 100644 plugins/KeyboardioHID/avr/boards.txt delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/Arduino.h delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/Client.h delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.cpp delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.h delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/HardwareSerial0.cpp delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/HardwareSerial1.cpp delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/HardwareSerial2.cpp delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/HardwareSerial3.cpp delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/HardwareSerial_private.h delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/IPAddress.cpp delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/IPAddress.h delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/Print.cpp delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/Print.h delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/Printable.h delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/Server.h delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/Stream.cpp delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/Stream.h delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/Tone.cpp delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/USB-Core/CDC.cpp delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/USB-Core/CDC.h delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.cpp delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/USB-Core/HIDAPI.h delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/USB-Core/HIDTables.h delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.cpp delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.cpp delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.h delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/USB-Core/RawHID.cpp delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/USB-Core/RawHID.h delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBAPI.h delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBCore.cpp delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBCore.h delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBDesc.h delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/Udp.h delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/WCharacter.h delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/WInterrupts.c delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/WMath.cpp delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/WString.cpp delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/WString.h delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/abi.cpp delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/binary.h delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/hooks.c delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/main.cpp delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/new.cpp delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/new.h delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/wiring.c delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/wiring_analog.c delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/wiring_digital.c delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/wiring_private.h delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/wiring_pulse.c delete mode 100644 plugins/KeyboardioHID/avr/cores/hid/wiring_shift.c delete mode 100644 plugins/KeyboardioHID/avr/libraries/EEPROM/EEPROM.h delete mode 100644 plugins/KeyboardioHID/avr/libraries/EEPROM/README.md delete mode 100644 plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_clear/eeprom_clear.ino delete mode 100644 plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_crc/eeprom_crc.ino delete mode 100644 plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_get/eeprom_get.ino delete mode 100644 plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_iteration/eeprom_iteration.ino delete mode 100644 plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_put/eeprom_put.ino delete mode 100644 plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_read/eeprom_read.ino delete mode 100644 plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_update/eeprom_update.ino delete mode 100644 plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_write/eeprom_write.ino delete mode 100644 plugins/KeyboardioHID/avr/libraries/EEPROM/keywords.txt delete mode 100644 plugins/KeyboardioHID/avr/libraries/EEPROM/library.properties delete mode 100644 plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.cpp delete mode 100644 plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.h delete mode 100644 plugins/KeyboardioHID/avr/libraries/HIDBridge/NHP.c delete mode 100644 plugins/KeyboardioHID/avr/libraries/HIDBridge/NHP.h delete mode 100644 plugins/KeyboardioHID/avr/libraries/SPI/SPI.cpp delete mode 100644 plugins/KeyboardioHID/avr/libraries/SPI/SPI.h delete mode 100644 plugins/KeyboardioHID/avr/libraries/SPI/examples/BarometricPressureSensor/BarometricPressureSensor.ino delete mode 100644 plugins/KeyboardioHID/avr/libraries/SPI/examples/DigitalPotControl/DigitalPotControl.ino delete mode 100644 plugins/KeyboardioHID/avr/libraries/SPI/keywords.txt delete mode 100644 plugins/KeyboardioHID/avr/libraries/SPI/library.properties delete mode 100644 plugins/KeyboardioHID/avr/libraries/SoftwareSerial/SoftwareSerial.cpp delete mode 100644 plugins/KeyboardioHID/avr/libraries/SoftwareSerial/SoftwareSerial.h delete mode 100644 plugins/KeyboardioHID/avr/libraries/SoftwareSerial/examples/SoftwareSerialExample/SoftwareSerialExample.ino delete mode 100644 plugins/KeyboardioHID/avr/libraries/SoftwareSerial/examples/TwoPortReceive/TwoPortReceive.ino delete mode 100644 plugins/KeyboardioHID/avr/libraries/SoftwareSerial/keywords.txt delete mode 100644 plugins/KeyboardioHID/avr/libraries/SoftwareSerial/library.properties delete mode 100644 plugins/KeyboardioHID/avr/libraries/Wire/Wire.cpp delete mode 100644 plugins/KeyboardioHID/avr/libraries/Wire/Wire.h delete mode 100644 plugins/KeyboardioHID/avr/libraries/Wire/examples/SFRRanger_reader/SFRRanger_reader.ino delete mode 100644 plugins/KeyboardioHID/avr/libraries/Wire/examples/digital_potentiometer/digital_potentiometer.ino delete mode 100644 plugins/KeyboardioHID/avr/libraries/Wire/examples/master_reader/master_reader.ino delete mode 100644 plugins/KeyboardioHID/avr/libraries/Wire/examples/master_writer/master_writer.ino delete mode 100644 plugins/KeyboardioHID/avr/libraries/Wire/examples/slave_receiver/slave_receiver.ino delete mode 100644 plugins/KeyboardioHID/avr/libraries/Wire/examples/slave_sender/slave_sender.ino delete mode 100644 plugins/KeyboardioHID/avr/libraries/Wire/keywords.txt delete mode 100644 plugins/KeyboardioHID/avr/libraries/Wire/library.properties delete mode 100644 plugins/KeyboardioHID/avr/libraries/Wire/utility/twi.c delete mode 100644 plugins/KeyboardioHID/avr/libraries/Wire/utility/twi.h delete mode 100644 plugins/KeyboardioHID/avr/platform.txt delete mode 100644 plugins/KeyboardioHID/avr/programmers.txt delete mode 100644 plugins/KeyboardioHID/avr/variants/leonardo/pins_arduino.h delete mode 100644 plugins/KeyboardioHID/avr/variants/leonardo_custom/pins_arduino.h delete mode 100644 plugins/KeyboardioHID/avr/variants/leonardo_gamepad/pins_arduino.h delete mode 100644 plugins/KeyboardioHID/avr/variants/leonardo_hid/pins_arduino.h delete mode 100644 plugins/KeyboardioHID/avr/variants/leonardo_no_usb/no_usb_isr.cpp delete mode 100644 plugins/KeyboardioHID/avr/variants/leonardo_no_usb/pins_arduino.h delete mode 100644 plugins/KeyboardioHID/avr/variants/micro/pins_arduino.h delete mode 100644 plugins/KeyboardioHID/avr/variants/micro_custom/pins_arduino.h delete mode 100644 plugins/KeyboardioHID/avr/variants/micro_gamepad/pins_arduino.h delete mode 100644 plugins/KeyboardioHID/avr/variants/micro_hid/pins_arduino.h delete mode 100644 plugins/KeyboardioHID/avr/variants/micro_no_usb/no_usb_isr.cpp delete mode 100644 plugins/KeyboardioHID/avr/variants/micro_no_usb/pins_arduino.h rename plugins/KeyboardioHID/examples/{HID/Consumer_Basic/Consumer_Basic.ino => Consumer/Consumer.ino} (77%) create mode 100644 plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino delete mode 100644 plugins/KeyboardioHID/examples/HID/Gamepad_Advanced/Gamepad_Advanced.ino delete mode 100644 plugins/KeyboardioHID/examples/HID/Gamepad_Basic/Gamepad_Basic.ino delete mode 100644 plugins/KeyboardioHID/examples/HID/Keyboard_Advanced/Keyboard_Advanced.ino delete mode 100644 plugins/KeyboardioHID/examples/HID/Keyboard_Basic/Keyboard_Basic.ino delete mode 100644 plugins/KeyboardioHID/examples/HID/Keyboard_Keycode/Keyboard_Keycode.ino delete mode 100644 plugins/KeyboardioHID/examples/HID/Keyboard_Led/Keyboard_Led.ino delete mode 100644 plugins/KeyboardioHID/examples/HID/Mouse_Basic/Mouse_Basic.ino delete mode 100644 plugins/KeyboardioHID/examples/HID/RawHID_Advanced/RawHID_Advanced.ino delete mode 100644 plugins/KeyboardioHID/examples/HelloWorld/HelloWorld.ino delete mode 100644 plugins/KeyboardioHID/examples/Projects/ArduinoISP/ArduinoISP.ino delete mode 100644 plugins/KeyboardioHID/examples/Projects/Gamepad_Project/Gamepad_Project.ino delete mode 100644 plugins/KeyboardioHID/examples/Projects/HID-Bridge/HID-Bridge_IO/HID-Bridge_IO.ino delete mode 100644 plugins/KeyboardioHID/examples/Projects/HID-Bridge/HID-Bridge_USB/HID-Bridge_USB.ino delete mode 100644 plugins/KeyboardioHID/examples/Projects/HoodLoader1_API_Legacy/HoodLoader1_API_Legacy.ino delete mode 100644 plugins/KeyboardioHID/examples/Projects/HoodLoader2_PWM_Fade/HoodLoader2_PWM_Fade.ino delete mode 100644 plugins/KeyboardioHID/examples/Projects/HoodLoader2_RunBootloader/HoodLoader2_RunBootloader.ino delete mode 100644 plugins/KeyboardioHID/examples/Projects/HoodLoader2_SerialKeyboard/HoodLoader2_SerialKeyboard.ino delete mode 100644 plugins/KeyboardioHID/examples/Projects/USB-Serial/USB-Serial.ino rename plugins/KeyboardioHID/examples/{HID/System_Basic/System_Basic.ino => System/System.ino} (72%) rename plugins/KeyboardioHID/{avr/libraries/HIDBridge => }/keywords.txt (95%) create mode 100644 plugins/KeyboardioHID/library.properties rename plugins/KeyboardioHID/{avr/cores/hid/USB-Core => src}/Consumer.cpp (93%) rename plugins/KeyboardioHID/{avr/cores/hid/USB-Core => src}/Consumer.h (70%) rename plugins/KeyboardioHID/{avr/cores/hid/USB-Core => src}/Gamepad.cpp (93%) rename plugins/KeyboardioHID/{avr/cores/hid/USB-Core => src}/Gamepad.h (58%) create mode 100644 plugins/KeyboardioHID/src/HID-Project.h rename plugins/KeyboardioHID/{avr/cores/hid/USB-Core => src}/System.cpp (91%) rename plugins/KeyboardioHID/{avr/cores/hid/USB-Core => src}/System.h (59%) diff --git a/plugins/KeyboardioHID/.development b/plugins/KeyboardioHID/.development new file mode 100644 index 0000000000..e69de29bb2 diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index f231a0ad7f..c54eb39da0 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -1,220 +1,232 @@ -Arduino HID Project 2.3 -======================= - -![Header Picture](header.jpg) - -This project went through a lot of phases and has now reached a new Arduino USB-Core -with a lot of new functions like extended HID. It also supports HoodLoader1+2. -The idea is to enable enhanced USB functions to almost all 'standard' Arduino boards. - -See the [wiki](https://github.com/NicoHood/HID/wiki/Features) for more information about features etc. - +MSGEQ7 Library 1.2 + Board v1.0 +=============================== +![Header](header.png) + +The MSGEQ7 is an IC designed to analyze music on different frequencies. +This library reads the MSGEQ7 with 7 different frequencies from range 0-255, stereo or mono. +It can be used to visualize audio through Leds for example. +This repository also includes the source of an [Breakout Board](https://github.com/NicoHood/MSGEQ7/tree/dev#breakout-board). + +The frequencies are: +63Hz, 160Hz, 400Hz, 1kHz, 2.5kHz, 6.25KHz, 16kHz + +####Features +* IDE 1.6.x with every Arduino compatibly +* [Sparkfun Spectrum Shield](https://www.sparkfun.com/products/13116) compatible +* Reads 1-n MSGEQ7 sensors +* Compact and fast implementation +* More compact and flexible 8 bit resolution +* Optional 10 bit resolution +* Value smoothing +* Tools to reduce noise +* A [Breakout Board](https://github.com/NicoHood/MSGEQ7/tree/dev#breakout-board). + +####Examples included: +* Led: blinks led, shows basic usage +* Serial: shows spectrum via serial and how to use more channels +* FastLED: blinks led strip with different frequencies. Shows how to use different syntax. +Uses [FastLED library](https://github.com/FastLED/FastLED) + +More projects/contact: +http://www.NicoHood.de + + +Hardware Setup +============== +To use the MSGEQ7 you first need a few other parts and connect them properly. +Make sure the 33pF capacitor and the 200k Ohm resistor are precise. +Otherwise the frequencies may be off. +See the [data sheet](https://www.sparkfun.com/datasheets/Components/General/MSGEQ7.pdf) for more information. + +#####Required parts (stereo): +* 2x [MSGEQ7 IC](https://www.sparkfun.com/products/10468) +* 1x [Audio Jack 3.5mm](https://www.sparkfun.com/products/8032) (or any other audio input) +* 2x 10nF Capacitor +* 4x 100nF Capacitor +* 2x 33pF Capacitor +* 2x 200k Ohm Resistor +* Led or Led strips +* 1x 220 Ohm Resistor (for Led) + +###Breadboard Setup +This would be an example breadboard setup for the Led example. + +![Schematic](extras/breadboard/MSGEQ7_Schematic.png) + +![Breadboard Setup](extras/breadboard/MSGEQ7_Breadboard.png) + + +Software installation +===================== +Install the library as you are used to. +More information can be found [here](http://arduino.cc/en/guide/libraries). + + +API Documentation +================= + +#####`template class CMSGEQ7` +Every CMSGEQ7 instance needs some pins passed via template to optimize the code. +If you want to smooth the readings with the last reading pass true as first argument. +The reset and strobe pin can be anyone on the board. +You can input as many analog pins as needed. +For example as mono mode only a single IC, stereo 2 or surround as many channels as you want. + +#####`void begin(void);` +Do whatever is required to initialize the IC and resets it. + +#####`void end(void);` +Sets pins to input again to safely remove connections if needed + +#####`void reset(void);` +Resets IC, so it starts reading at 0 again. +Normally this is not needed since its done in the `begin()` function. + +#####`bool read(void);` +Basic read function. Reads all channels and saves value inside the buffer. +You can access the buffer with the `get()` function. +Up to 400FPS are possible with 2 channels I've measured. + +#####`bool read(const uint32_t currentMicros, const uint32_t interval);` +To automatically read every X seconds you may also use this function. +Use the `ReadsPerSecond(f)` Makro with the interval and you can easily choose a good speed interval. +You can also leave out the first argument, this will be automatically replaced with a `micros()`. + +#####`MSGEQ7_data_t get(const uint8_t frequency, const uint8_t channel);` +Returns the data of the selected frequency and channel. +By default this returns an `uint8_t` value, for 10bit resolution `uint16_t`. +Frequency should be 0-6 where 0 is the lowest frequency (Bass) and 6 the highest. +Depending on how many analog pins you have attached you can select the channel here (0-n). +You can also leave out the channel variable to get an average value of all channels. + +#####`MSGEQ7_data_t getVolume(uint8_t channel);` +Returns the overall volume of all frequencies of a channel. +By default this returns an `uint8_t` value, for 10bit resolution `uint16_t`. +Depending on how many analog pins you have attached you can select the channel here (0-n). +You can also leave out the channel variable to get an average volume of all channels. + +#####`MSGEQ7_data_t map(MSGEQ7_data_t x, MSGEQ7_data_t in_min = MSGEQ7_IN_MIN, MSGEQ7_data_t in_max = MSGEQ7_IN_MAX, MSGEQ7_data_t out_min = MSGEQ7_OUT_MIN, MSGEQ7_data_t out_max = MSGEQ7_OUT_MAX);` +Maps the input from a given input range to an output range. +This is useful to reduce noise. All MSGEQ7 produce a noise of about 15-19 if no music is played. +This macro can be used to remap the input. You can leave out the last 4 arguments, they will be replaced with default values. +For 10 bit resolution the function uses `uint16_t` and 1023 as default maximum value. + +#####`Definitions` +```cpp +//#define MSGEQ7_10BIT +#define ReadsPerSecond(f) (1000000UL / (f)) + +// basic frequencys definitions (0-6 valid, 7 channels) +#define MSGEQ7_0 0 +#define MSGEQ7_1 1 +#define MSGEQ7_2 2 +#define MSGEQ7_3 3 +#define MSGEQ7_4 4 +#define MSGEQ7_5 5 +#define MSGEQ7_6 6 +#define MSGEQ7_BASS 0 +#define MSGEQ7_LOW 0 +#define MSGEQ7_MID 3 +#define MSGEQ7_HIGH 5 +``` -Download -======== -You have 3 versions you can download: -* The master includes all fixes to the current stable release. Download it by clicking download at the right. -Use the [online Wiki](https://github.com/NicoHood/HID/wiki) to get the newest documentation. -* Download an offline version in [releases](https://github.com/NicoHood/HID/releases). -It's a snapshot of the current stable release but might have missed some updates that the current master branch has included. -This also includes an offline version of the wiki. Offline versions will be available after some time when the official release is out. -* Select [branch 'dev'](https://github.com/NicoHood/HID/tree/dev) to test the bleeding edge of this software. It might now work at all or has a lot of debugging stuff in it. -If the dev version gets near to a new release a note will be placed here, that you can test the new dev beta. -Currently there is no beta available. +Breakout Board +============== +The MSGEQ7 Breakout Board lets you easily hook up an audio source or microphone to your microcontroller. +You may also use a 2nd audio output to pass the audio signal to music boxes again. +You can solder a 6 or 8 pin header to the board and connect it to a breadboard for example. +It is fully open source so you can create a copy for yourself or modify it. +#####Features: +* Stereo music analyze +* Audio input via 3.5mm Jack +* Additional audio output +* Additional audio in/output via pin header +* Mounting holes +* Breadboard compatible +* Easy to solder (DIP parts) +* [Open Source Hardware](http://www.oshwa.org/definition/) -Wiki -==== +#####Required parts: +* 2x [MSGEQ7 IC](https://www.sparkfun.com/products/10468) +* 2x [Audio Jack 3.5mm](https://www.sparkfun.com/products/8032) +* 8 pin header male +* 2x IC socket 8 pins (optional) +* 2x 10nF Capacitor +* 4x 100nF Capacitor +* 2x 33pF Capacitor +* 2x 200k Ohm Resistor -All documentation moved to the [wiki page](https://github.com/NicoHood/HID/wiki). -An offline snapshot is available in [releases](https://github.com/NicoHood/HID/releases). +#####Files: +You can find all needed files in the [board](extras/board/) folder. +Click view raw to download the PDF files. +#####Schematic +![Schematic](extras/board/MSGEQ7_Schematic.png) -Contact -======= +#####PCB +![PCB](extras/board/MSGEQ7_PCB.png) -You can contact me on my wordpress blog in the contact section. -www.nicohood.de +Additional Information +====================== +This library started as my very first one and become better and better over the time. +To be honest it is now very complex, due to the optimization and API flexibility. +The read function itself is simple though. +Have a look at the library itself, its not so complicated. +But keep attention to the LOW and HIGH setting of strobe and reset -TODO -==== +Keep in mind that the smoothed value is created from the last read + current read divided by 2. +I found out that reading with 50 FPS is a good value to use. -Under Construction. This is a todo list for myself. +You can reset the IC with myMSGEQ7.reset() but you don't need that normally. -``` -Keyboard Layout for different Languages -Clean up USB Core code from fixed values. Use better understandable definitions -Magic key fix for 32u4? +If you only want to use mono mode or one IC just connect the two inputs together to the MSGEQ7 +and only use one analog input. But you can also use multiply ICs and connect them to an analog input each. +The reset and strobe line is connected to every IC, so you don't need to multiply them. -Check Keyboard keycode function again -Generalize HID key definitions via HIDTables for example? +The output only ranges from 0-255 to save memory use it easier. You don't lose much information. +If you still want to read up to 1023 define MSGEQ7_10BIT before including the library. -Test with Android phone (HL1) -improve keywords.txt -``` +The IC has a standard value at about 10-19. You should keep that in mind. +In this case the Led always glims a bit. Have a look at the map() function to improve this. Version History =============== ``` -2.3 Release (xx.xx.2015) -* Updated Libraries -* Updated Arduino Core -* Added Minor Consumer definitions -* Fixed platforms.txt -* SERIAL_RX_BUFFER_SIZE reverted to 16 (TODO add -D to build option) - -2.2 Release (12.04.2015) -* added experimental, not finished nor documented HID-Bridge between 16u2 and 328/2560 -* increased HW Serial1 RX buffer size from 16 to 32 (TX still 16) -* added colour highlighting (through HID-Bridge library) -* removed fixed size in report buffers -* used HID_KeyboardReport_Data_t now in Keyboard API -* Arduino as ISP fix for 328 -* Upload verification on USB hubs fix for HL2.0.4 -* No USB workaround for Leonardo integrated into variants -* Changed USB Wakeup in System API -* Consumer Key fix (issue #3) -* Gamepad fix (issue #14) -* Added Keycode example -* Mouse press + release fix - -2.1 Release (28.01.2015) -* Reworked the whole USB-Core from scratch -* Uses less flash if HID or Serial is not used -* Extended and compacter(flash) HID Report Descriptors -* Fixed USB Device Descriptor -* Added u2 compatibility with smaller USB_EP_SIZE (16u2 etc) -* Added Serial Event for LineEncoding and LineState -* Added Serial Function to get dtr state, line encoding etc -* Added Keyboard Led Out report to get Led states (for numlock etc) -* Made CDC-Core independent from USB-Core -* Made HID-Core independent from USB-Core -* Made HID-API independent from HID-Core -* Removed not needed virtual functions in Keyboard -* Made HID Reports and its IDs replaceable via pins_Arduino.h -* Added Absolute Mouse -* Removed uint8_t USBPutChar(uint8_t c); in HID.cpp -* Made void Recv(volatile u8* data, u8 count) in USBCore.cpp static inline -* HID-APIs sends a clean report on begin() and end() now. -* Removed virtual functions in Keyboard API -* Added Keycode functions in Keyboard API -* Inlined a lot of the HID API functions to save flash -* Added Gamepad -* Added RawHID API (but RawHID itself isnt working still) -* Added USB Wakeup support -* Separated USB-Core in its own folder -* Added HID Tables -* USB-Serial now fully reprogrammable -* Easy USB-Core selection via Tools->USB-Core -* Added Arduino as ISP fix for 32u4 and 16u2 -* Moved documentation to the wiki -* Added AVR libraries to the core with the better SoftSerial - -2.0 Release (29.11.2014) -* Added HoodLoader2 -* Separated HoodLoader1&2 more -* Added u2 series for USB-Core -* Extended USB core and fixed minor things for the u2 series -* Added Led Out report. -* Added CDC Line state -* Reworked the whole library structure again - -1.8 Beta Release (26.08.2014) -* Changes in the Hoodloader1: - * **Huge improvements**, see Hoodloader1 repository - * Reworked the whole library, easy installation now - * HID fixes for Media Keys/Ubuntu - * Removed Joystick, added 4 Gamepads - -1.7.3 Beta Release (10.08.2014) -* Changes in the Hoodloader1: - * Fixed HID flush bug (1.6 - 1.7.2) - -1.7.2 Beta Release (10.08.2014) -* Changes in the Hoodloader1: - * Added Lite version for 8u2 - * Added Versions that show up as Uno/Mega (not recommended) - * Makefile and structure changes - -1.7.1 Beta Release (10.08.2014) -* Changes in the Hoodloader1: - * Fixed HID deactivation bug - -1.7 Beta Release (10.08.2014) -* Changes in the Hoodloader1: - * Works as ISP now. See Hoodloader1 Repository for more information. - * Exceeded 8kb limit. For flashing a 8u2 use v1.6 please! -* Changed Readme text - -1.6 Beta Release (09.08.2014) -* Bugfixes in the Hoodloader1: - * Changed HID management (not blocking that much, faster) - * added RawHID in/out (HID to Serial) -* Added RawHID Class and example - -1.5 Beta Release (21.07.2014) -* Moved Hoodloader1 source to a separate Github page -* Bugfixes in the Hoodloader: - * Firmware is still available here - * Overall a lot of ram improvements, now with a big global union of ram - * Removed USBtoUSART buffer (not needed, saved 128/500 bytes) - * Removed Lite version because of better ram usage not needed - * Separated different modes better to not cause any errors in default mode - * Improved the deactivate option - * Integrated NHP directly - * Replaced LightweightRingbuffer with native Lufa Ringbuffer - * Improved writing to CDC Host - * Fixed a bug in checkNHPProtocol: & needs to be a == - * General structure changes - * Improved stability - * Fixed Arduino as ISP bug - -1.4.1 Beta Release (10.07.2014) -* #define Bugfix in USBAPI.h - -1.4 Beta Release (10.07.2014) -* Bugfixes in the Hoodloader1: - * Added Lite Version with less ram usage - * Changed PIDs, edited driver file -* merged v1.0.x and v1.5.x together (both are compatible!) -* added IDE v1.5.7 support -* added Tutorials - -1.3 Beta Release (01.07.2014) -* Bugfixes in the Hoodloader1: - * Improved ram usage -* **Important NHP fix inside the HID Class for Uno/Mega** - -1.2 Beta Release (22.06.2014) -* Added 1.0.x/1.5.x support -* Bugfixes in the Hoodloader1: - * Sometimes HID Devices weren't updating - when using more than 1 Device (set forcewrite to true) - * Fast updates crashed the bootloader - (too much ram usage, set CDC buffer from 128b to 100b each) -* Minor file structure changes - -1.1 Beta Release (05.06.2014) -* Added Leonardo/Micro support -* Included NicoHoodProtocol -* Minor fixes - -1.0 Beta Release (03.06.2014) +1.2.1 Release (xx.xx.2015) +* Added 1.6.x library schema + +1.2 Release (23.04.2015) +* Added breakout board files v1.0 +* Optimized performance +* Variable number of ICs readable +* Added optional 10bit resolution +* Added more functions/tools +* Improved examples +* Added MSGEQ7_VERSION definition +* Added library.properties + +1.1 Release (10.07.2014) +* Changed syntax +* Optimized performance +* Added more examples + +1.0 Release (13.04.2014) +* Added general functionality ``` -Licence and Copyright +License and Copyright ===================== If you use this library for any cool project let me know! ``` Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/plugins/KeyboardioHID/avr/boards.txt b/plugins/KeyboardioHID/avr/boards.txt deleted file mode 100644 index 4645d70ab6..0000000000 --- a/plugins/KeyboardioHID/avr/boards.txt +++ /dev/null @@ -1,98 +0,0 @@ -#HID Project board definition file - -menu.usbcore=USB Core - -############################################################## - -leonardoExtended.name=Arduino Leonardo HID-Project -leonardoExtended.upload.tool=arduino:avrdude -leonardoExtended.upload.protocol=avr109 -leonardoExtended.upload.maximum_size=28672 -leonardoExtended.upload.maximum_data_size=2560 -leonardoExtended.upload.speed=57600 -leonardoExtended.upload.disable_flushing=true -leonardoExtended.upload.use_1200bps_touch=true -leonardoExtended.upload.wait_for_upload_port=true - -leonardoExtended.bootloader.tool=arduino:avrdude -leonardoExtended.bootloader.low_fuses=0xff -leonardoExtended.bootloader.high_fuses=0xd8 -leonardoExtended.bootloader.extended_fuses=0xcb -leonardoExtended.bootloader.file=arduino:caterina/Caterina-leonardo.hex -leonardoExtended.bootloader.unlock_bits=0x3F -leonardoExtended.bootloader.lock_bits=0x2F - -leonardoExtended.build.mcu=atmega32u4 -leonardoExtended.build.f_cpu=16000000L -leonardoExtended.build.core=HID:hid -leonardoExtended.build.vid=0x2341 -#leonardoExtended.build.pid=0x8036 -leonardoExtended.build.usb_product="Arduino Leonardo" -leonardoExtended.build.board=AVR_LEONARDO -leonardoExtended.build.extra_flags={build.usb_flags} - -#USB core selection -#HID Project needs to be installed https://github.com/NicoHood/HID -leonardoExtended.menu.usbcore.hid=Serial + Extended HID -leonardoExtended.menu.usbcore.hid.build.variant=leonardo_hid -leonardoExtended.menu.usbcore.hid.build.pid=0x8036 -leonardoExtended.menu.usbcore.gamepad=Serial + Gamepad HID -leonardoExtended.menu.usbcore.gamepad.build.variant=leonardo_gamepad -leonardoExtended.menu.usbcore.gamepad.build.pid=0x8036 -leonardoExtended.menu.usbcore.custom=Serial + Custom HID -leonardoExtended.menu.usbcore.custom.build.variant=leonardo_custom -leonardoExtended.menu.usbcore.custom.build.pid=0x8036 -leonardoExtended.menu.usbcore.USB_CORE=Default Core -leonardoExtended.menu.usbcore.USB_CORE.build.variant=leonardo -leonardoExtended.menu.usbcore.USB_CORE.build.pid=0x8036 -leonardoExtended.menu.usbcore.NO_USB=No USB functions -leonardoExtended.menu.usbcore.NO_USB.build.variant=leonardo_no_usb -leonardoExtended.menu.usbcore.NO_USB.build.pid=0x8036 - -############################################################## - -microExtended.name=Arduino Micro HID-Project -microExtended.upload.tool=arduino:avrdude -microExtended.upload.protocol=avr109 -microExtended.upload.maximum_size=28672 -microExtended.upload.maximum_data_size=2560 -microExtended.upload.speed=57600 -microExtended.upload.disable_flushing=true -microExtended.upload.use_1200bps_touch=true -microExtended.upload.wait_for_upload_port=true - -microExtended.bootloader.tool=arduino:avrdude -microExtended.bootloader.low_fuses=0xff -microExtended.bootloader.high_fuses=0xd8 -microExtended.bootloader.extended_fuses=0xcb -microExtended.bootloader.file=arduino:caterina/Caterina-Micro.hex -microExtended.bootloader.unlock_bits=0x3F -microExtended.bootloader.lock_bits=0x2F - -microExtended.build.mcu=atmega32u4 -microExtended.build.f_cpu=16000000L -microExtended.build.core=HID:hid -microExtended.build.vid=0x2341 -#microExtended.build.pid=0x8037 -microExtended.build.usb_product="Arduino Micro" -microExtended.build.board=AVR_MICRO -microExtended.build.extra_flags={build.usb_flags} - -#USB core selection -#HID Project needs to be installed https://github.com/NicoHood/HID -microExtended.menu.usbcore.hid=Serial + Extended HID -microExtended.menu.usbcore.hid.build.variant=micro_hid -microExtended.menu.usbcore.hid.build.pid=0x8037 -microExtended.menu.usbcore.gamepad=Serial + Gamepad HID -microExtended.menu.usbcore.gamepad.build.variant=micro_gamepad -microExtended.menu.usbcore.gamepad.build.pid=0x8037 -microExtended.menu.usbcore.custom=Serial + Custom HID -microExtended.menu.usbcore.custom.build.variant=micro_custom -microExtended.menu.usbcore.custom.build.pid=0x8037 -microExtended.menu.usbcore.USB_CORE=Default Core -microExtended.menu.usbcore.USB_CORE.build.variant=micro -microExtended.menu.usbcore.USB_CORE.build.pid=0x8037 -microExtended.menu.usbcore.NO_USB=No USB functions -microExtended.menu.usbcore.NO_USB.build.variant=micro_no_usb -microExtended.menu.usbcore.NO_USB.build.pid=0x8037 - diff --git a/plugins/KeyboardioHID/avr/cores/hid/Arduino.h b/plugins/KeyboardioHID/avr/cores/hid/Arduino.h deleted file mode 100644 index df7990a503..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/Arduino.h +++ /dev/null @@ -1,273 +0,0 @@ -/* - Arduino.h - Main include file for the Arduino SDK - Copyright (c) 2005-2013 Arduino Team. 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 -*/ - -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. -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 Arduino_h -#define Arduino_h - -#include -#include -#include -#include - -#include -#include -#include - -#include "binary.h" - -#ifdef __cplusplus -extern "C"{ -#endif - -void yield(void); - -#define HIGH 0x1 -#define LOW 0x0 - -#define INPUT 0x0 -#define OUTPUT 0x1 -#define INPUT_PULLUP 0x2 - -#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 EULER 2.718281828459045235360287471352 - -#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_ATmega1284__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644A__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__) -#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)) - -// avr-libc defines _NOP() since 1.6.2 -#ifndef _NOP -#define _NOP() do { __asm__ volatile ("nop"); } while (0) -#endif - -typedef unsigned int word; - -#define bit(b) (1UL << (b)) - -typedef bool boolean; -typedef uint8_t byte; - -void init(void); -void initVariant(void); - -int atexit(void (*func)()) __attribute__((weak)); - -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 - -#define NOT_AN_INTERRUPT -1 - -#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 TIMER1C 5 -#define TIMER2 6 -#define TIMER2A 7 -#define TIMER2B 8 - -#define TIMER3A 9 -#define TIMER3B 10 -#define TIMER3C 11 -#define TIMER4A 12 -#define TIMER4B 13 -#define TIMER4C 14 -#define TIMER4D 15 -#define TIMER5A 16 -#define TIMER5B 17 -#define TIMER5C 18 - -#ifdef __cplusplus -} // extern "C" -#endif - -#ifdef __cplusplus -#include "WCharacter.h" -#include "WString.h" -#include "HardwareSerial.h" -#include "USB-Core/USBAPI.h" -#include "USB-Core/CDC.h" -#include "USB-Core/HID.h" -#include "USB-Core/HIDTables.h" - -#if defined(HAVE_HWSERIAL0) && defined(HAVE_CDCSERIAL) -#error "Targets with both UART0 and CDC serial not supported" -#endif - -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/plugins/KeyboardioHID/avr/cores/hid/Client.h b/plugins/KeyboardioHID/avr/cores/hid/Client.h deleted file mode 100644 index b8e5d935f2..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/Client.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - Client.h - Base class that provides Client - 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 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/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.cpp b/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.cpp deleted file mode 100644 index 41935e3205..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.cpp +++ /dev/null @@ -1,252 +0,0 @@ -/* - 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 - Modified 14 August 2012 by Alarus - Modified 3 December 2013 by Matthijs Kooijman -*/ - -#include -#include -#include -#include -#include "Arduino.h" - -#include "HardwareSerial.h" -#include "HardwareSerial_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(HAVE_HWSERIAL0) || defined(HAVE_HWSERIAL1) || defined(HAVE_HWSERIAL2) || defined(HAVE_HWSERIAL3) - -// SerialEvent functions are weak, so when the user doesn't define them, -// the linker just sets their address to 0 (which is checked below). -// The Serialx_available is just a wrapper around Serialx.available(), -// but we can refer to it weakly so we don't pull in the entire -// HardwareSerial instance if the user doesn't also refer to it. -#if defined(HAVE_HWSERIAL0) - void serialEvent() __attribute__((weak)); - bool Serial0_available() __attribute__((weak)); -#endif - -#if defined(HAVE_HWSERIAL1) - void serialEvent1() __attribute__((weak)); - bool Serial1_available() __attribute__((weak)); -#endif - -#if defined(HAVE_HWSERIAL2) - void serialEvent2() __attribute__((weak)); - bool Serial2_available() __attribute__((weak)); -#endif - -#if defined(HAVE_HWSERIAL3) - void serialEvent3() __attribute__((weak)); - bool Serial3_available() __attribute__((weak)); -#endif - -void serialEventRun(void) -{ -#if defined(HAVE_HWSERIAL0) - if (Serial0_available && serialEvent && Serial0_available()) serialEvent(); -#endif -#if defined(HAVE_HWSERIAL1) - if (Serial1_available && serialEvent1 && Serial1_available()) serialEvent1(); -#endif -#if defined(HAVE_HWSERIAL2) - if (Serial2_available && serialEvent2 && Serial2_available()) serialEvent2(); -#endif -#if defined(HAVE_HWSERIAL3) - if (Serial3_available && serialEvent3 && Serial3_available()) serialEvent3(); -#endif -} - -// Actual interrupt handlers ////////////////////////////////////////////////////////////// - -void HardwareSerial::_tx_udr_empty_irq(void) -{ - // If interrupts are enabled, there must be more data in the output - // buffer. Send the next byte - unsigned char c = _tx_buffer[_tx_buffer_tail]; - _tx_buffer_tail = (_tx_buffer_tail + 1) % SERIAL_TX_BUFFER_SIZE; - - *_udr = c; - - // clear the TXC bit -- "can be cleared by writing a one to its bit - // location". This makes sure flush() won't return until the bytes - // actually got written - sbi(*_ucsra, TXC0); - - if (_tx_buffer_head == _tx_buffer_tail) { - // Buffer empty, so disable interrupts - cbi(*_ucsrb, UDRIE0); - } -} - -// Public Methods ////////////////////////////////////////////////////////////// - -void HardwareSerial::begin(unsigned long baud, byte config) -{ - // Try u2x mode first - uint16_t baud_setting = (F_CPU / 4 / baud - 1) / 2; - *_ucsra = 1 << U2X0; - - // hardcoded exception for 57600 for compatibility with the bootloader - // shipped with the Duemilanove and previous boards and the firmware - // on the 8U2 on the Uno and Mega 2560. Also, The baud_setting cannot - // be > 4095, so switch back to non-u2x mode if the baud rate is too - // low. - if (((F_CPU == 16000000UL) && (baud == 57600)) || (baud_setting >4095)) - { - *_ucsra = 0; - baud_setting = (F_CPU / 8 / baud - 1) / 2; - } - - // assign the baud_setting, a.k.a. ubrr (USART Baud Rate Register) - *_ubrrh = baud_setting >> 8; - *_ubrrl = baud_setting; - - _written = false; - - //set the data bits, parity, and stop bits -#if defined(__AVR_ATmega8__) - config |= 0x80; // select UCSRC register (shared with UBRRH) -#endif - *_ucsrc = config; - - sbi(*_ucsrb, RXEN0); - sbi(*_ucsrb, TXEN0); - sbi(*_ucsrb, RXCIE0); - cbi(*_ucsrb, UDRIE0); -} - -void HardwareSerial::end() -{ - // wait for transmission of outgoing data - while (_tx_buffer_head != _tx_buffer_tail) - ; - - cbi(*_ucsrb, RXEN0); - cbi(*_ucsrb, TXEN0); - cbi(*_ucsrb, RXCIE0); - cbi(*_ucsrb, UDRIE0); - - // clear any received data - _rx_buffer_head = _rx_buffer_tail; -} - -int HardwareSerial::available(void) -{ - return ((unsigned int)(SERIAL_RX_BUFFER_SIZE + _rx_buffer_head - _rx_buffer_tail)) % SERIAL_RX_BUFFER_SIZE; -} - -int HardwareSerial::peek(void) -{ - if (_rx_buffer_head == _rx_buffer_tail) { - return -1; - } else { - return _rx_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[_rx_buffer_tail]; - _rx_buffer_tail = (rx_buffer_index_t)(_rx_buffer_tail + 1) % SERIAL_RX_BUFFER_SIZE; - return c; - } -} - -int HardwareSerial::availableForWrite(void) -{ -#if (SERIAL_TX_BUFFER_SIZE>256) - uint8_t oldSREG = SREG; - cli(); -#endif - tx_buffer_index_t head = _tx_buffer_head; - tx_buffer_index_t tail = _tx_buffer_tail; -#if (SERIAL_TX_BUFFER_SIZE>256) - SREG = oldSREG; -#endif - if (head >= tail) return SERIAL_TX_BUFFER_SIZE - 1 - head + tail; - return tail - head - 1; -} - -void HardwareSerial::flush() -{ - // If we have never written a byte, no need to flush. This special - // case is needed since there is no way to force the TXC (transmit - // complete) bit to 1 during initialization - if (!_written) - return; - - while (bit_is_set(*_ucsrb, UDRIE0) || bit_is_clear(*_ucsra, TXC0)) { - if (bit_is_clear(SREG, SREG_I) && bit_is_set(*_ucsrb, UDRIE0)) - // Interrupts are globally disabled, but the DR empty - // interrupt should be enabled, so poll the DR empty flag to - // prevent deadlock - if (bit_is_set(*_ucsra, UDRE0)) - _tx_udr_empty_irq(); - } - // If we get here, nothing is queued anymore (DRIE is disabled) and - // the hardware finished tranmission (TXC is set). -} - -size_t HardwareSerial::write(uint8_t c) -{ - // If the buffer and the data register is empty, just write the byte - // to the data register and be done. This shortcut helps - // significantly improve the effective datarate at high (> - // 500kbit/s) bitrates, where interrupt overhead becomes a slowdown. - if (_tx_buffer_head == _tx_buffer_tail && bit_is_set(*_ucsra, UDRE0)) { - *_udr = c; - sbi(*_ucsra, TXC0); - return 1; - } - tx_buffer_index_t i = (_tx_buffer_head + 1) % SERIAL_TX_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 - while (i == _tx_buffer_tail) { - if (bit_is_clear(SREG, SREG_I)) { - // Interrupts are disabled, so we'll have to poll the data - // register empty flag ourselves. If it is set, pretend an - // interrupt has happened and call the handler to free up - // space for us. - if(bit_is_set(*_ucsra, UDRE0)) - _tx_udr_empty_irq(); - } else { - // nop, the interrupt handler will free up space for us - } - } - - _tx_buffer[_tx_buffer_head] = c; - _tx_buffer_head = i; - - sbi(*_ucsrb, UDRIE0); - _written = true; - - return 1; -} - - -#endif // whole file diff --git a/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.h b/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.h deleted file mode 100644 index 7f4f162d68..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial.h +++ /dev/null @@ -1,156 +0,0 @@ -/* - 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 - Modified 14 August 2012 by Alarus - Modified 3 December 2013 by Matthijs Kooijman -*/ - -#ifndef HardwareSerial_h -#define HardwareSerial_h - -#include - -#include "Stream.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. -// NOTE: a "power of 2" buffer size is reccomended to dramatically -// optimize all the modulo operations for ring buffers. -#if !defined(SERIAL_TX_BUFFER_SIZE) -#if (RAMEND < 1000) -#define SERIAL_TX_BUFFER_SIZE 16 -#else -#define SERIAL_TX_BUFFER_SIZE 64 -#endif -#endif -#if !defined(SERIAL_RX_BUFFER_SIZE) -#if (RAMEND < 1000) -#define SERIAL_RX_BUFFER_SIZE 16 -#else -#define SERIAL_RX_BUFFER_SIZE 64 -#endif -#endif -#if (SERIAL_TX_BUFFER_SIZE>256) -typedef uint16_t tx_buffer_index_t; -#else -typedef uint8_t tx_buffer_index_t; -#endif -#if (SERIAL_RX_BUFFER_SIZE>256) -typedef uint16_t rx_buffer_index_t; -#else -typedef uint8_t rx_buffer_index_t; -#endif - -// Define config for Serial.begin(baud, config); -#define SERIAL_5N1 0x00 -#define SERIAL_6N1 0x02 -#define SERIAL_7N1 0x04 -#define SERIAL_8N1 0x06 -#define SERIAL_5N2 0x08 -#define SERIAL_6N2 0x0A -#define SERIAL_7N2 0x0C -#define SERIAL_8N2 0x0E -#define SERIAL_5E1 0x20 -#define SERIAL_6E1 0x22 -#define SERIAL_7E1 0x24 -#define SERIAL_8E1 0x26 -#define SERIAL_5E2 0x28 -#define SERIAL_6E2 0x2A -#define SERIAL_7E2 0x2C -#define SERIAL_8E2 0x2E -#define SERIAL_5O1 0x30 -#define SERIAL_6O1 0x32 -#define SERIAL_7O1 0x34 -#define SERIAL_8O1 0x36 -#define SERIAL_5O2 0x38 -#define SERIAL_6O2 0x3A -#define SERIAL_7O2 0x3C -#define SERIAL_8O2 0x3E - -class HardwareSerial : public Stream -{ - protected: - volatile uint8_t * const _ubrrh; - volatile uint8_t * const _ubrrl; - volatile uint8_t * const _ucsra; - volatile uint8_t * const _ucsrb; - volatile uint8_t * const _ucsrc; - volatile uint8_t * const _udr; - // Has any byte been written to the UART since begin() - bool _written; - - volatile rx_buffer_index_t _rx_buffer_head; - volatile rx_buffer_index_t _rx_buffer_tail; - volatile tx_buffer_index_t _tx_buffer_head; - volatile tx_buffer_index_t _tx_buffer_tail; - - // Don't put any members after these buffers, since only the first - // 32 bytes of this struct can be accessed quickly using the ldd - // instruction. - unsigned char _rx_buffer[SERIAL_RX_BUFFER_SIZE]; - unsigned char _tx_buffer[SERIAL_TX_BUFFER_SIZE]; - - public: - inline HardwareSerial( - volatile uint8_t *ubrrh, volatile uint8_t *ubrrl, - volatile uint8_t *ucsra, volatile uint8_t *ucsrb, - volatile uint8_t *ucsrc, volatile uint8_t *udr); - void begin(unsigned long baud) { begin(baud, SERIAL_8N1); } - void begin(unsigned long, uint8_t); - void end(); - virtual int available(void); - virtual int peek(void); - virtual int read(void); - int availableForWrite(void); - virtual void flush(void); - virtual size_t write(uint8_t); - inline size_t write(unsigned long n) { return write((uint8_t)n); } - inline size_t write(long n) { return write((uint8_t)n); } - inline size_t write(unsigned int n) { return write((uint8_t)n); } - inline size_t write(int n) { return write((uint8_t)n); } - using Print::write; // pull in write(str) and write(buf, size) from Print - operator bool() { return true; } - - // Interrupt handlers - Not intended to be called externally - inline void _rx_complete_irq(void); - void _tx_udr_empty_irq(void); -}; - -#if defined(UBRRH) || defined(UBRR0H) - extern HardwareSerial Serial; - #define HAVE_HWSERIAL0 -#endif -#if defined(UBRR1H) - extern HardwareSerial Serial1; - #define HAVE_HWSERIAL1 -#endif -#if defined(UBRR2H) - extern HardwareSerial Serial2; - #define HAVE_HWSERIAL2 -#endif -#if defined(UBRR3H) - extern HardwareSerial Serial3; - #define HAVE_HWSERIAL3 -#endif - -extern void serialEventRun(void) __attribute__((weak)); - -#endif diff --git a/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial0.cpp b/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial0.cpp deleted file mode 100644 index 1146eebab6..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial0.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - HardwareSerial0.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 - Modified 14 August 2012 by Alarus - Modified 3 December 2013 by Matthijs Kooijman -*/ - -#include "Arduino.h" -#include "HardwareSerial.h" -#include "HardwareSerial_private.h" - -// Each HardwareSerial is defined in its own file, sine the linker pulls -// in the entire file when any element inside is used. --gc-sections can -// additionally cause unused symbols to be dropped, but ISRs have the -// "used" attribute so are never dropped and they keep the -// HardwareSerial instance in as well. Putting each instance in its own -// file prevents the linker from pulling in any unused instances in the -// first place. - -#if defined(HAVE_HWSERIAL0) - -#if defined(USART_RX_vect) - ISR(USART_RX_vect) -#elif defined(USART0_RX_vect) - ISR(USART0_RX_vect) -#elif defined(USART_RXC_vect) - ISR(USART_RXC_vect) // ATmega8 -#else - #error "Don't know what the Data Received vector is called for Serial" -#endif - { - Serial._rx_complete_irq(); - } - -#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) -#else - #error "Don't know what the Data Register Empty vector is called for Serial" -#endif -{ - Serial._tx_udr_empty_irq(); -} - -#if defined(UBRRH) && defined(UBRRL) - HardwareSerial Serial(&UBRRH, &UBRRL, &UCSRA, &UCSRB, &UCSRC, &UDR); -#else - HardwareSerial Serial(&UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UCSR0C, &UDR0); -#endif - -// Function that can be weakly referenced by serialEventRun to prevent -// pulling in this file if it's not otherwise used. -bool Serial0_available() { - return Serial.available(); -} - -#endif // HAVE_HWSERIAL0 diff --git a/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial1.cpp b/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial1.cpp deleted file mode 100644 index 19625e235d..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial1.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - HardwareSerial1.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 - Modified 14 August 2012 by Alarus - Modified 3 December 2013 by Matthijs Kooijman -*/ - -#include "Arduino.h" -#include "HardwareSerial.h" -#include "HardwareSerial_private.h" - -// Each HardwareSerial is defined in its own file, sine the linker pulls -// in the entire file when any element inside is used. --gc-sections can -// additionally cause unused symbols to be dropped, but ISRs have the -// "used" attribute so are never dropped and they keep the -// HardwareSerial instance in as well. Putting each instance in its own -// file prevents the linker from pulling in any unused instances in the -// first place. - -#if defined(HAVE_HWSERIAL1) - -#if defined(UART1_RX_vect) -ISR(UART1_RX_vect) -#elif defined(USART1_RX_vect) -ISR(USART1_RX_vect) -#else -#error "Don't know what the Data Register Empty vector is called for Serial1" -#endif -{ - Serial1._rx_complete_irq(); -} - -#if defined(UART1_UDRE_vect) -ISR(UART1_UDRE_vect) -#elif defined(USART1_UDRE_vect) -ISR(USART1_UDRE_vect) -#else -#error "Don't know what the Data Register Empty vector is called for Serial1" -#endif -{ - Serial1._tx_udr_empty_irq(); -} - -HardwareSerial Serial1(&UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UCSR1C, &UDR1); - -// Function that can be weakly referenced by serialEventRun to prevent -// pulling in this file if it's not otherwise used. -bool Serial1_available() { - return Serial1.available(); -} - -#endif // HAVE_HWSERIAL1 diff --git a/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial2.cpp b/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial2.cpp deleted file mode 100644 index fd334ae15b..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial2.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* - HardwareSerial2.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 - Modified 14 August 2012 by Alarus - Modified 3 December 2013 by Matthijs Kooijman -*/ - -#include "Arduino.h" -#include "HardwareSerial.h" -#include "HardwareSerial_private.h" - -// Each HardwareSerial is defined in its own file, sine the linker pulls -// in the entire file when any element inside is used. --gc-sections can -// additionally cause unused symbols to be dropped, but ISRs have the -// "used" attribute so are never dropped and they keep the -// HardwareSerial instance in as well. Putting each instance in its own -// file prevents the linker from pulling in any unused instances in the -// first place. - -#if defined(HAVE_HWSERIAL2) - -ISR(USART2_RX_vect) -{ - Serial2._rx_complete_irq(); -} - -ISR(USART2_UDRE_vect) -{ - Serial2._tx_udr_empty_irq(); -} - -HardwareSerial Serial2(&UBRR2H, &UBRR2L, &UCSR2A, &UCSR2B, &UCSR2C, &UDR2); - -// Function that can be weakly referenced by serialEventRun to prevent -// pulling in this file if it's not otherwise used. -bool Serial2_available() { - return Serial2.available(); -} - -#endif // HAVE_HWSERIAL2 diff --git a/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial3.cpp b/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial3.cpp deleted file mode 100644 index a68095b37c..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial3.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* - HardwareSerial3.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 - Modified 14 August 2012 by Alarus - Modified 3 December 2013 by Matthijs Kooijman -*/ - -#include "Arduino.h" -#include "HardwareSerial.h" -#include "HardwareSerial_private.h" - -// Each HardwareSerial is defined in its own file, sine the linker pulls -// in the entire file when any element inside is used. --gc-sections can -// additionally cause unused symbols to be dropped, but ISRs have the -// "used" attribute so are never dropped and they keep the -// HardwareSerial instance in as well. Putting each instance in its own -// file prevents the linker from pulling in any unused instances in the -// first place. - -#if defined(HAVE_HWSERIAL3) - -ISR(USART3_RX_vect) -{ - Serial3._rx_complete_irq(); -} - -ISR(USART3_UDRE_vect) -{ - Serial3._tx_udr_empty_irq(); -} - -HardwareSerial Serial3(&UBRR3H, &UBRR3L, &UCSR3A, &UCSR3B, &UCSR3C, &UDR3); - -// Function that can be weakly referenced by serialEventRun to prevent -// pulling in this file if it's not otherwise used. -bool Serial3_available() { - return Serial3.available(); -} - -#endif // HAVE_HWSERIAL3 diff --git a/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial_private.h b/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial_private.h deleted file mode 100644 index 761a5e559c..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/HardwareSerial_private.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - HardwareSerial_private.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 23 November 2006 by David A. Mellis - Modified 28 September 2010 by Mark Sproul - Modified 14 August 2012 by Alarus -*/ - -#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(HAVE_HWSERIAL0) || defined(HAVE_HWSERIAL1) || defined(HAVE_HWSERIAL2) || defined(HAVE_HWSERIAL3) - -// Ensure that the various bit positions we use are available with a 0 -// postfix, so we can always use the values for UART0 for all UARTs. The -// alternative, passing the various values for each UART to the -// HardwareSerial constructor also works, but makes the code bigger and -// slower. -#if !defined(TXC0) -#if defined(TXC) -// Some chips like ATmega8 don't have UPE, only PE. The other bits are -// named as expected. -#if !defined(UPE) && defined(PE) -#define UPE PE -#endif -// On ATmega8, the uart and its bits are not numbered, so there is no TXC0 etc. -#define TXC0 TXC -#define RXEN0 RXEN -#define TXEN0 TXEN -#define RXCIE0 RXCIE -#define UDRIE0 UDRIE -#define U2X0 U2X -#define UPE0 UPE -#define UDRE0 UDRE -#elif defined(TXC1) -// Some devices have uart1 but no uart0 -#define TXC0 TXC1 -#define RXEN0 RXEN1 -#define TXEN0 TXEN1 -#define RXCIE0 RXCIE1 -#define UDRIE0 UDRIE1 -#define U2X0 U2X1 -#define UPE0 UPE1 -#define UDRE0 UDRE1 -#else -#error No UART found in HardwareSerial.cpp -#endif -#endif // !defined TXC0 - -// Check at compiletime that it is really ok to use the bit positions of -// UART0 for the other UARTs as well, in case these values ever get -// changed for future hardware. -#if defined(TXC1) && (TXC1 != TXC0 || RXEN1 != RXEN0 || RXCIE1 != RXCIE0 || \ - UDRIE1 != UDRIE0 || U2X1 != U2X0 || UPE1 != UPE0 || \ - UDRE1 != UDRE0) -#error "Not all bit positions for UART1 are the same as for UART0" -#endif -#if defined(TXC2) && (TXC2 != TXC0 || RXEN2 != RXEN0 || RXCIE2 != RXCIE0 || \ - UDRIE2 != UDRIE0 || U2X2 != U2X0 || UPE2 != UPE0 || \ - UDRE2 != UDRE0) -#error "Not all bit positions for UART2 are the same as for UART0" -#endif -#if defined(TXC3) && (TXC3 != TXC0 || RXEN3 != RXEN0 || RXCIE3 != RXCIE0 || \ - UDRIE3 != UDRIE0 || U3X3 != U3X0 || UPE3 != UPE0 || \ - UDRE3 != UDRE0) -#error "Not all bit positions for UART3 are the same as for UART0" -#endif - -// Constructors //////////////////////////////////////////////////////////////// - -HardwareSerial::HardwareSerial( - volatile uint8_t *ubrrh, volatile uint8_t *ubrrl, - volatile uint8_t *ucsra, volatile uint8_t *ucsrb, - volatile uint8_t *ucsrc, volatile uint8_t *udr) : - _ubrrh(ubrrh), _ubrrl(ubrrl), - _ucsra(ucsra), _ucsrb(ucsrb), _ucsrc(ucsrc), - _udr(udr), - _rx_buffer_head(0), _rx_buffer_tail(0), - _tx_buffer_head(0), _tx_buffer_tail(0) -{ -} - -// Actual interrupt handlers ////////////////////////////////////////////////////////////// - -void HardwareSerial::_rx_complete_irq(void) -{ - if (bit_is_clear(*_ucsra, UPE0)) { - // No Parity error, read byte and store it in the buffer if there is - // room - unsigned char c = *_udr; - rx_buffer_index_t i = (unsigned int)(_rx_buffer_head + 1) % SERIAL_RX_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 != _rx_buffer_tail) { - _rx_buffer[_rx_buffer_head] = c; - _rx_buffer_head = i; - } - } else { - // Parity error, read byte but discard it - *_udr; - }; -} - -#endif // whole file diff --git a/plugins/KeyboardioHID/avr/cores/hid/IPAddress.cpp b/plugins/KeyboardioHID/avr/cores/hid/IPAddress.cpp deleted file mode 100644 index 899cbd4eda..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/IPAddress.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/* - IPAddress.cpp - Base class that provides IPAddress - 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 -*/ - -#include -#include - -IPAddress::IPAddress() -{ - _address.dword = 0; -} - -IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet) -{ - _address.bytes[0] = first_octet; - _address.bytes[1] = second_octet; - _address.bytes[2] = third_octet; - _address.bytes[3] = fourth_octet; -} - -IPAddress::IPAddress(uint32_t address) -{ - _address.dword = address; -} - -IPAddress::IPAddress(const uint8_t *address) -{ - memcpy(_address.bytes, address, sizeof(_address.bytes)); -} - -IPAddress& IPAddress::operator=(const uint8_t *address) -{ - memcpy(_address.bytes, address, sizeof(_address.bytes)); - return *this; -} - -IPAddress& IPAddress::operator=(uint32_t address) -{ - _address.dword = address; - return *this; -} - -bool IPAddress::operator==(const uint8_t* addr) const -{ - return memcmp(addr, _address.bytes, sizeof(_address.bytes)) == 0; -} - -size_t IPAddress::printTo(Print& p) const -{ - size_t n = 0; - for (int i =0; i < 3; i++) - { - n += p.print(_address.bytes[i], DEC); - n += p.print('.'); - } - n += p.print(_address.bytes[3], DEC); - return n; -} - diff --git a/plugins/KeyboardioHID/avr/cores/hid/IPAddress.h b/plugins/KeyboardioHID/avr/cores/hid/IPAddress.h deleted file mode 100644 index 94acdc4566..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/IPAddress.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - IPAddress.h - Base class that provides IPAddress - 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 IPAddress_h -#define IPAddress_h - -#include -#include - -// A class to make it easier to handle and pass around IP addresses - -class IPAddress : public Printable { -private: - union { - uint8_t bytes[4]; // IPv4 address - uint32_t dword; - } _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.bytes; }; - -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() const { return _address.dword; }; - bool operator==(const IPAddress& addr) const { return _address.dword == addr._address.dword; }; - bool operator==(const uint8_t* addr) const; - - // Overloaded index operator to allow getting and setting individual octets of the address - uint8_t operator[](int index) const { return _address.bytes[index]; }; - uint8_t& operator[](int index) { return _address.bytes[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/plugins/KeyboardioHID/avr/cores/hid/Print.cpp b/plugins/KeyboardioHID/avr/cores/hid/Print.cpp deleted file mode 100644 index 5df56306e9..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/Print.cpp +++ /dev/null @@ -1,264 +0,0 @@ -/* - 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 -#include -#include -#include -#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) -{ - PGM_P p = reinterpret_cast(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) -{ - return write(s.c_str(), s.length()); -} - -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; - - if (isnan(number)) return print("nan"); - if (isinf(number)) return print("inf"); - if (number > 4294967040.0) return print ("ovf"); // constant determined empirically - if (number <-4294967040.0) return print ("ovf"); // constant determined empirically - - // 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 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/plugins/KeyboardioHID/avr/cores/hid/Print.h b/plugins/KeyboardioHID/avr/cores/hid/Print.h deleted file mode 100644 index 7b53aa4d17..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/Print.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - 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 -#include // 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) { - if (str == NULL) return 0; - return write((const uint8_t *)str, strlen(str)); - } - virtual size_t write(const uint8_t *buffer, size_t size); - size_t write(const char *buffer, size_t size) { - return write((const uint8_t *)buffer, 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/plugins/KeyboardioHID/avr/cores/hid/Printable.h b/plugins/KeyboardioHID/avr/cores/hid/Printable.h deleted file mode 100644 index 2a1b2e9f2c..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/Printable.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - 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 - -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/plugins/KeyboardioHID/avr/cores/hid/Server.h b/plugins/KeyboardioHID/avr/cores/hid/Server.h deleted file mode 100644 index 69e3e39fe6..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/Server.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - Server.h - Base class that provides Server - 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 server_h -#define server_h - -#include "Print.h" - -class Server : public Print { -public: - virtual void begin() =0; -}; - -#endif diff --git a/plugins/KeyboardioHID/avr/cores/hid/Stream.cpp b/plugins/KeyboardioHID/avr/cores/hid/Stream.cpp deleted file mode 100644 index b31942f293..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/Stream.cpp +++ /dev/null @@ -1,317 +0,0 @@ -/* - 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 - - findMulti/findUntil routines written by Jim Leonard/Xuth - */ - -#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, strlen(target), NULL, 0); -} - -// 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) -{ - if (terminator == NULL) { - MultiTarget t[1] = {{target, targetLen, 0}}; - return findMulti(t, 1) == 0 ? true : false; - } else { - MultiTarget t[2] = {{target, targetLen, 0}, {terminator, termLen, 0}}; - return findMulti(t, 2) == 0 ? true : 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) -{ - bool 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){ - bool isNegative = false; - bool 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; -} - -int Stream::findMulti( struct Stream::MultiTarget *targets, int tCount) { - // any zero length target string automatically matches and would make - // a mess of the rest of the algorithm. - for (struct MultiTarget *t = targets; t < targets+tCount; ++t) { - if (t->len <= 0) - return t - targets; - } - - while (1) { - int c = timedRead(); - if (c < 0) - return -1; - - for (struct MultiTarget *t = targets; t < targets+tCount; ++t) { - // the simple case is if we match, deal with that first. - if (c == t->str[t->index]) { - if (++t->index == t->len) - return t - targets; - else - continue; - } - - // if not we need to walk back and see if we could have matched further - // down the stream (ie '1112' doesn't match the first position in '11112' - // but it will match the second position so we can't just reset the current - // index to 0 when we find a mismatch. - if (t->index == 0) - continue; - - int origIndex = t->index; - do { - --t->index; - // first check if current char works against the new current index - if (c != t->str[t->index]) - continue; - - // if it's the only char then we're good, nothing more to check - if (t->index == 0) { - t->index++; - break; - } - - // otherwise we need to check the rest of the found string - int diff = origIndex - t->index; - size_t i; - for (i = 0; i < t->index; ++i) { - if (t->str[i] != t->str[i + diff]) - break; - } - - // if we successfully got through the previous loop then our current - // index is good. - if (i == t->index) { - t->index++; - break; - } - - // otherwise we just try the next index - } while (t->index); - } - } - // unreachable - return -1; -} diff --git a/plugins/KeyboardioHID/avr/cores/hid/Stream.h b/plugins/KeyboardioHID/avr/cores/hid/Stream.h deleted file mode 100644 index a8101320c9..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/Stream.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - 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 -#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 -{ - protected: - 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 - bool find(uint8_t *target) { return find ((char *)target); } - // 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 - bool find(uint8_t *target, size_t length) { return find ((char *)target, length); } - // 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(uint8_t *target, char *terminator) { return findUntil((char *)target, terminator); } - - bool findUntil(char *target, size_t targetLen, char *terminate, size_t termLen); // as above but search ends if the terminate string is found - bool findUntil(uint8_t *target, size_t targetLen, char *terminate, size_t termLen) {return findUntil((char *)target, targetLen, terminate, termLen); } - - - 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 - size_t readBytes( uint8_t *buffer, size_t length) { return readBytes((char *)buffer, length); } - // 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 - size_t readBytesUntil( char terminator, uint8_t *buffer, size_t length) { return readBytesUntil(terminator, (char *)buffer, length); } - // 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 - - struct MultiTarget { - const char *str; // string you're searching for - size_t len; // length of string you're searching for - size_t index; // index used by the search routine. - }; - - // This allows you to search for an arbitrary number of strings. - // Returns index of the target that is found first or -1 if timeout occurs. - int findMulti(struct MultiTarget *targets, int tCount); -}; - - -#endif diff --git a/plugins/KeyboardioHID/avr/cores/hid/Tone.cpp b/plugins/KeyboardioHID/avr/cores/hid/Tone.cpp deleted file mode 100644 index 7216219750..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/Tone.cpp +++ /dev/null @@ -1,618 +0,0 @@ -/* 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 -0008 S Kanemoto 12/06/22 Fixed for Leonardo by @maris_HY -0009 J Reucker 15/04/10 Issue #292 Fixed problems with ATmega8 (thanks to Pete62) -0010 jipp 15/04/13 added additional define check #2923 -*************************************************/ - -#include -#include -#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 - - -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) - -#define AVAILABLE_TONE_PINS 1 -#define USE_TIMER2 - -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 -#define USE_TIMER2 - -const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 1 */ }; -static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255 */ }; - -#elif defined(__AVR_ATmega32U4__) - -#define AVAILABLE_TONE_PINS 1 -#define USE_TIMER3 - -const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 3 /*, 1 */ }; -static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255 */ }; - -#else - -#define AVAILABLE_TONE_PINS 1 -#define USE_TIMER2 - -// 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) && defined(WGM01) - 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 = (TCCR0B & 0b11111000) | prescalarbits; - } - else -#endif -#if defined(TCCR2B) - { - TCCR2B = (TCCR2B & 0b11111000) | 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(OCR3A) && defined(TIMSK3) && defined(OCIE3A) - case 3: - OCR3A = ocr; - timer3_toggle_count = toggle_count; - bitWrite(TIMSK3, OCIE3A, 1); - break; -#endif - -#if defined(OCR4A) && defined(TIMSK4) && defined(OCIE4A) - 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) && defined(OCIE3A) - case 3: - bitWrite(TIMSK3, OCIE3A, 0); - break; -#endif - -#if defined(TIMSK4) && defined(OCIE4A) - case 4: - bitWrite(TIMSK4, OCIE4A, 0); - break; -#endif - -#if defined(TIMSK5) && defined(OCIE5A) - case 5: - bitWrite(TIMSK5, OCIE5A, 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); -} - -#ifdef USE_TIMER0 -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 - - -#ifdef USE_TIMER1 -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 - - -#ifdef USE_TIMER2 -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 - } -} -#endif - - -#ifdef USE_TIMER3 -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 - } -} -#endif - - -#ifdef USE_TIMER4 -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 - } -} -#endif - - -#ifdef USE_TIMER5 -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/plugins/KeyboardioHID/avr/cores/hid/USB-Core/CDC.cpp b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/CDC.cpp deleted file mode 100644 index e846f0b8f2..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/CDC.cpp +++ /dev/null @@ -1,304 +0,0 @@ -/* 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. -*/ - -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -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 "CDC.h" -#include - -#if defined(USBCON) -#ifdef CDC_ENABLED - -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), - // edit by NicoHood - D_ENDPOINT(USB_ENDPOINT_OUT(CDC_ENDPOINT_OUT), USB_ENDPOINT_TYPE_BULK, USB_EP_SIZE, 0), - D_ENDPOINT(USB_ENDPOINT_IN(CDC_ENDPOINT_IN), USB_ENDPOINT_TYPE_BULK, USB_EP_SIZE, 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); - CDC_LineEncodingEvent(); - } - - if (CDC_SET_CONTROL_LINE_STATE == r) - { - _usbLineInfo.lineState = setup.wValueL; - CDC_LineStateEvent(); - } - - if (CDC_SET_LINE_CODING == r || CDC_SET_CONTROL_LINE_STATE == r) - { - // 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 - - // We check DTR state to determine if host port is open (bit 0 of lineState). - if (1200 == _usbLineInfo.dwDTERate && (_usbLineInfo.lineState & 0x01) == 0) - { - // edit by NicoHood - // change ram pointer to fit the 16u2's ram size and only use an 8bit value -#if defined(__AVR_ATmega32U4__) - *(uint16_t *)0x0800 = 0x7777; - wdt_enable(WDTO_120MS); -#else - // workaround for this issue: - // https://github.com/arduino/Arduino/issues/2474 - // I didn't change this for the 32u4 to simply not touch their code - // the correct way would be to add a compiler flag like this: - // -Wl,--section-start=.blkey=0x280 - //volatile uint8_t MagicBootKey __attribute__((section(".blkey"))); - cli(); - - //MagicBootKey = 0x77; - *(uint8_t *)0x0280 = 0x77; - - wdt_enable(WDTO_120MS); - - // wait for reset - for (;;); -#endif - } - 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. - - // edit by NicoHood -#if defined(__AVR_ATmega32U4__) - wdt_disable(); - wdt_reset(); - *(uint16_t *)0x0800 = 0x0; -#else - // not used because of the workaround above - //wdt_disable(); - //wdt_reset(); - //MagicBootKey = 0x00; - //*(uint8_t *)0x0280 = 0x00; -#endif - } - } - return true; - } - return false; -} - -void WEAK CDC_LineEncodingEvent(void) -{ - // has to be implemented by the user -} - -void WEAK CDC_LineStateEvent(void) -{ - // has to be implemented by the user -} - -void Serial_::begin(unsigned long /* baud_count */) -{ - peek_buffer = -1; -} - -void Serial_::begin(unsigned long /* baud_count */, byte /* config */) -{ - peek_buffer = -1; -} - -void Serial_::end(void) -{ -} - -int Serial_::available(void) -{ - if (peek_buffer >= 0) { - return 1 + USB_Available(CDC_RX); - } - return USB_Available(CDC_RX); -} - -int Serial_::peek(void) -{ - if (peek_buffer < 0) - peek_buffer = USB_Recv(CDC_RX); - return peek_buffer; -} - -int Serial_::read(void) -{ - if (peek_buffer >= 0) { - int c = peek_buffer; - peek_buffer = -1; - return c; - } - return USB_Recv(CDC_RX); -} - -void Serial_::flush(void) -{ - USB_Flush(CDC_TX); -} - -size_t Serial_::write(uint8_t c) -{ - return write(&c, 1); -} - -size_t Serial_::write(const uint8_t *buffer, size_t size) -{ - /* 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, buffer, size); - if (r > 0) { - return r; - } - else { - setWriteError(); - return 0; - } - } - setWriteError(); - return 0; -} - -uint32_t Serial_::baud(void) -{ - return _usbLineInfo.dwDTERate; -} - -uint8_t Serial_::stopbits(void) -{ - return _usbLineInfo.bCharFormat; -} - -uint8_t Serial_::paritytype(void) -{ - return _usbLineInfo.bParityType; -} - -uint8_t Serial_::numbits(void) -{ - return _usbLineInfo.bDataBits; -} - -bool Serial_::dtr(void) -{ - return (_usbLineInfo.lineState & CDC_CONTROL_LINE_OUT_DTR) ? true : false; -} - -bool Serial_::rts(void) -{ - return (_usbLineInfo.lineState & CDC_CONTROL_LINE_OUT_RTS) ? true : false; -} - -// 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/plugins/KeyboardioHID/avr/cores/hid/USB-Core/CDC.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/CDC.h deleted file mode 100644 index 99b62faa31..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/CDC.h +++ /dev/null @@ -1,105 +0,0 @@ -/* -CDC.h -Copyright (c) 2005-2014 Arduino. All right reserved. - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -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 __CDC__ -#define __CDC__ - -#include "Arduino.h" - -#if defined(USBCON) - -#include "USBDesc.h" -#include "USBCore.h" - -//================================================================================ -//================================================================================ -// Serial over CDC (Serial1 is the physical port) - -struct ring_buffer; - -#ifndef SERIAL_BUFFER_SIZE -#if (RAMEND < 1000) -#define SERIAL_BUFFER_SIZE 16 -#else -#define SERIAL_BUFFER_SIZE 64 -#endif -#endif -#if (SERIAL_BUFFER_SIZE>256) -#error Please lower the CDC Buffer size -#endif - -class Serial_ : public Stream -{ -private: - int peek_buffer; -public: - Serial_() { peek_buffer = -1; }; - void begin(unsigned long); - void begin(unsigned long, uint8_t); - void end(void); - - virtual int available(void); - virtual int peek(void); - virtual int read(void); - virtual void flush(void); - virtual size_t write(uint8_t); - virtual size_t write(const uint8_t*, size_t); - using Print::write; // pull in write(str) and write(buf, size) from Print - uint32_t baud(void); - uint8_t stopbits(void); - uint8_t paritytype(void); - uint8_t numbits(void); - bool dtr(void); - bool rts(void); - operator bool(); - - volatile uint8_t _rx_buffer_head; - volatile uint8_t _rx_buffer_tail; - unsigned char _rx_buffer[SERIAL_BUFFER_SIZE]; -}; -extern Serial_ Serial; - -#define HAVE_CDCSERIAL - -#endif /* if defined(USBCON) */ - -#endif \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.cpp b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.cpp deleted file mode 100644 index 7ec2a409aa..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/* 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. -*/ - -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -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 "HID.h" - -#define WEAK __attribute__ ((weak)) - -#if defined(USBCON) -#ifdef HID_ENABLED - -//================================================================================ -//================================================================================ - -extern const u8 _hidReportDescriptor[] PROGMEM; -const u8 _hidReportDescriptor[] = { - // by default use the standard HID descriptors - // extern descriptors can be passed via pins_Arduino.h -#ifdef EXTERN_HID_REPORT - EXTERN_HID_REPORT -#else - // use the hid descriptors of the selected hid devices -#ifdef HID_KEYBOARD_LEDS_ENABLE //TODO move keyboard below mouse? - HID_REPORT_KEYBOARD_LEDS(HID_REPORTID_KEYBOARD), -#elif defined(HID_KEYBOARD_KEYS_ENABLE) - HID_REPORT_KEYBOARD_KEYS(HID_REPORTID_KEYBOARD), -#endif -#if defined(HID_MOUSE_ENABLE) - HID_REPORT_MOUSE(HID_REPORTID_MOUSE), -#endif -#if defined(HID_MOUSE_ABSOLUTE_ENABLE) - HID_REPORT_MOUSE_ABSOLUTE(HID_REPORTID_MOUSE_ABSOLUTE), -#endif -#ifdef HID_RAWHID_ENABLE - HID_REPORT_RAWHID(HID_REPORTID_RAWHID), // not working at the moment -#endif -#ifdef HID_CONSUMERCONTROL_ENABLE - HID_REPORT_CONSUMERCONTROL(HID_REPORTID_CONSUMERCONTROL), -#endif -#ifdef HID_SYSTEM_ENABLE - HID_REPORT_SYSTEMCONTROL(HID_REPORTID_SYSTEMCONTROL), -#endif -#ifdef HID_GAMEPAD_ENABLE - HID_REPORT_GAMEPAD(HID_REPORTID_GAMEPAD), -#endif -#endif -}; - -extern const HIDDescriptor _hidInterface PROGMEM; -const HIDDescriptor _hidInterface = -{ - D_INTERFACE(HID_INTERFACE, 1, 3, 0, 0), - D_HIDREPORT(sizeof(_hidReportDescriptor)), - // edit by NicoHood - D_ENDPOINT(USB_ENDPOINT_IN(HID_ENDPOINT_INT), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) -}; - -#if defined(HID_KEYBOARD_LEDS_ENABLED) -volatile uint8_t hid_keyboard_leds = 0; -#endif - -//================================================================================ -//================================================================================ -// Driver - -u8 _hid_protocol = 1; -u8 _hid_idle = 1; - -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(uint8_t 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; - } -#if defined(HID_KEYBOARD_LEDS_ENABLED) - if (HID_SET_REPORT == r) - { - //TODO check correct report ID (not needed for now, no other device has an out report) - // maybe make this a general weak implementation to use it for RAW HID later? - if (setup.wLength == 2) - { - // write led out report data - uint8_t data[2]; - if (2 == USB_RecvControl(data, 2)) - hid_keyboard_leds = data[1]; - } - // else TODO check for other devices like RAW HID, not needed for now - } -#endif - } - return false; -} - -#endif - -#else /* if defined(USBCON) */ - -void WEAK HID_SendReport(u8 id, const void* data, int len) -{ - // empty to let the user use the HIDAPI for different use -} - -#endif /* if defined(USBCON) */ diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h deleted file mode 100644 index 1ce2518320..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HID.h +++ /dev/null @@ -1,441 +0,0 @@ -/* -HID.h -Copyright (c) 2005-2014 Arduino. All right reserved. - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -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 __HID__ -#define __HID__ - -#include "Arduino.h" - -// for the extern HID descriptors + settings -#include "pins_arduino.h" - -#if !defined(EXTERN_HID_REPORT) && !defined(HID_MOUSE_ENABLE) && !defined(HID_KEYBOARD_KEYS_ENABLE) \ -&& !defined(HID_KEYBOARD_LEDS_ENABLE) && !defined(HID_MOUSE_ABSOLUTE_ENABLE) && !defined(HID_RAWHID_ENABLE) \ -&& !defined(HID_CONSUMERCONTROL_ENABLE) && !defined(HID_SYSTEM_ENABLE) && !defined(HID_GAMEPAD_ENABLE) -// by default enable mouse + keyboard api -#define HID_MOUSE_ENABLE -#define HID_KEYBOARD_KEYS_ENABLE -#endif - -#ifdef HID_KEYBOARD_LEDS_ENABLE -// enable the Keyboard Led functions if the led report is selected -#define HID_KEYBOARD_LEDS_ENABLED -#endif - -#if defined(HID_MOUSE_ENABLE) || defined(HID_MOUSE_ABSOLUTE_API_ENABLE) -#define HID_MOUSE_API_ENABLE -#endif -#if defined(HID_MOUSE_ABSOLUTE_ENABLE) -#define HID_MOUSE_ABSOLUTE_API_ENABLE -#endif -#if defined(HID_KEYBOARD_LEDS_ENABLE) || defined(HID_KEYBOARD_KEYS_ENABLE) -#define HID_KEYBOARD_ENABLE -#define HID_KEYBOARD_API_ENABLE -#endif -#ifdef HID_RAWHID_ENABLE -#define HID_RAWHID_API_ENABLE -#endif -#ifdef HID_CONSUMERCONTROL_ENABLE -#define HID_CONSUMERCONTROL_API_ENABLE -#endif -#ifdef HID_SYSTEMCONTROL_ENABLE -#define HID_SYSTEMCONTROL_API_ENABLE -#endif -#ifdef HID_GAMEPAD_ENABLE -#define HID_GAMEPAD_API_ENABLE -#endif - -// extern accessible led out report -#if defined(HID_KEYBOARD_LEDS_ENABLED) -extern volatile uint8_t hid_keyboard_leds; -#endif - -// HID report IDs -// note by NicoHood: I would not change the current IDs, since it can confuse the OS -// I had several problems if i change the report id and its use. -// It doesnt matter if a device is not presented and there is a lack of IDs (at least number 1 must be represented) -// Report IDs and the report itself can be overwritten by the pins_arduino.h -#ifndef HID_REPORTID_MOUSE -#define HID_REPORTID_MOUSE 1 -#endif -#ifndef HID_REPORTID_KEYBOARD -#define HID_REPORTID_KEYBOARD 2 -#endif -#ifndef HID_REPORTID_RAWHID -#define HID_REPORTID_RAWHID 3 -#endif -#ifndef HID_REPORTID_CONSUMERCONTROL -#define HID_REPORTID_CONSUMERCONTROL 4 -#endif -#ifndef HID_REPORTID_SYSTEMCONTROL -#define HID_REPORTID_SYSTEMCONTROL 5 -#endif -#ifndef HID_REPORTID_GAMEPAD -#define HID_REPORTID_GAMEPAD 6 -#endif -#ifndef HID_REPORTID_MOUSE_ABSOLUTE -#define HID_REPORTID_MOUSE_ABSOLUTE 7 -#endif - -// HID reports -// Report IDs and the report itself can be overwritten by the pins_arduino.h - - -#ifndef HID_REPORT_MOUSE -#define HID_REPORT_MOUSE(report_id) /* Mouse relative */ \ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 54 */ \ - 0x09, 0x02, /* USAGE (Mouse) */ \ - 0xa1, 0x01, /* COLLECTION (Application) */ \ - 0x85, report_id, /* REPORT_ID */ \ -\ - /* 8 Buttons */ \ - 0x05, 0x09, /* USAGE_PAGE (Button) */ \ - 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ \ - 0x29, 0x08, /* USAGE_MAXIMUM (Button 8) */ \ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \ - 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ \ - 0x95, 0x08, /* REPORT_COUNT (8) */ \ - 0x75, 0x01, /* REPORT_SIZE (1) */ \ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ -\ - /* X, Y, Wheel */ \ - 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) */ \ -\ - /* End */ \ - 0xc0 /* END_COLLECTION */ -#endif - -#ifndef HID_REPORT_MOUSE_ABSOLUTE -#define HID_REPORT_MOUSE_ABSOLUTE(report_id) /* Mouse absolute */ \ - 0x05, 0x01, /* Usage Page (Generic Desktop) */ \ - 0x09, 0x02, /* Usage (Mouse) */ \ - 0xA1, 0x01, /* Collection (Application) */ \ - 0x85, report_id, /* REPORT_ID */ \ - 0x05, 0x01, /* Usage Page (Generic Desktop) */ \ - 0x09, 0x30, /* Usage (X) */ \ - 0x09, 0x31, /* Usage (Y) */ \ - 0x15, 0x00, /* Logical Minimum (0) */ \ - 0x26, 0xFF, 0x7F, /* Logical Maximum (32767) */ \ - 0x75, 0x10, /* Report Size (16), */ \ - 0x95, 0x02, /* Report Count (2), */ \ - 0x81, 0x02, /* Input (Data, Variable, Absolute) */ \ - 0xC0 /* End Collection */ -#endif - -#ifndef HID_REPORT_KEYBOARD_LEDS -#define HID_REPORT_KEYBOARD_LEDS(report_id) /* Keyboard */ \ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 47 */ \ - 0x09, 0x06, /* USAGE (Keyboard) */ \ - 0xa1, 0x01, /* COLLECTION (Application) */ \ - 0x85, report_id, /* REPORT_ID */ \ - 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ \ -\ - /* Keyboard Modifiers (shift, alt, ...) */ \ - 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) */ \ -\ - /* Reserved byte */ \ - 0x95, 0x01, /* REPORT_COUNT (1) */ \ - 0x75, 0x08, /* REPORT_SIZE (8) */ \ - 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ \ -\ - /* 5 LEDs for num lock etc */ \ - 0x05, 0x08, /* USAGE_PAGE (LEDs) */ \ - 0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */ \ - 0x29, 0x05, /* USAGE_MAXIMUM (Kana) */ \ - 0x95, 0x05, /* REPORT_COUNT (5) */ \ - 0x75, 0x01, /* REPORT_SIZE (1) */ \ - 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */ \ - /* Reserved 3 bits */ \ - 0x95, 0x01, /* REPORT_COUNT (1) */ \ - 0x75, 0x03, /* REPORT_SIZE (3) */ \ - 0x91, 0x03, /* OUTPUT (Cnst,Var,Abs) */ \ -\ - /* 6 Keyboard keys */ \ - 0x95, 0x06, /* REPORT_COUNT (6) */ \ - 0x75, 0x08, /* REPORT_SIZE (8) */ \ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \ - 0x26, 0xE7, 0x00, /* LOGICAL_MAXIMUM (231) */ \ - 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ \ - 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ \ - 0x29, 0xE7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ \ - 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ \ -\ - /* End */ \ - 0xc0 /* END_COLLECTION */ -#endif - -#ifndef HID_REPORT_KEYBOARD_KEYS -#define HID_REPORT_KEYBOARD_KEYS(report_id) /* Keyboard */ \ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 47 */ \ - 0x09, 0x06, /* USAGE (Keyboard) */ \ - 0xa1, 0x01, /* COLLECTION (Application) */ \ - 0x85, report_id, /* REPORT_ID */ \ - 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ \ -\ - /* Keyboard Modifiers (shift, alt, ...) */ \ - 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) */ \ -\ - /* Reserved byte */ \ - 0x95, 0x01, /* REPORT_COUNT (1) */ \ - 0x75, 0x08, /* REPORT_SIZE (8) */ \ - 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ \ -\ - /* 6 Keyboard keys */ \ - 0x95, 0x06, /* REPORT_COUNT (6) */ \ - 0x75, 0x08, /* REPORT_SIZE (8) */ \ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \ - 0x26, 0xE7, 0x00, /* LOGICAL_MAXIMUM (231) */ \ - 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ \ - 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ \ - 0x29, 0xE7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ \ - 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ \ -\ - /* End */ \ - 0xc0 /* END_COLLECTION */ -#endif - -//TODO limit to system keys only? -#ifndef HID_REPORT_SYSTEMCONTROL -#define HID_REPORT_SYSTEMCONTROL(report_id) /* System Control (Power Down, Sleep, Wakeup, ...) */ \ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ \ - 0x09, 0x80, /* USAGE (System Control) */ \ - 0xa1, 0x01, /* COLLECTION (Application) */ \ - 0x85, report_id, /* REPORT_ID */ \ - /* 1 system key */ \ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \ - 0x26, 0xff, 0x00, /* LOGICAL_MAXIMUM (255) */ \ - 0x19, 0x00, /* USAGE_MINIMUM (Undefined) */ \ - 0x29, 0xff, /* USAGE_MAXIMUM (System Menu Down) */ \ - 0x95, 0x01, /* REPORT_COUNT (1) */ \ - 0x75, 0x08, /* REPORT_SIZE (8) */ \ - 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ \ - 0xc0 /* END_COLLECTION */ -#endif - -#ifndef HID_REPORT_CONSUMERCONTROL -#define HID_REPORT_CONSUMERCONTROL(report_id) /* Consumer Control (Sound/Media keys) */ \ - 0x05, 0x0C, /* usage page (consumer device) */ \ - 0x09, 0x01, /* usage -- consumer control */ \ - 0xA1, 0x01, /* collection (application) */ \ - 0x85, report_id, /* report id */ \ - /* 4 Media Keys */ \ - 0x15, 0x00, /* logical minimum */ \ - 0x26, 0xFF, 0x03, /* logical maximum (3ff) */ \ - 0x19, 0x00, /* usage minimum (0) */ \ - 0x2A, 0xFF, 0x03, /* usage maximum (3ff) */ \ - 0x95, 0x04, /* report count (4) */ \ - 0x75, 0x10, /* report size (16) */ \ - 0x81, 0x00, /* input */ \ - 0xC0 /* end collection */ -#endif - -#ifndef HID_REPORT_GAMEPAD -#define HID_REPORT_GAMEPAD(report_id) /* Gamepad with 32 buttons and 6 axis*/ \ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ \ - 0x09, 0x04, /* USAGE (Joystick) */ \ - 0xa1, 0x01, /* COLLECTION (Application) */ \ - 0x85, report_id, /* REPORT_ID */ \ - /* 32 Buttons */ \ - 0x05, 0x09, /* USAGE_PAGE (Button) */ \ - 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ \ - 0x29, 0x20, /* USAGE_MAXIMUM (Button 32) */ \ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \ - 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ \ - 0x75, 0x01, /* REPORT_SIZE (1) */ \ - 0x95, 0x20, /* REPORT_COUNT (32) */ \ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ - /* 4 16bit Axis */ \ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ \ - 0xa1, 0x00, /* COLLECTION (Physical) */ \ - 0x09, 0x30, /* USAGE (X) */ \ - 0x09, 0x31, /* USAGE (Y) */ \ - 0x09, 0x33, /* USAGE (Rx) */ \ - 0x09, 0x34, /* USAGE (Ry) */ \ - 0x16, 0x00, 0x80, /* LOGICAL_MINIMUM (-32768) */ \ - 0x26, 0xFF, 0x7F, /* LOGICAL_MAXIMUM (32767) */ \ - 0x75, 0x10, /* REPORT_SIZE (16) */ \ - 0x95, 0x04, /* REPORT_COUNT (4) */ \ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ - /* 2 8bit Axis */ \ - 0x09, 0x32, /* USAGE (Z) */ \ - 0x09, 0x35, /* USAGE (Rz) */ \ - 0x15, 0x80, /* LOGICAL_MINIMUM (-128) */ \ - 0x25, 0x7F, /* LOGICAL_MAXIMUM (127) */ \ - 0x75, 0x08, /* REPORT_SIZE (8) */ \ - 0x95, 0x02, /* REPORT_COUNT (2) */ \ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ - 0xc0, /* END_COLLECTION */ \ - /* 2 Hat Switches */ \ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ \ - 0x09, 0x39, /* USAGE (Hat switch) */ \ - 0x09, 0x39, /* USAGE (Hat switch) */ \ - 0x15, 0x01, /* LOGICAL_MINIMUM (1) */ \ - 0x25, 0x08, /* LOGICAL_MAXIMUM (8) */ \ - 0x95, 0x02, /* REPORT_COUNT (2) */ \ - 0x75, 0x04, /* REPORT_SIZE (4) */ \ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ - 0xc0 /* END_COLLECTION */ -#endif - -// note by NicoHood: RawHID might never work with multireports, because of OS problems -// therefore we have to make it a single report with no idea. No other HID device will be supported then. -#ifndef RAWHID_USAGE_PAGE -#define RAWHID_USAGE_PAGE 0xFFC0 // recommended: 0xFF00 to 0xFFFF -#endif -#ifndef RAWHID_USAGE -#define RAWHID_USAGE 0x0C00 // recommended: 0x0100 to 0xFFFF -#endif -#ifndef RAWHID_TX_SIZE -#define RAWHID_TX_SIZE (USB_EP_SIZE-1) -#endif -#ifndef RAWHID_RX_SIZE -#define RAWHID_RX_SIZE (USB_EP_SIZE-1) -#endif - -#define LSB(_x) ((_x) & 0xFF) -#define MSB(_x) ((_x) >> 8) - -#ifndef HID_REPORT_RAWHID -#define HID_REPORT_RAWHID(report_id) /* RAW HID */ \ - 0x06, LSB(RAWHID_USAGE_PAGE), MSB(RAWHID_USAGE_PAGE), /* 30 */ \ - 0x0A, LSB(RAWHID_USAGE), MSB(RAWHID_USAGE), \ -\ - 0xA1, 0x01, /* Collection 0x01 */ \ - 0x85, report_id, /* REPORT_ID */ \ - 0x75, 0x08, /* report size = 8 bits */ \ - 0x15, 0x00, /* logical minimum = 0 */ \ - 0x26, 0xFF, 0x00, /* logical maximum = 255 */ \ -\ - 0x95, RAWHID_TX_SIZE, /* report count TX */ \ - 0x09, 0x01, /* usage */ \ - 0x81, 0x02, /* Input (array) */ \ -\ - 0x95, RAWHID_RX_SIZE, /* report count RX */ \ - 0x09, 0x02, /* usage */ \ - 0x91, 0x02, /* Output (array) */ \ - 0xC0 /* end collection */ -#endif - -#if defined(USBCON) - -#include "USBDesc.h" -#include "USBCore.h" - -//================================================================================ -//================================================================================ -// 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); - -#else /* if defined(USBCON) */ - -// (weak) function prototype to let the user use the HIDAPI for different use -// if he include the api himself -void HID_SendReport(uint8_t id, const void* data, int len); - -#endif /* if defined(USBCON) */ - - -// only include HIDAPIs if we have an USB AVR MCU. -// only enable specific APIs to throw an error if the hid report wasn't set -// The user can overwrite HID_SendReport() and manually include the APIs for a non USB AVR -// the include has to be done at the end so that the HID-APIs see the report ids and the send prototype. - -#ifdef HID_ENABLE_ALL_APIS -// include all HID APIs -#define HID_MOUSE_API_ENABLE -#define HID_MOUSE_ABSOLUTE_API_ENABLE -#define HID_KEYBOARD_API_ENABLE -#define HID_RAWHID_API_ENABLE -#define HID_CONSUMERCONTROL_API_ENABLE -#define HID_SYSTEMCONTROL_API_ENABLE -#define HID_GAMEPAD_API_ENABLE -#endif - -#ifdef HID_MOUSE_API_ENABLE -#include "Mouse.h" -#endif - -#ifdef HID_KEYBOARD_API_ENABLE -#include "Keyboard.h" -#endif - -#ifdef HID_RAWHID_API_ENABLE -#include "RawHID.h" -#endif - -#ifdef HID_CONSUMERCONTROL_API_ENABLE -#include "Consumer.h" -#endif - -#ifdef HID_SYSTEMCONTROL_API_ENABLE -#include "System.h" -#endif - -#ifdef HID_GAMEPAD_API_ENABLE -#include "Gamepad.h" -#endif - -#endif diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HIDAPI.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HIDAPI.h deleted file mode 100644 index 4ca593da06..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HIDAPI.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -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 __HIDAPI__ -#define __HIDAPI__ - -// include all HID APIs -#include "Keyboard.h" -#include "Mouse.h" -#include "Consumer.h" -#include "System.h" -#include "Gamepad.h" - -#endif \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HIDTables.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HIDTables.h deleted file mode 100644 index 8092e1fbf8..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/HIDTables.h +++ /dev/null @@ -1,677 +0,0 @@ -#ifndef __HIDTables__ -#define HID___HIDTables__ - - -// These mappings were extracted and transcribed from -// http://www.usb.org_SLASH_developers_SLASH_devclass_docs_SLASH_Hut1_12v2.pdf -// -// In most cases, I've preserved the "official" USB Implementers forum -// "Usage Name", though I've standardized some abbreviations and spacing -// that were inconsistent in the original specification. Non alpha-numeric -// characters in symbol names were converted into those characters' names. -// -// To match Arduino code style, all hid usage names are fully upper case. -// -// Not every HID usage listed in this file is currently supported by Arduino -// In particular, any System Control or Consumer Control entry that doesn't -// have a comment indicating that it's "HID type OSC" will require additional -// code in the Arduino core to work. -// -// Non-working usages are listed here in the interest of not having to manually -// convert more usage names each and every time our HID stack gets a little bit -// better. -// -// -// -- Jesse Vincent , January 2014 - - - -// System control mappings - -#define HID_SYSTEM_POWER_DOWN 0x81 // HID type OSC -#define HID_SYSTEM_SLEEP 0x82 // HID type OSC -#define HID_SYSTEM_WAKE_UP 0x83 // HID type OSC -#define HID_SYSTEM_CONTEXT_MENU 0x84 // HID type OSC -#define HID_SYSTEM_MAIN_MENU 0x85 // HID type OSC -#define HID_SYSTEM_APP_MENU 0x86 // HID type OSC -#define HID_SYSTEM_MENU_HELP 0x87 // HID type OSC -#define HID_SYSTEM_MENU_EXIT 0x88 // HID type OSC -#define HID_SYSTEM_MENU_SELECT 0x89 // HID type OSC -#define HID_SYSTEM_MENU_RIGHT 0x8A // HID type RTC -#define HID_SYSTEM_MENU_LEFT 0x8B // HID type RTC -#define HID_SYSTEM_MENU_UP 0x8C // HID type RTC -#define HID_SYSTEM_MENU_DOWN 0x8D // HID type RTC -#define HID_SYSTEM_COLD_RESTART 0x8E // HID type OSC -#define HID_SYSTEM_WARM_RESTART 0x8F // HID type OSC -#define HID_D_PAD_UP 0x90 // HID type OOC -#define HID_D_PAD_DOWN 0x91 // HID type OOC -#define HID_D_PAD_RIGHT 0x92 // HID type OOC -#define HID_D_PAD_LEFT 0x93 // HID type OOC -// 0x94-0x9F are reserved -#define HID_SYSTEM_DOCK 0xA0 // HID type OSC -#define HID_SYSTEM_UNDOCK 0xA1 // HID type OSC -#define HID_SYSTEM_SETUP 0xA2 // HID type OSC -#define HID_SYSTEM_BREAK 0xA3 // HID type OSC -#define HID_SYSTEM_DEBUGGER_BREAK 0xA4 // HID type OSC -#define HID_APPLICATION_BREAK 0xA5 // HID type OSC -#define HID_APPLICATION_DEBUGGER_BREAK 0xA6 // HID type OSC -#define HID_SYSTEM_SPEAKER_MUTE 0xA7 // HID type OSC -#define HID_SYSTEM_HIBERNATE 0xA8 // HID type OSC -// 0xA9-0xAF are reserved -#define HID_SYSTEM_DISPLAY_INVERT 0xB0 // HID type OSC -#define HID_SYSTEM_DISPLAY_INTERNAL 0xB1 // HID type OSC -#define HID_SYSTEM_DISPLAY_EXTERNAL 0xB2 // HID type OSC -#define HID_SYSTEM_DISPLAY_BOTH 0xB3 // HID type OSC -#define HID_SYSTEM_DISPLAY_DUAL 0xB4 // HID type OSC -#define HID_SYSTEM_DISPLAY_TOGGLE_INT_SLASH_EXT 0xB5 // HID type OSC -#define HID_SYSTEM_DISPLAY_SWAP_PRIMARY_SLASH_SECONDARY 0xB6 // HID type OSC -#define HID_SYSTEM_DISPLAY_LCD_AUTOSCALE 0xB7 // HID type OSC - -// Keyboard HID mappings - -// Reserved (no_event_indicated) 0x00 -#define HID_KEYBOARD_ERROR_ROLLOVER 0x01 -#define HID_KEYBOARD_POST_FAIL 0x02 -#define HID_KEYBOARD_ERROR_UNDEFINED 0x03 -#define HID_KEYBOARD_A_AND_A 0x04 -#define HID_KEYBOARD_B_AND_B 0x05 -#define HID_KEYBOARD_C_AND_C 0x06 -#define HID_KEYBOARD_D_AND_D 0x07 -#define HID_KEYBOARD_E_AND_E 0x08 -#define HID_KEYBOARD_F_AND_F 0x09 -#define HID_KEYBOARD_G_AND_G 0x0A -#define HID_KEYBOARD_H_AND_H 0x0B -#define HID_KEYBOARD_I_AND_I 0x0C -#define HID_KEYBOARD_J_AND_J 0x0D -#define HID_KEYBOARD_K_AND_K 0x0E -#define HID_KEYBOARD_L_AND_L 0x0F -#define HID_KEYBOARD_M_AND_M 0x10 -#define HID_KEYBOARD_N_AND_N 0x11 -#define HID_KEYBOARD_O_AND_O 0x12 -#define HID_KEYBOARD_P_AND_P 0x13 -#define HID_KEYBOARD_Q_AND_Q 0x14 -#define HID_KEYBOARD_R_AND_R 0x15 -#define HID_KEYBOARD_S_AND_S 0x16 -#define HID_KEYBOARD_T_AND_T 0x17 -#define HID_KEYBOARD_U_AND_U 0x18 -#define HID_KEYBOARD_V_AND_V 0x19 -#define HID_KEYBOARD_W_AND_W 0x1A -#define HID_KEYBOARD_X_AND_X 0x1B -#define HID_KEYBOARD_Y_AND_Y 0x1C -#define HID_KEYBOARD_Z_AND_Z 0x1D -#define HID_KEYBOARD_1_AND_EXCLAMATION_POINT 0x1E -#define HID_KEYBOARD_2_AND_AT 0x1F -#define HID_KEYBOARD_3_AND_POUND 0x20 -#define HID_KEYBOARD_4_AND_DOLLAR 0x21 -#define HID_KEYBOARD_5_AND_PERCENT 0x22 -#define HID_KEYBOARD_6_AND_CARAT 0x23 -#define HID_KEYBOARD_7_AND_AMPERSAND 0x24 -#define HID_KEYBOARD_8_AND_ASTERISK 0x25 -#define HID_KEYBOARD_9_AND_LEFT_PAREN 0x26 -#define HID_KEYBOARD_0_AND_RIGHT_PAREN 0x27 -#define HID_KEYBOARD_ENTER 0x28 // (MARKED AS ENTER_SLASH_RETURN) -#define HID_KEYBOARD_ESCAPE 0x29 -#define HID_KEYBOARD_DELETE 0x2A // (BACKSPACE) -#define HID_KEYBOARD_TAB 0x2B -#define HID_KEYBOARD_SPACEBAR 0x2C -#define HID_KEYBOARD_MINUS_AND_UNDERSCORE 0x2D // (UNDERSCORE) -#define HID_KEYBOARD_EQUALS_AND_PLUS 0x2E -#define HID_KEYBOARD_LEFT_BRACKET_AND_LEFT_CURLY_BRACE 0x2F -#define HID_KEYBOARD_RIGHT_BRACKET_AND_RIGHT_CURLY_BRACE 0x30 -#define HID_KEYBOARD_BACKSLASH_AND_PIPE 0x31 -#define HID_KEYBOARD_NON_US_POUND_AND_TILDE 0x32 -#define HID_KEYBOARD_SEMICOLON_AND_COLON 0x33 -#define HID_KEYBOARD_QUOTE_AND_DOUBLEQUOTE 0x34 -#define HID_KEYBOARD_GRAVE_ACCENT_AND_TILDE 0x35 -#define HID_KEYBOARD_COMMA_AND_LESS_THAN 0x36 -#define HID_KEYBOARD_PERIOD_AND_GREATER_THAN 0x37 -#define HID_KEYBOARD_SLASH_AND_QUESTION_MARK 0x38 -#define HID_KEYBOARD_CAPS_LOCK 0x39 -#define HID_KEYBOARD_F1 0x3A -#define HID_KEYBOARD_F2 0x3B -#define HID_KEYBOARD_F3 0x3C -#define HID_KEYBOARD_F4 0x3D -#define HID_KEYBOARD_F5 0x3E -#define HID_KEYBOARD_F6 0x3F -#define HID_KEYBOARD_F7 0x40 -#define HID_KEYBOARD_F8 0x41 -#define HID_KEYBOARD_F9 0x42 -#define HID_KEYBOARD_F10 0x43 -#define HID_KEYBOARD_F11 0x44 -#define HID_KEYBOARD_F12 0x45 -#define HID_KEYBOARD_PRINTSCREEN 0x46 -#define HID_KEYBOARD_SCROLL_LOCK 0x47 -#define HID_KEYBOARD_PAUSE 0x48 -#define HID_KEYBOARD_INSERT 0x49 -#define HID_KEYBOARD_HOME 0x4A -#define HID_KEYBOARD_PAGE_UP 0x4B -#define HID_KEYBOARD_DELETE_FORWARD 0x4C -#define HID_KEYBOARD_END 0x4D -#define HID_KEYBOARD_PAGE_DOWN 0x4E -#define HID_KEYBOARD_RIGHTARROW 0x4F -#define HID_KEYBOARD_LEFTARROW 0x50 -#define HID_KEYBOARD_DOWNARROW 0x51 -#define HID_KEYBOARD_UPARROW 0x52 -#define HID_KEYPAD_NUM_LOCK_AND_CLEAR 0x53 -#define HID_KEYPAD_DIVIDE 0x54 -#define HID_KEYPAD_MULTIPLY 0x55 -#define HID_KEYPAD_SUBTRACT 0x56 -#define HID_KEYPAD_ADD 0x57 -#define HID_KEYPAD_ENTER 0x58 -#define HID_KEYPAD_1_AND_END 0x59 -#define HID_KEYPAD_2_AND_DOWN_ARROW 0x5A -#define HID_KEYPAD_3_AND_PAGE_DOWN 0x5B -#define HID_KEYPAD_4_AND_LEFT_ARROW 0x5C -#define HID_KEYPAD_5 0x5D -#define HID_KEYPAD_6_AND_RIGHT_ARROW 0x5E -#define HID_KEYPAD_7_AND_HOME 0x5F -#define HID_KEYPAD_8_AND_UP_ARROW 0x60 -#define HID_KEYPAD_9_AND_PAGE_UP 0x61 -#define HID_KEYPAD_0_AND_INSERT 0x62 -#define HID_KEYPAD_PERIOD_AND_DELETE 0x63 -#define HID_KEYBOARD_NON_US_BACKSLASH_AND_PIPE 0x64 -#define HID_KEYBOARD_APPLICATION 0x65 -#define HID_KEYBOARD_POWER 0x66 -#define HID_KEYPAD_EQUALS 0x67 -#define HID_KEYBOARD_F13 0x68 -#define HID_KEYBOARD_F14 0x69 -#define HID_KEYBOARD_F15 0x6A -#define HID_KEYBOARD_F16 0x6B -#define HID_KEYBOARD_F17 0x6C -#define HID_KEYBOARD_F18 0x6D -#define HID_KEYBOARD_F19 0x6E -#define HID_KEYBOARD_F20 0x6F -#define HID_KEYBOARD_F21 0x70 -#define HID_KEYBOARD_F22 0x71 -#define HID_KEYBOARD_F23 0x72 -#define HID_KEYBOARD_F24 0x73 -#define HID_KEYBOARD_EXECUTE 0x74 -#define HID_KEYBOARD_HELP 0x75 -#define HID_KEYBOARD_MENU 0x76 -#define HID_KEYBOARD_SELECT 0x77 -#define HID_KEYBOARD_STOP 0x78 -#define HID_KEYBOARD_AGAIN 0x79 -#define HID_KEYBOARD_UNDO 0x7A -#define HID_KEYBOARD_CUT 0x7B -#define HID_KEYBOARD_COPY 0x7C -#define HID_KEYBOARD_PASTE 0x7D -#define HID_KEYBOARD_FIND 0x7E -#define HID_KEYBOARD_MUTE 0x7F -#define HID_KEYBOARD_VOLUME_UP 0x80 -#define HID_KEYBOARD_VOLUME_DOWN 0x81 -#define HID_KEYBOARD_LOCKING_CAPS_LOCK 0x82 -#define HID_KEYBOARD_LOCKING_NUM_LOCK 0x83 -#define HID_KEYBOARD_LOCKING_SCROLL_LOCK 0x84 -#define HID_KEYPAD_COMMA 0x85 -#define HID_KEYPAD_EQUAL_SIGN 0x86 -#define HID_KEYBOARD_INTERNATIONAL1 0x87 -#define HID_KEYBOARD_INTERNATIONAL2 0x88 -#define HID_KEYBOARD_INTERNATIONAL3 0x89 -#define HID_KEYBOARD_INTERNATIONAL4 0x8A -#define HID_KEYBOARD_INTERNATIONAL5 0x8B -#define HID_KEYBOARD_INTERNATIONAL6 0x8C -#define HID_KEYBOARD_INTERNATIONAL7 0x8D -#define HID_KEYBOARD_INTERNATIONAL8 0x8E -#define HID_KEYBOARD_INTERNATIONAL9 0x8F -#define HID_KEYBOARD_LANG1 0x90 -#define HID_KEYBOARD_LANG2 0x91 -#define HID_KEYBOARD_LANG3 0x92 -#define HID_KEYBOARD_LANG4 0x93 -#define HID_KEYBOARD_LANG5 0x94 -#define HID_KEYBOARD_LANG6 0x95 -#define HID_KEYBOARD_LANG7 0x96 -#define HID_KEYBOARD_LANG8 0x97 -#define HID_KEYBOARD_LANG9 0x98 -#define HID_KEYBOARD_ALTERNATE_ERASE 0x99 -#define HID_KEYBOARD_SYSREQ_SLASH_ATTENTION 0x9A -#define HID_KEYBOARD_CANCEL 0x9B -#define HID_KEYBOARD_CLEAR 0x9C -#define HID_KEYBOARD_PRIOR 0x9D -#define HID_KEYBOARD_RETURN 0x9E -#define HID_KEYBOARD_SEPARATOR 0x9F -#define HID_KEYBOARD_OUT 0xA0 -#define HID_KEYBOARD_OPER 0xA1 -#define HID_KEYBOARD_CLEAR_SLASH_AGAIN 0xA2 -#define HID_KEYBOARD_CRSEL_SLASH_PROPS 0xA3 -#define HID_KEYBOARD_EXSEL 0xA4 -// Reserved 0xA5-AF -#define HID_KEYPAD_00 0xB0 -#define HID_KEYPAD_000 0xB1 -#define HID_THOUSANDS_SEPARATOR 0xB2 -#define HID_DECIMAL_SEPARATOR 0xB3 -#define HID_CURRENCY_UNIT 0xB4 -#define HID_CURRENCY_SUBUNIT 0xB5 -#define HID_KEYPAD_LEFT_PAREN 0xB6 -#define HID_KEYPAD_RIGHT_PAREN 0xB7 -#define HID_KEYPAD_LEFT_CURLY_BRACE 0xB8 -#define HID_KEYPAD_RIGHT_CURLY_BRACE 0xB9 -#define HID_KEYPAD_TAB 0xBA -#define HID_KEYPAD_BACKSPACE 0xBB -#define HID_KEYPAD_A 0xBC -#define HID_KEYPAD_B 0xBD -#define HID_KEYPAD_C 0xBE -#define HID_KEYPAD_D 0xBF -#define HID_KEYPAD_E 0xC0 -#define HID_KEYPAD_F 0xC1 -#define HID_KEYPAD_XOR 0xC2 -#define HID_KEYPAD_CARAT 0xC3 -#define HID_KEYPAD_PERCENT 0xC4 -#define HID_KEYPAD_LESS_THAN 0xC5 -#define HID_KEYPAD_GREATER_THAN 0xC6 -#define HID_KEYPAD_AMPERSAND 0xC7 -#define HID_KEYPAD_DOUBLEAMPERSAND 0xC8 -#define HID_KEYPAD_PIPE 0xC9 -#define HID_KEYPAD_DOUBLEPIPE 0xCA -#define HID_KEYPAD_COLON 0xCB -#define HID_KEYPAD_POUND_SIGN 0xCC -#define HID_KEYPAD_SPACE 0xCD -#define HID_KEYPAD_AT_SIGN 0xCE -#define HID_KEYPAD_EXCLAMATION_POINT 0xCF -#define HID_KEYPAD_MEMORY_STORE 0xD0 -#define HID_KEYPAD_MEMORY_RECALL 0xD1 -#define HID_KEYPAD_MEMORY_CLEAR 0xD2 -#define HID_KEYPAD_MEMORY_ADD 0xD3 -#define HID_KEYPAD_MEMORY_SUBTRACT 0xD4 -#define HID_KEYPAD_MEMORY_MULTIPLY 0xD5 -#define HID_KEYPAD_MEMORY_DIVIDE 0xD6 -#define HID_KEYPAD_PLUS_SLASH_MINUS 0xD7 -#define HID_KEYPAD_CLEAR 0xD8 -#define HID_KEYPAD_CLEAR_ENTRY 0xD9 -#define HID_KEYPAD_BINARY 0xDA -#define HID_KEYPAD_OCTAL 0xDB -#define HID_KEYPAD_DECIMAL 0xDC -#define HID_KEYPAD_HEXADECIMAL 0xDD - -// 0xDE-0xDF - RESERVED -#define HID_KEYBOARD_LEFT_CONTROL 0xE0 -#define HID_KEYBOARD_LEFT_SHIFT 0xE1 -#define HID_KEYBOARD_LEFT_ALT 0xE2 -#define HID_KEYBOARD_LEFT_GUI 0xE3 -#define HID_KEYBOARD_RIGHT_CONTROL 0xE4 -#define HID_KEYBOARD_RIGHT_SHIFT 0xE5 -#define HID_KEYBOARD_RIGHT_ALT 0xE6 -#define HID_KEYBOARD_RIGHT_GUI 0xE7 - - -// Consumer_Page_(0x0C) 0x15 -#define HID_CONSUMER_NUMERIC_KEY_PAD 0x02 // HID type NARY -#define HID_CONSUMER_PROGRAMMABLE_BUTTONS 0x03 // HID type NARY -#define HID_CONSUMER_MICROPHONE_CA 0x04 -#define HID_CONSUMER_HEADPHONE_CA 0x05 -#define HID_CONSUMER_GRAPHIC_EQUALIZER_CA 0x06 -// Reserved 0x07-1F -#define HID_CONSUMER_PLUS_10 0x20 // HID type OSC -#define HID_CONSUMER_PLUS_100 0x21 // HID type OSC -#define HID_CONSUMER_AM_SLASH_PM 0x22 // HID type OSC -// Reserved 0x23-3F -#define HID_CONSUMER_POWER 0x30 // HID type OOC -#define HID_CONSUMER_RESET 0x31 // HID type OSC -#define HID_CONSUMER_SLEEP 0x32 // HID type OSC -#define HID_CONSUMER_SLEEP_AFTER 0x33 // HID type OSC -#define HID_CONSUMER_SLEEP_MODE 0x34 // HID type RTC -#define HID_CONSUMER_ILLUMINATION 0x35 // HID type OOC -#define HID_CONSUMER_FUNCTION_BUTTONS 0x36 // HID type NARY -// Reserved 0x37-3F -#define HID_CONSUMER_MENU 0x40 // HID type OOC -#define HID_CONSUMER_MENU_PICK 0x41 // HID type OSC -#define HID_CONSUMER_MENU_UP 0x42 // HID type OSC -#define HID_CONSUMER_MENU_DOWN 0x43 // HID type OSC -#define HID_CONSUMER_MENU_LEFT 0x44 // HID type OSC -#define HID_CONSUMER_MENU_RIGHT 0x45 // HID type OSC -#define HID_CONSUMER_MENU_ESCAPE 0x46 // HID type OSC -#define HID_CONSUMER_MENU_VALUE_INCREASE 0x47 // HID type OSC -#define HID_CONSUMER_MENU_VALUE_DECREASE 0x48 // HID type OSC -// Reserved 0x49-5F -#define HID_CONSUMER_DATA_ON_SCREEN 0x60 // HID type OOC -#define HID_CONSUMER_CLOSED_CAPTION 0x61 // HID type OOC -#define HID_CONSUMER_CLOSED_CAPTION_SELECT 0x62 // HID type OSC -#define HID_CONSUMER_VCR_SLASH_TV 0x63 // HID type OOC -#define HID_CONSUMER_BROADCAST_MODE 0x64 // HID type OSC -#define HID_CONSUMER_SNAPSHOT 0x65 // HID type OSC -#define HID_CONSUMER_STILL 0x66 // HID type OSC -// Reserved 0x67-7F -#define HID_CONSUMER_SELECTION 0x80 // HID type NARY -#define HID_CONSUMER_ASSIGN_SELECTION 0x81 // HID type OSC -#define HID_CONSUMER_MODE_STEP 0x82 // HID type OSC -#define HID_CONSUMER_RECALL_LAST 0x83 // HID type OSC -#define HID_CONSUMER_ENTER_CHANNEL 0x84 // HID type OSC -#define HID_CONSUMER_ORDER_MOVIE 0x85 // HID type OSC -#define HID_CONSUMER_CHANNEL 0x86 // HID type LC -#define HID_CONSUMER_MEDIA_SELECTION 0x87 // HID type NARY -#define HID_CONSUMER_MEDIA_SELECT_COMPUTER 0x88 // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_TV 0x89 // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_WWW 0x8A // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_DVD 0x8B // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_TELEPHONE 0x8C // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_PROGRAM_GUIDE 0x8D // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_VIDEO_PHONE 0x8E // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_GAMES 0x8F // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_MESSAGES 0x90 // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_CD 0x91 // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_VCR 0x92 // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_TUNER 0x93 // HID type SEL -#define HID_CONSUMER_QUIT 0x94 // HID type OSC -#define HID_CONSUMER_HELP 0x95 // HID type OOC -#define HID_CONSUMER_MEDIA_SELECT_TAPE 0x96 // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_CABLE 0x97 // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_SATELLITE 0x98 // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_SECURITY 0x99 // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_HOME 0x9A // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_CALL 0x9B // HID type SEL -#define HID_CONSUMER_CHANNEL_INCREMENT 0x9C // HID type OSC -#define HID_CONSUMER_CHANNEL_DECREMENT 0x9D // HID type OSC -#define HID_CONSUMER_MEDIA_SELECT_SAP 0x9E // HID type SEL -// Reserved 0x9F -#define HID_CONSUMER_VCR_PLUS 0xA0 // HID type OSC -#define HID_CONSUMER_ONCE 0xA1 // HID type OSC -#define HID_CONSUMER_DAILY 0xA2 // HID type OSC -#define HID_CONSUMER_WEEKLY 0xA3 // HID type OSC -#define HID_CONSUMER_MONTHLY 0xA4 // HID type OSC -// Reserved 0xA5-AF -#define HID_CONSUMER_PLAY 0xB0 // HID type OOC -#define HID_CONSUMER_PAUSE 0xB1 // HID type OOC -#define HID_CONSUMER_RECORD 0xB2 // HID type OOC -#define HID_CONSUMER_FAST_FORWARD 0xB3 // HID type OOC -#define HID_CONSUMER_REWIND 0xB4 // HID type OOC -#define HID_CONSUMER_SCAN_NEXT_TRACK 0xB5 // HID type OSC -#define HID_CONSUMER_SCAN_PREVIOUS_TRACK 0xB6 // HID type OSC -#define HID_CONSUMER_STOP 0xB7 // HID type OSC -#define HID_CONSUMER_EJECT 0xB8 // HID type OSC -#define HID_CONSUMER_RANDOM_PLAY 0xB9 // HID type OOC -#define HID_CONSUMER_SELECT_DISC 0xBA // HID type NARY -#define HID_CONSUMER_ENTER_DISC_MC 0xBB -#define HID_CONSUMER_REPEAT 0xBC // HID type OSC -#define HID_CONSUMER_TRACKING 0xBD // HID type LC -#define HID_CONSUMER_TRACK_NORMAL 0xBE // HID type OSC -#define HID_CONSUMER_SLOW_TRACKING 0xBF // HID type LC -#define HID_CONSUMER_FRAME_FORWARD 0xC0 // HID type RTC -#define HID_CONSUMER_FRAME_BACK 0xC1 // HID type RTC -#define HID_CONSUMER_MARK 0xC2 // HID type OSC -#define HID_CONSUMER_CLEAR_MARK 0xC3 // HID type OSC -#define HID_CONSUMER_REPEAT_FROM_MARK 0xC4 // HID type OOC -#define HID_CONSUMER_RETURN_TO_MARK 0xC5 // HID type OSC -#define HID_CONSUMER_SEARCH_MARK_FORWARD 0xC6 // HID type OSC -#define HID_CONSUMER_SEARCH_MARK_BACKWARDS 0xC7 // HID type OSC -#define HID_CONSUMER_COUNTER_RESET 0xC8 // HID type OSC -#define HID_CONSUMER_SHOW_COUNTER 0xC9 // HID type OSC -#define HID_CONSUMER_TRACKING_INCREMENT 0xCA // HID type RTC -#define HID_CONSUMER_TRACKING_DECREMENT 0xCB // HID type RTC -#define HID_CONSUMER_STOP_SLASH_EJECT 0xCC // HID type OSC -#define HID_CONSUMER_PLAY_SLASH_PAUSE 0xCD // HID type OSC -#define HID_CONSUMER_PLAY_SLASH_SKIP 0xCE // HID type OSC -// Reserved 0xCF-DF -#define HID_CONSUMER_VOLUME 0xE0 // HID type LC -#define HID_CONSUMER_BALANCE 0xE1 // HID type LC -#define HID_CONSUMER_MUTE 0xE2 // HID type OOC -#define HID_CONSUMER_BASS 0xE3 // HID type LC -#define HID_CONSUMER_TREBLE 0xE4 // HID type LC -#define HID_CONSUMER_BASS_BOOST 0xE5 // HID type OOC -#define HID_CONSUMER_SURROUND_MODE 0xE6 // HID type OSC -#define HID_CONSUMER_LOUDNESS 0xE7 // HID type OOC -#define HID_CONSUMER_MPX 0xE8 // HID type OOC -#define HID_CONSUMER_VOLUME_INCREMENT 0xE9 // HID type RTC -#define HID_CONSUMER_VOLUME_DECREMENT 0xEA // HID type RTC -// Reserved 0xEB-EF -#define HID_CONSUMER_SPEED_SELECT 0xF0 // HID type OSC -#define HID_CONSUMER_PLAYBACK_SPEED 0xF1 // HID type NARY -#define HID_CONSUMER_STANDARD_PLAY 0xF2 // HID type SEL -#define HID_CONSUMER_LONG_PLAY 0xF3 // HID type SEL -#define HID_CONSUMER_EXTENDED_PLAY 0xF4 // HID type SEL -#define HID_CONSUMER_SLOW 0xF5 // HID type OSC -// Reserved 0xF6-FF -#define HID_CONSUMER_FAN_ENABLE 0x100 // HID type OOC -#define HID_CONSUMER_FAN_SPEED 0x101 // HID type LC -#define HID_CONSUMER_LIGHT_ENABLE 0x102 // HID type OOC -#define HID_CONSUMER_LIGHT_ILLUMINATION_LEVEL 0x103 // HID type LC -#define HID_CONSUMER_CLIMATE_CONTROL_ENABLE 0x104 // HID type OOC -#define HID_CONSUMER_ROOM_TEMPERATURE 0x105 // HID type LC -#define HID_CONSUMER_SECURITY_ENABLE 0x106 // HID type OOC -#define HID_CONSUMER_FIRE_ALARM 0x107 // HID type OSC -#define HID_CONSUMER_POLICE_ALARM 0x108 // HID type OSC -#define HID_CONSUMER_PROXIMITY 0x109 // HID type LC -#define HID_CONSUMER_MOTION 0x10A // HID type OSC -#define HID_CONSUMER_DURESS_ALARM 0x10B // HID type OSC -#define HID_CONSUMER_HOLDUP_ALARM 0x10C // HID type OSC -#define HID_CONSUMER_MEDICAL_ALARM 0x10D // HID type OSC -// Reserved 0x10E-14F -#define HID_CONSUMER_BALANCE_RIGHT 0x150 // HID type RTC -#define HID_CONSUMER_BALANCE_LEFT 0x151 // HID type RTC -#define HID_CONSUMER_BASS_INCREMENT 0x152 // HID type RTC -#define HID_CONSUMER_BASS_DECREMENT 0x153 // HID type RTC -#define HID_CONSUMER_TREBLE_INCREMENT 0x154 // HID type RTC -#define HID_CONSUMER_TREBLE_DECREMENT 0x155 // HID type RTC -// Reserved 0x156-15F -#define HID_CONSUMER_SPEAKER_SYSTEM 0x160 // HID type CL -#define HID_CONSUMER_CHANNEL_LEFT 0x161 // HID type CL -#define HID_CONSUMER_CHANNEL_RIGHT 0x162 // HID type CL -#define HID_CONSUMER_CHANNEL_CENTER 0x163 // HID type CL -#define HID_CONSUMER_CHANNEL_FRONT 0x164 // HID type CL -#define HID_CONSUMER_CHANNEL_CENTER_FRONT 0x165 // HID type CL -#define HID_CONSUMER_CHANNEL_SIDE 0x166 // HID type CL -#define HID_CONSUMER_CHANNEL_SURROUND 0x167 // HID type CL -#define HID_CONSUMER_CHANNEL_LOW_FREQUENCY_ENHANCEMENT 0x168 // HID type CL -#define HID_CONSUMER_CHANNEL_TOP 0x169 // HID type CL -#define HID_CONSUMER_CHANNEL_UNKNOWN 0x16A // HID type CL -// Reserved 0x16B-16F -#define HID_CONSUMER_SUB-CHANNEL 0x170 // HID type LC -#define HID_CONSUMER_SUB-CHANNEL_INCREMENT 0x171 // HID type OSC -#define HID_CONSUMER_SUB-CHANNEL_DECREMENT 0x172 // HID type OSC -#define HID_CONSUMER_ALTERNATE_AUDIO_INCREMENT 0x173 // HID type OSC -#define HID_CONSUMER_ALTERNATE_AUDIO_DECREMENT 0x174 // HID type OSC -// Reserved 0x175-17F -#define HID_CONSUMER_APPLICATION_LAUNCH_BUTTONS 0x180 // HID type NARY -#define HID_CONSUMER_AL_LAUNCH_BUTTON_CONFIGURATION_TOOL 0x181 // HID type SEL -#define HID_CONSUMER_AL_PROGRAMMABLE_BUTTON_CONFIGURATION 0x182 // HID type SEL -#define HID_CONSUMER_AL_CONSUMER_CONTROL_CONFIGURATION 0x183 // HID type SEL -#define HID_CONSUMER_AL_WORD_PROCESSOR 0x184 // HID type SEL -#define HID_CONSUMER_AL_TEXT_EDITOR 0x185 // HID type SEL -#define HID_CONSUMER_AL_SPREADSHEET 0x186 // HID type SEL -#define HID_CONSUMER_AL_GRAPHICS_EDITOR 0x187 // HID type SEL -#define HID_CONSUMER_AL_PRESENTATION_APP 0x188 // HID type SEL -#define HID_CONSUMER_AL_DATABASE_APP 0x189 // HID type SEL -#define HID_CONSUMER_AL_EMAIL_READER 0x18A // HID type SEL -#define HID_CONSUMER_AL_NEWSREADER 0x18B // HID type SEL -#define HID_CONSUMER_AL_VOICEMAIL 0x18C // HID type SEL -#define HID_CONSUMER_AL_CONTACTS_SLASH_ADDRESS_BOOK 0x18D // HID type SEL -#define HID_CONSUMER_AL_CALENDAR_SLASH_SCHEDULE 0x18E // HID type SEL -#define HID_CONSUMER_AL_TASK_SLASH_PROJECT_MANAGER 0x18F // HID type SEL -#define HID_CONSUMER_AL_LOG_SLASH_JOURNAL_SLASH_TIMECARD 0x190 // HID type SEL -#define HID_CONSUMER_AL_CHECKBOOK_SLASH_FINANCE 0x191 // HID type SEL -#define HID_CONSUMER_AL_CALCULATOR 0x192 // HID type SEL -#define HID_CONSUMER_AL_A_SLASH_V_CAPTURE_SLASH_PLAYBACK 0x193 // HID type SEL -#define HID_CONSUMER_AL_LOCAL_MACHINE_BROWSER 0x194 // HID type SEL -#define HID_CONSUMER_AL_LAN_SLASH_WAN_BROWSER 0x195 // HID type SEL -#define HID_CONSUMER_AL_INTERNET_BROWSER 0x196 // HID type SEL -#define HID_CONSUMER_AL_REMOTE_NETWORKING_SLASH_ISP_CONNECT 0x197 // HID type SEL -#define HID_CONSUMER_AL_NETWORK_CONFERENCE 0x198 // HID type SEL -#define HID_CONSUMER_AL_NETWORK_CHAT 0x199 // HID type SEL -#define HID_CONSUMER_AL_TELEPHONY_SLASH_DIALER 0x19A // HID type SEL -#define HID_CONSUMER_AL_LOGON 0x19B // HID type SEL -#define HID_CONSUMER_AL_LOGOFF 0x19C // HID type SEL -#define HID_CONSUMER_AL_LOGON_SLASH_LOGOFF 0x19D // HID type SEL -#define HID_CONSUMER_AL_TERMINAL_LOCK_SLASH_SCREENSAVER 0x19E // HID type SEL -#define HID_CONSUMER_AL_CONTROL_PANEL 0x19F // HID type SEL -#define HID_CONSUMER_AL_COMMAND_LINE_PROCESSOR_SLASH_RUN 0x1A0 // HID type SEL -#define HID_CONSUMER_AL_PROCESS_SLASH_TASK_MANAGER 0x1A1 // HID type SEL -#define HID_CONSUMER_AL_SELECT_TASK_SLASH_APPLICATION 0x1A2 // HID type SEL -#define HID_CONSUMER_AL_NEXT_TASK_SLASH_APPLICATION 0x1A3 // HID type SEL -#define HID_CONSUMER_AL_PREVIOUS_TASK_SLASH_APPLICATION 0x1A4 // HID type SEL -#define HID_CONSUMER_AL_PREEMPTIVE_HALT_TASK_SLASH_APPLICATION 0x1A5 // HID type SEL -#define HID_CONSUMER_AL_INTEGRATED_HELP_CENTER 0x1A6 // HID type SEL -#define HID_CONSUMER_AL_DOCUMENTS 0x1A7 // HID type SEL -#define HID_CONSUMER_AL_THESAURUS 0x1A8 // HID type SEL -#define HID_CONSUMER_AL_DICTIONARY 0x1A9 // HID type SEL -#define HID_CONSUMER_AL_DESKTOP 0x1AA // HID type SEL -#define HID_CONSUMER_AL_SPELL_CHECK 0x1AB // HID type SEL -#define HID_CONSUMER_AL_GRAMMAR_CHECK 0x1AC // HID type SEL -#define HID_CONSUMER_AL_WIRELESS_STATUS 0x1AD // HID type SEL -#define HID_CONSUMER_AL_KEYBOARD_LAYOUT 0x1AE // HID type SEL -#define HID_CONSUMER_AL_VIRUS_PROTECTION 0x1AF // HID type SEL -#define HID_CONSUMER_AL_ENCRYPTION 0x1B0 // HID type SEL -#define HID_CONSUMER_AL_SCREEN_SAVER 0x1B1 // HID type SEL -#define HID_CONSUMER_AL_ALARMS 0x1B2 // HID type SEL -#define HID_CONSUMER_AL_CLOCK 0x1B3 // HID type SEL -#define HID_CONSUMER_AL_FILE_BROWSER 0x1B4 // HID type SEL -#define HID_CONSUMER_AL_POWER_STATUS 0x1B5 // HID type SEL -#define HID_CONSUMER_AL_IMAGE_BROWSER 0x1B6 // HID type SEL -#define HID_CONSUMER_AL_AUDIO_BROWSER 0x1B7 // HID type SEL -#define HID_CONSUMER_AL_MOVIE_BROWSER 0x1B8 // HID type SEL -#define HID_CONSUMER_AL_DIGITAL_RIGHTS_MANAGER 0x1B9 // HID type SEL -#define HID_CONSUMER_AL_DIGITAL_WALLET 0x1BA // HID type SEL -// _Reserved 0x1BB -#define HID_CONSUMER_AL_INSTANT_MESSAGING 0x1BC // HID type SEL -#define HID_CONSUMER_AL_OEM_FEATURES_SLASH__TIPS_SLASH_TUTORIAL_BROWSER 0x1BD // HID type SEL -#define HID_CONSUMER_AL_OEM_HELP 0x1BE // HID type SEL -#define HID_CONSUMER_AL_ONLINE_COMMUNITY 0x1BF // HID type SEL -#define HID_CONSUMER_AL_ENTERTAINMENT_CONTENT_BROWSER 0x1C0 // HID type SEL -#define HID_CONSUMER_AL_ONLINE_SHOPPING_BROWSER 0x1C1 // HID type SEL -#define HID_CONSUMER_AL_SMARTCARD_INFORMATION_SLASH_HELP 0x1C2 // HID type SEL -#define HID_CONSUMER_AL_MARKET_MONITOR_SLASH_FINANCE_BROWSER 0x1C3 // HID type SEL -#define HID_CONSUMER_AL_CUSTOMIZED_CORPORATE_NEWS_BROWSER 0x1C4 // HID type SEL -#define HID_CONSUMER_AL_ONLINE_ACTIVITY_BROWSER 0x1C5 // HID type SEL -#define HID_CONSUMER_AL_RESEARCH_SLASH_SEARCH_BROWSER 0x1C6 // HID type SEL -#define HID_CONSUMER_AL_AUDIO_PLAYER 0x1C7 // HID type SEL -// Reserved 0x1C8-1FF -#define HID_CONSUMER_GENERIC_GUI_APPLICATION_CONTROLS 0x200 // HID type NARY -#define HID_CONSUMER_AC_NEW 0x201 // HID type SEL -#define HID_CONSUMER_AC_OPEN 0x202 // HID type SEL -#define HID_CONSUMER_AC_CLOSE 0x203 // HID type SEL -#define HID_CONSUMER_AC_EXIT 0x204 // HID type SEL -#define HID_CONSUMER_AC_MAXIMIZE 0x205 // HID type SEL -#define HID_CONSUMER_AC_MINIMIZE 0x206 // HID type SEL -#define HID_CONSUMER_AC_SAVE 0x207 // HID type SEL -#define HID_CONSUMER_AC_PRINT 0x208 // HID type SEL -#define HID_CONSUMER_AC_PROPERTIES 0x209 // HID type SEL -#define HID_CONSUMER_AC_UNDO 0x21A // HID type SEL -#define HID_CONSUMER_AC_COPY 0x21B // HID type SEL -#define HID_CONSUMER_AC_CUT 0x21C // HID type SEL -#define HID_CONSUMER_AC_PASTE 0x21D // HID type SEL -#define HID_CONSUMER_AC_SELECT_ALL 0x21E // HID type SEL -#define HID_CONSUMER_AC_FIND 0x21F // HID type SEL -#define HID_CONSUMER_AC_FIND_AND_REPLACE 0x220 // HID type SEL -#define HID_CONSUMER_AC_SEARCH 0x221 // HID type SEL -#define HID_CONSUMER_AC_GO_TO 0x222 // HID type SEL -#define HID_CONSUMER_AC_HOME 0x223 // HID type SEL -#define HID_CONSUMER_AC_BACK 0x224 // HID type SEL -#define HID_CONSUMER_AC_FORWARD 0x225 // HID type SEL -#define HID_CONSUMER_AC_STOP 0x226 // HID type SEL -#define HID_CONSUMER_AC_REFRESH 0x227 // HID type SEL -#define HID_CONSUMER_AC_PREVIOUS_LINK 0x228 // HID type SEL -#define HID_CONSUMER_AC_NEXT_LINK 0x229 // HID type SEL -#define HID_CONSUMER_AC_BOOKMARKS 0x22A // HID type SEL -#define HID_CONSUMER_AC_HISTORY 0x22B // HID type SEL -#define HID_CONSUMER_AC_SUBSCRIPTIONS 0x22C // HID type SEL -#define HID_CONSUMER_AC_ZOOM_IN 0x22D // HID type SEL -#define HID_CONSUMER_AC_ZOOM_OUT 0x22E // HID type SEL -#define HID_CONSUMER_AC_ZOOM 0x22F // HID type LC -#define HID_CONSUMER_AC_FULL_SCREEN_VIEW 0x230 // HID type SEL -#define HID_CONSUMER_AC_NORMAL_VIEW 0x231 // HID type SEL -#define HID_CONSUMER_AC_VIEW_TOGGLE 0x232 // HID type SEL -#define HID_CONSUMER_AC_SCROLL_UP 0x233 // HID type SEL -#define HID_CONSUMER_AC_SCROLL_DOWN 0x234 // HID type SEL -#define HID_CONSUMER_AC_SCROLL 0x235 // HID type LC -#define HID_CONSUMER_AC_PAN_LEFT 0x236 // HID type SEL -#define HID_CONSUMER_AC_PAN_RIGHT 0x237 // HID type SEL -#define HID_CONSUMER_AC_PAN 0x238 // HID type LC -#define HID_CONSUMER_AC_NEW_WINDOW 0x239 // HID type SEL -#define HID_CONSUMER_AC_TILE_HORIZONTALLY 0x23A // HID type SEL -#define HID_CONSUMER_AC_TILE_VERTICALLY 0x23B // HID type SEL -#define HID_CONSUMER_AC_FORMAT 0x23C // HID type SEL -#define HID_CONSUMER_AC_EDIT 0x23D // HID type SEL -#define HID_CONSUMER_AC_BOLD 0x23E // HID type SEL -#define HID_CONSUMER_AC_ITALICS 0x23F // HID type SEL -#define HID_CONSUMER_AC_UNDERLINE 0x240 // HID type SEL -#define HID_CONSUMER_AC_STRIKETHROUGH 0x241 // HID type SEL -#define HID_CONSUMER_AC_SUBSCRIPT 0x242 // HID type SEL -#define HID_CONSUMER_AC_SUPERSCRIPT 0x243 // HID type SEL -#define HID_CONSUMER_AC_ALL_CAPS 0x244 // HID type SEL -#define HID_CONSUMER_AC_ROTATE 0x245 // HID type SEL -#define HID_CONSUMER_AC_RESIZE 0x246 // HID type SEL -#define HID_CONSUMER_AC_FLIP_HORIZONTAL 0x247 // HID type SEL -#define HID_CONSUMER_AC_FLIP_VERTICAL 0x248 // HID type SEL -#define HID_CONSUMER_AC_MIRROR_HORIZONTAL 0x249 // HID type SEL -#define HID_CONSUMER_AC_MIRROR_VERTICAL 0x24A // HID type SEL -#define HID_CONSUMER_AC_FONT_SELECT 0x24B // HID type SEL -#define HID_CONSUMER_AC_FONT_COLOR 0x24C // HID type SEL -#define HID_CONSUMER_AC_FONT_SIZE 0x24D // HID type SEL -#define HID_CONSUMER_AC_JUSTIFY_LEFT 0x24E // HID type SEL -#define HID_CONSUMER_AC_JUSTIFY_CENTER_H 0x24F // HID type SEL -#define HID_CONSUMER_AC_JUSTIFY_RIGHT 0x250 // HID type SEL -#define HID_CONSUMER_AC_JUSTIFY_BLOCK_H 0x251 // HID type SEL -#define HID_CONSUMER_AC_JUSTIFY_TOP 0x252 // HID type SEL -#define HID_CONSUMER_AC_JUSTIFY_CENTER_V 0x253 // HID type SEL -#define HID_CONSUMER_AC_JUSTIFY_BOTTOM 0x254 // HID type SEL -#define HID_CONSUMER_AC_JUSTIFY_BLOCK_V 0x255 // HID type SEL -#define HID_CONSUMER_AC_INDENT_DECREASE 0x256 // HID type SEL -#define HID_CONSUMER_AC_INDENT_INCREASE 0x257 // HID type SEL -#define HID_CONSUMER_AC_NUMBERED_LIST 0x258 // HID type SEL -#define HID_CONSUMER_AC_RESTART_NUMBERING 0x259 // HID type SEL -#define HID_CONSUMER_AC_BULLETED_LIST 0x25A // HID type SEL -#define HID_CONSUMER_AC_PROMOTE 0x25B // HID type SEL -#define HID_CONSUMER_AC_DEMOTE 0x25C // HID type SEL -#define HID_CONSUMER_AC_YES 0x25D // HID type SEL -#define HID_CONSUMER_AC_NO 0x25E // HID type SEL -#define HID_CONSUMER_AC_CANCEL 0x25F // HID type SEL -#define HID_CONSUMER_AC_CATALOG 0x260 // HID type SEL -#define HID_CONSUMER_AC_BUY_SLASH_CHECKOUT 0x261 // HID type SEL -#define HID_CONSUMER_AC_ADD_TO_CART 0x262 // HID type SEL -#define HID_CONSUMER_AC_EXPAND 0x263 // HID type SEL -#define HID_CONSUMER_AC_EXPAND_ALL 0x264 // HID type SEL -#define HID_CONSUMER_AC_COLLAPSE 0x265 // HID type SEL -#define HID_CONSUMER_AC_COLLAPSE_ALL 0x266 // HID type SEL -#define HID_CONSUMER_AC_PRINT_PREVIEW 0x267 // HID type SEL -#define HID_CONSUMER_AC_PASTE_SPECIAL 0x268 // HID type SEL -#define HID_CONSUMER_AC_INSERT_MODE 0x269 // HID type SEL -#define HID_CONSUMER_AC_DELETE 0x26A // HID type SEL -#define HID_CONSUMER_AC_LOCK 0x26B // HID type SEL -#define HID_CONSUMER_AC_UNLOCK 0x26C // HID type SEL -#define HID_CONSUMER_AC_PROTECT 0x26D // HID type SEL -#define HID_CONSUMER_AC_UNPROTECT 0x26E // HID type SEL -#define HID_CONSUMER_AC_ATTACH_COMMENT 0x26F // HID type SEL -#define HID_CONSUMER_AC_DELETE_COMMENT 0x270 // HID type SEL -#define HID_CONSUMER_AC_VIEW_COMMENT 0x271 // HID type SEL -#define HID_CONSUMER_AC_SELECT_WORD 0x272 // HID type SEL -#define HID_CONSUMER_AC_SELECT_SENTENCE 0x273 // HID type SEL -#define HID_CONSUMER_AC_SELECT_PARAGRAPH 0x274 // HID type SEL -#define HID_CONSUMER_AC_SELECT_COLUMN 0x275 // HID type SEL -#define HID_CONSUMER_AC_SELECT_ROW 0x276 // HID type SEL -#define HID_CONSUMER_AC_SELECT_TABLE 0x277 // HID type SEL -#define HID_CONSUMER_AC_SELECT_OBJECT 0x278 // HID type SEL -#define HID_CONSUMER_AC_REDO_SLASH_REPEAT 0x279 // HID type SEL -#define HID_CONSUMER_AC_SORT 0x27A // HID type SEL -#define HID_CONSUMER_AC_SORT_ASCENDING 0x27B // HID type SEL -#define HID_CONSUMER_AC_SORT_DESCENDING 0x27C // HID type SEL -#define HID_CONSUMER_AC_FILTER 0x27D // HID type SEL -#define HID_CONSUMER_AC_SET_CLOCK 0x27E // HID type SEL -#define HID_CONSUMER_AC_VIEW_CLOCK 0x27F // HID type SEL -#define HID_CONSUMER_AC_SELECT_TIME_ZONE 0x280 // HID type SEL -#define HID_CONSUMER_AC_EDIT_TIME_ZONES 0x281 // HID type SEL -#define HID_CONSUMER_AC_SET_ALARM 0x282 // HID type SEL -#define HID_CONSUMER_AC_CLEAR_ALARM 0x283 // HID type SEL -#define HID_CONSUMER_AC_SNOOZE_ALARM 0x284 // HID type SEL -#define HID_CONSUMER_AC_RESET_ALARM 0x285 // HID type SEL -#define HID_CONSUMER_AC_SYNCHRONIZE 0x286 // HID type SEL -#define HID_CONSUMER_AC_SEND_SLASH_RECEIVE 0x287 // HID type SEL -#define HID_CONSUMER_AC_SEND_TO 0x288 // HID type SEL -#define HID_CONSUMER_AC_REPLY 0x289 // HID type SEL -#define HID_CONSUMER_AC_REPLY_ALL 0x28A // HID type SEL -#define HID_CONSUMER_AC_FORWARD_MSG 0x28B // HID type SEL -#define HID_CONSUMER_AC_SEND 0x28C // HID type SEL -#define HID_CONSUMER_AC_ATTACH_FILE 0x28D // HID type SEL -#define HID_CONSUMER_AC_UPLOAD 0x28E // HID type SEL -#define HID_CONSUMER_AC_DOWNLOAD_(SAVE_TARGET_AS) 0x28F // HID type SEL -#define HID_CONSUMER_AC_SET_BORDERS 0x290 // HID type SEL -#define HID_CONSUMER_AC_INSERT_ROW 0x291 // HID type SEL -#define HID_CONSUMER_AC_INSERT_COLUMN 0x292 // HID type SEL -#define HID_CONSUMER_AC_INSERT_FILE 0x293 // HID type SEL -#define HID_CONSUMER_AC_INSERT_PICTURE 0x294 // HID type SEL -#define HID_CONSUMER_AC_INSERT_OBJECT 0x295 // HID type SEL -#define HID_CONSUMER_AC_INSERT_SYMBOL 0x296 // HID type SEL -#define HID_CONSUMER_AC_SAVE_AND_CLOSE 0x297 // HID type SEL -#define HID_CONSUMER_AC_RENAME 0x298 // HID type SEL -#define HID_CONSUMER_AC_MERGE 0x299 // HID type SEL -#define HID_CONSUMER_AC_SPLIT 0x29A // HID type SEL -#define HID_CONSUMER_AC_DISRIBUTE_HORIZONTALLY 0x29B // HID type SEL -#define HID_CONSUMER_AC_DISTRIBUTE_VERTICALLY 0x29C // HID type SEL - -#endif // __HIDTables__ diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.cpp b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.cpp deleted file mode 100644 index 66bcd997b2..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.cpp +++ /dev/null @@ -1,407 +0,0 @@ -/* -Keyboard.cpp -Copyright (c) 2005-2014 Arduino. All right reserved. - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -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 "Keyboard.h" - -//================================================================================ -//================================================================================ -// Keyboard - -Keyboard_ Keyboard; - -void Keyboard_::sendReport(HID_KeyboardReport_Data_t* keys) -{ - HID_SendReport(HID_REPORTID_KEYBOARD, keys, sizeof(keys)); -} - -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 -}; - -// 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 & SHIFT) { // it's a capital letter or other character reached with shift - _keyReport.modifiers |= 0x02; // the left shift modifier - k = k ^ SHIFT; - } - } - - // 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 & SHIFT) { // it's a capital letter or other character reached with shift - _keyReport.modifiers &= ~(0x02); // the left shift modifier - k = k ^ SHIFT; - } - } - - // 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) -{ - // release all keys - memset(&_keyReport, 0x00, sizeof(_keyReport)); - sendReport(&_keyReport); -} - -size_t Keyboard_::write(uint8_t c) -{ - uint8_t p = press(c); // Keydown - release(c); // Keyup - return p; // just return the result of press() since release() almost always returns 1 -} - - -// pressKeycode() 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 releaseKeycode(), releaseAll(), or otherwise clear the report and resend. -size_t Keyboard_::pressKeycode(uint8_t k) -{ - if (!addKeycodeToReport(k)) { - return 0; - } - sendReport(&_keyReport); -} - -size_t Keyboard_::addKeycodeToReport(uint8_t k) -{ - uint8_t index = 0; - uint8_t done = 0; - - if ((k >= HID_KEYBOARD_LEFT_CONTROL) && (k <= HID_KEYBOARD_RIGHT_GUI)) { - // it's a modifier key - _keyReport.modifiers |= (0x01 << (k - HID_KEYBOARD_LEFT_CONTROL)); - } - else { - // it's some other key: - // Add k to the key report only if it's not already present - // and if there is an empty slot. - for (index = 0; index < sizeof(_keyReport.keys); index++) { - if (_keyReport.keys[index] != k) { // is k already in list? - if (0 == _keyReport.keys[index]) { // have we found an empty slot? - _keyReport.keys[index] = k; - done = 1; - break; - } - } - else { - done = 1; - break; - } - - } - - // use separate variable to check if slot was found - // for style reasons - we do not know how the compiler - // handles the for() index when it leaves the loop - if (0 == done) { - setWriteError(); - return 0; - } - } - - return 1; -} - - -// releaseKeycode() 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. -// When send is set to FALSE (= 0) no sendReport() is executed. This comes in -// handy when combining key releases (e.g. SHIFT+A). -size_t Keyboard_::releaseKeycode(uint8_t k) -{ - if (!removeKeycodeFromReport(k)) { - return 0; - } - sendReport(&_keyReport); -} - -size_t Keyboard_::removeKeycodeFromReport(uint8_t k) -{ - uint8_t indexA; - uint8_t indexB; - uint8_t count; - - if ((k >= HID_KEYBOARD_LEFT_CONTROL) && (k <= HID_KEYBOARD_RIGHT_GUI)) { - // it's a modifier key - _keyReport.modifiers = _keyReport.modifiers & (~(0x01 << (k - HID_KEYBOARD_LEFT_CONTROL))); - } - else { - // it's some other key: - // 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 (indexA = 0; indexA < sizeof(_keyReport.keys); indexA++) { - if (_keyReport.keys[indexA] == k) { - _keyReport.keys[indexA] = 0; - } - } - - // finally rearrange the keys list so that the free (= 0x00) are at the - // end of the keys list - some implementations stop for keys at the - // first occurence of an 0x00 in the keys list - // so (0x00)(0x01)(0x00)(0x03)(0x02)(0x00) becomes - // (0x01)(0x03)(0x02)(0x00)(0x00)(0x00) - count = 0; // holds the number of zeros we've found - indexA = 0; - while ((indexA + count) < sizeof(_keyReport.keys)) { - if (0 == _keyReport.keys[indexA]) { - count++; // one more zero - for (indexB = indexA; indexB < sizeof(_keyReport.keys) - count; indexB++) { - _keyReport.keys[indexB] = _keyReport.keys[indexB + 1]; - } - _keyReport.keys[sizeof(_keyReport.keys) - count] = 0; - } - else { - indexA++; // one more non-zero - } - } - } - - return 1; -} - - -size_t Keyboard_::writeKeycode(uint8_t c) -{ - uint8_t p = pressKeycode(c); // Keydown - releaseKeycode(c); // Keyup - return (p); // just return the result of pressKeycode() since release() almost always returns 1 -} \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h deleted file mode 100644 index 41c5c6c625..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Keyboard.h +++ /dev/null @@ -1,196 +0,0 @@ -/* -Keyboard.h -Copyright (c) 2005-2014 Arduino. All right reserved. - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -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 __KEYBOARDAPI__ -#define __KEYBOARDAPI__ - -// to access the HID_SendReport via USBAPI.h, report number and the Print class -#include "Arduino.h" - -//================================================================================ -//================================================================================ -// Keyboard - -#define KEY_PRINT 0xCE -#define KEY_NUM_LOCK 0xDB -#define KEY_SCROLL_LOCK 0xCF -#define KEY_PAUSE 0xD0 -#define KEY_MENU 0xED // 0x65 in the official docs - -#define KEY_LEFT_CTRL 0x80 -#define KEY_LEFT_SHIFT 0x81 -#define KEY_LEFT_ALT 0x82 -#define KEY_LEFT_GUI 0x83 -#define KEY_LEFT_WINDOWS KEY_LEFT_GUI -#define KEY_RIGHT_CTRL 0x84 -#define KEY_RIGHT_SHIFT 0x85 -#define KEY_RIGHT_ALT 0x86 -#define KEY_RIGHT_GUI 0x87 -#define KEY_RIGHT_WINDOWS KEY_RIGHT_GUI - -#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 - -#define LED_NUM_LOCK 0x01 -#define LED_CAPS_LOCK 0x02 -#define LED_SCROLL_LOCK 0x04 - -//Raw Keyboard definitions -#define RAW_KEYBOARD_LEFT_CTRL (1 << 0) -#define RAW_KEYBOARD_LEFT_SHIFT (1 << 1) -#define RAW_KEYBOARD_LEFT_ALT (1 << 2) -#define RAW_KEYBOARD_LEFT_GUI (1 << 3) -#define RAW_KEYBOARD_RIGHT_CTRL (1 << 4) -#define RAW_KEYBOARD_RIGHT_SHIFT (1 << 5) -#define RAW_KEYBOARD_RIGHT_ALT (1 << 6) -#define RAW_KEYBOARD_RIGHT_GUI (1 << 7) - -#define RAW_KEYBOARD_KEY(key) ((key>='a' && key<='z') ? (0x04 + key-'a') :\ -(key>='A' && key<='Z') ? (0x04 + key-'A') : (key>='1' && key<='9') ? (0x1E + key-'1') : 0x27) - -#define RAW_KEYBOARD_UP_ARROW 0x52 -#define RAW_KEYBOARD_DOWN_ARROW 0x51 -#define RAW_KEYBOARD_LEFT_ARROW 0x50 -#define RAW_KEYBOARD_RIGHT_ARROW 0x4F -#define RAW_KEYBOARD_SPACEBAR 0x2C -#define RAW_KEYBOARD_BACKSPACE 0x2A -#define RAW_KEYBOARD_TAB 0x2B -#define RAW_KEYBOARD_RETURN 0x28 -#define RAW_KEYBOARD_ESC 0x29 -#define RAW_KEYBOARD_INSERT 0x49 -#define RAW_KEYBOARD_DELETE 0x4C -#define RAW_KEYBOARD_PAGE_UP 0x4B -#define RAW_KEYBOARD_PAGE_DOWN 0x4E -#define RAW_KEYBOARD_HOME 0x4A -#define RAW_KEYBOARD_END 0x4D -#define RAW_KEYBOARD_CAPS_LOCK 0x39 -#define RAW_KEYBOARD_F1 0x3A -#define RAW_KEYBOARD_F2 0x3B -#define RAW_KEYBOARD_F3 0x3C -#define RAW_KEYBOARD_F4 0x3D -#define RAW_KEYBOARD_F5 0x3E -#define RAW_KEYBOARD_F6 0x3F -#define RAW_KEYBOARD_F7 0x40 -#define RAW_KEYBOARD_F8 0x41 -#define RAW_KEYBOARD_F9 0x42 -#define RAW_KEYBOARD_F10 0x43 -#define RAW_KEYBOARD_F11 0x44 -#define RAW_KEYBOARD_F12 0x45 -#define RAW_KEYBOARD_PRINT 0x46 -#define RAW_KEYBOARD_SCROLL_LOCK 0x47 -#define RAW_KEYBOARD_PAUSE 0x48 - -typedef union{ - // Low level key report: up to 6 keys and shift, ctrl etc at once - uint8_t whole8[]; - uint16_t whole16[]; - uint32_t whole32[]; - struct{ - uint8_t modifiers; - uint8_t reserved; - uint8_t keys[6]; - }; -} HID_KeyboardReport_Data_t; - -class Keyboard_ : public Print -{ -protected: - HID_KeyboardReport_Data_t _keyReport; - void sendReport(HID_KeyboardReport_Data_t* keys); -public: - inline Keyboard_(void){ - // empty - } - - inline void begin(void){ - // edit by NicoHood - end(); - } - - inline void end(void){ - // edit by NicoHood - releaseAll(); - } - - size_t write(uint8_t k); - size_t press(uint8_t k); - size_t release(uint8_t k); - void releaseAll(void); - - size_t writeKeycode(uint8_t k); - size_t pressKeycode(uint8_t k); - size_t releaseKeycode(uint8_t k); - size_t addKeycodeToReport(uint8_t k); - size_t removeKeycodeFromReport(uint8_t k); - -#if defined(HID_KEYBOARD_LEDS_ENABLED) - inline uint8_t getLeds(void){ return hid_keyboard_leds; } -#endif -}; -extern Keyboard_ Keyboard; - -#endif diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.cpp b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.cpp deleted file mode 100644 index 779d58f349..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* -Mouse.cpp -Copyright (c) 2005-2014 Arduino. All right reserved. - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -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 "Mouse.h" - -//================================================================================ -//================================================================================ -// Mouse - -Mouse_ Mouse; - diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.h deleted file mode 100644 index 0ec0a1b3d8..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Mouse.h +++ /dev/null @@ -1,156 +0,0 @@ -/* -Mouse.h -Copyright (c) 2005-2014 Arduino. All right reserved. - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -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 __MOUSEAPI__ -#define __MOUSEAPI__ - -// to access the HID_SendReport via USBAPI.h and report number -#include "Arduino.h" - -//================================================================================ -//================================================================================ -// Mouse - -#define MOUSE_LEFT (1 << 0) -#define MOUSE_RIGHT (1 << 1) -#define MOUSE_MIDDLE (1 << 2) -#define MOUSE_PREV (1 << 3) -#define MOUSE_NEXT (1 << 4) -// actually this mouse report has 8 buttons (for smaller descriptor) -// but the last 3 wont do anything from what I tested -#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE | MOUSE_PREV | MOUSE_NEXT) - -typedef union{ - // mouse report: 8 buttons, position, wheel - uint8_t whole8[]; - uint16_t whole16[]; - uint32_t whole32[]; - struct{ - uint8_t buttons; - int8_t xAxis; - int8_t yAxis; - int8_t wheel; - }; -} HID_MouseReport_Data_t; - -typedef union{ - // mouse absolute report: 2 absolute axis - uint8_t whole8[]; - uint16_t whole16[]; - uint32_t whole32[]; - struct{ - int16_t xAxis; - int16_t yAxis; - }; -} HID_MouseAbsoluteReport_Data_t; - -class Mouse_ -{ -private: - uint8_t _buttons; - inline void buttons(uint8_t b){ - if (b != _buttons){ - _buttons = b; - move(0, 0, 0); - } - } -public: - inline Mouse_(void) { - // removed this to avoid creating an instance of Mouse if not needed - // the user should call begin first. - //: _buttons(0){ - // empty - } - - inline void begin(void){ - // release all buttons - end(); - } - - inline void end(void){ - _buttons = 0; - move(0, 0, 0); - } - - inline void click(uint8_t b = MOUSE_LEFT){ - _buttons = b; - move(0, 0, 0); - _buttons = 0; - move(0, 0, 0); - } - - inline void move(signed char x, signed char y, signed char wheel = 0){ - u8 m[4]; - m[0] = _buttons; - m[1] = x; - m[2] = y; - m[3] = wheel; - HID_SendReport(HID_REPORTID_MOUSE, m, 4); - } - - inline void press(uint8_t b = MOUSE_LEFT){ - // press LEFT by default - buttons(_buttons | b); - } - - inline void release(uint8_t b = MOUSE_LEFT){ - // release LEFT by default - buttons(_buttons & ~b); - } - - inline bool isPressed(uint8_t b = MOUSE_LEFT){ - // check LEFT by default - if ((b & _buttons) > 0) - return true; - return false; - } -#ifdef HID_MOUSE_ABSOLUTE_API_ENABLE - inline void moveTo(int16_t x, int16_t y){ - // uses different report ID and different HID mouse device! - uint32_t pos = ((uint32_t)y << 16) | x; - HID_SendReport(HID_REPORTID_MOUSE_ABSOLUTE, &pos, sizeof(pos)); - } -#endif -}; -extern Mouse_ Mouse; - -#endif diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/RawHID.cpp b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/RawHID.cpp deleted file mode 100644 index b5a168740a..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/RawHID.cpp +++ /dev/null @@ -1,30 +0,0 @@ -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -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 "RawHID.h" - -//================================================================================ -// RawHID -//================================================================================ - -RawHID_ RawHID; \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/RawHID.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/RawHID.h deleted file mode 100644 index f77a36880f..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/RawHID.h +++ /dev/null @@ -1,79 +0,0 @@ -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -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 __RAWHIDAPI__ -#define __RAWHIDAPI__ - -// to access the HID_SendReport via USBAPI.h and report number -#include "Arduino.h" - -//================================================================================ -// RawHID -//================================================================================ - -typedef union{ -// a RAWHID_TX_SIZE byte buffer for rx or tx -uint8_t whole8[]; -uint16_t whole16[]; -uint32_t whole32[]; -uint8_t buff[RAWHID_TX_SIZE]; -} HID_RawKeyboardReport_Data_t; - -class RawHID_ : public Print{ -public: - inline RawHID_(void){ - // empty - } - - inline void begin(void){ - // empty - } - - inline void end(void){ - // empty - } - - using Print::write; // to get the String version of write - inline size_t write(uint8_t b){ - write(&b, 1); - } - - inline size_t write(const uint8_t *buffer, size_t size){ - size_t bytesleft = size; - // first work through the buffer thats already there - while (bytesleft >= RAWHID_RX_SIZE){ - HID_SendReport(HID_REPORTID_RAWHID, &buffer[size - bytesleft], RAWHID_RX_SIZE); - bytesleft -= RAWHID_RX_SIZE; - } - // write down the other bytes and fill with zeros - if (bytesleft){ - uint8_t rest[RAWHID_RX_SIZE]; - memcpy(rest, &buffer[size - bytesleft], bytesleft); - memset(&rest[bytesleft], 0, RAWHID_RX_SIZE - bytesleft); - HID_SendReport(HID_REPORTID_RAWHID, &rest, RAWHID_RX_SIZE); - } - } -}; -extern RawHID_ RawHID; - -#endif \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBAPI.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBAPI.h deleted file mode 100644 index fe0156731e..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBAPI.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - USBAPI.h - Copyright (c) 2005-2014 Arduino. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. -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 __USBAPI__ -#define __USBAPI__ - -#include -#include -#include -#include -#include - -typedef unsigned char u8; -typedef unsigned short u16; -typedef unsigned long u32; - -#include "Arduino.h" - -// edit by NicoHood -// this definitions is usefull if you want to reduce the EP_SIZE to 16 -// at the moment only 64 and 16 as EP_SIZE for all EPs are supported except the control endpoint -#ifndef USB_EP_SIZE -#define USB_EP_SIZE 64 -#endif - -#if defined(USBCON) - -#include "USBDesc.h" -#include "USBCore.h" - -//================================================================================ -//================================================================================ -// USB - -class USBDevice_ -{ -public: - USBDevice_(); - bool configured(); - - void attach(); - void detach(); // Serial port goes down too... - void poll(); - bool wakeupHost(); // returns false, when wakeup cannot be processed -}; -extern USBDevice_ USBDevice; - -//================================================================================ -//================================================================================ -// 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); -void CDC_LineEncodingEvent(void); -void CDC_LineStateEvent(void); - -//================================================================================ -//================================================================================ - -#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) */ diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBCore.cpp b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBCore.cpp deleted file mode 100644 index 30318273e3..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBCore.cpp +++ /dev/null @@ -1,881 +0,0 @@ -/* Copyright (c) 2010, Peter Barrett -** -** Sleep/Wakeup/SystemControl support added by Michael Dreher -** -** 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. -*/ - -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. -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 "USBAPI.h" - -#if defined(USBCON) - -#define EP_TYPE_CONTROL (0x00) -#define EP_TYPE_BULK_IN ((1< len) - n = len; - { - LockEP lock(ep); - // Frame may have been released by the SOF interrupt handler - if (!ReadWriteAllowed()) - continue; - len -= n; - 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 -// edit by NicoHood -#define EP_SINGLE_16 0x12 - -static -void InitEP(u8 index, u8 type, u8 size) -{ - UENUM = index; - UECONX = (1 << EPEN); - UECFG0X = type; - UECFG1X = size; -} - -static -void InitEndpoints() -{ - for (u8 i = 1; i < sizeof(_initEndpoints); i++) - { - UENUM = i; - UECONX = (1 << EPEN); - UECFG0X = pgm_read_byte(_initEndpoints + i); - // edit by NicoHood -#if USB_EP_SIZE == 16 - UECFG1X = EP_SINGLE_16; -#elif USB_EP_SIZE == 64 - UECFG1X = EP_DOUBLE_64; -#else -#error Unsupported value for USB_EP_SIZE -#endif - } - 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; -} - -// Send a USB descriptor string. The string is stored in PROGMEM as a -// plain ASCII string but is sent out as UTF-16 with the correct 2-byte -// prefix -static bool USB_SendStringDescriptor(const u8*string_P, u8 string_len) { - SendControl(2 + string_len * 2); - SendControl(3); - for (u8 i = 0; i < string_len; i++) { - bool r = SendControl(pgm_read_byte(&string_P[i])); - r &= SendControl(0); // high byte - if (!r) { - return false; - } - } - return true; -} - -// 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 - - 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) { - return USB_SendStringDescriptor(STRING_PRODUCT, strlen(USB_PRODUCT)); - } - else if (setup.wValueL == IMANUFACTURER) { - return USB_SendStringDescriptor(STRING_MANUFACTURER, strlen(USB_MANUFACTURER)); - } - else - return false; - } - - if (desc_addr == 0) - return false; - u8 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; - u16 wValue = (setup.wValueH << 8) | setup.wValueL; - if (GET_STATUS == r) - { - if (requestType == (REQUEST_DEVICETOHOST | REQUEST_STANDARD | REQUEST_DEVICE)) - { - Send8(_usbCurrentStatus); - Send8(0); - } - else - { - // TODO: handle the HALT state of an endpoint here - // see "Figure 9-6. Information Returned by a GetStatus() Request to an Endpoint" in usb_20.pdf for more information - Send8(0); - Send8(0); - } - } - else if (CLEAR_FEATURE == r) - { - if ((requestType == (REQUEST_HOSTTODEVICE | REQUEST_STANDARD | REQUEST_DEVICE)) - && (wValue == DEVICE_REMOTE_WAKEUP)) - { - _usbCurrentStatus &= ~FEATURE_REMOTE_WAKEUP_ENABLED; - } - } - else if (SET_FEATURE == r) - { - if ((requestType == (REQUEST_HOSTTODEVICE | REQUEST_STANDARD | REQUEST_DEVICE)) - && (wValue == DEVICE_REMOTE_WAKEUP)) - { - _usbCurrentStatus |= FEATURE_REMOTE_WAKEUP_ENABLED; - } - } - 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(); -} - -static inline void USB_ClockDisable() -{ -#if defined(OTGPADE) - USBCON = (USBCON & ~(1 << OTGPADE)) | (1 << FRZCLK); // freeze clock and disable VBUS Pad -#else // u2 Series - USBCON = (1 << FRZCLK); // freeze clock -#endif - PLLCSR &= ~(1 << PLLE); // stop PLL -} - -static inline void USB_ClockEnable() -{ -#if defined(UHWCON) - UHWCON |= (1 << UVREGE); // power internal reg -#endif - USBCON = (1 << USBE) | (1 << FRZCLK); // clock frozen, usb enabled - - // ATmega32U4 -#if defined(PINDIV) -#if F_CPU == 16000000UL - PLLCSR |= (1 << PINDIV); // Need 16 MHz xtal -#elif F_CPU == 8000000UL - PLLCSR &= ~(1 << PINDIV); // Need 8 MHz xtal -#else -#error "Clock rate of F_CPU not supported" -#endif - -#elif defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega8U2__) - // for the u2 Series the datasheet is confusing. On page 40 its called PINDIV and on page 290 its called PLLP0 -#if F_CPU == 16000000UL - // Need 16 MHz xtal - PLLCSR |= (1 << PLLP0); -#elif F_CPU == 8000000UL - // Need 8 MHz xtal - PLLCSR &= ~(1 << PLLP0); -#endif - - // AT90USB646, AT90USB647, AT90USB1286, AT90USB1287 -#elif defined(PLLP2) -#if F_CPU == 16000000UL -#if defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) - // For Atmel AT90USB128x only. Do not use with Atmel AT90USB64x. - PLLCSR = (PLLCSR & ~(1 << PLLP1)) | ((1 << PLLP2) | (1 << PLLP0)); // Need 16 MHz xtal -#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) - // For AT90USB64x only. Do not use with AT90USB128x. - PLLCSR = (PLLCSR & ~(1 << PLLP0)) | ((1 << PLLP2) | (1 << PLLP1)); // Need 16 MHz xtal -#else -#error "USB Chip not supported, please defined method of USB PLL initialization" -#endif -#elif F_CPU == 8000000UL - // for Atmel AT90USB128x and AT90USB64x - PLLCSR = (PLLCSR & ~(1 << PLLP2)) | ((1 << PLLP1) | (1 << PLLP0)); // Need 8 MHz xtal -#else -#error "Clock rate of F_CPU not supported" -#endif -#else -#error "USB Chip not supported, please defined method of USB PLL initialization" -#endif - - PLLCSR |= (1 << PLLE); - while (!(PLLCSR & (1 << PLOCK))) // wait for lock pll - { - } - - // Some tests on specific versions of macosx (10.7.3), reported some - // strange behaviors when the board is reset using the serial - // port touch at 1200 bps. This delay fixes this behavior. - delay(1); -#if defined(OTGPADE) - USBCON = (USBCON & ~(1 << FRZCLK)) | (1 << OTGPADE); // start USB clock, enable VBUS Pad -#else - USBCON &= ~(1 << FRZCLK); // start USB clock -#endif - -#if defined(RSTCPU) -#if defined(LSM) - UDCON &= ~((1 << RSTCPU) | (1 << LSM) | (1 << RMWKUP) | (1 << DETACH)); // enable attach resistor, set full speed mode -#else // u2 Series - UDCON &= ~((1 << RSTCPU) | (1 << RMWKUP) | (1 << DETACH)); // enable attach resistor, set full speed mode -#endif -#else - // AT90USB64x and AT90USB128x don't have RSTCPU - UDCON &= ~((1 << LSM) | (1 << RMWKUP) | (1 << DETACH)); // enable attach resistor, set full speed mode -#endif -} - -// General interrupt -ISR(USB_GEN_vect) -{ - u8 udint = UDINT; - UDINT &= ~((1 << EORSTI) | (1 << SOFI)); // clear the IRQ flags for the IRQs which are handled here, except WAKEUPI and SUSPI (see below) - - // 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 -#endif - - // check whether the one-shot period has elapsed. if so, turn off the LED - if (TxLEDPulse && !(--TxLEDPulse)) - TXLED0; - if (RxLEDPulse && !(--RxLEDPulse)) - RXLED0; - } - - // the WAKEUPI interrupt is triggered as soon as there are non-idle patterns on the data - // lines. Thus, the WAKEUPI interrupt can occur even if the controller is not in the "suspend" mode. - // Therefore the we enable it only when USB is suspended - if (udint & (1 << WAKEUPI)) - { - UDIEN = (UDIEN & ~(1 << WAKEUPE)) | (1 << SUSPE); // Disable interrupts for WAKEUP and enable interrupts for SUSPEND - - //TODO - // WAKEUPI shall be cleared by software (USB clock inputs must be enabled before). - //USB_ClockEnable(); - UDINT &= ~(1 << WAKEUPI); - _usbSuspendState = (_usbSuspendState & ~(1 << SUSPI)) | (1 << WAKEUPI); - } - else if (udint & (1 << SUSPI)) // only one of the WAKEUPI / SUSPI bits can be active at time - { - UDIEN = (UDIEN & ~(1 << SUSPE)) | (1 << WAKEUPE); // Disable interrupts for SUSPEND and enable interrupts for WAKEUP - - //TODO - //USB_ClockDisable(); - - UDINT &= ~((1 << WAKEUPI) | (1 << SUSPI)); // clear any already pending WAKEUP IRQs and the SUSPI request - _usbSuspendState = (_usbSuspendState & ~(1 << WAKEUPI)) | (1 << SUSPI); - } -} - -// 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; - _usbCurrentStatus = 0; - _usbSuspendState = 0; - USB_ClockEnable(); - - UDINT &= ~((1 << WAKEUPI) | (1 << SUSPI)); // clear already pending WAKEUP / SUSPEND requests - UDIEN = (1 << EORSTE) | (1 << SOFE) | (1 << SUSPE); // Enable interrupts for EOR (End of Reset), SOF (start of frame) and SUSPEND - - TX_RX_LED_INIT; -} - -void USBDevice_::detach() -{ -} - -// Check for interrupts -// TODO: VBUS detection -bool USBDevice_::configured() -{ - return _usbConfiguration; -} - -void USBDevice_::poll() -{ -} - -bool USBDevice_::wakeupHost() -{ - // clear any previous wakeup request which might have been set but could be processed at that time - // e.g. because the host was not suspended at that time - UDCON &= ~(1 << RMWKUP); - - if (!(UDCON & (1 << RMWKUP)) - && (_usbSuspendState & (1 << SUSPI)) - && (_usbCurrentStatus & FEATURE_REMOTE_WAKEUP_ENABLED)) - { - // This short version will only work, when the device has not been suspended. Currently the - // Arduino core doesn't handle SUSPEND at all, so this is ok. - USB_ClockEnable(); - UDCON |= (1 << RMWKUP); // send the wakeup request - return true; - } - - return false; -} - -#endif /* if defined(USBCON) */ diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBCore.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBCore.h deleted file mode 100644 index f1ed5890f9..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBCore.h +++ /dev/null @@ -1,361 +0,0 @@ -// 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. -*/ - -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. -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 __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 CDC_CONTROL_LINE_OUT_DTR (1 << 0) -#define CDC_CONTROL_LINE_OUT_RTS (1 << 1) - -#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 - -// usb_20.pdf Table 9.6 Standard Feature Selectors -#define DEVICE_REMOTE_WAKEUP 1 -#define ENDPOINT_HALT 2 -#define TEST_MODE 3 -// usb_20.pdf Figure 9-4. Information Returned by a GetStatus() Request to a Device -#define FEATURE_SELFPOWERED_ENABLED (1 << 0) -#define FEATURE_REMOTE_WAKEUP_ENABLED (1 << 1) - -#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 - -// edit by NicoHood -// added new definitions for correct USB descriptors -// there are even more, these are the ones we need -#define USB_DEVICE_CLASS_IAD 0xEF -#define USB_DEVICE_SUB_CLASS_IAD 0x02 -#define USB_DEVICE_PROTOCOL_IAD 0x01 - -#define USB_DEVICE_CDC_CLASS 0x02 -#define USB_DEVICE_CDC_SUB_CLASS 0x00 -#define USB_DEVICE_CDC_PROTOCOL 0x00 // NoSpecific Protocol - -#define USB_DEVICE_NO_CLASS 0x00 -#define USB_DEVICE_NO_SUB_CLASS 0x00 -#define USB_DEVICE_NO_PROTOCOL 0x00 - -#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_REMOTE_WAKEUP, 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 } - -//================================================================================ -//================================================================================ -// Low level API - -typedef struct -{ - uint8_t bmRequestType; - uint8_t bRequest; - uint8_t wValueL; - uint8_t wValueH; - uint16_t wIndex; - uint16_t wLength; -} Setup; - -#endif \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBDesc.h b/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBDesc.h deleted file mode 100644 index d787f3ee72..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/USBDesc.h +++ /dev/null @@ -1,84 +0,0 @@ -/* 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. -*/ - -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -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. -*/ - -#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/plugins/KeyboardioHID/avr/cores/hid/Udp.h b/plugins/KeyboardioHID/avr/cores/hid/Udp.h deleted file mode 100644 index dc5644b9df..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/Udp.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * 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 -#include - -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/plugins/KeyboardioHID/avr/cores/hid/WCharacter.h b/plugins/KeyboardioHID/avr/cores/hid/WCharacter.h deleted file mode 100644 index 79733b50a5..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/WCharacter.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - 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 - -// 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/plugins/KeyboardioHID/avr/cores/hid/WInterrupts.c b/plugins/KeyboardioHID/avr/cores/hid/WInterrupts.c deleted file mode 100644 index d3fbf100e3..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/WInterrupts.c +++ /dev/null @@ -1,334 +0,0 @@ -/* -*- 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 -#include -#include -#include -#include - -#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<= 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/plugins/KeyboardioHID/avr/cores/hid/WString.cpp b/plugins/KeyboardioHID/avr/cores/hid/WString.cpp deleted file mode 100644 index dcd469d7dd..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/WString.cpp +++ /dev/null @@ -1,745 +0,0 @@ -/* - 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; -} - -String::String(const __FlashStringHelper *pstr) -{ - init(); - *this = pstr; -} - -#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[1 + 8 * sizeof(unsigned char)]; - utoa(value, buf, base); - *this = buf; -} - -String::String(int value, unsigned char base) -{ - init(); - char buf[2 + 8 * sizeof(int)]; - itoa(value, buf, base); - *this = buf; -} - -String::String(unsigned int value, unsigned char base) -{ - init(); - char buf[1 + 8 * sizeof(unsigned int)]; - utoa(value, buf, base); - *this = buf; -} - -String::String(long value, unsigned char base) -{ - init(); - char buf[2 + 8 * sizeof(long)]; - ltoa(value, buf, base); - *this = buf; -} - -String::String(unsigned long value, unsigned char base) -{ - init(); - char buf[1 + 8 * sizeof(unsigned long)]; - ultoa(value, buf, base); - *this = buf; -} - -String::String(float value, unsigned char decimalPlaces) -{ - init(); - char buf[33]; - *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf); -} - -String::String(double value, unsigned char decimalPlaces) -{ - init(); - char buf[33]; - *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf); -} - -String::~String() -{ - free(buffer); -} - -/*********************************************/ -/* Memory Management */ -/*********************************************/ - -inline void String::init(void) -{ - buffer = NULL; - capacity = 0; - len = 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; -} - -String & String::copy(const __FlashStringHelper *pstr, unsigned int length) -{ - if (!reserve(length)) { - invalidate(); - return *this; - } - len = length; - strcpy_P(buffer, (PGM_P)pstr); - 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; -} - -String & String::operator = (const __FlashStringHelper *pstr) -{ - if (pstr) copy(pstr, strlen_P((PGM_P)pstr)); - 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[1 + 3 * sizeof(unsigned char)]; - itoa(num, buf, 10); - return concat(buf, strlen(buf)); -} - -unsigned char String::concat(int num) -{ - char buf[2 + 3 * sizeof(int)]; - itoa(num, buf, 10); - return concat(buf, strlen(buf)); -} - -unsigned char String::concat(unsigned int num) -{ - char buf[1 + 3 * sizeof(unsigned int)]; - utoa(num, buf, 10); - return concat(buf, strlen(buf)); -} - -unsigned char String::concat(long num) -{ - char buf[2 + 3 * sizeof(long)]; - ltoa(num, buf, 10); - return concat(buf, strlen(buf)); -} - -unsigned char String::concat(unsigned long num) -{ - char buf[1 + 3 * sizeof(unsigned long)]; - ultoa(num, buf, 10); - return concat(buf, strlen(buf)); -} - -unsigned char String::concat(float num) -{ - char buf[20]; - char* string = dtostrf(num, 4, 2, buf); - return concat(string, strlen(string)); -} - -unsigned char String::concat(double num) -{ - char buf[20]; - char* string = dtostrf(num, 4, 2, buf); - return concat(string, strlen(string)); -} - -unsigned char String::concat(const __FlashStringHelper * str) -{ - if (!str) return 0; - int length = strlen_P((const char *) str); - if (length == 0) return 1; - unsigned int newlen = len + length; - if (!reserve(newlen)) return 0; - strcpy_P(buffer + len, (const char *) str); - len = newlen; - return 1; -} - -/*********************************************/ -/* Concatenate */ -/*********************************************/ - -StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(rhs.buffer, rhs.len)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr) -{ - StringSumHelper &a = const_cast(lhs); - if (!cstr || !a.concat(cstr, strlen(cstr))) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, char c) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(c)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, int num) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, long num) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, float num) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, double num) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(rhs)) 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, 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::remove(unsigned int index){ - // Pass the biggest integer as the count. The remove method - // below will take care of truncating it at the end of the - // string. - remove(index, (unsigned int)-1); -} - -void String::remove(unsigned int index, unsigned int count){ - if (index >= len) { return; } - if (count <= 0) { return; } - if (count > len - index) { count = len - index; } - char *writeTo = buffer + index; - len = len - count; - strncpy(writeTo, buffer + index + count,len - index); - buffer[len] = 0; -} - -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; -} - -float String::toFloat(void) const -{ - if (buffer) return float(atof(buffer)); - return 0; -} diff --git a/plugins/KeyboardioHID/avr/cores/hid/WString.h b/plugins/KeyboardioHID/avr/cores/hid/WString.h deleted file mode 100644 index 7402430927..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/WString.h +++ /dev/null @@ -1,224 +0,0 @@ -/* - 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 -#include -#include -#include - -// 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(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); - String(const __FlashStringHelper *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); - explicit String(float, unsigned char decimalPlaces=2); - explicit String(double, unsigned char decimalPlaces=2); - ~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); - String & operator = (const __FlashStringHelper *str); - #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); - unsigned char concat(float num); - unsigned char concat(double num); - unsigned char concat(const __FlashStringHelper * str); - - // 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);} - String & operator += (float num) {concat(num); return (*this);} - String & operator += (double num) {concat(num); return (*this);} - String & operator += (const __FlashStringHelper *str){concat(str); 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); - friend StringSumHelper & operator + (const StringSumHelper &lhs, float num); - friend StringSumHelper & operator + (const StringSumHelper &lhs, double num); - friend StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs); - - // 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);} - const char * c_str() const { return buffer; } - - // 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 { return substring(beginIndex, len); }; - 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 remove(unsigned int index); - void remove(unsigned int index, unsigned int count); - void toLowerCase(void); - void toUpperCase(void); - void trim(void); - - // parsing/conversion - long toInt(void) const; - float toFloat(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') -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); - String & copy(const __FlashStringHelper *pstr, 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) {} - StringSumHelper(float num) : String(num) {} - StringSumHelper(double num) : String(num) {} -}; - -#endif // __cplusplus -#endif // String_class_h diff --git a/plugins/KeyboardioHID/avr/cores/hid/abi.cpp b/plugins/KeyboardioHID/avr/cores/hid/abi.cpp deleted file mode 100644 index 8d719b8e64..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/abi.cpp +++ /dev/null @@ -1,35 +0,0 @@ -/* - Copyright (c) 2014 Arduino. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#include - -extern "C" void __cxa_pure_virtual(void) __attribute__ ((__noreturn__)); -extern "C" void __cxa_deleted_virtual(void) __attribute__ ((__noreturn__)); - -void __cxa_pure_virtual(void) { - // We might want to write some diagnostics to uart in this case - //std::terminate(); - abort(); -} - -void __cxa_deleted_virtual(void) { - // We might want to write some diagnostics to uart in this case - //std::terminate(); - abort(); -} - diff --git a/plugins/KeyboardioHID/avr/cores/hid/binary.h b/plugins/KeyboardioHID/avr/cores/hid/binary.h deleted file mode 100644 index aec4c733d4..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/binary.h +++ /dev/null @@ -1,534 +0,0 @@ -/* - binary.h - Definitions for binary constants - Copyright (c) 2006 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 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/plugins/KeyboardioHID/avr/cores/hid/hooks.c b/plugins/KeyboardioHID/avr/cores/hid/hooks.c deleted file mode 100644 index 641eabc737..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/hooks.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - Copyright (c) 2012 Arduino. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -/** - * Empty yield() hook. - * - * This function is intended to be used by library writers to build - * libraries or sketches that supports cooperative threads. - * - * Its defined as a weak symbol and it can be redefined to implement a - * real cooperative scheduler. - */ -static void __empty() { - // Empty -} -void yield(void) __attribute__ ((weak, alias("__empty"))); diff --git a/plugins/KeyboardioHID/avr/cores/hid/main.cpp b/plugins/KeyboardioHID/avr/cores/hid/main.cpp deleted file mode 100644 index a60980da57..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/main.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - main.cpp - Main loop for Arduino sketches - Copyright (c) 2005-2013 Arduino Team. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#include - -//Declared weak in Arduino.h to allow user redefinitions. -int atexit(void (*func)()) { return 0; } - -// Weak empty variant initialization function. -// May be redefined by variant files. -void initVariant() __attribute__((weak)); -void initVariant() { } - -int main(void) -{ - init(); - - initVariant(); - -#if defined(USBCON) - USBDevice.attach(); -#endif - - setup(); - - for (;;) { - loop(); - if (serialEventRun) serialEventRun(); - } - - return 0; -} - diff --git a/plugins/KeyboardioHID/avr/cores/hid/new.cpp b/plugins/KeyboardioHID/avr/cores/hid/new.cpp deleted file mode 100644 index cf6f89c178..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/new.cpp +++ /dev/null @@ -1,36 +0,0 @@ -/* - Copyright (c) 2014 Arduino. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#include - -void *operator new(size_t size) { - return malloc(size); -} - -void *operator new[](size_t size) { - return malloc(size); -} - -void operator delete(void * ptr) { - free(ptr); -} - -void operator delete[](void * ptr) { - free(ptr); -} - diff --git a/plugins/KeyboardioHID/avr/cores/hid/new.h b/plugins/KeyboardioHID/avr/cores/hid/new.h deleted file mode 100644 index 6e1b68f0da..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/new.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - Copyright (c) 2014 Arduino. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#ifndef NEW_H -#define NEW_H - -#include - -void * operator new(size_t size); -void * operator new[](size_t size); -void operator delete(void * ptr); -void operator delete[](void * ptr); - -#endif - diff --git a/plugins/KeyboardioHID/avr/cores/hid/wiring.c b/plugins/KeyboardioHID/avr/cores/hid/wiring.c deleted file mode 100644 index 6cb22c0032..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/wiring.c +++ /dev/null @@ -1,396 +0,0 @@ -/* - 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__) -ISR(TIM0_OVF_vect) -#else -ISR(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) { - yield(); - if (((uint16_t)micros() - start) >= 1000) { - ms--; - start += 1000; - } - } -} - -/* Delay for the given number of microseconds. Assumes a 1, 8, 12, 16, 20 or 24 MHz clock. */ -void delayMicroseconds(unsigned int us) -{ - // call = 4 cycles + 2 to 4 cycles to init us(2 for constant delay, 4 for variable) - - // 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 >= 24000000L - // for the 24 MHz clock for the aventurous ones, trying to overclock - - // zero delay fix - if (!us) return; // = 3 cycles, (4 when true) - - // the following loop takes a 1/6 of a microsecond (4 cycles) - // per iteration, so execute it six times for each microsecond of - // delay requested. - us *= 6; // x6 us, = 7 cycles - - // account for the time taken in the preceeding commands. - // we just burned 22 (24) cycles above, remove 5, (5*4=20) - // us is at least 6 so we can substract 5 - us -= 5; //=2 cycles - -#elif F_CPU >= 20000000L - // for the 20 MHz clock on rare Arduino boards - - // for a one-microsecond delay, simply return. the overhead - // of the function call takes 18 (20) cycles, which is 1us - __asm__ __volatile__ ( - "nop" "\n\t" - "nop" "\n\t" - "nop" "\n\t" - "nop"); //just waiting 4 cycles - if (us <= 1) return; // = 3 cycles, (4 when true) - - // 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, = 7 cycles - - // account for the time taken in the preceeding commands. - // we just burned 26 (28) cycles above, remove 7, (7*4=28) - // us is at least 10 so we can substract 7 - us -= 7; // 2 cycles - -#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 takes 14 (16) cycles, which is 1us - if (us <= 1) return; // = 3 cycles, (4 when true) - - // the following loop takes 1/4 of a microsecond (4 cycles) - // per iteration, so execute it four times for each microsecond of - // delay requested. - us <<= 2; // x4 us, = 4 cycles - - // account for the time taken in the preceeding commands. - // we just burned 19 (21) cycles above, remove 5, (5*4=20) - // us is at least 8 so we can substract 5 - us -= 5; // = 2 cycles, - -#elif F_CPU >= 12000000L - // for the 12 MHz clock if somebody is working with USB - - // for a 1 microsecond delay, simply return. the overhead - // of the function call takes 14 (16) cycles, which is 1.5us - if (us <= 1) return; // = 3 cycles, (4 when true) - - // the following loop takes 1/3 of a microsecond (4 cycles) - // per iteration, so execute it three times for each microsecond of - // delay requested. - us = (us << 1) + us; // x3 us, = 5 cycles - - // account for the time taken in the preceeding commands. - // we just burned 20 (22) cycles above, remove 5, (5*4=20) - // us is at least 6 so we can substract 5 - us -= 5; //2 cycles - -#elif F_CPU >= 8000000L - // for the 8 MHz internal clock - - // for a 1 and 2 microsecond delay, simply return. the overhead - // of the function call takes 14 (16) cycles, which is 2us - if (us <= 2) return; // = 3 cycles, (4 when true) - - // the following loop takes 1/2 of a microsecond (4 cycles) - // per iteration, so execute it twice for each microsecond of - // delay requested. - us <<= 1; //x2 us, = 2 cycles - - // account for the time taken in the preceeding commands. - // we just burned 17 (19) cycles above, remove 4, (4*4=16) - // us is at least 6 so we can substract 4 - us -= 4; // = 2 cycles - -#else - // for the 1 MHz internal clock (default settings for common Atmega microcontrollers) - - // the overhead of the function calls is 14 (16) cycles - if (us <= 16) return; //= 3 cycles, (4 when true) - if (us <= 25) return; //= 3 cycles, (4 when true), (must be at least 25 if we want to substract 22) - - // compensate for the time taken by the preceeding and next commands (about 22 cycles) - us -= 22; // = 2 cycles - // the following loop takes 4 microseconds (4 cycles) - // per iteration, so execute it us/4 times - // us is at least 4, divided by 4 gives us 1 (no zero delay bug) - us >>= 2; // us div 4, = 4 cycles - - -#endif - - // busy wait - __asm__ __volatile__ ( - "1: sbiw %0,1" "\n\t" // 2 cycles - "brne 1b" : "=w" (us) : "0" (us) // 2 cycles - ); - // return = 4 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 prescaler so we are inside the desired 50-200 KHz range. - #if F_CPU >= 16000000 // 16 MHz / 128 = 125 KHz - sbi(ADCSRA, ADPS2); - sbi(ADCSRA, ADPS1); - sbi(ADCSRA, ADPS0); - #elif F_CPU >= 8000000 // 8 MHz / 64 = 125 KHz - sbi(ADCSRA, ADPS2); - sbi(ADCSRA, ADPS1); - cbi(ADCSRA, ADPS0); - #elif F_CPU >= 4000000 // 4 MHz / 32 = 125 KHz - sbi(ADCSRA, ADPS2); - cbi(ADCSRA, ADPS1); - sbi(ADCSRA, ADPS0); - #elif F_CPU >= 2000000 // 2 MHz / 16 = 125 KHz - sbi(ADCSRA, ADPS2); - cbi(ADCSRA, ADPS1); - cbi(ADCSRA, ADPS0); - #elif F_CPU >= 1000000 // 1 MHz / 8 = 125 KHz - cbi(ADCSRA, ADPS2); - sbi(ADCSRA, ADPS1); - sbi(ADCSRA, ADPS0); - #else // 128 kHz / 2 = 64 KHz -> This is the closest you can get, the prescaler is 2 - cbi(ADCSRA, ADPS2); - cbi(ADCSRA, ADPS1); - sbi(ADCSRA, ADPS0); - #endif - // 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/plugins/KeyboardioHID/avr/cores/hid/wiring_analog.c b/plugins/KeyboardioHID/avr/cores/hid/wiring_analog.c deleted file mode 100644 index 48a9ef52d5..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/wiring_analog.c +++ /dev/null @@ -1,292 +0,0 @@ -/* - 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(analogPinToChannel) -#if defined(__AVR_ATmega32U4__) - if (pin >= 18) pin -= 18; // allow for channel or pin numbers -#endif - pin = analogPinToChannel(pin); -#elif 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__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644A__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__) - 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(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(TCCR1A) && defined(COM1C1) - case TIMER1C: - // connect pwm to pin on timer 1, channel B - sbi(TCCR1A, COM1C1); - OCR1C = 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/plugins/KeyboardioHID/avr/cores/hid/wiring_digital.c b/plugins/KeyboardioHID/avr/cores/hid/wiring_digital.c deleted file mode 100644 index df94cc1c5b..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/wiring_digital.c +++ /dev/null @@ -1,181 +0,0 @@ -/* - 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(TCCR1A) && defined(COM1C1) - case TIMER1C: cbi(TCCR1A, COM1C1); 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/plugins/KeyboardioHID/avr/cores/hid/wiring_private.h b/plugins/KeyboardioHID/avr/cores/hid/wiring_private.h deleted file mode 100644 index e37ec4dce7..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/wiring_private.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - 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 $ - */ - -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. -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 WiringPrivate_h -#define WiringPrivate_h - -#include -#include -#include -#include - -#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 - - // edit by NicoHood -#if defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega8U2__) \ -|| defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega128RFA1__) || defined(__AVR_ATmega256RFR2__) -#define EXTERNAL_NUM_INTERRUPTS 8 -#elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644A__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__) -#define EXTERNAL_NUM_INTERRUPTS 3 -#elif defined(__AVR_ATmega32U4__) -#define EXTERNAL_NUM_INTERRUPTS 5 -#else -#define EXTERNAL_NUM_INTERRUPTS 2 -#endif - -typedef void (*voidFuncPtr)(void); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif diff --git a/plugins/KeyboardioHID/avr/cores/hid/wiring_pulse.c b/plugins/KeyboardioHID/avr/cores/hid/wiring_pulse.c deleted file mode 100644 index 830c45408a..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/wiring_pulse.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - 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. There will be some error introduced by - // the interrupt handlers. - - // Conversion constants are compiler-dependent, different compiler versions - // have different levels of optimization. -#if __GNUC__==4 && __GNUC_MINOR__==3 && __GNUC_PATCHLEVEL__==2 - // avr-gcc 4.3.2 - return clockCyclesToMicroseconds(width * 21 + 16); -#elif __GNUC__==4 && __GNUC_MINOR__==8 && __GNUC_PATCHLEVEL__==1 - // avr-gcc 4.8.1 - return clockCyclesToMicroseconds(width * 24 + 16); -#elif __GNUC__<=4 && __GNUC_MINOR__<=3 - // avr-gcc <=4.3.x - #warning "pulseIn() results may not be accurate" - return clockCyclesToMicroseconds(width * 21 + 16); -#else - // avr-gcc >4.3.x - #warning "pulseIn() results may not be accurate" - return clockCyclesToMicroseconds(width * 24 + 16); -#endif - -} diff --git a/plugins/KeyboardioHID/avr/cores/hid/wiring_shift.c b/plugins/KeyboardioHID/avr/cores/hid/wiring_shift.c deleted file mode 100644 index cfe786758c..0000000000 --- a/plugins/KeyboardioHID/avr/cores/hid/wiring_shift.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - 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/plugins/KeyboardioHID/avr/libraries/EEPROM/EEPROM.h b/plugins/KeyboardioHID/avr/libraries/EEPROM/EEPROM.h deleted file mode 100644 index cde75dba9a..0000000000 --- a/plugins/KeyboardioHID/avr/libraries/EEPROM/EEPROM.h +++ /dev/null @@ -1,146 +0,0 @@ -/* - EEPROM.h - EEPROM library - Original Copyright (c) 2006 David A. Mellis. All right reserved. - New version by Christopher Andrews 2015. - - 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 EEPROM_h -#define EEPROM_h - -#include -#include -#include - -/*** - EERef class. - - This object references an EEPROM cell. - Its purpose is to mimic a typical byte of RAM, however its storage is the EEPROM. - This class has an overhead of two bytes, similar to storing a pointer to an EEPROM cell. -***/ - -struct EERef{ - - EERef( const int index ) - : index( index ) {} - - //Access/read members. - uint8_t operator*() const { return eeprom_read_byte( (uint8_t*) index ); } - operator const uint8_t() const { return **this; } - - //Assignment/write members. - EERef &operator=( const EERef &ref ) { return *this = *ref; } - EERef &operator=( uint8_t in ) { return eeprom_write_byte( (uint8_t*) index, in ), *this; } - EERef &operator +=( uint8_t in ) { return *this = **this + in; } - EERef &operator -=( uint8_t in ) { return *this = **this - in; } - EERef &operator *=( uint8_t in ) { return *this = **this * in; } - EERef &operator /=( uint8_t in ) { return *this = **this / in; } - EERef &operator ^=( uint8_t in ) { return *this = **this ^ in; } - EERef &operator %=( uint8_t in ) { return *this = **this % in; } - EERef &operator &=( uint8_t in ) { return *this = **this & in; } - EERef &operator |=( uint8_t in ) { return *this = **this | in; } - EERef &operator <<=( uint8_t in ) { return *this = **this << in; } - EERef &operator >>=( uint8_t in ) { return *this = **this >> in; } - - EERef &update( uint8_t in ) { return in != *this ? *this = in : *this; } - - /** Prefix increment/decrement **/ - EERef& operator++() { return *this += 1; } - EERef& operator--() { return *this -= 1; } - - /** Postfix increment/decrement **/ - uint8_t operator++ (int){ - uint8_t ret = **this; - return ++(*this), ret; - } - - uint8_t operator-- (int){ - uint8_t ret = **this; - return --(*this), ret; - } - - int index; //Index of current EEPROM cell. -}; - -/*** - EEPtr class. - - This object is a bidirectional pointer to EEPROM cells represented by EERef objects. - Just like a normal pointer type, this can be dereferenced and repositioned using - increment/decrement operators. -***/ - -struct EEPtr{ - - EEPtr( const int index ) - : index( index ) {} - - operator const int() const { return index; } - EEPtr &operator=( int in ) { return index = in, *this; } - - //Iterator functionality. - bool operator!=( const EEPtr &ptr ) { return index != ptr.index; } - EERef operator*() { return index; } - - /** Prefix & Postfix increment/decrement **/ - EEPtr& operator++() { return ++index, *this; } - EEPtr& operator--() { return --index, *this; } - EEPtr operator++ (int) { return index++; } - EEPtr operator-- (int) { return index--; } - - int index; //Index of current EEPROM cell. -}; - -/*** - EEPROMClass class. - - This object represents the entire EEPROM space. - It wraps the functionality of EEPtr and EERef into a basic interface. - This class is also 100% backwards compatible with earlier Arduino core releases. -***/ - -struct EEPROMClass{ - - //Basic user access methods. - EERef operator[]( const int idx ) { return idx; } - uint8_t read( int idx ) { return EERef( idx ); } - void write( int idx, uint8_t val ) { (EERef( idx )) = val; } - void update( int idx, uint8_t val ) { EERef( idx ).update( val ); } - - //STL and C++11 iteration capability. - EEPtr begin() { return 0x00; } - EEPtr end() { return length(); } //Standards requires this to be the item after the last valid entry. The returned pointer is invalid. - uint16_t length() { return E2END + 1; } - - //Functionality to 'get' and 'put' objects to and from EEPROM. - template< typename T > T &get( int idx, T &t ){ - EEPtr e = idx; - uint8_t *ptr = (uint8_t*) &t; - for( int count = sizeof(T) ; count ; --count, ++e ) *ptr++ = *e; - return t; - } - - template< typename T > const T &put( int idx, const T &t ){ - EEPtr e = idx; - const uint8_t *ptr = (const uint8_t*) &t; - for( int count = sizeof(T) ; count ; --count, ++e ) (*e).update( *ptr++ ); - return t; - } -}; - -static EEPROMClass EEPROM; -#endif \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/libraries/EEPROM/README.md b/plugins/KeyboardioHID/avr/libraries/EEPROM/README.md deleted file mode 100644 index a62413613d..0000000000 --- a/plugins/KeyboardioHID/avr/libraries/EEPROM/README.md +++ /dev/null @@ -1,139 +0,0 @@ -## **EEPROM Library V2.0** for Arduino - -**Written by:** _Christopher Andrews_. - -### **What is the EEPROM library.** - -Th EEPROM library provides an easy to use interface to interact with the internal non-volatile storage found in AVR based Arduino boards. This library will work on many AVR devices like ATtiny and ATmega chips. - -### **How to use it** -The EEPROM library is included in your IDE download. To add its functionality to your sketch you'll need to reference the library header file. You do this by adding an include directive to the top of your sketch. - -```Arduino -#include - -void setup(){ - -} - -void loop(){ - -} - -``` - -The library provides a global variable named `EEPROM`, you use this variable to access the library functions. The methods provided in the EEPROM class are listed below. - -You can view all the examples [here](examples/). - -### **Library functions** - -#### **`EEPROM.read( address )`** [[_example_]](examples/eeprom_read/eeprom_read.ino) - -This function allows you to read a single byte of data from the eeprom. -Its only parameter is an `int` which should be set to the address you wish to read. - -The function returns an `unsigned char` containing the value read. - -#### **`EEPROM.write( address, value )`** [[_example_]](examples/eeprom_write/eeprom_write.ino) - -The `write()` method allows you to write a single byte of data to the EEPROM. -Two parameters are needed. The first is an `int` containing the address that is to be written, and the second is a the data to be written (`unsigned char`). - -This function does not return any value. - -#### **`EEPROM.update( address, value )`** [[_example_]](examples/eeprom_update/eeprom_update.ino) - -This function is similar to `EEPROM.write()` however this method will only write data if the cell contents pointed to by `address` is different to `value`. This method can help prevent unnecessary wear on the EEPROM cells. - -This function does not return any value. - -#### **`EEPROM.get( address, object )`** [[_example_]](examples/eeprom_get/eeprom_get.ino) - -This function will retrieve any object from the EEPROM. -Two parameters are needed to call this function. The first is an `int` containing the address that is to be written, and the second is the object you would like to read. - -This function returns a reference to the `object` passed in. It does not need to be used and is only returned for conveience. - -#### **`EEPROM.put( address, object )`** [[_example_]](examples/eeprom_put/eeprom_put.ino) - -This function will write any object to the EEPROM. -Two parameters are needed to call this function. The first is an `int` containing the address that is to be written, and the second is the object you would like to write. - -This function uses the _update_ method to write its data, and therefore only rewrites changed cells. - -This function returns a reference to the `object` passed in. It does not need to be used and is only returned for conveience. - -#### **Subscript operator: `EEPROM[address]`** [[_example_]](examples/eeprom_crc/eeprom_crc.ino) - -This operator allows using the identifier `EEPROM` like an array. -EEPROM cells can be read _and_ **_written_** directly using this method. - -This operator returns a reference to the EEPROM cell. - -```c++ -unsigned char val; - -//Read first EEPROM cell. -val = EEPROM[ 0 ]; - -//Write first EEPROM cell. -EEPROM[ 0 ] = val; - -//Compare contents -if( val == EEPROM[ 0 ] ){ - //Do something... -} -``` - -#### **`EEPROM.length()`** - -This function returns an `unsigned int` containing the number of cells in the EEPROM. - ---- - -### **Advanced features** - -This library uses a component based approach to provide its functionality. This means you can also use these components to design a customized approach. Two background classes are available for use: `EERef` & `EEPtr`. - -#### **`EERef` class** - -This object references an EEPROM cell. -Its purpose is to mimic a typical byte of RAM, however its storage is the EEPROM. -This class has an overhead of two bytes, similar to storing a pointer to an EEPROM cell. - -```C++ -EERef ref = EEPROM[ 10 ]; //Create a reference to 11th cell. - -ref = 4; //write to EEPROM cell. - -unsigned char val = ref; //Read referenced cell. -``` - -#### **`EEPtr` class** - -This object is a bidirectional pointer to EEPROM cells represented by `EERef` objects. -Just like a normal pointer type, this type can be dereferenced and repositioned using -increment/decrement operators. - -```C++ -EEPtr ptr = 10; //Create a pointer to 11th cell. - -*ptr = 4; //dereference and write to EEPROM cell. - -unsigned char val = *ptr; //dereference and read. - -ptr++; //Move to next EEPROM cell. -``` - -#### **`EEPROM.begin()`** - -This function returns an `EEPtr` pointing to the first cell in the EEPROM. -This is useful for STL objects, custom iteration and C++11 style ranged for loops. - -#### **`EEPROM.end()`** - -This function returns an `EEPtr` pointing at the location after the last EEPROM cell. -Used with `begin()` to provide custom iteration. - -**Note:** The `EEPtr` returned is invalid as it is out of range. Infact the hardware causes wrapping of the address (overflow) and `EEPROM.end()` actually references the first EEPROM cell. diff --git a/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_clear/eeprom_clear.ino b/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_clear/eeprom_clear.ino deleted file mode 100644 index 49eb5fe55b..0000000000 --- a/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_clear/eeprom_clear.ino +++ /dev/null @@ -1,35 +0,0 @@ -/* - * EEPROM Clear - * - * Sets all of the bytes of the EEPROM to 0. - * Please see eeprom_iteration for a more in depth - * look at how to traverse the EEPROM. - * - * This example code is in the public domain. - */ - -#include - -void setup() -{ - - /*** - Iterate through each byte of the EEPROM storage. - - Larger AVR processors have larger EEPROM sizes, E.g: - - Arduno Duemilanove: 512b EEPROM storage. - - Arduino Uno: 1kb EEPROM storage. - - Arduino Mega: 4kb EEPROM storage. - - Rather than hard-coding the length, you should use the pre-provided length function. - This will make your code portable to all AVR processors. - ***/ - - for ( int i = 0 ; i < EEPROM.length() ; i++ ) - EEPROM.write(i, 0); - - // turn the LED on when we're done - digitalWrite(13, HIGH); -} - -void loop(){ /** Empty loop. **/ } diff --git a/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_crc/eeprom_crc.ino b/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_crc/eeprom_crc.ino deleted file mode 100644 index 8461d566a2..0000000000 --- a/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_crc/eeprom_crc.ino +++ /dev/null @@ -1,50 +0,0 @@ -/*** - Written by Christopher Andrews. - CRC algorithm generated by pycrc, MIT licence ( https://github.com/tpircher/pycrc ). - - A CRC is a simple way of checking whether data has changed or become corrupted. - This example calculates a CRC value directly on the EEPROM values. - The purpose of this example is to highlight how the EEPROM object can be used just like an array. -***/ - -#include -#include - -void setup(){ - - //Start serial - Serial.begin(9600); - while (!Serial) { - ; // wait for serial port to connect. Needed for Leonardo only - } - - //Print length of data to run CRC on. - Serial.print( "EEPROM length: " ); - Serial.println( EEPROM.length() ); - - //Print the result of calling eeprom_crc() - Serial.print( "CRC32 of EEPROM data: 0x" ); - Serial.println( eeprom_crc(), HEX ); - Serial.print( "\n\nDone!" ); -} - -void loop(){ /* Empty loop */ } - -unsigned long eeprom_crc( void ){ - - const unsigned long crc_table[16] = { - 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, - 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, - 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, - 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c - }; - - unsigned long crc = ~0L; - - for( int index = 0 ; index < EEPROM.length() ; ++index ){ - crc = crc_table[( crc ^ EEPROM[index] ) & 0x0f] ^ (crc >> 4); - crc = crc_table[( crc ^ ( EEPROM[index] >> 4 )) & 0x0f] ^ (crc >> 4); - crc = ~crc; - } - return crc; -} \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_get/eeprom_get.ino b/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_get/eeprom_get.ino deleted file mode 100644 index 662099990c..0000000000 --- a/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_get/eeprom_get.ino +++ /dev/null @@ -1,66 +0,0 @@ -/*** - eeprom_get example. - - This shows how to use the EEPROM.get() method. - - To pre-set the EEPROM data, run the example sketch eeprom_put. - This sketch will run without it, however, the values shown - will be shown from what ever is already on the EEPROM. - - This may cause the serial object to print out a large string - of garbage if there is no null character inside one of the strings - loaded. - - Written by Christopher Andrews 2015 - Released under MIT licence. -***/ - -#include - -void setup(){ - - float f = 0.00f; //Variable to store data read from EEPROM. - int eeAddress = 0; //EEPROM address to start reading from - - Serial.begin( 9600 ); - while (!Serial) { - ; // wait for serial port to connect. Needed for Leonardo only - } - Serial.print( "Read float from EEPROM: " ); - - //Get the float data from the EEPROM at position 'eeAddress' - EEPROM.get( eeAddress, f ); - Serial.println( f, 3 ); //This may print 'ovf, nan' if the data inside the EEPROM is not a valid float. - - /*** - As get also returns a reference to 'f', you can use it inline. - E.g: Serial.print( EEPROM.get( eeAddress, f ) ); - ***/ - - /*** - Get can be used with custom structures too. - I have separated this into an extra function. - ***/ - - secondTest(); //Run the next test. -} - -struct MyObject{ - float field1; - byte field2; - char name[10]; -}; - -void secondTest(){ - int eeAddress = sizeof(float); //Move address to the next byte after float 'f'. - - MyObject customVar; //Variable to store custom object read from EEPROM. - EEPROM.get( eeAddress, customVar ); - - Serial.println( "Read custom object from EEPROM: " ); - Serial.println( customVar.field1 ); - Serial.println( customVar.field2 ); - Serial.println( customVar.name ); -} - -void loop(){ /* Empty loop */ } \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_iteration/eeprom_iteration.ino b/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_iteration/eeprom_iteration.ino deleted file mode 100644 index 650c90a75f..0000000000 --- a/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_iteration/eeprom_iteration.ino +++ /dev/null @@ -1,57 +0,0 @@ -/*** - eeprom_iteration example. - - A set of example snippets highlighting the - simplest methods for traversing the EEPROM. - - Running this sketch is not necessary, this is - simply highlighting certain programming methods. - - Written by Christopher Andrews 2015 - Released under MIT licence. -***/ - -#include - -void setup() { - - /*** - Iterate the EEPROM using a for loop. - ***/ - - for( int index = 0 ; index < EEPROM.length() ; index++ ){ - - //Add one to each cell in the EEPROM - EEPROM[ index ] += 1; - } - - /*** - Iterate the EEPROM using a while loop. - ***/ - - int index = 0; - - while( index < EEPROM.length() ){ - - //Add one to each cell in the EEPROM - EEPROM[ index ] += 1; - index++; - } - - /*** - Iterate the EEPROM using a do-while loop. - ***/ - - int idx = 0; //Used 'idx' to avoid name conflict with 'index' above. - - do{ - - //Add one to each cell in the EEPROM - EEPROM[ idx ] += 1; - idx++; - }while( idx < EEPROM.length() ); - - -} //End of setup function. - -void loop(){} \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_put/eeprom_put.ino b/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_put/eeprom_put.ino deleted file mode 100644 index 186cf95bdc..0000000000 --- a/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_put/eeprom_put.ino +++ /dev/null @@ -1,56 +0,0 @@ -/*** - eeprom_put example. - - This shows how to use the EEPROM.put() method. - Also, this sketch will pre-set the EEPROM data for the - example sketch eeprom_get. - - Note, unlike the single byte version EEPROM.write(), - the put method will use update semantics. As in a byte - will only be written to the EEPROM if the data is actually - different. - - Written by Christopher Andrews 2015 - Released under MIT licence. -***/ - -#include - -struct MyObject{ - float field1; - byte field2; - char name[10]; -}; - -void setup(){ - - Serial.begin(9600); - while (!Serial) { - ; // wait for serial port to connect. Needed for Leonardo only - } - - float f = 123.456f; //Variable to store in EEPROM. - int eeAddress = 0; //Location we want the data to be put. - - - //One simple call, with the address first and the object second. - EEPROM.put( eeAddress, f ); - - Serial.println("Written float data type!"); - - /** Put is designed for use with custom structures also. **/ - - //Data to store. - MyObject customVar = { - 3.14f, - 65, - "Working!" - }; - - eeAddress += sizeof(float); //Move address to the next byte after float 'f'. - - EEPROM.put( eeAddress, customVar ); - Serial.print( "Written custom data type! \n\nView the example sketch eeprom_get to see how you can retrieve the values!" ); -} - -void loop(){ /* Empty loop */ } \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_read/eeprom_read.ino b/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_read/eeprom_read.ino deleted file mode 100644 index 68c4ffc745..0000000000 --- a/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_read/eeprom_read.ino +++ /dev/null @@ -1,57 +0,0 @@ -/* - * EEPROM Read - * - * Reads the value of each byte of the EEPROM and prints it - * to the computer. - * This example code is in the public domain. - */ - -#include - -// start reading from the first byte (address 0) of the EEPROM -int address = 0; -byte value; - -void setup() -{ - // initialize serial and wait for port to open: - Serial.begin(9600); - while (!Serial) { - ; // wait for serial port to connect. Needed for Leonardo only - } -} - -void loop() -{ - // read a byte from the current address of the EEPROM - value = EEPROM.read(address); - - Serial.print(address); - Serial.print("\t"); - Serial.print(value, DEC); - Serial.println(); - - /*** - Advance to the next address, when at the end restart at the beginning. - - Larger AVR processors have larger EEPROM sizes, E.g: - - Arduno Duemilanove: 512b EEPROM storage. - - Arduino Uno: 1kb EEPROM storage. - - Arduino Mega: 4kb EEPROM storage. - - Rather than hard-coding the length, you should use the pre-provided length function. - This will make your code portable to all AVR processors. - ***/ - address = address + 1; - if(address == EEPROM.length()) - address = 0; - - /*** - As the EEPROM sizes are powers of two, wrapping (preventing overflow) of an - EEPROM address is also doable by a bitwise and of the length - 1. - - ++address &= EEPROM.length() - 1; - ***/ - - delay(500); -} diff --git a/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_update/eeprom_update.ino b/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_update/eeprom_update.ino deleted file mode 100644 index 831056fd7d..0000000000 --- a/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_update/eeprom_update.ino +++ /dev/null @@ -1,69 +0,0 @@ -/*** - EEPROM Update method - - Stores values read from analog input 0 into the EEPROM. - These values will stay in the EEPROM when the board is - turned off and may be retrieved later by another sketch. - - If a value has not changed in the EEPROM, it is not overwritten - which would reduce the life span of the EEPROM unnecessarily. - - Released using MIT licence. - ***/ - -#include - -/** the current address in the EEPROM (i.e. which byte we're going to write to next) **/ -int address = 0; - -void setup(){ /** EMpty setup **/ } - -void loop() -{ - /*** - need to divide by 4 because analog inputs range from - 0 to 1023 and each byte of the EEPROM can only hold a - value from 0 to 255. - ***/ - int val = analogRead(0) / 4; - - /*** - Update the particular EEPROM cell. - these values will remain there when the board is - turned off. - ***/ - EEPROM.update(address, val); - - /*** - The function EEPROM.update(address, val) is equivalent to the following: - - if( EEPROM.read(address) != val ){ - EEPROM.write(address, val); - } - ***/ - - - /*** - Advance to the next address, when at the end restart at the beginning. - - Larger AVR processors have larger EEPROM sizes, E.g: - - Arduno Duemilanove: 512b EEPROM storage. - - Arduino Uno: 1kb EEPROM storage. - - Arduino Mega: 4kb EEPROM storage. - - Rather than hard-coding the length, you should use the pre-provided length function. - This will make your code portable to all AVR processors. - ***/ - address = address + 1; - if(address == EEPROM.length()) - address = 0; - - /*** - As the EEPROM sizes are powers of two, wrapping (preventing overflow) of an - EEPROM address is also doable by a bitwise and of the length - 1. - - ++address &= EEPROM.length() - 1; - ***/ - - delay(100); -} diff --git a/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_write/eeprom_write.ino b/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_write/eeprom_write.ino deleted file mode 100644 index f07446c5a5..0000000000 --- a/plugins/KeyboardioHID/avr/libraries/EEPROM/examples/eeprom_write/eeprom_write.ino +++ /dev/null @@ -1,58 +0,0 @@ -/* - * EEPROM Write - * - * Stores values read from analog input 0 into the EEPROM. - * These values will stay in the EEPROM when the board is - * turned off and may be retrieved later by another sketch. - */ - -#include - -/** the current address in the EEPROM (i.e. which byte we're going to write to next) **/ -int addr = 0; - -void setup(){ /** Empty setup. **/} - -void loop() -{ - /*** - Need to divide by 4 because analog inputs range from - 0 to 1023 and each byte of the EEPROM can only hold a - value from 0 to 255. - ***/ - - int val = analogRead(0) / 4; - - /*** - Write the value to the appropriate byte of the EEPROM. - these values will remain there when the board is - turned off. - ***/ - - EEPROM.write(addr, val); - - /*** - Advance to the next address, when at the end restart at the beginning. - - Larger AVR processors have larger EEPROM sizes, E.g: - - Arduno Duemilanove: 512b EEPROM storage. - - Arduino Uno: 1kb EEPROM storage. - - Arduino Mega: 4kb EEPROM storage. - - Rather than hard-coding the length, you should use the pre-provided length function. - This will make your code portable to all AVR processors. - ***/ - addr = addr + 1; - if(addr == EEPROM.length()) - addr = 0; - - /*** - As the EEPROM sizes are powers of two, wrapping (preventing overflow) of an - EEPROM address is also doable by a bitwise and of the length - 1. - - ++addr &= EEPROM.length() - 1; - ***/ - - - delay(100); -} diff --git a/plugins/KeyboardioHID/avr/libraries/EEPROM/keywords.txt b/plugins/KeyboardioHID/avr/libraries/EEPROM/keywords.txt deleted file mode 100644 index 2cabc0b062..0000000000 --- a/plugins/KeyboardioHID/avr/libraries/EEPROM/keywords.txt +++ /dev/null @@ -1,22 +0,0 @@ -####################################### -# Syntax Coloring Map For EEPROM -####################################### - -####################################### -# Datatypes (KEYWORD1) -####################################### - -EEPROM KEYWORD1 -EERef KEYWORD1 -EEPtr KEYWORD2 - -####################################### -# Methods and Functions (KEYWORD2) -####################################### - -update KEYWORD2 - -####################################### -# Constants (LITERAL1) -####################################### - diff --git a/plugins/KeyboardioHID/avr/libraries/EEPROM/library.properties b/plugins/KeyboardioHID/avr/libraries/EEPROM/library.properties deleted file mode 100644 index 21437ffdf6..0000000000 --- a/plugins/KeyboardioHID/avr/libraries/EEPROM/library.properties +++ /dev/null @@ -1,9 +0,0 @@ -name=EEPROM -version=2.0 -author=Arduino, Christopher Andrews -maintainer=Arduino -sentence=Enables reading and writing to the permanent board storage. For all Arduino boards BUT Arduino DUE. -paragraph= -url=http://www.arduino.cc/en/Reference/EEPROM -architectures=avr - diff --git a/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.cpp b/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.cpp deleted file mode 100644 index 99c32aa7e8..0000000000 --- a/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.cpp +++ /dev/null @@ -1,388 +0,0 @@ -/* -Copyright (c) 2015 NicoHood -See the readme for credit to other people. - -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 "HIDBridge.h" - -HIDBridge_ HIDBridge; - -HIDBridge_::HIDBridge_(void){ - // empty -} - -void HIDBridge_::begin(void) -{ - // start the serial at our own baud rate - HIDBRIDGE_SERIAL.begin(HIDBRIDGE_BAUD); - - rxReady = true; - txReady = false; //move to end? - - // wait for/send the first request to see if usb device is connected - available(); -} - -void HIDBridge_::end(void) -{ - // end the serial transmission and reset our helper values - HIDBRIDGE_SERIAL.end(); - nhp_read.mode = NHP_RESET; - rxReady = false; //TODO - isConnected = false; - //TODO reset more stuff -} - - -void HIDBridge_::err(uint8_t error) -{ - if (!debug) - return; - debug->print("err"); - debug->println(error); -} - - -void HIDBridge_::writeState(void) { - // send the current state to the other mcu - NHP_Write_Data_t n; - writeNHPAddress(HIDBRIDGE_CONTROL_ADDRESS, rxReady, &n); - HIDBRIDGE_SERIAL.write(n.writeBuffer, n.writeLength); - - // save new timeout - writeTimeout = millis(); -} - -void HIDBridge_::task(void){ - //TODO implement Serialevent strong for this task? -#ifdef HIDBRIDGE_RX - // if hid request timed out, send a new one - // this is important if the main mcu gets a reset or misses an acknowledge - uint32_t currentMillis = millis(); - if ((currentMillis - writeTimeout) > HIDBRIDGE_TX_TIMEOUT) { - writeState(); - // do not write timeout value, will be written in the function above -#ifdef USB_DEBUG - debug->println("ack 1s"); -#endif - } -#endif - - // read in new controls or data - read(); -} - -void HIDBridge_::read(void) -{ - // check for read timeout only if really needed - if (!nhp_read.mode){ - if (millis() - readTimeout > HIDBRIDGE_RX_TIMEOUT) { - // reset reportID and NHP if we have a timeout - reportID = 0; - nhp_read.mode = NHP_RESET; - err(HIDBRIDGE_ERR_READ_TO); - } - } - - // read as long as the Serial is available - // but do not block forever - rx_buffer_index_t i; - for (i = 0; i < SERIAL_RX_BUFFER_SIZE; i++){ - - // read in new Serial byte - int b = HIDBRIDGE_SERIAL.read(); - if (b < 0) - break; - - // process with NHP protocol - if (readNHP(b, &nhp_read)) { - - // command indicates a new hidReport (command==reportID) or the end (command==0) - if (nhp_read.mode == NHP_COMMAND) - proceedCommand(); - - // NHP address contains control data or hid in/out report data - else if (nhp_read.mode == NHP_ADDRESS) - proceedAddress(); - } - - // NHP reading error - else if (nhp_read.errorLevel) { - // ASCII - if (b < 128) { - // possible main mcu reset - if (!b) - err(HIDBRIDGE_ERR_MCU_RST); - else { //TODO different errors? - err(HIDBRIDGE_ERR_SERIALB); - } - } - else - err(HIDBRIDGE_ERR_SERIALB); - - // do not change rxReady state because of a possible full buffer - // which causes NHP corruption - err(HIDBRIDGE_ERR_NHP_ERR); - } - } // end of for reading loop - - // save new time - if (i) - readTimeout = millis(); -} - - -bool HIDBridge_::available(void) -{ - // try to wait for a new request/acknowledge - uint32_t currentMillis = millis(); - do{ - // check for new state information - // maybe the host sended a pause signal - read(); - - // check for timeout, do not wait longer if usb device is not connected - if (!isConnected || (millis() - currentMillis) > HIDBRIDGE_TX_TIMEOUT) { - err(HIDBRIDGE_ERR_TIMEOUT); - break; - } - } while (!txReady); - - return txReady; -} - - -void HIDBridge_::proceedCommand(void){ -#ifdef DEBUG - debug->print("c"); - debug->println(nhp_read.command); -#endif - -#ifdef HIDBRIDGE_RX - // proceed a possible end flag - if (nhp_read.command == HIDBRIDGE_COMMAND_END) { - - // we've got a correct USB protocol received. Write it to the host now. - if (reportID && (recvLength == reportLength)) { - rxReady = false; //TODO not needed? -#ifdef USB_DEBUG - // debug print HID reports - debug->print("USBk "); - debug->print(reportID, DEC); - for (uint8_t i = 0; i < reportLength; i++) { - debug->print(", 0x"); - debug->print(hidReport[i], HEX); - } - debug->println(); -#endif - HID_SendReport(reportID, hidReport, reportLength); - - // acknowledge signal - rxReady = true; - writeState(); - } - // log an error - else - err(HIDBRIDGE_ERR_CMD_END); - - // reset reportID in any case - reportID = 0; - } - - // proceed a possible new reportID lead - else { - // flag an error if we have a pending report - if (reportID) - err(HIDBRIDGE_ERR_CMD_RID); - - // determine the new report length - switch (nhp_read.command) { //TODO progmem lookup table -#ifdef HID_MOUSE_ENABLE - case HID_REPORTID_MOUSE: - reportLength = sizeof(HID_MouseReport_Data_t); - break; -#endif - -#ifdef HID_MOUSE_ABSOLUTE_ENABLE - case HID_REPORTID_MOUSE_ABSOLUTE: - reportLength = sizeof(HID_MouseAbsoluteReport_Data_t); - break; -#endif - -#ifdef HID_KEYBOARD_ENABLE - case HID_REPORTID_KEYBOARD: - reportLength = sizeof(HID_KeyboardReport_Data_t); - break; -#endif - -#ifdef HID_CONSUMERCONTROL_ENABLE - case HID_REPORTID_CONSUMERCONTROL: - reportLength = sizeof(HID_ConsumerControlReport_Data_t); - break; -#endif - -#ifdef HID_SYSTEMCONTROL_ENABLE - case HID_REPORTID_SYSTEMCONTROL: - reportLength = sizeof(HID_SystemControlReport_Data_t); - break; -#endif - -#ifdef HID_GAMEPAD_ENABLE - case HID_REPORTID_GAMEPAD: - reportLength = sizeof(HID_GamepadReport_Data_t); - break; -#endif - - default: - // error - reportLength = 0; - break; - } - - if (reportLength) { - // save new report properties - reportID = nhp_read.command; - recvLength = 0; - } - else { - // new reportID is not supported - //TODO recv length =0? - reportID = 0; - err(HIDBRIDGE_ERR_COMMAND); - } - } -#else // ifdef HIDBRIDGE_RX - err(HIDBRIDGE_ERR_COMMAND); -#endif -} - - -void HIDBridge_::proceedAddress(void){ -#ifdef DEBUG - debug->print("a"); - debug->print(nhp_read.address); - debug->print(", "); - debug->println(nhp_read.data, HEX); -#endif - - // received a control address - if (nhp_read.address == HIDBRIDGE_CONTROL_ADDRESS) { - reportID = 0; - - // acknowledge/request - if (nhp_read.data == HIDBRIDGE_CONTROL_READY){ - txReady = true; - isConnected = true; - } - - // pause - else if (nhp_read.data == HIDBRIDGE_CONTROL_NOTREADY){ - txReady = false; - isConnected = true; - } - - // usb device detached - else if (nhp_read.data == HIDBRIDGE_CONTROL_NOTCONNECTED){ - txReady = false; - isConnected = false; - } - - // not defined control command - else - err(HIDBRIDGE_ERR_CONTROL); - } -#ifdef HIDBRIDGE_RX - // received correct reportID (in/out) - else if (reportID && (reportID == nhp_read.address) && (recvLength < reportLength)) { - for (uint8_t i = 0; i < 4; i++) { - // save hidReport - hidReport[recvLength++] = nhp_read.data8[i]; - - // abort if report finished - if (recvLength == reportLength) - break; - } - } -#endif - // received wrong data: lead command missing/wrong reportID/report too long - else { - reportID = 0; - err(HIDBRIDGE_ERR_ADDRESS); - } -} - - -void HIDBridge_::SendReport(uint8_t reportID, const void* data, int len) -{ - // check the latest request/acknowledge, pause or error - if (!available()){ - err(HIDBRIDGE_ERR_NOT_RDY); - return; - } - - // begin transfer with reportID as command - HIDBRIDGE_SERIAL.write(writeNHPCommand(reportID)); - - // send data in 4 byte packets with the address of the reportID - // the rest (if any, e.g. with 2 byte) is filled with random bytes - NHP_Write_Data_t n; - for (int i = 0; i < len; i += 4) { - writeNHPAddress(reportID, UINT32_AT_OFFSET(data, i), &n); - HIDBRIDGE_SERIAL.write(n.writeBuffer, n.writeLength); - } - - // end transfer with zero command - HIDBRIDGE_SERIAL.write(writeNHPCommand(0)); - - // need a request/acknowledge next time again - txReady = false; - - err(42); -} - -//================================================================================ -// Strong function implementations -//================================================================================ - -// IO MCU only -#ifdef HIDBRIDGE_IO -#ifdef HIDBRIDGE_TX -// overwrites the HID_SendReport function which is empty/not used on a 328/2560 -void HID_SendReport(uint8_t reportID, const void* data, int len) -{ - HIDBridge.SendReport(reportID, data, len); -} -#endif -#endif // #ifdef HIDBRIDGE_IO - - -#ifdef HIDBRIDGE_USE_SERIAL_EVENT -/* -SerialEvent occurs whenever a new data comes in the -hardware serial RX. This routine is run between each -time loop() runs, so using delay inside loop can delay -response. Multiple bytes of data may be available. -*/ -void HIDBRIDGE_SERIAL_EVENT(void) { - HIDBridge.task(); - Serial.println("kk"); -} -#endif diff --git a/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.h b/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.h deleted file mode 100644 index 089d680c20..0000000000 --- a/plugins/KeyboardioHID/avr/libraries/HIDBridge/HIDBridge.h +++ /dev/null @@ -1,167 +0,0 @@ -/* -Copyright (c) 2015 NicoHood -See the readme for credit to other people. - -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 HIDBRIDGE_H -#define HIDBRIDGE_H - -#include -#include "NHP.h" - -//================================================================================ -// Settings -//================================================================================ - -//TODO replace with USB and IO -#define HIDBRIDGE_SERIAL SERIAL_PORT_HARDWARE - -#define HIDBRIDGE_BAUD 2000000 // transfer at highest possible baud - -// use Arduino builtin serialEvent() function to call the HIDBridge task? -#define HIDBRIDGE_USE_SERIAL_EVENT - -//#define DEBUG -#define USB_DEBUG - -// which MCU should act as USB or IO part? -#ifdef USBCON -#define HIDBRIDGE_USB -#else -#define HIDBRIDGE_IO -#endif - -// define if the MCU can do RX, TX or both -// minimal setup: USB RX, IO TX -#ifdef HIDBRIDGE_USB -#define HIDBRIDGE_RX -//#define HIDBRIDGE_TX -#endif -#ifdef HIDBRIDGE_IO -//#define HIDBRIDGE_RX -#define HIDBRIDGE_TX -#endif - -//================================================================================ -// Definitions -//================================================================================ - -#if defined(HIDBRIDGE_USB) && defined(HIDBRIDGE_IO) -#error Cannot send and receive at the same time -// also because it will create the instance of the class -// even if its not used, so we dont separate the TX and RX class names -// function names are kept similar -#endif - -#define HIDBRIDGE_SERIAL_EVENT_WRAPPER_Serial serialEvent -#define HIDBRIDGE_SERIAL_EVENT_WRAPPER_Serial1 serialEvent1 -#define HIDBRIDGE_SERIAL_EVENT HIDBRIDGE_SERIAL_EVENT_WRAPPER_ ## Serial1 - - -#define HIDBRIDGE_TX_TIMEOUT 800 // should be smaller than RX -#define HIDBRIDGE_RX_TIMEOUT 1000 - -#define HIDBRIDGE_CONTROL_ADDRESS 0x00 -#define HIDBRIDGE_CONTROL_NOTREADY 0 -#define HIDBRIDGE_CONTROL_READY 1 -#define HIDBRIDGE_CONTROL_NOTCONNECTED 2 - -#define HIDBRIDGE_COMMAND_END 0 - - -#define HIDBRIDGE_ERR_TIMEOUT 0 -#define HIDBRIDGE_ERR_NHP_ERR 1 -#define HIDBRIDGE_ERR_COMMAND 2 -#define HIDBRIDGE_ERR_ADDRESS 3 -#define HIDBRIDGE_ERR_CONTROL 4 -#define HIDBRIDGE_ERR_NOT_RDY 5 -#define HIDBRIDGE_ERR_READ_TO 6 -#define HIDBRIDGE_ERR_CMD_END 7 -#define HIDBRIDGE_ERR_CMD_RID 8 -#define HIDBRIDGE_ERR_MCU_RST 9 -#define HIDBRIDGE_ERR_SERIALB 10 - - -//================================================================================ -// HIDBridge -//================================================================================ - - -class HIDBridge_{ -public: - HIDBridge_(void); - - // user functions - void begin(void); - void end(void); - - void task(void); - - // advanced user functions - void read(void); - bool available(void); - - // public to access via HID_SendReport - void SendReport(uint8_t reportID, const void* data, int len); - - // debug - void err(uint8_t error); - void writeState(void); - - inline void debugStream(Stream* s){ - debug = s; - } - Stream* debug; - - - - bool txReady; - bool rxReady; - - -private: - - // inlined functions to clear the code - // used in read(), not public accessible - inline void proceedAddress(void); //TODO change to always inline? - inline void proceedCommand(void); - - bool isConnected; - uint32_t readTimeout; - uint32_t writeTimeout; - uint8_t recvLength; - uint8_t reportID; - uint8_t reportLength; - uint8_t hidReport[USB_EP_SIZE - 1]; - - // temporary NHP protocol read data - NHP_Read_Data_t nhp_read; -}; - -extern HIDBridge_ HIDBridge; - - -//================================================================================ -// Function prototypes -//================================================================================ - - -#endif // include guard \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/libraries/HIDBridge/NHP.c b/plugins/KeyboardioHID/avr/libraries/HIDBridge/NHP.c deleted file mode 100644 index d2560fc901..0000000000 --- a/plugins/KeyboardioHID/avr/libraries/HIDBridge/NHP.c +++ /dev/null @@ -1,195 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 "NHP.h" - -//================================================================================ -// Read NHP -//================================================================================ - -bool readNHP(uint8_t input, NHP_Read_Data_t* protocol) { - // get old protocol states and save into temporary variables (better compiler optimization) - uint8_t readLength = protocol->readLength; - uint8_t mode; - uint8_t blocks = protocol->blocks; - uint8_t errorLevel = protocol->errorLevel; - uint32_t data = protocol->data; - uint8_t address; - bool newInput = false; - - // completely reset the protocol after sucessfull reading/error last time - if (protocol->mode) { - blocks = 0; - readLength = 0; - } - // check if previous reading had a lead error, copy that lead byte to the beginning - else if (errorLevel == NHP_ERR_LEAD) { - protocol->readBuffer[0] = protocol->readBuffer[readLength]; - readLength = 1; - } - - // write new byte input to the buffer - protocol->readBuffer[readLength++] = input; - - // reset mode and errorLevel to the default (no error, no input) - errorLevel = NHP_ERR_NONE; - mode = NHP_IN_PROGRESS; - - // check the header(lead/data/end) indicator - uint8_t header = input & NHP_HEADER_MASK; - - if (header == NHP_HEADER_LEAD) - { - if (blocks) { - // we were still reading! Log an error but continue reading with this new lead - // set indicator to move this lead byte to the beginning next reading - errorLevel = NHP_ERR_LEAD; - // write the buffer without the new lead, move it next reading - readLength--; - } - - // read command indicator or block length - blocks = (input >> NHP_LENGTH_OFFSET) & (NHP_LENGTH_MASK >> NHP_LENGTH_OFFSET); - - if (blocks == NHP_LENGTH_COMMAND_0 || blocks == NHP_LENGTH_COMMAND_1) { - // save command in data variable - data = input & NHP_COMMAND_MASK; - // return command indicator, reset next reading - mode = NHP_COMMAND; - newInput = true; - } - // address data - else if (blocks == NHP_LENGTH_HIGH_MSB31) { - // save block length + first 4 data bits (special 32 bit case) - data = input & NHP_DATA_4BIT_MASK; - blocks -= 2; - } - else { - // save block length + first 3 data bits - data = input & NHP_DATA_3BIT_MASK; - blocks--; - } - } - - else if (header == NHP_HEADER_END) - { - // reset next reading on both: valid input or error - if (blocks == 1){ - // valid input, save the address - address = input & NHP_ADDRESS_MASK; - mode = NHP_ADDRESS; - newInput = true; - } - else{ - // too early for an end, reset next time - errorLevel = NHP_ERR_END; - mode = NHP_RESET; - } - } - - else if (header == NHP_HEADER_DATA_A || header == NHP_HEADER_DATA_B) - { - if (blocks > 1) { - // get next 7 bits of data - blocks--; - data <<= NHP_DATA_7BIT; - // normally dont need & NHP_DATA_7BIT_MASK because the MSB bit is zero - data |= (input & NHP_DATA_7BIT_MASK); - } - else { - // log an error, expecting a lead or end byte - errorLevel = NHP_ERR_DATA; - mode = NHP_RESET; - } - } - - // save temporary values to the data struct - protocol->blocks = blocks; - protocol->mode = mode; - protocol->readLength = readLength; - protocol->address = address; - protocol->errorLevel = errorLevel; - protocol->data = data; - - // return if we have a new address or command - return newInput; -} - -//================================================================================ -// Write NHP -//================================================================================ - -uint8_t writeNHPCommand(uint8_t command) { - // write lead mask 11 + length 00|0 or 00|1 including the last bit for the 4 bit command - // return the command with protocol around - return NHP_HEADER_LEAD | (command & NHP_COMMAND_MASK); -} - -void writeNHPAddress(uint8_t address, uint32_t data, NHP_Write_Data_t* protocol) { - // start with the maximum size of blocks (6+1 for special MSB case) - uint8_t blocks = 7; - - // check for the first 7 bit block that doesnt fit into the first 3 bits - while (blocks > 2) { - // get the next 7 bit data block, starting from MSB to LSB - uint8_t nextvalue = (data >> (7 * (blocks - 3))); - if (nextvalue > NHP_DATA_3BIT_MASK) { - // data won't fit into the first 3 bits, wee need an extra block for them - // don't write them to the lead block, keep the data for the data blocks - if (blocks == 7) { - // special case for the MSB where we still want to write - // the 'too big' value into the lead block - protocol->writeBuffer[0] = nextvalue; - blocks = 6; - } - break; - } - else { - // write the possible first 3 bits and check again if the value is zero - // this also ensures that the first byte is always initialized - protocol->writeBuffer[0] = nextvalue; - blocks--; - - // we have our first bits, stop - if (nextvalue) - break; - } - } - - // write the rest of the data blocks - uint8_t datablocks = blocks - 2; - while (datablocks > 0) { - protocol->writeBuffer[datablocks] = data & NHP_DATA_7BIT_MASK; - data >>= 7; - datablocks--; - } - - // add lead 11 + length to the first 3 (or 4 for special MSB case) data bits - protocol->writeBuffer[0] |= NHP_HEADER_LEAD | (blocks << NHP_LENGTH_OFFSET); - - // write end 10 + address - protocol->writeBuffer[blocks - 1] = NHP_HEADER_END | (address & NHP_ADDRESS_MASK); - - // save the number of blocks - protocol->writeLength = blocks; -} \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/libraries/HIDBridge/NHP.h b/plugins/KeyboardioHID/avr/libraries/HIDBridge/NHP.h deleted file mode 100644 index 71e29f9140..0000000000 --- a/plugins/KeyboardioHID/avr/libraries/HIDBridge/NHP.h +++ /dev/null @@ -1,142 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 NHP_H -#define NHP_H - - -#ifdef __cplusplus -extern "C"{ -#endif - -#include //uint_t definitions -#include //bool type - -//================================================================================ -//Settings -//================================================================================ - -// empty - -//================================================================================ -//Definitions -//================================================================================ - -// Header Masks -#define NHP_HEADER_MASK 0xC0 // B11|000000 the two MSB bits determine the block type -#define NHP_HEADER_LEAD 0xC0 // B11|000000 11 MSB -#define NHP_HEADER_DATA_A 0x00 // B00|000000 0X MSB only the first MSB is important -#define NHP_HEADER_DATA_B 0x40 // B01|000000 0X MSB only the first MSB is important -#define NHP_HEADER_END 0x80 // B10|000000 01 MSB - -// Lead -#define NHP_LENGTH_MASK 0x38 // B00|111|000 -#define NHP_LENGTH_OFFSET 3 -#define NHP_LENGTH_COMMAND_0 0 // length 0 indicates a command -#define NHP_LENGTH_COMMAND_1 1 // length 1 indicates a command -#define NHP_LENGTH_HIGH_MSB31 7 // length 7 indicates MSB 31 is high (1) -#define NHP_COMMAND_MASK 0x0F // B0000|1111 // 4bit command(0-15) in lead block - -// Data -#define NHP_DATA_7BIT 7 // data blocks contain 7 bit of information -#define NHP_DATA_7BIT_MASK 0x7F // B0|1111111 // data in data block -#define NHP_DATA_4BIT_MASK 0x0F // B0000|1111 // data in lead (32 bit special MSB case) -#define NHP_DATA_3BIT_MASK 0x07 // B00000|111 // data in lead - -// End -#define NHP_ADDRESS_MASK 0x3F // B00|111111 // 6 bit address (0-63) in end block - -// mode indicators -#define NHP_IN_PROGRESS 0 -#define NHP_ADDRESS 1 -#define NHP_COMMAND 2 -#define NHP_RESET 3 - -// errorLevels -#define NHP_ERR_NONE 0 -#define NHP_ERR_LEAD 1 -#define NHP_ERR_DATA 2 -#define NHP_ERR_END 3 - -// buffer sizes -#define NHP_BUFFER_SIZE 6 -#define NHP_READ_BUFFER_SIZE NHP_BUFFER_SIZE -#define NHP_WRITE_BUFFER_SIZE NHP_BUFFER_SIZE - -// definition to convert an uint8_t array to an uint16_t/uint32_t at any position (thx timeage!) -#define UINT16_AT_OFFSET(p_to_8, offset) ((uint16_t)*((const uint16_t *)((p_to_8)+(offset)))) -#define UINT32_AT_OFFSET(p_to_8, offset) ((uint32_t)*((const uint32_t *)((p_to_8)+(offset)))) - -//================================================================================ -// Typedefs -//================================================================================ - -// protocol read data for temporary variables -typedef union { - struct { - // buffer for read operations - uint8_t readBuffer[NHP_READ_BUFFER_SIZE]; - - // in progress reading data variables - uint8_t readLength : 3; // 0-6 (7 invalid) - uint8_t mode : 2; // in progress, address, command, reset on error (except lead) - uint8_t blocks : 3; // 0-7 - // 2nd byte - uint8_t errorLevel : 2; // no err, lead err, data err, end err - uint8_t address : 6; // 6 bit address (0-63) - union{ - // temporary + final data - uint32_t data; - uint32_t data32; - uint16_t data16[sizeof(uint32_t) / sizeof(uint16_t)]; - uint8_t data8[sizeof(uint32_t) / sizeof(uint8_t)]; - uint8_t command : 4; - }; - }; - uint8_t raw[NHP_READ_BUFFER_SIZE + sizeof(uint8_t) + sizeof(uint8_t) + sizeof(uint32_t)]; -} NHP_Read_Data_t; - -// protocol write data for temporary variables -typedef union { - struct{ - // buffer for write operations - uint8_t writeBuffer[NHP_WRITE_BUFFER_SIZE]; - uint8_t writeLength; - }; - - uint8_t raw[NHP_WRITE_BUFFER_SIZE + sizeof(uint8_t)]; -} NHP_Write_Data_t; - -//================================================================================ -// Function Prototypes -//================================================================================ - -bool readNHP(uint8_t input, NHP_Read_Data_t* protocol); -uint8_t writeNHPCommand(uint8_t command); -void writeNHPAddress(uint8_t address, uint32_t data, NHP_Write_Data_t* protocol); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // include guard \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/libraries/SPI/SPI.cpp b/plugins/KeyboardioHID/avr/libraries/SPI/SPI.cpp deleted file mode 100644 index af14e07b12..0000000000 --- a/plugins/KeyboardioHID/avr/libraries/SPI/SPI.cpp +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (c) 2010 by Cristian Maglie - * Copyright (c) 2014 by Paul Stoffregen (Transaction API) - * Copyright (c) 2014 by Matthijs Kooijman (SPISettings AVR) - * Copyright (c) 2014 by Andrew J. Kroll (atomicity fixes) - * SPI Master library for arduino. - * - * This file is free software; you can redistribute it and/or modify - * it under the terms of either the GNU General Public License version 2 - * or the GNU Lesser General Public License version 2.1, both as - * published by the Free Software Foundation. - */ - -#include "SPI.h" - -SPIClass SPI; - -uint8_t SPIClass::initialized = 0; -uint8_t SPIClass::interruptMode = 0; -uint8_t SPIClass::interruptMask = 0; -uint8_t SPIClass::interruptSave = 0; -#ifdef SPI_TRANSACTION_MISMATCH_LED -uint8_t SPIClass::inTransactionFlag = 0; -#endif - -void SPIClass::begin() -{ - uint8_t sreg = SREG; - noInterrupts(); // Protect from a scheduler and prevent transactionBegin - if (!initialized) { - // Set SS to high so a connected chip will be "deselected" by default - uint8_t port = digitalPinToPort(SS); - uint8_t bit = digitalPinToBitMask(SS); - volatile uint8_t *reg = portModeRegister(port); - - // if the SS pin is not already configured as an output - // then set it high (to enable the internal pull-up resistor) - if(!(*reg & bit)){ - digitalWrite(SS, HIGH); - } - - // When the SS pin is set as OUTPUT, it can be used as - // a general purpose output port (it doesn't influence - // SPI operations). - pinMode(SS, OUTPUT); - - // Warning: if the SS pin ever becomes a LOW INPUT then SPI - // automatically switches to Slave, so the data direction of - // the SS pin MUST be kept as OUTPUT. - SPCR |= _BV(MSTR); - SPCR |= _BV(SPE); - - // Set direction register for SCK and MOSI pin. - // MISO pin automatically overrides to INPUT. - // By doing this AFTER enabling SPI, we avoid accidentally - // clocking in a single bit since the lines go directly - // from "input" to SPI control. - // http://code.google.com/p/arduino/issues/detail?id=888 - pinMode(SCK, OUTPUT); - pinMode(MOSI, OUTPUT); - } - initialized++; // reference count - SREG = sreg; -} - -void SPIClass::end() { - uint8_t sreg = SREG; - noInterrupts(); // Protect from a scheduler and prevent transactionBegin - // Decrease the reference counter - if (initialized) - initialized--; - // If there are no more references disable SPI - if (!initialized) { - SPCR &= ~_BV(SPE); - interruptMode = 0; - #ifdef SPI_TRANSACTION_MISMATCH_LED - inTransactionFlag = 0; - #endif - } - SREG = sreg; -} - -// mapping of interrupt numbers to bits within SPI_AVR_EIMSK -#if defined(__AVR_ATmega32U4__) - #define SPI_INT0_MASK (1< - * Copyright (c) 2014 by Paul Stoffregen (Transaction API) - * Copyright (c) 2014 by Matthijs Kooijman (SPISettings AVR) - * Copyright (c) 2014 by Andrew J. Kroll (atomicity fixes) - * SPI Master library for arduino. - * - * This file is free software; you can redistribute it and/or modify - * it under the terms of either the GNU General Public License version 2 - * or the GNU Lesser General Public License version 2.1, both as - * published by the Free Software Foundation. - */ - -#ifndef _SPI_H_INCLUDED -#define _SPI_H_INCLUDED - -#include - -// SPI_HAS_TRANSACTION means SPI has beginTransaction(), endTransaction(), -// usingInterrupt(), and SPISetting(clock, bitOrder, dataMode) -#define SPI_HAS_TRANSACTION 1 - -// SPI_HAS_NOTUSINGINTERRUPT means that SPI has notUsingInterrupt() method -#define SPI_HAS_NOTUSINGINTERRUPT 1 - -// SPI_ATOMIC_VERSION means that SPI has atomicity fixes and what version. -// This way when there is a bug fix you can check this define to alert users -// of your code if it uses better version of this library. -// This also implies everything that SPI_HAS_TRANSACTION as documented above is -// available too. -#define SPI_ATOMIC_VERSION 1 - -// Uncomment this line to add detection of mismatched begin/end transactions. -// A mismatch occurs if other libraries fail to use SPI.endTransaction() for -// each SPI.beginTransaction(). Connect an LED to this pin. The LED will turn -// on if any mismatch is ever detected. -//#define SPI_TRANSACTION_MISMATCH_LED 5 - -#ifndef LSBFIRST -#define LSBFIRST 0 -#endif -#ifndef MSBFIRST -#define MSBFIRST 1 -#endif - -#define SPI_CLOCK_DIV4 0x00 -#define SPI_CLOCK_DIV16 0x01 -#define SPI_CLOCK_DIV64 0x02 -#define SPI_CLOCK_DIV128 0x03 -#define SPI_CLOCK_DIV2 0x04 -#define SPI_CLOCK_DIV8 0x05 -#define SPI_CLOCK_DIV32 0x06 - -#define SPI_MODE0 0x00 -#define SPI_MODE1 0x04 -#define SPI_MODE2 0x08 -#define SPI_MODE3 0x0C - -#define SPI_MODE_MASK 0x0C // CPOL = bit 3, CPHA = bit 2 on SPCR -#define SPI_CLOCK_MASK 0x03 // SPR1 = bit 1, SPR0 = bit 0 on SPCR -#define SPI_2XCLOCK_MASK 0x01 // SPI2X = bit 0 on SPSR - -// define SPI_AVR_EIMSK for AVR boards with external interrupt pins -#if defined(EIMSK) - #define SPI_AVR_EIMSK EIMSK -#elif defined(GICR) - #define SPI_AVR_EIMSK GICR -#elif defined(GIMSK) - #define SPI_AVR_EIMSK GIMSK -#endif - -class SPISettings { -public: - SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) { - if (__builtin_constant_p(clock)) { - init_AlwaysInline(clock, bitOrder, dataMode); - } else { - init_MightInline(clock, bitOrder, dataMode); - } - } - SPISettings() { - init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0); - } -private: - void init_MightInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) { - init_AlwaysInline(clock, bitOrder, dataMode); - } - void init_AlwaysInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) - __attribute__((__always_inline__)) { - // Clock settings are defined as follows. Note that this shows SPI2X - // inverted, so the bits form increasing numbers. Also note that - // fosc/64 appears twice - // SPR1 SPR0 ~SPI2X Freq - // 0 0 0 fosc/2 - // 0 0 1 fosc/4 - // 0 1 0 fosc/8 - // 0 1 1 fosc/16 - // 1 0 0 fosc/32 - // 1 0 1 fosc/64 - // 1 1 0 fosc/64 - // 1 1 1 fosc/128 - - // We find the fastest clock that is less than or equal to the - // given clock rate. The clock divider that results in clock_setting - // is 2 ^^ (clock_div + 1). If nothing is slow enough, we'll use the - // slowest (128 == 2 ^^ 7, so clock_div = 6). - uint8_t clockDiv; - - // When the clock is known at compiletime, use this if-then-else - // cascade, which the compiler knows how to completely optimize - // away. When clock is not known, use a loop instead, which generates - // shorter code. - if (__builtin_constant_p(clock)) { - if (clock >= F_CPU / 2) { - clockDiv = 0; - } else if (clock >= F_CPU / 4) { - clockDiv = 1; - } else if (clock >= F_CPU / 8) { - clockDiv = 2; - } else if (clock >= F_CPU / 16) { - clockDiv = 3; - } else if (clock >= F_CPU / 32) { - clockDiv = 4; - } else if (clock >= F_CPU / 64) { - clockDiv = 5; - } else { - clockDiv = 6; - } - } else { - uint32_t clockSetting = F_CPU / 2; - clockDiv = 0; - while (clockDiv < 6 && clock < clockSetting) { - clockSetting /= 2; - clockDiv++; - } - } - - // Compensate for the duplicate fosc/64 - if (clockDiv == 6) - clockDiv = 7; - - // Invert the SPI2X bit - clockDiv ^= 0x1; - - // Pack into the SPISettings class - spcr = _BV(SPE) | _BV(MSTR) | ((bitOrder == LSBFIRST) ? _BV(DORD) : 0) | - (dataMode & SPI_MODE_MASK) | ((clockDiv >> 1) & SPI_CLOCK_MASK); - spsr = clockDiv & SPI_2XCLOCK_MASK; - } - uint8_t spcr; - uint8_t spsr; - friend class SPIClass; -}; - - -class SPIClass { -public: - // Initialize the SPI library - static void begin(); - - // If SPI is used from within an interrupt, this function registers - // that interrupt with the SPI library, so beginTransaction() can - // prevent conflicts. The input interruptNumber is the number used - // with attachInterrupt. If SPI is used from a different interrupt - // (eg, a timer), interruptNumber should be 255. - static void usingInterrupt(uint8_t interruptNumber); - // And this does the opposite. - static void notUsingInterrupt(uint8_t interruptNumber); - // Note: the usingInterrupt and notUsingInterrupt functions should - // not to be called from ISR context or inside a transaction. - // For details see: - // https://github.com/arduino/Arduino/pull/2381 - // https://github.com/arduino/Arduino/pull/2449 - - // Before using SPI.transfer() or asserting chip select pins, - // this function is used to gain exclusive access to the SPI bus - // and configure the correct settings. - inline static void beginTransaction(SPISettings settings) { - if (interruptMode > 0) { - uint8_t sreg = SREG; - noInterrupts(); - - #ifdef SPI_AVR_EIMSK - if (interruptMode == 1) { - interruptSave = SPI_AVR_EIMSK; - SPI_AVR_EIMSK &= ~interruptMask; - SREG = sreg; - } else - #endif - { - interruptSave = sreg; - } - } - - #ifdef SPI_TRANSACTION_MISMATCH_LED - if (inTransactionFlag) { - pinMode(SPI_TRANSACTION_MISMATCH_LED, OUTPUT); - digitalWrite(SPI_TRANSACTION_MISMATCH_LED, HIGH); - } - inTransactionFlag = 1; - #endif - - SPCR = settings.spcr; - SPSR = settings.spsr; - } - - // Write to the SPI bus (MOSI pin) and also receive (MISO pin) - inline static uint8_t transfer(uint8_t data) { - SPDR = data; - /* - * The following NOP introduces a small delay that can prevent the wait - * loop form iterating when running at the maximum speed. This gives - * about 10% more speed, even if it seems counter-intuitive. At lower - * speeds it is unnoticed. - */ - asm volatile("nop"); - while (!(SPSR & _BV(SPIF))) ; // wait - return SPDR; - } - inline static uint16_t transfer16(uint16_t data) { - union { uint16_t val; struct { uint8_t lsb; uint8_t msb; }; } in, out; - in.val = data; - if (!(SPCR & _BV(DORD))) { - SPDR = in.msb; - asm volatile("nop"); // See transfer(uint8_t) function - while (!(SPSR & _BV(SPIF))) ; - out.msb = SPDR; - SPDR = in.lsb; - asm volatile("nop"); - while (!(SPSR & _BV(SPIF))) ; - out.lsb = SPDR; - } else { - SPDR = in.lsb; - asm volatile("nop"); - while (!(SPSR & _BV(SPIF))) ; - out.lsb = SPDR; - SPDR = in.msb; - asm volatile("nop"); - while (!(SPSR & _BV(SPIF))) ; - out.msb = SPDR; - } - return out.val; - } - inline static void transfer(void *buf, size_t count) { - if (count == 0) return; - uint8_t *p = (uint8_t *)buf; - SPDR = *p; - while (--count > 0) { - uint8_t out = *(p + 1); - while (!(SPSR & _BV(SPIF))) ; - uint8_t in = SPDR; - SPDR = out; - *p++ = in; - } - while (!(SPSR & _BV(SPIF))) ; - *p = SPDR; - } - // After performing a group of transfers and releasing the chip select - // signal, this function allows others to access the SPI bus - inline static void endTransaction(void) { - #ifdef SPI_TRANSACTION_MISMATCH_LED - if (!inTransactionFlag) { - pinMode(SPI_TRANSACTION_MISMATCH_LED, OUTPUT); - digitalWrite(SPI_TRANSACTION_MISMATCH_LED, HIGH); - } - inTransactionFlag = 0; - #endif - - if (interruptMode > 0) { - #ifdef SPI_AVR_EIMSK - uint8_t sreg = SREG; - #endif - noInterrupts(); - #ifdef SPI_AVR_EIMSK - if (interruptMode == 1) { - SPI_AVR_EIMSK = interruptSave; - SREG = sreg; - } else - #endif - { - SREG = interruptSave; - } - } - } - - // Disable the SPI bus - static void end(); - - // This function is deprecated. New applications should use - // beginTransaction() to configure SPI settings. - inline static void setBitOrder(uint8_t bitOrder) { - if (bitOrder == LSBFIRST) SPCR |= _BV(DORD); - else SPCR &= ~(_BV(DORD)); - } - // This function is deprecated. New applications should use - // beginTransaction() to configure SPI settings. - inline static void setDataMode(uint8_t dataMode) { - SPCR = (SPCR & ~SPI_MODE_MASK) | dataMode; - } - // This function is deprecated. New applications should use - // beginTransaction() to configure SPI settings. - inline static void setClockDivider(uint8_t clockDiv) { - SPCR = (SPCR & ~SPI_CLOCK_MASK) | (clockDiv & SPI_CLOCK_MASK); - SPSR = (SPSR & ~SPI_2XCLOCK_MASK) | ((clockDiv >> 2) & SPI_2XCLOCK_MASK); - } - // These undocumented functions should not be used. SPI.transfer() - // polls the hardware flag which is automatically cleared as the - // AVR responds to SPI's interrupt - inline static void attachInterrupt() { SPCR |= _BV(SPIE); } - inline static void detachInterrupt() { SPCR &= ~_BV(SPIE); } - -private: - static uint8_t initialized; - static uint8_t interruptMode; // 0=none, 1=mask, 2=global - static uint8_t interruptMask; // which interrupts to mask - static uint8_t interruptSave; // temp storage, to restore state - #ifdef SPI_TRANSACTION_MISMATCH_LED - static uint8_t inTransactionFlag; - #endif -}; - -extern SPIClass SPI; - -#endif diff --git a/plugins/KeyboardioHID/avr/libraries/SPI/examples/BarometricPressureSensor/BarometricPressureSensor.ino b/plugins/KeyboardioHID/avr/libraries/SPI/examples/BarometricPressureSensor/BarometricPressureSensor.ino deleted file mode 100644 index 8104fcbc25..0000000000 --- a/plugins/KeyboardioHID/avr/libraries/SPI/examples/BarometricPressureSensor/BarometricPressureSensor.ino +++ /dev/null @@ -1,143 +0,0 @@ -/* - SCP1000 Barometric Pressure Sensor Display - - Shows the output of a Barometric Pressure Sensor on a - Uses the SPI library. For details on the sensor, see: - http://www.sparkfun.com/commerce/product_info.php?products_id=8161 - http://www.vti.fi/en/support/obsolete_products/pressure_sensors/ - - This sketch adapted from Nathan Seidle's SCP1000 example for PIC: - http://www.sparkfun.com/datasheets/Sensors/SCP1000-Testing.zip - - Circuit: - SCP1000 sensor attached to pins 6, 7, 10 - 13: - DRDY: pin 6 - CSB: pin 7 - MOSI: pin 11 - MISO: pin 12 - SCK: pin 13 - - created 31 July 2010 - modified 14 August 2010 - by Tom Igoe - */ - -// the sensor communicates using SPI, so include the library: -#include - -//Sensor's memory register addresses: -const int PRESSURE = 0x1F; //3 most significant bits of pressure -const int PRESSURE_LSB = 0x20; //16 least significant bits of pressure -const int TEMPERATURE = 0x21; //16 bit temperature reading -const byte READ = 0b11111100; // SCP1000's read command -const byte WRITE = 0b00000010; // SCP1000's write command - -// pins used for the connection with the sensor -// the other you need are controlled by the SPI library): -const int dataReadyPin = 6; -const int chipSelectPin = 7; - -void setup() { - Serial.begin(9600); - - // start the SPI library: - SPI.begin(); - - // initalize the data ready and chip select pins: - pinMode(dataReadyPin, INPUT); - pinMode(chipSelectPin, OUTPUT); - - //Configure SCP1000 for low noise configuration: - writeRegister(0x02, 0x2D); - writeRegister(0x01, 0x03); - writeRegister(0x03, 0x02); - // give the sensor time to set up: - delay(100); -} - -void loop() { - //Select High Resolution Mode - writeRegister(0x03, 0x0A); - - // don't do anything until the data ready pin is high: - if (digitalRead(dataReadyPin) == HIGH) { - //Read the temperature data - int tempData = readRegister(0x21, 2); - - // convert the temperature to celsius and display it: - float realTemp = (float)tempData / 20.0; - Serial.print("Temp[C]="); - Serial.print(realTemp); - - - //Read the pressure data highest 3 bits: - byte pressure_data_high = readRegister(0x1F, 1); - pressure_data_high &= 0b00000111; //you only needs bits 2 to 0 - - //Read the pressure data lower 16 bits: - unsigned int pressure_data_low = readRegister(0x20, 2); - //combine the two parts into one 19-bit number: - long pressure = ((pressure_data_high << 16) | pressure_data_low) / 4; - - // display the temperature: - Serial.println("\tPressure [Pa]=" + String(pressure)); - } -} - -//Read from or write to register from the SCP1000: -unsigned int readRegister(byte thisRegister, int bytesToRead ) { - byte inByte = 0; // incoming byte from the SPI - unsigned int result = 0; // result to return - Serial.print(thisRegister, BIN); - Serial.print("\t"); - // SCP1000 expects the register name in the upper 6 bits - // of the byte. So shift the bits left by two bits: - thisRegister = thisRegister << 2; - // now combine the address and the command into one byte - byte dataToSend = thisRegister & READ; - Serial.println(thisRegister, BIN); - // take the chip select low to select the device: - digitalWrite(chipSelectPin, LOW); - // send the device the register you want to read: - SPI.transfer(dataToSend); - // send a value of 0 to read the first byte returned: - result = SPI.transfer(0x00); - // decrement the number of bytes left to read: - bytesToRead--; - // if you still have another byte to read: - if (bytesToRead > 0) { - // shift the first byte left, then get the second byte: - result = result << 8; - inByte = SPI.transfer(0x00); - // combine the byte you just got with the previous one: - result = result | inByte; - // decrement the number of bytes left to read: - bytesToRead--; - } - // take the chip select high to de-select: - digitalWrite(chipSelectPin, HIGH); - // return the result: - return(result); -} - - -//Sends a write command to SCP1000 - -void writeRegister(byte thisRegister, byte thisValue) { - - // SCP1000 expects the register address in the upper 6 bits - // of the byte. So shift the bits left by two bits: - thisRegister = thisRegister << 2; - // now combine the register address and the command into one byte: - byte dataToSend = thisRegister | WRITE; - - // take the chip select low to select the device: - digitalWrite(chipSelectPin, LOW); - - SPI.transfer(dataToSend); //Send register location - SPI.transfer(thisValue); //Send value to record into register - - // take the chip select high to de-select: - digitalWrite(chipSelectPin, HIGH); -} - diff --git a/plugins/KeyboardioHID/avr/libraries/SPI/examples/DigitalPotControl/DigitalPotControl.ino b/plugins/KeyboardioHID/avr/libraries/SPI/examples/DigitalPotControl/DigitalPotControl.ino deleted file mode 100644 index b135a74f4e..0000000000 --- a/plugins/KeyboardioHID/avr/libraries/SPI/examples/DigitalPotControl/DigitalPotControl.ino +++ /dev/null @@ -1,71 +0,0 @@ -/* - Digital Pot Control - - This example controls an Analog Devices AD5206 digital potentiometer. - The AD5206 has 6 potentiometer channels. Each channel's pins are labeled - A - connect this to voltage - W - this is the pot's wiper, which changes when you set it - B - connect this to ground. - - The AD5206 is SPI-compatible,and to command it, you send two bytes, - one with the channel number (0 - 5) and one with the resistance value for the - channel (0 - 255). - - The circuit: - * All A pins of AD5206 connected to +5V - * All B pins of AD5206 connected to ground - * An LED and a 220-ohm resisor in series connected from each W pin to ground - * CS - to digital pin 10 (SS pin) - * SDI - to digital pin 11 (MOSI pin) - * CLK - to digital pin 13 (SCK pin) - - created 10 Aug 2010 - by Tom Igoe - - Thanks to Heather Dewey-Hagborg for the original tutorial, 2005 - -*/ - - -// inslude the SPI library: -#include - - -// set pin 10 as the slave select for the digital pot: -const int slaveSelectPin = 10; - -void setup() { - // set the slaveSelectPin as an output: - pinMode (slaveSelectPin, OUTPUT); - // initialize SPI: - SPI.begin(); -} - -void loop() { - // go through the six channels of the digital pot: - for (int channel = 0; channel < 6; channel++) { - // change the resistance on this channel from min to max: - for (int level = 0; level < 255; level++) { - digitalPotWrite(channel, level); - delay(10); - } - // wait a second at the top: - delay(100); - // change the resistance on this channel from max to min: - for (int level = 0; level < 255; level++) { - digitalPotWrite(channel, 255 - level); - delay(10); - } - } - -} - -void digitalPotWrite(int address, int value) { - // take the SS pin low to select the chip: - digitalWrite(slaveSelectPin, LOW); - // send in the address and value via SPI: - SPI.transfer(address); - SPI.transfer(value); - // take the SS pin high to de-select the chip: - digitalWrite(slaveSelectPin, HIGH); -} diff --git a/plugins/KeyboardioHID/avr/libraries/SPI/keywords.txt b/plugins/KeyboardioHID/avr/libraries/SPI/keywords.txt deleted file mode 100644 index fa7616581a..0000000000 --- a/plugins/KeyboardioHID/avr/libraries/SPI/keywords.txt +++ /dev/null @@ -1,36 +0,0 @@ -####################################### -# Syntax Coloring Map SPI -####################################### - -####################################### -# Datatypes (KEYWORD1) -####################################### - -SPI KEYWORD1 - -####################################### -# Methods and Functions (KEYWORD2) -####################################### -begin KEYWORD2 -end KEYWORD2 -transfer KEYWORD2 -setBitOrder KEYWORD2 -setDataMode KEYWORD2 -setClockDivider KEYWORD2 - - -####################################### -# Constants (LITERAL1) -####################################### -SPI_CLOCK_DIV4 LITERAL1 -SPI_CLOCK_DIV16 LITERAL1 -SPI_CLOCK_DIV64 LITERAL1 -SPI_CLOCK_DIV128 LITERAL1 -SPI_CLOCK_DIV2 LITERAL1 -SPI_CLOCK_DIV8 LITERAL1 -SPI_CLOCK_DIV32 LITERAL1 -SPI_CLOCK_DIV64 LITERAL1 -SPI_MODE0 LITERAL1 -SPI_MODE1 LITERAL1 -SPI_MODE2 LITERAL1 -SPI_MODE3 LITERAL1 \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/libraries/SPI/library.properties b/plugins/KeyboardioHID/avr/libraries/SPI/library.properties deleted file mode 100644 index 2964aecfe5..0000000000 --- a/plugins/KeyboardioHID/avr/libraries/SPI/library.properties +++ /dev/null @@ -1,9 +0,0 @@ -name=SPI -version=1.0 -author=Arduino -maintainer=Arduino -sentence=Enables the communication with devices that use the Serial Peripheral Interface (SPI) Bus. For all Arduino boards, BUT Arduino DUE. -paragraph= -url=http://www.arduino.cc/en/Reference/SPI -architectures=avr - diff --git a/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/SoftwareSerial.cpp b/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/SoftwareSerial.cpp deleted file mode 100644 index b4e4529513..0000000000 --- a/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/SoftwareSerial.cpp +++ /dev/null @@ -1,490 +0,0 @@ -/* -SoftwareSerial.cpp (formerly NewSoftSerial.cpp) - -Multi-instance software serial library for Arduino/Wiring --- Interrupt-driven receive and other improvements by ladyada - (http://ladyada.net) --- Tuning, circular buffer, derivation from class Print/Stream, - multi-instance support, porting to 8MHz processors, - various optimizations, PROGMEM delay tables, inverse logic and - direct port writing by Mikal Hart (http://www.arduiniana.org) --- Pin change interrupt macros by Paul Stoffregen (http://www.pjrc.com) --- 20MHz processor support by Garrett Mace (http://www.macetech.com) --- ATmega1280/2560 support by Brett Hagman (http://www.roguerobotics.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 - -The latest version of this library can always be found at -http://arduiniana.org. -*/ - -// When set, _DEBUG co-opts pins 11 and 13 for debugging with an -// oscilloscope or logic analyzer. Beware: it also slightly modifies -// the bit times, so don't rely on it too much at high baud rates -#define _DEBUG 0 -#define _DEBUG_PIN1 11 -#define _DEBUG_PIN2 13 -// -// Includes -// -#include -#include -#include -#include -#include - -// -// Statics -// -SoftwareSerial *SoftwareSerial::active_object = 0; -char SoftwareSerial::_receive_buffer[_SS_MAX_RX_BUFF]; -volatile uint8_t SoftwareSerial::_receive_buffer_tail = 0; -volatile uint8_t SoftwareSerial::_receive_buffer_head = 0; - -// -// Debugging -// -// This function generates a brief pulse -// for debugging or measuring on an oscilloscope. -inline void DebugPulse(uint8_t pin, uint8_t count) -{ -#if _DEBUG - volatile uint8_t *pport = portOutputRegister(digitalPinToPort(pin)); - - uint8_t val = *pport; - while (count--) - { - *pport = val | digitalPinToBitMask(pin); - *pport = val; - } -#endif -} - -// -// Private methods -// - -/* static */ -inline void SoftwareSerial::tunedDelay(uint16_t delay) { - _delay_loop_2(delay); -} - -// This function sets the current object as the "listening" -// one and returns true if it replaces another -bool SoftwareSerial::listen() -{ - if (!_rx_delay_stopbit) - return false; - - if (active_object != this) - { - if (active_object) - active_object->stopListening(); - - _buffer_overflow = false; - _receive_buffer_head = _receive_buffer_tail = 0; - active_object = this; - - setRxIntMsk(true); - return true; - } - - return false; -} - -// Stop listening. Returns true if we were actually listening. -bool SoftwareSerial::stopListening() -{ - if (active_object == this) - { - setRxIntMsk(false); - active_object = NULL; - return true; - } - return false; -} - -// -// The receive routine called by the interrupt handler -// -void SoftwareSerial::recv() -{ - -#if GCC_VERSION < 40302 -// Work-around for avr-gcc 4.3.0 OSX version bug -// Preserve the registers that the compiler misses -// (courtesy of Arduino forum user *etracer*) - asm volatile( - "push r18 \n\t" - "push r19 \n\t" - "push r20 \n\t" - "push r21 \n\t" - "push r22 \n\t" - "push r23 \n\t" - "push r26 \n\t" - "push r27 \n\t" - ::); -#endif - - uint8_t d = 0; - - // If RX line is high, then we don't see any start bit - // so interrupt is probably not for us - if (_inverse_logic ? rx_pin_read() : !rx_pin_read()) - { - // Disable further interrupts during reception, this prevents - // triggering another interrupt directly after we return, which can - // cause problems at higher baudrates. - setRxIntMsk(false); - - // Wait approximately 1/2 of a bit width to "center" the sample - tunedDelay(_rx_delay_centering); - DebugPulse(_DEBUG_PIN2, 1); - - // Read each of the 8 bits - for (uint8_t i=8; i > 0; --i) - { - tunedDelay(_rx_delay_intrabit); - d >>= 1; - DebugPulse(_DEBUG_PIN2, 1); - if (rx_pin_read()) - d |= 0x80; - } - - if (_inverse_logic) - d = ~d; - - // if buffer full, set the overflow flag and return - uint8_t next = (_receive_buffer_tail + 1) % _SS_MAX_RX_BUFF; - if (next != _receive_buffer_head) - { - // save new data in buffer: tail points to where byte goes - _receive_buffer[_receive_buffer_tail] = d; // save new byte - _receive_buffer_tail = next; - } - else - { - DebugPulse(_DEBUG_PIN1, 1); - _buffer_overflow = true; - } - - // skip the stop bit - tunedDelay(_rx_delay_stopbit); - DebugPulse(_DEBUG_PIN1, 1); - - // Re-enable interrupts when we're sure to be inside the stop bit - setRxIntMsk(true); - - } - -#if GCC_VERSION < 40302 -// Work-around for avr-gcc 4.3.0 OSX version bug -// Restore the registers that the compiler misses - asm volatile( - "pop r27 \n\t" - "pop r26 \n\t" - "pop r23 \n\t" - "pop r22 \n\t" - "pop r21 \n\t" - "pop r20 \n\t" - "pop r19 \n\t" - "pop r18 \n\t" - ::); -#endif -} - -uint8_t SoftwareSerial::rx_pin_read() -{ - return *_receivePortRegister & _receiveBitMask; -} - -// -// Interrupt handling -// - -/* static */ -inline void SoftwareSerial::handle_interrupt() -{ - if (active_object) - { - active_object->recv(); - } -} - -#if defined(PCINT0_vect) -ISR(PCINT0_vect) -{ - SoftwareSerial::handle_interrupt(); -} -#endif - -#if defined(PCINT1_vect) -ISR(PCINT1_vect, ISR_ALIASOF(PCINT0_vect)); -#endif - -#if defined(PCINT2_vect) -ISR(PCINT2_vect, ISR_ALIASOF(PCINT0_vect)); -#endif - -#if defined(PCINT3_vect) -ISR(PCINT3_vect, ISR_ALIASOF(PCINT0_vect)); -#endif - -// -// Constructor -// -SoftwareSerial::SoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic /* = false */) : - _rx_delay_centering(0), - _rx_delay_intrabit(0), - _rx_delay_stopbit(0), - _tx_delay(0), - _buffer_overflow(false), - _inverse_logic(inverse_logic) -{ - setTX(transmitPin); - setRX(receivePin); -} - -// -// Destructor -// -SoftwareSerial::~SoftwareSerial() -{ - end(); -} - -void SoftwareSerial::setTX(uint8_t tx) -{ - // First write, then set output. If we do this the other way around, - // the pin would be output low for a short while before switching to - // output hihg. Now, it is input with pullup for a short while, which - // is fine. With inverse logic, either order is fine. - digitalWrite(tx, _inverse_logic ? LOW : HIGH); - pinMode(tx, OUTPUT); - _transmitBitMask = digitalPinToBitMask(tx); - uint8_t port = digitalPinToPort(tx); - _transmitPortRegister = portOutputRegister(port); -} - -void SoftwareSerial::setRX(uint8_t rx) -{ - pinMode(rx, INPUT); - if (!_inverse_logic) - digitalWrite(rx, HIGH); // pullup for normal logic! - _receivePin = rx; - _receiveBitMask = digitalPinToBitMask(rx); - uint8_t port = digitalPinToPort(rx); - _receivePortRegister = portInputRegister(port); -} - -uint16_t SoftwareSerial::subtract_cap(uint16_t num, uint16_t sub) { - if (num > sub) - return num - sub; - else - return 1; -} - -// -// Public methods -// - -void SoftwareSerial::begin(long speed) -{ - _rx_delay_centering = _rx_delay_intrabit = _rx_delay_stopbit = _tx_delay = 0; - - // Precalculate the various delays, in number of 4-cycle delays - uint16_t bit_delay = (F_CPU / speed) / 4; - - // 12 (gcc 4.8.2) or 13 (gcc 4.3.2) cycles from start bit to first bit, - // 15 (gcc 4.8.2) or 16 (gcc 4.3.2) cycles between bits, - // 12 (gcc 4.8.2) or 14 (gcc 4.3.2) cycles from last bit to stop bit - // These are all close enough to just use 15 cycles, since the inter-bit - // timings are the most critical (deviations stack 8 times) - _tx_delay = subtract_cap(bit_delay, 15 / 4); - - // Only setup rx when we have a valid PCINT for this pin - if (digitalPinToPCICR(_receivePin)) { - #if GCC_VERSION > 40800 - // Timings counted from gcc 4.8.2 output. This works up to 115200 on - // 16Mhz and 57600 on 8Mhz. - // - // When the start bit occurs, there are 3 or 4 cycles before the - // interrupt flag is set, 4 cycles before the PC is set to the right - // interrupt vector address and the old PC is pushed on the stack, - // and then 75 cycles of instructions (including the RJMP in the - // ISR vector table) until the first delay. After the delay, there - // are 17 more cycles until the pin value is read (excluding the - // delay in the loop). - // We want to have a total delay of 1.5 bit time. Inside the loop, - // we already wait for 1 bit time - 23 cycles, so here we wait for - // 0.5 bit time - (71 + 18 - 22) cycles. - _rx_delay_centering = subtract_cap(bit_delay / 2, (4 + 4 + 75 + 17 - 23) / 4); - - // There are 23 cycles in each loop iteration (excluding the delay) - _rx_delay_intrabit = subtract_cap(bit_delay, 23 / 4); - - // There are 37 cycles from the last bit read to the start of - // stopbit delay and 11 cycles from the delay until the interrupt - // mask is enabled again (which _must_ happen during the stopbit). - // This delay aims at 3/4 of a bit time, meaning the end of the - // delay will be at 1/4th of the stopbit. This allows some extra - // time for ISR cleanup, which makes 115200 baud at 16Mhz work more - // reliably - _rx_delay_stopbit = subtract_cap(bit_delay * 3 / 4, (37 + 11) / 4); - #else // Timings counted from gcc 4.3.2 output - // Note that this code is a _lot_ slower, mostly due to bad register - // allocation choices of gcc. This works up to 57600 on 16Mhz and - // 38400 on 8Mhz. - _rx_delay_centering = subtract_cap(bit_delay / 2, (4 + 4 + 97 + 29 - 11) / 4); - _rx_delay_intrabit = subtract_cap(bit_delay, 11 / 4); - _rx_delay_stopbit = subtract_cap(bit_delay * 3 / 4, (44 + 17) / 4); - #endif - - - // Enable the PCINT for the entire port here, but never disable it - // (others might also need it, so we disable the interrupt by using - // the per-pin PCMSK register). - *digitalPinToPCICR(_receivePin) |= _BV(digitalPinToPCICRbit(_receivePin)); - // Precalculate the pcint mask register and value, so setRxIntMask - // can be used inside the ISR without costing too much time. - _pcint_maskreg = digitalPinToPCMSK(_receivePin); - _pcint_maskvalue = _BV(digitalPinToPCMSKbit(_receivePin)); - - tunedDelay(_tx_delay); // if we were low this establishes the end - } - -#if _DEBUG - pinMode(_DEBUG_PIN1, OUTPUT); - pinMode(_DEBUG_PIN2, OUTPUT); -#endif - - listen(); -} - -void SoftwareSerial::setRxIntMsk(bool enable) -{ - if (enable) - *_pcint_maskreg |= _pcint_maskvalue; - else - *_pcint_maskreg &= ~_pcint_maskvalue; -} - -void SoftwareSerial::end() -{ - stopListening(); -} - - -// Read data from buffer -int SoftwareSerial::read() -{ - if (!isListening()) - return -1; - - // Empty buffer? - if (_receive_buffer_head == _receive_buffer_tail) - return -1; - - // Read from "head" - uint8_t d = _receive_buffer[_receive_buffer_head]; // grab next byte - _receive_buffer_head = (_receive_buffer_head + 1) % _SS_MAX_RX_BUFF; - return d; -} - -int SoftwareSerial::available() -{ - if (!isListening()) - return 0; - - return (_receive_buffer_tail + _SS_MAX_RX_BUFF - _receive_buffer_head) % _SS_MAX_RX_BUFF; -} - -size_t SoftwareSerial::write(uint8_t b) -{ - if (_tx_delay == 0) { - setWriteError(); - return 0; - } - - // By declaring these as local variables, the compiler will put them - // in registers _before_ disabling interrupts and entering the - // critical timing sections below, which makes it a lot easier to - // verify the cycle timings - volatile uint8_t *reg = _transmitPortRegister; - uint8_t reg_mask = _transmitBitMask; - uint8_t inv_mask = ~_transmitBitMask; - uint8_t oldSREG = SREG; - bool inv = _inverse_logic; - uint16_t delay = _tx_delay; - - if (inv) - b = ~b; - - cli(); // turn off interrupts for a clean txmit - - // Write the start bit - if (inv) - *reg |= reg_mask; - else - *reg &= inv_mask; - - tunedDelay(delay); - - // Write each of the 8 bits - for (uint8_t i = 8; i > 0; --i) - { - if (b & 1) // choose bit - *reg |= reg_mask; // send 1 - else - *reg &= inv_mask; // send 0 - - tunedDelay(delay); - b >>= 1; - } - - // restore pin to natural state - if (inv) - *reg &= inv_mask; - else - *reg |= reg_mask; - - SREG = oldSREG; // turn interrupts back on - tunedDelay(_tx_delay); - - return 1; -} - -void SoftwareSerial::flush() -{ - if (!isListening()) - return; - - uint8_t oldSREG = SREG; - cli(); - _receive_buffer_head = _receive_buffer_tail = 0; - SREG = oldSREG; -} - -int SoftwareSerial::peek() -{ - if (!isListening()) - return -1; - - // Empty buffer? - if (_receive_buffer_head == _receive_buffer_tail) - return -1; - - // Read from "head" - return _receive_buffer[_receive_buffer_head]; -} diff --git a/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/SoftwareSerial.h b/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/SoftwareSerial.h deleted file mode 100644 index 680e40db1f..0000000000 --- a/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/SoftwareSerial.h +++ /dev/null @@ -1,121 +0,0 @@ -/* -SoftwareSerial.h (formerly NewSoftSerial.h) - -Multi-instance software serial library for Arduino/Wiring --- Interrupt-driven receive and other improvements by ladyada - (http://ladyada.net) --- Tuning, circular buffer, derivation from class Print/Stream, - multi-instance support, porting to 8MHz processors, - various optimizations, PROGMEM delay tables, inverse logic and - direct port writing by Mikal Hart (http://www.arduiniana.org) --- Pin change interrupt macros by Paul Stoffregen (http://www.pjrc.com) --- 20MHz processor support by Garrett Mace (http://www.macetech.com) --- ATmega1280/2560 support by Brett Hagman (http://www.roguerobotics.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 - -The latest version of this library can always be found at -http://arduiniana.org. -*/ - -#ifndef SoftwareSerial_h -#define SoftwareSerial_h - -#include -#include - -/****************************************************************************** -* Definitions -******************************************************************************/ - -#define _SS_MAX_RX_BUFF 64 // RX buffer size -#ifndef GCC_VERSION -#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) -#endif - -class SoftwareSerial : public Stream -{ -private: - // per object data - uint8_t _receivePin; - uint8_t _receiveBitMask; - volatile uint8_t *_receivePortRegister; - uint8_t _transmitBitMask; - volatile uint8_t *_transmitPortRegister; - volatile uint8_t *_pcint_maskreg; - uint8_t _pcint_maskvalue; - - // Expressed as 4-cycle delays (must never be 0!) - uint16_t _rx_delay_centering; - uint16_t _rx_delay_intrabit; - uint16_t _rx_delay_stopbit; - uint16_t _tx_delay; - - uint16_t _buffer_overflow:1; - uint16_t _inverse_logic:1; - - // static data - static char _receive_buffer[_SS_MAX_RX_BUFF]; - static volatile uint8_t _receive_buffer_tail; - static volatile uint8_t _receive_buffer_head; - static SoftwareSerial *active_object; - - // private methods - void recv() __attribute__((__always_inline__)); - uint8_t rx_pin_read(); - void tx_pin_write(uint8_t pin_state) __attribute__((__always_inline__)); - void setTX(uint8_t transmitPin); - void setRX(uint8_t receivePin); - void setRxIntMsk(bool enable) __attribute__((__always_inline__)); - - // Return num - sub, or 1 if the result would be < 1 - static uint16_t subtract_cap(uint16_t num, uint16_t sub); - - // private static method for timing - static inline void tunedDelay(uint16_t delay); - -public: - // public methods - SoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic = false); - ~SoftwareSerial(); - void begin(long speed); - bool listen(); - void end(); - bool isListening() { return this == active_object; } - bool stopListening(); - bool overflow() { bool ret = _buffer_overflow; if (ret) _buffer_overflow = false; return ret; } - int peek(); - - virtual size_t write(uint8_t byte); - virtual int read(); - virtual int available(); - virtual void flush(); - operator bool() { return true; } - - using Print::write; - - // public only for easy access by interrupt handlers - static inline void handle_interrupt() __attribute__((__always_inline__)); -}; - -// Arduino 0012 workaround -#undef int -#undef char -#undef long -#undef byte -#undef float -#undef abs -#undef round - -#endif diff --git a/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/examples/SoftwareSerialExample/SoftwareSerialExample.ino b/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/examples/SoftwareSerialExample/SoftwareSerialExample.ino deleted file mode 100644 index f659133010..0000000000 --- a/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/examples/SoftwareSerialExample/SoftwareSerialExample.ino +++ /dev/null @@ -1,55 +0,0 @@ -/* - Software serial multple serial test - - Receives from the hardware serial, sends to software serial. - Receives from software serial, sends to hardware serial. - - The circuit: - * RX is digital pin 10 (connect to TX of other device) - * TX is digital pin 11 (connect to RX of other device) - - Note: - Not all pins on the Mega and Mega 2560 support change interrupts, - so only the following can be used for RX: - 10, 11, 12, 13, 50, 51, 52, 53, 62, 63, 64, 65, 66, 67, 68, 69 - - Not all pins on the Leonardo support change interrupts, - so only the following can be used for RX: - 8, 9, 10, 11, 14 (MISO), 15 (SCK), 16 (MOSI). - - created back in the mists of time - modified 25 May 2012 - by Tom Igoe - based on Mikal Hart's example - - This example code is in the public domain. - - */ -#include - -SoftwareSerial mySerial(10, 11); // RX, TX - -void setup() -{ - // Open serial communications and wait for port to open: - Serial.begin(57600); - while (!Serial) { - ; // wait for serial port to connect. Needed for Leonardo only - } - - - Serial.println("Goodnight moon!"); - - // set the data rate for the SoftwareSerial port - mySerial.begin(4800); - mySerial.println("Hello, world?"); -} - -void loop() // run over and over -{ - if (mySerial.available()) - Serial.write(mySerial.read()); - if (Serial.available()) - mySerial.write(Serial.read()); -} - diff --git a/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/examples/TwoPortReceive/TwoPortReceive.ino b/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/examples/TwoPortReceive/TwoPortReceive.ino deleted file mode 100644 index 95881a6c41..0000000000 --- a/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/examples/TwoPortReceive/TwoPortReceive.ino +++ /dev/null @@ -1,93 +0,0 @@ -/* - Software serial multple serial test - - Receives from the two software serial ports, - sends to the hardware serial port. - - In order to listen on a software port, you call port.listen(). - When using two software serial ports, you have to switch ports - by listen()ing on each one in turn. Pick a logical time to switch - ports, like the end of an expected transmission, or when the - buffer is empty. This example switches ports when there is nothing - more to read from a port - - The circuit: - Two devices which communicate serially are needed. - * First serial device's TX attached to digital pin 2, RX to pin 3 - * Second serial device's TX attached to digital pin 4, RX to pin 5 - - Note: - Not all pins on the Mega and Mega 2560 support change interrupts, - so only the following can be used for RX: - 10, 11, 12, 13, 50, 51, 52, 53, 62, 63, 64, 65, 66, 67, 68, 69 - - Not all pins on the Leonardo support change interrupts, - so only the following can be used for RX: - 8, 9, 10, 11, 14 (MISO), 15 (SCK), 16 (MOSI). - - created 18 Apr. 2011 - modified 25 May 2012 - by Tom Igoe - based on Mikal Hart's twoPortRXExample - - This example code is in the public domain. - - */ - -#include -// software serial #1: TX = digital pin 10, RX = digital pin 11 -SoftwareSerial portOne(10, 11); - -// software serial #2: TX = digital pin 8, RX = digital pin 9 -// on the Mega, use other pins instead, since 8 and 9 don't work on the Mega -SoftwareSerial portTwo(8, 9); - -void setup() -{ - // Open serial communications and wait for port to open: - Serial.begin(9600); - while (!Serial) { - ; // wait for serial port to connect. Needed for Leonardo only - } - - - // Start each software serial port - portOne.begin(9600); - portTwo.begin(9600); -} - -void loop() -{ - // By default, the last intialized port is listening. - // when you want to listen on a port, explicitly select it: - portOne.listen(); - Serial.println("Data from port one:"); - // while there is data coming in, read it - // and send to the hardware serial port: - while (portOne.available() > 0) { - char inByte = portOne.read(); - Serial.write(inByte); - } - - // blank line to separate data from the two ports: - Serial.println(); - - // Now listen on the second port - portTwo.listen(); - // while there is data coming in, read it - // and send to the hardware serial port: - Serial.println("Data from port two:"); - while (portTwo.available() > 0) { - char inByte = portTwo.read(); - Serial.write(inByte); - } - - // blank line to separate data from the two ports: - Serial.println(); -} - - - - - - diff --git a/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/keywords.txt b/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/keywords.txt deleted file mode 100644 index aaea17c202..0000000000 --- a/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/keywords.txt +++ /dev/null @@ -1,30 +0,0 @@ -####################################### -# Syntax Coloring Map for SoftwareSerial -# (formerly NewSoftSerial) -####################################### - -####################################### -# Datatypes (KEYWORD1) -####################################### - -SoftwareSerial KEYWORD1 - -####################################### -# Methods and Functions (KEYWORD2) -####################################### - -begin KEYWORD2 -end KEYWORD2 -read KEYWORD2 -write KEYWORD2 -available KEYWORD2 -isListening KEYWORD2 -overflow KEYWORD2 -flush KEYWORD2 -listen KEYWORD2 -peek KEYWORD2 - -####################################### -# Constants (LITERAL1) -####################################### - diff --git a/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/library.properties b/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/library.properties deleted file mode 100644 index 37eb04b3dc..0000000000 --- a/plugins/KeyboardioHID/avr/libraries/SoftwareSerial/library.properties +++ /dev/null @@ -1,9 +0,0 @@ -name=SoftwareSerial -version=1.0 -author=Arduino -maintainer=Arduino -sentence=Enables serial communication on digital pins. For all Arduino boards, BUT Arduino DUE. -paragraph= -url=http://www.arduino.cc/en/Reference/SoftwareSerial -architectures=avr - diff --git a/plugins/KeyboardioHID/avr/libraries/Wire/Wire.cpp b/plugins/KeyboardioHID/avr/libraries/Wire/Wire.cpp deleted file mode 100644 index 553add7822..0000000000 --- a/plugins/KeyboardioHID/avr/libraries/Wire/Wire.cpp +++ /dev/null @@ -1,303 +0,0 @@ -/* - TwoWire.cpp - TWI/I2C library for Wiring & Arduino - 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 2012 by Todd Krein (todd@krein.org) to implement repeated starts -*/ - -extern "C" { - #include - #include - #include - #include "twi.h" -} - -#include "Wire.h" - -// Initialize Class Variables ////////////////////////////////////////////////// - -uint8_t TwoWire::rxBuffer[BUFFER_LENGTH]; -uint8_t TwoWire::rxBufferIndex = 0; -uint8_t TwoWire::rxBufferLength = 0; - -uint8_t TwoWire::txAddress = 0; -uint8_t TwoWire::txBuffer[BUFFER_LENGTH]; -uint8_t TwoWire::txBufferIndex = 0; -uint8_t TwoWire::txBufferLength = 0; - -uint8_t TwoWire::transmitting = 0; -void (*TwoWire::user_onRequest)(void); -void (*TwoWire::user_onReceive)(int); - -// Constructors //////////////////////////////////////////////////////////////// - -TwoWire::TwoWire() -{ -} - -// Public Methods ////////////////////////////////////////////////////////////// - -void TwoWire::begin(void) -{ - rxBufferIndex = 0; - rxBufferLength = 0; - - txBufferIndex = 0; - txBufferLength = 0; - - twi_init(); -} - -void TwoWire::begin(uint8_t address) -{ - twi_setAddress(address); - twi_attachSlaveTxEvent(onRequestService); - twi_attachSlaveRxEvent(onReceiveService); - begin(); -} - -void TwoWire::begin(int address) -{ - begin((uint8_t)address); -} - -void TwoWire::setClock(uint32_t frequency) -{ - TWBR = ((F_CPU / frequency) - 16) / 2; -} - -uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop) -{ - // clamp to buffer length - if(quantity > BUFFER_LENGTH){ - quantity = BUFFER_LENGTH; - } - // perform blocking read into buffer - uint8_t read = twi_readFrom(address, rxBuffer, quantity, sendStop); - // set rx buffer iterator vars - rxBufferIndex = 0; - rxBufferLength = read; - - return read; -} - -uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity) -{ - return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true); -} - -uint8_t TwoWire::requestFrom(int address, int quantity) -{ - return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true); -} - -uint8_t TwoWire::requestFrom(int address, int quantity, int sendStop) -{ - return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)sendStop); -} - -void TwoWire::beginTransmission(uint8_t address) -{ - // indicate that we are transmitting - transmitting = 1; - // set address of targeted slave - txAddress = address; - // reset tx buffer iterator vars - txBufferIndex = 0; - txBufferLength = 0; -} - -void TwoWire::beginTransmission(int address) -{ - beginTransmission((uint8_t)address); -} - -// -// Originally, 'endTransmission' was an f(void) function. -// It has been modified to take one parameter indicating -// whether or not a STOP should be performed on the bus. -// Calling endTransmission(false) allows a sketch to -// perform a repeated start. -// -// WARNING: Nothing in the library keeps track of whether -// the bus tenure has been properly ended with a STOP. It -// is very possible to leave the bus in a hung state if -// no call to endTransmission(true) is made. Some I2C -// devices will behave oddly if they do not see a STOP. -// -uint8_t TwoWire::endTransmission(uint8_t sendStop) -{ - // transmit buffer (blocking) - int8_t ret = twi_writeTo(txAddress, txBuffer, txBufferLength, 1, sendStop); - // reset tx buffer iterator vars - txBufferIndex = 0; - txBufferLength = 0; - // indicate that we are done transmitting - transmitting = 0; - return ret; -} - -// This provides backwards compatibility with the original -// definition, and expected behaviour, of endTransmission -// -uint8_t TwoWire::endTransmission(void) -{ - return endTransmission(true); -} - -// must be called in: -// slave tx event callback -// or after beginTransmission(address) -size_t TwoWire::write(uint8_t data) -{ - if(transmitting){ - // in master transmitter mode - // don't bother if buffer is full - if(txBufferLength >= BUFFER_LENGTH){ - setWriteError(); - return 0; - } - // put byte in tx buffer - txBuffer[txBufferIndex] = data; - ++txBufferIndex; - // update amount in buffer - txBufferLength = txBufferIndex; - }else{ - // in slave send mode - // reply to master - twi_transmit(&data, 1); - } - return 1; -} - -// must be called in: -// slave tx event callback -// or after beginTransmission(address) -size_t TwoWire::write(const uint8_t *data, size_t quantity) -{ - if(transmitting){ - // in master transmitter mode - for(size_t i = 0; i < quantity; ++i){ - write(data[i]); - } - }else{ - // in slave send mode - // reply to master - twi_transmit(data, quantity); - } - return quantity; -} - -// must be called in: -// slave rx event callback -// or after requestFrom(address, numBytes) -int TwoWire::available(void) -{ - return rxBufferLength - rxBufferIndex; -} - -// must be called in: -// slave rx event callback -// or after requestFrom(address, numBytes) -int TwoWire::read(void) -{ - int value = -1; - - // get each successive byte on each call - if(rxBufferIndex < rxBufferLength){ - value = rxBuffer[rxBufferIndex]; - ++rxBufferIndex; - } - - return value; -} - -// must be called in: -// slave rx event callback -// or after requestFrom(address, numBytes) -int TwoWire::peek(void) -{ - int value = -1; - - if(rxBufferIndex < rxBufferLength){ - value = rxBuffer[rxBufferIndex]; - } - - return value; -} - -void TwoWire::flush(void) -{ - // XXX: to be implemented. -} - -// behind the scenes function that is called when data is received -void TwoWire::onReceiveService(uint8_t* inBytes, int numBytes) -{ - // don't bother if user hasn't registered a callback - if(!user_onReceive){ - return; - } - // don't bother if rx buffer is in use by a master requestFrom() op - // i know this drops data, but it allows for slight stupidity - // meaning, they may not have read all the master requestFrom() data yet - if(rxBufferIndex < rxBufferLength){ - return; - } - // copy twi rx buffer into local read buffer - // this enables new reads to happen in parallel - for(uint8_t i = 0; i < numBytes; ++i){ - rxBuffer[i] = inBytes[i]; - } - // set rx iterator vars - rxBufferIndex = 0; - rxBufferLength = numBytes; - // alert user program - user_onReceive(numBytes); -} - -// behind the scenes function that is called when data is requested -void TwoWire::onRequestService(void) -{ - // don't bother if user hasn't registered a callback - if(!user_onRequest){ - return; - } - // reset tx buffer iterator vars - // !!! this will kill any pending pre-master sendTo() activity - txBufferIndex = 0; - txBufferLength = 0; - // alert user program - user_onRequest(); -} - -// sets function called on slave write -void TwoWire::onReceive( void (*function)(int) ) -{ - user_onReceive = function; -} - -// sets function called on slave read -void TwoWire::onRequest( void (*function)(void) ) -{ - user_onRequest = function; -} - -// Preinstantiate Objects ////////////////////////////////////////////////////// - -TwoWire Wire = TwoWire(); - diff --git a/plugins/KeyboardioHID/avr/libraries/Wire/Wire.h b/plugins/KeyboardioHID/avr/libraries/Wire/Wire.h deleted file mode 100644 index 732bdc314e..0000000000 --- a/plugins/KeyboardioHID/avr/libraries/Wire/Wire.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - TwoWire.h - TWI/I2C library for Arduino & 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 2012 by Todd Krein (todd@krein.org) to implement repeated starts -*/ - -#ifndef TwoWire_h -#define TwoWire_h - -#include -#include "Stream.h" - -#define BUFFER_LENGTH 32 - -class TwoWire : public Stream -{ - private: - static uint8_t rxBuffer[]; - static uint8_t rxBufferIndex; - static uint8_t rxBufferLength; - - static uint8_t txAddress; - static uint8_t txBuffer[]; - static uint8_t txBufferIndex; - static uint8_t txBufferLength; - - static uint8_t transmitting; - static void (*user_onRequest)(void); - static void (*user_onReceive)(int); - static void onRequestService(void); - static void onReceiveService(uint8_t*, int); - public: - TwoWire(); - void begin(); - void begin(uint8_t); - void begin(int); - void setClock(uint32_t); - void beginTransmission(uint8_t); - void beginTransmission(int); - uint8_t endTransmission(void); - uint8_t endTransmission(uint8_t); - uint8_t requestFrom(uint8_t, uint8_t); - uint8_t requestFrom(uint8_t, uint8_t, uint8_t); - uint8_t requestFrom(int, int); - uint8_t requestFrom(int, int, int); - virtual size_t write(uint8_t); - virtual size_t write(const uint8_t *, size_t); - virtual int available(void); - virtual int read(void); - virtual int peek(void); - virtual void flush(void); - void onReceive( void (*)(int) ); - void onRequest( void (*)(void) ); - - inline size_t write(unsigned long n) { return write((uint8_t)n); } - inline size_t write(long n) { return write((uint8_t)n); } - inline size_t write(unsigned int n) { return write((uint8_t)n); } - inline size_t write(int n) { return write((uint8_t)n); } - using Print::write; -}; - -extern TwoWire Wire; - -#endif - diff --git a/plugins/KeyboardioHID/avr/libraries/Wire/examples/SFRRanger_reader/SFRRanger_reader.ino b/plugins/KeyboardioHID/avr/libraries/Wire/examples/SFRRanger_reader/SFRRanger_reader.ino deleted file mode 100644 index d97a9e3cf8..0000000000 --- a/plugins/KeyboardioHID/avr/libraries/Wire/examples/SFRRanger_reader/SFRRanger_reader.ino +++ /dev/null @@ -1,87 +0,0 @@ -// I2C SRF10 or SRF08 Devantech Ultrasonic Ranger Finder -// by Nicholas Zambetti -// and James Tichenor - -// Demonstrates use of the Wire library reading data from the -// Devantech Utrasonic Rangers SFR08 and SFR10 - -// Created 29 April 2006 - -// This example code is in the public domain. - - -#include - -void setup() -{ - Wire.begin(); // join i2c bus (address optional for master) - Serial.begin(9600); // start serial communication at 9600bps -} - -int reading = 0; - -void loop() -{ - // step 1: instruct sensor to read echoes - Wire.beginTransmission(112); // transmit to device #112 (0x70) - // the address specified in the datasheet is 224 (0xE0) - // but i2c adressing uses the high 7 bits so it's 112 - Wire.write(byte(0x00)); // sets register pointer to the command register (0x00) - Wire.write(byte(0x50)); // command sensor to measure in "inches" (0x50) - // use 0x51 for centimeters - // use 0x52 for ping microseconds - Wire.endTransmission(); // stop transmitting - - // step 2: wait for readings to happen - delay(70); // datasheet suggests at least 65 milliseconds - - // step 3: instruct sensor to return a particular echo reading - Wire.beginTransmission(112); // transmit to device #112 - Wire.write(byte(0x02)); // sets register pointer to echo #1 register (0x02) - Wire.endTransmission(); // stop transmitting - - // step 4: request reading from sensor - Wire.requestFrom(112, 2); // request 2 bytes from slave device #112 - - // step 5: receive reading from sensor - if (2 <= Wire.available()) // if two bytes were received - { - reading = Wire.read(); // receive high byte (overwrites previous reading) - reading = reading << 8; // shift high byte to be high 8 bits - reading |= Wire.read(); // receive low byte as lower 8 bits - Serial.println(reading); // print the reading - } - - delay(250); // wait a bit since people have to read the output :) -} - - -/* - -// The following code changes the address of a Devantech Ultrasonic Range Finder (SRF10 or SRF08) -// usage: changeAddress(0x70, 0xE6); - -void changeAddress(byte oldAddress, byte newAddress) -{ - Wire.beginTransmission(oldAddress); - Wire.write(byte(0x00)); - Wire.write(byte(0xA0)); - Wire.endTransmission(); - - Wire.beginTransmission(oldAddress); - Wire.write(byte(0x00)); - Wire.write(byte(0xAA)); - Wire.endTransmission(); - - Wire.beginTransmission(oldAddress); - Wire.write(byte(0x00)); - Wire.write(byte(0xA5)); - Wire.endTransmission(); - - Wire.beginTransmission(oldAddress); - Wire.write(byte(0x00)); - Wire.write(newAddress); - Wire.endTransmission(); -} - -*/ diff --git a/plugins/KeyboardioHID/avr/libraries/Wire/examples/digital_potentiometer/digital_potentiometer.ino b/plugins/KeyboardioHID/avr/libraries/Wire/examples/digital_potentiometer/digital_potentiometer.ino deleted file mode 100644 index 4d1580a61e..0000000000 --- a/plugins/KeyboardioHID/avr/libraries/Wire/examples/digital_potentiometer/digital_potentiometer.ino +++ /dev/null @@ -1,39 +0,0 @@ -// I2C Digital Potentiometer -// by Nicholas Zambetti -// and Shawn Bonkowski - -// Demonstrates use of the Wire library -// Controls AD5171 digital potentiometer via I2C/TWI - -// Created 31 March 2006 - -// This example code is in the public domain. - -// This example code is in the public domain. - - -#include - -void setup() -{ - Wire.begin(); // join i2c bus (address optional for master) -} - -byte val = 0; - -void loop() -{ - Wire.beginTransmission(44); // transmit to device #44 (0x2c) - // device address is specified in datasheet - Wire.write(byte(0x00)); // sends instruction byte - Wire.write(val); // sends potentiometer value byte - Wire.endTransmission(); // stop transmitting - - val++; // increment value - if (val == 64) // if reached 64th position (max) - { - val = 0; // start over from lowest value - } - delay(500); -} - diff --git a/plugins/KeyboardioHID/avr/libraries/Wire/examples/master_reader/master_reader.ino b/plugins/KeyboardioHID/avr/libraries/Wire/examples/master_reader/master_reader.ino deleted file mode 100644 index 2d2419b323..0000000000 --- a/plugins/KeyboardioHID/avr/libraries/Wire/examples/master_reader/master_reader.ino +++ /dev/null @@ -1,32 +0,0 @@ -// Wire Master Reader -// by Nicholas Zambetti - -// Demonstrates use of the Wire library -// Reads data from an I2C/TWI slave device -// Refer to the "Wire Slave Sender" example for use with this - -// Created 29 March 2006 - -// This example code is in the public domain. - - -#include - -void setup() -{ - Wire.begin(); // join i2c bus (address optional for master) - Serial.begin(9600); // start serial for output -} - -void loop() -{ - Wire.requestFrom(8, 6); // request 6 bytes from slave device #8 - - while (Wire.available()) // slave may send less than requested - { - char c = Wire.read(); // receive a byte as character - Serial.print(c); // print the character - } - - delay(500); -} diff --git a/plugins/KeyboardioHID/avr/libraries/Wire/examples/master_writer/master_writer.ino b/plugins/KeyboardioHID/avr/libraries/Wire/examples/master_writer/master_writer.ino deleted file mode 100644 index 9933cc2cdd..0000000000 --- a/plugins/KeyboardioHID/avr/libraries/Wire/examples/master_writer/master_writer.ino +++ /dev/null @@ -1,31 +0,0 @@ -// Wire Master Writer -// by Nicholas Zambetti - -// Demonstrates use of the Wire library -// Writes data to an I2C/TWI slave device -// Refer to the "Wire Slave Receiver" example for use with this - -// Created 29 March 2006 - -// This example code is in the public domain. - - -#include - -void setup() -{ - Wire.begin(); // join i2c bus (address optional for master) -} - -byte x = 0; - -void loop() -{ - Wire.beginTransmission(8); // transmit to device #8 - Wire.write("x is "); // sends five bytes - Wire.write(x); // sends one byte - Wire.endTransmission(); // stop transmitting - - x++; - delay(500); -} diff --git a/plugins/KeyboardioHID/avr/libraries/Wire/examples/slave_receiver/slave_receiver.ino b/plugins/KeyboardioHID/avr/libraries/Wire/examples/slave_receiver/slave_receiver.ino deleted file mode 100644 index 53df27449f..0000000000 --- a/plugins/KeyboardioHID/avr/libraries/Wire/examples/slave_receiver/slave_receiver.ino +++ /dev/null @@ -1,38 +0,0 @@ -// Wire Slave Receiver -// by Nicholas Zambetti - -// Demonstrates use of the Wire library -// Receives data as an I2C/TWI slave device -// Refer to the "Wire Master Writer" example for use with this - -// Created 29 March 2006 - -// This example code is in the public domain. - - -#include - -void setup() -{ - Wire.begin(8); // join i2c bus with address #8 - Wire.onReceive(receiveEvent); // register event - Serial.begin(9600); // start serial for output -} - -void loop() -{ - delay(100); -} - -// function that executes whenever data is received from master -// this function is registered as an event, see setup() -void receiveEvent(int howMany) -{ - while (1 < Wire.available()) // loop through all but the last - { - char c = Wire.read(); // receive byte as a character - Serial.print(c); // print the character - } - int x = Wire.read(); // receive byte as an integer - Serial.println(x); // print the integer -} diff --git a/plugins/KeyboardioHID/avr/libraries/Wire/examples/slave_sender/slave_sender.ino b/plugins/KeyboardioHID/avr/libraries/Wire/examples/slave_sender/slave_sender.ino deleted file mode 100644 index 26b9e52608..0000000000 --- a/plugins/KeyboardioHID/avr/libraries/Wire/examples/slave_sender/slave_sender.ino +++ /dev/null @@ -1,32 +0,0 @@ -// Wire Slave Sender -// by Nicholas Zambetti - -// Demonstrates use of the Wire library -// Sends data as an I2C/TWI slave device -// Refer to the "Wire Master Reader" example for use with this - -// Created 29 March 2006 - -// This example code is in the public domain. - - -#include - -void setup() -{ - Wire.begin(8); // join i2c bus with address #8 - Wire.onRequest(requestEvent); // register event -} - -void loop() -{ - delay(100); -} - -// function that executes whenever data is requested by master -// this function is registered as an event, see setup() -void requestEvent() -{ - Wire.write("hello "); // respond with message of 6 bytes - // as expected by master -} diff --git a/plugins/KeyboardioHID/avr/libraries/Wire/keywords.txt b/plugins/KeyboardioHID/avr/libraries/Wire/keywords.txt deleted file mode 100644 index ff31475920..0000000000 --- a/plugins/KeyboardioHID/avr/libraries/Wire/keywords.txt +++ /dev/null @@ -1,32 +0,0 @@ -####################################### -# Syntax Coloring Map For Wire -####################################### - -####################################### -# Datatypes (KEYWORD1) -####################################### - -####################################### -# Methods and Functions (KEYWORD2) -####################################### - -begin KEYWORD2 -setClock KEYWORD2 -beginTransmission KEYWORD2 -endTransmission KEYWORD2 -requestFrom KEYWORD2 -send KEYWORD2 -receive KEYWORD2 -onReceive KEYWORD2 -onRequest KEYWORD2 - -####################################### -# Instances (KEYWORD2) -####################################### - -Wire KEYWORD2 - -####################################### -# Constants (LITERAL1) -####################################### - diff --git a/plugins/KeyboardioHID/avr/libraries/Wire/library.properties b/plugins/KeyboardioHID/avr/libraries/Wire/library.properties deleted file mode 100644 index 0805847431..0000000000 --- a/plugins/KeyboardioHID/avr/libraries/Wire/library.properties +++ /dev/null @@ -1,9 +0,0 @@ -name=Wire -version=1.0 -author=Arduino -maintainer=Arduino -sentence=Allows the communication between devices or sensors connected via Two Wire Interface Bus. For all Arduino boards, BUT Arduino DUE. -paragraph= -url=http://www.arduino.cc/en/Reference/Wire -architectures=avr - diff --git a/plugins/KeyboardioHID/avr/libraries/Wire/utility/twi.c b/plugins/KeyboardioHID/avr/libraries/Wire/utility/twi.c deleted file mode 100644 index 201d7d1bbb..0000000000 --- a/plugins/KeyboardioHID/avr/libraries/Wire/utility/twi.c +++ /dev/null @@ -1,527 +0,0 @@ -/* - twi.c - TWI/I2C library for Wiring & Arduino - 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 2012 by Todd Krein (todd@krein.org) to implement repeated starts -*/ - -#include -#include -#include -#include -#include -#include -#include "Arduino.h" // for digitalWrite - -#ifndef cbi -#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) -#endif - -#ifndef sbi -#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) -#endif - -#include "pins_arduino.h" -#include "twi.h" - -static volatile uint8_t twi_state; -static volatile uint8_t twi_slarw; -static volatile uint8_t twi_sendStop; // should the transaction end with a stop -static volatile uint8_t twi_inRepStart; // in the middle of a repeated start - -static void (*twi_onSlaveTransmit)(void); -static void (*twi_onSlaveReceive)(uint8_t*, int); - -static uint8_t twi_masterBuffer[TWI_BUFFER_LENGTH]; -static volatile uint8_t twi_masterBufferIndex; -static volatile uint8_t twi_masterBufferLength; - -static uint8_t twi_txBuffer[TWI_BUFFER_LENGTH]; -static volatile uint8_t twi_txBufferIndex; -static volatile uint8_t twi_txBufferLength; - -static uint8_t twi_rxBuffer[TWI_BUFFER_LENGTH]; -static volatile uint8_t twi_rxBufferIndex; - -static volatile uint8_t twi_error; - -/* - * Function twi_init - * Desc readys twi pins and sets twi bitrate - * Input none - * Output none - */ -void twi_init(void) -{ - // initialize state - twi_state = TWI_READY; - twi_sendStop = true; // default value - twi_inRepStart = false; - - // activate internal pullups for twi. - digitalWrite(SDA, 1); - digitalWrite(SCL, 1); - - // initialize twi prescaler and bit rate - cbi(TWSR, TWPS0); - cbi(TWSR, TWPS1); - TWBR = ((F_CPU / TWI_FREQ) - 16) / 2; - - /* twi bit rate formula from atmega128 manual pg 204 - SCL Frequency = CPU Clock Frequency / (16 + (2 * TWBR)) - note: TWBR should be 10 or higher for master mode - It is 72 for a 16mhz Wiring board with 100kHz TWI */ - - // enable twi module, acks, and twi interrupt - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA); -} - -/* - * Function twi_slaveInit - * Desc sets slave address and enables interrupt - * Input none - * Output none - */ -void twi_setAddress(uint8_t address) -{ - // set twi slave address (skip over TWGCE bit) - TWAR = address << 1; -} - -/* - * Function twi_readFrom - * Desc attempts to become twi bus master and read a - * series of bytes from a device on the bus - * Input address: 7bit i2c device address - * data: pointer to byte array - * length: number of bytes to read into array - * sendStop: Boolean indicating whether to send a stop at the end - * Output number of bytes read - */ -uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length, uint8_t sendStop) -{ - uint8_t i; - - // ensure data will fit into buffer - if(TWI_BUFFER_LENGTH < length){ - return 0; - } - - // wait until twi is ready, become master receiver - while(TWI_READY != twi_state){ - continue; - } - twi_state = TWI_MRX; - twi_sendStop = sendStop; - // reset error state (0xFF.. no error occured) - twi_error = 0xFF; - - // initialize buffer iteration vars - twi_masterBufferIndex = 0; - twi_masterBufferLength = length-1; // This is not intuitive, read on... - // On receive, the previously configured ACK/NACK setting is transmitted in - // response to the received byte before the interrupt is signalled. - // Therefor we must actually set NACK when the _next_ to last byte is - // received, causing that NACK to be sent in response to receiving the last - // expected byte of data. - - // build sla+w, slave device address + w bit - twi_slarw = TW_READ; - twi_slarw |= address << 1; - - if (true == twi_inRepStart) { - // if we're in the repeated start state, then we've already sent the start, - // (@@@ we hope), and the TWI statemachine is just waiting for the address byte. - // We need to remove ourselves from the repeated start state before we enable interrupts, - // since the ISR is ASYNC, and we could get confused if we hit the ISR before cleaning - // up. Also, don't enable the START interrupt. There may be one pending from the - // repeated start that we sent outselves, and that would really confuse things. - twi_inRepStart = false; // remember, we're dealing with an ASYNC ISR - TWDR = twi_slarw; - TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE); // enable INTs, but not START - } - else - // send start condition - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA); - - // wait for read operation to complete - while(TWI_MRX == twi_state){ - continue; - } - - if (twi_masterBufferIndex < length) - length = twi_masterBufferIndex; - - // copy twi buffer to data - for(i = 0; i < length; ++i){ - data[i] = twi_masterBuffer[i]; - } - - return length; -} - -/* - * Function twi_writeTo - * Desc attempts to become twi bus master and write a - * series of bytes to a device on the bus - * Input address: 7bit i2c device address - * data: pointer to byte array - * length: number of bytes in array - * wait: boolean indicating to wait for write or not - * sendStop: boolean indicating whether or not to send a stop at the end - * Output 0 .. success - * 1 .. length to long for buffer - * 2 .. address send, NACK received - * 3 .. data send, NACK received - * 4 .. other twi error (lost bus arbitration, bus error, ..) - */ -uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait, uint8_t sendStop) -{ - uint8_t i; - - // ensure data will fit into buffer - if(TWI_BUFFER_LENGTH < length){ - return 1; - } - - // wait until twi is ready, become master transmitter - while(TWI_READY != twi_state){ - continue; - } - twi_state = TWI_MTX; - twi_sendStop = sendStop; - // reset error state (0xFF.. no error occured) - twi_error = 0xFF; - - // initialize buffer iteration vars - twi_masterBufferIndex = 0; - twi_masterBufferLength = length; - - // copy data to twi buffer - for(i = 0; i < length; ++i){ - twi_masterBuffer[i] = data[i]; - } - - // build sla+w, slave device address + w bit - twi_slarw = TW_WRITE; - twi_slarw |= address << 1; - - // if we're in a repeated start, then we've already sent the START - // in the ISR. Don't do it again. - // - if (true == twi_inRepStart) { - // if we're in the repeated start state, then we've already sent the start, - // (@@@ we hope), and the TWI statemachine is just waiting for the address byte. - // We need to remove ourselves from the repeated start state before we enable interrupts, - // since the ISR is ASYNC, and we could get confused if we hit the ISR before cleaning - // up. Also, don't enable the START interrupt. There may be one pending from the - // repeated start that we sent outselves, and that would really confuse things. - twi_inRepStart = false; // remember, we're dealing with an ASYNC ISR - TWDR = twi_slarw; - TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE); // enable INTs, but not START - } - else - // send start condition - TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE) | _BV(TWSTA); // enable INTs - - // wait for write operation to complete - while(wait && (TWI_MTX == twi_state)){ - continue; - } - - if (twi_error == 0xFF) - return 0; // success - else if (twi_error == TW_MT_SLA_NACK) - return 2; // error: address send, nack received - else if (twi_error == TW_MT_DATA_NACK) - return 3; // error: data send, nack received - else - return 4; // other twi error -} - -/* - * Function twi_transmit - * Desc fills slave tx buffer with data - * must be called in slave tx event callback - * Input data: pointer to byte array - * length: number of bytes in array - * Output 1 length too long for buffer - * 2 not slave transmitter - * 0 ok - */ -uint8_t twi_transmit(const uint8_t* data, uint8_t length) -{ - uint8_t i; - - // ensure data will fit into buffer - if(TWI_BUFFER_LENGTH < length){ - return 1; - } - - // ensure we are currently a slave transmitter - if(TWI_STX != twi_state){ - return 2; - } - - // set length and copy data into tx buffer - twi_txBufferLength = length; - for(i = 0; i < length; ++i){ - twi_txBuffer[i] = data[i]; - } - - return 0; -} - -/* - * Function twi_attachSlaveRxEvent - * Desc sets function called before a slave read operation - * Input function: callback function to use - * Output none - */ -void twi_attachSlaveRxEvent( void (*function)(uint8_t*, int) ) -{ - twi_onSlaveReceive = function; -} - -/* - * Function twi_attachSlaveTxEvent - * Desc sets function called before a slave write operation - * Input function: callback function to use - * Output none - */ -void twi_attachSlaveTxEvent( void (*function)(void) ) -{ - twi_onSlaveTransmit = function; -} - -/* - * Function twi_reply - * Desc sends byte or readys receive line - * Input ack: byte indicating to ack or to nack - * Output none - */ -void twi_reply(uint8_t ack) -{ - // transmit master read ready signal, with or without ack - if(ack){ - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA); - }else{ - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT); - } -} - -/* - * Function twi_stop - * Desc relinquishes bus master status - * Input none - * Output none - */ -void twi_stop(void) -{ - // send stop condition - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTO); - - // wait for stop condition to be exectued on bus - // TWINT is not set after a stop condition! - while(TWCR & _BV(TWSTO)){ - continue; - } - - // update twi state - twi_state = TWI_READY; -} - -/* - * Function twi_releaseBus - * Desc releases bus control - * Input none - * Output none - */ -void twi_releaseBus(void) -{ - // release bus - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT); - - // update twi state - twi_state = TWI_READY; -} - -ISR(TWI_vect) -{ - switch(TW_STATUS){ - // All Master - case TW_START: // sent start condition - case TW_REP_START: // sent repeated start condition - // copy device address and r/w bit to output register and ack - TWDR = twi_slarw; - twi_reply(1); - break; - - // Master Transmitter - case TW_MT_SLA_ACK: // slave receiver acked address - case TW_MT_DATA_ACK: // slave receiver acked data - // if there is data to send, send it, otherwise stop - if(twi_masterBufferIndex < twi_masterBufferLength){ - // copy data to output register and ack - TWDR = twi_masterBuffer[twi_masterBufferIndex++]; - twi_reply(1); - }else{ - if (twi_sendStop) - twi_stop(); - else { - twi_inRepStart = true; // we're gonna send the START - // don't enable the interrupt. We'll generate the start, but we - // avoid handling the interrupt until we're in the next transaction, - // at the point where we would normally issue the start. - TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ; - twi_state = TWI_READY; - } - } - break; - case TW_MT_SLA_NACK: // address sent, nack received - twi_error = TW_MT_SLA_NACK; - twi_stop(); - break; - case TW_MT_DATA_NACK: // data sent, nack received - twi_error = TW_MT_DATA_NACK; - twi_stop(); - break; - case TW_MT_ARB_LOST: // lost bus arbitration - twi_error = TW_MT_ARB_LOST; - twi_releaseBus(); - break; - - // Master Receiver - case TW_MR_DATA_ACK: // data received, ack sent - // put byte into buffer - twi_masterBuffer[twi_masterBufferIndex++] = TWDR; - case TW_MR_SLA_ACK: // address sent, ack received - // ack if more bytes are expected, otherwise nack - if(twi_masterBufferIndex < twi_masterBufferLength){ - twi_reply(1); - }else{ - twi_reply(0); - } - break; - case TW_MR_DATA_NACK: // data received, nack sent - // put final byte into buffer - twi_masterBuffer[twi_masterBufferIndex++] = TWDR; - if (twi_sendStop) - twi_stop(); - else { - twi_inRepStart = true; // we're gonna send the START - // don't enable the interrupt. We'll generate the start, but we - // avoid handling the interrupt until we're in the next transaction, - // at the point where we would normally issue the start. - TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ; - twi_state = TWI_READY; - } - break; - case TW_MR_SLA_NACK: // address sent, nack received - twi_stop(); - break; - // TW_MR_ARB_LOST handled by TW_MT_ARB_LOST case - - // Slave Receiver - case TW_SR_SLA_ACK: // addressed, returned ack - case TW_SR_GCALL_ACK: // addressed generally, returned ack - case TW_SR_ARB_LOST_SLA_ACK: // lost arbitration, returned ack - case TW_SR_ARB_LOST_GCALL_ACK: // lost arbitration, returned ack - // enter slave receiver mode - twi_state = TWI_SRX; - // indicate that rx buffer can be overwritten and ack - twi_rxBufferIndex = 0; - twi_reply(1); - break; - case TW_SR_DATA_ACK: // data received, returned ack - case TW_SR_GCALL_DATA_ACK: // data received generally, returned ack - // if there is still room in the rx buffer - if(twi_rxBufferIndex < TWI_BUFFER_LENGTH){ - // put byte in buffer and ack - twi_rxBuffer[twi_rxBufferIndex++] = TWDR; - twi_reply(1); - }else{ - // otherwise nack - twi_reply(0); - } - break; - case TW_SR_STOP: // stop or repeated start condition received - // put a null char after data if there's room - if(twi_rxBufferIndex < TWI_BUFFER_LENGTH){ - twi_rxBuffer[twi_rxBufferIndex] = '\0'; - } - // sends ack and stops interface for clock stretching - twi_stop(); - // callback to user defined callback - twi_onSlaveReceive(twi_rxBuffer, twi_rxBufferIndex); - // since we submit rx buffer to "wire" library, we can reset it - twi_rxBufferIndex = 0; - // ack future responses and leave slave receiver state - twi_releaseBus(); - break; - case TW_SR_DATA_NACK: // data received, returned nack - case TW_SR_GCALL_DATA_NACK: // data received generally, returned nack - // nack back at master - twi_reply(0); - break; - - // Slave Transmitter - case TW_ST_SLA_ACK: // addressed, returned ack - case TW_ST_ARB_LOST_SLA_ACK: // arbitration lost, returned ack - // enter slave transmitter mode - twi_state = TWI_STX; - // ready the tx buffer index for iteration - twi_txBufferIndex = 0; - // set tx buffer length to be zero, to verify if user changes it - twi_txBufferLength = 0; - // request for txBuffer to be filled and length to be set - // note: user must call twi_transmit(bytes, length) to do this - twi_onSlaveTransmit(); - // if they didn't change buffer & length, initialize it - if(0 == twi_txBufferLength){ - twi_txBufferLength = 1; - twi_txBuffer[0] = 0x00; - } - // transmit first byte from buffer, fall - case TW_ST_DATA_ACK: // byte sent, ack returned - // copy data to output register - TWDR = twi_txBuffer[twi_txBufferIndex++]; - // if there is more to send, ack, otherwise nack - if(twi_txBufferIndex < twi_txBufferLength){ - twi_reply(1); - }else{ - twi_reply(0); - } - break; - case TW_ST_DATA_NACK: // received nack, we are done - case TW_ST_LAST_DATA: // received ack, but we are done already! - // ack future responses - twi_reply(1); - // leave slave receiver state - twi_state = TWI_READY; - break; - - // All - case TW_NO_INFO: // no state information - break; - case TW_BUS_ERROR: // bus error, illegal stop/start - twi_error = TW_BUS_ERROR; - twi_stop(); - break; - } -} - diff --git a/plugins/KeyboardioHID/avr/libraries/Wire/utility/twi.h b/plugins/KeyboardioHID/avr/libraries/Wire/utility/twi.h deleted file mode 100644 index 6526593394..0000000000 --- a/plugins/KeyboardioHID/avr/libraries/Wire/utility/twi.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - twi.h - TWI/I2C library for Wiring & Arduino - 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 -*/ - -#ifndef twi_h -#define twi_h - - #include - - //#define ATMEGA8 - - #ifndef TWI_FREQ - #define TWI_FREQ 100000L - #endif - - #ifndef TWI_BUFFER_LENGTH - #define TWI_BUFFER_LENGTH 32 - #endif - - #define TWI_READY 0 - #define TWI_MRX 1 - #define TWI_MTX 2 - #define TWI_SRX 3 - #define TWI_STX 4 - - void twi_init(void); - void twi_setAddress(uint8_t); - uint8_t twi_readFrom(uint8_t, uint8_t*, uint8_t, uint8_t); - uint8_t twi_writeTo(uint8_t, uint8_t*, uint8_t, uint8_t, uint8_t); - uint8_t twi_transmit(const uint8_t*, uint8_t); - void twi_attachSlaveRxEvent( void (*)(uint8_t*, int) ); - void twi_attachSlaveTxEvent( void (*)(void) ); - void twi_reply(uint8_t); - void twi_stop(void); - void twi_releaseBus(void); - -#endif - diff --git a/plugins/KeyboardioHID/avr/platform.txt b/plugins/KeyboardioHID/avr/platform.txt deleted file mode 100644 index e482e9238a..0000000000 --- a/plugins/KeyboardioHID/avr/platform.txt +++ /dev/null @@ -1,116 +0,0 @@ - -# Arduino AVR Core and platform. -# ------------------------------ - -# For more info: -# https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification -# https://github.com/arduino/Arduino/wiki/Arduino-Hardware-Cores-migration-guide-from-1.0-to-1.6 - -# https://github.com/NicoHood - -name=HID Project USB-Core -version=2.2 - -# AVR compile variables -# --------------------- - -compiler.warning_flags=-w -compiler.warning_flags.none=-w -compiler.warning_flags.default= -compiler.warning_flags.more=-Wall -compiler.warning_flags.all=-Wall -Wextra - -# Default "compiler.path" is correct, change only if you want to overidde the initial value -compiler.path={runtime.tools.avr-gcc.path}/bin/ -compiler.c.cmd=avr-gcc -compiler.c.flags=-c -g -Os {compiler.warning_flags} -ffunction-sections -fdata-sections -MMD -# -w flag added to avoid printing a wrong warning http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59396 -# This is fixed in gcc 4.8.3 and will be removed as soon as we update the toolchain -compiler.c.elf.flags={compiler.warning_flags} -Os -Wl,--gc-sections -compiler.c.elf.cmd=avr-gcc -compiler.S.flags=-c -g -x assembler-with-cpp -compiler.cpp.cmd=avr-g++ -compiler.cpp.flags=-c -g -Os {compiler.warning_flags} -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD -compiler.ar.cmd=avr-ar -compiler.ar.flags=rcs -compiler.objcopy.cmd=avr-objcopy -compiler.objcopy.eep.flags=-O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 -compiler.elf2hex.flags=-O ihex -R .eeprom -compiler.elf2hex.cmd=avr-objcopy -compiler.ldflags= -compiler.size.cmd=avr-size - -# This can be overriden in boards.txt -build.extra_flags= - -# These can be overridden in platform.local.txt -compiler.c.extra_flags= -compiler.c.elf.extra_flags= -compiler.S.extra_flags= -compiler.cpp.extra_flags= -compiler.ar.extra_flags= -compiler.objcopy.eep.extra_flags= -compiler.elf2hex.extra_flags= - -# AVR compile patterns -# -------------------- - -## Compile c files -recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" - -## Compile c++ files -recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" - -## Compile S files -recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.S.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.S.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" - -## Create archives -recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{build.path}/{archive_file}" "{object_file}" - -## Combine gc-sections, archives, and objects -recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mmcu={build.mcu} {compiler.c.elf.extra_flags} -o "{build.path}/sketch/{build.project_name}.elf" {object_files} "{build.path}/{archive_file}" "-L{build.path}" -lm - -## Create output files (.eep and .hex) -recipe.objcopy.eep.pattern="{compiler.path}{compiler.objcopy.cmd}" {compiler.objcopy.eep.flags} {compiler.objcopy.eep.extra_flags} "{build.path}/sketch/{build.project_name}.elf" "{build.path}/sketch/{build.project_name}.eep" -recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.flags} {compiler.elf2hex.extra_flags} "{build.path}/sketch/{build.project_name}.elf" "{build.path}/sketch/{build.project_name}.hex" - -## Save hex -recipe.output.tmp_file={build.project_name}.hex -recipe.output.save_file={build.project_name}.{build.variant}.hex - -## Compute size -recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/sketch/{build.project_name}.elf" -recipe.size.regex=^(?:\.text|\.data|\.bootloader)\s+([0-9]+).* -recipe.size.regex.data=^(?:\.data|\.bss|\.noinit)\s+([0-9]+).* -recipe.size.regex.eeprom=^(?:\.eeprom)\s+([0-9]+).* - - -# AVR Uploader/Programmers tools -# ------------------------------ - -tools.avrdude.path={runtime.tools.avrdude.path} -tools.avrdude.cmd.path={path}/bin/avrdude -tools.avrdude.config.path={path}/etc/avrdude.conf - -tools.avrdude.upload.params.verbose=-v -tools.avrdude.upload.params.quiet=-q -q -tools.avrdude.upload.pattern="{cmd.path}" "-C{config.path}" {upload.verbose} -p{build.mcu} -c{upload.protocol} -P{serial.port} -b{upload.speed} -D "-Uflash:w:{build.path}/sketch/{build.project_name}.hex:i" - -tools.avrdude.program.params.verbose=-v -tools.avrdude.program.params.quiet=-q -q -tools.avrdude.program.pattern="{cmd.path}" "-C{config.path}" {program.verbose} -p{build.mcu} -c{protocol} {program.extra_params} "-Uflash:w:{build.path}/sketch/{build.project_name}.hex:i" - -tools.avrdude.erase.params.verbose=-v -tools.avrdude.erase.params.quiet=-q -q -tools.avrdude.erase.pattern="{cmd.path}" "-C{config.path}" {erase.verbose} -p{build.mcu} -c{protocol} {program.extra_params} -e -Ulock:w:{bootloader.unlock_bits}:m -Uefuse:w:{bootloader.extended_fuses}:m -Uhfuse:w:{bootloader.high_fuses}:m -Ulfuse:w:{bootloader.low_fuses}:m - -tools.avrdude.bootloader.params.verbose=-v -tools.avrdude.bootloader.params.quiet=-q -q -tools.avrdude.bootloader.pattern="{cmd.path}" "-C{config.path}" {bootloader.verbose} -p{build.mcu} -c{protocol} {program.extra_params} "-Uflash:w:{runtime.platform.path}/bootloaders/{bootloader.file}:i" -Ulock:w:{bootloader.lock_bits}:m - - -# USB Default Flags -# Default blank usb manufacturer will be filled it at compile time -# - from numeric vendor ID, set to Unknown otherwise -build.usb_manufacturer="Unknown" -build.usb_flags=-DUSB_VID={build.vid} -DUSB_PID={build.pid} '-DUSB_MANUFACTURER={build.usb_manufacturer}' '-DUSB_PRODUCT={build.usb_product}' diff --git a/plugins/KeyboardioHID/avr/programmers.txt b/plugins/KeyboardioHID/avr/programmers.txt deleted file mode 100644 index 4aa9d6e5c0..0000000000 --- a/plugins/KeyboardioHID/avr/programmers.txt +++ /dev/null @@ -1,8 +0,0 @@ -arduinoispleo.name=Arduino as ISP (Leonardo) -arduinoispleo.communication=serial -arduinoispleo.protocol=arduino -arduinoispleo.speed=19200 -arduinoispleo.program.protocol=arduino -arduinoispleo.program.speed=19200 -arduinoispleo.program.tool=avrdude -arduinoispleo.program.extra_params=-P{serial.port} -b{program.speed} \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/variants/leonardo/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/leonardo/pins_arduino.h deleted file mode 100644 index fd75373c12..0000000000 --- a/plugins/KeyboardioHID/avr/variants/leonardo/pins_arduino.h +++ /dev/null @@ -1,361 +0,0 @@ -/* - 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 - -// Workaround for wrong definitions in "iom32u4.h". -// This should be fixed in the AVR toolchain. -#undef UHCON -#undef UHINT -#undef UHIEN -#undef UHADDR -#undef UHFNUM -#undef UHFNUML -#undef UHFNUMH -#undef UHFLEN -#undef UPINRQX -#undef UPINTX -#undef UPNUM -#undef UPRST -#undef UPCONX -#undef UPCFG0X -#undef UPCFG1X -#undef UPSTAX -#undef UPCFG2X -#undef UPIENX -#undef UPDATX -#undef TCCR2A -#undef WGM20 -#undef WGM21 -#undef COM2B0 -#undef COM2B1 -#undef COM2A0 -#undef COM2A1 -#undef TCCR2B -#undef CS20 -#undef CS21 -#undef CS22 -#undef WGM22 -#undef FOC2B -#undef FOC2A -#undef TCNT2 -#undef TCNT2_0 -#undef TCNT2_1 -#undef TCNT2_2 -#undef TCNT2_3 -#undef TCNT2_4 -#undef TCNT2_5 -#undef TCNT2_6 -#undef TCNT2_7 -#undef OCR2A -#undef OCR2_0 -#undef OCR2_1 -#undef OCR2_2 -#undef OCR2_3 -#undef OCR2_4 -#undef OCR2_5 -#undef OCR2_6 -#undef OCR2_7 -#undef OCR2B -#undef OCR2_0 -#undef OCR2_1 -#undef OCR2_2 -#undef OCR2_3 -#undef OCR2_4 -#undef OCR2_5 -#undef OCR2_6 -#undef OCR2_7 - -#define NUM_DIGITAL_PINS 30 -#define NUM_ANALOG_INPUTS 12 - -#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; -#define LED_BUILTIN 13 - -// 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) ) ) - -#define digitalPinToInterrupt(p) ((p) == 0 ? 2 : ((p) == 1 ? 3 : ((p) == 2 ? 1 : ((p) == 3 ? 0 : ((p) == 7 ? 4 : NOT_AN_INTERRUPT))))) - -#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[] = { - 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[] = { - _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[] = { - 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, - NOT_ON_TIMER, - NOT_ON_TIMER, - NOT_ON_TIMER, - NOT_ON_TIMER, - - NOT_ON_TIMER, - NOT_ON_TIMER, - NOT_ON_TIMER, - NOT_ON_TIMER, - NOT_ON_TIMER, - NOT_ON_TIMER, - NOT_ON_TIMER, - NOT_ON_TIMER, - NOT_ON_TIMER, - NOT_ON_TIMER, -}; - -const uint8_t PROGMEM analog_pin_to_channel_PGM[] = { - 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 */ - -// These serial port names are intended to allow libraries and architecture-neutral -// sketches to automatically default to the correct port name for a particular type -// of use. For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN, -// the first hardware serial port whose RX/TX pins are not dedicated to another use. -// -// SERIAL_PORT_MONITOR Port which normally prints to the Arduino Serial Monitor -// -// SERIAL_PORT_USBVIRTUAL Port which is USB virtual serial -// -// SERIAL_PORT_LINUXBRIDGE Port which connects to a Linux system via Bridge library -// -// SERIAL_PORT_HARDWARE Hardware serial port, physical RX & TX pins. -// -// SERIAL_PORT_HARDWARE_OPEN Hardware serial ports which are open for use. Their RX & TX -// pins are NOT connected to anything by default. -#define SERIAL_PORT_MONITOR Serial -#define SERIAL_PORT_USBVIRTUAL Serial -#define SERIAL_PORT_HARDWARE Serial1 -#define SERIAL_PORT_HARDWARE_OPEN Serial1 - -#endif /* Pins_Arduino_h */ diff --git a/plugins/KeyboardioHID/avr/variants/leonardo_custom/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/leonardo_custom/pins_arduino.h deleted file mode 100644 index 8901811bb0..0000000000 --- a/plugins/KeyboardioHID/avr/variants/leonardo_custom/pins_arduino.h +++ /dev/null @@ -1,157 +0,0 @@ -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -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 the standard leonardo board definition file -#include "../leonardo/pins_arduino.h" - -//================================================================================ -// HID Settings -//================================================================================ - -/* -You have two options to enable/disbale hid functions: - -The nearly full automatic way which enables the specific hid report for you, -enables the specific hid api and also enables the keyboard led function if needed. - -The fully customizable variant where you can create your very own HID report. -You still can use the predefined hid reports or add you very own ones. -You have to enable the specific hid apis on your own then, also the keyboard led function. -*/ - -#define HID_AUTOMATIC -//#define HID_CUSTOM_SETTINGS - -//================================================================================ -// Automatic -//================================================================================ - -#ifdef HID_AUTOMATIC -// pre selected hid reports with autoinclude of the api -#define HID_MOUSE_ENABLE // normal mouse with buttons + wheel -//#define HID_MOUSE_ABSOLUTE_ENABLE // only works with system and without gamepad -#define HID_KEYBOARD_LEDS_ENABLE // leds OR keys -//#define HID_KEYBOARD_KEYS_ENABLE -//#define HID_RAWHID_ENABLE // currently not working -//#define HID_CONSUMERCONTROL_ENABLE -//#define HID_SYSTEMCONTROL_ENABLE -//#define HID_GAMEPAD_ENABLE // only works without mouse absolute - -//================================================================================ -// Custom Settings -//================================================================================ - -#elif defined(HID_CUSTOM_SETTINGS) - -// default setting here shows a mouse + keyboard with no led function -// like in IDE 1.0.6/1.5.8 or lower - -// use this to enable the Keyboard Led functions -//#define HID_KEYBOARD_LEDS_ENABLED - -// add your custom report here: -#define EXTERN_HID_REPORT \ -HID_REPORT_KEYBOARD_KEYS(HID_REPORTID_KEYBOARD), \ -HID_REPORT_MOUSE(HID_REPORTID_MOUSE) - -// activate your custom HID-APIs here: -#define HID_MOUSE_API_ENABLE -//#define HID_MOUSE_ABSOLUTE_API_ENABLE -#define HID_KEYBOARD_API_ENABLE -//#define HID_RAWHID_API_ENABLE -//#define HID_CONSUMERCONTROL_API_ENABLE -//#define HID_SYSTEMCONTROL_API_ENABLE -//#define HID_GAMEPAD_API_ENABLE -//#define HID_ENABLE_ALL_APIS // enables all of the ones above - - -//// 2nd example with a custom Joystick report (the Gamepad API wont work anymor since the report is different) -//#define EXTERN_HID_REPORT \ /* Gamepad with 32 buttons and 10 axis*/ \ -//0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ \ -//0x09, 0x04, /* USAGE (Joystick) */ \ -//0xa1, 0x01, /* COLLECTION (Application) */ \ -//0x85, HID_REPORTID_GAMEPAD, /* REPORT_ID */ \ -///* 32 Buttons */ \ -//0x05, 0x09, /* USAGE_PAGE (Button) */ \ -//0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ \ -//0x29, 0x20, /* USAGE_MAXIMUM (Button 32) */ \ -//0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \ -//0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ \ -//0x75, 0x01, /* REPORT_SIZE (1) */ \ -//0x95, 0x20, /* REPORT_COUNT (32) */ \ -//0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ -///* 10 8bit Axis */ \ -//0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ \ -//0xa1, 0x00, /* COLLECTION (Physical) */ \ -//0x09, 0x30, /* USAGE (X) */ \ -//0x09, 0x31, /* USAGE (Y) */ \ -//0x09, 0x33, /* USAGE (Rx) */ \ -//0x09, 0x34, /* USAGE (Ry) */ \ -//0x09, 0x32, /* USAGE (Z) */ \ -//0x09, 0x35, /* USAGE (Rz) */ \ -//0x09, 0x36, /* Usage (Slider) */ \ -//0x09, 0x36, /* Usage (Slider) */ \ -//0x09, 0x36, /* Usage (Slider) */ \ -//0x09, 0x36, /* Usage (Slider) */ \ -//0x15, 0x80, /* LOGICAL_MINIMUM (-128) */ \ -//0x25, 0x7F, /* LOGICAL_MAXIMUM (127) */ \ -//0x75, 0x08, /* REPORT_SIZE (8) */ \ -//0x95, 0x0A, /* REPORT_COUNT (10) */ \ -//0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ -//0xc0, /* END_COLLECTION */ \ -//0xc0 /* END_COLLECTION */ -// -//// activate your custom HID-APIs here: -////#define HID_MOUSE_API_ENABLE -////#define HID_MOUSE_ABSOLUTE_API_ENABLE -////#define HID_KEYBOARD_API_ENABLE -////#define HID_RAWHID_API_ENABLE -////#define HID_CONSUMERCONTROL_API_ENABLE -////#define HID_SYSTEMCONTROL_API_ENABLE -////#define HID_GAMEPAD_API_ENABLE -////#define HID_ENABLE_ALL_APIS // enables all of the ones above - - -/* -You can use the pre defined reports as well. -Keep in mind that changing the ids or reports might confuse your OS. -Then you might need to reinstall all drivers or change the USB PID. -Mouse Abs only works with a System report together. -Gamepad and Mouse Abs dont work together. -Gamepads can causes some recognition problems with some OS. -RAW HID seems to not works properly in a multireport. -Currently available pre defined reports : -*/ - -//HID_REPORT_KEYBOARD_LEDS(HID_REPORTID_KEYBOARD), -//HID_REPORT_KEYBOARD_KEYS(HID_REPORTID_KEYBOARD), -//HID_REPORT_MOUSE(HID_REPORTID_MOUSE), -//HID_REPORT_MOUSE_ABSOLUTE(HID_REPORTID_MOUSE_ABSOLUTE), -//HID_REPORT_RAWHID(HID_REPORTID_RAWHID), -//HID_REPORT_CONSUMERCONTROL(HID_REPORTID_CONSUMERCONTROL), -//HID_REPORT_SYSTEMCONTROL(HID_REPORTID_SYSTEMCONTROL), -//HID_REPORT_GAMEPAD(HID_REPORTID_GAMEPAD), - -#else -#error Please select automatic or custom hid report in the pins_arduino.h! -#endif \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/variants/leonardo_gamepad/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/leonardo_gamepad/pins_arduino.h deleted file mode 100644 index 3924ea93a6..0000000000 --- a/plugins/KeyboardioHID/avr/variants/leonardo_gamepad/pins_arduino.h +++ /dev/null @@ -1,39 +0,0 @@ -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -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 the standard leonardo board definition file -#include "../leonardo/pins_arduino.h" - -//================================================================================ -// HID Settings -//================================================================================ - -// pre selected hid reports with autoinclude of the api -//#define HID_MOUSE_ENABLE // normal mouse with buttons + wheel -//#define HID_MOUSE_ABSOLUTE_ENABLE // only works with system and without gamepad -//#define HID_KEYBOARD_LEDS_ENABLE // leds OR keys -//#define HID_KEYBOARD_KEYS_ENABLE -//#define HID_RAWHID_ENABLE // currently not working -//#define HID_CONSUMERCONTROL_ENABLE -//#define HID_SYSTEMCONTROL_ENABLE -#define HID_GAMEPAD_ENABLE // only works without mouse absolute diff --git a/plugins/KeyboardioHID/avr/variants/leonardo_hid/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/leonardo_hid/pins_arduino.h deleted file mode 100644 index 8f1f8f3ea6..0000000000 --- a/plugins/KeyboardioHID/avr/variants/leonardo_hid/pins_arduino.h +++ /dev/null @@ -1,39 +0,0 @@ -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -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 the standard leonardo board definition file -#include "../leonardo/pins_arduino.h" - -//================================================================================ -// HID Settings -//================================================================================ - -// pre selected hid reports with autoinclude of the api -#define HID_MOUSE_ENABLE // normal mouse with buttons + wheel -#define HID_MOUSE_ABSOLUTE_ENABLE // only works with system and without gamepad -#define HID_KEYBOARD_LEDS_ENABLE // leds OR keys -//#define HID_KEYBOARD_KEYS_ENABLE -//#define HID_RAWHID_ENABLE // currently not working -#define HID_CONSUMERCONTROL_ENABLE -#define HID_SYSTEMCONTROL_ENABLE -//#define HID_GAMEPAD_ENABLE // only works without mouse absolute diff --git a/plugins/KeyboardioHID/avr/variants/leonardo_no_usb/no_usb_isr.cpp b/plugins/KeyboardioHID/avr/variants/leonardo_no_usb/no_usb_isr.cpp deleted file mode 100644 index 5c5f42242f..0000000000 --- a/plugins/KeyboardioHID/avr/variants/leonardo_no_usb/no_usb_isr.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 -#include - -// workaround for undefined USBCON has to be placed in every sketch -// otherwise the timings wont work correctly -// this is only needed for Leonardo/Micro boards and not for HoodLoader2 -// due to a better bootloader reset (usb clock does not run after programming) -ISR(USB_GEN_vect) -{ - UDINT = 0; -} \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/variants/leonardo_no_usb/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/leonardo_no_usb/pins_arduino.h deleted file mode 100644 index 7d84c5c093..0000000000 --- a/plugins/KeyboardioHID/avr/variants/leonardo_no_usb/pins_arduino.h +++ /dev/null @@ -1,28 +0,0 @@ -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -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 the standard leonardo board definition file -#include "../leonardo/pins_arduino.h" - -// deactivate usb functions -#undef USBCON diff --git a/plugins/KeyboardioHID/avr/variants/micro/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/micro/pins_arduino.h deleted file mode 100644 index ea8e42dd23..0000000000 --- a/plugins/KeyboardioHID/avr/variants/micro/pins_arduino.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - 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 "../leonardo/pins_arduino.h" - -#undef TXLED0 -#undef TXLED1 -#undef RXLED0 -#undef RXLED1 -#undef TX_RX_LED_INIT - -#define TXLED0 PORTD &= ~(1<<5) -#define TXLED1 PORTD |= (1<<5) -#define RXLED0 PORTB &= ~(1<<0) -#define RXLED1 PORTB |= (1<<0) -#define TX_RX_LED_INIT DDRD |= (1<<5), DDRB |= (1<<0), TXLED0, RXLED0 \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/variants/micro_custom/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/micro_custom/pins_arduino.h deleted file mode 100644 index 987774fcec..0000000000 --- a/plugins/KeyboardioHID/avr/variants/micro_custom/pins_arduino.h +++ /dev/null @@ -1,157 +0,0 @@ -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -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 the standard micro board definition file -#include "../micro/pins_arduino.h" - -//================================================================================ -// HID Settings -//================================================================================ - -/* -You have two options to enable/disbale hid functions: - -The nearly full automatic way which enables the specific hid report for you, -enables the specific hid api and also enables the keyboard led function if needed. - -The fully customizable variant where you can create your very own HID report. -You still can use the predefined hid reports or add you very own ones. -You have to enable the specific hid apis on your own then, also the keyboard led function. -*/ - -#define HID_AUTOMATIC -//#define HID_CUSTOM_SETTINGS - -//================================================================================ -// Automatic -//================================================================================ - -#ifdef HID_AUTOMATIC -// pre selected hid reports with autoinclude of the api -#define HID_MOUSE_ENABLE // normal mouse with buttons + wheel -//#define HID_MOUSE_ABSOLUTE_ENABLE // only works with system and without gamepad -#define HID_KEYBOARD_LEDS_ENABLE // leds OR keys -//#define HID_KEYBOARD_KEYS_ENABLE -//#define HID_RAWHID_ENABLE // currently not working -//#define HID_CONSUMERCONTROL_ENABLE -//#define HID_SYSTEMCONTROL_ENABLE -//#define HID_GAMEPAD_ENABLE // only works without mouse absolute - -//================================================================================ -// Custom Settings -//================================================================================ - -#elif defined(HID_CUSTOM_SETTINGS) - -// default setting here shows a mouse + keyboard with no led function -// like in IDE 1.0.6/1.5.8 or lower - -// use this to enable the Keyboard Led functions -//#define HID_KEYBOARD_LEDS_ENABLED - -// add your custom report here: -#define EXTERN_HID_REPORT \ -HID_REPORT_KEYBOARD_KEYS(HID_REPORTID_KEYBOARD), \ -HID_REPORT_MOUSE(HID_REPORTID_MOUSE) - -// activate your custom HID-APIs here: -#define HID_MOUSE_API_ENABLE -//#define HID_MOUSE_ABSOLUTE_API_ENABLE -#define HID_KEYBOARD_API_ENABLE -//#define HID_RAWHID_API_ENABLE -//#define HID_CONSUMERCONTROL_API_ENABLE -//#define HID_SYSTEMCONTROL_API_ENABLE -//#define HID_GAMEPAD_API_ENABLE -//#define HID_ENABLE_ALL_APIS // enables all of the ones above - - -//// 2nd example with a custom Joystick report (the Gamepad API wont work anymor since the report is different) -//#define EXTERN_HID_REPORT \ /* Gamepad with 32 buttons and 10 axis*/ \ -//0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ \ -//0x09, 0x04, /* USAGE (Joystick) */ \ -//0xa1, 0x01, /* COLLECTION (Application) */ \ -//0x85, HID_REPORTID_GAMEPAD, /* REPORT_ID */ \ -///* 32 Buttons */ \ -//0x05, 0x09, /* USAGE_PAGE (Button) */ \ -//0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ \ -//0x29, 0x20, /* USAGE_MAXIMUM (Button 32) */ \ -//0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \ -//0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ \ -//0x75, 0x01, /* REPORT_SIZE (1) */ \ -//0x95, 0x20, /* REPORT_COUNT (32) */ \ -//0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ -///* 10 8bit Axis */ \ -//0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ \ -//0xa1, 0x00, /* COLLECTION (Physical) */ \ -//0x09, 0x30, /* USAGE (X) */ \ -//0x09, 0x31, /* USAGE (Y) */ \ -//0x09, 0x33, /* USAGE (Rx) */ \ -//0x09, 0x34, /* USAGE (Ry) */ \ -//0x09, 0x32, /* USAGE (Z) */ \ -//0x09, 0x35, /* USAGE (Rz) */ \ -//0x09, 0x36, /* Usage (Slider) */ \ -//0x09, 0x36, /* Usage (Slider) */ \ -//0x09, 0x36, /* Usage (Slider) */ \ -//0x09, 0x36, /* Usage (Slider) */ \ -//0x15, 0x80, /* LOGICAL_MINIMUM (-128) */ \ -//0x25, 0x7F, /* LOGICAL_MAXIMUM (127) */ \ -//0x75, 0x08, /* REPORT_SIZE (8) */ \ -//0x95, 0x0A, /* REPORT_COUNT (10) */ \ -//0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ -//0xc0, /* END_COLLECTION */ \ -//0xc0 /* END_COLLECTION */ -// -//// activate your custom HID-APIs here: -////#define HID_MOUSE_API_ENABLE -////#define HID_MOUSE_ABSOLUTE_API_ENABLE -////#define HID_KEYBOARD_API_ENABLE -////#define HID_RAWHID_API_ENABLE -////#define HID_CONSUMERCONTROL_API_ENABLE -////#define HID_SYSTEMCONTROL_API_ENABLE -////#define HID_GAMEPAD_API_ENABLE -////#define HID_ENABLE_ALL_APIS // enables all of the ones above - - -/* -You can use the pre defined reports as well. -Keep in mind that changing the ids or reports might confuse your OS. -Then you might need to reinstall all drivers or change the USB PID. -Mouse Abs only works with a System report together. -Gamepad and Mouse Abs dont work together. -Gamepads can causes some recognition problems with some OS. -RAW HID seems to not works properly in a multireport. -Currently available pre defined reports : -*/ - -//HID_REPORT_KEYBOARD_LEDS(HID_REPORTID_KEYBOARD), -//HID_REPORT_KEYBOARD_KEYS(HID_REPORTID_KEYBOARD), -//HID_REPORT_MOUSE(HID_REPORTID_MOUSE), -//HID_REPORT_MOUSE_ABSOLUTE(HID_REPORTID_MOUSE_ABSOLUTE), -//HID_REPORT_RAWHID(HID_REPORTID_RAWHID), -//HID_REPORT_CONSUMERCONTROL(HID_REPORTID_CONSUMERCONTROL), -//HID_REPORT_SYSTEMCONTROL(HID_REPORTID_SYSTEMCONTROL), -//HID_REPORT_GAMEPAD(HID_REPORTID_GAMEPAD), - -#else -#error Please select automatic or custom hid report in the pins_arduino.h! -#endif \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/variants/micro_gamepad/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/micro_gamepad/pins_arduino.h deleted file mode 100644 index 2bf0c34db8..0000000000 --- a/plugins/KeyboardioHID/avr/variants/micro_gamepad/pins_arduino.h +++ /dev/null @@ -1,39 +0,0 @@ -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -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 the standard micro board definition file -#include "../micro/pins_arduino.h" - -//================================================================================ -// HID Settings -//================================================================================ - -// pre selected hid reports with autoinclude of the api -//#define HID_MOUSE_ENABLE // normal mouse with buttons + wheel -//#define HID_MOUSE_ABSOLUTE_ENABLE // only works with system and without gamepad -//#define HID_KEYBOARD_LEDS_ENABLE // leds OR keys -//#define HID_KEYBOARD_KEYS_ENABLE -//#define HID_RAWHID_ENABLE // currently not working -//#define HID_CONSUMERCONTROL_ENABLE -//#define HID_SYSTEMCONTROL_ENABLE -#define HID_GAMEPAD_ENABLE // only works without mouse absolute diff --git a/plugins/KeyboardioHID/avr/variants/micro_hid/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/micro_hid/pins_arduino.h deleted file mode 100644 index 32e49b0d5c..0000000000 --- a/plugins/KeyboardioHID/avr/variants/micro_hid/pins_arduino.h +++ /dev/null @@ -1,39 +0,0 @@ -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -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 the standard micro board definition file -#include "../micro/pins_arduino.h" - -//================================================================================ -// HID Settings -//================================================================================ - -// pre selected hid reports with autoinclude of the api -#define HID_MOUSE_ENABLE // normal mouse with buttons + wheel -#define HID_MOUSE_ABSOLUTE_ENABLE // only works with system and without gamepad -#define HID_KEYBOARD_LEDS_ENABLE // leds OR keys -//#define HID_KEYBOARD_KEYS_ENABLE -//#define HID_RAWHID_ENABLE // currently not working -#define HID_CONSUMERCONTROL_ENABLE -#define HID_SYSTEMCONTROL_ENABLE -//#define HID_GAMEPAD_ENABLE // only works without mouse absolute diff --git a/plugins/KeyboardioHID/avr/variants/micro_no_usb/no_usb_isr.cpp b/plugins/KeyboardioHID/avr/variants/micro_no_usb/no_usb_isr.cpp deleted file mode 100644 index 5c5f42242f..0000000000 --- a/plugins/KeyboardioHID/avr/variants/micro_no_usb/no_usb_isr.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 -#include - -// workaround for undefined USBCON has to be placed in every sketch -// otherwise the timings wont work correctly -// this is only needed for Leonardo/Micro boards and not for HoodLoader2 -// due to a better bootloader reset (usb clock does not run after programming) -ISR(USB_GEN_vect) -{ - UDINT = 0; -} \ No newline at end of file diff --git a/plugins/KeyboardioHID/avr/variants/micro_no_usb/pins_arduino.h b/plugins/KeyboardioHID/avr/variants/micro_no_usb/pins_arduino.h deleted file mode 100644 index 8cbee830bc..0000000000 --- a/plugins/KeyboardioHID/avr/variants/micro_no_usb/pins_arduino.h +++ /dev/null @@ -1,28 +0,0 @@ -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -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 the standard micro board definition file -#include "../micro/pins_arduino.h" - -// deactivate usb functions -#undef USBCON diff --git a/plugins/KeyboardioHID/examples/HID/Consumer_Basic/Consumer_Basic.ino b/plugins/KeyboardioHID/examples/Consumer/Consumer.ino similarity index 77% rename from plugins/KeyboardioHID/examples/HID/Consumer_Basic/Consumer_Basic.ino rename to plugins/KeyboardioHID/examples/Consumer/Consumer.ino index 12bc93780e..1590007df1 100644 --- a/plugins/KeyboardioHID/examples/HID/Consumer_Basic/Consumer_Basic.ino +++ b/plugins/KeyboardioHID/examples/Consumer/Consumer.ino @@ -1,14 +1,17 @@ /* - Copyright (c) 2014 NicoHood + Copyright (c) 2014-2015 NicoHood See the readme for credit to other people. - Consumer example (former Media example) - + Consumer example Press a button to play/pause music player + See HID Project documentation for more Consumer keys. https://github.com/NicoHood/HID/wiki/Consumer-API */ +#include "HID.h" +#include "Consumer.h" + const int pinLed = LED_BUILTIN; const int pinButton = 2; @@ -24,10 +27,10 @@ void loop() { if (!digitalRead(pinButton)) { digitalWrite(pinLed, HIGH); - // See list above for more definitions or the official usb documentation + // See HID Project documentation for more Consumer keys Consumer.write(MEDIA_PLAY_PAUSE); - // simple debounce + // Simple debounce delay(300); digitalWrite(pinLed, LOW); } diff --git a/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino b/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino new file mode 100644 index 0000000000..008df47d22 --- /dev/null +++ b/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino @@ -0,0 +1,65 @@ +/* + Copyright (c) 2014-2015 NicoHood + See the readme for credit to other people. + + Gamepad example + Press a button and demonstrate Gamepad actions + + See HID Project documentation for more infos + https://github.com/NicoHood/HID/wiki/Gamepad-API +*/ + +#include "Mouse.h" +#include "HID.h" +#include "Gamepad.h" + +const int pinLed = LED_BUILTIN; +const int pinButton = 2; + +void setup() { + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); + + // Sends a clean report to the host. This is important on any Arduino type. + Gamepad.begin(); +} + +void loop() { + if (!digitalRead(pinButton)) { + digitalWrite(pinLed, HIGH); + + // Press button 1-32 + static uint8_t count = 0; + count++; + if (count == 33) { + Gamepad.releaseAll(); + count = 0; + } + else + Gamepad.press(count); + + // Move x/y Axis to a new position (16bit) + Gamepad.xAxis(random(0xFFFF)); + Gamepad.yAxis(random(0xFFFF)); + + // Go through all dPad positions + // values: 0-8 (0==centered) + static uint8_t dpad1 = GAMEPAD_DPAD_CENTERED; + Gamepad.dPad1(dpad1++); + if (dpad1 > GAMEPAD_DPAD_UP_LEFT) + dpad1 = GAMEPAD_DPAD_CENTERED; + + static int8_t dpad2 = GAMEPAD_DPAD_CENTERED; + Gamepad.dPad2(dpad2--); + if (dpad2 < GAMEPAD_DPAD_CENTERED) + dpad2 = GAMEPAD_DPAD_UP_LEFT; + + // Functions above only set the values. + // This writes the report to the host. + Gamepad.write(); + + // Simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } +} diff --git a/plugins/KeyboardioHID/examples/HID/Gamepad_Advanced/Gamepad_Advanced.ino b/plugins/KeyboardioHID/examples/HID/Gamepad_Advanced/Gamepad_Advanced.ino deleted file mode 100644 index 0aeb3df2df..0000000000 --- a/plugins/KeyboardioHID/examples/HID/Gamepad_Advanced/Gamepad_Advanced.ino +++ /dev/null @@ -1,46 +0,0 @@ -/* - Copyright (c) 2014 NicoHood - See the readme for credit to other people. - - Advanced Gamepad example -*/ - -const int pinLed = LED_BUILTIN; -const int pinButton = 2; - -// see HID_Reports.h for all data structures -HID_GamepadReport_Data_t Gamepadreport; - -void setup() { - pinMode(pinLed, OUTPUT); - pinMode(pinButton, INPUT_PULLUP); - - // Sends a clean report to the host. This is important on any Arduino type. - memset(&Gamepadreport, 0, sizeof(Gamepadreport)); - HID_SendReport(HID_REPORTID_GAMEPAD, &Gamepadreport, sizeof(Gamepadreport)); -} - -void loop() { - if (!digitalRead(pinButton)) { - digitalWrite(pinLed, HIGH); - - // This demo is actually made for advanced users to show them how they can write an own report. - // This might be useful for a Gamepad if you want to edit the values direct on your own. - - // count with buttons binary - static uint32_t count = 0; - Gamepadreport.whole32[0] = count++; - - // move x/y Axis to a new position (16bit) - Gamepadreport.whole16[2] = (random(0xFFFF)); - - // functions before only set the values - // this writes the report to the host - HID_SendReport(HID_REPORTID_GAMEPAD, &Gamepadreport, sizeof(Gamepadreport)); - - // simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } -} - diff --git a/plugins/KeyboardioHID/examples/HID/Gamepad_Basic/Gamepad_Basic.ino b/plugins/KeyboardioHID/examples/HID/Gamepad_Basic/Gamepad_Basic.ino deleted file mode 100644 index 54c4bc4ad8..0000000000 --- a/plugins/KeyboardioHID/examples/HID/Gamepad_Basic/Gamepad_Basic.ino +++ /dev/null @@ -1,57 +0,0 @@ -/* - Copyright (c) 2014 NicoHood - See the readme for credit to other people. - - Gamepad example - - Press a button and demonstrate Gamepad actions - See HID Project documentation for more infos - https://github.com/NicoHood/HID/wiki/Gamepad-API - */ - -const int pinLed = LED_BUILTIN; -const int pinButton = 2; - -void setup() { - pinMode(pinLed, OUTPUT); - pinMode(pinButton, INPUT_PULLUP); - - // Sends a clean report to the host. This is important on any Arduino type. - Gamepad.begin(); -} - -void loop() { - if (!digitalRead(pinButton)) { - digitalWrite(pinLed, HIGH); - - // press button 1-32 and reset (34 because its written later) - static uint8_t count = 1; - Gamepad.press(count++); - if (count == 34) { - Gamepad.releaseAll(); - count = 1; - } - - // move x/y Axis to a new position (16bit) - Gamepad.xAxis(random(0xFFFF)); - Gamepad.yAxis(random(0xFFFF)); - - // go through all dPad positions - // values: 0-8 (0==centred) - static uint8_t dpad1 = GAMEPAD_DPAD_CENTERED; - Gamepad.dPad1(dpad1++); - if (dpad1 > GAMEPAD_DPAD_UP_LEFT) dpad1 = GAMEPAD_DPAD_CENTERED; - static int8_t dpad2 = GAMEPAD_DPAD_CENTERED; - Gamepad.dPad2(dpad2--); - if (dpad2 < GAMEPAD_DPAD_CENTERED) dpad2 = GAMEPAD_DPAD_UP_LEFT; - - - // functions above only set the values - // this writes the report to the host - Gamepad.write(); - - // simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } -} diff --git a/plugins/KeyboardioHID/examples/HID/Keyboard_Advanced/Keyboard_Advanced.ino b/plugins/KeyboardioHID/examples/HID/Keyboard_Advanced/Keyboard_Advanced.ino deleted file mode 100644 index 8e8d5bb47f..0000000000 --- a/plugins/KeyboardioHID/examples/HID/Keyboard_Advanced/Keyboard_Advanced.ino +++ /dev/null @@ -1,97 +0,0 @@ -/* - Copyright (c) 2014 NicoHood - See the readme for credit to other people. - - Advanced Keyboard example - - This demo is actually made for advanced users to show them how they can write an own report. - This might be useful for a Keyboard if you only use one key, - because the library has a lot of code for simple use - */ - -const int pinLed = LED_BUILTIN; -const int pinButton = 2; - -void setup() { - pinMode(pinLed, OUTPUT); - pinMode(pinButton, INPUT_PULLUP); - - // Sends a clean report to the host. This is important on any Arduino type. - pressRawKeyboard(0, 0); -} - -void loop() { - if (!digitalRead(pinButton)) { - digitalWrite(pinLed, HIGH); - - // press normal keys (a-z, A-Z, 0-9) - pressRawKeyboard(0, RAW_KEYBOARD_KEY('a')); //modifiers + a - pressRawKeyboard(0, RAW_KEYBOARD_KEY('Z')); //modifiers + Z - - // press STRG + ALT + DEL on keyboard (see usb documentation for more) - //pressRawKeyboard(RAW_KEYBOARD_LEFT_CTRL | RAW_KEYBOARD_LEFT_ALT , RAW_KEYBOARD_DELETE); //modifiers + key - - // release! Important - pressRawKeyboard(0, 0); - - // simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } -} - -void pressRawKeyboard(uint8_t modifiers, uint8_t key) { - uint8_t keys[8] = { - modifiers, 0, key, 0, 0, 0, 0, 0 - }; //modifiers, reserved, key[0] - HID_SendReport(HID_REPORTID_KEYBOARD, keys, sizeof(keys)); -} - -/* -See Hut1_12v2.pdf Chapter 10 (Page 53) for more Keys - (especially a-z, a=0x04 z=29) - Definitions: - - RAW_KEYBOARD_LEFT_CTRL - RAW_KEYBOARD_LEFT_SHIFT - RAW_KEYBOARD_LEFT_ALT - RAW_KEYBOARD_LEFT_GUI - RAW_KEYBOARD_RIGHT_CTRL - RAW_KEYBOARD_RIGHT_SHIFT - RAW_KEYBOARD_RIGHT_ALT - RAW_KEYBOARD_RIGHT_GUI - - RAW_KEYBOARD_KEY(key) - - RAW_KEYBOARD_UP_ARROW - RAW_KEYBOARD_DOWN_ARROW - RAW_KEYBOARD_LEFT_ARROW - RAW_KEYBOARD_RIGHT_ARROW - RAW_KEYBOARD_SPACEBAR - RAW_KEYBOARD_BACKSPACE - RAW_KEYBOARD_TAB - RAW_KEYBOARD_RETURN - RAW_KEYBOARD_ESC - RAW_KEYBOARD_INSERT - RAW_KEYBOARD_DELETE - RAW_KEYBOARD_PAGE_UP - RAW_KEYBOARD_PAGE_DOWN - RAW_KEYBOARD_HOME - RAW_KEYBOARD_END - RAW_KEYBOARD_CAPS_LOCK - RAW_KEYBOARD_F1 - RAW_KEYBOARD_F2 - RAW_KEYBOARD_F3 - RAW_KEYBOARD_F4 - RAW_KEYBOARD_F5 - RAW_KEYBOARD_F6 - RAW_KEYBOARD_F7 - RAW_KEYBOARD_F8 - RAW_KEYBOARD_F9 - RAW_KEYBOARD_F10 - RAW_KEYBOARD_F11 - RAW_KEYBOARD_F12 - RAW_KEYBOARD_PRINT - RAW_KEYBOARD_SCROLL_LOCK - RAW_KEYBOARD_PAUSE - */ \ No newline at end of file diff --git a/plugins/KeyboardioHID/examples/HID/Keyboard_Basic/Keyboard_Basic.ino b/plugins/KeyboardioHID/examples/HID/Keyboard_Basic/Keyboard_Basic.ino deleted file mode 100644 index afba459a38..0000000000 --- a/plugins/KeyboardioHID/examples/HID/Keyboard_Basic/Keyboard_Basic.ino +++ /dev/null @@ -1,39 +0,0 @@ -/* - Copyright (c) 2014-2015 NicoHood - See the readme for credit to other people. - - Keyboard example - - Press a button to write some text to your pc. - See official and HID Project documentation for more infos - https://github.com/NicoHood/HID/wiki/Keyboard-API -*/ - -const int pinLed = LED_BUILTIN; -const int pinButton = 2; - -void setup() { - pinMode(pinLed, OUTPUT); - pinMode(pinButton, INPUT_PULLUP); - - // Starts Serial debug output - Serial.begin(115200); - - // Sends a clean report to the host. This is important on any Arduino type. - Keyboard.begin(); -} - - -void loop() { - if (!digitalRead(pinButton)) { - digitalWrite(pinLed, HIGH); - - // Same use as the official library, pretty much self explaining - Keyboard.println(F("This message was sent with my Arduino.")); - Serial.println(F("Serial port is still working and not glitching out")); - - // simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } -} diff --git a/plugins/KeyboardioHID/examples/HID/Keyboard_Keycode/Keyboard_Keycode.ino b/plugins/KeyboardioHID/examples/HID/Keyboard_Keycode/Keyboard_Keycode.ino deleted file mode 100644 index d195dcd2f9..0000000000 --- a/plugins/KeyboardioHID/examples/HID/Keyboard_Keycode/Keyboard_Keycode.ino +++ /dev/null @@ -1,56 +0,0 @@ -/* - Copyright (c) 2014 NicoHood - See the readme for credit to other people. - - Keyboard Keycode example - - Press a button to write some text to your pc. - This example is made for advanced users, to add specific keys to the HID report. - See official and HID Project and USB docs documentation for more infos - https://github.com/NicoHood/HID/wiki/Keyboard-API - http://www.usb.org/developers/hidpage/Hut1_12v2.pdf -*/ - -const int pinLed = LED_BUILTIN; -const int pinButton = 2; - -void setup() { - pinMode(pinLed, OUTPUT); - pinMode(pinButton, INPUT_PULLUP); - - // Sends a clean report to the host. This is important on any Arduino type. - Keyboard.begin(); -} - -void loop() { - if (!digitalRead(pinButton)) { - digitalWrite(pinLed, HIGH); - - // the "normal" way - //Keyboard.println("Test"); - - // press 'a' via normal API - //Keyboard.write('a'); - - // press 'a' via keycodes - Keyboard.writeKeycode(0x04); - - // press the contect menu button via normal API - //Keyboard.write(KEY_MENU); - - // press the context menu button via keycodes (right mouse click) - //Keyboard.writeKeycode(0x65); - - // You can also try some specific keys that do not work on every OS - /* - #define HID_KEYBOARD_MUTE 0x7F - #define HID_KEYBOARD_VOLUME_UP 0x80 - #define HID_KEYBOARD_VOLUME_DOWN 0x81 - */ - //Keyboard.writeKeycode(0x7F); - - // simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } -} diff --git a/plugins/KeyboardioHID/examples/HID/Keyboard_Led/Keyboard_Led.ino b/plugins/KeyboardioHID/examples/HID/Keyboard_Led/Keyboard_Led.ino deleted file mode 100644 index 829a6c9340..0000000000 --- a/plugins/KeyboardioHID/examples/HID/Keyboard_Led/Keyboard_Led.ino +++ /dev/null @@ -1,40 +0,0 @@ -/* - Copyright (c) 2014-2015 NicoHood - See the readme for credit to other people. - - Keyboard Led example - - Press a button to toogle caps lock. - Caps lock state is represented by the onboard led. - See official and HID Project documentation for more infos - https://github.com/NicoHood/HID/wiki/Keyboard-API -*/ - -const int pinLed = LED_BUILTIN; -const int pinButton = 2; - -void setup() { - pinMode(pinLed, OUTPUT); - pinMode(pinButton, INPUT_PULLUP); - - // Sends a clean report to the host. This is important on any Arduino type. - Keyboard.begin(); -} - - -void loop() { - // update Led equal to the caps lock state - // keep in mind on HoodLoader2 high&low are inverted (like this) - if (Keyboard.getLeds() & LED_CAPS_LOCK) - digitalWrite(pinLed, LOW); - else - digitalWrite(pinLed, HIGH); - - if (!digitalRead(pinButton)) { - // trigger caps lock - Keyboard.write(KEY_CAPS_LOCK); - - // simple debounce - delay(500); - } - diff --git a/plugins/KeyboardioHID/examples/HID/Mouse_Basic/Mouse_Basic.ino b/plugins/KeyboardioHID/examples/HID/Mouse_Basic/Mouse_Basic.ino deleted file mode 100644 index d5cf16bb90..0000000000 --- a/plugins/KeyboardioHID/examples/HID/Mouse_Basic/Mouse_Basic.ino +++ /dev/null @@ -1,69 +0,0 @@ -/* - Copyright (c) 2014 NicoHood - See the readme for credit to other people. - - Mouse example - - Press a button to click, move, moveTo the mouse. - See official documentation for more infos - - Mouse Key definitions: - MOUSE_LEFT - MOUSE_RIGHT - MOUSE_MIDDLE - MOUSE_PREV - MOUSE_NEXT -*/ - -const int pinLed = LED_BUILTIN; -const int pinButtonC = 2; -const int pinButtonR = 3; -const int pinButtonT = 4; - -void setup() { - // prepare led + buttons - pinMode(pinLed, OUTPUT); - pinMode(pinButtonC, INPUT_PULLUP); - pinMode(pinButtonR, INPUT_PULLUP); - pinMode(pinButtonT, INPUT_PULLUP); - - // Sends a clean report to the host. This is important on any Arduino type. - Mouse.begin(); -} - -void loop() { - if (!digitalRead(pinButtonC)) { - digitalWrite(pinLed, HIGH); - - // Same use as the official library, pretty much self explaining - Mouse.click(); - //Mouse.click(MOUSE_RIGHT); - - // simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } - - if (!digitalRead(pinButtonR)) { - digitalWrite(pinLed, HIGH); - - // Same use as the official library, pretty much self explaining - Mouse.move(100, 0); - - // simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } - - if (!digitalRead(pinButtonT)) { - digitalWrite(pinLed, HIGH); - - // Moves Mouse to an absolute position(0- 32767). - // Make sure the Absolute Mouse report is set in hid_descriptors.h - Mouse.moveTo(16384, 16384); - - // simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } -} diff --git a/plugins/KeyboardioHID/examples/HID/RawHID_Advanced/RawHID_Advanced.ino b/plugins/KeyboardioHID/examples/HID/RawHID_Advanced/RawHID_Advanced.ino deleted file mode 100644 index 494094759e..0000000000 --- a/plugins/KeyboardioHID/examples/HID/RawHID_Advanced/RawHID_Advanced.ino +++ /dev/null @@ -1,108 +0,0 @@ -/* - Copyright (c) 2014 NicoHood - See the readme for credit to other people. - - Advanced RawHID example (currently not available/broken) - - Shows how to send bytes via raw HID - Press a button to send some example values. - Keep in mind that you can only send full data packets, the rest is filled with zero! - - Definitions from HID_Reports.h: - RAWHID_USAGE_PAGE 0xFFC0 // recommended: 0xFF00 to 0xFFFF - RAWHID_USAGE 0x0C00 // recommended: 0x0100 to 0xFFFF - RAWHID_TX_SIZE 15 // 1 byte for report ID - RAWHID_RX_SIZE 15 // 1 byte for report ID - */ - -const int pinLed = LED_BUILTIN; -const int pinButton = 2; - -void setup() { - pinMode(pinLed, OUTPUT); - pinMode(pinButton, INPUT_PULLUP); - - // no begin function needed for RawHID -} - -void loop() { - if (!digitalRead(pinButton)) { - digitalWrite(pinLed, HIGH); - - // direct without library. Always send RAWHID_RX_SIZE bytes! - uint8_t buff[RAWHID_RX_SIZE]; // unitialized, has random values - HID_SendReport(HID_REPORTID_RAWHID, buff, sizeof(buff)); - - // with library - memset(&buff, 42, sizeof(buff)); - RawHID.write(buff, sizeof(buff)); - - // write a single byte, will fill the rest with zeros - RawHID.write(0xCD); - - // huge buffer with library, will fill the rest with zeros - uint8_t megabuff[64]; - for (int i = 0; i < sizeof(megabuff); i++) - megabuff[i] = i; - RawHID.write(megabuff, sizeof(megabuff)); - - // You can use print too, but better dont use a linefeed - RawHID.println("Hello World"); - - // And compare it to write: - RawHID.write("Hello World\r\n"); - - // simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } -} - -/* -Expected output: - -// manual with unintialized buff -recv 15 bytes: -01 55 C1 FF 01 01 01 00 00 01 00 00 01 00 20 - -// filled buff -recv 15 bytes: -2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A - -// single byte filled with zero -recv 15 bytes: -CD 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - -// huge buffer filled with zero at the end -recv 15 bytes: -00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E - -recv 15 bytes: -0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D - -recv 15 bytes: -1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C - -recv 15 bytes: -2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B - -recv 15 bytes: -3C 3D 3E 3F 00 00 00 00 00 00 00 00 00 00 00 - -// print -recv 15 bytes: -48 65 6C 6C 6F 20 57 6F 72 6C 64 00 00 00 00 - -//\r -recv 15 bytes: -0D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - -//\n -recv 15 bytes: -0A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - -//write -recv 15 bytes: -48 65 6C 6C 6F 20 57 6F 72 6C 64 0D 0A 00 00 - -*/ diff --git a/plugins/KeyboardioHID/examples/HelloWorld/HelloWorld.ino b/plugins/KeyboardioHID/examples/HelloWorld/HelloWorld.ino deleted file mode 100644 index 187908d571..0000000000 --- a/plugins/KeyboardioHID/examples/HelloWorld/HelloWorld.ino +++ /dev/null @@ -1,35 +0,0 @@ -/* - Copyright (c) 2014 NicoHood - See the readme for credit to other people. - - Hello World Keyboard Beginner example - - Press a button to write some text to your pc. - See official and HID Project documentation for more information. - https://github.com/NicoHood/HID/wiki -*/ - -const int pinLed = LED_BUILTIN; -const int pinButton = 2; - -void setup() { - // hardware setup - pinMode(pinLed, OUTPUT); - pinMode(pinButton, INPUT_PULLUP); - - // Sends a clean report to the host. This is important on any Arduino type. - Keyboard.begin(); -} - -void loop() { - if (digitalRead(pinButton) == LOW) { - digitalWrite(pinLed, HIGH); - - // Same use as the official library, pretty much self explaining - Keyboard.println("Hello World"); - - // simple debounce - delay(500); - digitalWrite(pinLed, LOW); - } -} diff --git a/plugins/KeyboardioHID/examples/Projects/ArduinoISP/ArduinoISP.ino b/plugins/KeyboardioHID/examples/Projects/ArduinoISP/ArduinoISP.ino deleted file mode 100644 index 5a9266e2a3..0000000000 --- a/plugins/KeyboardioHID/examples/Projects/ArduinoISP/ArduinoISP.ino +++ /dev/null @@ -1,546 +0,0 @@ -// ArduinoISP version 04m3 -// Copyright (c) 2008-2011 Randall Bohn -// If you require a license, see -// http://www.opensource.org/licenses/bsd-license.php -// -// This sketch turns the Arduino into a AVRISP -// using the following arduino pins: -// -// pin name: not-mega: mega(1280 and 2560) -// slave reset: 10: 53 -// MOSI: 11: 51 -// MISO: 12: 50 -// SCK: 13: 52 -// -// Put an LED (with resistor) on the following pins: -// 9: Heartbeat - shows the programmer is running -// 8: Error - Lights up if something goes wrong (use red if that makes sense) -// 7: Programming - In communication with the slave -// -// 23 July 2011 Randall Bohn -// -Address Arduino issue 509 :: Portability of ArduinoISP -// http://code.google.com/p/arduino/issues/detail?id=509 -// -// October 2010 by Randall Bohn -// - Write to EEPROM > 256 bytes -// - Better use of LEDs: -// -- Flash LED_PMODE on each flash commit -// -- Flash LED_PMODE while writing EEPROM (both give visual feedback of writing progress) -// - Light LED_ERR whenever we hit a STK_NOSYNC. Turn it off when back in sync. -// - Use pins_arduino.h (should also work on Arduino Mega) -// -// October 2009 by David A. Mellis -// - Added support for the read signature command -// -// February 2009 by Randall Bohn -// - Added support for writing to EEPROM (what took so long?) -// Windows users should consider WinAVR's avrdude instead of the -// avrdude included with Arduino software. -// -// January 2008 by Randall Bohn -// - Thanks to Amplificar for helping me with the STK500 protocol -// - The AVRISP/STK500 (mk I) protocol is used in the arduino bootloader -// - The SPI functions herein were developed for the AVR910_ARD programmer -// - More information at http://code.google.com/p/mega-isp - -#include "SPI.h" -#include "pins_arduino.h" - -#ifdef ARDUINO_HOODLOADER2 -#define RESET 4 -#else -#define RESET 10 -#endif - -#define LED_HB 9 -#define LED_ERR 8 -#define LED_PMODE 7 -#define PROG_FLICKER true - -#define HWVER 2 -#define SWMAJ 1 -#define SWMIN 18 - -// STK Definitions -#define STK_OK 0x10 -#define STK_FAILED 0x11 -#define STK_UNKNOWN 0x12 -#define STK_INSYNC 0x14 -#define STK_NOSYNC 0x15 -#define CRC_EOP 0x20 //ok it is a space... - -void pulse(int pin, int times); - -void setup() { - Serial.begin(19200); - SPI.setDataMode(0); - SPI.setBitOrder(MSBFIRST); - // Clock Div can be 2,4,8,16,32,64, or 128 - SPI.setClockDivider(SPI_CLOCK_DIV128); - pinMode(LED_PMODE, OUTPUT); - pulse(LED_PMODE, 2); - pinMode(LED_ERR, OUTPUT); - pulse(LED_ERR, 2); - pinMode(LED_HB, OUTPUT); - pulse(LED_HB, 2); - -} - -int error=0; -int pmode=0; -// address for reading and writing, set by 'U' command -int here; -uint8_t buff[256]; // global block storage - -#define beget16(addr) (*addr * 256 + *(addr+1) ) -typedef struct param { - uint8_t devicecode; - uint8_t revision; - uint8_t progtype; - uint8_t parmode; - uint8_t polling; - uint8_t selftimed; - uint8_t lockbytes; - uint8_t fusebytes; - uint8_t flashpoll; - uint16_t eeprompoll; - uint16_t pagesize; - uint16_t eepromsize; - uint32_t flashsize; -} -parameter; - -parameter param; - -// this provides a heartbeat on pin 9, so you can tell the software is running. -uint8_t hbval=128; -int8_t hbdelta=8; -void heartbeat() { - if (hbval > 192) hbdelta = -hbdelta; - if (hbval < 32) hbdelta = -hbdelta; - hbval += hbdelta; - analogWrite(LED_HB, hbval); - delay(20); -} - - -void loop(void) { - // is pmode active? - if (pmode) digitalWrite(LED_PMODE, HIGH); - else digitalWrite(LED_PMODE, LOW); - // is there an error? - if (error) digitalWrite(LED_ERR, HIGH); - else digitalWrite(LED_ERR, LOW); - - // light the heartbeat LED - heartbeat(); - if (Serial.available()) { - avrisp(); - } -} - -uint8_t getch() { - while(!Serial.available()); - return Serial.read(); -} -void fill(int n) { - for (int x = 0; x < n; x++) { - buff[x] = getch(); - } -} - -#define PTIME 30 -void pulse(int pin, int times) { - do { - digitalWrite(pin, HIGH); - delay(PTIME); - digitalWrite(pin, LOW); - delay(PTIME); - } - while (times--); -} - -void prog_lamp(int state) { - if (PROG_FLICKER) - digitalWrite(LED_PMODE, state); -} - -uint8_t spi_transaction(uint8_t a, uint8_t b, uint8_t c, uint8_t d) { - uint8_t n; - SPI.transfer(a); - n=SPI.transfer(b); - //if (n != a) error = -1; - n=SPI.transfer(c); - return SPI.transfer(d); -} - -void empty_reply() { - if (CRC_EOP == getch()) { - Serial.print((char)STK_INSYNC); - Serial.print((char)STK_OK); - } - else { - error++; - Serial.print((char)STK_NOSYNC); - } -} - -void breply(uint8_t b) { - if (CRC_EOP == getch()) { - Serial.print((char)STK_INSYNC); - Serial.print((char)b); - Serial.print((char)STK_OK); - } - else { - error++; - Serial.print((char)STK_NOSYNC); - } -} - -void get_version(uint8_t c) { - switch(c) { - case 0x80: - breply(HWVER); - break; - case 0x81: - breply(SWMAJ); - break; - case 0x82: - breply(SWMIN); - break; - case 0x93: - breply('S'); // serial programmer - break; - default: - breply(0); - } -} - -void set_parameters() { - // call this after reading paramter packet into buff[] - param.devicecode = buff[0]; - param.revision = buff[1]; - param.progtype = buff[2]; - param.parmode = buff[3]; - param.polling = buff[4]; - param.selftimed = buff[5]; - param.lockbytes = buff[6]; - param.fusebytes = buff[7]; - param.flashpoll = buff[8]; - // ignore buff[9] (= buff[8]) - // following are 16 bits (big endian) - param.eeprompoll = beget16(&buff[10]); - param.pagesize = beget16(&buff[12]); - param.eepromsize = beget16(&buff[14]); - - // 32 bits flashsize (big endian) - param.flashsize = buff[16] * 0x01000000 - + buff[17] * 0x00010000 - + buff[18] * 0x00000100 - + buff[19]; - -} - -void start_pmode() { - SPI.begin(); - digitalWrite(RESET, HIGH); - pinMode(RESET, OUTPUT); - digitalWrite(SCK, LOW); - delay(20); - digitalWrite(RESET, LOW); - spi_transaction(0xAC, 0x53, 0x00, 0x00); - pmode = 1; -} - -void end_pmode() { - SPI.end(); - digitalWrite(RESET, HIGH); - pinMode(RESET, INPUT); - pmode = 0; -} - -void universal() { - int w; - uint8_t ch; - - fill(4); - ch = spi_transaction(buff[0], buff[1], buff[2], buff[3]); - breply(ch); -} - -void flash(uint8_t hilo, int addr, uint8_t data) { - spi_transaction(0x40+8*hilo, - addr>>8 & 0xFF, - addr & 0xFF, - data); -} -void commit(int addr) { - if (PROG_FLICKER) prog_lamp(LOW); - spi_transaction(0x4C, (addr >> 8) & 0xFF, addr & 0xFF, 0); - if (PROG_FLICKER) { - delay(PTIME); - prog_lamp(HIGH); - } -} - -//#define _current_page(x) (here & 0xFFFFE0) -int current_page(int addr) { - if (param.pagesize == 32) return here & 0xFFFFFFF0; - if (param.pagesize == 64) return here & 0xFFFFFFE0; - if (param.pagesize == 128) return here & 0xFFFFFFC0; - if (param.pagesize == 256) return here & 0xFFFFFF80; - return here; -} - - -void write_flash(int length) { - fill(length); - if (CRC_EOP == getch()) { - Serial.print((char) STK_INSYNC); - Serial.print((char) write_flash_pages(length)); - } - else { - error++; - Serial.print((char) STK_NOSYNC); - } -} - -uint8_t write_flash_pages(int length) { - int x = 0; - int page = current_page(here); - while (x < length) { - if (page != current_page(here)) { - commit(page); - page = current_page(here); - } - flash(LOW, here, buff[x++]); - flash(HIGH, here, buff[x++]); - here++; - } - - commit(page); - - return STK_OK; -} - -#define EECHUNK (32) -uint8_t write_eeprom(int length) { - // here is a word address, get the byte address - int start = here * 2; - int remaining = length; - if (length > param.eepromsize) { - error++; - return STK_FAILED; - } - while (remaining > EECHUNK) { - write_eeprom_chunk(start, EECHUNK); - start += EECHUNK; - remaining -= EECHUNK; - } - write_eeprom_chunk(start, remaining); - return STK_OK; -} -// write (length) bytes, (start) is a byte address -uint8_t write_eeprom_chunk(int start, int length) { - // this writes byte-by-byte, - // page writing may be faster (4 bytes at a time) - fill(length); - prog_lamp(LOW); - for (int x = 0; x < length; x++) { - int addr = start+x; - spi_transaction(0xC0, (addr>>8) & 0xFF, addr & 0xFF, buff[x]); - delay(45); - } - prog_lamp(HIGH); - return STK_OK; -} - -void program_page() { - char result = (char) STK_FAILED; - int length = 256 * getch(); - length += getch(); - char memtype = getch(); - // flash memory @here, (length) bytes - if (memtype == 'F') { - write_flash(length); - return; - } - if (memtype == 'E') { - result = (char)write_eeprom(length); - if (CRC_EOP == getch()) { - Serial.print((char) STK_INSYNC); - Serial.print(result); - } - else { - error++; - Serial.print((char) STK_NOSYNC); - } - return; - } - Serial.print((char)STK_FAILED); - return; -} - -uint8_t flash_read(uint8_t hilo, int addr) { - return spi_transaction(0x20 + hilo * 8, - (addr >> 8) & 0xFF, - addr & 0xFF, - 0); -} - -char flash_read_page(int length) { - for (int x = 0; x < length; x+=2) { - uint8_t low = flash_read(LOW, here); - Serial.print((char) low); - uint8_t high = flash_read(HIGH, here); - Serial.print((char) high); - here++; - } - return STK_OK; -} - -char eeprom_read_page(int length) { - // here again we have a word address - int start = here * 2; - for (int x = 0; x < length; x++) { - int addr = start + x; - uint8_t ee = spi_transaction(0xA0, (addr >> 8) & 0xFF, addr & 0xFF, 0xFF); - Serial.print((char) ee); - } - return STK_OK; -} - -void read_page() { - char result = (char)STK_FAILED; - int length = 256 * getch(); - length += getch(); - char memtype = getch(); - if (CRC_EOP != getch()) { - error++; - Serial.print((char) STK_NOSYNC); - return; - } - Serial.print((char) STK_INSYNC); - if (memtype == 'F') result = flash_read_page(length); - if (memtype == 'E') result = eeprom_read_page(length); - Serial.print(result); - return; -} - -void read_signature() { - if (CRC_EOP != getch()) { - error++; - Serial.print((char) STK_NOSYNC); - return; - } - Serial.print((char) STK_INSYNC); - uint8_t high = spi_transaction(0x30, 0x00, 0x00, 0x00); - Serial.print((char) high); - uint8_t middle = spi_transaction(0x30, 0x00, 0x01, 0x00); - Serial.print((char) middle); - uint8_t low = spi_transaction(0x30, 0x00, 0x02, 0x00); - Serial.print((char) low); - Serial.print((char) STK_OK); -} -////////////////////////////////////////// -////////////////////////////////////////// - - -//////////////////////////////////// -//////////////////////////////////// -int avrisp() { - uint8_t data, low, high; - uint8_t ch = getch(); - switch (ch) { - case '0': // signon - error = 0; - empty_reply(); - break; - case '1': - if (getch() == CRC_EOP) { - Serial.print((char) STK_INSYNC); - Serial.print("AVR ISP"); - Serial.print((char) STK_OK); - } else { - error++; - Serial.print((char) STK_NOSYNC); - } - break; - case 'A': - get_version(getch()); - break; - case 'B': - fill(20); - set_parameters(); - empty_reply(); - break; - case 'E': // extended parameters - ignore for now - fill(5); - empty_reply(); - break; - - case 'P': - if (pmode) { - pulse(LED_ERR, 3); - } else { - start_pmode(); - } - empty_reply(); - break; - case 'U': // set address (word) - here = getch(); - here += 256 * getch(); - empty_reply(); - break; - - case 0x60: //STK_PROG_FLASH - low = getch(); - high = getch(); - empty_reply(); - break; - case 0x61: //STK_PROG_DATA - data = getch(); - empty_reply(); - break; - - case 0x64: //STK_PROG_PAGE - program_page(); - break; - - case 0x74: //STK_READ_PAGE 't' - read_page(); - break; - - case 'V': //0x56 - universal(); - break; - case 'Q': //0x51 - error=0; - end_pmode(); - empty_reply(); - break; - - case 0x75: //STK_READ_SIGN 'u' - read_signature(); - break; - - // expecting a command, not CRC_EOP - // this is how we can get back in sync - case CRC_EOP: - error++; - Serial.print((char) STK_NOSYNC); - break; - - // anything else we will return STK_UNKNOWN - default: - error++; - if (CRC_EOP == getch()) - Serial.print((char)STK_UNKNOWN); - else - Serial.print((char)STK_NOSYNC); - } -} - - - - diff --git a/plugins/KeyboardioHID/examples/Projects/Gamepad_Project/Gamepad_Project.ino b/plugins/KeyboardioHID/examples/Projects/Gamepad_Project/Gamepad_Project.ino deleted file mode 100644 index 3bf9771d65..0000000000 --- a/plugins/KeyboardioHID/examples/Projects/Gamepad_Project/Gamepad_Project.ino +++ /dev/null @@ -1,112 +0,0 @@ -/* - Copyright (c) 2014 NicoHood - See the readme for credit to other people. - - Gamepad example project - - Press physical buttons to press USB Gamepad buttons. - This can be used for a simple SNES Controller. - - Make sure the Gamepad report is set in: - sketchbook/hardware/HID/avr/variants/hid_descriptors/hid_descriptors.h -*/ - -// pin mappings -const int pinButton1 = 2; -const int pinButton2 = 3; -const int pinButton3 = 4; -const int pinButton4 = 5; -const int pinButton5 = 6; -const int pinButton6 = 7; -const int pinButton7 = 8; -const int pinButton8 = 9; -const int pinButton9 = 10; -const int pinButton10 = 18; -const int pinButton11 = 19; -const int pinButton12 = 20; - -void setup() { - // pinsetup - pinMode(pinButton1, INPUT_PULLUP); - pinMode(pinButton2, INPUT_PULLUP); - pinMode(pinButton3, INPUT_PULLUP); - pinMode(pinButton4, INPUT_PULLUP); - pinMode(pinButton5, INPUT_PULLUP); - pinMode(pinButton6, INPUT_PULLUP); - pinMode(pinButton7, INPUT_PULLUP); - pinMode(pinButton8, INPUT_PULLUP); - pinMode(pinButton9, INPUT_PULLUP); - pinMode(pinButton10, INPUT_PULLUP); - pinMode(pinButton11, INPUT_PULLUP); - pinMode(pinButton12, INPUT_PULLUP); - - // Sends a clean report to the host. This is important on any Arduino type. - Gamepad.begin(); -} - -void loop() { - // check each button and press Gamepad if needed - if (!digitalRead(pinButton1)) - Gamepad.press(1); - else - Gamepad.release(1); - - if (!digitalRead(pinButton2)) - Gamepad.press(2); - else - Gamepad.release(2); - - if (!digitalRead(pinButton3)) - Gamepad.press(3); - else - Gamepad.release(3); - - if (!digitalRead(pinButton4)) - Gamepad.press(4); - else - Gamepad.release(4); - - if (!digitalRead(pinButton5)) - Gamepad.press(5); - else - Gamepad.release(5); - - if (!digitalRead(pinButton6)) - Gamepad.press(6); - else - Gamepad.release(6); - - if (!digitalRead(pinButton7)) - Gamepad.press(7); - else - Gamepad.release(7); - - if (!digitalRead(pinButton8)) - Gamepad.press(8); - else - Gamepad.release(8); - - if (!digitalRead(pinButton9)) - Gamepad.press(9); - else - Gamepad.release(9); - - if (!digitalRead(pinButton10)) - Gamepad.press(10); - else - Gamepad.release(10); - - if (!digitalRead(pinButton11)) - Gamepad.press(11); - else - Gamepad.release(11); - - if (!digitalRead(pinButton12)) - Gamepad.press(12); - else - Gamepad.release(12); - - // write the information to the host now! - Gamepad.write(); -} - diff --git a/plugins/KeyboardioHID/examples/Projects/HID-Bridge/HID-Bridge_IO/HID-Bridge_IO.ino b/plugins/KeyboardioHID/examples/Projects/HID-Bridge/HID-Bridge_IO/HID-Bridge_IO.ino deleted file mode 100644 index 32ce692e6a..0000000000 --- a/plugins/KeyboardioHID/examples/Projects/HID-Bridge/HID-Bridge_IO/HID-Bridge_IO.ino +++ /dev/null @@ -1,22 +0,0 @@ -/* - Copyright (c) 2014-2015 NicoHood - See the readme for credit to other people. - - Serial HID-Bridge I/O - Select Arduino Uno/Mega HID-Bridge as board. - - After upload make sure the 16u2 sketch runs, not the HoodLoader2 bootloader. -*/ - -void setup() { - // start the Serial which is connected with the 16u2. - // make sure both baud rates are the same - // you can go up to 2000000 for very fast data transmission - Serial.begin(115200); -} - -void loop() { - // send random letters to the USB MCU - Serial.write(random('a', 'z')); - delay(1000); -} diff --git a/plugins/KeyboardioHID/examples/Projects/HID-Bridge/HID-Bridge_USB/HID-Bridge_USB.ino b/plugins/KeyboardioHID/examples/Projects/HID-Bridge/HID-Bridge_USB/HID-Bridge_USB.ino deleted file mode 100644 index 3073f8d899..0000000000 --- a/plugins/KeyboardioHID/examples/Projects/HID-Bridge/HID-Bridge_USB/HID-Bridge_USB.ino +++ /dev/null @@ -1,34 +0,0 @@ -/* - Copyright (c) 2014-2015 NicoHood - See the readme for credit to other people. - - Serial HID-Bridge USB - Select Arduino Uno/Mega HID-Bridge as board. - - After upload make sure the 16u2 sketch runs, not the HoodLoader2 bootloader. -*/ - -void setup() { - // start the Serial1 which is connected with the 16u2. - // make sure both baud rates are the same - // you can go up to 2000000 for very fast data transmission - Serial1.begin(115200); - - // Sends a clean report to the host. This is important on any Arduino type. - Keyboard.begin(); - - // start the USB Serial for debugging - Serial.begin(115200); -} - -void loop() { - // check if any Serial data from the I/O MCU was received - char c = Serial1.read(); - - // if it's a character, print it! - if (c >= 'a' && c <= 'z') { - Serial.print(F("USB: ")); - Serial.println(c); - Keyboard.println(c); - } -} diff --git a/plugins/KeyboardioHID/examples/Projects/HoodLoader1_API_Legacy/HoodLoader1_API_Legacy.ino b/plugins/KeyboardioHID/examples/Projects/HoodLoader1_API_Legacy/HoodLoader1_API_Legacy.ino deleted file mode 100644 index b8f4fe90e8..0000000000 --- a/plugins/KeyboardioHID/examples/Projects/HoodLoader1_API_Legacy/HoodLoader1_API_Legacy.ino +++ /dev/null @@ -1,165 +0,0 @@ -/* - Copyright (c) 2014 NicoHood - See the readme for credit to other people. - - Keyboard HoodLoader1 API Legacy example - - Legacy Example on how to access the Serial HID API of HoodLoader1. - This methode is outdated, because you can now control the whole - 16u2 with HoodLoader2. It might be still usefull if you want the 328/2560 - keep control of the USB functions. Keep in mind that there is no such thing - as flushing HID reports. If the USB Host is too slow HID reports might be missed. - - You can also adapt the sending method below to send Mouse/Keyboard/Media/System reports. - Gamepads/RawHID have a general problem with the original HoodLoader1 firmware, so please avoid this. - It might be compatible with the new HoodLoader2 port of the protocol later on. - - HID reports are converted into a special Serial Protocol with NHP. - This sketch should only be used with a 328/2560, not a 16u2. - The 16u2 has a HoodLoader1 compatible sketch/firmware loaded and will - listen to the Serial Port for these Protocol packets on baud 115200. - - The HID_SendReport function is implemented weak, so we can overwrite it - in this sketch below. A simple NHP implementation encapsulated the HID reports - into NHP packets with correct addresses and checksums. - - Press a button to write some text to your pc. - See official documentation for more infos - */ - -#include "USB-Core/Keyboard.h" - -// Serial to write Protocol data to. Default: Serial -#define HID_SERIAL Serial -#define SERIAL_HID_BAUD 115200 - -// extra delay for raspberry. Only needed for Hoodloader and slow devices -//#define HID_EXTRADELAY 20 - -const int pinLed = 13; -const int pinButton = 8; - -void setup() { - pinMode(pinLed, OUTPUT); - pinMode(pinButton, INPUT_PULLUP); - - // Starts Serial at baud 115200 otherwise HID wont work with HoodLoader1. - // This is not needed for Leonado/(Pro)Micro/16u2(HoodLoader2) - Serial.begin(SERIAL_HID_BAUD); - - // Sends a clean report to the host. This is important on any Arduino type. - // Make sure all desired USB functions are activated in USBAPI.h! - Keyboard.begin(); -} - - -void loop() { - if (!digitalRead(pinButton)) { - digitalWrite(pinLed, HIGH); - - // Same use as the official library, pretty much self explaining - Keyboard.println("This message was sent with my Arduino."); - Serial.println("Serial port is still working and not glitching out"); - - // simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } -} - -//================================================================================ -// HoodLoader1 compatible NHP sending API -//================================================================================ - -// Start Mask -#define NHP_MASK_START 0xC0 //B11|000000 the two MSB bits -#define NHP_MASK_LEAD 0xC0 //B11|000000 -#define NHP_MASK_DATA 0x00 //B0|0000000 only the first MSB is important -#define NHP_MASK_END 0x80 //B10|000000 - -// Content Mask -#define NHP_MASK_LENGTH 0x38 //B00|111|000 -#define NHP_MASK_COMMAND 0x0F //B0000|1111 -#define NHP_MASK_DATA_7BIT 0x7F //B0|1111111 -#define NHP_MASK_DATA_4BIT 0x0F //B0000|1111 -#define NHP_MASK_DATA_3BIT 0x07 //B00000|111 -#define NHP_MASK_ADDRESS 0x3F //B00|111111 - -// Reserved Addresses -#define NHP_ADDRESS_CONTROL 0x01 - -// Reserved Usages -#define NHP_USAGE_ARDUINOHID 0x01 - -// overwrites the HID_SendReport function which is empty/not used on a 328/2560 -void HID_SendReport(uint8_t id, const void* data, int len) -{ - // write the Report via Protocol and checksum. 16bit for each sending - // send control address - NHPwriteChecksum(NHP_ADDRESS_CONTROL, (NHP_USAGE_ARDUINOHID << 8) | id); - const uint8_t* report = (const uint8_t*)data; - for (int i = 0; i < len; i++) { - uint8_t data0 = report[i++]; - uint8_t data1 = 0; - if (i != len) - data1 = report[i]; - // valid HID reports start at Address 2 - NHPwriteChecksum(2 + i / 2, (data1 << 8) | data0); - } -#ifdef HID_EXTRADELAY - delay(HID_EXTRADELAY); -#endif -} - -// simple copy/modification of the NicoHoodProtocol writechecksum function -void NHPwriteChecksum(uint8_t address, uint16_t indata) { - // writes two bytes with its inverse - uint32_t temp = ~indata; - uint32_t data = (temp << 16) | indata; - - // buffer for write operation - uint8_t writebuffer[6]; - - // start with the maximum size of blocks - uint8_t blocks = 7; - - // check for the first 7 bit block that doesnt fit into the first 3 bits - while (blocks > 2) { - uint8_t nextvalue = (data >> (7 * (blocks - 3))); - - if (nextvalue > NHP_MASK_DATA_3BIT) { - // special case for the MSB - if (blocks == 7) { - writebuffer[0] = nextvalue; - blocks--; - } - // this block is too big, write this into the next data block - break; - } - else { - // write the possible first 3 bits and check again after if zero - writebuffer[0] = nextvalue; - blocks--; - // we have our first bits, stop (nonzero) - if (nextvalue) - break; - } - } - - // write the rest of the data bits - uint8_t datablocks = blocks - 2; - while (datablocks > 0) { - writebuffer[datablocks] = data & NHP_MASK_DATA_7BIT; - data >>= 7; - datablocks--; - } - - // write lead + length mask - writebuffer[0] |= NHP_MASK_LEAD | (blocks << 3); - - // write end mask - writebuffer[blocks - 1] = NHP_MASK_END | ((address - 1) & NHP_MASK_ADDRESS); - - // write the buffer - HID_SERIAL.write(writebuffer, blocks); -} diff --git a/plugins/KeyboardioHID/examples/Projects/HoodLoader2_PWM_Fade/HoodLoader2_PWM_Fade.ino b/plugins/KeyboardioHID/examples/Projects/HoodLoader2_PWM_Fade/HoodLoader2_PWM_Fade.ino deleted file mode 100644 index 0ba22c889f..0000000000 --- a/plugins/KeyboardioHID/examples/Projects/HoodLoader2_PWM_Fade/HoodLoader2_PWM_Fade.ino +++ /dev/null @@ -1,39 +0,0 @@ -/* - Copyright (c) 2014 NicoHood - See the readme for credit to other people. - - PWM Fade - - This example shows how to fade an LED on pin 7 - using the analogWrite() function. - - Basically it is a demonstartion that PWM on pin 7 works fine. - You can also deactivate the USB Core for this example, but then you'd - need the workaround. See the other example for this. -*/ - -int led = 7; // the pin that the LED is attached to -int brightness = 0; // how bright the LED is -int fadeAmount = 5; // how many points to fade the LED by - -// the setup routine runs once when you press reset: -void setup() { - // declare pin 9 to be an output: - pinMode(led, OUTPUT); -} - -// the loop routine runs over and over again forever: -void loop() { - // set the brightness of pin 9: - analogWrite(led, 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 == 255) { - fadeAmount = -fadeAmount ; - } - // wait for 30 milliseconds to see the dimming effect - delay(30); -} diff --git a/plugins/KeyboardioHID/examples/Projects/HoodLoader2_RunBootloader/HoodLoader2_RunBootloader.ino b/plugins/KeyboardioHID/examples/Projects/HoodLoader2_RunBootloader/HoodLoader2_RunBootloader.ino deleted file mode 100644 index fc6bd37383..0000000000 --- a/plugins/KeyboardioHID/examples/Projects/HoodLoader2_RunBootloader/HoodLoader2_RunBootloader.ino +++ /dev/null @@ -1,33 +0,0 @@ -/* - Copyright (c) 2015 NicoHood - See the readme for credit to other people. - - HoodLoader2 Run Bootloader example - - Starts Bootloader mode. - This is useful if you only want to use - the USB-Serial bridge again. - - You could delete the program with avrdude, - but this sketch is way simpler to upload. - - It forces a watchdog reset, - meaning the bootloader is started completely indipendant. -*/ - -#include - -void setup() { - // close interrupts - cli(); - - // write magic key to ram - *(uint8_t *)0x0280 = 0x77; - - // watchdog reset - wdt_enable(WDTO_120MS); -} - -void loop() { - // wait for reset -} diff --git a/plugins/KeyboardioHID/examples/Projects/HoodLoader2_SerialKeyboard/HoodLoader2_SerialKeyboard.ino b/plugins/KeyboardioHID/examples/Projects/HoodLoader2_SerialKeyboard/HoodLoader2_SerialKeyboard.ino deleted file mode 100644 index 5aef44609e..0000000000 --- a/plugins/KeyboardioHID/examples/Projects/HoodLoader2_SerialKeyboard/HoodLoader2_SerialKeyboard.ino +++ /dev/null @@ -1,54 +0,0 @@ -/* - Copyright (c) 2014 NicoHood - See the readme for credit to other people. - - HoodLoader2 SerialKeyboard example - - This sketch should demonstrate how to program a basic sketch with HoodLoader2. - It was used to demonstrate that Serial and HID is working properly. - The the other examples on how to use the other APIs, it works the same. - - Use the F() macro to save strings in PROGMEM to keep ram usage low. - The 16u2 has very low RAM, so don't try to use that much ram. - - Open the Serial port, type in anything and see that Serial and Keyboard is working. - See official documentation for more infos. - */ - -void setup() { - // start + wait for serial debug in/output - while (!Serial); - Serial.begin(115200); - Serial.println(F("Startup")); - - // Sends a clean report to the host. This is important because - // the 16u2 of the Uno/Mega is not turned off while programming - // so you want to start with a clean report to avoid strange bugs after reset. - Keyboard.begin(); -} - - -void loop() { - if (Serial.available()) { - // discard all Serial bytes to avoid multiple sendings - unsigned long currentMillis = millis(); - while (millis() - currentMillis < 100) { - if (Serial.available()) - Serial.write(Serial.read()); - } - - // print an information back to the serial port - Serial.println(); - Serial.println(F("Serial port working. Printing Text in 3 seconds.")); - - // wait 3 seconds and discard all new in bytes to not crash the Arduino - currentMillis = millis(); - while (millis() - currentMillis < 3000) { - if (Serial.available()) - Serial.write(Serial.read()); - } - - // same use as the official library, pretty much self explaining - Keyboard.print(F("This message was sent with my Arduino.")); - } -} \ No newline at end of file diff --git a/plugins/KeyboardioHID/examples/Projects/USB-Serial/USB-Serial.ino b/plugins/KeyboardioHID/examples/Projects/USB-Serial/USB-Serial.ino deleted file mode 100644 index 9f6d757c26..0000000000 --- a/plugins/KeyboardioHID/examples/Projects/USB-Serial/USB-Serial.ino +++ /dev/null @@ -1,61 +0,0 @@ -/* - Copyright (c) 2014 NicoHood - See the readme for credit to other people. - - USB-Serial - - Transferes from USB to HW Serial and vice versa. - It also resets the main MCU on a DTR rise. - */ - -// define the reset pin to reset the destination MCU. -// this definition is made for HoodLoader2 (pin 20) -// but you still can use it with any other USB MCU or pin -const int resetPin = MAIN_MCU_RESET_PIN; - -void setup() { - // set main MCU by default active - pinMode(resetPin, OUTPUT); - digitalWrite(resetPin, HIGH); - - // Start USB Serial - Serial.begin(115200); -} - -void loop() { - // USB -> Serial - uint8_t i; - for (i = 0; i < USB_EP_SIZE; i++) { - // read maximum one EP_SIZE to not block - int b = Serial.read(); - if (b < 0) - break; - Serial1.write(b); - } - - // Serial -> USB - uint8_t buff[USB_EP_SIZE]; - for (i = 0; i < sizeof(buff); i++) { - // read maximum one EP_SIZE to not block - int b = Serial1.read(); - if (b < 0) - break; - buff[i] = b; - } - // send maximum one EP_SIZE to give the usb some time to flush the buffer - Serial.write(buff, i); -} - -void CDC_LineEncodingEvent(void) { - // start HW Serial with new baud rate - Serial1.end(); - Serial1.begin(Serial.baud()); -} - -void CDC_LineStateEvent(void) { - // reset the main mcu if DTR goes HIGH - if (Serial.dtr()) - digitalWrite(resetPin, LOW); - else - digitalWrite(resetPin, HIGH); -} diff --git a/plugins/KeyboardioHID/examples/HID/System_Basic/System_Basic.ino b/plugins/KeyboardioHID/examples/System/System.ino similarity index 72% rename from plugins/KeyboardioHID/examples/HID/System_Basic/System_Basic.ino rename to plugins/KeyboardioHID/examples/System/System.ino index f4faf239f8..a3308b51d8 100644 --- a/plugins/KeyboardioHID/examples/HID/System_Basic/System_Basic.ino +++ b/plugins/KeyboardioHID/examples/System/System.ino @@ -1,14 +1,17 @@ /* - Copyright (c) 2014 NicoHood + Copyright (c) 2014-2015 NicoHood See the readme for credit to other people. System example - Press a button to put pc into sleep/shut it down or wake it up again. - See HID Project documentation for more infos + + See HID Project documentation for more Consumer keys. https://github.com/NicoHood/HID/wiki/System-API */ +#include "HID.h" +#include "System.h" + const int pinLed = LED_BUILTIN; const int pinButtonS = 2; const int pinButtonW = 3; @@ -27,11 +30,11 @@ void loop() { if (!digitalRead(pinButtonS)) { digitalWrite(pinLed, HIGH); - // puts pc into sleep mode/shuts it down + // Puts pc into sleep mode/shuts it down System.write(SYSTEM_SLEEP); //System.write(SYSTEM_POWER_DOWN); - // simple debounce + // Simple debounce delay(300); digitalWrite(pinLed, LOW); } @@ -39,11 +42,11 @@ void loop() { if (!digitalRead(pinButtonW)) { digitalWrite(pinLed, HIGH); - // tries to wake up the PC - // this might fail on some PCs where USB wakeup isnt supported + // Tries to wake up the PC + // This might fail on some PCs/Laptops where USB wakeup is not supported System.write(SYSTEM_WAKE_UP); - // simple debounce + // Simple debounce delay(300); digitalWrite(pinLed, LOW); } diff --git a/plugins/KeyboardioHID/avr/libraries/HIDBridge/keywords.txt b/plugins/KeyboardioHID/keywords.txt similarity index 95% rename from plugins/KeyboardioHID/avr/libraries/HIDBridge/keywords.txt rename to plugins/KeyboardioHID/keywords.txt index 897337075b..34ff98a366 100644 --- a/plugins/KeyboardioHID/avr/libraries/HIDBridge/keywords.txt +++ b/plugins/KeyboardioHID/keywords.txt @@ -1,5 +1,5 @@ ####################################### -# Syntax Coloring Map For HID-Bridge +# Syntax Coloring Map For HID-Project ####################################### ####################################### @@ -10,8 +10,6 @@ # Methods and Functions (KEYWORD2) ####################################### -#USB-related keywords - USBDevice KEYWORD3 Keyboard KEYWORD3 Mouse KEYWORD3 diff --git a/plugins/KeyboardioHID/library.properties b/plugins/KeyboardioHID/library.properties new file mode 100644 index 0000000000..62d0c8c71a --- /dev/null +++ b/plugins/KeyboardioHID/library.properties @@ -0,0 +1,9 @@ +name=HID-Project +version=2.4 +author=NicoHood +maintainer=NicoHood +sentence=Extended HID Functions for Arduino +paragraph=Includes Consumer, System and Gamepad. Also compatible with Arduino Uno/Mega via HoodLoader2. +category=Device Control +url=https://github.com/NicoHood/HID +architectures=* diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Consumer.cpp b/plugins/KeyboardioHID/src/Consumer.cpp similarity index 93% rename from plugins/KeyboardioHID/avr/cores/hid/USB-Core/Consumer.cpp rename to plugins/KeyboardioHID/src/Consumer.cpp index 051fdda148..e9311cf68f 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Consumer.cpp +++ b/plugins/KeyboardioHID/src/Consumer.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2014 NicoHood +Copyright (c) 2014-2015 NicoHood See the readme for credit to other people. Permission is hereby granted, free of charge, to any person obtaining a copy @@ -27,5 +27,9 @@ THE SOFTWARE. // Consumer //================================================================================ +#if defined(_USING_HID) + // object instance -Consumer_ Consumer; \ No newline at end of file +Consumer_ Consumer; + +#endif diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Consumer.h b/plugins/KeyboardioHID/src/Consumer.h similarity index 70% rename from plugins/KeyboardioHID/avr/cores/hid/USB-Core/Consumer.h rename to plugins/KeyboardioHID/src/Consumer.h index 5c5433f1ed..51670a50ba 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Consumer.h +++ b/plugins/KeyboardioHID/src/Consumer.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2014 NicoHood +Copyright (c) 2014-2015 NicoHood See the readme for credit to other people. Permission is hereby granted, free of charge, to any person obtaining a copy @@ -21,16 +21,24 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef __CONSUMERAPI__ -#define __CONSUMERAPI__ +#pragma once -// to access the HID_SendReport via USBAPI.h and report number -#include "Arduino.h" +#include "HID.h" + +#if !defined(_USING_HID) + +#warning "Using legacy HID core (non pluggable)" + +#else //================================================================================ // Consumer //================================================================================ +#ifndef HID_REPORTID_CONSUMERCONTROL +#define HID_REPORTID_CONSUMERCONTROL 4 +#endif + // Media key definitions, see official USB docs for more #define MEDIA_FAST_FORWARD 0xB3 #define MEDIA_REWIND 0xB4 @@ -59,6 +67,23 @@ THE SOFTWARE. #define CONSUMER_BROWSER_REFRESH 0x227 #define CONSUMER_BROWSER_BOOKMARKS 0x22A +static const u8 _hidReportDescriptor[] PROGMEM = { + /* Consumer Control (Sound/Media keys) */ + 0x05, 0x0C, /* usage page (consumer device) */ + 0x09, 0x01, /* usage -- consumer control */ + 0xA1, 0x01, /* collection (application) */ + 0x85, HID_REPORTID_CONSUMERCONTROL, /* report id */ + /* 4 Media Keys */ + 0x15, 0x00, /* logical minimum */ + 0x26, 0xFF, 0x03, /* logical maximum (3ff) */ + 0x19, 0x00, /* usage minimum (0) */ + 0x2A, 0xFF, 0x03, /* usage maximum (3ff) */ + 0x95, 0x04, /* report count (4) */ + 0x75, 0x10, /* report size (16) */ + 0x81, 0x00, /* input */ + 0xC0 /* end collection */ +}; + typedef union { // every usable Consumer key possible, up to 4 keys presses possible uint8_t whole8[]; @@ -72,23 +97,34 @@ typedef union { }; } HID_ConsumerControlReport_Data_t; +extern HID_ HID; + class Consumer_ { public: inline Consumer_(void) { - // empty + static HID_Descriptor cb = { + .length = sizeof(_hidReportDescriptor), + .descriptor = _hidReportDescriptor, + }; + static HIDDescriptorListNode node(&cb); + HID.AppendDescriptor(&node); } + inline void begin(void) { // release all buttons end(); } + inline void end(void) { memset(&_report, 0, sizeof(_report)); - HID_SendReport(HID_REPORTID_CONSUMERCONTROL, &_report, sizeof(_report)); + HID.SendReport(HID_REPORTID_CONSUMERCONTROL, &_report, sizeof(_report)); } + inline void write(uint16_t m) { press(m); release(m); } + inline void press(uint16_t m) { // search for a free spot for (int i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { @@ -97,8 +133,9 @@ class Consumer_ { break; } } - HID_SendReport(HID_REPORTID_CONSUMERCONTROL, &_report, sizeof(_report)); + HID.SendReport(HID_REPORTID_CONSUMERCONTROL, &_report, sizeof(_report)); } + inline void release(uint16_t m) { // search and release the keypress for (int i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { @@ -107,14 +144,16 @@ class Consumer_ { // no break to delete multiple keys } } - HID_SendReport(HID_REPORTID_CONSUMERCONTROL, &_report, sizeof(_report)); + HID.SendReport(HID_REPORTID_CONSUMERCONTROL, &_report, sizeof(_report)); } + inline void releaseAll(void) { end(); } + private: HID_ConsumerControlReport_Data_t _report; }; extern Consumer_ Consumer; -#endif \ No newline at end of file +#endif diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.cpp b/plugins/KeyboardioHID/src/Gamepad.cpp similarity index 93% rename from plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.cpp rename to plugins/KeyboardioHID/src/Gamepad.cpp index 6a86a7c456..0d40740e99 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.cpp +++ b/plugins/KeyboardioHID/src/Gamepad.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2014 NicoHood +Copyright (c) 2014-2015 NicoHood See the readme for credit to other people. Permission is hereby granted, free of charge, to any person obtaining a copy @@ -27,5 +27,9 @@ THE SOFTWARE. // Gamepad //================================================================================ +#if defined(_USING_HID) + // object instance -Gamepad_ Gamepad; \ No newline at end of file +Gamepad_ Gamepad; + +#endif diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.h b/plugins/KeyboardioHID/src/Gamepad.h similarity index 58% rename from plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.h rename to plugins/KeyboardioHID/src/Gamepad.h index 7c3927b73c..97d2e20da9 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/Gamepad.h +++ b/plugins/KeyboardioHID/src/Gamepad.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2014 NicoHood +Copyright (c) 2014-2015 NicoHood See the readme for credit to other people. Permission is hereby granted, free of charge, to any person obtaining a copy @@ -21,16 +21,24 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef __GAMEPADAPI__ -#define __GAMEPADAPI__ +#pragma once -// to access the HID_SendReport via USBAPI.h and report number -#include "Arduino.h" +#include "HID.h" + +#if !defined(_USING_HID) + +#warning "Using legacy HID core (non pluggable)" + +#else //================================================================================ // Gamepad //================================================================================ +#ifndef HID_REPORTID_GAMEPAD +#define HID_REPORTID_GAMEPAD 6 +#endif + // Dpad directions #define GAMEPAD_DPAD_CENTERED 0 #define GAMEPAD_DPAD_UP 1 @@ -42,6 +50,54 @@ THE SOFTWARE. #define GAMEPAD_DPAD_LEFT 7 #define GAMEPAD_DPAD_UP_LEFT 8 +static const u8 _hidReportDescriptor[] PROGMEM = { + /* Gamepad with 32 buttons and 6 axis*/ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x04, /* USAGE (Joystick) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + 0x85, HID_REPORTID_GAMEPAD, /* REPORT_ID */ + /* 32 Buttons */ + 0x05, 0x09, /* USAGE_PAGE (Button) */ + 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ + 0x29, 0x20, /* USAGE_MAXIMUM (Button 32) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x95, 0x20, /* REPORT_COUNT (32) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + /* 4 16bit Axis */ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0xa1, 0x00, /* COLLECTION (Physical) */ + 0x09, 0x30, /* USAGE (X) */ + 0x09, 0x31, /* USAGE (Y) */ + 0x09, 0x33, /* USAGE (Rx) */ + 0x09, 0x34, /* USAGE (Ry) */ + 0x16, 0x00, 0x80, /* LOGICAL_MINIMUM (-32768) */ + 0x26, 0xFF, 0x7F, /* LOGICAL_MAXIMUM (32767) */ + 0x75, 0x10, /* REPORT_SIZE (16) */ + 0x95, 0x04, /* REPORT_COUNT (4) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + /* 2 8bit Axis */ + 0x09, 0x32, /* USAGE (Z) */ + 0x09, 0x35, /* USAGE (Rz) */ + 0x15, 0x80, /* LOGICAL_MINIMUM (-128) */ + 0x25, 0x7F, /* LOGICAL_MAXIMUM (127) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x02, /* REPORT_COUNT (2) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + 0xc0, /* END_COLLECTION */ + /* 2 Hat Switches */ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x39, /* USAGE (Hat switch) */ + 0x09, 0x39, /* USAGE (Hat switch) */ + 0x15, 0x01, /* LOGICAL_MINIMUM (1) */ + 0x25, 0x08, /* LOGICAL_MAXIMUM (8) */ + 0x95, 0x02, /* REPORT_COUNT (2) */ + 0x75, 0x04, /* REPORT_SIZE (4) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + 0xc0 /* END_COLLECTION */ +}; + typedef union { // 32 Buttons, 6 Axis, 2 D-Pads uint8_t whole8[]; @@ -100,10 +156,17 @@ typedef union { }; } HID_GamepadReport_Data_t; +extern HID_ HID; + class Gamepad_{ public: inline Gamepad_(void){ - // empty + static HID_Descriptor cb = { + .length = sizeof(_hidReportDescriptor), + .descriptor = _hidReportDescriptor, + }; + static HIDDescriptorListNode node(&cb); + HID.AppendDescriptor(&node); } inline void begin(void){ @@ -113,10 +176,10 @@ class Gamepad_{ inline void end(void){ memset(&_report, 0, sizeof(_report)); - HID_SendReport(HID_REPORTID_GAMEPAD, &_report, sizeof(_report)); + HID.SendReport(HID_REPORTID_GAMEPAD, &_report, sizeof(_report)); } - inline void write(void){ HID_SendReport(HID_REPORTID_GAMEPAD, &_report, sizeof(_report)); } + inline void write(void){ HID.SendReport(HID_REPORTID_GAMEPAD, &_report, sizeof(_report)); } inline void press(uint8_t b){ _report.buttons |= (uint32_t)1 << (b - 1); } inline void release(uint8_t b){ _report.buttons &= ~((uint32_t)1 << (b - 1)); } inline void releaseAll(void){ memset(&_report, 0x00, sizeof(_report)); } @@ -136,4 +199,4 @@ class Gamepad_{ }; extern Gamepad_ Gamepad; -#endif \ No newline at end of file +#endif diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.cpp b/plugins/KeyboardioHID/src/System.cpp similarity index 91% rename from plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.cpp rename to plugins/KeyboardioHID/src/System.cpp index b4fb6ae471..4b59ec18eb 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.cpp +++ b/plugins/KeyboardioHID/src/System.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2014 NicoHood +Copyright (c) 2014-2015 NicoHood See the readme for credit to other people. Permission is hereby granted, free of charge, to any person obtaining a copy @@ -27,6 +27,8 @@ THE SOFTWARE. // System //================================================================================ +#if defined(_USING_HID) + System_ System; void System_::press(uint8_t s){ @@ -35,5 +37,7 @@ void System_::press(uint8_t s){ USBDevice.wakeupHost(); else #endif - HID_SendReport(HID_REPORTID_SYSTEMCONTROL, &s, sizeof(s)); -} \ No newline at end of file + HID.SendReport(HID_REPORTID_SYSTEMCONTROL, &s, sizeof(s)); +} + +#endif diff --git a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.h b/plugins/KeyboardioHID/src/System.h similarity index 59% rename from plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.h rename to plugins/KeyboardioHID/src/System.h index 7e57389053..5cb4d136e3 100644 --- a/plugins/KeyboardioHID/avr/cores/hid/USB-Core/System.h +++ b/plugins/KeyboardioHID/src/System.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2014 NicoHood +Copyright (c) 2014-2015 NicoHood See the readme for credit to other people. Permission is hereby granted, free of charge, to any person obtaining a copy @@ -21,30 +21,63 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef __SYSTEMAPI__ -#define __SYSTEMAPI__ +#pragma once -// to access the HID_SendReport via USBAPI.h and report number -#include "Arduino.h" +#include "HID.h" + +#if !defined(_USING_HID) + +#warning "Using legacy HID core (non pluggable)" + +#else //================================================================================ // System //================================================================================ +#ifndef HID_REPORTID_SYSTEMCONTROL +#define HID_REPORTID_SYSTEMCONTROL 5 +#endif + #define SYSTEM_POWER_DOWN 0x81 #define SYSTEM_SLEEP 0x82 #define SYSTEM_WAKE_UP 0x83 +static const u8 _hidReportDescriptor[] PROGMEM = { + //TODO limit to system keys only? + /* System Control (Power Down, Sleep, Wakeup, ...) */ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x80, /* USAGE (System Control) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + 0x85, HID_REPORTID_SYSTEMCONTROL, /* REPORT_ID */ + /* 1 system key */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x26, 0xff, 0x00, /* LOGICAL_MAXIMUM (255) */ + 0x19, 0x00, /* USAGE_MINIMUM (Undefined) */ + 0x29, 0xff, /* USAGE_MAXIMUM (System Menu Down) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ + 0xc0 /* END_COLLECTION */ +}; + typedef union{ // every usable system control key possible uint8_t whole8[]; uint8_t key; } HID_SystemControlReport_Data_t; +extern HID_ HID; + class System_{ public: inline System_(void){ - // empty + static HID_Descriptor cb = { + .length = sizeof(_hidReportDescriptor), + .descriptor = _hidReportDescriptor, + }; + static HIDDescriptorListNode node(&cb); + HID.AppendDescriptor(&node); } inline void begin(void){ // release all buttons @@ -52,7 +85,7 @@ class System_{ } inline void end(void){ uint8_t _report = 0; - HID_SendReport(HID_REPORTID_SYSTEMCONTROL, &_report, sizeof(_report)); + HID.SendReport(HID_REPORTID_SYSTEMCONTROL, &_report, sizeof(_report)); } inline void write(uint8_t s){ press(s); @@ -68,4 +101,4 @@ class System_{ }; extern System_ System; -#endif \ No newline at end of file +#endif From f14eea9adbc656998d071e6d6101fe8283e46dc1 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 9 Aug 2015 14:41:38 +0200 Subject: [PATCH 204/602] Upated wrong readme file --- plugins/KeyboardioHID/Readme.md | 393 ++++++++++++++++---------------- 1 file changed, 193 insertions(+), 200 deletions(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index c54eb39da0..cb0fbc2671 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -1,232 +1,225 @@ -MSGEQ7 Library 1.2 + Board v1.0 -=============================== -![Header](header.png) - -The MSGEQ7 is an IC designed to analyze music on different frequencies. -This library reads the MSGEQ7 with 7 different frequencies from range 0-255, stereo or mono. -It can be used to visualize audio through Leds for example. -This repository also includes the source of an [Breakout Board](https://github.com/NicoHood/MSGEQ7/tree/dev#breakout-board). - -The frequencies are: -63Hz, 160Hz, 400Hz, 1kHz, 2.5kHz, 6.25KHz, 16kHz - -####Features -* IDE 1.6.x with every Arduino compatibly -* [Sparkfun Spectrum Shield](https://www.sparkfun.com/products/13116) compatible -* Reads 1-n MSGEQ7 sensors -* Compact and fast implementation -* More compact and flexible 8 bit resolution -* Optional 10 bit resolution -* Value smoothing -* Tools to reduce noise -* A [Breakout Board](https://github.com/NicoHood/MSGEQ7/tree/dev#breakout-board). - -####Examples included: -* Led: blinks led, shows basic usage -* Serial: shows spectrum via serial and how to use more channels -* FastLED: blinks led strip with different frequencies. Shows how to use different syntax. -Uses [FastLED library](https://github.com/FastLED/FastLED) - -More projects/contact: -http://www.NicoHood.de - - -Hardware Setup -============== -To use the MSGEQ7 you first need a few other parts and connect them properly. -Make sure the 33pF capacitor and the 200k Ohm resistor are precise. -Otherwise the frequencies may be off. -See the [data sheet](https://www.sparkfun.com/datasheets/Components/General/MSGEQ7.pdf) for more information. - -#####Required parts (stereo): -* 2x [MSGEQ7 IC](https://www.sparkfun.com/products/10468) -* 1x [Audio Jack 3.5mm](https://www.sparkfun.com/products/8032) (or any other audio input) -* 2x 10nF Capacitor -* 4x 100nF Capacitor -* 2x 33pF Capacitor -* 2x 200k Ohm Resistor -* Led or Led strips -* 1x 220 Ohm Resistor (for Led) - -###Breadboard Setup -This would be an example breadboard setup for the Led example. - -![Schematic](extras/breadboard/MSGEQ7_Schematic.png) - -![Breadboard Setup](extras/breadboard/MSGEQ7_Breadboard.png) - - -Software installation -===================== -Install the library as you are used to. -More information can be found [here](http://arduino.cc/en/guide/libraries). - - -API Documentation -================= - -#####`template class CMSGEQ7` -Every CMSGEQ7 instance needs some pins passed via template to optimize the code. -If you want to smooth the readings with the last reading pass true as first argument. -The reset and strobe pin can be anyone on the board. -You can input as many analog pins as needed. -For example as mono mode only a single IC, stereo 2 or surround as many channels as you want. - -#####`void begin(void);` -Do whatever is required to initialize the IC and resets it. - -#####`void end(void);` -Sets pins to input again to safely remove connections if needed - -#####`void reset(void);` -Resets IC, so it starts reading at 0 again. -Normally this is not needed since its done in the `begin()` function. - -#####`bool read(void);` -Basic read function. Reads all channels and saves value inside the buffer. -You can access the buffer with the `get()` function. -Up to 400FPS are possible with 2 channels I've measured. - -#####`bool read(const uint32_t currentMicros, const uint32_t interval);` -To automatically read every X seconds you may also use this function. -Use the `ReadsPerSecond(f)` Makro with the interval and you can easily choose a good speed interval. -You can also leave out the first argument, this will be automatically replaced with a `micros()`. - -#####`MSGEQ7_data_t get(const uint8_t frequency, const uint8_t channel);` -Returns the data of the selected frequency and channel. -By default this returns an `uint8_t` value, for 10bit resolution `uint16_t`. -Frequency should be 0-6 where 0 is the lowest frequency (Bass) and 6 the highest. -Depending on how many analog pins you have attached you can select the channel here (0-n). -You can also leave out the channel variable to get an average value of all channels. - -#####`MSGEQ7_data_t getVolume(uint8_t channel);` -Returns the overall volume of all frequencies of a channel. -By default this returns an `uint8_t` value, for 10bit resolution `uint16_t`. -Depending on how many analog pins you have attached you can select the channel here (0-n). -You can also leave out the channel variable to get an average volume of all channels. - -#####`MSGEQ7_data_t map(MSGEQ7_data_t x, MSGEQ7_data_t in_min = MSGEQ7_IN_MIN, MSGEQ7_data_t in_max = MSGEQ7_IN_MAX, MSGEQ7_data_t out_min = MSGEQ7_OUT_MIN, MSGEQ7_data_t out_max = MSGEQ7_OUT_MAX);` -Maps the input from a given input range to an output range. -This is useful to reduce noise. All MSGEQ7 produce a noise of about 15-19 if no music is played. -This macro can be used to remap the input. You can leave out the last 4 arguments, they will be replaced with default values. -For 10 bit resolution the function uses `uint16_t` and 1023 as default maximum value. - -#####`Definitions` -```cpp -//#define MSGEQ7_10BIT -#define ReadsPerSecond(f) (1000000UL / (f)) - -// basic frequencys definitions (0-6 valid, 7 channels) -#define MSGEQ7_0 0 -#define MSGEQ7_1 1 -#define MSGEQ7_2 2 -#define MSGEQ7_3 3 -#define MSGEQ7_4 4 -#define MSGEQ7_5 5 -#define MSGEQ7_6 6 -#define MSGEQ7_BASS 0 -#define MSGEQ7_LOW 0 -#define MSGEQ7_MID 3 -#define MSGEQ7_HIGH 5 -``` +Arduino HID Project 2.4 +======================= + +![Header Picture](header.jpg) + +This project went through a lot of phases and has now reached a new Arduino ~~USB-Core~~ Library +with a lot of new functions like extended HID. It also supports HoodLoader1+2. +The idea is to enable enhanced USB functions to almost all 'standard' Arduino boards. +See the [wiki](https://github.com/NicoHood/HID/wiki/Features) for more information about features etc. -Breakout Board -============== -The MSGEQ7 Breakout Board lets you easily hook up an audio source or microphone to your microcontroller. -You may also use a 2nd audio output to pass the audio signal to music boxes again. -You can solder a 6 or 8 pin header to the board and connect it to a breadboard for example. -It is fully open source so you can create a copy for yourself or modify it. -#####Features: -* Stereo music analyze -* Audio input via 3.5mm Jack -* Additional audio output -* Additional audio in/output via pin header -* Mounting holes -* Breadboard compatible -* Easy to solder (DIP parts) -* [Open Source Hardware](http://www.oshwa.org/definition/) +Download +======== -#####Required parts: -* 2x [MSGEQ7 IC](https://www.sparkfun.com/products/10468) -* 2x [Audio Jack 3.5mm](https://www.sparkfun.com/products/8032) -* 8 pin header male -* 2x IC socket 8 pins (optional) -* 2x 10nF Capacitor -* 4x 100nF Capacitor -* 2x 33pF Capacitor -* 2x 200k Ohm Resistor +You have 3 versions you can download: +* The master includes all fixes to the current stable release. Download it by clicking download at the right. +Use the [online Wiki](https://github.com/NicoHood/HID/wiki) to get the newest documentation. +* Download an offline version in [releases](https://github.com/NicoHood/HID/releases). +It's a snapshot of the current stable release but might have missed some updates that the current master branch has included. +This also includes an offline version of the wiki. Offline versions will be available after some time when the official release is out. +* Select [branch 'dev'](https://github.com/NicoHood/HID/tree/dev) to test the bleeding edge of this software. It might now work at all or has a lot of debugging stuff in it. +If the dev version gets near to a new release a note will be placed here, that you can test the new dev beta. +Currently there is no beta available. -#####Files: -You can find all needed files in the [board](extras/board/) folder. -Click view raw to download the PDF files. +Wiki +==== -#####Schematic -![Schematic](extras/board/MSGEQ7_Schematic.png) +All documentation moved to the [wiki page](https://github.com/NicoHood/HID/wiki). -#####PCB -![PCB](extras/board/MSGEQ7_PCB.png) +An offline snapshot is available in [releases](https://github.com/NicoHood/HID/releases). -Additional Information -====================== -This library started as my very first one and become better and better over the time. -To be honest it is now very complex, due to the optimization and API flexibility. +Contact +======= -The read function itself is simple though. -Have a look at the library itself, its not so complicated. -But keep attention to the LOW and HIGH setting of strobe and reset +You can contact me on my wordpress blog in the contact section. -Keep in mind that the smoothed value is created from the last read + current read divided by 2. -I found out that reading with 50 FPS is a good value to use. +www.nicohood.de -You can reset the IC with myMSGEQ7.reset() but you don't need that normally. -If you only want to use mono mode or one IC just connect the two inputs together to the MSGEQ7 -and only use one analog input. But you can also use multiply ICs and connect them to an analog input each. -The reset and strobe line is connected to every IC, so you don't need to multiply them. +TODO +==== -The output only ranges from 0-255 to save memory use it easier. You don't lose much information. -If you still want to read up to 1023 define MSGEQ7_10BIT before including the library. +Under Construction. This is a todo list for myself. -The IC has a standard value at about 10-19. You should keep that in mind. -In this case the Led always glims a bit. Have a look at the map() function to improve this. +``` +Keyboard Layout for different Languages +Clean up USB Core code from fixed values. Use better understandable definitions +Magic key fix for 32u4? + +Check Keyboard keycode function again +Generalize HID key definitions via HIDTables for example? + +Test with Android phone (HL1) +improve keywords.txt +``` Version History =============== ``` -1.2.1 Release (xx.xx.2015) -* Added 1.6.x library schema - -1.2 Release (23.04.2015) -* Added breakout board files v1.0 -* Optimized performance -* Variable number of ICs readable -* Added optional 10bit resolution -* Added more functions/tools -* Improved examples -* Added MSGEQ7_VERSION definition -* Added library.properties - -1.1 Release (10.07.2014) -* Changed syntax -* Optimized performance -* Added more examples - -1.0 Release (13.04.2014) -* Added general functionality +2.4 Release (xx.xx.2015) +* Added Arduino IDE 1.6.6 compatibility with Pluggable HID +* Changed USB-Core into a simple library, only possible with Pluggable HID +* Removed HID presets (like mouse + keyboard + consumer + system) + +2.3 Release (xx.xx.2015) (never released) +* Updated Libraries +* Updated Arduino Core +* Added Minor Consumer definitions +* Fixed platforms.txt +* SERIAL_RX_BUFFER_SIZE reverted to 16 (TODO add -D to build option) + +2.2 Release (12.04.2015) +* added experimental, not finished nor documented HID-Bridge between 16u2 and 328/2560 +* increased HW Serial1 RX buffer size from 16 to 32 (TX still 16) +* added colour highlighting (through HID-Bridge library) +* removed fixed size in report buffers +* used HID_KeyboardReport_Data_t now in Keyboard API +* Arduino as ISP fix for 328 +* Upload verification on USB hubs fix for HL2.0.4 +* No USB workaround for Leonardo integrated into variants +* Changed USB Wakeup in System API +* Consumer Key fix (issue #3) +* Gamepad fix (issue #14) +* Added Keycode example +* Mouse press + release fix + +2.1 Release (28.01.2015) +* Reworked the whole USB-Core from scratch +* Uses less flash if HID or Serial is not used +* Extended and compacter(flash) HID Report Descriptors +* Fixed USB Device Descriptor +* Added u2 compatibility with smaller USB_EP_SIZE (16u2 etc) +* Added Serial Event for LineEncoding and LineState +* Added Serial Function to get dtr state, line encoding etc +* Added Keyboard Led Out report to get Led states (for numlock etc) +* Made CDC-Core independent from USB-Core +* Made HID-Core independent from USB-Core +* Made HID-API independent from HID-Core +* Removed not needed virtual functions in Keyboard +* Made HID Reports and its IDs replaceable via pins_Arduino.h +* Added Absolute Mouse +* Removed uint8_t USBPutChar(uint8_t c); in HID.cpp +* Made void Recv(volatile u8* data, u8 count) in USBCore.cpp static inline +* HID-APIs sends a clean report on begin() and end() now. +* Removed virtual functions in Keyboard API +* Added Keycode functions in Keyboard API +* Inlined a lot of the HID API functions to save flash +* Added Gamepad +* Added RawHID API (but RawHID itself isnt working still) +* Added USB Wakeup support +* Separated USB-Core in its own folder +* Added HID Tables +* USB-Serial now fully reprogrammable +* Easy USB-Core selection via Tools->USB-Core +* Added Arduino as ISP fix for 32u4 and 16u2 +* Moved documentation to the wiki +* Added AVR libraries to the core with the better SoftSerial + +2.0 Release (29.11.2014) +* Added HoodLoader2 +* Separated HoodLoader1&2 more +* Added u2 series for USB-Core +* Extended USB core and fixed minor things for the u2 series +* Added Led Out report. +* Added CDC Line state +* Reworked the whole library structure again + +1.8 Beta Release (26.08.2014) +* Changes in the Hoodloader1: + * **Huge improvements**, see Hoodloader1 repository + * Reworked the whole library, easy installation now + * HID fixes for Media Keys/Ubuntu + * Removed Joystick, added 4 Gamepads + +1.7.3 Beta Release (10.08.2014) +* Changes in the Hoodloader1: + * Fixed HID flush bug (1.6 - 1.7.2) + +1.7.2 Beta Release (10.08.2014) +* Changes in the Hoodloader1: + * Added Lite version for 8u2 + * Added Versions that show up as Uno/Mega (not recommended) + * Makefile and structure changes + +1.7.1 Beta Release (10.08.2014) +* Changes in the Hoodloader1: + * Fixed HID deactivation bug + +1.7 Beta Release (10.08.2014) +* Changes in the Hoodloader1: + * Works as ISP now. See Hoodloader1 Repository for more information. + * Exceeded 8kb limit. For flashing a 8u2 use v1.6 please! +* Changed Readme text + +1.6 Beta Release (09.08.2014) +* Bugfixes in the Hoodloader1: + * Changed HID management (not blocking that much, faster) + * added RawHID in/out (HID to Serial) +* Added RawHID Class and example + +1.5 Beta Release (21.07.2014) +* Moved Hoodloader1 source to a separate Github page +* Bugfixes in the Hoodloader: + * Firmware is still available here + * Overall a lot of ram improvements, now with a big global union of ram + * Removed USBtoUSART buffer (not needed, saved 128/500 bytes) + * Removed Lite version because of better ram usage not needed + * Separated different modes better to not cause any errors in default mode + * Improved the deactivate option + * Integrated NHP directly + * Replaced LightweightRingbuffer with native Lufa Ringbuffer + * Improved writing to CDC Host + * Fixed a bug in checkNHPProtocol: & needs to be a == + * General structure changes + * Improved stability + * Fixed Arduino as ISP bug + +1.4.1 Beta Release (10.07.2014) +* #define Bugfix in USBAPI.h + +1.4 Beta Release (10.07.2014) +* Bugfixes in the Hoodloader1: + * Added Lite Version with less ram usage + * Changed PIDs, edited driver file +* merged v1.0.x and v1.5.x together (both are compatible!) +* added IDE v1.5.7 support +* added Tutorials + +1.3 Beta Release (01.07.2014) +* Bugfixes in the Hoodloader1: + * Improved ram usage +* **Important NHP fix inside the HID Class for Uno/Mega** + +1.2 Beta Release (22.06.2014) +* Added 1.0.x/1.5.x support +* Bugfixes in the Hoodloader1: + * Sometimes HID Devices weren't updating + when using more than 1 Device (set forcewrite to true) + * Fast updates crashed the bootloader + (too much ram usage, set CDC buffer from 128b to 100b each) +* Minor file structure changes + +1.1 Beta Release (05.06.2014) +* Added Leonardo/Micro support +* Included NicoHoodProtocol +* Minor fixes + +1.0 Beta Release (03.06.2014) ``` -License and Copyright +Licence and Copyright ===================== If you use this library for any cool project let me know! ``` Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 69cbb53d1874bde49d9adc045e2d2af3aacb75fe Mon Sep 17 00:00:00 2001 From: Nico Date: Sun, 9 Aug 2015 14:45:01 +0200 Subject: [PATCH 205/602] Update Readme.md --- plugins/KeyboardioHID/Readme.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 213f18681b..9058a1405d 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -1,9 +1,12 @@ Arduino HID Project 2.2 ======================= -[![Join the chat at https://gitter.im/NicoHood/HID](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/NicoHood/HID?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) ![Header Picture](header.jpg) +##IDE 1.6.6 compatible library is [now available here.](https://github.com/NicoHood/HID/tree/dev_2_4) +Install it as library, not as hardware file. IDE 1.6.6 introduced pluggable HID where you +dont need to patch the whole Arduino-Core anymore. + This project went through a lot of phases and has now reached a new Arduino USB-Core with a lot of new functions like extended HID. It also supports HoodLoader1+2. The idea is to enable enhanced USB functions to almost all 'standard' Arduino boards. From 6362fb7a351150671dd781d30a8ae31cc86b31df Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 9 Aug 2015 19:08:12 +0200 Subject: [PATCH 206/602] Added Absolute Mouse --- .../examples/AbsoluteMouse/AbsoluteMouse.ino | 68 ++++++ plugins/KeyboardioHID/src/AbsoluteMouse.cpp | 34 +++ plugins/KeyboardioHID/src/AbsoluteMouse.h | 198 ++++++++++++++++++ 3 files changed, 300 insertions(+) create mode 100644 plugins/KeyboardioHID/examples/AbsoluteMouse/AbsoluteMouse.ino create mode 100644 plugins/KeyboardioHID/src/AbsoluteMouse.cpp create mode 100644 plugins/KeyboardioHID/src/AbsoluteMouse.h diff --git a/plugins/KeyboardioHID/examples/AbsoluteMouse/AbsoluteMouse.ino b/plugins/KeyboardioHID/examples/AbsoluteMouse/AbsoluteMouse.ino new file mode 100644 index 0000000000..89c762daca --- /dev/null +++ b/plugins/KeyboardioHID/examples/AbsoluteMouse/AbsoluteMouse.ino @@ -0,0 +1,68 @@ +/* + Copyright (c) 2014-2015 NicoHood + See the readme for credit to other people. + + AbsoluteMouse example + Press a button to click, moveTo the mouse. + + See HID Project documentation for more infos + https://github.com/NicoHood/HID/wiki/Mouse-API + https://github.com/NicoHood/HID/wiki/AbsoluteMouse-API +*/ + +#include "HID.h" +#include "AbsoluteMouse.h" + +const int pinLed = LED_BUILTIN; +const int pinButtonClick = 2; +const int pinButtonCenter = 3; +const int pinButtonMove = 1; + +void setup() { + // Prepare led + buttons + pinMode(pinLed, OUTPUT); + pinMode(pinButtonClick, INPUT_PULLUP); + pinMode(pinButtonCenter, INPUT_PULLUP); + pinMode(pinButtonMove, INPUT_PULLUP); + + // Sends a clean report to the host. This is important on any Arduino type. + AbsoluteMouse.begin(); +} + +void loop() { + if (!digitalRead(pinButtonClick)) { + digitalWrite(pinLed, HIGH); + + // Same use as the official library, pretty much self explaining + AbsoluteMouse.click(); + //AbsoluteMouse.click(MOUSE_RIGHT); + + // Simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } + + if (!digitalRead(pinButtonCenter)) { + digitalWrite(pinLed, HIGH); + + // Move to coordinate (16bit signed, -32768 - 32767) + // Moving to the same position twice will not work! + // X and Y start in the upper left corner. + AbsoluteMouse.moveTo(0, 0); + + // Simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } + + if (!digitalRead(pinButtonMove)) { + digitalWrite(pinLed, HIGH); + + // Move relative to last coordinate + AbsoluteMouse.move(1000, 1000); + + // Simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } +} diff --git a/plugins/KeyboardioHID/src/AbsoluteMouse.cpp b/plugins/KeyboardioHID/src/AbsoluteMouse.cpp new file mode 100644 index 0000000000..9c88adf9b4 --- /dev/null +++ b/plugins/KeyboardioHID/src/AbsoluteMouse.cpp @@ -0,0 +1,34 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 "AbsoluteMouse.h" + +//================================================================================ +//================================================================================ +// Mouse + +#if defined(_USING_HID) + +AbsMouse_ AbsoluteMouse; + +#endif diff --git a/plugins/KeyboardioHID/src/AbsoluteMouse.h b/plugins/KeyboardioHID/src/AbsoluteMouse.h new file mode 100644 index 0000000000..de6647ad6f --- /dev/null +++ b/plugins/KeyboardioHID/src/AbsoluteMouse.h @@ -0,0 +1,198 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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. +*/ + +#pragma once + +#include "HID.h" + +#if !defined(_USING_HID) + +#warning "Using legacy HID core (non pluggable)" + +#else + +//================================================================================ +//================================================================================ +// Mouse + +#ifndef HID_REPORTID_MOUSE_ABSOLUTE +#define HID_REPORTID_MOUSE_ABSOLUTE 7 +#endif + +#define MOUSE_LEFT (1 << 0) +#define MOUSE_RIGHT (1 << 1) +#define MOUSE_MIDDLE (1 << 2) +#define MOUSE_PREV (1 << 3) +#define MOUSE_NEXT (1 << 4) +// actually this mouse report has 8 buttons (for smaller descriptor) +// but the last 3 wont do anything from what I tested +#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE | MOUSE_PREV | MOUSE_NEXT) + +static const u8 _hidReportDescriptor[] PROGMEM = { + /* Mouse absolute */ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 54 */ + 0x09, 0x02, /* USAGE (Mouse) */ + 0xA1, 0x01, /* COLLECTION (Application) */ + 0x85, HID_REPORTID_MOUSE_ABSOLUTE, /* REPORT_ID */ + + /* 8 Buttons */ + 0x05, 0x09, /* USAGE_PAGE (Button) */ + 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ + 0x29, 0x08, /* USAGE_MAXIMUM (Button 8) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x95, 0x08, /* REPORT_COUNT (8) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + + /* X, Y */ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x30, /* USAGE (X) */ + 0x09, 0x31, /* USAGE (Y) */ + 0x16, 0x00, 0x80, /* Logical Minimum (-32768) */ + 0x26, 0xFF, 0x7F, /* Logical Maximum (32767) */ + 0x75, 0x10, /* Report Size (16), */ + 0x95, 0x02, /* Report Count (2), */ + 0x81, 0x02, /* Input (Data, Variable, Absolute) */ + + /* Wheel */ + 0x09, 0x38, /* USAGE (Wheel) */ + 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) */ + + /* End */ + 0xc0 /* END_COLLECTION */ +}; + +typedef union{ + // mouse absolute report: 8 buttons, 2 absolute axis, wheel + uint8_t whole8[]; + uint16_t whole16[]; + uint32_t whole32[]; + struct{ + uint8_t buttons; + int16_t xAxis; + int16_t yAxis; + int8_t wheel; + }; +} HID_MouseAbsoluteReport_Data_t; + +extern HID_ HID; + +class AbsMouse_ +{ +private: + int16_t xAxis = 0; + int16_t yAxis = 0; + uint8_t _buttons = 0; + inline void buttons(uint8_t b){ + if (b != _buttons){ + _buttons = b; + moveTo(xAxis, yAxis, 0); + } + } + + inline int16_t qadd16(int16_t base, int16_t increment) { + // Separate between subtracting and adding + if (increment < 0) { + // Subtracting more would cause an undefined overflow + if ((int16_t)0x8000 - increment > base) + base = 0x8000; + else + base += increment; + } + else { + // Adding more would cause an undefined overflow + if ((int16_t)0x7FFF - increment < base) + base = 0x7FFF; + else + base += increment; + } + return base; + } + +public: + inline AbsMouse_(void) { + static HID_Descriptor cb = { + .length = sizeof(_hidReportDescriptor), + .descriptor = _hidReportDescriptor, + }; + static HIDDescriptorListNode node(&cb); + HID.AppendDescriptor(&node); + } + + inline void begin(void){ + // release all buttons + end(); + } + + inline void end(void){ + _buttons = 0; + moveTo(xAxis, yAxis, 0); + } + + inline void click(uint8_t b = MOUSE_LEFT){ + _buttons = b; + moveTo(xAxis, yAxis, 0); + _buttons = 0; + moveTo(xAxis, yAxis, 0); + } + + inline void moveTo(int x, int y, signed char wheel = 0){ + xAxis = x; + yAxis = y; + HID_MouseAbsoluteReport_Data_t report; + report.buttons = _buttons; + report.xAxis = x; + report.yAxis = y; + report.wheel = wheel; + HID.SendReport(HID_REPORTID_MOUSE_ABSOLUTE, &report, sizeof(report)); + } + + inline void move(int x, int y, signed char wheel = 0){ + moveTo(qadd16(xAxis, x), qadd16(yAxis, y), wheel); + } + + inline void press(uint8_t b = MOUSE_LEFT){ + // press LEFT by default + buttons(_buttons | b); + } + + inline void release(uint8_t b = MOUSE_LEFT){ + // release LEFT by default + buttons(_buttons & ~b); + } + + inline bool isPressed(uint8_t b = MOUSE_LEFT){ + // check LEFT by default + if ((b & _buttons) > 0) + return true; + return false; + } +}; +extern AbsMouse_ AbsoluteMouse; + +#endif From 91aec4a85e779e5d3fdc19123cadd815a4d17cb3 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Mon, 24 Aug 2015 17:05:20 +0200 Subject: [PATCH 207/602] Added .a linkage PR fix --- .../examples/AbsoluteMouse/AbsoluteMouse.ino | 2 +- .../examples/Consumer/Consumer.ino | 2 +- .../examples/Gamepad/Gamepad.ino | 3 +- .../KeyboardioHID/examples/System/System.ino | 2 +- plugins/KeyboardioHID/library.properties | 1 + plugins/KeyboardioHID/src/AbsoluteMouse.h | 8 ++--- plugins/KeyboardioHID/src/Consumer.h | 8 ++--- plugins/KeyboardioHID/src/Gamepad.h | 8 ++--- plugins/KeyboardioHID/src/HID-Project.h | 36 +++++++++++++++++++ plugins/KeyboardioHID/src/System.h | 8 ++--- 10 files changed, 57 insertions(+), 21 deletions(-) diff --git a/plugins/KeyboardioHID/examples/AbsoluteMouse/AbsoluteMouse.ino b/plugins/KeyboardioHID/examples/AbsoluteMouse/AbsoluteMouse.ino index 89c762daca..4abccd9de6 100644 --- a/plugins/KeyboardioHID/examples/AbsoluteMouse/AbsoluteMouse.ino +++ b/plugins/KeyboardioHID/examples/AbsoluteMouse/AbsoluteMouse.ino @@ -11,7 +11,7 @@ */ #include "HID.h" -#include "AbsoluteMouse.h" +#include "HID-Project.h" const int pinLed = LED_BUILTIN; const int pinButtonClick = 2; diff --git a/plugins/KeyboardioHID/examples/Consumer/Consumer.ino b/plugins/KeyboardioHID/examples/Consumer/Consumer.ino index 1590007df1..fa75e2665e 100644 --- a/plugins/KeyboardioHID/examples/Consumer/Consumer.ino +++ b/plugins/KeyboardioHID/examples/Consumer/Consumer.ino @@ -10,7 +10,7 @@ */ #include "HID.h" -#include "Consumer.h" +#include "HID-Project.h" const int pinLed = LED_BUILTIN; const int pinButton = 2; diff --git a/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino b/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino index 008df47d22..bff18dac64 100644 --- a/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino +++ b/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino @@ -9,9 +9,8 @@ https://github.com/NicoHood/HID/wiki/Gamepad-API */ -#include "Mouse.h" #include "HID.h" -#include "Gamepad.h" +#include "HID-Project.h" const int pinLed = LED_BUILTIN; const int pinButton = 2; diff --git a/plugins/KeyboardioHID/examples/System/System.ino b/plugins/KeyboardioHID/examples/System/System.ino index a3308b51d8..92445d6f8c 100644 --- a/plugins/KeyboardioHID/examples/System/System.ino +++ b/plugins/KeyboardioHID/examples/System/System.ino @@ -10,7 +10,7 @@ */ #include "HID.h" -#include "System.h" +#include "HID-Project.h" const int pinLed = LED_BUILTIN; const int pinButtonS = 2; diff --git a/plugins/KeyboardioHID/library.properties b/plugins/KeyboardioHID/library.properties index 62d0c8c71a..e75184e261 100644 --- a/plugins/KeyboardioHID/library.properties +++ b/plugins/KeyboardioHID/library.properties @@ -7,3 +7,4 @@ paragraph=Includes Consumer, System and Gamepad. Also compatible with Arduino Un category=Device Control url=https://github.com/NicoHood/HID architectures=* +alinkage=true diff --git a/plugins/KeyboardioHID/src/AbsoluteMouse.h b/plugins/KeyboardioHID/src/AbsoluteMouse.h index de6647ad6f..94b2eeefa2 100644 --- a/plugins/KeyboardioHID/src/AbsoluteMouse.h +++ b/plugins/KeyboardioHID/src/AbsoluteMouse.h @@ -27,7 +27,7 @@ THE SOFTWARE. #if !defined(_USING_HID) -#warning "Using legacy HID core (non pluggable)" +#error "This is not an USB AVR or you use an old version of the IDE." #else @@ -48,7 +48,7 @@ THE SOFTWARE. // but the last 3 wont do anything from what I tested #define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE | MOUSE_PREV | MOUSE_NEXT) -static const u8 _hidReportDescriptor[] PROGMEM = { +static const uint8_t _absmouseReportDescriptor[] PROGMEM = { /* Mouse absolute */ 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 54 */ 0x09, 0x02, /* USAGE (Mouse) */ @@ -137,8 +137,8 @@ class AbsMouse_ public: inline AbsMouse_(void) { static HID_Descriptor cb = { - .length = sizeof(_hidReportDescriptor), - .descriptor = _hidReportDescriptor, + .length = sizeof(_absmouseReportDescriptor), + .descriptor = _absmouseReportDescriptor, }; static HIDDescriptorListNode node(&cb); HID.AppendDescriptor(&node); diff --git a/plugins/KeyboardioHID/src/Consumer.h b/plugins/KeyboardioHID/src/Consumer.h index 51670a50ba..041660ae9a 100644 --- a/plugins/KeyboardioHID/src/Consumer.h +++ b/plugins/KeyboardioHID/src/Consumer.h @@ -27,7 +27,7 @@ THE SOFTWARE. #if !defined(_USING_HID) -#warning "Using legacy HID core (non pluggable)" +#error "This is not an USB AVR or you use an old version of the IDE." #else @@ -67,7 +67,7 @@ THE SOFTWARE. #define CONSUMER_BROWSER_REFRESH 0x227 #define CONSUMER_BROWSER_BOOKMARKS 0x22A -static const u8 _hidReportDescriptor[] PROGMEM = { +static const uint8_t _consumerReportDescriptor[] PROGMEM = { /* Consumer Control (Sound/Media keys) */ 0x05, 0x0C, /* usage page (consumer device) */ 0x09, 0x01, /* usage -- consumer control */ @@ -103,8 +103,8 @@ class Consumer_ { public: inline Consumer_(void) { static HID_Descriptor cb = { - .length = sizeof(_hidReportDescriptor), - .descriptor = _hidReportDescriptor, + .length = sizeof(_consumerReportDescriptor), + .descriptor = _consumerReportDescriptor, }; static HIDDescriptorListNode node(&cb); HID.AppendDescriptor(&node); diff --git a/plugins/KeyboardioHID/src/Gamepad.h b/plugins/KeyboardioHID/src/Gamepad.h index 97d2e20da9..ecd478d8ca 100644 --- a/plugins/KeyboardioHID/src/Gamepad.h +++ b/plugins/KeyboardioHID/src/Gamepad.h @@ -27,7 +27,7 @@ THE SOFTWARE. #if !defined(_USING_HID) -#warning "Using legacy HID core (non pluggable)" +#error "This is not an USB AVR or you use an old version of the IDE." #else @@ -50,7 +50,7 @@ THE SOFTWARE. #define GAMEPAD_DPAD_LEFT 7 #define GAMEPAD_DPAD_UP_LEFT 8 -static const u8 _hidReportDescriptor[] PROGMEM = { +static const uint8_t _gamepadReportDescriptor[] PROGMEM = { /* Gamepad with 32 buttons and 6 axis*/ 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ 0x09, 0x04, /* USAGE (Joystick) */ @@ -162,8 +162,8 @@ class Gamepad_{ public: inline Gamepad_(void){ static HID_Descriptor cb = { - .length = sizeof(_hidReportDescriptor), - .descriptor = _hidReportDescriptor, + .length = sizeof(_gamepadReportDescriptor), + .descriptor = _gamepadReportDescriptor, }; static HIDDescriptorListNode node(&cb); HID.AppendDescriptor(&node); diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index e69de29bb2..9d17d30874 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -0,0 +1,36 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 guard +#pragma once + +// Software version +#define HID_PROJECT_VERSION 240 + +#include + +// Include all HID libraries (.a linkage required to work) properly +#include "AbsoluteMouse.h" +#include "Consumer.h" +#include "Gamepad.h" +#include "System.h" diff --git a/plugins/KeyboardioHID/src/System.h b/plugins/KeyboardioHID/src/System.h index 5cb4d136e3..fbe42c1bcf 100644 --- a/plugins/KeyboardioHID/src/System.h +++ b/plugins/KeyboardioHID/src/System.h @@ -27,7 +27,7 @@ THE SOFTWARE. #if !defined(_USING_HID) -#warning "Using legacy HID core (non pluggable)" +#error "This is not an USB AVR or you use an old version of the IDE." #else @@ -43,7 +43,7 @@ THE SOFTWARE. #define SYSTEM_SLEEP 0x82 #define SYSTEM_WAKE_UP 0x83 -static const u8 _hidReportDescriptor[] PROGMEM = { +static const uint8_t _systemReportDescriptor[] PROGMEM = { //TODO limit to system keys only? /* System Control (Power Down, Sleep, Wakeup, ...) */ 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ @@ -73,8 +73,8 @@ class System_{ public: inline System_(void){ static HID_Descriptor cb = { - .length = sizeof(_hidReportDescriptor), - .descriptor = _hidReportDescriptor, + .length = sizeof(_systemReportDescriptor), + .descriptor = _systemReportDescriptor, }; static HIDDescriptorListNode node(&cb); HID.AppendDescriptor(&node); From e7bb24bd19690076baab3f2b5fc989569e8a2d94 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 29 Aug 2015 18:12:51 +0200 Subject: [PATCH 208/602] Added Improved Keyboard No changes made yet --- plugins/KeyboardioHID/src/HID-Project.h | 5 + .../KeyboardioHID/src/ImprovedKeyboard.cpp | 326 ++++++++++++++++++ plugins/KeyboardioHID/src/ImprovedKeyboard.h | 100 ++++++ 3 files changed, 431 insertions(+) create mode 100644 plugins/KeyboardioHID/src/ImprovedKeyboard.cpp create mode 100644 plugins/KeyboardioHID/src/ImprovedKeyboard.h diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index 9d17d30874..bdff37e594 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -29,7 +29,12 @@ THE SOFTWARE. #include +#if !defined(USBCON) +#error "This is not an USB AVR or you use an old version of the IDE." +#endif + // Include all HID libraries (.a linkage required to work) properly +#include "ImprovedKeyboard.h" #include "AbsoluteMouse.h" #include "Consumer.h" #include "Gamepad.h" diff --git a/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp b/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp new file mode 100644 index 0000000000..980bbbc08b --- /dev/null +++ b/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp @@ -0,0 +1,326 @@ +/* + Keyboard.cpp + + Copyright (c) 2015, Arduino LLC + Original code (pre-library): Copyright (c) 2011, Peter Barrett + + 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 "ImprovedKeyboard.h" + +#if defined(_USING_HID) + +//================================================================================ +//================================================================================ +// Keyboard + +static const u8 _hidReportDescriptor[] PROGMEM = { + + // 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 +}; + +Keyboard_::Keyboard_(void) +{ + static HID_Descriptor cb = { + .length = sizeof(_hidReportDescriptor), + .descriptor = _hidReportDescriptor, + }; + static HIDDescriptorListNode node(&cb); + HID.AppendDescriptor(&node); +} + +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 + release(c); // Keyup + return p; // just return the result of press() since release() almost always returns 1 +} + +Keyboard_ Keyboard; + +#endif diff --git a/plugins/KeyboardioHID/src/ImprovedKeyboard.h b/plugins/KeyboardioHID/src/ImprovedKeyboard.h new file mode 100644 index 0000000000..1c728ae9e4 --- /dev/null +++ b/plugins/KeyboardioHID/src/ImprovedKeyboard.h @@ -0,0 +1,100 @@ +/* + Keyboard.h + + Copyright (c) 2015, Arduino LLC + Original code (pre-library): Copyright (c) 2011, Peter Barrett + + 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 KEYBOARD_h +#define KEYBOARD_h + +#include "HID.h" + +#if !defined(_USING_HID) + +#warning "Using legacy HID core (non pluggable)" + +#else + +//================================================================================ +//================================================================================ +// 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); + size_t write(uint8_t k); + size_t press(uint8_t k); + size_t release(uint8_t k); + void releaseAll(void); +}; +extern Keyboard_ Keyboard; +extern HID_ HID; + +#endif +#endif From 8ab8e969184c12d6289b08f988dcc7fa75b87095 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 29 Aug 2015 18:13:54 +0200 Subject: [PATCH 209/602] Imrpoved Keyboard Key definitions --- plugins/KeyboardioHID/src/ImprovedKeyboard.h | 84 +++++++++++--------- 1 file changed, 48 insertions(+), 36 deletions(-) diff --git a/plugins/KeyboardioHID/src/ImprovedKeyboard.h b/plugins/KeyboardioHID/src/ImprovedKeyboard.h index 1c728ae9e4..0713aaf61b 100644 --- a/plugins/KeyboardioHID/src/ImprovedKeyboard.h +++ b/plugins/KeyboardioHID/src/ImprovedKeyboard.h @@ -34,42 +34,54 @@ //================================================================================ // 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 +#define KEY_PRINT 0xCE +#define KEY_NUM_LOCK 0xDB +#define KEY_SCROLL_LOCK 0xCF +#define KEY_PAUSE 0xD0 +#define KEY_MENU 0xED + +#define KEY_LEFT_CTRL 0x80 +#define KEY_LEFT_SHIFT 0x81 +#define KEY_LEFT_ALT 0x82 +#define KEY_LEFT_GUI 0x83 +#define KEY_LEFT_WINDOWS KEY_LEFT_GUI +#define KEY_RIGHT_CTRL 0x84 +#define KEY_RIGHT_SHIFT 0x85 +#define KEY_RIGHT_ALT 0x86 +#define KEY_RIGHT_GUI 0x87 +#define KEY_RIGHT_WINDOWS KEY_RIGHT_GUI + +#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 + +#define LED_NUM_LOCK 0x01 +#define LED_CAPS_LOCK 0x02 +#define LED_SCROLL_LOCK 0x04 // Low level key report: up to 6 keys and shift, ctrl etc at once typedef struct From a542c74a6f15cb824461ed90852cd6703092e54e Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 30 Aug 2015 19:06:56 +0200 Subject: [PATCH 210/602] Added different keyboard layouts function --- .../KeyboardioHID/src/ImprovedKeyboard.cpp | 45 ++--- plugins/KeyboardioHID/src/ImprovedKeyboard.h | 6 + .../KeyboardioHID/src/Keylayout_German.cpp | 166 ++++++++++++++++++ plugins/KeyboardioHID/src/Keylayout_US.cpp | 166 ++++++++++++++++++ 4 files changed, 361 insertions(+), 22 deletions(-) create mode 100644 plugins/KeyboardioHID/src/Keylayout_German.cpp create mode 100644 plugins/KeyboardioHID/src/Keylayout_US.cpp diff --git a/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp b/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp index 980bbbc08b..a1c18fe9d3 100644 --- a/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp +++ b/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp @@ -1,22 +1,24 @@ /* - Keyboard.cpp +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. - Copyright (c) 2015, Arduino LLC - Original code (pre-library): Copyright (c) 2011, Peter Barrett +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: - 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. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. - 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 +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 "ImprovedKeyboard.h" @@ -83,11 +85,8 @@ 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] = +static const uint8_t _asciimap[128] PROGMEM = { 0x00, // NUL 0x00, // SOH @@ -220,8 +219,10 @@ const uint8_t _asciimap[128] = 0 // DEL }; +uint8_t Keyboard_::getKeycode(uint8_t k){ + return pgm_read_byte(_asciimap + k); +} -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 @@ -236,7 +237,7 @@ size_t Keyboard_::press(uint8_t k) _keyReport.modifiers |= (1<<(k-128)); k = 0; } else { // it's a printing key - k = pgm_read_byte(_asciimap + k); + k = getKeycode(k); if (!k) { setWriteError(); return 0; @@ -280,7 +281,7 @@ size_t Keyboard_::release(uint8_t k) _keyReport.modifiers &= ~(1<<(k-128)); k = 0; } else { // it's a printing key - k = pgm_read_byte(_asciimap + k); + k = getKeycode(k); if (!k) { return 0; } diff --git a/plugins/KeyboardioHID/src/ImprovedKeyboard.h b/plugins/KeyboardioHID/src/ImprovedKeyboard.h index 0713aaf61b..4a3043ffd5 100644 --- a/plugins/KeyboardioHID/src/ImprovedKeyboard.h +++ b/plugins/KeyboardioHID/src/ImprovedKeyboard.h @@ -56,6 +56,7 @@ #define KEY_LEFT_ARROW 0xD8 #define KEY_RIGHT_ARROW 0xD7 #define KEY_BACKSPACE 0xB2 +#define KEY_SPACE ' ' #define KEY_TAB 0xB3 #define KEY_RETURN 0xB0 #define KEY_ESC 0xB1 @@ -96,6 +97,7 @@ class Keyboard_ : public Print private: KeyReport _keyReport; void sendReport(KeyReport* keys); + uint8_t getKeycode(uint8_t k) __attribute__((weak)); public: Keyboard_(void); void begin(void); @@ -104,6 +106,10 @@ class Keyboard_ : public Print size_t press(uint8_t k); size_t release(uint8_t k); void releaseAll(void); + + // Select a different layout optional: + void useLayoutGerman(void); + void useLayoutUS(void); }; extern Keyboard_ Keyboard; extern HID_ HID; diff --git a/plugins/KeyboardioHID/src/Keylayout_German.cpp b/plugins/KeyboardioHID/src/Keylayout_German.cpp new file mode 100644 index 0000000000..0b3bb52dfe --- /dev/null +++ b/plugins/KeyboardioHID/src/Keylayout_German.cpp @@ -0,0 +1,166 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 "ImprovedKeyboard.h" + +#define SHIFT 0x80 +static const uint8_t _asciimap[128] PROGMEM = +{ + 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 + 0x1d|SHIFT, // Z + 0x1c|SHIFT, // Y + 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 + 0x1d, // z + 0x1c, // y + 0x2f|SHIFT, // + 0x31|SHIFT, // | + 0x30|SHIFT, // } + 0x35|SHIFT, // ~ + 0 // DEL +}; + +uint8_t Keyboard_::getKeycode(uint8_t k){ + return pgm_read_byte(_asciimap + k); +} + +void Keyboard_::useLayoutGerman(void) { + // Empty +} diff --git a/plugins/KeyboardioHID/src/Keylayout_US.cpp b/plugins/KeyboardioHID/src/Keylayout_US.cpp new file mode 100644 index 0000000000..27b0f582fb --- /dev/null +++ b/plugins/KeyboardioHID/src/Keylayout_US.cpp @@ -0,0 +1,166 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 "ImprovedKeyboard.h" + +#define SHIFT 0x80 +static const uint8_t _asciimap[128] PROGMEM = +{ + 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 + 0x15|SHIFT, // Y + 0x14|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 Keyboard_::getKeycode(uint8_t k){ + return pgm_read_byte(_asciimap + k); +} + +void Keyboard_::useLayoutUS(void) { + // Empty +} From 4f03e898cef16fe1001f92b7b00f397ffb7f7387 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 6 Sep 2015 19:51:30 +0200 Subject: [PATCH 211/602] Keyboard fixes --- .../KeyboardioHID/src/ImprovedKeyboard.cpp | 4 +- plugins/KeyboardioHID/src/ImprovedKeyboard.h | 42 +++++++++++-------- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp b/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp index a1c18fe9d3..3b4f926475 100644 --- a/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp +++ b/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp @@ -35,7 +35,7 @@ static const u8 _hidReportDescriptor[] PROGMEM = { 0x05, 0x01, // USAGE_PAGE (Generic Desktop) // 47 0x09, 0x06, // USAGE (Keyboard) 0xa1, 0x01, // COLLECTION (Application) - 0x85, 0x02, // REPORT_ID (2) + 0x85, HID_REPORTID_KEYBOARD, // REPORT_ID (2) 0x05, 0x07, // USAGE_PAGE (Keyboard) 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl) @@ -82,7 +82,7 @@ void Keyboard_::end(void) void Keyboard_::sendReport(KeyReport* keys) { - HID.SendReport(2,keys,sizeof(KeyReport)); + HID.SendReport(HID_REPORTID_KEYBOARD,keys,sizeof(KeyReport)); } #define SHIFT 0x80 diff --git a/plugins/KeyboardioHID/src/ImprovedKeyboard.h b/plugins/KeyboardioHID/src/ImprovedKeyboard.h index 4a3043ffd5..1ba70301f4 100644 --- a/plugins/KeyboardioHID/src/ImprovedKeyboard.h +++ b/plugins/KeyboardioHID/src/ImprovedKeyboard.h @@ -1,22 +1,24 @@ /* - Keyboard.h - - Copyright (c) 2015, Arduino LLC - Original code (pre-library): Copyright (c) 2011, Peter Barrett - - 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 +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 KEYBOARD_h @@ -34,6 +36,10 @@ //================================================================================ // Keyboard +#ifndef HID_REPORTID_KEYBOARD +#define HID_REPORTID_KEYBOARD 2 +#endif + #define KEY_PRINT 0xCE #define KEY_NUM_LOCK 0xDB #define KEY_SCROLL_LOCK 0xCF From e9b9f9f133c62174ed39f70b21386619643fbe82 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 6 Sep 2015 19:52:33 +0200 Subject: [PATCH 212/602] Added Teensy Keyboard --- plugins/KeyboardioHID/src/HID-Project.h | 5 +- .../KeyboardioHID/src/Keylayout_German.cpp | 2 +- plugins/KeyboardioHID/src/TeensyKeyboard.cpp | 388 ++ plugins/KeyboardioHID/src/TeensyKeyboard.h | 126 + plugins/KeyboardioHID/src/TeensyKeylayouts.c | 66 + plugins/KeyboardioHID/src/TeensyKeylayouts.h | 5422 +++++++++++++++++ 6 files changed, 6007 insertions(+), 2 deletions(-) create mode 100644 plugins/KeyboardioHID/src/TeensyKeyboard.cpp create mode 100644 plugins/KeyboardioHID/src/TeensyKeyboard.h create mode 100644 plugins/KeyboardioHID/src/TeensyKeylayouts.c create mode 100644 plugins/KeyboardioHID/src/TeensyKeylayouts.h diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index bdff37e594..0287128076 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -34,8 +34,11 @@ THE SOFTWARE. #endif // Include all HID libraries (.a linkage required to work) properly -#include "ImprovedKeyboard.h" +//#include "ImprovedKeyboard.h" #include "AbsoluteMouse.h" #include "Consumer.h" #include "Gamepad.h" #include "System.h" + +// Include Teensy HID afterwards to overwrite key definitions if used +#include "TeensyKeyboard.h" diff --git a/plugins/KeyboardioHID/src/Keylayout_German.cpp b/plugins/KeyboardioHID/src/Keylayout_German.cpp index 0b3bb52dfe..65ef07ebd8 100644 --- a/plugins/KeyboardioHID/src/Keylayout_German.cpp +++ b/plugins/KeyboardioHID/src/Keylayout_German.cpp @@ -156,7 +156,7 @@ static const uint8_t _asciimap[128] PROGMEM = 0x35|SHIFT, // ~ 0 // DEL }; - +Keyboard_ Keyboard; uint8_t Keyboard_::getKeycode(uint8_t k){ return pgm_read_byte(_asciimap + k); } diff --git a/plugins/KeyboardioHID/src/TeensyKeyboard.cpp b/plugins/KeyboardioHID/src/TeensyKeyboard.cpp new file mode 100644 index 0000000000..770035046a --- /dev/null +++ b/plugins/KeyboardioHID/src/TeensyKeyboard.cpp @@ -0,0 +1,388 @@ +/* USB API for Teensy USB Development Board + * http://www.pjrc.com/teensy/teensyduino.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 "TeensyKeyboard.h" + +usb_keyboard_class::usb_keyboard_class(void){ + static HID_Descriptor cb = { + .length = sizeof(keyboard_hid_report_desc), + .descriptor = keyboard_hid_report_desc, + }; + static HIDDescriptorListNode node(&cb); + HID.AppendDescriptor(&node); +} + +// Step #1, decode UTF8 to Unicode code points +// +size_t usb_keyboard_class::write(uint8_t c) +{ + if (c < 0x80) { + // single byte encoded, 0x00 to 0x7F + utf8_state = 0; + write_unicode(c); + } else if (c < 0xC0) { + // 2nd, 3rd or 4th byte, 0x80 to 0xBF + c &= 0x3F; + if (utf8_state == 1) { + utf8_state = 0; + write_unicode(unicode_wchar | c); + } else if (utf8_state == 2) { + unicode_wchar |= ((uint16_t)c << 6); + utf8_state = 1; + } + } else if (c < 0xE0) { + // begin 2 byte sequence, 0xC2 to 0xDF + // or illegal 2 byte sequence, 0xC0 to 0xC1 + unicode_wchar = (uint16_t)(c & 0x1F) << 6; + utf8_state = 1; + } else if (c < 0xF0) { + // begin 3 byte sequence, 0xE0 to 0xEF + unicode_wchar = (uint16_t)(c & 0x0F) << 12; + utf8_state = 2; + } else { + // begin 4 byte sequence (not supported), 0xF0 to 0xF4 + // or illegal, 0xF5 to 0xFF + utf8_state = 255; + } + return 1; +} + + +// Step #2: translate Unicode code point to keystroke sequence +// +KEYCODE_TYPE usb_keyboard_class::unicode_to_keycode(uint16_t cpoint) +{ + // Unicode code points beyond U+FFFF are not supported + // technically this input should probably be called UCS-2 + if (cpoint < 32) { + if (cpoint == 10) return KEY_ENTER & 0x3FFF; + return 0; + } + if (cpoint < 128) { + if (sizeof(KEYCODE_TYPE) == 1) { + return pgm_read_byte(keycodes_ascii + (cpoint - 0x20)); + } else if (sizeof(KEYCODE_TYPE) == 2) { + return pgm_read_word(keycodes_ascii + (cpoint - 0x20)); + } + return 0; + } + #ifdef ISO_8859_1_A0 + if (cpoint <= 0xA0) return 0; + if (cpoint < 0x100) { + if (sizeof(KEYCODE_TYPE) == 1) { + return pgm_read_byte(keycodes_iso_8859_1 + (cpoint - 0xA0)); + } else if (sizeof(KEYCODE_TYPE) == 2) { + return pgm_read_word(keycodes_iso_8859_1 + (cpoint - 0xA0)); + } + return 0; + } + #endif + //#ifdef UNICODE_20AC + //if (cpoint == 0x20AC) return UNICODE_20AC & 0x3FFF; + //#endif + #ifdef KEYCODE_EXTRA00 + if (cpoint == UNICODE_EXTRA00) return KEYCODE_EXTRA00 & 0x3FFF; + #endif + #ifdef KEYCODE_EXTRA01 + if (cpoint == UNICODE_EXTRA01) return KEYCODE_EXTRA01 & 0x3FFF; + #endif + #ifdef KEYCODE_EXTRA02 + if (cpoint == UNICODE_EXTRA02) return KEYCODE_EXTRA02 & 0x3FFF; + #endif + #ifdef KEYCODE_EXTRA03 + if (cpoint == UNICODE_EXTRA03) return KEYCODE_EXTRA03 & 0x3FFF; + #endif + #ifdef KEYCODE_EXTRA04 + if (cpoint == UNICODE_EXTRA04) return KEYCODE_EXTRA04 & 0x3FFF; + #endif + #ifdef KEYCODE_EXTRA05 + if (cpoint == UNICODE_EXTRA05) return KEYCODE_EXTRA05 & 0x3FFF; + #endif + #ifdef KEYCODE_EXTRA06 + if (cpoint == UNICODE_EXTRA06) return KEYCODE_EXTRA06 & 0x3FFF; + #endif + #ifdef KEYCODE_EXTRA07 + if (cpoint == UNICODE_EXTRA07) return KEYCODE_EXTRA07 & 0x3FFF; + #endif + #ifdef KEYCODE_EXTRA08 + if (cpoint == UNICODE_EXTRA08) return KEYCODE_EXTRA08 & 0x3FFF; + #endif + #ifdef KEYCODE_EXTRA09 + if (cpoint == UNICODE_EXTRA09) return KEYCODE_EXTRA09 & 0x3FFF; + #endif + return 0; +} + +// Step #3: execute keystroke sequence +// +void usb_keyboard_class::write_keycode(KEYCODE_TYPE keycode) +{ + if (!keycode) return; + #ifdef DEADKEYS_MASK + KEYCODE_TYPE deadkeycode = deadkey_to_keycode(keycode); + if (deadkeycode) write_key(deadkeycode); + #endif + write_key(keycode); +} + +KEYCODE_TYPE usb_keyboard_class::deadkey_to_keycode(KEYCODE_TYPE keycode) +{ + #ifdef DEADKEYS_MASK + keycode &= DEADKEYS_MASK; + if (keycode == 0) return 0; + #ifdef ACUTE_ACCENT_BITS + if (keycode == ACUTE_ACCENT_BITS) return DEADKEY_ACUTE_ACCENT; + #endif + #ifdef CEDILLA_BITS + if (keycode == CEDILLA_BITS) return DEADKEY_CEDILLA; + #endif + #ifdef CIRCUMFLEX_BITS + if (keycode == CIRCUMFLEX_BITS) return DEADKEY_CIRCUMFLEX; + #endif + #ifdef DIAERESIS_BITS + if (keycode == DIAERESIS_BITS) return DEADKEY_DIAERESIS; + #endif + #ifdef GRAVE_ACCENT_BITS + if (keycode == GRAVE_ACCENT_BITS) return DEADKEY_GRAVE_ACCENT; + #endif + #ifdef TILDE_BITS + if (keycode == TILDE_BITS) return DEADKEY_TILDE; + #endif + #ifdef RING_ABOVE_BITS + if (keycode == RING_ABOVE_BITS) return DEADKEY_RING_ABOVE; + #endif + #endif // DEADKEYS_MASK + return 0; +} + +// Step #4: do each keystroke +// +void usb_keyboard_class::write_key(KEYCODE_TYPE keycode) +{ + keyboard_report_data[0] = keycode_to_modifier(keycode); + keyboard_report_data[1] = 0; + keyboard_report_data[2] = keycode_to_key(keycode); + keyboard_report_data[3] = 0; + keyboard_report_data[4] = 0; + keyboard_report_data[5] = 0; + keyboard_report_data[6] = 0; + keyboard_report_data[7] = 0; + send_now(); + keyboard_report_data[0] = 0; + keyboard_report_data[2] = 0; + send_now(); +} + +uint8_t usb_keyboard_class::keycode_to_modifier(KEYCODE_TYPE keycode) +{ + uint8_t modifier=0; + + #ifdef SHIFT_MASK + if (keycode & SHIFT_MASK) modifier |= MODIFIERKEY_SHIFT; + #endif + #ifdef ALTGR_MASK + if (keycode & ALTGR_MASK) modifier |= MODIFIERKEY_RIGHT_ALT; + #endif + #ifdef RCTRL_MASK + if (keycode & RCTRL_MASK) modifier |= MODIFIERKEY_RIGHT_CTRL; + #endif + return modifier; +} + +uint8_t usb_keyboard_class::keycode_to_key(KEYCODE_TYPE keycode) +{ + uint8_t key = keycode & 0x3F; + #ifdef KEY_NON_US_100 + if (key == KEY_NON_US_100) key = 100; + #endif + return key; +} + + + +void usb_keyboard_class::set_modifier(uint8_t c) +{ + keyboard_report_data[0] = c; +} +void usb_keyboard_class::set_key1(uint8_t c) +{ + keyboard_report_data[2] = c; +} +void usb_keyboard_class::set_key2(uint8_t c) +{ + keyboard_report_data[3] = c; +} +void usb_keyboard_class::set_key3(uint8_t c) +{ + keyboard_report_data[4] = c; +} +void usb_keyboard_class::set_key4(uint8_t c) +{ + keyboard_report_data[5] = c; +} +void usb_keyboard_class::set_key5(uint8_t c) +{ + keyboard_report_data[6] = c; +} +void usb_keyboard_class::set_key6(uint8_t c) +{ + keyboard_report_data[7] = c; +} +void usb_keyboard_class::set_media(uint8_t c) +{ + keyboard_report_data[1] = c; +} + + +void usb_keyboard_class::send_now(void) +{ + HID.SendReport(HID_REPORTID_KEYBOARD,keyboard_report_data,sizeof(keyboard_report_data)); +} + + +void usb_keyboard_class::press(uint16_t n) +{ + uint8_t key, mod, msb, modrestore=0; + + msb = n >> 8; + if (msb >= 0xC2 && msb <= 0xDF) { + n = (n & 0x3F) | ((uint16_t)(msb & 0x1F) << 6); + } else + if (msb == 0x80) { + presskey(0, n); + return; + } else + if (msb == 0x40) { + presskey(n, 0); + return; + } + KEYCODE_TYPE keycode = unicode_to_keycode(n); + if (!keycode) return; + #ifdef DEADKEYS_MASK + KEYCODE_TYPE deadkeycode = deadkey_to_keycode(keycode); + if (deadkeycode) { + modrestore = keyboard_report_data[0]; + if (modrestore) { + keyboard_report_data[0] = 0; + send_now(); + } + // TODO: test if operating systems recognize + // deadkey sequences when other keys are held + mod = keycode_to_modifier(deadkeycode); + key = keycode_to_key(deadkeycode); + presskey(key, mod); + releasekey(key, mod); + } + #endif + mod = keycode_to_modifier(keycode); + key = keycode_to_key(keycode); + presskey(key, mod | modrestore); +} + +void usb_keyboard_class::release(uint16_t n) +{ + uint8_t key, mod, msb; + + msb = n >> 8; + if (msb >= 0xC2 && msb <= 0xDF) { + n = (n & 0x3F) | ((uint16_t)(msb & 0x1F) << 6); + } else + if (msb == 0x80) { + releasekey(0, n); + return; + } else + if (msb == 0x40) { + releasekey(n, 0); + return; + } + KEYCODE_TYPE keycode = unicode_to_keycode(n); + if (!keycode) return; + mod = keycode_to_modifier(keycode); + key = keycode_to_key(keycode); + releasekey(key, mod); +} + +void usb_keyboard_class::presskey(uint8_t key, uint8_t modifier) +{ + bool send_required = false; + uint8_t i; + + if (modifier) { + if ((keyboard_report_data[0] & modifier) != modifier) { + keyboard_report_data[0] |= modifier; + send_required = true; + } + } + if (key) { + for (i=2; i < 8; i++) { + if (keyboard_report_data[i] == key) goto end; + } + for (i=2; i < 8; i++) { + if (keyboard_report_data[i] == 0) { + keyboard_report_data[i] = key; + send_required = true; + goto end; + } + } + } + end: + if (send_required) send_now(); +} + +void usb_keyboard_class::releasekey(uint8_t key, uint8_t modifier) +{ + bool send_required = false; + uint8_t i; + + if (modifier) { + if ((keyboard_report_data[0] & modifier) != 0) { + keyboard_report_data[0] &= ~modifier; + send_required = true; + } + } + if (key) { + for (i=2; i < 8; i++) { + if (keyboard_report_data[i] == key) { + keyboard_report_data[i] = 0; + send_required = true; + } + } + } + if (send_required) send_now(); +} + +void usb_keyboard_class::releaseAll(void) +{ + uint8_t i, anybits; + + anybits = keyboard_report_data[0]; + for (i=2; i < 8; i++) { + anybits |= keyboard_report_data[i]; + keyboard_report_data[i] = 0; + } + if (!anybits) return; + keyboard_report_data[0] = 0; + send_now(); +} + +usb_keyboard_class TeensyKeyboard = usb_keyboard_class(); diff --git a/plugins/KeyboardioHID/src/TeensyKeyboard.h b/plugins/KeyboardioHID/src/TeensyKeyboard.h new file mode 100644 index 0000000000..bc02f6c6e7 --- /dev/null +++ b/plugins/KeyboardioHID/src/TeensyKeyboard.h @@ -0,0 +1,126 @@ +/* USB API for Teensy USB Development Board + * http://www.pjrc.com/teensy/teensyduino.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. + */ + +#pragma once + +#include "HID.h" + +#if !defined(_USING_HID) + +#error "This is not an USB AVR or you use an old version of the IDE." + +#else + +#include "TeensyKeylayouts.h" + +#ifndef HID_REPORTID_KEYBOARD +#define HID_REPORTID_KEYBOARD 2 +#endif + +// 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), + 0x85, HID_REPORTID_KEYBOARD, // REPORT_ID (2) + 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, 0x08, // Report Count (8), + 0x75, 0x01, // Report Size (1), + 0x15, 0x00, // Logical Minimum (0), + 0x25, 0x01, // Logical Maximum (1), + 0x05, 0x0C, // Usage Page (Consumer), + 0x09, 0xE9, // Usage (Volume Increment), + 0x09, 0xEA, // Usage (Volume Decrement), + 0x09, 0xE2, // Usage (Mute), + 0x09, 0xCD, // Usage (Play/Pause), + 0x09, 0xB5, // Usage (Scan Next Track), + 0x09, 0xB6, // Usage (Scan Previous Track), + 0x09, 0xB7, // Usage (Stop), + 0x09, 0xB8, // Usage (Eject), + 0x81, 0x02, // Input (Data, Variable, Absolute), ;Media keys + 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, 0x7F, // Logical Maximum(104), + 0x05, 0x07, // Usage Page (Key Codes), + 0x19, 0x00, // Usage Minimum (0), + 0x29, 0x7F, // Usage Maximum (104), + 0x81, 0x00, // Input (Data, Array), ;Normal keys + 0xc0 // End Collection +}; + +class usb_keyboard_class : public Print +{ + public: + usb_keyboard_class(void); + void begin(void) { } + void end(void) { } + virtual size_t write(uint8_t); + using Print::write; + inline void write_unicode(uint16_t unicode) { write_keycode(unicode_to_keycode(unicode)); } + void set_modifier(uint8_t); + void set_key1(uint8_t); + void set_key2(uint8_t); + void set_key3(uint8_t); + void set_key4(uint8_t); + void set_key5(uint8_t); + void set_key6(uint8_t); + void set_media(uint8_t); + void send_now(void); + void press(uint16_t n); + void release(uint16_t n); + void releaseAll(void); + private: + KEYCODE_TYPE unicode_to_keycode(uint16_t unicode); + KEYCODE_TYPE deadkey_to_keycode(KEYCODE_TYPE keycode); + uint8_t keycode_to_modifier(KEYCODE_TYPE keycode); + uint8_t keycode_to_key(KEYCODE_TYPE keycode); + void presskey(uint8_t key, uint8_t modifier); + void releasekey(uint8_t key, uint8_t modifier); + void write_keycode(KEYCODE_TYPE key); + void write_key(KEYCODE_TYPE code); + uint8_t utf8_state; + uint16_t unicode_wchar; + uint8_t keyboard_report_data[8]; +}; + +extern usb_keyboard_class TeensyKeyboard; +extern HID_ HID; + +#endif diff --git a/plugins/KeyboardioHID/src/TeensyKeylayouts.c b/plugins/KeyboardioHID/src/TeensyKeylayouts.c new file mode 100644 index 0000000000..9ff3b673bd --- /dev/null +++ b/plugins/KeyboardioHID/src/TeensyKeylayouts.c @@ -0,0 +1,66 @@ +#include +#include + +#include "TeensyKeylayouts.h" + +#ifdef M +#undef M +#endif +#define M(n) ((n) & 0x3FFF) + +const KEYCODE_TYPE PROGMEM keycodes_ascii[] = { + M(ASCII_20), M(ASCII_21), M(ASCII_22), M(ASCII_23), + M(ASCII_24), M(ASCII_25), M(ASCII_26), M(ASCII_27), + M(ASCII_28), M(ASCII_29), M(ASCII_2A), M(ASCII_2B), + M(ASCII_2C), M(ASCII_2D), M(ASCII_2E), M(ASCII_2F), + M(ASCII_30), M(ASCII_31), M(ASCII_32), M(ASCII_33), + M(ASCII_34), M(ASCII_35), M(ASCII_36), M(ASCII_37), + M(ASCII_38), M(ASCII_39), M(ASCII_3A), M(ASCII_3B), + M(ASCII_3C), M(ASCII_3D), M(ASCII_3E), M(ASCII_3F), + M(ASCII_40), M(ASCII_41), M(ASCII_42), M(ASCII_43), + M(ASCII_44), M(ASCII_45), M(ASCII_46), M(ASCII_47), + M(ASCII_48), M(ASCII_49), M(ASCII_4A), M(ASCII_4B), + M(ASCII_4C), M(ASCII_4D), M(ASCII_4E), M(ASCII_4F), + M(ASCII_50), M(ASCII_51), M(ASCII_52), M(ASCII_53), + M(ASCII_54), M(ASCII_55), M(ASCII_56), M(ASCII_57), + M(ASCII_58), M(ASCII_59), M(ASCII_5A), M(ASCII_5B), + M(ASCII_5C), M(ASCII_5D), M(ASCII_5E), M(ASCII_5F), + M(ASCII_60), M(ASCII_61), M(ASCII_62), M(ASCII_63), + M(ASCII_64), M(ASCII_65), M(ASCII_66), M(ASCII_67), + M(ASCII_68), M(ASCII_69), M(ASCII_6A), M(ASCII_6B), + M(ASCII_6C), M(ASCII_6D), M(ASCII_6E), M(ASCII_6F), + M(ASCII_70), M(ASCII_71), M(ASCII_72), M(ASCII_73), + M(ASCII_74), M(ASCII_75), M(ASCII_76), M(ASCII_77), + M(ASCII_78), M(ASCII_79), M(ASCII_7A), M(ASCII_7B), + M(ASCII_7C), M(ASCII_7D), M(ASCII_7E), M(ASCII_7F) +}; + +#ifdef ISO_8859_1_A0 +const KEYCODE_TYPE PROGMEM keycodes_iso_8859_1[] = { + M(ISO_8859_1_A0), M(ISO_8859_1_A1), M(ISO_8859_1_A2), M(ISO_8859_1_A3), + M(ISO_8859_1_A4), M(ISO_8859_1_A5), M(ISO_8859_1_A6), M(ISO_8859_1_A7), + M(ISO_8859_1_A8), M(ISO_8859_1_A9), M(ISO_8859_1_AA), M(ISO_8859_1_AB), + M(ISO_8859_1_AC), M(ISO_8859_1_AD), M(ISO_8859_1_AE), M(ISO_8859_1_AF), + M(ISO_8859_1_B0), M(ISO_8859_1_B1), M(ISO_8859_1_B2), M(ISO_8859_1_B3), + M(ISO_8859_1_B4), M(ISO_8859_1_B5), M(ISO_8859_1_B6), M(ISO_8859_1_B7), + M(ISO_8859_1_B8), M(ISO_8859_1_B9), M(ISO_8859_1_BA), M(ISO_8859_1_BB), + M(ISO_8859_1_BC), M(ISO_8859_1_BD), M(ISO_8859_1_BE), M(ISO_8859_1_BF), + M(ISO_8859_1_C0), M(ISO_8859_1_C1), M(ISO_8859_1_C2), M(ISO_8859_1_C3), + M(ISO_8859_1_C4), M(ISO_8859_1_C5), M(ISO_8859_1_C6), M(ISO_8859_1_C7), + M(ISO_8859_1_C8), M(ISO_8859_1_C9), M(ISO_8859_1_CA), M(ISO_8859_1_CB), + M(ISO_8859_1_CC), M(ISO_8859_1_CD), M(ISO_8859_1_CE), M(ISO_8859_1_CF), + M(ISO_8859_1_D0), M(ISO_8859_1_D1), M(ISO_8859_1_D2), M(ISO_8859_1_D3), + M(ISO_8859_1_D4), M(ISO_8859_1_D5), M(ISO_8859_1_D6), M(ISO_8859_1_D7), + M(ISO_8859_1_D8), M(ISO_8859_1_D9), M(ISO_8859_1_DA), M(ISO_8859_1_DB), + M(ISO_8859_1_DC), M(ISO_8859_1_DD), M(ISO_8859_1_DE), M(ISO_8859_1_DF), + M(ISO_8859_1_E0), M(ISO_8859_1_E1), M(ISO_8859_1_E2), M(ISO_8859_1_E3), + M(ISO_8859_1_E4), M(ISO_8859_1_E5), M(ISO_8859_1_E6), M(ISO_8859_1_E7), + M(ISO_8859_1_E8), M(ISO_8859_1_E9), M(ISO_8859_1_EA), M(ISO_8859_1_EB), + M(ISO_8859_1_EC), M(ISO_8859_1_ED), M(ISO_8859_1_EE), M(ISO_8859_1_EF), + M(ISO_8859_1_F0), M(ISO_8859_1_F1), M(ISO_8859_1_F2), M(ISO_8859_1_F3), + M(ISO_8859_1_F4), M(ISO_8859_1_F5), M(ISO_8859_1_F6), M(ISO_8859_1_F7), + M(ISO_8859_1_F8), M(ISO_8859_1_F9), M(ISO_8859_1_FA), M(ISO_8859_1_FB), + M(ISO_8859_1_FC), M(ISO_8859_1_FD), M(ISO_8859_1_FE), M(ISO_8859_1_FF) +}; +#endif // ISO_8859_1_A0 + diff --git a/plugins/KeyboardioHID/src/TeensyKeylayouts.h b/plugins/KeyboardioHID/src/TeensyKeylayouts.h new file mode 100644 index 0000000000..58ce9b21b3 --- /dev/null +++ b/plugins/KeyboardioHID/src/TeensyKeylayouts.h @@ -0,0 +1,5422 @@ +/* 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. + */ + + +#ifndef KEYLAYOUTS_H__ +#define KEYLAYOUTS_H__ + +#include +#include + +#ifdef __cplusplus +extern "C"{ +#endif + +//#define LAYOUT_US_ENGLISH +//#define LAYOUT_CANADIAN_FRENCH +//#define LAYOUT_CANADIAN_MULTILINGUAL +//#define LAYOUT_DANISH +//#define LAYOUT_FINNISH +//#define LAYOUT_FRENCH +//#define LAYOUT_FRENCH_BELGIAN +//#define LAYOUT_FRENCH_SWISS +#define LAYOUT_GERMAN +//#define LAYOUT_GERMAN_MAC +//#define LAYOUT_GERMAN_SWISS +//#define LAYOUT_ICELANDIC +//#define LAYOUT_IRISH +//#define LAYOUT_ITALIAN +//#define LAYOUT_NORWEGIAN +//#define LAYOUT_PORTUGUESE +//#define LAYOUT_PORTUGUESE_BRAZILIAN +//#define LAYOUT_SPANISH +//#define LAYOUT_SPANISH_LATIN_AMERICA +//#define LAYOUT_SWEDISH +//#define LAYOUT_TURKISH +//#define LAYOUT_UNITED_KINGDOM +//#define LAYOUT_US_INTERNATIONAL + + + +// http://en.wikipedia.org/wiki/Keyboard_layout + + +#define MODIFIERKEY_CTRL ( 0x01 | 0x8000 ) +#define MODIFIERKEY_SHIFT ( 0x02 | 0x8000 ) +#define MODIFIERKEY_ALT ( 0x04 | 0x8000 ) +#define MODIFIERKEY_GUI ( 0x08 | 0x8000 ) +#define MODIFIERKEY_LEFT_CTRL ( 0x01 | 0x8000 ) +#define MODIFIERKEY_LEFT_SHIFT ( 0x02 | 0x8000 ) +#define MODIFIERKEY_LEFT_ALT ( 0x04 | 0x8000 ) +#define MODIFIERKEY_LEFT_GUI ( 0x08 | 0x8000 ) +#define MODIFIERKEY_RIGHT_CTRL ( 0x10 | 0x8000 ) +#define MODIFIERKEY_RIGHT_SHIFT ( 0x20 | 0x8000 ) +#define MODIFIERKEY_RIGHT_ALT ( 0x40 | 0x8000 ) +#define MODIFIERKEY_RIGHT_GUI ( 0x80 | 0x8000 ) + +#define KEY_MEDIA_VOLUME_INC 0x01 +#define KEY_MEDIA_VOLUME_DEC 0x02 +#define KEY_MEDIA_MUTE 0x04 +#define KEY_MEDIA_PLAY_PAUSE 0x08 +#define KEY_MEDIA_NEXT_TRACK 0x10 +#define KEY_MEDIA_PREV_TRACK 0x20 +#define KEY_MEDIA_STOP 0x40 +#define KEY_MEDIA_EJECT 0x80 + +#define KEY_A ( 4 | 0x4000 ) +#define KEY_B ( 5 | 0x4000 ) +#define KEY_C ( 6 | 0x4000 ) +#define KEY_D ( 7 | 0x4000 ) +#define KEY_E ( 8 | 0x4000 ) +#define KEY_F ( 9 | 0x4000 ) +#define KEY_G ( 10 | 0x4000 ) +#define KEY_H ( 11 | 0x4000 ) +#define KEY_I ( 12 | 0x4000 ) +#define KEY_J ( 13 | 0x4000 ) +#define KEY_K ( 14 | 0x4000 ) +#define KEY_L ( 15 | 0x4000 ) +#define KEY_M ( 16 | 0x4000 ) +#define KEY_N ( 17 | 0x4000 ) +#define KEY_O ( 18 | 0x4000 ) +#define KEY_P ( 19 | 0x4000 ) +#define KEY_Q ( 20 | 0x4000 ) +#define KEY_R ( 21 | 0x4000 ) +#define KEY_S ( 22 | 0x4000 ) +#define KEY_T ( 23 | 0x4000 ) +#define KEY_U ( 24 | 0x4000 ) +#define KEY_V ( 25 | 0x4000 ) +#define KEY_W ( 26 | 0x4000 ) +#define KEY_X ( 27 | 0x4000 ) +#define KEY_Y ( 28 | 0x4000 ) +#define KEY_Z ( 29 | 0x4000 ) +#define KEY_1 ( 30 | 0x4000 ) +#define KEY_2 ( 31 | 0x4000 ) +#define KEY_3 ( 32 | 0x4000 ) +#define KEY_4 ( 33 | 0x4000 ) +#define KEY_5 ( 34 | 0x4000 ) +#define KEY_6 ( 35 | 0x4000 ) +#define KEY_7 ( 36 | 0x4000 ) +#define KEY_8 ( 37 | 0x4000 ) +#define KEY_9 ( 38 | 0x4000 ) +#define KEY_0 ( 39 | 0x4000 ) +#define KEY_ENTER ( 40 | 0x4000 ) +#define KEY_ESC ( 41 | 0x4000 ) +#define KEY_BACKSPACE ( 42 | 0x4000 ) +#define KEY_TAB ( 43 | 0x4000 ) +#define KEY_SPACE ( 44 | 0x4000 ) +#define KEY_MINUS ( 45 | 0x4000 ) +#define KEY_EQUAL ( 46 | 0x4000 ) +#define KEY_LEFT_BRACE ( 47 | 0x4000 ) +#define KEY_RIGHT_BRACE ( 48 | 0x4000 ) +#define KEY_BACKSLASH ( 49 | 0x4000 ) +#define KEY_NON_US_NUM ( 50 | 0x4000 ) +#define KEY_SEMICOLON ( 51 | 0x4000 ) +#define KEY_QUOTE ( 52 | 0x4000 ) +#define KEY_TILDE ( 53 | 0x4000 ) +#define KEY_COMMA ( 54 | 0x4000 ) +#define KEY_PERIOD ( 55 | 0x4000 ) +#define KEY_SLASH ( 56 | 0x4000 ) +#define KEY_CAPS_LOCK ( 57 | 0x4000 ) +#define KEY_F1 ( 58 | 0x4000 ) +#define KEY_F2 ( 59 | 0x4000 ) +#define KEY_F3 ( 60 | 0x4000 ) +#define KEY_F4 ( 61 | 0x4000 ) +#define KEY_F5 ( 62 | 0x4000 ) +#define KEY_F6 ( 63 | 0x4000 ) +#define KEY_F7 ( 64 | 0x4000 ) +#define KEY_F8 ( 65 | 0x4000 ) +#define KEY_F9 ( 66 | 0x4000 ) +#define KEY_F10 ( 67 | 0x4000 ) +#define KEY_F11 ( 68 | 0x4000 ) +#define KEY_F12 ( 69 | 0x4000 ) +#define KEY_PRINTSCREEN ( 70 | 0x4000 ) +#define KEY_SCROLL_LOCK ( 71 | 0x4000 ) +#define KEY_PAUSE ( 72 | 0x4000 ) +#define KEY_INSERT ( 73 | 0x4000 ) +#define KEY_HOME ( 74 | 0x4000 ) +#define KEY_PAGE_UP ( 75 | 0x4000 ) +#define KEY_DELETE ( 76 | 0x4000 ) +#define KEY_END ( 77 | 0x4000 ) +#define KEY_PAGE_DOWN ( 78 | 0x4000 ) +#define KEY_RIGHT ( 79 | 0x4000 ) +#define KEY_LEFT ( 80 | 0x4000 ) +#define KEY_DOWN ( 81 | 0x4000 ) +#define KEY_UP ( 82 | 0x4000 ) +#define KEY_NUM_LOCK ( 83 | 0x4000 ) +#define KEYPAD_SLASH ( 84 | 0x4000 ) +#define KEYPAD_ASTERIX ( 85 | 0x4000 ) +#define KEYPAD_MINUS ( 86 | 0x4000 ) +#define KEYPAD_PLUS ( 87 | 0x4000 ) +#define KEYPAD_ENTER ( 88 | 0x4000 ) +#define KEYPAD_1 ( 89 | 0x4000 ) +#define KEYPAD_2 ( 90 | 0x4000 ) +#define KEYPAD_3 ( 91 | 0x4000 ) +#define KEYPAD_4 ( 92 | 0x4000 ) +#define KEYPAD_5 ( 93 | 0x4000 ) +#define KEYPAD_6 ( 94 | 0x4000 ) +#define KEYPAD_7 ( 95 | 0x4000 ) +#define KEYPAD_8 ( 96 | 0x4000 ) +#define KEYPAD_9 ( 97 | 0x4000 ) +#define KEYPAD_0 ( 98 | 0x4000 ) +#define KEYPAD_PERIOD ( 99 | 0x4000 ) +#define KEY_MENU ( 101 | 0x4000 ) +#define KEY_F13 ( 104 | 0x4000 ) +#define KEY_F14 ( 105 | 0x4000 ) +#define KEY_F15 ( 106 | 0x4000 ) +#define KEY_F16 ( 107 | 0x4000 ) +#define KEY_F17 ( 108 | 0x4000 ) +#define KEY_F18 ( 109 | 0x4000 ) +#define KEY_F19 ( 110 | 0x4000 ) +#define KEY_F20 ( 111 | 0x4000 ) +#define KEY_F21 ( 112 | 0x4000 ) +#define KEY_F22 ( 113 | 0x4000 ) +#define KEY_F23 ( 114 | 0x4000 ) +#define KEY_F24 ( 115 | 0x4000 ) + + +// for compatibility with Leonardo's slightly different names +#define KEY_UP_ARROW KEY_UP +#define KEY_DOWN_ARROW KEY_DOWN +#define KEY_LEFT_ARROW KEY_LEFT +#define KEY_RIGHT_ARROW KEY_RIGHT +#define KEY_RETURN KEY_ENTER +#define KEY_LEFT_CTRL MODIFIERKEY_LEFT_CTRL +#define KEY_LEFT_SHIFT MODIFIERKEY_LEFT_SHIFT +#define KEY_LEFT_ALT MODIFIERKEY_LEFT_ALT +#define KEY_LEFT_GUI MODIFIERKEY_LEFT_GUI +#define KEY_RIGHT_CTRL MODIFIERKEY_RIGHT_CTRL +#define KEY_RIGHT_SHIFT MODIFIERKEY_RIGHT_SHIFT +#define KEY_RIGHT_ALT MODIFIERKEY_RIGHT_ALT +#define KEY_RIGHT_GUI MODIFIERKEY_RIGHT_GUI + + +// Everything below this line is not intended for use in "normal" programs. +// These private symbols populate lookup tables, which are used to translate +// ascii and UTF8 unicode into keystroke sequences. + + +#ifdef LAYOUT_US_ENGLISH + +#define SHIFT_MASK 0x40 +#define KEYCODE_TYPE uint8_t + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! +#define ASCII_22 KEY_QUOTE + SHIFT_MASK // 34 " +#define ASCII_23 KEY_3 + SHIFT_MASK // 35 # +#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ +#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % +#define ASCII_26 KEY_7 + SHIFT_MASK // 38 & +#define ASCII_27 KEY_QUOTE // 39 ' +#define ASCII_28 KEY_9 + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_0 + SHIFT_MASK // 41 ) +#define ASCII_2A KEY_8 + SHIFT_MASK // 42 * +#define ASCII_2B KEY_EQUAL + SHIFT_MASK // 43 + +#define ASCII_2C KEY_COMMA // 44 , +#define ASCII_2D KEY_MINUS // 45 - +#define ASCII_2E KEY_PERIOD // 46 . +#define ASCII_2F KEY_SLASH // 47 / +#define ASCII_30 KEY_0 // 48 0 +#define ASCII_31 KEY_1 // 49 1 +#define ASCII_32 KEY_2 // 50 2 +#define ASCII_33 KEY_3 // 51 3 +#define ASCII_34 KEY_4 // 52 4 +#define ASCII_35 KEY_5 // 53 5 +#define ASCII_36 KEY_6 // 54 6 +#define ASCII_37 KEY_7 // 55 7 +#define ASCII_38 KEY_8 // 55 8 +#define ASCII_39 KEY_9 // 57 9 +#define ASCII_3A KEY_SEMICOLON + SHIFT_MASK // 58 : +#define ASCII_3B KEY_SEMICOLON // 59 ; +#define ASCII_3C KEY_COMMA + SHIFT_MASK // 60 < +#define ASCII_3D KEY_EQUAL // 61 = +#define ASCII_3E KEY_PERIOD + SHIFT_MASK // 62 > +#define ASCII_3F KEY_SLASH + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_2 + SHIFT_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_LEFT_BRACE // 91 [ +#define ASCII_5C KEY_BACKSLASH // 92 +#define ASCII_5D KEY_RIGHT_BRACE // 93 ] +#define ASCII_5E KEY_6 + SHIFT_MASK // 94 ^ +#define ASCII_5F KEY_MINUS + SHIFT_MASK // 95 _ +#define ASCII_60 KEY_TILDE // 96 ` +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Y // 121 y +#define ASCII_7A KEY_Z // 122 z +#define ASCII_7B KEY_LEFT_BRACE + SHIFT_MASK // 123 { +#define ASCII_7C KEY_BACKSLASH + SHIFT_MASK // 124 | +#define ASCII_7D KEY_RIGHT_BRACE + SHIFT_MASK // 125 } +#define ASCII_7E KEY_TILDE + SHIFT_MASK // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 + +#endif // LAYOUT_US_ENGLISH + + + + +#ifdef LAYOUT_US_INTERNATIONAL + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define DEADKEYS_MASK 0x0700 +#define CIRCUMFLEX_BITS 0x0100 +#define ACUTE_ACCENT_BITS 0x0200 +#define GRAVE_ACCENT_BITS 0x0300 +#define TILDE_BITS 0x0400 +#define DIAERESIS_BITS 0x0500 +#define KEYCODE_TYPE uint16_t +#define DEADKEY_CIRCUMFLEX KEY_6 + SHIFT_MASK +#define DEADKEY_ACUTE_ACCENT KEY_QUOTE +#define DEADKEY_GRAVE_ACCENT KEY_TILDE +#define DEADKEY_TILDE KEY_TILDE + SHIFT_MASK +#define DEADKEY_DIAERESIS KEY_QUOTE + SHIFT_MASK + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! +#define ASCII_22 DIAERESIS_BITS + KEY_SPACE // 34 " +#define ASCII_23 KEY_3 + SHIFT_MASK // 35 # +#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ +#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % +#define ASCII_26 KEY_7 + SHIFT_MASK // 38 & +#define ASCII_27 ACUTE_ACCENT_BITS + KEY_SPACE // 39 ' +#define ASCII_28 KEY_9 + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_0 + SHIFT_MASK // 41 ) +#define ASCII_2A KEY_8 + SHIFT_MASK // 42 * +#define ASCII_2B KEY_EQUAL + SHIFT_MASK // 43 + +#define ASCII_2C KEY_COMMA // 44 , +#define ASCII_2D KEY_MINUS // 45 - +#define ASCII_2E KEY_PERIOD // 46 . +#define ASCII_2F KEY_SLASH // 47 / +#define ASCII_30 KEY_0 // 48 0 +#define ASCII_31 KEY_1 // 49 1 +#define ASCII_32 KEY_2 // 50 2 +#define ASCII_33 KEY_3 // 51 3 +#define ASCII_34 KEY_4 // 52 4 +#define ASCII_35 KEY_5 // 53 5 +#define ASCII_36 KEY_6 // 54 6 +#define ASCII_37 KEY_7 // 55 7 +#define ASCII_38 KEY_8 // 55 8 +#define ASCII_39 KEY_9 // 57 9 +#define ASCII_3A KEY_SEMICOLON + SHIFT_MASK // 58 : +#define ASCII_3B KEY_SEMICOLON // 59 ; +#define ASCII_3C KEY_COMMA + SHIFT_MASK // 60 < +#define ASCII_3D KEY_EQUAL // 61 = +#define ASCII_3E KEY_PERIOD + SHIFT_MASK // 62 > +#define ASCII_3F KEY_SLASH + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_2 + SHIFT_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_LEFT_BRACE // 91 [ +#define ASCII_5C KEY_BACKSLASH // 92 +#define ASCII_5D KEY_RIGHT_BRACE // 93 ] +#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ +#define ASCII_5F KEY_MINUS + SHIFT_MASK // 95 _ +#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Y // 121 y +#define ASCII_7A KEY_Z // 122 z +#define ASCII_7B KEY_LEFT_BRACE + SHIFT_MASK // 123 { +#define ASCII_7C KEY_BACKSLASH + SHIFT_MASK // 124 | +#define ASCII_7D KEY_RIGHT_BRACE + SHIFT_MASK // 125 } +#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 +#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space +#define ISO_8859_1_A1 KEY_1 + ALTGR_MASK // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 KEY_C + ALTGR_MASK + SHIFT_MASK // 162 ¢ Cent SIGN +#define ISO_8859_1_A3 KEY_4 + ALTGR_MASK + SHIFT_MASK // 163 £ Pound Sign +#define ISO_8859_1_A4 KEY_4 + ALTGR_MASK // 164 ¤ Currency or Euro Sign +#define ISO_8859_1_A5 KEY_MINUS + ALTGR_MASK // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 KEY_BACKSLASH + ALTGR_MASK + SHIFT_MASK // 166 ¦ BROKEN BAR ?? +#define ISO_8859_1_A7 KEY_S + ALTGR_MASK + SHIFT_MASK // 167 § SECTION SIGN +#define ISO_8859_1_A8 KEY_QUOTE + ALTGR_MASK + SHIFT_MASK // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 KEY_C + ALTGR_MASK // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB KEY_LEFT_BRACE + ALTGR_MASK // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC KEY_BACKSLASH + ALTGR_MASK // 172 ¬ NOT SIGN ?? +#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN +#define ISO_8859_1_AE KEY_R + ALTGR_MASK // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF 0 // 175 ¯ MACRON +#define ISO_8859_1_B0 KEY_SEMICOLON + ALTGR_MASK + SHIFT_MASK // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 KEY_2 + ALTGR_MASK // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 KEY_3 + ALTGR_MASK // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 KEY_QUOTE + ALTGR_MASK // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 KEY_M + ALTGR_MASK // 181 µ MICRO SIGN +#define ISO_8859_1_B6 KEY_SEMICOLON + ALTGR_MASK // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT +#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA +#define ISO_8859_1_B9 KEY_1 + ALTGR_MASK + SHIFT_MASK // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB KEY_RIGHT_BRACE + ALTGR_MASK // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC KEY_6 + ALTGR_MASK // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD KEY_7 + ALTGR_MASK // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE KEY_8 + ALTGR_MASK // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF KEY_SLASH + ALTGR_MASK // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE +#define ISO_8859_1_C1 KEY_A + ALTGR_MASK + SHIFT_MASK // 193 Á A ACUTE +#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE +#define ISO_8859_1_C4 KEY_Q + ALTGR_MASK + SHIFT_MASK // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 KEY_W + ALTGR_MASK + SHIFT_MASK // 197 Å A RING ABOVE +#define ISO_8859_1_C6 KEY_Z + ALTGR_MASK + SHIFT_MASK // 198 Æ AE +#define ISO_8859_1_C7 KEY_COMMA + ALTGR_MASK + SHIFT_MASK // 199 Ç C CEDILLA +#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE +#define ISO_8859_1_C9 KEY_E + ALTGR_MASK + SHIFT_MASK // 201 É E ACUTE +#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS +#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE +#define ISO_8859_1_CD KEY_I + ALTGR_MASK + SHIFT_MASK // 205 Í I ACUTE +#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 KEY_D + ALTGR_MASK + SHIFT_MASK // 208 Ð ETH +#define ISO_8859_1_D1 KEY_N + ALTGR_MASK + SHIFT_MASK // 209 Ñ N TILDE +#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE +#define ISO_8859_1_D3 KEY_O + ALTGR_MASK + SHIFT_MASK // 211 Ó O ACUTE +#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE +#define ISO_8859_1_D6 KEY_P + ALTGR_MASK + SHIFT_MASK // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 KEY_EQUAL + ALTGR_MASK // 215 × MULTIPLICATION +#define ISO_8859_1_D8 KEY_L + ALTGR_MASK + SHIFT_MASK // 216 Ø O STROKE +#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE +#define ISO_8859_1_DA KEY_U + ALTGR_MASK + SHIFT_MASK // 218 Ú U ACUTE +#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC KEY_Y + ALTGR_MASK + SHIFT_MASK // 220 Ü U DIAERESIS +#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE +#define ISO_8859_1_DE KEY_T + ALTGR_MASK + SHIFT_MASK // 222 Þ THORN +#define ISO_8859_1_DF KEY_S + ALTGR_MASK // 223 ß SHARP S +#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE +#define ISO_8859_1_E1 KEY_A + ALTGR_MASK // 225 á a ACUTE +#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE +#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS +#define ISO_8859_1_E5 KEY_W + ALTGR_MASK // 229 å a RING ABOVE +#define ISO_8859_1_E6 KEY_Z + ALTGR_MASK // 230 æ ae +#define ISO_8859_1_E7 KEY_COMMA + ALTGR_MASK // 231 ç c CEDILLA +#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE +#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE +#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS +#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE +#define ISO_8859_1_ED KEY_I + ALTGR_MASK // 237 í i ACUTE +#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS +#define ISO_8859_1_F0 KEY_D + ALTGR_MASK // 240 ð ETH +#define ISO_8859_1_F1 KEY_N + ALTGR_MASK // 241 ñ n TILDE +#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE +#define ISO_8859_1_F3 KEY_O + ALTGR_MASK // 243 ó o ACUTE +#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE +#define ISO_8859_1_F6 KEY_P + ALTGR_MASK // 246 ö o DIAERESIS +#define ISO_8859_1_F7 KEY_EQUAL + ALTGR_MASK + SHIFT_MASK // 247 ÷ DIVISION +#define ISO_8859_1_F8 KEY_L + ALTGR_MASK // 248 ø o STROKE +#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE +#define ISO_8859_1_FA KEY_U + ALTGR_MASK // 250 ú u ACUTE +#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC KEY_Y + ALTGR_MASK // 252 ü u DIAERESIS +#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE +#define ISO_8859_1_FE KEY_T + ALTGR_MASK // 254 þ THORN +#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS +#define UNICODE_20AC KEY_5 + ALTGR_MASK // € Euro Sign +// not yet implemented +#define UNICODE_EXTRA00 0x20AC +#define KEYCODE_EXTRA00 KEY_5 + ALTGR_MASK // 20AC € Euro Sign + +#endif // LAYOUT_US_INTERNATIONAL + + + +#ifdef LAYOUT_GERMAN + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define DEADKEYS_MASK 0x0700 +#define SHIFT_MASK 0x0100 +#define ALTGR_MASK 0x0200 +#define CIRCUMFLEX_BITS 0x0300 +#define ACUTE_ACCENT_BITS 0x0400 +#define GRAVE_ACCENT_BITS 0x0500 +#define KEYCODE_TYPE uint16_t +#define DEADKEY_CIRCUMFLEX KEY_TILDE +//#define DEADKEY_CIRCUMFLEX KEY_NON_US_100 +#define DEADKEY_ACUTE_ACCENT KEY_EQUAL +#define DEADKEY_GRAVE_ACCENT KEY_EQUAL + SHIFT_MASK +#define KEY_NON_US_100 63 + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! +#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " +#define ASCII_23 KEY_BACKSLASH // 35 # ?? +#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ +#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % +#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & +#define ASCII_27 KEY_BACKSLASH + SHIFT_MASK // 39 ' +#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) +#define ASCII_2A KEY_RIGHT_BRACE + SHIFT_MASK // 42 * +#define ASCII_2B KEY_RIGHT_BRACE // 43 + +#define ASCII_2C KEY_COMMA // 44 , +#define ASCII_2D KEY_SLASH // 45 - +#define ASCII_2E KEY_PERIOD // 46 . +#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / +#define ASCII_30 KEY_0 // 48 0 +#define ASCII_31 KEY_1 // 49 1 +#define ASCII_32 KEY_2 // 50 2 +#define ASCII_33 KEY_3 // 51 3 +#define ASCII_34 KEY_4 // 52 4 +#define ASCII_35 KEY_5 // 53 5 +#define ASCII_36 KEY_6 // 54 6 +#define ASCII_37 KEY_7 // 55 7 +#define ASCII_38 KEY_8 // 55 8 +#define ASCII_39 KEY_9 // 57 9 +#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : +#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; +#define ASCII_3C KEY_NON_US_100 // 60 < +#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = +#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > +#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_Q + ALTGR_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Z + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Y + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_8 + ALTGR_MASK // 91 [ +#define ASCII_5C KEY_MINUS + ALTGR_MASK // 92 +#define ASCII_5D KEY_9 + ALTGR_MASK // 93 ] +#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ +#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ +#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Z // 121 y +#define ASCII_7A KEY_Y // 122 z +#define ASCII_7B KEY_7 + ALTGR_MASK // 123 { +#define ASCII_7C KEY_NON_US_100 + ALTGR_MASK // 124 | +#define ASCII_7D KEY_0 + ALTGR_MASK // 125 } +#define ASCII_7E KEY_RIGHT_BRACE + ALTGR_MASK // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 +#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space +#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 0 // 162 ¢ Cent Sign +#define ISO_8859_1_A3 0 // 163 £ Pound Sign +#define ISO_8859_1_A4 KEY_E + ALTGR_MASK // 164 ¤ Currency Sign +#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR +#define ISO_8859_1_A7 KEY_3 + SHIFT_MASK // 167 § SECTION SIGN +#define ISO_8859_1_A8 0 // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN +#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN +#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF 0 // 175 ¯ MACRON +#define ISO_8859_1_B0 KEY_TILDE + SHIFT_MASK // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 KEY_2 + ALTGR_MASK // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 KEY_3 + ALTGR_MASK // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 0 // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 KEY_M + ALTGR_MASK // 181 µ MICRO SIGN +#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT +#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA +#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE +#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE +#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 0 // 195 Ã A TILDE +#define ISO_8859_1_C4 KEY_QUOTE + SHIFT_MASK // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE +#define ISO_8859_1_C6 0 // 198 Æ AE +#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA +#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE +#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE +#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB 0 // 203 Ë E DIAERESIS +#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE +#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE +#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF 0 // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 0 // 208 Ð ETH +#define ISO_8859_1_D1 0 // 209 Ñ N TILDE +#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE +#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE +#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 0 // 213 Õ O TILDE +#define ISO_8859_1_D6 KEY_SEMICOLON + SHIFT_MASK // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION +#define ISO_8859_1_D8 0 // 216 Ø O STROKE +#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE +#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE +#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC KEY_LEFT_BRACE + SHIFT_MASK // 220 Ü U DIAERESIS +#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Z + SHIFT_MASK // 221 Ý Y ACUTE +#define ISO_8859_1_DE 0 // 222 Þ THORN +#define ISO_8859_1_DF KEY_MINUS // 223 ß SHARP S +#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE +#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE +#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 0 // 227 ã a TILDE +#define ISO_8859_1_E4 KEY_QUOTE // 228 ä a DIAERESIS +#define ISO_8859_1_E5 0 // 229 å a RING ABOVE +#define ISO_8859_1_E6 0 // 230 æ ae +#define ISO_8859_1_E7 0 // 231 ç c CEDILLA +#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE +#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE +#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB 0 // 235 ë e DIAERESIS +#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE +#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE +#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF 0 // 239 ï i DIAERESIS +#define ISO_8859_1_F0 0 // 240 ð ETH +#define ISO_8859_1_F1 0 // 241 ñ n TILDE +#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE +#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE +#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 0 // 245 õ o TILDE +#define ISO_8859_1_F6 KEY_SEMICOLON // 246 ö o DIAERESIS +#define ISO_8859_1_F7 0 // 247 ÷ DIVISION +#define ISO_8859_1_F8 0 // 248 ø o STROKE +#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE +#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE +#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC KEY_LEFT_BRACE // 252 ü u DIAERESIS +#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Z // 253 ý y ACUTE +#define ISO_8859_1_FE 0 // 254 þ THORN +#define ISO_8859_1_FF 0 // 255 ÿ y DIAERESIS +#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign +// not yet implemented +#define UNICODE_EXTRA00 0x20AC +#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign + +#endif // LAYOUT_GERMAN + + + +#ifdef LAYOUT_GERMAN_MAC + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define DEADKEYS_MASK 0x0700 +#define ACUTE_ACCENT_BITS 0x0100 +#define GRAVE_ACCENT_BITS 0x0200 +#define CIRCUMFLEX_BITS 0x0300 +#define DIAERESIS_BITS 0x0400 +#define TILDE_BITS 0x0500 +#define KEYCODE_TYPE uint16_t +#define DEADKEY_ACUTE_ACCENT KEY_EQUAL +#define DEADKEY_GRAVE_ACCENT KEY_EQUAL + SHIFT_MASK +#define DEADKEY_CIRCUMFLEX KEY_6 + SHIFT_MASK + ALTGR_MASK +#define DEADKEY_DIAERESIS KEY_U + ALTGR_MASK +#define DEADKEY_TILDE KEY_N + ALTGR_MASK +#define KEY_NON_US_100 63 + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! +#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " +#define ASCII_23 KEY_BACKSLASH // 35 # ?? +#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ +#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % +#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & +#define ASCII_27 KEY_BACKSLASH + SHIFT_MASK // 39 ' +#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) +#define ASCII_2A KEY_RIGHT_BRACE + SHIFT_MASK // 42 * +#define ASCII_2B KEY_RIGHT_BRACE // 43 + +#define ASCII_2C KEY_COMMA // 44 , +#define ASCII_2D KEY_SLASH // 45 - +#define ASCII_2E KEY_PERIOD // 46 . +#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / +#define ASCII_30 KEY_0 // 48 0 +#define ASCII_31 KEY_1 // 49 1 +#define ASCII_32 KEY_2 // 50 2 +#define ASCII_33 KEY_3 // 51 3 +#define ASCII_34 KEY_4 // 52 4 +#define ASCII_35 KEY_5 // 53 5 +#define ASCII_36 KEY_6 // 54 6 +#define ASCII_37 KEY_7 // 55 7 +#define ASCII_38 KEY_8 // 55 8 +#define ASCII_39 KEY_9 // 57 9 +#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : +#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; +#define ASCII_3C KEY_TILDE // 60 < +#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = +#define ASCII_3E KEY_TILDE + SHIFT_MASK // 62 > +#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_Q + ALTGR_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Z + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Y + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_5 + ALTGR_MASK // 91 [ +#define ASCII_5C KEY_7 + ALTGR_MASK + SHIFT_MASK // 92 +#define ASCII_5D KEY_6 + ALTGR_MASK // 93 ] +#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ +#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ +#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Z // 121 y +#define ASCII_7A KEY_Y // 122 z +#define ASCII_7B KEY_8 + ALTGR_MASK // 123 { +#define ASCII_7C KEY_7 + ALTGR_MASK // 124 | +#define ASCII_7D KEY_9 + ALTGR_MASK // 125 } +#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 +#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space +#define ISO_8859_1_A1 KEY_1 + ALTGR_MASK // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 KEY_4 + ALTGR_MASK // 162 ¢ Cent Sign +#define ISO_8859_1_A3 KEY_4 + SHIFT_MASK + ALTGR_MASK // 163 £ Pound Sign +#define ISO_8859_1_A4 KEY_E + ALTGR_MASK // 164 ¤ Currency Sign +#define ISO_8859_1_A5 KEY_Z + ALTGR_MASK // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR +#define ISO_8859_1_A7 KEY_3 + SHIFT_MASK // 167 § SECTION SIGN +#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 KEY_G + ALTGR_MASK // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA KEY_H + ALTGR_MASK // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB KEY_Q + ALTGR_MASK // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN +#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN +#define ISO_8859_1_AE KEY_R + ALTGR_MASK // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF KEY_0 + SHIFT_MASK + ALTGR_MASK // 175 ¯ MACRON +#define ISO_8859_1_B0 KEY_LEFT_BRACE + ALTGR_MASK + SHIFT_MASK// 176 ° DEGREE SIGN +#define ISO_8859_1_B1 KEY_RIGHT_BRACE + ALTGR_MASK // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 KEY_M + ALTGR_MASK // 181 µ MICRO SIGN +#define ISO_8859_1_B6 KEY_3 + ALTGR_MASK // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 KEY_9 + SHIFT_MASK + ALTGR_MASK // 183 · MIDDLE DOT +#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA +#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA KEY_J + ALTGR_MASK // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB KEY_Q + SHIFT_MASK + ALTGR_MASK // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF KEY_MINUS + ALTGR_MASK // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE +#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE +#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE +#define ISO_8859_1_C4 KEY_QUOTE + SHIFT_MASK // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 KEY_A + ALTGR_MASK + SHIFT_MASK // 197 Å A RING ABOVE +#define ISO_8859_1_C6 KEY_QUOTE + ALTGR_MASK + SHIFT_MASK // 198 Æ AE +#define ISO_8859_1_C7 KEY_C + ALTGR_MASK + SHIFT_MASK // 199 Ç C CEDILLA +#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE +#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE +#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS +#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE +#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE +#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 0 // 208 Ð ETH +#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE +#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE +#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE +#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE +#define ISO_8859_1_D6 KEY_SEMICOLON + SHIFT_MASK // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION +#define ISO_8859_1_D8 KEY_O + ALTGR_MASK + SHIFT_MASK // 216 Ø O STROKE +#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE +#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE +#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC KEY_LEFT_BRACE + SHIFT_MASK // 220 Ü U DIAERESIS +#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Z + SHIFT_MASK // 221 Ý Y ACUTE +#define ISO_8859_1_DE 0 // 222 Þ THORN +#define ISO_8859_1_DF KEY_MINUS // 223 ß SHARP S +#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE +#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE +#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE +#define ISO_8859_1_E4 KEY_QUOTE // 228 ä a DIAERESIS +#define ISO_8859_1_E5 KEY_A + ALTGR_MASK // 229 å a RING ABOVE +#define ISO_8859_1_E6 KEY_QUOTE + ALTGR_MASK // 230 æ ae +#define ISO_8859_1_E7 KEY_C + ALTGR_MASK // 231 ç c CEDILLA +#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE +#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE +#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS +#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE +#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE +#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS +#define ISO_8859_1_F0 0 // 240 ð ETH +#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE +#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE +#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE +#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE +#define ISO_8859_1_F6 KEY_SEMICOLON // 246 ö o DIAERESIS +#define ISO_8859_1_F7 0 // 247 ÷ DIVISION +#define ISO_8859_1_F8 KEY_O + ALTGR_MASK // 248 ø o STROKE +#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE +#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE +#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC KEY_LEFT_BRACE // 252 ü u DIAERESIS +#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Z // 253 ý y ACUTE +#define ISO_8859_1_FE 0 // 254 þ THORN +#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Z // 255 ÿ y DIAERESIS +#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign +// not yet implemented +#define UNICODE_EXTRA00 0x20AC +#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign + +#endif // LAYOUT_GERMAN_MAC + + + + + + +#ifdef LAYOUT_CANADIAN_FRENCH + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define DEADKEYS_MASK 0x0700 +#define CIRCUMFLEX_BITS 0x0100 +#define ACUTE_ACCENT_BITS 0x0200 +#define GRAVE_ACCENT_BITS 0x0300 +#define DIAERESIS_BITS 0x0400 +#define CEDILLA_BITS 0x0500 + +#define KEYCODE_TYPE uint16_t +#define DEADKEY_CIRCUMFLEX KEY_LEFT_BRACE +#define DEADKEY_ACUTE_ACCENT KEY_SLASH + ALTGR_MASK +#define DEADKEY_GRAVE_ACCENT KEY_QUOTE +#define DEADKEY_DIAERESIS KEY_RIGHT_BRACE + SHIFT_MASK +#define DEADKEY_CEDILLA KEY_RIGHT_BRACE +#define KEY_NON_US_100 63 + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! +#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " +#define ASCII_23 KEY_TILDE + SHIFT_MASK // 35 # +#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ +#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % +#define ASCII_26 KEY_7 + SHIFT_MASK // 38 & +#define ASCII_27 KEY_COMMA + SHIFT_MASK // 39 ' +//#define ASCII_27 ACUTE_ACCENT_BITS + KEY_SPACE // 39 ' +#define ASCII_28 KEY_9 + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_0 + SHIFT_MASK // 41 ) +#define ASCII_2A KEY_8 + SHIFT_MASK // 42 * +#define ASCII_2B KEY_EQUAL + SHIFT_MASK // 43 + +#define ASCII_2C KEY_COMMA // 44 , +#define ASCII_2D KEY_MINUS // 45 - +#define ASCII_2E KEY_PERIOD // 46 . +#define ASCII_2F KEY_3 + SHIFT_MASK // 47 / +#define ASCII_30 KEY_0 // 48 0 +#define ASCII_31 KEY_1 // 49 1 +#define ASCII_32 KEY_2 // 50 2 +#define ASCII_33 KEY_3 // 51 3 +#define ASCII_34 KEY_4 // 52 4 +#define ASCII_35 KEY_5 // 53 5 +#define ASCII_36 KEY_6 // 54 6 +#define ASCII_37 KEY_7 // 55 7 +#define ASCII_38 KEY_8 // 55 8 +#define ASCII_39 KEY_9 // 57 9 +#define ASCII_3A KEY_SEMICOLON + SHIFT_MASK // 58 : +#define ASCII_3B KEY_SEMICOLON // 59 ; +#define ASCII_3C KEY_BACKSLASH // 60 < +#define ASCII_3D KEY_EQUAL // 61 = +#define ASCII_3E KEY_BACKSLASH + SHIFT_MASK // 62 > +#define ASCII_3F KEY_6 + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_2 + ALTGR_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_LEFT_BRACE + ALTGR_MASK // 91 [ +#define ASCII_5C KEY_TILDE + ALTGR_MASK // 92 +#define ASCII_5D KEY_RIGHT_BRACE + ALTGR_MASK // 93 ] +#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ +#define ASCII_5F KEY_MINUS + SHIFT_MASK // 95 _ +#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Y // 121 y +#define ASCII_7A KEY_Z // 122 z +#define ASCII_7B KEY_QUOTE + ALTGR_MASK // 123 { +#define ASCII_7C KEY_TILDE + SHIFT_MASK // 124 | +#define ASCII_7D KEY_BACKSLASH + ALTGR_MASK // 125 } +#define ASCII_7E KEY_SEMICOLON + ALTGR_MASK // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 +#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space +#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 KEY_4 + ALTGR_MASK // 162 ¢ Cent SIGN +#define ISO_8859_1_A3 KEY_3 + ALTGR_MASK // 163 £ Pound Sign +#define ISO_8859_1_A4 KEY_5 + ALTGR_MASK // 164 ¤ Currency or Euro Sign +#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 KEY_7 + ALTGR_MASK // 166 ¦ BROKEN BAR +#define ISO_8859_1_A7 KEY_O + ALTGR_MASK // 167 § SECTION SIGN +#define ISO_8859_1_A8 0 // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB KEY_NON_US_100 // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC KEY_6 + ALTGR_MASK // 172 ¬ NOT SIGN +#define ISO_8859_1_AD KEY_PERIOD + ALTGR_MASK // 173 SOFT HYPHEN +#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF KEY_COMMA + ALTGR_MASK // 175 ¯ MACRON +#define ISO_8859_1_B0 KEY_NON_US_100 + ALTGR_MASK // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 KEY_1 + ALTGR_MASK // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 KEY_8 + ALTGR_MASK // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 KEY_9 + ALTGR_MASK // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 0 // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 KEY_M + ALTGR_MASK // 181 µ MICRO SIGN +#define ISO_8859_1_B6 KEY_P + ALTGR_MASK // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT +#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA +#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB KEY_NON_US_100 + SHIFT_MASK // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC KEY_0 + ALTGR_MASK // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD KEY_MINUS + ALTGR_MASK // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE KEY_EQUAL + ALTGR_MASK // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE +#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE +#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 0 // 195 Ã A TILDE +#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE +#define ISO_8859_1_C6 0 // 198 Æ AE +#define ISO_8859_1_C7 CEDILLA_BITS + KEY_C + SHIFT_MASK // 199 Ç C CEDILLA +#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE +#define ISO_8859_1_C9 KEY_SLASH + SHIFT_MASK // 201 É E ACUTE +#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS +#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE +#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE +#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 0 // 208 Ð ETH +#define ISO_8859_1_D1 0 // 209 Ñ N TILDE +#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE +#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE +#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 0 // 213 Õ O TILDE +#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION +#define ISO_8859_1_D8 0 // 216 Ø O STROKE +#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE +#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE +#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U // 220 Ü U DIAERESIS +#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE +#define ISO_8859_1_DE 0 // 222 Þ THORN +#define ISO_8859_1_DF 0 // 223 ß SHARP S +#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE +#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE +#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 0 // 227 ã a TILDE +#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS +#define ISO_8859_1_E5 0 // 229 å a RING ABOVE +#define ISO_8859_1_E6 0 // 230 æ ae +#define ISO_8859_1_E7 CEDILLA_BITS + KEY_C // 231 ç c CEDILLA +#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE +#define ISO_8859_1_E9 KEY_SLASH // 233 é e ACUTE +#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS +#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE +#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE +#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS +#define ISO_8859_1_F0 0 // 240 ð ETH +#define ISO_8859_1_F1 0 // 241 ñ n TILDE +#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE +#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE +#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 0 // 245 õ o TILDE +#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS +#define ISO_8859_1_F7 0 // 247 ÷ DIVISION +#define ISO_8859_1_F8 0 // 248 ø o STROKE +#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE +#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE +#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS +#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE +#define ISO_8859_1_FE 0 // 254 þ THORN +#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS + +#endif // LAYOUT_CANADIAN_FRENCH + + + +#ifdef LAYOUT_CANADIAN_MULTILINGUAL + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define RCTRL_MASK 0x0800 +#define DEADKEYS_MASK 0x0700 +#define CIRCUMFLEX_BITS 0x0100 +#define DIAERESIS_BITS 0x0200 +#define ACUTE_ACCENT_BITS 0x0300 +#define CEDILLA_BITS 0x0400 +#define GRAVE_ACCENT_BITS 0x0500 +#define TILDE_BITS 0x0600 +#define RING_ABOVE_BITS 0x0700 +#define KEYCODE_TYPE uint16_t +#define DEADKEY_CIRCUMFLEX KEY_LEFT_BRACE +#define DEADKEY_DIAERESIS KEY_LEFT_BRACE + SHIFT_MASK +#define DEADKEY_ACUTE_ACCENT KEY_SEMICOLON + RCTRL_MASK +#define DEADKEY_CEDILLA KEY_EQUAL + RCTRL_MASK +#define DEADKEY_GRAVE_ACCENT KEY_LEFT_BRACE + ALTGR_MASK +#define DEADKEY_TILDE KEY_RIGHT_BRACE + ALTGR_MASK +#define DEADKEY_RING_ABOVE KEY_LEFT_BRACE + SHIFT_MASK + RCTRL_MASK +#define KEY_NON_US_100 63 + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! +#define ASCII_22 KEY_PERIOD + SHIFT_MASK // 34 " +#define ASCII_23 KEY_3 + SHIFT_MASK // 35 # +#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ +#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % +#define ASCII_26 KEY_7 + SHIFT_MASK // 38 & +#define ASCII_27 KEY_COMMA + SHIFT_MASK // 39 ' +#define ASCII_28 KEY_9 + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_0 + SHIFT_MASK // 41 ) +#define ASCII_2A KEY_8 + SHIFT_MASK // 42 * +#define ASCII_2B KEY_EQUAL + SHIFT_MASK // 43 + +#define ASCII_2C KEY_COMMA // 44 , +#define ASCII_2D KEY_MINUS // 45 - +#define ASCII_2E KEY_PERIOD // 46 . +#define ASCII_2F KEY_TILDE // 47 / +#define ASCII_30 KEY_0 // 48 0 +#define ASCII_31 KEY_1 // 49 1 +#define ASCII_32 KEY_2 // 50 2 +#define ASCII_33 KEY_3 // 51 3 +#define ASCII_34 KEY_4 // 52 4 +#define ASCII_35 KEY_5 // 53 5 +#define ASCII_36 KEY_6 // 54 6 +#define ASCII_37 KEY_7 // 55 7 +#define ASCII_38 KEY_8 // 55 8 +#define ASCII_39 KEY_9 // 57 9 +#define ASCII_3A KEY_SEMICOLON + SHIFT_MASK // 58 : +#define ASCII_3B KEY_SEMICOLON // 59 ; +#define ASCII_3C KEY_COMMA + ALTGR_MASK // 60 < +#define ASCII_3D KEY_EQUAL // 61 = +#define ASCII_3E KEY_PERIOD + ALTGR_MASK // 62 > +#define ASCII_3F KEY_6 + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_2 + SHIFT_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_9 + ALTGR_MASK // 91 [ +#define ASCII_5C KEY_TILDE + SHIFT_MASK // 92 +#define ASCII_5D KEY_0 + ALTGR_MASK // 93 ] +#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ +#define ASCII_5F KEY_MINUS + SHIFT_MASK // 95 _ +#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Y // 121 y +#define ASCII_7A KEY_Z // 122 z +#define ASCII_7B KEY_7 + ALTGR_MASK // 123 { +#define ASCII_7C KEY_TILDE + ALTGR_MASK // 124 | +#define ASCII_7D KEY_8 + ALTGR_MASK // 125 } +#define ASCII_7E KEY_RIGHT_BRACE + RCTRL_MASK // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 +#define ISO_8859_1_A0 KEY_SPACE + ALTGR_MASK // 160 Nonbreakng Space +#define ISO_8859_1_A1 KEY_1 + SHIFT_MASK + RCTRL_MASK // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 KEY_C + RCTRL_MASK // 162 ¢ Cent SIGN +#define ISO_8859_1_A3 KEY_3 + SHIFT_MASK + RCTRL_MASK // 163 £ Pound Sign +#define ISO_8859_1_A4 KEY_4 + SHIFT_MASK + RCTRL_MASK // 164 ¤ Currency or Euro Sign +#define ISO_8859_1_A5 KEY_Y + SHIFT_MASK + RCTRL_MASK // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 KEY_NON_US_100 + SHIFT_MASK + RCTRL_MASK// 166 ¦ BROKEN BAR +#define ISO_8859_1_A7 KEY_S + SHIFT_MASK + RCTRL_MASK // 167 § SECTION SIGN +#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 KEY_C + SHIFT_MASK + RCTRL_MASK // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA KEY_F + SHIFT_MASK + RCTRL_MASK // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB KEY_Z + ALTGR_MASK // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC KEY_EQUAL + ALTGR_MASK // 172 ¬ NOT SIGN +#define ISO_8859_1_AD KEY_TILDE + SHIFT_MASK + RCTRL_MASK // 173 SOFT HYPHEN +#define ISO_8859_1_AE KEY_R + SHIFT_MASK + RCTRL_MASK // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF 0 // special dead key - no implemented // 175 ¯ MACRON +#define ISO_8859_1_B0 KEY_SEMICOLON + ALTGR_MASK // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 KEY_9 + SHIFT_MASK + RCTRL_MASK // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 KEY_2 + RCTRL_MASK // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 KEY_3 + RCTRL_MASK // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 KEY_M + RCTRL_MASK // 181 µ MICRO SIGN +#define ISO_8859_1_B6 KEY_R + RCTRL_MASK // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT +#define ISO_8859_1_B8 CEDILLA_BITS + KEY_SPACE // 184 ¸ CEDILLA +#define ISO_8859_1_B9 KEY_1 + RCTRL_MASK // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA KEY_M + SHIFT_MASK + RCTRL_MASK // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB KEY_X + ALTGR_MASK // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC KEY_4 + RCTRL_MASK // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD KEY_5 + RCTRL_MASK // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE KEY_6 + RCTRL_MASK // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF KEY_MINUS + SHIFT_MASK + RCTRL_MASK // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 KEY_BACKSLASH + SHIFT_MASK // 192 À A GRAVE +#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE +#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE +#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 RING_ABOVE_BITS + KEY_A + SHIFT_MASK // 197 Å A RING ABOVE +#define ISO_8859_1_C6 KEY_A + SHIFT_MASK + RCTRL_MASK // 198 Æ AE +#define ISO_8859_1_C7 KEY_RIGHT_BRACE + SHIFT_MASK // 199 Ç C CEDILLA +#define ISO_8859_1_C8 KEY_QUOTE + SHIFT_MASK // 200 È E GRAVE +#define ISO_8859_1_C9 KEY_SLASH + SHIFT_MASK // 201 É E ACUTE +#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS +#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE +#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE +#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 KEY_D + SHIFT_MASK + RCTRL_MASK // 208 Ð ETH +#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE +#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE +#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE +#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE +#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 KEY_COMMA + SHIFT_MASK + RCTRL_MASK // 215 × MULTIPLICATION +#define ISO_8859_1_D8 KEY_O + SHIFT_MASK + RCTRL_MASK // 216 Ø O STROKE +#define ISO_8859_1_D9 KEY_NON_US_100 + SHIFT_MASK // 217 Ù U GRAVE +#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE +#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U // 220 Ü U DIAERESIS +#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE +#define ISO_8859_1_DE KEY_P + RCTRL_MASK + SHIFT_MASK // 222 Þ THORN +#define ISO_8859_1_DF KEY_S + RCTRL_MASK // 223 ß SHARP S +#define ISO_8859_1_E0 KEY_BACKSLASH // 224 à a GRAVE +#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE +#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE +#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS +#define ISO_8859_1_E5 RING_ABOVE_BITS + KEY_A // 229 å a RING ABOVE +#define ISO_8859_1_E6 KEY_A + RCTRL_MASK // 230 æ ae +#define ISO_8859_1_E7 KEY_RIGHT_BRACE // 231 ç c CEDILLA +#define ISO_8859_1_E8 KEY_QUOTE // 232 è e GRAVE +#define ISO_8859_1_E9 KEY_SLASH // 233 é e ACUTE +#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS +#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE +#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE +#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS +#define ISO_8859_1_F0 KEY_D + RCTRL_MASK // 240 ð ETH +#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE +#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE +#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE +#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE +#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS +#define ISO_8859_1_F7 KEY_PERIOD + SHIFT_MASK + RCTRL_MASK // 247 ÷ DIVISION +#define ISO_8859_1_F8 KEY_O + RCTRL_MASK // 248 ø o STROKE +#define ISO_8859_1_F9 KEY_NON_US_100 // 249 ù u GRAVE +#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE +#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS +#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE +#define ISO_8859_1_FE KEY_P + RCTRL_MASK // 254 þ THORN +#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS + +#endif // LAYOUT_CANADIAN_MULTILINGUAL + + + + + + +#ifdef LAYOUT_UNITED_KINGDOM + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define KEYCODE_TYPE uint8_t +#define KEY_NON_US_100 63 + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! +#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " +#define ASCII_23 KEY_BACKSPACE // 35 # +#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ +#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % +#define ASCII_26 KEY_7 + SHIFT_MASK // 38 & +#define ASCII_27 KEY_QUOTE // 39 ' +#define ASCII_28 KEY_9 + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_0 + SHIFT_MASK // 41 ) +#define ASCII_2A KEY_8 + SHIFT_MASK // 42 * +#define ASCII_2B KEY_EQUAL + SHIFT_MASK // 43 + +#define ASCII_2C KEY_COMMA // 44 , +#define ASCII_2D KEY_MINUS // 45 - +#define ASCII_2E KEY_PERIOD // 46 . +#define ASCII_2F KEY_SLASH // 47 / +#define ASCII_30 KEY_0 // 48 0 +#define ASCII_31 KEY_1 // 49 1 +#define ASCII_32 KEY_2 // 50 2 +#define ASCII_33 KEY_3 // 51 3 +#define ASCII_34 KEY_4 // 52 4 +#define ASCII_35 KEY_5 // 53 5 +#define ASCII_36 KEY_6 // 54 6 +#define ASCII_37 KEY_7 // 55 7 +#define ASCII_38 KEY_8 // 55 8 +#define ASCII_39 KEY_9 // 57 9 +#define ASCII_3A KEY_SEMICOLON + SHIFT_MASK // 58 : +#define ASCII_3B KEY_SEMICOLON // 59 ; +#define ASCII_3C KEY_COMMA + SHIFT_MASK // 60 < +#define ASCII_3D KEY_EQUAL // 61 = +#define ASCII_3E KEY_PERIOD + SHIFT_MASK // 62 > +#define ASCII_3F KEY_SLASH + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_QUOTE + SHIFT_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_LEFT_BRACE // 91 [ +#define ASCII_5C KEY_NON_US_100 // 92 +#define ASCII_5D KEY_RIGHT_BRACE // 93 ] +#define ASCII_5E KEY_6 + SHIFT_MASK // 94 ^ +#define ASCII_5F KEY_MINUS + SHIFT_MASK // 95 _ +#define ASCII_60 KEY_TILDE // 96 ` +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Y // 121 y +#define ASCII_7A KEY_Z // 122 z +#define ASCII_7B KEY_LEFT_BRACE + SHIFT_MASK // 123 { +#define ASCII_7C KEY_NON_US_100 + SHIFT_MASK // 124 | +#define ASCII_7D KEY_RIGHT_BRACE + SHIFT_MASK // 125 } +#define ASCII_7E KEY_BACKSLASH + SHIFT_MASK // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 + +#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space +#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN +#define ISO_8859_1_A3 KEY_3 + SHIFT_MASK // 163 £ Pound Sign +#define ISO_8859_1_A4 0 // 164 ¤ Currency or Euro Sign +#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 KEY_TILDE + ALTGR_MASK // 166 ¦ BROKEN BAR +#define ISO_8859_1_A7 0 // 167 § SECTION SIGN +#define ISO_8859_1_A8 0 // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC KEY_TILDE + SHIFT_MASK // 172 ¬ NOT SIGN +#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN +#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF 0 // 175 ¯ MACRON +#define ISO_8859_1_B0 0 // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 0 // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN +#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT +#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA +#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 0 // 192 À A GRAVE +#define ISO_8859_1_C1 KEY_A + ALTGR_MASK + SHIFT_MASK // 193 Á A ACUTE +#define ISO_8859_1_C2 0 // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 0 // 195 Ã A TILDE +#define ISO_8859_1_C4 0 // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE +#define ISO_8859_1_C6 0 // 198 Æ AE +#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA +#define ISO_8859_1_C8 0 // 200 È E GRAVE +#define ISO_8859_1_C9 KEY_E + ALTGR_MASK + SHIFT_MASK // 201 É E ACUTE +#define ISO_8859_1_CA 0 // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB 0 // 203 Ë E DIAERESIS +#define ISO_8859_1_CC 0 // 204 Ì I GRAVE +#define ISO_8859_1_CD KEY_I + ALTGR_MASK + SHIFT_MASK // 205 Í I ACUTE +#define ISO_8859_1_CE 0 // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF 0 // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 0 // 208 Ð ETH +#define ISO_8859_1_D1 0 // 209 Ñ N TILDE +#define ISO_8859_1_D2 0 // 210 Ò O GRAVE +#define ISO_8859_1_D3 KEY_O + ALTGR_MASK + SHIFT_MASK // 211 Ó O ACUTE +#define ISO_8859_1_D4 0 // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 0 // 213 Õ O TILDE +#define ISO_8859_1_D6 0 // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION +#define ISO_8859_1_D8 0 // 216 Ø O STROKE +#define ISO_8859_1_D9 0 // 217 Ù U GRAVE +#define ISO_8859_1_DA KEY_U + ALTGR_MASK + SHIFT_MASK // 218 Ú U ACUTE +#define ISO_8859_1_DB 0 // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC 0 // 220 Ü U DIAERESIS +#define ISO_8859_1_DD 0 // 221 Ý Y ACUTE +#define ISO_8859_1_DE 0 // 222 Þ THORN +#define ISO_8859_1_DF 0 // 223 ß SHARP S +#define ISO_8859_1_E0 0 // 224 à a GRAVE +#define ISO_8859_1_E1 KEY_A + ALTGR_MASK // 225 á a ACUTE +#define ISO_8859_1_E2 0 // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 0 // 227 ã a TILDE +#define ISO_8859_1_E4 0 // 228 ä a DIAERESIS +#define ISO_8859_1_E5 0 // 229 å a RING ABOVE +#define ISO_8859_1_E6 0 // 230 æ ae +#define ISO_8859_1_E7 0 // 231 ç c CEDILLA +#define ISO_8859_1_E8 0 // 232 è e GRAVE +#define ISO_8859_1_E9 KEY_E + ALTGR_MASK // 233 é e ACUTE +#define ISO_8859_1_EA 0 // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB 0 // 235 ë e DIAERESIS +#define ISO_8859_1_EC 0 // 236 ì i GRAVE +#define ISO_8859_1_ED KEY_I + ALTGR_MASK // 237 í i ACUTE +#define ISO_8859_1_EE 0 // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF 0 // 239 ï i DIAERESIS +#define ISO_8859_1_F0 0 // 240 ð ETH +#define ISO_8859_1_F1 0 // 241 ñ n TILDE +#define ISO_8859_1_F2 0 // 242 ò o GRAVE +#define ISO_8859_1_F3 KEY_O + ALTGR_MASK // 243 ó o ACUTE +#define ISO_8859_1_F4 0 // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 0 // 245 õ o TILDE +#define ISO_8859_1_F6 0 // 246 ö o DIAERESIS +#define ISO_8859_1_F7 0 // 247 ÷ DIVISION +#define ISO_8859_1_F8 0 // 248 ø o STROKE +#define ISO_8859_1_F9 0 // 249 ù u GRAVE +#define ISO_8859_1_FA KEY_U + ALTGR_MASK // 250 ú u ACUTE +#define ISO_8859_1_FB 0 // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC 0 // 252 ü u DIAERESIS +#define ISO_8859_1_FD 0 // 253 ý y ACUTE +#define ISO_8859_1_FE 0 // 254 þ THORN +#define ISO_8859_1_FF 0 // 255 ÿ y DIAERESIS +#define UNICODE_20AC KEY_4 + ALTGR_MASK // € Euro Sign +// not yet implemented +#define UNICODE_EXTRA00 0x20AC +#define KEYCODE_EXTRA00 KEY_4 + ALTGR_MASK // 20AC € Euro Sign + +#endif // LAYOUT_UNITED_KINGDOM + + + +#ifdef LAYOUT_FINNISH + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define DEADKEYS_MASK 0x0700 +#define CIRCUMFLEX_BITS 0x0100 +#define ACUTE_ACCENT_BITS 0x0200 +#define GRAVE_ACCENT_BITS 0x0300 +#define TILDE_BITS 0x0400 +#define DIAERESIS_BITS 0x0500 +#define KEYCODE_TYPE uint16_t +#define DEADKEY_CIRCUMFLEX KEY_RIGHT_BRACE + SHIFT_MASK +#define DEADKEY_ACUTE_ACCENT KEY_EQUAL +#define DEADKEY_GRAVE_ACCENT KEY_EQUAL + SHIFT_MASK +#define DEADKEY_TILDE KEY_RIGHT_BRACE + ALTGR_MASK +#define DEADKEY_DIAERESIS KEY_RIGHT_BRACE +#define KEY_NON_US_100 63 + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! +#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " +#define ASCII_23 KEY_3 + SHIFT_MASK // 35 # +#define ASCII_24 KEY_4 + ALTGR_MASK // 36 $ +#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % +#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & +#define ASCII_27 KEY_BACKSLASH // 39 ' +#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) +#define ASCII_2A KEY_BACKSLASH + SHIFT_MASK // 42 * +#define ASCII_2B KEY_MINUS // 43 + +#define ASCII_2C KEY_COMMA // 44 , +#define ASCII_2D KEY_SLASH // 45 - +#define ASCII_2E KEY_PERIOD // 46 . +#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / +#define ASCII_30 KEY_0 // 48 0 +#define ASCII_31 KEY_1 // 49 1 +#define ASCII_32 KEY_2 // 50 2 +#define ASCII_33 KEY_3 // 51 3 +#define ASCII_34 KEY_4 // 52 4 +#define ASCII_35 KEY_5 // 53 5 +#define ASCII_36 KEY_6 // 54 6 +#define ASCII_37 KEY_7 // 55 7 +#define ASCII_38 KEY_8 // 55 8 +#define ASCII_39 KEY_9 // 57 9 +#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : +#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; +#define ASCII_3C KEY_NON_US_100 // 60 < +#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = +#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > +#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_2 + ALTGR_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_8 + ALTGR_MASK // 91 [ +#define ASCII_5C KEY_MINUS + ALTGR_MASK // 92 +#define ASCII_5D KEY_9 + ALTGR_MASK // 93 ] +#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ +#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ +#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Y // 121 y +#define ASCII_7A KEY_Z // 122 z +#define ASCII_7B KEY_7 + ALTGR_MASK // 123 { +#define ASCII_7C KEY_NON_US_100 + ALTGR_MASK // 124 | +#define ASCII_7D KEY_0 + ALTGR_MASK // 125 } +#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 +#define ISO_8859_1_A0 KEY_SPACE + ALTGR_MASK // 160 Nonbreakng Space +#define ISO_8859_1_A1 KEY_1 + SHIFT_MASK + ALTGR_MASK // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN +#define ISO_8859_1_A3 KEY_3 + ALTGR_MASK // 163 £ Pound Sign +#define ISO_8859_1_A4 KEY_4 + SHIFT_MASK // 164 ¤ Currency or Euro Sign +#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR +#define ISO_8859_1_A7 KEY_TILDE // 167 § SECTION SIGN +#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB KEY_4 + ALTGR_MASK + SHIFT_MASK // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN +#define ISO_8859_1_AD KEY_SLASH + ALTGR_MASK // 173 SOFT HYPHEN +#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF 0 // 175 ¯ MACRON +#define ISO_8859_1_B0 KEY_0 + ALTGR_MASK + SHIFT_MASK // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 KEY_M + ALTGR_MASK // 181 µ MICRO SIGN +#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 KEY_X + ALTGR_MASK + SHIFT_MASK // 183 · MIDDLE DOT +#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA +#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB KEY_3 + ALTGR_MASK + SHIFT_MASK // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD KEY_TILDE + SHIFT_MASK // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF KEY_MINUS + ALTGR_MASK + SHIFT_MASK // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE +#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE +#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE +#define ISO_8859_1_C4 KEY_QUOTE + SHIFT_MASK // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 KEY_LEFT_BRACE + SHIFT_MASK // 197 Å A RING ABOVE +#define ISO_8859_1_C6 KEY_QUOTE + ALTGR_MASK + SHIFT_MASK // 198 Æ AE +#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA +#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE +#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE +#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS +#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE +#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE +#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 KEY_D + ALTGR_MASK + SHIFT_MASK // 208 Ð ETH +#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE +#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE +#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE +#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE +#define ISO_8859_1_D6 KEY_SEMICOLON + SHIFT_MASK // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 KEY_X + ALTGR_MASK // 215 × MULTIPLICATION +#define ISO_8859_1_D8 KEY_SEMICOLON + ALTGR_MASK + SHIFT_MASK // 216 Ø O STROKE +#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE +#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE +#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS +#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE +#define ISO_8859_1_DE KEY_T + ALTGR_MASK + SHIFT_MASK // 222 Þ THORN +#define ISO_8859_1_DF KEY_S + ALTGR_MASK // 223 ß SHARP S +#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE +#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE +#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE +#define ISO_8859_1_E4 KEY_QUOTE // 228 ä a DIAERESIS +#define ISO_8859_1_E5 KEY_LEFT_BRACE // 229 å a RING ABOVE +#define ISO_8859_1_E6 KEY_QUOTE + ALTGR_MASK // 230 æ ae +#define ISO_8859_1_E7 0 // 231 ç c CEDILLA +#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE +#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE +#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS +#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE +#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE +#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS +#define ISO_8859_1_F0 KEY_D + ALTGR_MASK // 240 ð ETH +#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE +#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE +#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE +#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE +#define ISO_8859_1_F6 KEY_SEMICOLON // 246 ö o DIAERESIS +#define ISO_8859_1_F7 0 // 247 ÷ DIVISION +#define ISO_8859_1_F8 KEY_SEMICOLON + ALTGR_MASK // 248 ø o STROKE +#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE +#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE +#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS +#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE +#define ISO_8859_1_FE KEY_T + ALTGR_MASK // 254 þ THORN +#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS +#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign +// not yet implemented +#define UNICODE_EXTRA00 0x20AC +#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign +// TODO: Finnish Multilingual layout can type many more glyphs +// but we currently don't have tables tables to store them... + +#endif // LAYOUT_FINNISH + + + + + + + +#ifdef LAYOUT_FRENCH + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define DEADKEYS_MASK 0x0700 +#define CIRCUMFLEX_BITS 0x0100 +#define GRAVE_ACCENT_BITS 0x0200 +#define DIAERESIS_BITS 0x0300 +#define TILDE_BITS 0x0400 +#define KEYCODE_TYPE uint16_t +#define DEADKEY_CIRCUMFLEX KEY_LEFT_BRACE +#define DEADKEY_GRAVE_ACCENT KEY_7 + ALTGR_MASK +#define DEADKEY_DIAERESIS KEY_LEFT_BRACE + SHIFT_MASK +#define DEADKEY_TILDE KEY_2 + ALTGR_MASK +#define KEY_NON_US_100 63 + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_SLASH // 33 ! +#define ASCII_22 KEY_3 // 34 " +#define ASCII_23 KEY_3 + ALTGR_MASK // 35 # +#define ASCII_24 KEY_RIGHT_BRACE // 36 $ +#define ASCII_25 KEY_QUOTE + SHIFT_MASK // 37 % +#define ASCII_26 KEY_1 // 38 & +#define ASCII_27 KEY_4 // 39 ' +#define ASCII_28 KEY_5 // 40 ( +#define ASCII_29 KEY_MINUS // 41 ) +#define ASCII_2A KEY_BACKSLASH // 42 * +#define ASCII_2B KEY_EQUAL + SHIFT_MASK // 43 + +#define ASCII_2C KEY_M // 44 , +#define ASCII_2D KEY_6 // 45 - +#define ASCII_2E KEY_COMMA + SHIFT_MASK // 46 . +#define ASCII_2F KEY_PERIOD + SHIFT_MASK // 47 / +#define ASCII_30 KEY_0 + SHIFT_MASK // 48 0 +#define ASCII_31 KEY_1 + SHIFT_MASK // 49 1 +#define ASCII_32 KEY_2 + SHIFT_MASK // 50 2 +#define ASCII_33 KEY_3 + SHIFT_MASK // 51 3 +#define ASCII_34 KEY_4 + SHIFT_MASK // 52 4 +#define ASCII_35 KEY_5 + SHIFT_MASK // 53 5 +#define ASCII_36 KEY_6 + SHIFT_MASK // 54 6 +#define ASCII_37 KEY_7 + SHIFT_MASK // 55 7 +#define ASCII_38 KEY_8 + SHIFT_MASK // 55 8 +#define ASCII_39 KEY_9 + SHIFT_MASK // 57 9 +#define ASCII_3A KEY_PERIOD // 58 : +#define ASCII_3B KEY_COMMA // 59 ; +#define ASCII_3C KEY_NON_US_100 // 60 < +#define ASCII_3D KEY_EQUAL // 61 = +#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > +#define ASCII_3F KEY_M + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_0 + ALTGR_MASK // 64 @ +#define ASCII_41 KEY_Q + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_SEMICOLON + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_A + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_Z + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_W + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_5 + ALTGR_MASK // 91 [ +#define ASCII_5C KEY_8 + ALTGR_MASK // 92 +#define ASCII_5D KEY_MINUS + ALTGR_MASK // 93 ] +#define ASCII_5E KEY_9 + ALTGR_MASK // 94 ^ +#define ASCII_5F KEY_8 // 95 _ +#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` +#define ASCII_61 KEY_Q // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_SEMICOLON // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_A // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_Z // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Y // 121 y +#define ASCII_7A KEY_W // 122 z +#define ASCII_7B KEY_4 + ALTGR_MASK // 123 { +#define ASCII_7C KEY_6 + ALTGR_MASK // 124 | +#define ASCII_7D KEY_EQUAL + ALTGR_MASK // 125 } +#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 +#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space +#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN +#define ISO_8859_1_A3 KEY_RIGHT_BRACE + SHIFT_MASK // 163 £ Pound Sign +#define ISO_8859_1_A4 KEY_RIGHT_BRACE + ALTGR_MASK // 164 ¤ Currency or Euro Sign +#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR +#define ISO_8859_1_A7 KEY_SLASH + SHIFT_MASK // 167 § SECTION SIGN +#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN +#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN +#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF 0 // 175 ¯ MACRON +#define ISO_8859_1_B0 KEY_MINUS + SHIFT_MASK // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 KEY_TILDE // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 0 // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 KEY_BACKSLASH + SHIFT_MASK // 181 µ MICRO SIGN +#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT +#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA +#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_Q + SHIFT_MASK // 192 À A GRAVE +#define ISO_8859_1_C1 0 // 193 Á A ACUTE +#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_Q + SHIFT_MASK // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 TILDE_BITS + KEY_Q + SHIFT_MASK // 195 Ã A TILDE +#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_Q + SHIFT_MASK // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE +#define ISO_8859_1_C6 0 // 198 Æ AE +#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA +#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE +#define ISO_8859_1_C9 0 // 201 É E ACUTE +#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS +#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE +#define ISO_8859_1_CD 0 // 205 Í I ACUTE +#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 0 // 208 Ð ETH +#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE +#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE +#define ISO_8859_1_D3 0 // 211 Ó O ACUTE +#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE +#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION +#define ISO_8859_1_D8 0 // 216 Ø O STROKE +#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE +#define ISO_8859_1_DA 0 // 218 Ú U ACUTE +#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U // 220 Ü U DIAERESIS +#define ISO_8859_1_DD 0 // 221 Ý Y ACUTE +#define ISO_8859_1_DE 0 // 222 Þ THORN +#define ISO_8859_1_DF 0 // 223 ß SHARP S +#define ISO_8859_1_E0 KEY_0 // 224 à a GRAVE +#define ISO_8859_1_E1 0 // 225 á a ACUTE +#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_Q // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 TILDE_BITS + KEY_Q // 227 ã a TILDE +#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_Q // 228 ä a DIAERESIS +#define ISO_8859_1_E5 0 // 229 å a RING ABOVE +#define ISO_8859_1_E6 0 // 230 æ ae +#define ISO_8859_1_E7 KEY_9 // 231 ç c CEDILLA +#define ISO_8859_1_E8 KEY_7 // 232 è e GRAVE +#define ISO_8859_1_E9 KEY_2 // 233 é e ACUTE +#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS +#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE +#define ISO_8859_1_ED 0 // 237 í i ACUTE +#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS +#define ISO_8859_1_F0 0 // 240 ð ETH +#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE +#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE +#define ISO_8859_1_F3 0 // 243 ó o ACUTE +#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE +#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS +#define ISO_8859_1_F7 0 // 247 ÷ DIVISION +#define ISO_8859_1_F8 0 // 248 ø o STROKE +#define ISO_8859_1_F9 KEY_SEMICOLON // 249 ù u GRAVE +#define ISO_8859_1_FA 0 // 250 ú u ACUTE +#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS +#define ISO_8859_1_FD 0 // 253 ý y ACUTE +#define ISO_8859_1_FE 0 // 254 þ THORN +#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS +#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign +// not yet implemented +#define UNICODE_EXTRA00 0x20AC +#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign + +#endif // LAYOUT_FRENCH + + + + + +#ifdef LAYOUT_DANISH + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define DEADKEYS_MASK 0x0700 +#define CIRCUMFLEX_BITS 0x0100 +#define ACUTE_ACCENT_BITS 0x0200 +#define GRAVE_ACCENT_BITS 0x0300 +#define TILDE_BITS 0x0400 +#define DIAERESIS_BITS 0x0500 +#define KEYCODE_TYPE uint16_t +#define DEADKEY_CIRCUMFLEX KEY_RIGHT_BRACE + SHIFT_MASK +#define DEADKEY_ACUTE_ACCENT KEY_EQUAL +#define DEADKEY_GRAVE_ACCENT KEY_EQUAL + SHIFT_MASK +#define DEADKEY_TILDE KEY_RIGHT_BRACE + ALTGR_MASK +#define DEADKEY_DIAERESIS KEY_RIGHT_BRACE +#define KEY_NON_US_100 63 + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! +#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " +#define ASCII_23 KEY_3 + SHIFT_MASK // 35 # +#define ASCII_24 KEY_4 + ALTGR_MASK // 36 $ +#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % +#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & +#define ASCII_27 KEY_BACKSLASH // 39 ' +#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) +#define ASCII_2A KEY_BACKSLASH + SHIFT_MASK // 42 * +#define ASCII_2B KEY_MINUS // 43 + +#define ASCII_2C KEY_COMMA // 44 , +#define ASCII_2D KEY_SLASH // 45 - +#define ASCII_2E KEY_PERIOD // 46 . +#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / +#define ASCII_30 KEY_0 // 48 0 +#define ASCII_31 KEY_1 // 49 1 +#define ASCII_32 KEY_2 // 50 2 +#define ASCII_33 KEY_3 // 51 3 +#define ASCII_34 KEY_4 // 52 4 +#define ASCII_35 KEY_5 // 53 5 +#define ASCII_36 KEY_6 // 54 6 +#define ASCII_37 KEY_7 // 55 7 +#define ASCII_38 KEY_8 // 55 8 +#define ASCII_39 KEY_9 // 57 9 +#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : +#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; +#define ASCII_3C KEY_NON_US_100 // 60 < +#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = +#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > +#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_2 + ALTGR_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_8 + ALTGR_MASK // 91 [ +#define ASCII_5C KEY_NON_US_100 + ALTGR_MASK // 92 +#define ASCII_5D KEY_9 + ALTGR_MASK // 93 ] +#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ +#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ +#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Y // 121 y +#define ASCII_7A KEY_Z // 122 z +#define ASCII_7B KEY_7 + ALTGR_MASK // 123 { +#define ASCII_7C KEY_EQUAL + ALTGR_MASK // 124 | +#define ASCII_7D KEY_0 + ALTGR_MASK // 125 } +#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 + +#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space +#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN +#define ISO_8859_1_A3 KEY_3 + ALTGR_MASK // 163 £ Pound Sign +#define ISO_8859_1_A4 KEY_4 + SHIFT_MASK // 164 ¤ Currency Sign +#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR +#define ISO_8859_1_A7 KEY_TILDE + SHIFT_MASK // 167 § SECTION SIGN +#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB KEY_4 // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN +#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN +#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF 0 // 175 ¯ MACRON +#define ISO_8859_1_B0 0 // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 KEY_M + ALTGR_MASK // 181 µ MICRO SIGN +#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT +#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA +#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD KEY_TILDE // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE +#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE +#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE +#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 KEY_LEFT_BRACE + SHIFT_MASK // 197 Å A RING ABOVE +#define ISO_8859_1_C6 KEY_SEMICOLON + SHIFT_MASK // 198 Æ AE +#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA +#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE +#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE +#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS +#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE +#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE +#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 KEY_D + ALTGR_MASK + SHIFT_MASK // 208 Ð ETH +#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE +#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE +#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE +#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE +#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION +#define ISO_8859_1_D8 KEY_QUOTE + SHIFT_MASK // 216 Ø O STROKE +#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE +#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE +#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS +#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE +#define ISO_8859_1_DE KEY_T + ALTGR_MASK + SHIFT_MASK // 222 Þ THORN +#define ISO_8859_1_DF KEY_S + ALTGR_MASK // 223 ß SHARP S +#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE +#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE +#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE +#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS +#define ISO_8859_1_E5 KEY_LEFT_BRACE // 229 å a RING ABOVE +#define ISO_8859_1_E6 KEY_SEMICOLON // 230 æ ae +#define ISO_8859_1_E7 0 // 231 ç c CEDILLA +#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE +#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE +#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS +#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE +#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE +#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS +#define ISO_8859_1_F0 KEY_D + ALTGR_MASK // 240 ð ETH +#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE +#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE +#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE +#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE +#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS +#define ISO_8859_1_F7 0 // 247 ÷ DIVISION +#define ISO_8859_1_F8 KEY_QUOTE // 248 ø o STROKE +#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE +#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE +#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS +#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE +#define ISO_8859_1_FE KEY_T + ALTGR_MASK // 254 þ THORN +#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS +#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign +// not yet implemented +#define UNICODE_EXTRA00 0x20AC +#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign + +#endif // LAYOUT_DANISH + + + + + +#ifdef LAYOUT_NORWEGIAN + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define DEADKEYS_MASK 0x0700 +#define CIRCUMFLEX_BITS 0x0100 +#define ACUTE_ACCENT_BITS 0x0200 +#define GRAVE_ACCENT_BITS 0x0300 +#define TILDE_BITS 0x0400 +#define DIAERESIS_BITS 0x0500 +#define KEYCODE_TYPE uint16_t +#define DEADKEY_CIRCUMFLEX KEY_RIGHT_BRACE + SHIFT_MASK +#define DEADKEY_ACUTE_ACCENT KEY_EQUAL + ALTGR_MASK +#define DEADKEY_GRAVE_ACCENT KEY_EQUAL + SHIFT_MASK +#define DEADKEY_TILDE KEY_RIGHT_BRACE + ALTGR_MASK +#define DEADKEY_DIAERESIS KEY_RIGHT_BRACE +#define KEY_NON_US_100 63 + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! +#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " +#define ASCII_23 KEY_3 + SHIFT_MASK // 35 # +#define ASCII_24 KEY_4 + ALTGR_MASK // 36 $ +#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % +#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & +#define ASCII_27 KEY_BACKSLASH // 39 ' +#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) +#define ASCII_2A KEY_BACKSLASH + SHIFT_MASK // 42 * +#define ASCII_2B KEY_MINUS // 43 + +#define ASCII_2C KEY_COMMA // 44 , +#define ASCII_2D KEY_SLASH // 45 - +#define ASCII_2E KEY_PERIOD // 46 . +#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / +#define ASCII_30 KEY_0 // 48 0 +#define ASCII_31 KEY_1 // 49 1 +#define ASCII_32 KEY_2 // 50 2 +#define ASCII_33 KEY_3 // 51 3 +#define ASCII_34 KEY_4 // 52 4 +#define ASCII_35 KEY_5 // 53 5 +#define ASCII_36 KEY_6 // 54 6 +#define ASCII_37 KEY_7 // 55 7 +#define ASCII_38 KEY_8 // 55 8 +#define ASCII_39 KEY_9 // 57 9 +#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : +#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; +#define ASCII_3C KEY_NON_US_100 // 60 < +#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = +#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > +#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_2 + ALTGR_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_8 + ALTGR_MASK // 91 [ +#define ASCII_5C KEY_EQUAL // 92 +#define ASCII_5D KEY_9 + ALTGR_MASK // 93 ] +#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ +#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ +#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Y // 121 y +#define ASCII_7A KEY_Z // 122 z +#define ASCII_7B KEY_7 + ALTGR_MASK // 123 { +#define ASCII_7C KEY_TILDE // 124 | +#define ASCII_7D KEY_0 + ALTGR_MASK // 125 } +#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 + +#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space +#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN +#define ISO_8859_1_A3 KEY_3 + ALTGR_MASK // 163 £ Pound Sign +#define ISO_8859_1_A4 KEY_4 + SHIFT_MASK // 164 ¤ Currency Sign +#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR +#define ISO_8859_1_A7 KEY_TILDE + SHIFT_MASK // 167 § SECTION SIGN +#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB KEY_4 // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN +#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN +#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF 0 // 175 ¯ MACRON +#define ISO_8859_1_B0 0 // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 KEY_M + ALTGR_MASK // 181 µ MICRO SIGN +#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT +#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA +#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD KEY_TILDE // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE +#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE +#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE +#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 KEY_LEFT_BRACE + SHIFT_MASK // 197 Å A RING ABOVE +#define ISO_8859_1_C6 KEY_QUOTE + SHIFT_MASK // 198 Æ AE +#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA +#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE +#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE +#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS +#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE +#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE +#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 KEY_D + ALTGR_MASK + SHIFT_MASK // 208 Ð ETH +#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE +#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE +#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE +#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE +#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION +#define ISO_8859_1_D8 KEY_SEMICOLON + SHIFT_MASK // 216 Ø O STROKE +#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE +#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE +#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS +#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE +#define ISO_8859_1_DE KEY_T + ALTGR_MASK + SHIFT_MASK // 222 Þ THORN +#define ISO_8859_1_DF KEY_S + ALTGR_MASK // 223 ß SHARP S +#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE +#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE +#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE +#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS +#define ISO_8859_1_E5 KEY_LEFT_BRACE // 229 å a RING ABOVE +#define ISO_8859_1_E6 KEY_QUOTE // 230 æ ae +#define ISO_8859_1_E7 0 // 231 ç c CEDILLA +#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE +#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE +#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS +#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE +#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE +#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS +#define ISO_8859_1_F0 KEY_D + ALTGR_MASK // 240 ð ETH +#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE +#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE +#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE +#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE +#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS +#define ISO_8859_1_F7 0 // 247 ÷ DIVISION +#define ISO_8859_1_F8 KEY_SEMICOLON // 248 ø o STROKE +#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE +#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE +#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS +#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE +#define ISO_8859_1_FE KEY_T + ALTGR_MASK // 254 þ THORN +#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS +#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign +// not yet implemented +#define UNICODE_EXTRA00 0x20AC +#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign + +#endif // LAYOUT_NORWEGIAN + + + + + + +#ifdef LAYOUT_SWEDISH + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define DEADKEYS_MASK 0x0700 +#define CIRCUMFLEX_BITS 0x0100 +#define ACUTE_ACCENT_BITS 0x0200 +#define GRAVE_ACCENT_BITS 0x0300 +#define TILDE_BITS 0x0400 +#define DIAERESIS_BITS 0x0500 +#define KEYCODE_TYPE uint16_t +#define DEADKEY_CIRCUMFLEX KEY_RIGHT_BRACE + SHIFT_MASK +#define DEADKEY_ACUTE_ACCENT KEY_EQUAL +#define DEADKEY_GRAVE_ACCENT KEY_EQUAL + SHIFT_MASK +#define DEADKEY_TILDE KEY_RIGHT_BRACE + ALTGR_MASK +#define DEADKEY_DIAERESIS KEY_RIGHT_BRACE +#define KEY_NON_US_100 63 + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! +#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " +#define ASCII_23 KEY_3 + SHIFT_MASK // 35 # +#define ASCII_24 KEY_4 + ALTGR_MASK // 36 $ +#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % +#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & +#define ASCII_27 KEY_BACKSLASH // 39 ' +#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) +#define ASCII_2A KEY_BACKSLASH + SHIFT_MASK // 42 * +#define ASCII_2B KEY_MINUS // 43 + +#define ASCII_2C KEY_COMMA // 44 , +#define ASCII_2D KEY_SLASH // 45 - +#define ASCII_2E KEY_PERIOD // 46 . +#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / +#define ASCII_30 KEY_0 // 48 0 +#define ASCII_31 KEY_1 // 49 1 +#define ASCII_32 KEY_2 // 50 2 +#define ASCII_33 KEY_3 // 51 3 +#define ASCII_34 KEY_4 // 52 4 +#define ASCII_35 KEY_5 // 53 5 +#define ASCII_36 KEY_6 // 54 6 +#define ASCII_37 KEY_7 // 55 7 +#define ASCII_38 KEY_8 // 55 8 +#define ASCII_39 KEY_9 // 57 9 +#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : +#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; +#define ASCII_3C KEY_NON_US_100 // 60 < +#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = +#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > +#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_2 + ALTGR_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_8 + ALTGR_MASK // 91 [ +#define ASCII_5C KEY_MINUS + ALTGR_MASK // 92 +#define ASCII_5D KEY_9 + ALTGR_MASK // 93 ] +#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ +#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ +#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Y // 121 y +#define ASCII_7A KEY_Z // 122 z +#define ASCII_7B KEY_7 + ALTGR_MASK // 123 { +#define ASCII_7C KEY_NON_US_100 + ALTGR_MASK // 124 | +#define ASCII_7D KEY_0 + ALTGR_MASK // 125 } +#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 + +#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space +#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN +#define ISO_8859_1_A3 KEY_3 + ALTGR_MASK // 163 £ Pound Sign +#define ISO_8859_1_A4 KEY_4 + SHIFT_MASK // 164 ¤ Currency Sign +#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR +#define ISO_8859_1_A7 KEY_TILDE // 167 § SECTION SIGN +#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB KEY_4 // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN +#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN +#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF 0 // 175 ¯ MACRON +#define ISO_8859_1_B0 0 // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 KEY_M + ALTGR_MASK // 181 µ MICRO SIGN +#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT +#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA +#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD KEY_TILDE + SHIFT_MASK // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE +#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE +#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE +#define ISO_8859_1_C4 KEY_QUOTE + SHIFT_MASK // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 KEY_LEFT_BRACE + SHIFT_MASK // 197 Å A RING ABOVE +#define ISO_8859_1_C6 0 // 198 Æ AE +#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA +#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE +#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE +#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS +#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE +#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE +#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 KEY_D + ALTGR_MASK + SHIFT_MASK // 208 Ð ETH +#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE +#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE +#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE +#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE +#define ISO_8859_1_D6 KEY_SEMICOLON + SHIFT_MASK // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION +#define ISO_8859_1_D8 0 // 216 Ø O STROKE +#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE +#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE +#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS +#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE +#define ISO_8859_1_DE KEY_T + ALTGR_MASK + SHIFT_MASK // 222 Þ THORN +#define ISO_8859_1_DF KEY_S + ALTGR_MASK // 223 ß SHARP S +#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE +#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE +#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE +#define ISO_8859_1_E4 KEY_QUOTE // 228 ä a DIAERESIS +#define ISO_8859_1_E5 KEY_LEFT_BRACE // 229 å a RING ABOVE +#define ISO_8859_1_E6 0 // 230 æ ae +#define ISO_8859_1_E7 0 // 231 ç c CEDILLA +#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE +#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE +#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS +#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE +#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE +#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS +#define ISO_8859_1_F0 KEY_D + ALTGR_MASK // 240 ð ETH +#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE +#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE +#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE +#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE +#define ISO_8859_1_F6 KEY_SEMICOLON // 246 ö o DIAERESIS +#define ISO_8859_1_F7 0 // 247 ÷ DIVISION +#define ISO_8859_1_F8 0 // 248 ø o STROKE +#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE +#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE +#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS +#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE +#define ISO_8859_1_FE KEY_T + ALTGR_MASK // 254 þ THORN +#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS +#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign +// not yet implemented +#define UNICODE_EXTRA00 0x20AC +#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign + +#endif // LAYOUT_SWEDISH + + + + + + +#ifdef LAYOUT_SPANISH + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define DEADKEYS_MASK 0x0700 +#define CIRCUMFLEX_BITS 0x0100 +#define ACUTE_ACCENT_BITS 0x0200 +#define GRAVE_ACCENT_BITS 0x0300 +#define TILDE_BITS 0x0400 +#define DIAERESIS_BITS 0x0500 +#define KEYCODE_TYPE uint16_t +#define DEADKEY_CIRCUMFLEX KEY_LEFT_BRACE + SHIFT_MASK +#define DEADKEY_ACUTE_ACCENT KEY_QUOTE +#define DEADKEY_GRAVE_ACCENT KEY_LEFT_BRACE +#define DEADKEY_TILDE KEY_4 + ALTGR_MASK +#define DEADKEY_DIAERESIS KEY_QUOTE + SHIFT_MASK +#define KEY_NON_US_100 63 + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! +#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " +#define ASCII_23 KEY_3 + ALTGR_MASK // 35 # +#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ +#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % +#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & +#define ASCII_27 KEY_MINUS // 39 ' +#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) +#define ASCII_2A KEY_RIGHT_BRACE + SHIFT_MASK // 42 * +#define ASCII_2B KEY_RIGHT_BRACE // 43 + +#define ASCII_2C KEY_COMMA // 44 , +#define ASCII_2D KEY_SLASH // 45 - +#define ASCII_2E KEY_PERIOD // 46 . +#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / +#define ASCII_30 KEY_0 // 48 0 +#define ASCII_31 KEY_1 // 49 1 +#define ASCII_32 KEY_2 // 50 2 +#define ASCII_33 KEY_3 // 51 3 +#define ASCII_34 KEY_4 // 52 4 +#define ASCII_35 KEY_5 // 53 5 +#define ASCII_36 KEY_6 // 54 6 +#define ASCII_37 KEY_7 // 55 7 +#define ASCII_38 KEY_8 // 55 8 +#define ASCII_39 KEY_9 // 57 9 +#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : +#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; +#define ASCII_3C KEY_NON_US_100 // 60 < +#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = +#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > +#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_2 + ALTGR_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_LEFT_BRACE + ALTGR_MASK // 91 [ +#define ASCII_5C KEY_TILDE + ALTGR_MASK // 92 +#define ASCII_5D KEY_RIGHT_BRACE + ALTGR_MASK // 93 ] +#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ +#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ +#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Y // 121 y +#define ASCII_7A KEY_Z // 122 z +#define ASCII_7B KEY_QUOTE + ALTGR_MASK // 123 { +#define ASCII_7C KEY_1 + ALTGR_MASK // 124 | +#define ASCII_7D KEY_BACKSLASH + ALTGR_MASK // 125 } +#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 + +#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space +#define ISO_8859_1_A1 KEY_EQUAL // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN +#define ISO_8859_1_A3 0 // 163 £ Pound Sign +#define ISO_8859_1_A4 0 // 164 ¤ Currency Sign +#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR +#define ISO_8859_1_A7 0 // 167 § SECTION SIGN +#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA KEY_TILDE + SHIFT_MASK // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC KEY_6 + ALTGR_MASK // 172 ¬ NOT SIGN +#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN +#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF 0 // 175 ¯ MACRON +#define ISO_8859_1_B0 0 // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN +#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 KEY_3 + SHIFT_MASK // 183 · MIDDLE DOT +#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA +#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA KEY_TILDE // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF KEY_EQUAL // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE +#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE +#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE +#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE +#define ISO_8859_1_C6 0 // 198 Æ AE +#define ISO_8859_1_C7 KEY_BACKSLASH + SHIFT_MASK // 199 Ç C CEDILLA +#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE +#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE +#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS +#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE +#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE +#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 0 // 208 Ð ETH +#define ISO_8859_1_D1 KEY_SEMICOLON + SHIFT_MASK // 209 Ñ N TILDE +#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE +#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE +#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE +#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION +#define ISO_8859_1_D8 0 // 216 Ø O STROKE +#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE +#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE +#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS +#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE +#define ISO_8859_1_DE 0 // 222 Þ THORN +#define ISO_8859_1_DF 0 // 223 ß SHARP S +#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE +#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE +#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE +#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS +#define ISO_8859_1_E5 0 // 229 å a RING ABOVE +#define ISO_8859_1_E6 0 // 230 æ ae +#define ISO_8859_1_E7 KEY_BACKSLASH // 231 ç c CEDILLA +#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE +#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE +#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS +#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE +#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE +#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS +#define ISO_8859_1_F0 0 // 240 ð ETH +#define ISO_8859_1_F1 KEY_SEMICOLON // 241 ñ n TILDE +#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE +#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE +#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE +#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS +#define ISO_8859_1_F7 0 // 247 ÷ DIVISION +#define ISO_8859_1_F8 0 // 248 ø o STROKE +#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE +#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE +#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS +#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE +#define ISO_8859_1_FE 0 // 254 þ THORN +#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS +#define UNICODE_20AC KEY_5 + ALTGR_MASK // € Euro Sign +// not yet implemented +#define UNICODE_EXTRA00 0x20AC +#define KEYCODE_EXTRA00 KEY_5 + ALTGR_MASK // 20AC € Euro Sign + +#endif // LAYOUT_SPANISH + + + + +#ifdef LAYOUT_PORTUGUESE + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define DEADKEYS_MASK 0x0700 +#define CIRCUMFLEX_BITS 0x0100 +#define ACUTE_ACCENT_BITS 0x0200 +#define GRAVE_ACCENT_BITS 0x0300 +#define TILDE_BITS 0x0400 +#define DIAERESIS_BITS 0x0500 +#define KEYCODE_TYPE uint16_t +#define DEADKEY_CIRCUMFLEX KEY_BACKSLASH +#define DEADKEY_ACUTE_ACCENT KEY_RIGHT_BRACE + SHIFT_MASK +#define DEADKEY_GRAVE_ACCENT KEY_RIGHT_BRACE + SHIFT_MASK +#define DEADKEY_TILDE KEY_BACKSLASH +#define DEADKEY_DIAERESIS KEY_LEFT_BRACE + SHIFT_MASK +#define KEY_NON_US_100 63 + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! +#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " +#define ASCII_23 KEY_3 + ALTGR_MASK // 35 # +#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ +#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % +#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & +#define ASCII_27 KEY_MINUS // 39 ' +#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) +#define ASCII_2A KEY_LEFT_BRACE + SHIFT_MASK // 42 * +#define ASCII_2B KEY_LEFT_BRACE // 43 + +#define ASCII_2C KEY_COMMA // 44 , +#define ASCII_2D KEY_SLASH // 45 - +#define ASCII_2E KEY_PERIOD // 46 . +#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / +#define ASCII_30 KEY_0 // 48 0 +#define ASCII_31 KEY_1 // 49 1 +#define ASCII_32 KEY_2 // 50 2 +#define ASCII_33 KEY_3 // 51 3 +#define ASCII_34 KEY_4 // 52 4 +#define ASCII_35 KEY_5 // 53 5 +#define ASCII_36 KEY_6 // 54 6 +#define ASCII_37 KEY_7 // 55 7 +#define ASCII_38 KEY_8 // 55 8 +#define ASCII_39 KEY_9 // 57 9 +#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : +#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; +#define ASCII_3C KEY_NON_US_100 // 60 < +#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = +#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > +#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_2 + ALTGR_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_8 + ALTGR_MASK // 91 [ +#define ASCII_5C KEY_TILDE + ALTGR_MASK // 92 +#define ASCII_5D KEY_9 + ALTGR_MASK // 93 ] +#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ +#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ +#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Y // 121 y +#define ASCII_7A KEY_Z // 122 z +#define ASCII_7B KEY_7 + ALTGR_MASK // 123 { +#define ASCII_7C KEY_TILDE + SHIFT_MASK // 124 | +#define ASCII_7D KEY_0 + ALTGR_MASK // 125 } +#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 + +#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space +#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN +#define ISO_8859_1_A3 KEY_3 + ALTGR_MASK // 163 £ Pound Sign +#define ISO_8859_1_A4 0 // 164 ¤ Currency Sign +#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR +#define ISO_8859_1_A7 KEY_4 + ALTGR_MASK // 167 § SECTION SIGN +#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA KEY_QUOTE + SHIFT_MASK // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB KEY_EQUAL // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN +#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN +#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF 0 // 175 ¯ MACRON +#define ISO_8859_1_B0 0 // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN +#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT +#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA +#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA KEY_QUOTE // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB KEY_EQUAL + SHIFT_MASK // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE +#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE +#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE +#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE +#define ISO_8859_1_C6 0 // 198 Æ AE +#define ISO_8859_1_C7 KEY_SEMICOLON + SHIFT_MASK // 199 Ç C CEDILLA +#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE +#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE +#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS +#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE +#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE +#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 0 // 208 Ð ETH +#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE +#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE +#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE +#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE +#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION +#define ISO_8859_1_D8 0 // 216 Ø O STROKE +#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE +#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE +#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS +#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE +#define ISO_8859_1_DE 0 // 222 Þ THORN +#define ISO_8859_1_DF 0 // 223 ß SHARP S +#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE +#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE +#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE +#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS +#define ISO_8859_1_E5 0 // 229 å a RING ABOVE +#define ISO_8859_1_E6 0 // 230 æ ae +#define ISO_8859_1_E7 KEY_SEMICOLON // 231 ç c CEDILLA +#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE +#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE +#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS +#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE +#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE +#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS +#define ISO_8859_1_F0 0 // 240 ð ETH +#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE +#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE +#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE +#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE +#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS +#define ISO_8859_1_F7 0 // 247 ÷ DIVISION +#define ISO_8859_1_F8 0 // 248 ø o STROKE +#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE +#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE +#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS +#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE +#define ISO_8859_1_FE 0 // 254 þ THORN +#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS +#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign +// not yet implemented +#define UNICODE_EXTRA00 0x20AC +#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign + +#endif // LAYOUT_PORTUGUESE + + + + + + + +#ifdef LAYOUT_ITALIAN + +#define SHIFT_MASK 0x40 +#define ALTGR_MASK 0x80 +#define KEYCODE_TYPE uint8_t +#define KEY_NON_US_100 63 + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! +#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " +#define ASCII_23 KEY_QUOTE + ALTGR_MASK // 35 # +#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ +#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % +#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & +#define ASCII_27 KEY_MINUS // 39 ' +#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) +#define ASCII_2A KEY_RIGHT_BRACE + SHIFT_MASK // 42 * +#define ASCII_2B KEY_RIGHT_BRACE // 43 + +#define ASCII_2C KEY_COMMA // 44 , +#define ASCII_2D KEY_SLASH // 45 - +#define ASCII_2E KEY_PERIOD // 46 . +#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / +#define ASCII_30 KEY_0 // 48 0 +#define ASCII_31 KEY_1 // 49 1 +#define ASCII_32 KEY_2 // 50 2 +#define ASCII_33 KEY_3 // 51 3 +#define ASCII_34 KEY_4 // 52 4 +#define ASCII_35 KEY_5 // 53 5 +#define ASCII_36 KEY_6 // 54 6 +#define ASCII_37 KEY_7 // 55 7 +#define ASCII_38 KEY_8 // 55 8 +#define ASCII_39 KEY_9 // 57 9 +#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : +#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; +#define ASCII_3C KEY_NON_US_100 // 60 < +#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = +#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > +#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_SEMICOLON + ALTGR_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_LEFT_BRACE + ALTGR_MASK // 91 [ +#define ASCII_5C KEY_TILDE // 92 +#define ASCII_5D KEY_RIGHT_BRACE + ALTGR_MASK // 93 ] +#define ASCII_5E KEY_EQUAL + SHIFT_MASK // 94 ^ +#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ +#define ASCII_60 0 // 96 ` (how to type this on Italian?) +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Y // 121 y +#define ASCII_7A KEY_Z // 122 z +#define ASCII_7B KEY_LEFT_BRACE + SHIFT_MASK + ALTGR_MASK // 123 { +#define ASCII_7C KEY_TILDE + SHIFT_MASK // 124 | +#define ASCII_7D KEY_RIGHT_BRACE + SHIFT_MASK + ALTGR_MASK // 125 } +#define ASCII_7E 0 // 126 ~ (how to type this on Italian?) +#define ASCII_7F KEY_BACKSPACE // 127 + +#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space +#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 0 // 162 ¢ Cent Sign +#define ISO_8859_1_A3 KEY_3 + SHIFT_MASK // 163 £ Pound Sign +#define ISO_8859_1_A4 0 // 164 ¤ Currency Sign +#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR +#define ISO_8859_1_A7 KEY_BACKSLASH + SHIFT_MASK // 167 § SECTION SIGN +#define ISO_8859_1_A8 0 // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN +#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN +#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF 0 // 175 ¯ MACRON +#define ISO_8859_1_B0 KEY_QUOTE + SHIFT_MASK // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 0 // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN +#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT +#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA +#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 0 // 192 À A GRAVE +#define ISO_8859_1_C1 0 // 193 Á A ACUTE +#define ISO_8859_1_C2 0 // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 0 // 195 Ã A TILDE +#define ISO_8859_1_C4 0 // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE +#define ISO_8859_1_C6 0 // 198 Æ AE +#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA +#define ISO_8859_1_C8 0 // 200 È E GRAVE +#define ISO_8859_1_C9 0 // 201 É E ACUTE +#define ISO_8859_1_CA 0 // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB 0 // 203 Ë E DIAERESIS +#define ISO_8859_1_CC 0 // 204 Ì I GRAVE +#define ISO_8859_1_CD 0 // 205 Í I ACUTE +#define ISO_8859_1_CE 0 // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF 0 // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 0 // 208 Ð ETH +#define ISO_8859_1_D1 0 // 209 Ñ N TILDE +#define ISO_8859_1_D2 0 // 210 Ò O GRAVE +#define ISO_8859_1_D3 0 // 211 Ó O ACUTE +#define ISO_8859_1_D4 0 // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 0 // 213 Õ O TILDE +#define ISO_8859_1_D6 0 // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION +#define ISO_8859_1_D8 0 // 216 Ø O STROKE +#define ISO_8859_1_D9 0 // 217 Ù U GRAVE +#define ISO_8859_1_DA 0 // 218 Ú U ACUTE +#define ISO_8859_1_DB 0 // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC 0 // 220 Ü U DIAERESIS +#define ISO_8859_1_DD 0 // 221 Ý Y ACUTE +#define ISO_8859_1_DE 0 // 222 Þ THORN +#define ISO_8859_1_DF 0 // 223 ß SHARP S +#define ISO_8859_1_E0 KEY_QUOTE // 224 à a GRAVE +#define ISO_8859_1_E1 0 // 225 á a ACUTE +#define ISO_8859_1_E2 0 // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 0 // 227 ã a TILDE +#define ISO_8859_1_E4 0 // 228 ä a DIAERESIS +#define ISO_8859_1_E5 0 // 229 å a RING ABOVE +#define ISO_8859_1_E6 0 // 230 æ ae +#define ISO_8859_1_E7 KEY_SEMICOLON + SHIFT_MASK // 231 ç c CEDILLA +#define ISO_8859_1_E8 KEY_LEFT_BRACE // 232 è e GRAVE +#define ISO_8859_1_E9 KEY_LEFT_BRACE + SHIFT_MASK // 233 é e ACUTE +#define ISO_8859_1_EA 0 // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB 0 // 235 ë e DIAERESIS +#define ISO_8859_1_EC KEY_EQUAL // 236 ì i GRAVE +#define ISO_8859_1_ED 0 // 237 í i ACUTE +#define ISO_8859_1_EE 0 // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF 0 // 239 ï i DIAERESIS +#define ISO_8859_1_F0 0 // 240 ð ETH +#define ISO_8859_1_F1 0 // 241 ñ n TILDE +#define ISO_8859_1_F2 KEY_SEMICOLON // 242 ò o GRAVE +#define ISO_8859_1_F3 0 // 243 ó o ACUTE +#define ISO_8859_1_F4 0 // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 0 // 245 õ o TILDE +#define ISO_8859_1_F6 0 // 246 ö o DIAERESIS +#define ISO_8859_1_F7 0 // 247 ÷ DIVISION +#define ISO_8859_1_F8 0 // 248 ø o STROKE +#define ISO_8859_1_F9 KEY_BACKSLASH // 249 ù u GRAVE +#define ISO_8859_1_FA 0 // 250 ú u ACUTE +#define ISO_8859_1_FB 0 // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC 0 // 252 ü u DIAERESIS +#define ISO_8859_1_FD 0 // 253 ý y ACUTE +#define ISO_8859_1_FE 0 // 254 þ THORN +#define ISO_8859_1_FF 0 // 255 ÿ y DIAERESIS + +#endif // LAYOUT_ITALIAN + + + + +#ifdef LAYOUT_PORTUGUESE_BRAZILIAN + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define DEADKEYS_MASK 0x0700 +#define CIRCUMFLEX_BITS 0x0100 +#define ACUTE_ACCENT_BITS 0x0200 +#define GRAVE_ACCENT_BITS 0x0300 +#define TILDE_BITS 0x0400 +#define DIAERESIS_BITS 0x0500 +#define KEYCODE_TYPE uint16_t +#define DEADKEY_CIRCUMFLEX KEY_QUOTE + SHIFT_MASK +#define DEADKEY_ACUTE_ACCENT KEY_LEFT_BRACE +#define DEADKEY_GRAVE_ACCENT KEY_LEFT_BRACE + SHIFT_MASK +#define DEADKEY_TILDE KEY_QUOTE +#define DEADKEY_DIAERESIS KEY_6 + SHIFT_MASK +#define KEY_NON_US_100 63 + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! +#define ASCII_22 KEY_TILDE + SHIFT_MASK // 34 " +#define ASCII_23 KEY_3 + ALTGR_MASK // 35 # +#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ +#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % +#define ASCII_26 KEY_7 + SHIFT_MASK // 38 & +#define ASCII_27 KEY_TILDE // 39 ' +#define ASCII_28 KEY_9 + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_0 + SHIFT_MASK // 41 ) +#define ASCII_2A KEY_7 + SHIFT_MASK // 42 * +#define ASCII_2B KEY_EQUAL + SHIFT_MASK // 43 + +#define ASCII_2C KEY_COMMA // 44 , +#define ASCII_2D KEY_MINUS // 45 - +#define ASCII_2E KEY_PERIOD // 46 . +#define ASCII_2F KEY_Q + ALTGR_MASK // 47 / +#define ASCII_30 KEY_0 // 48 0 +#define ASCII_31 KEY_1 // 49 1 +#define ASCII_32 KEY_2 // 50 2 +#define ASCII_33 KEY_3 // 51 3 +#define ASCII_34 KEY_4 // 52 4 +#define ASCII_35 KEY_5 // 53 5 +#define ASCII_36 KEY_6 // 54 6 +#define ASCII_37 KEY_7 // 55 7 +#define ASCII_38 KEY_8 // 55 8 +#define ASCII_39 KEY_9 // 57 9 +#define ASCII_3A KEY_SLASH + SHIFT_MASK // 58 : +#define ASCII_3B KEY_SLASH // 59 ; +#define ASCII_3C KEY_COMMA + SHIFT_MASK // 60 < +#define ASCII_3D KEY_EQUAL // 61 = +#define ASCII_3E KEY_PERIOD + SHIFT_MASK // 62 > +#define ASCII_3F KEY_W + ALTGR_MASK // 63 ? +#define ASCII_40 KEY_2 + SHIFT_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_RIGHT_BRACE // 91 [ +#define ASCII_5C KEY_NON_US_100 // 92 +#define ASCII_5D KEY_BACKSLASH // 93 ] +#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ +#define ASCII_5F KEY_MINUS + SHIFT_MASK // 95 _ +#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Y // 121 y +#define ASCII_7A KEY_Z // 122 z +#define ASCII_7B KEY_RIGHT_BRACE + SHIFT_MASK // 123 { +#define ASCII_7C KEY_NON_US_100 + SHIFT_MASK // 124 | +#define ASCII_7D KEY_BACKSLASH + SHIFT_MASK // 125 } +#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 + +#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space +#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 KEY_5 + ALTGR_MASK // 162 ¢ Cent SIGN +#define ISO_8859_1_A3 KEY_4 + ALTGR_MASK // 163 £ Pound Sign +#define ISO_8859_1_A4 0 // 164 ¤ Currency Sign +#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR +#define ISO_8859_1_A7 KEY_EQUAL + ALTGR_MASK // 167 § SECTION SIGN +#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA KEY_RIGHT_BRACE + ALTGR_MASK // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC KEY_6 + ALTGR_MASK // 172 ¬ NOT SIGN +#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN +#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF 0 // 175 ¯ MACRON +#define ISO_8859_1_B0 KEY_E + ALTGR_MASK // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 KEY_2 + ALTGR_MASK // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 KEY_2 + ALTGR_MASK // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN +#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT +#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA +#define ISO_8859_1_B9 KEY_1 + ALTGR_MASK // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA KEY_BACKSLASH + ALTGR_MASK // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE +#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE +#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE +#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE +#define ISO_8859_1_C6 0 // 198 Æ AE +#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA +#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE +#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE +#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS +#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE +#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE +#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 0 // 208 Ð ETH +#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE +#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE +#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE +#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE +#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION +#define ISO_8859_1_D8 0 // 216 Ø O STROKE +#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE +#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE +#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS +#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE +#define ISO_8859_1_DE 0 // 222 Þ THORN +#define ISO_8859_1_DF 0 // 223 ß SHARP S +#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE +#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE +#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE +#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS +#define ISO_8859_1_E5 0 // 229 å a RING ABOVE +#define ISO_8859_1_E6 0 // 230 æ ae +#define ISO_8859_1_E7 0 // 231 ç c CEDILLA +#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE +#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE +#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS +#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE +#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE +#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS +#define ISO_8859_1_F0 0 // 240 ð ETH +#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE +#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE +#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE +#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE +#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS +#define ISO_8859_1_F7 0 // 247 ÷ DIVISION +#define ISO_8859_1_F8 0 // 248 ø o STROKE +#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE +#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE +#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS +#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE +#define ISO_8859_1_FE 0 // 254 þ THORN +#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS + +#endif // LAYOUT_PORTUGUESE_BRAZILIAN + + + +#ifdef LAYOUT_FRENCH_BELGIAN + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define DEADKEYS_MASK 0x0700 +#define CIRCUMFLEX_BITS 0x0100 +#define GRAVE_ACCENT_BITS 0x0200 +#define DIAERESIS_BITS 0x0300 +#define TILDE_BITS 0x0400 +#define ACUTE_ACCENT_BITS 0x0500 +#define KEYCODE_TYPE uint16_t +#define DEADKEY_CIRCUMFLEX KEY_LEFT_BRACE +#define DEADKEY_ACUTE_ACCENT KEY_QUOTE + ALTGR_MASK +#define DEADKEY_GRAVE_ACCENT KEY_BACKSLASH + ALTGR_MASK +#define DEADKEY_DIAERESIS KEY_LEFT_BRACE + SHIFT_MASK +#define DEADKEY_TILDE KEY_SLASH + ALTGR_MASK +#define KEY_NON_US_100 63 + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_8 // 33 ! +#define ASCII_22 KEY_3 // 34 " +#define ASCII_23 KEY_3 + ALTGR_MASK // 35 # +#define ASCII_24 KEY_RIGHT_BRACE // 36 $ +#define ASCII_25 KEY_QUOTE + SHIFT_MASK // 37 % +#define ASCII_26 KEY_1 // 38 & +#define ASCII_27 KEY_4 // 39 ' +#define ASCII_28 KEY_5 // 40 ( +#define ASCII_29 KEY_MINUS // 41 ) +#define ASCII_2A KEY_RIGHT_BRACE + SHIFT_MASK // 42 * +#define ASCII_2B KEY_SLASH + SHIFT_MASK // 43 + +#define ASCII_2C KEY_M // 44 , +#define ASCII_2D KEY_EQUAL // 45 - +#define ASCII_2E KEY_COMMA + SHIFT_MASK // 46 . +#define ASCII_2F KEY_PERIOD + SHIFT_MASK // 47 / +#define ASCII_30 KEY_0 + SHIFT_MASK // 48 0 +#define ASCII_31 KEY_1 + SHIFT_MASK // 49 1 +#define ASCII_32 KEY_2 + SHIFT_MASK // 50 2 +#define ASCII_33 KEY_3 + SHIFT_MASK // 51 3 +#define ASCII_34 KEY_4 + SHIFT_MASK // 52 4 +#define ASCII_35 KEY_5 + SHIFT_MASK // 53 5 +#define ASCII_36 KEY_6 + SHIFT_MASK // 54 6 +#define ASCII_37 KEY_7 + SHIFT_MASK // 55 7 +#define ASCII_38 KEY_8 + SHIFT_MASK // 55 8 +#define ASCII_39 KEY_9 + SHIFT_MASK // 57 9 +#define ASCII_3A KEY_PERIOD // 58 : +#define ASCII_3B KEY_COMMA // 59 ; +#define ASCII_3C KEY_NON_US_100 // 60 < +#define ASCII_3D KEY_SLASH // 61 = +#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > +#define ASCII_3F KEY_M + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_2 + ALTGR_MASK // 64 @ +#define ASCII_41 KEY_Q + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_SEMICOLON + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_A + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_Z + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_W + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_RIGHT_BRACE + ALTGR_MASK // 91 [ +#define ASCII_5C KEY_NON_US_100 + ALTGR_MASK // 92 +#define ASCII_5D KEY_LEFT_BRACE + ALTGR_MASK // 93 ] +#define ASCII_5E KEY_6 + ALTGR_MASK // 94 ^ +#define ASCII_5F KEY_EQUAL + SHIFT_MASK // 95 _ +#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` +#define ASCII_61 KEY_Q // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_SEMICOLON // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_A // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_Z // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Y // 121 y +#define ASCII_7A KEY_W // 122 z +#define ASCII_7B KEY_9 + ALTGR_MASK // 123 { +#define ASCII_7C KEY_1 + ALTGR_MASK // 124 | +#define ASCII_7D KEY_0 + ALTGR_MASK // 125 } +#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 +#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space +#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN +#define ISO_8859_1_A3 KEY_BACKSLASH + SHIFT_MASK // 163 £ Pound Sign +#define ISO_8859_1_A4 0 // 164 ¤ Currency or Euro Sign +#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR +#define ISO_8859_1_A7 KEY_6 // 167 § SECTION SIGN +#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN +#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN +#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF 0 // 175 ¯ MACRON +#define ISO_8859_1_B0 KEY_MINUS + SHIFT_MASK // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 KEY_TILDE // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 KEY_TILDE + SHIFT_MASK // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 KEY_BACKSLASH // 181 µ MICRO SIGN +#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT +#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA +#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_Q + SHIFT_MASK // 192 À A GRAVE +#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_Q + SHIFT_MASK // 193 Á A ACUTE +#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_Q + SHIFT_MASK // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 TILDE_BITS + KEY_Q + SHIFT_MASK // 195 Ã A TILDE +#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_Q + SHIFT_MASK // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE +#define ISO_8859_1_C6 0 // 198 Æ AE +#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA +#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE +#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE +#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS +#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE +#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE +#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 0 // 208 Ð ETH +#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE +#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE +#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE +#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE +#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION +#define ISO_8859_1_D8 0 // 216 Ø O STROKE +#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE +#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE +#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U // 220 Ü U DIAERESIS +#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE +#define ISO_8859_1_DE 0 // 222 Þ THORN +#define ISO_8859_1_DF 0 // 223 ß SHARP S +#define ISO_8859_1_E0 KEY_0 // 224 à a GRAVE +#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_Q // 225 á a ACUTE +#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_Q // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 TILDE_BITS + KEY_Q // 227 ã a TILDE +#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_Q // 228 ä a DIAERESIS +#define ISO_8859_1_E5 0 // 229 å a RING ABOVE +#define ISO_8859_1_E6 0 // 230 æ ae +#define ISO_8859_1_E7 KEY_9 // 231 ç c CEDILLA +#define ISO_8859_1_E8 KEY_7 // 232 è e GRAVE +#define ISO_8859_1_E9 KEY_2 // 233 é e ACUTE +#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS +#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE +#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE +#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS +#define ISO_8859_1_F0 0 // 240 ð ETH +#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE +#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE +#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE +#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE +#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS +#define ISO_8859_1_F7 0 // 247 ÷ DIVISION +#define ISO_8859_1_F8 0 // 248 ø o STROKE +#define ISO_8859_1_F9 KEY_QUOTE // 249 ù u GRAVE - TODO; check FRENCH +#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE +#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS +#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE +#define ISO_8859_1_FE 0 // 254 þ THORN +#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS +#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign +// not yet implemented +#define UNICODE_EXTRA00 0x20AC +#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign + +#endif // LAYOUT_FRENCH_BELGIAN + + + + +#ifdef LAYOUT_GERMAN_SWISS + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define DEADKEYS_MASK 0x0700 +#define CIRCUMFLEX_BITS 0x0100 +#define GRAVE_ACCENT_BITS 0x0200 +#define DIAERESIS_BITS 0x0300 +#define TILDE_BITS 0x0400 +#define ACUTE_ACCENT_BITS 0x0500 +#define KEYCODE_TYPE uint16_t +#define DEADKEY_CIRCUMFLEX KEY_EQUAL +#define DEADKEY_ACUTE_ACCENT KEY_MINUS + ALTGR_MASK +#define DEADKEY_GRAVE_ACCENT KEY_EQUAL + SHIFT_MASK +#define DEADKEY_DIAERESIS KEY_RIGHT_BRACE +#define DEADKEY_TILDE KEY_EQUAL + ALTGR_MASK +#define KEY_NON_US_100 63 + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_RIGHT_BRACE + SHIFT_MASK // 33 ! +#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " +#define ASCII_23 KEY_3 + ALTGR_MASK // 35 # +#define ASCII_24 KEY_BACKSLASH // 36 $ +#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % +#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & +#define ASCII_27 KEY_MINUS // 39 ' +#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) +#define ASCII_2A KEY_3 + SHIFT_MASK // 42 * +#define ASCII_2B KEY_1 + SHIFT_MASK // 43 + +#define ASCII_2C KEY_COMMA // 44 , +#define ASCII_2D KEY_SLASH // 45 - +#define ASCII_2E KEY_PERIOD // 46 . +#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / +#define ASCII_30 KEY_0 // 48 0 +#define ASCII_31 KEY_1 // 49 1 +#define ASCII_32 KEY_2 // 50 2 +#define ASCII_33 KEY_3 // 51 3 +#define ASCII_34 KEY_4 // 52 4 +#define ASCII_35 KEY_5 // 53 5 +#define ASCII_36 KEY_6 // 54 6 +#define ASCII_37 KEY_7 // 55 7 +#define ASCII_38 KEY_8 // 55 8 +#define ASCII_39 KEY_9 // 57 9 +#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : +#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; +#define ASCII_3C KEY_NON_US_100 // 60 < +#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = +#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > +#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_2 + ALTGR_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Z + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Y + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_LEFT_BRACE + ALTGR_MASK // 91 [ +#define ASCII_5C KEY_NON_US_100 + ALTGR_MASK // 92 +#define ASCII_5D KEY_RIGHT_BRACE + ALTGR_MASK // 93 ] +#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ +#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ +#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Z // 121 y +#define ASCII_7A KEY_Y // 122 z +#define ASCII_7B KEY_QUOTE + ALTGR_MASK // 123 { +#define ASCII_7C KEY_7 + ALTGR_MASK // 124 | +#define ASCII_7D KEY_BACKSLASH + ALTGR_MASK // 125 } +#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 +#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space +#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 KEY_8 + ALTGR_MASK // 162 ¢ Cent Sign +#define ISO_8859_1_A3 KEY_BACKSLASH + SHIFT_MASK // 163 £ Pound Sign +#define ISO_8859_1_A4 0 // 164 ¤ Currency Sign +#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 KEY_1 + ALTGR_MASK // 166 ¦ BROKEN BAR +#define ISO_8859_1_A7 KEY_5 + ALTGR_MASK // 167 § SECTION SIGN +#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC KEY_6 + ALTGR_MASK // 172 ¬ NOT SIGN +#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN +#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF 0 // 175 ¯ MACRON +#define ISO_8859_1_B0 KEY_4 + ALTGR_MASK // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN +#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT +#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA +#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE +#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE +#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE +#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE +#define ISO_8859_1_C6 0 // 198 Æ AE +#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA +#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE +#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE +#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS +#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE +#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE +#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 0 // 208 Ð ETH +#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE +#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE +#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE +#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE +#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION +#define ISO_8859_1_D8 0 // 216 Ø O STROKE +#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE +#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE +#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS +#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE +#define ISO_8859_1_DE 0 // 222 Þ THORN +#define ISO_8859_1_DF 0 // 223 ß SHARP S +#define ISO_8859_1_E0 KEY_QUOTE + SHIFT_MASK // 224 à a GRAVE +#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE +#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE +#define ISO_8859_1_E4 KEY_QUOTE // 228 ä a DIAERESIS +#define ISO_8859_1_E5 0 // 229 å a RING ABOVE +#define ISO_8859_1_E6 0 // 230 æ ae +#define ISO_8859_1_E7 KEY_4 + SHIFT_MASK // 231 ç c CEDILLA +#define ISO_8859_1_E8 KEY_LEFT_BRACE + SHIFT_MASK // 232 è e GRAVE +#define ISO_8859_1_E9 KEY_SEMICOLON + SHIFT_MASK // 233 é e ACUTE +#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS TODO: check this +#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE +#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE +#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS +#define ISO_8859_1_F0 0 // 240 ð ETH +#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE +#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE +#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE +#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE +#define ISO_8859_1_F6 KEY_SEMICOLON // 246 ö o DIAERESIS +#define ISO_8859_1_F7 0 // 247 ÷ DIVISION +#define ISO_8859_1_F8 0 // 248 ø o STROKE +#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE +#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE +#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC KEY_LEFT_BRACE // 252 ü u DIAERESIS +#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE +#define ISO_8859_1_FE 0 // 254 þ THORN +#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS +#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign +// not yet implemented +#define UNICODE_EXTRA00 0x20AC +#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign + +#endif // LAYOUT_GERMAN_SWISS + + + + +#ifdef LAYOUT_FRENCH_SWISS + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define DEADKEYS_MASK 0x0700 +#define CIRCUMFLEX_BITS 0x0100 +#define GRAVE_ACCENT_BITS 0x0200 +#define DIAERESIS_BITS 0x0300 +#define TILDE_BITS 0x0400 +#define ACUTE_ACCENT_BITS 0x0500 +#define KEYCODE_TYPE uint16_t +#define DEADKEY_CIRCUMFLEX KEY_EQUAL +#define DEADKEY_ACUTE_ACCENT KEY_MINUS + ALTGR_MASK +#define DEADKEY_GRAVE_ACCENT KEY_EQUAL + SHIFT_MASK +#define DEADKEY_DIAERESIS KEY_RIGHT_BRACE +#define DEADKEY_TILDE KEY_EQUAL + ALTGR_MASK +#define KEY_NON_US_100 63 + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_RIGHT_BRACE + SHIFT_MASK // 33 ! +#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " +#define ASCII_23 KEY_3 + ALTGR_MASK // 35 # +#define ASCII_24 KEY_BACKSLASH // 36 $ +#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % +#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & +#define ASCII_27 KEY_MINUS // 39 ' +#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) +#define ASCII_2A KEY_3 + SHIFT_MASK // 42 * +#define ASCII_2B KEY_1 + SHIFT_MASK // 43 + +#define ASCII_2C KEY_COMMA // 44 , +#define ASCII_2D KEY_SLASH // 45 - +#define ASCII_2E KEY_PERIOD // 46 . +#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / +#define ASCII_30 KEY_0 // 48 0 +#define ASCII_31 KEY_1 // 49 1 +#define ASCII_32 KEY_2 // 50 2 +#define ASCII_33 KEY_3 // 51 3 +#define ASCII_34 KEY_4 // 52 4 +#define ASCII_35 KEY_5 // 53 5 +#define ASCII_36 KEY_6 // 54 6 +#define ASCII_37 KEY_7 // 55 7 +#define ASCII_38 KEY_8 // 55 8 +#define ASCII_39 KEY_9 // 57 9 +#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : +#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; +#define ASCII_3C KEY_NON_US_100 // 60 < +#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = +#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > +#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_2 + ALTGR_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Z + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Y + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_LEFT_BRACE + ALTGR_MASK // 91 [ +#define ASCII_5C KEY_NON_US_100 + ALTGR_MASK // 92 +#define ASCII_5D KEY_RIGHT_BRACE + ALTGR_MASK // 93 ] +#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ +#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ +#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Z // 121 y +#define ASCII_7A KEY_Y // 122 z +#define ASCII_7B KEY_QUOTE + ALTGR_MASK // 123 { +#define ASCII_7C KEY_7 + ALTGR_MASK // 124 | +#define ASCII_7D KEY_BACKSLASH + ALTGR_MASK // 125 } +#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 +#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space +#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 KEY_8 + ALTGR_MASK // 162 ¢ Cent Sign +#define ISO_8859_1_A3 KEY_BACKSLASH + SHIFT_MASK // 163 £ Pound Sign +#define ISO_8859_1_A4 0 // 164 ¤ Currency Sign +#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 KEY_1 + ALTGR_MASK // 166 ¦ BROKEN BAR +#define ISO_8859_1_A7 KEY_5 + ALTGR_MASK // 167 § SECTION SIGN +#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC KEY_6 + ALTGR_MASK // 172 ¬ NOT SIGN +#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN +#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF 0 // 175 ¯ MACRON +#define ISO_8859_1_B0 KEY_4 + ALTGR_MASK // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN +#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT +#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA +#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE +#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE +#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE +#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE +#define ISO_8859_1_C6 0 // 198 Æ AE +#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA +#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE +#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE +#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS +#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE +#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE +#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 0 // 208 Ð ETH +#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE +#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE +#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE +#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE +#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION +#define ISO_8859_1_D8 0 // 216 Ø O STROKE +#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE +#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE +#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS +#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE +#define ISO_8859_1_DE 0 // 222 Þ THORN +#define ISO_8859_1_DF 0 // 223 ß SHARP S +#define ISO_8859_1_E0 KEY_QUOTE // 224 à a GRAVE +#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE +#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE +#define ISO_8859_1_E4 KEY_QUOTE + SHIFT_MASK // 228 ä a DIAERESIS +#define ISO_8859_1_E5 0 // 229 å a RING ABOVE +#define ISO_8859_1_E6 0 // 230 æ ae +#define ISO_8859_1_E7 KEY_4 + SHIFT_MASK // 231 ç c CEDILLA +#define ISO_8859_1_E8 KEY_LEFT_BRACE // 232 è e GRAVE +#define ISO_8859_1_E9 KEY_SEMICOLON // 233 é e ACUTE +#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS +#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE +#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE +#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS +#define ISO_8859_1_F0 0 // 240 ð ETH +#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE +#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE +#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE +#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE +#define ISO_8859_1_F6 KEY_SEMICOLON + SHIFT_MASK // 246 ö o DIAERESIS +#define ISO_8859_1_F7 0 // 247 ÷ DIVISION +#define ISO_8859_1_F8 0 // 248 ø o STROKE +#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE +#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE +#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC KEY_LEFT_BRACE + SHIFT_MASK // 252 ü u DIAERESIS +#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE +#define ISO_8859_1_FE 0 // 254 þ THORN +#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS +#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign +// not yet implemented +#define UNICODE_EXTRA00 0x20AC +#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign + +#endif // LAYOUT_FRENCH_SWISS + + + + + +#ifdef LAYOUT_SPANISH_LATIN_AMERICA + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define DEADKEYS_MASK 0x0700 +#define CIRCUMFLEX_BITS 0x0100 +#define ACUTE_ACCENT_BITS 0x0200 +#define GRAVE_ACCENT_BITS 0x0300 +#define DIAERESIS_BITS 0x0400 +#define KEYCODE_TYPE uint16_t +#define DEADKEY_CIRCUMFLEX KEY_QUOTE + ALTGR_MASK +#define DEADKEY_ACUTE_ACCENT KEY_LEFT_BRACE +#define DEADKEY_GRAVE_ACCENT KEY_BACKSLASH + ALTGR_MASK +#define DEADKEY_DIAERESIS KEY_LEFT_BRACE + SHIFT_MASK +#define KEY_NON_US_100 63 + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! +#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " +#define ASCII_23 KEY_3 + ALTGR_MASK // 35 # +#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ +#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % +#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & +#define ASCII_27 KEY_MINUS // 39 ' +#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) +#define ASCII_2A KEY_RIGHT_BRACE + SHIFT_MASK // 42 * +#define ASCII_2B KEY_RIGHT_BRACE // 43 + +#define ASCII_2C KEY_COMMA // 44 , +#define ASCII_2D KEY_SLASH // 45 - +#define ASCII_2E KEY_PERIOD // 46 . +#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / +#define ASCII_30 KEY_0 // 48 0 +#define ASCII_31 KEY_1 // 49 1 +#define ASCII_32 KEY_2 // 50 2 +#define ASCII_33 KEY_3 // 51 3 +#define ASCII_34 KEY_4 // 52 4 +#define ASCII_35 KEY_5 // 53 5 +#define ASCII_36 KEY_6 // 54 6 +#define ASCII_37 KEY_7 // 55 7 +#define ASCII_38 KEY_8 // 55 8 +#define ASCII_39 KEY_9 // 57 9 +#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : +#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; +#define ASCII_3C KEY_NON_US_100 // 60 < +#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = +#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > +#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_Q + ALTGR_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_QUOTE + SHIFT_MASK // 91 [ +#define ASCII_5C KEY_MINUS + ALTGR_MASK // 92 +#define ASCII_5D KEY_BACKSLASH + SHIFT_MASK // 93 ] +#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ +#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ +#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Y // 121 y +#define ASCII_7A KEY_Z // 122 z +#define ASCII_7B KEY_QUOTE // 123 { +#define ASCII_7C KEY_TILDE // 124 | +#define ASCII_7D KEY_BACKSLASH // 125 } +#define ASCII_7E KEY_RIGHT_BRACE + ALTGR_MASK // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 + +#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space +#define ISO_8859_1_A1 KEY_EQUAL + SHIFT_MASK // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN +#define ISO_8859_1_A3 0 // 163 £ Pound Sign +#define ISO_8859_1_A4 0 // 164 ¤ Currency Sign +#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR +#define ISO_8859_1_A7 0 // 167 § SECTION SIGN +#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC KEY_TILDE + ALTGR_MASK // 172 ¬ NOT SIGN +#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN +#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF 0 // 175 ¯ MACRON +#define ISO_8859_1_B0 KEY_TILDE + SHIFT_MASK // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN +#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT +#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA +#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF KEY_EQUAL // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE +#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE +#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 0 // 195 Ã A TILDE +#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE +#define ISO_8859_1_C6 0 // 198 Æ AE +#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA +#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE +#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE +#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS +#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE +#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE +#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 0 // 208 Ð ETH +#define ISO_8859_1_D1 KEY_SEMICOLON + SHIFT_MASK // 209 Ñ N TILDE +#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE +#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE +#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 0 // 213 Õ O TILDE +#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION +#define ISO_8859_1_D8 0 // 216 Ø O STROKE +#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE +#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE +#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS +#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE +#define ISO_8859_1_DE 0 // 222 Þ THORN +#define ISO_8859_1_DF 0 // 223 ß SHARP S +#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE +#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE +#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 0 // 227 ã a TILDE +#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS +#define ISO_8859_1_E5 0 // 229 å a RING ABOVE +#define ISO_8859_1_E6 0 // 230 æ ae +#define ISO_8859_1_E7 0 // 231 ç c CEDILLA +#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE +#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE +#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS +#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE +#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE +#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS +#define ISO_8859_1_F0 0 // 240 ð ETH +#define ISO_8859_1_F1 KEY_SEMICOLON // 241 ñ n TILDE +#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE +#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE +#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 0 // 245 õ o TILDE +#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS +#define ISO_8859_1_F7 0 // 247 ÷ DIVISION +#define ISO_8859_1_F8 0 // 248 ø o STROKE +#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE +#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE +#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS +#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE +#define ISO_8859_1_FE 0 // 254 þ THORN +#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS + +#endif // LAYOUT_SPANISH_LATIN_AMERICA + + + +#ifdef LAYOUT_IRISH + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define DEADKEYS_MASK 0x0300 +#define GRAVE_ACCENT_BITS 0x0100 +#define ACUTE_ACCENT_BITS 0x0200 +#define KEYCODE_TYPE uint16_t +#define DEADKEY_ACUTE_ACCENT KEY_QUOTE + ALTGR_MASK +#define DEADKEY_GRAVE_ACCENT KEY_TILDE +#define KEY_NON_US_100 63 + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! +#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " +#define ASCII_23 KEY_BACKSPACE // 35 # +#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ +#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % +#define ASCII_26 KEY_7 + SHIFT_MASK // 38 & +#define ASCII_27 KEY_QUOTE // 39 ' +#define ASCII_28 KEY_9 + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_0 + SHIFT_MASK // 41 ) +#define ASCII_2A KEY_8 + SHIFT_MASK // 42 * +#define ASCII_2B KEY_EQUAL + SHIFT_MASK // 43 + +#define ASCII_2C KEY_COMMA // 44 , +#define ASCII_2D KEY_MINUS // 45 - +#define ASCII_2E KEY_PERIOD // 46 . +#define ASCII_2F KEY_SLASH // 47 / +#define ASCII_30 KEY_0 // 48 0 +#define ASCII_31 KEY_1 // 49 1 +#define ASCII_32 KEY_2 // 50 2 +#define ASCII_33 KEY_3 // 51 3 +#define ASCII_34 KEY_4 // 52 4 +#define ASCII_35 KEY_5 // 53 5 +#define ASCII_36 KEY_6 // 54 6 +#define ASCII_37 KEY_7 // 55 7 +#define ASCII_38 KEY_8 // 55 8 +#define ASCII_39 KEY_9 // 57 9 +#define ASCII_3A KEY_SEMICOLON + SHIFT_MASK // 58 : +#define ASCII_3B KEY_SEMICOLON // 59 ; +#define ASCII_3C KEY_COMMA + SHIFT_MASK // 60 < +#define ASCII_3D KEY_EQUAL // 61 = +#define ASCII_3E KEY_PERIOD + SHIFT_MASK // 62 > +#define ASCII_3F KEY_SLASH + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_QUOTE + SHIFT_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_LEFT_BRACE // 91 [ +#define ASCII_5C KEY_NON_US_100 // 92 +#define ASCII_5D KEY_RIGHT_BRACE // 93 ] +#define ASCII_5E KEY_6 + SHIFT_MASK // 94 ^ +#define ASCII_5F KEY_MINUS + SHIFT_MASK // 95 _ +#define ASCII_60 KEY_QUOTE + SHIFT_MASK + ALTGR_MASK // 96 ` +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Y // 121 y +#define ASCII_7A KEY_Z // 122 z +#define ASCII_7B KEY_LEFT_BRACE + SHIFT_MASK // 123 { +#define ASCII_7C KEY_NON_US_100 + SHIFT_MASK // 124 | +#define ASCII_7D KEY_RIGHT_BRACE + SHIFT_MASK // 125 } +#define ASCII_7E KEY_BACKSLASH + SHIFT_MASK // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 + +#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space +#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN +#define ISO_8859_1_A3 KEY_3 + SHIFT_MASK // 163 £ Pound Sign +#define ISO_8859_1_A4 0 // 164 ¤ Currency or Euro Sign +#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 KEY_TILDE + ALTGR_MASK // 166 ¦ BROKEN BAR +#define ISO_8859_1_A7 0 // 167 § SECTION SIGN +#define ISO_8859_1_A8 0 // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC KEY_TILDE + SHIFT_MASK // 172 ¬ NOT SIGN +#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN +#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF 0 // 175 ¯ MACRON +#define ISO_8859_1_B0 0 // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 0 // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN +#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT +#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA +#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A // 192 À A GRAVE +#define ISO_8859_1_C1 KEY_A + ALTGR_MASK + SHIFT_MASK // 193 Á A ACUTE +#define ISO_8859_1_C2 0 // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 0 // 195 Ã A TILDE +#define ISO_8859_1_C4 0 // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE +#define ISO_8859_1_C6 0 // 198 Æ AE +#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA +#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E // 200 È E GRAVE +#define ISO_8859_1_C9 KEY_E + ALTGR_MASK + SHIFT_MASK // 201 É E ACUTE +#define ISO_8859_1_CA 0 // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB 0 // 203 Ë E DIAERESIS +#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I // 204 Ì I GRAVE +#define ISO_8859_1_CD KEY_I + ALTGR_MASK + SHIFT_MASK // 205 Í I ACUTE +#define ISO_8859_1_CE 0 // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF 0 // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 0 // 208 Ð ETH +#define ISO_8859_1_D1 0 // 209 Ñ N TILDE +#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O // 210 Ò O GRAVE +#define ISO_8859_1_D3 KEY_O + ALTGR_MASK + SHIFT_MASK // 211 Ó O ACUTE +#define ISO_8859_1_D4 0 // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 0 // 213 Õ O TILDE +#define ISO_8859_1_D6 0 // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION +#define ISO_8859_1_D8 0 // 216 Ø O STROKE +#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U // 217 Ù U GRAVE +#define ISO_8859_1_DA KEY_U + ALTGR_MASK + SHIFT_MASK // 218 Ú U ACUTE +#define ISO_8859_1_DB 0 // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC 0 // 220 Ü U DIAERESIS +#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE +#define ISO_8859_1_DE 0 // 222 Þ THORN +#define ISO_8859_1_DF 0 // 223 ß SHARP S +#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE +#define ISO_8859_1_E1 KEY_A + ALTGR_MASK // 225 á a ACUTE +#define ISO_8859_1_E2 0 // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 0 // 227 ã a TILDE +#define ISO_8859_1_E4 0 // 228 ä a DIAERESIS +#define ISO_8859_1_E5 0 // 229 å a RING ABOVE +#define ISO_8859_1_E6 0 // 230 æ ae +#define ISO_8859_1_E7 0 // 231 ç c CEDILLA +#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE +#define ISO_8859_1_E9 KEY_E + ALTGR_MASK // 233 é e ACUTE +#define ISO_8859_1_EA 0 // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB 0 // 235 ë e DIAERESIS +#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE +#define ISO_8859_1_ED KEY_I + ALTGR_MASK // 237 í i ACUTE +#define ISO_8859_1_EE 0 // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF 0 // 239 ï i DIAERESIS +#define ISO_8859_1_F0 0 // 240 ð ETH +#define ISO_8859_1_F1 0 // 241 ñ n TILDE +#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE +#define ISO_8859_1_F3 KEY_O + ALTGR_MASK // 243 ó o ACUTE +#define ISO_8859_1_F4 0 // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 0 // 245 õ o TILDE +#define ISO_8859_1_F6 0 // 246 ö o DIAERESIS +#define ISO_8859_1_F7 0 // 247 ÷ DIVISION +#define ISO_8859_1_F8 0 // 248 ø o STROKE +#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE +#define ISO_8859_1_FA KEY_U + ALTGR_MASK // 250 ú u ACUTE +#define ISO_8859_1_FB 0 // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC 0 // 252 ü u DIAERESIS +#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE +#define ISO_8859_1_FE 0 // 254 þ THORN +#define ISO_8859_1_FF 0 // 255 ÿ y DIAERESIS +#define UNICODE_20AC KEY_4 + ALTGR_MASK // € Euro Sign +// not yet implemented +#define UNICODE_EXTRA00 0x20AC +#define KEYCODE_EXTRA00 KEY_4 + ALTGR_MASK // 20AC € Euro Sign + +#endif // LAYOUT_IRISH + + + + +#ifdef LAYOUT_ICELANDIC + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define DEADKEYS_MASK 0x0700 +#define CIRCUMFLEX_BITS 0x0100 +#define ACUTE_ACCENT_BITS 0x0200 +#define GRAVE_ACCENT_BITS 0x0300 +#define DIAERESIS_BITS 0x0400 +#define RING_ABOVE_BITS 0x0500 +#define KEYCODE_TYPE uint16_t +#define DEADKEY_CIRCUMFLEX KEY_QUOTE + ALTGR_MASK +#define DEADKEY_ACUTE_ACCENT KEY_QUOTE +#define DEADKEY_GRAVE_ACCENT KEY_BACKSLASH + ALTGR_MASK +#define DEADKEY_DIAERESIS KEY_TILDE + SHIFT_MASK +#define DEADKEY_RING_ABOVE KEY_TILDE +#define KEY_NON_US_100 63 + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! +#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " +#define ASCII_23 KEY_3 + SHIFT_MASK // 35 # +#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ +#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % +#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & +#define ASCII_27 KEY_QUOTE + SHIFT_MASK // 39 ' +#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) +#define ASCII_2A KEY_BACKSLASH + SHIFT_MASK // 42 * +#define ASCII_2B KEY_BACKSLASH // 43 + +#define ASCII_2C KEY_COMMA // 44 , +#define ASCII_2D KEY_EQUAL // 45 - +#define ASCII_2E KEY_PERIOD // 46 . +#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / +#define ASCII_30 KEY_0 // 48 0 +#define ASCII_31 KEY_1 // 49 1 +#define ASCII_32 KEY_2 // 50 2 +#define ASCII_33 KEY_3 // 51 3 +#define ASCII_34 KEY_4 // 52 4 +#define ASCII_35 KEY_5 // 53 5 +#define ASCII_36 KEY_6 // 54 6 +#define ASCII_37 KEY_7 // 55 7 +#define ASCII_38 KEY_8 // 55 8 +#define ASCII_39 KEY_9 // 57 9 +#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : +#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; +#define ASCII_3C KEY_NON_US_100 // 60 < +#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = +#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > +#define ASCII_3F KEY_RIGHT_BRACE + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_Q + ALTGR_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_8 + ALTGR_MASK // 91 [ +#define ASCII_5C KEY_MINUS + ALTGR_MASK // 92 +#define ASCII_5D KEY_9 + ALTGR_MASK // 93 ] +#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ +#define ASCII_5F KEY_EQUAL + SHIFT_MASK // 95 _ +#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Y // 121 y +#define ASCII_7A KEY_Z // 122 z +#define ASCII_7B KEY_7 + ALTGR_MASK // 123 { +#define ASCII_7C KEY_NON_US_100 + ALTGR_MASK // 124 | +#define ASCII_7D KEY_0 + ALTGR_MASK // 125 } +#define ASCII_7E KEY_RIGHT_BRACE + ALTGR_MASK // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 + +#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space +#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN +#define ISO_8859_1_A3 0 // 163 £ Pound Sign +#define ISO_8859_1_A4 0 // 164 ¤ Currency or Euro Sign +#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR ?? +#define ISO_8859_1_A7 0 // 167 § SECTION SIGN +#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN ?? +#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN +#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF 0 // 175 ¯ MACRON +#define ISO_8859_1_B0 KEY_TILDE + ALTGR_MASK // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 KEY_M + ALTGR_MASK // 181 µ MICRO SIGN +#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT +#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA +#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE +#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + ALTGR_MASK // 193 Á A ACUTE +#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 0 // 195 Ã A TILDE +#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 RING_ABOVE_BITS + KEY_A + SHIFT_MASK // 197 Å A RING ABOVE +#define ISO_8859_1_C6 KEY_SEMICOLON + SHIFT_MASK // 198 Æ AE +#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA +#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE +#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE +#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS +#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE +#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE +#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 KEY_LEFT_BRACE + SHIFT_MASK // 208 Ð ETH +#define ISO_8859_1_D1 0 // 209 Ñ N TILDE +#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE +#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE +#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 0 // 213 Õ O TILDE +#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION +#define ISO_8859_1_D8 0 // 216 Ø O STROKE +#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE +#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE +#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS +#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE +#define ISO_8859_1_DE KEY_SLASH + SHIFT_MASK // 222 Þ THORN +#define ISO_8859_1_DF 0 // 223 ß SHARP S +#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE +#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE +#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 0 // 227 ã a TILDE +#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS +#define ISO_8859_1_E5 RING_ABOVE_BITS + KEY_A // 229 å a RING ABOVE +#define ISO_8859_1_E6 KEY_SEMICOLON // 230 æ ae +#define ISO_8859_1_E7 0 // 231 ç c CEDILLA +#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE +#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE +#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS +#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE +#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE +#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS +#define ISO_8859_1_F0 KEY_LEFT_BRACE // 240 ð ETH +#define ISO_8859_1_F1 0 // 241 ñ n TILDE +#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE +#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE +#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 0 // 245 õ o TILDE +#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS +#define ISO_8859_1_F7 0 // 247 ÷ DIVISION +#define ISO_8859_1_F8 0 // 248 ø o STROKE +#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE +#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE +#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS +#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE +#define ISO_8859_1_FE KEY_SLASH // 254 þ THORN +#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS +#define UNICODE_20AC KEY_5 + ALTGR_MASK // € Euro Sign +// not yet implemented +#define UNICODE_EXTRA00 0x20AC +#define KEYCODE_EXTRA00 KEY_5 + ALTGR_MASK // 20AC € Euro Sign + +#endif // LAYOUT_ICELANDIC + + + +#ifdef LAYOUT_TURKISH +// http://forum.pjrc.com/threads/18781-Turkish-Language-Support + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define DEADKEYS_MASK 0x0700 +#define CIRCUMFLEX_BITS 0x0100 +#define ACUTE_ACCENT_BITS 0x0200 +#define GRAVE_ACCENT_BITS 0x0300 +#define TILDE_BITS 0x0400 +#define DIAERESIS_BITS 0x0500 +#define KEYCODE_TYPE uint16_t +#define DEADKEY_CIRCUMFLEX KEY_3 + SHIFT_MASK +#define DEADKEY_ACUTE_ACCENT KEY_SEMICOLON + ALTGR_MASK +#define DEADKEY_GRAVE_ACCENT KEY_BACKSLASH + ALTGR_MASK +#define DEADKEY_TILDE KEY_RIGHT_BRACE + ALTGR_MASK +#define DEADKEY_DIAERESIS KEY_LEFT_BRACE + ALTGR_MASK + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! +#define ASCII_22 KEY_TILDE // 34 " +#define ASCII_23 KEY_3 + ALTGR_MASK // 35 # +#define ASCII_24 KEY_4 + ALTGR_MASK // 36 $ +#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % +#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & +#define ASCII_27 KEY_2 + SHIFT_MASK // 39 ' +#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) +#define ASCII_2A KEY_MINUS // 42 * +#define ASCII_2B KEY_4 + SHIFT_MASK // 43 + +#define ASCII_2C KEY_BACKSLASH // 44 , +#define ASCII_2D KEY_EQUAL // 45 - +#define ASCII_2E KEY_SLASH // 46 . +#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / +#define ASCII_30 KEY_0 // 48 0 +#define ASCII_31 KEY_1 // 49 1 +#define ASCII_32 KEY_2 // 50 2 +#define ASCII_33 KEY_3 // 51 3 +#define ASCII_34 KEY_4 // 52 4 +#define ASCII_35 KEY_5 // 53 5 +#define ASCII_36 KEY_6 // 54 6 +#define ASCII_37 KEY_7 // 55 7 +#define ASCII_38 KEY_8 // 55 8 +#define ASCII_39 KEY_9 // 57 9 +#define ASCII_3A KEY_SLASH + SHIFT_MASK // 58 : +#define ASCII_3B KEY_BACKSLASH + SHIFT_MASK // 59 ; +#define ASCII_3C KEY_TILDE + ALTGR_MASK // 60 < +#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = +#define ASCII_3E KEY_1 + ALTGR_MASK // 62 > +#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_Q + ALTGR_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_8 + ALTGR_MASK // 91 [ +#define ASCII_5C KEY_MINUS + ALTGR_MASK // 92 +#define ASCII_5D KEY_9 + ALTGR_MASK // 93 ] +#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ +#define ASCII_5F KEY_EQUAL + SHIFT_MASK // 95 _ +#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_QUOTE // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Y // 121 y +#define ASCII_7A KEY_Z // 122 z +#define ASCII_7B KEY_7 + ALTGR_MASK // 123 { +#define ASCII_7C KEY_EQUAL + ALTGR_MASK // 124 | +#define ASCII_7D KEY_0 + ALTGR_MASK // 125 } +#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 + +#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space +#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN +#define ISO_8859_1_A3 KEY_2 + ALTGR_MASK // 163 £ Pound Sign +#define ISO_8859_1_A4 0 // 164 ¤ Currency or Euro Sign +#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR ?? +#define ISO_8859_1_A7 0 // 167 § SECTION SIGN +#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN ?? +#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN +#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF 0 // 175 ¯ MACRON +#define ISO_8859_1_B0 0 // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN +#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT +#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA +#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD KEY_5 + ALTGR_MASK // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE +#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE +#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE +#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE +#define ISO_8859_1_C6 KEY_A + ALTGR_MASK // 198 Æ AE +#define ISO_8859_1_C7 KEY_PERIOD + SHIFT_MASK // 199 Ç C CEDILLA +#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE +#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE +#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS +#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE +#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE +#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 0 // 208 Ð ETH +#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE +#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE +#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE +#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE +#define ISO_8859_1_D6 KEY_COMMA + SHIFT_MASK // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION +#define ISO_8859_1_D8 0 // 216 Ø O STROKE +#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE +#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE +#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC KEY_RIGHT_BRACE + SHIFT_MASK // 220 Ü U DIAERESIS +#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE +#define ISO_8859_1_DE 0 // 222 Þ THORN +#define ISO_8859_1_DF KEY_S + ALTGR_MASK // 223 ß SHARP S +#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE +#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE +#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE +#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS +#define ISO_8859_1_E5 0 // 229 å a RING ABOVE +#define ISO_8859_1_E6 0 // 230 æ ae +#define ISO_8859_1_E7 KEY_PERIOD // 231 ç c CEDILLA +#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE +#define ISO_8859_1_E9 KEY_TILDE + SHIFT_MASK // 233 é e ACUTE +#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS +#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE +#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE +#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS +#define ISO_8859_1_F0 0 // 240 ð ETH +#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE +#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE +#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE +#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE +#define ISO_8859_1_F6 KEY_COMMA // 246 ö o DIAERESIS +#define ISO_8859_1_F7 0 // 247 ÷ DIVISION +#define ISO_8859_1_F8 0 // 248 ø o STROKE +#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE +#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE +#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC KEY_RIGHT_BRACE // 252 ü u DIAERESIS +#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE +#define ISO_8859_1_FE 0 // 254 þ THORN +#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS +#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign + +// not yet implemented +#define UNICODE_EXTRA00 0x20AC +#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign +#define UNICODE_EXTRA01 0x011E +#define KEYCODE_EXTRA01 KEY_LEFT_BRACE + SHIFT_MASK // 011E Ğ Latin capital letter G with breve +#define UNICODE_EXTRA02 0x011F +#define KEYCODE_EXTRA02 KEY_LEFT_BRACE // 011F ğ Latin small letter g with breve +#define UNICODE_EXTRA03 0x0130 +#define KEYCODE_EXTRA03 KEY_QUOTE + SHIFT_MASK // 0130 İ Latin captial letter I with dot above +#define UNICODE_EXTRA04 0x0131 +#define KEYCODE_EXTRA04 KEY_I // 0131 ı Latin small letter dotless i +#define UNICODE_EXTRA05 0x015E +#define KEYCODE_EXTRA05 KEY_SEMICOLON + SHIFT_MASK // 015E Ş Latin capital letter S with cedilla +#define UNICODE_EXTRA06 0x0151 +#define KEYCODE_EXTRA06 KEY_SEMICOLON // 0151 ş Latin small letter s with cedilla + +#endif // LAYOUT_TURKISH + + + +#ifdef LAYOUT_CZECH +// http://forum.pjrc.com/threads/24495-Czech-keyboard + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define DEADKEYS_MASK 0x0F00 +#define ACUTE_ACCENT_BITS 0x0100 // TODO: the Czech might not support some +#define DEGREE_SIGN_BITS 0x0200 // of these deadkeys, perhaps not any??? +#define CARON_BITS 0x0300 +//#define CIRCUMFLEX_BITS 0x0400 +#define BREVE_BITS 0x0500 +#define OGONEK_BITS 0x0600 +//#define GRAVE_ACCENT_BITS 0x0700 +#define DOT_ABOVE_BITS 0x0800 +#define DOUBLE_ACUTE_BITS 0x0900 +//#define DIAERESIS_BITS 0x0A00 +#define CEDILLA_BITS 0x0B00 +#define KEYCODE_TYPE uint16_t +#define DEADKEY_ACUTE_ACCENT KEY_EQUAL // TODO: is it KEY_9 + ALTGR_MASK +#define DEADKEY_DEGREE_SIGN KEY_TILDE + SHIFT_MASK // TODO: is it KEY_5 + ALTGR_MASK +#define DEADKEY_CARON KEY_EQUAL + SHIFT_MASK // TODO: is it KEY_2 + ALTGR_MASK +//#define DEADKEY_CIRCUMFLEX KEY_3 + ALTGR_MASK +#define DEADKEY_BREVE KEY_4 + ALTGR_MASK +#define DEADKEY_OGONEK KEY_6 + ALTGR_MASK +//#define DEADKEY_GRAVE_ACCENT KEY_7 + ALTGR_MASK +#define DEADKEY_DOT_ABOVE KEY_8 + ALTGR_MASK +#define DEADKEY_DOUBLE_ACUTE KEY_0 + ALTGR_MASK +#define DEADKEY_DIAERESIS KEY_MINUS + ALTGR_MASK +#define DEADKEY_CEDILLA KEY_EQUAL + ALTGR_MASK +#define KEY_NON_US_100 63 +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_QUOTE + SHIFT_MASK // 33 ! +#define ASCII_22 KEY_SEMICOLON + SHIFT_MASK // 34 " +#define ASCII_23 KEY_X + ALTGR_MASK // 35 # +#define ASCII_24 KEY_SEMICOLON + ALTGR_MASK // 36 $ +#define ASCII_25 KEY_MINUS + SHIFT_MASK // 37 % +#define ASCII_26 KEY_C + ALTGR_MASK // 38 & +#define ASCII_27 KEY_BACKSLASH + SHIFT_MASK // 39 ' +#define ASCII_28 KEY_RIGHT_BRACE + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_RIGHT_BRACE // 41 ) +#define ASCII_2A KEY_SLASH + ALTGR_MASK // 42 * +#define ASCII_2B KEY_1 // 43 + +#define ASCII_2C KEY_COMMA // 44 , +#define ASCII_2D KEY_SLASH // 45 - +#define ASCII_2E KEY_PERIOD // 46 . +#define ASCII_2F KEY_LEFT_BRACE + SHIFT_MASK // 47 / +#define ASCII_30 KEY_0 + SHIFT_MASK // 48 0 +#define ASCII_31 KEY_1 + SHIFT_MASK // 49 1 +#define ASCII_32 KEY_2 + SHIFT_MASK // 50 2 +#define ASCII_33 KEY_3 + SHIFT_MASK // 51 3 +#define ASCII_34 KEY_4 + SHIFT_MASK // 52 4 +#define ASCII_35 KEY_5 + SHIFT_MASK // 53 5 +#define ASCII_36 KEY_6 + SHIFT_MASK // 54 6 +#define ASCII_37 KEY_7 + SHIFT_MASK // 55 7 +#define ASCII_38 KEY_8 + SHIFT_MASK // 55 8 +#define ASCII_39 KEY_9 + SHIFT_MASK // 57 9 +#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : +#define ASCII_3B KEY_TILDE // 59 ; +#define ASCII_3C KEY_COMMA + ALTGR_MASK // 60 < +#define ASCII_3D KEY_MINUS // 61 = +#define ASCII_3E KEY_PERIOD + ALTGR_MASK // 62 > +#define ASCII_3F KEY_COMMA + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_V + ALTGR_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Z + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Y + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_F + ALTGR_MASK // 91 [ +#define ASCII_5C KEY_NON_US_100 // 92 +#define ASCII_5D KEY_G + ALTGR_MASK // 93 ] +#define ASCII_5E KEY_3 + ALTGR_MASK // 94 ^ TODO: testme +#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ +#define ASCII_60 KEY_7 + ALTGR_MASK // 96 ` TODO: testme +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Z // 121 y +#define ASCII_7A KEY_Y // 122 z +#define ASCII_7B KEY_B + ALTGR_MASK // 123 { +#define ASCII_7C KEY_NON_US_100 + SHIFT_MASK // 124 | +#define ASCII_7D KEY_N + ALTGR_MASK // 125 } +#define ASCII_7E KEY_1 + ALTGR_MASK // 126 ~ TODO: fixme +#define ASCII_7F KEY_BACKSPACE // 127 +#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space +#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 0 // 162 ¢ Cent Sign +#define ISO_8859_1_A3 0 // 163 £ Pound Sign +#define ISO_8859_1_A4 KEY_BACKSLASH + ALTGR_MASK // 164 ¤ Currency Sign +#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR +#define ISO_8859_1_A7 KEY_QUOTE // 167 § SECTION SIGN +#define ISO_8859_1_A8 0 // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN +#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN +#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF 0 // 175 ¯ MACRON +#define ISO_8859_1_B0 DEGREE_SIGN_BITS + KEY_SPACE // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN +#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT +#define ISO_8859_1_B8 CEDILLA_BITS + KEY_SPACE // 184 ¸ CEDILLA +#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 0 // 192 À A GRAVE +#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE +#define ISO_8859_1_C2 0 // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 0 // 195 Ã A TILDE +#define ISO_8859_1_C4 0 // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE +#define ISO_8859_1_C6 0 // 198 Æ AE +#define ISO_8859_1_C7 CEDILLA_BITS + KEY_C + SHIFT_MASK // 199 Ç C CEDILLA +#define ISO_8859_1_C8 0 // 200 È E GRAVE +#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE +#define ISO_8859_1_CA 0 // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB 0 // 203 Ë E DIAERESIS +#define ISO_8859_1_CC 0 // 204 Ì I GRAVE +#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE +#define ISO_8859_1_CE 0 // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF 0 // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 0 // 208 Ð ETH +#define ISO_8859_1_D1 0 // 209 Ñ N TILDE +#define ISO_8859_1_D2 0 // 210 Ò O GRAVE +#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE +#define ISO_8859_1_D4 0 // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 0 // 213 Õ O TILDE +#define ISO_8859_1_D6 0 // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 KEY_RIGHT_BRACE + ALTGR_MASK // 215 × MULTIPLICATION +#define ISO_8859_1_D8 0 // 216 Ø O STROKE +#define ISO_8859_1_D9 0 // 217 Ù U GRAVE +#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE +#define ISO_8859_1_DB 0 // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC 0 // 220 Ü U DIAERESIS +#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Z + SHIFT_MASK // 221 Ý Y ACUTE +#define ISO_8859_1_DE 0 // 222 Þ THORN +#define ISO_8859_1_DF KEY_QUOTE + ALTGR_MASK // 223 ß SHARP S TODO: testme +#define ISO_8859_1_E0 0 // 224 à a GRAVE +#define ISO_8859_1_E1 KEY_8 // 225 á a ACUTE +#define ISO_8859_1_E2 0 // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 0 // 227 ã a TILDE +#define ISO_8859_1_E4 0 // 228 ä a DIAERESIS +#define ISO_8859_1_E5 0 // 229 å a RING ABOVE +#define ISO_8859_1_E6 0 // 230 æ ae +#define ISO_8859_1_E7 CEDILLA_BITS + KEY_C // 231 ç c CEDILLA +#define ISO_8859_1_E8 0 // 232 è e GRAVE +#define ISO_8859_1_E9 KEY_0 // 233 é e ACUTE +#define ISO_8859_1_EA 0 // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB 0 // 235 ë e DIAERESIS +#define ISO_8859_1_EC 0 // 236 ì i GRAVE +#define ISO_8859_1_ED KEY_9 // 237 í i ACUTE +#define ISO_8859_1_EE 0 // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF 0 // 239 ï i DIAERESIS +#define ISO_8859_1_F0 0 // 240 ð ETH +#define ISO_8859_1_F1 0 // 241 ñ n TILDE +#define ISO_8859_1_F2 0 // 242 ò o GRAVE +#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE +#define ISO_8859_1_F4 0 // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 0 // 245 õ o TILDE +#define ISO_8859_1_F6 0 // 246 ö o DIAERESIS +#define ISO_8859_1_F7 KEY_LEFT_BRACE + ALTGR_MASK // 247 ÷ DIVISION +#define ISO_8859_1_F8 0 // 248 ø o STROKE +#define ISO_8859_1_F9 0 // 249 ù u GRAVE +#define ISO_8859_1_FA KEY_LEFT_BRACE // 250 ú u ACUTE +#define ISO_8859_1_FB 0 // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC 0 // 252 ü u DIAERESIS +#define ISO_8859_1_FD KEY_7 // 253 ý y ACUTE +#define ISO_8859_1_FE 0 // 254 þ THORN +#define ISO_8859_1_FF 0 // 255 ÿ y DIAERESIS +#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign + +#define UNICODE_EXTRA00 0x011B // ě Small Letter E with caron +#define KEYCODE_EXTRA00 KEY_2 +#define UNICODE_EXTRA01 0x0161 // š Small Letter S with caron +#define KEYCODE_EXTRA01 KEY_3 +#define UNICODE_EXTRA02 0x010D // č Small Letter C with caron +#define KEYCODE_EXTRA02 KEY_4 +#define UNICODE_EXTRA03 0x0159 // ř Small Letter R with caron +#define KEYCODE_EXTRA03 KEY_5 +#define UNICODE_EXTRA04 0x017E // ž Small Letter Z with caron +#define KEYCODE_EXTRA04 KEY_6 +#define UNICODE_EXTRA05 0x016F // ů Small Letter U with ring above +#define KEYCODE_EXTRA05 KEY_SEMICOLON +#define UNICODE_EXTRA06 0x0111 // đ Small Letter D with stroke +#define KEYCODE_EXTRA06 KEY_S + ALTGR_MASK +#define UNICODE_EXTRA07 0x0110 // Đ Capital Letter D with stroke +#define KEYCODE_EXTRA07 KEY_D + ALTGR_MASK +#define UNICODE_EXTRA08 0x0142 // ł Small Letter L with stroke +#define KEYCODE_EXTRA08 KEY_K + ALTGR_MASK +#define UNICODE_EXTRA09 0x0141 // Ł Capital Letter L with stroke +#define KEYCODE_EXTRA09 KEY_L + ALTGR_MASK +#define UNICODE_EXTRA0A 0x20AC // € Euro Sign +#define KEYCODE_EXTRA0A KEY_E + ALTGR_MASK + +#endif // LAYOUT_CZECH + + + + + + +extern const KEYCODE_TYPE keycodes_ascii[]; +extern const KEYCODE_TYPE keycodes_iso_8859_1[]; + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif From a8ada58e919ffb8d7a248eae0e7303f39b46f407 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Tue, 8 Sep 2015 17:31:29 +0200 Subject: [PATCH 213/602] Different inclusion of Teensy Keyboard Moved Report IDs to the HID-Project.h file --- plugins/KeyboardioHID/src/Consumer.h | 4 +- plugins/KeyboardioHID/src/Gamepad.h | 4 +- plugins/KeyboardioHID/src/HID-Project.h | 48 +++++++++++++- .../KeyboardioHID/src/ImprovedKeyboard.cpp | 2 +- plugins/KeyboardioHID/src/ImprovedKeyboard.h | 4 +- .../KeyboardioHID/src/Keylayout_German.cpp | 2 +- plugins/KeyboardioHID/src/System.h | 4 +- plugins/KeyboardioHID/src/TeensyKeyboard.cpp | 66 ++++++++++++++++++- plugins/KeyboardioHID/src/TeensyKeyboard.h | 7 +- plugins/KeyboardioHID/src/TeensyKeylayouts.c | 66 ------------------- plugins/KeyboardioHID/src/TeensyKeylayouts.h | 17 ++++- 11 files changed, 134 insertions(+), 90 deletions(-) delete mode 100644 plugins/KeyboardioHID/src/TeensyKeylayouts.c diff --git a/plugins/KeyboardioHID/src/Consumer.h b/plugins/KeyboardioHID/src/Consumer.h index 041660ae9a..377a59f40a 100644 --- a/plugins/KeyboardioHID/src/Consumer.h +++ b/plugins/KeyboardioHID/src/Consumer.h @@ -35,9 +35,7 @@ THE SOFTWARE. // Consumer //================================================================================ -#ifndef HID_REPORTID_CONSUMERCONTROL -#define HID_REPORTID_CONSUMERCONTROL 4 -#endif +#include "HID-Project.h" // Media key definitions, see official USB docs for more #define MEDIA_FAST_FORWARD 0xB3 diff --git a/plugins/KeyboardioHID/src/Gamepad.h b/plugins/KeyboardioHID/src/Gamepad.h index ecd478d8ca..70881a3c6b 100644 --- a/plugins/KeyboardioHID/src/Gamepad.h +++ b/plugins/KeyboardioHID/src/Gamepad.h @@ -35,9 +35,7 @@ THE SOFTWARE. // Gamepad //================================================================================ -#ifndef HID_REPORTID_GAMEPAD -#define HID_REPORTID_GAMEPAD 6 -#endif +#include "HID-Project.h" // Dpad directions #define GAMEPAD_DPAD_CENTERED 0 diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index 0287128076..e9dadcde96 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -33,12 +33,58 @@ THE SOFTWARE. #error "This is not an USB AVR or you use an old version of the IDE." #endif +//#define LAYOUT_US_ENGLISH +//#define LAYOUT_CANADIAN_FRENCH +//#define LAYOUT_CANADIAN_MULTILINGUAL +//#define LAYOUT_DANISH +//#define LAYOUT_FINNISH +//#define LAYOUT_FRENCH +//#define LAYOUT_FRENCH_BELGIAN +//#define LAYOUT_FRENCH_SWISS +//#define LAYOUT_GERMAN +//#define LAYOUT_GERMAN_MAC +//#define LAYOUT_GERMAN_SWISS +//#define LAYOUT_ICELANDIC +//#define LAYOUT_IRISH +//#define LAYOUT_ITALIAN +//#define LAYOUT_NORWEGIAN +//#define LAYOUT_PORTUGUESE +//#define LAYOUT_PORTUGUESE_BRAZILIAN +//#define LAYOUT_SPANISH +//#define LAYOUT_SPANISH_LATIN_AMERICA +//#define LAYOUT_SWEDISH +//#define LAYOUT_TURKISH +//#define LAYOUT_UNITED_KINGDOM +//#define LAYOUT_US_INTERNATIONAL + +#ifndef HID_REPORTID_KEYBOARD +#define HID_REPORTID_KEYBOARD 2 +#endif + +#ifndef HID_REPORTID_CONSUMERCONTROL +#define HID_REPORTID_CONSUMERCONTROL 4 +#endif + +#ifndef HID_REPORTID_SYSTEMCONTROL +#define HID_REPORTID_SYSTEMCONTROL 5 +#endif + +#ifndef HID_REPORTID_GAMEPAD +#define HID_REPORTID_GAMEPAD 6 +#endif + +#ifndef HID_REPORTID_TEENSY_KEYBOARD +#define HID_REPORTID_TEENSY_KEYBOARD 9 +#endif + // Include all HID libraries (.a linkage required to work) properly -//#include "ImprovedKeyboard.h" +#include "ImprovedKeyboard.h" #include "AbsoluteMouse.h" #include "Consumer.h" #include "Gamepad.h" #include "System.h" // Include Teensy HID afterwards to overwrite key definitions if used +#ifdef USE_TEENSY_KEYBOARD #include "TeensyKeyboard.h" +#endif diff --git a/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp b/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp index 3b4f926475..2b512e4edd 100644 --- a/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp +++ b/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp @@ -35,7 +35,7 @@ static const u8 _hidReportDescriptor[] PROGMEM = { 0x05, 0x01, // USAGE_PAGE (Generic Desktop) // 47 0x09, 0x06, // USAGE (Keyboard) 0xa1, 0x01, // COLLECTION (Application) - 0x85, HID_REPORTID_KEYBOARD, // REPORT_ID (2) + 0x85, HID_REPORTID_KEYBOARD, // REPORT_ID 0x05, 0x07, // USAGE_PAGE (Keyboard) 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl) diff --git a/plugins/KeyboardioHID/src/ImprovedKeyboard.h b/plugins/KeyboardioHID/src/ImprovedKeyboard.h index 1ba70301f4..659be475cc 100644 --- a/plugins/KeyboardioHID/src/ImprovedKeyboard.h +++ b/plugins/KeyboardioHID/src/ImprovedKeyboard.h @@ -36,9 +36,7 @@ THE SOFTWARE. //================================================================================ // Keyboard -#ifndef HID_REPORTID_KEYBOARD -#define HID_REPORTID_KEYBOARD 2 -#endif +#include "HID-Project.h" #define KEY_PRINT 0xCE #define KEY_NUM_LOCK 0xDB diff --git a/plugins/KeyboardioHID/src/Keylayout_German.cpp b/plugins/KeyboardioHID/src/Keylayout_German.cpp index 65ef07ebd8..0b3bb52dfe 100644 --- a/plugins/KeyboardioHID/src/Keylayout_German.cpp +++ b/plugins/KeyboardioHID/src/Keylayout_German.cpp @@ -156,7 +156,7 @@ static const uint8_t _asciimap[128] PROGMEM = 0x35|SHIFT, // ~ 0 // DEL }; -Keyboard_ Keyboard; + uint8_t Keyboard_::getKeycode(uint8_t k){ return pgm_read_byte(_asciimap + k); } diff --git a/plugins/KeyboardioHID/src/System.h b/plugins/KeyboardioHID/src/System.h index fbe42c1bcf..8a778ae38e 100644 --- a/plugins/KeyboardioHID/src/System.h +++ b/plugins/KeyboardioHID/src/System.h @@ -35,9 +35,7 @@ THE SOFTWARE. // System //================================================================================ -#ifndef HID_REPORTID_SYSTEMCONTROL -#define HID_REPORTID_SYSTEMCONTROL 5 -#endif +#include "HID-Project.h" #define SYSTEM_POWER_DOWN 0x81 #define SYSTEM_SLEEP 0x82 diff --git a/plugins/KeyboardioHID/src/TeensyKeyboard.cpp b/plugins/KeyboardioHID/src/TeensyKeyboard.cpp index 770035046a..46d7e484b1 100644 --- a/plugins/KeyboardioHID/src/TeensyKeyboard.cpp +++ b/plugins/KeyboardioHID/src/TeensyKeyboard.cpp @@ -256,7 +256,7 @@ void usb_keyboard_class::set_media(uint8_t c) void usb_keyboard_class::send_now(void) { - HID.SendReport(HID_REPORTID_KEYBOARD,keyboard_report_data,sizeof(keyboard_report_data)); + HID.SendReport(HID_REPORTID_TEENSY_KEYBOARD,keyboard_report_data,sizeof(keyboard_report_data)); } @@ -386,3 +386,67 @@ void usb_keyboard_class::releaseAll(void) } usb_keyboard_class TeensyKeyboard = usb_keyboard_class(); + +#include +#include + +#ifdef M +#undef M +#endif +#define M(n) ((n) & 0x3FFF) + +const KEYCODE_TYPE PROGMEM keycodes_ascii[] = { + M(ASCII_20), M(ASCII_21), M(ASCII_22), M(ASCII_23), + M(ASCII_24), M(ASCII_25), M(ASCII_26), M(ASCII_27), + M(ASCII_28), M(ASCII_29), M(ASCII_2A), M(ASCII_2B), + M(ASCII_2C), M(ASCII_2D), M(ASCII_2E), M(ASCII_2F), + M(ASCII_30), M(ASCII_31), M(ASCII_32), M(ASCII_33), + M(ASCII_34), M(ASCII_35), M(ASCII_36), M(ASCII_37), + M(ASCII_38), M(ASCII_39), M(ASCII_3A), M(ASCII_3B), + M(ASCII_3C), M(ASCII_3D), M(ASCII_3E), M(ASCII_3F), + M(ASCII_40), M(ASCII_41), M(ASCII_42), M(ASCII_43), + M(ASCII_44), M(ASCII_45), M(ASCII_46), M(ASCII_47), + M(ASCII_48), M(ASCII_49), M(ASCII_4A), M(ASCII_4B), + M(ASCII_4C), M(ASCII_4D), M(ASCII_4E), M(ASCII_4F), + M(ASCII_50), M(ASCII_51), M(ASCII_52), M(ASCII_53), + M(ASCII_54), M(ASCII_55), M(ASCII_56), M(ASCII_57), + M(ASCII_58), M(ASCII_59), M(ASCII_5A), M(ASCII_5B), + M(ASCII_5C), M(ASCII_5D), M(ASCII_5E), M(ASCII_5F), + M(ASCII_60), M(ASCII_61), M(ASCII_62), M(ASCII_63), + M(ASCII_64), M(ASCII_65), M(ASCII_66), M(ASCII_67), + M(ASCII_68), M(ASCII_69), M(ASCII_6A), M(ASCII_6B), + M(ASCII_6C), M(ASCII_6D), M(ASCII_6E), M(ASCII_6F), + M(ASCII_70), M(ASCII_71), M(ASCII_72), M(ASCII_73), + M(ASCII_74), M(ASCII_75), M(ASCII_76), M(ASCII_77), + M(ASCII_78), M(ASCII_79), M(ASCII_7A), M(ASCII_7B), + M(ASCII_7C), M(ASCII_7D), M(ASCII_7E), M(ASCII_7F) +}; + +#ifdef ISO_8859_1_A0 +const KEYCODE_TYPE PROGMEM keycodes_iso_8859_1[] = { + M(ISO_8859_1_A0), M(ISO_8859_1_A1), M(ISO_8859_1_A2), M(ISO_8859_1_A3), + M(ISO_8859_1_A4), M(ISO_8859_1_A5), M(ISO_8859_1_A6), M(ISO_8859_1_A7), + M(ISO_8859_1_A8), M(ISO_8859_1_A9), M(ISO_8859_1_AA), M(ISO_8859_1_AB), + M(ISO_8859_1_AC), M(ISO_8859_1_AD), M(ISO_8859_1_AE), M(ISO_8859_1_AF), + M(ISO_8859_1_B0), M(ISO_8859_1_B1), M(ISO_8859_1_B2), M(ISO_8859_1_B3), + M(ISO_8859_1_B4), M(ISO_8859_1_B5), M(ISO_8859_1_B6), M(ISO_8859_1_B7), + M(ISO_8859_1_B8), M(ISO_8859_1_B9), M(ISO_8859_1_BA), M(ISO_8859_1_BB), + M(ISO_8859_1_BC), M(ISO_8859_1_BD), M(ISO_8859_1_BE), M(ISO_8859_1_BF), + M(ISO_8859_1_C0), M(ISO_8859_1_C1), M(ISO_8859_1_C2), M(ISO_8859_1_C3), + M(ISO_8859_1_C4), M(ISO_8859_1_C5), M(ISO_8859_1_C6), M(ISO_8859_1_C7), + M(ISO_8859_1_C8), M(ISO_8859_1_C9), M(ISO_8859_1_CA), M(ISO_8859_1_CB), + M(ISO_8859_1_CC), M(ISO_8859_1_CD), M(ISO_8859_1_CE), M(ISO_8859_1_CF), + M(ISO_8859_1_D0), M(ISO_8859_1_D1), M(ISO_8859_1_D2), M(ISO_8859_1_D3), + M(ISO_8859_1_D4), M(ISO_8859_1_D5), M(ISO_8859_1_D6), M(ISO_8859_1_D7), + M(ISO_8859_1_D8), M(ISO_8859_1_D9), M(ISO_8859_1_DA), M(ISO_8859_1_DB), + M(ISO_8859_1_DC), M(ISO_8859_1_DD), M(ISO_8859_1_DE), M(ISO_8859_1_DF), + M(ISO_8859_1_E0), M(ISO_8859_1_E1), M(ISO_8859_1_E2), M(ISO_8859_1_E3), + M(ISO_8859_1_E4), M(ISO_8859_1_E5), M(ISO_8859_1_E6), M(ISO_8859_1_E7), + M(ISO_8859_1_E8), M(ISO_8859_1_E9), M(ISO_8859_1_EA), M(ISO_8859_1_EB), + M(ISO_8859_1_EC), M(ISO_8859_1_ED), M(ISO_8859_1_EE), M(ISO_8859_1_EF), + M(ISO_8859_1_F0), M(ISO_8859_1_F1), M(ISO_8859_1_F2), M(ISO_8859_1_F3), + M(ISO_8859_1_F4), M(ISO_8859_1_F5), M(ISO_8859_1_F6), M(ISO_8859_1_F7), + M(ISO_8859_1_F8), M(ISO_8859_1_F9), M(ISO_8859_1_FA), M(ISO_8859_1_FB), + M(ISO_8859_1_FC), M(ISO_8859_1_FD), M(ISO_8859_1_FE), M(ISO_8859_1_FF) +}; +#endif // ISO_8859_1_A0 diff --git a/plugins/KeyboardioHID/src/TeensyKeyboard.h b/plugins/KeyboardioHID/src/TeensyKeyboard.h index bc02f6c6e7..639e332747 100644 --- a/plugins/KeyboardioHID/src/TeensyKeyboard.h +++ b/plugins/KeyboardioHID/src/TeensyKeyboard.h @@ -31,18 +31,15 @@ #else +#include "HID-Project.h" #include "TeensyKeylayouts.h" -#ifndef HID_REPORTID_KEYBOARD -#define HID_REPORTID_KEYBOARD 2 -#endif - // 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), - 0x85, HID_REPORTID_KEYBOARD, // REPORT_ID (2) + 0x85, HID_REPORTID_TEENSY_KEYBOARD, // REPORT_ID 0x75, 0x01, // Report Size (1), 0x95, 0x08, // Report Count (8), 0x05, 0x07, // Usage Page (Key Codes), diff --git a/plugins/KeyboardioHID/src/TeensyKeylayouts.c b/plugins/KeyboardioHID/src/TeensyKeylayouts.c deleted file mode 100644 index 9ff3b673bd..0000000000 --- a/plugins/KeyboardioHID/src/TeensyKeylayouts.c +++ /dev/null @@ -1,66 +0,0 @@ -#include -#include - -#include "TeensyKeylayouts.h" - -#ifdef M -#undef M -#endif -#define M(n) ((n) & 0x3FFF) - -const KEYCODE_TYPE PROGMEM keycodes_ascii[] = { - M(ASCII_20), M(ASCII_21), M(ASCII_22), M(ASCII_23), - M(ASCII_24), M(ASCII_25), M(ASCII_26), M(ASCII_27), - M(ASCII_28), M(ASCII_29), M(ASCII_2A), M(ASCII_2B), - M(ASCII_2C), M(ASCII_2D), M(ASCII_2E), M(ASCII_2F), - M(ASCII_30), M(ASCII_31), M(ASCII_32), M(ASCII_33), - M(ASCII_34), M(ASCII_35), M(ASCII_36), M(ASCII_37), - M(ASCII_38), M(ASCII_39), M(ASCII_3A), M(ASCII_3B), - M(ASCII_3C), M(ASCII_3D), M(ASCII_3E), M(ASCII_3F), - M(ASCII_40), M(ASCII_41), M(ASCII_42), M(ASCII_43), - M(ASCII_44), M(ASCII_45), M(ASCII_46), M(ASCII_47), - M(ASCII_48), M(ASCII_49), M(ASCII_4A), M(ASCII_4B), - M(ASCII_4C), M(ASCII_4D), M(ASCII_4E), M(ASCII_4F), - M(ASCII_50), M(ASCII_51), M(ASCII_52), M(ASCII_53), - M(ASCII_54), M(ASCII_55), M(ASCII_56), M(ASCII_57), - M(ASCII_58), M(ASCII_59), M(ASCII_5A), M(ASCII_5B), - M(ASCII_5C), M(ASCII_5D), M(ASCII_5E), M(ASCII_5F), - M(ASCII_60), M(ASCII_61), M(ASCII_62), M(ASCII_63), - M(ASCII_64), M(ASCII_65), M(ASCII_66), M(ASCII_67), - M(ASCII_68), M(ASCII_69), M(ASCII_6A), M(ASCII_6B), - M(ASCII_6C), M(ASCII_6D), M(ASCII_6E), M(ASCII_6F), - M(ASCII_70), M(ASCII_71), M(ASCII_72), M(ASCII_73), - M(ASCII_74), M(ASCII_75), M(ASCII_76), M(ASCII_77), - M(ASCII_78), M(ASCII_79), M(ASCII_7A), M(ASCII_7B), - M(ASCII_7C), M(ASCII_7D), M(ASCII_7E), M(ASCII_7F) -}; - -#ifdef ISO_8859_1_A0 -const KEYCODE_TYPE PROGMEM keycodes_iso_8859_1[] = { - M(ISO_8859_1_A0), M(ISO_8859_1_A1), M(ISO_8859_1_A2), M(ISO_8859_1_A3), - M(ISO_8859_1_A4), M(ISO_8859_1_A5), M(ISO_8859_1_A6), M(ISO_8859_1_A7), - M(ISO_8859_1_A8), M(ISO_8859_1_A9), M(ISO_8859_1_AA), M(ISO_8859_1_AB), - M(ISO_8859_1_AC), M(ISO_8859_1_AD), M(ISO_8859_1_AE), M(ISO_8859_1_AF), - M(ISO_8859_1_B0), M(ISO_8859_1_B1), M(ISO_8859_1_B2), M(ISO_8859_1_B3), - M(ISO_8859_1_B4), M(ISO_8859_1_B5), M(ISO_8859_1_B6), M(ISO_8859_1_B7), - M(ISO_8859_1_B8), M(ISO_8859_1_B9), M(ISO_8859_1_BA), M(ISO_8859_1_BB), - M(ISO_8859_1_BC), M(ISO_8859_1_BD), M(ISO_8859_1_BE), M(ISO_8859_1_BF), - M(ISO_8859_1_C0), M(ISO_8859_1_C1), M(ISO_8859_1_C2), M(ISO_8859_1_C3), - M(ISO_8859_1_C4), M(ISO_8859_1_C5), M(ISO_8859_1_C6), M(ISO_8859_1_C7), - M(ISO_8859_1_C8), M(ISO_8859_1_C9), M(ISO_8859_1_CA), M(ISO_8859_1_CB), - M(ISO_8859_1_CC), M(ISO_8859_1_CD), M(ISO_8859_1_CE), M(ISO_8859_1_CF), - M(ISO_8859_1_D0), M(ISO_8859_1_D1), M(ISO_8859_1_D2), M(ISO_8859_1_D3), - M(ISO_8859_1_D4), M(ISO_8859_1_D5), M(ISO_8859_1_D6), M(ISO_8859_1_D7), - M(ISO_8859_1_D8), M(ISO_8859_1_D9), M(ISO_8859_1_DA), M(ISO_8859_1_DB), - M(ISO_8859_1_DC), M(ISO_8859_1_DD), M(ISO_8859_1_DE), M(ISO_8859_1_DF), - M(ISO_8859_1_E0), M(ISO_8859_1_E1), M(ISO_8859_1_E2), M(ISO_8859_1_E3), - M(ISO_8859_1_E4), M(ISO_8859_1_E5), M(ISO_8859_1_E6), M(ISO_8859_1_E7), - M(ISO_8859_1_E8), M(ISO_8859_1_E9), M(ISO_8859_1_EA), M(ISO_8859_1_EB), - M(ISO_8859_1_EC), M(ISO_8859_1_ED), M(ISO_8859_1_EE), M(ISO_8859_1_EF), - M(ISO_8859_1_F0), M(ISO_8859_1_F1), M(ISO_8859_1_F2), M(ISO_8859_1_F3), - M(ISO_8859_1_F4), M(ISO_8859_1_F5), M(ISO_8859_1_F6), M(ISO_8859_1_F7), - M(ISO_8859_1_F8), M(ISO_8859_1_F9), M(ISO_8859_1_FA), M(ISO_8859_1_FB), - M(ISO_8859_1_FC), M(ISO_8859_1_FD), M(ISO_8859_1_FE), M(ISO_8859_1_FF) -}; -#endif // ISO_8859_1_A0 - diff --git a/plugins/KeyboardioHID/src/TeensyKeylayouts.h b/plugins/KeyboardioHID/src/TeensyKeylayouts.h index 58ce9b21b3..10bf60217c 100644 --- a/plugins/KeyboardioHID/src/TeensyKeylayouts.h +++ b/plugins/KeyboardioHID/src/TeensyKeylayouts.h @@ -47,7 +47,7 @@ extern "C"{ //#define LAYOUT_FRENCH //#define LAYOUT_FRENCH_BELGIAN //#define LAYOUT_FRENCH_SWISS -#define LAYOUT_GERMAN +//#define LAYOUT_GERMAN //#define LAYOUT_GERMAN_MAC //#define LAYOUT_GERMAN_SWISS //#define LAYOUT_ICELANDIC @@ -60,10 +60,21 @@ extern "C"{ //#define LAYOUT_SPANISH_LATIN_AMERICA //#define LAYOUT_SWEDISH //#define LAYOUT_TURKISH -//#define LAYOUT_UNITED_KINGDOM +//#define LAYOUT_UNITED_KINGDOM //#define LAYOUT_US_INTERNATIONAL - +// Default US keyboard layout +#if !defined(LAYOUT_CANADIAN_FRENCH) && !defined(LAYOUT_CANADIAN_MULTILINGUAL) \ +&& !defined(LAYOUT_DANISH) && !defined(LAYOUT_FINNISH) && !defined(LAYOUT_FRENCH) \ +&& !defined(LAYOUT_FRENCH_BELGIAN) && !defined(LAYOUT_FRENCH_SWISS) && !defined(LAYOUT_GERMAN) \ +&& !defined(LAYOUT_GERMAN_MAC) && !defined(LAYOUT_GERMAN_SWISS) && !defined(LAYOUT_ICELANDIC) \ +&& !defined(LAYOUT_IRISH) && !defined(LAYOUT_ITALIAN) && !defined(LAYOUT_NORWEGIAN) \ +&& !defined(LAYOUT_PORTUGUESE) && !defined(LAYOUT_PORTUGUESE_BRAZILIAN) \ +&& !defined(LAYOUT_SPANISH) && !defined(LAYOUT_SPANISH_LATIN_AMERICA) \ +&& !defined(LAYOUT_SWEDISH) && !defined(LAYOUT_TURKISH) && !defined(LAYOUT_UNITED_KINGDOM) \ +&& !defined(LAYOUT_US_INTERNATIONAL) && !defined(LAYOUT_US_ENGLISH) +#define LAYOUT_US_ENGLISH +#endif // http://en.wikipedia.org/wiki/Keyboard_layout From 72559c7ff081b302c6efa9819f066317b5e50184 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Tue, 8 Sep 2015 17:50:01 +0200 Subject: [PATCH 214/602] Some Generailzations --- plugins/KeyboardioHID/src/AbsoluteMouse.h | 6 +- plugins/KeyboardioHID/src/Consumer.h | 2 - plugins/KeyboardioHID/src/Gamepad.h | 2 - plugins/KeyboardioHID/src/HID-Project.h | 28 +++ .../KeyboardioHID/src/ImprovedKeyboard.cpp | 135 -------------- plugins/KeyboardioHID/src/ImprovedKeyboard.h | 56 +----- .../KeyboardioHID/src/Keylayout_German.cpp | 166 ------------------ plugins/KeyboardioHID/src/Keylayout_US.cpp | 166 ------------------ plugins/KeyboardioHID/src/System.h | 2 - plugins/KeyboardioHID/src/TeensyKeyboard.h | 1 - plugins/KeyboardioHID/src/TeensyKeylayouts.h | 13 -- 11 files changed, 31 insertions(+), 546 deletions(-) delete mode 100644 plugins/KeyboardioHID/src/Keylayout_German.cpp delete mode 100644 plugins/KeyboardioHID/src/Keylayout_US.cpp diff --git a/plugins/KeyboardioHID/src/AbsoluteMouse.h b/plugins/KeyboardioHID/src/AbsoluteMouse.h index 94b2eeefa2..9aadca64c9 100644 --- a/plugins/KeyboardioHID/src/AbsoluteMouse.h +++ b/plugins/KeyboardioHID/src/AbsoluteMouse.h @@ -35,9 +35,7 @@ THE SOFTWARE. //================================================================================ // Mouse -#ifndef HID_REPORTID_MOUSE_ABSOLUTE -#define HID_REPORTID_MOUSE_ABSOLUTE 7 -#endif +#include "HID-Project.h" #define MOUSE_LEFT (1 << 0) #define MOUSE_RIGHT (1 << 1) @@ -100,8 +98,6 @@ typedef union{ }; } HID_MouseAbsoluteReport_Data_t; -extern HID_ HID; - class AbsMouse_ { private: diff --git a/plugins/KeyboardioHID/src/Consumer.h b/plugins/KeyboardioHID/src/Consumer.h index 377a59f40a..1039137017 100644 --- a/plugins/KeyboardioHID/src/Consumer.h +++ b/plugins/KeyboardioHID/src/Consumer.h @@ -95,8 +95,6 @@ typedef union { }; } HID_ConsumerControlReport_Data_t; -extern HID_ HID; - class Consumer_ { public: inline Consumer_(void) { diff --git a/plugins/KeyboardioHID/src/Gamepad.h b/plugins/KeyboardioHID/src/Gamepad.h index 70881a3c6b..1a09c24cd6 100644 --- a/plugins/KeyboardioHID/src/Gamepad.h +++ b/plugins/KeyboardioHID/src/Gamepad.h @@ -154,8 +154,6 @@ typedef union { }; } HID_GamepadReport_Data_t; -extern HID_ HID; - class Gamepad_{ public: inline Gamepad_(void){ diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index e9dadcde96..8664c4682d 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -57,6 +57,23 @@ THE SOFTWARE. //#define LAYOUT_UNITED_KINGDOM //#define LAYOUT_US_INTERNATIONAL +// Default US keyboard layout +#if !defined(LAYOUT_CANADIAN_FRENCH) && !defined(LAYOUT_CANADIAN_MULTILINGUAL) \ +&& !defined(LAYOUT_DANISH) && !defined(LAYOUT_FINNISH) && !defined(LAYOUT_FRENCH) \ +&& !defined(LAYOUT_FRENCH_BELGIAN) && !defined(LAYOUT_FRENCH_SWISS) && !defined(LAYOUT_GERMAN) \ +&& !defined(LAYOUT_GERMAN_MAC) && !defined(LAYOUT_GERMAN_SWISS) && !defined(LAYOUT_ICELANDIC) \ +&& !defined(LAYOUT_IRISH) && !defined(LAYOUT_ITALIAN) && !defined(LAYOUT_NORWEGIAN) \ +&& !defined(LAYOUT_PORTUGUESE) && !defined(LAYOUT_PORTUGUESE_BRAZILIAN) \ +&& !defined(LAYOUT_SPANISH) && !defined(LAYOUT_SPANISH_LATIN_AMERICA) \ +&& !defined(LAYOUT_SWEDISH) && !defined(LAYOUT_TURKISH) && !defined(LAYOUT_UNITED_KINGDOM) \ +&& !defined(LAYOUT_US_INTERNATIONAL) && !defined(LAYOUT_US_ENGLISH) +#define LAYOUT_US_ENGLISH +#endif + +#ifndef HID_REPORTID_MOUSE +#define HID_REPORTID_MOUSE 1 +#endif + #ifndef HID_REPORTID_KEYBOARD #define HID_REPORTID_KEYBOARD 2 #endif @@ -73,11 +90,22 @@ THE SOFTWARE. #define HID_REPORTID_GAMEPAD 6 #endif +#ifndef HID_REPORTID_MOUSE_ABSOLUTE +#define HID_REPORTID_MOUSE_ABSOLUTE 7 +#endif + +#ifndef HID_REPORTID_NKRO_KEYBOARD +#define HID_REPORTID_NKRO_KEYBOARD 8 +#endif + #ifndef HID_REPORTID_TEENSY_KEYBOARD #define HID_REPORTID_TEENSY_KEYBOARD 9 #endif +extern HID_ HID; + // Include all HID libraries (.a linkage required to work) properly +#include "ImprovedKeylayouts.h" #include "ImprovedKeyboard.h" #include "AbsoluteMouse.h" #include "Consumer.h" diff --git a/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp b/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp index 2b512e4edd..74f93556d1 100644 --- a/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp +++ b/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp @@ -85,145 +85,10 @@ void Keyboard_::sendReport(KeyReport* keys) HID.SendReport(HID_REPORTID_KEYBOARD,keys,sizeof(KeyReport)); } -#define SHIFT 0x80 -static const uint8_t _asciimap[128] PROGMEM = -{ - 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 Keyboard_::getKeycode(uint8_t k){ return pgm_read_byte(_asciimap + k); } - // 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 diff --git a/plugins/KeyboardioHID/src/ImprovedKeyboard.h b/plugins/KeyboardioHID/src/ImprovedKeyboard.h index 659be475cc..7fb1aba162 100644 --- a/plugins/KeyboardioHID/src/ImprovedKeyboard.h +++ b/plugins/KeyboardioHID/src/ImprovedKeyboard.h @@ -21,8 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef KEYBOARD_h -#define KEYBOARD_h +#pragma once #include "HID.h" @@ -37,56 +36,7 @@ THE SOFTWARE. // Keyboard #include "HID-Project.h" - -#define KEY_PRINT 0xCE -#define KEY_NUM_LOCK 0xDB -#define KEY_SCROLL_LOCK 0xCF -#define KEY_PAUSE 0xD0 -#define KEY_MENU 0xED - -#define KEY_LEFT_CTRL 0x80 -#define KEY_LEFT_SHIFT 0x81 -#define KEY_LEFT_ALT 0x82 -#define KEY_LEFT_GUI 0x83 -#define KEY_LEFT_WINDOWS KEY_LEFT_GUI -#define KEY_RIGHT_CTRL 0x84 -#define KEY_RIGHT_SHIFT 0x85 -#define KEY_RIGHT_ALT 0x86 -#define KEY_RIGHT_GUI 0x87 -#define KEY_RIGHT_WINDOWS KEY_RIGHT_GUI - -#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_SPACE ' ' -#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 - -#define LED_NUM_LOCK 0x01 -#define LED_CAPS_LOCK 0x02 -#define LED_SCROLL_LOCK 0x04 +#include "ImprovedKeylayouts.h" // Low level key report: up to 6 keys and shift, ctrl etc at once typedef struct @@ -116,7 +66,5 @@ class Keyboard_ : public Print void useLayoutUS(void); }; extern Keyboard_ Keyboard; -extern HID_ HID; #endif -#endif diff --git a/plugins/KeyboardioHID/src/Keylayout_German.cpp b/plugins/KeyboardioHID/src/Keylayout_German.cpp deleted file mode 100644 index 0b3bb52dfe..0000000000 --- a/plugins/KeyboardioHID/src/Keylayout_German.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 "ImprovedKeyboard.h" - -#define SHIFT 0x80 -static const uint8_t _asciimap[128] PROGMEM = -{ - 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 - 0x1d|SHIFT, // Z - 0x1c|SHIFT, // Y - 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 - 0x1d, // z - 0x1c, // y - 0x2f|SHIFT, // - 0x31|SHIFT, // | - 0x30|SHIFT, // } - 0x35|SHIFT, // ~ - 0 // DEL -}; - -uint8_t Keyboard_::getKeycode(uint8_t k){ - return pgm_read_byte(_asciimap + k); -} - -void Keyboard_::useLayoutGerman(void) { - // Empty -} diff --git a/plugins/KeyboardioHID/src/Keylayout_US.cpp b/plugins/KeyboardioHID/src/Keylayout_US.cpp deleted file mode 100644 index 27b0f582fb..0000000000 --- a/plugins/KeyboardioHID/src/Keylayout_US.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 "ImprovedKeyboard.h" - -#define SHIFT 0x80 -static const uint8_t _asciimap[128] PROGMEM = -{ - 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 - 0x15|SHIFT, // Y - 0x14|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 Keyboard_::getKeycode(uint8_t k){ - return pgm_read_byte(_asciimap + k); -} - -void Keyboard_::useLayoutUS(void) { - // Empty -} diff --git a/plugins/KeyboardioHID/src/System.h b/plugins/KeyboardioHID/src/System.h index 8a778ae38e..22baebe0d2 100644 --- a/plugins/KeyboardioHID/src/System.h +++ b/plugins/KeyboardioHID/src/System.h @@ -65,8 +65,6 @@ typedef union{ uint8_t key; } HID_SystemControlReport_Data_t; -extern HID_ HID; - class System_{ public: inline System_(void){ diff --git a/plugins/KeyboardioHID/src/TeensyKeyboard.h b/plugins/KeyboardioHID/src/TeensyKeyboard.h index 639e332747..82a633527c 100644 --- a/plugins/KeyboardioHID/src/TeensyKeyboard.h +++ b/plugins/KeyboardioHID/src/TeensyKeyboard.h @@ -118,6 +118,5 @@ class usb_keyboard_class : public Print }; extern usb_keyboard_class TeensyKeyboard; -extern HID_ HID; #endif diff --git a/plugins/KeyboardioHID/src/TeensyKeylayouts.h b/plugins/KeyboardioHID/src/TeensyKeylayouts.h index 10bf60217c..f91749a923 100644 --- a/plugins/KeyboardioHID/src/TeensyKeylayouts.h +++ b/plugins/KeyboardioHID/src/TeensyKeylayouts.h @@ -63,19 +63,6 @@ extern "C"{ //#define LAYOUT_UNITED_KINGDOM //#define LAYOUT_US_INTERNATIONAL -// Default US keyboard layout -#if !defined(LAYOUT_CANADIAN_FRENCH) && !defined(LAYOUT_CANADIAN_MULTILINGUAL) \ -&& !defined(LAYOUT_DANISH) && !defined(LAYOUT_FINNISH) && !defined(LAYOUT_FRENCH) \ -&& !defined(LAYOUT_FRENCH_BELGIAN) && !defined(LAYOUT_FRENCH_SWISS) && !defined(LAYOUT_GERMAN) \ -&& !defined(LAYOUT_GERMAN_MAC) && !defined(LAYOUT_GERMAN_SWISS) && !defined(LAYOUT_ICELANDIC) \ -&& !defined(LAYOUT_IRISH) && !defined(LAYOUT_ITALIAN) && !defined(LAYOUT_NORWEGIAN) \ -&& !defined(LAYOUT_PORTUGUESE) && !defined(LAYOUT_PORTUGUESE_BRAZILIAN) \ -&& !defined(LAYOUT_SPANISH) && !defined(LAYOUT_SPANISH_LATIN_AMERICA) \ -&& !defined(LAYOUT_SWEDISH) && !defined(LAYOUT_TURKISH) && !defined(LAYOUT_UNITED_KINGDOM) \ -&& !defined(LAYOUT_US_INTERNATIONAL) && !defined(LAYOUT_US_ENGLISH) -#define LAYOUT_US_ENGLISH -#endif - // http://en.wikipedia.org/wiki/Keyboard_layout From cbe1a133a852059f25605408ffca1e50b51f1621 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Tue, 8 Sep 2015 17:57:04 +0200 Subject: [PATCH 215/602] removed weak asciimap wrapper --- plugins/KeyboardioHID/src/ImprovedKeyboard.cpp | 8 ++------ plugins/KeyboardioHID/src/ImprovedKeyboard.h | 1 - 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp b/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp index 74f93556d1..1a42027194 100644 --- a/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp +++ b/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp @@ -85,10 +85,6 @@ void Keyboard_::sendReport(KeyReport* keys) HID.SendReport(HID_REPORTID_KEYBOARD,keys,sizeof(KeyReport)); } -uint8_t Keyboard_::getKeycode(uint8_t k){ - return pgm_read_byte(_asciimap + k); -} - // 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 @@ -102,7 +98,7 @@ size_t Keyboard_::press(uint8_t k) _keyReport.modifiers |= (1<<(k-128)); k = 0; } else { // it's a printing key - k = getKeycode(k); + k = pgm_read_byte(_asciimap + k); if (!k) { setWriteError(); return 0; @@ -146,7 +142,7 @@ size_t Keyboard_::release(uint8_t k) _keyReport.modifiers &= ~(1<<(k-128)); k = 0; } else { // it's a printing key - k = getKeycode(k); + k = pgm_read_byte(_asciimap + k); if (!k) { return 0; } diff --git a/plugins/KeyboardioHID/src/ImprovedKeyboard.h b/plugins/KeyboardioHID/src/ImprovedKeyboard.h index 7fb1aba162..63fda4bc6c 100644 --- a/plugins/KeyboardioHID/src/ImprovedKeyboard.h +++ b/plugins/KeyboardioHID/src/ImprovedKeyboard.h @@ -51,7 +51,6 @@ class Keyboard_ : public Print private: KeyReport _keyReport; void sendReport(KeyReport* keys); - uint8_t getKeycode(uint8_t k) __attribute__((weak)); public: Keyboard_(void); void begin(void); From 5a4d7a05978817629978dc5fa60e015c6b6dc9f9 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Tue, 8 Sep 2015 18:10:32 +0200 Subject: [PATCH 216/602] Fixed Keyboard and added HID-Tables --- plugins/KeyboardioHID/src/HID-Project.h | 2 + plugins/KeyboardioHID/src/HID-Tables.h | 671 ++++++++++++++++++ .../KeyboardioHID/src/ImprovedKeyboard.cpp | 139 +++- plugins/KeyboardioHID/src/ImprovedKeyboard.h | 29 +- 4 files changed, 817 insertions(+), 24 deletions(-) create mode 100644 plugins/KeyboardioHID/src/HID-Tables.h diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index 8664c4682d..e2c20bcab4 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -104,6 +104,8 @@ THE SOFTWARE. extern HID_ HID; +#include "HID-Tables.h" + // Include all HID libraries (.a linkage required to work) properly #include "ImprovedKeylayouts.h" #include "ImprovedKeyboard.h" diff --git a/plugins/KeyboardioHID/src/HID-Tables.h b/plugins/KeyboardioHID/src/HID-Tables.h new file mode 100644 index 0000000000..066f0fb483 --- /dev/null +++ b/plugins/KeyboardioHID/src/HID-Tables.h @@ -0,0 +1,671 @@ +// These mappings were extracted and transcribed from +// http://www.usb.org_SLASH_developers_SLASH_devclass_docs_SLASH_Hut1_12v2.pdf +// +// In most cases, I've preserved the "official" USB Implementers forum +// "Usage Name", though I've standardized some abbreviations and spacing +// that were inconsistent in the original specification. Non alpha-numeric +// characters in symbol names were converted into those characters' names. +// +// To match Arduino code style, all hid usage names are fully upper case. +// +// Not every HID usage listed in this file is currently supported by Arduino +// In particular, any System Control or Consumer Control entry that doesn't +// have a comment indicating that it's "HID type OSC" will require additional +// code in the Arduino core to work. +// +// Non-working usages are listed here in the interest of not having to manually +// convert more usage names each and every time our HID stack gets a little bit +// better. +// +// +// -- Jesse Vincent , January 2014 + +#pragma once + +// System control mappings + +#define HID_SYSTEM_POWER_DOWN 0x81 // HID type OSC +#define HID_SYSTEM_SLEEP 0x82 // HID type OSC +#define HID_SYSTEM_WAKE_UP 0x83 // HID type OSC +#define HID_SYSTEM_CONTEXT_MENU 0x84 // HID type OSC +#define HID_SYSTEM_MAIN_MENU 0x85 // HID type OSC +#define HID_SYSTEM_APP_MENU 0x86 // HID type OSC +#define HID_SYSTEM_MENU_HELP 0x87 // HID type OSC +#define HID_SYSTEM_MENU_EXIT 0x88 // HID type OSC +#define HID_SYSTEM_MENU_SELECT 0x89 // HID type OSC +#define HID_SYSTEM_MENU_RIGHT 0x8A // HID type RTC +#define HID_SYSTEM_MENU_LEFT 0x8B // HID type RTC +#define HID_SYSTEM_MENU_UP 0x8C // HID type RTC +#define HID_SYSTEM_MENU_DOWN 0x8D // HID type RTC +#define HID_SYSTEM_COLD_RESTART 0x8E // HID type OSC +#define HID_SYSTEM_WARM_RESTART 0x8F // HID type OSC +#define HID_D_PAD_UP 0x90 // HID type OOC +#define HID_D_PAD_DOWN 0x91 // HID type OOC +#define HID_D_PAD_RIGHT 0x92 // HID type OOC +#define HID_D_PAD_LEFT 0x93 // HID type OOC +// 0x94-0x9F are reserved +#define HID_SYSTEM_DOCK 0xA0 // HID type OSC +#define HID_SYSTEM_UNDOCK 0xA1 // HID type OSC +#define HID_SYSTEM_SETUP 0xA2 // HID type OSC +#define HID_SYSTEM_BREAK 0xA3 // HID type OSC +#define HID_SYSTEM_DEBUGGER_BREAK 0xA4 // HID type OSC +#define HID_APPLICATION_BREAK 0xA5 // HID type OSC +#define HID_APPLICATION_DEBUGGER_BREAK 0xA6 // HID type OSC +#define HID_SYSTEM_SPEAKER_MUTE 0xA7 // HID type OSC +#define HID_SYSTEM_HIBERNATE 0xA8 // HID type OSC +// 0xA9-0xAF are reserved +#define HID_SYSTEM_DISPLAY_INVERT 0xB0 // HID type OSC +#define HID_SYSTEM_DISPLAY_INTERNAL 0xB1 // HID type OSC +#define HID_SYSTEM_DISPLAY_EXTERNAL 0xB2 // HID type OSC +#define HID_SYSTEM_DISPLAY_BOTH 0xB3 // HID type OSC +#define HID_SYSTEM_DISPLAY_DUAL 0xB4 // HID type OSC +#define HID_SYSTEM_DISPLAY_TOGGLE_INT_SLASH_EXT 0xB5 // HID type OSC +#define HID_SYSTEM_DISPLAY_SWAP_PRIMARY_SLASH_SECONDARY 0xB6 // HID type OSC +#define HID_SYSTEM_DISPLAY_LCD_AUTOSCALE 0xB7 // HID type OSC + +// Keyboard HID mappings + +// Reserved (no_event_indicated) 0x00 +#define HID_KEYBOARD_ERROR_ROLLOVER 0x01 +#define HID_KEYBOARD_POST_FAIL 0x02 +#define HID_KEYBOARD_ERROR_UNDEFINED 0x03 +#define HID_KEYBOARD_A_AND_A 0x04 +#define HID_KEYBOARD_B_AND_B 0x05 +#define HID_KEYBOARD_C_AND_C 0x06 +#define HID_KEYBOARD_D_AND_D 0x07 +#define HID_KEYBOARD_E_AND_E 0x08 +#define HID_KEYBOARD_F_AND_F 0x09 +#define HID_KEYBOARD_G_AND_G 0x0A +#define HID_KEYBOARD_H_AND_H 0x0B +#define HID_KEYBOARD_I_AND_I 0x0C +#define HID_KEYBOARD_J_AND_J 0x0D +#define HID_KEYBOARD_K_AND_K 0x0E +#define HID_KEYBOARD_L_AND_L 0x0F +#define HID_KEYBOARD_M_AND_M 0x10 +#define HID_KEYBOARD_N_AND_N 0x11 +#define HID_KEYBOARD_O_AND_O 0x12 +#define HID_KEYBOARD_P_AND_P 0x13 +#define HID_KEYBOARD_Q_AND_Q 0x14 +#define HID_KEYBOARD_R_AND_R 0x15 +#define HID_KEYBOARD_S_AND_S 0x16 +#define HID_KEYBOARD_T_AND_T 0x17 +#define HID_KEYBOARD_U_AND_U 0x18 +#define HID_KEYBOARD_V_AND_V 0x19 +#define HID_KEYBOARD_W_AND_W 0x1A +#define HID_KEYBOARD_X_AND_X 0x1B +#define HID_KEYBOARD_Y_AND_Y 0x1C +#define HID_KEYBOARD_Z_AND_Z 0x1D +#define HID_KEYBOARD_1_AND_EXCLAMATION_POINT 0x1E +#define HID_KEYBOARD_2_AND_AT 0x1F +#define HID_KEYBOARD_3_AND_POUND 0x20 +#define HID_KEYBOARD_4_AND_DOLLAR 0x21 +#define HID_KEYBOARD_5_AND_PERCENT 0x22 +#define HID_KEYBOARD_6_AND_CARAT 0x23 +#define HID_KEYBOARD_7_AND_AMPERSAND 0x24 +#define HID_KEYBOARD_8_AND_ASTERISK 0x25 +#define HID_KEYBOARD_9_AND_LEFT_PAREN 0x26 +#define HID_KEYBOARD_0_AND_RIGHT_PAREN 0x27 +#define HID_KEYBOARD_ENTER 0x28 // (MARKED AS ENTER_SLASH_RETURN) +#define HID_KEYBOARD_ESCAPE 0x29 +#define HID_KEYBOARD_DELETE 0x2A // (BACKSPACE) +#define HID_KEYBOARD_TAB 0x2B +#define HID_KEYBOARD_SPACEBAR 0x2C +#define HID_KEYBOARD_MINUS_AND_UNDERSCORE 0x2D // (UNDERSCORE) +#define HID_KEYBOARD_EQUALS_AND_PLUS 0x2E +#define HID_KEYBOARD_LEFT_BRACKET_AND_LEFT_CURLY_BRACE 0x2F +#define HID_KEYBOARD_RIGHT_BRACKET_AND_RIGHT_CURLY_BRACE 0x30 +#define HID_KEYBOARD_BACKSLASH_AND_PIPE 0x31 +#define HID_KEYBOARD_NON_US_POUND_AND_TILDE 0x32 +#define HID_KEYBOARD_SEMICOLON_AND_COLON 0x33 +#define HID_KEYBOARD_QUOTE_AND_DOUBLEQUOTE 0x34 +#define HID_KEYBOARD_GRAVE_ACCENT_AND_TILDE 0x35 +#define HID_KEYBOARD_COMMA_AND_LESS_THAN 0x36 +#define HID_KEYBOARD_PERIOD_AND_GREATER_THAN 0x37 +#define HID_KEYBOARD_SLASH_AND_QUESTION_MARK 0x38 +#define HID_KEYBOARD_CAPS_LOCK 0x39 +#define HID_KEYBOARD_F1 0x3A +#define HID_KEYBOARD_F2 0x3B +#define HID_KEYBOARD_F3 0x3C +#define HID_KEYBOARD_F4 0x3D +#define HID_KEYBOARD_F5 0x3E +#define HID_KEYBOARD_F6 0x3F +#define HID_KEYBOARD_F7 0x40 +#define HID_KEYBOARD_F8 0x41 +#define HID_KEYBOARD_F9 0x42 +#define HID_KEYBOARD_F10 0x43 +#define HID_KEYBOARD_F11 0x44 +#define HID_KEYBOARD_F12 0x45 +#define HID_KEYBOARD_PRINTSCREEN 0x46 +#define HID_KEYBOARD_SCROLL_LOCK 0x47 +#define HID_KEYBOARD_PAUSE 0x48 +#define HID_KEYBOARD_INSERT 0x49 +#define HID_KEYBOARD_HOME 0x4A +#define HID_KEYBOARD_PAGE_UP 0x4B +#define HID_KEYBOARD_DELETE_FORWARD 0x4C +#define HID_KEYBOARD_END 0x4D +#define HID_KEYBOARD_PAGE_DOWN 0x4E +#define HID_KEYBOARD_RIGHTARROW 0x4F +#define HID_KEYBOARD_LEFTARROW 0x50 +#define HID_KEYBOARD_DOWNARROW 0x51 +#define HID_KEYBOARD_UPARROW 0x52 +#define HID_KEYPAD_NUM_LOCK_AND_CLEAR 0x53 +#define HID_KEYPAD_DIVIDE 0x54 +#define HID_KEYPAD_MULTIPLY 0x55 +#define HID_KEYPAD_SUBTRACT 0x56 +#define HID_KEYPAD_ADD 0x57 +#define HID_KEYPAD_ENTER 0x58 +#define HID_KEYPAD_1_AND_END 0x59 +#define HID_KEYPAD_2_AND_DOWN_ARROW 0x5A +#define HID_KEYPAD_3_AND_PAGE_DOWN 0x5B +#define HID_KEYPAD_4_AND_LEFT_ARROW 0x5C +#define HID_KEYPAD_5 0x5D +#define HID_KEYPAD_6_AND_RIGHT_ARROW 0x5E +#define HID_KEYPAD_7_AND_HOME 0x5F +#define HID_KEYPAD_8_AND_UP_ARROW 0x60 +#define HID_KEYPAD_9_AND_PAGE_UP 0x61 +#define HID_KEYPAD_0_AND_INSERT 0x62 +#define HID_KEYPAD_PERIOD_AND_DELETE 0x63 +#define HID_KEYBOARD_NON_US_BACKSLASH_AND_PIPE 0x64 +#define HID_KEYBOARD_APPLICATION 0x65 +#define HID_KEYBOARD_POWER 0x66 +#define HID_KEYPAD_EQUALS 0x67 +#define HID_KEYBOARD_F13 0x68 +#define HID_KEYBOARD_F14 0x69 +#define HID_KEYBOARD_F15 0x6A +#define HID_KEYBOARD_F16 0x6B +#define HID_KEYBOARD_F17 0x6C +#define HID_KEYBOARD_F18 0x6D +#define HID_KEYBOARD_F19 0x6E +#define HID_KEYBOARD_F20 0x6F +#define HID_KEYBOARD_F21 0x70 +#define HID_KEYBOARD_F22 0x71 +#define HID_KEYBOARD_F23 0x72 +#define HID_KEYBOARD_F24 0x73 +#define HID_KEYBOARD_EXECUTE 0x74 +#define HID_KEYBOARD_HELP 0x75 +#define HID_KEYBOARD_MENU 0x76 +#define HID_KEYBOARD_SELECT 0x77 +#define HID_KEYBOARD_STOP 0x78 +#define HID_KEYBOARD_AGAIN 0x79 +#define HID_KEYBOARD_UNDO 0x7A +#define HID_KEYBOARD_CUT 0x7B +#define HID_KEYBOARD_COPY 0x7C +#define HID_KEYBOARD_PASTE 0x7D +#define HID_KEYBOARD_FIND 0x7E +#define HID_KEYBOARD_MUTE 0x7F +#define HID_KEYBOARD_VOLUME_UP 0x80 +#define HID_KEYBOARD_VOLUME_DOWN 0x81 +#define HID_KEYBOARD_LOCKING_CAPS_LOCK 0x82 +#define HID_KEYBOARD_LOCKING_NUM_LOCK 0x83 +#define HID_KEYBOARD_LOCKING_SCROLL_LOCK 0x84 +#define HID_KEYPAD_COMMA 0x85 +#define HID_KEYPAD_EQUAL_SIGN 0x86 +#define HID_KEYBOARD_INTERNATIONAL1 0x87 +#define HID_KEYBOARD_INTERNATIONAL2 0x88 +#define HID_KEYBOARD_INTERNATIONAL3 0x89 +#define HID_KEYBOARD_INTERNATIONAL4 0x8A +#define HID_KEYBOARD_INTERNATIONAL5 0x8B +#define HID_KEYBOARD_INTERNATIONAL6 0x8C +#define HID_KEYBOARD_INTERNATIONAL7 0x8D +#define HID_KEYBOARD_INTERNATIONAL8 0x8E +#define HID_KEYBOARD_INTERNATIONAL9 0x8F +#define HID_KEYBOARD_LANG1 0x90 +#define HID_KEYBOARD_LANG2 0x91 +#define HID_KEYBOARD_LANG3 0x92 +#define HID_KEYBOARD_LANG4 0x93 +#define HID_KEYBOARD_LANG5 0x94 +#define HID_KEYBOARD_LANG6 0x95 +#define HID_KEYBOARD_LANG7 0x96 +#define HID_KEYBOARD_LANG8 0x97 +#define HID_KEYBOARD_LANG9 0x98 +#define HID_KEYBOARD_ALTERNATE_ERASE 0x99 +#define HID_KEYBOARD_SYSREQ_SLASH_ATTENTION 0x9A +#define HID_KEYBOARD_CANCEL 0x9B +#define HID_KEYBOARD_CLEAR 0x9C +#define HID_KEYBOARD_PRIOR 0x9D +#define HID_KEYBOARD_RETURN 0x9E +#define HID_KEYBOARD_SEPARATOR 0x9F +#define HID_KEYBOARD_OUT 0xA0 +#define HID_KEYBOARD_OPER 0xA1 +#define HID_KEYBOARD_CLEAR_SLASH_AGAIN 0xA2 +#define HID_KEYBOARD_CRSEL_SLASH_PROPS 0xA3 +#define HID_KEYBOARD_EXSEL 0xA4 +// Reserved 0xA5-AF +#define HID_KEYPAD_00 0xB0 +#define HID_KEYPAD_000 0xB1 +#define HID_THOUSANDS_SEPARATOR 0xB2 +#define HID_DECIMAL_SEPARATOR 0xB3 +#define HID_CURRENCY_UNIT 0xB4 +#define HID_CURRENCY_SUBUNIT 0xB5 +#define HID_KEYPAD_LEFT_PAREN 0xB6 +#define HID_KEYPAD_RIGHT_PAREN 0xB7 +#define HID_KEYPAD_LEFT_CURLY_BRACE 0xB8 +#define HID_KEYPAD_RIGHT_CURLY_BRACE 0xB9 +#define HID_KEYPAD_TAB 0xBA +#define HID_KEYPAD_BACKSPACE 0xBB +#define HID_KEYPAD_A 0xBC +#define HID_KEYPAD_B 0xBD +#define HID_KEYPAD_C 0xBE +#define HID_KEYPAD_D 0xBF +#define HID_KEYPAD_E 0xC0 +#define HID_KEYPAD_F 0xC1 +#define HID_KEYPAD_XOR 0xC2 +#define HID_KEYPAD_CARAT 0xC3 +#define HID_KEYPAD_PERCENT 0xC4 +#define HID_KEYPAD_LESS_THAN 0xC5 +#define HID_KEYPAD_GREATER_THAN 0xC6 +#define HID_KEYPAD_AMPERSAND 0xC7 +#define HID_KEYPAD_DOUBLEAMPERSAND 0xC8 +#define HID_KEYPAD_PIPE 0xC9 +#define HID_KEYPAD_DOUBLEPIPE 0xCA +#define HID_KEYPAD_COLON 0xCB +#define HID_KEYPAD_POUND_SIGN 0xCC +#define HID_KEYPAD_SPACE 0xCD +#define HID_KEYPAD_AT_SIGN 0xCE +#define HID_KEYPAD_EXCLAMATION_POINT 0xCF +#define HID_KEYPAD_MEMORY_STORE 0xD0 +#define HID_KEYPAD_MEMORY_RECALL 0xD1 +#define HID_KEYPAD_MEMORY_CLEAR 0xD2 +#define HID_KEYPAD_MEMORY_ADD 0xD3 +#define HID_KEYPAD_MEMORY_SUBTRACT 0xD4 +#define HID_KEYPAD_MEMORY_MULTIPLY 0xD5 +#define HID_KEYPAD_MEMORY_DIVIDE 0xD6 +#define HID_KEYPAD_PLUS_SLASH_MINUS 0xD7 +#define HID_KEYPAD_CLEAR 0xD8 +#define HID_KEYPAD_CLEAR_ENTRY 0xD9 +#define HID_KEYPAD_BINARY 0xDA +#define HID_KEYPAD_OCTAL 0xDB +#define HID_KEYPAD_DECIMAL 0xDC +#define HID_KEYPAD_HEXADECIMAL 0xDD + +// 0xDE-0xDF - RESERVED +#define HID_KEYBOARD_LEFT_CONTROL 0xE0 +#define HID_KEYBOARD_LEFT_SHIFT 0xE1 +#define HID_KEYBOARD_LEFT_ALT 0xE2 +#define HID_KEYBOARD_LEFT_GUI 0xE3 +#define HID_KEYBOARD_RIGHT_CONTROL 0xE4 +#define HID_KEYBOARD_RIGHT_SHIFT 0xE5 +#define HID_KEYBOARD_RIGHT_ALT 0xE6 +#define HID_KEYBOARD_RIGHT_GUI 0xE7 + + +// Consumer_Page_(0x0C) 0x15 +#define HID_CONSUMER_NUMERIC_KEY_PAD 0x02 // HID type NARY +#define HID_CONSUMER_PROGRAMMABLE_BUTTONS 0x03 // HID type NARY +#define HID_CONSUMER_MICROPHONE_CA 0x04 +#define HID_CONSUMER_HEADPHONE_CA 0x05 +#define HID_CONSUMER_GRAPHIC_EQUALIZER_CA 0x06 +// Reserved 0x07-1F +#define HID_CONSUMER_PLUS_10 0x20 // HID type OSC +#define HID_CONSUMER_PLUS_100 0x21 // HID type OSC +#define HID_CONSUMER_AM_SLASH_PM 0x22 // HID type OSC +// Reserved 0x23-3F +#define HID_CONSUMER_POWER 0x30 // HID type OOC +#define HID_CONSUMER_RESET 0x31 // HID type OSC +#define HID_CONSUMER_SLEEP 0x32 // HID type OSC +#define HID_CONSUMER_SLEEP_AFTER 0x33 // HID type OSC +#define HID_CONSUMER_SLEEP_MODE 0x34 // HID type RTC +#define HID_CONSUMER_ILLUMINATION 0x35 // HID type OOC +#define HID_CONSUMER_FUNCTION_BUTTONS 0x36 // HID type NARY +// Reserved 0x37-3F +#define HID_CONSUMER_MENU 0x40 // HID type OOC +#define HID_CONSUMER_MENU_PICK 0x41 // HID type OSC +#define HID_CONSUMER_MENU_UP 0x42 // HID type OSC +#define HID_CONSUMER_MENU_DOWN 0x43 // HID type OSC +#define HID_CONSUMER_MENU_LEFT 0x44 // HID type OSC +#define HID_CONSUMER_MENU_RIGHT 0x45 // HID type OSC +#define HID_CONSUMER_MENU_ESCAPE 0x46 // HID type OSC +#define HID_CONSUMER_MENU_VALUE_INCREASE 0x47 // HID type OSC +#define HID_CONSUMER_MENU_VALUE_DECREASE 0x48 // HID type OSC +// Reserved 0x49-5F +#define HID_CONSUMER_DATA_ON_SCREEN 0x60 // HID type OOC +#define HID_CONSUMER_CLOSED_CAPTION 0x61 // HID type OOC +#define HID_CONSUMER_CLOSED_CAPTION_SELECT 0x62 // HID type OSC +#define HID_CONSUMER_VCR_SLASH_TV 0x63 // HID type OOC +#define HID_CONSUMER_BROADCAST_MODE 0x64 // HID type OSC +#define HID_CONSUMER_SNAPSHOT 0x65 // HID type OSC +#define HID_CONSUMER_STILL 0x66 // HID type OSC +// Reserved 0x67-7F +#define HID_CONSUMER_SELECTION 0x80 // HID type NARY +#define HID_CONSUMER_ASSIGN_SELECTION 0x81 // HID type OSC +#define HID_CONSUMER_MODE_STEP 0x82 // HID type OSC +#define HID_CONSUMER_RECALL_LAST 0x83 // HID type OSC +#define HID_CONSUMER_ENTER_CHANNEL 0x84 // HID type OSC +#define HID_CONSUMER_ORDER_MOVIE 0x85 // HID type OSC +#define HID_CONSUMER_CHANNEL 0x86 // HID type LC +#define HID_CONSUMER_MEDIA_SELECTION 0x87 // HID type NARY +#define HID_CONSUMER_MEDIA_SELECT_COMPUTER 0x88 // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_TV 0x89 // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_WWW 0x8A // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_DVD 0x8B // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_TELEPHONE 0x8C // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_PROGRAM_GUIDE 0x8D // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_VIDEO_PHONE 0x8E // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_GAMES 0x8F // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_MESSAGES 0x90 // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_CD 0x91 // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_VCR 0x92 // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_TUNER 0x93 // HID type SEL +#define HID_CONSUMER_QUIT 0x94 // HID type OSC +#define HID_CONSUMER_HELP 0x95 // HID type OOC +#define HID_CONSUMER_MEDIA_SELECT_TAPE 0x96 // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_CABLE 0x97 // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_SATELLITE 0x98 // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_SECURITY 0x99 // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_HOME 0x9A // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_CALL 0x9B // HID type SEL +#define HID_CONSUMER_CHANNEL_INCREMENT 0x9C // HID type OSC +#define HID_CONSUMER_CHANNEL_DECREMENT 0x9D // HID type OSC +#define HID_CONSUMER_MEDIA_SELECT_SAP 0x9E // HID type SEL +// Reserved 0x9F +#define HID_CONSUMER_VCR_PLUS 0xA0 // HID type OSC +#define HID_CONSUMER_ONCE 0xA1 // HID type OSC +#define HID_CONSUMER_DAILY 0xA2 // HID type OSC +#define HID_CONSUMER_WEEKLY 0xA3 // HID type OSC +#define HID_CONSUMER_MONTHLY 0xA4 // HID type OSC +// Reserved 0xA5-AF +#define HID_CONSUMER_PLAY 0xB0 // HID type OOC +#define HID_CONSUMER_PAUSE 0xB1 // HID type OOC +#define HID_CONSUMER_RECORD 0xB2 // HID type OOC +#define HID_CONSUMER_FAST_FORWARD 0xB3 // HID type OOC +#define HID_CONSUMER_REWIND 0xB4 // HID type OOC +#define HID_CONSUMER_SCAN_NEXT_TRACK 0xB5 // HID type OSC +#define HID_CONSUMER_SCAN_PREVIOUS_TRACK 0xB6 // HID type OSC +#define HID_CONSUMER_STOP 0xB7 // HID type OSC +#define HID_CONSUMER_EJECT 0xB8 // HID type OSC +#define HID_CONSUMER_RANDOM_PLAY 0xB9 // HID type OOC +#define HID_CONSUMER_SELECT_DISC 0xBA // HID type NARY +#define HID_CONSUMER_ENTER_DISC_MC 0xBB +#define HID_CONSUMER_REPEAT 0xBC // HID type OSC +#define HID_CONSUMER_TRACKING 0xBD // HID type LC +#define HID_CONSUMER_TRACK_NORMAL 0xBE // HID type OSC +#define HID_CONSUMER_SLOW_TRACKING 0xBF // HID type LC +#define HID_CONSUMER_FRAME_FORWARD 0xC0 // HID type RTC +#define HID_CONSUMER_FRAME_BACK 0xC1 // HID type RTC +#define HID_CONSUMER_MARK 0xC2 // HID type OSC +#define HID_CONSUMER_CLEAR_MARK 0xC3 // HID type OSC +#define HID_CONSUMER_REPEAT_FROM_MARK 0xC4 // HID type OOC +#define HID_CONSUMER_RETURN_TO_MARK 0xC5 // HID type OSC +#define HID_CONSUMER_SEARCH_MARK_FORWARD 0xC6 // HID type OSC +#define HID_CONSUMER_SEARCH_MARK_BACKWARDS 0xC7 // HID type OSC +#define HID_CONSUMER_COUNTER_RESET 0xC8 // HID type OSC +#define HID_CONSUMER_SHOW_COUNTER 0xC9 // HID type OSC +#define HID_CONSUMER_TRACKING_INCREMENT 0xCA // HID type RTC +#define HID_CONSUMER_TRACKING_DECREMENT 0xCB // HID type RTC +#define HID_CONSUMER_STOP_SLASH_EJECT 0xCC // HID type OSC +#define HID_CONSUMER_PLAY_SLASH_PAUSE 0xCD // HID type OSC +#define HID_CONSUMER_PLAY_SLASH_SKIP 0xCE // HID type OSC +// Reserved 0xCF-DF +#define HID_CONSUMER_VOLUME 0xE0 // HID type LC +#define HID_CONSUMER_BALANCE 0xE1 // HID type LC +#define HID_CONSUMER_MUTE 0xE2 // HID type OOC +#define HID_CONSUMER_BASS 0xE3 // HID type LC +#define HID_CONSUMER_TREBLE 0xE4 // HID type LC +#define HID_CONSUMER_BASS_BOOST 0xE5 // HID type OOC +#define HID_CONSUMER_SURROUND_MODE 0xE6 // HID type OSC +#define HID_CONSUMER_LOUDNESS 0xE7 // HID type OOC +#define HID_CONSUMER_MPX 0xE8 // HID type OOC +#define HID_CONSUMER_VOLUME_INCREMENT 0xE9 // HID type RTC +#define HID_CONSUMER_VOLUME_DECREMENT 0xEA // HID type RTC +// Reserved 0xEB-EF +#define HID_CONSUMER_SPEED_SELECT 0xF0 // HID type OSC +#define HID_CONSUMER_PLAYBACK_SPEED 0xF1 // HID type NARY +#define HID_CONSUMER_STANDARD_PLAY 0xF2 // HID type SEL +#define HID_CONSUMER_LONG_PLAY 0xF3 // HID type SEL +#define HID_CONSUMER_EXTENDED_PLAY 0xF4 // HID type SEL +#define HID_CONSUMER_SLOW 0xF5 // HID type OSC +// Reserved 0xF6-FF +#define HID_CONSUMER_FAN_ENABLE 0x100 // HID type OOC +#define HID_CONSUMER_FAN_SPEED 0x101 // HID type LC +#define HID_CONSUMER_LIGHT_ENABLE 0x102 // HID type OOC +#define HID_CONSUMER_LIGHT_ILLUMINATION_LEVEL 0x103 // HID type LC +#define HID_CONSUMER_CLIMATE_CONTROL_ENABLE 0x104 // HID type OOC +#define HID_CONSUMER_ROOM_TEMPERATURE 0x105 // HID type LC +#define HID_CONSUMER_SECURITY_ENABLE 0x106 // HID type OOC +#define HID_CONSUMER_FIRE_ALARM 0x107 // HID type OSC +#define HID_CONSUMER_POLICE_ALARM 0x108 // HID type OSC +#define HID_CONSUMER_PROXIMITY 0x109 // HID type LC +#define HID_CONSUMER_MOTION 0x10A // HID type OSC +#define HID_CONSUMER_DURESS_ALARM 0x10B // HID type OSC +#define HID_CONSUMER_HOLDUP_ALARM 0x10C // HID type OSC +#define HID_CONSUMER_MEDICAL_ALARM 0x10D // HID type OSC +// Reserved 0x10E-14F +#define HID_CONSUMER_BALANCE_RIGHT 0x150 // HID type RTC +#define HID_CONSUMER_BALANCE_LEFT 0x151 // HID type RTC +#define HID_CONSUMER_BASS_INCREMENT 0x152 // HID type RTC +#define HID_CONSUMER_BASS_DECREMENT 0x153 // HID type RTC +#define HID_CONSUMER_TREBLE_INCREMENT 0x154 // HID type RTC +#define HID_CONSUMER_TREBLE_DECREMENT 0x155 // HID type RTC +// Reserved 0x156-15F +#define HID_CONSUMER_SPEAKER_SYSTEM 0x160 // HID type CL +#define HID_CONSUMER_CHANNEL_LEFT 0x161 // HID type CL +#define HID_CONSUMER_CHANNEL_RIGHT 0x162 // HID type CL +#define HID_CONSUMER_CHANNEL_CENTER 0x163 // HID type CL +#define HID_CONSUMER_CHANNEL_FRONT 0x164 // HID type CL +#define HID_CONSUMER_CHANNEL_CENTER_FRONT 0x165 // HID type CL +#define HID_CONSUMER_CHANNEL_SIDE 0x166 // HID type CL +#define HID_CONSUMER_CHANNEL_SURROUND 0x167 // HID type CL +#define HID_CONSUMER_CHANNEL_LOW_FREQUENCY_ENHANCEMENT 0x168 // HID type CL +#define HID_CONSUMER_CHANNEL_TOP 0x169 // HID type CL +#define HID_CONSUMER_CHANNEL_UNKNOWN 0x16A // HID type CL +// Reserved 0x16B-16F +#define HID_CONSUMER_SUB-CHANNEL 0x170 // HID type LC +#define HID_CONSUMER_SUB-CHANNEL_INCREMENT 0x171 // HID type OSC +#define HID_CONSUMER_SUB-CHANNEL_DECREMENT 0x172 // HID type OSC +#define HID_CONSUMER_ALTERNATE_AUDIO_INCREMENT 0x173 // HID type OSC +#define HID_CONSUMER_ALTERNATE_AUDIO_DECREMENT 0x174 // HID type OSC +// Reserved 0x175-17F +#define HID_CONSUMER_APPLICATION_LAUNCH_BUTTONS 0x180 // HID type NARY +#define HID_CONSUMER_AL_LAUNCH_BUTTON_CONFIGURATION_TOOL 0x181 // HID type SEL +#define HID_CONSUMER_AL_PROGRAMMABLE_BUTTON_CONFIGURATION 0x182 // HID type SEL +#define HID_CONSUMER_AL_CONSUMER_CONTROL_CONFIGURATION 0x183 // HID type SEL +#define HID_CONSUMER_AL_WORD_PROCESSOR 0x184 // HID type SEL +#define HID_CONSUMER_AL_TEXT_EDITOR 0x185 // HID type SEL +#define HID_CONSUMER_AL_SPREADSHEET 0x186 // HID type SEL +#define HID_CONSUMER_AL_GRAPHICS_EDITOR 0x187 // HID type SEL +#define HID_CONSUMER_AL_PRESENTATION_APP 0x188 // HID type SEL +#define HID_CONSUMER_AL_DATABASE_APP 0x189 // HID type SEL +#define HID_CONSUMER_AL_EMAIL_READER 0x18A // HID type SEL +#define HID_CONSUMER_AL_NEWSREADER 0x18B // HID type SEL +#define HID_CONSUMER_AL_VOICEMAIL 0x18C // HID type SEL +#define HID_CONSUMER_AL_CONTACTS_SLASH_ADDRESS_BOOK 0x18D // HID type SEL +#define HID_CONSUMER_AL_CALENDAR_SLASH_SCHEDULE 0x18E // HID type SEL +#define HID_CONSUMER_AL_TASK_SLASH_PROJECT_MANAGER 0x18F // HID type SEL +#define HID_CONSUMER_AL_LOG_SLASH_JOURNAL_SLASH_TIMECARD 0x190 // HID type SEL +#define HID_CONSUMER_AL_CHECKBOOK_SLASH_FINANCE 0x191 // HID type SEL +#define HID_CONSUMER_AL_CALCULATOR 0x192 // HID type SEL +#define HID_CONSUMER_AL_A_SLASH_V_CAPTURE_SLASH_PLAYBACK 0x193 // HID type SEL +#define HID_CONSUMER_AL_LOCAL_MACHINE_BROWSER 0x194 // HID type SEL +#define HID_CONSUMER_AL_LAN_SLASH_WAN_BROWSER 0x195 // HID type SEL +#define HID_CONSUMER_AL_INTERNET_BROWSER 0x196 // HID type SEL +#define HID_CONSUMER_AL_REMOTE_NETWORKING_SLASH_ISP_CONNECT 0x197 // HID type SEL +#define HID_CONSUMER_AL_NETWORK_CONFERENCE 0x198 // HID type SEL +#define HID_CONSUMER_AL_NETWORK_CHAT 0x199 // HID type SEL +#define HID_CONSUMER_AL_TELEPHONY_SLASH_DIALER 0x19A // HID type SEL +#define HID_CONSUMER_AL_LOGON 0x19B // HID type SEL +#define HID_CONSUMER_AL_LOGOFF 0x19C // HID type SEL +#define HID_CONSUMER_AL_LOGON_SLASH_LOGOFF 0x19D // HID type SEL +#define HID_CONSUMER_AL_TERMINAL_LOCK_SLASH_SCREENSAVER 0x19E // HID type SEL +#define HID_CONSUMER_AL_CONTROL_PANEL 0x19F // HID type SEL +#define HID_CONSUMER_AL_COMMAND_LINE_PROCESSOR_SLASH_RUN 0x1A0 // HID type SEL +#define HID_CONSUMER_AL_PROCESS_SLASH_TASK_MANAGER 0x1A1 // HID type SEL +#define HID_CONSUMER_AL_SELECT_TASK_SLASH_APPLICATION 0x1A2 // HID type SEL +#define HID_CONSUMER_AL_NEXT_TASK_SLASH_APPLICATION 0x1A3 // HID type SEL +#define HID_CONSUMER_AL_PREVIOUS_TASK_SLASH_APPLICATION 0x1A4 // HID type SEL +#define HID_CONSUMER_AL_PREEMPTIVE_HALT_TASK_SLASH_APPLICATION 0x1A5 // HID type SEL +#define HID_CONSUMER_AL_INTEGRATED_HELP_CENTER 0x1A6 // HID type SEL +#define HID_CONSUMER_AL_DOCUMENTS 0x1A7 // HID type SEL +#define HID_CONSUMER_AL_THESAURUS 0x1A8 // HID type SEL +#define HID_CONSUMER_AL_DICTIONARY 0x1A9 // HID type SEL +#define HID_CONSUMER_AL_DESKTOP 0x1AA // HID type SEL +#define HID_CONSUMER_AL_SPELL_CHECK 0x1AB // HID type SEL +#define HID_CONSUMER_AL_GRAMMAR_CHECK 0x1AC // HID type SEL +#define HID_CONSUMER_AL_WIRELESS_STATUS 0x1AD // HID type SEL +#define HID_CONSUMER_AL_KEYBOARD_LAYOUT 0x1AE // HID type SEL +#define HID_CONSUMER_AL_VIRUS_PROTECTION 0x1AF // HID type SEL +#define HID_CONSUMER_AL_ENCRYPTION 0x1B0 // HID type SEL +#define HID_CONSUMER_AL_SCREEN_SAVER 0x1B1 // HID type SEL +#define HID_CONSUMER_AL_ALARMS 0x1B2 // HID type SEL +#define HID_CONSUMER_AL_CLOCK 0x1B3 // HID type SEL +#define HID_CONSUMER_AL_FILE_BROWSER 0x1B4 // HID type SEL +#define HID_CONSUMER_AL_POWER_STATUS 0x1B5 // HID type SEL +#define HID_CONSUMER_AL_IMAGE_BROWSER 0x1B6 // HID type SEL +#define HID_CONSUMER_AL_AUDIO_BROWSER 0x1B7 // HID type SEL +#define HID_CONSUMER_AL_MOVIE_BROWSER 0x1B8 // HID type SEL +#define HID_CONSUMER_AL_DIGITAL_RIGHTS_MANAGER 0x1B9 // HID type SEL +#define HID_CONSUMER_AL_DIGITAL_WALLET 0x1BA // HID type SEL +// _Reserved 0x1BB +#define HID_CONSUMER_AL_INSTANT_MESSAGING 0x1BC // HID type SEL +#define HID_CONSUMER_AL_OEM_FEATURES_SLASH__TIPS_SLASH_TUTORIAL_BROWSER 0x1BD // HID type SEL +#define HID_CONSUMER_AL_OEM_HELP 0x1BE // HID type SEL +#define HID_CONSUMER_AL_ONLINE_COMMUNITY 0x1BF // HID type SEL +#define HID_CONSUMER_AL_ENTERTAINMENT_CONTENT_BROWSER 0x1C0 // HID type SEL +#define HID_CONSUMER_AL_ONLINE_SHOPPING_BROWSER 0x1C1 // HID type SEL +#define HID_CONSUMER_AL_SMARTCARD_INFORMATION_SLASH_HELP 0x1C2 // HID type SEL +#define HID_CONSUMER_AL_MARKET_MONITOR_SLASH_FINANCE_BROWSER 0x1C3 // HID type SEL +#define HID_CONSUMER_AL_CUSTOMIZED_CORPORATE_NEWS_BROWSER 0x1C4 // HID type SEL +#define HID_CONSUMER_AL_ONLINE_ACTIVITY_BROWSER 0x1C5 // HID type SEL +#define HID_CONSUMER_AL_RESEARCH_SLASH_SEARCH_BROWSER 0x1C6 // HID type SEL +#define HID_CONSUMER_AL_AUDIO_PLAYER 0x1C7 // HID type SEL +// Reserved 0x1C8-1FF +#define HID_CONSUMER_GENERIC_GUI_APPLICATION_CONTROLS 0x200 // HID type NARY +#define HID_CONSUMER_AC_NEW 0x201 // HID type SEL +#define HID_CONSUMER_AC_OPEN 0x202 // HID type SEL +#define HID_CONSUMER_AC_CLOSE 0x203 // HID type SEL +#define HID_CONSUMER_AC_EXIT 0x204 // HID type SEL +#define HID_CONSUMER_AC_MAXIMIZE 0x205 // HID type SEL +#define HID_CONSUMER_AC_MINIMIZE 0x206 // HID type SEL +#define HID_CONSUMER_AC_SAVE 0x207 // HID type SEL +#define HID_CONSUMER_AC_PRINT 0x208 // HID type SEL +#define HID_CONSUMER_AC_PROPERTIES 0x209 // HID type SEL +#define HID_CONSUMER_AC_UNDO 0x21A // HID type SEL +#define HID_CONSUMER_AC_COPY 0x21B // HID type SEL +#define HID_CONSUMER_AC_CUT 0x21C // HID type SEL +#define HID_CONSUMER_AC_PASTE 0x21D // HID type SEL +#define HID_CONSUMER_AC_SELECT_ALL 0x21E // HID type SEL +#define HID_CONSUMER_AC_FIND 0x21F // HID type SEL +#define HID_CONSUMER_AC_FIND_AND_REPLACE 0x220 // HID type SEL +#define HID_CONSUMER_AC_SEARCH 0x221 // HID type SEL +#define HID_CONSUMER_AC_GO_TO 0x222 // HID type SEL +#define HID_CONSUMER_AC_HOME 0x223 // HID type SEL +#define HID_CONSUMER_AC_BACK 0x224 // HID type SEL +#define HID_CONSUMER_AC_FORWARD 0x225 // HID type SEL +#define HID_CONSUMER_AC_STOP 0x226 // HID type SEL +#define HID_CONSUMER_AC_REFRESH 0x227 // HID type SEL +#define HID_CONSUMER_AC_PREVIOUS_LINK 0x228 // HID type SEL +#define HID_CONSUMER_AC_NEXT_LINK 0x229 // HID type SEL +#define HID_CONSUMER_AC_BOOKMARKS 0x22A // HID type SEL +#define HID_CONSUMER_AC_HISTORY 0x22B // HID type SEL +#define HID_CONSUMER_AC_SUBSCRIPTIONS 0x22C // HID type SEL +#define HID_CONSUMER_AC_ZOOM_IN 0x22D // HID type SEL +#define HID_CONSUMER_AC_ZOOM_OUT 0x22E // HID type SEL +#define HID_CONSUMER_AC_ZOOM 0x22F // HID type LC +#define HID_CONSUMER_AC_FULL_SCREEN_VIEW 0x230 // HID type SEL +#define HID_CONSUMER_AC_NORMAL_VIEW 0x231 // HID type SEL +#define HID_CONSUMER_AC_VIEW_TOGGLE 0x232 // HID type SEL +#define HID_CONSUMER_AC_SCROLL_UP 0x233 // HID type SEL +#define HID_CONSUMER_AC_SCROLL_DOWN 0x234 // HID type SEL +#define HID_CONSUMER_AC_SCROLL 0x235 // HID type LC +#define HID_CONSUMER_AC_PAN_LEFT 0x236 // HID type SEL +#define HID_CONSUMER_AC_PAN_RIGHT 0x237 // HID type SEL +#define HID_CONSUMER_AC_PAN 0x238 // HID type LC +#define HID_CONSUMER_AC_NEW_WINDOW 0x239 // HID type SEL +#define HID_CONSUMER_AC_TILE_HORIZONTALLY 0x23A // HID type SEL +#define HID_CONSUMER_AC_TILE_VERTICALLY 0x23B // HID type SEL +#define HID_CONSUMER_AC_FORMAT 0x23C // HID type SEL +#define HID_CONSUMER_AC_EDIT 0x23D // HID type SEL +#define HID_CONSUMER_AC_BOLD 0x23E // HID type SEL +#define HID_CONSUMER_AC_ITALICS 0x23F // HID type SEL +#define HID_CONSUMER_AC_UNDERLINE 0x240 // HID type SEL +#define HID_CONSUMER_AC_STRIKETHROUGH 0x241 // HID type SEL +#define HID_CONSUMER_AC_SUBSCRIPT 0x242 // HID type SEL +#define HID_CONSUMER_AC_SUPERSCRIPT 0x243 // HID type SEL +#define HID_CONSUMER_AC_ALL_CAPS 0x244 // HID type SEL +#define HID_CONSUMER_AC_ROTATE 0x245 // HID type SEL +#define HID_CONSUMER_AC_RESIZE 0x246 // HID type SEL +#define HID_CONSUMER_AC_FLIP_HORIZONTAL 0x247 // HID type SEL +#define HID_CONSUMER_AC_FLIP_VERTICAL 0x248 // HID type SEL +#define HID_CONSUMER_AC_MIRROR_HORIZONTAL 0x249 // HID type SEL +#define HID_CONSUMER_AC_MIRROR_VERTICAL 0x24A // HID type SEL +#define HID_CONSUMER_AC_FONT_SELECT 0x24B // HID type SEL +#define HID_CONSUMER_AC_FONT_COLOR 0x24C // HID type SEL +#define HID_CONSUMER_AC_FONT_SIZE 0x24D // HID type SEL +#define HID_CONSUMER_AC_JUSTIFY_LEFT 0x24E // HID type SEL +#define HID_CONSUMER_AC_JUSTIFY_CENTER_H 0x24F // HID type SEL +#define HID_CONSUMER_AC_JUSTIFY_RIGHT 0x250 // HID type SEL +#define HID_CONSUMER_AC_JUSTIFY_BLOCK_H 0x251 // HID type SEL +#define HID_CONSUMER_AC_JUSTIFY_TOP 0x252 // HID type SEL +#define HID_CONSUMER_AC_JUSTIFY_CENTER_V 0x253 // HID type SEL +#define HID_CONSUMER_AC_JUSTIFY_BOTTOM 0x254 // HID type SEL +#define HID_CONSUMER_AC_JUSTIFY_BLOCK_V 0x255 // HID type SEL +#define HID_CONSUMER_AC_INDENT_DECREASE 0x256 // HID type SEL +#define HID_CONSUMER_AC_INDENT_INCREASE 0x257 // HID type SEL +#define HID_CONSUMER_AC_NUMBERED_LIST 0x258 // HID type SEL +#define HID_CONSUMER_AC_RESTART_NUMBERING 0x259 // HID type SEL +#define HID_CONSUMER_AC_BULLETED_LIST 0x25A // HID type SEL +#define HID_CONSUMER_AC_PROMOTE 0x25B // HID type SEL +#define HID_CONSUMER_AC_DEMOTE 0x25C // HID type SEL +#define HID_CONSUMER_AC_YES 0x25D // HID type SEL +#define HID_CONSUMER_AC_NO 0x25E // HID type SEL +#define HID_CONSUMER_AC_CANCEL 0x25F // HID type SEL +#define HID_CONSUMER_AC_CATALOG 0x260 // HID type SEL +#define HID_CONSUMER_AC_BUY_SLASH_CHECKOUT 0x261 // HID type SEL +#define HID_CONSUMER_AC_ADD_TO_CART 0x262 // HID type SEL +#define HID_CONSUMER_AC_EXPAND 0x263 // HID type SEL +#define HID_CONSUMER_AC_EXPAND_ALL 0x264 // HID type SEL +#define HID_CONSUMER_AC_COLLAPSE 0x265 // HID type SEL +#define HID_CONSUMER_AC_COLLAPSE_ALL 0x266 // HID type SEL +#define HID_CONSUMER_AC_PRINT_PREVIEW 0x267 // HID type SEL +#define HID_CONSUMER_AC_PASTE_SPECIAL 0x268 // HID type SEL +#define HID_CONSUMER_AC_INSERT_MODE 0x269 // HID type SEL +#define HID_CONSUMER_AC_DELETE 0x26A // HID type SEL +#define HID_CONSUMER_AC_LOCK 0x26B // HID type SEL +#define HID_CONSUMER_AC_UNLOCK 0x26C // HID type SEL +#define HID_CONSUMER_AC_PROTECT 0x26D // HID type SEL +#define HID_CONSUMER_AC_UNPROTECT 0x26E // HID type SEL +#define HID_CONSUMER_AC_ATTACH_COMMENT 0x26F // HID type SEL +#define HID_CONSUMER_AC_DELETE_COMMENT 0x270 // HID type SEL +#define HID_CONSUMER_AC_VIEW_COMMENT 0x271 // HID type SEL +#define HID_CONSUMER_AC_SELECT_WORD 0x272 // HID type SEL +#define HID_CONSUMER_AC_SELECT_SENTENCE 0x273 // HID type SEL +#define HID_CONSUMER_AC_SELECT_PARAGRAPH 0x274 // HID type SEL +#define HID_CONSUMER_AC_SELECT_COLUMN 0x275 // HID type SEL +#define HID_CONSUMER_AC_SELECT_ROW 0x276 // HID type SEL +#define HID_CONSUMER_AC_SELECT_TABLE 0x277 // HID type SEL +#define HID_CONSUMER_AC_SELECT_OBJECT 0x278 // HID type SEL +#define HID_CONSUMER_AC_REDO_SLASH_REPEAT 0x279 // HID type SEL +#define HID_CONSUMER_AC_SORT 0x27A // HID type SEL +#define HID_CONSUMER_AC_SORT_ASCENDING 0x27B // HID type SEL +#define HID_CONSUMER_AC_SORT_DESCENDING 0x27C // HID type SEL +#define HID_CONSUMER_AC_FILTER 0x27D // HID type SEL +#define HID_CONSUMER_AC_SET_CLOCK 0x27E // HID type SEL +#define HID_CONSUMER_AC_VIEW_CLOCK 0x27F // HID type SEL +#define HID_CONSUMER_AC_SELECT_TIME_ZONE 0x280 // HID type SEL +#define HID_CONSUMER_AC_EDIT_TIME_ZONES 0x281 // HID type SEL +#define HID_CONSUMER_AC_SET_ALARM 0x282 // HID type SEL +#define HID_CONSUMER_AC_CLEAR_ALARM 0x283 // HID type SEL +#define HID_CONSUMER_AC_SNOOZE_ALARM 0x284 // HID type SEL +#define HID_CONSUMER_AC_RESET_ALARM 0x285 // HID type SEL +#define HID_CONSUMER_AC_SYNCHRONIZE 0x286 // HID type SEL +#define HID_CONSUMER_AC_SEND_SLASH_RECEIVE 0x287 // HID type SEL +#define HID_CONSUMER_AC_SEND_TO 0x288 // HID type SEL +#define HID_CONSUMER_AC_REPLY 0x289 // HID type SEL +#define HID_CONSUMER_AC_REPLY_ALL 0x28A // HID type SEL +#define HID_CONSUMER_AC_FORWARD_MSG 0x28B // HID type SEL +#define HID_CONSUMER_AC_SEND 0x28C // HID type SEL +#define HID_CONSUMER_AC_ATTACH_FILE 0x28D // HID type SEL +#define HID_CONSUMER_AC_UPLOAD 0x28E // HID type SEL +#define HID_CONSUMER_AC_DOWNLOAD_(SAVE_TARGET_AS) 0x28F // HID type SEL +#define HID_CONSUMER_AC_SET_BORDERS 0x290 // HID type SEL +#define HID_CONSUMER_AC_INSERT_ROW 0x291 // HID type SEL +#define HID_CONSUMER_AC_INSERT_COLUMN 0x292 // HID type SEL +#define HID_CONSUMER_AC_INSERT_FILE 0x293 // HID type SEL +#define HID_CONSUMER_AC_INSERT_PICTURE 0x294 // HID type SEL +#define HID_CONSUMER_AC_INSERT_OBJECT 0x295 // HID type SEL +#define HID_CONSUMER_AC_INSERT_SYMBOL 0x296 // HID type SEL +#define HID_CONSUMER_AC_SAVE_AND_CLOSE 0x297 // HID type SEL +#define HID_CONSUMER_AC_RENAME 0x298 // HID type SEL +#define HID_CONSUMER_AC_MERGE 0x299 // HID type SEL +#define HID_CONSUMER_AC_SPLIT 0x29A // HID type SEL +#define HID_CONSUMER_AC_DISRIBUTE_HORIZONTALLY 0x29B // HID type SEL +#define HID_CONSUMER_AC_DISTRIBUTE_VERTICALLY 0x29C // HID type SEL diff --git a/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp b/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp index 1a42027194..06a0ed535c 100644 --- a/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp +++ b/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp @@ -80,9 +80,9 @@ void Keyboard_::end(void) { } -void Keyboard_::sendReport(KeyReport* keys) +void Keyboard_::sendReport(HID_KeyboardReport_Data_t* keys) { - HID.SendReport(HID_REPORTID_KEYBOARD,keys,sizeof(KeyReport)); + HID.SendReport(HID_REPORTID_KEYBOARD,keys,sizeof(HID_KeyboardReport_Data_t)); } // press() adds the specified key (printing, non-printing, or modifier) @@ -103,9 +103,9 @@ size_t Keyboard_::press(uint8_t k) setWriteError(); return 0; } - if (k & 0x80) { // it's a capital letter or other character reached with shift + if (k & SHIFT) { // it's a capital letter or other character reached with shift _keyReport.modifiers |= 0x02; // the left shift modifier - k &= 0x7F; + k = k ^ SHIFT; } } @@ -146,9 +146,9 @@ size_t Keyboard_::release(uint8_t k) if (!k) { return 0; } - if (k & 0x80) { // it's a capital letter or other character reached with shift + if (k & SHIFT) { // it's a capital letter or other character reached with shift _keyReport.modifiers &= ~(0x02); // the left shift modifier - k &= 0x7F; + k = k ^ SHIFT; } } @@ -166,13 +166,8 @@ size_t Keyboard_::release(uint8_t k) 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; + // release all keys + memset(&_keyReport, 0x00, sizeof(_keyReport)); sendReport(&_keyReport); } @@ -183,6 +178,124 @@ size_t Keyboard_::write(uint8_t c) return p; // just return the result of press() since release() almost always returns 1 } +// pressKeycode() 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 releaseKeycode(), releaseAll(), or otherwise clear the report and resend. +size_t Keyboard_::pressKeycode(uint8_t k) +{ + if (!addKeycodeToReport(k)) { + return 0; + } + sendReport(&_keyReport); +} + +size_t Keyboard_::addKeycodeToReport(uint8_t k) +{ + uint8_t index = 0; + uint8_t done = 0; + + if ((k >= HID_KEYBOARD_LEFT_CONTROL) && (k <= HID_KEYBOARD_RIGHT_GUI)) { + // it's a modifier key + _keyReport.modifiers |= (0x01 << (k - HID_KEYBOARD_LEFT_CONTROL)); + } + else { + // it's some other key: + // Add k to the key report only if it's not already present + // and if there is an empty slot. + for (index = 0; index < sizeof(_keyReport.keys); index++) { + if (_keyReport.keys[index] != k) { // is k already in list? + if (0 == _keyReport.keys[index]) { // have we found an empty slot? + _keyReport.keys[index] = k; + done = 1; + break; + } + } + else { + done = 1; + break; + } + + } + + // use separate variable to check if slot was found + // for style reasons - we do not know how the compiler + // handles the for() index when it leaves the loop + if (0 == done) { + setWriteError(); + return 0; + } + } + + return 1; +} + + +// releaseKeycode() 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. +// When send is set to FALSE (= 0) no sendReport() is executed. This comes in +// handy when combining key releases (e.g. SHIFT+A). +size_t Keyboard_::releaseKeycode(uint8_t k) +{ + if (!removeKeycodeFromReport(k)) { + return 0; + } + sendReport(&_keyReport); +} + +size_t Keyboard_::removeKeycodeFromReport(uint8_t k) +{ + uint8_t indexA; + uint8_t indexB; + uint8_t count; + + if ((k >= HID_KEYBOARD_LEFT_CONTROL) && (k <= HID_KEYBOARD_RIGHT_GUI)) { + // it's a modifier key + _keyReport.modifiers = _keyReport.modifiers & (~(0x01 << (k - HID_KEYBOARD_LEFT_CONTROL))); + } + else { + // it's some other key: + // 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 (indexA = 0; indexA < sizeof(_keyReport.keys); indexA++) { + if (_keyReport.keys[indexA] == k) { + _keyReport.keys[indexA] = 0; + } + } + + // finally rearrange the keys list so that the free (= 0x00) are at the + // end of the keys list - some implementations stop for keys at the + // first occurence of an 0x00 in the keys list + // so (0x00)(0x01)(0x00)(0x03)(0x02)(0x00) becomes + // (0x01)(0x03)(0x02)(0x00)(0x00)(0x00) + count = 0; // holds the number of zeros we've found + indexA = 0; + while ((indexA + count) < sizeof(_keyReport.keys)) { + if (0 == _keyReport.keys[indexA]) { + count++; // one more zero + for (indexB = indexA; indexB < sizeof(_keyReport.keys) - count; indexB++) { + _keyReport.keys[indexB] = _keyReport.keys[indexB + 1]; + } + _keyReport.keys[sizeof(_keyReport.keys) - count] = 0; + } + else { + indexA++; // one more non-zero + } + } + } + + return 1; +} + + +size_t Keyboard_::writeKeycode(uint8_t c) +{ + uint8_t p = pressKeycode(c); // Keydown + releaseKeycode(c); // Keyup + return (p); // just return the result of pressKeycode() since release() almost always returns 1 +} + Keyboard_ Keyboard; #endif diff --git a/plugins/KeyboardioHID/src/ImprovedKeyboard.h b/plugins/KeyboardioHID/src/ImprovedKeyboard.h index 63fda4bc6c..c0cd373de3 100644 --- a/plugins/KeyboardioHID/src/ImprovedKeyboard.h +++ b/plugins/KeyboardioHID/src/ImprovedKeyboard.h @@ -39,18 +39,23 @@ THE SOFTWARE. #include "ImprovedKeylayouts.h" // 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; +typedef union{ + // Low level key report: up to 6 keys and shift, ctrl etc at once + uint8_t whole8[]; + uint16_t whole16[]; + uint32_t whole32[]; + struct{ + uint8_t modifiers; + uint8_t reserved; + uint8_t keys[6]; + }; +} HID_KeyboardReport_Data_t; class Keyboard_ : public Print { private: - KeyReport _keyReport; - void sendReport(KeyReport* keys); + HID_KeyboardReport_Data_t _keyReport; + void sendReport(HID_KeyboardReport_Data_t* keys); public: Keyboard_(void); void begin(void); @@ -60,9 +65,11 @@ class Keyboard_ : public Print size_t release(uint8_t k); void releaseAll(void); - // Select a different layout optional: - void useLayoutGerman(void); - void useLayoutUS(void); + size_t writeKeycode(uint8_t k); + size_t pressKeycode(uint8_t k); + size_t releaseKeycode(uint8_t k); + size_t addKeycodeToReport(uint8_t k); + size_t removeKeycodeFromReport(uint8_t k); }; extern Keyboard_ Keyboard; From ccaa08832fbe3e73195a0e03580418aba05e64cd Mon Sep 17 00:00:00 2001 From: NicoHood Date: Tue, 8 Sep 2015 18:11:46 +0200 Subject: [PATCH 217/602] Added missing keylayouts file forgot in the last commits to add it --- .../KeyboardioHID/src/ImprovedKeylayouts.h | 265 ++++++++++++++++++ 1 file changed, 265 insertions(+) create mode 100644 plugins/KeyboardioHID/src/ImprovedKeylayouts.h diff --git a/plugins/KeyboardioHID/src/ImprovedKeylayouts.h b/plugins/KeyboardioHID/src/ImprovedKeylayouts.h new file mode 100644 index 0000000000..78353ecb5d --- /dev/null +++ b/plugins/KeyboardioHID/src/ImprovedKeylayouts.h @@ -0,0 +1,265 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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. +*/ + +#pragma once + +//================================================================================ +// LAYOUT_US_ENGLISH +//================================================================================ + +#ifdef LAYOUT_US_ENGLISH + +#define KEY_PRINT 0xCE +#define KEY_NUM_LOCK 0xDB +#define KEY_SCROLL_LOCK 0xCF +#define KEY_PAUSE 0xD0 +#define KEY_MENU 0xED + +#define KEY_LEFT_CTRL 0x80 +#define KEY_LEFT_SHIFT 0x81 +#define KEY_LEFT_ALT 0x82 +#define KEY_LEFT_GUI 0x83 +#define KEY_LEFT_WINDOWS KEY_LEFT_GUI +#define KEY_RIGHT_CTRL 0x84 +#define KEY_RIGHT_SHIFT 0x85 +#define KEY_RIGHT_ALT 0x86 +#define KEY_RIGHT_GUI 0x87 +#define KEY_RIGHT_WINDOWS KEY_RIGHT_GUI + +#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_SPACE ' ' +#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 + +#define LED_NUM_LOCK 0x01 +#define LED_CAPS_LOCK 0x02 +#define LED_SCROLL_LOCK 0x04 + +//Raw Keyboard definitions +#define RAW_KEYBOARD_LEFT_CTRL (1 << 0) +#define RAW_KEYBOARD_LEFT_SHIFT (1 << 1) +#define RAW_KEYBOARD_LEFT_ALT (1 << 2) +#define RAW_KEYBOARD_LEFT_GUI (1 << 3) +#define RAW_KEYBOARD_RIGHT_CTRL (1 << 4) +#define RAW_KEYBOARD_RIGHT_SHIFT (1 << 5) +#define RAW_KEYBOARD_RIGHT_ALT (1 << 6) +#define RAW_KEYBOARD_RIGHT_GUI (1 << 7) + +#define RAW_KEYBOARD_KEY(key) ((key>='a' && key<='z') ? (0x04 + key-'a') :\ +(key>='A' && key<='Z') ? (0x04 + key-'A') : (key>='1' && key<='9') ? (0x1E + key-'1') : 0x27) + +#define RAW_KEYBOARD_UP_ARROW 0x52 +#define RAW_KEYBOARD_DOWN_ARROW 0x51 +#define RAW_KEYBOARD_LEFT_ARROW 0x50 +#define RAW_KEYBOARD_RIGHT_ARROW 0x4F +#define RAW_KEYBOARD_SPACEBAR 0x2C +#define RAW_KEYBOARD_BACKSPACE 0x2A +#define RAW_KEYBOARD_TAB 0x2B +#define RAW_KEYBOARD_RETURN 0x28 +#define RAW_KEYBOARD_ESC 0x29 +#define RAW_KEYBOARD_INSERT 0x49 +#define RAW_KEYBOARD_DELETE 0x4C +#define RAW_KEYBOARD_PAGE_UP 0x4B +#define RAW_KEYBOARD_PAGE_DOWN 0x4E +#define RAW_KEYBOARD_HOME 0x4A +#define RAW_KEYBOARD_END 0x4D +#define RAW_KEYBOARD_CAPS_LOCK 0x39 +#define RAW_KEYBOARD_F1 0x3A +#define RAW_KEYBOARD_F2 0x3B +#define RAW_KEYBOARD_F3 0x3C +#define RAW_KEYBOARD_F4 0x3D +#define RAW_KEYBOARD_F5 0x3E +#define RAW_KEYBOARD_F6 0x3F +#define RAW_KEYBOARD_F7 0x40 +#define RAW_KEYBOARD_F8 0x41 +#define RAW_KEYBOARD_F9 0x42 +#define RAW_KEYBOARD_F10 0x43 +#define RAW_KEYBOARD_F11 0x44 +#define RAW_KEYBOARD_F12 0x45 +#define RAW_KEYBOARD_PRINT 0x46 +#define RAW_KEYBOARD_SCROLL_LOCK 0x47 +#define RAW_KEYBOARD_PAUSE 0x48 + +#define SHIFT 0x80 +static const uint8_t _asciimap[128] PROGMEM = +{ + 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 +}; + +#else + +//TODO other layouts + +#endif From 23c80723c2099d55dc24796b63d77c298802262f Mon Sep 17 00:00:00 2001 From: NicoHood Date: Tue, 8 Sep 2015 19:12:22 +0200 Subject: [PATCH 218/602] Improved Keylayout definition --- .../KeyboardioHID/src/ImprovedKeylayouts.h | 284 +++++++++++------- 1 file changed, 175 insertions(+), 109 deletions(-) diff --git a/plugins/KeyboardioHID/src/ImprovedKeylayouts.h b/plugins/KeyboardioHID/src/ImprovedKeylayouts.h index 78353ecb5d..b76ebe1dd6 100644 --- a/plugins/KeyboardioHID/src/ImprovedKeylayouts.h +++ b/plugins/KeyboardioHID/src/ImprovedKeylayouts.h @@ -24,62 +24,71 @@ THE SOFTWARE. #pragma once //================================================================================ -// LAYOUT_US_ENGLISH +// Key definitions //================================================================================ -#ifdef LAYOUT_US_ENGLISH - -#define KEY_PRINT 0xCE -#define KEY_NUM_LOCK 0xDB -#define KEY_SCROLL_LOCK 0xCF -#define KEY_PAUSE 0xD0 -#define KEY_MENU 0xED - +// Modifiers #define KEY_LEFT_CTRL 0x80 #define KEY_LEFT_SHIFT 0x81 #define KEY_LEFT_ALT 0x82 #define KEY_LEFT_GUI 0x83 -#define KEY_LEFT_WINDOWS KEY_LEFT_GUI #define KEY_RIGHT_CTRL 0x84 #define KEY_RIGHT_SHIFT 0x85 #define KEY_RIGHT_ALT 0x86 #define KEY_RIGHT_GUI 0x87 -#define KEY_RIGHT_WINDOWS KEY_RIGHT_GUI -#define KEY_UP_ARROW 0xDA -#define KEY_DOWN_ARROW 0xD9 -#define KEY_LEFT_ARROW 0xD8 -#define KEY_RIGHT_ARROW 0xD7 -#define KEY_BACKSPACE 0xB2 +// Normal keys +#define KEY_UP_ARROW (RAW_KEYBOARD_UP_ARROW + 136) +#define KEY_DOWN_ARROW (RAW_KEYBOARD_DOWN_ARROW + 136) +#define KEY_LEFT_ARROW (RAW_KEYBOARD_LEFT_ARROW + 136) +#define KEY_RIGHT_ARROW (RAW_KEYBOARD_RIGHT_ARROW + 136) +#define KEY_BACKSPACE (RAW_KEYBOARD_BACKSPACE + 136) +#define KEY_TAB (RAW_KEYBOARD_TAB + 136) +#define KEY_RETURN (RAW_KEYBOARD_RETURN + 136) +#define KEY_ESC (RAW_KEYBOARD_ESC + 136) +#define KEY_INSERT (RAW_KEYBOARD_INSERT + 136) +#define KEY_DELETE (RAW_KEYBOARD_DELETE + 136) +#define KEY_PAGE_UP (RAW_KEYBOARD_PAGE_UP + 136) +#define KEY_PAGE_DOWN (RAW_KEYBOARD_PAGE_DOWN + 136) +#define KEY_HOME (RAW_KEYBOARD_HOME + 136) +#define KEY_END (RAW_KEYBOARD_END + 136) +#define KEY_CAPS_LOCK (RAW_KEYBOARD_CAPS_LOCK + 136) +#define KEY_F1 (RAW_KEYBOARD_F1 + 136) +#define KEY_F2 (RAW_KEYBOARD_F2 + 136) +#define KEY_F3 (RAW_KEYBOARD_F3 + 136) +#define KEY_F4 (RAW_KEYBOARD_F4 + 136) +#define KEY_F5 (RAW_KEYBOARD_F5 + 136) +#define KEY_F6 (RAW_KEYBOARD_F6 + 136) +#define KEY_F7 (RAW_KEYBOARD_F7 + 136) +#define KEY_F8 (RAW_KEYBOARD_F8 + 136) +#define KEY_F9 (RAW_KEYBOARD_F9 + 136) +#define KEY_F10 (RAW_KEYBOARD_F10 + 136) +#define KEY_F11 (RAW_KEYBOARD_F11 + 136) +#define KEY_F12 (RAW_KEYBOARD_F12 + 136) + + +// New key definitions +#define KEY_PRINT (RAW_KEYBOARD_PRINT + 136) +#define KEY_NUM_LOCK (RAW_KEYBOARD_NUM_LOCK + 136) +#define KEY_SCROLL_LOCK (RAW_KEYBOARD_SCROLL_LOCK + 136) +#define KEY_PAUSE (RAW_KEYBOARD_PAUSE + 136) +#define KEY_MENU (RAW_KEYBOARD_MENU + 136) #define KEY_SPACE ' ' -#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 +#define KEY_LEFT_WINDOWS KEY_LEFT_GUI +#define KEY_RIGHT_WINDOWS KEY_RIGHT_GUI +#define KEY_PRINTSCREEN KEY_PRINT +// TODO implement Leds #define LED_NUM_LOCK 0x01 #define LED_CAPS_LOCK 0x02 #define LED_SCROLL_LOCK 0x04 -//Raw Keyboard definitions +//================================================================================ +// LAYOUT_US_ENGLISH +//================================================================================ + +#ifdef LAYOUT_US_ENGLISH + #define RAW_KEYBOARD_LEFT_CTRL (1 << 0) #define RAW_KEYBOARD_LEFT_SHIFT (1 << 1) #define RAW_KEYBOARD_LEFT_ALT (1 << 2) @@ -89,9 +98,6 @@ THE SOFTWARE. #define RAW_KEYBOARD_RIGHT_ALT (1 << 6) #define RAW_KEYBOARD_RIGHT_GUI (1 << 7) -#define RAW_KEYBOARD_KEY(key) ((key>='a' && key<='z') ? (0x04 + key-'a') :\ -(key>='A' && key<='Z') ? (0x04 + key-'A') : (key>='1' && key<='9') ? (0x1E + key-'1') : 0x27) - #define RAW_KEYBOARD_UP_ARROW 0x52 #define RAW_KEYBOARD_DOWN_ARROW 0x51 #define RAW_KEYBOARD_LEFT_ARROW 0x50 @@ -120,9 +126,69 @@ THE SOFTWARE. #define RAW_KEYBOARD_F10 0x43 #define RAW_KEYBOARD_F11 0x44 #define RAW_KEYBOARD_F12 0x45 + +#define RAW_KEYBOARD_KEY(key) ((key>='a' && key<='z') ? (0x04 + key-'a') :\ +(key>='A' && key<='Z') ? (0x04 + key-'A') : (key>='1' && key<='9') ? (0x1E + key-'1') : 0x27) + +#define RAW_KEYBOARD_A ( 4 ) +#define RAW_KEYBOARD_B ( 5 ) +#define RAW_KEYBOARD_C ( 6 ) +#define RAW_KEYBOARD_D ( 7 ) +#define RAW_KEYBOARD_E ( 8 ) +#define RAW_KEYBOARD_F ( 9 ) +#define RAW_KEYBOARD_G ( 10 ) +#define RAW_KEYBOARD_H ( 11 ) +#define RAW_KEYBOARD_I ( 12 ) +#define RAW_KEYBOARD_J ( 13 ) +#define RAW_KEYBOARD_K ( 14 ) +#define RAW_KEYBOARD_L ( 15 ) +#define RAW_KEYBOARD_M ( 16 ) +#define RAW_KEYBOARD_N ( 17 ) +#define RAW_KEYBOARD_O ( 18 ) +#define RAW_KEYBOARD_P ( 19 ) +#define RAW_KEYBOARD_Q ( 20 ) +#define RAW_KEYBOARD_R ( 21 ) +#define RAW_KEYBOARD_S ( 22 ) +#define RAW_KEYBOARD_T ( 23 ) +#define RAW_KEYBOARD_U ( 24 ) +#define RAW_KEYBOARD_V ( 25 ) +#define RAW_KEYBOARD_W ( 26 ) +#define RAW_KEYBOARD_X ( 27 ) +#define RAW_KEYBOARD_Y ( 28 ) +#define RAW_KEYBOARD_Z ( 29 ) +#define RAW_KEYBOARD_1 ( 30 ) +#define RAW_KEYBOARD_2 ( 31 ) +#define RAW_KEYBOARD_3 ( 32 ) +#define RAW_KEYBOARD_4 ( 33 ) +#define RAW_KEYBOARD_5 ( 34 ) +#define RAW_KEYBOARD_6 ( 35 ) +#define RAW_KEYBOARD_7 ( 36 ) +#define RAW_KEYBOARD_8 ( 37 ) +#define RAW_KEYBOARD_9 ( 38 ) +#define RAW_KEYBOARD_0 ( 39 ) +#define RAW_KEYBOARD_ENTER ( 40 ) +#define RAW_KEYBOARD_ESC ( 41 ) +#define RAW_KEYBOARD_BACKSPACE ( 42 ) +#define RAW_KEYBOARD_TAB ( 43 ) +#define RAW_KEYBOARD_SPACE ( 44 ) +#define RAW_KEYBOARD_MINUS ( 45 ) +#define RAW_KEYBOARD_EQUAL ( 46 ) +#define RAW_KEYBOARD_LEFT_BRACE ( 47 ) +#define RAW_KEYBOARD_RIGHT_BRACE ( 48 ) +#define RAW_KEYBOARD_BACKSLASH ( 49 ) +#define RAW_KEYBOARD_NON_US_NUM ( 50 ) +#define RAW_KEYBOARD_SEMICOLON ( 51 ) +#define RAW_KEYBOARD_QUOTE ( 52 ) +#define RAW_KEYBOARD_TILDE ( 53 ) +#define RAW_KEYBOARD_COMMA ( 54 ) +#define RAW_KEYBOARD_PERIOD ( 55 ) +#define RAW_KEYBOARD_SLASH ( 56 ) + #define RAW_KEYBOARD_PRINT 0x46 +#define RAW_KEYBOARD_NUM_LOCK 0x53 #define RAW_KEYBOARD_SCROLL_LOCK 0x47 #define RAW_KEYBOARD_PAUSE 0x48 +#define RAW_KEYBOARD_MENU 0x65 #define SHIFT 0x80 static const uint8_t _asciimap[128] PROGMEM = @@ -135,9 +201,9 @@ static const uint8_t _asciimap[128] PROGMEM = 0x00, // ENQ 0x00, // ACK 0x00, // BEL - 0x2a, // BS Backspace - 0x2b, // TAB Tab - 0x28, // LF Enter + RAW_KEYBOARD_BACKSPACE, // BS Backspace + RAW_KEYBOARD_TAB, // TAB Tab + RAW_KEYBOARD_RETURN, // LF Enter 0x00, // VT 0x00, // FF 0x00, // CR @@ -160,7 +226,7 @@ static const uint8_t _asciimap[128] PROGMEM = 0x00, // RS 0x00, // US - 0x2c, // ' ' + RAW_KEYBOARD_SPACE, // ' ' 0x1e|SHIFT, // ! 0x34|SHIFT, // " 0x20|SHIFT, // # @@ -173,19 +239,19 @@ static const uint8_t _asciimap[128] PROGMEM = 0x25|SHIFT, // * 0x2e|SHIFT, // + 0x36, // , - 0x2d, // - + RAW_KEYBOARD_MINUS, // - 0x37, // . 0x38, // / - 0x27, // 0 - 0x1e, // 1 - 0x1f, // 2 - 0x20, // 3 - 0x21, // 4 - 0x22, // 5 - 0x23, // 6 - 0x24, // 7 - 0x25, // 8 - 0x26, // 9 + RAW_KEYBOARD_0, // 0 + RAW_KEYBOARD_1, // 1 + RAW_KEYBOARD_2, // 2 + RAW_KEYBOARD_3, // 3 + RAW_KEYBOARD_4, // 4 + RAW_KEYBOARD_5, // 5 + RAW_KEYBOARD_6, // 6 + RAW_KEYBOARD_7, // 7 + RAW_KEYBOARD_8, // 8 + RAW_KEYBOARD_9, // 9 0x33|SHIFT, // : 0x33, // ; 0x36|SHIFT, // < @@ -193,64 +259,64 @@ static const uint8_t _asciimap[128] PROGMEM = 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 + RAW_KEYBOARD_A|SHIFT, // A + RAW_KEYBOARD_B|SHIFT, // B + RAW_KEYBOARD_C|SHIFT, // C + RAW_KEYBOARD_D|SHIFT, // D + RAW_KEYBOARD_E|SHIFT, // E + RAW_KEYBOARD_F|SHIFT, // F + RAW_KEYBOARD_G|SHIFT, // G + RAW_KEYBOARD_H|SHIFT, // H + RAW_KEYBOARD_I|SHIFT, // I + RAW_KEYBOARD_J|SHIFT, // J + RAW_KEYBOARD_K|SHIFT, // K + RAW_KEYBOARD_L|SHIFT, // L + RAW_KEYBOARD_M|SHIFT, // M + RAW_KEYBOARD_N|SHIFT, // N + RAW_KEYBOARD_O|SHIFT, // O + RAW_KEYBOARD_P|SHIFT, // P + RAW_KEYBOARD_Q|SHIFT, // Q + RAW_KEYBOARD_R|SHIFT, // R + RAW_KEYBOARD_S|SHIFT, // S + RAW_KEYBOARD_T|SHIFT, // T + RAW_KEYBOARD_U|SHIFT, // U + RAW_KEYBOARD_V|SHIFT, // V + RAW_KEYBOARD_W|SHIFT, // W + RAW_KEYBOARD_X|SHIFT, // X + RAW_KEYBOARD_Y|SHIFT, // Y + RAW_KEYBOARD_Z|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 + RAW_KEYBOARD_A, // a + RAW_KEYBOARD_B, // b + RAW_KEYBOARD_C, // c + RAW_KEYBOARD_D, // d + RAW_KEYBOARD_E, // e + RAW_KEYBOARD_F, // f + RAW_KEYBOARD_G, // g + RAW_KEYBOARD_H, // h + RAW_KEYBOARD_I, // i + RAW_KEYBOARD_J, // j + RAW_KEYBOARD_K, // k + RAW_KEYBOARD_L, // l + RAW_KEYBOARD_M, // m + RAW_KEYBOARD_N, // n + RAW_KEYBOARD_O, // o + RAW_KEYBOARD_P, // p + RAW_KEYBOARD_Q, // q + RAW_KEYBOARD_R, // r + RAW_KEYBOARD_S, // s + RAW_KEYBOARD_T, // t + RAW_KEYBOARD_U, // u + RAW_KEYBOARD_V, // v + RAW_KEYBOARD_W, // w + RAW_KEYBOARD_X, // x + RAW_KEYBOARD_Y, // y + RAW_KEYBOARD_Z, // z 0x2f|SHIFT, // 0x31|SHIFT, // | 0x30|SHIFT, // } From 92223b7ccfed32e8e38c8a5cf2f7f0f2f92c86ed Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 19 Sep 2015 09:09:25 +0200 Subject: [PATCH 219/602] minor fixes --- plugins/KeyboardioHID/Readme.md | 17 ++++++++++++++++- plugins/KeyboardioHID/src/Consumer.h | 2 ++ plugins/KeyboardioHID/src/HID-Project.h | 9 ++++++--- plugins/KeyboardioHID/src/ImprovedKeylayouts.h | 9 +-------- 4 files changed, 25 insertions(+), 12 deletions(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index cb0fbc2671..0a27b5a170 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -7,6 +7,21 @@ This project went through a lot of phases and has now reached a new Arduino ~~US with a lot of new functions like extended HID. It also supports HoodLoader1+2. The idea is to enable enhanced USB functions to almost all 'standard' Arduino boards. +**Supported Arduinos (IDE 1.6.6 or higher!):** +* Uno (with HoodLoader2) +* Mega (with HoodLoader2) +* Leonardo +* (Pro)Micro +* Any other 8u2/16u/at90usb162/32u2/32u4 compatible board + +**Supported HID devices:** +* Keyboard ~~with Leds out (modifiers + 6 keys pressed at the same time)~~ +* Mouse (5 buttons, move, wheel) +* Absolute Mouse +* Consumer/Media Keys (4 keys for music player, web browser and more) +* System Key (for PC standby/shutdown) +* Gamepad (32 buttons, 4 16bit axis, 2 8bit axis, 2 D-Pads) + See the [wiki](https://github.com/NicoHood/HID/wiki/Features) for more information about features etc. @@ -66,7 +81,7 @@ Version History * Changed USB-Core into a simple library, only possible with Pluggable HID * Removed HID presets (like mouse + keyboard + consumer + system) -2.3 Release (xx.xx.2015) (never released) +2.3 Release (never released) * Updated Libraries * Updated Arduino Core * Added Minor Consumer definitions diff --git a/plugins/KeyboardioHID/src/Consumer.h b/plugins/KeyboardioHID/src/Consumer.h index 1039137017..f5f9fd81e0 100644 --- a/plugins/KeyboardioHID/src/Consumer.h +++ b/plugins/KeyboardioHID/src/Consumer.h @@ -55,6 +55,8 @@ THE SOFTWARE. #define CONSUMER_SCREENSAVER 0x19e +#define CONSUMER_PROGRAMMABLE_BUTTON_CONFIGURATION 0x182 +#define CONSUMER_CONTROL_CONFIGURATION 0x183 #define CONSUMER_EMAIL_READER 0x18A #define CONSUMER_CALCULATOR 0x192 #define CONSUMER_EXPLORER 0x194 diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index e2c20bcab4..0260c32799 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -41,7 +41,7 @@ THE SOFTWARE. //#define LAYOUT_FRENCH //#define LAYOUT_FRENCH_BELGIAN //#define LAYOUT_FRENCH_SWISS -//#define LAYOUT_GERMAN +#define LAYOUT_GERMAN //#define LAYOUT_GERMAN_MAC //#define LAYOUT_GERMAN_SWISS //#define LAYOUT_ICELANDIC @@ -102,13 +102,13 @@ THE SOFTWARE. #define HID_REPORTID_TEENSY_KEYBOARD 9 #endif +#include "HID.h" + extern HID_ HID; #include "HID-Tables.h" // Include all HID libraries (.a linkage required to work) properly -#include "ImprovedKeylayouts.h" -#include "ImprovedKeyboard.h" #include "AbsoluteMouse.h" #include "Consumer.h" #include "Gamepad.h" @@ -117,4 +117,7 @@ extern HID_ HID; // Include Teensy HID afterwards to overwrite key definitions if used #ifdef USE_TEENSY_KEYBOARD #include "TeensyKeyboard.h" +#else +#include "ImprovedKeylayouts.h" +#include "ImprovedKeyboard.h" #endif diff --git a/plugins/KeyboardioHID/src/ImprovedKeylayouts.h b/plugins/KeyboardioHID/src/ImprovedKeylayouts.h index b76ebe1dd6..5a5a5f44e8 100644 --- a/plugins/KeyboardioHID/src/ImprovedKeylayouts.h +++ b/plugins/KeyboardioHID/src/ImprovedKeylayouts.h @@ -21,6 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +// Include guard #pragma once //================================================================================ @@ -87,8 +88,6 @@ THE SOFTWARE. // LAYOUT_US_ENGLISH //================================================================================ -#ifdef LAYOUT_US_ENGLISH - #define RAW_KEYBOARD_LEFT_CTRL (1 << 0) #define RAW_KEYBOARD_LEFT_SHIFT (1 << 1) #define RAW_KEYBOARD_LEFT_ALT (1 << 2) @@ -323,9 +322,3 @@ static const uint8_t _asciimap[128] PROGMEM = 0x35|SHIFT, // ~ 0 // DEL }; - -#else - -//TODO other layouts - -#endif From 0eebb3f62b2f2fdce3c3dac44939648b43a2c964 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 19 Sep 2015 09:10:12 +0200 Subject: [PATCH 220/602] Added Pluggable HID duplicate --- plugins/KeyboardioHID/src/HID.h | 1 + .../KeyboardioHID/src/PluggableHID/HID.cpp | 167 ++++++++++++++++++ plugins/KeyboardioHID/src/PluggableHID/HID.h | 98 ++++++++++ 3 files changed, 266 insertions(+) create mode 100644 plugins/KeyboardioHID/src/HID.h create mode 100644 plugins/KeyboardioHID/src/PluggableHID/HID.cpp create mode 100644 plugins/KeyboardioHID/src/PluggableHID/HID.h diff --git a/plugins/KeyboardioHID/src/HID.h b/plugins/KeyboardioHID/src/HID.h new file mode 100644 index 0000000000..f7644baed6 --- /dev/null +++ b/plugins/KeyboardioHID/src/HID.h @@ -0,0 +1 @@ +#include "PluggableHID/HID.h" diff --git a/plugins/KeyboardioHID/src/PluggableHID/HID.cpp b/plugins/KeyboardioHID/src/PluggableHID/HID.cpp new file mode 100644 index 0000000000..881296fe7e --- /dev/null +++ b/plugins/KeyboardioHID/src/PluggableHID/HID.cpp @@ -0,0 +1,167 @@ +/* Copyright (c) 2015, Arduino LLC +** +** Original code (pre-library): 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 "PluggableUSB.h" +#include "HID.h" + +#if defined(USBCON) + +HID_ HID; + +static u8 HID_ENDPOINT_INT; + +//================================================================================ +//================================================================================ + +// 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 + +static u8 HID_INTERFACE; + +HIDDescriptor _hidInterface; + +static HIDDescriptorListNode* rootNode = NULL; +static uint16_t sizeof_hidReportDescriptor = 0; +static uint8_t modules_count = 0; +//================================================================================ +//================================================================================ +// Driver + +u8 _hid_protocol = 1; +u8 _hid_idle = 1; + +int HID_GetInterface(u8* interfaceNum) +{ + interfaceNum[0] += 1; // uses 1 + _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,USB_EP_SIZE,0x01) + }; + return USB_SendControl(0,&_hidInterface,sizeof(_hidInterface)); +} + +int HID_GetDescriptor(int8_t t) +{ + if (HID_REPORT_DESCRIPTOR_TYPE == t) { + HIDDescriptorListNode* current = rootNode; + int total = 0; + while(current != NULL) { + total += USB_SendControl(TRANSFER_PGM,current->cb->descriptor,current->cb->length); + current = current->next; + } + return total; + } else { + return 0; + } +} + +void HID_::AppendDescriptor(HIDDescriptorListNode *node) +{ + if (modules_count == 0) { + rootNode = node; + } else { + HIDDescriptorListNode *current = rootNode; + while(current->next != NULL) { + current = current->next; + } + current->next = node; + } + modules_count++; + sizeof_hidReportDescriptor += (uint16_t)node->cb->length; +} + +void HID_::SendReport(u8 id, const void* data, int len) +{ + USB_Send(HID_TX, &id, 1); + USB_Send(HID_TX | TRANSFER_RELEASE,data,len); +} + +bool HID_Setup(USBSetup& setup, u8 i) +{ + if (HID_INTERFACE != i) { + return false; + } else { + 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; + } +} + +HID_::HID_(void) +{ + static uint8_t endpointType[1]; + + endpointType[0] = EP_TYPE_INTERRUPT_IN; + + static PUSBCallbacks cb = { + .setup = &HID_Setup, + .getInterface = &HID_GetInterface, + .getDescriptor = &HID_GetDescriptor, + .numEndpoints = 1, + .numInterfaces = 1, + .endpointType = endpointType, + }; + + static PUSBListNode node(&cb); + + HID_ENDPOINT_INT = PUSB_AddFunction(&node, &HID_INTERFACE); +} + +int HID_::begin(void) +{ +} + +#endif /* if defined(USBCON) */ + diff --git a/plugins/KeyboardioHID/src/PluggableHID/HID.h b/plugins/KeyboardioHID/src/PluggableHID/HID.h new file mode 100644 index 0000000000..e2c9469edf --- /dev/null +++ b/plugins/KeyboardioHID/src/PluggableHID/HID.h @@ -0,0 +1,98 @@ +/* + HID.h + + Copyright (c) 2015, Arduino LLC + Original code (pre-library): Copyright (c) 2011, Peter Barrett + + 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 HID_h +#define HID_h + +#include +#include + +#if defined(USBCON) + +#define _USING_HID + +//================================================================================ +//================================================================================ +// HID 'Driver' + +#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 + +#define HID_HID_DESCRIPTOR_TYPE 0x21 +#define HID_REPORT_DESCRIPTOR_TYPE 0x22 +#define HID_PHYSICAL_DESCRIPTOR_TYPE 0x23 + +typedef struct __attribute__((packed)) { + uint16_t length; + const void* descriptor; +} HID_Descriptor; + +class HIDDescriptorListNode { +public: + HIDDescriptorListNode *next = NULL; + const HID_Descriptor * cb; + HIDDescriptorListNode(const HID_Descriptor *ncb) {cb = ncb;} +}; + +class HID_ +{ +public: + HID_(void); + int begin(void); + void SendReport(uint8_t id, const void* data, int len); + void AppendDescriptor(HIDDescriptorListNode* node); +}; + +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 HID_TX HID_ENDPOINT_INT + +#define D_HIDREPORT(_descriptorLength) \ + { 9, 0x21, 0x1, 0x1, 0, 1, 0x22, _descriptorLength & 0xFF, _descriptorLength >> 8 } + +#define WEAK __attribute__ ((weak)) + +#endif + +#endif + From ef705c7e88040ddfb8d8fa6289696a4413a5458d Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 19 Sep 2015 12:16:29 +0200 Subject: [PATCH 221/602] Added KeyboardLeds/HID Out Report This also enables the option for further raw HID development. --- .../examples/KeyboardLed/KeyboardLed.ino | 43 ++++++++ plugins/KeyboardioHID/src/HID-Project.h | 8 +- .../KeyboardioHID/src/ImprovedKeyboard.cpp | 101 +++++++++++------- plugins/KeyboardioHID/src/ImprovedKeyboard.h | 7 +- .../KeyboardioHID/src/ImprovedKeylayouts.h | 2 +- .../KeyboardioHID/src/PluggableHID/HID.cpp | 50 +++++++-- plugins/KeyboardioHID/src/PluggableHID/HID.h | 22 ++-- .../src/PluggableHID/HIDDevice.cpp | 29 +++++ .../src/PluggableHID/HIDDevice.h | 59 ++++++++++ 9 files changed, 251 insertions(+), 70 deletions(-) create mode 100644 plugins/KeyboardioHID/examples/KeyboardLed/KeyboardLed.ino create mode 100644 plugins/KeyboardioHID/src/PluggableHID/HIDDevice.cpp create mode 100644 plugins/KeyboardioHID/src/PluggableHID/HIDDevice.h diff --git a/plugins/KeyboardioHID/examples/KeyboardLed/KeyboardLed.ino b/plugins/KeyboardioHID/examples/KeyboardLed/KeyboardLed.ino new file mode 100644 index 0000000000..3d7e5844c1 --- /dev/null +++ b/plugins/KeyboardioHID/examples/KeyboardLed/KeyboardLed.ino @@ -0,0 +1,43 @@ +/* + Copyright (c) 2014-2015 NicoHood + See the readme for credit to other people. + + KeyboardLed example + + Press a button to toogle caps lock. + Caps lock state is represented by the onboard led. + + See HID Project documentation for more information. + https://github.com/NicoHood/HID/wiki/Keyboard-API +*/ + +#include "HID-Project.h" + +const int pinLed = LED_BUILTIN; +const int pinButton = 2; + +void setup() { + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); + + // Sends a clean report to the host. This is important on any Arduino type. + Keyboard.begin(); +} + + +void loop() { + // Update Led equal to the caps lock state. + // Keep in mind that on a 16u2 and Arduino Micro HIGH and LOW for TX/RX Leds are inverted. + if (Keyboard.getLeds()&LED_CAPS_LOCK) + digitalWrite(pinLed, HIGH); + else + digitalWrite(pinLed, LOW); + + // Trigger caps lock manually via button + if (!digitalRead(pinButton)) { + Keyboard.write(KEY_CAPS_LOCK); + + // Simple debounce + delay(300); + } +} diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index 0260c32799..009023b486 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -109,10 +109,10 @@ extern HID_ HID; #include "HID-Tables.h" // Include all HID libraries (.a linkage required to work) properly -#include "AbsoluteMouse.h" -#include "Consumer.h" -#include "Gamepad.h" -#include "System.h" +//#include "AbsoluteMouse.h" +//#include "Consumer.h" +//#include "Gamepad.h" +//#include "System.h" // Include Teensy HID afterwards to overwrite key definitions if used #ifdef USE_TEENSY_KEYBOARD diff --git a/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp b/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp index 06a0ed535c..680648aa5d 100644 --- a/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp +++ b/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp @@ -30,46 +30,58 @@ THE SOFTWARE. // Keyboard static const u8 _hidReportDescriptor[] PROGMEM = { - - // Keyboard - 0x05, 0x01, // USAGE_PAGE (Generic Desktop) // 47 - 0x09, 0x06, // USAGE (Keyboard) - 0xa1, 0x01, // COLLECTION (Application) - 0x85, HID_REPORTID_KEYBOARD, // REPORT_ID - 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 + // Keyboard + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 47 */ + 0x09, 0x06, /* USAGE (Keyboard) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + 0x85, HID_REPORTID_KEYBOARD, /* REPORT_ID */ + 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ + + /* Keyboard Modifiers (shift, alt, ...) */ + 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) */ + + /* Reserved byte */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ + + /* 5 LEDs for num lock etc */ + 0x05, 0x08, /* USAGE_PAGE (LEDs) */ + 0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */ + 0x29, 0x05, /* USAGE_MAXIMUM (Kana) */ + 0x95, 0x05, /* REPORT_COUNT (5) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */ + /* Reserved 3 bits */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x03, /* REPORT_SIZE (3) */ + 0x91, 0x03, /* OUTPUT (Cnst,Var,Abs) */ + + /* 6 Keyboard keys */ + 0x95, 0x06, /* REPORT_COUNT (6) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x26, 0xE7, 0x00, /* LOGICAL_MAXIMUM (231) */ + 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ + 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ + 0x29, 0xE7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ + 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ + + /* End */ + 0xc0 /* END_COLLECTION */ }; -Keyboard_::Keyboard_(void) +Keyboard_::Keyboard_(void) : +HIDDevice((uint8_t*)_hidReportDescriptor, sizeof(_hidReportDescriptor), HID_REPORTID_KEYBOARD), +leds(0) { - static HID_Descriptor cb = { - .length = sizeof(_hidReportDescriptor), - .descriptor = _hidReportDescriptor, - }; - static HIDDescriptorListNode node(&cb); - HID.AppendDescriptor(&node); + // HID Descriptor is appended via the inherited HIDDevice class } void Keyboard_::begin(void) @@ -82,9 +94,22 @@ void Keyboard_::end(void) void Keyboard_::sendReport(HID_KeyboardReport_Data_t* keys) { - HID.SendReport(HID_REPORTID_KEYBOARD,keys,sizeof(HID_KeyboardReport_Data_t)); + // Call the inherited function. + // This wrapper still saves us some bytes + SendReport(keys,sizeof(HID_KeyboardReport_Data_t)); +} + +void Keyboard_::setReportData(const void* data, int len){ + // Save led state + if(len == 1) + leds = *(uint8_t*)data; } +uint8_t Keyboard_::getLeds(void){ + return leds; +} + + // 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 diff --git a/plugins/KeyboardioHID/src/ImprovedKeyboard.h b/plugins/KeyboardioHID/src/ImprovedKeyboard.h index c0cd373de3..49d6cc5844 100644 --- a/plugins/KeyboardioHID/src/ImprovedKeyboard.h +++ b/plugins/KeyboardioHID/src/ImprovedKeyboard.h @@ -36,6 +36,7 @@ THE SOFTWARE. // Keyboard #include "HID-Project.h" +#include "PluggableHID/HIDDevice.h" #include "ImprovedKeylayouts.h" // Low level key report: up to 6 keys and shift, ctrl etc at once @@ -51,11 +52,13 @@ typedef union{ }; } HID_KeyboardReport_Data_t; -class Keyboard_ : public Print +class Keyboard_ : public Print, public HIDDevice { private: HID_KeyboardReport_Data_t _keyReport; void sendReport(HID_KeyboardReport_Data_t* keys); + virtual void setReportData(const void* data, int len); + uint8_t leds; public: Keyboard_(void); void begin(void); @@ -70,6 +73,8 @@ class Keyboard_ : public Print size_t releaseKeycode(uint8_t k); size_t addKeycodeToReport(uint8_t k); size_t removeKeycodeFromReport(uint8_t k); + + uint8_t getLeds(void); }; extern Keyboard_ Keyboard; diff --git a/plugins/KeyboardioHID/src/ImprovedKeylayouts.h b/plugins/KeyboardioHID/src/ImprovedKeylayouts.h index 5a5a5f44e8..2ba3d454eb 100644 --- a/plugins/KeyboardioHID/src/ImprovedKeylayouts.h +++ b/plugins/KeyboardioHID/src/ImprovedKeylayouts.h @@ -79,7 +79,7 @@ THE SOFTWARE. #define KEY_RIGHT_WINDOWS KEY_RIGHT_GUI #define KEY_PRINTSCREEN KEY_PRINT -// TODO implement Leds +// Keyboard Leds #define LED_NUM_LOCK 0x01 #define LED_CAPS_LOCK 0x02 #define LED_SCROLL_LOCK 0x04 diff --git a/plugins/KeyboardioHID/src/PluggableHID/HID.cpp b/plugins/KeyboardioHID/src/PluggableHID/HID.cpp index 881296fe7e..de7b8ed42b 100644 --- a/plugins/KeyboardioHID/src/PluggableHID/HID.cpp +++ b/plugins/KeyboardioHID/src/PluggableHID/HID.cpp @@ -18,6 +18,7 @@ #include "PluggableUSB.h" #include "HID.h" +#include "HIDDevice.h" #if defined(USBCON) @@ -42,7 +43,7 @@ static u8 HID_INTERFACE; HIDDescriptor _hidInterface; -static HIDDescriptorListNode* rootNode = NULL; +static HIDDevice* rootDevice = NULL; static uint16_t sizeof_hidReportDescriptor = 0; static uint8_t modules_count = 0; //================================================================================ @@ -67,10 +68,10 @@ int HID_GetInterface(u8* interfaceNum) int HID_GetDescriptor(int8_t t) { if (HID_REPORT_DESCRIPTOR_TYPE == t) { - HIDDescriptorListNode* current = rootNode; + HIDDevice* current = rootDevice; int total = 0; while(current != NULL) { - total += USB_SendControl(TRANSFER_PGM,current->cb->descriptor,current->cb->length); + total += USB_SendControl(TRANSFER_PGM,current->descriptorData,current->descriptorLength); current = current->next; } return total; @@ -79,19 +80,19 @@ int HID_GetDescriptor(int8_t t) } } -void HID_::AppendDescriptor(HIDDescriptorListNode *node) +void HID_::AppendDescriptor(HIDDevice *device) { if (modules_count == 0) { - rootNode = node; + rootDevice = device; } else { - HIDDescriptorListNode *current = rootNode; + HIDDevice *current = rootDevice; while(current->next != NULL) { current = current->next; } - current->next = node; + current->next = device; } modules_count++; - sizeof_hidReportDescriptor += (uint16_t)node->cb->length; + sizeof_hidReportDescriptor += (uint16_t)device->descriptorLength; } void HID_::SendReport(u8 id, const void* data, int len) @@ -100,7 +101,7 @@ void HID_::SendReport(u8 id, const void* data, int len) USB_Send(HID_TX | TRANSFER_RELEASE,data,len); } -bool HID_Setup(USBSetup& setup, u8 i) +bool HID_::HID_Setup(USBSetup& setup, u8 i) { if (HID_INTERFACE != i) { return false; @@ -134,6 +135,35 @@ bool HID_Setup(USBSetup& setup, u8 i) _hid_idle = setup.wValueL; return true; } + + if (HID_SET_REPORT == r) + { + // Get reportID and search for the suited HIDDevice + uint8_t ID = setup.wIndex; + HIDDevice *current = rootDevice; + while(current != NULL) + { + // TODO implementation for non reportID HID devices + // This would could make rawHID work. reportID 0 could be used as indicator + if(current->reportID == ID) + { + // Get the data length information and the corresponding bytes + uint8_t length = setup.wLength; + uint8_t data[length]; + USB_RecvControl(data, length); + + // Skip report ID data + current->setReportData(data+1, length-1); + + // Dont search any further + break; + } + current = current->next; + } + //TODO return true?? + // https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/USBCore.cpp#L613-L618 + return true; + } } return false; } @@ -146,7 +176,7 @@ HID_::HID_(void) endpointType[0] = EP_TYPE_INTERRUPT_IN; static PUSBCallbacks cb = { - .setup = &HID_Setup, + .setup = HID_Setup, .getInterface = &HID_GetInterface, .getDescriptor = &HID_GetDescriptor, .numEndpoints = 1, diff --git a/plugins/KeyboardioHID/src/PluggableHID/HID.h b/plugins/KeyboardioHID/src/PluggableHID/HID.h index e2c9469edf..8b1c150295 100644 --- a/plugins/KeyboardioHID/src/PluggableHID/HID.h +++ b/plugins/KeyboardioHID/src/PluggableHID/HID.h @@ -19,7 +19,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef HID_h +#pragma once + #define HID_h #include @@ -44,17 +45,7 @@ #define HID_REPORT_DESCRIPTOR_TYPE 0x22 #define HID_PHYSICAL_DESCRIPTOR_TYPE 0x23 -typedef struct __attribute__((packed)) { - uint16_t length; - const void* descriptor; -} HID_Descriptor; - -class HIDDescriptorListNode { -public: - HIDDescriptorListNode *next = NULL; - const HID_Descriptor * cb; - HIDDescriptorListNode(const HID_Descriptor *ncb) {cb = ncb;} -}; +class HIDDevice; class HID_ { @@ -62,7 +53,9 @@ class HID_ HID_(void); int begin(void); void SendReport(uint8_t id, const void* data, int len); - void AppendDescriptor(HIDDescriptorListNode* node); + void AppendDescriptor(HIDDevice* device); +private: + static bool HID_Setup(USBSetup& setup, u8 i); }; typedef struct @@ -93,6 +86,3 @@ typedef struct #define WEAK __attribute__ ((weak)) #endif - -#endif - diff --git a/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.cpp b/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.cpp new file mode 100644 index 0000000000..a0c311eef6 --- /dev/null +++ b/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.cpp @@ -0,0 +1,29 @@ + +#include "PluggableUSB.h" +#include "HIDDevice.h" +#include "HID.h" + +#ifdef kkk +#error +#endif + +#if defined(USBCON) + +HIDDevice::HIDDevice(uint8_t* data, uint16_t length, uint8_t ID) : +descriptorData(data), descriptorLength(length), reportID(ID) +{ + // TODO call Append + // TODO init const data + // TODO template? + HID.AppendDescriptor(this); +} + +void HIDDevice::SendReport(const void* data, int len){ + HID.SendReport(reportID, data, len); +} + +void HIDDevice::setReportData(const void* data, int len){ + // Discard this information if its not implemented by the HIDDevice +} + +#endif diff --git a/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.h b/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.h new file mode 100644 index 0000000000..54d6804089 --- /dev/null +++ b/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.h @@ -0,0 +1,59 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 guard +#pragma once + +#define HID_h + +#include +#include + +//http://stackoverflow.com/questions/1837165/can-two-classes-see-each-other-using-c + +class HID_; +extern HID_ HID; + +class HIDDevice +{ +public: + HIDDevice(uint8_t* data, uint16_t length, uint8_t ID); + + // Needs to be public for static HID_ function access +//private: + HIDDevice* next = NULL; + + // HID Descriptor + const uint8_t* descriptorData; + const uint16_t descriptorLength; + const uint8_t reportID; + + virtual void setReportData(const void* data, int len); + +protected: + // TODO make this public for custom, professional usage? + void SendReport(const void* data, int len); +}; + + + From cebcbfe7f33aa40601863c121da6325b61859ffc Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 19 Sep 2015 12:45:43 +0200 Subject: [PATCH 222/602] Minor fixes --- plugins/KeyboardioHID/Readme.md | 12 ++++++++++-- plugins/KeyboardioHID/src/HID-Project.h | 4 ++-- plugins/KeyboardioHID/src/ImprovedKeyboard.cpp | 13 ++++++++++--- plugins/KeyboardioHID/src/ImprovedKeyboard.h | 6 +++++- plugins/KeyboardioHID/src/PluggableHID/HID.h | 1 - plugins/KeyboardioHID/src/PluggableHID/HIDDevice.h | 6 +++--- 6 files changed, 30 insertions(+), 12 deletions(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 0a27b5a170..68c392a4be 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -15,7 +15,8 @@ The idea is to enable enhanced USB functions to almost all 'standard' Arduino bo * Any other 8u2/16u/at90usb162/32u2/32u4 compatible board **Supported HID devices:** -* Keyboard ~~with Leds out (modifiers + 6 keys pressed at the same time)~~ +* Keyboard with Leds out (modifiers + 6 keys pressed at the same time) +* NKRO Keyboard with Leds out (press up to 113 keys at the same time) * Mouse (5 buttons, move, wheel) * Absolute Mouse * Consumer/Media Keys (4 keys for music player, web browser and more) @@ -78,8 +79,15 @@ Version History ``` 2.4 Release (xx.xx.2015) * Added Arduino IDE 1.6.6 compatibility with Pluggable HID +* Improved Pluggable HID (have its own modifed copy now) * Changed USB-Core into a simple library, only possible with Pluggable HID -* Removed HID presets (like mouse + keyboard + consumer + system) +* Removed HID presets in boards menu (like mouse + keyboard + consumer + system) +* Added Teensy Keyboard +* Added NKRO Keyboard +* Added Led report for Keyboard +* Added HID out report in general (RAW HID preparation) +* Added a few key definitions +* Uses .alinkage custom IDE option 2.3 Release (never released) * Updated Libraries diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index 009023b486..ed7d460531 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -33,6 +33,8 @@ THE SOFTWARE. #error "This is not an USB AVR or you use an old version of the IDE." #endif +#define HID_KEYBOARD_LEDS_ENABLED + //#define LAYOUT_US_ENGLISH //#define LAYOUT_CANADIAN_FRENCH //#define LAYOUT_CANADIAN_MULTILINGUAL @@ -104,8 +106,6 @@ THE SOFTWARE. #include "HID.h" -extern HID_ HID; - #include "HID-Tables.h" // Include all HID libraries (.a linkage required to work) properly diff --git a/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp b/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp index 680648aa5d..e53a3f3402 100644 --- a/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp +++ b/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp @@ -50,7 +50,9 @@ static const u8 _hidReportDescriptor[] PROGMEM = { 0x95, 0x01, /* REPORT_COUNT (1) */ 0x75, 0x08, /* REPORT_SIZE (8) */ 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ - + +#if defined(HID_KEYBOARD_LEDS_ENABLED) +//TODO remove reserved bytes to add 3 more custom data bits for advanced users? /* 5 LEDs for num lock etc */ 0x05, 0x08, /* USAGE_PAGE (LEDs) */ 0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */ @@ -62,6 +64,7 @@ static const u8 _hidReportDescriptor[] PROGMEM = { 0x95, 0x01, /* REPORT_COUNT (1) */ 0x75, 0x03, /* REPORT_SIZE (3) */ 0x91, 0x03, /* OUTPUT (Cnst,Var,Abs) */ +#endif /* 6 Keyboard keys */ 0x95, 0x06, /* REPORT_COUNT (6) */ @@ -78,8 +81,10 @@ static const u8 _hidReportDescriptor[] PROGMEM = { }; Keyboard_::Keyboard_(void) : -HIDDevice((uint8_t*)_hidReportDescriptor, sizeof(_hidReportDescriptor), HID_REPORTID_KEYBOARD), -leds(0) +HIDDevice((uint8_t*)_hidReportDescriptor, sizeof(_hidReportDescriptor), HID_REPORTID_KEYBOARD) +#if defined(HID_KEYBOARD_LEDS_ENABLED) +,leds(0) +#endif { // HID Descriptor is appended via the inherited HIDDevice class } @@ -99,6 +104,7 @@ void Keyboard_::sendReport(HID_KeyboardReport_Data_t* keys) SendReport(keys,sizeof(HID_KeyboardReport_Data_t)); } +#if defined(HID_KEYBOARD_LEDS_ENABLED) void Keyboard_::setReportData(const void* data, int len){ // Save led state if(len == 1) @@ -108,6 +114,7 @@ void Keyboard_::setReportData(const void* data, int len){ uint8_t Keyboard_::getLeds(void){ return leds; } +#endif // press() adds the specified key (printing, non-printing, or modifier) diff --git a/plugins/KeyboardioHID/src/ImprovedKeyboard.h b/plugins/KeyboardioHID/src/ImprovedKeyboard.h index 49d6cc5844..6a46cc8283 100644 --- a/plugins/KeyboardioHID/src/ImprovedKeyboard.h +++ b/plugins/KeyboardioHID/src/ImprovedKeyboard.h @@ -57,8 +57,10 @@ class Keyboard_ : public Print, public HIDDevice private: HID_KeyboardReport_Data_t _keyReport; void sendReport(HID_KeyboardReport_Data_t* keys); +#if defined(HID_KEYBOARD_LEDS_ENABLED) virtual void setReportData(const void* data, int len); uint8_t leds; +#endif public: Keyboard_(void); void begin(void); @@ -73,8 +75,10 @@ class Keyboard_ : public Print, public HIDDevice size_t releaseKeycode(uint8_t k); size_t addKeycodeToReport(uint8_t k); size_t removeKeycodeFromReport(uint8_t k); - + +#if defined(HID_KEYBOARD_LEDS_ENABLED) uint8_t getLeds(void); +#endif }; extern Keyboard_ Keyboard; diff --git a/plugins/KeyboardioHID/src/PluggableHID/HID.h b/plugins/KeyboardioHID/src/PluggableHID/HID.h index 8b1c150295..e15c858e10 100644 --- a/plugins/KeyboardioHID/src/PluggableHID/HID.h +++ b/plugins/KeyboardioHID/src/PluggableHID/HID.h @@ -23,7 +23,6 @@ #define HID_h -#include #include #if defined(USBCON) diff --git a/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.h b/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.h index 54d6804089..6d43866818 100644 --- a/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.h +++ b/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.h @@ -49,9 +49,9 @@ class HIDDevice const uint8_t reportID; virtual void setReportData(const void* data, int len); - -protected: - // TODO make this public for custom, professional usage? + + // Public for custom, professional usage, like raw Keyboard +//protected: void SendReport(const void* data, int len); }; From b8d0f34cac023d1ca8c2582b54612e12ad6c9a39 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 19 Sep 2015 13:15:32 +0200 Subject: [PATCH 223/602] Updated HIDDevices for new, modified Pluggable HID version Keyboard got improved a bit as well. --- .../examples/AbsoluteMouse/AbsoluteMouse.ino | 1 - .../examples/Consumer/Consumer.ino | 17 +++++++-------- .../examples/Gamepad/Gamepad.ino | 1 - .../KeyboardioHID/examples/System/System.ino | 5 ++--- plugins/KeyboardioHID/src/AbsoluteMouse.h | 15 ++++++------- plugins/KeyboardioHID/src/Consumer.h | 19 +++++++---------- plugins/KeyboardioHID/src/Gamepad.h | 17 +++++++-------- plugins/KeyboardioHID/src/HID-Project.h | 8 +++---- plugins/KeyboardioHID/src/HID.h | 1 + plugins/KeyboardioHID/src/ImprovedKeyboard.h | 3 +-- .../src/PluggableHID/HIDDevice.cpp | 3 --- .../src/PluggableHID/HIDDevice.h | 6 ++++-- plugins/KeyboardioHID/src/System.cpp | 2 +- plugins/KeyboardioHID/src/System.h | 21 +++++++++++-------- plugins/KeyboardioHID/src/TeensyKeyboard.cpp | 13 +++++------- plugins/KeyboardioHID/src/TeensyKeyboard.h | 4 ++-- 16 files changed, 61 insertions(+), 75 deletions(-) diff --git a/plugins/KeyboardioHID/examples/AbsoluteMouse/AbsoluteMouse.ino b/plugins/KeyboardioHID/examples/AbsoluteMouse/AbsoluteMouse.ino index 4abccd9de6..872ee63eb6 100644 --- a/plugins/KeyboardioHID/examples/AbsoluteMouse/AbsoluteMouse.ino +++ b/plugins/KeyboardioHID/examples/AbsoluteMouse/AbsoluteMouse.ino @@ -10,7 +10,6 @@ https://github.com/NicoHood/HID/wiki/AbsoluteMouse-API */ -#include "HID.h" #include "HID-Project.h" const int pinLed = LED_BUILTIN; diff --git a/plugins/KeyboardioHID/examples/Consumer/Consumer.ino b/plugins/KeyboardioHID/examples/Consumer/Consumer.ino index fa75e2665e..0c566e960c 100644 --- a/plugins/KeyboardioHID/examples/Consumer/Consumer.ino +++ b/plugins/KeyboardioHID/examples/Consumer/Consumer.ino @@ -1,15 +1,14 @@ /* - Copyright (c) 2014-2015 NicoHood - See the readme for credit to other people. - - Consumer example - Press a button to play/pause music player - - See HID Project documentation for more Consumer keys. - https://github.com/NicoHood/HID/wiki/Consumer-API + Copyright (c) 2014-2015 NicoHood + See the readme for credit to other people. + + Consumer example + Press a button to play/pause music player + + See HID Project documentation for more Consumer keys. + https://github.com/NicoHood/HID/wiki/Consumer-API */ -#include "HID.h" #include "HID-Project.h" const int pinLed = LED_BUILTIN; diff --git a/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino b/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino index bff18dac64..c567c0ae9c 100644 --- a/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino +++ b/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino @@ -9,7 +9,6 @@ https://github.com/NicoHood/HID/wiki/Gamepad-API */ -#include "HID.h" #include "HID-Project.h" const int pinLed = LED_BUILTIN; diff --git a/plugins/KeyboardioHID/examples/System/System.ino b/plugins/KeyboardioHID/examples/System/System.ino index 92445d6f8c..696a82af10 100644 --- a/plugins/KeyboardioHID/examples/System/System.ino +++ b/plugins/KeyboardioHID/examples/System/System.ino @@ -9,7 +9,6 @@ https://github.com/NicoHood/HID/wiki/System-API */ -#include "HID.h" #include "HID-Project.h" const int pinLed = LED_BUILTIN; @@ -30,7 +29,7 @@ void loop() { if (!digitalRead(pinButtonS)) { digitalWrite(pinLed, HIGH); - // Puts pc into sleep mode/shuts it down + // Puts PC into sleep mode/shuts it down System.write(SYSTEM_SLEEP); //System.write(SYSTEM_POWER_DOWN); @@ -42,7 +41,7 @@ void loop() { if (!digitalRead(pinButtonW)) { digitalWrite(pinLed, HIGH); - // Tries to wake up the PC + // Try to wake up the PC // This might fail on some PCs/Laptops where USB wakeup is not supported System.write(SYSTEM_WAKE_UP); diff --git a/plugins/KeyboardioHID/src/AbsoluteMouse.h b/plugins/KeyboardioHID/src/AbsoluteMouse.h index 9aadca64c9..be646a4d35 100644 --- a/plugins/KeyboardioHID/src/AbsoluteMouse.h +++ b/plugins/KeyboardioHID/src/AbsoluteMouse.h @@ -98,7 +98,7 @@ typedef union{ }; } HID_MouseAbsoluteReport_Data_t; -class AbsMouse_ +class AbsMouse_ : private HIDDevice { private: int16_t xAxis = 0; @@ -131,13 +131,10 @@ class AbsMouse_ } public: - inline AbsMouse_(void) { - static HID_Descriptor cb = { - .length = sizeof(_absmouseReportDescriptor), - .descriptor = _absmouseReportDescriptor, - }; - static HIDDescriptorListNode node(&cb); - HID.AppendDescriptor(&node); + inline AbsMouse_(void): + HIDDevice((uint8_t*)_absmouseReportDescriptor, sizeof(_absmouseReportDescriptor), HID_REPORTID_MOUSE_ABSOLUTE) + { + // HID Descriptor is appended via the inherited HIDDevice class } inline void begin(void){ @@ -165,7 +162,7 @@ class AbsMouse_ report.xAxis = x; report.yAxis = y; report.wheel = wheel; - HID.SendReport(HID_REPORTID_MOUSE_ABSOLUTE, &report, sizeof(report)); + SendReport(&report, sizeof(report)); } inline void move(int x, int y, signed char wheel = 0){ diff --git a/plugins/KeyboardioHID/src/Consumer.h b/plugins/KeyboardioHID/src/Consumer.h index f5f9fd81e0..80da75d5e3 100644 --- a/plugins/KeyboardioHID/src/Consumer.h +++ b/plugins/KeyboardioHID/src/Consumer.h @@ -97,15 +97,12 @@ typedef union { }; } HID_ConsumerControlReport_Data_t; -class Consumer_ { +class Consumer_ : private HIDDevice { public: - inline Consumer_(void) { - static HID_Descriptor cb = { - .length = sizeof(_consumerReportDescriptor), - .descriptor = _consumerReportDescriptor, - }; - static HIDDescriptorListNode node(&cb); - HID.AppendDescriptor(&node); + inline Consumer_(void) : + HIDDevice((uint8_t*)_consumerReportDescriptor, sizeof(_consumerReportDescriptor), HID_REPORTID_CONSUMERCONTROL) + { + // HID Descriptor is appended via the inherited HIDDevice class } inline void begin(void) { @@ -115,7 +112,7 @@ class Consumer_ { inline void end(void) { memset(&_report, 0, sizeof(_report)); - HID.SendReport(HID_REPORTID_CONSUMERCONTROL, &_report, sizeof(_report)); + SendReport(&_report, sizeof(_report)); } inline void write(uint16_t m) { @@ -131,7 +128,7 @@ class Consumer_ { break; } } - HID.SendReport(HID_REPORTID_CONSUMERCONTROL, &_report, sizeof(_report)); + SendReport(&_report, sizeof(_report)); } inline void release(uint16_t m) { @@ -142,7 +139,7 @@ class Consumer_ { // no break to delete multiple keys } } - HID.SendReport(HID_REPORTID_CONSUMERCONTROL, &_report, sizeof(_report)); + SendReport(&_report, sizeof(_report)); } inline void releaseAll(void) { diff --git a/plugins/KeyboardioHID/src/Gamepad.h b/plugins/KeyboardioHID/src/Gamepad.h index 1a09c24cd6..d9671be6f4 100644 --- a/plugins/KeyboardioHID/src/Gamepad.h +++ b/plugins/KeyboardioHID/src/Gamepad.h @@ -154,15 +154,12 @@ typedef union { }; } HID_GamepadReport_Data_t; -class Gamepad_{ +class Gamepad_ : private HIDDevice{ public: - inline Gamepad_(void){ - static HID_Descriptor cb = { - .length = sizeof(_gamepadReportDescriptor), - .descriptor = _gamepadReportDescriptor, - }; - static HIDDescriptorListNode node(&cb); - HID.AppendDescriptor(&node); + inline Gamepad_(void) : + HIDDevice((uint8_t*)_gamepadReportDescriptor, sizeof(_gamepadReportDescriptor), HID_REPORTID_GAMEPAD) + { + // HID Descriptor is appended via the inherited HIDDevice class } inline void begin(void){ @@ -172,10 +169,10 @@ class Gamepad_{ inline void end(void){ memset(&_report, 0, sizeof(_report)); - HID.SendReport(HID_REPORTID_GAMEPAD, &_report, sizeof(_report)); + SendReport(&_report, sizeof(_report)); } - inline void write(void){ HID.SendReport(HID_REPORTID_GAMEPAD, &_report, sizeof(_report)); } + inline void write(void){ SendReport(&_report, sizeof(_report)); } inline void press(uint8_t b){ _report.buttons |= (uint32_t)1 << (b - 1); } inline void release(uint8_t b){ _report.buttons &= ~((uint32_t)1 << (b - 1)); } inline void releaseAll(void){ memset(&_report, 0x00, sizeof(_report)); } diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index ed7d460531..bd8286f816 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -109,10 +109,10 @@ THE SOFTWARE. #include "HID-Tables.h" // Include all HID libraries (.a linkage required to work) properly -//#include "AbsoluteMouse.h" -//#include "Consumer.h" -//#include "Gamepad.h" -//#include "System.h" +#include "AbsoluteMouse.h" +#include "Consumer.h" +#include "Gamepad.h" +#include "System.h" // Include Teensy HID afterwards to overwrite key definitions if used #ifdef USE_TEENSY_KEYBOARD diff --git a/plugins/KeyboardioHID/src/HID.h b/plugins/KeyboardioHID/src/HID.h index f7644baed6..775c6177ae 100644 --- a/plugins/KeyboardioHID/src/HID.h +++ b/plugins/KeyboardioHID/src/HID.h @@ -1 +1,2 @@ #include "PluggableHID/HID.h" +#include "PluggableHID/HIDDevice.h" diff --git a/plugins/KeyboardioHID/src/ImprovedKeyboard.h b/plugins/KeyboardioHID/src/ImprovedKeyboard.h index 6a46cc8283..c6119e28c6 100644 --- a/plugins/KeyboardioHID/src/ImprovedKeyboard.h +++ b/plugins/KeyboardioHID/src/ImprovedKeyboard.h @@ -36,7 +36,6 @@ THE SOFTWARE. // Keyboard #include "HID-Project.h" -#include "PluggableHID/HIDDevice.h" #include "ImprovedKeylayouts.h" // Low level key report: up to 6 keys and shift, ctrl etc at once @@ -52,7 +51,7 @@ typedef union{ }; } HID_KeyboardReport_Data_t; -class Keyboard_ : public Print, public HIDDevice +class Keyboard_ : public Print, private HIDDevice { private: HID_KeyboardReport_Data_t _keyReport; diff --git a/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.cpp b/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.cpp index a0c311eef6..b29295d923 100644 --- a/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.cpp +++ b/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.cpp @@ -12,9 +12,6 @@ HIDDevice::HIDDevice(uint8_t* data, uint16_t length, uint8_t ID) : descriptorData(data), descriptorLength(length), reportID(ID) { - // TODO call Append - // TODO init const data - // TODO template? HID.AppendDescriptor(this); } diff --git a/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.h b/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.h index 6d43866818..6663263041 100644 --- a/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.h +++ b/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.h @@ -40,6 +40,7 @@ class HIDDevice HIDDevice(uint8_t* data, uint16_t length, uint8_t ID); // Needs to be public for static HID_ function access + // Inherit this device private and everything should be fine //private: HIDDevice* next = NULL; @@ -50,8 +51,9 @@ class HIDDevice virtual void setReportData(const void* data, int len); - // Public for custom, professional usage, like raw Keyboard -//protected: +protected: + // Could be used and inherited public for custom, professional usage, like raw Keyboard + // As an alternative you may still call the HID singleton. void SendReport(const void* data, int len); }; diff --git a/plugins/KeyboardioHID/src/System.cpp b/plugins/KeyboardioHID/src/System.cpp index 4b59ec18eb..f4cd4e9e90 100644 --- a/plugins/KeyboardioHID/src/System.cpp +++ b/plugins/KeyboardioHID/src/System.cpp @@ -37,7 +37,7 @@ void System_::press(uint8_t s){ USBDevice.wakeupHost(); else #endif - HID.SendReport(HID_REPORTID_SYSTEMCONTROL, &s, sizeof(s)); + SendReport(&s, sizeof(s)); } #endif diff --git a/plugins/KeyboardioHID/src/System.h b/plugins/KeyboardioHID/src/System.h index 22baebe0d2..816403cd57 100644 --- a/plugins/KeyboardioHID/src/System.h +++ b/plugins/KeyboardioHID/src/System.h @@ -65,32 +65,35 @@ typedef union{ uint8_t key; } HID_SystemControlReport_Data_t; -class System_{ +class System_ : private HIDDevice{ public: - inline System_(void){ - static HID_Descriptor cb = { - .length = sizeof(_systemReportDescriptor), - .descriptor = _systemReportDescriptor, - }; - static HIDDescriptorListNode node(&cb); - HID.AppendDescriptor(&node); + inline System_(void) : + HIDDevice((uint8_t*)_systemReportDescriptor, sizeof(_systemReportDescriptor), HID_REPORTID_SYSTEMCONTROL) + { + // HID Descriptor is appended via the inherited HIDDevice class } + inline void begin(void){ // release all buttons end(); } + inline void end(void){ uint8_t _report = 0; - HID.SendReport(HID_REPORTID_SYSTEMCONTROL, &_report, sizeof(_report)); + SendReport(&_report, sizeof(_report)); } + inline void write(uint8_t s){ press(s); release(); } + void press(uint8_t s); + inline void release(void){ begin(); } + inline void releaseAll(void){ begin(); } diff --git a/plugins/KeyboardioHID/src/TeensyKeyboard.cpp b/plugins/KeyboardioHID/src/TeensyKeyboard.cpp index 46d7e484b1..2a8f8b6843 100644 --- a/plugins/KeyboardioHID/src/TeensyKeyboard.cpp +++ b/plugins/KeyboardioHID/src/TeensyKeyboard.cpp @@ -23,13 +23,10 @@ #include "TeensyKeyboard.h" -usb_keyboard_class::usb_keyboard_class(void){ - static HID_Descriptor cb = { - .length = sizeof(keyboard_hid_report_desc), - .descriptor = keyboard_hid_report_desc, - }; - static HIDDescriptorListNode node(&cb); - HID.AppendDescriptor(&node); +usb_keyboard_class::usb_keyboard_class(void) : +HIDDevice((uint8_t*)teensykeyboard_hid_report_desc, sizeof(teensykeyboard_hid_report_desc), HID_REPORTID_TEENSY_KEYBOARD) +{ + // HID Descriptor is appended via the inherited HIDDevice class } // Step #1, decode UTF8 to Unicode code points @@ -256,7 +253,7 @@ void usb_keyboard_class::set_media(uint8_t c) void usb_keyboard_class::send_now(void) { - HID.SendReport(HID_REPORTID_TEENSY_KEYBOARD,keyboard_report_data,sizeof(keyboard_report_data)); + SendReport(keyboard_report_data,sizeof(keyboard_report_data)); } diff --git a/plugins/KeyboardioHID/src/TeensyKeyboard.h b/plugins/KeyboardioHID/src/TeensyKeyboard.h index 82a633527c..7b1fb2d319 100644 --- a/plugins/KeyboardioHID/src/TeensyKeyboard.h +++ b/plugins/KeyboardioHID/src/TeensyKeyboard.h @@ -35,7 +35,7 @@ #include "TeensyKeylayouts.h" // Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60 -static const uint8_t PROGMEM keyboard_hid_report_desc[] = { +static const uint8_t PROGMEM teensykeyboard_hid_report_desc[] = { 0x05, 0x01, // Usage Page (Generic Desktop), 0x09, 0x06, // Usage (Keyboard), 0xA1, 0x01, // Collection (Application), @@ -82,7 +82,7 @@ static const uint8_t PROGMEM keyboard_hid_report_desc[] = { 0xc0 // End Collection }; -class usb_keyboard_class : public Print +class usb_keyboard_class : public Print, private HIDDevice { public: usb_keyboard_class(void); From 6a714630ad94dd11ad3356f586094ea627c7b8a0 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 19 Sep 2015 14:37:42 +0200 Subject: [PATCH 224/602] Added Boot Keyboard support If enabled the keyboard will not work in the OS again. This still needs to be fixed. Experimental! --- plugins/KeyboardioHID/src/HID-Project.h | 3 +++ .../KeyboardioHID/src/ImprovedKeyboard.cpp | 4 ++++ .../KeyboardioHID/src/PluggableHID/HID.cpp | 23 +++++++++++++++---- plugins/KeyboardioHID/src/TeensyKeyboard.cpp | 4 ++++ 4 files changed, 29 insertions(+), 5 deletions(-) diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index bd8286f816..ad8882f3b3 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -34,6 +34,7 @@ THE SOFTWARE. #endif #define HID_KEYBOARD_LEDS_ENABLED +//#define USE_BOOT_KEYBOARD_PROTOCOL //#define LAYOUT_US_ENGLISH //#define LAYOUT_CANADIAN_FRENCH @@ -72,6 +73,8 @@ THE SOFTWARE. #define LAYOUT_US_ENGLISH #endif +#define HID_REPORTID_NONE 0 + #ifndef HID_REPORTID_MOUSE #define HID_REPORTID_MOUSE 1 #endif diff --git a/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp b/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp index e53a3f3402..1f1019afe7 100644 --- a/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp +++ b/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp @@ -101,7 +101,11 @@ void Keyboard_::sendReport(HID_KeyboardReport_Data_t* keys) { // Call the inherited function. // This wrapper still saves us some bytes +#if defined(USE_BOOT_KEYBOARD_PROTOCOL) + HID.SendReport(HID_REPORTID_NONE, keys,sizeof(HID_KeyboardReport_Data_t)); +#else SendReport(keys,sizeof(HID_KeyboardReport_Data_t)); +#endif } #if defined(HID_KEYBOARD_LEDS_ENABLED) diff --git a/plugins/KeyboardioHID/src/PluggableHID/HID.cpp b/plugins/KeyboardioHID/src/PluggableHID/HID.cpp index de7b8ed42b..01a7c764ee 100644 --- a/plugins/KeyboardioHID/src/PluggableHID/HID.cpp +++ b/plugins/KeyboardioHID/src/PluggableHID/HID.cpp @@ -19,6 +19,7 @@ #include "PluggableUSB.h" #include "HID.h" #include "HIDDevice.h" +#include "HID-Project.h" // Only used for the BootKeyboard setting #if defined(USBCON) @@ -58,7 +59,11 @@ int HID_GetInterface(u8* interfaceNum) interfaceNum[0] += 1; // uses 1 _hidInterface = { +#if defined(USE_BOOT_KEYBOARD_PROTOCOL) + D_INTERFACE(HID_INTERFACE,1,3,1,1), +#else D_INTERFACE(HID_INTERFACE,1,3,0,0), +#endif D_HIDREPORT(sizeof_hidReportDescriptor), D_ENDPOINT(USB_ENDPOINT_IN (HID_ENDPOINT_INT),USB_ENDPOINT_TYPE_INTERRUPT,USB_EP_SIZE,0x01) }; @@ -97,7 +102,10 @@ void HID_::AppendDescriptor(HIDDevice *device) void HID_::SendReport(u8 id, const void* data, int len) { - USB_Send(HID_TX, &id, 1); + // Only send report ID if it exists + if(id){ + USB_Send(HID_TX, &id, 1); + } USB_Send(HID_TX | TRANSFER_RELEASE,data,len); } @@ -143,8 +151,7 @@ bool HID_::HID_Setup(USBSetup& setup, u8 i) HIDDevice *current = rootDevice; while(current != NULL) { - // TODO implementation for non reportID HID devices - // This would could make rawHID work. reportID 0 could be used as indicator + // Search HIDDevice for report ID if(current->reportID == ID) { // Get the data length information and the corresponding bytes @@ -152,8 +159,14 @@ bool HID_::HID_Setup(USBSetup& setup, u8 i) uint8_t data[length]; USB_RecvControl(data, length); - // Skip report ID data - current->setReportData(data+1, length-1); + // Skip report ID data, if any + if(ID){ + current->setReportData(data+1, length-1); + } + // TODO test this case + else{ + current->setReportData(data, length); + } // Dont search any further break; diff --git a/plugins/KeyboardioHID/src/TeensyKeyboard.cpp b/plugins/KeyboardioHID/src/TeensyKeyboard.cpp index 2a8f8b6843..25855faebf 100644 --- a/plugins/KeyboardioHID/src/TeensyKeyboard.cpp +++ b/plugins/KeyboardioHID/src/TeensyKeyboard.cpp @@ -253,7 +253,11 @@ void usb_keyboard_class::set_media(uint8_t c) void usb_keyboard_class::send_now(void) { +#if defined(USE_BOOT_KEYBOARD_PROTOCOL) + HID.SendReport(HID_REPORTID_NONE, keyboard_report_data,sizeof(keyboard_report_data)); +#else SendReport(keyboard_report_data,sizeof(keyboard_report_data)); +#endif } From 2362a7e8314252acd226a1db067d1d6401750361 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 19 Sep 2015 15:24:06 +0200 Subject: [PATCH 225/602] Important CDC Lag fix --- plugins/KeyboardioHID/src/PluggableHID/HID.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/plugins/KeyboardioHID/src/PluggableHID/HID.cpp b/plugins/KeyboardioHID/src/PluggableHID/HID.cpp index 01a7c764ee..3470caacb3 100644 --- a/plugins/KeyboardioHID/src/PluggableHID/HID.cpp +++ b/plugins/KeyboardioHID/src/PluggableHID/HID.cpp @@ -173,9 +173,6 @@ bool HID_::HID_Setup(USBSetup& setup, u8 i) } current = current->next; } - //TODO return true?? - // https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/USBCore.cpp#L613-L618 - return true; } } return false; From 60278fe022a72b761e02c25d071eeb711780ef5d Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 19 Sep 2015 15:41:41 +0200 Subject: [PATCH 226/602] Made HID_ class members static inside the class, not global. --- .../KeyboardioHID/src/PluggableHID/HID.cpp | 24 ++++++------ plugins/KeyboardioHID/src/PluggableHID/HID.h | 39 +++++++++++++------ .../src/PluggableHID/HIDDevice.cpp | 4 ++ .../src/PluggableHID/HIDDevice.h | 1 + 4 files changed, 44 insertions(+), 24 deletions(-) diff --git a/plugins/KeyboardioHID/src/PluggableHID/HID.cpp b/plugins/KeyboardioHID/src/PluggableHID/HID.cpp index 3470caacb3..96ffb3950c 100644 --- a/plugins/KeyboardioHID/src/PluggableHID/HID.cpp +++ b/plugins/KeyboardioHID/src/PluggableHID/HID.cpp @@ -25,8 +25,6 @@ HID_ HID; -static u8 HID_ENDPOINT_INT; - //================================================================================ //================================================================================ @@ -40,21 +38,21 @@ static u8 HID_ENDPOINT_INT; #define RAWHID_TX_SIZE 64 #define RAWHID_RX_SIZE 64 -static u8 HID_INTERFACE; - -HIDDescriptor _hidInterface; +// Static variables +uint8_t HID_::HID_ENDPOINT_INT; +uint8_t HID_::HID_INTERFACE; +HIDDescriptor HID_::_hidInterface; +HIDDevice* HID_::rootDevice = NULL; +uint16_t HID_::sizeof_hidReportDescriptor = 0; +uint8_t HID_::modules_count = 0; +uint8_t HID_::_hid_protocol = 1; +uint8_t HID_::_hid_idle = 1; -static HIDDevice* rootDevice = NULL; -static uint16_t sizeof_hidReportDescriptor = 0; -static uint8_t modules_count = 0; //================================================================================ //================================================================================ // Driver -u8 _hid_protocol = 1; -u8 _hid_idle = 1; - -int HID_GetInterface(u8* interfaceNum) +int HID_::HID_GetInterface(u8* interfaceNum) { interfaceNum[0] += 1; // uses 1 _hidInterface = @@ -70,7 +68,7 @@ int HID_GetInterface(u8* interfaceNum) return USB_SendControl(0,&_hidInterface,sizeof(_hidInterface)); } -int HID_GetDescriptor(int8_t t) +int HID_::HID_GetDescriptor(int8_t t) { if (HID_REPORT_DESCRIPTOR_TYPE == t) { HIDDevice* current = rootDevice; diff --git a/plugins/KeyboardioHID/src/PluggableHID/HID.h b/plugins/KeyboardioHID/src/PluggableHID/HID.h index e15c858e10..e53a4df875 100644 --- a/plugins/KeyboardioHID/src/PluggableHID/HID.h +++ b/plugins/KeyboardioHID/src/PluggableHID/HID.h @@ -46,17 +46,6 @@ class HIDDevice; -class HID_ -{ -public: - HID_(void); - int begin(void); - void SendReport(uint8_t id, const void* data, int len); - void AppendDescriptor(HIDDevice* device); -private: - static bool HID_Setup(USBSetup& setup, u8 i); -}; - typedef struct { u8 len; // 9 @@ -77,6 +66,34 @@ typedef struct EndpointDescriptor in; } HIDDescriptor; +class HID_ +{ +public: + HID_(void); + + // Only access this class via the HIDDevice +private: + friend HIDDevice; + int begin(void); + void SendReport(uint8_t id, const void* data, int len); + void AppendDescriptor(HIDDevice* device); + + // Static functions + static int HID_GetInterface(u8* interfaceNum); + static int HID_GetDescriptor(int8_t t); + static bool HID_Setup(USBSetup& setup, u8 i); + + // Static variables + static uint8_t HID_ENDPOINT_INT; + static uint8_t HID_INTERFACE; + static HIDDescriptor _hidInterface; + static HIDDevice* rootDevice; + static uint16_t sizeof_hidReportDescriptor; + static uint8_t modules_count; + static uint8_t _hid_protocol; + static uint8_t _hid_idle; +}; + #define HID_TX HID_ENDPOINT_INT #define D_HIDREPORT(_descriptorLength) \ diff --git a/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.cpp b/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.cpp index b29295d923..d697f400ca 100644 --- a/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.cpp +++ b/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.cpp @@ -22,5 +22,9 @@ void HIDDevice::SendReport(const void* data, int len){ void HIDDevice::setReportData(const void* data, int len){ // Discard this information if its not implemented by the HIDDevice } + +uint8_t HIDDevice::getProtocol(void){ + return HID._hid_protocol; +} #endif diff --git a/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.h b/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.h index 6663263041..ef2fcf5585 100644 --- a/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.h +++ b/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.h @@ -55,6 +55,7 @@ class HIDDevice // Could be used and inherited public for custom, professional usage, like raw Keyboard // As an alternative you may still call the HID singleton. void SendReport(const void* data, int len); + uint8_t getProtocol(void); }; From cf0db8a7b9c2e01308eb2e9897469794a3bafaee Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 19 Sep 2015 15:55:22 +0200 Subject: [PATCH 227/602] Enabled BootKeyboard by default, now dynamically chooses the protocol type --- plugins/KeyboardioHID/Readme.md | 5 ++++- plugins/KeyboardioHID/src/HID-Project.h | 2 +- plugins/KeyboardioHID/src/ImprovedKeyboard.cpp | 8 +++++--- plugins/KeyboardioHID/src/PluggableHID/HIDDevice.cpp | 9 +++++---- plugins/KeyboardioHID/src/PluggableHID/HIDDevice.h | 1 + plugins/KeyboardioHID/src/TeensyKeyboard.cpp | 8 +++++--- 6 files changed, 21 insertions(+), 12 deletions(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 68c392a4be..3fcddc20c7 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -12,10 +12,12 @@ The idea is to enable enhanced USB functions to almost all 'standard' Arduino bo * Mega (with HoodLoader2) * Leonardo * (Pro)Micro -* Any other 8u2/16u/at90usb162/32u2/32u4 compatible board +* Any other 8u2/16u2/at90usb8/162/32u2/32u4 compatible board **Supported HID devices:** * Keyboard with Leds out (modifiers + 6 keys pressed at the same time) +* Teensy Keyboard with different keyboard layouts (german, french and many more) +* BootKeyboard protocol for Improved/Teensy Keyboard (works under BIOS) * NKRO Keyboard with Leds out (press up to 113 keys at the same time) * Mouse (5 buttons, move, wheel) * Absolute Mouse @@ -88,6 +90,7 @@ Version History * Added HID out report in general (RAW HID preparation) * Added a few key definitions * Uses .alinkage custom IDE option +* Added BootKeyboard support (BIOS compatibility) 2.3 Release (never released) * Updated Libraries diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index ad8882f3b3..ffce021612 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -34,7 +34,7 @@ THE SOFTWARE. #endif #define HID_KEYBOARD_LEDS_ENABLED -//#define USE_BOOT_KEYBOARD_PROTOCOL +#define USE_BOOT_KEYBOARD_PROTOCOL //#define LAYOUT_US_ENGLISH //#define LAYOUT_CANADIAN_FRENCH diff --git a/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp b/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp index 1f1019afe7..146818d50a 100644 --- a/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp +++ b/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp @@ -102,10 +102,12 @@ void Keyboard_::sendReport(HID_KeyboardReport_Data_t* keys) // Call the inherited function. // This wrapper still saves us some bytes #if defined(USE_BOOT_KEYBOARD_PROTOCOL) - HID.SendReport(HID_REPORTID_NONE, keys,sizeof(HID_KeyboardReport_Data_t)); -#else - SendReport(keys,sizeof(HID_KeyboardReport_Data_t)); + if(getProtocol() != 1){ + SendRawReport(keys,sizeof(HID_KeyboardReport_Data_t)); + } + else #endif + SendReport(keys,sizeof(HID_KeyboardReport_Data_t)); } #if defined(HID_KEYBOARD_LEDS_ENABLED) diff --git a/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.cpp b/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.cpp index d697f400ca..97b5c83570 100644 --- a/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.cpp +++ b/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.cpp @@ -2,10 +2,7 @@ #include "PluggableUSB.h" #include "HIDDevice.h" #include "HID.h" - -#ifdef kkk -#error -#endif +#include "HID-Project.h" #if defined(USBCON) @@ -19,6 +16,10 @@ void HIDDevice::SendReport(const void* data, int len){ HID.SendReport(reportID, data, len); } +void HIDDevice::SendRawReport(const void* data, int len){ + HID.SendReport(HID_REPORTID_NONE, data, len); +} + void HIDDevice::setReportData(const void* data, int len){ // Discard this information if its not implemented by the HIDDevice } diff --git a/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.h b/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.h index ef2fcf5585..1ec3495a10 100644 --- a/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.h +++ b/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.h @@ -55,6 +55,7 @@ class HIDDevice // Could be used and inherited public for custom, professional usage, like raw Keyboard // As an alternative you may still call the HID singleton. void SendReport(const void* data, int len); + void SendRawReport(const void* data, int len); uint8_t getProtocol(void); }; diff --git a/plugins/KeyboardioHID/src/TeensyKeyboard.cpp b/plugins/KeyboardioHID/src/TeensyKeyboard.cpp index 25855faebf..10f36a33e1 100644 --- a/plugins/KeyboardioHID/src/TeensyKeyboard.cpp +++ b/plugins/KeyboardioHID/src/TeensyKeyboard.cpp @@ -254,10 +254,12 @@ void usb_keyboard_class::set_media(uint8_t c) void usb_keyboard_class::send_now(void) { #if defined(USE_BOOT_KEYBOARD_PROTOCOL) - HID.SendReport(HID_REPORTID_NONE, keyboard_report_data,sizeof(keyboard_report_data)); -#else - SendReport(keyboard_report_data,sizeof(keyboard_report_data)); + if(getProtocol() != 1){ + SendRawReport(keyboard_report_data,sizeof(keyboard_report_data)); + } + else #endif + SendReport(keyboard_report_data,sizeof(keyboard_report_data)); } From 20fb8c1caa2e9f913b7f0f52a06aedf799911a41 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 19 Sep 2015 16:15:33 +0200 Subject: [PATCH 228/602] Prevent other reports from sending while in bios mode --- plugins/KeyboardioHID/src/PluggableHID/HID.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/plugins/KeyboardioHID/src/PluggableHID/HID.cpp b/plugins/KeyboardioHID/src/PluggableHID/HID.cpp index 96ffb3950c..03774142ae 100644 --- a/plugins/KeyboardioHID/src/PluggableHID/HID.cpp +++ b/plugins/KeyboardioHID/src/PluggableHID/HID.cpp @@ -102,8 +102,19 @@ void HID_::SendReport(u8 id, const void* data, int len) { // Only send report ID if it exists if(id){ +#if defined(USE_BOOT_KEYBOARD_PROTOCOL) + // Do not send a normal report while in Bootloader mode. + if(_hid_protocol != 1){ + return; + } +#endif USB_Send(HID_TX, &id, 1); } + // Non reportID reports (rawHID) will still try to send data. + // If this happens at PC boot this can cause wrong keypresses. + // Normally any data > 8 byte should be ignored due to the USB specs. + // To avoid this, use the getProtocol() function of the HIDDevice + // inside the rawHID etc or disable the boot protocol. USB_Send(HID_TX | TRANSFER_RELEASE,data,len); } From bc9f9f7f118833cf5dec9379ee7ae5f06a4321ef Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 19 Sep 2015 16:17:09 +0200 Subject: [PATCH 229/602] Added Arduino Mouse library (not compatible) The next commit will patch the files for HID-Project --- plugins/KeyboardioHID/src/ImprovedMouse.cpp | 127 ++++++++++++++++++++ plugins/KeyboardioHID/src/ImprovedMouse.h | 61 ++++++++++ 2 files changed, 188 insertions(+) create mode 100644 plugins/KeyboardioHID/src/ImprovedMouse.cpp create mode 100644 plugins/KeyboardioHID/src/ImprovedMouse.h diff --git a/plugins/KeyboardioHID/src/ImprovedMouse.cpp b/plugins/KeyboardioHID/src/ImprovedMouse.cpp new file mode 100644 index 0000000000..234ca60341 --- /dev/null +++ b/plugins/KeyboardioHID/src/ImprovedMouse.cpp @@ -0,0 +1,127 @@ +/* + Mouse.cpp + + Copyright (c) 2015, Arduino LLC + Original code (pre-library): Copyright (c) 2011, Peter Barrett + + 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 "Mouse.h" + +#if defined(_USING_HID) + +static const uint8_t _hidReportDescriptor[] PROGMEM = { + + // 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 +}; + +//================================================================================ +//================================================================================ +// Mouse + +Mouse_::Mouse_(void) : _buttons(0) +{ + const static HID_Descriptor cb = { + .length = sizeof(_hidReportDescriptor), + .descriptor = _hidReportDescriptor, + }; + static HIDDescriptorListNode node(&cb); + HID.AppendDescriptor(&node); +} + +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) +{ + uint8_t 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; +} + +Mouse_ Mouse; + +#endif diff --git a/plugins/KeyboardioHID/src/ImprovedMouse.h b/plugins/KeyboardioHID/src/ImprovedMouse.h new file mode 100644 index 0000000000..3ab57a5eb1 --- /dev/null +++ b/plugins/KeyboardioHID/src/ImprovedMouse.h @@ -0,0 +1,61 @@ +/* + Mouse.h + + Copyright (c) 2015, Arduino LLC + Original code (pre-library): Copyright (c) 2011, Peter Barrett + + 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 MOUSE_h +#define MOUSE_h + +#include "HID.h" + +#if !defined(_USING_HID) + +#warning "Using legacy HID core (non pluggable)" + +#else + +//================================================================================ +//================================================================================ +// 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; +extern HID_ HID; + +#endif +#endif \ No newline at end of file From 8334f4c2c3dc6fcba722f9d08c33af3d47389714 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 19 Sep 2015 16:35:58 +0200 Subject: [PATCH 230/602] Added Improved Mouse Made Mouse API compatible with HID-Project --- plugins/KeyboardioHID/src/HID-Project.h | 1 + plugins/KeyboardioHID/src/ImprovedMouse.cpp | 86 ++++++++++----------- plugins/KeyboardioHID/src/ImprovedMouse.h | 66 ++++++++++------ 3 files changed, 85 insertions(+), 68 deletions(-) diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index ffce021612..b3a556207b 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -113,6 +113,7 @@ THE SOFTWARE. // Include all HID libraries (.a linkage required to work) properly #include "AbsoluteMouse.h" +#include "ImprovedMouse.h" #include "Consumer.h" #include "Gamepad.h" #include "System.h" diff --git a/plugins/KeyboardioHID/src/ImprovedMouse.cpp b/plugins/KeyboardioHID/src/ImprovedMouse.cpp index 234ca60341..483feb17bb 100644 --- a/plugins/KeyboardioHID/src/ImprovedMouse.cpp +++ b/plugins/KeyboardioHID/src/ImprovedMouse.cpp @@ -19,63 +19,61 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "Mouse.h" +#include "ImprovedMouse.h" #if defined(_USING_HID) static const uint8_t _hidReportDescriptor[] PROGMEM = { - - // 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 + /* Mouse relative */ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 54 */ + 0x09, 0x02, /* USAGE (Mouse) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + 0x85, HID_REPORTID_MOUSE, /* REPORT_ID */ + + /* 8 Buttons */ + 0x05, 0x09, /* USAGE_PAGE (Button) */ + 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ + 0x29, 0x08, /* USAGE_MAXIMUM (Button 8) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x95, 0x08, /* REPORT_COUNT (8) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + + /* X, Y, Wheel */ + 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) */ + + /* End */ + 0xc0 /* END_COLLECTION */ }; //================================================================================ //================================================================================ // Mouse -Mouse_::Mouse_(void) : _buttons(0) +Mouse_::Mouse_(void) : _buttons(0), +HIDDevice((uint8_t*)_hidReportDescriptor, sizeof(_hidReportDescriptor), HID_REPORTID_MOUSE) { - const static HID_Descriptor cb = { - .length = sizeof(_hidReportDescriptor), - .descriptor = _hidReportDescriptor, - }; - static HIDDescriptorListNode node(&cb); - HID.AppendDescriptor(&node); + // HID Descriptor is appended via the inherited HIDDevice class } void Mouse_::begin(void) { + end(); } void Mouse_::end(void) { + _buttons = 0; + move(0, 0, 0); } void Mouse_::click(uint8_t b) @@ -88,12 +86,12 @@ void Mouse_::click(uint8_t b) void Mouse_::move(signed char x, signed char y, signed char wheel) { - uint8_t m[4]; - m[0] = _buttons; - m[1] = x; - m[2] = y; - m[3] = wheel; - HID.SendReport(1,m,4); + HID_MouseReport_Data_t report; + report.buttons = _buttons; + report.xAxis = x; + report.yAxis = y; + report.wheel = wheel; + SendReport(&report, sizeof(report)); } void Mouse_::buttons(uint8_t b) diff --git a/plugins/KeyboardioHID/src/ImprovedMouse.h b/plugins/KeyboardioHID/src/ImprovedMouse.h index 3ab57a5eb1..0265208b84 100644 --- a/plugins/KeyboardioHID/src/ImprovedMouse.h +++ b/plugins/KeyboardioHID/src/ImprovedMouse.h @@ -1,26 +1,27 @@ /* - Mouse.h +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. - Copyright (c) 2015, Arduino LLC - Original code (pre-library): Copyright (c) 2011, Peter Barrett +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: - 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. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. - 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 +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 MOUSE_h -#define MOUSE_h +#pragma once #include "HID.h" @@ -34,12 +35,31 @@ //================================================================================ // Mouse -#define MOUSE_LEFT 1 -#define MOUSE_RIGHT 2 -#define MOUSE_MIDDLE 4 -#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE) +#include "HID-Project.h" + +#define MOUSE_LEFT (1 << 0) +#define MOUSE_RIGHT (1 << 1) +#define MOUSE_MIDDLE (1 << 2) +#define MOUSE_PREV (1 << 3) +#define MOUSE_NEXT (1 << 4) +// actually this mouse report has 8 buttons (for smaller descriptor) +// but the last 3 wont do anything from what I tested +#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE | MOUSE_PREV | MOUSE_NEXT) + +typedef union{ + // mouse report: 8 buttons, position, wheel + uint8_t whole8[]; + uint16_t whole16[]; + uint32_t whole32[]; + struct{ + uint8_t buttons; + int8_t xAxis; + int8_t yAxis; + int8_t wheel; + }; +} HID_MouseReport_Data_t; -class Mouse_ +class Mouse_ : private HIDDevice { private: uint8_t _buttons; @@ -55,7 +75,5 @@ class Mouse_ bool isPressed(uint8_t b = MOUSE_LEFT); // check LEFT by default }; extern Mouse_ Mouse; -extern HID_ HID; #endif -#endif \ No newline at end of file From 94ca708bf2791ab414ff4e5c916b53a07668994c Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 19 Sep 2015 16:46:08 +0200 Subject: [PATCH 231/602] Added boot protocol for mouse --- plugins/KeyboardioHID/src/HID-Project.h | 14 ++++++++++++++ plugins/KeyboardioHID/src/ImprovedMouse.cpp | 9 +++++++++ plugins/KeyboardioHID/src/PluggableHID/HID.cpp | 4 +++- 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index b3a556207b..e5d5b8c5ae 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -33,8 +33,13 @@ THE SOFTWARE. #error "This is not an USB AVR or you use an old version of the IDE." #endif +//================================================================================ +// Settings +//================================================================================ + #define HID_KEYBOARD_LEDS_ENABLED #define USE_BOOT_KEYBOARD_PROTOCOL +//#define USE_BOOT_MOUSE_PROTOCOL //#define LAYOUT_US_ENGLISH //#define LAYOUT_CANADIAN_FRENCH @@ -60,6 +65,10 @@ THE SOFTWARE. //#define LAYOUT_UNITED_KINGDOM //#define LAYOUT_US_INTERNATIONAL +//================================================================================ +// Definitions and Helpers +//================================================================================ + // Default US keyboard layout #if !defined(LAYOUT_CANADIAN_FRENCH) && !defined(LAYOUT_CANADIAN_MULTILINGUAL) \ && !defined(LAYOUT_DANISH) && !defined(LAYOUT_FINNISH) && !defined(LAYOUT_FRENCH) \ @@ -107,6 +116,11 @@ THE SOFTWARE. #define HID_REPORTID_TEENSY_KEYBOARD 9 #endif +#if defined(USE_BOOT_KEYBOARD_PROTOCOL) && defined(USE_BOOT_MOUSE_PROTOCOL) +// Technically it is possible but not within this (simpler) API. +#error "You cannot use a boot compatible keyboard and mouse at the same time." +#endif + #include "HID.h" #include "HID-Tables.h" diff --git a/plugins/KeyboardioHID/src/ImprovedMouse.cpp b/plugins/KeyboardioHID/src/ImprovedMouse.cpp index 483feb17bb..46740bbc21 100644 --- a/plugins/KeyboardioHID/src/ImprovedMouse.cpp +++ b/plugins/KeyboardioHID/src/ImprovedMouse.cpp @@ -91,6 +91,15 @@ void Mouse_::move(signed char x, signed char y, signed char wheel) report.xAxis = x; report.yAxis = y; report.wheel = wheel; +#if defined(USE_BOOT_MOUSE_PROTOCOL) + if(getProtocol() != 1){ + // Do not send the wheel information. + // It should be discarded by the host, + // but to be sure we better leave it out. + SendRawReport(&report, sizeof(report)-1); + } + else +#endif SendReport(&report, sizeof(report)); } diff --git a/plugins/KeyboardioHID/src/PluggableHID/HID.cpp b/plugins/KeyboardioHID/src/PluggableHID/HID.cpp index 03774142ae..17fa0b0d7e 100644 --- a/plugins/KeyboardioHID/src/PluggableHID/HID.cpp +++ b/plugins/KeyboardioHID/src/PluggableHID/HID.cpp @@ -59,6 +59,8 @@ int HID_::HID_GetInterface(u8* interfaceNum) { #if defined(USE_BOOT_KEYBOARD_PROTOCOL) D_INTERFACE(HID_INTERFACE,1,3,1,1), +#elif defined(USE_BOOT_MOUSE_PROTOCOL) + D_INTERFACE(HID_INTERFACE,1,3,1,2), #else D_INTERFACE(HID_INTERFACE,1,3,0,0), #endif @@ -102,7 +104,7 @@ void HID_::SendReport(u8 id, const void* data, int len) { // Only send report ID if it exists if(id){ -#if defined(USE_BOOT_KEYBOARD_PROTOCOL) +#if defined(USE_BOOT_KEYBOARD_PROTOCOL) || defined(USE_BOOT_MOUSE_PROTOCOL) // Do not send a normal report while in Bootloader mode. if(_hid_protocol != 1){ return; From 1de5fd79b58a0652c2b68e41c0dce2252208ab2b Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 19 Sep 2015 16:46:34 +0200 Subject: [PATCH 232/602] Added Mouse example --- .../examples/ImprovedMouse/ImprovedMouse.ino | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 plugins/KeyboardioHID/examples/ImprovedMouse/ImprovedMouse.ino diff --git a/plugins/KeyboardioHID/examples/ImprovedMouse/ImprovedMouse.ino b/plugins/KeyboardioHID/examples/ImprovedMouse/ImprovedMouse.ino new file mode 100644 index 0000000000..5ccdb96adb --- /dev/null +++ b/plugins/KeyboardioHID/examples/ImprovedMouse/ImprovedMouse.ino @@ -0,0 +1,65 @@ +/* + Copyright (c) 2014-2015 NicoHood + See the readme for credit to other people. + + Mouse example + Press a button to click or move the mouse. + + See HID Project documentation for more Information. + https://github.com/NicoHood/HID/wiki/Mouse-API +*/ + +#include "HID-Project.h" + +const int pinLed = LED_BUILTIN; +const int pinButtonClick = 2; +const int pinButtonMove = 3; +const int pinButtonScroll = 4; + +void setup() { + // Prepare led + buttons + pinMode(pinLed, OUTPUT); + pinMode(pinButtonClick, INPUT_PULLUP); + pinMode(pinButtonMove, INPUT_PULLUP); + pinMode(pinButtonScroll, INPUT_PULLUP); + + // Sends a clean report to the host. This is important on any Arduino type. + Mouse.begin(); +} + +void loop() { + if (!digitalRead(pinButtonClick)) { + digitalWrite(pinLed, HIGH); + + // Same use as the official library, pretty much self explaining + Mouse.click(); + //Mouse.click(MOUSE_RIGHT); + + // Simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } + + if (!digitalRead(pinButtonMove)) { + digitalWrite(pinLed, HIGH); + + // Same use as the official library, pretty much self explaining + Mouse.move(100, 0); + + // Simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } + + if (!digitalRead(pinButtonScroll)) { + digitalWrite(pinLed, HIGH); + + // Scroll down a bit, make sure the value is high enough + Mouse.move(0, 0, 160); + + // simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } +} + From 9f316971af3a8fe6e3e1d96a93e4304677431181 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 19 Sep 2015 16:54:47 +0200 Subject: [PATCH 233/602] Release keyboard keys on begin() and end() --- plugins/KeyboardioHID/src/ImprovedKeyboard.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp b/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp index 146818d50a..aff0e2160e 100644 --- a/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp +++ b/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp @@ -91,10 +91,12 @@ HIDDevice((uint8_t*)_hidReportDescriptor, sizeof(_hidReportDescriptor), HID_REPO void Keyboard_::begin(void) { + releaseAll(); } void Keyboard_::end(void) { + releaseAll(); } void Keyboard_::sendReport(HID_KeyboardReport_Data_t* keys) From a1f04a7ad3625658eaa1b6213c613ce01d5d1890 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 19 Sep 2015 17:28:36 +0200 Subject: [PATCH 234/602] added bool operator --- plugins/KeyboardioHID/src/PluggableHID/HID.cpp | 10 ++++++++++ plugins/KeyboardioHID/src/PluggableHID/HID.h | 1 + 2 files changed, 11 insertions(+) diff --git a/plugins/KeyboardioHID/src/PluggableHID/HID.cpp b/plugins/KeyboardioHID/src/PluggableHID/HID.cpp index 17fa0b0d7e..1e6f196f50 100644 --- a/plugins/KeyboardioHID/src/PluggableHID/HID.cpp +++ b/plugins/KeyboardioHID/src/PluggableHID/HID.cpp @@ -210,6 +210,16 @@ HID_::HID_(void) HID_ENDPOINT_INT = PUSB_AddFunction(&node, &HID_INTERFACE); } +HID_::operator bool() { + if(USBDevice.configured()){ + delay(10); + return true; + } + else{ + return false; + } +} + int HID_::begin(void) { } diff --git a/plugins/KeyboardioHID/src/PluggableHID/HID.h b/plugins/KeyboardioHID/src/PluggableHID/HID.h index e53a4df875..5562f9e2ac 100644 --- a/plugins/KeyboardioHID/src/PluggableHID/HID.h +++ b/plugins/KeyboardioHID/src/PluggableHID/HID.h @@ -70,6 +70,7 @@ class HID_ { public: HID_(void); + operator bool(); // Only access this class via the HIDDevice private: From 0589d4aea0676ee550894598d0c81423d41a3625 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 19 Sep 2015 17:58:35 +0200 Subject: [PATCH 235/602] Added NKRO Keyboard --- .../examples/NKROKeyboard/NKROKeyboard.ino | 68 +++++ plugins/KeyboardioHID/src/HID-Project.h | 1 + plugins/KeyboardioHID/src/NKROKeyboard.cpp | 283 ++++++++++++++++++ plugins/KeyboardioHID/src/NKROKeyboard.h | 83 +++++ 4 files changed, 435 insertions(+) create mode 100644 plugins/KeyboardioHID/examples/NKROKeyboard/NKROKeyboard.ino create mode 100644 plugins/KeyboardioHID/src/NKROKeyboard.cpp create mode 100644 plugins/KeyboardioHID/src/NKROKeyboard.h diff --git a/plugins/KeyboardioHID/examples/NKROKeyboard/NKROKeyboard.ino b/plugins/KeyboardioHID/examples/NKROKeyboard/NKROKeyboard.ino new file mode 100644 index 0000000000..dae938571c --- /dev/null +++ b/plugins/KeyboardioHID/examples/NKROKeyboard/NKROKeyboard.ino @@ -0,0 +1,68 @@ +/* + Copyright (c) 2014-2015 NicoHood + See the readme for credit to other people. + + NKROKeyboard example + + Press a button to press a lot of keys at the same time. + NKRO can push 113 keys at the same time, + the other Keyboards only 6 keys + 8 modifiers! + + See HID Project documentation for more information. + https://github.com/NicoHood/HID/wiki/Keyboard-API +*/ + +#include "HID-Project.h" + +const int pinLed = LED_BUILTIN; +const int pinButton = 2; + +void setup() { + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); + + // Sends a clean report to the host. This is important on any Arduino type. + NKROKeyboard.begin(); +} + +void loop() { + // Press a lot of keys at the same time + if (!digitalRead(pinButton)) { + digitalWrite(pinLed, HIGH); + + NKROKeyboard.press('a'); + NKROKeyboard.press('b'); + NKROKeyboard.press('c'); + NKROKeyboard.press('d'); + NKROKeyboard.press('e'); + NKROKeyboard.press('f'); + NKROKeyboard.press('g'); + NKROKeyboard.press('h'); + NKROKeyboard.press('i'); + NKROKeyboard.press('j'); + NKROKeyboard.press('k'); + NKROKeyboard.press('l'); + NKROKeyboard.press('m'); + NKROKeyboard.press('n'); + NKROKeyboard.press('o'); + NKROKeyboard.press('p'); + NKROKeyboard.press('q'); + NKROKeyboard.press('r'); + NKROKeyboard.press('s'); + NKROKeyboard.press('t'); + NKROKeyboard.press('u'); + NKROKeyboard.press('v'); + NKROKeyboard.press('w'); + NKROKeyboard.press('x'); + NKROKeyboard.press('y'); + NKROKeyboard.press('z'); + + // Release all keys and hit enter + NKROKeyboard.releaseAll(); + NKROKeyboard.println(); + + // Simple debounce + delay(300); + } +} + diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index e5d5b8c5ae..222e6b5dc7 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -138,4 +138,5 @@ THE SOFTWARE. #else #include "ImprovedKeylayouts.h" #include "ImprovedKeyboard.h" +#include "NKROKeyboard.h" #endif diff --git a/plugins/KeyboardioHID/src/NKROKeyboard.cpp b/plugins/KeyboardioHID/src/NKROKeyboard.cpp new file mode 100644 index 0000000000..96befe6a55 --- /dev/null +++ b/plugins/KeyboardioHID/src/NKROKeyboard.cpp @@ -0,0 +1,283 @@ +/* +Copyright (c) 2015 NicoHood +See the readme for credit to other people. + +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 "NKROKeyboard.h" + +#if defined(_USING_HID) + +//================================================================================ +//================================================================================ +// NKROKeyboard + +static const u8 _hidReportDescriptor[] PROGMEM = { + // NKRO Keyboard + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 47 */ + 0x09, 0x06, /* USAGE (Keyboard) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + 0x85, HID_REPORTID_NKRO_KEYBOARD, /* REPORT_ID */ + 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ + + /* Keyboard Modifiers (shift, alt, ...) */ + 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) */ + +#if defined(HID_KEYBOARD_LEDS_ENABLED) +//TODO remove reserved bytes to add 3 more custom data bits for advanced users? + /* 5 LEDs for num lock etc */ + 0x05, 0x08, /* USAGE_PAGE (LEDs) */ + 0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */ + 0x29, 0x05, /* USAGE_MAXIMUM (Kana) */ + 0x95, 0x05, /* REPORT_COUNT (5) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */ + /* Reserved 3 bits */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x03, /* REPORT_SIZE (3) */ + 0x91, 0x03, /* OUTPUT (Cnst,Var,Abs) */ +#endif + + /* 104 Keys as bitmap */ + 0x05, 0x07, /* Usage Page (Key Codes) */ + 0x19, 0x00, /* Usage Minimum (0) */ + 0x29, NKRO_KEY_COUNT - 1, /* Usage Maximum (103) */ + 0x15, 0x00, /* Logical Minimum (0) */ + 0x25, 0x01, /* Logical Maximum (1) */ + 0x75, 0x01, /* Report Size (1) */ + 0x95, NKRO_KEY_COUNT, /* Report Count (104) */ + 0x81, 0x02, /* Input (Data, Variable, Absolute) */ + + /* 1 Custom Keyboard key */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x26, 0xE7, 0x00, /* LOGICAL_MAXIMUM (231) */ + /*0x05, 0x07, USAGE_PAGE (Keyboard) */ + 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ + 0x29, 0xE7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ + 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ + + /* End */ + 0xC0 /* End Collection */ +}; + +NKROKeyboard_::NKROKeyboard_(void) : +HIDDevice((uint8_t*)_hidReportDescriptor, sizeof(_hidReportDescriptor), HID_REPORTID_NKRO_KEYBOARD) +#if defined(HID_KEYBOARD_LEDS_ENABLED) +,leds(0) +#endif +{ + // HID Descriptor is appended via the inherited HIDDevice class +} + +void NKROKeyboard_::begin(void) +{ + releaseAll(); +} + +void NKROKeyboard_::end(void) +{ + releaseAll(); +} + +void NKROKeyboard_::sendReport(HID_NKROKeyboardReport_Data_t* keys) +{ + // Call the inherited function. + // This wrapper still saves us some bytes +#if defined(USE_BOOT_KEYBOARD_PROTOCOL) + if(getProtocol() != 1){ + SendRawReport(keys, sizeof(HID_NKROKeyboardReport_Data_t)); + } + else +#endif + SendReport(keys, sizeof(HID_NKROKeyboardReport_Data_t)); +} + +#if defined(HID_KEYBOARD_LEDS_ENABLED) +void NKROKeyboard_::setReportData(const void* data, int len){ + // Save led state + if(len == 1) + leds = *(uint8_t*)data; +} + +uint8_t Keyboard_::getLeds(void){ + return leds; +} +#endif + +// 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 NKROKeyboard_::press(uint8_t k) +{ + // it's a non-printing key (not a modifier) + if (k >= 136) + k = k - 136; + + // it's a modifier key + else if (k >= 128) + k = k - 128; + + // it's a printing key + else { + k = pgm_read_byte(_asciimap + k); + if (!k) + return 0; + + // it's a capital letter or other character reached with shift + if (k & SHIFT) { + // the left shift modifier + _keyReport.modifiers |= 0x02; + k = k ^ SHIFT; + } + } + + addKeycodeToReport(k); + 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 NKROKeyboard_::release(uint8_t k) +{ + // it's a non-printing key (not a modifier) + if (k >= 136) + k = k - 136; + + // it's a modifier key + else if (k >= 128) + k = k - 128; + + // it's a printing key + else { + k = pgm_read_byte(_asciimap + k); + if (!k) + return 0; + + // it's a capital letter or other character reached with shift + if (k & SHIFT) { + // the left shift modifier + _keyReport.modifiers &= ~(0x02); + k = k ^ SHIFT; + } + } + + removeKeycodeFromReport(k); + sendReport(&_keyReport); + + return 1; +} + +void NKROKeyboard_::releaseAll(void) +{ + // release all keys + memset(&_keyReport, 0x00, sizeof(_keyReport)); + sendReport(&_keyReport); +} + +size_t NKROKeyboard_::write(uint8_t c) +{ + uint8_t p = press(c); // Keydown + release(c); // Keyup + return p; // just return the result of press() since release() almost always returns 1 +} + + +// pressKeycode() 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 releaseKeycode(), releaseAll(), or otherwise clear the report and resend. +size_t NKROKeyboard_::pressKeycode(uint8_t k) +{ + if (!addKeycodeToReport(k)) { + return 0; + } + sendReport(&_keyReport); +} + +size_t NKROKeyboard_::addKeycodeToReport(uint8_t k) +{ + // keymap key + if (k < NKRO_KEY_COUNT) + _keyReport.keys[k / 8] |= 1 << (k % 8); + + // it's a modifier key + else if ((k >= HID_KEYBOARD_LEFT_CONTROL) && (k <= HID_KEYBOARD_RIGHT_GUI)) + _keyReport.modifiers |= (0x01 << (k - HID_KEYBOARD_LEFT_CONTROL)); + + // custom key + else + _keyReport.key = k; + + return 1; +} + + +// releaseKeycode() 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. +// When send is set to FALSE (= 0) no sendReport() is executed. This comes in +// handy when combining key releases (e.g. SHIFT+A). +size_t NKROKeyboard_::releaseKeycode(uint8_t k) +{ + if (!removeKeycodeFromReport(k)) { + return 0; + } + sendReport(&_keyReport); +} + +size_t NKROKeyboard_::removeKeycodeFromReport(uint8_t k) +{ + // keymap key + if (k < NKRO_KEY_COUNT) + _keyReport.keys[k / 8] &= ~(1 << (k % 8)); + + // it's a modifier key + else if ((k >= HID_KEYBOARD_LEFT_CONTROL) && (k <= HID_KEYBOARD_RIGHT_GUI)) + _keyReport.modifiers &= ~(0x01 << (k - HID_KEYBOARD_LEFT_CONTROL)); + + // custom key + else + _keyReport.key = 0x00; + + return 1; +} + + +size_t NKROKeyboard_::writeKeycode(uint8_t c) +{ + uint8_t p = pressKeycode(c); // Keydown + releaseKeycode(c); // Keyup + return (p); // just return the result of pressKeycode() since release() almost always returns 1 +} + +NKROKeyboard_ NKROKeyboard; + +#endif diff --git a/plugins/KeyboardioHID/src/NKROKeyboard.h b/plugins/KeyboardioHID/src/NKROKeyboard.h new file mode 100644 index 0000000000..ee133b46d7 --- /dev/null +++ b/plugins/KeyboardioHID/src/NKROKeyboard.h @@ -0,0 +1,83 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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. +*/ + +#pragma once + +#include "HID.h" + +#if !defined(_USING_HID) + +#warning "Using legacy HID core (non pluggable)" + +#else + +#include "HID-Project.h" +#include "ImprovedKeylayouts.h" + +// Max value for USB EP_SIZE 16 +// +1 reportID, +1 modifier, +1 custom key +#define NKRO_KEY_COUNT (8*13) + +typedef union{ + // modifier + keymap + 1 custom key + uint8_t whole8[]; + uint16_t whole16[]; + uint32_t whole32[]; + struct{ + uint8_t modifiers; + uint8_t keys[NKRO_KEY_COUNT / 8]; + uint8_t key; + }; +} HID_NKROKeyboardReport_Data_t; + +class NKROKeyboard_ : public Print, private HIDDevice +{ +protected: + HID_NKROKeyboardReport_Data_t _keyReport; + void sendReport(HID_NKROKeyboardReport_Data_t* keys); +#if defined(HID_KEYBOARD_LEDS_ENABLED) + virtual void setReportData(const void* data, int len); + uint8_t leds; +#endif +public: + NKROKeyboard_(void); + void begin(void); + void end(void); + size_t write(uint8_t k); + size_t press(uint8_t k); + size_t release(uint8_t k); + void releaseAll(void); + + size_t writeKeycode(uint8_t k); + size_t pressKeycode(uint8_t k); + size_t releaseKeycode(uint8_t k); + size_t addKeycodeToReport(uint8_t k); + size_t removeKeycodeFromReport(uint8_t k); + +#if defined(HID_KEYBOARD_LEDS_ENABLED) + uint8_t getLeds(void); +#endif +}; +extern NKROKeyboard_ NKROKeyboard; + +#endif From 8beecc4ed7e6f1124296c67ffd72bf754caa1d8c Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 19 Sep 2015 18:10:39 +0200 Subject: [PATCH 236/602] Added TeensyKeyboard example --- .../TeensyKeyboard/TeensyKeyboard.ino | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 plugins/KeyboardioHID/examples/TeensyKeyboard/TeensyKeyboard.ino diff --git a/plugins/KeyboardioHID/examples/TeensyKeyboard/TeensyKeyboard.ino b/plugins/KeyboardioHID/examples/TeensyKeyboard/TeensyKeyboard.ino new file mode 100644 index 0000000000..0f17282fc5 --- /dev/null +++ b/plugins/KeyboardioHID/examples/TeensyKeyboard/TeensyKeyboard.ino @@ -0,0 +1,52 @@ +/* + Copyright (c) 2014 NicoHood + See the readme for credit to other people. + + Teens Keyboard example + Press a button to write some text to your PC. + + You can change the keyboard layout to a different language. + + See official and HID Project documentation for more infos + https://github.com/NicoHood/HID/wiki/Keyboard-API +*/ + +// Add this before you include the HID-Project. +// This is required because the Teensy uses different KEY definitions. +#define USE_TEENSY_KEYBOARD +#include "HID-Project.h" + +const int pinLed = LED_BUILTIN; +const int pinButton = 2; + +void setup() { + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); + + // Sends a clean report to the host. This is important on any Arduino type. + TeensyKeyboard.begin(); +} + + +void loop() { + if (!digitalRead(pinButton)) { + digitalWrite(pinLed, HIGH); + + // Similar the official library, pretty much self explaining + TeensyKeyboard.println(F("This message was sent with my Arduino.")); + TeensyKeyboard.println(F("Lowercase: abcdefghijklmnopqrstuvwxyz")); + TeensyKeyboard.println(F("Uppercase: ABCDEFGHIJKLMNOPQRSTUVWXYZ")); + + // For a single keypress use press() and release() + TeensyKeyboard.press(KEY_ENTER); + TeensyKeyboard.releaseAll(); + + // Do NOT use write(). See documentation for more help. + //TeensyKeyboard.write(KEY_ENTER); + + // Simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } +} + From c45b7e24bb52c1c17c975645e729832a33001e49 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 19 Sep 2015 18:20:10 +0200 Subject: [PATCH 237/602] Updated keywords.txt --- .../examples/KeyboardLed/KeyboardLed.ino | 2 +- plugins/KeyboardioHID/keywords.txt | 48 ++++++++++++------- 2 files changed, 32 insertions(+), 18 deletions(-) diff --git a/plugins/KeyboardioHID/examples/KeyboardLed/KeyboardLed.ino b/plugins/KeyboardioHID/examples/KeyboardLed/KeyboardLed.ino index 3d7e5844c1..54b90fc114 100644 --- a/plugins/KeyboardioHID/examples/KeyboardLed/KeyboardLed.ino +++ b/plugins/KeyboardioHID/examples/KeyboardLed/KeyboardLed.ino @@ -28,7 +28,7 @@ void setup() { void loop() { // Update Led equal to the caps lock state. // Keep in mind that on a 16u2 and Arduino Micro HIGH and LOW for TX/RX Leds are inverted. - if (Keyboard.getLeds()&LED_CAPS_LOCK) + if (Keyboard.getLeds() & LED_CAPS_LOCK) digitalWrite(pinLed, HIGH); else digitalWrite(pinLed, LOW); diff --git a/plugins/KeyboardioHID/keywords.txt b/plugins/KeyboardioHID/keywords.txt index 34ff98a366..6238ab7a38 100644 --- a/plugins/KeyboardioHID/keywords.txt +++ b/plugins/KeyboardioHID/keywords.txt @@ -10,27 +10,35 @@ # Methods and Functions (KEYWORD2) ####################################### -USBDevice KEYWORD3 -Keyboard KEYWORD3 -Mouse KEYWORD3 -RawHID KEYWORD3 -System KEYWORD3 -Consumer KEYWORD3 -Gamepad KEYWORD3 +begin KEYWORD2 +end KEYWORD2 press KEYWORD2 release KEYWORD2 releaseAll KEYWORD2 -accept KEYWORD2 + click KEYWORD2 move KEYWORD2 moveTo KEYWORD2 isPressed KEYWORD2 + getLeds KEYWORD2 pressKeycode KEYWORD2 releaseKeycode KEYWORD2 writeKeycode KEYWORD2 addKeycodeToReport KEYWORD2 removeKeycodeFromReport KEYWORD2 + +write_unicode KEYWORD2 +set_modifier KEYWORD2 +set_key1 KEYWORD2 +set_key2 KEYWORD2 +set_key3 KEYWORD2 +set_key4 KEYWORD2 +set_key5 KEYWORD2 +set_key6 KEYWORD2 +set_media KEYWORD2 +send_now KEYWORD2 + buttons KEYWORD2 xAxis KEYWORD2 yAxis KEYWORD2 @@ -40,20 +48,26 @@ ryAxis KEYWORD2 rzAxis KEYWORD2 dPad1 KEYWORD2 dPad2 KEYWORD2 -HID_SendReport KEYWORD2 -wakeupHost KEYWORD2 -baud KEYWORD2 -stopbits KEYWORD2 -paritytype KEYWORD2 -numbits KEYWORD2 -dtr KEYWORD2 -rts KEYWORD2 + ####################################### -# Instances (KEYWORD2) +# Instances (KEYWORD1) ####################################### +USBDevice KEYWORD1 +HID KEYWORD1 +Keyboard KEYWORD1 +Mouse KEYWORD1 +RawHID KEYWORD1 +System KEYWORD1 +Consumer KEYWORD1 +Gamepad KEYWORD1 +TeensyKeyboard KEYWORD1 +NKROKeyboard KEYWORD1 +AbsoluteMouse KEYWORD1 + ####################################### # Constants (LITERAL1) ####################################### +#TODO add key definitions like KEY_ENTER From e7e92f09a91cd2c5f26d12c22432b7e4ac01b093 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 19 Sep 2015 18:51:16 +0200 Subject: [PATCH 238/602] fixed some led issues, added leds for teensy seems to still not work for nkro and teensy? --- .../examples/KeyboardLed/KeyboardLed.ino | 14 +++++++++++--- plugins/KeyboardioHID/src/ImprovedKeyboard.cpp | 11 +++++------ plugins/KeyboardioHID/src/NKROKeyboard.cpp | 13 ++++++------- plugins/KeyboardioHID/src/TeensyKeyboard.cpp | 12 ++++++++++++ plugins/KeyboardioHID/src/TeensyKeyboard.h | 16 ++++++++++++++++ 5 files changed, 50 insertions(+), 16 deletions(-) diff --git a/plugins/KeyboardioHID/examples/KeyboardLed/KeyboardLed.ino b/plugins/KeyboardioHID/examples/KeyboardLed/KeyboardLed.ino index 54b90fc114..06b6d4caba 100644 --- a/plugins/KeyboardioHID/examples/KeyboardLed/KeyboardLed.ino +++ b/plugins/KeyboardioHID/examples/KeyboardLed/KeyboardLed.ino @@ -11,6 +11,14 @@ https://github.com/NicoHood/HID/wiki/Keyboard-API */ +// Choose your favourite keyboard +#define USBKEYBOARD Keyboard + +//#define USBKEYBOARD NKROKeyboard + +//#define USBKEYBOARD TeensyKeyboard +//#define USE_TEENSY_KEYBOARD + #include "HID-Project.h" const int pinLed = LED_BUILTIN; @@ -21,21 +29,21 @@ void setup() { pinMode(pinButton, INPUT_PULLUP); // Sends a clean report to the host. This is important on any Arduino type. - Keyboard.begin(); + USBKEYBOARD.begin(); } void loop() { // Update Led equal to the caps lock state. // Keep in mind that on a 16u2 and Arduino Micro HIGH and LOW for TX/RX Leds are inverted. - if (Keyboard.getLeds() & LED_CAPS_LOCK) + if (USBKEYBOARD.getLeds() & LED_CAPS_LOCK) digitalWrite(pinLed, HIGH); else digitalWrite(pinLed, LOW); // Trigger caps lock manually via button if (!digitalRead(pinButton)) { - Keyboard.write(KEY_CAPS_LOCK); + USBKEYBOARD.write(KEY_CAPS_LOCK); // Simple debounce delay(300); diff --git a/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp b/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp index aff0e2160e..f8bf184b08 100644 --- a/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp +++ b/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp @@ -52,18 +52,17 @@ static const u8 _hidReportDescriptor[] PROGMEM = { 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ #if defined(HID_KEYBOARD_LEDS_ENABLED) -//TODO remove reserved bytes to add 3 more custom data bits for advanced users? - /* 5 LEDs for num lock etc */ + /* 5 LEDs for num lock etc, 3 left for advanced, custom usage */ 0x05, 0x08, /* USAGE_PAGE (LEDs) */ 0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */ 0x29, 0x05, /* USAGE_MAXIMUM (Kana) */ - 0x95, 0x05, /* REPORT_COUNT (5) */ + 0x95, 0x08, /* REPORT_COUNT (8) */ 0x75, 0x01, /* REPORT_SIZE (1) */ 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */ /* Reserved 3 bits */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0x75, 0x03, /* REPORT_SIZE (3) */ - 0x91, 0x03, /* OUTPUT (Cnst,Var,Abs) */ + //0x95, 0x01, /* REPORT_COUNT (1) */ + //0x75, 0x03, /* REPORT_SIZE (3) */ + //0x91, 0x03, /* OUTPUT (Cnst,Var,Abs) */ #endif /* 6 Keyboard keys */ diff --git a/plugins/KeyboardioHID/src/NKROKeyboard.cpp b/plugins/KeyboardioHID/src/NKROKeyboard.cpp index 96befe6a55..feecd0650f 100644 --- a/plugins/KeyboardioHID/src/NKROKeyboard.cpp +++ b/plugins/KeyboardioHID/src/NKROKeyboard.cpp @@ -47,18 +47,17 @@ static const u8 _hidReportDescriptor[] PROGMEM = { 0x81, 0x02, /* INPUT (Data,Var,Abs) */ #if defined(HID_KEYBOARD_LEDS_ENABLED) -//TODO remove reserved bytes to add 3 more custom data bits for advanced users? - /* 5 LEDs for num lock etc */ + /* 5 LEDs for num lock etc, 3 left for advanced, custom usage */ 0x05, 0x08, /* USAGE_PAGE (LEDs) */ 0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */ 0x29, 0x05, /* USAGE_MAXIMUM (Kana) */ - 0x95, 0x05, /* REPORT_COUNT (5) */ + 0x95, 0x08, /* REPORT_COUNT (8) */ 0x75, 0x01, /* REPORT_SIZE (1) */ 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */ /* Reserved 3 bits */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0x75, 0x03, /* REPORT_SIZE (3) */ - 0x91, 0x03, /* OUTPUT (Cnst,Var,Abs) */ + //0x95, 0x01, /* REPORT_COUNT (1) */ + //0x75, 0x03, /* REPORT_SIZE (3) */ + //0x91, 0x03, /* OUTPUT (Cnst,Var,Abs) */ #endif /* 104 Keys as bitmap */ @@ -124,7 +123,7 @@ void NKROKeyboard_::setReportData(const void* data, int len){ leds = *(uint8_t*)data; } -uint8_t Keyboard_::getLeds(void){ +uint8_t NKROKeyboard_::getLeds(void){ return leds; } #endif diff --git a/plugins/KeyboardioHID/src/TeensyKeyboard.cpp b/plugins/KeyboardioHID/src/TeensyKeyboard.cpp index 10f36a33e1..fd7ba3af07 100644 --- a/plugins/KeyboardioHID/src/TeensyKeyboard.cpp +++ b/plugins/KeyboardioHID/src/TeensyKeyboard.cpp @@ -29,6 +29,18 @@ HIDDevice((uint8_t*)teensykeyboard_hid_report_desc, sizeof(teensykeyboard_hid_re // HID Descriptor is appended via the inherited HIDDevice class } +#if defined(HID_KEYBOARD_LEDS_ENABLED) +void usb_keyboard_class::setReportData(const void* data, int len){ + // Save led state + if(len == 1) + leds = *(uint8_t*)data; +} + +uint8_t usb_keyboard_class::getLeds(void){ + return leds; +} +#endif + // Step #1, decode UTF8 to Unicode code points // size_t usb_keyboard_class::write(uint8_t c) diff --git a/plugins/KeyboardioHID/src/TeensyKeyboard.h b/plugins/KeyboardioHID/src/TeensyKeyboard.h index 7b1fb2d319..a2996f27ed 100644 --- a/plugins/KeyboardioHID/src/TeensyKeyboard.h +++ b/plugins/KeyboardioHID/src/TeensyKeyboard.h @@ -61,6 +61,7 @@ static const uint8_t PROGMEM teensykeyboard_hid_report_desc[] = { 0x09, 0xB6, // Usage (Scan Previous Track), 0x09, 0xB7, // Usage (Stop), 0x09, 0xB8, // Usage (Eject), +// Note: Teensy ledreport was not modified to 8 bit, nor left out when leds are deactivated 0x81, 0x02, // Input (Data, Variable, Absolute), ;Media keys 0x95, 0x05, // Report Count (5), 0x75, 0x01, // Report Size (1), @@ -82,10 +83,20 @@ static const uint8_t PROGMEM teensykeyboard_hid_report_desc[] = { 0xc0 // End Collection }; +// Keyboard Leds +#define LED_NUM_LOCK 0x01 +#define LED_CAPS_LOCK 0x02 +#define LED_SCROLL_LOCK 0x04 + class usb_keyboard_class : public Print, private HIDDevice { public: usb_keyboard_class(void); + +#if defined(HID_KEYBOARD_LEDS_ENABLED) + uint8_t getLeds(void); +#endif + void begin(void) { } void end(void) { } virtual size_t write(uint8_t); @@ -115,6 +126,11 @@ class usb_keyboard_class : public Print, private HIDDevice uint8_t utf8_state; uint16_t unicode_wchar; uint8_t keyboard_report_data[8]; + +#if defined(HID_KEYBOARD_LEDS_ENABLED) + virtual void setReportData(const void* data, int len); + uint8_t leds; +#endif }; extern usb_keyboard_class TeensyKeyboard; From 75eda85d024f65eda0bb2bd7f692d0f1f78fd909 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 20 Sep 2015 08:50:39 +0200 Subject: [PATCH 239/602] Fixed HID Out report (leds) --- plugins/KeyboardioHID/src/PluggableHID/HID.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/PluggableHID/HID.cpp b/plugins/KeyboardioHID/src/PluggableHID/HID.cpp index 1e6f196f50..b8dc38d4db 100644 --- a/plugins/KeyboardioHID/src/PluggableHID/HID.cpp +++ b/plugins/KeyboardioHID/src/PluggableHID/HID.cpp @@ -158,7 +158,7 @@ bool HID_::HID_Setup(USBSetup& setup, u8 i) if (HID_SET_REPORT == r) { // Get reportID and search for the suited HIDDevice - uint8_t ID = setup.wIndex; + uint8_t ID = setup.wValueL; HIDDevice *current = rootDevice; while(current != NULL) { From 5fe1bde80d5cb61548c56842b538933f194009a1 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 20 Sep 2015 10:55:13 +0200 Subject: [PATCH 240/602] (NKRO) Keyboard improvements --- .../examples/NKROKeyboard/NKROKeyboard.ino | 44 ++++------ plugins/KeyboardioHID/keywords.txt | 2 + .../KeyboardioHID/src/ImprovedKeyboard.cpp | 87 +++++++++++-------- plugins/KeyboardioHID/src/ImprovedKeyboard.h | 3 + plugins/KeyboardioHID/src/NKROKeyboard.cpp | 77 ++++++++++------ plugins/KeyboardioHID/src/NKROKeyboard.h | 3 + 6 files changed, 127 insertions(+), 89 deletions(-) diff --git a/plugins/KeyboardioHID/examples/NKROKeyboard/NKROKeyboard.ino b/plugins/KeyboardioHID/examples/NKROKeyboard/NKROKeyboard.ino index dae938571c..16cca5f2dd 100644 --- a/plugins/KeyboardioHID/examples/NKROKeyboard/NKROKeyboard.ino +++ b/plugins/KeyboardioHID/examples/NKROKeyboard/NKROKeyboard.ino @@ -4,7 +4,7 @@ NKROKeyboard example - Press a button to press a lot of keys at the same time. + Press a button to hold a lot of keys at the same time. NKRO can push 113 keys at the same time, the other Keyboards only 6 keys + 8 modifiers! @@ -26,36 +26,24 @@ void setup() { } void loop() { - // Press a lot of keys at the same time + // Hold a lot of keys at the same time if (!digitalRead(pinButton)) { digitalWrite(pinLed, HIGH); - NKROKeyboard.press('a'); - NKROKeyboard.press('b'); - NKROKeyboard.press('c'); - NKROKeyboard.press('d'); - NKROKeyboard.press('e'); - NKROKeyboard.press('f'); - NKROKeyboard.press('g'); - NKROKeyboard.press('h'); - NKROKeyboard.press('i'); - NKROKeyboard.press('j'); - NKROKeyboard.press('k'); - NKROKeyboard.press('l'); - NKROKeyboard.press('m'); - NKROKeyboard.press('n'); - NKROKeyboard.press('o'); - NKROKeyboard.press('p'); - NKROKeyboard.press('q'); - NKROKeyboard.press('r'); - NKROKeyboard.press('s'); - NKROKeyboard.press('t'); - NKROKeyboard.press('u'); - NKROKeyboard.press('v'); - NKROKeyboard.press('w'); - NKROKeyboard.press('x'); - NKROKeyboard.press('y'); - NKROKeyboard.press('z'); + // Do not press to many at once or some OS will have problems. + // Note that the resulting pressed order might differ, + // because all keys are pressed at the same time. + NKROKeyboard.addKeyToReport('0'); + NKROKeyboard.addKeyToReport('1'); + NKROKeyboard.addKeyToReport('2'); + NKROKeyboard.addKeyToReport('3'); + NKROKeyboard.addKeyToReport('4'); + NKROKeyboard.addKeyToReport('5'); + NKROKeyboard.addKeyToReport('6'); + NKROKeyboard.addKeyToReport('7'); + NKROKeyboard.addKeyToReport('8'); + NKROKeyboard.addKeyToReport('9'); + NKROKeyboard.send_now(); // Release all keys and hit enter NKROKeyboard.releaseAll(); diff --git a/plugins/KeyboardioHID/keywords.txt b/plugins/KeyboardioHID/keywords.txt index 6238ab7a38..41c51121ab 100644 --- a/plugins/KeyboardioHID/keywords.txt +++ b/plugins/KeyboardioHID/keywords.txt @@ -25,7 +25,9 @@ getLeds KEYWORD2 pressKeycode KEYWORD2 releaseKeycode KEYWORD2 writeKeycode KEYWORD2 +addKeyToReport KEYWORD2 addKeycodeToReport KEYWORD2 +removeKeyFromReport KEYWORD2 removeKeycodeFromReport KEYWORD2 write_unicode KEYWORD2 diff --git a/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp b/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp index f8bf184b08..b06ad38469 100644 --- a/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp +++ b/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp @@ -111,6 +111,10 @@ void Keyboard_::sendReport(HID_KeyboardReport_Data_t* keys) SendReport(keys,sizeof(HID_KeyboardReport_Data_t)); } +void Keyboard_::send_now(void){ + sendReport(&_keyReport); +} + #if defined(HID_KEYBOARD_LEDS_ENABLED) void Keyboard_::setReportData(const void* data, int len){ // Save led state @@ -130,43 +134,11 @@ uint8_t Keyboard_::getLeds(void){ // 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 & SHIFT) { // it's a capital letter or other character reached with shift - _keyReport.modifiers |= 0x02; // the left shift modifier - k = k ^ SHIFT; - } - } - - // 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; - } + size_t ret = addKeyToReport(k); + if(ret){ + sendReport(&_keyReport); } - sendReport(&_keyReport); - return 1; + return ret; } // release() takes the specified key out of the persistent key report and @@ -229,6 +201,28 @@ size_t Keyboard_::pressKeycode(uint8_t k) sendReport(&_keyReport); } +size_t Keyboard_::addKeyToReport(uint8_t k) +{ + 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 & SHIFT) { // it's a capital letter or other character reached with shift + _keyReport.modifiers |= 0x02; // the left shift modifier + k = k ^ SHIFT; + } + } + + return addKeycodeToReport(k); +} + size_t Keyboard_::addKeycodeToReport(uint8_t k) { uint8_t index = 0; @@ -283,6 +277,27 @@ size_t Keyboard_::releaseKeycode(uint8_t k) sendReport(&_keyReport); } +size_t Keyboard_::removeKeyFromReport(uint8_t k) +{ + 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 & SHIFT) { // it's a capital letter or other character reached with shift + _keyReport.modifiers &= ~(0x02); // the left shift modifier + k = k ^ SHIFT; + } + } + + return removeKeycodeFromReport(k); +} + size_t Keyboard_::removeKeycodeFromReport(uint8_t k) { uint8_t indexA; diff --git a/plugins/KeyboardioHID/src/ImprovedKeyboard.h b/plugins/KeyboardioHID/src/ImprovedKeyboard.h index c6119e28c6..a8fddc17ba 100644 --- a/plugins/KeyboardioHID/src/ImprovedKeyboard.h +++ b/plugins/KeyboardioHID/src/ImprovedKeyboard.h @@ -68,11 +68,14 @@ class Keyboard_ : public Print, private HIDDevice size_t press(uint8_t k); size_t release(uint8_t k); void releaseAll(void); + void send_now(void); size_t writeKeycode(uint8_t k); size_t pressKeycode(uint8_t k); size_t releaseKeycode(uint8_t k); + size_t addKeyToReport(uint8_t k); size_t addKeycodeToReport(uint8_t k); + size_t removeKeyFromReport(uint8_t k); size_t removeKeycodeFromReport(uint8_t k); #if defined(HID_KEYBOARD_LEDS_ENABLED) diff --git a/plugins/KeyboardioHID/src/NKROKeyboard.cpp b/plugins/KeyboardioHID/src/NKROKeyboard.cpp index feecd0650f..c37f48829f 100644 --- a/plugins/KeyboardioHID/src/NKROKeyboard.cpp +++ b/plugins/KeyboardioHID/src/NKROKeyboard.cpp @@ -116,6 +116,10 @@ void NKROKeyboard_::sendReport(HID_NKROKeyboardReport_Data_t* keys) SendReport(keys, sizeof(HID_NKROKeyboardReport_Data_t)); } +void NKROKeyboard_::send_now(void){ + sendReport(&_keyReport); +} + #if defined(HID_KEYBOARD_LEDS_ENABLED) void NKROKeyboard_::setReportData(const void* data, int len){ // Save led state @@ -134,31 +138,11 @@ uint8_t NKROKeyboard_::getLeds(void){ // call release(), releaseAll(), or otherwise clear the report and resend. size_t NKROKeyboard_::press(uint8_t k) { - // it's a non-printing key (not a modifier) - if (k >= 136) - k = k - 136; - - // it's a modifier key - else if (k >= 128) - k = k - 128; - - // it's a printing key - else { - k = pgm_read_byte(_asciimap + k); - if (!k) - return 0; - - // it's a capital letter or other character reached with shift - if (k & SHIFT) { - // the left shift modifier - _keyReport.modifiers |= 0x02; - k = k ^ SHIFT; - } + size_t ret = addKeyToReport(k); + if(ret){ + sendReport(&_keyReport); } - - addKeycodeToReport(k); - sendReport(&_keyReport); - return 1; + return ret; } // release() takes the specified key out of the persistent key report and @@ -189,7 +173,7 @@ size_t NKROKeyboard_::release(uint8_t k) } removeKeycodeFromReport(k); - sendReport(&_keyReport); + sendReport(&_keyReport); return 1; } @@ -221,6 +205,28 @@ size_t NKROKeyboard_::pressKeycode(uint8_t k) sendReport(&_keyReport); } +size_t NKROKeyboard_::addKeyToReport(uint8_t k) +{ + 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 & SHIFT) { // it's a capital letter or other character reached with shift + _keyReport.modifiers |= 0x02; // the left shift modifier + k = k ^ SHIFT; + } + } + + return addKeycodeToReport(k); +} + size_t NKROKeyboard_::addKeycodeToReport(uint8_t k) { // keymap key @@ -252,6 +258,27 @@ size_t NKROKeyboard_::releaseKeycode(uint8_t k) sendReport(&_keyReport); } +size_t NKROKeyboard_::removeKeyFromReport(uint8_t k) +{ + 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 & SHIFT) { // it's a capital letter or other character reached with shift + _keyReport.modifiers &= ~(0x02); // the left shift modifier + k = k ^ SHIFT; + } + } + + return removeKeycodeFromReport(k); +} + size_t NKROKeyboard_::removeKeycodeFromReport(uint8_t k) { // keymap key diff --git a/plugins/KeyboardioHID/src/NKROKeyboard.h b/plugins/KeyboardioHID/src/NKROKeyboard.h index ee133b46d7..60d62ccaa0 100644 --- a/plugins/KeyboardioHID/src/NKROKeyboard.h +++ b/plugins/KeyboardioHID/src/NKROKeyboard.h @@ -67,11 +67,14 @@ class NKROKeyboard_ : public Print, private HIDDevice size_t press(uint8_t k); size_t release(uint8_t k); void releaseAll(void); + void send_now(void); size_t writeKeycode(uint8_t k); size_t pressKeycode(uint8_t k); size_t releaseKeycode(uint8_t k); + size_t addKeyToReport(uint8_t k); size_t addKeycodeToReport(uint8_t k); + size_t removeKeyFromReport(uint8_t k); size_t removeKeycodeFromReport(uint8_t k); #if defined(HID_KEYBOARD_LEDS_ENABLED) From 78862d07c4151c41c478b6fd6691b345fb1cdea3 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 20 Sep 2015 12:30:43 +0200 Subject: [PATCH 241/602] Changed setReportData length to 1 byte --- plugins/KeyboardioHID/src/ImprovedKeyboard.cpp | 2 +- plugins/KeyboardioHID/src/ImprovedKeyboard.h | 2 +- plugins/KeyboardioHID/src/NKROKeyboard.cpp | 2 +- plugins/KeyboardioHID/src/NKROKeyboard.h | 2 +- plugins/KeyboardioHID/src/PluggableHID/HID.cpp | 2 ++ plugins/KeyboardioHID/src/PluggableHID/HIDDevice.cpp | 2 +- plugins/KeyboardioHID/src/PluggableHID/HIDDevice.h | 2 +- plugins/KeyboardioHID/src/TeensyKeyboard.cpp | 2 +- plugins/KeyboardioHID/src/TeensyKeyboard.h | 2 +- 9 files changed, 10 insertions(+), 8 deletions(-) diff --git a/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp b/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp index b06ad38469..4ddae0cf96 100644 --- a/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp +++ b/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp @@ -116,7 +116,7 @@ void Keyboard_::send_now(void){ } #if defined(HID_KEYBOARD_LEDS_ENABLED) -void Keyboard_::setReportData(const void* data, int len){ +void Keyboard_::setReportData(const void* data, uint8_t len){ // Save led state if(len == 1) leds = *(uint8_t*)data; diff --git a/plugins/KeyboardioHID/src/ImprovedKeyboard.h b/plugins/KeyboardioHID/src/ImprovedKeyboard.h index a8fddc17ba..8b94c341d4 100644 --- a/plugins/KeyboardioHID/src/ImprovedKeyboard.h +++ b/plugins/KeyboardioHID/src/ImprovedKeyboard.h @@ -57,7 +57,7 @@ class Keyboard_ : public Print, private HIDDevice HID_KeyboardReport_Data_t _keyReport; void sendReport(HID_KeyboardReport_Data_t* keys); #if defined(HID_KEYBOARD_LEDS_ENABLED) - virtual void setReportData(const void* data, int len); + virtual void setReportData(const void* data, uint8_t len); uint8_t leds; #endif public: diff --git a/plugins/KeyboardioHID/src/NKROKeyboard.cpp b/plugins/KeyboardioHID/src/NKROKeyboard.cpp index c37f48829f..0f9ae2c306 100644 --- a/plugins/KeyboardioHID/src/NKROKeyboard.cpp +++ b/plugins/KeyboardioHID/src/NKROKeyboard.cpp @@ -121,7 +121,7 @@ void NKROKeyboard_::send_now(void){ } #if defined(HID_KEYBOARD_LEDS_ENABLED) -void NKROKeyboard_::setReportData(const void* data, int len){ +void NKROKeyboard_::setReportData(const void* data, uint8_t len){ // Save led state if(len == 1) leds = *(uint8_t*)data; diff --git a/plugins/KeyboardioHID/src/NKROKeyboard.h b/plugins/KeyboardioHID/src/NKROKeyboard.h index 60d62ccaa0..0efb7ba1ec 100644 --- a/plugins/KeyboardioHID/src/NKROKeyboard.h +++ b/plugins/KeyboardioHID/src/NKROKeyboard.h @@ -56,7 +56,7 @@ class NKROKeyboard_ : public Print, private HIDDevice HID_NKROKeyboardReport_Data_t _keyReport; void sendReport(HID_NKROKeyboardReport_Data_t* keys); #if defined(HID_KEYBOARD_LEDS_ENABLED) - virtual void setReportData(const void* data, int len); + virtual void setReportData(const void* data, uint8_t len); uint8_t leds; #endif public: diff --git a/plugins/KeyboardioHID/src/PluggableHID/HID.cpp b/plugins/KeyboardioHID/src/PluggableHID/HID.cpp index b8dc38d4db..d91ca563d3 100644 --- a/plugins/KeyboardioHID/src/PluggableHID/HID.cpp +++ b/plugins/KeyboardioHID/src/PluggableHID/HID.cpp @@ -160,12 +160,14 @@ bool HID_::HID_Setup(USBSetup& setup, u8 i) // Get reportID and search for the suited HIDDevice uint8_t ID = setup.wValueL; HIDDevice *current = rootDevice; + while(current != NULL) { // Search HIDDevice for report ID if(current->reportID == ID) { // Get the data length information and the corresponding bytes + // Assuming the host will never send more than 255 bytes uint8_t length = setup.wLength; uint8_t data[length]; USB_RecvControl(data, length); diff --git a/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.cpp b/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.cpp index 97b5c83570..f971f6d094 100644 --- a/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.cpp +++ b/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.cpp @@ -20,7 +20,7 @@ void HIDDevice::SendRawReport(const void* data, int len){ HID.SendReport(HID_REPORTID_NONE, data, len); } -void HIDDevice::setReportData(const void* data, int len){ +void HIDDevice::setReportData(const void* data, uint8_t len){ // Discard this information if its not implemented by the HIDDevice } diff --git a/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.h b/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.h index 1ec3495a10..62f78ecdac 100644 --- a/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.h +++ b/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.h @@ -49,7 +49,7 @@ class HIDDevice const uint16_t descriptorLength; const uint8_t reportID; - virtual void setReportData(const void* data, int len); + virtual void setReportData(const void* data, uint8_t len); protected: // Could be used and inherited public for custom, professional usage, like raw Keyboard diff --git a/plugins/KeyboardioHID/src/TeensyKeyboard.cpp b/plugins/KeyboardioHID/src/TeensyKeyboard.cpp index fd7ba3af07..5af384ea60 100644 --- a/plugins/KeyboardioHID/src/TeensyKeyboard.cpp +++ b/plugins/KeyboardioHID/src/TeensyKeyboard.cpp @@ -30,7 +30,7 @@ HIDDevice((uint8_t*)teensykeyboard_hid_report_desc, sizeof(teensykeyboard_hid_re } #if defined(HID_KEYBOARD_LEDS_ENABLED) -void usb_keyboard_class::setReportData(const void* data, int len){ +void usb_keyboard_class::setReportData(const void* data, uint8_t len){ // Save led state if(len == 1) leds = *(uint8_t*)data; diff --git a/plugins/KeyboardioHID/src/TeensyKeyboard.h b/plugins/KeyboardioHID/src/TeensyKeyboard.h index a2996f27ed..3db7299621 100644 --- a/plugins/KeyboardioHID/src/TeensyKeyboard.h +++ b/plugins/KeyboardioHID/src/TeensyKeyboard.h @@ -128,7 +128,7 @@ class usb_keyboard_class : public Print, private HIDDevice uint8_t keyboard_report_data[8]; #if defined(HID_KEYBOARD_LEDS_ENABLED) - virtual void setReportData(const void* data, int len); + virtual void setReportData(const void* data, uint8_t len); uint8_t leds; #endif }; From 74ec92f93b7afc3e4be5532b95cbcaa17ed116e5 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 20 Sep 2015 14:05:08 +0200 Subject: [PATCH 242/602] Send the whole data for an out report RawHID does not add the reportID again, so we need to see the first byte there For the keyboard led you can just ignore this byte --- plugins/KeyboardioHID/src/ImprovedKeyboard.cpp | 4 ++-- plugins/KeyboardioHID/src/ImprovedKeyboard.h | 1 - plugins/KeyboardioHID/src/NKROKeyboard.cpp | 4 ++-- plugins/KeyboardioHID/src/PluggableHID/HID.cpp | 12 +++--------- plugins/KeyboardioHID/src/TeensyKeyboard.cpp | 4 ++-- 5 files changed, 9 insertions(+), 16 deletions(-) diff --git a/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp b/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp index 4ddae0cf96..df912d4a91 100644 --- a/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp +++ b/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp @@ -118,8 +118,8 @@ void Keyboard_::send_now(void){ #if defined(HID_KEYBOARD_LEDS_ENABLED) void Keyboard_::setReportData(const void* data, uint8_t len){ // Save led state - if(len == 1) - leds = *(uint8_t*)data; + if(len == 2) + leds = *(uint8_t*)(data+1); } uint8_t Keyboard_::getLeds(void){ diff --git a/plugins/KeyboardioHID/src/ImprovedKeyboard.h b/plugins/KeyboardioHID/src/ImprovedKeyboard.h index 8b94c341d4..496b9a61e4 100644 --- a/plugins/KeyboardioHID/src/ImprovedKeyboard.h +++ b/plugins/KeyboardioHID/src/ImprovedKeyboard.h @@ -38,7 +38,6 @@ THE SOFTWARE. #include "HID-Project.h" #include "ImprovedKeylayouts.h" -// Low level key report: up to 6 keys and shift, ctrl etc at once typedef union{ // Low level key report: up to 6 keys and shift, ctrl etc at once uint8_t whole8[]; diff --git a/plugins/KeyboardioHID/src/NKROKeyboard.cpp b/plugins/KeyboardioHID/src/NKROKeyboard.cpp index 0f9ae2c306..83a72f7674 100644 --- a/plugins/KeyboardioHID/src/NKROKeyboard.cpp +++ b/plugins/KeyboardioHID/src/NKROKeyboard.cpp @@ -123,8 +123,8 @@ void NKROKeyboard_::send_now(void){ #if defined(HID_KEYBOARD_LEDS_ENABLED) void NKROKeyboard_::setReportData(const void* data, uint8_t len){ // Save led state - if(len == 1) - leds = *(uint8_t*)data; + if(len == 2) + leds = *(uint8_t*)(data+1); } uint8_t NKROKeyboard_::getLeds(void){ diff --git a/plugins/KeyboardioHID/src/PluggableHID/HID.cpp b/plugins/KeyboardioHID/src/PluggableHID/HID.cpp index d91ca563d3..6291416476 100644 --- a/plugins/KeyboardioHID/src/PluggableHID/HID.cpp +++ b/plugins/KeyboardioHID/src/PluggableHID/HID.cpp @@ -171,16 +171,10 @@ bool HID_::HID_Setup(USBSetup& setup, u8 i) uint8_t length = setup.wLength; uint8_t data[length]; USB_RecvControl(data, length); - - // Skip report ID data, if any - if(ID){ - current->setReportData(data+1, length-1); - } - // TODO test this case - else{ - current->setReportData(data, length); - } + // Data may contain the report ID again (Keyboard), maybe not (RawHID) + current->setReportData(data, length); + // Dont search any further break; } diff --git a/plugins/KeyboardioHID/src/TeensyKeyboard.cpp b/plugins/KeyboardioHID/src/TeensyKeyboard.cpp index 5af384ea60..992df329fc 100644 --- a/plugins/KeyboardioHID/src/TeensyKeyboard.cpp +++ b/plugins/KeyboardioHID/src/TeensyKeyboard.cpp @@ -32,8 +32,8 @@ HIDDevice((uint8_t*)teensykeyboard_hid_report_desc, sizeof(teensykeyboard_hid_re #if defined(HID_KEYBOARD_LEDS_ENABLED) void usb_keyboard_class::setReportData(const void* data, uint8_t len){ // Save led state - if(len == 1) - leds = *(uint8_t*)data; + if(len == 2) + leds = *(uint8_t*)(data+1); } uint8_t usb_keyboard_class::getLeds(void){ From d1c0f35cddde7a56350034cb5769023c36590cd4 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Tue, 22 Sep 2015 20:48:35 +0200 Subject: [PATCH 243/602] Made SetReportData more flexible can now take more data and keep the data array if changed to zero. --- plugins/KeyboardioHID/Readme.md | 2 +- .../KeyboardioHID/src/ImprovedKeyboard.cpp | 2 +- plugins/KeyboardioHID/src/ImprovedKeyboard.h | 2 +- plugins/KeyboardioHID/src/NKROKeyboard.cpp | 2 +- plugins/KeyboardioHID/src/NKROKeyboard.h | 2 +- .../KeyboardioHID/src/PluggableHID/HID.cpp | 19 +++++++++++++++---- .../src/PluggableHID/HIDDevice.cpp | 2 +- .../src/PluggableHID/HIDDevice.h | 2 +- plugins/KeyboardioHID/src/TeensyKeyboard.cpp | 2 +- plugins/KeyboardioHID/src/TeensyKeyboard.h | 2 +- 10 files changed, 24 insertions(+), 13 deletions(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 3fcddc20c7..c3c92da3c2 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -37,7 +37,7 @@ Use the [online Wiki](https://github.com/NicoHood/HID/wiki) to get the newest do * Download an offline version in [releases](https://github.com/NicoHood/HID/releases). It's a snapshot of the current stable release but might have missed some updates that the current master branch has included. This also includes an offline version of the wiki. Offline versions will be available after some time when the official release is out. -* Select [branch 'dev'](https://github.com/NicoHood/HID/tree/dev) to test the bleeding edge of this software. It might now work at all or has a lot of debugging stuff in it. +* Select [branch 'dev'](https://github.com/NicoHood/HID/tree/dev) to test the bleeding edge of this software. It might not work at all or has a lot of debugging stuff in it. If the dev version gets near to a new release a note will be placed here, that you can test the new dev beta. Currently there is no beta available. diff --git a/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp b/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp index df912d4a91..ba0f32ba58 100644 --- a/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp +++ b/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp @@ -116,7 +116,7 @@ void Keyboard_::send_now(void){ } #if defined(HID_KEYBOARD_LEDS_ENABLED) -void Keyboard_::setReportData(const void* data, uint8_t len){ +void Keyboard_::setReportData(void* &data, uint16_t len){ // Save led state if(len == 2) leds = *(uint8_t*)(data+1); diff --git a/plugins/KeyboardioHID/src/ImprovedKeyboard.h b/plugins/KeyboardioHID/src/ImprovedKeyboard.h index 496b9a61e4..efa2538d27 100644 --- a/plugins/KeyboardioHID/src/ImprovedKeyboard.h +++ b/plugins/KeyboardioHID/src/ImprovedKeyboard.h @@ -56,7 +56,7 @@ class Keyboard_ : public Print, private HIDDevice HID_KeyboardReport_Data_t _keyReport; void sendReport(HID_KeyboardReport_Data_t* keys); #if defined(HID_KEYBOARD_LEDS_ENABLED) - virtual void setReportData(const void* data, uint8_t len); + virtual void setReportData(void* &data, uint16_t len); uint8_t leds; #endif public: diff --git a/plugins/KeyboardioHID/src/NKROKeyboard.cpp b/plugins/KeyboardioHID/src/NKROKeyboard.cpp index 83a72f7674..8dbd3e01c5 100644 --- a/plugins/KeyboardioHID/src/NKROKeyboard.cpp +++ b/plugins/KeyboardioHID/src/NKROKeyboard.cpp @@ -121,7 +121,7 @@ void NKROKeyboard_::send_now(void){ } #if defined(HID_KEYBOARD_LEDS_ENABLED) -void NKROKeyboard_::setReportData(const void* data, uint8_t len){ +void NKROKeyboard_::setReportData(void* &data, uint16_t len){ // Save led state if(len == 2) leds = *(uint8_t*)(data+1); diff --git a/plugins/KeyboardioHID/src/NKROKeyboard.h b/plugins/KeyboardioHID/src/NKROKeyboard.h index 0efb7ba1ec..c5c960d919 100644 --- a/plugins/KeyboardioHID/src/NKROKeyboard.h +++ b/plugins/KeyboardioHID/src/NKROKeyboard.h @@ -56,7 +56,7 @@ class NKROKeyboard_ : public Print, private HIDDevice HID_NKROKeyboardReport_Data_t _keyReport; void sendReport(HID_NKROKeyboardReport_Data_t* keys); #if defined(HID_KEYBOARD_LEDS_ENABLED) - virtual void setReportData(const void* data, uint8_t len); + virtual void setReportData(void* &data, uint16_t len); uint8_t leds; #endif public: diff --git a/plugins/KeyboardioHID/src/PluggableHID/HID.cpp b/plugins/KeyboardioHID/src/PluggableHID/HID.cpp index 6291416476..97a9292603 100644 --- a/plugins/KeyboardioHID/src/PluggableHID/HID.cpp +++ b/plugins/KeyboardioHID/src/PluggableHID/HID.cpp @@ -169,11 +169,22 @@ bool HID_::HID_Setup(USBSetup& setup, u8 i) // Get the data length information and the corresponding bytes // Assuming the host will never send more than 255 bytes uint8_t length = setup.wLength; - uint8_t data[length]; - USB_RecvControl(data, length); + void* data = malloc(length); + if(data){ + uint8_t recvLength = length; + //TODO loop can be improved maybe? Or does the compiler do this already? + while(recvLength > USB_EP_SIZE){ + USB_RecvControl(data + (length - recvLength), USB_EP_SIZE); + recvLength -= USB_EP_SIZE; + } + USB_RecvControl(data + (length - recvLength), recvLength); - // Data may contain the report ID again (Keyboard), maybe not (RawHID) - current->setReportData(data, length); + // Data may contain the report ID again (Keyboard), maybe not (RawHID) + current->setReportData(data, length); + } + + // Release data if the pointer still exists + free(data); // Dont search any further break; diff --git a/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.cpp b/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.cpp index f971f6d094..926af13896 100644 --- a/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.cpp +++ b/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.cpp @@ -20,7 +20,7 @@ void HIDDevice::SendRawReport(const void* data, int len){ HID.SendReport(HID_REPORTID_NONE, data, len); } -void HIDDevice::setReportData(const void* data, uint8_t len){ +void HIDDevice::setReportData(void* &data, uint16_t len){ // Discard this information if its not implemented by the HIDDevice } diff --git a/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.h b/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.h index 62f78ecdac..3997673d49 100644 --- a/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.h +++ b/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.h @@ -49,7 +49,7 @@ class HIDDevice const uint16_t descriptorLength; const uint8_t reportID; - virtual void setReportData(const void* data, uint8_t len); + virtual void setReportData(void* &data, uint16_t len); protected: // Could be used and inherited public for custom, professional usage, like raw Keyboard diff --git a/plugins/KeyboardioHID/src/TeensyKeyboard.cpp b/plugins/KeyboardioHID/src/TeensyKeyboard.cpp index 992df329fc..05c95521bf 100644 --- a/plugins/KeyboardioHID/src/TeensyKeyboard.cpp +++ b/plugins/KeyboardioHID/src/TeensyKeyboard.cpp @@ -30,7 +30,7 @@ HIDDevice((uint8_t*)teensykeyboard_hid_report_desc, sizeof(teensykeyboard_hid_re } #if defined(HID_KEYBOARD_LEDS_ENABLED) -void usb_keyboard_class::setReportData(const void* data, uint8_t len){ +void usb_keyboard_class::setReportData(void* &data, uint16_t len){ // Save led state if(len == 2) leds = *(uint8_t*)(data+1); diff --git a/plugins/KeyboardioHID/src/TeensyKeyboard.h b/plugins/KeyboardioHID/src/TeensyKeyboard.h index 3db7299621..e71ef2fc7a 100644 --- a/plugins/KeyboardioHID/src/TeensyKeyboard.h +++ b/plugins/KeyboardioHID/src/TeensyKeyboard.h @@ -128,7 +128,7 @@ class usb_keyboard_class : public Print, private HIDDevice uint8_t keyboard_report_data[8]; #if defined(HID_KEYBOARD_LEDS_ENABLED) - virtual void setReportData(const void* data, uint8_t len); + virtual void setReportData(void* &data, uint16_t len); uint8_t leds; #endif }; From 3716fd205019fdebd21c9a9386aa80167589eed3 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Tue, 22 Sep 2015 21:07:04 +0200 Subject: [PATCH 244/602] Fixed report out length --- .../KeyboardioHID/src/PluggableHID/HID.cpp | 36 ++++++++++--------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/plugins/KeyboardioHID/src/PluggableHID/HID.cpp b/plugins/KeyboardioHID/src/PluggableHID/HID.cpp index 97a9292603..c9d38542e3 100644 --- a/plugins/KeyboardioHID/src/PluggableHID/HID.cpp +++ b/plugins/KeyboardioHID/src/PluggableHID/HID.cpp @@ -167,24 +167,28 @@ bool HID_::HID_Setup(USBSetup& setup, u8 i) if(current->reportID == ID) { // Get the data length information and the corresponding bytes - // Assuming the host will never send more than 255 bytes - uint8_t length = setup.wLength; - void* data = malloc(length); - if(data){ - uint8_t recvLength = length; - //TODO loop can be improved maybe? Or does the compiler do this already? - while(recvLength > USB_EP_SIZE){ - USB_RecvControl(data + (length - recvLength), USB_EP_SIZE); - recvLength -= USB_EP_SIZE; + uint16_t length = (setup.wValueH << 8) | setup.wLength; + + // Ensure that there IS some data TODO needed? + if(length) + { + void* data = malloc(length); + if(data){ + uint16_t recvLength = length; + //TODO loop can be improved maybe? Or does the compiler do this already? + while(recvLength > USB_EP_SIZE){ + USB_RecvControl(data + (length - recvLength), USB_EP_SIZE); + recvLength -= USB_EP_SIZE; + } + USB_RecvControl(data + (length - recvLength), recvLength); + + // Data may contain the report ID again (Keyboard), maybe not (RawHID) + current->setReportData(data, length); } - USB_RecvControl(data + (length - recvLength), recvLength); - - // Data may contain the report ID again (Keyboard), maybe not (RawHID) - current->setReportData(data, length); + + // Release data if the pointer still exists + free(data); } - - // Release data if the pointer still exists - free(data); // Dont search any further break; From 86899f7551619d35e26dbceb2d902e7883c679b5 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Tue, 22 Sep 2015 21:25:11 +0200 Subject: [PATCH 245/602] Finally changes SetReportData function to int This was required since available() of stream also uses int and not uint16_t sadly --- plugins/KeyboardioHID/src/ImprovedKeyboard.cpp | 2 +- plugins/KeyboardioHID/src/ImprovedKeyboard.h | 2 +- plugins/KeyboardioHID/src/NKROKeyboard.cpp | 2 +- plugins/KeyboardioHID/src/NKROKeyboard.h | 2 +- plugins/KeyboardioHID/src/PluggableHID/HID.cpp | 8 ++++---- plugins/KeyboardioHID/src/PluggableHID/HIDDevice.cpp | 2 +- plugins/KeyboardioHID/src/PluggableHID/HIDDevice.h | 2 +- plugins/KeyboardioHID/src/TeensyKeyboard.cpp | 2 +- plugins/KeyboardioHID/src/TeensyKeyboard.h | 2 +- 9 files changed, 12 insertions(+), 12 deletions(-) diff --git a/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp b/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp index ba0f32ba58..ca83d3854e 100644 --- a/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp +++ b/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp @@ -116,7 +116,7 @@ void Keyboard_::send_now(void){ } #if defined(HID_KEYBOARD_LEDS_ENABLED) -void Keyboard_::setReportData(void* &data, uint16_t len){ +void Keyboard_::setReportData(void* &data, int len){ // Save led state if(len == 2) leds = *(uint8_t*)(data+1); diff --git a/plugins/KeyboardioHID/src/ImprovedKeyboard.h b/plugins/KeyboardioHID/src/ImprovedKeyboard.h index efa2538d27..08b95c94f3 100644 --- a/plugins/KeyboardioHID/src/ImprovedKeyboard.h +++ b/plugins/KeyboardioHID/src/ImprovedKeyboard.h @@ -56,7 +56,7 @@ class Keyboard_ : public Print, private HIDDevice HID_KeyboardReport_Data_t _keyReport; void sendReport(HID_KeyboardReport_Data_t* keys); #if defined(HID_KEYBOARD_LEDS_ENABLED) - virtual void setReportData(void* &data, uint16_t len); + virtual void setReportData(void* &data, int len); uint8_t leds; #endif public: diff --git a/plugins/KeyboardioHID/src/NKROKeyboard.cpp b/plugins/KeyboardioHID/src/NKROKeyboard.cpp index 8dbd3e01c5..fb2b6a6ee1 100644 --- a/plugins/KeyboardioHID/src/NKROKeyboard.cpp +++ b/plugins/KeyboardioHID/src/NKROKeyboard.cpp @@ -121,7 +121,7 @@ void NKROKeyboard_::send_now(void){ } #if defined(HID_KEYBOARD_LEDS_ENABLED) -void NKROKeyboard_::setReportData(void* &data, uint16_t len){ +void NKROKeyboard_::setReportData(void* &data, int len){ // Save led state if(len == 2) leds = *(uint8_t*)(data+1); diff --git a/plugins/KeyboardioHID/src/NKROKeyboard.h b/plugins/KeyboardioHID/src/NKROKeyboard.h index c5c960d919..a8cee0d91e 100644 --- a/plugins/KeyboardioHID/src/NKROKeyboard.h +++ b/plugins/KeyboardioHID/src/NKROKeyboard.h @@ -56,7 +56,7 @@ class NKROKeyboard_ : public Print, private HIDDevice HID_NKROKeyboardReport_Data_t _keyReport; void sendReport(HID_NKROKeyboardReport_Data_t* keys); #if defined(HID_KEYBOARD_LEDS_ENABLED) - virtual void setReportData(void* &data, uint16_t len); + virtual void setReportData(void* &data, int len); uint8_t leds; #endif public: diff --git a/plugins/KeyboardioHID/src/PluggableHID/HID.cpp b/plugins/KeyboardioHID/src/PluggableHID/HID.cpp index c9d38542e3..99560e02e7 100644 --- a/plugins/KeyboardioHID/src/PluggableHID/HID.cpp +++ b/plugins/KeyboardioHID/src/PluggableHID/HID.cpp @@ -167,14 +167,14 @@ bool HID_::HID_Setup(USBSetup& setup, u8 i) if(current->reportID == ID) { // Get the data length information and the corresponding bytes - uint16_t length = (setup.wValueH << 8) | setup.wLength; + int length = ((setup.wValueH << 8) | setup.wLength); - // Ensure that there IS some data TODO needed? - if(length) + // Ensure that there IS some data + if(length > 0) { void* data = malloc(length); if(data){ - uint16_t recvLength = length; + auto recvLength = length; //TODO loop can be improved maybe? Or does the compiler do this already? while(recvLength > USB_EP_SIZE){ USB_RecvControl(data + (length - recvLength), USB_EP_SIZE); diff --git a/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.cpp b/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.cpp index 926af13896..96f7f566d2 100644 --- a/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.cpp +++ b/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.cpp @@ -20,7 +20,7 @@ void HIDDevice::SendRawReport(const void* data, int len){ HID.SendReport(HID_REPORTID_NONE, data, len); } -void HIDDevice::setReportData(void* &data, uint16_t len){ +void HIDDevice::setReportData(void* &data, int len){ // Discard this information if its not implemented by the HIDDevice } diff --git a/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.h b/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.h index 3997673d49..8ae0d66c67 100644 --- a/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.h +++ b/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.h @@ -49,7 +49,7 @@ class HIDDevice const uint16_t descriptorLength; const uint8_t reportID; - virtual void setReportData(void* &data, uint16_t len); + virtual void setReportData(void* &data, int len); protected: // Could be used and inherited public for custom, professional usage, like raw Keyboard diff --git a/plugins/KeyboardioHID/src/TeensyKeyboard.cpp b/plugins/KeyboardioHID/src/TeensyKeyboard.cpp index 05c95521bf..a2c45f0c6d 100644 --- a/plugins/KeyboardioHID/src/TeensyKeyboard.cpp +++ b/plugins/KeyboardioHID/src/TeensyKeyboard.cpp @@ -30,7 +30,7 @@ HIDDevice((uint8_t*)teensykeyboard_hid_report_desc, sizeof(teensykeyboard_hid_re } #if defined(HID_KEYBOARD_LEDS_ENABLED) -void usb_keyboard_class::setReportData(void* &data, uint16_t len){ +void usb_keyboard_class::setReportData(void* &data, int len){ // Save led state if(len == 2) leds = *(uint8_t*)(data+1); diff --git a/plugins/KeyboardioHID/src/TeensyKeyboard.h b/plugins/KeyboardioHID/src/TeensyKeyboard.h index e71ef2fc7a..1d5a049808 100644 --- a/plugins/KeyboardioHID/src/TeensyKeyboard.h +++ b/plugins/KeyboardioHID/src/TeensyKeyboard.h @@ -128,7 +128,7 @@ class usb_keyboard_class : public Print, private HIDDevice uint8_t keyboard_report_data[8]; #if defined(HID_KEYBOARD_LEDS_ENABLED) - virtual void setReportData(void* &data, uint16_t len); + virtual void setReportData(void* &data, int len); uint8_t leds; #endif }; From 7b794f423e244d4f4f4b33822fc36efb20a48b18 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Tue, 22 Sep 2015 22:07:21 +0200 Subject: [PATCH 246/602] Added SetInterface function This might help use to set a different hid interface later via keyboard/mouse api --- .../KeyboardioHID/src/PluggableHID/HID.cpp | 20 +++++++++++-------- plugins/KeyboardioHID/src/PluggableHID/HID.h | 1 + 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/plugins/KeyboardioHID/src/PluggableHID/HID.cpp b/plugins/KeyboardioHID/src/PluggableHID/HID.cpp index 99560e02e7..e609adda3c 100644 --- a/plugins/KeyboardioHID/src/PluggableHID/HID.cpp +++ b/plugins/KeyboardioHID/src/PluggableHID/HID.cpp @@ -55,21 +55,25 @@ uint8_t HID_::_hid_idle = 1; int HID_::HID_GetInterface(u8* interfaceNum) { interfaceNum[0] += 1; // uses 1 - _hidInterface = - { + _hidInterface.hid = #if defined(USE_BOOT_KEYBOARD_PROTOCOL) - D_INTERFACE(HID_INTERFACE,1,3,1,1), + D_INTERFACE(HID_INTERFACE,1,3,1,1); #elif defined(USE_BOOT_MOUSE_PROTOCOL) - D_INTERFACE(HID_INTERFACE,1,3,1,2), + D_INTERFACE(HID_INTERFACE,1,3,1,2); #else - D_INTERFACE(HID_INTERFACE,1,3,0,0), + D_INTERFACE(HID_INTERFACE,1,3,0,0); #endif - D_HIDREPORT(sizeof_hidReportDescriptor), - D_ENDPOINT(USB_ENDPOINT_IN (HID_ENDPOINT_INT),USB_ENDPOINT_TYPE_INTERRUPT,USB_EP_SIZE,0x01) - }; + _hidInterface.desc = D_HIDREPORT(sizeof_hidReportDescriptor); + _hidInterface.in = D_ENDPOINT(USB_ENDPOINT_IN (HID_ENDPOINT_INT),USB_ENDPOINT_TYPE_INTERRUPT,USB_EP_SIZE,0x01); return USB_SendControl(0,&_hidInterface,sizeof(_hidInterface)); } +void HID_::SetInterface(InterfaceDescriptor interface) +{ + // Change the HID Interface (required for BOOT protocol) + _hidInterface.hid = interface; +} + int HID_::HID_GetDescriptor(int8_t t) { if (HID_REPORT_DESCRIPTOR_TYPE == t) { diff --git a/plugins/KeyboardioHID/src/PluggableHID/HID.h b/plugins/KeyboardioHID/src/PluggableHID/HID.h index 5562f9e2ac..1bde479a1b 100644 --- a/plugins/KeyboardioHID/src/PluggableHID/HID.h +++ b/plugins/KeyboardioHID/src/PluggableHID/HID.h @@ -78,6 +78,7 @@ class HID_ int begin(void); void SendReport(uint8_t id, const void* data, int len); void AppendDescriptor(HIDDevice* device); + void SetInterface(InterfaceDescriptor interface); // Static functions static int HID_GetInterface(u8* interfaceNum); From 72eb75cf2f88f48b126bdf752ef2ee498d34769a Mon Sep 17 00:00:00 2001 From: NicoHood Date: Tue, 22 Sep 2015 22:08:13 +0200 Subject: [PATCH 247/602] Added RawHID Works under linux with a patched Teensy RawHID testprogram Only works without any other HID device (like keyboard) used together --- .../KeyboardioHID/examples/RawHID/RawHID.ino | 133 ++++++++++++ plugins/KeyboardioHID/src/HID-Project.h | 7 + .../KeyboardioHID/src/PluggableHID/HID.cpp | 11 +- plugins/KeyboardioHID/src/RawHID.cpp | 30 +++ plugins/KeyboardioHID/src/RawHID.h | 204 ++++++++++++++++++ 5 files changed, 375 insertions(+), 10 deletions(-) create mode 100644 plugins/KeyboardioHID/examples/RawHID/RawHID.ino create mode 100644 plugins/KeyboardioHID/src/RawHID.cpp create mode 100644 plugins/KeyboardioHID/src/RawHID.h diff --git a/plugins/KeyboardioHID/examples/RawHID/RawHID.ino b/plugins/KeyboardioHID/examples/RawHID/RawHID.ino new file mode 100644 index 0000000000..ae6c3a7901 --- /dev/null +++ b/plugins/KeyboardioHID/examples/RawHID/RawHID.ino @@ -0,0 +1,133 @@ +/* + Copyright (c) 2014-2015 NicoHood + See the readme for credit to other people. + + Advanced RawHID example + + Shows how to send bytes via RawHID. + Press a button to send some example values. + Keep in mind that you can only send full data packets, + the rest is filled with zero! + + Definitions from HID_Reports.h: + RAWHID_USAGE_PAGE 0xFFC0 // recommended: 0xFF00 to 0xFFFF + RAWHID_USAGE 0x0C00 // recommended: 0x0100 to 0xFFFF + RAWHID_TX_SIZE 15 // 1 byte for report ID + RAWHID_RX_SIZE 15 // 1 byte for report ID + + See HID Project documentation for more information. + https://github.com/NicoHood/HID/wiki/RawHID-API +*/ + +#include "HID-Project.h" + +const int pinLed = LED_BUILTIN; +const int pinButton = 2; + +void setup() { + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); + Serial.begin(0);//TODO + //Keyboard.begin(); + // No begin function needed for RawHID +} + +void loop() { + if (!digitalRead(pinButton)) { + digitalWrite(pinLed, HIGH); + + // Direct without library. Always send RAWHID_RX_SIZE bytes! + uint8_t buff[RAWHID_TX_SIZE] = {0}; + + // With library + memset(&buff, 42, sizeof(buff)); + RawHID.write(buff, sizeof(buff)); + + // Write a single byte, will fill the rest with zeros + RawHID.write(0xCD); + + // Huge buffer with library, will fill the rest with zeros + uint8_t megabuff[100]; + for (int i = 0; i < sizeof(megabuff); i++) + megabuff[i] = i; + RawHID.write(megabuff, sizeof(megabuff)); + + // You can use print too, but better do not use a linefeed. + // A linefeed will send the \r and \n in a separate report. + RawHID.println("Hello World"); + + // Compare print to write: + RawHID.write("Hello World\r\n"); + + // Simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } + + uint8_t len = RawHID.available(); + if (len) { + digitalWrite(pinLed, HIGH); + + // Mirror the incoming data from the host back + uint8_t buff[len + 1]; + buff[0] = len; + for (int i = 1; i < sizeof(buff); i++) { + buff[i] = RawHID.read(); + } + RawHID.write(buff, len); + + // Simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } +} + +/* + Expected output: + + // manual with unintialized buff + recv 15 bytes: + 01 55 C1 FF 01 01 01 00 00 01 00 00 01 00 20 + + // filled buff + recv 15 bytes: + 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A + + // single byte filled with zero + recv 15 bytes: + CD 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + // huge buffer filled with zero at the end + recv 15 bytes: + 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E + + recv 15 bytes: + 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D + + recv 15 bytes: + 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C + + recv 15 bytes: + 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B + + recv 15 bytes: + 3C 3D 3E 3F 00 00 00 00 00 00 00 00 00 00 00 + + // print + recv 15 bytes: + 48 65 6C 6C 6F 20 57 6F 72 6C 64 00 00 00 00 + + //\r + recv 15 bytes: + 0D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + //\n + recv 15 bytes: + 0A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + //write + recv 15 bytes: + 48 65 6C 6C 6F 20 57 6F 72 6C 64 0D 0A 00 00 + +*/ + diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index 222e6b5dc7..86800b2570 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -92,6 +92,12 @@ THE SOFTWARE. #define HID_REPORTID_KEYBOARD 2 #endif +#ifndef HID_REPORTID_RAWHID +// On Windows you might want to use 0 here and no other HID device combined. +// Make sure to also disable the boot protocol for keyboard or mouse. +#define HID_REPORTID_RAWHID 3 +#endif + #ifndef HID_REPORTID_CONSUMERCONTROL #define HID_REPORTID_CONSUMERCONTROL 4 #endif @@ -131,6 +137,7 @@ THE SOFTWARE. #include "Consumer.h" #include "Gamepad.h" #include "System.h" +#include "RawHID.h" // Include Teensy HID afterwards to overwrite key definitions if used #ifdef USE_TEENSY_KEYBOARD diff --git a/plugins/KeyboardioHID/src/PluggableHID/HID.cpp b/plugins/KeyboardioHID/src/PluggableHID/HID.cpp index e609adda3c..ec8dcd2c41 100644 --- a/plugins/KeyboardioHID/src/PluggableHID/HID.cpp +++ b/plugins/KeyboardioHID/src/PluggableHID/HID.cpp @@ -27,16 +27,7 @@ HID_ HID; //================================================================================ //================================================================================ - -// 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 +// HID Interface // Static variables uint8_t HID_::HID_ENDPOINT_INT; diff --git a/plugins/KeyboardioHID/src/RawHID.cpp b/plugins/KeyboardioHID/src/RawHID.cpp new file mode 100644 index 0000000000..3358c2f483 --- /dev/null +++ b/plugins/KeyboardioHID/src/RawHID.cpp @@ -0,0 +1,30 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 "RawHID.h" + +//================================================================================ +// RawHID +//================================================================================ + +RawHID_ RawHID; diff --git a/plugins/KeyboardioHID/src/RawHID.h b/plugins/KeyboardioHID/src/RawHID.h new file mode 100644 index 0000000000..d4b8230f21 --- /dev/null +++ b/plugins/KeyboardioHID/src/RawHID.h @@ -0,0 +1,204 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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. +*/ + +#pragma once + +#include "HID.h" + +#if !defined(_USING_HID) + +#warning "Using legacy HID core (non pluggable)" + +#else + +#include "HID-Project.h" + +//================================================================================ +// RawHID +//================================================================================ + +// RawHID might never work with multireports, because of OS problems +// therefore we have to make it a single report with no idea. No other HID device will be supported then. +#undef RAWHID_USAGE_PAGE +#define RAWHID_USAGE_PAGE 0xFFC0 // recommended: 0xFF00 to 0xFFFF + +#undef RAWHID_USAGE +#define RAWHID_USAGE 0x0C00 // recommended: 0x0100 to 0xFFFF + +// Keep one byte offset for the reportID if used +#if (HID_REPORTID_RAWHID) +#define RAWHID_SIZE (USB_EP_SIZE-1) +#else +#define RAWHID_SIZE (USB_EP_SIZE) +#endif + +#undef RAWHID_TX_SIZE +#define RAWHID_TX_SIZE RAWHID_SIZE + +#undef RAWHID_RX_SIZE +#define RAWHID_RX_SIZE RAWHID_SIZE + +#define LSB(_x) ((_x) & 0xFF) +#define MSB(_x) ((_x) >> 8) + +static const uint8_t _rawhidReportDescriptor[] PROGMEM = { + /* RAW HID */ + 0x06, LSB(RAWHID_USAGE_PAGE), MSB(RAWHID_USAGE_PAGE), /* 30 */ + 0x0A, LSB(RAWHID_USAGE), MSB(RAWHID_USAGE), + + 0xA1, 0x01, /* Collection 0x01 */ +#if (HID_REPORTID_RAWHID) + 0x85, HID_REPORTID_RAWHID, /* REPORT_ID */ +#endif + 0x75, 0x08, /* report size = 8 bits */ + 0x15, 0x00, /* logical minimum = 0 */ + 0x26, 0xFF, 0x00, /* logical maximum = 255 */ + + 0x95, RAWHID_TX_SIZE, /* report count TX */ + 0x09, 0x01, /* usage */ + 0x81, 0x02, /* Input (array) */ + + 0x95, RAWHID_RX_SIZE, /* report count RX */ + 0x09, 0x02, /* usage */ + 0x91, 0x02, /* Output (array) */ + 0xC0 /* end collection */ +}; + +typedef union{ + // a RAWHID_TX_SIZE byte buffer for tx + uint8_t whole8[]; + uint16_t whole16[]; + uint32_t whole32[]; + uint8_t buff[RAWHID_TX_SIZE]; +} HID_RawKeyboardTXReport_Data_t; + +typedef union{ + // a RAWHID_TX_SIZE byte buffer for rx + uint8_t whole8[]; + uint16_t whole16[]; + uint32_t whole32[]; + uint8_t buff[RAWHID_RX_SIZE]; +} HID_RawKeyboardRXReport_Data_t; + +class RawHID_ : public Stream, private HIDDevice +{ +public: + RawHID_(void) : + HIDDevice((uint8_t*)_rawhidReportDescriptor, sizeof(_rawhidReportDescriptor), HID_REPORTID_RAWHID), + dataLength(0) + { + // HID Descriptor is appended via the inherited HIDDevice class + } + + void begin(void){ + // empty + } + + void end(void){ + // empty + } + + virtual int available(void){ + return dataLength; + } + + virtual int read(){ + if(dataLength){ + // Get next data byte + uint8_t data = *(dataTail - dataLength); + dataLength--; + + // Release buffer if its read fully + if(!dataLength){ + free(dataHead); + } + + return data; + } + return -1; + } + + virtual int peek(){ + if(dataLength){ + return *(dataTail - dataLength); + } + return -1; + } + + virtual void flush(void){ + // Delete all incoming bytes + if(dataLength){ + free(dataHead); + dataLength = 0; + } + } + + using Print::write; + virtual size_t write(uint8_t b){ + write(&b, 1); + } + + virtual size_t write(const uint8_t *buffer, size_t size){ + // TODO this only sends the report ID in the first packat + // TODO this will split the data into USB_EP_SIZE packets + SendReport(buffer, size); + return size; + + size_t bytesleft = size; + // First work through the buffer thats already there + while (bytesleft >= RAWHID_TX_SIZE){ + SendReport(&buffer[size - bytesleft], RAWHID_TX_SIZE); + bytesleft -= RAWHID_TX_SIZE; + } + + // Write down the leftover bytes and fill with zeros + if (bytesleft){ + SendReport(&buffer[size - bytesleft], bytesleft); + } + + return size; + } + +private: + virtual void setReportData(void* &data, int len){ + // Only overwrite the buffer if its empty. + // This avoids corrupted data while reading. + if(!dataLength){ + // Save new data + dataLength = len; + dataHead = (uint8_t*) data; + dataTail = (uint8_t*)(data + len); + + // Clear the passed in pointer to not free the data + data = NULL; + } + } + + // Buffer pointers to hold the received data + int dataLength; + uint8_t* dataHead; + uint8_t* dataTail; +}; +extern RawHID_ RawHID; + +#endif From 670bf8bb7cf2fc07921f951db9b05b8990a61234 Mon Sep 17 00:00:00 2001 From: Nico Date: Thu, 24 Sep 2015 10:47:59 +0200 Subject: [PATCH 248/602] Add Arduino 1.6.6 DotALinkage support No special PR build is required now :) --- plugins/KeyboardioHID/library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/library.properties b/plugins/KeyboardioHID/library.properties index e75184e261..d984e65717 100644 --- a/plugins/KeyboardioHID/library.properties +++ b/plugins/KeyboardioHID/library.properties @@ -7,4 +7,4 @@ paragraph=Includes Consumer, System and Gamepad. Also compatible with Arduino Un category=Device Control url=https://github.com/NicoHood/HID architectures=* -alinkage=true +dot_a_linkage=true From 4934e65070fedb8449f558402cd30ee344eee404 Mon Sep 17 00:00:00 2001 From: Nico Date: Thu, 24 Sep 2015 11:40:24 +0200 Subject: [PATCH 249/602] Remove duplicate RAW_KEYBOARD definition warnings --- .../KeyboardioHID/src/ImprovedKeylayouts.h | 54 +++++++++---------- 1 file changed, 24 insertions(+), 30 deletions(-) diff --git a/plugins/KeyboardioHID/src/ImprovedKeylayouts.h b/plugins/KeyboardioHID/src/ImprovedKeylayouts.h index 2ba3d454eb..7b89939c3e 100644 --- a/plugins/KeyboardioHID/src/ImprovedKeylayouts.h +++ b/plugins/KeyboardioHID/src/ImprovedKeylayouts.h @@ -97,35 +97,6 @@ THE SOFTWARE. #define RAW_KEYBOARD_RIGHT_ALT (1 << 6) #define RAW_KEYBOARD_RIGHT_GUI (1 << 7) -#define RAW_KEYBOARD_UP_ARROW 0x52 -#define RAW_KEYBOARD_DOWN_ARROW 0x51 -#define RAW_KEYBOARD_LEFT_ARROW 0x50 -#define RAW_KEYBOARD_RIGHT_ARROW 0x4F -#define RAW_KEYBOARD_SPACEBAR 0x2C -#define RAW_KEYBOARD_BACKSPACE 0x2A -#define RAW_KEYBOARD_TAB 0x2B -#define RAW_KEYBOARD_RETURN 0x28 -#define RAW_KEYBOARD_ESC 0x29 -#define RAW_KEYBOARD_INSERT 0x49 -#define RAW_KEYBOARD_DELETE 0x4C -#define RAW_KEYBOARD_PAGE_UP 0x4B -#define RAW_KEYBOARD_PAGE_DOWN 0x4E -#define RAW_KEYBOARD_HOME 0x4A -#define RAW_KEYBOARD_END 0x4D -#define RAW_KEYBOARD_CAPS_LOCK 0x39 -#define RAW_KEYBOARD_F1 0x3A -#define RAW_KEYBOARD_F2 0x3B -#define RAW_KEYBOARD_F3 0x3C -#define RAW_KEYBOARD_F4 0x3D -#define RAW_KEYBOARD_F5 0x3E -#define RAW_KEYBOARD_F6 0x3F -#define RAW_KEYBOARD_F7 0x40 -#define RAW_KEYBOARD_F8 0x41 -#define RAW_KEYBOARD_F9 0x42 -#define RAW_KEYBOARD_F10 0x43 -#define RAW_KEYBOARD_F11 0x44 -#define RAW_KEYBOARD_F12 0x45 - #define RAW_KEYBOARD_KEY(key) ((key>='a' && key<='z') ? (0x04 + key-'a') :\ (key>='A' && key<='Z') ? (0x04 + key-'A') : (key>='1' && key<='9') ? (0x1E + key-'1') : 0x27) @@ -183,10 +154,33 @@ THE SOFTWARE. #define RAW_KEYBOARD_PERIOD ( 55 ) #define RAW_KEYBOARD_SLASH ( 56 ) +#define RAW_KEYBOARD_CAPS_LOCK 0x39 +#define RAW_KEYBOARD_F1 0x3A +#define RAW_KEYBOARD_F2 0x3B +#define RAW_KEYBOARD_F3 0x3C +#define RAW_KEYBOARD_F4 0x3D +#define RAW_KEYBOARD_F5 0x3E +#define RAW_KEYBOARD_F6 0x3F +#define RAW_KEYBOARD_F7 0x40 +#define RAW_KEYBOARD_F8 0x41 +#define RAW_KEYBOARD_F9 0x42 +#define RAW_KEYBOARD_F10 0x43 +#define RAW_KEYBOARD_F11 0x44 +#define RAW_KEYBOARD_F12 0x45 #define RAW_KEYBOARD_PRINT 0x46 -#define RAW_KEYBOARD_NUM_LOCK 0x53 #define RAW_KEYBOARD_SCROLL_LOCK 0x47 #define RAW_KEYBOARD_PAUSE 0x48 +#define RAW_KEYBOARD_INSERT 0x49 +#define RAW_KEYBOARD_HOME 0x4A +#define RAW_KEYBOARD_PAGE_UP 0x4B +#define RAW_KEYBOARD_DELETE 0x4C +#define RAW_KEYBOARD_END 0x4D +#define RAW_KEYBOARD_PAGE_DOWN 0x4E +#define RAW_KEYBOARD_RIGHT_ARROW 0x4F +#define RAW_KEYBOARD_LEFT_ARROW 0x50 +#define RAW_KEYBOARD_DOWN_ARROW 0x51 +#define RAW_KEYBOARD_UP_ARROW 0x52 +#define RAW_KEYBOARD_NUM_LOCK 0x53 #define RAW_KEYBOARD_MENU 0x65 #define SHIFT 0x80 From 1eeb93a65670ff8b535a5b199518dd60f02aedcc Mon Sep 17 00:00:00 2001 From: Nico Date: Thu, 24 Sep 2015 11:41:32 +0200 Subject: [PATCH 250/602] Remove Makro Warnings --- plugins/KeyboardioHID/src/HID-Tables.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/KeyboardioHID/src/HID-Tables.h b/plugins/KeyboardioHID/src/HID-Tables.h index 066f0fb483..bc56d52843 100644 --- a/plugins/KeyboardioHID/src/HID-Tables.h +++ b/plugins/KeyboardioHID/src/HID-Tables.h @@ -449,9 +449,9 @@ #define HID_CONSUMER_CHANNEL_TOP 0x169 // HID type CL #define HID_CONSUMER_CHANNEL_UNKNOWN 0x16A // HID type CL // Reserved 0x16B-16F -#define HID_CONSUMER_SUB-CHANNEL 0x170 // HID type LC -#define HID_CONSUMER_SUB-CHANNEL_INCREMENT 0x171 // HID type OSC -#define HID_CONSUMER_SUB-CHANNEL_DECREMENT 0x172 // HID type OSC +#define HID_CONSUMER_SUB_CHANNEL 0x170 // HID type LC +#define HID_CONSUMER_SUB_CHANNEL_INCREMENT 0x171 // HID type OSC +#define HID_CONSUMER_SUB_CHANNEL_DECREMENT 0x172 // HID type OSC #define HID_CONSUMER_ALTERNATE_AUDIO_INCREMENT 0x173 // HID type OSC #define HID_CONSUMER_ALTERNATE_AUDIO_DECREMENT 0x174 // HID type OSC // Reserved 0x175-17F From ce8729fee214d62a373fc793858a8b9f75ac5888 Mon Sep 17 00:00:00 2001 From: Nico Date: Thu, 24 Sep 2015 11:45:26 +0200 Subject: [PATCH 251/602] Fix KEY_ENTER compile error --- plugins/KeyboardioHID/src/ImprovedKeylayouts.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/ImprovedKeylayouts.h b/plugins/KeyboardioHID/src/ImprovedKeylayouts.h index 7b89939c3e..ba0ef97098 100644 --- a/plugins/KeyboardioHID/src/ImprovedKeylayouts.h +++ b/plugins/KeyboardioHID/src/ImprovedKeylayouts.h @@ -46,6 +46,7 @@ THE SOFTWARE. #define KEY_BACKSPACE (RAW_KEYBOARD_BACKSPACE + 136) #define KEY_TAB (RAW_KEYBOARD_TAB + 136) #define KEY_RETURN (RAW_KEYBOARD_RETURN + 136) +#define KEY_ENTER KEY_RETURN #define KEY_ESC (RAW_KEYBOARD_ESC + 136) #define KEY_INSERT (RAW_KEYBOARD_INSERT + 136) #define KEY_DELETE (RAW_KEYBOARD_DELETE + 136) @@ -196,7 +197,7 @@ static const uint8_t _asciimap[128] PROGMEM = 0x00, // BEL RAW_KEYBOARD_BACKSPACE, // BS Backspace RAW_KEYBOARD_TAB, // TAB Tab - RAW_KEYBOARD_RETURN, // LF Enter + RAW_KEYBOARD_ENTER, // LF Enter 0x00, // VT 0x00, // FF 0x00, // CR From 2a4e31d5c6245a604d68a9b601b92cdc87dc9448 Mon Sep 17 00:00:00 2001 From: Nico Date: Thu, 24 Sep 2015 11:46:48 +0200 Subject: [PATCH 252/602] Fix compiler warnings and reduce flash --- plugins/KeyboardioHID/src/Consumer.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/KeyboardioHID/src/Consumer.h b/plugins/KeyboardioHID/src/Consumer.h index 80da75d5e3..3a4e963ed9 100644 --- a/plugins/KeyboardioHID/src/Consumer.h +++ b/plugins/KeyboardioHID/src/Consumer.h @@ -122,7 +122,7 @@ class Consumer_ : private HIDDevice { inline void press(uint16_t m) { // search for a free spot - for (int i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { + for (uint8_t i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { if (_report.whole16[i] == 0x00) { _report.whole16[i] = m; break; @@ -133,7 +133,7 @@ class Consumer_ : private HIDDevice { inline void release(uint16_t m) { // search and release the keypress - for (int i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { + for (uint8_t i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { if (_report.whole16[i] == m) { _report.whole16[i] = 0x00; // no break to delete multiple keys From b359d888b46ed92bd1059f9e1c67d71acef7a576 Mon Sep 17 00:00:00 2001 From: Nico Date: Thu, 24 Sep 2015 11:48:48 +0200 Subject: [PATCH 253/602] Fix compiler Warnings in raw HID --- plugins/KeyboardioHID/src/RawHID.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/KeyboardioHID/src/RawHID.h b/plugins/KeyboardioHID/src/RawHID.h index d4b8230f21..104c7ce2ab 100644 --- a/plugins/KeyboardioHID/src/RawHID.h +++ b/plugins/KeyboardioHID/src/RawHID.h @@ -155,7 +155,7 @@ class RawHID_ : public Stream, private HIDDevice using Print::write; virtual size_t write(uint8_t b){ - write(&b, 1); + return write(&b, 1); } virtual size_t write(const uint8_t *buffer, size_t size){ @@ -187,7 +187,7 @@ class RawHID_ : public Stream, private HIDDevice // Save new data dataLength = len; dataHead = (uint8_t*) data; - dataTail = (uint8_t*)(data + len); + dataTail = (uint8_t*)(data) + len; // Clear the passed in pointer to not free the data data = NULL; From ad927668f8512672730e46bbb42e2aa127b2df21 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Mon, 28 Sep 2015 12:48:29 +0200 Subject: [PATCH 254/602] Removed default german keyboard layout --- plugins/KeyboardioHID/examples/RawHID/RawHID.ino | 8 -------- plugins/KeyboardioHID/src/HID-Project.h | 2 +- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/plugins/KeyboardioHID/examples/RawHID/RawHID.ino b/plugins/KeyboardioHID/examples/RawHID/RawHID.ino index ae6c3a7901..a6b83f6ef5 100644 --- a/plugins/KeyboardioHID/examples/RawHID/RawHID.ino +++ b/plugins/KeyboardioHID/examples/RawHID/RawHID.ino @@ -6,14 +6,6 @@ Shows how to send bytes via RawHID. Press a button to send some example values. - Keep in mind that you can only send full data packets, - the rest is filled with zero! - - Definitions from HID_Reports.h: - RAWHID_USAGE_PAGE 0xFFC0 // recommended: 0xFF00 to 0xFFFF - RAWHID_USAGE 0x0C00 // recommended: 0x0100 to 0xFFFF - RAWHID_TX_SIZE 15 // 1 byte for report ID - RAWHID_RX_SIZE 15 // 1 byte for report ID See HID Project documentation for more information. https://github.com/NicoHood/HID/wiki/RawHID-API diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index 86800b2570..58f7b84c8a 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -49,7 +49,7 @@ THE SOFTWARE. //#define LAYOUT_FRENCH //#define LAYOUT_FRENCH_BELGIAN //#define LAYOUT_FRENCH_SWISS -#define LAYOUT_GERMAN +//#define LAYOUT_GERMAN //#define LAYOUT_GERMAN_MAC //#define LAYOUT_GERMAN_SWISS //#define LAYOUT_ICELANDIC From 3c7ee29dd9a3b12d11bad648020067d28afd3b8e Mon Sep 17 00:00:00 2001 From: NicoHood Date: Mon, 28 Sep 2015 14:22:11 +0200 Subject: [PATCH 255/602] Completed asciimap aliases --- .../KeyboardioHID/src/ImprovedKeylayouts.h | 64 +++++++++---------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/plugins/KeyboardioHID/src/ImprovedKeylayouts.h b/plugins/KeyboardioHID/src/ImprovedKeylayouts.h index ba0ef97098..fcb469c794 100644 --- a/plugins/KeyboardioHID/src/ImprovedKeylayouts.h +++ b/plugins/KeyboardioHID/src/ImprovedKeylayouts.h @@ -221,21 +221,21 @@ static const uint8_t _asciimap[128] PROGMEM = 0x00, // US RAW_KEYBOARD_SPACE, // ' ' - 0x1e|SHIFT, // ! - 0x34|SHIFT, // " - 0x20|SHIFT, // # - 0x21|SHIFT, // $ - 0x22|SHIFT, // % - 0x24|SHIFT, // & - 0x34, // ' - 0x26|SHIFT, // ( - 0x27|SHIFT, // ) - 0x25|SHIFT, // * - 0x2e|SHIFT, // + - 0x36, // , + RAW_KEYBOARD_1|SHIFT, // ! + RAW_KEYBOARD_QUOTE|SHIFT, // " + RAW_KEYBOARD_3|SHIFT, // # + RAW_KEYBOARD_4|SHIFT, // $ + RAW_KEYBOARD_5|SHIFT, // % + RAW_KEYBOARD_7|SHIFT, // & + RAW_KEYBOARD_QUOTE, // ' + RAW_KEYBOARD_9|SHIFT, // ( + RAW_KEYBOARD_0|SHIFT, // ) + RAW_KEYBOARD_8|SHIFT, // * + RAW_KEYBOARD_EQUAL|SHIFT, // + + RAW_KEYBOARD_COMMA, // , RAW_KEYBOARD_MINUS, // - - 0x37, // . - 0x38, // / + RAW_KEYBOARD_PERIOD, // . + RAW_KEYBOARD_SLASH, // / RAW_KEYBOARD_0, // 0 RAW_KEYBOARD_1, // 1 RAW_KEYBOARD_2, // 2 @@ -246,13 +246,13 @@ static const uint8_t _asciimap[128] PROGMEM = RAW_KEYBOARD_7, // 7 RAW_KEYBOARD_8, // 8 RAW_KEYBOARD_9, // 9 - 0x33|SHIFT, // : - 0x33, // ; - 0x36|SHIFT, // < - 0x2e, // = - 0x37|SHIFT, // > - 0x38|SHIFT, // ? - 0x1f|SHIFT, // @ + RAW_KEYBOARD_SEMICOLON|SHIFT, // : + RAW_KEYBOARD_SEMICOLON, // ; + RAW_KEYBOARD_COMMA|SHIFT, // < + RAW_KEYBOARD_EQUAL, // = + RAW_KEYBOARD_PERIOD|SHIFT, // > + RAW_KEYBOARD_SLASH|SHIFT, // ? + RAW_KEYBOARD_2|SHIFT, // @ RAW_KEYBOARD_A|SHIFT, // A RAW_KEYBOARD_B|SHIFT, // B RAW_KEYBOARD_C|SHIFT, // C @@ -279,12 +279,12 @@ static const uint8_t _asciimap[128] PROGMEM = RAW_KEYBOARD_X|SHIFT, // X RAW_KEYBOARD_Y|SHIFT, // Y RAW_KEYBOARD_Z|SHIFT, // Z - 0x2f, // [ - 0x31, // bslash - 0x30, // ] - 0x23|SHIFT, // ^ - 0x2d|SHIFT, // _ - 0x35, // ` + RAW_KEYBOARD_LEFT_BRACE, // [ + RAW_KEYBOARD_BACKSLASH, // bslash + RAW_KEYBOARD_RIGHT_BRACE, // ] + RAW_KEYBOARD_6|SHIFT, // ^ + RAW_KEYBOARD_MINUS|SHIFT, // _ + RAW_KEYBOARD_TILDE, // ` RAW_KEYBOARD_A, // a RAW_KEYBOARD_B, // b RAW_KEYBOARD_C, // c @@ -311,9 +311,9 @@ static const uint8_t _asciimap[128] PROGMEM = RAW_KEYBOARD_X, // x RAW_KEYBOARD_Y, // y RAW_KEYBOARD_Z, // z - 0x2f|SHIFT, // - 0x31|SHIFT, // | - 0x30|SHIFT, // } - 0x35|SHIFT, // ~ - 0 // DEL + RAW_KEYBOARD_LEFT_BRACE|SHIFT, // { + RAW_KEYBOARD_BACKSLASH|SHIFT, // | + RAW_KEYBOARD_RIGHT_BRACE|SHIFT, // } + RAW_KEYBOARD_TILDE|SHIFT, // ~ + 0x00 // DEL }; From 4ea24007a2bb415800169a1fcb58e29ef87eca67 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Mon, 28 Sep 2015 14:42:23 +0200 Subject: [PATCH 256/602] Added UK Keyboard layout to improved API --- .../KeyboardioHID/src/ImprovedKeylayouts.h | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/plugins/KeyboardioHID/src/ImprovedKeylayouts.h b/plugins/KeyboardioHID/src/ImprovedKeylayouts.h index fcb469c794..b512e64627 100644 --- a/plugins/KeyboardioHID/src/ImprovedKeylayouts.h +++ b/plugins/KeyboardioHID/src/ImprovedKeylayouts.h @@ -89,6 +89,10 @@ THE SOFTWARE. // LAYOUT_US_ENGLISH //================================================================================ +#if !defined(LAYOUT_US_ENGLISH) && !defined(LAYOUT_UNITED_KINGDOM) +#error This API does not support non english layouts. Please select an US or UK Keyboard. +#endif + #define RAW_KEYBOARD_LEFT_CTRL (1 << 0) #define RAW_KEYBOARD_LEFT_SHIFT (1 << 1) #define RAW_KEYBOARD_LEFT_ALT (1 << 2) @@ -182,6 +186,7 @@ THE SOFTWARE. #define RAW_KEYBOARD_DOWN_ARROW 0x51 #define RAW_KEYBOARD_UP_ARROW 0x52 #define RAW_KEYBOARD_NUM_LOCK 0x53 +#define RAW_KEYBOARD_NON_US 0x64 #define RAW_KEYBOARD_MENU 0x65 #define SHIFT 0x80 @@ -222,8 +227,16 @@ static const uint8_t _asciimap[128] PROGMEM = RAW_KEYBOARD_SPACE, // ' ' RAW_KEYBOARD_1|SHIFT, // ! +#ifdef LAYOUT_UNITED_KINGDOM + RAW_KEYBOARD_2|SHIFT, // " +#else RAW_KEYBOARD_QUOTE|SHIFT, // " +#endif +#ifdef LAYOUT_UNITED_KINGDOM + RAW_KEYBOARD_BACKSLASH +#else RAW_KEYBOARD_3|SHIFT, // # +#endif RAW_KEYBOARD_4|SHIFT, // $ RAW_KEYBOARD_5|SHIFT, // % RAW_KEYBOARD_7|SHIFT, // & @@ -252,7 +265,11 @@ static const uint8_t _asciimap[128] PROGMEM = RAW_KEYBOARD_EQUAL, // = RAW_KEYBOARD_PERIOD|SHIFT, // > RAW_KEYBOARD_SLASH|SHIFT, // ? +#ifdef LAYOUT_UNITED_KINGDOM + RAW_KEYBOARD_QUOTE|SHIFT, // @ +#else RAW_KEYBOARD_2|SHIFT, // @ +#endif RAW_KEYBOARD_A|SHIFT, // A RAW_KEYBOARD_B|SHIFT, // B RAW_KEYBOARD_C|SHIFT, // C @@ -280,7 +297,11 @@ static const uint8_t _asciimap[128] PROGMEM = RAW_KEYBOARD_Y|SHIFT, // Y RAW_KEYBOARD_Z|SHIFT, // Z RAW_KEYBOARD_LEFT_BRACE, // [ +#ifdef LAYOUT_UNITED_KINGDOM + RAW_KEYBOARD_NON_US, // bslash +#else RAW_KEYBOARD_BACKSLASH, // bslash +#endif RAW_KEYBOARD_RIGHT_BRACE, // ] RAW_KEYBOARD_6|SHIFT, // ^ RAW_KEYBOARD_MINUS|SHIFT, // _ @@ -312,8 +333,16 @@ static const uint8_t _asciimap[128] PROGMEM = RAW_KEYBOARD_Y, // y RAW_KEYBOARD_Z, // z RAW_KEYBOARD_LEFT_BRACE|SHIFT, // { +#ifdef LAYOUT_UNITED_KINGDOM + RAW_KEYBOARD_NON_US|SHIFT, // | +#else RAW_KEYBOARD_BACKSLASH|SHIFT, // | +#endif RAW_KEYBOARD_RIGHT_BRACE|SHIFT, // } +#ifdef LAYOUT_UNITED_KINGDOM + RAW_KEYBOARD_BACKSLASH|SHIFT, // ~ +#else RAW_KEYBOARD_TILDE|SHIFT, // ~ +#endif 0x00 // DEL }; From 51adc52e315a83cfc3cf14536d2058c5e3847e46 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Mon, 28 Sep 2015 17:15:45 +0200 Subject: [PATCH 257/602] Added missing HID.begin return --- plugins/KeyboardioHID/src/PluggableHID/HID.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/KeyboardioHID/src/PluggableHID/HID.cpp b/plugins/KeyboardioHID/src/PluggableHID/HID.cpp index ec8dcd2c41..ed4138928f 100644 --- a/plugins/KeyboardioHID/src/PluggableHID/HID.cpp +++ b/plugins/KeyboardioHID/src/PluggableHID/HID.cpp @@ -228,6 +228,7 @@ HID_::operator bool() { int HID_::begin(void) { + return 0; } #endif /* if defined(USBCON) */ From 7a26fbe1347aea762ff0368127a1d933fa199a4f Mon Sep 17 00:00:00 2001 From: NicoHood Date: Fri, 9 Oct 2015 21:44:21 +0200 Subject: [PATCH 258/602] Clean start (once more) This is required after a lot of IDE USB Core changes. To get the code working properly I will add the new updated devices commit per commit. However the diff is not good visible, but that changed since 2.3 anyways so who cares and reads this message. --- plugins/KeyboardioHID/src/AbsoluteMouse.cpp | 34 - plugins/KeyboardioHID/src/AbsoluteMouse.h | 191 - plugins/KeyboardioHID/src/Consumer.cpp | 35 - plugins/KeyboardioHID/src/Consumer.h | 154 - plugins/KeyboardioHID/src/Gamepad.cpp | 35 - plugins/KeyboardioHID/src/Gamepad.h | 195 - plugins/KeyboardioHID/src/HID-Project.h | 123 +- plugins/KeyboardioHID/src/HID-Tables.h | 671 -- plugins/KeyboardioHID/src/HID.h | 2 - .../KeyboardioHID/src/ImprovedKeyboard.cpp | 355 -- plugins/KeyboardioHID/src/ImprovedKeyboard.h | 86 - .../KeyboardioHID/src/ImprovedKeylayouts.h | 348 -- plugins/KeyboardioHID/src/ImprovedMouse.cpp | 134 - plugins/KeyboardioHID/src/ImprovedMouse.h | 79 - plugins/KeyboardioHID/src/NKROKeyboard.cpp | 309 - plugins/KeyboardioHID/src/NKROKeyboard.h | 86 - .../KeyboardioHID/src/PluggableHID/HID.cpp | 235 - plugins/KeyboardioHID/src/PluggableHID/HID.h | 106 - .../src/PluggableHID/HIDDevice.cpp | 31 - .../src/PluggableHID/HIDDevice.h | 63 - plugins/KeyboardioHID/src/RawHID.cpp | 30 - plugins/KeyboardioHID/src/RawHID.h | 204 - plugins/KeyboardioHID/src/System.cpp | 43 - plugins/KeyboardioHID/src/System.h | 103 - plugins/KeyboardioHID/src/TeensyKeyboard.cpp | 467 -- plugins/KeyboardioHID/src/TeensyKeyboard.h | 138 - plugins/KeyboardioHID/src/TeensyKeylayouts.h | 5420 ----------------- 27 files changed, 15 insertions(+), 9662 deletions(-) delete mode 100644 plugins/KeyboardioHID/src/AbsoluteMouse.cpp delete mode 100644 plugins/KeyboardioHID/src/AbsoluteMouse.h delete mode 100644 plugins/KeyboardioHID/src/Consumer.cpp delete mode 100644 plugins/KeyboardioHID/src/Consumer.h delete mode 100644 plugins/KeyboardioHID/src/Gamepad.cpp delete mode 100644 plugins/KeyboardioHID/src/Gamepad.h delete mode 100644 plugins/KeyboardioHID/src/HID-Tables.h delete mode 100644 plugins/KeyboardioHID/src/HID.h delete mode 100644 plugins/KeyboardioHID/src/ImprovedKeyboard.cpp delete mode 100644 plugins/KeyboardioHID/src/ImprovedKeyboard.h delete mode 100644 plugins/KeyboardioHID/src/ImprovedKeylayouts.h delete mode 100644 plugins/KeyboardioHID/src/ImprovedMouse.cpp delete mode 100644 plugins/KeyboardioHID/src/ImprovedMouse.h delete mode 100644 plugins/KeyboardioHID/src/NKROKeyboard.cpp delete mode 100644 plugins/KeyboardioHID/src/NKROKeyboard.h delete mode 100644 plugins/KeyboardioHID/src/PluggableHID/HID.cpp delete mode 100644 plugins/KeyboardioHID/src/PluggableHID/HID.h delete mode 100644 plugins/KeyboardioHID/src/PluggableHID/HIDDevice.cpp delete mode 100644 plugins/KeyboardioHID/src/PluggableHID/HIDDevice.h delete mode 100644 plugins/KeyboardioHID/src/RawHID.cpp delete mode 100644 plugins/KeyboardioHID/src/RawHID.h delete mode 100644 plugins/KeyboardioHID/src/System.cpp delete mode 100644 plugins/KeyboardioHID/src/System.h delete mode 100644 plugins/KeyboardioHID/src/TeensyKeyboard.cpp delete mode 100644 plugins/KeyboardioHID/src/TeensyKeyboard.h delete mode 100644 plugins/KeyboardioHID/src/TeensyKeylayouts.h diff --git a/plugins/KeyboardioHID/src/AbsoluteMouse.cpp b/plugins/KeyboardioHID/src/AbsoluteMouse.cpp deleted file mode 100644 index 9c88adf9b4..0000000000 --- a/plugins/KeyboardioHID/src/AbsoluteMouse.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 "AbsoluteMouse.h" - -//================================================================================ -//================================================================================ -// Mouse - -#if defined(_USING_HID) - -AbsMouse_ AbsoluteMouse; - -#endif diff --git a/plugins/KeyboardioHID/src/AbsoluteMouse.h b/plugins/KeyboardioHID/src/AbsoluteMouse.h deleted file mode 100644 index be646a4d35..0000000000 --- a/plugins/KeyboardioHID/src/AbsoluteMouse.h +++ /dev/null @@ -1,191 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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. -*/ - -#pragma once - -#include "HID.h" - -#if !defined(_USING_HID) - -#error "This is not an USB AVR or you use an old version of the IDE." - -#else - -//================================================================================ -//================================================================================ -// Mouse - -#include "HID-Project.h" - -#define MOUSE_LEFT (1 << 0) -#define MOUSE_RIGHT (1 << 1) -#define MOUSE_MIDDLE (1 << 2) -#define MOUSE_PREV (1 << 3) -#define MOUSE_NEXT (1 << 4) -// actually this mouse report has 8 buttons (for smaller descriptor) -// but the last 3 wont do anything from what I tested -#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE | MOUSE_PREV | MOUSE_NEXT) - -static const uint8_t _absmouseReportDescriptor[] PROGMEM = { - /* Mouse absolute */ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 54 */ - 0x09, 0x02, /* USAGE (Mouse) */ - 0xA1, 0x01, /* COLLECTION (Application) */ - 0x85, HID_REPORTID_MOUSE_ABSOLUTE, /* REPORT_ID */ - - /* 8 Buttons */ - 0x05, 0x09, /* USAGE_PAGE (Button) */ - 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ - 0x29, 0x08, /* USAGE_MAXIMUM (Button 8) */ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ - 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ - 0x95, 0x08, /* REPORT_COUNT (8) */ - 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - - /* X, Y */ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ - 0x09, 0x30, /* USAGE (X) */ - 0x09, 0x31, /* USAGE (Y) */ - 0x16, 0x00, 0x80, /* Logical Minimum (-32768) */ - 0x26, 0xFF, 0x7F, /* Logical Maximum (32767) */ - 0x75, 0x10, /* Report Size (16), */ - 0x95, 0x02, /* Report Count (2), */ - 0x81, 0x02, /* Input (Data, Variable, Absolute) */ - - /* Wheel */ - 0x09, 0x38, /* USAGE (Wheel) */ - 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) */ - - /* End */ - 0xc0 /* END_COLLECTION */ -}; - -typedef union{ - // mouse absolute report: 8 buttons, 2 absolute axis, wheel - uint8_t whole8[]; - uint16_t whole16[]; - uint32_t whole32[]; - struct{ - uint8_t buttons; - int16_t xAxis; - int16_t yAxis; - int8_t wheel; - }; -} HID_MouseAbsoluteReport_Data_t; - -class AbsMouse_ : private HIDDevice -{ -private: - int16_t xAxis = 0; - int16_t yAxis = 0; - uint8_t _buttons = 0; - inline void buttons(uint8_t b){ - if (b != _buttons){ - _buttons = b; - moveTo(xAxis, yAxis, 0); - } - } - - inline int16_t qadd16(int16_t base, int16_t increment) { - // Separate between subtracting and adding - if (increment < 0) { - // Subtracting more would cause an undefined overflow - if ((int16_t)0x8000 - increment > base) - base = 0x8000; - else - base += increment; - } - else { - // Adding more would cause an undefined overflow - if ((int16_t)0x7FFF - increment < base) - base = 0x7FFF; - else - base += increment; - } - return base; - } - -public: - inline AbsMouse_(void): - HIDDevice((uint8_t*)_absmouseReportDescriptor, sizeof(_absmouseReportDescriptor), HID_REPORTID_MOUSE_ABSOLUTE) - { - // HID Descriptor is appended via the inherited HIDDevice class - } - - inline void begin(void){ - // release all buttons - end(); - } - - inline void end(void){ - _buttons = 0; - moveTo(xAxis, yAxis, 0); - } - - inline void click(uint8_t b = MOUSE_LEFT){ - _buttons = b; - moveTo(xAxis, yAxis, 0); - _buttons = 0; - moveTo(xAxis, yAxis, 0); - } - - inline void moveTo(int x, int y, signed char wheel = 0){ - xAxis = x; - yAxis = y; - HID_MouseAbsoluteReport_Data_t report; - report.buttons = _buttons; - report.xAxis = x; - report.yAxis = y; - report.wheel = wheel; - SendReport(&report, sizeof(report)); - } - - inline void move(int x, int y, signed char wheel = 0){ - moveTo(qadd16(xAxis, x), qadd16(yAxis, y), wheel); - } - - inline void press(uint8_t b = MOUSE_LEFT){ - // press LEFT by default - buttons(_buttons | b); - } - - inline void release(uint8_t b = MOUSE_LEFT){ - // release LEFT by default - buttons(_buttons & ~b); - } - - inline bool isPressed(uint8_t b = MOUSE_LEFT){ - // check LEFT by default - if ((b & _buttons) > 0) - return true; - return false; - } -}; -extern AbsMouse_ AbsoluteMouse; - -#endif diff --git a/plugins/KeyboardioHID/src/Consumer.cpp b/plugins/KeyboardioHID/src/Consumer.cpp deleted file mode 100644 index e9311cf68f..0000000000 --- a/plugins/KeyboardioHID/src/Consumer.cpp +++ /dev/null @@ -1,35 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 "Consumer.h" - -//================================================================================ -// Consumer -//================================================================================ - -#if defined(_USING_HID) - -// object instance -Consumer_ Consumer; - -#endif diff --git a/plugins/KeyboardioHID/src/Consumer.h b/plugins/KeyboardioHID/src/Consumer.h deleted file mode 100644 index 3a4e963ed9..0000000000 --- a/plugins/KeyboardioHID/src/Consumer.h +++ /dev/null @@ -1,154 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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. -*/ - -#pragma once - -#include "HID.h" - -#if !defined(_USING_HID) - -#error "This is not an USB AVR or you use an old version of the IDE." - -#else - -//================================================================================ -// Consumer -//================================================================================ - -#include "HID-Project.h" - -// Media key definitions, see official USB docs for more -#define MEDIA_FAST_FORWARD 0xB3 -#define MEDIA_REWIND 0xB4 -#define MEDIA_NEXT 0xB5 -#define MEDIA_PREVIOUS 0xB6 -#define MEDIA_PREV MEDIA_PREVIOUS -#define MEDIA_STOP 0xB7 -#define MEDIA_PLAY_PAUSE 0xCD - -#define MEDIA_VOLUME_MUTE 0xE2 -#define MEDIA_VOLUME_UP 0xE9 -#define MEDIA_VOLUME_DOWN 0xEA -#define MEDIA_VOL_MUTE MEDIA_VOLUME_MUTE -#define MEDIA_VOL_UP MEDIA_VOLUME_UP -#define MEDIA_VOL_DOWN MEDIA_VOLUME_DOWN - -#define CONSUMER_SCREENSAVER 0x19e - -#define CONSUMER_PROGRAMMABLE_BUTTON_CONFIGURATION 0x182 -#define CONSUMER_CONTROL_CONFIGURATION 0x183 -#define CONSUMER_EMAIL_READER 0x18A -#define CONSUMER_CALCULATOR 0x192 -#define CONSUMER_EXPLORER 0x194 - -#define CONSUMER_BROWSER_HOME 0x223 -#define CONSUMER_BROWSER_BACK 0x224 -#define CONSUMER_BROWSER_FORWARD 0x225 -#define CONSUMER_BROWSER_REFRESH 0x227 -#define CONSUMER_BROWSER_BOOKMARKS 0x22A - -static const uint8_t _consumerReportDescriptor[] PROGMEM = { - /* Consumer Control (Sound/Media keys) */ - 0x05, 0x0C, /* usage page (consumer device) */ - 0x09, 0x01, /* usage -- consumer control */ - 0xA1, 0x01, /* collection (application) */ - 0x85, HID_REPORTID_CONSUMERCONTROL, /* report id */ - /* 4 Media Keys */ - 0x15, 0x00, /* logical minimum */ - 0x26, 0xFF, 0x03, /* logical maximum (3ff) */ - 0x19, 0x00, /* usage minimum (0) */ - 0x2A, 0xFF, 0x03, /* usage maximum (3ff) */ - 0x95, 0x04, /* report count (4) */ - 0x75, 0x10, /* report size (16) */ - 0x81, 0x00, /* input */ - 0xC0 /* end collection */ -}; - -typedef union { - // every usable Consumer key possible, up to 4 keys presses possible - uint8_t whole8[]; - uint16_t whole16[]; - uint32_t whole32[]; - struct { - uint16_t key1; - uint16_t key2; - uint16_t key3; - uint16_t key4; - }; -} HID_ConsumerControlReport_Data_t; - -class Consumer_ : private HIDDevice { -public: - inline Consumer_(void) : - HIDDevice((uint8_t*)_consumerReportDescriptor, sizeof(_consumerReportDescriptor), HID_REPORTID_CONSUMERCONTROL) - { - // HID Descriptor is appended via the inherited HIDDevice class - } - - inline void begin(void) { - // release all buttons - end(); - } - - inline void end(void) { - memset(&_report, 0, sizeof(_report)); - SendReport(&_report, sizeof(_report)); - } - - inline void write(uint16_t m) { - press(m); - release(m); - } - - inline void press(uint16_t m) { - // search for a free spot - for (uint8_t i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { - if (_report.whole16[i] == 0x00) { - _report.whole16[i] = m; - break; - } - } - SendReport(&_report, sizeof(_report)); - } - - inline void release(uint16_t m) { - // search and release the keypress - for (uint8_t i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { - if (_report.whole16[i] == m) { - _report.whole16[i] = 0x00; - // no break to delete multiple keys - } - } - SendReport(&_report, sizeof(_report)); - } - - inline void releaseAll(void) { - end(); - } - -private: - HID_ConsumerControlReport_Data_t _report; -}; -extern Consumer_ Consumer; - -#endif diff --git a/plugins/KeyboardioHID/src/Gamepad.cpp b/plugins/KeyboardioHID/src/Gamepad.cpp deleted file mode 100644 index 0d40740e99..0000000000 --- a/plugins/KeyboardioHID/src/Gamepad.cpp +++ /dev/null @@ -1,35 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 "Gamepad.h" - -//================================================================================ -// Gamepad -//================================================================================ - -#if defined(_USING_HID) - -// object instance -Gamepad_ Gamepad; - -#endif diff --git a/plugins/KeyboardioHID/src/Gamepad.h b/plugins/KeyboardioHID/src/Gamepad.h deleted file mode 100644 index d9671be6f4..0000000000 --- a/plugins/KeyboardioHID/src/Gamepad.h +++ /dev/null @@ -1,195 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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. -*/ - -#pragma once - -#include "HID.h" - -#if !defined(_USING_HID) - -#error "This is not an USB AVR or you use an old version of the IDE." - -#else - -//================================================================================ -// Gamepad -//================================================================================ - -#include "HID-Project.h" - -// Dpad directions -#define GAMEPAD_DPAD_CENTERED 0 -#define GAMEPAD_DPAD_UP 1 -#define GAMEPAD_DPAD_UP_RIGHT 2 -#define GAMEPAD_DPAD_RIGHT 3 -#define GAMEPAD_DPAD_DOWN_RIGHT 4 -#define GAMEPAD_DPAD_DOWN 5 -#define GAMEPAD_DPAD_DOWN_LEFT 6 -#define GAMEPAD_DPAD_LEFT 7 -#define GAMEPAD_DPAD_UP_LEFT 8 - -static const uint8_t _gamepadReportDescriptor[] PROGMEM = { - /* Gamepad with 32 buttons and 6 axis*/ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ - 0x09, 0x04, /* USAGE (Joystick) */ - 0xa1, 0x01, /* COLLECTION (Application) */ - 0x85, HID_REPORTID_GAMEPAD, /* REPORT_ID */ - /* 32 Buttons */ - 0x05, 0x09, /* USAGE_PAGE (Button) */ - 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ - 0x29, 0x20, /* USAGE_MAXIMUM (Button 32) */ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ - 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ - 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x95, 0x20, /* REPORT_COUNT (32) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - /* 4 16bit Axis */ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ - 0xa1, 0x00, /* COLLECTION (Physical) */ - 0x09, 0x30, /* USAGE (X) */ - 0x09, 0x31, /* USAGE (Y) */ - 0x09, 0x33, /* USAGE (Rx) */ - 0x09, 0x34, /* USAGE (Ry) */ - 0x16, 0x00, 0x80, /* LOGICAL_MINIMUM (-32768) */ - 0x26, 0xFF, 0x7F, /* LOGICAL_MAXIMUM (32767) */ - 0x75, 0x10, /* REPORT_SIZE (16) */ - 0x95, 0x04, /* REPORT_COUNT (4) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - /* 2 8bit Axis */ - 0x09, 0x32, /* USAGE (Z) */ - 0x09, 0x35, /* USAGE (Rz) */ - 0x15, 0x80, /* LOGICAL_MINIMUM (-128) */ - 0x25, 0x7F, /* LOGICAL_MAXIMUM (127) */ - 0x75, 0x08, /* REPORT_SIZE (8) */ - 0x95, 0x02, /* REPORT_COUNT (2) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - 0xc0, /* END_COLLECTION */ - /* 2 Hat Switches */ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ - 0x09, 0x39, /* USAGE (Hat switch) */ - 0x09, 0x39, /* USAGE (Hat switch) */ - 0x15, 0x01, /* LOGICAL_MINIMUM (1) */ - 0x25, 0x08, /* LOGICAL_MAXIMUM (8) */ - 0x95, 0x02, /* REPORT_COUNT (2) */ - 0x75, 0x04, /* REPORT_SIZE (4) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - 0xc0 /* END_COLLECTION */ -}; - -typedef union { - // 32 Buttons, 6 Axis, 2 D-Pads - uint8_t whole8[]; - uint16_t whole16[]; - uint32_t whole32[]; - uint32_t buttons; - - struct{ - uint8_t button1 : 1; - uint8_t button2 : 1; - uint8_t button3 : 1; - uint8_t button4 : 1; - uint8_t button5 : 1; - uint8_t button6 : 1; - uint8_t button7 : 1; - uint8_t button8 : 1; - - uint8_t button9 : 1; - uint8_t button10 : 1; - uint8_t button11 : 1; - uint8_t button12 : 1; - uint8_t button13 : 1; - uint8_t button14 : 1; - uint8_t button15 : 1; - uint8_t button16 : 1; - - uint8_t button17 : 1; - uint8_t button18 : 1; - uint8_t button19 : 1; - uint8_t button20 : 1; - uint8_t button21 : 1; - uint8_t button22 : 1; - uint8_t button23 : 1; - uint8_t button24 : 1; - - uint8_t button25 : 1; - uint8_t button26 : 1; - uint8_t button27 : 1; - uint8_t button28 : 1; - uint8_t button29 : 1; - uint8_t button30 : 1; - uint8_t button31 : 1; - uint8_t button32 : 1; - - int16_t xAxis; - int16_t yAxis; - - int16_t rxAxis; - int16_t ryAxis; - - int8_t zAxis; - int8_t rzAxis; - - uint8_t dPad1 : 4; - uint8_t dPad2 : 4; - }; -} HID_GamepadReport_Data_t; - -class Gamepad_ : private HIDDevice{ -public: - inline Gamepad_(void) : - HIDDevice((uint8_t*)_gamepadReportDescriptor, sizeof(_gamepadReportDescriptor), HID_REPORTID_GAMEPAD) - { - // HID Descriptor is appended via the inherited HIDDevice class - } - - inline void begin(void){ - // release all buttons - end(); - } - - inline void end(void){ - memset(&_report, 0, sizeof(_report)); - SendReport(&_report, sizeof(_report)); - } - - inline void write(void){ SendReport(&_report, sizeof(_report)); } - inline void press(uint8_t b){ _report.buttons |= (uint32_t)1 << (b - 1); } - inline void release(uint8_t b){ _report.buttons &= ~((uint32_t)1 << (b - 1)); } - inline void releaseAll(void){ memset(&_report, 0x00, sizeof(_report)); } - - inline void buttons(uint32_t b){ _report.buttons = b; } - inline void xAxis(int16_t a){ _report.xAxis = a; } - inline void yAxis(int16_t a){ _report.yAxis = a; } - inline void zAxis(int8_t a){ _report.zAxis = a; } - inline void rxAxis(int16_t a){ _report.rxAxis = a; } - inline void ryAxis(int16_t a){ _report.ryAxis = a; } - inline void rzAxis(int8_t a){ _report.rzAxis = a; } - inline void dPad1(int8_t d){ _report.dPad1 = d; } - inline void dPad2(int8_t d){ _report.dPad2 = d; } - -private: - HID_GamepadReport_Data_t _report; -}; -extern Gamepad_ Gamepad; - -#endif diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index 58f7b84c8a..53c953defe 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -27,123 +27,30 @@ THE SOFTWARE. // Software version #define HID_PROJECT_VERSION 240 -#include +#include //TODO -#if !defined(USBCON) -#error "This is not an USB AVR or you use an old version of the IDE." -#endif - -//================================================================================ -// Settings -//================================================================================ - -#define HID_KEYBOARD_LEDS_ENABLED -#define USE_BOOT_KEYBOARD_PROTOCOL -//#define USE_BOOT_MOUSE_PROTOCOL - -//#define LAYOUT_US_ENGLISH -//#define LAYOUT_CANADIAN_FRENCH -//#define LAYOUT_CANADIAN_MULTILINGUAL -//#define LAYOUT_DANISH -//#define LAYOUT_FINNISH -//#define LAYOUT_FRENCH -//#define LAYOUT_FRENCH_BELGIAN -//#define LAYOUT_FRENCH_SWISS -//#define LAYOUT_GERMAN -//#define LAYOUT_GERMAN_MAC -//#define LAYOUT_GERMAN_SWISS -//#define LAYOUT_ICELANDIC -//#define LAYOUT_IRISH -//#define LAYOUT_ITALIAN -//#define LAYOUT_NORWEGIAN -//#define LAYOUT_PORTUGUESE -//#define LAYOUT_PORTUGUESE_BRAZILIAN -//#define LAYOUT_SPANISH -//#define LAYOUT_SPANISH_LATIN_AMERICA -//#define LAYOUT_SWEDISH -//#define LAYOUT_TURKISH -//#define LAYOUT_UNITED_KINGDOM -//#define LAYOUT_US_INTERNATIONAL - -//================================================================================ -// Definitions and Helpers -//================================================================================ - -// Default US keyboard layout -#if !defined(LAYOUT_CANADIAN_FRENCH) && !defined(LAYOUT_CANADIAN_MULTILINGUAL) \ -&& !defined(LAYOUT_DANISH) && !defined(LAYOUT_FINNISH) && !defined(LAYOUT_FRENCH) \ -&& !defined(LAYOUT_FRENCH_BELGIAN) && !defined(LAYOUT_FRENCH_SWISS) && !defined(LAYOUT_GERMAN) \ -&& !defined(LAYOUT_GERMAN_MAC) && !defined(LAYOUT_GERMAN_SWISS) && !defined(LAYOUT_ICELANDIC) \ -&& !defined(LAYOUT_IRISH) && !defined(LAYOUT_ITALIAN) && !defined(LAYOUT_NORWEGIAN) \ -&& !defined(LAYOUT_PORTUGUESE) && !defined(LAYOUT_PORTUGUESE_BRAZILIAN) \ -&& !defined(LAYOUT_SPANISH) && !defined(LAYOUT_SPANISH_LATIN_AMERICA) \ -&& !defined(LAYOUT_SWEDISH) && !defined(LAYOUT_TURKISH) && !defined(LAYOUT_UNITED_KINGDOM) \ -&& !defined(LAYOUT_US_INTERNATIONAL) && !defined(LAYOUT_US_ENGLISH) -#define LAYOUT_US_ENGLISH -#endif - -#define HID_REPORTID_NONE 0 - -#ifndef HID_REPORTID_MOUSE -#define HID_REPORTID_MOUSE 1 -#endif - -#ifndef HID_REPORTID_KEYBOARD -#define HID_REPORTID_KEYBOARD 2 -#endif - -#ifndef HID_REPORTID_RAWHID -// On Windows you might want to use 0 here and no other HID device combined. -// Make sure to also disable the boot protocol for keyboard or mouse. -#define HID_REPORTID_RAWHID 3 +#if ARDUINO < 10606 +#error HID Project requires Arduino IDE 1.6.6 or greater. Please update your IDE. #endif -#ifndef HID_REPORTID_CONSUMERCONTROL -#define HID_REPORTID_CONSUMERCONTROL 4 -#endif - -#ifndef HID_REPORTID_SYSTEMCONTROL -#define HID_REPORTID_SYSTEMCONTROL 5 -#endif - -#ifndef HID_REPORTID_GAMEPAD -#define HID_REPORTID_GAMEPAD 6 -#endif - -#ifndef HID_REPORTID_MOUSE_ABSOLUTE -#define HID_REPORTID_MOUSE_ABSOLUTE 7 -#endif - -#ifndef HID_REPORTID_NKRO_KEYBOARD -#define HID_REPORTID_NKRO_KEYBOARD 8 -#endif - -#ifndef HID_REPORTID_TEENSY_KEYBOARD -#define HID_REPORTID_TEENSY_KEYBOARD 9 -#endif - -#if defined(USE_BOOT_KEYBOARD_PROTOCOL) && defined(USE_BOOT_MOUSE_PROTOCOL) -// Technically it is possible but not within this (simpler) API. -#error "You cannot use a boot compatible keyboard and mouse at the same time." +#if !defined(USBCON) +#error HID Project can only be used with an USB MCU. #endif -#include "HID.h" - -#include "HID-Tables.h" // Include all HID libraries (.a linkage required to work) properly -#include "AbsoluteMouse.h" -#include "ImprovedMouse.h" -#include "Consumer.h" -#include "Gamepad.h" -#include "System.h" -#include "RawHID.h" +//#include "AbsoluteMouse.h" +//#include "ImprovedMouse.h" +//#include "Consumer.h" +//#include "Gamepad.h" +//#include "System.h" +//#include "RawHID.h" // Include Teensy HID afterwards to overwrite key definitions if used #ifdef USE_TEENSY_KEYBOARD -#include "TeensyKeyboard.h" +//#include "TeensyKeyboard.h" #else -#include "ImprovedKeylayouts.h" -#include "ImprovedKeyboard.h" -#include "NKROKeyboard.h" +#include "SingleReport/BootKeyboard.h" +#include "MultiReport/ImprovedKeyboard.h" +//#include "NKROKeyboard.h" #endif diff --git a/plugins/KeyboardioHID/src/HID-Tables.h b/plugins/KeyboardioHID/src/HID-Tables.h deleted file mode 100644 index bc56d52843..0000000000 --- a/plugins/KeyboardioHID/src/HID-Tables.h +++ /dev/null @@ -1,671 +0,0 @@ -// These mappings were extracted and transcribed from -// http://www.usb.org_SLASH_developers_SLASH_devclass_docs_SLASH_Hut1_12v2.pdf -// -// In most cases, I've preserved the "official" USB Implementers forum -// "Usage Name", though I've standardized some abbreviations and spacing -// that were inconsistent in the original specification. Non alpha-numeric -// characters in symbol names were converted into those characters' names. -// -// To match Arduino code style, all hid usage names are fully upper case. -// -// Not every HID usage listed in this file is currently supported by Arduino -// In particular, any System Control or Consumer Control entry that doesn't -// have a comment indicating that it's "HID type OSC" will require additional -// code in the Arduino core to work. -// -// Non-working usages are listed here in the interest of not having to manually -// convert more usage names each and every time our HID stack gets a little bit -// better. -// -// -// -- Jesse Vincent , January 2014 - -#pragma once - -// System control mappings - -#define HID_SYSTEM_POWER_DOWN 0x81 // HID type OSC -#define HID_SYSTEM_SLEEP 0x82 // HID type OSC -#define HID_SYSTEM_WAKE_UP 0x83 // HID type OSC -#define HID_SYSTEM_CONTEXT_MENU 0x84 // HID type OSC -#define HID_SYSTEM_MAIN_MENU 0x85 // HID type OSC -#define HID_SYSTEM_APP_MENU 0x86 // HID type OSC -#define HID_SYSTEM_MENU_HELP 0x87 // HID type OSC -#define HID_SYSTEM_MENU_EXIT 0x88 // HID type OSC -#define HID_SYSTEM_MENU_SELECT 0x89 // HID type OSC -#define HID_SYSTEM_MENU_RIGHT 0x8A // HID type RTC -#define HID_SYSTEM_MENU_LEFT 0x8B // HID type RTC -#define HID_SYSTEM_MENU_UP 0x8C // HID type RTC -#define HID_SYSTEM_MENU_DOWN 0x8D // HID type RTC -#define HID_SYSTEM_COLD_RESTART 0x8E // HID type OSC -#define HID_SYSTEM_WARM_RESTART 0x8F // HID type OSC -#define HID_D_PAD_UP 0x90 // HID type OOC -#define HID_D_PAD_DOWN 0x91 // HID type OOC -#define HID_D_PAD_RIGHT 0x92 // HID type OOC -#define HID_D_PAD_LEFT 0x93 // HID type OOC -// 0x94-0x9F are reserved -#define HID_SYSTEM_DOCK 0xA0 // HID type OSC -#define HID_SYSTEM_UNDOCK 0xA1 // HID type OSC -#define HID_SYSTEM_SETUP 0xA2 // HID type OSC -#define HID_SYSTEM_BREAK 0xA3 // HID type OSC -#define HID_SYSTEM_DEBUGGER_BREAK 0xA4 // HID type OSC -#define HID_APPLICATION_BREAK 0xA5 // HID type OSC -#define HID_APPLICATION_DEBUGGER_BREAK 0xA6 // HID type OSC -#define HID_SYSTEM_SPEAKER_MUTE 0xA7 // HID type OSC -#define HID_SYSTEM_HIBERNATE 0xA8 // HID type OSC -// 0xA9-0xAF are reserved -#define HID_SYSTEM_DISPLAY_INVERT 0xB0 // HID type OSC -#define HID_SYSTEM_DISPLAY_INTERNAL 0xB1 // HID type OSC -#define HID_SYSTEM_DISPLAY_EXTERNAL 0xB2 // HID type OSC -#define HID_SYSTEM_DISPLAY_BOTH 0xB3 // HID type OSC -#define HID_SYSTEM_DISPLAY_DUAL 0xB4 // HID type OSC -#define HID_SYSTEM_DISPLAY_TOGGLE_INT_SLASH_EXT 0xB5 // HID type OSC -#define HID_SYSTEM_DISPLAY_SWAP_PRIMARY_SLASH_SECONDARY 0xB6 // HID type OSC -#define HID_SYSTEM_DISPLAY_LCD_AUTOSCALE 0xB7 // HID type OSC - -// Keyboard HID mappings - -// Reserved (no_event_indicated) 0x00 -#define HID_KEYBOARD_ERROR_ROLLOVER 0x01 -#define HID_KEYBOARD_POST_FAIL 0x02 -#define HID_KEYBOARD_ERROR_UNDEFINED 0x03 -#define HID_KEYBOARD_A_AND_A 0x04 -#define HID_KEYBOARD_B_AND_B 0x05 -#define HID_KEYBOARD_C_AND_C 0x06 -#define HID_KEYBOARD_D_AND_D 0x07 -#define HID_KEYBOARD_E_AND_E 0x08 -#define HID_KEYBOARD_F_AND_F 0x09 -#define HID_KEYBOARD_G_AND_G 0x0A -#define HID_KEYBOARD_H_AND_H 0x0B -#define HID_KEYBOARD_I_AND_I 0x0C -#define HID_KEYBOARD_J_AND_J 0x0D -#define HID_KEYBOARD_K_AND_K 0x0E -#define HID_KEYBOARD_L_AND_L 0x0F -#define HID_KEYBOARD_M_AND_M 0x10 -#define HID_KEYBOARD_N_AND_N 0x11 -#define HID_KEYBOARD_O_AND_O 0x12 -#define HID_KEYBOARD_P_AND_P 0x13 -#define HID_KEYBOARD_Q_AND_Q 0x14 -#define HID_KEYBOARD_R_AND_R 0x15 -#define HID_KEYBOARD_S_AND_S 0x16 -#define HID_KEYBOARD_T_AND_T 0x17 -#define HID_KEYBOARD_U_AND_U 0x18 -#define HID_KEYBOARD_V_AND_V 0x19 -#define HID_KEYBOARD_W_AND_W 0x1A -#define HID_KEYBOARD_X_AND_X 0x1B -#define HID_KEYBOARD_Y_AND_Y 0x1C -#define HID_KEYBOARD_Z_AND_Z 0x1D -#define HID_KEYBOARD_1_AND_EXCLAMATION_POINT 0x1E -#define HID_KEYBOARD_2_AND_AT 0x1F -#define HID_KEYBOARD_3_AND_POUND 0x20 -#define HID_KEYBOARD_4_AND_DOLLAR 0x21 -#define HID_KEYBOARD_5_AND_PERCENT 0x22 -#define HID_KEYBOARD_6_AND_CARAT 0x23 -#define HID_KEYBOARD_7_AND_AMPERSAND 0x24 -#define HID_KEYBOARD_8_AND_ASTERISK 0x25 -#define HID_KEYBOARD_9_AND_LEFT_PAREN 0x26 -#define HID_KEYBOARD_0_AND_RIGHT_PAREN 0x27 -#define HID_KEYBOARD_ENTER 0x28 // (MARKED AS ENTER_SLASH_RETURN) -#define HID_KEYBOARD_ESCAPE 0x29 -#define HID_KEYBOARD_DELETE 0x2A // (BACKSPACE) -#define HID_KEYBOARD_TAB 0x2B -#define HID_KEYBOARD_SPACEBAR 0x2C -#define HID_KEYBOARD_MINUS_AND_UNDERSCORE 0x2D // (UNDERSCORE) -#define HID_KEYBOARD_EQUALS_AND_PLUS 0x2E -#define HID_KEYBOARD_LEFT_BRACKET_AND_LEFT_CURLY_BRACE 0x2F -#define HID_KEYBOARD_RIGHT_BRACKET_AND_RIGHT_CURLY_BRACE 0x30 -#define HID_KEYBOARD_BACKSLASH_AND_PIPE 0x31 -#define HID_KEYBOARD_NON_US_POUND_AND_TILDE 0x32 -#define HID_KEYBOARD_SEMICOLON_AND_COLON 0x33 -#define HID_KEYBOARD_QUOTE_AND_DOUBLEQUOTE 0x34 -#define HID_KEYBOARD_GRAVE_ACCENT_AND_TILDE 0x35 -#define HID_KEYBOARD_COMMA_AND_LESS_THAN 0x36 -#define HID_KEYBOARD_PERIOD_AND_GREATER_THAN 0x37 -#define HID_KEYBOARD_SLASH_AND_QUESTION_MARK 0x38 -#define HID_KEYBOARD_CAPS_LOCK 0x39 -#define HID_KEYBOARD_F1 0x3A -#define HID_KEYBOARD_F2 0x3B -#define HID_KEYBOARD_F3 0x3C -#define HID_KEYBOARD_F4 0x3D -#define HID_KEYBOARD_F5 0x3E -#define HID_KEYBOARD_F6 0x3F -#define HID_KEYBOARD_F7 0x40 -#define HID_KEYBOARD_F8 0x41 -#define HID_KEYBOARD_F9 0x42 -#define HID_KEYBOARD_F10 0x43 -#define HID_KEYBOARD_F11 0x44 -#define HID_KEYBOARD_F12 0x45 -#define HID_KEYBOARD_PRINTSCREEN 0x46 -#define HID_KEYBOARD_SCROLL_LOCK 0x47 -#define HID_KEYBOARD_PAUSE 0x48 -#define HID_KEYBOARD_INSERT 0x49 -#define HID_KEYBOARD_HOME 0x4A -#define HID_KEYBOARD_PAGE_UP 0x4B -#define HID_KEYBOARD_DELETE_FORWARD 0x4C -#define HID_KEYBOARD_END 0x4D -#define HID_KEYBOARD_PAGE_DOWN 0x4E -#define HID_KEYBOARD_RIGHTARROW 0x4F -#define HID_KEYBOARD_LEFTARROW 0x50 -#define HID_KEYBOARD_DOWNARROW 0x51 -#define HID_KEYBOARD_UPARROW 0x52 -#define HID_KEYPAD_NUM_LOCK_AND_CLEAR 0x53 -#define HID_KEYPAD_DIVIDE 0x54 -#define HID_KEYPAD_MULTIPLY 0x55 -#define HID_KEYPAD_SUBTRACT 0x56 -#define HID_KEYPAD_ADD 0x57 -#define HID_KEYPAD_ENTER 0x58 -#define HID_KEYPAD_1_AND_END 0x59 -#define HID_KEYPAD_2_AND_DOWN_ARROW 0x5A -#define HID_KEYPAD_3_AND_PAGE_DOWN 0x5B -#define HID_KEYPAD_4_AND_LEFT_ARROW 0x5C -#define HID_KEYPAD_5 0x5D -#define HID_KEYPAD_6_AND_RIGHT_ARROW 0x5E -#define HID_KEYPAD_7_AND_HOME 0x5F -#define HID_KEYPAD_8_AND_UP_ARROW 0x60 -#define HID_KEYPAD_9_AND_PAGE_UP 0x61 -#define HID_KEYPAD_0_AND_INSERT 0x62 -#define HID_KEYPAD_PERIOD_AND_DELETE 0x63 -#define HID_KEYBOARD_NON_US_BACKSLASH_AND_PIPE 0x64 -#define HID_KEYBOARD_APPLICATION 0x65 -#define HID_KEYBOARD_POWER 0x66 -#define HID_KEYPAD_EQUALS 0x67 -#define HID_KEYBOARD_F13 0x68 -#define HID_KEYBOARD_F14 0x69 -#define HID_KEYBOARD_F15 0x6A -#define HID_KEYBOARD_F16 0x6B -#define HID_KEYBOARD_F17 0x6C -#define HID_KEYBOARD_F18 0x6D -#define HID_KEYBOARD_F19 0x6E -#define HID_KEYBOARD_F20 0x6F -#define HID_KEYBOARD_F21 0x70 -#define HID_KEYBOARD_F22 0x71 -#define HID_KEYBOARD_F23 0x72 -#define HID_KEYBOARD_F24 0x73 -#define HID_KEYBOARD_EXECUTE 0x74 -#define HID_KEYBOARD_HELP 0x75 -#define HID_KEYBOARD_MENU 0x76 -#define HID_KEYBOARD_SELECT 0x77 -#define HID_KEYBOARD_STOP 0x78 -#define HID_KEYBOARD_AGAIN 0x79 -#define HID_KEYBOARD_UNDO 0x7A -#define HID_KEYBOARD_CUT 0x7B -#define HID_KEYBOARD_COPY 0x7C -#define HID_KEYBOARD_PASTE 0x7D -#define HID_KEYBOARD_FIND 0x7E -#define HID_KEYBOARD_MUTE 0x7F -#define HID_KEYBOARD_VOLUME_UP 0x80 -#define HID_KEYBOARD_VOLUME_DOWN 0x81 -#define HID_KEYBOARD_LOCKING_CAPS_LOCK 0x82 -#define HID_KEYBOARD_LOCKING_NUM_LOCK 0x83 -#define HID_KEYBOARD_LOCKING_SCROLL_LOCK 0x84 -#define HID_KEYPAD_COMMA 0x85 -#define HID_KEYPAD_EQUAL_SIGN 0x86 -#define HID_KEYBOARD_INTERNATIONAL1 0x87 -#define HID_KEYBOARD_INTERNATIONAL2 0x88 -#define HID_KEYBOARD_INTERNATIONAL3 0x89 -#define HID_KEYBOARD_INTERNATIONAL4 0x8A -#define HID_KEYBOARD_INTERNATIONAL5 0x8B -#define HID_KEYBOARD_INTERNATIONAL6 0x8C -#define HID_KEYBOARD_INTERNATIONAL7 0x8D -#define HID_KEYBOARD_INTERNATIONAL8 0x8E -#define HID_KEYBOARD_INTERNATIONAL9 0x8F -#define HID_KEYBOARD_LANG1 0x90 -#define HID_KEYBOARD_LANG2 0x91 -#define HID_KEYBOARD_LANG3 0x92 -#define HID_KEYBOARD_LANG4 0x93 -#define HID_KEYBOARD_LANG5 0x94 -#define HID_KEYBOARD_LANG6 0x95 -#define HID_KEYBOARD_LANG7 0x96 -#define HID_KEYBOARD_LANG8 0x97 -#define HID_KEYBOARD_LANG9 0x98 -#define HID_KEYBOARD_ALTERNATE_ERASE 0x99 -#define HID_KEYBOARD_SYSREQ_SLASH_ATTENTION 0x9A -#define HID_KEYBOARD_CANCEL 0x9B -#define HID_KEYBOARD_CLEAR 0x9C -#define HID_KEYBOARD_PRIOR 0x9D -#define HID_KEYBOARD_RETURN 0x9E -#define HID_KEYBOARD_SEPARATOR 0x9F -#define HID_KEYBOARD_OUT 0xA0 -#define HID_KEYBOARD_OPER 0xA1 -#define HID_KEYBOARD_CLEAR_SLASH_AGAIN 0xA2 -#define HID_KEYBOARD_CRSEL_SLASH_PROPS 0xA3 -#define HID_KEYBOARD_EXSEL 0xA4 -// Reserved 0xA5-AF -#define HID_KEYPAD_00 0xB0 -#define HID_KEYPAD_000 0xB1 -#define HID_THOUSANDS_SEPARATOR 0xB2 -#define HID_DECIMAL_SEPARATOR 0xB3 -#define HID_CURRENCY_UNIT 0xB4 -#define HID_CURRENCY_SUBUNIT 0xB5 -#define HID_KEYPAD_LEFT_PAREN 0xB6 -#define HID_KEYPAD_RIGHT_PAREN 0xB7 -#define HID_KEYPAD_LEFT_CURLY_BRACE 0xB8 -#define HID_KEYPAD_RIGHT_CURLY_BRACE 0xB9 -#define HID_KEYPAD_TAB 0xBA -#define HID_KEYPAD_BACKSPACE 0xBB -#define HID_KEYPAD_A 0xBC -#define HID_KEYPAD_B 0xBD -#define HID_KEYPAD_C 0xBE -#define HID_KEYPAD_D 0xBF -#define HID_KEYPAD_E 0xC0 -#define HID_KEYPAD_F 0xC1 -#define HID_KEYPAD_XOR 0xC2 -#define HID_KEYPAD_CARAT 0xC3 -#define HID_KEYPAD_PERCENT 0xC4 -#define HID_KEYPAD_LESS_THAN 0xC5 -#define HID_KEYPAD_GREATER_THAN 0xC6 -#define HID_KEYPAD_AMPERSAND 0xC7 -#define HID_KEYPAD_DOUBLEAMPERSAND 0xC8 -#define HID_KEYPAD_PIPE 0xC9 -#define HID_KEYPAD_DOUBLEPIPE 0xCA -#define HID_KEYPAD_COLON 0xCB -#define HID_KEYPAD_POUND_SIGN 0xCC -#define HID_KEYPAD_SPACE 0xCD -#define HID_KEYPAD_AT_SIGN 0xCE -#define HID_KEYPAD_EXCLAMATION_POINT 0xCF -#define HID_KEYPAD_MEMORY_STORE 0xD0 -#define HID_KEYPAD_MEMORY_RECALL 0xD1 -#define HID_KEYPAD_MEMORY_CLEAR 0xD2 -#define HID_KEYPAD_MEMORY_ADD 0xD3 -#define HID_KEYPAD_MEMORY_SUBTRACT 0xD4 -#define HID_KEYPAD_MEMORY_MULTIPLY 0xD5 -#define HID_KEYPAD_MEMORY_DIVIDE 0xD6 -#define HID_KEYPAD_PLUS_SLASH_MINUS 0xD7 -#define HID_KEYPAD_CLEAR 0xD8 -#define HID_KEYPAD_CLEAR_ENTRY 0xD9 -#define HID_KEYPAD_BINARY 0xDA -#define HID_KEYPAD_OCTAL 0xDB -#define HID_KEYPAD_DECIMAL 0xDC -#define HID_KEYPAD_HEXADECIMAL 0xDD - -// 0xDE-0xDF - RESERVED -#define HID_KEYBOARD_LEFT_CONTROL 0xE0 -#define HID_KEYBOARD_LEFT_SHIFT 0xE1 -#define HID_KEYBOARD_LEFT_ALT 0xE2 -#define HID_KEYBOARD_LEFT_GUI 0xE3 -#define HID_KEYBOARD_RIGHT_CONTROL 0xE4 -#define HID_KEYBOARD_RIGHT_SHIFT 0xE5 -#define HID_KEYBOARD_RIGHT_ALT 0xE6 -#define HID_KEYBOARD_RIGHT_GUI 0xE7 - - -// Consumer_Page_(0x0C) 0x15 -#define HID_CONSUMER_NUMERIC_KEY_PAD 0x02 // HID type NARY -#define HID_CONSUMER_PROGRAMMABLE_BUTTONS 0x03 // HID type NARY -#define HID_CONSUMER_MICROPHONE_CA 0x04 -#define HID_CONSUMER_HEADPHONE_CA 0x05 -#define HID_CONSUMER_GRAPHIC_EQUALIZER_CA 0x06 -// Reserved 0x07-1F -#define HID_CONSUMER_PLUS_10 0x20 // HID type OSC -#define HID_CONSUMER_PLUS_100 0x21 // HID type OSC -#define HID_CONSUMER_AM_SLASH_PM 0x22 // HID type OSC -// Reserved 0x23-3F -#define HID_CONSUMER_POWER 0x30 // HID type OOC -#define HID_CONSUMER_RESET 0x31 // HID type OSC -#define HID_CONSUMER_SLEEP 0x32 // HID type OSC -#define HID_CONSUMER_SLEEP_AFTER 0x33 // HID type OSC -#define HID_CONSUMER_SLEEP_MODE 0x34 // HID type RTC -#define HID_CONSUMER_ILLUMINATION 0x35 // HID type OOC -#define HID_CONSUMER_FUNCTION_BUTTONS 0x36 // HID type NARY -// Reserved 0x37-3F -#define HID_CONSUMER_MENU 0x40 // HID type OOC -#define HID_CONSUMER_MENU_PICK 0x41 // HID type OSC -#define HID_CONSUMER_MENU_UP 0x42 // HID type OSC -#define HID_CONSUMER_MENU_DOWN 0x43 // HID type OSC -#define HID_CONSUMER_MENU_LEFT 0x44 // HID type OSC -#define HID_CONSUMER_MENU_RIGHT 0x45 // HID type OSC -#define HID_CONSUMER_MENU_ESCAPE 0x46 // HID type OSC -#define HID_CONSUMER_MENU_VALUE_INCREASE 0x47 // HID type OSC -#define HID_CONSUMER_MENU_VALUE_DECREASE 0x48 // HID type OSC -// Reserved 0x49-5F -#define HID_CONSUMER_DATA_ON_SCREEN 0x60 // HID type OOC -#define HID_CONSUMER_CLOSED_CAPTION 0x61 // HID type OOC -#define HID_CONSUMER_CLOSED_CAPTION_SELECT 0x62 // HID type OSC -#define HID_CONSUMER_VCR_SLASH_TV 0x63 // HID type OOC -#define HID_CONSUMER_BROADCAST_MODE 0x64 // HID type OSC -#define HID_CONSUMER_SNAPSHOT 0x65 // HID type OSC -#define HID_CONSUMER_STILL 0x66 // HID type OSC -// Reserved 0x67-7F -#define HID_CONSUMER_SELECTION 0x80 // HID type NARY -#define HID_CONSUMER_ASSIGN_SELECTION 0x81 // HID type OSC -#define HID_CONSUMER_MODE_STEP 0x82 // HID type OSC -#define HID_CONSUMER_RECALL_LAST 0x83 // HID type OSC -#define HID_CONSUMER_ENTER_CHANNEL 0x84 // HID type OSC -#define HID_CONSUMER_ORDER_MOVIE 0x85 // HID type OSC -#define HID_CONSUMER_CHANNEL 0x86 // HID type LC -#define HID_CONSUMER_MEDIA_SELECTION 0x87 // HID type NARY -#define HID_CONSUMER_MEDIA_SELECT_COMPUTER 0x88 // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_TV 0x89 // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_WWW 0x8A // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_DVD 0x8B // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_TELEPHONE 0x8C // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_PROGRAM_GUIDE 0x8D // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_VIDEO_PHONE 0x8E // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_GAMES 0x8F // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_MESSAGES 0x90 // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_CD 0x91 // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_VCR 0x92 // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_TUNER 0x93 // HID type SEL -#define HID_CONSUMER_QUIT 0x94 // HID type OSC -#define HID_CONSUMER_HELP 0x95 // HID type OOC -#define HID_CONSUMER_MEDIA_SELECT_TAPE 0x96 // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_CABLE 0x97 // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_SATELLITE 0x98 // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_SECURITY 0x99 // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_HOME 0x9A // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_CALL 0x9B // HID type SEL -#define HID_CONSUMER_CHANNEL_INCREMENT 0x9C // HID type OSC -#define HID_CONSUMER_CHANNEL_DECREMENT 0x9D // HID type OSC -#define HID_CONSUMER_MEDIA_SELECT_SAP 0x9E // HID type SEL -// Reserved 0x9F -#define HID_CONSUMER_VCR_PLUS 0xA0 // HID type OSC -#define HID_CONSUMER_ONCE 0xA1 // HID type OSC -#define HID_CONSUMER_DAILY 0xA2 // HID type OSC -#define HID_CONSUMER_WEEKLY 0xA3 // HID type OSC -#define HID_CONSUMER_MONTHLY 0xA4 // HID type OSC -// Reserved 0xA5-AF -#define HID_CONSUMER_PLAY 0xB0 // HID type OOC -#define HID_CONSUMER_PAUSE 0xB1 // HID type OOC -#define HID_CONSUMER_RECORD 0xB2 // HID type OOC -#define HID_CONSUMER_FAST_FORWARD 0xB3 // HID type OOC -#define HID_CONSUMER_REWIND 0xB4 // HID type OOC -#define HID_CONSUMER_SCAN_NEXT_TRACK 0xB5 // HID type OSC -#define HID_CONSUMER_SCAN_PREVIOUS_TRACK 0xB6 // HID type OSC -#define HID_CONSUMER_STOP 0xB7 // HID type OSC -#define HID_CONSUMER_EJECT 0xB8 // HID type OSC -#define HID_CONSUMER_RANDOM_PLAY 0xB9 // HID type OOC -#define HID_CONSUMER_SELECT_DISC 0xBA // HID type NARY -#define HID_CONSUMER_ENTER_DISC_MC 0xBB -#define HID_CONSUMER_REPEAT 0xBC // HID type OSC -#define HID_CONSUMER_TRACKING 0xBD // HID type LC -#define HID_CONSUMER_TRACK_NORMAL 0xBE // HID type OSC -#define HID_CONSUMER_SLOW_TRACKING 0xBF // HID type LC -#define HID_CONSUMER_FRAME_FORWARD 0xC0 // HID type RTC -#define HID_CONSUMER_FRAME_BACK 0xC1 // HID type RTC -#define HID_CONSUMER_MARK 0xC2 // HID type OSC -#define HID_CONSUMER_CLEAR_MARK 0xC3 // HID type OSC -#define HID_CONSUMER_REPEAT_FROM_MARK 0xC4 // HID type OOC -#define HID_CONSUMER_RETURN_TO_MARK 0xC5 // HID type OSC -#define HID_CONSUMER_SEARCH_MARK_FORWARD 0xC6 // HID type OSC -#define HID_CONSUMER_SEARCH_MARK_BACKWARDS 0xC7 // HID type OSC -#define HID_CONSUMER_COUNTER_RESET 0xC8 // HID type OSC -#define HID_CONSUMER_SHOW_COUNTER 0xC9 // HID type OSC -#define HID_CONSUMER_TRACKING_INCREMENT 0xCA // HID type RTC -#define HID_CONSUMER_TRACKING_DECREMENT 0xCB // HID type RTC -#define HID_CONSUMER_STOP_SLASH_EJECT 0xCC // HID type OSC -#define HID_CONSUMER_PLAY_SLASH_PAUSE 0xCD // HID type OSC -#define HID_CONSUMER_PLAY_SLASH_SKIP 0xCE // HID type OSC -// Reserved 0xCF-DF -#define HID_CONSUMER_VOLUME 0xE0 // HID type LC -#define HID_CONSUMER_BALANCE 0xE1 // HID type LC -#define HID_CONSUMER_MUTE 0xE2 // HID type OOC -#define HID_CONSUMER_BASS 0xE3 // HID type LC -#define HID_CONSUMER_TREBLE 0xE4 // HID type LC -#define HID_CONSUMER_BASS_BOOST 0xE5 // HID type OOC -#define HID_CONSUMER_SURROUND_MODE 0xE6 // HID type OSC -#define HID_CONSUMER_LOUDNESS 0xE7 // HID type OOC -#define HID_CONSUMER_MPX 0xE8 // HID type OOC -#define HID_CONSUMER_VOLUME_INCREMENT 0xE9 // HID type RTC -#define HID_CONSUMER_VOLUME_DECREMENT 0xEA // HID type RTC -// Reserved 0xEB-EF -#define HID_CONSUMER_SPEED_SELECT 0xF0 // HID type OSC -#define HID_CONSUMER_PLAYBACK_SPEED 0xF1 // HID type NARY -#define HID_CONSUMER_STANDARD_PLAY 0xF2 // HID type SEL -#define HID_CONSUMER_LONG_PLAY 0xF3 // HID type SEL -#define HID_CONSUMER_EXTENDED_PLAY 0xF4 // HID type SEL -#define HID_CONSUMER_SLOW 0xF5 // HID type OSC -// Reserved 0xF6-FF -#define HID_CONSUMER_FAN_ENABLE 0x100 // HID type OOC -#define HID_CONSUMER_FAN_SPEED 0x101 // HID type LC -#define HID_CONSUMER_LIGHT_ENABLE 0x102 // HID type OOC -#define HID_CONSUMER_LIGHT_ILLUMINATION_LEVEL 0x103 // HID type LC -#define HID_CONSUMER_CLIMATE_CONTROL_ENABLE 0x104 // HID type OOC -#define HID_CONSUMER_ROOM_TEMPERATURE 0x105 // HID type LC -#define HID_CONSUMER_SECURITY_ENABLE 0x106 // HID type OOC -#define HID_CONSUMER_FIRE_ALARM 0x107 // HID type OSC -#define HID_CONSUMER_POLICE_ALARM 0x108 // HID type OSC -#define HID_CONSUMER_PROXIMITY 0x109 // HID type LC -#define HID_CONSUMER_MOTION 0x10A // HID type OSC -#define HID_CONSUMER_DURESS_ALARM 0x10B // HID type OSC -#define HID_CONSUMER_HOLDUP_ALARM 0x10C // HID type OSC -#define HID_CONSUMER_MEDICAL_ALARM 0x10D // HID type OSC -// Reserved 0x10E-14F -#define HID_CONSUMER_BALANCE_RIGHT 0x150 // HID type RTC -#define HID_CONSUMER_BALANCE_LEFT 0x151 // HID type RTC -#define HID_CONSUMER_BASS_INCREMENT 0x152 // HID type RTC -#define HID_CONSUMER_BASS_DECREMENT 0x153 // HID type RTC -#define HID_CONSUMER_TREBLE_INCREMENT 0x154 // HID type RTC -#define HID_CONSUMER_TREBLE_DECREMENT 0x155 // HID type RTC -// Reserved 0x156-15F -#define HID_CONSUMER_SPEAKER_SYSTEM 0x160 // HID type CL -#define HID_CONSUMER_CHANNEL_LEFT 0x161 // HID type CL -#define HID_CONSUMER_CHANNEL_RIGHT 0x162 // HID type CL -#define HID_CONSUMER_CHANNEL_CENTER 0x163 // HID type CL -#define HID_CONSUMER_CHANNEL_FRONT 0x164 // HID type CL -#define HID_CONSUMER_CHANNEL_CENTER_FRONT 0x165 // HID type CL -#define HID_CONSUMER_CHANNEL_SIDE 0x166 // HID type CL -#define HID_CONSUMER_CHANNEL_SURROUND 0x167 // HID type CL -#define HID_CONSUMER_CHANNEL_LOW_FREQUENCY_ENHANCEMENT 0x168 // HID type CL -#define HID_CONSUMER_CHANNEL_TOP 0x169 // HID type CL -#define HID_CONSUMER_CHANNEL_UNKNOWN 0x16A // HID type CL -// Reserved 0x16B-16F -#define HID_CONSUMER_SUB_CHANNEL 0x170 // HID type LC -#define HID_CONSUMER_SUB_CHANNEL_INCREMENT 0x171 // HID type OSC -#define HID_CONSUMER_SUB_CHANNEL_DECREMENT 0x172 // HID type OSC -#define HID_CONSUMER_ALTERNATE_AUDIO_INCREMENT 0x173 // HID type OSC -#define HID_CONSUMER_ALTERNATE_AUDIO_DECREMENT 0x174 // HID type OSC -// Reserved 0x175-17F -#define HID_CONSUMER_APPLICATION_LAUNCH_BUTTONS 0x180 // HID type NARY -#define HID_CONSUMER_AL_LAUNCH_BUTTON_CONFIGURATION_TOOL 0x181 // HID type SEL -#define HID_CONSUMER_AL_PROGRAMMABLE_BUTTON_CONFIGURATION 0x182 // HID type SEL -#define HID_CONSUMER_AL_CONSUMER_CONTROL_CONFIGURATION 0x183 // HID type SEL -#define HID_CONSUMER_AL_WORD_PROCESSOR 0x184 // HID type SEL -#define HID_CONSUMER_AL_TEXT_EDITOR 0x185 // HID type SEL -#define HID_CONSUMER_AL_SPREADSHEET 0x186 // HID type SEL -#define HID_CONSUMER_AL_GRAPHICS_EDITOR 0x187 // HID type SEL -#define HID_CONSUMER_AL_PRESENTATION_APP 0x188 // HID type SEL -#define HID_CONSUMER_AL_DATABASE_APP 0x189 // HID type SEL -#define HID_CONSUMER_AL_EMAIL_READER 0x18A // HID type SEL -#define HID_CONSUMER_AL_NEWSREADER 0x18B // HID type SEL -#define HID_CONSUMER_AL_VOICEMAIL 0x18C // HID type SEL -#define HID_CONSUMER_AL_CONTACTS_SLASH_ADDRESS_BOOK 0x18D // HID type SEL -#define HID_CONSUMER_AL_CALENDAR_SLASH_SCHEDULE 0x18E // HID type SEL -#define HID_CONSUMER_AL_TASK_SLASH_PROJECT_MANAGER 0x18F // HID type SEL -#define HID_CONSUMER_AL_LOG_SLASH_JOURNAL_SLASH_TIMECARD 0x190 // HID type SEL -#define HID_CONSUMER_AL_CHECKBOOK_SLASH_FINANCE 0x191 // HID type SEL -#define HID_CONSUMER_AL_CALCULATOR 0x192 // HID type SEL -#define HID_CONSUMER_AL_A_SLASH_V_CAPTURE_SLASH_PLAYBACK 0x193 // HID type SEL -#define HID_CONSUMER_AL_LOCAL_MACHINE_BROWSER 0x194 // HID type SEL -#define HID_CONSUMER_AL_LAN_SLASH_WAN_BROWSER 0x195 // HID type SEL -#define HID_CONSUMER_AL_INTERNET_BROWSER 0x196 // HID type SEL -#define HID_CONSUMER_AL_REMOTE_NETWORKING_SLASH_ISP_CONNECT 0x197 // HID type SEL -#define HID_CONSUMER_AL_NETWORK_CONFERENCE 0x198 // HID type SEL -#define HID_CONSUMER_AL_NETWORK_CHAT 0x199 // HID type SEL -#define HID_CONSUMER_AL_TELEPHONY_SLASH_DIALER 0x19A // HID type SEL -#define HID_CONSUMER_AL_LOGON 0x19B // HID type SEL -#define HID_CONSUMER_AL_LOGOFF 0x19C // HID type SEL -#define HID_CONSUMER_AL_LOGON_SLASH_LOGOFF 0x19D // HID type SEL -#define HID_CONSUMER_AL_TERMINAL_LOCK_SLASH_SCREENSAVER 0x19E // HID type SEL -#define HID_CONSUMER_AL_CONTROL_PANEL 0x19F // HID type SEL -#define HID_CONSUMER_AL_COMMAND_LINE_PROCESSOR_SLASH_RUN 0x1A0 // HID type SEL -#define HID_CONSUMER_AL_PROCESS_SLASH_TASK_MANAGER 0x1A1 // HID type SEL -#define HID_CONSUMER_AL_SELECT_TASK_SLASH_APPLICATION 0x1A2 // HID type SEL -#define HID_CONSUMER_AL_NEXT_TASK_SLASH_APPLICATION 0x1A3 // HID type SEL -#define HID_CONSUMER_AL_PREVIOUS_TASK_SLASH_APPLICATION 0x1A4 // HID type SEL -#define HID_CONSUMER_AL_PREEMPTIVE_HALT_TASK_SLASH_APPLICATION 0x1A5 // HID type SEL -#define HID_CONSUMER_AL_INTEGRATED_HELP_CENTER 0x1A6 // HID type SEL -#define HID_CONSUMER_AL_DOCUMENTS 0x1A7 // HID type SEL -#define HID_CONSUMER_AL_THESAURUS 0x1A8 // HID type SEL -#define HID_CONSUMER_AL_DICTIONARY 0x1A9 // HID type SEL -#define HID_CONSUMER_AL_DESKTOP 0x1AA // HID type SEL -#define HID_CONSUMER_AL_SPELL_CHECK 0x1AB // HID type SEL -#define HID_CONSUMER_AL_GRAMMAR_CHECK 0x1AC // HID type SEL -#define HID_CONSUMER_AL_WIRELESS_STATUS 0x1AD // HID type SEL -#define HID_CONSUMER_AL_KEYBOARD_LAYOUT 0x1AE // HID type SEL -#define HID_CONSUMER_AL_VIRUS_PROTECTION 0x1AF // HID type SEL -#define HID_CONSUMER_AL_ENCRYPTION 0x1B0 // HID type SEL -#define HID_CONSUMER_AL_SCREEN_SAVER 0x1B1 // HID type SEL -#define HID_CONSUMER_AL_ALARMS 0x1B2 // HID type SEL -#define HID_CONSUMER_AL_CLOCK 0x1B3 // HID type SEL -#define HID_CONSUMER_AL_FILE_BROWSER 0x1B4 // HID type SEL -#define HID_CONSUMER_AL_POWER_STATUS 0x1B5 // HID type SEL -#define HID_CONSUMER_AL_IMAGE_BROWSER 0x1B6 // HID type SEL -#define HID_CONSUMER_AL_AUDIO_BROWSER 0x1B7 // HID type SEL -#define HID_CONSUMER_AL_MOVIE_BROWSER 0x1B8 // HID type SEL -#define HID_CONSUMER_AL_DIGITAL_RIGHTS_MANAGER 0x1B9 // HID type SEL -#define HID_CONSUMER_AL_DIGITAL_WALLET 0x1BA // HID type SEL -// _Reserved 0x1BB -#define HID_CONSUMER_AL_INSTANT_MESSAGING 0x1BC // HID type SEL -#define HID_CONSUMER_AL_OEM_FEATURES_SLASH__TIPS_SLASH_TUTORIAL_BROWSER 0x1BD // HID type SEL -#define HID_CONSUMER_AL_OEM_HELP 0x1BE // HID type SEL -#define HID_CONSUMER_AL_ONLINE_COMMUNITY 0x1BF // HID type SEL -#define HID_CONSUMER_AL_ENTERTAINMENT_CONTENT_BROWSER 0x1C0 // HID type SEL -#define HID_CONSUMER_AL_ONLINE_SHOPPING_BROWSER 0x1C1 // HID type SEL -#define HID_CONSUMER_AL_SMARTCARD_INFORMATION_SLASH_HELP 0x1C2 // HID type SEL -#define HID_CONSUMER_AL_MARKET_MONITOR_SLASH_FINANCE_BROWSER 0x1C3 // HID type SEL -#define HID_CONSUMER_AL_CUSTOMIZED_CORPORATE_NEWS_BROWSER 0x1C4 // HID type SEL -#define HID_CONSUMER_AL_ONLINE_ACTIVITY_BROWSER 0x1C5 // HID type SEL -#define HID_CONSUMER_AL_RESEARCH_SLASH_SEARCH_BROWSER 0x1C6 // HID type SEL -#define HID_CONSUMER_AL_AUDIO_PLAYER 0x1C7 // HID type SEL -// Reserved 0x1C8-1FF -#define HID_CONSUMER_GENERIC_GUI_APPLICATION_CONTROLS 0x200 // HID type NARY -#define HID_CONSUMER_AC_NEW 0x201 // HID type SEL -#define HID_CONSUMER_AC_OPEN 0x202 // HID type SEL -#define HID_CONSUMER_AC_CLOSE 0x203 // HID type SEL -#define HID_CONSUMER_AC_EXIT 0x204 // HID type SEL -#define HID_CONSUMER_AC_MAXIMIZE 0x205 // HID type SEL -#define HID_CONSUMER_AC_MINIMIZE 0x206 // HID type SEL -#define HID_CONSUMER_AC_SAVE 0x207 // HID type SEL -#define HID_CONSUMER_AC_PRINT 0x208 // HID type SEL -#define HID_CONSUMER_AC_PROPERTIES 0x209 // HID type SEL -#define HID_CONSUMER_AC_UNDO 0x21A // HID type SEL -#define HID_CONSUMER_AC_COPY 0x21B // HID type SEL -#define HID_CONSUMER_AC_CUT 0x21C // HID type SEL -#define HID_CONSUMER_AC_PASTE 0x21D // HID type SEL -#define HID_CONSUMER_AC_SELECT_ALL 0x21E // HID type SEL -#define HID_CONSUMER_AC_FIND 0x21F // HID type SEL -#define HID_CONSUMER_AC_FIND_AND_REPLACE 0x220 // HID type SEL -#define HID_CONSUMER_AC_SEARCH 0x221 // HID type SEL -#define HID_CONSUMER_AC_GO_TO 0x222 // HID type SEL -#define HID_CONSUMER_AC_HOME 0x223 // HID type SEL -#define HID_CONSUMER_AC_BACK 0x224 // HID type SEL -#define HID_CONSUMER_AC_FORWARD 0x225 // HID type SEL -#define HID_CONSUMER_AC_STOP 0x226 // HID type SEL -#define HID_CONSUMER_AC_REFRESH 0x227 // HID type SEL -#define HID_CONSUMER_AC_PREVIOUS_LINK 0x228 // HID type SEL -#define HID_CONSUMER_AC_NEXT_LINK 0x229 // HID type SEL -#define HID_CONSUMER_AC_BOOKMARKS 0x22A // HID type SEL -#define HID_CONSUMER_AC_HISTORY 0x22B // HID type SEL -#define HID_CONSUMER_AC_SUBSCRIPTIONS 0x22C // HID type SEL -#define HID_CONSUMER_AC_ZOOM_IN 0x22D // HID type SEL -#define HID_CONSUMER_AC_ZOOM_OUT 0x22E // HID type SEL -#define HID_CONSUMER_AC_ZOOM 0x22F // HID type LC -#define HID_CONSUMER_AC_FULL_SCREEN_VIEW 0x230 // HID type SEL -#define HID_CONSUMER_AC_NORMAL_VIEW 0x231 // HID type SEL -#define HID_CONSUMER_AC_VIEW_TOGGLE 0x232 // HID type SEL -#define HID_CONSUMER_AC_SCROLL_UP 0x233 // HID type SEL -#define HID_CONSUMER_AC_SCROLL_DOWN 0x234 // HID type SEL -#define HID_CONSUMER_AC_SCROLL 0x235 // HID type LC -#define HID_CONSUMER_AC_PAN_LEFT 0x236 // HID type SEL -#define HID_CONSUMER_AC_PAN_RIGHT 0x237 // HID type SEL -#define HID_CONSUMER_AC_PAN 0x238 // HID type LC -#define HID_CONSUMER_AC_NEW_WINDOW 0x239 // HID type SEL -#define HID_CONSUMER_AC_TILE_HORIZONTALLY 0x23A // HID type SEL -#define HID_CONSUMER_AC_TILE_VERTICALLY 0x23B // HID type SEL -#define HID_CONSUMER_AC_FORMAT 0x23C // HID type SEL -#define HID_CONSUMER_AC_EDIT 0x23D // HID type SEL -#define HID_CONSUMER_AC_BOLD 0x23E // HID type SEL -#define HID_CONSUMER_AC_ITALICS 0x23F // HID type SEL -#define HID_CONSUMER_AC_UNDERLINE 0x240 // HID type SEL -#define HID_CONSUMER_AC_STRIKETHROUGH 0x241 // HID type SEL -#define HID_CONSUMER_AC_SUBSCRIPT 0x242 // HID type SEL -#define HID_CONSUMER_AC_SUPERSCRIPT 0x243 // HID type SEL -#define HID_CONSUMER_AC_ALL_CAPS 0x244 // HID type SEL -#define HID_CONSUMER_AC_ROTATE 0x245 // HID type SEL -#define HID_CONSUMER_AC_RESIZE 0x246 // HID type SEL -#define HID_CONSUMER_AC_FLIP_HORIZONTAL 0x247 // HID type SEL -#define HID_CONSUMER_AC_FLIP_VERTICAL 0x248 // HID type SEL -#define HID_CONSUMER_AC_MIRROR_HORIZONTAL 0x249 // HID type SEL -#define HID_CONSUMER_AC_MIRROR_VERTICAL 0x24A // HID type SEL -#define HID_CONSUMER_AC_FONT_SELECT 0x24B // HID type SEL -#define HID_CONSUMER_AC_FONT_COLOR 0x24C // HID type SEL -#define HID_CONSUMER_AC_FONT_SIZE 0x24D // HID type SEL -#define HID_CONSUMER_AC_JUSTIFY_LEFT 0x24E // HID type SEL -#define HID_CONSUMER_AC_JUSTIFY_CENTER_H 0x24F // HID type SEL -#define HID_CONSUMER_AC_JUSTIFY_RIGHT 0x250 // HID type SEL -#define HID_CONSUMER_AC_JUSTIFY_BLOCK_H 0x251 // HID type SEL -#define HID_CONSUMER_AC_JUSTIFY_TOP 0x252 // HID type SEL -#define HID_CONSUMER_AC_JUSTIFY_CENTER_V 0x253 // HID type SEL -#define HID_CONSUMER_AC_JUSTIFY_BOTTOM 0x254 // HID type SEL -#define HID_CONSUMER_AC_JUSTIFY_BLOCK_V 0x255 // HID type SEL -#define HID_CONSUMER_AC_INDENT_DECREASE 0x256 // HID type SEL -#define HID_CONSUMER_AC_INDENT_INCREASE 0x257 // HID type SEL -#define HID_CONSUMER_AC_NUMBERED_LIST 0x258 // HID type SEL -#define HID_CONSUMER_AC_RESTART_NUMBERING 0x259 // HID type SEL -#define HID_CONSUMER_AC_BULLETED_LIST 0x25A // HID type SEL -#define HID_CONSUMER_AC_PROMOTE 0x25B // HID type SEL -#define HID_CONSUMER_AC_DEMOTE 0x25C // HID type SEL -#define HID_CONSUMER_AC_YES 0x25D // HID type SEL -#define HID_CONSUMER_AC_NO 0x25E // HID type SEL -#define HID_CONSUMER_AC_CANCEL 0x25F // HID type SEL -#define HID_CONSUMER_AC_CATALOG 0x260 // HID type SEL -#define HID_CONSUMER_AC_BUY_SLASH_CHECKOUT 0x261 // HID type SEL -#define HID_CONSUMER_AC_ADD_TO_CART 0x262 // HID type SEL -#define HID_CONSUMER_AC_EXPAND 0x263 // HID type SEL -#define HID_CONSUMER_AC_EXPAND_ALL 0x264 // HID type SEL -#define HID_CONSUMER_AC_COLLAPSE 0x265 // HID type SEL -#define HID_CONSUMER_AC_COLLAPSE_ALL 0x266 // HID type SEL -#define HID_CONSUMER_AC_PRINT_PREVIEW 0x267 // HID type SEL -#define HID_CONSUMER_AC_PASTE_SPECIAL 0x268 // HID type SEL -#define HID_CONSUMER_AC_INSERT_MODE 0x269 // HID type SEL -#define HID_CONSUMER_AC_DELETE 0x26A // HID type SEL -#define HID_CONSUMER_AC_LOCK 0x26B // HID type SEL -#define HID_CONSUMER_AC_UNLOCK 0x26C // HID type SEL -#define HID_CONSUMER_AC_PROTECT 0x26D // HID type SEL -#define HID_CONSUMER_AC_UNPROTECT 0x26E // HID type SEL -#define HID_CONSUMER_AC_ATTACH_COMMENT 0x26F // HID type SEL -#define HID_CONSUMER_AC_DELETE_COMMENT 0x270 // HID type SEL -#define HID_CONSUMER_AC_VIEW_COMMENT 0x271 // HID type SEL -#define HID_CONSUMER_AC_SELECT_WORD 0x272 // HID type SEL -#define HID_CONSUMER_AC_SELECT_SENTENCE 0x273 // HID type SEL -#define HID_CONSUMER_AC_SELECT_PARAGRAPH 0x274 // HID type SEL -#define HID_CONSUMER_AC_SELECT_COLUMN 0x275 // HID type SEL -#define HID_CONSUMER_AC_SELECT_ROW 0x276 // HID type SEL -#define HID_CONSUMER_AC_SELECT_TABLE 0x277 // HID type SEL -#define HID_CONSUMER_AC_SELECT_OBJECT 0x278 // HID type SEL -#define HID_CONSUMER_AC_REDO_SLASH_REPEAT 0x279 // HID type SEL -#define HID_CONSUMER_AC_SORT 0x27A // HID type SEL -#define HID_CONSUMER_AC_SORT_ASCENDING 0x27B // HID type SEL -#define HID_CONSUMER_AC_SORT_DESCENDING 0x27C // HID type SEL -#define HID_CONSUMER_AC_FILTER 0x27D // HID type SEL -#define HID_CONSUMER_AC_SET_CLOCK 0x27E // HID type SEL -#define HID_CONSUMER_AC_VIEW_CLOCK 0x27F // HID type SEL -#define HID_CONSUMER_AC_SELECT_TIME_ZONE 0x280 // HID type SEL -#define HID_CONSUMER_AC_EDIT_TIME_ZONES 0x281 // HID type SEL -#define HID_CONSUMER_AC_SET_ALARM 0x282 // HID type SEL -#define HID_CONSUMER_AC_CLEAR_ALARM 0x283 // HID type SEL -#define HID_CONSUMER_AC_SNOOZE_ALARM 0x284 // HID type SEL -#define HID_CONSUMER_AC_RESET_ALARM 0x285 // HID type SEL -#define HID_CONSUMER_AC_SYNCHRONIZE 0x286 // HID type SEL -#define HID_CONSUMER_AC_SEND_SLASH_RECEIVE 0x287 // HID type SEL -#define HID_CONSUMER_AC_SEND_TO 0x288 // HID type SEL -#define HID_CONSUMER_AC_REPLY 0x289 // HID type SEL -#define HID_CONSUMER_AC_REPLY_ALL 0x28A // HID type SEL -#define HID_CONSUMER_AC_FORWARD_MSG 0x28B // HID type SEL -#define HID_CONSUMER_AC_SEND 0x28C // HID type SEL -#define HID_CONSUMER_AC_ATTACH_FILE 0x28D // HID type SEL -#define HID_CONSUMER_AC_UPLOAD 0x28E // HID type SEL -#define HID_CONSUMER_AC_DOWNLOAD_(SAVE_TARGET_AS) 0x28F // HID type SEL -#define HID_CONSUMER_AC_SET_BORDERS 0x290 // HID type SEL -#define HID_CONSUMER_AC_INSERT_ROW 0x291 // HID type SEL -#define HID_CONSUMER_AC_INSERT_COLUMN 0x292 // HID type SEL -#define HID_CONSUMER_AC_INSERT_FILE 0x293 // HID type SEL -#define HID_CONSUMER_AC_INSERT_PICTURE 0x294 // HID type SEL -#define HID_CONSUMER_AC_INSERT_OBJECT 0x295 // HID type SEL -#define HID_CONSUMER_AC_INSERT_SYMBOL 0x296 // HID type SEL -#define HID_CONSUMER_AC_SAVE_AND_CLOSE 0x297 // HID type SEL -#define HID_CONSUMER_AC_RENAME 0x298 // HID type SEL -#define HID_CONSUMER_AC_MERGE 0x299 // HID type SEL -#define HID_CONSUMER_AC_SPLIT 0x29A // HID type SEL -#define HID_CONSUMER_AC_DISRIBUTE_HORIZONTALLY 0x29B // HID type SEL -#define HID_CONSUMER_AC_DISTRIBUTE_VERTICALLY 0x29C // HID type SEL diff --git a/plugins/KeyboardioHID/src/HID.h b/plugins/KeyboardioHID/src/HID.h deleted file mode 100644 index 775c6177ae..0000000000 --- a/plugins/KeyboardioHID/src/HID.h +++ /dev/null @@ -1,2 +0,0 @@ -#include "PluggableHID/HID.h" -#include "PluggableHID/HIDDevice.h" diff --git a/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp b/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp deleted file mode 100644 index ca83d3854e..0000000000 --- a/plugins/KeyboardioHID/src/ImprovedKeyboard.cpp +++ /dev/null @@ -1,355 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 "ImprovedKeyboard.h" - -#if defined(_USING_HID) - -//================================================================================ -//================================================================================ -// Keyboard - -static const u8 _hidReportDescriptor[] PROGMEM = { - // Keyboard - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 47 */ - 0x09, 0x06, /* USAGE (Keyboard) */ - 0xa1, 0x01, /* COLLECTION (Application) */ - 0x85, HID_REPORTID_KEYBOARD, /* REPORT_ID */ - 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ - - /* Keyboard Modifiers (shift, alt, ...) */ - 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) */ - - /* Reserved byte */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0x75, 0x08, /* REPORT_SIZE (8) */ - 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ - -#if defined(HID_KEYBOARD_LEDS_ENABLED) - /* 5 LEDs for num lock etc, 3 left for advanced, custom usage */ - 0x05, 0x08, /* USAGE_PAGE (LEDs) */ - 0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */ - 0x29, 0x05, /* USAGE_MAXIMUM (Kana) */ - 0x95, 0x08, /* REPORT_COUNT (8) */ - 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */ - /* Reserved 3 bits */ - //0x95, 0x01, /* REPORT_COUNT (1) */ - //0x75, 0x03, /* REPORT_SIZE (3) */ - //0x91, 0x03, /* OUTPUT (Cnst,Var,Abs) */ -#endif - - /* 6 Keyboard keys */ - 0x95, 0x06, /* REPORT_COUNT (6) */ - 0x75, 0x08, /* REPORT_SIZE (8) */ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ - 0x26, 0xE7, 0x00, /* LOGICAL_MAXIMUM (231) */ - 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ - 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ - 0x29, 0xE7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ - 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ - - /* End */ - 0xc0 /* END_COLLECTION */ -}; - -Keyboard_::Keyboard_(void) : -HIDDevice((uint8_t*)_hidReportDescriptor, sizeof(_hidReportDescriptor), HID_REPORTID_KEYBOARD) -#if defined(HID_KEYBOARD_LEDS_ENABLED) -,leds(0) -#endif -{ - // HID Descriptor is appended via the inherited HIDDevice class -} - -void Keyboard_::begin(void) -{ - releaseAll(); -} - -void Keyboard_::end(void) -{ - releaseAll(); -} - -void Keyboard_::sendReport(HID_KeyboardReport_Data_t* keys) -{ - // Call the inherited function. - // This wrapper still saves us some bytes -#if defined(USE_BOOT_KEYBOARD_PROTOCOL) - if(getProtocol() != 1){ - SendRawReport(keys,sizeof(HID_KeyboardReport_Data_t)); - } - else -#endif - SendReport(keys,sizeof(HID_KeyboardReport_Data_t)); -} - -void Keyboard_::send_now(void){ - sendReport(&_keyReport); -} - -#if defined(HID_KEYBOARD_LEDS_ENABLED) -void Keyboard_::setReportData(void* &data, int len){ - // Save led state - if(len == 2) - leds = *(uint8_t*)(data+1); -} - -uint8_t Keyboard_::getLeds(void){ - return leds; -} -#endif - - -// 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) -{ - size_t ret = addKeyToReport(k); - if(ret){ - sendReport(&_keyReport); - } - return ret; -} - -// 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 & SHIFT) { // it's a capital letter or other character reached with shift - _keyReport.modifiers &= ~(0x02); // the left shift modifier - k = k ^ SHIFT; - } - } - - // 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) -{ - // release all keys - memset(&_keyReport, 0x00, sizeof(_keyReport)); - sendReport(&_keyReport); -} - -size_t Keyboard_::write(uint8_t c) -{ - uint8_t p = press(c); // Keydown - release(c); // Keyup - return p; // just return the result of press() since release() almost always returns 1 -} - -// pressKeycode() 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 releaseKeycode(), releaseAll(), or otherwise clear the report and resend. -size_t Keyboard_::pressKeycode(uint8_t k) -{ - if (!addKeycodeToReport(k)) { - return 0; - } - sendReport(&_keyReport); -} - -size_t Keyboard_::addKeyToReport(uint8_t k) -{ - 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 & SHIFT) { // it's a capital letter or other character reached with shift - _keyReport.modifiers |= 0x02; // the left shift modifier - k = k ^ SHIFT; - } - } - - return addKeycodeToReport(k); -} - -size_t Keyboard_::addKeycodeToReport(uint8_t k) -{ - uint8_t index = 0; - uint8_t done = 0; - - if ((k >= HID_KEYBOARD_LEFT_CONTROL) && (k <= HID_KEYBOARD_RIGHT_GUI)) { - // it's a modifier key - _keyReport.modifiers |= (0x01 << (k - HID_KEYBOARD_LEFT_CONTROL)); - } - else { - // it's some other key: - // Add k to the key report only if it's not already present - // and if there is an empty slot. - for (index = 0; index < sizeof(_keyReport.keys); index++) { - if (_keyReport.keys[index] != k) { // is k already in list? - if (0 == _keyReport.keys[index]) { // have we found an empty slot? - _keyReport.keys[index] = k; - done = 1; - break; - } - } - else { - done = 1; - break; - } - - } - - // use separate variable to check if slot was found - // for style reasons - we do not know how the compiler - // handles the for() index when it leaves the loop - if (0 == done) { - setWriteError(); - return 0; - } - } - - return 1; -} - - -// releaseKeycode() 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. -// When send is set to FALSE (= 0) no sendReport() is executed. This comes in -// handy when combining key releases (e.g. SHIFT+A). -size_t Keyboard_::releaseKeycode(uint8_t k) -{ - if (!removeKeycodeFromReport(k)) { - return 0; - } - sendReport(&_keyReport); -} - -size_t Keyboard_::removeKeyFromReport(uint8_t k) -{ - 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 & SHIFT) { // it's a capital letter or other character reached with shift - _keyReport.modifiers &= ~(0x02); // the left shift modifier - k = k ^ SHIFT; - } - } - - return removeKeycodeFromReport(k); -} - -size_t Keyboard_::removeKeycodeFromReport(uint8_t k) -{ - uint8_t indexA; - uint8_t indexB; - uint8_t count; - - if ((k >= HID_KEYBOARD_LEFT_CONTROL) && (k <= HID_KEYBOARD_RIGHT_GUI)) { - // it's a modifier key - _keyReport.modifiers = _keyReport.modifiers & (~(0x01 << (k - HID_KEYBOARD_LEFT_CONTROL))); - } - else { - // it's some other key: - // 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 (indexA = 0; indexA < sizeof(_keyReport.keys); indexA++) { - if (_keyReport.keys[indexA] == k) { - _keyReport.keys[indexA] = 0; - } - } - - // finally rearrange the keys list so that the free (= 0x00) are at the - // end of the keys list - some implementations stop for keys at the - // first occurence of an 0x00 in the keys list - // so (0x00)(0x01)(0x00)(0x03)(0x02)(0x00) becomes - // (0x01)(0x03)(0x02)(0x00)(0x00)(0x00) - count = 0; // holds the number of zeros we've found - indexA = 0; - while ((indexA + count) < sizeof(_keyReport.keys)) { - if (0 == _keyReport.keys[indexA]) { - count++; // one more zero - for (indexB = indexA; indexB < sizeof(_keyReport.keys) - count; indexB++) { - _keyReport.keys[indexB] = _keyReport.keys[indexB + 1]; - } - _keyReport.keys[sizeof(_keyReport.keys) - count] = 0; - } - else { - indexA++; // one more non-zero - } - } - } - - return 1; -} - - -size_t Keyboard_::writeKeycode(uint8_t c) -{ - uint8_t p = pressKeycode(c); // Keydown - releaseKeycode(c); // Keyup - return (p); // just return the result of pressKeycode() since release() almost always returns 1 -} - -Keyboard_ Keyboard; - -#endif diff --git a/plugins/KeyboardioHID/src/ImprovedKeyboard.h b/plugins/KeyboardioHID/src/ImprovedKeyboard.h deleted file mode 100644 index 08b95c94f3..0000000000 --- a/plugins/KeyboardioHID/src/ImprovedKeyboard.h +++ /dev/null @@ -1,86 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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. -*/ - -#pragma once - -#include "HID.h" - -#if !defined(_USING_HID) - -#warning "Using legacy HID core (non pluggable)" - -#else - -//================================================================================ -//================================================================================ -// Keyboard - -#include "HID-Project.h" -#include "ImprovedKeylayouts.h" - -typedef union{ - // Low level key report: up to 6 keys and shift, ctrl etc at once - uint8_t whole8[]; - uint16_t whole16[]; - uint32_t whole32[]; - struct{ - uint8_t modifiers; - uint8_t reserved; - uint8_t keys[6]; - }; -} HID_KeyboardReport_Data_t; - -class Keyboard_ : public Print, private HIDDevice -{ -private: - HID_KeyboardReport_Data_t _keyReport; - void sendReport(HID_KeyboardReport_Data_t* keys); -#if defined(HID_KEYBOARD_LEDS_ENABLED) - virtual void setReportData(void* &data, int len); - uint8_t leds; -#endif -public: - Keyboard_(void); - void begin(void); - void end(void); - size_t write(uint8_t k); - size_t press(uint8_t k); - size_t release(uint8_t k); - void releaseAll(void); - void send_now(void); - - size_t writeKeycode(uint8_t k); - size_t pressKeycode(uint8_t k); - size_t releaseKeycode(uint8_t k); - size_t addKeyToReport(uint8_t k); - size_t addKeycodeToReport(uint8_t k); - size_t removeKeyFromReport(uint8_t k); - size_t removeKeycodeFromReport(uint8_t k); - -#if defined(HID_KEYBOARD_LEDS_ENABLED) - uint8_t getLeds(void); -#endif -}; -extern Keyboard_ Keyboard; - -#endif diff --git a/plugins/KeyboardioHID/src/ImprovedKeylayouts.h b/plugins/KeyboardioHID/src/ImprovedKeylayouts.h deleted file mode 100644 index b512e64627..0000000000 --- a/plugins/KeyboardioHID/src/ImprovedKeylayouts.h +++ /dev/null @@ -1,348 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 guard -#pragma once - -//================================================================================ -// Key definitions -//================================================================================ - -// Modifiers -#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 - -// Normal keys -#define KEY_UP_ARROW (RAW_KEYBOARD_UP_ARROW + 136) -#define KEY_DOWN_ARROW (RAW_KEYBOARD_DOWN_ARROW + 136) -#define KEY_LEFT_ARROW (RAW_KEYBOARD_LEFT_ARROW + 136) -#define KEY_RIGHT_ARROW (RAW_KEYBOARD_RIGHT_ARROW + 136) -#define KEY_BACKSPACE (RAW_KEYBOARD_BACKSPACE + 136) -#define KEY_TAB (RAW_KEYBOARD_TAB + 136) -#define KEY_RETURN (RAW_KEYBOARD_RETURN + 136) -#define KEY_ENTER KEY_RETURN -#define KEY_ESC (RAW_KEYBOARD_ESC + 136) -#define KEY_INSERT (RAW_KEYBOARD_INSERT + 136) -#define KEY_DELETE (RAW_KEYBOARD_DELETE + 136) -#define KEY_PAGE_UP (RAW_KEYBOARD_PAGE_UP + 136) -#define KEY_PAGE_DOWN (RAW_KEYBOARD_PAGE_DOWN + 136) -#define KEY_HOME (RAW_KEYBOARD_HOME + 136) -#define KEY_END (RAW_KEYBOARD_END + 136) -#define KEY_CAPS_LOCK (RAW_KEYBOARD_CAPS_LOCK + 136) -#define KEY_F1 (RAW_KEYBOARD_F1 + 136) -#define KEY_F2 (RAW_KEYBOARD_F2 + 136) -#define KEY_F3 (RAW_KEYBOARD_F3 + 136) -#define KEY_F4 (RAW_KEYBOARD_F4 + 136) -#define KEY_F5 (RAW_KEYBOARD_F5 + 136) -#define KEY_F6 (RAW_KEYBOARD_F6 + 136) -#define KEY_F7 (RAW_KEYBOARD_F7 + 136) -#define KEY_F8 (RAW_KEYBOARD_F8 + 136) -#define KEY_F9 (RAW_KEYBOARD_F9 + 136) -#define KEY_F10 (RAW_KEYBOARD_F10 + 136) -#define KEY_F11 (RAW_KEYBOARD_F11 + 136) -#define KEY_F12 (RAW_KEYBOARD_F12 + 136) - - -// New key definitions -#define KEY_PRINT (RAW_KEYBOARD_PRINT + 136) -#define KEY_NUM_LOCK (RAW_KEYBOARD_NUM_LOCK + 136) -#define KEY_SCROLL_LOCK (RAW_KEYBOARD_SCROLL_LOCK + 136) -#define KEY_PAUSE (RAW_KEYBOARD_PAUSE + 136) -#define KEY_MENU (RAW_KEYBOARD_MENU + 136) -#define KEY_SPACE ' ' -#define KEY_LEFT_WINDOWS KEY_LEFT_GUI -#define KEY_RIGHT_WINDOWS KEY_RIGHT_GUI -#define KEY_PRINTSCREEN KEY_PRINT - -// Keyboard Leds -#define LED_NUM_LOCK 0x01 -#define LED_CAPS_LOCK 0x02 -#define LED_SCROLL_LOCK 0x04 - -//================================================================================ -// LAYOUT_US_ENGLISH -//================================================================================ - -#if !defined(LAYOUT_US_ENGLISH) && !defined(LAYOUT_UNITED_KINGDOM) -#error This API does not support non english layouts. Please select an US or UK Keyboard. -#endif - -#define RAW_KEYBOARD_LEFT_CTRL (1 << 0) -#define RAW_KEYBOARD_LEFT_SHIFT (1 << 1) -#define RAW_KEYBOARD_LEFT_ALT (1 << 2) -#define RAW_KEYBOARD_LEFT_GUI (1 << 3) -#define RAW_KEYBOARD_RIGHT_CTRL (1 << 4) -#define RAW_KEYBOARD_RIGHT_SHIFT (1 << 5) -#define RAW_KEYBOARD_RIGHT_ALT (1 << 6) -#define RAW_KEYBOARD_RIGHT_GUI (1 << 7) - -#define RAW_KEYBOARD_KEY(key) ((key>='a' && key<='z') ? (0x04 + key-'a') :\ -(key>='A' && key<='Z') ? (0x04 + key-'A') : (key>='1' && key<='9') ? (0x1E + key-'1') : 0x27) - -#define RAW_KEYBOARD_A ( 4 ) -#define RAW_KEYBOARD_B ( 5 ) -#define RAW_KEYBOARD_C ( 6 ) -#define RAW_KEYBOARD_D ( 7 ) -#define RAW_KEYBOARD_E ( 8 ) -#define RAW_KEYBOARD_F ( 9 ) -#define RAW_KEYBOARD_G ( 10 ) -#define RAW_KEYBOARD_H ( 11 ) -#define RAW_KEYBOARD_I ( 12 ) -#define RAW_KEYBOARD_J ( 13 ) -#define RAW_KEYBOARD_K ( 14 ) -#define RAW_KEYBOARD_L ( 15 ) -#define RAW_KEYBOARD_M ( 16 ) -#define RAW_KEYBOARD_N ( 17 ) -#define RAW_KEYBOARD_O ( 18 ) -#define RAW_KEYBOARD_P ( 19 ) -#define RAW_KEYBOARD_Q ( 20 ) -#define RAW_KEYBOARD_R ( 21 ) -#define RAW_KEYBOARD_S ( 22 ) -#define RAW_KEYBOARD_T ( 23 ) -#define RAW_KEYBOARD_U ( 24 ) -#define RAW_KEYBOARD_V ( 25 ) -#define RAW_KEYBOARD_W ( 26 ) -#define RAW_KEYBOARD_X ( 27 ) -#define RAW_KEYBOARD_Y ( 28 ) -#define RAW_KEYBOARD_Z ( 29 ) -#define RAW_KEYBOARD_1 ( 30 ) -#define RAW_KEYBOARD_2 ( 31 ) -#define RAW_KEYBOARD_3 ( 32 ) -#define RAW_KEYBOARD_4 ( 33 ) -#define RAW_KEYBOARD_5 ( 34 ) -#define RAW_KEYBOARD_6 ( 35 ) -#define RAW_KEYBOARD_7 ( 36 ) -#define RAW_KEYBOARD_8 ( 37 ) -#define RAW_KEYBOARD_9 ( 38 ) -#define RAW_KEYBOARD_0 ( 39 ) -#define RAW_KEYBOARD_ENTER ( 40 ) -#define RAW_KEYBOARD_ESC ( 41 ) -#define RAW_KEYBOARD_BACKSPACE ( 42 ) -#define RAW_KEYBOARD_TAB ( 43 ) -#define RAW_KEYBOARD_SPACE ( 44 ) -#define RAW_KEYBOARD_MINUS ( 45 ) -#define RAW_KEYBOARD_EQUAL ( 46 ) -#define RAW_KEYBOARD_LEFT_BRACE ( 47 ) -#define RAW_KEYBOARD_RIGHT_BRACE ( 48 ) -#define RAW_KEYBOARD_BACKSLASH ( 49 ) -#define RAW_KEYBOARD_NON_US_NUM ( 50 ) -#define RAW_KEYBOARD_SEMICOLON ( 51 ) -#define RAW_KEYBOARD_QUOTE ( 52 ) -#define RAW_KEYBOARD_TILDE ( 53 ) -#define RAW_KEYBOARD_COMMA ( 54 ) -#define RAW_KEYBOARD_PERIOD ( 55 ) -#define RAW_KEYBOARD_SLASH ( 56 ) - -#define RAW_KEYBOARD_CAPS_LOCK 0x39 -#define RAW_KEYBOARD_F1 0x3A -#define RAW_KEYBOARD_F2 0x3B -#define RAW_KEYBOARD_F3 0x3C -#define RAW_KEYBOARD_F4 0x3D -#define RAW_KEYBOARD_F5 0x3E -#define RAW_KEYBOARD_F6 0x3F -#define RAW_KEYBOARD_F7 0x40 -#define RAW_KEYBOARD_F8 0x41 -#define RAW_KEYBOARD_F9 0x42 -#define RAW_KEYBOARD_F10 0x43 -#define RAW_KEYBOARD_F11 0x44 -#define RAW_KEYBOARD_F12 0x45 -#define RAW_KEYBOARD_PRINT 0x46 -#define RAW_KEYBOARD_SCROLL_LOCK 0x47 -#define RAW_KEYBOARD_PAUSE 0x48 -#define RAW_KEYBOARD_INSERT 0x49 -#define RAW_KEYBOARD_HOME 0x4A -#define RAW_KEYBOARD_PAGE_UP 0x4B -#define RAW_KEYBOARD_DELETE 0x4C -#define RAW_KEYBOARD_END 0x4D -#define RAW_KEYBOARD_PAGE_DOWN 0x4E -#define RAW_KEYBOARD_RIGHT_ARROW 0x4F -#define RAW_KEYBOARD_LEFT_ARROW 0x50 -#define RAW_KEYBOARD_DOWN_ARROW 0x51 -#define RAW_KEYBOARD_UP_ARROW 0x52 -#define RAW_KEYBOARD_NUM_LOCK 0x53 -#define RAW_KEYBOARD_NON_US 0x64 -#define RAW_KEYBOARD_MENU 0x65 - -#define SHIFT 0x80 -static const uint8_t _asciimap[128] PROGMEM = -{ - 0x00, // NUL - 0x00, // SOH - 0x00, // STX - 0x00, // ETX - 0x00, // EOT - 0x00, // ENQ - 0x00, // ACK - 0x00, // BEL - RAW_KEYBOARD_BACKSPACE, // BS Backspace - RAW_KEYBOARD_TAB, // TAB Tab - RAW_KEYBOARD_ENTER, // 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 - - RAW_KEYBOARD_SPACE, // ' ' - RAW_KEYBOARD_1|SHIFT, // ! -#ifdef LAYOUT_UNITED_KINGDOM - RAW_KEYBOARD_2|SHIFT, // " -#else - RAW_KEYBOARD_QUOTE|SHIFT, // " -#endif -#ifdef LAYOUT_UNITED_KINGDOM - RAW_KEYBOARD_BACKSLASH -#else - RAW_KEYBOARD_3|SHIFT, // # -#endif - RAW_KEYBOARD_4|SHIFT, // $ - RAW_KEYBOARD_5|SHIFT, // % - RAW_KEYBOARD_7|SHIFT, // & - RAW_KEYBOARD_QUOTE, // ' - RAW_KEYBOARD_9|SHIFT, // ( - RAW_KEYBOARD_0|SHIFT, // ) - RAW_KEYBOARD_8|SHIFT, // * - RAW_KEYBOARD_EQUAL|SHIFT, // + - RAW_KEYBOARD_COMMA, // , - RAW_KEYBOARD_MINUS, // - - RAW_KEYBOARD_PERIOD, // . - RAW_KEYBOARD_SLASH, // / - RAW_KEYBOARD_0, // 0 - RAW_KEYBOARD_1, // 1 - RAW_KEYBOARD_2, // 2 - RAW_KEYBOARD_3, // 3 - RAW_KEYBOARD_4, // 4 - RAW_KEYBOARD_5, // 5 - RAW_KEYBOARD_6, // 6 - RAW_KEYBOARD_7, // 7 - RAW_KEYBOARD_8, // 8 - RAW_KEYBOARD_9, // 9 - RAW_KEYBOARD_SEMICOLON|SHIFT, // : - RAW_KEYBOARD_SEMICOLON, // ; - RAW_KEYBOARD_COMMA|SHIFT, // < - RAW_KEYBOARD_EQUAL, // = - RAW_KEYBOARD_PERIOD|SHIFT, // > - RAW_KEYBOARD_SLASH|SHIFT, // ? -#ifdef LAYOUT_UNITED_KINGDOM - RAW_KEYBOARD_QUOTE|SHIFT, // @ -#else - RAW_KEYBOARD_2|SHIFT, // @ -#endif - RAW_KEYBOARD_A|SHIFT, // A - RAW_KEYBOARD_B|SHIFT, // B - RAW_KEYBOARD_C|SHIFT, // C - RAW_KEYBOARD_D|SHIFT, // D - RAW_KEYBOARD_E|SHIFT, // E - RAW_KEYBOARD_F|SHIFT, // F - RAW_KEYBOARD_G|SHIFT, // G - RAW_KEYBOARD_H|SHIFT, // H - RAW_KEYBOARD_I|SHIFT, // I - RAW_KEYBOARD_J|SHIFT, // J - RAW_KEYBOARD_K|SHIFT, // K - RAW_KEYBOARD_L|SHIFT, // L - RAW_KEYBOARD_M|SHIFT, // M - RAW_KEYBOARD_N|SHIFT, // N - RAW_KEYBOARD_O|SHIFT, // O - RAW_KEYBOARD_P|SHIFT, // P - RAW_KEYBOARD_Q|SHIFT, // Q - RAW_KEYBOARD_R|SHIFT, // R - RAW_KEYBOARD_S|SHIFT, // S - RAW_KEYBOARD_T|SHIFT, // T - RAW_KEYBOARD_U|SHIFT, // U - RAW_KEYBOARD_V|SHIFT, // V - RAW_KEYBOARD_W|SHIFT, // W - RAW_KEYBOARD_X|SHIFT, // X - RAW_KEYBOARD_Y|SHIFT, // Y - RAW_KEYBOARD_Z|SHIFT, // Z - RAW_KEYBOARD_LEFT_BRACE, // [ -#ifdef LAYOUT_UNITED_KINGDOM - RAW_KEYBOARD_NON_US, // bslash -#else - RAW_KEYBOARD_BACKSLASH, // bslash -#endif - RAW_KEYBOARD_RIGHT_BRACE, // ] - RAW_KEYBOARD_6|SHIFT, // ^ - RAW_KEYBOARD_MINUS|SHIFT, // _ - RAW_KEYBOARD_TILDE, // ` - RAW_KEYBOARD_A, // a - RAW_KEYBOARD_B, // b - RAW_KEYBOARD_C, // c - RAW_KEYBOARD_D, // d - RAW_KEYBOARD_E, // e - RAW_KEYBOARD_F, // f - RAW_KEYBOARD_G, // g - RAW_KEYBOARD_H, // h - RAW_KEYBOARD_I, // i - RAW_KEYBOARD_J, // j - RAW_KEYBOARD_K, // k - RAW_KEYBOARD_L, // l - RAW_KEYBOARD_M, // m - RAW_KEYBOARD_N, // n - RAW_KEYBOARD_O, // o - RAW_KEYBOARD_P, // p - RAW_KEYBOARD_Q, // q - RAW_KEYBOARD_R, // r - RAW_KEYBOARD_S, // s - RAW_KEYBOARD_T, // t - RAW_KEYBOARD_U, // u - RAW_KEYBOARD_V, // v - RAW_KEYBOARD_W, // w - RAW_KEYBOARD_X, // x - RAW_KEYBOARD_Y, // y - RAW_KEYBOARD_Z, // z - RAW_KEYBOARD_LEFT_BRACE|SHIFT, // { -#ifdef LAYOUT_UNITED_KINGDOM - RAW_KEYBOARD_NON_US|SHIFT, // | -#else - RAW_KEYBOARD_BACKSLASH|SHIFT, // | -#endif - RAW_KEYBOARD_RIGHT_BRACE|SHIFT, // } -#ifdef LAYOUT_UNITED_KINGDOM - RAW_KEYBOARD_BACKSLASH|SHIFT, // ~ -#else - RAW_KEYBOARD_TILDE|SHIFT, // ~ -#endif - 0x00 // DEL -}; diff --git a/plugins/KeyboardioHID/src/ImprovedMouse.cpp b/plugins/KeyboardioHID/src/ImprovedMouse.cpp deleted file mode 100644 index 46740bbc21..0000000000 --- a/plugins/KeyboardioHID/src/ImprovedMouse.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/* - Mouse.cpp - - Copyright (c) 2015, Arduino LLC - Original code (pre-library): Copyright (c) 2011, Peter Barrett - - 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 "ImprovedMouse.h" - -#if defined(_USING_HID) - -static const uint8_t _hidReportDescriptor[] PROGMEM = { - /* Mouse relative */ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 54 */ - 0x09, 0x02, /* USAGE (Mouse) */ - 0xa1, 0x01, /* COLLECTION (Application) */ - 0x85, HID_REPORTID_MOUSE, /* REPORT_ID */ - - /* 8 Buttons */ - 0x05, 0x09, /* USAGE_PAGE (Button) */ - 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ - 0x29, 0x08, /* USAGE_MAXIMUM (Button 8) */ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ - 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ - 0x95, 0x08, /* REPORT_COUNT (8) */ - 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - - /* X, Y, Wheel */ - 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) */ - - /* End */ - 0xc0 /* END_COLLECTION */ -}; - -//================================================================================ -//================================================================================ -// Mouse - -Mouse_::Mouse_(void) : _buttons(0), -HIDDevice((uint8_t*)_hidReportDescriptor, sizeof(_hidReportDescriptor), HID_REPORTID_MOUSE) -{ - // HID Descriptor is appended via the inherited HIDDevice class -} - -void Mouse_::begin(void) -{ - end(); -} - -void Mouse_::end(void) -{ - _buttons = 0; - move(0, 0, 0); -} - -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) -{ - HID_MouseReport_Data_t report; - report.buttons = _buttons; - report.xAxis = x; - report.yAxis = y; - report.wheel = wheel; -#if defined(USE_BOOT_MOUSE_PROTOCOL) - if(getProtocol() != 1){ - // Do not send the wheel information. - // It should be discarded by the host, - // but to be sure we better leave it out. - SendRawReport(&report, sizeof(report)-1); - } - else -#endif - SendReport(&report, sizeof(report)); -} - -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; -} - -Mouse_ Mouse; - -#endif diff --git a/plugins/KeyboardioHID/src/ImprovedMouse.h b/plugins/KeyboardioHID/src/ImprovedMouse.h deleted file mode 100644 index 0265208b84..0000000000 --- a/plugins/KeyboardioHID/src/ImprovedMouse.h +++ /dev/null @@ -1,79 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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. -*/ - -#pragma once - -#include "HID.h" - -#if !defined(_USING_HID) - -#warning "Using legacy HID core (non pluggable)" - -#else - -//================================================================================ -//================================================================================ -// Mouse - -#include "HID-Project.h" - -#define MOUSE_LEFT (1 << 0) -#define MOUSE_RIGHT (1 << 1) -#define MOUSE_MIDDLE (1 << 2) -#define MOUSE_PREV (1 << 3) -#define MOUSE_NEXT (1 << 4) -// actually this mouse report has 8 buttons (for smaller descriptor) -// but the last 3 wont do anything from what I tested -#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE | MOUSE_PREV | MOUSE_NEXT) - -typedef union{ - // mouse report: 8 buttons, position, wheel - uint8_t whole8[]; - uint16_t whole16[]; - uint32_t whole32[]; - struct{ - uint8_t buttons; - int8_t xAxis; - int8_t yAxis; - int8_t wheel; - }; -} HID_MouseReport_Data_t; - -class Mouse_ : private HIDDevice -{ -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; - -#endif diff --git a/plugins/KeyboardioHID/src/NKROKeyboard.cpp b/plugins/KeyboardioHID/src/NKROKeyboard.cpp deleted file mode 100644 index fb2b6a6ee1..0000000000 --- a/plugins/KeyboardioHID/src/NKROKeyboard.cpp +++ /dev/null @@ -1,309 +0,0 @@ -/* -Copyright (c) 2015 NicoHood -See the readme for credit to other people. - -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 "NKROKeyboard.h" - -#if defined(_USING_HID) - -//================================================================================ -//================================================================================ -// NKROKeyboard - -static const u8 _hidReportDescriptor[] PROGMEM = { - // NKRO Keyboard - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 47 */ - 0x09, 0x06, /* USAGE (Keyboard) */ - 0xa1, 0x01, /* COLLECTION (Application) */ - 0x85, HID_REPORTID_NKRO_KEYBOARD, /* REPORT_ID */ - 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ - - /* Keyboard Modifiers (shift, alt, ...) */ - 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) */ - -#if defined(HID_KEYBOARD_LEDS_ENABLED) - /* 5 LEDs for num lock etc, 3 left for advanced, custom usage */ - 0x05, 0x08, /* USAGE_PAGE (LEDs) */ - 0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */ - 0x29, 0x05, /* USAGE_MAXIMUM (Kana) */ - 0x95, 0x08, /* REPORT_COUNT (8) */ - 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */ - /* Reserved 3 bits */ - //0x95, 0x01, /* REPORT_COUNT (1) */ - //0x75, 0x03, /* REPORT_SIZE (3) */ - //0x91, 0x03, /* OUTPUT (Cnst,Var,Abs) */ -#endif - - /* 104 Keys as bitmap */ - 0x05, 0x07, /* Usage Page (Key Codes) */ - 0x19, 0x00, /* Usage Minimum (0) */ - 0x29, NKRO_KEY_COUNT - 1, /* Usage Maximum (103) */ - 0x15, 0x00, /* Logical Minimum (0) */ - 0x25, 0x01, /* Logical Maximum (1) */ - 0x75, 0x01, /* Report Size (1) */ - 0x95, NKRO_KEY_COUNT, /* Report Count (104) */ - 0x81, 0x02, /* Input (Data, Variable, Absolute) */ - - /* 1 Custom Keyboard key */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0x75, 0x08, /* REPORT_SIZE (8) */ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ - 0x26, 0xE7, 0x00, /* LOGICAL_MAXIMUM (231) */ - /*0x05, 0x07, USAGE_PAGE (Keyboard) */ - 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ - 0x29, 0xE7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ - 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ - - /* End */ - 0xC0 /* End Collection */ -}; - -NKROKeyboard_::NKROKeyboard_(void) : -HIDDevice((uint8_t*)_hidReportDescriptor, sizeof(_hidReportDescriptor), HID_REPORTID_NKRO_KEYBOARD) -#if defined(HID_KEYBOARD_LEDS_ENABLED) -,leds(0) -#endif -{ - // HID Descriptor is appended via the inherited HIDDevice class -} - -void NKROKeyboard_::begin(void) -{ - releaseAll(); -} - -void NKROKeyboard_::end(void) -{ - releaseAll(); -} - -void NKROKeyboard_::sendReport(HID_NKROKeyboardReport_Data_t* keys) -{ - // Call the inherited function. - // This wrapper still saves us some bytes -#if defined(USE_BOOT_KEYBOARD_PROTOCOL) - if(getProtocol() != 1){ - SendRawReport(keys, sizeof(HID_NKROKeyboardReport_Data_t)); - } - else -#endif - SendReport(keys, sizeof(HID_NKROKeyboardReport_Data_t)); -} - -void NKROKeyboard_::send_now(void){ - sendReport(&_keyReport); -} - -#if defined(HID_KEYBOARD_LEDS_ENABLED) -void NKROKeyboard_::setReportData(void* &data, int len){ - // Save led state - if(len == 2) - leds = *(uint8_t*)(data+1); -} - -uint8_t NKROKeyboard_::getLeds(void){ - return leds; -} -#endif - -// 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 NKROKeyboard_::press(uint8_t k) -{ - size_t ret = addKeyToReport(k); - if(ret){ - sendReport(&_keyReport); - } - return ret; -} - -// 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 NKROKeyboard_::release(uint8_t k) -{ - // it's a non-printing key (not a modifier) - if (k >= 136) - k = k - 136; - - // it's a modifier key - else if (k >= 128) - k = k - 128; - - // it's a printing key - else { - k = pgm_read_byte(_asciimap + k); - if (!k) - return 0; - - // it's a capital letter or other character reached with shift - if (k & SHIFT) { - // the left shift modifier - _keyReport.modifiers &= ~(0x02); - k = k ^ SHIFT; - } - } - - removeKeycodeFromReport(k); - sendReport(&_keyReport); - - return 1; -} - -void NKROKeyboard_::releaseAll(void) -{ - // release all keys - memset(&_keyReport, 0x00, sizeof(_keyReport)); - sendReport(&_keyReport); -} - -size_t NKROKeyboard_::write(uint8_t c) -{ - uint8_t p = press(c); // Keydown - release(c); // Keyup - return p; // just return the result of press() since release() almost always returns 1 -} - - -// pressKeycode() 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 releaseKeycode(), releaseAll(), or otherwise clear the report and resend. -size_t NKROKeyboard_::pressKeycode(uint8_t k) -{ - if (!addKeycodeToReport(k)) { - return 0; - } - sendReport(&_keyReport); -} - -size_t NKROKeyboard_::addKeyToReport(uint8_t k) -{ - 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 & SHIFT) { // it's a capital letter or other character reached with shift - _keyReport.modifiers |= 0x02; // the left shift modifier - k = k ^ SHIFT; - } - } - - return addKeycodeToReport(k); -} - -size_t NKROKeyboard_::addKeycodeToReport(uint8_t k) -{ - // keymap key - if (k < NKRO_KEY_COUNT) - _keyReport.keys[k / 8] |= 1 << (k % 8); - - // it's a modifier key - else if ((k >= HID_KEYBOARD_LEFT_CONTROL) && (k <= HID_KEYBOARD_RIGHT_GUI)) - _keyReport.modifiers |= (0x01 << (k - HID_KEYBOARD_LEFT_CONTROL)); - - // custom key - else - _keyReport.key = k; - - return 1; -} - - -// releaseKeycode() 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. -// When send is set to FALSE (= 0) no sendReport() is executed. This comes in -// handy when combining key releases (e.g. SHIFT+A). -size_t NKROKeyboard_::releaseKeycode(uint8_t k) -{ - if (!removeKeycodeFromReport(k)) { - return 0; - } - sendReport(&_keyReport); -} - -size_t NKROKeyboard_::removeKeyFromReport(uint8_t k) -{ - 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 & SHIFT) { // it's a capital letter or other character reached with shift - _keyReport.modifiers &= ~(0x02); // the left shift modifier - k = k ^ SHIFT; - } - } - - return removeKeycodeFromReport(k); -} - -size_t NKROKeyboard_::removeKeycodeFromReport(uint8_t k) -{ - // keymap key - if (k < NKRO_KEY_COUNT) - _keyReport.keys[k / 8] &= ~(1 << (k % 8)); - - // it's a modifier key - else if ((k >= HID_KEYBOARD_LEFT_CONTROL) && (k <= HID_KEYBOARD_RIGHT_GUI)) - _keyReport.modifiers &= ~(0x01 << (k - HID_KEYBOARD_LEFT_CONTROL)); - - // custom key - else - _keyReport.key = 0x00; - - return 1; -} - - -size_t NKROKeyboard_::writeKeycode(uint8_t c) -{ - uint8_t p = pressKeycode(c); // Keydown - releaseKeycode(c); // Keyup - return (p); // just return the result of pressKeycode() since release() almost always returns 1 -} - -NKROKeyboard_ NKROKeyboard; - -#endif diff --git a/plugins/KeyboardioHID/src/NKROKeyboard.h b/plugins/KeyboardioHID/src/NKROKeyboard.h deleted file mode 100644 index a8cee0d91e..0000000000 --- a/plugins/KeyboardioHID/src/NKROKeyboard.h +++ /dev/null @@ -1,86 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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. -*/ - -#pragma once - -#include "HID.h" - -#if !defined(_USING_HID) - -#warning "Using legacy HID core (non pluggable)" - -#else - -#include "HID-Project.h" -#include "ImprovedKeylayouts.h" - -// Max value for USB EP_SIZE 16 -// +1 reportID, +1 modifier, +1 custom key -#define NKRO_KEY_COUNT (8*13) - -typedef union{ - // modifier + keymap + 1 custom key - uint8_t whole8[]; - uint16_t whole16[]; - uint32_t whole32[]; - struct{ - uint8_t modifiers; - uint8_t keys[NKRO_KEY_COUNT / 8]; - uint8_t key; - }; -} HID_NKROKeyboardReport_Data_t; - -class NKROKeyboard_ : public Print, private HIDDevice -{ -protected: - HID_NKROKeyboardReport_Data_t _keyReport; - void sendReport(HID_NKROKeyboardReport_Data_t* keys); -#if defined(HID_KEYBOARD_LEDS_ENABLED) - virtual void setReportData(void* &data, int len); - uint8_t leds; -#endif -public: - NKROKeyboard_(void); - void begin(void); - void end(void); - size_t write(uint8_t k); - size_t press(uint8_t k); - size_t release(uint8_t k); - void releaseAll(void); - void send_now(void); - - size_t writeKeycode(uint8_t k); - size_t pressKeycode(uint8_t k); - size_t releaseKeycode(uint8_t k); - size_t addKeyToReport(uint8_t k); - size_t addKeycodeToReport(uint8_t k); - size_t removeKeyFromReport(uint8_t k); - size_t removeKeycodeFromReport(uint8_t k); - -#if defined(HID_KEYBOARD_LEDS_ENABLED) - uint8_t getLeds(void); -#endif -}; -extern NKROKeyboard_ NKROKeyboard; - -#endif diff --git a/plugins/KeyboardioHID/src/PluggableHID/HID.cpp b/plugins/KeyboardioHID/src/PluggableHID/HID.cpp deleted file mode 100644 index ed4138928f..0000000000 --- a/plugins/KeyboardioHID/src/PluggableHID/HID.cpp +++ /dev/null @@ -1,235 +0,0 @@ -/* Copyright (c) 2015, Arduino LLC -** -** Original code (pre-library): 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 "PluggableUSB.h" -#include "HID.h" -#include "HIDDevice.h" -#include "HID-Project.h" // Only used for the BootKeyboard setting - -#if defined(USBCON) - -HID_ HID; - -//================================================================================ -//================================================================================ -// HID Interface - -// Static variables -uint8_t HID_::HID_ENDPOINT_INT; -uint8_t HID_::HID_INTERFACE; -HIDDescriptor HID_::_hidInterface; -HIDDevice* HID_::rootDevice = NULL; -uint16_t HID_::sizeof_hidReportDescriptor = 0; -uint8_t HID_::modules_count = 0; -uint8_t HID_::_hid_protocol = 1; -uint8_t HID_::_hid_idle = 1; - -//================================================================================ -//================================================================================ -// Driver - -int HID_::HID_GetInterface(u8* interfaceNum) -{ - interfaceNum[0] += 1; // uses 1 - _hidInterface.hid = -#if defined(USE_BOOT_KEYBOARD_PROTOCOL) - D_INTERFACE(HID_INTERFACE,1,3,1,1); -#elif defined(USE_BOOT_MOUSE_PROTOCOL) - D_INTERFACE(HID_INTERFACE,1,3,1,2); -#else - D_INTERFACE(HID_INTERFACE,1,3,0,0); -#endif - _hidInterface.desc = D_HIDREPORT(sizeof_hidReportDescriptor); - _hidInterface.in = D_ENDPOINT(USB_ENDPOINT_IN (HID_ENDPOINT_INT),USB_ENDPOINT_TYPE_INTERRUPT,USB_EP_SIZE,0x01); - return USB_SendControl(0,&_hidInterface,sizeof(_hidInterface)); -} - -void HID_::SetInterface(InterfaceDescriptor interface) -{ - // Change the HID Interface (required for BOOT protocol) - _hidInterface.hid = interface; -} - -int HID_::HID_GetDescriptor(int8_t t) -{ - if (HID_REPORT_DESCRIPTOR_TYPE == t) { - HIDDevice* current = rootDevice; - int total = 0; - while(current != NULL) { - total += USB_SendControl(TRANSFER_PGM,current->descriptorData,current->descriptorLength); - current = current->next; - } - return total; - } else { - return 0; - } -} - -void HID_::AppendDescriptor(HIDDevice *device) -{ - if (modules_count == 0) { - rootDevice = device; - } else { - HIDDevice *current = rootDevice; - while(current->next != NULL) { - current = current->next; - } - current->next = device; - } - modules_count++; - sizeof_hidReportDescriptor += (uint16_t)device->descriptorLength; -} - -void HID_::SendReport(u8 id, const void* data, int len) -{ - // Only send report ID if it exists - if(id){ -#if defined(USE_BOOT_KEYBOARD_PROTOCOL) || defined(USE_BOOT_MOUSE_PROTOCOL) - // Do not send a normal report while in Bootloader mode. - if(_hid_protocol != 1){ - return; - } -#endif - USB_Send(HID_TX, &id, 1); - } - // Non reportID reports (rawHID) will still try to send data. - // If this happens at PC boot this can cause wrong keypresses. - // Normally any data > 8 byte should be ignored due to the USB specs. - // To avoid this, use the getProtocol() function of the HIDDevice - // inside the rawHID etc or disable the boot protocol. - USB_Send(HID_TX | TRANSFER_RELEASE,data,len); -} - -bool HID_::HID_Setup(USBSetup& setup, u8 i) -{ - if (HID_INTERFACE != i) { - return false; - } else { - 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; - } - - if (HID_SET_REPORT == r) - { - // Get reportID and search for the suited HIDDevice - uint8_t ID = setup.wValueL; - HIDDevice *current = rootDevice; - - while(current != NULL) - { - // Search HIDDevice for report ID - if(current->reportID == ID) - { - // Get the data length information and the corresponding bytes - int length = ((setup.wValueH << 8) | setup.wLength); - - // Ensure that there IS some data - if(length > 0) - { - void* data = malloc(length); - if(data){ - auto recvLength = length; - //TODO loop can be improved maybe? Or does the compiler do this already? - while(recvLength > USB_EP_SIZE){ - USB_RecvControl(data + (length - recvLength), USB_EP_SIZE); - recvLength -= USB_EP_SIZE; - } - USB_RecvControl(data + (length - recvLength), recvLength); - - // Data may contain the report ID again (Keyboard), maybe not (RawHID) - current->setReportData(data, length); - } - - // Release data if the pointer still exists - free(data); - } - - // Dont search any further - break; - } - current = current->next; - } - } - } - return false; - } -} - -HID_::HID_(void) -{ - static uint8_t endpointType[1]; - - endpointType[0] = EP_TYPE_INTERRUPT_IN; - - static PUSBCallbacks cb = { - .setup = HID_Setup, - .getInterface = &HID_GetInterface, - .getDescriptor = &HID_GetDescriptor, - .numEndpoints = 1, - .numInterfaces = 1, - .endpointType = endpointType, - }; - - static PUSBListNode node(&cb); - - HID_ENDPOINT_INT = PUSB_AddFunction(&node, &HID_INTERFACE); -} - -HID_::operator bool() { - if(USBDevice.configured()){ - delay(10); - return true; - } - else{ - return false; - } -} - -int HID_::begin(void) -{ - return 0; -} - -#endif /* if defined(USBCON) */ - diff --git a/plugins/KeyboardioHID/src/PluggableHID/HID.h b/plugins/KeyboardioHID/src/PluggableHID/HID.h deleted file mode 100644 index 1bde479a1b..0000000000 --- a/plugins/KeyboardioHID/src/PluggableHID/HID.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - HID.h - - Copyright (c) 2015, Arduino LLC - Original code (pre-library): Copyright (c) 2011, Peter Barrett - - 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 -*/ - -#pragma once - -#define HID_h - -#include - -#if defined(USBCON) - -#define _USING_HID - -//================================================================================ -//================================================================================ -// HID 'Driver' - -#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 - -#define HID_HID_DESCRIPTOR_TYPE 0x21 -#define HID_REPORT_DESCRIPTOR_TYPE 0x22 -#define HID_PHYSICAL_DESCRIPTOR_TYPE 0x23 - -class HIDDevice; - -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; - -class HID_ -{ -public: - HID_(void); - operator bool(); - - // Only access this class via the HIDDevice -private: - friend HIDDevice; - int begin(void); - void SendReport(uint8_t id, const void* data, int len); - void AppendDescriptor(HIDDevice* device); - void SetInterface(InterfaceDescriptor interface); - - // Static functions - static int HID_GetInterface(u8* interfaceNum); - static int HID_GetDescriptor(int8_t t); - static bool HID_Setup(USBSetup& setup, u8 i); - - // Static variables - static uint8_t HID_ENDPOINT_INT; - static uint8_t HID_INTERFACE; - static HIDDescriptor _hidInterface; - static HIDDevice* rootDevice; - static uint16_t sizeof_hidReportDescriptor; - static uint8_t modules_count; - static uint8_t _hid_protocol; - static uint8_t _hid_idle; -}; - -#define HID_TX HID_ENDPOINT_INT - -#define D_HIDREPORT(_descriptorLength) \ - { 9, 0x21, 0x1, 0x1, 0, 1, 0x22, _descriptorLength & 0xFF, _descriptorLength >> 8 } - -#define WEAK __attribute__ ((weak)) - -#endif diff --git a/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.cpp b/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.cpp deleted file mode 100644 index 96f7f566d2..0000000000 --- a/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.cpp +++ /dev/null @@ -1,31 +0,0 @@ - -#include "PluggableUSB.h" -#include "HIDDevice.h" -#include "HID.h" -#include "HID-Project.h" - -#if defined(USBCON) - -HIDDevice::HIDDevice(uint8_t* data, uint16_t length, uint8_t ID) : -descriptorData(data), descriptorLength(length), reportID(ID) -{ - HID.AppendDescriptor(this); -} - -void HIDDevice::SendReport(const void* data, int len){ - HID.SendReport(reportID, data, len); -} - -void HIDDevice::SendRawReport(const void* data, int len){ - HID.SendReport(HID_REPORTID_NONE, data, len); -} - -void HIDDevice::setReportData(void* &data, int len){ - // Discard this information if its not implemented by the HIDDevice -} - -uint8_t HIDDevice::getProtocol(void){ - return HID._hid_protocol; -} - -#endif diff --git a/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.h b/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.h deleted file mode 100644 index 8ae0d66c67..0000000000 --- a/plugins/KeyboardioHID/src/PluggableHID/HIDDevice.h +++ /dev/null @@ -1,63 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 guard -#pragma once - -#define HID_h - -#include -#include - -//http://stackoverflow.com/questions/1837165/can-two-classes-see-each-other-using-c - -class HID_; -extern HID_ HID; - -class HIDDevice -{ -public: - HIDDevice(uint8_t* data, uint16_t length, uint8_t ID); - - // Needs to be public for static HID_ function access - // Inherit this device private and everything should be fine -//private: - HIDDevice* next = NULL; - - // HID Descriptor - const uint8_t* descriptorData; - const uint16_t descriptorLength; - const uint8_t reportID; - - virtual void setReportData(void* &data, int len); - -protected: - // Could be used and inherited public for custom, professional usage, like raw Keyboard - // As an alternative you may still call the HID singleton. - void SendReport(const void* data, int len); - void SendRawReport(const void* data, int len); - uint8_t getProtocol(void); -}; - - - diff --git a/plugins/KeyboardioHID/src/RawHID.cpp b/plugins/KeyboardioHID/src/RawHID.cpp deleted file mode 100644 index 3358c2f483..0000000000 --- a/plugins/KeyboardioHID/src/RawHID.cpp +++ /dev/null @@ -1,30 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 "RawHID.h" - -//================================================================================ -// RawHID -//================================================================================ - -RawHID_ RawHID; diff --git a/plugins/KeyboardioHID/src/RawHID.h b/plugins/KeyboardioHID/src/RawHID.h deleted file mode 100644 index 104c7ce2ab..0000000000 --- a/plugins/KeyboardioHID/src/RawHID.h +++ /dev/null @@ -1,204 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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. -*/ - -#pragma once - -#include "HID.h" - -#if !defined(_USING_HID) - -#warning "Using legacy HID core (non pluggable)" - -#else - -#include "HID-Project.h" - -//================================================================================ -// RawHID -//================================================================================ - -// RawHID might never work with multireports, because of OS problems -// therefore we have to make it a single report with no idea. No other HID device will be supported then. -#undef RAWHID_USAGE_PAGE -#define RAWHID_USAGE_PAGE 0xFFC0 // recommended: 0xFF00 to 0xFFFF - -#undef RAWHID_USAGE -#define RAWHID_USAGE 0x0C00 // recommended: 0x0100 to 0xFFFF - -// Keep one byte offset for the reportID if used -#if (HID_REPORTID_RAWHID) -#define RAWHID_SIZE (USB_EP_SIZE-1) -#else -#define RAWHID_SIZE (USB_EP_SIZE) -#endif - -#undef RAWHID_TX_SIZE -#define RAWHID_TX_SIZE RAWHID_SIZE - -#undef RAWHID_RX_SIZE -#define RAWHID_RX_SIZE RAWHID_SIZE - -#define LSB(_x) ((_x) & 0xFF) -#define MSB(_x) ((_x) >> 8) - -static const uint8_t _rawhidReportDescriptor[] PROGMEM = { - /* RAW HID */ - 0x06, LSB(RAWHID_USAGE_PAGE), MSB(RAWHID_USAGE_PAGE), /* 30 */ - 0x0A, LSB(RAWHID_USAGE), MSB(RAWHID_USAGE), - - 0xA1, 0x01, /* Collection 0x01 */ -#if (HID_REPORTID_RAWHID) - 0x85, HID_REPORTID_RAWHID, /* REPORT_ID */ -#endif - 0x75, 0x08, /* report size = 8 bits */ - 0x15, 0x00, /* logical minimum = 0 */ - 0x26, 0xFF, 0x00, /* logical maximum = 255 */ - - 0x95, RAWHID_TX_SIZE, /* report count TX */ - 0x09, 0x01, /* usage */ - 0x81, 0x02, /* Input (array) */ - - 0x95, RAWHID_RX_SIZE, /* report count RX */ - 0x09, 0x02, /* usage */ - 0x91, 0x02, /* Output (array) */ - 0xC0 /* end collection */ -}; - -typedef union{ - // a RAWHID_TX_SIZE byte buffer for tx - uint8_t whole8[]; - uint16_t whole16[]; - uint32_t whole32[]; - uint8_t buff[RAWHID_TX_SIZE]; -} HID_RawKeyboardTXReport_Data_t; - -typedef union{ - // a RAWHID_TX_SIZE byte buffer for rx - uint8_t whole8[]; - uint16_t whole16[]; - uint32_t whole32[]; - uint8_t buff[RAWHID_RX_SIZE]; -} HID_RawKeyboardRXReport_Data_t; - -class RawHID_ : public Stream, private HIDDevice -{ -public: - RawHID_(void) : - HIDDevice((uint8_t*)_rawhidReportDescriptor, sizeof(_rawhidReportDescriptor), HID_REPORTID_RAWHID), - dataLength(0) - { - // HID Descriptor is appended via the inherited HIDDevice class - } - - void begin(void){ - // empty - } - - void end(void){ - // empty - } - - virtual int available(void){ - return dataLength; - } - - virtual int read(){ - if(dataLength){ - // Get next data byte - uint8_t data = *(dataTail - dataLength); - dataLength--; - - // Release buffer if its read fully - if(!dataLength){ - free(dataHead); - } - - return data; - } - return -1; - } - - virtual int peek(){ - if(dataLength){ - return *(dataTail - dataLength); - } - return -1; - } - - virtual void flush(void){ - // Delete all incoming bytes - if(dataLength){ - free(dataHead); - dataLength = 0; - } - } - - using Print::write; - virtual size_t write(uint8_t b){ - return write(&b, 1); - } - - virtual size_t write(const uint8_t *buffer, size_t size){ - // TODO this only sends the report ID in the first packat - // TODO this will split the data into USB_EP_SIZE packets - SendReport(buffer, size); - return size; - - size_t bytesleft = size; - // First work through the buffer thats already there - while (bytesleft >= RAWHID_TX_SIZE){ - SendReport(&buffer[size - bytesleft], RAWHID_TX_SIZE); - bytesleft -= RAWHID_TX_SIZE; - } - - // Write down the leftover bytes and fill with zeros - if (bytesleft){ - SendReport(&buffer[size - bytesleft], bytesleft); - } - - return size; - } - -private: - virtual void setReportData(void* &data, int len){ - // Only overwrite the buffer if its empty. - // This avoids corrupted data while reading. - if(!dataLength){ - // Save new data - dataLength = len; - dataHead = (uint8_t*) data; - dataTail = (uint8_t*)(data) + len; - - // Clear the passed in pointer to not free the data - data = NULL; - } - } - - // Buffer pointers to hold the received data - int dataLength; - uint8_t* dataHead; - uint8_t* dataTail; -}; -extern RawHID_ RawHID; - -#endif diff --git a/plugins/KeyboardioHID/src/System.cpp b/plugins/KeyboardioHID/src/System.cpp deleted file mode 100644 index f4cd4e9e90..0000000000 --- a/plugins/KeyboardioHID/src/System.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 "System.h" - -//================================================================================ -// System -//================================================================================ - -#if defined(_USING_HID) - -System_ System; - -void System_::press(uint8_t s){ -#ifdef USBCON - if (s == SYSTEM_WAKE_UP) - USBDevice.wakeupHost(); - else -#endif - SendReport(&s, sizeof(s)); -} - -#endif diff --git a/plugins/KeyboardioHID/src/System.h b/plugins/KeyboardioHID/src/System.h deleted file mode 100644 index 816403cd57..0000000000 --- a/plugins/KeyboardioHID/src/System.h +++ /dev/null @@ -1,103 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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. -*/ - -#pragma once - -#include "HID.h" - -#if !defined(_USING_HID) - -#error "This is not an USB AVR or you use an old version of the IDE." - -#else - -//================================================================================ -// System -//================================================================================ - -#include "HID-Project.h" - -#define SYSTEM_POWER_DOWN 0x81 -#define SYSTEM_SLEEP 0x82 -#define SYSTEM_WAKE_UP 0x83 - -static const uint8_t _systemReportDescriptor[] PROGMEM = { - //TODO limit to system keys only? - /* System Control (Power Down, Sleep, Wakeup, ...) */ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ - 0x09, 0x80, /* USAGE (System Control) */ - 0xa1, 0x01, /* COLLECTION (Application) */ - 0x85, HID_REPORTID_SYSTEMCONTROL, /* REPORT_ID */ - /* 1 system key */ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ - 0x26, 0xff, 0x00, /* LOGICAL_MAXIMUM (255) */ - 0x19, 0x00, /* USAGE_MINIMUM (Undefined) */ - 0x29, 0xff, /* USAGE_MAXIMUM (System Menu Down) */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0x75, 0x08, /* REPORT_SIZE (8) */ - 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ - 0xc0 /* END_COLLECTION */ -}; - -typedef union{ - // every usable system control key possible - uint8_t whole8[]; - uint8_t key; -} HID_SystemControlReport_Data_t; - -class System_ : private HIDDevice{ -public: - inline System_(void) : - HIDDevice((uint8_t*)_systemReportDescriptor, sizeof(_systemReportDescriptor), HID_REPORTID_SYSTEMCONTROL) - { - // HID Descriptor is appended via the inherited HIDDevice class - } - - inline void begin(void){ - // release all buttons - end(); - } - - inline void end(void){ - uint8_t _report = 0; - SendReport(&_report, sizeof(_report)); - } - - inline void write(uint8_t s){ - press(s); - release(); - } - - void press(uint8_t s); - - inline void release(void){ - begin(); - } - - inline void releaseAll(void){ - begin(); - } -}; -extern System_ System; - -#endif diff --git a/plugins/KeyboardioHID/src/TeensyKeyboard.cpp b/plugins/KeyboardioHID/src/TeensyKeyboard.cpp deleted file mode 100644 index a2c45f0c6d..0000000000 --- a/plugins/KeyboardioHID/src/TeensyKeyboard.cpp +++ /dev/null @@ -1,467 +0,0 @@ -/* USB API for Teensy USB Development Board - * http://www.pjrc.com/teensy/teensyduino.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 "TeensyKeyboard.h" - -usb_keyboard_class::usb_keyboard_class(void) : -HIDDevice((uint8_t*)teensykeyboard_hid_report_desc, sizeof(teensykeyboard_hid_report_desc), HID_REPORTID_TEENSY_KEYBOARD) -{ - // HID Descriptor is appended via the inherited HIDDevice class -} - -#if defined(HID_KEYBOARD_LEDS_ENABLED) -void usb_keyboard_class::setReportData(void* &data, int len){ - // Save led state - if(len == 2) - leds = *(uint8_t*)(data+1); -} - -uint8_t usb_keyboard_class::getLeds(void){ - return leds; -} -#endif - -// Step #1, decode UTF8 to Unicode code points -// -size_t usb_keyboard_class::write(uint8_t c) -{ - if (c < 0x80) { - // single byte encoded, 0x00 to 0x7F - utf8_state = 0; - write_unicode(c); - } else if (c < 0xC0) { - // 2nd, 3rd or 4th byte, 0x80 to 0xBF - c &= 0x3F; - if (utf8_state == 1) { - utf8_state = 0; - write_unicode(unicode_wchar | c); - } else if (utf8_state == 2) { - unicode_wchar |= ((uint16_t)c << 6); - utf8_state = 1; - } - } else if (c < 0xE0) { - // begin 2 byte sequence, 0xC2 to 0xDF - // or illegal 2 byte sequence, 0xC0 to 0xC1 - unicode_wchar = (uint16_t)(c & 0x1F) << 6; - utf8_state = 1; - } else if (c < 0xF0) { - // begin 3 byte sequence, 0xE0 to 0xEF - unicode_wchar = (uint16_t)(c & 0x0F) << 12; - utf8_state = 2; - } else { - // begin 4 byte sequence (not supported), 0xF0 to 0xF4 - // or illegal, 0xF5 to 0xFF - utf8_state = 255; - } - return 1; -} - - -// Step #2: translate Unicode code point to keystroke sequence -// -KEYCODE_TYPE usb_keyboard_class::unicode_to_keycode(uint16_t cpoint) -{ - // Unicode code points beyond U+FFFF are not supported - // technically this input should probably be called UCS-2 - if (cpoint < 32) { - if (cpoint == 10) return KEY_ENTER & 0x3FFF; - return 0; - } - if (cpoint < 128) { - if (sizeof(KEYCODE_TYPE) == 1) { - return pgm_read_byte(keycodes_ascii + (cpoint - 0x20)); - } else if (sizeof(KEYCODE_TYPE) == 2) { - return pgm_read_word(keycodes_ascii + (cpoint - 0x20)); - } - return 0; - } - #ifdef ISO_8859_1_A0 - if (cpoint <= 0xA0) return 0; - if (cpoint < 0x100) { - if (sizeof(KEYCODE_TYPE) == 1) { - return pgm_read_byte(keycodes_iso_8859_1 + (cpoint - 0xA0)); - } else if (sizeof(KEYCODE_TYPE) == 2) { - return pgm_read_word(keycodes_iso_8859_1 + (cpoint - 0xA0)); - } - return 0; - } - #endif - //#ifdef UNICODE_20AC - //if (cpoint == 0x20AC) return UNICODE_20AC & 0x3FFF; - //#endif - #ifdef KEYCODE_EXTRA00 - if (cpoint == UNICODE_EXTRA00) return KEYCODE_EXTRA00 & 0x3FFF; - #endif - #ifdef KEYCODE_EXTRA01 - if (cpoint == UNICODE_EXTRA01) return KEYCODE_EXTRA01 & 0x3FFF; - #endif - #ifdef KEYCODE_EXTRA02 - if (cpoint == UNICODE_EXTRA02) return KEYCODE_EXTRA02 & 0x3FFF; - #endif - #ifdef KEYCODE_EXTRA03 - if (cpoint == UNICODE_EXTRA03) return KEYCODE_EXTRA03 & 0x3FFF; - #endif - #ifdef KEYCODE_EXTRA04 - if (cpoint == UNICODE_EXTRA04) return KEYCODE_EXTRA04 & 0x3FFF; - #endif - #ifdef KEYCODE_EXTRA05 - if (cpoint == UNICODE_EXTRA05) return KEYCODE_EXTRA05 & 0x3FFF; - #endif - #ifdef KEYCODE_EXTRA06 - if (cpoint == UNICODE_EXTRA06) return KEYCODE_EXTRA06 & 0x3FFF; - #endif - #ifdef KEYCODE_EXTRA07 - if (cpoint == UNICODE_EXTRA07) return KEYCODE_EXTRA07 & 0x3FFF; - #endif - #ifdef KEYCODE_EXTRA08 - if (cpoint == UNICODE_EXTRA08) return KEYCODE_EXTRA08 & 0x3FFF; - #endif - #ifdef KEYCODE_EXTRA09 - if (cpoint == UNICODE_EXTRA09) return KEYCODE_EXTRA09 & 0x3FFF; - #endif - return 0; -} - -// Step #3: execute keystroke sequence -// -void usb_keyboard_class::write_keycode(KEYCODE_TYPE keycode) -{ - if (!keycode) return; - #ifdef DEADKEYS_MASK - KEYCODE_TYPE deadkeycode = deadkey_to_keycode(keycode); - if (deadkeycode) write_key(deadkeycode); - #endif - write_key(keycode); -} - -KEYCODE_TYPE usb_keyboard_class::deadkey_to_keycode(KEYCODE_TYPE keycode) -{ - #ifdef DEADKEYS_MASK - keycode &= DEADKEYS_MASK; - if (keycode == 0) return 0; - #ifdef ACUTE_ACCENT_BITS - if (keycode == ACUTE_ACCENT_BITS) return DEADKEY_ACUTE_ACCENT; - #endif - #ifdef CEDILLA_BITS - if (keycode == CEDILLA_BITS) return DEADKEY_CEDILLA; - #endif - #ifdef CIRCUMFLEX_BITS - if (keycode == CIRCUMFLEX_BITS) return DEADKEY_CIRCUMFLEX; - #endif - #ifdef DIAERESIS_BITS - if (keycode == DIAERESIS_BITS) return DEADKEY_DIAERESIS; - #endif - #ifdef GRAVE_ACCENT_BITS - if (keycode == GRAVE_ACCENT_BITS) return DEADKEY_GRAVE_ACCENT; - #endif - #ifdef TILDE_BITS - if (keycode == TILDE_BITS) return DEADKEY_TILDE; - #endif - #ifdef RING_ABOVE_BITS - if (keycode == RING_ABOVE_BITS) return DEADKEY_RING_ABOVE; - #endif - #endif // DEADKEYS_MASK - return 0; -} - -// Step #4: do each keystroke -// -void usb_keyboard_class::write_key(KEYCODE_TYPE keycode) -{ - keyboard_report_data[0] = keycode_to_modifier(keycode); - keyboard_report_data[1] = 0; - keyboard_report_data[2] = keycode_to_key(keycode); - keyboard_report_data[3] = 0; - keyboard_report_data[4] = 0; - keyboard_report_data[5] = 0; - keyboard_report_data[6] = 0; - keyboard_report_data[7] = 0; - send_now(); - keyboard_report_data[0] = 0; - keyboard_report_data[2] = 0; - send_now(); -} - -uint8_t usb_keyboard_class::keycode_to_modifier(KEYCODE_TYPE keycode) -{ - uint8_t modifier=0; - - #ifdef SHIFT_MASK - if (keycode & SHIFT_MASK) modifier |= MODIFIERKEY_SHIFT; - #endif - #ifdef ALTGR_MASK - if (keycode & ALTGR_MASK) modifier |= MODIFIERKEY_RIGHT_ALT; - #endif - #ifdef RCTRL_MASK - if (keycode & RCTRL_MASK) modifier |= MODIFIERKEY_RIGHT_CTRL; - #endif - return modifier; -} - -uint8_t usb_keyboard_class::keycode_to_key(KEYCODE_TYPE keycode) -{ - uint8_t key = keycode & 0x3F; - #ifdef KEY_NON_US_100 - if (key == KEY_NON_US_100) key = 100; - #endif - return key; -} - - - -void usb_keyboard_class::set_modifier(uint8_t c) -{ - keyboard_report_data[0] = c; -} -void usb_keyboard_class::set_key1(uint8_t c) -{ - keyboard_report_data[2] = c; -} -void usb_keyboard_class::set_key2(uint8_t c) -{ - keyboard_report_data[3] = c; -} -void usb_keyboard_class::set_key3(uint8_t c) -{ - keyboard_report_data[4] = c; -} -void usb_keyboard_class::set_key4(uint8_t c) -{ - keyboard_report_data[5] = c; -} -void usb_keyboard_class::set_key5(uint8_t c) -{ - keyboard_report_data[6] = c; -} -void usb_keyboard_class::set_key6(uint8_t c) -{ - keyboard_report_data[7] = c; -} -void usb_keyboard_class::set_media(uint8_t c) -{ - keyboard_report_data[1] = c; -} - - -void usb_keyboard_class::send_now(void) -{ -#if defined(USE_BOOT_KEYBOARD_PROTOCOL) - if(getProtocol() != 1){ - SendRawReport(keyboard_report_data,sizeof(keyboard_report_data)); - } - else -#endif - SendReport(keyboard_report_data,sizeof(keyboard_report_data)); -} - - -void usb_keyboard_class::press(uint16_t n) -{ - uint8_t key, mod, msb, modrestore=0; - - msb = n >> 8; - if (msb >= 0xC2 && msb <= 0xDF) { - n = (n & 0x3F) | ((uint16_t)(msb & 0x1F) << 6); - } else - if (msb == 0x80) { - presskey(0, n); - return; - } else - if (msb == 0x40) { - presskey(n, 0); - return; - } - KEYCODE_TYPE keycode = unicode_to_keycode(n); - if (!keycode) return; - #ifdef DEADKEYS_MASK - KEYCODE_TYPE deadkeycode = deadkey_to_keycode(keycode); - if (deadkeycode) { - modrestore = keyboard_report_data[0]; - if (modrestore) { - keyboard_report_data[0] = 0; - send_now(); - } - // TODO: test if operating systems recognize - // deadkey sequences when other keys are held - mod = keycode_to_modifier(deadkeycode); - key = keycode_to_key(deadkeycode); - presskey(key, mod); - releasekey(key, mod); - } - #endif - mod = keycode_to_modifier(keycode); - key = keycode_to_key(keycode); - presskey(key, mod | modrestore); -} - -void usb_keyboard_class::release(uint16_t n) -{ - uint8_t key, mod, msb; - - msb = n >> 8; - if (msb >= 0xC2 && msb <= 0xDF) { - n = (n & 0x3F) | ((uint16_t)(msb & 0x1F) << 6); - } else - if (msb == 0x80) { - releasekey(0, n); - return; - } else - if (msb == 0x40) { - releasekey(n, 0); - return; - } - KEYCODE_TYPE keycode = unicode_to_keycode(n); - if (!keycode) return; - mod = keycode_to_modifier(keycode); - key = keycode_to_key(keycode); - releasekey(key, mod); -} - -void usb_keyboard_class::presskey(uint8_t key, uint8_t modifier) -{ - bool send_required = false; - uint8_t i; - - if (modifier) { - if ((keyboard_report_data[0] & modifier) != modifier) { - keyboard_report_data[0] |= modifier; - send_required = true; - } - } - if (key) { - for (i=2; i < 8; i++) { - if (keyboard_report_data[i] == key) goto end; - } - for (i=2; i < 8; i++) { - if (keyboard_report_data[i] == 0) { - keyboard_report_data[i] = key; - send_required = true; - goto end; - } - } - } - end: - if (send_required) send_now(); -} - -void usb_keyboard_class::releasekey(uint8_t key, uint8_t modifier) -{ - bool send_required = false; - uint8_t i; - - if (modifier) { - if ((keyboard_report_data[0] & modifier) != 0) { - keyboard_report_data[0] &= ~modifier; - send_required = true; - } - } - if (key) { - for (i=2; i < 8; i++) { - if (keyboard_report_data[i] == key) { - keyboard_report_data[i] = 0; - send_required = true; - } - } - } - if (send_required) send_now(); -} - -void usb_keyboard_class::releaseAll(void) -{ - uint8_t i, anybits; - - anybits = keyboard_report_data[0]; - for (i=2; i < 8; i++) { - anybits |= keyboard_report_data[i]; - keyboard_report_data[i] = 0; - } - if (!anybits) return; - keyboard_report_data[0] = 0; - send_now(); -} - -usb_keyboard_class TeensyKeyboard = usb_keyboard_class(); - -#include -#include - -#ifdef M -#undef M -#endif -#define M(n) ((n) & 0x3FFF) - -const KEYCODE_TYPE PROGMEM keycodes_ascii[] = { - M(ASCII_20), M(ASCII_21), M(ASCII_22), M(ASCII_23), - M(ASCII_24), M(ASCII_25), M(ASCII_26), M(ASCII_27), - M(ASCII_28), M(ASCII_29), M(ASCII_2A), M(ASCII_2B), - M(ASCII_2C), M(ASCII_2D), M(ASCII_2E), M(ASCII_2F), - M(ASCII_30), M(ASCII_31), M(ASCII_32), M(ASCII_33), - M(ASCII_34), M(ASCII_35), M(ASCII_36), M(ASCII_37), - M(ASCII_38), M(ASCII_39), M(ASCII_3A), M(ASCII_3B), - M(ASCII_3C), M(ASCII_3D), M(ASCII_3E), M(ASCII_3F), - M(ASCII_40), M(ASCII_41), M(ASCII_42), M(ASCII_43), - M(ASCII_44), M(ASCII_45), M(ASCII_46), M(ASCII_47), - M(ASCII_48), M(ASCII_49), M(ASCII_4A), M(ASCII_4B), - M(ASCII_4C), M(ASCII_4D), M(ASCII_4E), M(ASCII_4F), - M(ASCII_50), M(ASCII_51), M(ASCII_52), M(ASCII_53), - M(ASCII_54), M(ASCII_55), M(ASCII_56), M(ASCII_57), - M(ASCII_58), M(ASCII_59), M(ASCII_5A), M(ASCII_5B), - M(ASCII_5C), M(ASCII_5D), M(ASCII_5E), M(ASCII_5F), - M(ASCII_60), M(ASCII_61), M(ASCII_62), M(ASCII_63), - M(ASCII_64), M(ASCII_65), M(ASCII_66), M(ASCII_67), - M(ASCII_68), M(ASCII_69), M(ASCII_6A), M(ASCII_6B), - M(ASCII_6C), M(ASCII_6D), M(ASCII_6E), M(ASCII_6F), - M(ASCII_70), M(ASCII_71), M(ASCII_72), M(ASCII_73), - M(ASCII_74), M(ASCII_75), M(ASCII_76), M(ASCII_77), - M(ASCII_78), M(ASCII_79), M(ASCII_7A), M(ASCII_7B), - M(ASCII_7C), M(ASCII_7D), M(ASCII_7E), M(ASCII_7F) -}; - -#ifdef ISO_8859_1_A0 -const KEYCODE_TYPE PROGMEM keycodes_iso_8859_1[] = { - M(ISO_8859_1_A0), M(ISO_8859_1_A1), M(ISO_8859_1_A2), M(ISO_8859_1_A3), - M(ISO_8859_1_A4), M(ISO_8859_1_A5), M(ISO_8859_1_A6), M(ISO_8859_1_A7), - M(ISO_8859_1_A8), M(ISO_8859_1_A9), M(ISO_8859_1_AA), M(ISO_8859_1_AB), - M(ISO_8859_1_AC), M(ISO_8859_1_AD), M(ISO_8859_1_AE), M(ISO_8859_1_AF), - M(ISO_8859_1_B0), M(ISO_8859_1_B1), M(ISO_8859_1_B2), M(ISO_8859_1_B3), - M(ISO_8859_1_B4), M(ISO_8859_1_B5), M(ISO_8859_1_B6), M(ISO_8859_1_B7), - M(ISO_8859_1_B8), M(ISO_8859_1_B9), M(ISO_8859_1_BA), M(ISO_8859_1_BB), - M(ISO_8859_1_BC), M(ISO_8859_1_BD), M(ISO_8859_1_BE), M(ISO_8859_1_BF), - M(ISO_8859_1_C0), M(ISO_8859_1_C1), M(ISO_8859_1_C2), M(ISO_8859_1_C3), - M(ISO_8859_1_C4), M(ISO_8859_1_C5), M(ISO_8859_1_C6), M(ISO_8859_1_C7), - M(ISO_8859_1_C8), M(ISO_8859_1_C9), M(ISO_8859_1_CA), M(ISO_8859_1_CB), - M(ISO_8859_1_CC), M(ISO_8859_1_CD), M(ISO_8859_1_CE), M(ISO_8859_1_CF), - M(ISO_8859_1_D0), M(ISO_8859_1_D1), M(ISO_8859_1_D2), M(ISO_8859_1_D3), - M(ISO_8859_1_D4), M(ISO_8859_1_D5), M(ISO_8859_1_D6), M(ISO_8859_1_D7), - M(ISO_8859_1_D8), M(ISO_8859_1_D9), M(ISO_8859_1_DA), M(ISO_8859_1_DB), - M(ISO_8859_1_DC), M(ISO_8859_1_DD), M(ISO_8859_1_DE), M(ISO_8859_1_DF), - M(ISO_8859_1_E0), M(ISO_8859_1_E1), M(ISO_8859_1_E2), M(ISO_8859_1_E3), - M(ISO_8859_1_E4), M(ISO_8859_1_E5), M(ISO_8859_1_E6), M(ISO_8859_1_E7), - M(ISO_8859_1_E8), M(ISO_8859_1_E9), M(ISO_8859_1_EA), M(ISO_8859_1_EB), - M(ISO_8859_1_EC), M(ISO_8859_1_ED), M(ISO_8859_1_EE), M(ISO_8859_1_EF), - M(ISO_8859_1_F0), M(ISO_8859_1_F1), M(ISO_8859_1_F2), M(ISO_8859_1_F3), - M(ISO_8859_1_F4), M(ISO_8859_1_F5), M(ISO_8859_1_F6), M(ISO_8859_1_F7), - M(ISO_8859_1_F8), M(ISO_8859_1_F9), M(ISO_8859_1_FA), M(ISO_8859_1_FB), - M(ISO_8859_1_FC), M(ISO_8859_1_FD), M(ISO_8859_1_FE), M(ISO_8859_1_FF) -}; -#endif // ISO_8859_1_A0 diff --git a/plugins/KeyboardioHID/src/TeensyKeyboard.h b/plugins/KeyboardioHID/src/TeensyKeyboard.h deleted file mode 100644 index 1d5a049808..0000000000 --- a/plugins/KeyboardioHID/src/TeensyKeyboard.h +++ /dev/null @@ -1,138 +0,0 @@ -/* USB API for Teensy USB Development Board - * http://www.pjrc.com/teensy/teensyduino.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. - */ - -#pragma once - -#include "HID.h" - -#if !defined(_USING_HID) - -#error "This is not an USB AVR or you use an old version of the IDE." - -#else - -#include "HID-Project.h" -#include "TeensyKeylayouts.h" - -// Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60 -static const uint8_t PROGMEM teensykeyboard_hid_report_desc[] = { - 0x05, 0x01, // Usage Page (Generic Desktop), - 0x09, 0x06, // Usage (Keyboard), - 0xA1, 0x01, // Collection (Application), - 0x85, HID_REPORTID_TEENSY_KEYBOARD, // REPORT_ID - 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, 0x08, // Report Count (8), - 0x75, 0x01, // Report Size (1), - 0x15, 0x00, // Logical Minimum (0), - 0x25, 0x01, // Logical Maximum (1), - 0x05, 0x0C, // Usage Page (Consumer), - 0x09, 0xE9, // Usage (Volume Increment), - 0x09, 0xEA, // Usage (Volume Decrement), - 0x09, 0xE2, // Usage (Mute), - 0x09, 0xCD, // Usage (Play/Pause), - 0x09, 0xB5, // Usage (Scan Next Track), - 0x09, 0xB6, // Usage (Scan Previous Track), - 0x09, 0xB7, // Usage (Stop), - 0x09, 0xB8, // Usage (Eject), -// Note: Teensy ledreport was not modified to 8 bit, nor left out when leds are deactivated - 0x81, 0x02, // Input (Data, Variable, Absolute), ;Media keys - 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, 0x7F, // Logical Maximum(104), - 0x05, 0x07, // Usage Page (Key Codes), - 0x19, 0x00, // Usage Minimum (0), - 0x29, 0x7F, // Usage Maximum (104), - 0x81, 0x00, // Input (Data, Array), ;Normal keys - 0xc0 // End Collection -}; - -// Keyboard Leds -#define LED_NUM_LOCK 0x01 -#define LED_CAPS_LOCK 0x02 -#define LED_SCROLL_LOCK 0x04 - -class usb_keyboard_class : public Print, private HIDDevice -{ - public: - usb_keyboard_class(void); - -#if defined(HID_KEYBOARD_LEDS_ENABLED) - uint8_t getLeds(void); -#endif - - void begin(void) { } - void end(void) { } - virtual size_t write(uint8_t); - using Print::write; - inline void write_unicode(uint16_t unicode) { write_keycode(unicode_to_keycode(unicode)); } - void set_modifier(uint8_t); - void set_key1(uint8_t); - void set_key2(uint8_t); - void set_key3(uint8_t); - void set_key4(uint8_t); - void set_key5(uint8_t); - void set_key6(uint8_t); - void set_media(uint8_t); - void send_now(void); - void press(uint16_t n); - void release(uint16_t n); - void releaseAll(void); - private: - KEYCODE_TYPE unicode_to_keycode(uint16_t unicode); - KEYCODE_TYPE deadkey_to_keycode(KEYCODE_TYPE keycode); - uint8_t keycode_to_modifier(KEYCODE_TYPE keycode); - uint8_t keycode_to_key(KEYCODE_TYPE keycode); - void presskey(uint8_t key, uint8_t modifier); - void releasekey(uint8_t key, uint8_t modifier); - void write_keycode(KEYCODE_TYPE key); - void write_key(KEYCODE_TYPE code); - uint8_t utf8_state; - uint16_t unicode_wchar; - uint8_t keyboard_report_data[8]; - -#if defined(HID_KEYBOARD_LEDS_ENABLED) - virtual void setReportData(void* &data, int len); - uint8_t leds; -#endif -}; - -extern usb_keyboard_class TeensyKeyboard; - -#endif diff --git a/plugins/KeyboardioHID/src/TeensyKeylayouts.h b/plugins/KeyboardioHID/src/TeensyKeylayouts.h deleted file mode 100644 index f91749a923..0000000000 --- a/plugins/KeyboardioHID/src/TeensyKeylayouts.h +++ /dev/null @@ -1,5420 +0,0 @@ -/* 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. - */ - - -#ifndef KEYLAYOUTS_H__ -#define KEYLAYOUTS_H__ - -#include -#include - -#ifdef __cplusplus -extern "C"{ -#endif - -//#define LAYOUT_US_ENGLISH -//#define LAYOUT_CANADIAN_FRENCH -//#define LAYOUT_CANADIAN_MULTILINGUAL -//#define LAYOUT_DANISH -//#define LAYOUT_FINNISH -//#define LAYOUT_FRENCH -//#define LAYOUT_FRENCH_BELGIAN -//#define LAYOUT_FRENCH_SWISS -//#define LAYOUT_GERMAN -//#define LAYOUT_GERMAN_MAC -//#define LAYOUT_GERMAN_SWISS -//#define LAYOUT_ICELANDIC -//#define LAYOUT_IRISH -//#define LAYOUT_ITALIAN -//#define LAYOUT_NORWEGIAN -//#define LAYOUT_PORTUGUESE -//#define LAYOUT_PORTUGUESE_BRAZILIAN -//#define LAYOUT_SPANISH -//#define LAYOUT_SPANISH_LATIN_AMERICA -//#define LAYOUT_SWEDISH -//#define LAYOUT_TURKISH -//#define LAYOUT_UNITED_KINGDOM -//#define LAYOUT_US_INTERNATIONAL - -// http://en.wikipedia.org/wiki/Keyboard_layout - - -#define MODIFIERKEY_CTRL ( 0x01 | 0x8000 ) -#define MODIFIERKEY_SHIFT ( 0x02 | 0x8000 ) -#define MODIFIERKEY_ALT ( 0x04 | 0x8000 ) -#define MODIFIERKEY_GUI ( 0x08 | 0x8000 ) -#define MODIFIERKEY_LEFT_CTRL ( 0x01 | 0x8000 ) -#define MODIFIERKEY_LEFT_SHIFT ( 0x02 | 0x8000 ) -#define MODIFIERKEY_LEFT_ALT ( 0x04 | 0x8000 ) -#define MODIFIERKEY_LEFT_GUI ( 0x08 | 0x8000 ) -#define MODIFIERKEY_RIGHT_CTRL ( 0x10 | 0x8000 ) -#define MODIFIERKEY_RIGHT_SHIFT ( 0x20 | 0x8000 ) -#define MODIFIERKEY_RIGHT_ALT ( 0x40 | 0x8000 ) -#define MODIFIERKEY_RIGHT_GUI ( 0x80 | 0x8000 ) - -#define KEY_MEDIA_VOLUME_INC 0x01 -#define KEY_MEDIA_VOLUME_DEC 0x02 -#define KEY_MEDIA_MUTE 0x04 -#define KEY_MEDIA_PLAY_PAUSE 0x08 -#define KEY_MEDIA_NEXT_TRACK 0x10 -#define KEY_MEDIA_PREV_TRACK 0x20 -#define KEY_MEDIA_STOP 0x40 -#define KEY_MEDIA_EJECT 0x80 - -#define KEY_A ( 4 | 0x4000 ) -#define KEY_B ( 5 | 0x4000 ) -#define KEY_C ( 6 | 0x4000 ) -#define KEY_D ( 7 | 0x4000 ) -#define KEY_E ( 8 | 0x4000 ) -#define KEY_F ( 9 | 0x4000 ) -#define KEY_G ( 10 | 0x4000 ) -#define KEY_H ( 11 | 0x4000 ) -#define KEY_I ( 12 | 0x4000 ) -#define KEY_J ( 13 | 0x4000 ) -#define KEY_K ( 14 | 0x4000 ) -#define KEY_L ( 15 | 0x4000 ) -#define KEY_M ( 16 | 0x4000 ) -#define KEY_N ( 17 | 0x4000 ) -#define KEY_O ( 18 | 0x4000 ) -#define KEY_P ( 19 | 0x4000 ) -#define KEY_Q ( 20 | 0x4000 ) -#define KEY_R ( 21 | 0x4000 ) -#define KEY_S ( 22 | 0x4000 ) -#define KEY_T ( 23 | 0x4000 ) -#define KEY_U ( 24 | 0x4000 ) -#define KEY_V ( 25 | 0x4000 ) -#define KEY_W ( 26 | 0x4000 ) -#define KEY_X ( 27 | 0x4000 ) -#define KEY_Y ( 28 | 0x4000 ) -#define KEY_Z ( 29 | 0x4000 ) -#define KEY_1 ( 30 | 0x4000 ) -#define KEY_2 ( 31 | 0x4000 ) -#define KEY_3 ( 32 | 0x4000 ) -#define KEY_4 ( 33 | 0x4000 ) -#define KEY_5 ( 34 | 0x4000 ) -#define KEY_6 ( 35 | 0x4000 ) -#define KEY_7 ( 36 | 0x4000 ) -#define KEY_8 ( 37 | 0x4000 ) -#define KEY_9 ( 38 | 0x4000 ) -#define KEY_0 ( 39 | 0x4000 ) -#define KEY_ENTER ( 40 | 0x4000 ) -#define KEY_ESC ( 41 | 0x4000 ) -#define KEY_BACKSPACE ( 42 | 0x4000 ) -#define KEY_TAB ( 43 | 0x4000 ) -#define KEY_SPACE ( 44 | 0x4000 ) -#define KEY_MINUS ( 45 | 0x4000 ) -#define KEY_EQUAL ( 46 | 0x4000 ) -#define KEY_LEFT_BRACE ( 47 | 0x4000 ) -#define KEY_RIGHT_BRACE ( 48 | 0x4000 ) -#define KEY_BACKSLASH ( 49 | 0x4000 ) -#define KEY_NON_US_NUM ( 50 | 0x4000 ) -#define KEY_SEMICOLON ( 51 | 0x4000 ) -#define KEY_QUOTE ( 52 | 0x4000 ) -#define KEY_TILDE ( 53 | 0x4000 ) -#define KEY_COMMA ( 54 | 0x4000 ) -#define KEY_PERIOD ( 55 | 0x4000 ) -#define KEY_SLASH ( 56 | 0x4000 ) -#define KEY_CAPS_LOCK ( 57 | 0x4000 ) -#define KEY_F1 ( 58 | 0x4000 ) -#define KEY_F2 ( 59 | 0x4000 ) -#define KEY_F3 ( 60 | 0x4000 ) -#define KEY_F4 ( 61 | 0x4000 ) -#define KEY_F5 ( 62 | 0x4000 ) -#define KEY_F6 ( 63 | 0x4000 ) -#define KEY_F7 ( 64 | 0x4000 ) -#define KEY_F8 ( 65 | 0x4000 ) -#define KEY_F9 ( 66 | 0x4000 ) -#define KEY_F10 ( 67 | 0x4000 ) -#define KEY_F11 ( 68 | 0x4000 ) -#define KEY_F12 ( 69 | 0x4000 ) -#define KEY_PRINTSCREEN ( 70 | 0x4000 ) -#define KEY_SCROLL_LOCK ( 71 | 0x4000 ) -#define KEY_PAUSE ( 72 | 0x4000 ) -#define KEY_INSERT ( 73 | 0x4000 ) -#define KEY_HOME ( 74 | 0x4000 ) -#define KEY_PAGE_UP ( 75 | 0x4000 ) -#define KEY_DELETE ( 76 | 0x4000 ) -#define KEY_END ( 77 | 0x4000 ) -#define KEY_PAGE_DOWN ( 78 | 0x4000 ) -#define KEY_RIGHT ( 79 | 0x4000 ) -#define KEY_LEFT ( 80 | 0x4000 ) -#define KEY_DOWN ( 81 | 0x4000 ) -#define KEY_UP ( 82 | 0x4000 ) -#define KEY_NUM_LOCK ( 83 | 0x4000 ) -#define KEYPAD_SLASH ( 84 | 0x4000 ) -#define KEYPAD_ASTERIX ( 85 | 0x4000 ) -#define KEYPAD_MINUS ( 86 | 0x4000 ) -#define KEYPAD_PLUS ( 87 | 0x4000 ) -#define KEYPAD_ENTER ( 88 | 0x4000 ) -#define KEYPAD_1 ( 89 | 0x4000 ) -#define KEYPAD_2 ( 90 | 0x4000 ) -#define KEYPAD_3 ( 91 | 0x4000 ) -#define KEYPAD_4 ( 92 | 0x4000 ) -#define KEYPAD_5 ( 93 | 0x4000 ) -#define KEYPAD_6 ( 94 | 0x4000 ) -#define KEYPAD_7 ( 95 | 0x4000 ) -#define KEYPAD_8 ( 96 | 0x4000 ) -#define KEYPAD_9 ( 97 | 0x4000 ) -#define KEYPAD_0 ( 98 | 0x4000 ) -#define KEYPAD_PERIOD ( 99 | 0x4000 ) -#define KEY_MENU ( 101 | 0x4000 ) -#define KEY_F13 ( 104 | 0x4000 ) -#define KEY_F14 ( 105 | 0x4000 ) -#define KEY_F15 ( 106 | 0x4000 ) -#define KEY_F16 ( 107 | 0x4000 ) -#define KEY_F17 ( 108 | 0x4000 ) -#define KEY_F18 ( 109 | 0x4000 ) -#define KEY_F19 ( 110 | 0x4000 ) -#define KEY_F20 ( 111 | 0x4000 ) -#define KEY_F21 ( 112 | 0x4000 ) -#define KEY_F22 ( 113 | 0x4000 ) -#define KEY_F23 ( 114 | 0x4000 ) -#define KEY_F24 ( 115 | 0x4000 ) - - -// for compatibility with Leonardo's slightly different names -#define KEY_UP_ARROW KEY_UP -#define KEY_DOWN_ARROW KEY_DOWN -#define KEY_LEFT_ARROW KEY_LEFT -#define KEY_RIGHT_ARROW KEY_RIGHT -#define KEY_RETURN KEY_ENTER -#define KEY_LEFT_CTRL MODIFIERKEY_LEFT_CTRL -#define KEY_LEFT_SHIFT MODIFIERKEY_LEFT_SHIFT -#define KEY_LEFT_ALT MODIFIERKEY_LEFT_ALT -#define KEY_LEFT_GUI MODIFIERKEY_LEFT_GUI -#define KEY_RIGHT_CTRL MODIFIERKEY_RIGHT_CTRL -#define KEY_RIGHT_SHIFT MODIFIERKEY_RIGHT_SHIFT -#define KEY_RIGHT_ALT MODIFIERKEY_RIGHT_ALT -#define KEY_RIGHT_GUI MODIFIERKEY_RIGHT_GUI - - -// Everything below this line is not intended for use in "normal" programs. -// These private symbols populate lookup tables, which are used to translate -// ascii and UTF8 unicode into keystroke sequences. - - -#ifdef LAYOUT_US_ENGLISH - -#define SHIFT_MASK 0x40 -#define KEYCODE_TYPE uint8_t - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! -#define ASCII_22 KEY_QUOTE + SHIFT_MASK // 34 " -#define ASCII_23 KEY_3 + SHIFT_MASK // 35 # -#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ -#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % -#define ASCII_26 KEY_7 + SHIFT_MASK // 38 & -#define ASCII_27 KEY_QUOTE // 39 ' -#define ASCII_28 KEY_9 + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_0 + SHIFT_MASK // 41 ) -#define ASCII_2A KEY_8 + SHIFT_MASK // 42 * -#define ASCII_2B KEY_EQUAL + SHIFT_MASK // 43 + -#define ASCII_2C KEY_COMMA // 44 , -#define ASCII_2D KEY_MINUS // 45 - -#define ASCII_2E KEY_PERIOD // 46 . -#define ASCII_2F KEY_SLASH // 47 / -#define ASCII_30 KEY_0 // 48 0 -#define ASCII_31 KEY_1 // 49 1 -#define ASCII_32 KEY_2 // 50 2 -#define ASCII_33 KEY_3 // 51 3 -#define ASCII_34 KEY_4 // 52 4 -#define ASCII_35 KEY_5 // 53 5 -#define ASCII_36 KEY_6 // 54 6 -#define ASCII_37 KEY_7 // 55 7 -#define ASCII_38 KEY_8 // 55 8 -#define ASCII_39 KEY_9 // 57 9 -#define ASCII_3A KEY_SEMICOLON + SHIFT_MASK // 58 : -#define ASCII_3B KEY_SEMICOLON // 59 ; -#define ASCII_3C KEY_COMMA + SHIFT_MASK // 60 < -#define ASCII_3D KEY_EQUAL // 61 = -#define ASCII_3E KEY_PERIOD + SHIFT_MASK // 62 > -#define ASCII_3F KEY_SLASH + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_2 + SHIFT_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_LEFT_BRACE // 91 [ -#define ASCII_5C KEY_BACKSLASH // 92 -#define ASCII_5D KEY_RIGHT_BRACE // 93 ] -#define ASCII_5E KEY_6 + SHIFT_MASK // 94 ^ -#define ASCII_5F KEY_MINUS + SHIFT_MASK // 95 _ -#define ASCII_60 KEY_TILDE // 96 ` -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Y // 121 y -#define ASCII_7A KEY_Z // 122 z -#define ASCII_7B KEY_LEFT_BRACE + SHIFT_MASK // 123 { -#define ASCII_7C KEY_BACKSLASH + SHIFT_MASK // 124 | -#define ASCII_7D KEY_RIGHT_BRACE + SHIFT_MASK // 125 } -#define ASCII_7E KEY_TILDE + SHIFT_MASK // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 - -#endif // LAYOUT_US_ENGLISH - - - - -#ifdef LAYOUT_US_INTERNATIONAL - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define DEADKEYS_MASK 0x0700 -#define CIRCUMFLEX_BITS 0x0100 -#define ACUTE_ACCENT_BITS 0x0200 -#define GRAVE_ACCENT_BITS 0x0300 -#define TILDE_BITS 0x0400 -#define DIAERESIS_BITS 0x0500 -#define KEYCODE_TYPE uint16_t -#define DEADKEY_CIRCUMFLEX KEY_6 + SHIFT_MASK -#define DEADKEY_ACUTE_ACCENT KEY_QUOTE -#define DEADKEY_GRAVE_ACCENT KEY_TILDE -#define DEADKEY_TILDE KEY_TILDE + SHIFT_MASK -#define DEADKEY_DIAERESIS KEY_QUOTE + SHIFT_MASK - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! -#define ASCII_22 DIAERESIS_BITS + KEY_SPACE // 34 " -#define ASCII_23 KEY_3 + SHIFT_MASK // 35 # -#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ -#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % -#define ASCII_26 KEY_7 + SHIFT_MASK // 38 & -#define ASCII_27 ACUTE_ACCENT_BITS + KEY_SPACE // 39 ' -#define ASCII_28 KEY_9 + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_0 + SHIFT_MASK // 41 ) -#define ASCII_2A KEY_8 + SHIFT_MASK // 42 * -#define ASCII_2B KEY_EQUAL + SHIFT_MASK // 43 + -#define ASCII_2C KEY_COMMA // 44 , -#define ASCII_2D KEY_MINUS // 45 - -#define ASCII_2E KEY_PERIOD // 46 . -#define ASCII_2F KEY_SLASH // 47 / -#define ASCII_30 KEY_0 // 48 0 -#define ASCII_31 KEY_1 // 49 1 -#define ASCII_32 KEY_2 // 50 2 -#define ASCII_33 KEY_3 // 51 3 -#define ASCII_34 KEY_4 // 52 4 -#define ASCII_35 KEY_5 // 53 5 -#define ASCII_36 KEY_6 // 54 6 -#define ASCII_37 KEY_7 // 55 7 -#define ASCII_38 KEY_8 // 55 8 -#define ASCII_39 KEY_9 // 57 9 -#define ASCII_3A KEY_SEMICOLON + SHIFT_MASK // 58 : -#define ASCII_3B KEY_SEMICOLON // 59 ; -#define ASCII_3C KEY_COMMA + SHIFT_MASK // 60 < -#define ASCII_3D KEY_EQUAL // 61 = -#define ASCII_3E KEY_PERIOD + SHIFT_MASK // 62 > -#define ASCII_3F KEY_SLASH + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_2 + SHIFT_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_LEFT_BRACE // 91 [ -#define ASCII_5C KEY_BACKSLASH // 92 -#define ASCII_5D KEY_RIGHT_BRACE // 93 ] -#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ -#define ASCII_5F KEY_MINUS + SHIFT_MASK // 95 _ -#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Y // 121 y -#define ASCII_7A KEY_Z // 122 z -#define ASCII_7B KEY_LEFT_BRACE + SHIFT_MASK // 123 { -#define ASCII_7C KEY_BACKSLASH + SHIFT_MASK // 124 | -#define ASCII_7D KEY_RIGHT_BRACE + SHIFT_MASK // 125 } -#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 -#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space -#define ISO_8859_1_A1 KEY_1 + ALTGR_MASK // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 KEY_C + ALTGR_MASK + SHIFT_MASK // 162 ¢ Cent SIGN -#define ISO_8859_1_A3 KEY_4 + ALTGR_MASK + SHIFT_MASK // 163 £ Pound Sign -#define ISO_8859_1_A4 KEY_4 + ALTGR_MASK // 164 ¤ Currency or Euro Sign -#define ISO_8859_1_A5 KEY_MINUS + ALTGR_MASK // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 KEY_BACKSLASH + ALTGR_MASK + SHIFT_MASK // 166 ¦ BROKEN BAR ?? -#define ISO_8859_1_A7 KEY_S + ALTGR_MASK + SHIFT_MASK // 167 § SECTION SIGN -#define ISO_8859_1_A8 KEY_QUOTE + ALTGR_MASK + SHIFT_MASK // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 KEY_C + ALTGR_MASK // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB KEY_LEFT_BRACE + ALTGR_MASK // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC KEY_BACKSLASH + ALTGR_MASK // 172 ¬ NOT SIGN ?? -#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN -#define ISO_8859_1_AE KEY_R + ALTGR_MASK // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF 0 // 175 ¯ MACRON -#define ISO_8859_1_B0 KEY_SEMICOLON + ALTGR_MASK + SHIFT_MASK // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 KEY_2 + ALTGR_MASK // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 KEY_3 + ALTGR_MASK // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 KEY_QUOTE + ALTGR_MASK // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 KEY_M + ALTGR_MASK // 181 µ MICRO SIGN -#define ISO_8859_1_B6 KEY_SEMICOLON + ALTGR_MASK // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT -#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA -#define ISO_8859_1_B9 KEY_1 + ALTGR_MASK + SHIFT_MASK // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB KEY_RIGHT_BRACE + ALTGR_MASK // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC KEY_6 + ALTGR_MASK // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD KEY_7 + ALTGR_MASK // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE KEY_8 + ALTGR_MASK // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF KEY_SLASH + ALTGR_MASK // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE -#define ISO_8859_1_C1 KEY_A + ALTGR_MASK + SHIFT_MASK // 193 Á A ACUTE -#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE -#define ISO_8859_1_C4 KEY_Q + ALTGR_MASK + SHIFT_MASK // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 KEY_W + ALTGR_MASK + SHIFT_MASK // 197 Å A RING ABOVE -#define ISO_8859_1_C6 KEY_Z + ALTGR_MASK + SHIFT_MASK // 198 Æ AE -#define ISO_8859_1_C7 KEY_COMMA + ALTGR_MASK + SHIFT_MASK // 199 Ç C CEDILLA -#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE -#define ISO_8859_1_C9 KEY_E + ALTGR_MASK + SHIFT_MASK // 201 É E ACUTE -#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS -#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE -#define ISO_8859_1_CD KEY_I + ALTGR_MASK + SHIFT_MASK // 205 Í I ACUTE -#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 KEY_D + ALTGR_MASK + SHIFT_MASK // 208 Ð ETH -#define ISO_8859_1_D1 KEY_N + ALTGR_MASK + SHIFT_MASK // 209 Ñ N TILDE -#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE -#define ISO_8859_1_D3 KEY_O + ALTGR_MASK + SHIFT_MASK // 211 Ó O ACUTE -#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE -#define ISO_8859_1_D6 KEY_P + ALTGR_MASK + SHIFT_MASK // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 KEY_EQUAL + ALTGR_MASK // 215 × MULTIPLICATION -#define ISO_8859_1_D8 KEY_L + ALTGR_MASK + SHIFT_MASK // 216 Ø O STROKE -#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE -#define ISO_8859_1_DA KEY_U + ALTGR_MASK + SHIFT_MASK // 218 Ú U ACUTE -#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC KEY_Y + ALTGR_MASK + SHIFT_MASK // 220 Ü U DIAERESIS -#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE -#define ISO_8859_1_DE KEY_T + ALTGR_MASK + SHIFT_MASK // 222 Þ THORN -#define ISO_8859_1_DF KEY_S + ALTGR_MASK // 223 ß SHARP S -#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE -#define ISO_8859_1_E1 KEY_A + ALTGR_MASK // 225 á a ACUTE -#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE -#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS -#define ISO_8859_1_E5 KEY_W + ALTGR_MASK // 229 å a RING ABOVE -#define ISO_8859_1_E6 KEY_Z + ALTGR_MASK // 230 æ ae -#define ISO_8859_1_E7 KEY_COMMA + ALTGR_MASK // 231 ç c CEDILLA -#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE -#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE -#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS -#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE -#define ISO_8859_1_ED KEY_I + ALTGR_MASK // 237 í i ACUTE -#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS -#define ISO_8859_1_F0 KEY_D + ALTGR_MASK // 240 ð ETH -#define ISO_8859_1_F1 KEY_N + ALTGR_MASK // 241 ñ n TILDE -#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE -#define ISO_8859_1_F3 KEY_O + ALTGR_MASK // 243 ó o ACUTE -#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE -#define ISO_8859_1_F6 KEY_P + ALTGR_MASK // 246 ö o DIAERESIS -#define ISO_8859_1_F7 KEY_EQUAL + ALTGR_MASK + SHIFT_MASK // 247 ÷ DIVISION -#define ISO_8859_1_F8 KEY_L + ALTGR_MASK // 248 ø o STROKE -#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE -#define ISO_8859_1_FA KEY_U + ALTGR_MASK // 250 ú u ACUTE -#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC KEY_Y + ALTGR_MASK // 252 ü u DIAERESIS -#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE -#define ISO_8859_1_FE KEY_T + ALTGR_MASK // 254 þ THORN -#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS -#define UNICODE_20AC KEY_5 + ALTGR_MASK // € Euro Sign -// not yet implemented -#define UNICODE_EXTRA00 0x20AC -#define KEYCODE_EXTRA00 KEY_5 + ALTGR_MASK // 20AC € Euro Sign - -#endif // LAYOUT_US_INTERNATIONAL - - - -#ifdef LAYOUT_GERMAN - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define DEADKEYS_MASK 0x0700 -#define SHIFT_MASK 0x0100 -#define ALTGR_MASK 0x0200 -#define CIRCUMFLEX_BITS 0x0300 -#define ACUTE_ACCENT_BITS 0x0400 -#define GRAVE_ACCENT_BITS 0x0500 -#define KEYCODE_TYPE uint16_t -#define DEADKEY_CIRCUMFLEX KEY_TILDE -//#define DEADKEY_CIRCUMFLEX KEY_NON_US_100 -#define DEADKEY_ACUTE_ACCENT KEY_EQUAL -#define DEADKEY_GRAVE_ACCENT KEY_EQUAL + SHIFT_MASK -#define KEY_NON_US_100 63 - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! -#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " -#define ASCII_23 KEY_BACKSLASH // 35 # ?? -#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ -#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % -#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & -#define ASCII_27 KEY_BACKSLASH + SHIFT_MASK // 39 ' -#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) -#define ASCII_2A KEY_RIGHT_BRACE + SHIFT_MASK // 42 * -#define ASCII_2B KEY_RIGHT_BRACE // 43 + -#define ASCII_2C KEY_COMMA // 44 , -#define ASCII_2D KEY_SLASH // 45 - -#define ASCII_2E KEY_PERIOD // 46 . -#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / -#define ASCII_30 KEY_0 // 48 0 -#define ASCII_31 KEY_1 // 49 1 -#define ASCII_32 KEY_2 // 50 2 -#define ASCII_33 KEY_3 // 51 3 -#define ASCII_34 KEY_4 // 52 4 -#define ASCII_35 KEY_5 // 53 5 -#define ASCII_36 KEY_6 // 54 6 -#define ASCII_37 KEY_7 // 55 7 -#define ASCII_38 KEY_8 // 55 8 -#define ASCII_39 KEY_9 // 57 9 -#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : -#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; -#define ASCII_3C KEY_NON_US_100 // 60 < -#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = -#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > -#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_Q + ALTGR_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Z + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Y + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_8 + ALTGR_MASK // 91 [ -#define ASCII_5C KEY_MINUS + ALTGR_MASK // 92 -#define ASCII_5D KEY_9 + ALTGR_MASK // 93 ] -#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ -#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ -#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Z // 121 y -#define ASCII_7A KEY_Y // 122 z -#define ASCII_7B KEY_7 + ALTGR_MASK // 123 { -#define ASCII_7C KEY_NON_US_100 + ALTGR_MASK // 124 | -#define ASCII_7D KEY_0 + ALTGR_MASK // 125 } -#define ASCII_7E KEY_RIGHT_BRACE + ALTGR_MASK // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 -#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space -#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 0 // 162 ¢ Cent Sign -#define ISO_8859_1_A3 0 // 163 £ Pound Sign -#define ISO_8859_1_A4 KEY_E + ALTGR_MASK // 164 ¤ Currency Sign -#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR -#define ISO_8859_1_A7 KEY_3 + SHIFT_MASK // 167 § SECTION SIGN -#define ISO_8859_1_A8 0 // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN -#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN -#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF 0 // 175 ¯ MACRON -#define ISO_8859_1_B0 KEY_TILDE + SHIFT_MASK // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 KEY_2 + ALTGR_MASK // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 KEY_3 + ALTGR_MASK // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 0 // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 KEY_M + ALTGR_MASK // 181 µ MICRO SIGN -#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT -#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA -#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE -#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE -#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 0 // 195 Ã A TILDE -#define ISO_8859_1_C4 KEY_QUOTE + SHIFT_MASK // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE -#define ISO_8859_1_C6 0 // 198 Æ AE -#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA -#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE -#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE -#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB 0 // 203 Ë E DIAERESIS -#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE -#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE -#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF 0 // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 0 // 208 Ð ETH -#define ISO_8859_1_D1 0 // 209 Ñ N TILDE -#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE -#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE -#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 0 // 213 Õ O TILDE -#define ISO_8859_1_D6 KEY_SEMICOLON + SHIFT_MASK // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION -#define ISO_8859_1_D8 0 // 216 Ø O STROKE -#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE -#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE -#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC KEY_LEFT_BRACE + SHIFT_MASK // 220 Ü U DIAERESIS -#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Z + SHIFT_MASK // 221 Ý Y ACUTE -#define ISO_8859_1_DE 0 // 222 Þ THORN -#define ISO_8859_1_DF KEY_MINUS // 223 ß SHARP S -#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE -#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE -#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 0 // 227 ã a TILDE -#define ISO_8859_1_E4 KEY_QUOTE // 228 ä a DIAERESIS -#define ISO_8859_1_E5 0 // 229 å a RING ABOVE -#define ISO_8859_1_E6 0 // 230 æ ae -#define ISO_8859_1_E7 0 // 231 ç c CEDILLA -#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE -#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE -#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB 0 // 235 ë e DIAERESIS -#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE -#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE -#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF 0 // 239 ï i DIAERESIS -#define ISO_8859_1_F0 0 // 240 ð ETH -#define ISO_8859_1_F1 0 // 241 ñ n TILDE -#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE -#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE -#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 0 // 245 õ o TILDE -#define ISO_8859_1_F6 KEY_SEMICOLON // 246 ö o DIAERESIS -#define ISO_8859_1_F7 0 // 247 ÷ DIVISION -#define ISO_8859_1_F8 0 // 248 ø o STROKE -#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE -#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE -#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC KEY_LEFT_BRACE // 252 ü u DIAERESIS -#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Z // 253 ý y ACUTE -#define ISO_8859_1_FE 0 // 254 þ THORN -#define ISO_8859_1_FF 0 // 255 ÿ y DIAERESIS -#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign -// not yet implemented -#define UNICODE_EXTRA00 0x20AC -#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign - -#endif // LAYOUT_GERMAN - - - -#ifdef LAYOUT_GERMAN_MAC - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define DEADKEYS_MASK 0x0700 -#define ACUTE_ACCENT_BITS 0x0100 -#define GRAVE_ACCENT_BITS 0x0200 -#define CIRCUMFLEX_BITS 0x0300 -#define DIAERESIS_BITS 0x0400 -#define TILDE_BITS 0x0500 -#define KEYCODE_TYPE uint16_t -#define DEADKEY_ACUTE_ACCENT KEY_EQUAL -#define DEADKEY_GRAVE_ACCENT KEY_EQUAL + SHIFT_MASK -#define DEADKEY_CIRCUMFLEX KEY_6 + SHIFT_MASK + ALTGR_MASK -#define DEADKEY_DIAERESIS KEY_U + ALTGR_MASK -#define DEADKEY_TILDE KEY_N + ALTGR_MASK -#define KEY_NON_US_100 63 - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! -#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " -#define ASCII_23 KEY_BACKSLASH // 35 # ?? -#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ -#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % -#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & -#define ASCII_27 KEY_BACKSLASH + SHIFT_MASK // 39 ' -#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) -#define ASCII_2A KEY_RIGHT_BRACE + SHIFT_MASK // 42 * -#define ASCII_2B KEY_RIGHT_BRACE // 43 + -#define ASCII_2C KEY_COMMA // 44 , -#define ASCII_2D KEY_SLASH // 45 - -#define ASCII_2E KEY_PERIOD // 46 . -#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / -#define ASCII_30 KEY_0 // 48 0 -#define ASCII_31 KEY_1 // 49 1 -#define ASCII_32 KEY_2 // 50 2 -#define ASCII_33 KEY_3 // 51 3 -#define ASCII_34 KEY_4 // 52 4 -#define ASCII_35 KEY_5 // 53 5 -#define ASCII_36 KEY_6 // 54 6 -#define ASCII_37 KEY_7 // 55 7 -#define ASCII_38 KEY_8 // 55 8 -#define ASCII_39 KEY_9 // 57 9 -#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : -#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; -#define ASCII_3C KEY_TILDE // 60 < -#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = -#define ASCII_3E KEY_TILDE + SHIFT_MASK // 62 > -#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_Q + ALTGR_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Z + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Y + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_5 + ALTGR_MASK // 91 [ -#define ASCII_5C KEY_7 + ALTGR_MASK + SHIFT_MASK // 92 -#define ASCII_5D KEY_6 + ALTGR_MASK // 93 ] -#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ -#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ -#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Z // 121 y -#define ASCII_7A KEY_Y // 122 z -#define ASCII_7B KEY_8 + ALTGR_MASK // 123 { -#define ASCII_7C KEY_7 + ALTGR_MASK // 124 | -#define ASCII_7D KEY_9 + ALTGR_MASK // 125 } -#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 -#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space -#define ISO_8859_1_A1 KEY_1 + ALTGR_MASK // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 KEY_4 + ALTGR_MASK // 162 ¢ Cent Sign -#define ISO_8859_1_A3 KEY_4 + SHIFT_MASK + ALTGR_MASK // 163 £ Pound Sign -#define ISO_8859_1_A4 KEY_E + ALTGR_MASK // 164 ¤ Currency Sign -#define ISO_8859_1_A5 KEY_Z + ALTGR_MASK // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR -#define ISO_8859_1_A7 KEY_3 + SHIFT_MASK // 167 § SECTION SIGN -#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 KEY_G + ALTGR_MASK // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA KEY_H + ALTGR_MASK // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB KEY_Q + ALTGR_MASK // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN -#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN -#define ISO_8859_1_AE KEY_R + ALTGR_MASK // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF KEY_0 + SHIFT_MASK + ALTGR_MASK // 175 ¯ MACRON -#define ISO_8859_1_B0 KEY_LEFT_BRACE + ALTGR_MASK + SHIFT_MASK// 176 ° DEGREE SIGN -#define ISO_8859_1_B1 KEY_RIGHT_BRACE + ALTGR_MASK // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 KEY_M + ALTGR_MASK // 181 µ MICRO SIGN -#define ISO_8859_1_B6 KEY_3 + ALTGR_MASK // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 KEY_9 + SHIFT_MASK + ALTGR_MASK // 183 · MIDDLE DOT -#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA -#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA KEY_J + ALTGR_MASK // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB KEY_Q + SHIFT_MASK + ALTGR_MASK // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF KEY_MINUS + ALTGR_MASK // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE -#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE -#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE -#define ISO_8859_1_C4 KEY_QUOTE + SHIFT_MASK // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 KEY_A + ALTGR_MASK + SHIFT_MASK // 197 Å A RING ABOVE -#define ISO_8859_1_C6 KEY_QUOTE + ALTGR_MASK + SHIFT_MASK // 198 Æ AE -#define ISO_8859_1_C7 KEY_C + ALTGR_MASK + SHIFT_MASK // 199 Ç C CEDILLA -#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE -#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE -#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS -#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE -#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE -#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 0 // 208 Ð ETH -#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE -#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE -#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE -#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE -#define ISO_8859_1_D6 KEY_SEMICOLON + SHIFT_MASK // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION -#define ISO_8859_1_D8 KEY_O + ALTGR_MASK + SHIFT_MASK // 216 Ø O STROKE -#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE -#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE -#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC KEY_LEFT_BRACE + SHIFT_MASK // 220 Ü U DIAERESIS -#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Z + SHIFT_MASK // 221 Ý Y ACUTE -#define ISO_8859_1_DE 0 // 222 Þ THORN -#define ISO_8859_1_DF KEY_MINUS // 223 ß SHARP S -#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE -#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE -#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE -#define ISO_8859_1_E4 KEY_QUOTE // 228 ä a DIAERESIS -#define ISO_8859_1_E5 KEY_A + ALTGR_MASK // 229 å a RING ABOVE -#define ISO_8859_1_E6 KEY_QUOTE + ALTGR_MASK // 230 æ ae -#define ISO_8859_1_E7 KEY_C + ALTGR_MASK // 231 ç c CEDILLA -#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE -#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE -#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS -#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE -#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE -#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS -#define ISO_8859_1_F0 0 // 240 ð ETH -#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE -#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE -#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE -#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE -#define ISO_8859_1_F6 KEY_SEMICOLON // 246 ö o DIAERESIS -#define ISO_8859_1_F7 0 // 247 ÷ DIVISION -#define ISO_8859_1_F8 KEY_O + ALTGR_MASK // 248 ø o STROKE -#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE -#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE -#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC KEY_LEFT_BRACE // 252 ü u DIAERESIS -#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Z // 253 ý y ACUTE -#define ISO_8859_1_FE 0 // 254 þ THORN -#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Z // 255 ÿ y DIAERESIS -#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign -// not yet implemented -#define UNICODE_EXTRA00 0x20AC -#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign - -#endif // LAYOUT_GERMAN_MAC - - - - - - -#ifdef LAYOUT_CANADIAN_FRENCH - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define DEADKEYS_MASK 0x0700 -#define CIRCUMFLEX_BITS 0x0100 -#define ACUTE_ACCENT_BITS 0x0200 -#define GRAVE_ACCENT_BITS 0x0300 -#define DIAERESIS_BITS 0x0400 -#define CEDILLA_BITS 0x0500 - -#define KEYCODE_TYPE uint16_t -#define DEADKEY_CIRCUMFLEX KEY_LEFT_BRACE -#define DEADKEY_ACUTE_ACCENT KEY_SLASH + ALTGR_MASK -#define DEADKEY_GRAVE_ACCENT KEY_QUOTE -#define DEADKEY_DIAERESIS KEY_RIGHT_BRACE + SHIFT_MASK -#define DEADKEY_CEDILLA KEY_RIGHT_BRACE -#define KEY_NON_US_100 63 - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! -#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " -#define ASCII_23 KEY_TILDE + SHIFT_MASK // 35 # -#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ -#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % -#define ASCII_26 KEY_7 + SHIFT_MASK // 38 & -#define ASCII_27 KEY_COMMA + SHIFT_MASK // 39 ' -//#define ASCII_27 ACUTE_ACCENT_BITS + KEY_SPACE // 39 ' -#define ASCII_28 KEY_9 + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_0 + SHIFT_MASK // 41 ) -#define ASCII_2A KEY_8 + SHIFT_MASK // 42 * -#define ASCII_2B KEY_EQUAL + SHIFT_MASK // 43 + -#define ASCII_2C KEY_COMMA // 44 , -#define ASCII_2D KEY_MINUS // 45 - -#define ASCII_2E KEY_PERIOD // 46 . -#define ASCII_2F KEY_3 + SHIFT_MASK // 47 / -#define ASCII_30 KEY_0 // 48 0 -#define ASCII_31 KEY_1 // 49 1 -#define ASCII_32 KEY_2 // 50 2 -#define ASCII_33 KEY_3 // 51 3 -#define ASCII_34 KEY_4 // 52 4 -#define ASCII_35 KEY_5 // 53 5 -#define ASCII_36 KEY_6 // 54 6 -#define ASCII_37 KEY_7 // 55 7 -#define ASCII_38 KEY_8 // 55 8 -#define ASCII_39 KEY_9 // 57 9 -#define ASCII_3A KEY_SEMICOLON + SHIFT_MASK // 58 : -#define ASCII_3B KEY_SEMICOLON // 59 ; -#define ASCII_3C KEY_BACKSLASH // 60 < -#define ASCII_3D KEY_EQUAL // 61 = -#define ASCII_3E KEY_BACKSLASH + SHIFT_MASK // 62 > -#define ASCII_3F KEY_6 + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_2 + ALTGR_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_LEFT_BRACE + ALTGR_MASK // 91 [ -#define ASCII_5C KEY_TILDE + ALTGR_MASK // 92 -#define ASCII_5D KEY_RIGHT_BRACE + ALTGR_MASK // 93 ] -#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ -#define ASCII_5F KEY_MINUS + SHIFT_MASK // 95 _ -#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Y // 121 y -#define ASCII_7A KEY_Z // 122 z -#define ASCII_7B KEY_QUOTE + ALTGR_MASK // 123 { -#define ASCII_7C KEY_TILDE + SHIFT_MASK // 124 | -#define ASCII_7D KEY_BACKSLASH + ALTGR_MASK // 125 } -#define ASCII_7E KEY_SEMICOLON + ALTGR_MASK // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 -#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space -#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 KEY_4 + ALTGR_MASK // 162 ¢ Cent SIGN -#define ISO_8859_1_A3 KEY_3 + ALTGR_MASK // 163 £ Pound Sign -#define ISO_8859_1_A4 KEY_5 + ALTGR_MASK // 164 ¤ Currency or Euro Sign -#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 KEY_7 + ALTGR_MASK // 166 ¦ BROKEN BAR -#define ISO_8859_1_A7 KEY_O + ALTGR_MASK // 167 § SECTION SIGN -#define ISO_8859_1_A8 0 // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB KEY_NON_US_100 // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC KEY_6 + ALTGR_MASK // 172 ¬ NOT SIGN -#define ISO_8859_1_AD KEY_PERIOD + ALTGR_MASK // 173 SOFT HYPHEN -#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF KEY_COMMA + ALTGR_MASK // 175 ¯ MACRON -#define ISO_8859_1_B0 KEY_NON_US_100 + ALTGR_MASK // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 KEY_1 + ALTGR_MASK // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 KEY_8 + ALTGR_MASK // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 KEY_9 + ALTGR_MASK // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 0 // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 KEY_M + ALTGR_MASK // 181 µ MICRO SIGN -#define ISO_8859_1_B6 KEY_P + ALTGR_MASK // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT -#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA -#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB KEY_NON_US_100 + SHIFT_MASK // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC KEY_0 + ALTGR_MASK // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD KEY_MINUS + ALTGR_MASK // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE KEY_EQUAL + ALTGR_MASK // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE -#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE -#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 0 // 195 Ã A TILDE -#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE -#define ISO_8859_1_C6 0 // 198 Æ AE -#define ISO_8859_1_C7 CEDILLA_BITS + KEY_C + SHIFT_MASK // 199 Ç C CEDILLA -#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE -#define ISO_8859_1_C9 KEY_SLASH + SHIFT_MASK // 201 É E ACUTE -#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS -#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE -#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE -#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 0 // 208 Ð ETH -#define ISO_8859_1_D1 0 // 209 Ñ N TILDE -#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE -#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE -#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 0 // 213 Õ O TILDE -#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION -#define ISO_8859_1_D8 0 // 216 Ø O STROKE -#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE -#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE -#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U // 220 Ü U DIAERESIS -#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE -#define ISO_8859_1_DE 0 // 222 Þ THORN -#define ISO_8859_1_DF 0 // 223 ß SHARP S -#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE -#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE -#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 0 // 227 ã a TILDE -#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS -#define ISO_8859_1_E5 0 // 229 å a RING ABOVE -#define ISO_8859_1_E6 0 // 230 æ ae -#define ISO_8859_1_E7 CEDILLA_BITS + KEY_C // 231 ç c CEDILLA -#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE -#define ISO_8859_1_E9 KEY_SLASH // 233 é e ACUTE -#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS -#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE -#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE -#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS -#define ISO_8859_1_F0 0 // 240 ð ETH -#define ISO_8859_1_F1 0 // 241 ñ n TILDE -#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE -#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE -#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 0 // 245 õ o TILDE -#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS -#define ISO_8859_1_F7 0 // 247 ÷ DIVISION -#define ISO_8859_1_F8 0 // 248 ø o STROKE -#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE -#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE -#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS -#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE -#define ISO_8859_1_FE 0 // 254 þ THORN -#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS - -#endif // LAYOUT_CANADIAN_FRENCH - - - -#ifdef LAYOUT_CANADIAN_MULTILINGUAL - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define RCTRL_MASK 0x0800 -#define DEADKEYS_MASK 0x0700 -#define CIRCUMFLEX_BITS 0x0100 -#define DIAERESIS_BITS 0x0200 -#define ACUTE_ACCENT_BITS 0x0300 -#define CEDILLA_BITS 0x0400 -#define GRAVE_ACCENT_BITS 0x0500 -#define TILDE_BITS 0x0600 -#define RING_ABOVE_BITS 0x0700 -#define KEYCODE_TYPE uint16_t -#define DEADKEY_CIRCUMFLEX KEY_LEFT_BRACE -#define DEADKEY_DIAERESIS KEY_LEFT_BRACE + SHIFT_MASK -#define DEADKEY_ACUTE_ACCENT KEY_SEMICOLON + RCTRL_MASK -#define DEADKEY_CEDILLA KEY_EQUAL + RCTRL_MASK -#define DEADKEY_GRAVE_ACCENT KEY_LEFT_BRACE + ALTGR_MASK -#define DEADKEY_TILDE KEY_RIGHT_BRACE + ALTGR_MASK -#define DEADKEY_RING_ABOVE KEY_LEFT_BRACE + SHIFT_MASK + RCTRL_MASK -#define KEY_NON_US_100 63 - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! -#define ASCII_22 KEY_PERIOD + SHIFT_MASK // 34 " -#define ASCII_23 KEY_3 + SHIFT_MASK // 35 # -#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ -#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % -#define ASCII_26 KEY_7 + SHIFT_MASK // 38 & -#define ASCII_27 KEY_COMMA + SHIFT_MASK // 39 ' -#define ASCII_28 KEY_9 + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_0 + SHIFT_MASK // 41 ) -#define ASCII_2A KEY_8 + SHIFT_MASK // 42 * -#define ASCII_2B KEY_EQUAL + SHIFT_MASK // 43 + -#define ASCII_2C KEY_COMMA // 44 , -#define ASCII_2D KEY_MINUS // 45 - -#define ASCII_2E KEY_PERIOD // 46 . -#define ASCII_2F KEY_TILDE // 47 / -#define ASCII_30 KEY_0 // 48 0 -#define ASCII_31 KEY_1 // 49 1 -#define ASCII_32 KEY_2 // 50 2 -#define ASCII_33 KEY_3 // 51 3 -#define ASCII_34 KEY_4 // 52 4 -#define ASCII_35 KEY_5 // 53 5 -#define ASCII_36 KEY_6 // 54 6 -#define ASCII_37 KEY_7 // 55 7 -#define ASCII_38 KEY_8 // 55 8 -#define ASCII_39 KEY_9 // 57 9 -#define ASCII_3A KEY_SEMICOLON + SHIFT_MASK // 58 : -#define ASCII_3B KEY_SEMICOLON // 59 ; -#define ASCII_3C KEY_COMMA + ALTGR_MASK // 60 < -#define ASCII_3D KEY_EQUAL // 61 = -#define ASCII_3E KEY_PERIOD + ALTGR_MASK // 62 > -#define ASCII_3F KEY_6 + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_2 + SHIFT_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_9 + ALTGR_MASK // 91 [ -#define ASCII_5C KEY_TILDE + SHIFT_MASK // 92 -#define ASCII_5D KEY_0 + ALTGR_MASK // 93 ] -#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ -#define ASCII_5F KEY_MINUS + SHIFT_MASK // 95 _ -#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Y // 121 y -#define ASCII_7A KEY_Z // 122 z -#define ASCII_7B KEY_7 + ALTGR_MASK // 123 { -#define ASCII_7C KEY_TILDE + ALTGR_MASK // 124 | -#define ASCII_7D KEY_8 + ALTGR_MASK // 125 } -#define ASCII_7E KEY_RIGHT_BRACE + RCTRL_MASK // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 -#define ISO_8859_1_A0 KEY_SPACE + ALTGR_MASK // 160 Nonbreakng Space -#define ISO_8859_1_A1 KEY_1 + SHIFT_MASK + RCTRL_MASK // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 KEY_C + RCTRL_MASK // 162 ¢ Cent SIGN -#define ISO_8859_1_A3 KEY_3 + SHIFT_MASK + RCTRL_MASK // 163 £ Pound Sign -#define ISO_8859_1_A4 KEY_4 + SHIFT_MASK + RCTRL_MASK // 164 ¤ Currency or Euro Sign -#define ISO_8859_1_A5 KEY_Y + SHIFT_MASK + RCTRL_MASK // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 KEY_NON_US_100 + SHIFT_MASK + RCTRL_MASK// 166 ¦ BROKEN BAR -#define ISO_8859_1_A7 KEY_S + SHIFT_MASK + RCTRL_MASK // 167 § SECTION SIGN -#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 KEY_C + SHIFT_MASK + RCTRL_MASK // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA KEY_F + SHIFT_MASK + RCTRL_MASK // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB KEY_Z + ALTGR_MASK // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC KEY_EQUAL + ALTGR_MASK // 172 ¬ NOT SIGN -#define ISO_8859_1_AD KEY_TILDE + SHIFT_MASK + RCTRL_MASK // 173 SOFT HYPHEN -#define ISO_8859_1_AE KEY_R + SHIFT_MASK + RCTRL_MASK // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF 0 // special dead key - no implemented // 175 ¯ MACRON -#define ISO_8859_1_B0 KEY_SEMICOLON + ALTGR_MASK // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 KEY_9 + SHIFT_MASK + RCTRL_MASK // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 KEY_2 + RCTRL_MASK // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 KEY_3 + RCTRL_MASK // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 KEY_M + RCTRL_MASK // 181 µ MICRO SIGN -#define ISO_8859_1_B6 KEY_R + RCTRL_MASK // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT -#define ISO_8859_1_B8 CEDILLA_BITS + KEY_SPACE // 184 ¸ CEDILLA -#define ISO_8859_1_B9 KEY_1 + RCTRL_MASK // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA KEY_M + SHIFT_MASK + RCTRL_MASK // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB KEY_X + ALTGR_MASK // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC KEY_4 + RCTRL_MASK // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD KEY_5 + RCTRL_MASK // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE KEY_6 + RCTRL_MASK // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF KEY_MINUS + SHIFT_MASK + RCTRL_MASK // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 KEY_BACKSLASH + SHIFT_MASK // 192 À A GRAVE -#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE -#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE -#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 RING_ABOVE_BITS + KEY_A + SHIFT_MASK // 197 Å A RING ABOVE -#define ISO_8859_1_C6 KEY_A + SHIFT_MASK + RCTRL_MASK // 198 Æ AE -#define ISO_8859_1_C7 KEY_RIGHT_BRACE + SHIFT_MASK // 199 Ç C CEDILLA -#define ISO_8859_1_C8 KEY_QUOTE + SHIFT_MASK // 200 È E GRAVE -#define ISO_8859_1_C9 KEY_SLASH + SHIFT_MASK // 201 É E ACUTE -#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS -#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE -#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE -#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 KEY_D + SHIFT_MASK + RCTRL_MASK // 208 Ð ETH -#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE -#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE -#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE -#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE -#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 KEY_COMMA + SHIFT_MASK + RCTRL_MASK // 215 × MULTIPLICATION -#define ISO_8859_1_D8 KEY_O + SHIFT_MASK + RCTRL_MASK // 216 Ø O STROKE -#define ISO_8859_1_D9 KEY_NON_US_100 + SHIFT_MASK // 217 Ù U GRAVE -#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE -#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U // 220 Ü U DIAERESIS -#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE -#define ISO_8859_1_DE KEY_P + RCTRL_MASK + SHIFT_MASK // 222 Þ THORN -#define ISO_8859_1_DF KEY_S + RCTRL_MASK // 223 ß SHARP S -#define ISO_8859_1_E0 KEY_BACKSLASH // 224 à a GRAVE -#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE -#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE -#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS -#define ISO_8859_1_E5 RING_ABOVE_BITS + KEY_A // 229 å a RING ABOVE -#define ISO_8859_1_E6 KEY_A + RCTRL_MASK // 230 æ ae -#define ISO_8859_1_E7 KEY_RIGHT_BRACE // 231 ç c CEDILLA -#define ISO_8859_1_E8 KEY_QUOTE // 232 è e GRAVE -#define ISO_8859_1_E9 KEY_SLASH // 233 é e ACUTE -#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS -#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE -#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE -#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS -#define ISO_8859_1_F0 KEY_D + RCTRL_MASK // 240 ð ETH -#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE -#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE -#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE -#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE -#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS -#define ISO_8859_1_F7 KEY_PERIOD + SHIFT_MASK + RCTRL_MASK // 247 ÷ DIVISION -#define ISO_8859_1_F8 KEY_O + RCTRL_MASK // 248 ø o STROKE -#define ISO_8859_1_F9 KEY_NON_US_100 // 249 ù u GRAVE -#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE -#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS -#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE -#define ISO_8859_1_FE KEY_P + RCTRL_MASK // 254 þ THORN -#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS - -#endif // LAYOUT_CANADIAN_MULTILINGUAL - - - - - - -#ifdef LAYOUT_UNITED_KINGDOM - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define KEYCODE_TYPE uint8_t -#define KEY_NON_US_100 63 - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! -#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " -#define ASCII_23 KEY_BACKSPACE // 35 # -#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ -#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % -#define ASCII_26 KEY_7 + SHIFT_MASK // 38 & -#define ASCII_27 KEY_QUOTE // 39 ' -#define ASCII_28 KEY_9 + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_0 + SHIFT_MASK // 41 ) -#define ASCII_2A KEY_8 + SHIFT_MASK // 42 * -#define ASCII_2B KEY_EQUAL + SHIFT_MASK // 43 + -#define ASCII_2C KEY_COMMA // 44 , -#define ASCII_2D KEY_MINUS // 45 - -#define ASCII_2E KEY_PERIOD // 46 . -#define ASCII_2F KEY_SLASH // 47 / -#define ASCII_30 KEY_0 // 48 0 -#define ASCII_31 KEY_1 // 49 1 -#define ASCII_32 KEY_2 // 50 2 -#define ASCII_33 KEY_3 // 51 3 -#define ASCII_34 KEY_4 // 52 4 -#define ASCII_35 KEY_5 // 53 5 -#define ASCII_36 KEY_6 // 54 6 -#define ASCII_37 KEY_7 // 55 7 -#define ASCII_38 KEY_8 // 55 8 -#define ASCII_39 KEY_9 // 57 9 -#define ASCII_3A KEY_SEMICOLON + SHIFT_MASK // 58 : -#define ASCII_3B KEY_SEMICOLON // 59 ; -#define ASCII_3C KEY_COMMA + SHIFT_MASK // 60 < -#define ASCII_3D KEY_EQUAL // 61 = -#define ASCII_3E KEY_PERIOD + SHIFT_MASK // 62 > -#define ASCII_3F KEY_SLASH + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_QUOTE + SHIFT_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_LEFT_BRACE // 91 [ -#define ASCII_5C KEY_NON_US_100 // 92 -#define ASCII_5D KEY_RIGHT_BRACE // 93 ] -#define ASCII_5E KEY_6 + SHIFT_MASK // 94 ^ -#define ASCII_5F KEY_MINUS + SHIFT_MASK // 95 _ -#define ASCII_60 KEY_TILDE // 96 ` -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Y // 121 y -#define ASCII_7A KEY_Z // 122 z -#define ASCII_7B KEY_LEFT_BRACE + SHIFT_MASK // 123 { -#define ASCII_7C KEY_NON_US_100 + SHIFT_MASK // 124 | -#define ASCII_7D KEY_RIGHT_BRACE + SHIFT_MASK // 125 } -#define ASCII_7E KEY_BACKSLASH + SHIFT_MASK // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 - -#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space -#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN -#define ISO_8859_1_A3 KEY_3 + SHIFT_MASK // 163 £ Pound Sign -#define ISO_8859_1_A4 0 // 164 ¤ Currency or Euro Sign -#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 KEY_TILDE + ALTGR_MASK // 166 ¦ BROKEN BAR -#define ISO_8859_1_A7 0 // 167 § SECTION SIGN -#define ISO_8859_1_A8 0 // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC KEY_TILDE + SHIFT_MASK // 172 ¬ NOT SIGN -#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN -#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF 0 // 175 ¯ MACRON -#define ISO_8859_1_B0 0 // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 0 // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN -#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT -#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA -#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 0 // 192 À A GRAVE -#define ISO_8859_1_C1 KEY_A + ALTGR_MASK + SHIFT_MASK // 193 Á A ACUTE -#define ISO_8859_1_C2 0 // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 0 // 195 Ã A TILDE -#define ISO_8859_1_C4 0 // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE -#define ISO_8859_1_C6 0 // 198 Æ AE -#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA -#define ISO_8859_1_C8 0 // 200 È E GRAVE -#define ISO_8859_1_C9 KEY_E + ALTGR_MASK + SHIFT_MASK // 201 É E ACUTE -#define ISO_8859_1_CA 0 // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB 0 // 203 Ë E DIAERESIS -#define ISO_8859_1_CC 0 // 204 Ì I GRAVE -#define ISO_8859_1_CD KEY_I + ALTGR_MASK + SHIFT_MASK // 205 Í I ACUTE -#define ISO_8859_1_CE 0 // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF 0 // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 0 // 208 Ð ETH -#define ISO_8859_1_D1 0 // 209 Ñ N TILDE -#define ISO_8859_1_D2 0 // 210 Ò O GRAVE -#define ISO_8859_1_D3 KEY_O + ALTGR_MASK + SHIFT_MASK // 211 Ó O ACUTE -#define ISO_8859_1_D4 0 // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 0 // 213 Õ O TILDE -#define ISO_8859_1_D6 0 // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION -#define ISO_8859_1_D8 0 // 216 Ø O STROKE -#define ISO_8859_1_D9 0 // 217 Ù U GRAVE -#define ISO_8859_1_DA KEY_U + ALTGR_MASK + SHIFT_MASK // 218 Ú U ACUTE -#define ISO_8859_1_DB 0 // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC 0 // 220 Ü U DIAERESIS -#define ISO_8859_1_DD 0 // 221 Ý Y ACUTE -#define ISO_8859_1_DE 0 // 222 Þ THORN -#define ISO_8859_1_DF 0 // 223 ß SHARP S -#define ISO_8859_1_E0 0 // 224 à a GRAVE -#define ISO_8859_1_E1 KEY_A + ALTGR_MASK // 225 á a ACUTE -#define ISO_8859_1_E2 0 // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 0 // 227 ã a TILDE -#define ISO_8859_1_E4 0 // 228 ä a DIAERESIS -#define ISO_8859_1_E5 0 // 229 å a RING ABOVE -#define ISO_8859_1_E6 0 // 230 æ ae -#define ISO_8859_1_E7 0 // 231 ç c CEDILLA -#define ISO_8859_1_E8 0 // 232 è e GRAVE -#define ISO_8859_1_E9 KEY_E + ALTGR_MASK // 233 é e ACUTE -#define ISO_8859_1_EA 0 // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB 0 // 235 ë e DIAERESIS -#define ISO_8859_1_EC 0 // 236 ì i GRAVE -#define ISO_8859_1_ED KEY_I + ALTGR_MASK // 237 í i ACUTE -#define ISO_8859_1_EE 0 // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF 0 // 239 ï i DIAERESIS -#define ISO_8859_1_F0 0 // 240 ð ETH -#define ISO_8859_1_F1 0 // 241 ñ n TILDE -#define ISO_8859_1_F2 0 // 242 ò o GRAVE -#define ISO_8859_1_F3 KEY_O + ALTGR_MASK // 243 ó o ACUTE -#define ISO_8859_1_F4 0 // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 0 // 245 õ o TILDE -#define ISO_8859_1_F6 0 // 246 ö o DIAERESIS -#define ISO_8859_1_F7 0 // 247 ÷ DIVISION -#define ISO_8859_1_F8 0 // 248 ø o STROKE -#define ISO_8859_1_F9 0 // 249 ù u GRAVE -#define ISO_8859_1_FA KEY_U + ALTGR_MASK // 250 ú u ACUTE -#define ISO_8859_1_FB 0 // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC 0 // 252 ü u DIAERESIS -#define ISO_8859_1_FD 0 // 253 ý y ACUTE -#define ISO_8859_1_FE 0 // 254 þ THORN -#define ISO_8859_1_FF 0 // 255 ÿ y DIAERESIS -#define UNICODE_20AC KEY_4 + ALTGR_MASK // € Euro Sign -// not yet implemented -#define UNICODE_EXTRA00 0x20AC -#define KEYCODE_EXTRA00 KEY_4 + ALTGR_MASK // 20AC € Euro Sign - -#endif // LAYOUT_UNITED_KINGDOM - - - -#ifdef LAYOUT_FINNISH - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define DEADKEYS_MASK 0x0700 -#define CIRCUMFLEX_BITS 0x0100 -#define ACUTE_ACCENT_BITS 0x0200 -#define GRAVE_ACCENT_BITS 0x0300 -#define TILDE_BITS 0x0400 -#define DIAERESIS_BITS 0x0500 -#define KEYCODE_TYPE uint16_t -#define DEADKEY_CIRCUMFLEX KEY_RIGHT_BRACE + SHIFT_MASK -#define DEADKEY_ACUTE_ACCENT KEY_EQUAL -#define DEADKEY_GRAVE_ACCENT KEY_EQUAL + SHIFT_MASK -#define DEADKEY_TILDE KEY_RIGHT_BRACE + ALTGR_MASK -#define DEADKEY_DIAERESIS KEY_RIGHT_BRACE -#define KEY_NON_US_100 63 - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! -#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " -#define ASCII_23 KEY_3 + SHIFT_MASK // 35 # -#define ASCII_24 KEY_4 + ALTGR_MASK // 36 $ -#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % -#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & -#define ASCII_27 KEY_BACKSLASH // 39 ' -#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) -#define ASCII_2A KEY_BACKSLASH + SHIFT_MASK // 42 * -#define ASCII_2B KEY_MINUS // 43 + -#define ASCII_2C KEY_COMMA // 44 , -#define ASCII_2D KEY_SLASH // 45 - -#define ASCII_2E KEY_PERIOD // 46 . -#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / -#define ASCII_30 KEY_0 // 48 0 -#define ASCII_31 KEY_1 // 49 1 -#define ASCII_32 KEY_2 // 50 2 -#define ASCII_33 KEY_3 // 51 3 -#define ASCII_34 KEY_4 // 52 4 -#define ASCII_35 KEY_5 // 53 5 -#define ASCII_36 KEY_6 // 54 6 -#define ASCII_37 KEY_7 // 55 7 -#define ASCII_38 KEY_8 // 55 8 -#define ASCII_39 KEY_9 // 57 9 -#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : -#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; -#define ASCII_3C KEY_NON_US_100 // 60 < -#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = -#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > -#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_2 + ALTGR_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_8 + ALTGR_MASK // 91 [ -#define ASCII_5C KEY_MINUS + ALTGR_MASK // 92 -#define ASCII_5D KEY_9 + ALTGR_MASK // 93 ] -#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ -#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ -#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Y // 121 y -#define ASCII_7A KEY_Z // 122 z -#define ASCII_7B KEY_7 + ALTGR_MASK // 123 { -#define ASCII_7C KEY_NON_US_100 + ALTGR_MASK // 124 | -#define ASCII_7D KEY_0 + ALTGR_MASK // 125 } -#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 -#define ISO_8859_1_A0 KEY_SPACE + ALTGR_MASK // 160 Nonbreakng Space -#define ISO_8859_1_A1 KEY_1 + SHIFT_MASK + ALTGR_MASK // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN -#define ISO_8859_1_A3 KEY_3 + ALTGR_MASK // 163 £ Pound Sign -#define ISO_8859_1_A4 KEY_4 + SHIFT_MASK // 164 ¤ Currency or Euro Sign -#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR -#define ISO_8859_1_A7 KEY_TILDE // 167 § SECTION SIGN -#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB KEY_4 + ALTGR_MASK + SHIFT_MASK // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN -#define ISO_8859_1_AD KEY_SLASH + ALTGR_MASK // 173 SOFT HYPHEN -#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF 0 // 175 ¯ MACRON -#define ISO_8859_1_B0 KEY_0 + ALTGR_MASK + SHIFT_MASK // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 KEY_M + ALTGR_MASK // 181 µ MICRO SIGN -#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 KEY_X + ALTGR_MASK + SHIFT_MASK // 183 · MIDDLE DOT -#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA -#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB KEY_3 + ALTGR_MASK + SHIFT_MASK // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD KEY_TILDE + SHIFT_MASK // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF KEY_MINUS + ALTGR_MASK + SHIFT_MASK // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE -#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE -#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE -#define ISO_8859_1_C4 KEY_QUOTE + SHIFT_MASK // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 KEY_LEFT_BRACE + SHIFT_MASK // 197 Å A RING ABOVE -#define ISO_8859_1_C6 KEY_QUOTE + ALTGR_MASK + SHIFT_MASK // 198 Æ AE -#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA -#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE -#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE -#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS -#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE -#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE -#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 KEY_D + ALTGR_MASK + SHIFT_MASK // 208 Ð ETH -#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE -#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE -#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE -#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE -#define ISO_8859_1_D6 KEY_SEMICOLON + SHIFT_MASK // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 KEY_X + ALTGR_MASK // 215 × MULTIPLICATION -#define ISO_8859_1_D8 KEY_SEMICOLON + ALTGR_MASK + SHIFT_MASK // 216 Ø O STROKE -#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE -#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE -#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS -#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE -#define ISO_8859_1_DE KEY_T + ALTGR_MASK + SHIFT_MASK // 222 Þ THORN -#define ISO_8859_1_DF KEY_S + ALTGR_MASK // 223 ß SHARP S -#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE -#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE -#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE -#define ISO_8859_1_E4 KEY_QUOTE // 228 ä a DIAERESIS -#define ISO_8859_1_E5 KEY_LEFT_BRACE // 229 å a RING ABOVE -#define ISO_8859_1_E6 KEY_QUOTE + ALTGR_MASK // 230 æ ae -#define ISO_8859_1_E7 0 // 231 ç c CEDILLA -#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE -#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE -#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS -#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE -#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE -#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS -#define ISO_8859_1_F0 KEY_D + ALTGR_MASK // 240 ð ETH -#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE -#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE -#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE -#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE -#define ISO_8859_1_F6 KEY_SEMICOLON // 246 ö o DIAERESIS -#define ISO_8859_1_F7 0 // 247 ÷ DIVISION -#define ISO_8859_1_F8 KEY_SEMICOLON + ALTGR_MASK // 248 ø o STROKE -#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE -#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE -#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS -#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE -#define ISO_8859_1_FE KEY_T + ALTGR_MASK // 254 þ THORN -#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS -#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign -// not yet implemented -#define UNICODE_EXTRA00 0x20AC -#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign -// TODO: Finnish Multilingual layout can type many more glyphs -// but we currently don't have tables tables to store them... - -#endif // LAYOUT_FINNISH - - - - - - - -#ifdef LAYOUT_FRENCH - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define DEADKEYS_MASK 0x0700 -#define CIRCUMFLEX_BITS 0x0100 -#define GRAVE_ACCENT_BITS 0x0200 -#define DIAERESIS_BITS 0x0300 -#define TILDE_BITS 0x0400 -#define KEYCODE_TYPE uint16_t -#define DEADKEY_CIRCUMFLEX KEY_LEFT_BRACE -#define DEADKEY_GRAVE_ACCENT KEY_7 + ALTGR_MASK -#define DEADKEY_DIAERESIS KEY_LEFT_BRACE + SHIFT_MASK -#define DEADKEY_TILDE KEY_2 + ALTGR_MASK -#define KEY_NON_US_100 63 - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_SLASH // 33 ! -#define ASCII_22 KEY_3 // 34 " -#define ASCII_23 KEY_3 + ALTGR_MASK // 35 # -#define ASCII_24 KEY_RIGHT_BRACE // 36 $ -#define ASCII_25 KEY_QUOTE + SHIFT_MASK // 37 % -#define ASCII_26 KEY_1 // 38 & -#define ASCII_27 KEY_4 // 39 ' -#define ASCII_28 KEY_5 // 40 ( -#define ASCII_29 KEY_MINUS // 41 ) -#define ASCII_2A KEY_BACKSLASH // 42 * -#define ASCII_2B KEY_EQUAL + SHIFT_MASK // 43 + -#define ASCII_2C KEY_M // 44 , -#define ASCII_2D KEY_6 // 45 - -#define ASCII_2E KEY_COMMA + SHIFT_MASK // 46 . -#define ASCII_2F KEY_PERIOD + SHIFT_MASK // 47 / -#define ASCII_30 KEY_0 + SHIFT_MASK // 48 0 -#define ASCII_31 KEY_1 + SHIFT_MASK // 49 1 -#define ASCII_32 KEY_2 + SHIFT_MASK // 50 2 -#define ASCII_33 KEY_3 + SHIFT_MASK // 51 3 -#define ASCII_34 KEY_4 + SHIFT_MASK // 52 4 -#define ASCII_35 KEY_5 + SHIFT_MASK // 53 5 -#define ASCII_36 KEY_6 + SHIFT_MASK // 54 6 -#define ASCII_37 KEY_7 + SHIFT_MASK // 55 7 -#define ASCII_38 KEY_8 + SHIFT_MASK // 55 8 -#define ASCII_39 KEY_9 + SHIFT_MASK // 57 9 -#define ASCII_3A KEY_PERIOD // 58 : -#define ASCII_3B KEY_COMMA // 59 ; -#define ASCII_3C KEY_NON_US_100 // 60 < -#define ASCII_3D KEY_EQUAL // 61 = -#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > -#define ASCII_3F KEY_M + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_0 + ALTGR_MASK // 64 @ -#define ASCII_41 KEY_Q + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_SEMICOLON + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_A + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_Z + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_W + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_5 + ALTGR_MASK // 91 [ -#define ASCII_5C KEY_8 + ALTGR_MASK // 92 -#define ASCII_5D KEY_MINUS + ALTGR_MASK // 93 ] -#define ASCII_5E KEY_9 + ALTGR_MASK // 94 ^ -#define ASCII_5F KEY_8 // 95 _ -#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` -#define ASCII_61 KEY_Q // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_SEMICOLON // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_A // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_Z // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Y // 121 y -#define ASCII_7A KEY_W // 122 z -#define ASCII_7B KEY_4 + ALTGR_MASK // 123 { -#define ASCII_7C KEY_6 + ALTGR_MASK // 124 | -#define ASCII_7D KEY_EQUAL + ALTGR_MASK // 125 } -#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 -#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space -#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN -#define ISO_8859_1_A3 KEY_RIGHT_BRACE + SHIFT_MASK // 163 £ Pound Sign -#define ISO_8859_1_A4 KEY_RIGHT_BRACE + ALTGR_MASK // 164 ¤ Currency or Euro Sign -#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR -#define ISO_8859_1_A7 KEY_SLASH + SHIFT_MASK // 167 § SECTION SIGN -#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN -#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN -#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF 0 // 175 ¯ MACRON -#define ISO_8859_1_B0 KEY_MINUS + SHIFT_MASK // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 KEY_TILDE // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 0 // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 KEY_BACKSLASH + SHIFT_MASK // 181 µ MICRO SIGN -#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT -#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA -#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_Q + SHIFT_MASK // 192 À A GRAVE -#define ISO_8859_1_C1 0 // 193 Á A ACUTE -#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_Q + SHIFT_MASK // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 TILDE_BITS + KEY_Q + SHIFT_MASK // 195 Ã A TILDE -#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_Q + SHIFT_MASK // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE -#define ISO_8859_1_C6 0 // 198 Æ AE -#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA -#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE -#define ISO_8859_1_C9 0 // 201 É E ACUTE -#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS -#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE -#define ISO_8859_1_CD 0 // 205 Í I ACUTE -#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 0 // 208 Ð ETH -#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE -#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE -#define ISO_8859_1_D3 0 // 211 Ó O ACUTE -#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE -#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION -#define ISO_8859_1_D8 0 // 216 Ø O STROKE -#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE -#define ISO_8859_1_DA 0 // 218 Ú U ACUTE -#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U // 220 Ü U DIAERESIS -#define ISO_8859_1_DD 0 // 221 Ý Y ACUTE -#define ISO_8859_1_DE 0 // 222 Þ THORN -#define ISO_8859_1_DF 0 // 223 ß SHARP S -#define ISO_8859_1_E0 KEY_0 // 224 à a GRAVE -#define ISO_8859_1_E1 0 // 225 á a ACUTE -#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_Q // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 TILDE_BITS + KEY_Q // 227 ã a TILDE -#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_Q // 228 ä a DIAERESIS -#define ISO_8859_1_E5 0 // 229 å a RING ABOVE -#define ISO_8859_1_E6 0 // 230 æ ae -#define ISO_8859_1_E7 KEY_9 // 231 ç c CEDILLA -#define ISO_8859_1_E8 KEY_7 // 232 è e GRAVE -#define ISO_8859_1_E9 KEY_2 // 233 é e ACUTE -#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS -#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE -#define ISO_8859_1_ED 0 // 237 í i ACUTE -#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS -#define ISO_8859_1_F0 0 // 240 ð ETH -#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE -#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE -#define ISO_8859_1_F3 0 // 243 ó o ACUTE -#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE -#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS -#define ISO_8859_1_F7 0 // 247 ÷ DIVISION -#define ISO_8859_1_F8 0 // 248 ø o STROKE -#define ISO_8859_1_F9 KEY_SEMICOLON // 249 ù u GRAVE -#define ISO_8859_1_FA 0 // 250 ú u ACUTE -#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS -#define ISO_8859_1_FD 0 // 253 ý y ACUTE -#define ISO_8859_1_FE 0 // 254 þ THORN -#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS -#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign -// not yet implemented -#define UNICODE_EXTRA00 0x20AC -#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign - -#endif // LAYOUT_FRENCH - - - - - -#ifdef LAYOUT_DANISH - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define DEADKEYS_MASK 0x0700 -#define CIRCUMFLEX_BITS 0x0100 -#define ACUTE_ACCENT_BITS 0x0200 -#define GRAVE_ACCENT_BITS 0x0300 -#define TILDE_BITS 0x0400 -#define DIAERESIS_BITS 0x0500 -#define KEYCODE_TYPE uint16_t -#define DEADKEY_CIRCUMFLEX KEY_RIGHT_BRACE + SHIFT_MASK -#define DEADKEY_ACUTE_ACCENT KEY_EQUAL -#define DEADKEY_GRAVE_ACCENT KEY_EQUAL + SHIFT_MASK -#define DEADKEY_TILDE KEY_RIGHT_BRACE + ALTGR_MASK -#define DEADKEY_DIAERESIS KEY_RIGHT_BRACE -#define KEY_NON_US_100 63 - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! -#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " -#define ASCII_23 KEY_3 + SHIFT_MASK // 35 # -#define ASCII_24 KEY_4 + ALTGR_MASK // 36 $ -#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % -#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & -#define ASCII_27 KEY_BACKSLASH // 39 ' -#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) -#define ASCII_2A KEY_BACKSLASH + SHIFT_MASK // 42 * -#define ASCII_2B KEY_MINUS // 43 + -#define ASCII_2C KEY_COMMA // 44 , -#define ASCII_2D KEY_SLASH // 45 - -#define ASCII_2E KEY_PERIOD // 46 . -#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / -#define ASCII_30 KEY_0 // 48 0 -#define ASCII_31 KEY_1 // 49 1 -#define ASCII_32 KEY_2 // 50 2 -#define ASCII_33 KEY_3 // 51 3 -#define ASCII_34 KEY_4 // 52 4 -#define ASCII_35 KEY_5 // 53 5 -#define ASCII_36 KEY_6 // 54 6 -#define ASCII_37 KEY_7 // 55 7 -#define ASCII_38 KEY_8 // 55 8 -#define ASCII_39 KEY_9 // 57 9 -#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : -#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; -#define ASCII_3C KEY_NON_US_100 // 60 < -#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = -#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > -#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_2 + ALTGR_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_8 + ALTGR_MASK // 91 [ -#define ASCII_5C KEY_NON_US_100 + ALTGR_MASK // 92 -#define ASCII_5D KEY_9 + ALTGR_MASK // 93 ] -#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ -#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ -#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Y // 121 y -#define ASCII_7A KEY_Z // 122 z -#define ASCII_7B KEY_7 + ALTGR_MASK // 123 { -#define ASCII_7C KEY_EQUAL + ALTGR_MASK // 124 | -#define ASCII_7D KEY_0 + ALTGR_MASK // 125 } -#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 - -#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space -#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN -#define ISO_8859_1_A3 KEY_3 + ALTGR_MASK // 163 £ Pound Sign -#define ISO_8859_1_A4 KEY_4 + SHIFT_MASK // 164 ¤ Currency Sign -#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR -#define ISO_8859_1_A7 KEY_TILDE + SHIFT_MASK // 167 § SECTION SIGN -#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB KEY_4 // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN -#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN -#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF 0 // 175 ¯ MACRON -#define ISO_8859_1_B0 0 // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 KEY_M + ALTGR_MASK // 181 µ MICRO SIGN -#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT -#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA -#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD KEY_TILDE // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE -#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE -#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE -#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 KEY_LEFT_BRACE + SHIFT_MASK // 197 Å A RING ABOVE -#define ISO_8859_1_C6 KEY_SEMICOLON + SHIFT_MASK // 198 Æ AE -#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA -#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE -#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE -#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS -#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE -#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE -#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 KEY_D + ALTGR_MASK + SHIFT_MASK // 208 Ð ETH -#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE -#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE -#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE -#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE -#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION -#define ISO_8859_1_D8 KEY_QUOTE + SHIFT_MASK // 216 Ø O STROKE -#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE -#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE -#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS -#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE -#define ISO_8859_1_DE KEY_T + ALTGR_MASK + SHIFT_MASK // 222 Þ THORN -#define ISO_8859_1_DF KEY_S + ALTGR_MASK // 223 ß SHARP S -#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE -#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE -#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE -#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS -#define ISO_8859_1_E5 KEY_LEFT_BRACE // 229 å a RING ABOVE -#define ISO_8859_1_E6 KEY_SEMICOLON // 230 æ ae -#define ISO_8859_1_E7 0 // 231 ç c CEDILLA -#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE -#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE -#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS -#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE -#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE -#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS -#define ISO_8859_1_F0 KEY_D + ALTGR_MASK // 240 ð ETH -#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE -#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE -#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE -#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE -#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS -#define ISO_8859_1_F7 0 // 247 ÷ DIVISION -#define ISO_8859_1_F8 KEY_QUOTE // 248 ø o STROKE -#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE -#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE -#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS -#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE -#define ISO_8859_1_FE KEY_T + ALTGR_MASK // 254 þ THORN -#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS -#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign -// not yet implemented -#define UNICODE_EXTRA00 0x20AC -#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign - -#endif // LAYOUT_DANISH - - - - - -#ifdef LAYOUT_NORWEGIAN - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define DEADKEYS_MASK 0x0700 -#define CIRCUMFLEX_BITS 0x0100 -#define ACUTE_ACCENT_BITS 0x0200 -#define GRAVE_ACCENT_BITS 0x0300 -#define TILDE_BITS 0x0400 -#define DIAERESIS_BITS 0x0500 -#define KEYCODE_TYPE uint16_t -#define DEADKEY_CIRCUMFLEX KEY_RIGHT_BRACE + SHIFT_MASK -#define DEADKEY_ACUTE_ACCENT KEY_EQUAL + ALTGR_MASK -#define DEADKEY_GRAVE_ACCENT KEY_EQUAL + SHIFT_MASK -#define DEADKEY_TILDE KEY_RIGHT_BRACE + ALTGR_MASK -#define DEADKEY_DIAERESIS KEY_RIGHT_BRACE -#define KEY_NON_US_100 63 - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! -#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " -#define ASCII_23 KEY_3 + SHIFT_MASK // 35 # -#define ASCII_24 KEY_4 + ALTGR_MASK // 36 $ -#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % -#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & -#define ASCII_27 KEY_BACKSLASH // 39 ' -#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) -#define ASCII_2A KEY_BACKSLASH + SHIFT_MASK // 42 * -#define ASCII_2B KEY_MINUS // 43 + -#define ASCII_2C KEY_COMMA // 44 , -#define ASCII_2D KEY_SLASH // 45 - -#define ASCII_2E KEY_PERIOD // 46 . -#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / -#define ASCII_30 KEY_0 // 48 0 -#define ASCII_31 KEY_1 // 49 1 -#define ASCII_32 KEY_2 // 50 2 -#define ASCII_33 KEY_3 // 51 3 -#define ASCII_34 KEY_4 // 52 4 -#define ASCII_35 KEY_5 // 53 5 -#define ASCII_36 KEY_6 // 54 6 -#define ASCII_37 KEY_7 // 55 7 -#define ASCII_38 KEY_8 // 55 8 -#define ASCII_39 KEY_9 // 57 9 -#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : -#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; -#define ASCII_3C KEY_NON_US_100 // 60 < -#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = -#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > -#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_2 + ALTGR_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_8 + ALTGR_MASK // 91 [ -#define ASCII_5C KEY_EQUAL // 92 -#define ASCII_5D KEY_9 + ALTGR_MASK // 93 ] -#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ -#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ -#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Y // 121 y -#define ASCII_7A KEY_Z // 122 z -#define ASCII_7B KEY_7 + ALTGR_MASK // 123 { -#define ASCII_7C KEY_TILDE // 124 | -#define ASCII_7D KEY_0 + ALTGR_MASK // 125 } -#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 - -#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space -#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN -#define ISO_8859_1_A3 KEY_3 + ALTGR_MASK // 163 £ Pound Sign -#define ISO_8859_1_A4 KEY_4 + SHIFT_MASK // 164 ¤ Currency Sign -#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR -#define ISO_8859_1_A7 KEY_TILDE + SHIFT_MASK // 167 § SECTION SIGN -#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB KEY_4 // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN -#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN -#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF 0 // 175 ¯ MACRON -#define ISO_8859_1_B0 0 // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 KEY_M + ALTGR_MASK // 181 µ MICRO SIGN -#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT -#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA -#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD KEY_TILDE // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE -#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE -#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE -#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 KEY_LEFT_BRACE + SHIFT_MASK // 197 Å A RING ABOVE -#define ISO_8859_1_C6 KEY_QUOTE + SHIFT_MASK // 198 Æ AE -#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA -#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE -#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE -#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS -#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE -#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE -#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 KEY_D + ALTGR_MASK + SHIFT_MASK // 208 Ð ETH -#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE -#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE -#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE -#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE -#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION -#define ISO_8859_1_D8 KEY_SEMICOLON + SHIFT_MASK // 216 Ø O STROKE -#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE -#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE -#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS -#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE -#define ISO_8859_1_DE KEY_T + ALTGR_MASK + SHIFT_MASK // 222 Þ THORN -#define ISO_8859_1_DF KEY_S + ALTGR_MASK // 223 ß SHARP S -#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE -#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE -#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE -#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS -#define ISO_8859_1_E5 KEY_LEFT_BRACE // 229 å a RING ABOVE -#define ISO_8859_1_E6 KEY_QUOTE // 230 æ ae -#define ISO_8859_1_E7 0 // 231 ç c CEDILLA -#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE -#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE -#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS -#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE -#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE -#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS -#define ISO_8859_1_F0 KEY_D + ALTGR_MASK // 240 ð ETH -#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE -#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE -#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE -#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE -#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS -#define ISO_8859_1_F7 0 // 247 ÷ DIVISION -#define ISO_8859_1_F8 KEY_SEMICOLON // 248 ø o STROKE -#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE -#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE -#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS -#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE -#define ISO_8859_1_FE KEY_T + ALTGR_MASK // 254 þ THORN -#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS -#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign -// not yet implemented -#define UNICODE_EXTRA00 0x20AC -#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign - -#endif // LAYOUT_NORWEGIAN - - - - - - -#ifdef LAYOUT_SWEDISH - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define DEADKEYS_MASK 0x0700 -#define CIRCUMFLEX_BITS 0x0100 -#define ACUTE_ACCENT_BITS 0x0200 -#define GRAVE_ACCENT_BITS 0x0300 -#define TILDE_BITS 0x0400 -#define DIAERESIS_BITS 0x0500 -#define KEYCODE_TYPE uint16_t -#define DEADKEY_CIRCUMFLEX KEY_RIGHT_BRACE + SHIFT_MASK -#define DEADKEY_ACUTE_ACCENT KEY_EQUAL -#define DEADKEY_GRAVE_ACCENT KEY_EQUAL + SHIFT_MASK -#define DEADKEY_TILDE KEY_RIGHT_BRACE + ALTGR_MASK -#define DEADKEY_DIAERESIS KEY_RIGHT_BRACE -#define KEY_NON_US_100 63 - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! -#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " -#define ASCII_23 KEY_3 + SHIFT_MASK // 35 # -#define ASCII_24 KEY_4 + ALTGR_MASK // 36 $ -#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % -#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & -#define ASCII_27 KEY_BACKSLASH // 39 ' -#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) -#define ASCII_2A KEY_BACKSLASH + SHIFT_MASK // 42 * -#define ASCII_2B KEY_MINUS // 43 + -#define ASCII_2C KEY_COMMA // 44 , -#define ASCII_2D KEY_SLASH // 45 - -#define ASCII_2E KEY_PERIOD // 46 . -#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / -#define ASCII_30 KEY_0 // 48 0 -#define ASCII_31 KEY_1 // 49 1 -#define ASCII_32 KEY_2 // 50 2 -#define ASCII_33 KEY_3 // 51 3 -#define ASCII_34 KEY_4 // 52 4 -#define ASCII_35 KEY_5 // 53 5 -#define ASCII_36 KEY_6 // 54 6 -#define ASCII_37 KEY_7 // 55 7 -#define ASCII_38 KEY_8 // 55 8 -#define ASCII_39 KEY_9 // 57 9 -#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : -#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; -#define ASCII_3C KEY_NON_US_100 // 60 < -#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = -#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > -#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_2 + ALTGR_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_8 + ALTGR_MASK // 91 [ -#define ASCII_5C KEY_MINUS + ALTGR_MASK // 92 -#define ASCII_5D KEY_9 + ALTGR_MASK // 93 ] -#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ -#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ -#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Y // 121 y -#define ASCII_7A KEY_Z // 122 z -#define ASCII_7B KEY_7 + ALTGR_MASK // 123 { -#define ASCII_7C KEY_NON_US_100 + ALTGR_MASK // 124 | -#define ASCII_7D KEY_0 + ALTGR_MASK // 125 } -#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 - -#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space -#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN -#define ISO_8859_1_A3 KEY_3 + ALTGR_MASK // 163 £ Pound Sign -#define ISO_8859_1_A4 KEY_4 + SHIFT_MASK // 164 ¤ Currency Sign -#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR -#define ISO_8859_1_A7 KEY_TILDE // 167 § SECTION SIGN -#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB KEY_4 // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN -#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN -#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF 0 // 175 ¯ MACRON -#define ISO_8859_1_B0 0 // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 KEY_M + ALTGR_MASK // 181 µ MICRO SIGN -#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT -#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA -#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD KEY_TILDE + SHIFT_MASK // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE -#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE -#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE -#define ISO_8859_1_C4 KEY_QUOTE + SHIFT_MASK // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 KEY_LEFT_BRACE + SHIFT_MASK // 197 Å A RING ABOVE -#define ISO_8859_1_C6 0 // 198 Æ AE -#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA -#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE -#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE -#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS -#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE -#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE -#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 KEY_D + ALTGR_MASK + SHIFT_MASK // 208 Ð ETH -#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE -#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE -#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE -#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE -#define ISO_8859_1_D6 KEY_SEMICOLON + SHIFT_MASK // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION -#define ISO_8859_1_D8 0 // 216 Ø O STROKE -#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE -#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE -#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS -#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE -#define ISO_8859_1_DE KEY_T + ALTGR_MASK + SHIFT_MASK // 222 Þ THORN -#define ISO_8859_1_DF KEY_S + ALTGR_MASK // 223 ß SHARP S -#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE -#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE -#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE -#define ISO_8859_1_E4 KEY_QUOTE // 228 ä a DIAERESIS -#define ISO_8859_1_E5 KEY_LEFT_BRACE // 229 å a RING ABOVE -#define ISO_8859_1_E6 0 // 230 æ ae -#define ISO_8859_1_E7 0 // 231 ç c CEDILLA -#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE -#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE -#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS -#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE -#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE -#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS -#define ISO_8859_1_F0 KEY_D + ALTGR_MASK // 240 ð ETH -#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE -#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE -#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE -#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE -#define ISO_8859_1_F6 KEY_SEMICOLON // 246 ö o DIAERESIS -#define ISO_8859_1_F7 0 // 247 ÷ DIVISION -#define ISO_8859_1_F8 0 // 248 ø o STROKE -#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE -#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE -#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS -#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE -#define ISO_8859_1_FE KEY_T + ALTGR_MASK // 254 þ THORN -#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS -#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign -// not yet implemented -#define UNICODE_EXTRA00 0x20AC -#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign - -#endif // LAYOUT_SWEDISH - - - - - - -#ifdef LAYOUT_SPANISH - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define DEADKEYS_MASK 0x0700 -#define CIRCUMFLEX_BITS 0x0100 -#define ACUTE_ACCENT_BITS 0x0200 -#define GRAVE_ACCENT_BITS 0x0300 -#define TILDE_BITS 0x0400 -#define DIAERESIS_BITS 0x0500 -#define KEYCODE_TYPE uint16_t -#define DEADKEY_CIRCUMFLEX KEY_LEFT_BRACE + SHIFT_MASK -#define DEADKEY_ACUTE_ACCENT KEY_QUOTE -#define DEADKEY_GRAVE_ACCENT KEY_LEFT_BRACE -#define DEADKEY_TILDE KEY_4 + ALTGR_MASK -#define DEADKEY_DIAERESIS KEY_QUOTE + SHIFT_MASK -#define KEY_NON_US_100 63 - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! -#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " -#define ASCII_23 KEY_3 + ALTGR_MASK // 35 # -#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ -#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % -#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & -#define ASCII_27 KEY_MINUS // 39 ' -#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) -#define ASCII_2A KEY_RIGHT_BRACE + SHIFT_MASK // 42 * -#define ASCII_2B KEY_RIGHT_BRACE // 43 + -#define ASCII_2C KEY_COMMA // 44 , -#define ASCII_2D KEY_SLASH // 45 - -#define ASCII_2E KEY_PERIOD // 46 . -#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / -#define ASCII_30 KEY_0 // 48 0 -#define ASCII_31 KEY_1 // 49 1 -#define ASCII_32 KEY_2 // 50 2 -#define ASCII_33 KEY_3 // 51 3 -#define ASCII_34 KEY_4 // 52 4 -#define ASCII_35 KEY_5 // 53 5 -#define ASCII_36 KEY_6 // 54 6 -#define ASCII_37 KEY_7 // 55 7 -#define ASCII_38 KEY_8 // 55 8 -#define ASCII_39 KEY_9 // 57 9 -#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : -#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; -#define ASCII_3C KEY_NON_US_100 // 60 < -#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = -#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > -#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_2 + ALTGR_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_LEFT_BRACE + ALTGR_MASK // 91 [ -#define ASCII_5C KEY_TILDE + ALTGR_MASK // 92 -#define ASCII_5D KEY_RIGHT_BRACE + ALTGR_MASK // 93 ] -#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ -#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ -#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Y // 121 y -#define ASCII_7A KEY_Z // 122 z -#define ASCII_7B KEY_QUOTE + ALTGR_MASK // 123 { -#define ASCII_7C KEY_1 + ALTGR_MASK // 124 | -#define ASCII_7D KEY_BACKSLASH + ALTGR_MASK // 125 } -#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 - -#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space -#define ISO_8859_1_A1 KEY_EQUAL // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN -#define ISO_8859_1_A3 0 // 163 £ Pound Sign -#define ISO_8859_1_A4 0 // 164 ¤ Currency Sign -#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR -#define ISO_8859_1_A7 0 // 167 § SECTION SIGN -#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA KEY_TILDE + SHIFT_MASK // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC KEY_6 + ALTGR_MASK // 172 ¬ NOT SIGN -#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN -#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF 0 // 175 ¯ MACRON -#define ISO_8859_1_B0 0 // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN -#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 KEY_3 + SHIFT_MASK // 183 · MIDDLE DOT -#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA -#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA KEY_TILDE // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF KEY_EQUAL // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE -#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE -#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE -#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE -#define ISO_8859_1_C6 0 // 198 Æ AE -#define ISO_8859_1_C7 KEY_BACKSLASH + SHIFT_MASK // 199 Ç C CEDILLA -#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE -#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE -#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS -#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE -#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE -#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 0 // 208 Ð ETH -#define ISO_8859_1_D1 KEY_SEMICOLON + SHIFT_MASK // 209 Ñ N TILDE -#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE -#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE -#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE -#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION -#define ISO_8859_1_D8 0 // 216 Ø O STROKE -#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE -#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE -#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS -#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE -#define ISO_8859_1_DE 0 // 222 Þ THORN -#define ISO_8859_1_DF 0 // 223 ß SHARP S -#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE -#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE -#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE -#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS -#define ISO_8859_1_E5 0 // 229 å a RING ABOVE -#define ISO_8859_1_E6 0 // 230 æ ae -#define ISO_8859_1_E7 KEY_BACKSLASH // 231 ç c CEDILLA -#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE -#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE -#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS -#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE -#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE -#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS -#define ISO_8859_1_F0 0 // 240 ð ETH -#define ISO_8859_1_F1 KEY_SEMICOLON // 241 ñ n TILDE -#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE -#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE -#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE -#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS -#define ISO_8859_1_F7 0 // 247 ÷ DIVISION -#define ISO_8859_1_F8 0 // 248 ø o STROKE -#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE -#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE -#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS -#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE -#define ISO_8859_1_FE 0 // 254 þ THORN -#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS -#define UNICODE_20AC KEY_5 + ALTGR_MASK // € Euro Sign -// not yet implemented -#define UNICODE_EXTRA00 0x20AC -#define KEYCODE_EXTRA00 KEY_5 + ALTGR_MASK // 20AC € Euro Sign - -#endif // LAYOUT_SPANISH - - - - -#ifdef LAYOUT_PORTUGUESE - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define DEADKEYS_MASK 0x0700 -#define CIRCUMFLEX_BITS 0x0100 -#define ACUTE_ACCENT_BITS 0x0200 -#define GRAVE_ACCENT_BITS 0x0300 -#define TILDE_BITS 0x0400 -#define DIAERESIS_BITS 0x0500 -#define KEYCODE_TYPE uint16_t -#define DEADKEY_CIRCUMFLEX KEY_BACKSLASH -#define DEADKEY_ACUTE_ACCENT KEY_RIGHT_BRACE + SHIFT_MASK -#define DEADKEY_GRAVE_ACCENT KEY_RIGHT_BRACE + SHIFT_MASK -#define DEADKEY_TILDE KEY_BACKSLASH -#define DEADKEY_DIAERESIS KEY_LEFT_BRACE + SHIFT_MASK -#define KEY_NON_US_100 63 - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! -#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " -#define ASCII_23 KEY_3 + ALTGR_MASK // 35 # -#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ -#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % -#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & -#define ASCII_27 KEY_MINUS // 39 ' -#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) -#define ASCII_2A KEY_LEFT_BRACE + SHIFT_MASK // 42 * -#define ASCII_2B KEY_LEFT_BRACE // 43 + -#define ASCII_2C KEY_COMMA // 44 , -#define ASCII_2D KEY_SLASH // 45 - -#define ASCII_2E KEY_PERIOD // 46 . -#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / -#define ASCII_30 KEY_0 // 48 0 -#define ASCII_31 KEY_1 // 49 1 -#define ASCII_32 KEY_2 // 50 2 -#define ASCII_33 KEY_3 // 51 3 -#define ASCII_34 KEY_4 // 52 4 -#define ASCII_35 KEY_5 // 53 5 -#define ASCII_36 KEY_6 // 54 6 -#define ASCII_37 KEY_7 // 55 7 -#define ASCII_38 KEY_8 // 55 8 -#define ASCII_39 KEY_9 // 57 9 -#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : -#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; -#define ASCII_3C KEY_NON_US_100 // 60 < -#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = -#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > -#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_2 + ALTGR_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_8 + ALTGR_MASK // 91 [ -#define ASCII_5C KEY_TILDE + ALTGR_MASK // 92 -#define ASCII_5D KEY_9 + ALTGR_MASK // 93 ] -#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ -#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ -#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Y // 121 y -#define ASCII_7A KEY_Z // 122 z -#define ASCII_7B KEY_7 + ALTGR_MASK // 123 { -#define ASCII_7C KEY_TILDE + SHIFT_MASK // 124 | -#define ASCII_7D KEY_0 + ALTGR_MASK // 125 } -#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 - -#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space -#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN -#define ISO_8859_1_A3 KEY_3 + ALTGR_MASK // 163 £ Pound Sign -#define ISO_8859_1_A4 0 // 164 ¤ Currency Sign -#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR -#define ISO_8859_1_A7 KEY_4 + ALTGR_MASK // 167 § SECTION SIGN -#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA KEY_QUOTE + SHIFT_MASK // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB KEY_EQUAL // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN -#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN -#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF 0 // 175 ¯ MACRON -#define ISO_8859_1_B0 0 // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN -#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT -#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA -#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA KEY_QUOTE // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB KEY_EQUAL + SHIFT_MASK // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE -#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE -#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE -#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE -#define ISO_8859_1_C6 0 // 198 Æ AE -#define ISO_8859_1_C7 KEY_SEMICOLON + SHIFT_MASK // 199 Ç C CEDILLA -#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE -#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE -#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS -#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE -#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE -#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 0 // 208 Ð ETH -#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE -#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE -#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE -#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE -#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION -#define ISO_8859_1_D8 0 // 216 Ø O STROKE -#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE -#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE -#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS -#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE -#define ISO_8859_1_DE 0 // 222 Þ THORN -#define ISO_8859_1_DF 0 // 223 ß SHARP S -#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE -#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE -#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE -#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS -#define ISO_8859_1_E5 0 // 229 å a RING ABOVE -#define ISO_8859_1_E6 0 // 230 æ ae -#define ISO_8859_1_E7 KEY_SEMICOLON // 231 ç c CEDILLA -#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE -#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE -#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS -#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE -#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE -#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS -#define ISO_8859_1_F0 0 // 240 ð ETH -#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE -#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE -#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE -#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE -#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS -#define ISO_8859_1_F7 0 // 247 ÷ DIVISION -#define ISO_8859_1_F8 0 // 248 ø o STROKE -#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE -#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE -#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS -#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE -#define ISO_8859_1_FE 0 // 254 þ THORN -#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS -#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign -// not yet implemented -#define UNICODE_EXTRA00 0x20AC -#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign - -#endif // LAYOUT_PORTUGUESE - - - - - - - -#ifdef LAYOUT_ITALIAN - -#define SHIFT_MASK 0x40 -#define ALTGR_MASK 0x80 -#define KEYCODE_TYPE uint8_t -#define KEY_NON_US_100 63 - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! -#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " -#define ASCII_23 KEY_QUOTE + ALTGR_MASK // 35 # -#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ -#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % -#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & -#define ASCII_27 KEY_MINUS // 39 ' -#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) -#define ASCII_2A KEY_RIGHT_BRACE + SHIFT_MASK // 42 * -#define ASCII_2B KEY_RIGHT_BRACE // 43 + -#define ASCII_2C KEY_COMMA // 44 , -#define ASCII_2D KEY_SLASH // 45 - -#define ASCII_2E KEY_PERIOD // 46 . -#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / -#define ASCII_30 KEY_0 // 48 0 -#define ASCII_31 KEY_1 // 49 1 -#define ASCII_32 KEY_2 // 50 2 -#define ASCII_33 KEY_3 // 51 3 -#define ASCII_34 KEY_4 // 52 4 -#define ASCII_35 KEY_5 // 53 5 -#define ASCII_36 KEY_6 // 54 6 -#define ASCII_37 KEY_7 // 55 7 -#define ASCII_38 KEY_8 // 55 8 -#define ASCII_39 KEY_9 // 57 9 -#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : -#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; -#define ASCII_3C KEY_NON_US_100 // 60 < -#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = -#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > -#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_SEMICOLON + ALTGR_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_LEFT_BRACE + ALTGR_MASK // 91 [ -#define ASCII_5C KEY_TILDE // 92 -#define ASCII_5D KEY_RIGHT_BRACE + ALTGR_MASK // 93 ] -#define ASCII_5E KEY_EQUAL + SHIFT_MASK // 94 ^ -#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ -#define ASCII_60 0 // 96 ` (how to type this on Italian?) -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Y // 121 y -#define ASCII_7A KEY_Z // 122 z -#define ASCII_7B KEY_LEFT_BRACE + SHIFT_MASK + ALTGR_MASK // 123 { -#define ASCII_7C KEY_TILDE + SHIFT_MASK // 124 | -#define ASCII_7D KEY_RIGHT_BRACE + SHIFT_MASK + ALTGR_MASK // 125 } -#define ASCII_7E 0 // 126 ~ (how to type this on Italian?) -#define ASCII_7F KEY_BACKSPACE // 127 - -#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space -#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 0 // 162 ¢ Cent Sign -#define ISO_8859_1_A3 KEY_3 + SHIFT_MASK // 163 £ Pound Sign -#define ISO_8859_1_A4 0 // 164 ¤ Currency Sign -#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR -#define ISO_8859_1_A7 KEY_BACKSLASH + SHIFT_MASK // 167 § SECTION SIGN -#define ISO_8859_1_A8 0 // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN -#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN -#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF 0 // 175 ¯ MACRON -#define ISO_8859_1_B0 KEY_QUOTE + SHIFT_MASK // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 0 // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN -#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT -#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA -#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 0 // 192 À A GRAVE -#define ISO_8859_1_C1 0 // 193 Á A ACUTE -#define ISO_8859_1_C2 0 // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 0 // 195 Ã A TILDE -#define ISO_8859_1_C4 0 // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE -#define ISO_8859_1_C6 0 // 198 Æ AE -#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA -#define ISO_8859_1_C8 0 // 200 È E GRAVE -#define ISO_8859_1_C9 0 // 201 É E ACUTE -#define ISO_8859_1_CA 0 // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB 0 // 203 Ë E DIAERESIS -#define ISO_8859_1_CC 0 // 204 Ì I GRAVE -#define ISO_8859_1_CD 0 // 205 Í I ACUTE -#define ISO_8859_1_CE 0 // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF 0 // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 0 // 208 Ð ETH -#define ISO_8859_1_D1 0 // 209 Ñ N TILDE -#define ISO_8859_1_D2 0 // 210 Ò O GRAVE -#define ISO_8859_1_D3 0 // 211 Ó O ACUTE -#define ISO_8859_1_D4 0 // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 0 // 213 Õ O TILDE -#define ISO_8859_1_D6 0 // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION -#define ISO_8859_1_D8 0 // 216 Ø O STROKE -#define ISO_8859_1_D9 0 // 217 Ù U GRAVE -#define ISO_8859_1_DA 0 // 218 Ú U ACUTE -#define ISO_8859_1_DB 0 // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC 0 // 220 Ü U DIAERESIS -#define ISO_8859_1_DD 0 // 221 Ý Y ACUTE -#define ISO_8859_1_DE 0 // 222 Þ THORN -#define ISO_8859_1_DF 0 // 223 ß SHARP S -#define ISO_8859_1_E0 KEY_QUOTE // 224 à a GRAVE -#define ISO_8859_1_E1 0 // 225 á a ACUTE -#define ISO_8859_1_E2 0 // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 0 // 227 ã a TILDE -#define ISO_8859_1_E4 0 // 228 ä a DIAERESIS -#define ISO_8859_1_E5 0 // 229 å a RING ABOVE -#define ISO_8859_1_E6 0 // 230 æ ae -#define ISO_8859_1_E7 KEY_SEMICOLON + SHIFT_MASK // 231 ç c CEDILLA -#define ISO_8859_1_E8 KEY_LEFT_BRACE // 232 è e GRAVE -#define ISO_8859_1_E9 KEY_LEFT_BRACE + SHIFT_MASK // 233 é e ACUTE -#define ISO_8859_1_EA 0 // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB 0 // 235 ë e DIAERESIS -#define ISO_8859_1_EC KEY_EQUAL // 236 ì i GRAVE -#define ISO_8859_1_ED 0 // 237 í i ACUTE -#define ISO_8859_1_EE 0 // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF 0 // 239 ï i DIAERESIS -#define ISO_8859_1_F0 0 // 240 ð ETH -#define ISO_8859_1_F1 0 // 241 ñ n TILDE -#define ISO_8859_1_F2 KEY_SEMICOLON // 242 ò o GRAVE -#define ISO_8859_1_F3 0 // 243 ó o ACUTE -#define ISO_8859_1_F4 0 // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 0 // 245 õ o TILDE -#define ISO_8859_1_F6 0 // 246 ö o DIAERESIS -#define ISO_8859_1_F7 0 // 247 ÷ DIVISION -#define ISO_8859_1_F8 0 // 248 ø o STROKE -#define ISO_8859_1_F9 KEY_BACKSLASH // 249 ù u GRAVE -#define ISO_8859_1_FA 0 // 250 ú u ACUTE -#define ISO_8859_1_FB 0 // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC 0 // 252 ü u DIAERESIS -#define ISO_8859_1_FD 0 // 253 ý y ACUTE -#define ISO_8859_1_FE 0 // 254 þ THORN -#define ISO_8859_1_FF 0 // 255 ÿ y DIAERESIS - -#endif // LAYOUT_ITALIAN - - - - -#ifdef LAYOUT_PORTUGUESE_BRAZILIAN - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define DEADKEYS_MASK 0x0700 -#define CIRCUMFLEX_BITS 0x0100 -#define ACUTE_ACCENT_BITS 0x0200 -#define GRAVE_ACCENT_BITS 0x0300 -#define TILDE_BITS 0x0400 -#define DIAERESIS_BITS 0x0500 -#define KEYCODE_TYPE uint16_t -#define DEADKEY_CIRCUMFLEX KEY_QUOTE + SHIFT_MASK -#define DEADKEY_ACUTE_ACCENT KEY_LEFT_BRACE -#define DEADKEY_GRAVE_ACCENT KEY_LEFT_BRACE + SHIFT_MASK -#define DEADKEY_TILDE KEY_QUOTE -#define DEADKEY_DIAERESIS KEY_6 + SHIFT_MASK -#define KEY_NON_US_100 63 - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! -#define ASCII_22 KEY_TILDE + SHIFT_MASK // 34 " -#define ASCII_23 KEY_3 + ALTGR_MASK // 35 # -#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ -#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % -#define ASCII_26 KEY_7 + SHIFT_MASK // 38 & -#define ASCII_27 KEY_TILDE // 39 ' -#define ASCII_28 KEY_9 + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_0 + SHIFT_MASK // 41 ) -#define ASCII_2A KEY_7 + SHIFT_MASK // 42 * -#define ASCII_2B KEY_EQUAL + SHIFT_MASK // 43 + -#define ASCII_2C KEY_COMMA // 44 , -#define ASCII_2D KEY_MINUS // 45 - -#define ASCII_2E KEY_PERIOD // 46 . -#define ASCII_2F KEY_Q + ALTGR_MASK // 47 / -#define ASCII_30 KEY_0 // 48 0 -#define ASCII_31 KEY_1 // 49 1 -#define ASCII_32 KEY_2 // 50 2 -#define ASCII_33 KEY_3 // 51 3 -#define ASCII_34 KEY_4 // 52 4 -#define ASCII_35 KEY_5 // 53 5 -#define ASCII_36 KEY_6 // 54 6 -#define ASCII_37 KEY_7 // 55 7 -#define ASCII_38 KEY_8 // 55 8 -#define ASCII_39 KEY_9 // 57 9 -#define ASCII_3A KEY_SLASH + SHIFT_MASK // 58 : -#define ASCII_3B KEY_SLASH // 59 ; -#define ASCII_3C KEY_COMMA + SHIFT_MASK // 60 < -#define ASCII_3D KEY_EQUAL // 61 = -#define ASCII_3E KEY_PERIOD + SHIFT_MASK // 62 > -#define ASCII_3F KEY_W + ALTGR_MASK // 63 ? -#define ASCII_40 KEY_2 + SHIFT_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_RIGHT_BRACE // 91 [ -#define ASCII_5C KEY_NON_US_100 // 92 -#define ASCII_5D KEY_BACKSLASH // 93 ] -#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ -#define ASCII_5F KEY_MINUS + SHIFT_MASK // 95 _ -#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Y // 121 y -#define ASCII_7A KEY_Z // 122 z -#define ASCII_7B KEY_RIGHT_BRACE + SHIFT_MASK // 123 { -#define ASCII_7C KEY_NON_US_100 + SHIFT_MASK // 124 | -#define ASCII_7D KEY_BACKSLASH + SHIFT_MASK // 125 } -#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 - -#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space -#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 KEY_5 + ALTGR_MASK // 162 ¢ Cent SIGN -#define ISO_8859_1_A3 KEY_4 + ALTGR_MASK // 163 £ Pound Sign -#define ISO_8859_1_A4 0 // 164 ¤ Currency Sign -#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR -#define ISO_8859_1_A7 KEY_EQUAL + ALTGR_MASK // 167 § SECTION SIGN -#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA KEY_RIGHT_BRACE + ALTGR_MASK // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC KEY_6 + ALTGR_MASK // 172 ¬ NOT SIGN -#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN -#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF 0 // 175 ¯ MACRON -#define ISO_8859_1_B0 KEY_E + ALTGR_MASK // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 KEY_2 + ALTGR_MASK // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 KEY_2 + ALTGR_MASK // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN -#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT -#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA -#define ISO_8859_1_B9 KEY_1 + ALTGR_MASK // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA KEY_BACKSLASH + ALTGR_MASK // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE -#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE -#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE -#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE -#define ISO_8859_1_C6 0 // 198 Æ AE -#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA -#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE -#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE -#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS -#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE -#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE -#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 0 // 208 Ð ETH -#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE -#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE -#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE -#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE -#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION -#define ISO_8859_1_D8 0 // 216 Ø O STROKE -#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE -#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE -#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS -#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE -#define ISO_8859_1_DE 0 // 222 Þ THORN -#define ISO_8859_1_DF 0 // 223 ß SHARP S -#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE -#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE -#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE -#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS -#define ISO_8859_1_E5 0 // 229 å a RING ABOVE -#define ISO_8859_1_E6 0 // 230 æ ae -#define ISO_8859_1_E7 0 // 231 ç c CEDILLA -#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE -#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE -#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS -#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE -#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE -#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS -#define ISO_8859_1_F0 0 // 240 ð ETH -#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE -#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE -#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE -#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE -#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS -#define ISO_8859_1_F7 0 // 247 ÷ DIVISION -#define ISO_8859_1_F8 0 // 248 ø o STROKE -#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE -#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE -#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS -#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE -#define ISO_8859_1_FE 0 // 254 þ THORN -#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS - -#endif // LAYOUT_PORTUGUESE_BRAZILIAN - - - -#ifdef LAYOUT_FRENCH_BELGIAN - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define DEADKEYS_MASK 0x0700 -#define CIRCUMFLEX_BITS 0x0100 -#define GRAVE_ACCENT_BITS 0x0200 -#define DIAERESIS_BITS 0x0300 -#define TILDE_BITS 0x0400 -#define ACUTE_ACCENT_BITS 0x0500 -#define KEYCODE_TYPE uint16_t -#define DEADKEY_CIRCUMFLEX KEY_LEFT_BRACE -#define DEADKEY_ACUTE_ACCENT KEY_QUOTE + ALTGR_MASK -#define DEADKEY_GRAVE_ACCENT KEY_BACKSLASH + ALTGR_MASK -#define DEADKEY_DIAERESIS KEY_LEFT_BRACE + SHIFT_MASK -#define DEADKEY_TILDE KEY_SLASH + ALTGR_MASK -#define KEY_NON_US_100 63 - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_8 // 33 ! -#define ASCII_22 KEY_3 // 34 " -#define ASCII_23 KEY_3 + ALTGR_MASK // 35 # -#define ASCII_24 KEY_RIGHT_BRACE // 36 $ -#define ASCII_25 KEY_QUOTE + SHIFT_MASK // 37 % -#define ASCII_26 KEY_1 // 38 & -#define ASCII_27 KEY_4 // 39 ' -#define ASCII_28 KEY_5 // 40 ( -#define ASCII_29 KEY_MINUS // 41 ) -#define ASCII_2A KEY_RIGHT_BRACE + SHIFT_MASK // 42 * -#define ASCII_2B KEY_SLASH + SHIFT_MASK // 43 + -#define ASCII_2C KEY_M // 44 , -#define ASCII_2D KEY_EQUAL // 45 - -#define ASCII_2E KEY_COMMA + SHIFT_MASK // 46 . -#define ASCII_2F KEY_PERIOD + SHIFT_MASK // 47 / -#define ASCII_30 KEY_0 + SHIFT_MASK // 48 0 -#define ASCII_31 KEY_1 + SHIFT_MASK // 49 1 -#define ASCII_32 KEY_2 + SHIFT_MASK // 50 2 -#define ASCII_33 KEY_3 + SHIFT_MASK // 51 3 -#define ASCII_34 KEY_4 + SHIFT_MASK // 52 4 -#define ASCII_35 KEY_5 + SHIFT_MASK // 53 5 -#define ASCII_36 KEY_6 + SHIFT_MASK // 54 6 -#define ASCII_37 KEY_7 + SHIFT_MASK // 55 7 -#define ASCII_38 KEY_8 + SHIFT_MASK // 55 8 -#define ASCII_39 KEY_9 + SHIFT_MASK // 57 9 -#define ASCII_3A KEY_PERIOD // 58 : -#define ASCII_3B KEY_COMMA // 59 ; -#define ASCII_3C KEY_NON_US_100 // 60 < -#define ASCII_3D KEY_SLASH // 61 = -#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > -#define ASCII_3F KEY_M + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_2 + ALTGR_MASK // 64 @ -#define ASCII_41 KEY_Q + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_SEMICOLON + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_A + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_Z + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_W + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_RIGHT_BRACE + ALTGR_MASK // 91 [ -#define ASCII_5C KEY_NON_US_100 + ALTGR_MASK // 92 -#define ASCII_5D KEY_LEFT_BRACE + ALTGR_MASK // 93 ] -#define ASCII_5E KEY_6 + ALTGR_MASK // 94 ^ -#define ASCII_5F KEY_EQUAL + SHIFT_MASK // 95 _ -#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` -#define ASCII_61 KEY_Q // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_SEMICOLON // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_A // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_Z // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Y // 121 y -#define ASCII_7A KEY_W // 122 z -#define ASCII_7B KEY_9 + ALTGR_MASK // 123 { -#define ASCII_7C KEY_1 + ALTGR_MASK // 124 | -#define ASCII_7D KEY_0 + ALTGR_MASK // 125 } -#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 -#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space -#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN -#define ISO_8859_1_A3 KEY_BACKSLASH + SHIFT_MASK // 163 £ Pound Sign -#define ISO_8859_1_A4 0 // 164 ¤ Currency or Euro Sign -#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR -#define ISO_8859_1_A7 KEY_6 // 167 § SECTION SIGN -#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN -#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN -#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF 0 // 175 ¯ MACRON -#define ISO_8859_1_B0 KEY_MINUS + SHIFT_MASK // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 KEY_TILDE // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 KEY_TILDE + SHIFT_MASK // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 KEY_BACKSLASH // 181 µ MICRO SIGN -#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT -#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA -#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_Q + SHIFT_MASK // 192 À A GRAVE -#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_Q + SHIFT_MASK // 193 Á A ACUTE -#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_Q + SHIFT_MASK // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 TILDE_BITS + KEY_Q + SHIFT_MASK // 195 Ã A TILDE -#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_Q + SHIFT_MASK // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE -#define ISO_8859_1_C6 0 // 198 Æ AE -#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA -#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE -#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE -#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS -#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE -#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE -#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 0 // 208 Ð ETH -#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE -#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE -#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE -#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE -#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION -#define ISO_8859_1_D8 0 // 216 Ø O STROKE -#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE -#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE -#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U // 220 Ü U DIAERESIS -#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE -#define ISO_8859_1_DE 0 // 222 Þ THORN -#define ISO_8859_1_DF 0 // 223 ß SHARP S -#define ISO_8859_1_E0 KEY_0 // 224 à a GRAVE -#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_Q // 225 á a ACUTE -#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_Q // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 TILDE_BITS + KEY_Q // 227 ã a TILDE -#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_Q // 228 ä a DIAERESIS -#define ISO_8859_1_E5 0 // 229 å a RING ABOVE -#define ISO_8859_1_E6 0 // 230 æ ae -#define ISO_8859_1_E7 KEY_9 // 231 ç c CEDILLA -#define ISO_8859_1_E8 KEY_7 // 232 è e GRAVE -#define ISO_8859_1_E9 KEY_2 // 233 é e ACUTE -#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS -#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE -#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE -#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS -#define ISO_8859_1_F0 0 // 240 ð ETH -#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE -#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE -#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE -#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE -#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS -#define ISO_8859_1_F7 0 // 247 ÷ DIVISION -#define ISO_8859_1_F8 0 // 248 ø o STROKE -#define ISO_8859_1_F9 KEY_QUOTE // 249 ù u GRAVE - TODO; check FRENCH -#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE -#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS -#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE -#define ISO_8859_1_FE 0 // 254 þ THORN -#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS -#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign -// not yet implemented -#define UNICODE_EXTRA00 0x20AC -#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign - -#endif // LAYOUT_FRENCH_BELGIAN - - - - -#ifdef LAYOUT_GERMAN_SWISS - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define DEADKEYS_MASK 0x0700 -#define CIRCUMFLEX_BITS 0x0100 -#define GRAVE_ACCENT_BITS 0x0200 -#define DIAERESIS_BITS 0x0300 -#define TILDE_BITS 0x0400 -#define ACUTE_ACCENT_BITS 0x0500 -#define KEYCODE_TYPE uint16_t -#define DEADKEY_CIRCUMFLEX KEY_EQUAL -#define DEADKEY_ACUTE_ACCENT KEY_MINUS + ALTGR_MASK -#define DEADKEY_GRAVE_ACCENT KEY_EQUAL + SHIFT_MASK -#define DEADKEY_DIAERESIS KEY_RIGHT_BRACE -#define DEADKEY_TILDE KEY_EQUAL + ALTGR_MASK -#define KEY_NON_US_100 63 - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_RIGHT_BRACE + SHIFT_MASK // 33 ! -#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " -#define ASCII_23 KEY_3 + ALTGR_MASK // 35 # -#define ASCII_24 KEY_BACKSLASH // 36 $ -#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % -#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & -#define ASCII_27 KEY_MINUS // 39 ' -#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) -#define ASCII_2A KEY_3 + SHIFT_MASK // 42 * -#define ASCII_2B KEY_1 + SHIFT_MASK // 43 + -#define ASCII_2C KEY_COMMA // 44 , -#define ASCII_2D KEY_SLASH // 45 - -#define ASCII_2E KEY_PERIOD // 46 . -#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / -#define ASCII_30 KEY_0 // 48 0 -#define ASCII_31 KEY_1 // 49 1 -#define ASCII_32 KEY_2 // 50 2 -#define ASCII_33 KEY_3 // 51 3 -#define ASCII_34 KEY_4 // 52 4 -#define ASCII_35 KEY_5 // 53 5 -#define ASCII_36 KEY_6 // 54 6 -#define ASCII_37 KEY_7 // 55 7 -#define ASCII_38 KEY_8 // 55 8 -#define ASCII_39 KEY_9 // 57 9 -#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : -#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; -#define ASCII_3C KEY_NON_US_100 // 60 < -#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = -#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > -#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_2 + ALTGR_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Z + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Y + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_LEFT_BRACE + ALTGR_MASK // 91 [ -#define ASCII_5C KEY_NON_US_100 + ALTGR_MASK // 92 -#define ASCII_5D KEY_RIGHT_BRACE + ALTGR_MASK // 93 ] -#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ -#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ -#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Z // 121 y -#define ASCII_7A KEY_Y // 122 z -#define ASCII_7B KEY_QUOTE + ALTGR_MASK // 123 { -#define ASCII_7C KEY_7 + ALTGR_MASK // 124 | -#define ASCII_7D KEY_BACKSLASH + ALTGR_MASK // 125 } -#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 -#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space -#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 KEY_8 + ALTGR_MASK // 162 ¢ Cent Sign -#define ISO_8859_1_A3 KEY_BACKSLASH + SHIFT_MASK // 163 £ Pound Sign -#define ISO_8859_1_A4 0 // 164 ¤ Currency Sign -#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 KEY_1 + ALTGR_MASK // 166 ¦ BROKEN BAR -#define ISO_8859_1_A7 KEY_5 + ALTGR_MASK // 167 § SECTION SIGN -#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC KEY_6 + ALTGR_MASK // 172 ¬ NOT SIGN -#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN -#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF 0 // 175 ¯ MACRON -#define ISO_8859_1_B0 KEY_4 + ALTGR_MASK // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN -#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT -#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA -#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE -#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE -#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE -#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE -#define ISO_8859_1_C6 0 // 198 Æ AE -#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA -#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE -#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE -#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS -#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE -#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE -#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 0 // 208 Ð ETH -#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE -#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE -#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE -#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE -#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION -#define ISO_8859_1_D8 0 // 216 Ø O STROKE -#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE -#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE -#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS -#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE -#define ISO_8859_1_DE 0 // 222 Þ THORN -#define ISO_8859_1_DF 0 // 223 ß SHARP S -#define ISO_8859_1_E0 KEY_QUOTE + SHIFT_MASK // 224 à a GRAVE -#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE -#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE -#define ISO_8859_1_E4 KEY_QUOTE // 228 ä a DIAERESIS -#define ISO_8859_1_E5 0 // 229 å a RING ABOVE -#define ISO_8859_1_E6 0 // 230 æ ae -#define ISO_8859_1_E7 KEY_4 + SHIFT_MASK // 231 ç c CEDILLA -#define ISO_8859_1_E8 KEY_LEFT_BRACE + SHIFT_MASK // 232 è e GRAVE -#define ISO_8859_1_E9 KEY_SEMICOLON + SHIFT_MASK // 233 é e ACUTE -#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS TODO: check this -#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE -#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE -#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS -#define ISO_8859_1_F0 0 // 240 ð ETH -#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE -#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE -#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE -#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE -#define ISO_8859_1_F6 KEY_SEMICOLON // 246 ö o DIAERESIS -#define ISO_8859_1_F7 0 // 247 ÷ DIVISION -#define ISO_8859_1_F8 0 // 248 ø o STROKE -#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE -#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE -#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC KEY_LEFT_BRACE // 252 ü u DIAERESIS -#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE -#define ISO_8859_1_FE 0 // 254 þ THORN -#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS -#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign -// not yet implemented -#define UNICODE_EXTRA00 0x20AC -#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign - -#endif // LAYOUT_GERMAN_SWISS - - - - -#ifdef LAYOUT_FRENCH_SWISS - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define DEADKEYS_MASK 0x0700 -#define CIRCUMFLEX_BITS 0x0100 -#define GRAVE_ACCENT_BITS 0x0200 -#define DIAERESIS_BITS 0x0300 -#define TILDE_BITS 0x0400 -#define ACUTE_ACCENT_BITS 0x0500 -#define KEYCODE_TYPE uint16_t -#define DEADKEY_CIRCUMFLEX KEY_EQUAL -#define DEADKEY_ACUTE_ACCENT KEY_MINUS + ALTGR_MASK -#define DEADKEY_GRAVE_ACCENT KEY_EQUAL + SHIFT_MASK -#define DEADKEY_DIAERESIS KEY_RIGHT_BRACE -#define DEADKEY_TILDE KEY_EQUAL + ALTGR_MASK -#define KEY_NON_US_100 63 - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_RIGHT_BRACE + SHIFT_MASK // 33 ! -#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " -#define ASCII_23 KEY_3 + ALTGR_MASK // 35 # -#define ASCII_24 KEY_BACKSLASH // 36 $ -#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % -#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & -#define ASCII_27 KEY_MINUS // 39 ' -#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) -#define ASCII_2A KEY_3 + SHIFT_MASK // 42 * -#define ASCII_2B KEY_1 + SHIFT_MASK // 43 + -#define ASCII_2C KEY_COMMA // 44 , -#define ASCII_2D KEY_SLASH // 45 - -#define ASCII_2E KEY_PERIOD // 46 . -#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / -#define ASCII_30 KEY_0 // 48 0 -#define ASCII_31 KEY_1 // 49 1 -#define ASCII_32 KEY_2 // 50 2 -#define ASCII_33 KEY_3 // 51 3 -#define ASCII_34 KEY_4 // 52 4 -#define ASCII_35 KEY_5 // 53 5 -#define ASCII_36 KEY_6 // 54 6 -#define ASCII_37 KEY_7 // 55 7 -#define ASCII_38 KEY_8 // 55 8 -#define ASCII_39 KEY_9 // 57 9 -#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : -#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; -#define ASCII_3C KEY_NON_US_100 // 60 < -#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = -#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > -#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_2 + ALTGR_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Z + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Y + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_LEFT_BRACE + ALTGR_MASK // 91 [ -#define ASCII_5C KEY_NON_US_100 + ALTGR_MASK // 92 -#define ASCII_5D KEY_RIGHT_BRACE + ALTGR_MASK // 93 ] -#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ -#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ -#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Z // 121 y -#define ASCII_7A KEY_Y // 122 z -#define ASCII_7B KEY_QUOTE + ALTGR_MASK // 123 { -#define ASCII_7C KEY_7 + ALTGR_MASK // 124 | -#define ASCII_7D KEY_BACKSLASH + ALTGR_MASK // 125 } -#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 -#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space -#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 KEY_8 + ALTGR_MASK // 162 ¢ Cent Sign -#define ISO_8859_1_A3 KEY_BACKSLASH + SHIFT_MASK // 163 £ Pound Sign -#define ISO_8859_1_A4 0 // 164 ¤ Currency Sign -#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 KEY_1 + ALTGR_MASK // 166 ¦ BROKEN BAR -#define ISO_8859_1_A7 KEY_5 + ALTGR_MASK // 167 § SECTION SIGN -#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC KEY_6 + ALTGR_MASK // 172 ¬ NOT SIGN -#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN -#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF 0 // 175 ¯ MACRON -#define ISO_8859_1_B0 KEY_4 + ALTGR_MASK // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN -#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT -#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA -#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE -#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE -#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE -#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE -#define ISO_8859_1_C6 0 // 198 Æ AE -#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA -#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE -#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE -#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS -#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE -#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE -#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 0 // 208 Ð ETH -#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE -#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE -#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE -#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE -#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION -#define ISO_8859_1_D8 0 // 216 Ø O STROKE -#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE -#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE -#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS -#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE -#define ISO_8859_1_DE 0 // 222 Þ THORN -#define ISO_8859_1_DF 0 // 223 ß SHARP S -#define ISO_8859_1_E0 KEY_QUOTE // 224 à a GRAVE -#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE -#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE -#define ISO_8859_1_E4 KEY_QUOTE + SHIFT_MASK // 228 ä a DIAERESIS -#define ISO_8859_1_E5 0 // 229 å a RING ABOVE -#define ISO_8859_1_E6 0 // 230 æ ae -#define ISO_8859_1_E7 KEY_4 + SHIFT_MASK // 231 ç c CEDILLA -#define ISO_8859_1_E8 KEY_LEFT_BRACE // 232 è e GRAVE -#define ISO_8859_1_E9 KEY_SEMICOLON // 233 é e ACUTE -#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS -#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE -#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE -#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS -#define ISO_8859_1_F0 0 // 240 ð ETH -#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE -#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE -#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE -#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE -#define ISO_8859_1_F6 KEY_SEMICOLON + SHIFT_MASK // 246 ö o DIAERESIS -#define ISO_8859_1_F7 0 // 247 ÷ DIVISION -#define ISO_8859_1_F8 0 // 248 ø o STROKE -#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE -#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE -#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC KEY_LEFT_BRACE + SHIFT_MASK // 252 ü u DIAERESIS -#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE -#define ISO_8859_1_FE 0 // 254 þ THORN -#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS -#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign -// not yet implemented -#define UNICODE_EXTRA00 0x20AC -#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign - -#endif // LAYOUT_FRENCH_SWISS - - - - - -#ifdef LAYOUT_SPANISH_LATIN_AMERICA - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define DEADKEYS_MASK 0x0700 -#define CIRCUMFLEX_BITS 0x0100 -#define ACUTE_ACCENT_BITS 0x0200 -#define GRAVE_ACCENT_BITS 0x0300 -#define DIAERESIS_BITS 0x0400 -#define KEYCODE_TYPE uint16_t -#define DEADKEY_CIRCUMFLEX KEY_QUOTE + ALTGR_MASK -#define DEADKEY_ACUTE_ACCENT KEY_LEFT_BRACE -#define DEADKEY_GRAVE_ACCENT KEY_BACKSLASH + ALTGR_MASK -#define DEADKEY_DIAERESIS KEY_LEFT_BRACE + SHIFT_MASK -#define KEY_NON_US_100 63 - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! -#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " -#define ASCII_23 KEY_3 + ALTGR_MASK // 35 # -#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ -#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % -#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & -#define ASCII_27 KEY_MINUS // 39 ' -#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) -#define ASCII_2A KEY_RIGHT_BRACE + SHIFT_MASK // 42 * -#define ASCII_2B KEY_RIGHT_BRACE // 43 + -#define ASCII_2C KEY_COMMA // 44 , -#define ASCII_2D KEY_SLASH // 45 - -#define ASCII_2E KEY_PERIOD // 46 . -#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / -#define ASCII_30 KEY_0 // 48 0 -#define ASCII_31 KEY_1 // 49 1 -#define ASCII_32 KEY_2 // 50 2 -#define ASCII_33 KEY_3 // 51 3 -#define ASCII_34 KEY_4 // 52 4 -#define ASCII_35 KEY_5 // 53 5 -#define ASCII_36 KEY_6 // 54 6 -#define ASCII_37 KEY_7 // 55 7 -#define ASCII_38 KEY_8 // 55 8 -#define ASCII_39 KEY_9 // 57 9 -#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : -#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; -#define ASCII_3C KEY_NON_US_100 // 60 < -#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = -#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > -#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_Q + ALTGR_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_QUOTE + SHIFT_MASK // 91 [ -#define ASCII_5C KEY_MINUS + ALTGR_MASK // 92 -#define ASCII_5D KEY_BACKSLASH + SHIFT_MASK // 93 ] -#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ -#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ -#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Y // 121 y -#define ASCII_7A KEY_Z // 122 z -#define ASCII_7B KEY_QUOTE // 123 { -#define ASCII_7C KEY_TILDE // 124 | -#define ASCII_7D KEY_BACKSLASH // 125 } -#define ASCII_7E KEY_RIGHT_BRACE + ALTGR_MASK // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 - -#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space -#define ISO_8859_1_A1 KEY_EQUAL + SHIFT_MASK // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN -#define ISO_8859_1_A3 0 // 163 £ Pound Sign -#define ISO_8859_1_A4 0 // 164 ¤ Currency Sign -#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR -#define ISO_8859_1_A7 0 // 167 § SECTION SIGN -#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC KEY_TILDE + ALTGR_MASK // 172 ¬ NOT SIGN -#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN -#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF 0 // 175 ¯ MACRON -#define ISO_8859_1_B0 KEY_TILDE + SHIFT_MASK // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN -#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT -#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA -#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF KEY_EQUAL // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE -#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE -#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 0 // 195 Ã A TILDE -#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE -#define ISO_8859_1_C6 0 // 198 Æ AE -#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA -#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE -#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE -#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS -#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE -#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE -#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 0 // 208 Ð ETH -#define ISO_8859_1_D1 KEY_SEMICOLON + SHIFT_MASK // 209 Ñ N TILDE -#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE -#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE -#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 0 // 213 Õ O TILDE -#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION -#define ISO_8859_1_D8 0 // 216 Ø O STROKE -#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE -#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE -#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS -#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE -#define ISO_8859_1_DE 0 // 222 Þ THORN -#define ISO_8859_1_DF 0 // 223 ß SHARP S -#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE -#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE -#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 0 // 227 ã a TILDE -#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS -#define ISO_8859_1_E5 0 // 229 å a RING ABOVE -#define ISO_8859_1_E6 0 // 230 æ ae -#define ISO_8859_1_E7 0 // 231 ç c CEDILLA -#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE -#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE -#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS -#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE -#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE -#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS -#define ISO_8859_1_F0 0 // 240 ð ETH -#define ISO_8859_1_F1 KEY_SEMICOLON // 241 ñ n TILDE -#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE -#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE -#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 0 // 245 õ o TILDE -#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS -#define ISO_8859_1_F7 0 // 247 ÷ DIVISION -#define ISO_8859_1_F8 0 // 248 ø o STROKE -#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE -#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE -#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS -#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE -#define ISO_8859_1_FE 0 // 254 þ THORN -#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS - -#endif // LAYOUT_SPANISH_LATIN_AMERICA - - - -#ifdef LAYOUT_IRISH - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define DEADKEYS_MASK 0x0300 -#define GRAVE_ACCENT_BITS 0x0100 -#define ACUTE_ACCENT_BITS 0x0200 -#define KEYCODE_TYPE uint16_t -#define DEADKEY_ACUTE_ACCENT KEY_QUOTE + ALTGR_MASK -#define DEADKEY_GRAVE_ACCENT KEY_TILDE -#define KEY_NON_US_100 63 - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! -#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " -#define ASCII_23 KEY_BACKSPACE // 35 # -#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ -#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % -#define ASCII_26 KEY_7 + SHIFT_MASK // 38 & -#define ASCII_27 KEY_QUOTE // 39 ' -#define ASCII_28 KEY_9 + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_0 + SHIFT_MASK // 41 ) -#define ASCII_2A KEY_8 + SHIFT_MASK // 42 * -#define ASCII_2B KEY_EQUAL + SHIFT_MASK // 43 + -#define ASCII_2C KEY_COMMA // 44 , -#define ASCII_2D KEY_MINUS // 45 - -#define ASCII_2E KEY_PERIOD // 46 . -#define ASCII_2F KEY_SLASH // 47 / -#define ASCII_30 KEY_0 // 48 0 -#define ASCII_31 KEY_1 // 49 1 -#define ASCII_32 KEY_2 // 50 2 -#define ASCII_33 KEY_3 // 51 3 -#define ASCII_34 KEY_4 // 52 4 -#define ASCII_35 KEY_5 // 53 5 -#define ASCII_36 KEY_6 // 54 6 -#define ASCII_37 KEY_7 // 55 7 -#define ASCII_38 KEY_8 // 55 8 -#define ASCII_39 KEY_9 // 57 9 -#define ASCII_3A KEY_SEMICOLON + SHIFT_MASK // 58 : -#define ASCII_3B KEY_SEMICOLON // 59 ; -#define ASCII_3C KEY_COMMA + SHIFT_MASK // 60 < -#define ASCII_3D KEY_EQUAL // 61 = -#define ASCII_3E KEY_PERIOD + SHIFT_MASK // 62 > -#define ASCII_3F KEY_SLASH + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_QUOTE + SHIFT_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_LEFT_BRACE // 91 [ -#define ASCII_5C KEY_NON_US_100 // 92 -#define ASCII_5D KEY_RIGHT_BRACE // 93 ] -#define ASCII_5E KEY_6 + SHIFT_MASK // 94 ^ -#define ASCII_5F KEY_MINUS + SHIFT_MASK // 95 _ -#define ASCII_60 KEY_QUOTE + SHIFT_MASK + ALTGR_MASK // 96 ` -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Y // 121 y -#define ASCII_7A KEY_Z // 122 z -#define ASCII_7B KEY_LEFT_BRACE + SHIFT_MASK // 123 { -#define ASCII_7C KEY_NON_US_100 + SHIFT_MASK // 124 | -#define ASCII_7D KEY_RIGHT_BRACE + SHIFT_MASK // 125 } -#define ASCII_7E KEY_BACKSLASH + SHIFT_MASK // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 - -#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space -#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN -#define ISO_8859_1_A3 KEY_3 + SHIFT_MASK // 163 £ Pound Sign -#define ISO_8859_1_A4 0 // 164 ¤ Currency or Euro Sign -#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 KEY_TILDE + ALTGR_MASK // 166 ¦ BROKEN BAR -#define ISO_8859_1_A7 0 // 167 § SECTION SIGN -#define ISO_8859_1_A8 0 // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC KEY_TILDE + SHIFT_MASK // 172 ¬ NOT SIGN -#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN -#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF 0 // 175 ¯ MACRON -#define ISO_8859_1_B0 0 // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 0 // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN -#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT -#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA -#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A // 192 À A GRAVE -#define ISO_8859_1_C1 KEY_A + ALTGR_MASK + SHIFT_MASK // 193 Á A ACUTE -#define ISO_8859_1_C2 0 // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 0 // 195 Ã A TILDE -#define ISO_8859_1_C4 0 // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE -#define ISO_8859_1_C6 0 // 198 Æ AE -#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA -#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E // 200 È E GRAVE -#define ISO_8859_1_C9 KEY_E + ALTGR_MASK + SHIFT_MASK // 201 É E ACUTE -#define ISO_8859_1_CA 0 // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB 0 // 203 Ë E DIAERESIS -#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I // 204 Ì I GRAVE -#define ISO_8859_1_CD KEY_I + ALTGR_MASK + SHIFT_MASK // 205 Í I ACUTE -#define ISO_8859_1_CE 0 // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF 0 // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 0 // 208 Ð ETH -#define ISO_8859_1_D1 0 // 209 Ñ N TILDE -#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O // 210 Ò O GRAVE -#define ISO_8859_1_D3 KEY_O + ALTGR_MASK + SHIFT_MASK // 211 Ó O ACUTE -#define ISO_8859_1_D4 0 // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 0 // 213 Õ O TILDE -#define ISO_8859_1_D6 0 // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION -#define ISO_8859_1_D8 0 // 216 Ø O STROKE -#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U // 217 Ù U GRAVE -#define ISO_8859_1_DA KEY_U + ALTGR_MASK + SHIFT_MASK // 218 Ú U ACUTE -#define ISO_8859_1_DB 0 // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC 0 // 220 Ü U DIAERESIS -#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE -#define ISO_8859_1_DE 0 // 222 Þ THORN -#define ISO_8859_1_DF 0 // 223 ß SHARP S -#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE -#define ISO_8859_1_E1 KEY_A + ALTGR_MASK // 225 á a ACUTE -#define ISO_8859_1_E2 0 // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 0 // 227 ã a TILDE -#define ISO_8859_1_E4 0 // 228 ä a DIAERESIS -#define ISO_8859_1_E5 0 // 229 å a RING ABOVE -#define ISO_8859_1_E6 0 // 230 æ ae -#define ISO_8859_1_E7 0 // 231 ç c CEDILLA -#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE -#define ISO_8859_1_E9 KEY_E + ALTGR_MASK // 233 é e ACUTE -#define ISO_8859_1_EA 0 // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB 0 // 235 ë e DIAERESIS -#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE -#define ISO_8859_1_ED KEY_I + ALTGR_MASK // 237 í i ACUTE -#define ISO_8859_1_EE 0 // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF 0 // 239 ï i DIAERESIS -#define ISO_8859_1_F0 0 // 240 ð ETH -#define ISO_8859_1_F1 0 // 241 ñ n TILDE -#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE -#define ISO_8859_1_F3 KEY_O + ALTGR_MASK // 243 ó o ACUTE -#define ISO_8859_1_F4 0 // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 0 // 245 õ o TILDE -#define ISO_8859_1_F6 0 // 246 ö o DIAERESIS -#define ISO_8859_1_F7 0 // 247 ÷ DIVISION -#define ISO_8859_1_F8 0 // 248 ø o STROKE -#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE -#define ISO_8859_1_FA KEY_U + ALTGR_MASK // 250 ú u ACUTE -#define ISO_8859_1_FB 0 // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC 0 // 252 ü u DIAERESIS -#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE -#define ISO_8859_1_FE 0 // 254 þ THORN -#define ISO_8859_1_FF 0 // 255 ÿ y DIAERESIS -#define UNICODE_20AC KEY_4 + ALTGR_MASK // € Euro Sign -// not yet implemented -#define UNICODE_EXTRA00 0x20AC -#define KEYCODE_EXTRA00 KEY_4 + ALTGR_MASK // 20AC € Euro Sign - -#endif // LAYOUT_IRISH - - - - -#ifdef LAYOUT_ICELANDIC - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define DEADKEYS_MASK 0x0700 -#define CIRCUMFLEX_BITS 0x0100 -#define ACUTE_ACCENT_BITS 0x0200 -#define GRAVE_ACCENT_BITS 0x0300 -#define DIAERESIS_BITS 0x0400 -#define RING_ABOVE_BITS 0x0500 -#define KEYCODE_TYPE uint16_t -#define DEADKEY_CIRCUMFLEX KEY_QUOTE + ALTGR_MASK -#define DEADKEY_ACUTE_ACCENT KEY_QUOTE -#define DEADKEY_GRAVE_ACCENT KEY_BACKSLASH + ALTGR_MASK -#define DEADKEY_DIAERESIS KEY_TILDE + SHIFT_MASK -#define DEADKEY_RING_ABOVE KEY_TILDE -#define KEY_NON_US_100 63 - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! -#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " -#define ASCII_23 KEY_3 + SHIFT_MASK // 35 # -#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ -#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % -#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & -#define ASCII_27 KEY_QUOTE + SHIFT_MASK // 39 ' -#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) -#define ASCII_2A KEY_BACKSLASH + SHIFT_MASK // 42 * -#define ASCII_2B KEY_BACKSLASH // 43 + -#define ASCII_2C KEY_COMMA // 44 , -#define ASCII_2D KEY_EQUAL // 45 - -#define ASCII_2E KEY_PERIOD // 46 . -#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / -#define ASCII_30 KEY_0 // 48 0 -#define ASCII_31 KEY_1 // 49 1 -#define ASCII_32 KEY_2 // 50 2 -#define ASCII_33 KEY_3 // 51 3 -#define ASCII_34 KEY_4 // 52 4 -#define ASCII_35 KEY_5 // 53 5 -#define ASCII_36 KEY_6 // 54 6 -#define ASCII_37 KEY_7 // 55 7 -#define ASCII_38 KEY_8 // 55 8 -#define ASCII_39 KEY_9 // 57 9 -#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : -#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; -#define ASCII_3C KEY_NON_US_100 // 60 < -#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = -#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > -#define ASCII_3F KEY_RIGHT_BRACE + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_Q + ALTGR_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_8 + ALTGR_MASK // 91 [ -#define ASCII_5C KEY_MINUS + ALTGR_MASK // 92 -#define ASCII_5D KEY_9 + ALTGR_MASK // 93 ] -#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ -#define ASCII_5F KEY_EQUAL + SHIFT_MASK // 95 _ -#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Y // 121 y -#define ASCII_7A KEY_Z // 122 z -#define ASCII_7B KEY_7 + ALTGR_MASK // 123 { -#define ASCII_7C KEY_NON_US_100 + ALTGR_MASK // 124 | -#define ASCII_7D KEY_0 + ALTGR_MASK // 125 } -#define ASCII_7E KEY_RIGHT_BRACE + ALTGR_MASK // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 - -#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space -#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN -#define ISO_8859_1_A3 0 // 163 £ Pound Sign -#define ISO_8859_1_A4 0 // 164 ¤ Currency or Euro Sign -#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR ?? -#define ISO_8859_1_A7 0 // 167 § SECTION SIGN -#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN ?? -#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN -#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF 0 // 175 ¯ MACRON -#define ISO_8859_1_B0 KEY_TILDE + ALTGR_MASK // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 KEY_M + ALTGR_MASK // 181 µ MICRO SIGN -#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT -#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA -#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE -#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + ALTGR_MASK // 193 Á A ACUTE -#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 0 // 195 Ã A TILDE -#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 RING_ABOVE_BITS + KEY_A + SHIFT_MASK // 197 Å A RING ABOVE -#define ISO_8859_1_C6 KEY_SEMICOLON + SHIFT_MASK // 198 Æ AE -#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA -#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE -#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE -#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS -#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE -#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE -#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 KEY_LEFT_BRACE + SHIFT_MASK // 208 Ð ETH -#define ISO_8859_1_D1 0 // 209 Ñ N TILDE -#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE -#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE -#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 0 // 213 Õ O TILDE -#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION -#define ISO_8859_1_D8 0 // 216 Ø O STROKE -#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE -#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE -#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS -#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE -#define ISO_8859_1_DE KEY_SLASH + SHIFT_MASK // 222 Þ THORN -#define ISO_8859_1_DF 0 // 223 ß SHARP S -#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE -#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE -#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 0 // 227 ã a TILDE -#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS -#define ISO_8859_1_E5 RING_ABOVE_BITS + KEY_A // 229 å a RING ABOVE -#define ISO_8859_1_E6 KEY_SEMICOLON // 230 æ ae -#define ISO_8859_1_E7 0 // 231 ç c CEDILLA -#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE -#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE -#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS -#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE -#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE -#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS -#define ISO_8859_1_F0 KEY_LEFT_BRACE // 240 ð ETH -#define ISO_8859_1_F1 0 // 241 ñ n TILDE -#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE -#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE -#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 0 // 245 õ o TILDE -#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS -#define ISO_8859_1_F7 0 // 247 ÷ DIVISION -#define ISO_8859_1_F8 0 // 248 ø o STROKE -#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE -#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE -#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS -#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE -#define ISO_8859_1_FE KEY_SLASH // 254 þ THORN -#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS -#define UNICODE_20AC KEY_5 + ALTGR_MASK // € Euro Sign -// not yet implemented -#define UNICODE_EXTRA00 0x20AC -#define KEYCODE_EXTRA00 KEY_5 + ALTGR_MASK // 20AC € Euro Sign - -#endif // LAYOUT_ICELANDIC - - - -#ifdef LAYOUT_TURKISH -// http://forum.pjrc.com/threads/18781-Turkish-Language-Support - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define DEADKEYS_MASK 0x0700 -#define CIRCUMFLEX_BITS 0x0100 -#define ACUTE_ACCENT_BITS 0x0200 -#define GRAVE_ACCENT_BITS 0x0300 -#define TILDE_BITS 0x0400 -#define DIAERESIS_BITS 0x0500 -#define KEYCODE_TYPE uint16_t -#define DEADKEY_CIRCUMFLEX KEY_3 + SHIFT_MASK -#define DEADKEY_ACUTE_ACCENT KEY_SEMICOLON + ALTGR_MASK -#define DEADKEY_GRAVE_ACCENT KEY_BACKSLASH + ALTGR_MASK -#define DEADKEY_TILDE KEY_RIGHT_BRACE + ALTGR_MASK -#define DEADKEY_DIAERESIS KEY_LEFT_BRACE + ALTGR_MASK - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! -#define ASCII_22 KEY_TILDE // 34 " -#define ASCII_23 KEY_3 + ALTGR_MASK // 35 # -#define ASCII_24 KEY_4 + ALTGR_MASK // 36 $ -#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % -#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & -#define ASCII_27 KEY_2 + SHIFT_MASK // 39 ' -#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) -#define ASCII_2A KEY_MINUS // 42 * -#define ASCII_2B KEY_4 + SHIFT_MASK // 43 + -#define ASCII_2C KEY_BACKSLASH // 44 , -#define ASCII_2D KEY_EQUAL // 45 - -#define ASCII_2E KEY_SLASH // 46 . -#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / -#define ASCII_30 KEY_0 // 48 0 -#define ASCII_31 KEY_1 // 49 1 -#define ASCII_32 KEY_2 // 50 2 -#define ASCII_33 KEY_3 // 51 3 -#define ASCII_34 KEY_4 // 52 4 -#define ASCII_35 KEY_5 // 53 5 -#define ASCII_36 KEY_6 // 54 6 -#define ASCII_37 KEY_7 // 55 7 -#define ASCII_38 KEY_8 // 55 8 -#define ASCII_39 KEY_9 // 57 9 -#define ASCII_3A KEY_SLASH + SHIFT_MASK // 58 : -#define ASCII_3B KEY_BACKSLASH + SHIFT_MASK // 59 ; -#define ASCII_3C KEY_TILDE + ALTGR_MASK // 60 < -#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = -#define ASCII_3E KEY_1 + ALTGR_MASK // 62 > -#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_Q + ALTGR_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_8 + ALTGR_MASK // 91 [ -#define ASCII_5C KEY_MINUS + ALTGR_MASK // 92 -#define ASCII_5D KEY_9 + ALTGR_MASK // 93 ] -#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ -#define ASCII_5F KEY_EQUAL + SHIFT_MASK // 95 _ -#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_QUOTE // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Y // 121 y -#define ASCII_7A KEY_Z // 122 z -#define ASCII_7B KEY_7 + ALTGR_MASK // 123 { -#define ASCII_7C KEY_EQUAL + ALTGR_MASK // 124 | -#define ASCII_7D KEY_0 + ALTGR_MASK // 125 } -#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 - -#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space -#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN -#define ISO_8859_1_A3 KEY_2 + ALTGR_MASK // 163 £ Pound Sign -#define ISO_8859_1_A4 0 // 164 ¤ Currency or Euro Sign -#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR ?? -#define ISO_8859_1_A7 0 // 167 § SECTION SIGN -#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN ?? -#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN -#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF 0 // 175 ¯ MACRON -#define ISO_8859_1_B0 0 // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN -#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT -#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA -#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD KEY_5 + ALTGR_MASK // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE -#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE -#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE -#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE -#define ISO_8859_1_C6 KEY_A + ALTGR_MASK // 198 Æ AE -#define ISO_8859_1_C7 KEY_PERIOD + SHIFT_MASK // 199 Ç C CEDILLA -#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE -#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE -#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS -#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE -#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE -#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 0 // 208 Ð ETH -#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE -#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE -#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE -#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE -#define ISO_8859_1_D6 KEY_COMMA + SHIFT_MASK // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION -#define ISO_8859_1_D8 0 // 216 Ø O STROKE -#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE -#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE -#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC KEY_RIGHT_BRACE + SHIFT_MASK // 220 Ü U DIAERESIS -#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE -#define ISO_8859_1_DE 0 // 222 Þ THORN -#define ISO_8859_1_DF KEY_S + ALTGR_MASK // 223 ß SHARP S -#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE -#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE -#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE -#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS -#define ISO_8859_1_E5 0 // 229 å a RING ABOVE -#define ISO_8859_1_E6 0 // 230 æ ae -#define ISO_8859_1_E7 KEY_PERIOD // 231 ç c CEDILLA -#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE -#define ISO_8859_1_E9 KEY_TILDE + SHIFT_MASK // 233 é e ACUTE -#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS -#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE -#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE -#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS -#define ISO_8859_1_F0 0 // 240 ð ETH -#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE -#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE -#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE -#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE -#define ISO_8859_1_F6 KEY_COMMA // 246 ö o DIAERESIS -#define ISO_8859_1_F7 0 // 247 ÷ DIVISION -#define ISO_8859_1_F8 0 // 248 ø o STROKE -#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE -#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE -#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC KEY_RIGHT_BRACE // 252 ü u DIAERESIS -#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE -#define ISO_8859_1_FE 0 // 254 þ THORN -#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS -#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign - -// not yet implemented -#define UNICODE_EXTRA00 0x20AC -#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign -#define UNICODE_EXTRA01 0x011E -#define KEYCODE_EXTRA01 KEY_LEFT_BRACE + SHIFT_MASK // 011E Ğ Latin capital letter G with breve -#define UNICODE_EXTRA02 0x011F -#define KEYCODE_EXTRA02 KEY_LEFT_BRACE // 011F ğ Latin small letter g with breve -#define UNICODE_EXTRA03 0x0130 -#define KEYCODE_EXTRA03 KEY_QUOTE + SHIFT_MASK // 0130 İ Latin captial letter I with dot above -#define UNICODE_EXTRA04 0x0131 -#define KEYCODE_EXTRA04 KEY_I // 0131 ı Latin small letter dotless i -#define UNICODE_EXTRA05 0x015E -#define KEYCODE_EXTRA05 KEY_SEMICOLON + SHIFT_MASK // 015E Ş Latin capital letter S with cedilla -#define UNICODE_EXTRA06 0x0151 -#define KEYCODE_EXTRA06 KEY_SEMICOLON // 0151 ş Latin small letter s with cedilla - -#endif // LAYOUT_TURKISH - - - -#ifdef LAYOUT_CZECH -// http://forum.pjrc.com/threads/24495-Czech-keyboard - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define DEADKEYS_MASK 0x0F00 -#define ACUTE_ACCENT_BITS 0x0100 // TODO: the Czech might not support some -#define DEGREE_SIGN_BITS 0x0200 // of these deadkeys, perhaps not any??? -#define CARON_BITS 0x0300 -//#define CIRCUMFLEX_BITS 0x0400 -#define BREVE_BITS 0x0500 -#define OGONEK_BITS 0x0600 -//#define GRAVE_ACCENT_BITS 0x0700 -#define DOT_ABOVE_BITS 0x0800 -#define DOUBLE_ACUTE_BITS 0x0900 -//#define DIAERESIS_BITS 0x0A00 -#define CEDILLA_BITS 0x0B00 -#define KEYCODE_TYPE uint16_t -#define DEADKEY_ACUTE_ACCENT KEY_EQUAL // TODO: is it KEY_9 + ALTGR_MASK -#define DEADKEY_DEGREE_SIGN KEY_TILDE + SHIFT_MASK // TODO: is it KEY_5 + ALTGR_MASK -#define DEADKEY_CARON KEY_EQUAL + SHIFT_MASK // TODO: is it KEY_2 + ALTGR_MASK -//#define DEADKEY_CIRCUMFLEX KEY_3 + ALTGR_MASK -#define DEADKEY_BREVE KEY_4 + ALTGR_MASK -#define DEADKEY_OGONEK KEY_6 + ALTGR_MASK -//#define DEADKEY_GRAVE_ACCENT KEY_7 + ALTGR_MASK -#define DEADKEY_DOT_ABOVE KEY_8 + ALTGR_MASK -#define DEADKEY_DOUBLE_ACUTE KEY_0 + ALTGR_MASK -#define DEADKEY_DIAERESIS KEY_MINUS + ALTGR_MASK -#define DEADKEY_CEDILLA KEY_EQUAL + ALTGR_MASK -#define KEY_NON_US_100 63 -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_QUOTE + SHIFT_MASK // 33 ! -#define ASCII_22 KEY_SEMICOLON + SHIFT_MASK // 34 " -#define ASCII_23 KEY_X + ALTGR_MASK // 35 # -#define ASCII_24 KEY_SEMICOLON + ALTGR_MASK // 36 $ -#define ASCII_25 KEY_MINUS + SHIFT_MASK // 37 % -#define ASCII_26 KEY_C + ALTGR_MASK // 38 & -#define ASCII_27 KEY_BACKSLASH + SHIFT_MASK // 39 ' -#define ASCII_28 KEY_RIGHT_BRACE + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_RIGHT_BRACE // 41 ) -#define ASCII_2A KEY_SLASH + ALTGR_MASK // 42 * -#define ASCII_2B KEY_1 // 43 + -#define ASCII_2C KEY_COMMA // 44 , -#define ASCII_2D KEY_SLASH // 45 - -#define ASCII_2E KEY_PERIOD // 46 . -#define ASCII_2F KEY_LEFT_BRACE + SHIFT_MASK // 47 / -#define ASCII_30 KEY_0 + SHIFT_MASK // 48 0 -#define ASCII_31 KEY_1 + SHIFT_MASK // 49 1 -#define ASCII_32 KEY_2 + SHIFT_MASK // 50 2 -#define ASCII_33 KEY_3 + SHIFT_MASK // 51 3 -#define ASCII_34 KEY_4 + SHIFT_MASK // 52 4 -#define ASCII_35 KEY_5 + SHIFT_MASK // 53 5 -#define ASCII_36 KEY_6 + SHIFT_MASK // 54 6 -#define ASCII_37 KEY_7 + SHIFT_MASK // 55 7 -#define ASCII_38 KEY_8 + SHIFT_MASK // 55 8 -#define ASCII_39 KEY_9 + SHIFT_MASK // 57 9 -#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : -#define ASCII_3B KEY_TILDE // 59 ; -#define ASCII_3C KEY_COMMA + ALTGR_MASK // 60 < -#define ASCII_3D KEY_MINUS // 61 = -#define ASCII_3E KEY_PERIOD + ALTGR_MASK // 62 > -#define ASCII_3F KEY_COMMA + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_V + ALTGR_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Z + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Y + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_F + ALTGR_MASK // 91 [ -#define ASCII_5C KEY_NON_US_100 // 92 -#define ASCII_5D KEY_G + ALTGR_MASK // 93 ] -#define ASCII_5E KEY_3 + ALTGR_MASK // 94 ^ TODO: testme -#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ -#define ASCII_60 KEY_7 + ALTGR_MASK // 96 ` TODO: testme -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Z // 121 y -#define ASCII_7A KEY_Y // 122 z -#define ASCII_7B KEY_B + ALTGR_MASK // 123 { -#define ASCII_7C KEY_NON_US_100 + SHIFT_MASK // 124 | -#define ASCII_7D KEY_N + ALTGR_MASK // 125 } -#define ASCII_7E KEY_1 + ALTGR_MASK // 126 ~ TODO: fixme -#define ASCII_7F KEY_BACKSPACE // 127 -#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space -#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 0 // 162 ¢ Cent Sign -#define ISO_8859_1_A3 0 // 163 £ Pound Sign -#define ISO_8859_1_A4 KEY_BACKSLASH + ALTGR_MASK // 164 ¤ Currency Sign -#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR -#define ISO_8859_1_A7 KEY_QUOTE // 167 § SECTION SIGN -#define ISO_8859_1_A8 0 // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN -#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN -#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF 0 // 175 ¯ MACRON -#define ISO_8859_1_B0 DEGREE_SIGN_BITS + KEY_SPACE // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN -#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT -#define ISO_8859_1_B8 CEDILLA_BITS + KEY_SPACE // 184 ¸ CEDILLA -#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 0 // 192 À A GRAVE -#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE -#define ISO_8859_1_C2 0 // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 0 // 195 Ã A TILDE -#define ISO_8859_1_C4 0 // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE -#define ISO_8859_1_C6 0 // 198 Æ AE -#define ISO_8859_1_C7 CEDILLA_BITS + KEY_C + SHIFT_MASK // 199 Ç C CEDILLA -#define ISO_8859_1_C8 0 // 200 È E GRAVE -#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE -#define ISO_8859_1_CA 0 // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB 0 // 203 Ë E DIAERESIS -#define ISO_8859_1_CC 0 // 204 Ì I GRAVE -#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE -#define ISO_8859_1_CE 0 // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF 0 // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 0 // 208 Ð ETH -#define ISO_8859_1_D1 0 // 209 Ñ N TILDE -#define ISO_8859_1_D2 0 // 210 Ò O GRAVE -#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE -#define ISO_8859_1_D4 0 // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 0 // 213 Õ O TILDE -#define ISO_8859_1_D6 0 // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 KEY_RIGHT_BRACE + ALTGR_MASK // 215 × MULTIPLICATION -#define ISO_8859_1_D8 0 // 216 Ø O STROKE -#define ISO_8859_1_D9 0 // 217 Ù U GRAVE -#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE -#define ISO_8859_1_DB 0 // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC 0 // 220 Ü U DIAERESIS -#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Z + SHIFT_MASK // 221 Ý Y ACUTE -#define ISO_8859_1_DE 0 // 222 Þ THORN -#define ISO_8859_1_DF KEY_QUOTE + ALTGR_MASK // 223 ß SHARP S TODO: testme -#define ISO_8859_1_E0 0 // 224 à a GRAVE -#define ISO_8859_1_E1 KEY_8 // 225 á a ACUTE -#define ISO_8859_1_E2 0 // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 0 // 227 ã a TILDE -#define ISO_8859_1_E4 0 // 228 ä a DIAERESIS -#define ISO_8859_1_E5 0 // 229 å a RING ABOVE -#define ISO_8859_1_E6 0 // 230 æ ae -#define ISO_8859_1_E7 CEDILLA_BITS + KEY_C // 231 ç c CEDILLA -#define ISO_8859_1_E8 0 // 232 è e GRAVE -#define ISO_8859_1_E9 KEY_0 // 233 é e ACUTE -#define ISO_8859_1_EA 0 // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB 0 // 235 ë e DIAERESIS -#define ISO_8859_1_EC 0 // 236 ì i GRAVE -#define ISO_8859_1_ED KEY_9 // 237 í i ACUTE -#define ISO_8859_1_EE 0 // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF 0 // 239 ï i DIAERESIS -#define ISO_8859_1_F0 0 // 240 ð ETH -#define ISO_8859_1_F1 0 // 241 ñ n TILDE -#define ISO_8859_1_F2 0 // 242 ò o GRAVE -#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE -#define ISO_8859_1_F4 0 // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 0 // 245 õ o TILDE -#define ISO_8859_1_F6 0 // 246 ö o DIAERESIS -#define ISO_8859_1_F7 KEY_LEFT_BRACE + ALTGR_MASK // 247 ÷ DIVISION -#define ISO_8859_1_F8 0 // 248 ø o STROKE -#define ISO_8859_1_F9 0 // 249 ù u GRAVE -#define ISO_8859_1_FA KEY_LEFT_BRACE // 250 ú u ACUTE -#define ISO_8859_1_FB 0 // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC 0 // 252 ü u DIAERESIS -#define ISO_8859_1_FD KEY_7 // 253 ý y ACUTE -#define ISO_8859_1_FE 0 // 254 þ THORN -#define ISO_8859_1_FF 0 // 255 ÿ y DIAERESIS -#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign - -#define UNICODE_EXTRA00 0x011B // ě Small Letter E with caron -#define KEYCODE_EXTRA00 KEY_2 -#define UNICODE_EXTRA01 0x0161 // š Small Letter S with caron -#define KEYCODE_EXTRA01 KEY_3 -#define UNICODE_EXTRA02 0x010D // č Small Letter C with caron -#define KEYCODE_EXTRA02 KEY_4 -#define UNICODE_EXTRA03 0x0159 // ř Small Letter R with caron -#define KEYCODE_EXTRA03 KEY_5 -#define UNICODE_EXTRA04 0x017E // ž Small Letter Z with caron -#define KEYCODE_EXTRA04 KEY_6 -#define UNICODE_EXTRA05 0x016F // ů Small Letter U with ring above -#define KEYCODE_EXTRA05 KEY_SEMICOLON -#define UNICODE_EXTRA06 0x0111 // đ Small Letter D with stroke -#define KEYCODE_EXTRA06 KEY_S + ALTGR_MASK -#define UNICODE_EXTRA07 0x0110 // Đ Capital Letter D with stroke -#define KEYCODE_EXTRA07 KEY_D + ALTGR_MASK -#define UNICODE_EXTRA08 0x0142 // ł Small Letter L with stroke -#define KEYCODE_EXTRA08 KEY_K + ALTGR_MASK -#define UNICODE_EXTRA09 0x0141 // Ł Capital Letter L with stroke -#define KEYCODE_EXTRA09 KEY_L + ALTGR_MASK -#define UNICODE_EXTRA0A 0x20AC // € Euro Sign -#define KEYCODE_EXTRA0A KEY_E + ALTGR_MASK - -#endif // LAYOUT_CZECH - - - - - - -extern const KEYCODE_TYPE keycodes_ascii[]; -extern const KEYCODE_TYPE keycodes_iso_8859_1[]; - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif From d6e227961802e53b412d95d853147845d6f6fc43 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Fri, 9 Oct 2015 21:46:06 +0200 Subject: [PATCH 259/602] Initial commit of Keyboard API after IDE refactoring --- .../KeyboardioHID/src/HID-APIs/HID-Tables.h | 671 ++++++++++++++++++ .../src/HID-APIs/ImprovedKeylayouts.h | 348 +++++++++ .../src/HID-APIs/KeyboardAPI.cpp | 279 ++++++++ .../KeyboardioHID/src/HID-APIs/KeyboardAPI.h | 150 ++++ plugins/KeyboardioHID/src/HID-Settings.h | 112 +++ .../src/MultiReport/ImprovedKeyboard.cpp | 38 + .../src/MultiReport/ImprovedKeyboard.h | 43 ++ .../src/SingleReport/BootKeyboard.cpp | 109 +++ .../src/SingleReport/BootKeyboard.h | 55 ++ .../src/SingleReport/HID-Driver.h | 61 ++ 10 files changed, 1866 insertions(+) create mode 100644 plugins/KeyboardioHID/src/HID-APIs/HID-Tables.h create mode 100644 plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h create mode 100644 plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.cpp create mode 100644 plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h create mode 100644 plugins/KeyboardioHID/src/HID-Settings.h create mode 100644 plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.cpp create mode 100644 plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.h create mode 100644 plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp create mode 100644 plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h create mode 100644 plugins/KeyboardioHID/src/SingleReport/HID-Driver.h diff --git a/plugins/KeyboardioHID/src/HID-APIs/HID-Tables.h b/plugins/KeyboardioHID/src/HID-APIs/HID-Tables.h new file mode 100644 index 0000000000..bc56d52843 --- /dev/null +++ b/plugins/KeyboardioHID/src/HID-APIs/HID-Tables.h @@ -0,0 +1,671 @@ +// These mappings were extracted and transcribed from +// http://www.usb.org_SLASH_developers_SLASH_devclass_docs_SLASH_Hut1_12v2.pdf +// +// In most cases, I've preserved the "official" USB Implementers forum +// "Usage Name", though I've standardized some abbreviations and spacing +// that were inconsistent in the original specification. Non alpha-numeric +// characters in symbol names were converted into those characters' names. +// +// To match Arduino code style, all hid usage names are fully upper case. +// +// Not every HID usage listed in this file is currently supported by Arduino +// In particular, any System Control or Consumer Control entry that doesn't +// have a comment indicating that it's "HID type OSC" will require additional +// code in the Arduino core to work. +// +// Non-working usages are listed here in the interest of not having to manually +// convert more usage names each and every time our HID stack gets a little bit +// better. +// +// +// -- Jesse Vincent , January 2014 + +#pragma once + +// System control mappings + +#define HID_SYSTEM_POWER_DOWN 0x81 // HID type OSC +#define HID_SYSTEM_SLEEP 0x82 // HID type OSC +#define HID_SYSTEM_WAKE_UP 0x83 // HID type OSC +#define HID_SYSTEM_CONTEXT_MENU 0x84 // HID type OSC +#define HID_SYSTEM_MAIN_MENU 0x85 // HID type OSC +#define HID_SYSTEM_APP_MENU 0x86 // HID type OSC +#define HID_SYSTEM_MENU_HELP 0x87 // HID type OSC +#define HID_SYSTEM_MENU_EXIT 0x88 // HID type OSC +#define HID_SYSTEM_MENU_SELECT 0x89 // HID type OSC +#define HID_SYSTEM_MENU_RIGHT 0x8A // HID type RTC +#define HID_SYSTEM_MENU_LEFT 0x8B // HID type RTC +#define HID_SYSTEM_MENU_UP 0x8C // HID type RTC +#define HID_SYSTEM_MENU_DOWN 0x8D // HID type RTC +#define HID_SYSTEM_COLD_RESTART 0x8E // HID type OSC +#define HID_SYSTEM_WARM_RESTART 0x8F // HID type OSC +#define HID_D_PAD_UP 0x90 // HID type OOC +#define HID_D_PAD_DOWN 0x91 // HID type OOC +#define HID_D_PAD_RIGHT 0x92 // HID type OOC +#define HID_D_PAD_LEFT 0x93 // HID type OOC +// 0x94-0x9F are reserved +#define HID_SYSTEM_DOCK 0xA0 // HID type OSC +#define HID_SYSTEM_UNDOCK 0xA1 // HID type OSC +#define HID_SYSTEM_SETUP 0xA2 // HID type OSC +#define HID_SYSTEM_BREAK 0xA3 // HID type OSC +#define HID_SYSTEM_DEBUGGER_BREAK 0xA4 // HID type OSC +#define HID_APPLICATION_BREAK 0xA5 // HID type OSC +#define HID_APPLICATION_DEBUGGER_BREAK 0xA6 // HID type OSC +#define HID_SYSTEM_SPEAKER_MUTE 0xA7 // HID type OSC +#define HID_SYSTEM_HIBERNATE 0xA8 // HID type OSC +// 0xA9-0xAF are reserved +#define HID_SYSTEM_DISPLAY_INVERT 0xB0 // HID type OSC +#define HID_SYSTEM_DISPLAY_INTERNAL 0xB1 // HID type OSC +#define HID_SYSTEM_DISPLAY_EXTERNAL 0xB2 // HID type OSC +#define HID_SYSTEM_DISPLAY_BOTH 0xB3 // HID type OSC +#define HID_SYSTEM_DISPLAY_DUAL 0xB4 // HID type OSC +#define HID_SYSTEM_DISPLAY_TOGGLE_INT_SLASH_EXT 0xB5 // HID type OSC +#define HID_SYSTEM_DISPLAY_SWAP_PRIMARY_SLASH_SECONDARY 0xB6 // HID type OSC +#define HID_SYSTEM_DISPLAY_LCD_AUTOSCALE 0xB7 // HID type OSC + +// Keyboard HID mappings + +// Reserved (no_event_indicated) 0x00 +#define HID_KEYBOARD_ERROR_ROLLOVER 0x01 +#define HID_KEYBOARD_POST_FAIL 0x02 +#define HID_KEYBOARD_ERROR_UNDEFINED 0x03 +#define HID_KEYBOARD_A_AND_A 0x04 +#define HID_KEYBOARD_B_AND_B 0x05 +#define HID_KEYBOARD_C_AND_C 0x06 +#define HID_KEYBOARD_D_AND_D 0x07 +#define HID_KEYBOARD_E_AND_E 0x08 +#define HID_KEYBOARD_F_AND_F 0x09 +#define HID_KEYBOARD_G_AND_G 0x0A +#define HID_KEYBOARD_H_AND_H 0x0B +#define HID_KEYBOARD_I_AND_I 0x0C +#define HID_KEYBOARD_J_AND_J 0x0D +#define HID_KEYBOARD_K_AND_K 0x0E +#define HID_KEYBOARD_L_AND_L 0x0F +#define HID_KEYBOARD_M_AND_M 0x10 +#define HID_KEYBOARD_N_AND_N 0x11 +#define HID_KEYBOARD_O_AND_O 0x12 +#define HID_KEYBOARD_P_AND_P 0x13 +#define HID_KEYBOARD_Q_AND_Q 0x14 +#define HID_KEYBOARD_R_AND_R 0x15 +#define HID_KEYBOARD_S_AND_S 0x16 +#define HID_KEYBOARD_T_AND_T 0x17 +#define HID_KEYBOARD_U_AND_U 0x18 +#define HID_KEYBOARD_V_AND_V 0x19 +#define HID_KEYBOARD_W_AND_W 0x1A +#define HID_KEYBOARD_X_AND_X 0x1B +#define HID_KEYBOARD_Y_AND_Y 0x1C +#define HID_KEYBOARD_Z_AND_Z 0x1D +#define HID_KEYBOARD_1_AND_EXCLAMATION_POINT 0x1E +#define HID_KEYBOARD_2_AND_AT 0x1F +#define HID_KEYBOARD_3_AND_POUND 0x20 +#define HID_KEYBOARD_4_AND_DOLLAR 0x21 +#define HID_KEYBOARD_5_AND_PERCENT 0x22 +#define HID_KEYBOARD_6_AND_CARAT 0x23 +#define HID_KEYBOARD_7_AND_AMPERSAND 0x24 +#define HID_KEYBOARD_8_AND_ASTERISK 0x25 +#define HID_KEYBOARD_9_AND_LEFT_PAREN 0x26 +#define HID_KEYBOARD_0_AND_RIGHT_PAREN 0x27 +#define HID_KEYBOARD_ENTER 0x28 // (MARKED AS ENTER_SLASH_RETURN) +#define HID_KEYBOARD_ESCAPE 0x29 +#define HID_KEYBOARD_DELETE 0x2A // (BACKSPACE) +#define HID_KEYBOARD_TAB 0x2B +#define HID_KEYBOARD_SPACEBAR 0x2C +#define HID_KEYBOARD_MINUS_AND_UNDERSCORE 0x2D // (UNDERSCORE) +#define HID_KEYBOARD_EQUALS_AND_PLUS 0x2E +#define HID_KEYBOARD_LEFT_BRACKET_AND_LEFT_CURLY_BRACE 0x2F +#define HID_KEYBOARD_RIGHT_BRACKET_AND_RIGHT_CURLY_BRACE 0x30 +#define HID_KEYBOARD_BACKSLASH_AND_PIPE 0x31 +#define HID_KEYBOARD_NON_US_POUND_AND_TILDE 0x32 +#define HID_KEYBOARD_SEMICOLON_AND_COLON 0x33 +#define HID_KEYBOARD_QUOTE_AND_DOUBLEQUOTE 0x34 +#define HID_KEYBOARD_GRAVE_ACCENT_AND_TILDE 0x35 +#define HID_KEYBOARD_COMMA_AND_LESS_THAN 0x36 +#define HID_KEYBOARD_PERIOD_AND_GREATER_THAN 0x37 +#define HID_KEYBOARD_SLASH_AND_QUESTION_MARK 0x38 +#define HID_KEYBOARD_CAPS_LOCK 0x39 +#define HID_KEYBOARD_F1 0x3A +#define HID_KEYBOARD_F2 0x3B +#define HID_KEYBOARD_F3 0x3C +#define HID_KEYBOARD_F4 0x3D +#define HID_KEYBOARD_F5 0x3E +#define HID_KEYBOARD_F6 0x3F +#define HID_KEYBOARD_F7 0x40 +#define HID_KEYBOARD_F8 0x41 +#define HID_KEYBOARD_F9 0x42 +#define HID_KEYBOARD_F10 0x43 +#define HID_KEYBOARD_F11 0x44 +#define HID_KEYBOARD_F12 0x45 +#define HID_KEYBOARD_PRINTSCREEN 0x46 +#define HID_KEYBOARD_SCROLL_LOCK 0x47 +#define HID_KEYBOARD_PAUSE 0x48 +#define HID_KEYBOARD_INSERT 0x49 +#define HID_KEYBOARD_HOME 0x4A +#define HID_KEYBOARD_PAGE_UP 0x4B +#define HID_KEYBOARD_DELETE_FORWARD 0x4C +#define HID_KEYBOARD_END 0x4D +#define HID_KEYBOARD_PAGE_DOWN 0x4E +#define HID_KEYBOARD_RIGHTARROW 0x4F +#define HID_KEYBOARD_LEFTARROW 0x50 +#define HID_KEYBOARD_DOWNARROW 0x51 +#define HID_KEYBOARD_UPARROW 0x52 +#define HID_KEYPAD_NUM_LOCK_AND_CLEAR 0x53 +#define HID_KEYPAD_DIVIDE 0x54 +#define HID_KEYPAD_MULTIPLY 0x55 +#define HID_KEYPAD_SUBTRACT 0x56 +#define HID_KEYPAD_ADD 0x57 +#define HID_KEYPAD_ENTER 0x58 +#define HID_KEYPAD_1_AND_END 0x59 +#define HID_KEYPAD_2_AND_DOWN_ARROW 0x5A +#define HID_KEYPAD_3_AND_PAGE_DOWN 0x5B +#define HID_KEYPAD_4_AND_LEFT_ARROW 0x5C +#define HID_KEYPAD_5 0x5D +#define HID_KEYPAD_6_AND_RIGHT_ARROW 0x5E +#define HID_KEYPAD_7_AND_HOME 0x5F +#define HID_KEYPAD_8_AND_UP_ARROW 0x60 +#define HID_KEYPAD_9_AND_PAGE_UP 0x61 +#define HID_KEYPAD_0_AND_INSERT 0x62 +#define HID_KEYPAD_PERIOD_AND_DELETE 0x63 +#define HID_KEYBOARD_NON_US_BACKSLASH_AND_PIPE 0x64 +#define HID_KEYBOARD_APPLICATION 0x65 +#define HID_KEYBOARD_POWER 0x66 +#define HID_KEYPAD_EQUALS 0x67 +#define HID_KEYBOARD_F13 0x68 +#define HID_KEYBOARD_F14 0x69 +#define HID_KEYBOARD_F15 0x6A +#define HID_KEYBOARD_F16 0x6B +#define HID_KEYBOARD_F17 0x6C +#define HID_KEYBOARD_F18 0x6D +#define HID_KEYBOARD_F19 0x6E +#define HID_KEYBOARD_F20 0x6F +#define HID_KEYBOARD_F21 0x70 +#define HID_KEYBOARD_F22 0x71 +#define HID_KEYBOARD_F23 0x72 +#define HID_KEYBOARD_F24 0x73 +#define HID_KEYBOARD_EXECUTE 0x74 +#define HID_KEYBOARD_HELP 0x75 +#define HID_KEYBOARD_MENU 0x76 +#define HID_KEYBOARD_SELECT 0x77 +#define HID_KEYBOARD_STOP 0x78 +#define HID_KEYBOARD_AGAIN 0x79 +#define HID_KEYBOARD_UNDO 0x7A +#define HID_KEYBOARD_CUT 0x7B +#define HID_KEYBOARD_COPY 0x7C +#define HID_KEYBOARD_PASTE 0x7D +#define HID_KEYBOARD_FIND 0x7E +#define HID_KEYBOARD_MUTE 0x7F +#define HID_KEYBOARD_VOLUME_UP 0x80 +#define HID_KEYBOARD_VOLUME_DOWN 0x81 +#define HID_KEYBOARD_LOCKING_CAPS_LOCK 0x82 +#define HID_KEYBOARD_LOCKING_NUM_LOCK 0x83 +#define HID_KEYBOARD_LOCKING_SCROLL_LOCK 0x84 +#define HID_KEYPAD_COMMA 0x85 +#define HID_KEYPAD_EQUAL_SIGN 0x86 +#define HID_KEYBOARD_INTERNATIONAL1 0x87 +#define HID_KEYBOARD_INTERNATIONAL2 0x88 +#define HID_KEYBOARD_INTERNATIONAL3 0x89 +#define HID_KEYBOARD_INTERNATIONAL4 0x8A +#define HID_KEYBOARD_INTERNATIONAL5 0x8B +#define HID_KEYBOARD_INTERNATIONAL6 0x8C +#define HID_KEYBOARD_INTERNATIONAL7 0x8D +#define HID_KEYBOARD_INTERNATIONAL8 0x8E +#define HID_KEYBOARD_INTERNATIONAL9 0x8F +#define HID_KEYBOARD_LANG1 0x90 +#define HID_KEYBOARD_LANG2 0x91 +#define HID_KEYBOARD_LANG3 0x92 +#define HID_KEYBOARD_LANG4 0x93 +#define HID_KEYBOARD_LANG5 0x94 +#define HID_KEYBOARD_LANG6 0x95 +#define HID_KEYBOARD_LANG7 0x96 +#define HID_KEYBOARD_LANG8 0x97 +#define HID_KEYBOARD_LANG9 0x98 +#define HID_KEYBOARD_ALTERNATE_ERASE 0x99 +#define HID_KEYBOARD_SYSREQ_SLASH_ATTENTION 0x9A +#define HID_KEYBOARD_CANCEL 0x9B +#define HID_KEYBOARD_CLEAR 0x9C +#define HID_KEYBOARD_PRIOR 0x9D +#define HID_KEYBOARD_RETURN 0x9E +#define HID_KEYBOARD_SEPARATOR 0x9F +#define HID_KEYBOARD_OUT 0xA0 +#define HID_KEYBOARD_OPER 0xA1 +#define HID_KEYBOARD_CLEAR_SLASH_AGAIN 0xA2 +#define HID_KEYBOARD_CRSEL_SLASH_PROPS 0xA3 +#define HID_KEYBOARD_EXSEL 0xA4 +// Reserved 0xA5-AF +#define HID_KEYPAD_00 0xB0 +#define HID_KEYPAD_000 0xB1 +#define HID_THOUSANDS_SEPARATOR 0xB2 +#define HID_DECIMAL_SEPARATOR 0xB3 +#define HID_CURRENCY_UNIT 0xB4 +#define HID_CURRENCY_SUBUNIT 0xB5 +#define HID_KEYPAD_LEFT_PAREN 0xB6 +#define HID_KEYPAD_RIGHT_PAREN 0xB7 +#define HID_KEYPAD_LEFT_CURLY_BRACE 0xB8 +#define HID_KEYPAD_RIGHT_CURLY_BRACE 0xB9 +#define HID_KEYPAD_TAB 0xBA +#define HID_KEYPAD_BACKSPACE 0xBB +#define HID_KEYPAD_A 0xBC +#define HID_KEYPAD_B 0xBD +#define HID_KEYPAD_C 0xBE +#define HID_KEYPAD_D 0xBF +#define HID_KEYPAD_E 0xC0 +#define HID_KEYPAD_F 0xC1 +#define HID_KEYPAD_XOR 0xC2 +#define HID_KEYPAD_CARAT 0xC3 +#define HID_KEYPAD_PERCENT 0xC4 +#define HID_KEYPAD_LESS_THAN 0xC5 +#define HID_KEYPAD_GREATER_THAN 0xC6 +#define HID_KEYPAD_AMPERSAND 0xC7 +#define HID_KEYPAD_DOUBLEAMPERSAND 0xC8 +#define HID_KEYPAD_PIPE 0xC9 +#define HID_KEYPAD_DOUBLEPIPE 0xCA +#define HID_KEYPAD_COLON 0xCB +#define HID_KEYPAD_POUND_SIGN 0xCC +#define HID_KEYPAD_SPACE 0xCD +#define HID_KEYPAD_AT_SIGN 0xCE +#define HID_KEYPAD_EXCLAMATION_POINT 0xCF +#define HID_KEYPAD_MEMORY_STORE 0xD0 +#define HID_KEYPAD_MEMORY_RECALL 0xD1 +#define HID_KEYPAD_MEMORY_CLEAR 0xD2 +#define HID_KEYPAD_MEMORY_ADD 0xD3 +#define HID_KEYPAD_MEMORY_SUBTRACT 0xD4 +#define HID_KEYPAD_MEMORY_MULTIPLY 0xD5 +#define HID_KEYPAD_MEMORY_DIVIDE 0xD6 +#define HID_KEYPAD_PLUS_SLASH_MINUS 0xD7 +#define HID_KEYPAD_CLEAR 0xD8 +#define HID_KEYPAD_CLEAR_ENTRY 0xD9 +#define HID_KEYPAD_BINARY 0xDA +#define HID_KEYPAD_OCTAL 0xDB +#define HID_KEYPAD_DECIMAL 0xDC +#define HID_KEYPAD_HEXADECIMAL 0xDD + +// 0xDE-0xDF - RESERVED +#define HID_KEYBOARD_LEFT_CONTROL 0xE0 +#define HID_KEYBOARD_LEFT_SHIFT 0xE1 +#define HID_KEYBOARD_LEFT_ALT 0xE2 +#define HID_KEYBOARD_LEFT_GUI 0xE3 +#define HID_KEYBOARD_RIGHT_CONTROL 0xE4 +#define HID_KEYBOARD_RIGHT_SHIFT 0xE5 +#define HID_KEYBOARD_RIGHT_ALT 0xE6 +#define HID_KEYBOARD_RIGHT_GUI 0xE7 + + +// Consumer_Page_(0x0C) 0x15 +#define HID_CONSUMER_NUMERIC_KEY_PAD 0x02 // HID type NARY +#define HID_CONSUMER_PROGRAMMABLE_BUTTONS 0x03 // HID type NARY +#define HID_CONSUMER_MICROPHONE_CA 0x04 +#define HID_CONSUMER_HEADPHONE_CA 0x05 +#define HID_CONSUMER_GRAPHIC_EQUALIZER_CA 0x06 +// Reserved 0x07-1F +#define HID_CONSUMER_PLUS_10 0x20 // HID type OSC +#define HID_CONSUMER_PLUS_100 0x21 // HID type OSC +#define HID_CONSUMER_AM_SLASH_PM 0x22 // HID type OSC +// Reserved 0x23-3F +#define HID_CONSUMER_POWER 0x30 // HID type OOC +#define HID_CONSUMER_RESET 0x31 // HID type OSC +#define HID_CONSUMER_SLEEP 0x32 // HID type OSC +#define HID_CONSUMER_SLEEP_AFTER 0x33 // HID type OSC +#define HID_CONSUMER_SLEEP_MODE 0x34 // HID type RTC +#define HID_CONSUMER_ILLUMINATION 0x35 // HID type OOC +#define HID_CONSUMER_FUNCTION_BUTTONS 0x36 // HID type NARY +// Reserved 0x37-3F +#define HID_CONSUMER_MENU 0x40 // HID type OOC +#define HID_CONSUMER_MENU_PICK 0x41 // HID type OSC +#define HID_CONSUMER_MENU_UP 0x42 // HID type OSC +#define HID_CONSUMER_MENU_DOWN 0x43 // HID type OSC +#define HID_CONSUMER_MENU_LEFT 0x44 // HID type OSC +#define HID_CONSUMER_MENU_RIGHT 0x45 // HID type OSC +#define HID_CONSUMER_MENU_ESCAPE 0x46 // HID type OSC +#define HID_CONSUMER_MENU_VALUE_INCREASE 0x47 // HID type OSC +#define HID_CONSUMER_MENU_VALUE_DECREASE 0x48 // HID type OSC +// Reserved 0x49-5F +#define HID_CONSUMER_DATA_ON_SCREEN 0x60 // HID type OOC +#define HID_CONSUMER_CLOSED_CAPTION 0x61 // HID type OOC +#define HID_CONSUMER_CLOSED_CAPTION_SELECT 0x62 // HID type OSC +#define HID_CONSUMER_VCR_SLASH_TV 0x63 // HID type OOC +#define HID_CONSUMER_BROADCAST_MODE 0x64 // HID type OSC +#define HID_CONSUMER_SNAPSHOT 0x65 // HID type OSC +#define HID_CONSUMER_STILL 0x66 // HID type OSC +// Reserved 0x67-7F +#define HID_CONSUMER_SELECTION 0x80 // HID type NARY +#define HID_CONSUMER_ASSIGN_SELECTION 0x81 // HID type OSC +#define HID_CONSUMER_MODE_STEP 0x82 // HID type OSC +#define HID_CONSUMER_RECALL_LAST 0x83 // HID type OSC +#define HID_CONSUMER_ENTER_CHANNEL 0x84 // HID type OSC +#define HID_CONSUMER_ORDER_MOVIE 0x85 // HID type OSC +#define HID_CONSUMER_CHANNEL 0x86 // HID type LC +#define HID_CONSUMER_MEDIA_SELECTION 0x87 // HID type NARY +#define HID_CONSUMER_MEDIA_SELECT_COMPUTER 0x88 // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_TV 0x89 // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_WWW 0x8A // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_DVD 0x8B // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_TELEPHONE 0x8C // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_PROGRAM_GUIDE 0x8D // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_VIDEO_PHONE 0x8E // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_GAMES 0x8F // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_MESSAGES 0x90 // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_CD 0x91 // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_VCR 0x92 // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_TUNER 0x93 // HID type SEL +#define HID_CONSUMER_QUIT 0x94 // HID type OSC +#define HID_CONSUMER_HELP 0x95 // HID type OOC +#define HID_CONSUMER_MEDIA_SELECT_TAPE 0x96 // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_CABLE 0x97 // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_SATELLITE 0x98 // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_SECURITY 0x99 // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_HOME 0x9A // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_CALL 0x9B // HID type SEL +#define HID_CONSUMER_CHANNEL_INCREMENT 0x9C // HID type OSC +#define HID_CONSUMER_CHANNEL_DECREMENT 0x9D // HID type OSC +#define HID_CONSUMER_MEDIA_SELECT_SAP 0x9E // HID type SEL +// Reserved 0x9F +#define HID_CONSUMER_VCR_PLUS 0xA0 // HID type OSC +#define HID_CONSUMER_ONCE 0xA1 // HID type OSC +#define HID_CONSUMER_DAILY 0xA2 // HID type OSC +#define HID_CONSUMER_WEEKLY 0xA3 // HID type OSC +#define HID_CONSUMER_MONTHLY 0xA4 // HID type OSC +// Reserved 0xA5-AF +#define HID_CONSUMER_PLAY 0xB0 // HID type OOC +#define HID_CONSUMER_PAUSE 0xB1 // HID type OOC +#define HID_CONSUMER_RECORD 0xB2 // HID type OOC +#define HID_CONSUMER_FAST_FORWARD 0xB3 // HID type OOC +#define HID_CONSUMER_REWIND 0xB4 // HID type OOC +#define HID_CONSUMER_SCAN_NEXT_TRACK 0xB5 // HID type OSC +#define HID_CONSUMER_SCAN_PREVIOUS_TRACK 0xB6 // HID type OSC +#define HID_CONSUMER_STOP 0xB7 // HID type OSC +#define HID_CONSUMER_EJECT 0xB8 // HID type OSC +#define HID_CONSUMER_RANDOM_PLAY 0xB9 // HID type OOC +#define HID_CONSUMER_SELECT_DISC 0xBA // HID type NARY +#define HID_CONSUMER_ENTER_DISC_MC 0xBB +#define HID_CONSUMER_REPEAT 0xBC // HID type OSC +#define HID_CONSUMER_TRACKING 0xBD // HID type LC +#define HID_CONSUMER_TRACK_NORMAL 0xBE // HID type OSC +#define HID_CONSUMER_SLOW_TRACKING 0xBF // HID type LC +#define HID_CONSUMER_FRAME_FORWARD 0xC0 // HID type RTC +#define HID_CONSUMER_FRAME_BACK 0xC1 // HID type RTC +#define HID_CONSUMER_MARK 0xC2 // HID type OSC +#define HID_CONSUMER_CLEAR_MARK 0xC3 // HID type OSC +#define HID_CONSUMER_REPEAT_FROM_MARK 0xC4 // HID type OOC +#define HID_CONSUMER_RETURN_TO_MARK 0xC5 // HID type OSC +#define HID_CONSUMER_SEARCH_MARK_FORWARD 0xC6 // HID type OSC +#define HID_CONSUMER_SEARCH_MARK_BACKWARDS 0xC7 // HID type OSC +#define HID_CONSUMER_COUNTER_RESET 0xC8 // HID type OSC +#define HID_CONSUMER_SHOW_COUNTER 0xC9 // HID type OSC +#define HID_CONSUMER_TRACKING_INCREMENT 0xCA // HID type RTC +#define HID_CONSUMER_TRACKING_DECREMENT 0xCB // HID type RTC +#define HID_CONSUMER_STOP_SLASH_EJECT 0xCC // HID type OSC +#define HID_CONSUMER_PLAY_SLASH_PAUSE 0xCD // HID type OSC +#define HID_CONSUMER_PLAY_SLASH_SKIP 0xCE // HID type OSC +// Reserved 0xCF-DF +#define HID_CONSUMER_VOLUME 0xE0 // HID type LC +#define HID_CONSUMER_BALANCE 0xE1 // HID type LC +#define HID_CONSUMER_MUTE 0xE2 // HID type OOC +#define HID_CONSUMER_BASS 0xE3 // HID type LC +#define HID_CONSUMER_TREBLE 0xE4 // HID type LC +#define HID_CONSUMER_BASS_BOOST 0xE5 // HID type OOC +#define HID_CONSUMER_SURROUND_MODE 0xE6 // HID type OSC +#define HID_CONSUMER_LOUDNESS 0xE7 // HID type OOC +#define HID_CONSUMER_MPX 0xE8 // HID type OOC +#define HID_CONSUMER_VOLUME_INCREMENT 0xE9 // HID type RTC +#define HID_CONSUMER_VOLUME_DECREMENT 0xEA // HID type RTC +// Reserved 0xEB-EF +#define HID_CONSUMER_SPEED_SELECT 0xF0 // HID type OSC +#define HID_CONSUMER_PLAYBACK_SPEED 0xF1 // HID type NARY +#define HID_CONSUMER_STANDARD_PLAY 0xF2 // HID type SEL +#define HID_CONSUMER_LONG_PLAY 0xF3 // HID type SEL +#define HID_CONSUMER_EXTENDED_PLAY 0xF4 // HID type SEL +#define HID_CONSUMER_SLOW 0xF5 // HID type OSC +// Reserved 0xF6-FF +#define HID_CONSUMER_FAN_ENABLE 0x100 // HID type OOC +#define HID_CONSUMER_FAN_SPEED 0x101 // HID type LC +#define HID_CONSUMER_LIGHT_ENABLE 0x102 // HID type OOC +#define HID_CONSUMER_LIGHT_ILLUMINATION_LEVEL 0x103 // HID type LC +#define HID_CONSUMER_CLIMATE_CONTROL_ENABLE 0x104 // HID type OOC +#define HID_CONSUMER_ROOM_TEMPERATURE 0x105 // HID type LC +#define HID_CONSUMER_SECURITY_ENABLE 0x106 // HID type OOC +#define HID_CONSUMER_FIRE_ALARM 0x107 // HID type OSC +#define HID_CONSUMER_POLICE_ALARM 0x108 // HID type OSC +#define HID_CONSUMER_PROXIMITY 0x109 // HID type LC +#define HID_CONSUMER_MOTION 0x10A // HID type OSC +#define HID_CONSUMER_DURESS_ALARM 0x10B // HID type OSC +#define HID_CONSUMER_HOLDUP_ALARM 0x10C // HID type OSC +#define HID_CONSUMER_MEDICAL_ALARM 0x10D // HID type OSC +// Reserved 0x10E-14F +#define HID_CONSUMER_BALANCE_RIGHT 0x150 // HID type RTC +#define HID_CONSUMER_BALANCE_LEFT 0x151 // HID type RTC +#define HID_CONSUMER_BASS_INCREMENT 0x152 // HID type RTC +#define HID_CONSUMER_BASS_DECREMENT 0x153 // HID type RTC +#define HID_CONSUMER_TREBLE_INCREMENT 0x154 // HID type RTC +#define HID_CONSUMER_TREBLE_DECREMENT 0x155 // HID type RTC +// Reserved 0x156-15F +#define HID_CONSUMER_SPEAKER_SYSTEM 0x160 // HID type CL +#define HID_CONSUMER_CHANNEL_LEFT 0x161 // HID type CL +#define HID_CONSUMER_CHANNEL_RIGHT 0x162 // HID type CL +#define HID_CONSUMER_CHANNEL_CENTER 0x163 // HID type CL +#define HID_CONSUMER_CHANNEL_FRONT 0x164 // HID type CL +#define HID_CONSUMER_CHANNEL_CENTER_FRONT 0x165 // HID type CL +#define HID_CONSUMER_CHANNEL_SIDE 0x166 // HID type CL +#define HID_CONSUMER_CHANNEL_SURROUND 0x167 // HID type CL +#define HID_CONSUMER_CHANNEL_LOW_FREQUENCY_ENHANCEMENT 0x168 // HID type CL +#define HID_CONSUMER_CHANNEL_TOP 0x169 // HID type CL +#define HID_CONSUMER_CHANNEL_UNKNOWN 0x16A // HID type CL +// Reserved 0x16B-16F +#define HID_CONSUMER_SUB_CHANNEL 0x170 // HID type LC +#define HID_CONSUMER_SUB_CHANNEL_INCREMENT 0x171 // HID type OSC +#define HID_CONSUMER_SUB_CHANNEL_DECREMENT 0x172 // HID type OSC +#define HID_CONSUMER_ALTERNATE_AUDIO_INCREMENT 0x173 // HID type OSC +#define HID_CONSUMER_ALTERNATE_AUDIO_DECREMENT 0x174 // HID type OSC +// Reserved 0x175-17F +#define HID_CONSUMER_APPLICATION_LAUNCH_BUTTONS 0x180 // HID type NARY +#define HID_CONSUMER_AL_LAUNCH_BUTTON_CONFIGURATION_TOOL 0x181 // HID type SEL +#define HID_CONSUMER_AL_PROGRAMMABLE_BUTTON_CONFIGURATION 0x182 // HID type SEL +#define HID_CONSUMER_AL_CONSUMER_CONTROL_CONFIGURATION 0x183 // HID type SEL +#define HID_CONSUMER_AL_WORD_PROCESSOR 0x184 // HID type SEL +#define HID_CONSUMER_AL_TEXT_EDITOR 0x185 // HID type SEL +#define HID_CONSUMER_AL_SPREADSHEET 0x186 // HID type SEL +#define HID_CONSUMER_AL_GRAPHICS_EDITOR 0x187 // HID type SEL +#define HID_CONSUMER_AL_PRESENTATION_APP 0x188 // HID type SEL +#define HID_CONSUMER_AL_DATABASE_APP 0x189 // HID type SEL +#define HID_CONSUMER_AL_EMAIL_READER 0x18A // HID type SEL +#define HID_CONSUMER_AL_NEWSREADER 0x18B // HID type SEL +#define HID_CONSUMER_AL_VOICEMAIL 0x18C // HID type SEL +#define HID_CONSUMER_AL_CONTACTS_SLASH_ADDRESS_BOOK 0x18D // HID type SEL +#define HID_CONSUMER_AL_CALENDAR_SLASH_SCHEDULE 0x18E // HID type SEL +#define HID_CONSUMER_AL_TASK_SLASH_PROJECT_MANAGER 0x18F // HID type SEL +#define HID_CONSUMER_AL_LOG_SLASH_JOURNAL_SLASH_TIMECARD 0x190 // HID type SEL +#define HID_CONSUMER_AL_CHECKBOOK_SLASH_FINANCE 0x191 // HID type SEL +#define HID_CONSUMER_AL_CALCULATOR 0x192 // HID type SEL +#define HID_CONSUMER_AL_A_SLASH_V_CAPTURE_SLASH_PLAYBACK 0x193 // HID type SEL +#define HID_CONSUMER_AL_LOCAL_MACHINE_BROWSER 0x194 // HID type SEL +#define HID_CONSUMER_AL_LAN_SLASH_WAN_BROWSER 0x195 // HID type SEL +#define HID_CONSUMER_AL_INTERNET_BROWSER 0x196 // HID type SEL +#define HID_CONSUMER_AL_REMOTE_NETWORKING_SLASH_ISP_CONNECT 0x197 // HID type SEL +#define HID_CONSUMER_AL_NETWORK_CONFERENCE 0x198 // HID type SEL +#define HID_CONSUMER_AL_NETWORK_CHAT 0x199 // HID type SEL +#define HID_CONSUMER_AL_TELEPHONY_SLASH_DIALER 0x19A // HID type SEL +#define HID_CONSUMER_AL_LOGON 0x19B // HID type SEL +#define HID_CONSUMER_AL_LOGOFF 0x19C // HID type SEL +#define HID_CONSUMER_AL_LOGON_SLASH_LOGOFF 0x19D // HID type SEL +#define HID_CONSUMER_AL_TERMINAL_LOCK_SLASH_SCREENSAVER 0x19E // HID type SEL +#define HID_CONSUMER_AL_CONTROL_PANEL 0x19F // HID type SEL +#define HID_CONSUMER_AL_COMMAND_LINE_PROCESSOR_SLASH_RUN 0x1A0 // HID type SEL +#define HID_CONSUMER_AL_PROCESS_SLASH_TASK_MANAGER 0x1A1 // HID type SEL +#define HID_CONSUMER_AL_SELECT_TASK_SLASH_APPLICATION 0x1A2 // HID type SEL +#define HID_CONSUMER_AL_NEXT_TASK_SLASH_APPLICATION 0x1A3 // HID type SEL +#define HID_CONSUMER_AL_PREVIOUS_TASK_SLASH_APPLICATION 0x1A4 // HID type SEL +#define HID_CONSUMER_AL_PREEMPTIVE_HALT_TASK_SLASH_APPLICATION 0x1A5 // HID type SEL +#define HID_CONSUMER_AL_INTEGRATED_HELP_CENTER 0x1A6 // HID type SEL +#define HID_CONSUMER_AL_DOCUMENTS 0x1A7 // HID type SEL +#define HID_CONSUMER_AL_THESAURUS 0x1A8 // HID type SEL +#define HID_CONSUMER_AL_DICTIONARY 0x1A9 // HID type SEL +#define HID_CONSUMER_AL_DESKTOP 0x1AA // HID type SEL +#define HID_CONSUMER_AL_SPELL_CHECK 0x1AB // HID type SEL +#define HID_CONSUMER_AL_GRAMMAR_CHECK 0x1AC // HID type SEL +#define HID_CONSUMER_AL_WIRELESS_STATUS 0x1AD // HID type SEL +#define HID_CONSUMER_AL_KEYBOARD_LAYOUT 0x1AE // HID type SEL +#define HID_CONSUMER_AL_VIRUS_PROTECTION 0x1AF // HID type SEL +#define HID_CONSUMER_AL_ENCRYPTION 0x1B0 // HID type SEL +#define HID_CONSUMER_AL_SCREEN_SAVER 0x1B1 // HID type SEL +#define HID_CONSUMER_AL_ALARMS 0x1B2 // HID type SEL +#define HID_CONSUMER_AL_CLOCK 0x1B3 // HID type SEL +#define HID_CONSUMER_AL_FILE_BROWSER 0x1B4 // HID type SEL +#define HID_CONSUMER_AL_POWER_STATUS 0x1B5 // HID type SEL +#define HID_CONSUMER_AL_IMAGE_BROWSER 0x1B6 // HID type SEL +#define HID_CONSUMER_AL_AUDIO_BROWSER 0x1B7 // HID type SEL +#define HID_CONSUMER_AL_MOVIE_BROWSER 0x1B8 // HID type SEL +#define HID_CONSUMER_AL_DIGITAL_RIGHTS_MANAGER 0x1B9 // HID type SEL +#define HID_CONSUMER_AL_DIGITAL_WALLET 0x1BA // HID type SEL +// _Reserved 0x1BB +#define HID_CONSUMER_AL_INSTANT_MESSAGING 0x1BC // HID type SEL +#define HID_CONSUMER_AL_OEM_FEATURES_SLASH__TIPS_SLASH_TUTORIAL_BROWSER 0x1BD // HID type SEL +#define HID_CONSUMER_AL_OEM_HELP 0x1BE // HID type SEL +#define HID_CONSUMER_AL_ONLINE_COMMUNITY 0x1BF // HID type SEL +#define HID_CONSUMER_AL_ENTERTAINMENT_CONTENT_BROWSER 0x1C0 // HID type SEL +#define HID_CONSUMER_AL_ONLINE_SHOPPING_BROWSER 0x1C1 // HID type SEL +#define HID_CONSUMER_AL_SMARTCARD_INFORMATION_SLASH_HELP 0x1C2 // HID type SEL +#define HID_CONSUMER_AL_MARKET_MONITOR_SLASH_FINANCE_BROWSER 0x1C3 // HID type SEL +#define HID_CONSUMER_AL_CUSTOMIZED_CORPORATE_NEWS_BROWSER 0x1C4 // HID type SEL +#define HID_CONSUMER_AL_ONLINE_ACTIVITY_BROWSER 0x1C5 // HID type SEL +#define HID_CONSUMER_AL_RESEARCH_SLASH_SEARCH_BROWSER 0x1C6 // HID type SEL +#define HID_CONSUMER_AL_AUDIO_PLAYER 0x1C7 // HID type SEL +// Reserved 0x1C8-1FF +#define HID_CONSUMER_GENERIC_GUI_APPLICATION_CONTROLS 0x200 // HID type NARY +#define HID_CONSUMER_AC_NEW 0x201 // HID type SEL +#define HID_CONSUMER_AC_OPEN 0x202 // HID type SEL +#define HID_CONSUMER_AC_CLOSE 0x203 // HID type SEL +#define HID_CONSUMER_AC_EXIT 0x204 // HID type SEL +#define HID_CONSUMER_AC_MAXIMIZE 0x205 // HID type SEL +#define HID_CONSUMER_AC_MINIMIZE 0x206 // HID type SEL +#define HID_CONSUMER_AC_SAVE 0x207 // HID type SEL +#define HID_CONSUMER_AC_PRINT 0x208 // HID type SEL +#define HID_CONSUMER_AC_PROPERTIES 0x209 // HID type SEL +#define HID_CONSUMER_AC_UNDO 0x21A // HID type SEL +#define HID_CONSUMER_AC_COPY 0x21B // HID type SEL +#define HID_CONSUMER_AC_CUT 0x21C // HID type SEL +#define HID_CONSUMER_AC_PASTE 0x21D // HID type SEL +#define HID_CONSUMER_AC_SELECT_ALL 0x21E // HID type SEL +#define HID_CONSUMER_AC_FIND 0x21F // HID type SEL +#define HID_CONSUMER_AC_FIND_AND_REPLACE 0x220 // HID type SEL +#define HID_CONSUMER_AC_SEARCH 0x221 // HID type SEL +#define HID_CONSUMER_AC_GO_TO 0x222 // HID type SEL +#define HID_CONSUMER_AC_HOME 0x223 // HID type SEL +#define HID_CONSUMER_AC_BACK 0x224 // HID type SEL +#define HID_CONSUMER_AC_FORWARD 0x225 // HID type SEL +#define HID_CONSUMER_AC_STOP 0x226 // HID type SEL +#define HID_CONSUMER_AC_REFRESH 0x227 // HID type SEL +#define HID_CONSUMER_AC_PREVIOUS_LINK 0x228 // HID type SEL +#define HID_CONSUMER_AC_NEXT_LINK 0x229 // HID type SEL +#define HID_CONSUMER_AC_BOOKMARKS 0x22A // HID type SEL +#define HID_CONSUMER_AC_HISTORY 0x22B // HID type SEL +#define HID_CONSUMER_AC_SUBSCRIPTIONS 0x22C // HID type SEL +#define HID_CONSUMER_AC_ZOOM_IN 0x22D // HID type SEL +#define HID_CONSUMER_AC_ZOOM_OUT 0x22E // HID type SEL +#define HID_CONSUMER_AC_ZOOM 0x22F // HID type LC +#define HID_CONSUMER_AC_FULL_SCREEN_VIEW 0x230 // HID type SEL +#define HID_CONSUMER_AC_NORMAL_VIEW 0x231 // HID type SEL +#define HID_CONSUMER_AC_VIEW_TOGGLE 0x232 // HID type SEL +#define HID_CONSUMER_AC_SCROLL_UP 0x233 // HID type SEL +#define HID_CONSUMER_AC_SCROLL_DOWN 0x234 // HID type SEL +#define HID_CONSUMER_AC_SCROLL 0x235 // HID type LC +#define HID_CONSUMER_AC_PAN_LEFT 0x236 // HID type SEL +#define HID_CONSUMER_AC_PAN_RIGHT 0x237 // HID type SEL +#define HID_CONSUMER_AC_PAN 0x238 // HID type LC +#define HID_CONSUMER_AC_NEW_WINDOW 0x239 // HID type SEL +#define HID_CONSUMER_AC_TILE_HORIZONTALLY 0x23A // HID type SEL +#define HID_CONSUMER_AC_TILE_VERTICALLY 0x23B // HID type SEL +#define HID_CONSUMER_AC_FORMAT 0x23C // HID type SEL +#define HID_CONSUMER_AC_EDIT 0x23D // HID type SEL +#define HID_CONSUMER_AC_BOLD 0x23E // HID type SEL +#define HID_CONSUMER_AC_ITALICS 0x23F // HID type SEL +#define HID_CONSUMER_AC_UNDERLINE 0x240 // HID type SEL +#define HID_CONSUMER_AC_STRIKETHROUGH 0x241 // HID type SEL +#define HID_CONSUMER_AC_SUBSCRIPT 0x242 // HID type SEL +#define HID_CONSUMER_AC_SUPERSCRIPT 0x243 // HID type SEL +#define HID_CONSUMER_AC_ALL_CAPS 0x244 // HID type SEL +#define HID_CONSUMER_AC_ROTATE 0x245 // HID type SEL +#define HID_CONSUMER_AC_RESIZE 0x246 // HID type SEL +#define HID_CONSUMER_AC_FLIP_HORIZONTAL 0x247 // HID type SEL +#define HID_CONSUMER_AC_FLIP_VERTICAL 0x248 // HID type SEL +#define HID_CONSUMER_AC_MIRROR_HORIZONTAL 0x249 // HID type SEL +#define HID_CONSUMER_AC_MIRROR_VERTICAL 0x24A // HID type SEL +#define HID_CONSUMER_AC_FONT_SELECT 0x24B // HID type SEL +#define HID_CONSUMER_AC_FONT_COLOR 0x24C // HID type SEL +#define HID_CONSUMER_AC_FONT_SIZE 0x24D // HID type SEL +#define HID_CONSUMER_AC_JUSTIFY_LEFT 0x24E // HID type SEL +#define HID_CONSUMER_AC_JUSTIFY_CENTER_H 0x24F // HID type SEL +#define HID_CONSUMER_AC_JUSTIFY_RIGHT 0x250 // HID type SEL +#define HID_CONSUMER_AC_JUSTIFY_BLOCK_H 0x251 // HID type SEL +#define HID_CONSUMER_AC_JUSTIFY_TOP 0x252 // HID type SEL +#define HID_CONSUMER_AC_JUSTIFY_CENTER_V 0x253 // HID type SEL +#define HID_CONSUMER_AC_JUSTIFY_BOTTOM 0x254 // HID type SEL +#define HID_CONSUMER_AC_JUSTIFY_BLOCK_V 0x255 // HID type SEL +#define HID_CONSUMER_AC_INDENT_DECREASE 0x256 // HID type SEL +#define HID_CONSUMER_AC_INDENT_INCREASE 0x257 // HID type SEL +#define HID_CONSUMER_AC_NUMBERED_LIST 0x258 // HID type SEL +#define HID_CONSUMER_AC_RESTART_NUMBERING 0x259 // HID type SEL +#define HID_CONSUMER_AC_BULLETED_LIST 0x25A // HID type SEL +#define HID_CONSUMER_AC_PROMOTE 0x25B // HID type SEL +#define HID_CONSUMER_AC_DEMOTE 0x25C // HID type SEL +#define HID_CONSUMER_AC_YES 0x25D // HID type SEL +#define HID_CONSUMER_AC_NO 0x25E // HID type SEL +#define HID_CONSUMER_AC_CANCEL 0x25F // HID type SEL +#define HID_CONSUMER_AC_CATALOG 0x260 // HID type SEL +#define HID_CONSUMER_AC_BUY_SLASH_CHECKOUT 0x261 // HID type SEL +#define HID_CONSUMER_AC_ADD_TO_CART 0x262 // HID type SEL +#define HID_CONSUMER_AC_EXPAND 0x263 // HID type SEL +#define HID_CONSUMER_AC_EXPAND_ALL 0x264 // HID type SEL +#define HID_CONSUMER_AC_COLLAPSE 0x265 // HID type SEL +#define HID_CONSUMER_AC_COLLAPSE_ALL 0x266 // HID type SEL +#define HID_CONSUMER_AC_PRINT_PREVIEW 0x267 // HID type SEL +#define HID_CONSUMER_AC_PASTE_SPECIAL 0x268 // HID type SEL +#define HID_CONSUMER_AC_INSERT_MODE 0x269 // HID type SEL +#define HID_CONSUMER_AC_DELETE 0x26A // HID type SEL +#define HID_CONSUMER_AC_LOCK 0x26B // HID type SEL +#define HID_CONSUMER_AC_UNLOCK 0x26C // HID type SEL +#define HID_CONSUMER_AC_PROTECT 0x26D // HID type SEL +#define HID_CONSUMER_AC_UNPROTECT 0x26E // HID type SEL +#define HID_CONSUMER_AC_ATTACH_COMMENT 0x26F // HID type SEL +#define HID_CONSUMER_AC_DELETE_COMMENT 0x270 // HID type SEL +#define HID_CONSUMER_AC_VIEW_COMMENT 0x271 // HID type SEL +#define HID_CONSUMER_AC_SELECT_WORD 0x272 // HID type SEL +#define HID_CONSUMER_AC_SELECT_SENTENCE 0x273 // HID type SEL +#define HID_CONSUMER_AC_SELECT_PARAGRAPH 0x274 // HID type SEL +#define HID_CONSUMER_AC_SELECT_COLUMN 0x275 // HID type SEL +#define HID_CONSUMER_AC_SELECT_ROW 0x276 // HID type SEL +#define HID_CONSUMER_AC_SELECT_TABLE 0x277 // HID type SEL +#define HID_CONSUMER_AC_SELECT_OBJECT 0x278 // HID type SEL +#define HID_CONSUMER_AC_REDO_SLASH_REPEAT 0x279 // HID type SEL +#define HID_CONSUMER_AC_SORT 0x27A // HID type SEL +#define HID_CONSUMER_AC_SORT_ASCENDING 0x27B // HID type SEL +#define HID_CONSUMER_AC_SORT_DESCENDING 0x27C // HID type SEL +#define HID_CONSUMER_AC_FILTER 0x27D // HID type SEL +#define HID_CONSUMER_AC_SET_CLOCK 0x27E // HID type SEL +#define HID_CONSUMER_AC_VIEW_CLOCK 0x27F // HID type SEL +#define HID_CONSUMER_AC_SELECT_TIME_ZONE 0x280 // HID type SEL +#define HID_CONSUMER_AC_EDIT_TIME_ZONES 0x281 // HID type SEL +#define HID_CONSUMER_AC_SET_ALARM 0x282 // HID type SEL +#define HID_CONSUMER_AC_CLEAR_ALARM 0x283 // HID type SEL +#define HID_CONSUMER_AC_SNOOZE_ALARM 0x284 // HID type SEL +#define HID_CONSUMER_AC_RESET_ALARM 0x285 // HID type SEL +#define HID_CONSUMER_AC_SYNCHRONIZE 0x286 // HID type SEL +#define HID_CONSUMER_AC_SEND_SLASH_RECEIVE 0x287 // HID type SEL +#define HID_CONSUMER_AC_SEND_TO 0x288 // HID type SEL +#define HID_CONSUMER_AC_REPLY 0x289 // HID type SEL +#define HID_CONSUMER_AC_REPLY_ALL 0x28A // HID type SEL +#define HID_CONSUMER_AC_FORWARD_MSG 0x28B // HID type SEL +#define HID_CONSUMER_AC_SEND 0x28C // HID type SEL +#define HID_CONSUMER_AC_ATTACH_FILE 0x28D // HID type SEL +#define HID_CONSUMER_AC_UPLOAD 0x28E // HID type SEL +#define HID_CONSUMER_AC_DOWNLOAD_(SAVE_TARGET_AS) 0x28F // HID type SEL +#define HID_CONSUMER_AC_SET_BORDERS 0x290 // HID type SEL +#define HID_CONSUMER_AC_INSERT_ROW 0x291 // HID type SEL +#define HID_CONSUMER_AC_INSERT_COLUMN 0x292 // HID type SEL +#define HID_CONSUMER_AC_INSERT_FILE 0x293 // HID type SEL +#define HID_CONSUMER_AC_INSERT_PICTURE 0x294 // HID type SEL +#define HID_CONSUMER_AC_INSERT_OBJECT 0x295 // HID type SEL +#define HID_CONSUMER_AC_INSERT_SYMBOL 0x296 // HID type SEL +#define HID_CONSUMER_AC_SAVE_AND_CLOSE 0x297 // HID type SEL +#define HID_CONSUMER_AC_RENAME 0x298 // HID type SEL +#define HID_CONSUMER_AC_MERGE 0x299 // HID type SEL +#define HID_CONSUMER_AC_SPLIT 0x29A // HID type SEL +#define HID_CONSUMER_AC_DISRIBUTE_HORIZONTALLY 0x29B // HID type SEL +#define HID_CONSUMER_AC_DISTRIBUTE_VERTICALLY 0x29C // HID type SEL diff --git a/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h b/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h new file mode 100644 index 0000000000..b512e64627 --- /dev/null +++ b/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h @@ -0,0 +1,348 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 guard +#pragma once + +//================================================================================ +// Key definitions +//================================================================================ + +// Modifiers +#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 + +// Normal keys +#define KEY_UP_ARROW (RAW_KEYBOARD_UP_ARROW + 136) +#define KEY_DOWN_ARROW (RAW_KEYBOARD_DOWN_ARROW + 136) +#define KEY_LEFT_ARROW (RAW_KEYBOARD_LEFT_ARROW + 136) +#define KEY_RIGHT_ARROW (RAW_KEYBOARD_RIGHT_ARROW + 136) +#define KEY_BACKSPACE (RAW_KEYBOARD_BACKSPACE + 136) +#define KEY_TAB (RAW_KEYBOARD_TAB + 136) +#define KEY_RETURN (RAW_KEYBOARD_RETURN + 136) +#define KEY_ENTER KEY_RETURN +#define KEY_ESC (RAW_KEYBOARD_ESC + 136) +#define KEY_INSERT (RAW_KEYBOARD_INSERT + 136) +#define KEY_DELETE (RAW_KEYBOARD_DELETE + 136) +#define KEY_PAGE_UP (RAW_KEYBOARD_PAGE_UP + 136) +#define KEY_PAGE_DOWN (RAW_KEYBOARD_PAGE_DOWN + 136) +#define KEY_HOME (RAW_KEYBOARD_HOME + 136) +#define KEY_END (RAW_KEYBOARD_END + 136) +#define KEY_CAPS_LOCK (RAW_KEYBOARD_CAPS_LOCK + 136) +#define KEY_F1 (RAW_KEYBOARD_F1 + 136) +#define KEY_F2 (RAW_KEYBOARD_F2 + 136) +#define KEY_F3 (RAW_KEYBOARD_F3 + 136) +#define KEY_F4 (RAW_KEYBOARD_F4 + 136) +#define KEY_F5 (RAW_KEYBOARD_F5 + 136) +#define KEY_F6 (RAW_KEYBOARD_F6 + 136) +#define KEY_F7 (RAW_KEYBOARD_F7 + 136) +#define KEY_F8 (RAW_KEYBOARD_F8 + 136) +#define KEY_F9 (RAW_KEYBOARD_F9 + 136) +#define KEY_F10 (RAW_KEYBOARD_F10 + 136) +#define KEY_F11 (RAW_KEYBOARD_F11 + 136) +#define KEY_F12 (RAW_KEYBOARD_F12 + 136) + + +// New key definitions +#define KEY_PRINT (RAW_KEYBOARD_PRINT + 136) +#define KEY_NUM_LOCK (RAW_KEYBOARD_NUM_LOCK + 136) +#define KEY_SCROLL_LOCK (RAW_KEYBOARD_SCROLL_LOCK + 136) +#define KEY_PAUSE (RAW_KEYBOARD_PAUSE + 136) +#define KEY_MENU (RAW_KEYBOARD_MENU + 136) +#define KEY_SPACE ' ' +#define KEY_LEFT_WINDOWS KEY_LEFT_GUI +#define KEY_RIGHT_WINDOWS KEY_RIGHT_GUI +#define KEY_PRINTSCREEN KEY_PRINT + +// Keyboard Leds +#define LED_NUM_LOCK 0x01 +#define LED_CAPS_LOCK 0x02 +#define LED_SCROLL_LOCK 0x04 + +//================================================================================ +// LAYOUT_US_ENGLISH +//================================================================================ + +#if !defined(LAYOUT_US_ENGLISH) && !defined(LAYOUT_UNITED_KINGDOM) +#error This API does not support non english layouts. Please select an US or UK Keyboard. +#endif + +#define RAW_KEYBOARD_LEFT_CTRL (1 << 0) +#define RAW_KEYBOARD_LEFT_SHIFT (1 << 1) +#define RAW_KEYBOARD_LEFT_ALT (1 << 2) +#define RAW_KEYBOARD_LEFT_GUI (1 << 3) +#define RAW_KEYBOARD_RIGHT_CTRL (1 << 4) +#define RAW_KEYBOARD_RIGHT_SHIFT (1 << 5) +#define RAW_KEYBOARD_RIGHT_ALT (1 << 6) +#define RAW_KEYBOARD_RIGHT_GUI (1 << 7) + +#define RAW_KEYBOARD_KEY(key) ((key>='a' && key<='z') ? (0x04 + key-'a') :\ +(key>='A' && key<='Z') ? (0x04 + key-'A') : (key>='1' && key<='9') ? (0x1E + key-'1') : 0x27) + +#define RAW_KEYBOARD_A ( 4 ) +#define RAW_KEYBOARD_B ( 5 ) +#define RAW_KEYBOARD_C ( 6 ) +#define RAW_KEYBOARD_D ( 7 ) +#define RAW_KEYBOARD_E ( 8 ) +#define RAW_KEYBOARD_F ( 9 ) +#define RAW_KEYBOARD_G ( 10 ) +#define RAW_KEYBOARD_H ( 11 ) +#define RAW_KEYBOARD_I ( 12 ) +#define RAW_KEYBOARD_J ( 13 ) +#define RAW_KEYBOARD_K ( 14 ) +#define RAW_KEYBOARD_L ( 15 ) +#define RAW_KEYBOARD_M ( 16 ) +#define RAW_KEYBOARD_N ( 17 ) +#define RAW_KEYBOARD_O ( 18 ) +#define RAW_KEYBOARD_P ( 19 ) +#define RAW_KEYBOARD_Q ( 20 ) +#define RAW_KEYBOARD_R ( 21 ) +#define RAW_KEYBOARD_S ( 22 ) +#define RAW_KEYBOARD_T ( 23 ) +#define RAW_KEYBOARD_U ( 24 ) +#define RAW_KEYBOARD_V ( 25 ) +#define RAW_KEYBOARD_W ( 26 ) +#define RAW_KEYBOARD_X ( 27 ) +#define RAW_KEYBOARD_Y ( 28 ) +#define RAW_KEYBOARD_Z ( 29 ) +#define RAW_KEYBOARD_1 ( 30 ) +#define RAW_KEYBOARD_2 ( 31 ) +#define RAW_KEYBOARD_3 ( 32 ) +#define RAW_KEYBOARD_4 ( 33 ) +#define RAW_KEYBOARD_5 ( 34 ) +#define RAW_KEYBOARD_6 ( 35 ) +#define RAW_KEYBOARD_7 ( 36 ) +#define RAW_KEYBOARD_8 ( 37 ) +#define RAW_KEYBOARD_9 ( 38 ) +#define RAW_KEYBOARD_0 ( 39 ) +#define RAW_KEYBOARD_ENTER ( 40 ) +#define RAW_KEYBOARD_ESC ( 41 ) +#define RAW_KEYBOARD_BACKSPACE ( 42 ) +#define RAW_KEYBOARD_TAB ( 43 ) +#define RAW_KEYBOARD_SPACE ( 44 ) +#define RAW_KEYBOARD_MINUS ( 45 ) +#define RAW_KEYBOARD_EQUAL ( 46 ) +#define RAW_KEYBOARD_LEFT_BRACE ( 47 ) +#define RAW_KEYBOARD_RIGHT_BRACE ( 48 ) +#define RAW_KEYBOARD_BACKSLASH ( 49 ) +#define RAW_KEYBOARD_NON_US_NUM ( 50 ) +#define RAW_KEYBOARD_SEMICOLON ( 51 ) +#define RAW_KEYBOARD_QUOTE ( 52 ) +#define RAW_KEYBOARD_TILDE ( 53 ) +#define RAW_KEYBOARD_COMMA ( 54 ) +#define RAW_KEYBOARD_PERIOD ( 55 ) +#define RAW_KEYBOARD_SLASH ( 56 ) + +#define RAW_KEYBOARD_CAPS_LOCK 0x39 +#define RAW_KEYBOARD_F1 0x3A +#define RAW_KEYBOARD_F2 0x3B +#define RAW_KEYBOARD_F3 0x3C +#define RAW_KEYBOARD_F4 0x3D +#define RAW_KEYBOARD_F5 0x3E +#define RAW_KEYBOARD_F6 0x3F +#define RAW_KEYBOARD_F7 0x40 +#define RAW_KEYBOARD_F8 0x41 +#define RAW_KEYBOARD_F9 0x42 +#define RAW_KEYBOARD_F10 0x43 +#define RAW_KEYBOARD_F11 0x44 +#define RAW_KEYBOARD_F12 0x45 +#define RAW_KEYBOARD_PRINT 0x46 +#define RAW_KEYBOARD_SCROLL_LOCK 0x47 +#define RAW_KEYBOARD_PAUSE 0x48 +#define RAW_KEYBOARD_INSERT 0x49 +#define RAW_KEYBOARD_HOME 0x4A +#define RAW_KEYBOARD_PAGE_UP 0x4B +#define RAW_KEYBOARD_DELETE 0x4C +#define RAW_KEYBOARD_END 0x4D +#define RAW_KEYBOARD_PAGE_DOWN 0x4E +#define RAW_KEYBOARD_RIGHT_ARROW 0x4F +#define RAW_KEYBOARD_LEFT_ARROW 0x50 +#define RAW_KEYBOARD_DOWN_ARROW 0x51 +#define RAW_KEYBOARD_UP_ARROW 0x52 +#define RAW_KEYBOARD_NUM_LOCK 0x53 +#define RAW_KEYBOARD_NON_US 0x64 +#define RAW_KEYBOARD_MENU 0x65 + +#define SHIFT 0x80 +static const uint8_t _asciimap[128] PROGMEM = +{ + 0x00, // NUL + 0x00, // SOH + 0x00, // STX + 0x00, // ETX + 0x00, // EOT + 0x00, // ENQ + 0x00, // ACK + 0x00, // BEL + RAW_KEYBOARD_BACKSPACE, // BS Backspace + RAW_KEYBOARD_TAB, // TAB Tab + RAW_KEYBOARD_ENTER, // 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 + + RAW_KEYBOARD_SPACE, // ' ' + RAW_KEYBOARD_1|SHIFT, // ! +#ifdef LAYOUT_UNITED_KINGDOM + RAW_KEYBOARD_2|SHIFT, // " +#else + RAW_KEYBOARD_QUOTE|SHIFT, // " +#endif +#ifdef LAYOUT_UNITED_KINGDOM + RAW_KEYBOARD_BACKSLASH +#else + RAW_KEYBOARD_3|SHIFT, // # +#endif + RAW_KEYBOARD_4|SHIFT, // $ + RAW_KEYBOARD_5|SHIFT, // % + RAW_KEYBOARD_7|SHIFT, // & + RAW_KEYBOARD_QUOTE, // ' + RAW_KEYBOARD_9|SHIFT, // ( + RAW_KEYBOARD_0|SHIFT, // ) + RAW_KEYBOARD_8|SHIFT, // * + RAW_KEYBOARD_EQUAL|SHIFT, // + + RAW_KEYBOARD_COMMA, // , + RAW_KEYBOARD_MINUS, // - + RAW_KEYBOARD_PERIOD, // . + RAW_KEYBOARD_SLASH, // / + RAW_KEYBOARD_0, // 0 + RAW_KEYBOARD_1, // 1 + RAW_KEYBOARD_2, // 2 + RAW_KEYBOARD_3, // 3 + RAW_KEYBOARD_4, // 4 + RAW_KEYBOARD_5, // 5 + RAW_KEYBOARD_6, // 6 + RAW_KEYBOARD_7, // 7 + RAW_KEYBOARD_8, // 8 + RAW_KEYBOARD_9, // 9 + RAW_KEYBOARD_SEMICOLON|SHIFT, // : + RAW_KEYBOARD_SEMICOLON, // ; + RAW_KEYBOARD_COMMA|SHIFT, // < + RAW_KEYBOARD_EQUAL, // = + RAW_KEYBOARD_PERIOD|SHIFT, // > + RAW_KEYBOARD_SLASH|SHIFT, // ? +#ifdef LAYOUT_UNITED_KINGDOM + RAW_KEYBOARD_QUOTE|SHIFT, // @ +#else + RAW_KEYBOARD_2|SHIFT, // @ +#endif + RAW_KEYBOARD_A|SHIFT, // A + RAW_KEYBOARD_B|SHIFT, // B + RAW_KEYBOARD_C|SHIFT, // C + RAW_KEYBOARD_D|SHIFT, // D + RAW_KEYBOARD_E|SHIFT, // E + RAW_KEYBOARD_F|SHIFT, // F + RAW_KEYBOARD_G|SHIFT, // G + RAW_KEYBOARD_H|SHIFT, // H + RAW_KEYBOARD_I|SHIFT, // I + RAW_KEYBOARD_J|SHIFT, // J + RAW_KEYBOARD_K|SHIFT, // K + RAW_KEYBOARD_L|SHIFT, // L + RAW_KEYBOARD_M|SHIFT, // M + RAW_KEYBOARD_N|SHIFT, // N + RAW_KEYBOARD_O|SHIFT, // O + RAW_KEYBOARD_P|SHIFT, // P + RAW_KEYBOARD_Q|SHIFT, // Q + RAW_KEYBOARD_R|SHIFT, // R + RAW_KEYBOARD_S|SHIFT, // S + RAW_KEYBOARD_T|SHIFT, // T + RAW_KEYBOARD_U|SHIFT, // U + RAW_KEYBOARD_V|SHIFT, // V + RAW_KEYBOARD_W|SHIFT, // W + RAW_KEYBOARD_X|SHIFT, // X + RAW_KEYBOARD_Y|SHIFT, // Y + RAW_KEYBOARD_Z|SHIFT, // Z + RAW_KEYBOARD_LEFT_BRACE, // [ +#ifdef LAYOUT_UNITED_KINGDOM + RAW_KEYBOARD_NON_US, // bslash +#else + RAW_KEYBOARD_BACKSLASH, // bslash +#endif + RAW_KEYBOARD_RIGHT_BRACE, // ] + RAW_KEYBOARD_6|SHIFT, // ^ + RAW_KEYBOARD_MINUS|SHIFT, // _ + RAW_KEYBOARD_TILDE, // ` + RAW_KEYBOARD_A, // a + RAW_KEYBOARD_B, // b + RAW_KEYBOARD_C, // c + RAW_KEYBOARD_D, // d + RAW_KEYBOARD_E, // e + RAW_KEYBOARD_F, // f + RAW_KEYBOARD_G, // g + RAW_KEYBOARD_H, // h + RAW_KEYBOARD_I, // i + RAW_KEYBOARD_J, // j + RAW_KEYBOARD_K, // k + RAW_KEYBOARD_L, // l + RAW_KEYBOARD_M, // m + RAW_KEYBOARD_N, // n + RAW_KEYBOARD_O, // o + RAW_KEYBOARD_P, // p + RAW_KEYBOARD_Q, // q + RAW_KEYBOARD_R, // r + RAW_KEYBOARD_S, // s + RAW_KEYBOARD_T, // t + RAW_KEYBOARD_U, // u + RAW_KEYBOARD_V, // v + RAW_KEYBOARD_W, // w + RAW_KEYBOARD_X, // x + RAW_KEYBOARD_Y, // y + RAW_KEYBOARD_Z, // z + RAW_KEYBOARD_LEFT_BRACE|SHIFT, // { +#ifdef LAYOUT_UNITED_KINGDOM + RAW_KEYBOARD_NON_US|SHIFT, // | +#else + RAW_KEYBOARD_BACKSLASH|SHIFT, // | +#endif + RAW_KEYBOARD_RIGHT_BRACE|SHIFT, // } +#ifdef LAYOUT_UNITED_KINGDOM + RAW_KEYBOARD_BACKSLASH|SHIFT, // ~ +#else + RAW_KEYBOARD_TILDE|SHIFT, // ~ +#endif + 0x00 // DEL +}; diff --git a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.cpp b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.cpp new file mode 100644 index 0000000000..58cd47674d --- /dev/null +++ b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.cpp @@ -0,0 +1,279 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 "KeyboardAPI.h" + +const uint8_t _hidReportDescriptorKeyboard[] PROGMEM = { + HID_REPORT_KEYBOARD, +}; + +const uint8_t _hidMultiReportDescriptorKeyboard[] PROGMEM = { + HID_MULTIREPORT_KEYBOARD, +}; + +static_assert(sizeof _hidReportDescriptorKeyboard == HID_REPORT_KEYBOARD_SIZE, "Oops, sizes are not equal."); +static_assert(sizeof _hidMultiReportDescriptorKeyboard == HID_MULTIREPORT_KEYBOARD_SIZE, "Oops, sizes are not equal."); + + + +void KeyboardAPI::begin(void) +{ + releaseAll(); +} + + +void KeyboardAPI::end(void) +{ + releaseAll(); +} + + +void KeyboardAPI::send_now(void){ + sendReport(&_keyReport, sizeof(_keyReport)); +} + + +// 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 KeyboardAPI::press(uint8_t k) +{ + // TODO improve the whole mechanism + size_t ret = addKeyToReport(k); + if(ret){ + send_now(); + } + return ret; +} + +// 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 KeyboardAPI::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 & SHIFT) { // it's a capital letter or other character reached with shift + _keyReport.modifiers &= ~(0x02); // the left shift modifier + k = k ^ SHIFT; + } + } + + // 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; + } + } + + send_now(); + return 1; +} + +void KeyboardAPI::releaseAll(void) +{ + // release all keys + memset(&_keyReport, 0x00, sizeof(_keyReport)); + send_now(); +} + +size_t KeyboardAPI::write(uint8_t c) +{ + uint8_t p = press(c); // Keydown + release(c); // Keyup + return p; // just return the result of press() since release() almost always returns 1 +} + +// pressKeycode() 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 releaseKeycode(), releaseAll(), or otherwise clear the report and resend. +size_t KeyboardAPI::pressKeycode(uint8_t k) +{ + if (!addKeycodeToReport(k)) { + return 0; + } + send_now(); + return 1; +} + +size_t KeyboardAPI::addKeyToReport(uint8_t k) +{ + 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 & SHIFT) { // it's a capital letter or other character reached with shift + _keyReport.modifiers |= 0x02; // the left shift modifier + k = k ^ SHIFT; + } + } + + return addKeycodeToReport(k); +} + +size_t KeyboardAPI::addKeycodeToReport(uint8_t k) +{ + uint8_t index = 0; + uint8_t done = 0; + + if ((k >= HID_KEYBOARD_LEFT_CONTROL) && (k <= HID_KEYBOARD_RIGHT_GUI)) { + // it's a modifier key + _keyReport.modifiers |= (0x01 << (k - HID_KEYBOARD_LEFT_CONTROL)); + } + else { + // it's some other key: + // Add k to the key report only if it's not already present + // and if there is an empty slot. + for (index = 0; index < sizeof(_keyReport.keys); index++) { + if (_keyReport.keys[index] != k) { // is k already in list? + if (0 == _keyReport.keys[index]) { // have we found an empty slot? + _keyReport.keys[index] = k; + done = 1; + break; + } + } + else { + done = 1; + break; + } + + } + + // use separate variable to check if slot was found + // for style reasons - we do not know how the compiler + // handles the for() index when it leaves the loop + if (0 == done) { + setWriteError(); + return 0; + } + } + + return 1; +} + + +// releaseKeycode() 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. +// When send is set to FALSE (= 0) no sendReport() is executed. This comes in +// handy when combining key releases (e.g. SHIFT+A). +size_t KeyboardAPI::releaseKeycode(uint8_t k) +{ + if (!removeKeycodeFromReport(k)) { + return 0; + } + send_now(); + return 1; +} + +size_t KeyboardAPI::removeKeyFromReport(uint8_t k) +{ + 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 & SHIFT) { // it's a capital letter or other character reached with shift + _keyReport.modifiers &= ~(0x02); // the left shift modifier + k = k ^ SHIFT; + } + } + + return removeKeycodeFromReport(k); +} + +size_t KeyboardAPI::removeKeycodeFromReport(uint8_t k) +{ + uint8_t indexA; + uint8_t indexB; + uint8_t count; + + if ((k >= HID_KEYBOARD_LEFT_CONTROL) && (k <= HID_KEYBOARD_RIGHT_GUI)) { + // it's a modifier key + _keyReport.modifiers = _keyReport.modifiers & (~(0x01 << (k - HID_KEYBOARD_LEFT_CONTROL))); + } + else { + // it's some other key: + // 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 (indexA = 0; indexA < sizeof(_keyReport.keys); indexA++) { + if (_keyReport.keys[indexA] == k) { + _keyReport.keys[indexA] = 0; + } + } + + // finally rearrange the keys list so that the free (= 0x00) are at the + // end of the keys list - some implementations stop for keys at the + // first occurence of an 0x00 in the keys list + // so (0x00)(0x01)(0x00)(0x03)(0x02)(0x00) becomes + // (0x01)(0x03)(0x02)(0x00)(0x00)(0x00) + count = 0; // holds the number of zeros we've found + indexA = 0; + while ((indexA + count) < sizeof(_keyReport.keys)) { + if (0 == _keyReport.keys[indexA]) { + count++; // one more zero + for (indexB = indexA; indexB < sizeof(_keyReport.keys) - count; indexB++) { + _keyReport.keys[indexB] = _keyReport.keys[indexB + 1]; + } + _keyReport.keys[sizeof(_keyReport.keys) - count] = 0; + } + else { + indexA++; // one more non-zero + } + } + } + + return 1; +} + + +size_t KeyboardAPI::writeKeycode(uint8_t c) +{ + uint8_t p = pressKeycode(c); // Keydown + releaseKeycode(c); // Keyup + return (p); // just return the result of pressKeycode() since release() almost always returns 1 +} diff --git a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h new file mode 100644 index 0000000000..84bfe9a05d --- /dev/null +++ b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h @@ -0,0 +1,150 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 guard +#pragma once + +#include +#include "HID-Settings.h" +#include "ImprovedKeylayouts.h" +#include "HID-Tables.h" //TODO + + +#define HID_REPORT_KEYBOARD_START \ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 47 */ \ + 0x09, 0x06, /* USAGE (Keyboard) */ \ + 0xa1, 0x01 /* COLLECTION (Application) */ + +#define HID_REPORT_KEYBOARD_REPORTID \ + 0x85, HID_REPORTID_KEYBOARD /* REPORT_ID TODO order important?*/ + +#define HID_REPORT_KEYBOARD_START2 \ + 0x05, 0x07 /* USAGE_PAGE (Keyboard) */ + +#define HID_REPORT_KEYBOARD_MODIFIERS \ + /* Keyboard Modifiers (shift, alt, ...) */ \ + 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) */ + +#define HID_REPORT_KEYBOARD_RESERVED \ + /* Reserved byte TODO consumer and or system?*/ \ + 0x95, 0x01, /* REPORT_COUNT (1) */ \ + 0x75, 0x08, /* REPORT_SIZE (8) */ \ + 0x81, 0x03 /* INPUT (Cnst,Var,Abs) */ \ + +#define HID_REPORT_KEYBOARD_KEYS \ + /* 6 Keyboard keys */ \ + 0x95, 0x06, /* REPORT_COUNT (6) */ \ + 0x75, 0x08, /* REPORT_SIZE (8) */ \ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \ + 0x26, 0xE7, 0x00, /* LOGICAL_MAXIMUM (231) */ \ + 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ \ + 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ \ + 0x29, 0xE7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ \ + 0x81, 0x00 /* INPUT (Data,Ary,Abs) */ + +#define HID_REPORT_KEYBOARD_LEDS \ + /* 5 LEDs for num lock etc */ \ + 0x05, 0x08, /* USAGE_PAGE (LEDs) */ \ + 0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */ \ + 0x29, 0x05, /* USAGE_MAXIMUM (Kana) TODO */ \ + 0x95, 0x05, /* REPORT_COUNT (5) */ \ + 0x75, 0x01, /* REPORT_SIZE (1) */ \ + 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */ \ + /* Reserved 3 bits TODO */ \ + 0x95, 0x01, /* REPORT_COUNT (1) */ \ + 0x75, 0x03, /* REPORT_SIZE (3) */ \ + 0x91, 0x03 /* OUTPUT (Cnst,Var,Abs) */ + +#define HID_REPORT_KEYBOARD_END \ + /* End */ \ + 0xc0 /* END_COLLECTION */ + +#define HID_REPORT_KEYBOARD \ +HID_REPORT_KEYBOARD_START, \ +HID_REPORT_KEYBOARD_START2, \ +HID_REPORT_KEYBOARD_MODIFIERS, \ +HID_REPORT_KEYBOARD_RESERVED, \ +HID_REPORT_KEYBOARD_KEYS, \ +HID_REPORT_KEYBOARD_LEDS, \ +HID_REPORT_KEYBOARD_END + +#define HID_MULTIREPORT_KEYBOARD \ +HID_REPORT_KEYBOARD_START, \ +HID_REPORT_KEYBOARD_REPORTID, \ +HID_REPORT_KEYBOARD_START2, \ +HID_REPORT_KEYBOARD_MODIFIERS, \ +HID_REPORT_KEYBOARD_RESERVED, \ +HID_REPORT_KEYBOARD_KEYS, \ +HID_REPORT_KEYBOARD_END + +#define HID_REPORT_KEYBOARD_SIZE sizeof ((uint8_t[]) {HID_REPORT_KEYBOARD}) +#define HID_MULTIREPORT_KEYBOARD_SIZE sizeof ((uint8_t[]) {HID_MULTIREPORT_KEYBOARD}) + +extern const uint8_t _hidReportDescriptorKeyboard[HID_REPORT_KEYBOARD_SIZE] PROGMEM; +extern const uint8_t _hidMultiReportDescriptorKeyboard[HID_MULTIREPORT_KEYBOARD_SIZE] PROGMEM; + + +typedef union{ + // Low level key report: up to 6 keys and shift, ctrl etc at once + uint8_t whole8[]; + uint16_t whole16[]; + uint32_t whole32[]; + struct{ + uint8_t modifiers; + uint8_t reserved; + uint8_t keys[6]; + }; +} HID_KeyboardReport_Data_t; + +class KeyboardAPI : public Print +{ +public: +//TODO nkro compatiblity, merge them + void begin(void); + void end(void); + size_t write(uint8_t k); + size_t press(uint8_t k); + size_t release(uint8_t k); + void releaseAll(void); + void send_now(void); + + size_t writeKeycode(uint8_t k); + size_t pressKeycode(uint8_t k); + size_t releaseKeycode(uint8_t k); + size_t addKeyToReport(uint8_t k); + size_t addKeycodeToReport(uint8_t k); + size_t removeKeyFromReport(uint8_t k); + size_t removeKeycodeFromReport(uint8_t k); + + // Sending is public in the base class for advanced users. + virtual void sendReport(void* data, int length) = 0; + +protected: + HID_KeyboardReport_Data_t _keyReport; +}; diff --git a/plugins/KeyboardioHID/src/HID-Settings.h b/plugins/KeyboardioHID/src/HID-Settings.h new file mode 100644 index 0000000000..afa38be926 --- /dev/null +++ b/plugins/KeyboardioHID/src/HID-Settings.h @@ -0,0 +1,112 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 guard +#pragma once + +//================================================================================ +// Settings +//================================================================================ + +#define HID_KEYBOARD_LEDS_ENABLED + +//#define LAYOUT_US_ENGLISH +//#define LAYOUT_CANADIAN_FRENCH +//#define LAYOUT_CANADIAN_MULTILINGUAL +//#define LAYOUT_DANISH +//#define LAYOUT_FINNISH +//#define LAYOUT_FRENCH +//#define LAYOUT_FRENCH_BELGIAN +//#define LAYOUT_FRENCH_SWISS +//#define LAYOUT_GERMAN +//#define LAYOUT_GERMAN_MAC +//#define LAYOUT_GERMAN_SWISS +//#define LAYOUT_ICELANDIC +//#define LAYOUT_IRISH +//#define LAYOUT_ITALIAN +//#define LAYOUT_NORWEGIAN +//#define LAYOUT_PORTUGUESE +//#define LAYOUT_PORTUGUESE_BRAZILIAN +//#define LAYOUT_SPANISH +//#define LAYOUT_SPANISH_LATIN_AMERICA +//#define LAYOUT_SWEDISH +//#define LAYOUT_TURKISH +//#define LAYOUT_UNITED_KINGDOM +//#define LAYOUT_US_INTERNATIONAL + +//================================================================================ +// Definitions and Helpers +//================================================================================ + +// Default US keyboard layout +#if !defined(LAYOUT_CANADIAN_FRENCH) && !defined(LAYOUT_CANADIAN_MULTILINGUAL) \ +&& !defined(LAYOUT_DANISH) && !defined(LAYOUT_FINNISH) && !defined(LAYOUT_FRENCH) \ +&& !defined(LAYOUT_FRENCH_BELGIAN) && !defined(LAYOUT_FRENCH_SWISS) && !defined(LAYOUT_GERMAN) \ +&& !defined(LAYOUT_GERMAN_MAC) && !defined(LAYOUT_GERMAN_SWISS) && !defined(LAYOUT_ICELANDIC) \ +&& !defined(LAYOUT_IRISH) && !defined(LAYOUT_ITALIAN) && !defined(LAYOUT_NORWEGIAN) \ +&& !defined(LAYOUT_PORTUGUESE) && !defined(LAYOUT_PORTUGUESE_BRAZILIAN) \ +&& !defined(LAYOUT_SPANISH) && !defined(LAYOUT_SPANISH_LATIN_AMERICA) \ +&& !defined(LAYOUT_SWEDISH) && !defined(LAYOUT_TURKISH) && !defined(LAYOUT_UNITED_KINGDOM) \ +&& !defined(LAYOUT_US_INTERNATIONAL) && !defined(LAYOUT_US_ENGLISH) +#define LAYOUT_US_ENGLISH +#endif + +#define HID_REPORTID_NONE 0 + +#ifndef HID_REPORTID_MOUSE +#define HID_REPORTID_MOUSE 1 +#endif + +#ifndef HID_REPORTID_KEYBOARD +#define HID_REPORTID_KEYBOARD 2 +#endif + +#ifndef HID_REPORTID_RAWHID +// This will not work properly in most cases. +// The number is just kept from the old number counting. +#define HID_REPORTID_RAWHID 3 +#endif + +#ifndef HID_REPORTID_CONSUMERCONTROL +#define HID_REPORTID_CONSUMERCONTROL 4 +#endif + +#ifndef HID_REPORTID_SYSTEMCONTROL +#define HID_REPORTID_SYSTEMCONTROL 5 +#endif + +#ifndef HID_REPORTID_GAMEPAD +#define HID_REPORTID_GAMEPAD 6 +#endif + +#ifndef HID_REPORTID_MOUSE_ABSOLUTE +#define HID_REPORTID_MOUSE_ABSOLUTE 7 +#endif + +#ifndef HID_REPORTID_NKRO_KEYBOARD +#define HID_REPORTID_NKRO_KEYBOARD 8 +#endif + +#ifndef HID_REPORTID_TEENSY_KEYBOARD +#define HID_REPORTID_TEENSY_KEYBOARD 9 +#endif diff --git a/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.cpp new file mode 100644 index 0000000000..7e391a640f --- /dev/null +++ b/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.cpp @@ -0,0 +1,38 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 "ImprovedKeyboard.h" + +Keyboard_::Keyboard_(void) +{ + static HIDDescriptorListNode node(_hidMultiReportDescriptorKeyboard, sizeof(_hidMultiReportDescriptorKeyboard)); + HID().AppendDescriptor(&node); +} + +void Keyboard_::sendReport(void* data, int length) +{ + HID().SendReport(HID_REPORTID_KEYBOARD, data, length); +} + +Keyboard_ Keyboard; + diff --git a/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.h b/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.h new file mode 100644 index 0000000000..b6b9ab2882 --- /dev/null +++ b/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.h @@ -0,0 +1,43 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 guard +#pragma once + +#include +#include "PluggableUSB.h" +#include "HID-Settings.h" +#include "HID.h" +#include "../HID-APIs/KeyboardAPI.h" + + +class Keyboard_ : public KeyboardAPI +{ +public: + Keyboard_(void); + +protected: + virtual inline void sendReport(void* data, int length) override; +}; +extern Keyboard_ Keyboard; + diff --git a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp new file mode 100644 index 0000000000..b67fd00f15 --- /dev/null +++ b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp @@ -0,0 +1,109 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 "BootKeyboard.h" +#include "HID-Driver.h" + +BootKeyboard_::BootKeyboard_(void) : PUSBListNode(1, 1, epType), protocol(1), idle(1), leds(0) +{ + epType[0] = EP_TYPE_INTERRUPT_IN; + PluggableUSB().plug(this); +} + +int BootKeyboard_::getInterface(uint8_t* interfaceCount) +{ + *interfaceCount += 1; // uses 1 + HIDDescriptor hidInterface = { + D_INTERFACE(pluggedInterface, 1, 3, 1, 1), // Boot compatible keyboard + D_HIDREPORT(sizeof(_hidReportDescriptorKeyboard)), + D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) + }; + return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); +} + +int BootKeyboard_::getDescriptor(USBSetup& setup) +{ + // Check if this is a HID Class Descriptor request + if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { return 0; } + if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { return 0; } + + // In a HID Class Descriptor wIndex cointains the interface number + if (setup.wIndex != pluggedInterface) { return 0; } + + return USB_SendControl(TRANSFER_PGM, _hidReportDescriptorKeyboard, sizeof(_hidReportDescriptorKeyboard)); +} + +bool BootKeyboard_::setup(USBSetup& setup) +{ + // Check if this is a HID Class Descriptor request + if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { return false; } + if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { return false; } + + // In a HID Class Descriptor wIndex cointains the interface number + if (setup.wIndex != pluggedInterface) { return false; } + + uint8_t request = setup.bRequest; + uint8_t requestType = setup.bmRequestType; + + if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) + { + if (request == HID_GET_REPORT) { + // TODO: HID_GetReport(); + return true; + } + if (request == HID_GET_PROTOCOL) { + // TODO: Send8(protocol); + return true; + } + } + + if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) + { + if (request == HID_SET_PROTOCOL) { + protocol = setup.wValueL; + return true; + } + if (request == HID_SET_IDLE) { + idle = setup.wValueL; + return true; + } + if (request == HID_SET_REPORT) + { + //TODO + } + } + + return false; +} + +uint8_t BootKeyboard_::getLeds(void){ + return leds; +} + +void BootKeyboard_::sendReport(void* data, int length){ + USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, length); +} + +BootKeyboard_ BootKeyboard; + + diff --git a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h new file mode 100644 index 0000000000..01bcfcf23b --- /dev/null +++ b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h @@ -0,0 +1,55 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 guard +#pragma once + +#include +#include "PluggableUSB.h" +#include "HID-Settings.h" +#include "../HID-APIs/KeyboardAPI.h" + + +class BootKeyboard_ : public PUSBListNode, public KeyboardAPI +{ +public: + BootKeyboard_(void); + uint8_t getLeds(void); + +protected: + // Implementation of the PUSBListNode + int getInterface(uint8_t* interfaceCount); + int getDescriptor(USBSetup& setup); + bool setup(USBSetup& setup); + + uint8_t epType[1]; + uint8_t protocol; + uint8_t idle; + + uint8_t leds; + + virtual void sendReport(void* data, int length) override; +}; +extern BootKeyboard_ BootKeyboard; + + diff --git a/plugins/KeyboardioHID/src/SingleReport/HID-Driver.h b/plugins/KeyboardioHID/src/SingleReport/HID-Driver.h new file mode 100644 index 0000000000..9dcfd6ac3a --- /dev/null +++ b/plugins/KeyboardioHID/src/SingleReport/HID-Driver.h @@ -0,0 +1,61 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 guard +#pragma once + +// HID 'Driver' +// ------------ +#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 + +#define HID_HID_DESCRIPTOR_TYPE 0x21 +#define HID_REPORT_DESCRIPTOR_TYPE 0x22 +#define HID_PHYSICAL_DESCRIPTOR_TYPE 0x23 + +typedef struct +{ + uint8_t len; // 9 + uint8_t dtype; // 0x21 + uint8_t addr; + uint8_t versionL; // 0x101 + uint8_t versionH; // 0x101 + uint8_t country; + uint8_t desctype; // 0x22 report + uint8_t descLenL; + uint8_t descLenH; +} HIDDescDescriptor; + +typedef struct +{ + InterfaceDescriptor hid; + HIDDescDescriptor desc; + EndpointDescriptor in; +} HIDDescriptor; + +#define D_HIDREPORT(length) { 9, 0x21, 0x01, 0x01, 0, 1, 0x22, lowByte(length), highByte(length) } + From de60d8502914df176ffdc692f843e46f8737ae50 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Fri, 9 Oct 2015 22:27:09 +0200 Subject: [PATCH 260/602] Fixed Keyboard Leds --- .../src/SingleReport/BootKeyboard.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp index b67fd00f15..0dfd13ca06 100644 --- a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp @@ -55,12 +55,9 @@ int BootKeyboard_::getDescriptor(USBSetup& setup) bool BootKeyboard_::setup(USBSetup& setup) { - // Check if this is a HID Class Descriptor request - if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { return false; } - if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { return false; } - - // In a HID Class Descriptor wIndex cointains the interface number - if (setup.wIndex != pluggedInterface) { return false; } + if (pluggedInterface != setup.wIndex) { + return false; + } uint8_t request = setup.bRequest; uint8_t requestType = setup.bmRequestType; @@ -89,7 +86,11 @@ bool BootKeyboard_::setup(USBSetup& setup) } if (request == HID_SET_REPORT) { - //TODO + // Check if data has the correct length + auto length = setup.wLength; + if(length == sizeof(leds)){ + USB_RecvControl(&leds, length); + } } } From bc2d3544ea90a12a9b6b02d23450793f2dcb78e1 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 10 Oct 2015 07:52:22 +0200 Subject: [PATCH 261/602] Added HID protocol (bios/normal mode) --- plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp | 4 ++++ plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h | 1 + plugins/KeyboardioHID/src/SingleReport/HID-Driver.h | 4 ++++ 3 files changed, 9 insertions(+) diff --git a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp index 0dfd13ca06..8e6b811e07 100644 --- a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp @@ -101,6 +101,10 @@ uint8_t BootKeyboard_::getLeds(void){ return leds; } +uint8_t BootKeyboard_::getProtocol(void){ + return protocol; +} + void BootKeyboard_::sendReport(void* data, int length){ USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, length); } diff --git a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h index 01bcfcf23b..fdad4f3673 100644 --- a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h @@ -35,6 +35,7 @@ class BootKeyboard_ : public PUSBListNode, public KeyboardAPI public: BootKeyboard_(void); uint8_t getLeds(void); + uint8_t getProtocol(void); protected: // Implementation of the PUSBListNode diff --git a/plugins/KeyboardioHID/src/SingleReport/HID-Driver.h b/plugins/KeyboardioHID/src/SingleReport/HID-Driver.h index 9dcfd6ac3a..0dcde68c46 100644 --- a/plugins/KeyboardioHID/src/SingleReport/HID-Driver.h +++ b/plugins/KeyboardioHID/src/SingleReport/HID-Driver.h @@ -37,6 +37,10 @@ THE SOFTWARE. #define HID_REPORT_DESCRIPTOR_TYPE 0x22 #define HID_PHYSICAL_DESCRIPTOR_TYPE 0x23 +// Keyboard/Mouse protocols (normal or bios) HID1.11 Page 8 4.2 Subclass +#define HID_PROTOCOL_NO_SUBCLASS 0 +#define HID_PROTOCOL_BOOT 1 + typedef struct { uint8_t len; // 9 From ce65015189ecc97f3792807b673357e9e1770885 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 10 Oct 2015 07:58:32 +0200 Subject: [PATCH 262/602] Fixed KEY_RETURN definition --- plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h b/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h index b512e64627..0a5c397abc 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h +++ b/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h @@ -45,8 +45,8 @@ THE SOFTWARE. #define KEY_RIGHT_ARROW (RAW_KEYBOARD_RIGHT_ARROW + 136) #define KEY_BACKSPACE (RAW_KEYBOARD_BACKSPACE + 136) #define KEY_TAB (RAW_KEYBOARD_TAB + 136) -#define KEY_RETURN (RAW_KEYBOARD_RETURN + 136) -#define KEY_ENTER KEY_RETURN +#define KEY_RETURN KEY_ENTER +#define KEY_ENTER (RAW_KEYBOARD_ENTER + 136) #define KEY_ESC (RAW_KEYBOARD_ESC + 136) #define KEY_INSERT (RAW_KEYBOARD_INSERT + 136) #define KEY_DELETE (RAW_KEYBOARD_DELETE + 136) From a6d50fe0bdf0c142094d83f0eac7a8ccaee30f0d Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 10 Oct 2015 11:33:06 +0200 Subject: [PATCH 263/602] corrected protocol definition --- plugins/KeyboardioHID/src/SingleReport/HID-Driver.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/KeyboardioHID/src/SingleReport/HID-Driver.h b/plugins/KeyboardioHID/src/SingleReport/HID-Driver.h index 0dcde68c46..3c36f270fb 100644 --- a/plugins/KeyboardioHID/src/SingleReport/HID-Driver.h +++ b/plugins/KeyboardioHID/src/SingleReport/HID-Driver.h @@ -37,9 +37,9 @@ THE SOFTWARE. #define HID_REPORT_DESCRIPTOR_TYPE 0x22 #define HID_PHYSICAL_DESCRIPTOR_TYPE 0x23 -// Keyboard/Mouse protocols (normal or bios) HID1.11 Page 8 4.2 Subclass -#define HID_PROTOCOL_NO_SUBCLASS 0 -#define HID_PROTOCOL_BOOT 1 +// Keyboard/Mouse protocols (normal or bios) HID1.11 Page 54 7.2.5 Get_Protocol Request +#define HID_BOOT_PROTOCOL 0 +#define HID_REPORT_PROTOCOL 1 typedef struct { From d410bf66ef411a50c3d9963974bf1a4b2ae2a956 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 10 Oct 2015 11:59:18 +0200 Subject: [PATCH 264/602] Added Teensy API Not implemented as device yet --- .../src/HID-APIs/TeensyKeyboardAPI.cpp | 441 ++ .../src/HID-APIs/TeensyKeyboardAPI.h | 162 + .../src/HID-APIs/TeensyKeylayouts.h | 5420 +++++++++++++++++ 3 files changed, 6023 insertions(+) create mode 100644 plugins/KeyboardioHID/src/HID-APIs/TeensyKeyboardAPI.cpp create mode 100644 plugins/KeyboardioHID/src/HID-APIs/TeensyKeyboardAPI.h create mode 100644 plugins/KeyboardioHID/src/HID-APIs/TeensyKeylayouts.h diff --git a/plugins/KeyboardioHID/src/HID-APIs/TeensyKeyboardAPI.cpp b/plugins/KeyboardioHID/src/HID-APIs/TeensyKeyboardAPI.cpp new file mode 100644 index 0000000000..3e2bca4887 --- /dev/null +++ b/plugins/KeyboardioHID/src/HID-APIs/TeensyKeyboardAPI.cpp @@ -0,0 +1,441 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 "TeensyKeyboardAPI.h" + +// Step #1, decode UTF8 to Unicode code points +// +size_t TeensyKeyboardAPI::write(uint8_t c) +{ + if (c < 0x80) { + // single byte encoded, 0x00 to 0x7F + utf8_state = 0; + write_unicode(c); + } else if (c < 0xC0) { + // 2nd, 3rd or 4th byte, 0x80 to 0xBF + c &= 0x3F; + if (utf8_state == 1) { + utf8_state = 0; + write_unicode(unicode_wchar | c); + } else if (utf8_state == 2) { + unicode_wchar |= ((uint16_t)c << 6); + utf8_state = 1; + } + } else if (c < 0xE0) { + // begin 2 byte sequence, 0xC2 to 0xDF + // or illegal 2 byte sequence, 0xC0 to 0xC1 + unicode_wchar = (uint16_t)(c & 0x1F) << 6; + utf8_state = 1; + } else if (c < 0xF0) { + // begin 3 byte sequence, 0xE0 to 0xEF + unicode_wchar = (uint16_t)(c & 0x0F) << 12; + utf8_state = 2; + } else { + // begin 4 byte sequence (not supported), 0xF0 to 0xF4 + // or illegal, 0xF5 to 0xFF + utf8_state = 255; + } + return 1; +} + + +// Step #2: translate Unicode code point to keystroke sequence +// +KEYCODE_TYPE TeensyKeyboardAPI::unicode_to_keycode(uint16_t cpoint) +{ + // Unicode code points beyond U+FFFF are not supported + // technically this input should probably be called UCS-2 + if (cpoint < 32) { + if (cpoint == 10) return KEY_ENTER & 0x3FFF; + return 0; + } + if (cpoint < 128) { + if (sizeof(KEYCODE_TYPE) == 1) { + return pgm_read_byte(keycodes_ascii + (cpoint - 0x20)); + } else if (sizeof(KEYCODE_TYPE) == 2) { + return pgm_read_word(keycodes_ascii + (cpoint - 0x20)); + } + return 0; + } + #ifdef ISO_8859_1_A0 + if (cpoint <= 0xA0) return 0; + if (cpoint < 0x100) { + if (sizeof(KEYCODE_TYPE) == 1) { + return pgm_read_byte(keycodes_iso_8859_1 + (cpoint - 0xA0)); + } else if (sizeof(KEYCODE_TYPE) == 2) { + return pgm_read_word(keycodes_iso_8859_1 + (cpoint - 0xA0)); + } + return 0; + } + #endif + //#ifdef UNICODE_20AC + //if (cpoint == 0x20AC) return UNICODE_20AC & 0x3FFF; + //#endif + #ifdef KEYCODE_EXTRA00 + if (cpoint == UNICODE_EXTRA00) return KEYCODE_EXTRA00 & 0x3FFF; + #endif + #ifdef KEYCODE_EXTRA01 + if (cpoint == UNICODE_EXTRA01) return KEYCODE_EXTRA01 & 0x3FFF; + #endif + #ifdef KEYCODE_EXTRA02 + if (cpoint == UNICODE_EXTRA02) return KEYCODE_EXTRA02 & 0x3FFF; + #endif + #ifdef KEYCODE_EXTRA03 + if (cpoint == UNICODE_EXTRA03) return KEYCODE_EXTRA03 & 0x3FFF; + #endif + #ifdef KEYCODE_EXTRA04 + if (cpoint == UNICODE_EXTRA04) return KEYCODE_EXTRA04 & 0x3FFF; + #endif + #ifdef KEYCODE_EXTRA05 + if (cpoint == UNICODE_EXTRA05) return KEYCODE_EXTRA05 & 0x3FFF; + #endif + #ifdef KEYCODE_EXTRA06 + if (cpoint == UNICODE_EXTRA06) return KEYCODE_EXTRA06 & 0x3FFF; + #endif + #ifdef KEYCODE_EXTRA07 + if (cpoint == UNICODE_EXTRA07) return KEYCODE_EXTRA07 & 0x3FFF; + #endif + #ifdef KEYCODE_EXTRA08 + if (cpoint == UNICODE_EXTRA08) return KEYCODE_EXTRA08 & 0x3FFF; + #endif + #ifdef KEYCODE_EXTRA09 + if (cpoint == UNICODE_EXTRA09) return KEYCODE_EXTRA09 & 0x3FFF; + #endif + return 0; +} + +// Step #3: execute keystroke sequence +// +void TeensyKeyboardAPI::write_keycode(KEYCODE_TYPE keycode) +{ + if (!keycode) return; + #ifdef DEADKEYS_MASK + KEYCODE_TYPE deadkeycode = deadkey_to_keycode(keycode); + if (deadkeycode) write_key(deadkeycode); + #endif + write_key(keycode); +} + +KEYCODE_TYPE TeensyKeyboardAPI::deadkey_to_keycode(KEYCODE_TYPE keycode) +{ + #ifdef DEADKEYS_MASK + keycode &= DEADKEYS_MASK; + if (keycode == 0) return 0; + #ifdef ACUTE_ACCENT_BITS + if (keycode == ACUTE_ACCENT_BITS) return DEADKEY_ACUTE_ACCENT; + #endif + #ifdef CEDILLA_BITS + if (keycode == CEDILLA_BITS) return DEADKEY_CEDILLA; + #endif + #ifdef CIRCUMFLEX_BITS + if (keycode == CIRCUMFLEX_BITS) return DEADKEY_CIRCUMFLEX; + #endif + #ifdef DIAERESIS_BITS + if (keycode == DIAERESIS_BITS) return DEADKEY_DIAERESIS; + #endif + #ifdef GRAVE_ACCENT_BITS + if (keycode == GRAVE_ACCENT_BITS) return DEADKEY_GRAVE_ACCENT; + #endif + #ifdef TILDE_BITS + if (keycode == TILDE_BITS) return DEADKEY_TILDE; + #endif + #ifdef RING_ABOVE_BITS + if (keycode == RING_ABOVE_BITS) return DEADKEY_RING_ABOVE; + #endif + #endif // DEADKEYS_MASK + return 0; +} + +// Step #4: do each keystroke +// +void TeensyKeyboardAPI::write_key(KEYCODE_TYPE keycode) +{ + keyboard_report_data[0] = keycode_to_modifier(keycode); + keyboard_report_data[1] = 0; + keyboard_report_data[2] = keycode_to_key(keycode); + keyboard_report_data[3] = 0; + keyboard_report_data[4] = 0; + keyboard_report_data[5] = 0; + keyboard_report_data[6] = 0; + keyboard_report_data[7] = 0; + send_now(); + keyboard_report_data[0] = 0; + keyboard_report_data[2] = 0; + send_now(); +} + +uint8_t TeensyKeyboardAPI::keycode_to_modifier(KEYCODE_TYPE keycode) +{ + uint8_t modifier=0; + + #ifdef SHIFT_MASK + if (keycode & SHIFT_MASK) modifier |= MODIFIERKEY_SHIFT; + #endif + #ifdef ALTGR_MASK + if (keycode & ALTGR_MASK) modifier |= MODIFIERKEY_RIGHT_ALT; + #endif + #ifdef RCTRL_MASK + if (keycode & RCTRL_MASK) modifier |= MODIFIERKEY_RIGHT_CTRL; + #endif + return modifier; +} + +uint8_t TeensyKeyboardAPI::keycode_to_key(KEYCODE_TYPE keycode) +{ + uint8_t key = keycode & 0x3F; + #ifdef KEY_NON_US_100 + if (key == KEY_NON_US_100) key = 100; + #endif + return key; +} + + + +void TeensyKeyboardAPI::set_modifier(uint8_t c) +{ + keyboard_report_data[0] = c; +} +void TeensyKeyboardAPI::set_key1(uint8_t c) +{ + keyboard_report_data[2] = c; +} +void TeensyKeyboardAPI::set_key2(uint8_t c) +{ + keyboard_report_data[3] = c; +} +void TeensyKeyboardAPI::set_key3(uint8_t c) +{ + keyboard_report_data[4] = c; +} +void TeensyKeyboardAPI::set_key4(uint8_t c) +{ + keyboard_report_data[5] = c; +} +void TeensyKeyboardAPI::set_key5(uint8_t c) +{ + keyboard_report_data[6] = c; +} +void TeensyKeyboardAPI::set_key6(uint8_t c) +{ + keyboard_report_data[7] = c; +} +void TeensyKeyboardAPI::set_media(uint8_t c) +{ + keyboard_report_data[1] = c; +} + + +void TeensyKeyboardAPI::send_now(void) +{ + sendReport(keyboard_report_data, sizeof(keyboard_report_data)); +} + + +void TeensyKeyboardAPI::press(uint16_t n) +{ + uint8_t key, mod, msb, modrestore=0; + + msb = n >> 8; + if (msb >= 0xC2 && msb <= 0xDF) { + n = (n & 0x3F) | ((uint16_t)(msb & 0x1F) << 6); + } else + if (msb == 0x80) { + presskey(0, n); + return; + } else + if (msb == 0x40) { + presskey(n, 0); + return; + } + KEYCODE_TYPE keycode = unicode_to_keycode(n); + if (!keycode) return; + #ifdef DEADKEYS_MASK + KEYCODE_TYPE deadkeycode = deadkey_to_keycode(keycode); + if (deadkeycode) { + modrestore = keyboard_report_data[0]; + if (modrestore) { + keyboard_report_data[0] = 0; + send_now(); + } + // TODO: test if operating systems recognize + // deadkey sequences when other keys are held + mod = keycode_to_modifier(deadkeycode); + key = keycode_to_key(deadkeycode); + presskey(key, mod); + releasekey(key, mod); + } + #endif + mod = keycode_to_modifier(keycode); + key = keycode_to_key(keycode); + presskey(key, mod | modrestore); +} + +void TeensyKeyboardAPI::release(uint16_t n) +{ + uint8_t key, mod, msb; + + msb = n >> 8; + if (msb >= 0xC2 && msb <= 0xDF) { + n = (n & 0x3F) | ((uint16_t)(msb & 0x1F) << 6); + } else + if (msb == 0x80) { + releasekey(0, n); + return; + } else + if (msb == 0x40) { + releasekey(n, 0); + return; + } + KEYCODE_TYPE keycode = unicode_to_keycode(n); + if (!keycode) return; + mod = keycode_to_modifier(keycode); + key = keycode_to_key(keycode); + releasekey(key, mod); +} + +void TeensyKeyboardAPI::presskey(uint8_t key, uint8_t modifier) +{ + bool send_required = false; + uint8_t i; + + if (modifier) { + if ((keyboard_report_data[0] & modifier) != modifier) { + keyboard_report_data[0] |= modifier; + send_required = true; + } + } + if (key) { + for (i=2; i < 8; i++) { + if (keyboard_report_data[i] == key) goto end; + } + for (i=2; i < 8; i++) { + if (keyboard_report_data[i] == 0) { + keyboard_report_data[i] = key; + send_required = true; + goto end; + } + } + } + end: + if (send_required) send_now(); +} + +void TeensyKeyboardAPI::releasekey(uint8_t key, uint8_t modifier) +{ + bool send_required = false; + uint8_t i; + + if (modifier) { + if ((keyboard_report_data[0] & modifier) != 0) { + keyboard_report_data[0] &= ~modifier; + send_required = true; + } + } + if (key) { + for (i=2; i < 8; i++) { + if (keyboard_report_data[i] == key) { + keyboard_report_data[i] = 0; + send_required = true; + } + } + } + if (send_required) send_now(); +} + +void TeensyKeyboardAPI::releaseAll(void) +{ + uint8_t i, anybits; + + anybits = keyboard_report_data[0]; + for (i=2; i < 8; i++) { + anybits |= keyboard_report_data[i]; + keyboard_report_data[i] = 0; + } + if (!anybits) return; + keyboard_report_data[0] = 0; + send_now(); +} + +#include +#include + +#ifdef M +#undef M +#endif +#define M(n) ((n) & 0x3FFF) + +const KEYCODE_TYPE PROGMEM keycodes_ascii[] = { + M(ASCII_20), M(ASCII_21), M(ASCII_22), M(ASCII_23), + M(ASCII_24), M(ASCII_25), M(ASCII_26), M(ASCII_27), + M(ASCII_28), M(ASCII_29), M(ASCII_2A), M(ASCII_2B), + M(ASCII_2C), M(ASCII_2D), M(ASCII_2E), M(ASCII_2F), + M(ASCII_30), M(ASCII_31), M(ASCII_32), M(ASCII_33), + M(ASCII_34), M(ASCII_35), M(ASCII_36), M(ASCII_37), + M(ASCII_38), M(ASCII_39), M(ASCII_3A), M(ASCII_3B), + M(ASCII_3C), M(ASCII_3D), M(ASCII_3E), M(ASCII_3F), + M(ASCII_40), M(ASCII_41), M(ASCII_42), M(ASCII_43), + M(ASCII_44), M(ASCII_45), M(ASCII_46), M(ASCII_47), + M(ASCII_48), M(ASCII_49), M(ASCII_4A), M(ASCII_4B), + M(ASCII_4C), M(ASCII_4D), M(ASCII_4E), M(ASCII_4F), + M(ASCII_50), M(ASCII_51), M(ASCII_52), M(ASCII_53), + M(ASCII_54), M(ASCII_55), M(ASCII_56), M(ASCII_57), + M(ASCII_58), M(ASCII_59), M(ASCII_5A), M(ASCII_5B), + M(ASCII_5C), M(ASCII_5D), M(ASCII_5E), M(ASCII_5F), + M(ASCII_60), M(ASCII_61), M(ASCII_62), M(ASCII_63), + M(ASCII_64), M(ASCII_65), M(ASCII_66), M(ASCII_67), + M(ASCII_68), M(ASCII_69), M(ASCII_6A), M(ASCII_6B), + M(ASCII_6C), M(ASCII_6D), M(ASCII_6E), M(ASCII_6F), + M(ASCII_70), M(ASCII_71), M(ASCII_72), M(ASCII_73), + M(ASCII_74), M(ASCII_75), M(ASCII_76), M(ASCII_77), + M(ASCII_78), M(ASCII_79), M(ASCII_7A), M(ASCII_7B), + M(ASCII_7C), M(ASCII_7D), M(ASCII_7E), M(ASCII_7F) +}; + +#ifdef ISO_8859_1_A0 +const KEYCODE_TYPE PROGMEM keycodes_iso_8859_1[] = { + M(ISO_8859_1_A0), M(ISO_8859_1_A1), M(ISO_8859_1_A2), M(ISO_8859_1_A3), + M(ISO_8859_1_A4), M(ISO_8859_1_A5), M(ISO_8859_1_A6), M(ISO_8859_1_A7), + M(ISO_8859_1_A8), M(ISO_8859_1_A9), M(ISO_8859_1_AA), M(ISO_8859_1_AB), + M(ISO_8859_1_AC), M(ISO_8859_1_AD), M(ISO_8859_1_AE), M(ISO_8859_1_AF), + M(ISO_8859_1_B0), M(ISO_8859_1_B1), M(ISO_8859_1_B2), M(ISO_8859_1_B3), + M(ISO_8859_1_B4), M(ISO_8859_1_B5), M(ISO_8859_1_B6), M(ISO_8859_1_B7), + M(ISO_8859_1_B8), M(ISO_8859_1_B9), M(ISO_8859_1_BA), M(ISO_8859_1_BB), + M(ISO_8859_1_BC), M(ISO_8859_1_BD), M(ISO_8859_1_BE), M(ISO_8859_1_BF), + M(ISO_8859_1_C0), M(ISO_8859_1_C1), M(ISO_8859_1_C2), M(ISO_8859_1_C3), + M(ISO_8859_1_C4), M(ISO_8859_1_C5), M(ISO_8859_1_C6), M(ISO_8859_1_C7), + M(ISO_8859_1_C8), M(ISO_8859_1_C9), M(ISO_8859_1_CA), M(ISO_8859_1_CB), + M(ISO_8859_1_CC), M(ISO_8859_1_CD), M(ISO_8859_1_CE), M(ISO_8859_1_CF), + M(ISO_8859_1_D0), M(ISO_8859_1_D1), M(ISO_8859_1_D2), M(ISO_8859_1_D3), + M(ISO_8859_1_D4), M(ISO_8859_1_D5), M(ISO_8859_1_D6), M(ISO_8859_1_D7), + M(ISO_8859_1_D8), M(ISO_8859_1_D9), M(ISO_8859_1_DA), M(ISO_8859_1_DB), + M(ISO_8859_1_DC), M(ISO_8859_1_DD), M(ISO_8859_1_DE), M(ISO_8859_1_DF), + M(ISO_8859_1_E0), M(ISO_8859_1_E1), M(ISO_8859_1_E2), M(ISO_8859_1_E3), + M(ISO_8859_1_E4), M(ISO_8859_1_E5), M(ISO_8859_1_E6), M(ISO_8859_1_E7), + M(ISO_8859_1_E8), M(ISO_8859_1_E9), M(ISO_8859_1_EA), M(ISO_8859_1_EB), + M(ISO_8859_1_EC), M(ISO_8859_1_ED), M(ISO_8859_1_EE), M(ISO_8859_1_EF), + M(ISO_8859_1_F0), M(ISO_8859_1_F1), M(ISO_8859_1_F2), M(ISO_8859_1_F3), + M(ISO_8859_1_F4), M(ISO_8859_1_F5), M(ISO_8859_1_F6), M(ISO_8859_1_F7), + M(ISO_8859_1_F8), M(ISO_8859_1_F9), M(ISO_8859_1_FA), M(ISO_8859_1_FB), + M(ISO_8859_1_FC), M(ISO_8859_1_FD), M(ISO_8859_1_FE), M(ISO_8859_1_FF) +}; +#endif // ISO_8859_1_A0 diff --git a/plugins/KeyboardioHID/src/HID-APIs/TeensyKeyboardAPI.h b/plugins/KeyboardioHID/src/HID-APIs/TeensyKeyboardAPI.h new file mode 100644 index 0000000000..2aa4f9c235 --- /dev/null +++ b/plugins/KeyboardioHID/src/HID-APIs/TeensyKeyboardAPI.h @@ -0,0 +1,162 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 guard +#pragma once + +#include +#include "HID-Settings.h" +#include "TeensyKeylayouts.h" + +#define HID_REPORT_KEYBOARD_START \ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 47 */ \ + 0x09, 0x06, /* USAGE (Keyboard) */ \ + 0xa1, 0x01 /* COLLECTION (Application) */ + +#define HID_REPORT_KEYBOARD_REPORTID \ + 0x85, HID_REPORTID_KEYBOARD /* REPORT_ID TODO order important?*/ + +#define HID_REPORT_KEYBOARD_START2 \ + 0x05, 0x07 /* USAGE_PAGE (Keyboard) */ + +#define HID_REPORT_KEYBOARD_MODIFIERS \ + /* Keyboard Modifiers (shift, alt, ...) */ \ + 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) */ + +#define HID_REPORT_KEYBOARD_RESERVED \ + /* Reserved byte TODO consumer and or system?*/ \ + 0x95, 0x01, /* REPORT_COUNT (1) */ \ + 0x75, 0x08, /* REPORT_SIZE (8) */ \ + 0x81, 0x03 /* INPUT (Cnst,Var,Abs) */ \ + +#define HID_REPORT_KEYBOARD_KEYS \ + /* 6 Keyboard keys */ \ + 0x95, 0x06, /* REPORT_COUNT (6) */ \ + 0x75, 0x08, /* REPORT_SIZE (8) */ \ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \ + 0x26, 0xE7, 0x00, /* LOGICAL_MAXIMUM (231) */ \ + 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ \ + 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ \ + 0x29, 0xE7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ \ + 0x81, 0x00 /* INPUT (Data,Ary,Abs) */ + +#define HID_REPORT_KEYBOARD_LEDS \ + /* 5 LEDs for num lock etc */ \ + 0x05, 0x08, /* USAGE_PAGE (LEDs) */ \ + 0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */ \ + 0x29, 0x05, /* USAGE_MAXIMUM (Kana) TODO */ \ + 0x95, 0x05, /* REPORT_COUNT (5) */ \ + 0x75, 0x01, /* REPORT_SIZE (1) */ \ + 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */ \ + /* Reserved 3 bits TODO */ \ + 0x95, 0x01, /* REPORT_COUNT (1) */ \ + 0x75, 0x03, /* REPORT_SIZE (3) */ \ + 0x91, 0x03 /* OUTPUT (Cnst,Var,Abs) */ + +#define HID_REPORT_KEYBOARD_END \ + /* End */ \ + 0xc0 /* END_COLLECTION */ + +#define HID_REPORT_KEYBOARD \ +HID_REPORT_KEYBOARD_START, \ +HID_REPORT_KEYBOARD_START2, \ +HID_REPORT_KEYBOARD_MODIFIERS, \ +HID_REPORT_KEYBOARD_RESERVED, \ +HID_REPORT_KEYBOARD_KEYS, \ +HID_REPORT_KEYBOARD_LEDS, \ +HID_REPORT_KEYBOARD_END + +#define HID_MULTIREPORT_KEYBOARD \ +HID_REPORT_KEYBOARD_START, \ +HID_REPORT_KEYBOARD_REPORTID, \ +HID_REPORT_KEYBOARD_START2, \ +HID_REPORT_KEYBOARD_MODIFIERS, \ +HID_REPORT_KEYBOARD_RESERVED, \ +HID_REPORT_KEYBOARD_KEYS, \ +HID_REPORT_KEYBOARD_END + +#define HID_REPORT_KEYBOARD_SIZE sizeof ((uint8_t[]) {HID_REPORT_KEYBOARD}) +#define HID_MULTIREPORT_KEYBOARD_SIZE sizeof ((uint8_t[]) {HID_MULTIREPORT_KEYBOARD}) + +extern const uint8_t _hidReportDescriptorKeyboard[HID_REPORT_KEYBOARD_SIZE] PROGMEM; +extern const uint8_t _hidMultiReportDescriptorKeyboard[HID_MULTIREPORT_KEYBOARD_SIZE] PROGMEM; + + +typedef union{ + // Low level key report: up to 6 keys and shift, ctrl etc at once + uint8_t whole8[]; + uint16_t whole16[]; + uint32_t whole32[]; + struct{ + uint8_t modifiers; + uint8_t reserved; + uint8_t keys[6]; + }; +} HID_KeyboardReport_Data_t; + +class TeensyKeyboardAPI : public Print +{ + public: + TeensyKeyboardAPI(void) { } + + void begin(void) { } + void end(void) { } + virtual size_t write(uint8_t); + using Print::write; + inline void write_unicode(uint16_t unicode) { write_keycode(unicode_to_keycode(unicode)); } + void set_modifier(uint8_t); + void set_key1(uint8_t); + void set_key2(uint8_t); + void set_key3(uint8_t); + void set_key4(uint8_t); + void set_key5(uint8_t); + void set_key6(uint8_t); + void set_media(uint8_t); + void send_now(void); + void press(uint16_t n); + void release(uint16_t n); + void releaseAll(void); + + // Sending is public in the base class for advanced users. + virtual void sendReport(void* data, int length) = 0; + +private: + KEYCODE_TYPE unicode_to_keycode(uint16_t unicode); + KEYCODE_TYPE deadkey_to_keycode(KEYCODE_TYPE keycode); + uint8_t keycode_to_modifier(KEYCODE_TYPE keycode); + uint8_t keycode_to_key(KEYCODE_TYPE keycode); + void presskey(uint8_t key, uint8_t modifier); + void releasekey(uint8_t key, uint8_t modifier); + void write_keycode(KEYCODE_TYPE key); + void write_key(KEYCODE_TYPE code); + uint8_t utf8_state; + uint16_t unicode_wchar; + uint8_t keyboard_report_data[8]; +}; + diff --git a/plugins/KeyboardioHID/src/HID-APIs/TeensyKeylayouts.h b/plugins/KeyboardioHID/src/HID-APIs/TeensyKeylayouts.h new file mode 100644 index 0000000000..f91749a923 --- /dev/null +++ b/plugins/KeyboardioHID/src/HID-APIs/TeensyKeylayouts.h @@ -0,0 +1,5420 @@ +/* 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. + */ + + +#ifndef KEYLAYOUTS_H__ +#define KEYLAYOUTS_H__ + +#include +#include + +#ifdef __cplusplus +extern "C"{ +#endif + +//#define LAYOUT_US_ENGLISH +//#define LAYOUT_CANADIAN_FRENCH +//#define LAYOUT_CANADIAN_MULTILINGUAL +//#define LAYOUT_DANISH +//#define LAYOUT_FINNISH +//#define LAYOUT_FRENCH +//#define LAYOUT_FRENCH_BELGIAN +//#define LAYOUT_FRENCH_SWISS +//#define LAYOUT_GERMAN +//#define LAYOUT_GERMAN_MAC +//#define LAYOUT_GERMAN_SWISS +//#define LAYOUT_ICELANDIC +//#define LAYOUT_IRISH +//#define LAYOUT_ITALIAN +//#define LAYOUT_NORWEGIAN +//#define LAYOUT_PORTUGUESE +//#define LAYOUT_PORTUGUESE_BRAZILIAN +//#define LAYOUT_SPANISH +//#define LAYOUT_SPANISH_LATIN_AMERICA +//#define LAYOUT_SWEDISH +//#define LAYOUT_TURKISH +//#define LAYOUT_UNITED_KINGDOM +//#define LAYOUT_US_INTERNATIONAL + +// http://en.wikipedia.org/wiki/Keyboard_layout + + +#define MODIFIERKEY_CTRL ( 0x01 | 0x8000 ) +#define MODIFIERKEY_SHIFT ( 0x02 | 0x8000 ) +#define MODIFIERKEY_ALT ( 0x04 | 0x8000 ) +#define MODIFIERKEY_GUI ( 0x08 | 0x8000 ) +#define MODIFIERKEY_LEFT_CTRL ( 0x01 | 0x8000 ) +#define MODIFIERKEY_LEFT_SHIFT ( 0x02 | 0x8000 ) +#define MODIFIERKEY_LEFT_ALT ( 0x04 | 0x8000 ) +#define MODIFIERKEY_LEFT_GUI ( 0x08 | 0x8000 ) +#define MODIFIERKEY_RIGHT_CTRL ( 0x10 | 0x8000 ) +#define MODIFIERKEY_RIGHT_SHIFT ( 0x20 | 0x8000 ) +#define MODIFIERKEY_RIGHT_ALT ( 0x40 | 0x8000 ) +#define MODIFIERKEY_RIGHT_GUI ( 0x80 | 0x8000 ) + +#define KEY_MEDIA_VOLUME_INC 0x01 +#define KEY_MEDIA_VOLUME_DEC 0x02 +#define KEY_MEDIA_MUTE 0x04 +#define KEY_MEDIA_PLAY_PAUSE 0x08 +#define KEY_MEDIA_NEXT_TRACK 0x10 +#define KEY_MEDIA_PREV_TRACK 0x20 +#define KEY_MEDIA_STOP 0x40 +#define KEY_MEDIA_EJECT 0x80 + +#define KEY_A ( 4 | 0x4000 ) +#define KEY_B ( 5 | 0x4000 ) +#define KEY_C ( 6 | 0x4000 ) +#define KEY_D ( 7 | 0x4000 ) +#define KEY_E ( 8 | 0x4000 ) +#define KEY_F ( 9 | 0x4000 ) +#define KEY_G ( 10 | 0x4000 ) +#define KEY_H ( 11 | 0x4000 ) +#define KEY_I ( 12 | 0x4000 ) +#define KEY_J ( 13 | 0x4000 ) +#define KEY_K ( 14 | 0x4000 ) +#define KEY_L ( 15 | 0x4000 ) +#define KEY_M ( 16 | 0x4000 ) +#define KEY_N ( 17 | 0x4000 ) +#define KEY_O ( 18 | 0x4000 ) +#define KEY_P ( 19 | 0x4000 ) +#define KEY_Q ( 20 | 0x4000 ) +#define KEY_R ( 21 | 0x4000 ) +#define KEY_S ( 22 | 0x4000 ) +#define KEY_T ( 23 | 0x4000 ) +#define KEY_U ( 24 | 0x4000 ) +#define KEY_V ( 25 | 0x4000 ) +#define KEY_W ( 26 | 0x4000 ) +#define KEY_X ( 27 | 0x4000 ) +#define KEY_Y ( 28 | 0x4000 ) +#define KEY_Z ( 29 | 0x4000 ) +#define KEY_1 ( 30 | 0x4000 ) +#define KEY_2 ( 31 | 0x4000 ) +#define KEY_3 ( 32 | 0x4000 ) +#define KEY_4 ( 33 | 0x4000 ) +#define KEY_5 ( 34 | 0x4000 ) +#define KEY_6 ( 35 | 0x4000 ) +#define KEY_7 ( 36 | 0x4000 ) +#define KEY_8 ( 37 | 0x4000 ) +#define KEY_9 ( 38 | 0x4000 ) +#define KEY_0 ( 39 | 0x4000 ) +#define KEY_ENTER ( 40 | 0x4000 ) +#define KEY_ESC ( 41 | 0x4000 ) +#define KEY_BACKSPACE ( 42 | 0x4000 ) +#define KEY_TAB ( 43 | 0x4000 ) +#define KEY_SPACE ( 44 | 0x4000 ) +#define KEY_MINUS ( 45 | 0x4000 ) +#define KEY_EQUAL ( 46 | 0x4000 ) +#define KEY_LEFT_BRACE ( 47 | 0x4000 ) +#define KEY_RIGHT_BRACE ( 48 | 0x4000 ) +#define KEY_BACKSLASH ( 49 | 0x4000 ) +#define KEY_NON_US_NUM ( 50 | 0x4000 ) +#define KEY_SEMICOLON ( 51 | 0x4000 ) +#define KEY_QUOTE ( 52 | 0x4000 ) +#define KEY_TILDE ( 53 | 0x4000 ) +#define KEY_COMMA ( 54 | 0x4000 ) +#define KEY_PERIOD ( 55 | 0x4000 ) +#define KEY_SLASH ( 56 | 0x4000 ) +#define KEY_CAPS_LOCK ( 57 | 0x4000 ) +#define KEY_F1 ( 58 | 0x4000 ) +#define KEY_F2 ( 59 | 0x4000 ) +#define KEY_F3 ( 60 | 0x4000 ) +#define KEY_F4 ( 61 | 0x4000 ) +#define KEY_F5 ( 62 | 0x4000 ) +#define KEY_F6 ( 63 | 0x4000 ) +#define KEY_F7 ( 64 | 0x4000 ) +#define KEY_F8 ( 65 | 0x4000 ) +#define KEY_F9 ( 66 | 0x4000 ) +#define KEY_F10 ( 67 | 0x4000 ) +#define KEY_F11 ( 68 | 0x4000 ) +#define KEY_F12 ( 69 | 0x4000 ) +#define KEY_PRINTSCREEN ( 70 | 0x4000 ) +#define KEY_SCROLL_LOCK ( 71 | 0x4000 ) +#define KEY_PAUSE ( 72 | 0x4000 ) +#define KEY_INSERT ( 73 | 0x4000 ) +#define KEY_HOME ( 74 | 0x4000 ) +#define KEY_PAGE_UP ( 75 | 0x4000 ) +#define KEY_DELETE ( 76 | 0x4000 ) +#define KEY_END ( 77 | 0x4000 ) +#define KEY_PAGE_DOWN ( 78 | 0x4000 ) +#define KEY_RIGHT ( 79 | 0x4000 ) +#define KEY_LEFT ( 80 | 0x4000 ) +#define KEY_DOWN ( 81 | 0x4000 ) +#define KEY_UP ( 82 | 0x4000 ) +#define KEY_NUM_LOCK ( 83 | 0x4000 ) +#define KEYPAD_SLASH ( 84 | 0x4000 ) +#define KEYPAD_ASTERIX ( 85 | 0x4000 ) +#define KEYPAD_MINUS ( 86 | 0x4000 ) +#define KEYPAD_PLUS ( 87 | 0x4000 ) +#define KEYPAD_ENTER ( 88 | 0x4000 ) +#define KEYPAD_1 ( 89 | 0x4000 ) +#define KEYPAD_2 ( 90 | 0x4000 ) +#define KEYPAD_3 ( 91 | 0x4000 ) +#define KEYPAD_4 ( 92 | 0x4000 ) +#define KEYPAD_5 ( 93 | 0x4000 ) +#define KEYPAD_6 ( 94 | 0x4000 ) +#define KEYPAD_7 ( 95 | 0x4000 ) +#define KEYPAD_8 ( 96 | 0x4000 ) +#define KEYPAD_9 ( 97 | 0x4000 ) +#define KEYPAD_0 ( 98 | 0x4000 ) +#define KEYPAD_PERIOD ( 99 | 0x4000 ) +#define KEY_MENU ( 101 | 0x4000 ) +#define KEY_F13 ( 104 | 0x4000 ) +#define KEY_F14 ( 105 | 0x4000 ) +#define KEY_F15 ( 106 | 0x4000 ) +#define KEY_F16 ( 107 | 0x4000 ) +#define KEY_F17 ( 108 | 0x4000 ) +#define KEY_F18 ( 109 | 0x4000 ) +#define KEY_F19 ( 110 | 0x4000 ) +#define KEY_F20 ( 111 | 0x4000 ) +#define KEY_F21 ( 112 | 0x4000 ) +#define KEY_F22 ( 113 | 0x4000 ) +#define KEY_F23 ( 114 | 0x4000 ) +#define KEY_F24 ( 115 | 0x4000 ) + + +// for compatibility with Leonardo's slightly different names +#define KEY_UP_ARROW KEY_UP +#define KEY_DOWN_ARROW KEY_DOWN +#define KEY_LEFT_ARROW KEY_LEFT +#define KEY_RIGHT_ARROW KEY_RIGHT +#define KEY_RETURN KEY_ENTER +#define KEY_LEFT_CTRL MODIFIERKEY_LEFT_CTRL +#define KEY_LEFT_SHIFT MODIFIERKEY_LEFT_SHIFT +#define KEY_LEFT_ALT MODIFIERKEY_LEFT_ALT +#define KEY_LEFT_GUI MODIFIERKEY_LEFT_GUI +#define KEY_RIGHT_CTRL MODIFIERKEY_RIGHT_CTRL +#define KEY_RIGHT_SHIFT MODIFIERKEY_RIGHT_SHIFT +#define KEY_RIGHT_ALT MODIFIERKEY_RIGHT_ALT +#define KEY_RIGHT_GUI MODIFIERKEY_RIGHT_GUI + + +// Everything below this line is not intended for use in "normal" programs. +// These private symbols populate lookup tables, which are used to translate +// ascii and UTF8 unicode into keystroke sequences. + + +#ifdef LAYOUT_US_ENGLISH + +#define SHIFT_MASK 0x40 +#define KEYCODE_TYPE uint8_t + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! +#define ASCII_22 KEY_QUOTE + SHIFT_MASK // 34 " +#define ASCII_23 KEY_3 + SHIFT_MASK // 35 # +#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ +#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % +#define ASCII_26 KEY_7 + SHIFT_MASK // 38 & +#define ASCII_27 KEY_QUOTE // 39 ' +#define ASCII_28 KEY_9 + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_0 + SHIFT_MASK // 41 ) +#define ASCII_2A KEY_8 + SHIFT_MASK // 42 * +#define ASCII_2B KEY_EQUAL + SHIFT_MASK // 43 + +#define ASCII_2C KEY_COMMA // 44 , +#define ASCII_2D KEY_MINUS // 45 - +#define ASCII_2E KEY_PERIOD // 46 . +#define ASCII_2F KEY_SLASH // 47 / +#define ASCII_30 KEY_0 // 48 0 +#define ASCII_31 KEY_1 // 49 1 +#define ASCII_32 KEY_2 // 50 2 +#define ASCII_33 KEY_3 // 51 3 +#define ASCII_34 KEY_4 // 52 4 +#define ASCII_35 KEY_5 // 53 5 +#define ASCII_36 KEY_6 // 54 6 +#define ASCII_37 KEY_7 // 55 7 +#define ASCII_38 KEY_8 // 55 8 +#define ASCII_39 KEY_9 // 57 9 +#define ASCII_3A KEY_SEMICOLON + SHIFT_MASK // 58 : +#define ASCII_3B KEY_SEMICOLON // 59 ; +#define ASCII_3C KEY_COMMA + SHIFT_MASK // 60 < +#define ASCII_3D KEY_EQUAL // 61 = +#define ASCII_3E KEY_PERIOD + SHIFT_MASK // 62 > +#define ASCII_3F KEY_SLASH + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_2 + SHIFT_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_LEFT_BRACE // 91 [ +#define ASCII_5C KEY_BACKSLASH // 92 +#define ASCII_5D KEY_RIGHT_BRACE // 93 ] +#define ASCII_5E KEY_6 + SHIFT_MASK // 94 ^ +#define ASCII_5F KEY_MINUS + SHIFT_MASK // 95 _ +#define ASCII_60 KEY_TILDE // 96 ` +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Y // 121 y +#define ASCII_7A KEY_Z // 122 z +#define ASCII_7B KEY_LEFT_BRACE + SHIFT_MASK // 123 { +#define ASCII_7C KEY_BACKSLASH + SHIFT_MASK // 124 | +#define ASCII_7D KEY_RIGHT_BRACE + SHIFT_MASK // 125 } +#define ASCII_7E KEY_TILDE + SHIFT_MASK // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 + +#endif // LAYOUT_US_ENGLISH + + + + +#ifdef LAYOUT_US_INTERNATIONAL + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define DEADKEYS_MASK 0x0700 +#define CIRCUMFLEX_BITS 0x0100 +#define ACUTE_ACCENT_BITS 0x0200 +#define GRAVE_ACCENT_BITS 0x0300 +#define TILDE_BITS 0x0400 +#define DIAERESIS_BITS 0x0500 +#define KEYCODE_TYPE uint16_t +#define DEADKEY_CIRCUMFLEX KEY_6 + SHIFT_MASK +#define DEADKEY_ACUTE_ACCENT KEY_QUOTE +#define DEADKEY_GRAVE_ACCENT KEY_TILDE +#define DEADKEY_TILDE KEY_TILDE + SHIFT_MASK +#define DEADKEY_DIAERESIS KEY_QUOTE + SHIFT_MASK + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! +#define ASCII_22 DIAERESIS_BITS + KEY_SPACE // 34 " +#define ASCII_23 KEY_3 + SHIFT_MASK // 35 # +#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ +#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % +#define ASCII_26 KEY_7 + SHIFT_MASK // 38 & +#define ASCII_27 ACUTE_ACCENT_BITS + KEY_SPACE // 39 ' +#define ASCII_28 KEY_9 + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_0 + SHIFT_MASK // 41 ) +#define ASCII_2A KEY_8 + SHIFT_MASK // 42 * +#define ASCII_2B KEY_EQUAL + SHIFT_MASK // 43 + +#define ASCII_2C KEY_COMMA // 44 , +#define ASCII_2D KEY_MINUS // 45 - +#define ASCII_2E KEY_PERIOD // 46 . +#define ASCII_2F KEY_SLASH // 47 / +#define ASCII_30 KEY_0 // 48 0 +#define ASCII_31 KEY_1 // 49 1 +#define ASCII_32 KEY_2 // 50 2 +#define ASCII_33 KEY_3 // 51 3 +#define ASCII_34 KEY_4 // 52 4 +#define ASCII_35 KEY_5 // 53 5 +#define ASCII_36 KEY_6 // 54 6 +#define ASCII_37 KEY_7 // 55 7 +#define ASCII_38 KEY_8 // 55 8 +#define ASCII_39 KEY_9 // 57 9 +#define ASCII_3A KEY_SEMICOLON + SHIFT_MASK // 58 : +#define ASCII_3B KEY_SEMICOLON // 59 ; +#define ASCII_3C KEY_COMMA + SHIFT_MASK // 60 < +#define ASCII_3D KEY_EQUAL // 61 = +#define ASCII_3E KEY_PERIOD + SHIFT_MASK // 62 > +#define ASCII_3F KEY_SLASH + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_2 + SHIFT_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_LEFT_BRACE // 91 [ +#define ASCII_5C KEY_BACKSLASH // 92 +#define ASCII_5D KEY_RIGHT_BRACE // 93 ] +#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ +#define ASCII_5F KEY_MINUS + SHIFT_MASK // 95 _ +#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Y // 121 y +#define ASCII_7A KEY_Z // 122 z +#define ASCII_7B KEY_LEFT_BRACE + SHIFT_MASK // 123 { +#define ASCII_7C KEY_BACKSLASH + SHIFT_MASK // 124 | +#define ASCII_7D KEY_RIGHT_BRACE + SHIFT_MASK // 125 } +#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 +#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space +#define ISO_8859_1_A1 KEY_1 + ALTGR_MASK // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 KEY_C + ALTGR_MASK + SHIFT_MASK // 162 ¢ Cent SIGN +#define ISO_8859_1_A3 KEY_4 + ALTGR_MASK + SHIFT_MASK // 163 £ Pound Sign +#define ISO_8859_1_A4 KEY_4 + ALTGR_MASK // 164 ¤ Currency or Euro Sign +#define ISO_8859_1_A5 KEY_MINUS + ALTGR_MASK // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 KEY_BACKSLASH + ALTGR_MASK + SHIFT_MASK // 166 ¦ BROKEN BAR ?? +#define ISO_8859_1_A7 KEY_S + ALTGR_MASK + SHIFT_MASK // 167 § SECTION SIGN +#define ISO_8859_1_A8 KEY_QUOTE + ALTGR_MASK + SHIFT_MASK // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 KEY_C + ALTGR_MASK // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB KEY_LEFT_BRACE + ALTGR_MASK // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC KEY_BACKSLASH + ALTGR_MASK // 172 ¬ NOT SIGN ?? +#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN +#define ISO_8859_1_AE KEY_R + ALTGR_MASK // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF 0 // 175 ¯ MACRON +#define ISO_8859_1_B0 KEY_SEMICOLON + ALTGR_MASK + SHIFT_MASK // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 KEY_2 + ALTGR_MASK // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 KEY_3 + ALTGR_MASK // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 KEY_QUOTE + ALTGR_MASK // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 KEY_M + ALTGR_MASK // 181 µ MICRO SIGN +#define ISO_8859_1_B6 KEY_SEMICOLON + ALTGR_MASK // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT +#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA +#define ISO_8859_1_B9 KEY_1 + ALTGR_MASK + SHIFT_MASK // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB KEY_RIGHT_BRACE + ALTGR_MASK // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC KEY_6 + ALTGR_MASK // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD KEY_7 + ALTGR_MASK // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE KEY_8 + ALTGR_MASK // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF KEY_SLASH + ALTGR_MASK // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE +#define ISO_8859_1_C1 KEY_A + ALTGR_MASK + SHIFT_MASK // 193 Á A ACUTE +#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE +#define ISO_8859_1_C4 KEY_Q + ALTGR_MASK + SHIFT_MASK // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 KEY_W + ALTGR_MASK + SHIFT_MASK // 197 Å A RING ABOVE +#define ISO_8859_1_C6 KEY_Z + ALTGR_MASK + SHIFT_MASK // 198 Æ AE +#define ISO_8859_1_C7 KEY_COMMA + ALTGR_MASK + SHIFT_MASK // 199 Ç C CEDILLA +#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE +#define ISO_8859_1_C9 KEY_E + ALTGR_MASK + SHIFT_MASK // 201 É E ACUTE +#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS +#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE +#define ISO_8859_1_CD KEY_I + ALTGR_MASK + SHIFT_MASK // 205 Í I ACUTE +#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 KEY_D + ALTGR_MASK + SHIFT_MASK // 208 Ð ETH +#define ISO_8859_1_D1 KEY_N + ALTGR_MASK + SHIFT_MASK // 209 Ñ N TILDE +#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE +#define ISO_8859_1_D3 KEY_O + ALTGR_MASK + SHIFT_MASK // 211 Ó O ACUTE +#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE +#define ISO_8859_1_D6 KEY_P + ALTGR_MASK + SHIFT_MASK // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 KEY_EQUAL + ALTGR_MASK // 215 × MULTIPLICATION +#define ISO_8859_1_D8 KEY_L + ALTGR_MASK + SHIFT_MASK // 216 Ø O STROKE +#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE +#define ISO_8859_1_DA KEY_U + ALTGR_MASK + SHIFT_MASK // 218 Ú U ACUTE +#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC KEY_Y + ALTGR_MASK + SHIFT_MASK // 220 Ü U DIAERESIS +#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE +#define ISO_8859_1_DE KEY_T + ALTGR_MASK + SHIFT_MASK // 222 Þ THORN +#define ISO_8859_1_DF KEY_S + ALTGR_MASK // 223 ß SHARP S +#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE +#define ISO_8859_1_E1 KEY_A + ALTGR_MASK // 225 á a ACUTE +#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE +#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS +#define ISO_8859_1_E5 KEY_W + ALTGR_MASK // 229 å a RING ABOVE +#define ISO_8859_1_E6 KEY_Z + ALTGR_MASK // 230 æ ae +#define ISO_8859_1_E7 KEY_COMMA + ALTGR_MASK // 231 ç c CEDILLA +#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE +#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE +#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS +#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE +#define ISO_8859_1_ED KEY_I + ALTGR_MASK // 237 í i ACUTE +#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS +#define ISO_8859_1_F0 KEY_D + ALTGR_MASK // 240 ð ETH +#define ISO_8859_1_F1 KEY_N + ALTGR_MASK // 241 ñ n TILDE +#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE +#define ISO_8859_1_F3 KEY_O + ALTGR_MASK // 243 ó o ACUTE +#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE +#define ISO_8859_1_F6 KEY_P + ALTGR_MASK // 246 ö o DIAERESIS +#define ISO_8859_1_F7 KEY_EQUAL + ALTGR_MASK + SHIFT_MASK // 247 ÷ DIVISION +#define ISO_8859_1_F8 KEY_L + ALTGR_MASK // 248 ø o STROKE +#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE +#define ISO_8859_1_FA KEY_U + ALTGR_MASK // 250 ú u ACUTE +#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC KEY_Y + ALTGR_MASK // 252 ü u DIAERESIS +#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE +#define ISO_8859_1_FE KEY_T + ALTGR_MASK // 254 þ THORN +#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS +#define UNICODE_20AC KEY_5 + ALTGR_MASK // € Euro Sign +// not yet implemented +#define UNICODE_EXTRA00 0x20AC +#define KEYCODE_EXTRA00 KEY_5 + ALTGR_MASK // 20AC € Euro Sign + +#endif // LAYOUT_US_INTERNATIONAL + + + +#ifdef LAYOUT_GERMAN + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define DEADKEYS_MASK 0x0700 +#define SHIFT_MASK 0x0100 +#define ALTGR_MASK 0x0200 +#define CIRCUMFLEX_BITS 0x0300 +#define ACUTE_ACCENT_BITS 0x0400 +#define GRAVE_ACCENT_BITS 0x0500 +#define KEYCODE_TYPE uint16_t +#define DEADKEY_CIRCUMFLEX KEY_TILDE +//#define DEADKEY_CIRCUMFLEX KEY_NON_US_100 +#define DEADKEY_ACUTE_ACCENT KEY_EQUAL +#define DEADKEY_GRAVE_ACCENT KEY_EQUAL + SHIFT_MASK +#define KEY_NON_US_100 63 + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! +#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " +#define ASCII_23 KEY_BACKSLASH // 35 # ?? +#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ +#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % +#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & +#define ASCII_27 KEY_BACKSLASH + SHIFT_MASK // 39 ' +#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) +#define ASCII_2A KEY_RIGHT_BRACE + SHIFT_MASK // 42 * +#define ASCII_2B KEY_RIGHT_BRACE // 43 + +#define ASCII_2C KEY_COMMA // 44 , +#define ASCII_2D KEY_SLASH // 45 - +#define ASCII_2E KEY_PERIOD // 46 . +#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / +#define ASCII_30 KEY_0 // 48 0 +#define ASCII_31 KEY_1 // 49 1 +#define ASCII_32 KEY_2 // 50 2 +#define ASCII_33 KEY_3 // 51 3 +#define ASCII_34 KEY_4 // 52 4 +#define ASCII_35 KEY_5 // 53 5 +#define ASCII_36 KEY_6 // 54 6 +#define ASCII_37 KEY_7 // 55 7 +#define ASCII_38 KEY_8 // 55 8 +#define ASCII_39 KEY_9 // 57 9 +#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : +#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; +#define ASCII_3C KEY_NON_US_100 // 60 < +#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = +#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > +#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_Q + ALTGR_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Z + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Y + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_8 + ALTGR_MASK // 91 [ +#define ASCII_5C KEY_MINUS + ALTGR_MASK // 92 +#define ASCII_5D KEY_9 + ALTGR_MASK // 93 ] +#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ +#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ +#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Z // 121 y +#define ASCII_7A KEY_Y // 122 z +#define ASCII_7B KEY_7 + ALTGR_MASK // 123 { +#define ASCII_7C KEY_NON_US_100 + ALTGR_MASK // 124 | +#define ASCII_7D KEY_0 + ALTGR_MASK // 125 } +#define ASCII_7E KEY_RIGHT_BRACE + ALTGR_MASK // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 +#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space +#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 0 // 162 ¢ Cent Sign +#define ISO_8859_1_A3 0 // 163 £ Pound Sign +#define ISO_8859_1_A4 KEY_E + ALTGR_MASK // 164 ¤ Currency Sign +#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR +#define ISO_8859_1_A7 KEY_3 + SHIFT_MASK // 167 § SECTION SIGN +#define ISO_8859_1_A8 0 // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN +#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN +#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF 0 // 175 ¯ MACRON +#define ISO_8859_1_B0 KEY_TILDE + SHIFT_MASK // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 KEY_2 + ALTGR_MASK // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 KEY_3 + ALTGR_MASK // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 0 // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 KEY_M + ALTGR_MASK // 181 µ MICRO SIGN +#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT +#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA +#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE +#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE +#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 0 // 195 Ã A TILDE +#define ISO_8859_1_C4 KEY_QUOTE + SHIFT_MASK // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE +#define ISO_8859_1_C6 0 // 198 Æ AE +#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA +#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE +#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE +#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB 0 // 203 Ë E DIAERESIS +#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE +#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE +#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF 0 // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 0 // 208 Ð ETH +#define ISO_8859_1_D1 0 // 209 Ñ N TILDE +#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE +#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE +#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 0 // 213 Õ O TILDE +#define ISO_8859_1_D6 KEY_SEMICOLON + SHIFT_MASK // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION +#define ISO_8859_1_D8 0 // 216 Ø O STROKE +#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE +#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE +#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC KEY_LEFT_BRACE + SHIFT_MASK // 220 Ü U DIAERESIS +#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Z + SHIFT_MASK // 221 Ý Y ACUTE +#define ISO_8859_1_DE 0 // 222 Þ THORN +#define ISO_8859_1_DF KEY_MINUS // 223 ß SHARP S +#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE +#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE +#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 0 // 227 ã a TILDE +#define ISO_8859_1_E4 KEY_QUOTE // 228 ä a DIAERESIS +#define ISO_8859_1_E5 0 // 229 å a RING ABOVE +#define ISO_8859_1_E6 0 // 230 æ ae +#define ISO_8859_1_E7 0 // 231 ç c CEDILLA +#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE +#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE +#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB 0 // 235 ë e DIAERESIS +#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE +#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE +#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF 0 // 239 ï i DIAERESIS +#define ISO_8859_1_F0 0 // 240 ð ETH +#define ISO_8859_1_F1 0 // 241 ñ n TILDE +#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE +#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE +#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 0 // 245 õ o TILDE +#define ISO_8859_1_F6 KEY_SEMICOLON // 246 ö o DIAERESIS +#define ISO_8859_1_F7 0 // 247 ÷ DIVISION +#define ISO_8859_1_F8 0 // 248 ø o STROKE +#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE +#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE +#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC KEY_LEFT_BRACE // 252 ü u DIAERESIS +#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Z // 253 ý y ACUTE +#define ISO_8859_1_FE 0 // 254 þ THORN +#define ISO_8859_1_FF 0 // 255 ÿ y DIAERESIS +#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign +// not yet implemented +#define UNICODE_EXTRA00 0x20AC +#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign + +#endif // LAYOUT_GERMAN + + + +#ifdef LAYOUT_GERMAN_MAC + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define DEADKEYS_MASK 0x0700 +#define ACUTE_ACCENT_BITS 0x0100 +#define GRAVE_ACCENT_BITS 0x0200 +#define CIRCUMFLEX_BITS 0x0300 +#define DIAERESIS_BITS 0x0400 +#define TILDE_BITS 0x0500 +#define KEYCODE_TYPE uint16_t +#define DEADKEY_ACUTE_ACCENT KEY_EQUAL +#define DEADKEY_GRAVE_ACCENT KEY_EQUAL + SHIFT_MASK +#define DEADKEY_CIRCUMFLEX KEY_6 + SHIFT_MASK + ALTGR_MASK +#define DEADKEY_DIAERESIS KEY_U + ALTGR_MASK +#define DEADKEY_TILDE KEY_N + ALTGR_MASK +#define KEY_NON_US_100 63 + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! +#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " +#define ASCII_23 KEY_BACKSLASH // 35 # ?? +#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ +#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % +#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & +#define ASCII_27 KEY_BACKSLASH + SHIFT_MASK // 39 ' +#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) +#define ASCII_2A KEY_RIGHT_BRACE + SHIFT_MASK // 42 * +#define ASCII_2B KEY_RIGHT_BRACE // 43 + +#define ASCII_2C KEY_COMMA // 44 , +#define ASCII_2D KEY_SLASH // 45 - +#define ASCII_2E KEY_PERIOD // 46 . +#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / +#define ASCII_30 KEY_0 // 48 0 +#define ASCII_31 KEY_1 // 49 1 +#define ASCII_32 KEY_2 // 50 2 +#define ASCII_33 KEY_3 // 51 3 +#define ASCII_34 KEY_4 // 52 4 +#define ASCII_35 KEY_5 // 53 5 +#define ASCII_36 KEY_6 // 54 6 +#define ASCII_37 KEY_7 // 55 7 +#define ASCII_38 KEY_8 // 55 8 +#define ASCII_39 KEY_9 // 57 9 +#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : +#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; +#define ASCII_3C KEY_TILDE // 60 < +#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = +#define ASCII_3E KEY_TILDE + SHIFT_MASK // 62 > +#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_Q + ALTGR_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Z + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Y + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_5 + ALTGR_MASK // 91 [ +#define ASCII_5C KEY_7 + ALTGR_MASK + SHIFT_MASK // 92 +#define ASCII_5D KEY_6 + ALTGR_MASK // 93 ] +#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ +#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ +#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Z // 121 y +#define ASCII_7A KEY_Y // 122 z +#define ASCII_7B KEY_8 + ALTGR_MASK // 123 { +#define ASCII_7C KEY_7 + ALTGR_MASK // 124 | +#define ASCII_7D KEY_9 + ALTGR_MASK // 125 } +#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 +#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space +#define ISO_8859_1_A1 KEY_1 + ALTGR_MASK // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 KEY_4 + ALTGR_MASK // 162 ¢ Cent Sign +#define ISO_8859_1_A3 KEY_4 + SHIFT_MASK + ALTGR_MASK // 163 £ Pound Sign +#define ISO_8859_1_A4 KEY_E + ALTGR_MASK // 164 ¤ Currency Sign +#define ISO_8859_1_A5 KEY_Z + ALTGR_MASK // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR +#define ISO_8859_1_A7 KEY_3 + SHIFT_MASK // 167 § SECTION SIGN +#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 KEY_G + ALTGR_MASK // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA KEY_H + ALTGR_MASK // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB KEY_Q + ALTGR_MASK // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN +#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN +#define ISO_8859_1_AE KEY_R + ALTGR_MASK // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF KEY_0 + SHIFT_MASK + ALTGR_MASK // 175 ¯ MACRON +#define ISO_8859_1_B0 KEY_LEFT_BRACE + ALTGR_MASK + SHIFT_MASK// 176 ° DEGREE SIGN +#define ISO_8859_1_B1 KEY_RIGHT_BRACE + ALTGR_MASK // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 KEY_M + ALTGR_MASK // 181 µ MICRO SIGN +#define ISO_8859_1_B6 KEY_3 + ALTGR_MASK // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 KEY_9 + SHIFT_MASK + ALTGR_MASK // 183 · MIDDLE DOT +#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA +#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA KEY_J + ALTGR_MASK // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB KEY_Q + SHIFT_MASK + ALTGR_MASK // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF KEY_MINUS + ALTGR_MASK // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE +#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE +#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE +#define ISO_8859_1_C4 KEY_QUOTE + SHIFT_MASK // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 KEY_A + ALTGR_MASK + SHIFT_MASK // 197 Å A RING ABOVE +#define ISO_8859_1_C6 KEY_QUOTE + ALTGR_MASK + SHIFT_MASK // 198 Æ AE +#define ISO_8859_1_C7 KEY_C + ALTGR_MASK + SHIFT_MASK // 199 Ç C CEDILLA +#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE +#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE +#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS +#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE +#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE +#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 0 // 208 Ð ETH +#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE +#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE +#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE +#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE +#define ISO_8859_1_D6 KEY_SEMICOLON + SHIFT_MASK // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION +#define ISO_8859_1_D8 KEY_O + ALTGR_MASK + SHIFT_MASK // 216 Ø O STROKE +#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE +#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE +#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC KEY_LEFT_BRACE + SHIFT_MASK // 220 Ü U DIAERESIS +#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Z + SHIFT_MASK // 221 Ý Y ACUTE +#define ISO_8859_1_DE 0 // 222 Þ THORN +#define ISO_8859_1_DF KEY_MINUS // 223 ß SHARP S +#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE +#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE +#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE +#define ISO_8859_1_E4 KEY_QUOTE // 228 ä a DIAERESIS +#define ISO_8859_1_E5 KEY_A + ALTGR_MASK // 229 å a RING ABOVE +#define ISO_8859_1_E6 KEY_QUOTE + ALTGR_MASK // 230 æ ae +#define ISO_8859_1_E7 KEY_C + ALTGR_MASK // 231 ç c CEDILLA +#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE +#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE +#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS +#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE +#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE +#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS +#define ISO_8859_1_F0 0 // 240 ð ETH +#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE +#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE +#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE +#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE +#define ISO_8859_1_F6 KEY_SEMICOLON // 246 ö o DIAERESIS +#define ISO_8859_1_F7 0 // 247 ÷ DIVISION +#define ISO_8859_1_F8 KEY_O + ALTGR_MASK // 248 ø o STROKE +#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE +#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE +#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC KEY_LEFT_BRACE // 252 ü u DIAERESIS +#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Z // 253 ý y ACUTE +#define ISO_8859_1_FE 0 // 254 þ THORN +#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Z // 255 ÿ y DIAERESIS +#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign +// not yet implemented +#define UNICODE_EXTRA00 0x20AC +#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign + +#endif // LAYOUT_GERMAN_MAC + + + + + + +#ifdef LAYOUT_CANADIAN_FRENCH + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define DEADKEYS_MASK 0x0700 +#define CIRCUMFLEX_BITS 0x0100 +#define ACUTE_ACCENT_BITS 0x0200 +#define GRAVE_ACCENT_BITS 0x0300 +#define DIAERESIS_BITS 0x0400 +#define CEDILLA_BITS 0x0500 + +#define KEYCODE_TYPE uint16_t +#define DEADKEY_CIRCUMFLEX KEY_LEFT_BRACE +#define DEADKEY_ACUTE_ACCENT KEY_SLASH + ALTGR_MASK +#define DEADKEY_GRAVE_ACCENT KEY_QUOTE +#define DEADKEY_DIAERESIS KEY_RIGHT_BRACE + SHIFT_MASK +#define DEADKEY_CEDILLA KEY_RIGHT_BRACE +#define KEY_NON_US_100 63 + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! +#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " +#define ASCII_23 KEY_TILDE + SHIFT_MASK // 35 # +#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ +#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % +#define ASCII_26 KEY_7 + SHIFT_MASK // 38 & +#define ASCII_27 KEY_COMMA + SHIFT_MASK // 39 ' +//#define ASCII_27 ACUTE_ACCENT_BITS + KEY_SPACE // 39 ' +#define ASCII_28 KEY_9 + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_0 + SHIFT_MASK // 41 ) +#define ASCII_2A KEY_8 + SHIFT_MASK // 42 * +#define ASCII_2B KEY_EQUAL + SHIFT_MASK // 43 + +#define ASCII_2C KEY_COMMA // 44 , +#define ASCII_2D KEY_MINUS // 45 - +#define ASCII_2E KEY_PERIOD // 46 . +#define ASCII_2F KEY_3 + SHIFT_MASK // 47 / +#define ASCII_30 KEY_0 // 48 0 +#define ASCII_31 KEY_1 // 49 1 +#define ASCII_32 KEY_2 // 50 2 +#define ASCII_33 KEY_3 // 51 3 +#define ASCII_34 KEY_4 // 52 4 +#define ASCII_35 KEY_5 // 53 5 +#define ASCII_36 KEY_6 // 54 6 +#define ASCII_37 KEY_7 // 55 7 +#define ASCII_38 KEY_8 // 55 8 +#define ASCII_39 KEY_9 // 57 9 +#define ASCII_3A KEY_SEMICOLON + SHIFT_MASK // 58 : +#define ASCII_3B KEY_SEMICOLON // 59 ; +#define ASCII_3C KEY_BACKSLASH // 60 < +#define ASCII_3D KEY_EQUAL // 61 = +#define ASCII_3E KEY_BACKSLASH + SHIFT_MASK // 62 > +#define ASCII_3F KEY_6 + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_2 + ALTGR_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_LEFT_BRACE + ALTGR_MASK // 91 [ +#define ASCII_5C KEY_TILDE + ALTGR_MASK // 92 +#define ASCII_5D KEY_RIGHT_BRACE + ALTGR_MASK // 93 ] +#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ +#define ASCII_5F KEY_MINUS + SHIFT_MASK // 95 _ +#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Y // 121 y +#define ASCII_7A KEY_Z // 122 z +#define ASCII_7B KEY_QUOTE + ALTGR_MASK // 123 { +#define ASCII_7C KEY_TILDE + SHIFT_MASK // 124 | +#define ASCII_7D KEY_BACKSLASH + ALTGR_MASK // 125 } +#define ASCII_7E KEY_SEMICOLON + ALTGR_MASK // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 +#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space +#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 KEY_4 + ALTGR_MASK // 162 ¢ Cent SIGN +#define ISO_8859_1_A3 KEY_3 + ALTGR_MASK // 163 £ Pound Sign +#define ISO_8859_1_A4 KEY_5 + ALTGR_MASK // 164 ¤ Currency or Euro Sign +#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 KEY_7 + ALTGR_MASK // 166 ¦ BROKEN BAR +#define ISO_8859_1_A7 KEY_O + ALTGR_MASK // 167 § SECTION SIGN +#define ISO_8859_1_A8 0 // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB KEY_NON_US_100 // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC KEY_6 + ALTGR_MASK // 172 ¬ NOT SIGN +#define ISO_8859_1_AD KEY_PERIOD + ALTGR_MASK // 173 SOFT HYPHEN +#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF KEY_COMMA + ALTGR_MASK // 175 ¯ MACRON +#define ISO_8859_1_B0 KEY_NON_US_100 + ALTGR_MASK // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 KEY_1 + ALTGR_MASK // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 KEY_8 + ALTGR_MASK // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 KEY_9 + ALTGR_MASK // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 0 // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 KEY_M + ALTGR_MASK // 181 µ MICRO SIGN +#define ISO_8859_1_B6 KEY_P + ALTGR_MASK // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT +#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA +#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB KEY_NON_US_100 + SHIFT_MASK // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC KEY_0 + ALTGR_MASK // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD KEY_MINUS + ALTGR_MASK // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE KEY_EQUAL + ALTGR_MASK // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE +#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE +#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 0 // 195 Ã A TILDE +#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE +#define ISO_8859_1_C6 0 // 198 Æ AE +#define ISO_8859_1_C7 CEDILLA_BITS + KEY_C + SHIFT_MASK // 199 Ç C CEDILLA +#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE +#define ISO_8859_1_C9 KEY_SLASH + SHIFT_MASK // 201 É E ACUTE +#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS +#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE +#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE +#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 0 // 208 Ð ETH +#define ISO_8859_1_D1 0 // 209 Ñ N TILDE +#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE +#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE +#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 0 // 213 Õ O TILDE +#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION +#define ISO_8859_1_D8 0 // 216 Ø O STROKE +#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE +#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE +#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U // 220 Ü U DIAERESIS +#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE +#define ISO_8859_1_DE 0 // 222 Þ THORN +#define ISO_8859_1_DF 0 // 223 ß SHARP S +#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE +#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE +#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 0 // 227 ã a TILDE +#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS +#define ISO_8859_1_E5 0 // 229 å a RING ABOVE +#define ISO_8859_1_E6 0 // 230 æ ae +#define ISO_8859_1_E7 CEDILLA_BITS + KEY_C // 231 ç c CEDILLA +#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE +#define ISO_8859_1_E9 KEY_SLASH // 233 é e ACUTE +#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS +#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE +#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE +#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS +#define ISO_8859_1_F0 0 // 240 ð ETH +#define ISO_8859_1_F1 0 // 241 ñ n TILDE +#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE +#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE +#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 0 // 245 õ o TILDE +#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS +#define ISO_8859_1_F7 0 // 247 ÷ DIVISION +#define ISO_8859_1_F8 0 // 248 ø o STROKE +#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE +#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE +#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS +#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE +#define ISO_8859_1_FE 0 // 254 þ THORN +#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS + +#endif // LAYOUT_CANADIAN_FRENCH + + + +#ifdef LAYOUT_CANADIAN_MULTILINGUAL + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define RCTRL_MASK 0x0800 +#define DEADKEYS_MASK 0x0700 +#define CIRCUMFLEX_BITS 0x0100 +#define DIAERESIS_BITS 0x0200 +#define ACUTE_ACCENT_BITS 0x0300 +#define CEDILLA_BITS 0x0400 +#define GRAVE_ACCENT_BITS 0x0500 +#define TILDE_BITS 0x0600 +#define RING_ABOVE_BITS 0x0700 +#define KEYCODE_TYPE uint16_t +#define DEADKEY_CIRCUMFLEX KEY_LEFT_BRACE +#define DEADKEY_DIAERESIS KEY_LEFT_BRACE + SHIFT_MASK +#define DEADKEY_ACUTE_ACCENT KEY_SEMICOLON + RCTRL_MASK +#define DEADKEY_CEDILLA KEY_EQUAL + RCTRL_MASK +#define DEADKEY_GRAVE_ACCENT KEY_LEFT_BRACE + ALTGR_MASK +#define DEADKEY_TILDE KEY_RIGHT_BRACE + ALTGR_MASK +#define DEADKEY_RING_ABOVE KEY_LEFT_BRACE + SHIFT_MASK + RCTRL_MASK +#define KEY_NON_US_100 63 + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! +#define ASCII_22 KEY_PERIOD + SHIFT_MASK // 34 " +#define ASCII_23 KEY_3 + SHIFT_MASK // 35 # +#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ +#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % +#define ASCII_26 KEY_7 + SHIFT_MASK // 38 & +#define ASCII_27 KEY_COMMA + SHIFT_MASK // 39 ' +#define ASCII_28 KEY_9 + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_0 + SHIFT_MASK // 41 ) +#define ASCII_2A KEY_8 + SHIFT_MASK // 42 * +#define ASCII_2B KEY_EQUAL + SHIFT_MASK // 43 + +#define ASCII_2C KEY_COMMA // 44 , +#define ASCII_2D KEY_MINUS // 45 - +#define ASCII_2E KEY_PERIOD // 46 . +#define ASCII_2F KEY_TILDE // 47 / +#define ASCII_30 KEY_0 // 48 0 +#define ASCII_31 KEY_1 // 49 1 +#define ASCII_32 KEY_2 // 50 2 +#define ASCII_33 KEY_3 // 51 3 +#define ASCII_34 KEY_4 // 52 4 +#define ASCII_35 KEY_5 // 53 5 +#define ASCII_36 KEY_6 // 54 6 +#define ASCII_37 KEY_7 // 55 7 +#define ASCII_38 KEY_8 // 55 8 +#define ASCII_39 KEY_9 // 57 9 +#define ASCII_3A KEY_SEMICOLON + SHIFT_MASK // 58 : +#define ASCII_3B KEY_SEMICOLON // 59 ; +#define ASCII_3C KEY_COMMA + ALTGR_MASK // 60 < +#define ASCII_3D KEY_EQUAL // 61 = +#define ASCII_3E KEY_PERIOD + ALTGR_MASK // 62 > +#define ASCII_3F KEY_6 + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_2 + SHIFT_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_9 + ALTGR_MASK // 91 [ +#define ASCII_5C KEY_TILDE + SHIFT_MASK // 92 +#define ASCII_5D KEY_0 + ALTGR_MASK // 93 ] +#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ +#define ASCII_5F KEY_MINUS + SHIFT_MASK // 95 _ +#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Y // 121 y +#define ASCII_7A KEY_Z // 122 z +#define ASCII_7B KEY_7 + ALTGR_MASK // 123 { +#define ASCII_7C KEY_TILDE + ALTGR_MASK // 124 | +#define ASCII_7D KEY_8 + ALTGR_MASK // 125 } +#define ASCII_7E KEY_RIGHT_BRACE + RCTRL_MASK // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 +#define ISO_8859_1_A0 KEY_SPACE + ALTGR_MASK // 160 Nonbreakng Space +#define ISO_8859_1_A1 KEY_1 + SHIFT_MASK + RCTRL_MASK // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 KEY_C + RCTRL_MASK // 162 ¢ Cent SIGN +#define ISO_8859_1_A3 KEY_3 + SHIFT_MASK + RCTRL_MASK // 163 £ Pound Sign +#define ISO_8859_1_A4 KEY_4 + SHIFT_MASK + RCTRL_MASK // 164 ¤ Currency or Euro Sign +#define ISO_8859_1_A5 KEY_Y + SHIFT_MASK + RCTRL_MASK // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 KEY_NON_US_100 + SHIFT_MASK + RCTRL_MASK// 166 ¦ BROKEN BAR +#define ISO_8859_1_A7 KEY_S + SHIFT_MASK + RCTRL_MASK // 167 § SECTION SIGN +#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 KEY_C + SHIFT_MASK + RCTRL_MASK // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA KEY_F + SHIFT_MASK + RCTRL_MASK // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB KEY_Z + ALTGR_MASK // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC KEY_EQUAL + ALTGR_MASK // 172 ¬ NOT SIGN +#define ISO_8859_1_AD KEY_TILDE + SHIFT_MASK + RCTRL_MASK // 173 SOFT HYPHEN +#define ISO_8859_1_AE KEY_R + SHIFT_MASK + RCTRL_MASK // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF 0 // special dead key - no implemented // 175 ¯ MACRON +#define ISO_8859_1_B0 KEY_SEMICOLON + ALTGR_MASK // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 KEY_9 + SHIFT_MASK + RCTRL_MASK // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 KEY_2 + RCTRL_MASK // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 KEY_3 + RCTRL_MASK // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 KEY_M + RCTRL_MASK // 181 µ MICRO SIGN +#define ISO_8859_1_B6 KEY_R + RCTRL_MASK // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT +#define ISO_8859_1_B8 CEDILLA_BITS + KEY_SPACE // 184 ¸ CEDILLA +#define ISO_8859_1_B9 KEY_1 + RCTRL_MASK // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA KEY_M + SHIFT_MASK + RCTRL_MASK // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB KEY_X + ALTGR_MASK // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC KEY_4 + RCTRL_MASK // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD KEY_5 + RCTRL_MASK // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE KEY_6 + RCTRL_MASK // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF KEY_MINUS + SHIFT_MASK + RCTRL_MASK // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 KEY_BACKSLASH + SHIFT_MASK // 192 À A GRAVE +#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE +#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE +#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 RING_ABOVE_BITS + KEY_A + SHIFT_MASK // 197 Å A RING ABOVE +#define ISO_8859_1_C6 KEY_A + SHIFT_MASK + RCTRL_MASK // 198 Æ AE +#define ISO_8859_1_C7 KEY_RIGHT_BRACE + SHIFT_MASK // 199 Ç C CEDILLA +#define ISO_8859_1_C8 KEY_QUOTE + SHIFT_MASK // 200 È E GRAVE +#define ISO_8859_1_C9 KEY_SLASH + SHIFT_MASK // 201 É E ACUTE +#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS +#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE +#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE +#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 KEY_D + SHIFT_MASK + RCTRL_MASK // 208 Ð ETH +#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE +#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE +#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE +#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE +#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 KEY_COMMA + SHIFT_MASK + RCTRL_MASK // 215 × MULTIPLICATION +#define ISO_8859_1_D8 KEY_O + SHIFT_MASK + RCTRL_MASK // 216 Ø O STROKE +#define ISO_8859_1_D9 KEY_NON_US_100 + SHIFT_MASK // 217 Ù U GRAVE +#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE +#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U // 220 Ü U DIAERESIS +#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE +#define ISO_8859_1_DE KEY_P + RCTRL_MASK + SHIFT_MASK // 222 Þ THORN +#define ISO_8859_1_DF KEY_S + RCTRL_MASK // 223 ß SHARP S +#define ISO_8859_1_E0 KEY_BACKSLASH // 224 à a GRAVE +#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE +#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE +#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS +#define ISO_8859_1_E5 RING_ABOVE_BITS + KEY_A // 229 å a RING ABOVE +#define ISO_8859_1_E6 KEY_A + RCTRL_MASK // 230 æ ae +#define ISO_8859_1_E7 KEY_RIGHT_BRACE // 231 ç c CEDILLA +#define ISO_8859_1_E8 KEY_QUOTE // 232 è e GRAVE +#define ISO_8859_1_E9 KEY_SLASH // 233 é e ACUTE +#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS +#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE +#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE +#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS +#define ISO_8859_1_F0 KEY_D + RCTRL_MASK // 240 ð ETH +#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE +#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE +#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE +#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE +#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS +#define ISO_8859_1_F7 KEY_PERIOD + SHIFT_MASK + RCTRL_MASK // 247 ÷ DIVISION +#define ISO_8859_1_F8 KEY_O + RCTRL_MASK // 248 ø o STROKE +#define ISO_8859_1_F9 KEY_NON_US_100 // 249 ù u GRAVE +#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE +#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS +#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE +#define ISO_8859_1_FE KEY_P + RCTRL_MASK // 254 þ THORN +#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS + +#endif // LAYOUT_CANADIAN_MULTILINGUAL + + + + + + +#ifdef LAYOUT_UNITED_KINGDOM + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define KEYCODE_TYPE uint8_t +#define KEY_NON_US_100 63 + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! +#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " +#define ASCII_23 KEY_BACKSPACE // 35 # +#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ +#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % +#define ASCII_26 KEY_7 + SHIFT_MASK // 38 & +#define ASCII_27 KEY_QUOTE // 39 ' +#define ASCII_28 KEY_9 + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_0 + SHIFT_MASK // 41 ) +#define ASCII_2A KEY_8 + SHIFT_MASK // 42 * +#define ASCII_2B KEY_EQUAL + SHIFT_MASK // 43 + +#define ASCII_2C KEY_COMMA // 44 , +#define ASCII_2D KEY_MINUS // 45 - +#define ASCII_2E KEY_PERIOD // 46 . +#define ASCII_2F KEY_SLASH // 47 / +#define ASCII_30 KEY_0 // 48 0 +#define ASCII_31 KEY_1 // 49 1 +#define ASCII_32 KEY_2 // 50 2 +#define ASCII_33 KEY_3 // 51 3 +#define ASCII_34 KEY_4 // 52 4 +#define ASCII_35 KEY_5 // 53 5 +#define ASCII_36 KEY_6 // 54 6 +#define ASCII_37 KEY_7 // 55 7 +#define ASCII_38 KEY_8 // 55 8 +#define ASCII_39 KEY_9 // 57 9 +#define ASCII_3A KEY_SEMICOLON + SHIFT_MASK // 58 : +#define ASCII_3B KEY_SEMICOLON // 59 ; +#define ASCII_3C KEY_COMMA + SHIFT_MASK // 60 < +#define ASCII_3D KEY_EQUAL // 61 = +#define ASCII_3E KEY_PERIOD + SHIFT_MASK // 62 > +#define ASCII_3F KEY_SLASH + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_QUOTE + SHIFT_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_LEFT_BRACE // 91 [ +#define ASCII_5C KEY_NON_US_100 // 92 +#define ASCII_5D KEY_RIGHT_BRACE // 93 ] +#define ASCII_5E KEY_6 + SHIFT_MASK // 94 ^ +#define ASCII_5F KEY_MINUS + SHIFT_MASK // 95 _ +#define ASCII_60 KEY_TILDE // 96 ` +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Y // 121 y +#define ASCII_7A KEY_Z // 122 z +#define ASCII_7B KEY_LEFT_BRACE + SHIFT_MASK // 123 { +#define ASCII_7C KEY_NON_US_100 + SHIFT_MASK // 124 | +#define ASCII_7D KEY_RIGHT_BRACE + SHIFT_MASK // 125 } +#define ASCII_7E KEY_BACKSLASH + SHIFT_MASK // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 + +#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space +#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN +#define ISO_8859_1_A3 KEY_3 + SHIFT_MASK // 163 £ Pound Sign +#define ISO_8859_1_A4 0 // 164 ¤ Currency or Euro Sign +#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 KEY_TILDE + ALTGR_MASK // 166 ¦ BROKEN BAR +#define ISO_8859_1_A7 0 // 167 § SECTION SIGN +#define ISO_8859_1_A8 0 // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC KEY_TILDE + SHIFT_MASK // 172 ¬ NOT SIGN +#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN +#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF 0 // 175 ¯ MACRON +#define ISO_8859_1_B0 0 // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 0 // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN +#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT +#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA +#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 0 // 192 À A GRAVE +#define ISO_8859_1_C1 KEY_A + ALTGR_MASK + SHIFT_MASK // 193 Á A ACUTE +#define ISO_8859_1_C2 0 // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 0 // 195 Ã A TILDE +#define ISO_8859_1_C4 0 // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE +#define ISO_8859_1_C6 0 // 198 Æ AE +#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA +#define ISO_8859_1_C8 0 // 200 È E GRAVE +#define ISO_8859_1_C9 KEY_E + ALTGR_MASK + SHIFT_MASK // 201 É E ACUTE +#define ISO_8859_1_CA 0 // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB 0 // 203 Ë E DIAERESIS +#define ISO_8859_1_CC 0 // 204 Ì I GRAVE +#define ISO_8859_1_CD KEY_I + ALTGR_MASK + SHIFT_MASK // 205 Í I ACUTE +#define ISO_8859_1_CE 0 // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF 0 // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 0 // 208 Ð ETH +#define ISO_8859_1_D1 0 // 209 Ñ N TILDE +#define ISO_8859_1_D2 0 // 210 Ò O GRAVE +#define ISO_8859_1_D3 KEY_O + ALTGR_MASK + SHIFT_MASK // 211 Ó O ACUTE +#define ISO_8859_1_D4 0 // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 0 // 213 Õ O TILDE +#define ISO_8859_1_D6 0 // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION +#define ISO_8859_1_D8 0 // 216 Ø O STROKE +#define ISO_8859_1_D9 0 // 217 Ù U GRAVE +#define ISO_8859_1_DA KEY_U + ALTGR_MASK + SHIFT_MASK // 218 Ú U ACUTE +#define ISO_8859_1_DB 0 // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC 0 // 220 Ü U DIAERESIS +#define ISO_8859_1_DD 0 // 221 Ý Y ACUTE +#define ISO_8859_1_DE 0 // 222 Þ THORN +#define ISO_8859_1_DF 0 // 223 ß SHARP S +#define ISO_8859_1_E0 0 // 224 à a GRAVE +#define ISO_8859_1_E1 KEY_A + ALTGR_MASK // 225 á a ACUTE +#define ISO_8859_1_E2 0 // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 0 // 227 ã a TILDE +#define ISO_8859_1_E4 0 // 228 ä a DIAERESIS +#define ISO_8859_1_E5 0 // 229 å a RING ABOVE +#define ISO_8859_1_E6 0 // 230 æ ae +#define ISO_8859_1_E7 0 // 231 ç c CEDILLA +#define ISO_8859_1_E8 0 // 232 è e GRAVE +#define ISO_8859_1_E9 KEY_E + ALTGR_MASK // 233 é e ACUTE +#define ISO_8859_1_EA 0 // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB 0 // 235 ë e DIAERESIS +#define ISO_8859_1_EC 0 // 236 ì i GRAVE +#define ISO_8859_1_ED KEY_I + ALTGR_MASK // 237 í i ACUTE +#define ISO_8859_1_EE 0 // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF 0 // 239 ï i DIAERESIS +#define ISO_8859_1_F0 0 // 240 ð ETH +#define ISO_8859_1_F1 0 // 241 ñ n TILDE +#define ISO_8859_1_F2 0 // 242 ò o GRAVE +#define ISO_8859_1_F3 KEY_O + ALTGR_MASK // 243 ó o ACUTE +#define ISO_8859_1_F4 0 // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 0 // 245 õ o TILDE +#define ISO_8859_1_F6 0 // 246 ö o DIAERESIS +#define ISO_8859_1_F7 0 // 247 ÷ DIVISION +#define ISO_8859_1_F8 0 // 248 ø o STROKE +#define ISO_8859_1_F9 0 // 249 ù u GRAVE +#define ISO_8859_1_FA KEY_U + ALTGR_MASK // 250 ú u ACUTE +#define ISO_8859_1_FB 0 // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC 0 // 252 ü u DIAERESIS +#define ISO_8859_1_FD 0 // 253 ý y ACUTE +#define ISO_8859_1_FE 0 // 254 þ THORN +#define ISO_8859_1_FF 0 // 255 ÿ y DIAERESIS +#define UNICODE_20AC KEY_4 + ALTGR_MASK // € Euro Sign +// not yet implemented +#define UNICODE_EXTRA00 0x20AC +#define KEYCODE_EXTRA00 KEY_4 + ALTGR_MASK // 20AC € Euro Sign + +#endif // LAYOUT_UNITED_KINGDOM + + + +#ifdef LAYOUT_FINNISH + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define DEADKEYS_MASK 0x0700 +#define CIRCUMFLEX_BITS 0x0100 +#define ACUTE_ACCENT_BITS 0x0200 +#define GRAVE_ACCENT_BITS 0x0300 +#define TILDE_BITS 0x0400 +#define DIAERESIS_BITS 0x0500 +#define KEYCODE_TYPE uint16_t +#define DEADKEY_CIRCUMFLEX KEY_RIGHT_BRACE + SHIFT_MASK +#define DEADKEY_ACUTE_ACCENT KEY_EQUAL +#define DEADKEY_GRAVE_ACCENT KEY_EQUAL + SHIFT_MASK +#define DEADKEY_TILDE KEY_RIGHT_BRACE + ALTGR_MASK +#define DEADKEY_DIAERESIS KEY_RIGHT_BRACE +#define KEY_NON_US_100 63 + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! +#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " +#define ASCII_23 KEY_3 + SHIFT_MASK // 35 # +#define ASCII_24 KEY_4 + ALTGR_MASK // 36 $ +#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % +#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & +#define ASCII_27 KEY_BACKSLASH // 39 ' +#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) +#define ASCII_2A KEY_BACKSLASH + SHIFT_MASK // 42 * +#define ASCII_2B KEY_MINUS // 43 + +#define ASCII_2C KEY_COMMA // 44 , +#define ASCII_2D KEY_SLASH // 45 - +#define ASCII_2E KEY_PERIOD // 46 . +#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / +#define ASCII_30 KEY_0 // 48 0 +#define ASCII_31 KEY_1 // 49 1 +#define ASCII_32 KEY_2 // 50 2 +#define ASCII_33 KEY_3 // 51 3 +#define ASCII_34 KEY_4 // 52 4 +#define ASCII_35 KEY_5 // 53 5 +#define ASCII_36 KEY_6 // 54 6 +#define ASCII_37 KEY_7 // 55 7 +#define ASCII_38 KEY_8 // 55 8 +#define ASCII_39 KEY_9 // 57 9 +#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : +#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; +#define ASCII_3C KEY_NON_US_100 // 60 < +#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = +#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > +#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_2 + ALTGR_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_8 + ALTGR_MASK // 91 [ +#define ASCII_5C KEY_MINUS + ALTGR_MASK // 92 +#define ASCII_5D KEY_9 + ALTGR_MASK // 93 ] +#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ +#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ +#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Y // 121 y +#define ASCII_7A KEY_Z // 122 z +#define ASCII_7B KEY_7 + ALTGR_MASK // 123 { +#define ASCII_7C KEY_NON_US_100 + ALTGR_MASK // 124 | +#define ASCII_7D KEY_0 + ALTGR_MASK // 125 } +#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 +#define ISO_8859_1_A0 KEY_SPACE + ALTGR_MASK // 160 Nonbreakng Space +#define ISO_8859_1_A1 KEY_1 + SHIFT_MASK + ALTGR_MASK // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN +#define ISO_8859_1_A3 KEY_3 + ALTGR_MASK // 163 £ Pound Sign +#define ISO_8859_1_A4 KEY_4 + SHIFT_MASK // 164 ¤ Currency or Euro Sign +#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR +#define ISO_8859_1_A7 KEY_TILDE // 167 § SECTION SIGN +#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB KEY_4 + ALTGR_MASK + SHIFT_MASK // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN +#define ISO_8859_1_AD KEY_SLASH + ALTGR_MASK // 173 SOFT HYPHEN +#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF 0 // 175 ¯ MACRON +#define ISO_8859_1_B0 KEY_0 + ALTGR_MASK + SHIFT_MASK // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 KEY_M + ALTGR_MASK // 181 µ MICRO SIGN +#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 KEY_X + ALTGR_MASK + SHIFT_MASK // 183 · MIDDLE DOT +#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA +#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB KEY_3 + ALTGR_MASK + SHIFT_MASK // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD KEY_TILDE + SHIFT_MASK // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF KEY_MINUS + ALTGR_MASK + SHIFT_MASK // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE +#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE +#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE +#define ISO_8859_1_C4 KEY_QUOTE + SHIFT_MASK // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 KEY_LEFT_BRACE + SHIFT_MASK // 197 Å A RING ABOVE +#define ISO_8859_1_C6 KEY_QUOTE + ALTGR_MASK + SHIFT_MASK // 198 Æ AE +#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA +#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE +#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE +#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS +#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE +#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE +#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 KEY_D + ALTGR_MASK + SHIFT_MASK // 208 Ð ETH +#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE +#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE +#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE +#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE +#define ISO_8859_1_D6 KEY_SEMICOLON + SHIFT_MASK // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 KEY_X + ALTGR_MASK // 215 × MULTIPLICATION +#define ISO_8859_1_D8 KEY_SEMICOLON + ALTGR_MASK + SHIFT_MASK // 216 Ø O STROKE +#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE +#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE +#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS +#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE +#define ISO_8859_1_DE KEY_T + ALTGR_MASK + SHIFT_MASK // 222 Þ THORN +#define ISO_8859_1_DF KEY_S + ALTGR_MASK // 223 ß SHARP S +#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE +#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE +#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE +#define ISO_8859_1_E4 KEY_QUOTE // 228 ä a DIAERESIS +#define ISO_8859_1_E5 KEY_LEFT_BRACE // 229 å a RING ABOVE +#define ISO_8859_1_E6 KEY_QUOTE + ALTGR_MASK // 230 æ ae +#define ISO_8859_1_E7 0 // 231 ç c CEDILLA +#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE +#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE +#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS +#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE +#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE +#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS +#define ISO_8859_1_F0 KEY_D + ALTGR_MASK // 240 ð ETH +#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE +#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE +#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE +#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE +#define ISO_8859_1_F6 KEY_SEMICOLON // 246 ö o DIAERESIS +#define ISO_8859_1_F7 0 // 247 ÷ DIVISION +#define ISO_8859_1_F8 KEY_SEMICOLON + ALTGR_MASK // 248 ø o STROKE +#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE +#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE +#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS +#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE +#define ISO_8859_1_FE KEY_T + ALTGR_MASK // 254 þ THORN +#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS +#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign +// not yet implemented +#define UNICODE_EXTRA00 0x20AC +#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign +// TODO: Finnish Multilingual layout can type many more glyphs +// but we currently don't have tables tables to store them... + +#endif // LAYOUT_FINNISH + + + + + + + +#ifdef LAYOUT_FRENCH + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define DEADKEYS_MASK 0x0700 +#define CIRCUMFLEX_BITS 0x0100 +#define GRAVE_ACCENT_BITS 0x0200 +#define DIAERESIS_BITS 0x0300 +#define TILDE_BITS 0x0400 +#define KEYCODE_TYPE uint16_t +#define DEADKEY_CIRCUMFLEX KEY_LEFT_BRACE +#define DEADKEY_GRAVE_ACCENT KEY_7 + ALTGR_MASK +#define DEADKEY_DIAERESIS KEY_LEFT_BRACE + SHIFT_MASK +#define DEADKEY_TILDE KEY_2 + ALTGR_MASK +#define KEY_NON_US_100 63 + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_SLASH // 33 ! +#define ASCII_22 KEY_3 // 34 " +#define ASCII_23 KEY_3 + ALTGR_MASK // 35 # +#define ASCII_24 KEY_RIGHT_BRACE // 36 $ +#define ASCII_25 KEY_QUOTE + SHIFT_MASK // 37 % +#define ASCII_26 KEY_1 // 38 & +#define ASCII_27 KEY_4 // 39 ' +#define ASCII_28 KEY_5 // 40 ( +#define ASCII_29 KEY_MINUS // 41 ) +#define ASCII_2A KEY_BACKSLASH // 42 * +#define ASCII_2B KEY_EQUAL + SHIFT_MASK // 43 + +#define ASCII_2C KEY_M // 44 , +#define ASCII_2D KEY_6 // 45 - +#define ASCII_2E KEY_COMMA + SHIFT_MASK // 46 . +#define ASCII_2F KEY_PERIOD + SHIFT_MASK // 47 / +#define ASCII_30 KEY_0 + SHIFT_MASK // 48 0 +#define ASCII_31 KEY_1 + SHIFT_MASK // 49 1 +#define ASCII_32 KEY_2 + SHIFT_MASK // 50 2 +#define ASCII_33 KEY_3 + SHIFT_MASK // 51 3 +#define ASCII_34 KEY_4 + SHIFT_MASK // 52 4 +#define ASCII_35 KEY_5 + SHIFT_MASK // 53 5 +#define ASCII_36 KEY_6 + SHIFT_MASK // 54 6 +#define ASCII_37 KEY_7 + SHIFT_MASK // 55 7 +#define ASCII_38 KEY_8 + SHIFT_MASK // 55 8 +#define ASCII_39 KEY_9 + SHIFT_MASK // 57 9 +#define ASCII_3A KEY_PERIOD // 58 : +#define ASCII_3B KEY_COMMA // 59 ; +#define ASCII_3C KEY_NON_US_100 // 60 < +#define ASCII_3D KEY_EQUAL // 61 = +#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > +#define ASCII_3F KEY_M + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_0 + ALTGR_MASK // 64 @ +#define ASCII_41 KEY_Q + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_SEMICOLON + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_A + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_Z + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_W + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_5 + ALTGR_MASK // 91 [ +#define ASCII_5C KEY_8 + ALTGR_MASK // 92 +#define ASCII_5D KEY_MINUS + ALTGR_MASK // 93 ] +#define ASCII_5E KEY_9 + ALTGR_MASK // 94 ^ +#define ASCII_5F KEY_8 // 95 _ +#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` +#define ASCII_61 KEY_Q // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_SEMICOLON // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_A // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_Z // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Y // 121 y +#define ASCII_7A KEY_W // 122 z +#define ASCII_7B KEY_4 + ALTGR_MASK // 123 { +#define ASCII_7C KEY_6 + ALTGR_MASK // 124 | +#define ASCII_7D KEY_EQUAL + ALTGR_MASK // 125 } +#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 +#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space +#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN +#define ISO_8859_1_A3 KEY_RIGHT_BRACE + SHIFT_MASK // 163 £ Pound Sign +#define ISO_8859_1_A4 KEY_RIGHT_BRACE + ALTGR_MASK // 164 ¤ Currency or Euro Sign +#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR +#define ISO_8859_1_A7 KEY_SLASH + SHIFT_MASK // 167 § SECTION SIGN +#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN +#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN +#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF 0 // 175 ¯ MACRON +#define ISO_8859_1_B0 KEY_MINUS + SHIFT_MASK // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 KEY_TILDE // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 0 // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 KEY_BACKSLASH + SHIFT_MASK // 181 µ MICRO SIGN +#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT +#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA +#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_Q + SHIFT_MASK // 192 À A GRAVE +#define ISO_8859_1_C1 0 // 193 Á A ACUTE +#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_Q + SHIFT_MASK // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 TILDE_BITS + KEY_Q + SHIFT_MASK // 195 Ã A TILDE +#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_Q + SHIFT_MASK // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE +#define ISO_8859_1_C6 0 // 198 Æ AE +#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA +#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE +#define ISO_8859_1_C9 0 // 201 É E ACUTE +#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS +#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE +#define ISO_8859_1_CD 0 // 205 Í I ACUTE +#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 0 // 208 Ð ETH +#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE +#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE +#define ISO_8859_1_D3 0 // 211 Ó O ACUTE +#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE +#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION +#define ISO_8859_1_D8 0 // 216 Ø O STROKE +#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE +#define ISO_8859_1_DA 0 // 218 Ú U ACUTE +#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U // 220 Ü U DIAERESIS +#define ISO_8859_1_DD 0 // 221 Ý Y ACUTE +#define ISO_8859_1_DE 0 // 222 Þ THORN +#define ISO_8859_1_DF 0 // 223 ß SHARP S +#define ISO_8859_1_E0 KEY_0 // 224 à a GRAVE +#define ISO_8859_1_E1 0 // 225 á a ACUTE +#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_Q // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 TILDE_BITS + KEY_Q // 227 ã a TILDE +#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_Q // 228 ä a DIAERESIS +#define ISO_8859_1_E5 0 // 229 å a RING ABOVE +#define ISO_8859_1_E6 0 // 230 æ ae +#define ISO_8859_1_E7 KEY_9 // 231 ç c CEDILLA +#define ISO_8859_1_E8 KEY_7 // 232 è e GRAVE +#define ISO_8859_1_E9 KEY_2 // 233 é e ACUTE +#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS +#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE +#define ISO_8859_1_ED 0 // 237 í i ACUTE +#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS +#define ISO_8859_1_F0 0 // 240 ð ETH +#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE +#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE +#define ISO_8859_1_F3 0 // 243 ó o ACUTE +#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE +#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS +#define ISO_8859_1_F7 0 // 247 ÷ DIVISION +#define ISO_8859_1_F8 0 // 248 ø o STROKE +#define ISO_8859_1_F9 KEY_SEMICOLON // 249 ù u GRAVE +#define ISO_8859_1_FA 0 // 250 ú u ACUTE +#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS +#define ISO_8859_1_FD 0 // 253 ý y ACUTE +#define ISO_8859_1_FE 0 // 254 þ THORN +#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS +#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign +// not yet implemented +#define UNICODE_EXTRA00 0x20AC +#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign + +#endif // LAYOUT_FRENCH + + + + + +#ifdef LAYOUT_DANISH + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define DEADKEYS_MASK 0x0700 +#define CIRCUMFLEX_BITS 0x0100 +#define ACUTE_ACCENT_BITS 0x0200 +#define GRAVE_ACCENT_BITS 0x0300 +#define TILDE_BITS 0x0400 +#define DIAERESIS_BITS 0x0500 +#define KEYCODE_TYPE uint16_t +#define DEADKEY_CIRCUMFLEX KEY_RIGHT_BRACE + SHIFT_MASK +#define DEADKEY_ACUTE_ACCENT KEY_EQUAL +#define DEADKEY_GRAVE_ACCENT KEY_EQUAL + SHIFT_MASK +#define DEADKEY_TILDE KEY_RIGHT_BRACE + ALTGR_MASK +#define DEADKEY_DIAERESIS KEY_RIGHT_BRACE +#define KEY_NON_US_100 63 + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! +#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " +#define ASCII_23 KEY_3 + SHIFT_MASK // 35 # +#define ASCII_24 KEY_4 + ALTGR_MASK // 36 $ +#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % +#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & +#define ASCII_27 KEY_BACKSLASH // 39 ' +#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) +#define ASCII_2A KEY_BACKSLASH + SHIFT_MASK // 42 * +#define ASCII_2B KEY_MINUS // 43 + +#define ASCII_2C KEY_COMMA // 44 , +#define ASCII_2D KEY_SLASH // 45 - +#define ASCII_2E KEY_PERIOD // 46 . +#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / +#define ASCII_30 KEY_0 // 48 0 +#define ASCII_31 KEY_1 // 49 1 +#define ASCII_32 KEY_2 // 50 2 +#define ASCII_33 KEY_3 // 51 3 +#define ASCII_34 KEY_4 // 52 4 +#define ASCII_35 KEY_5 // 53 5 +#define ASCII_36 KEY_6 // 54 6 +#define ASCII_37 KEY_7 // 55 7 +#define ASCII_38 KEY_8 // 55 8 +#define ASCII_39 KEY_9 // 57 9 +#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : +#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; +#define ASCII_3C KEY_NON_US_100 // 60 < +#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = +#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > +#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_2 + ALTGR_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_8 + ALTGR_MASK // 91 [ +#define ASCII_5C KEY_NON_US_100 + ALTGR_MASK // 92 +#define ASCII_5D KEY_9 + ALTGR_MASK // 93 ] +#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ +#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ +#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Y // 121 y +#define ASCII_7A KEY_Z // 122 z +#define ASCII_7B KEY_7 + ALTGR_MASK // 123 { +#define ASCII_7C KEY_EQUAL + ALTGR_MASK // 124 | +#define ASCII_7D KEY_0 + ALTGR_MASK // 125 } +#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 + +#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space +#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN +#define ISO_8859_1_A3 KEY_3 + ALTGR_MASK // 163 £ Pound Sign +#define ISO_8859_1_A4 KEY_4 + SHIFT_MASK // 164 ¤ Currency Sign +#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR +#define ISO_8859_1_A7 KEY_TILDE + SHIFT_MASK // 167 § SECTION SIGN +#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB KEY_4 // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN +#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN +#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF 0 // 175 ¯ MACRON +#define ISO_8859_1_B0 0 // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 KEY_M + ALTGR_MASK // 181 µ MICRO SIGN +#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT +#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA +#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD KEY_TILDE // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE +#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE +#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE +#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 KEY_LEFT_BRACE + SHIFT_MASK // 197 Å A RING ABOVE +#define ISO_8859_1_C6 KEY_SEMICOLON + SHIFT_MASK // 198 Æ AE +#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA +#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE +#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE +#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS +#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE +#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE +#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 KEY_D + ALTGR_MASK + SHIFT_MASK // 208 Ð ETH +#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE +#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE +#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE +#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE +#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION +#define ISO_8859_1_D8 KEY_QUOTE + SHIFT_MASK // 216 Ø O STROKE +#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE +#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE +#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS +#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE +#define ISO_8859_1_DE KEY_T + ALTGR_MASK + SHIFT_MASK // 222 Þ THORN +#define ISO_8859_1_DF KEY_S + ALTGR_MASK // 223 ß SHARP S +#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE +#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE +#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE +#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS +#define ISO_8859_1_E5 KEY_LEFT_BRACE // 229 å a RING ABOVE +#define ISO_8859_1_E6 KEY_SEMICOLON // 230 æ ae +#define ISO_8859_1_E7 0 // 231 ç c CEDILLA +#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE +#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE +#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS +#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE +#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE +#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS +#define ISO_8859_1_F0 KEY_D + ALTGR_MASK // 240 ð ETH +#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE +#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE +#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE +#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE +#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS +#define ISO_8859_1_F7 0 // 247 ÷ DIVISION +#define ISO_8859_1_F8 KEY_QUOTE // 248 ø o STROKE +#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE +#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE +#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS +#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE +#define ISO_8859_1_FE KEY_T + ALTGR_MASK // 254 þ THORN +#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS +#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign +// not yet implemented +#define UNICODE_EXTRA00 0x20AC +#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign + +#endif // LAYOUT_DANISH + + + + + +#ifdef LAYOUT_NORWEGIAN + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define DEADKEYS_MASK 0x0700 +#define CIRCUMFLEX_BITS 0x0100 +#define ACUTE_ACCENT_BITS 0x0200 +#define GRAVE_ACCENT_BITS 0x0300 +#define TILDE_BITS 0x0400 +#define DIAERESIS_BITS 0x0500 +#define KEYCODE_TYPE uint16_t +#define DEADKEY_CIRCUMFLEX KEY_RIGHT_BRACE + SHIFT_MASK +#define DEADKEY_ACUTE_ACCENT KEY_EQUAL + ALTGR_MASK +#define DEADKEY_GRAVE_ACCENT KEY_EQUAL + SHIFT_MASK +#define DEADKEY_TILDE KEY_RIGHT_BRACE + ALTGR_MASK +#define DEADKEY_DIAERESIS KEY_RIGHT_BRACE +#define KEY_NON_US_100 63 + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! +#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " +#define ASCII_23 KEY_3 + SHIFT_MASK // 35 # +#define ASCII_24 KEY_4 + ALTGR_MASK // 36 $ +#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % +#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & +#define ASCII_27 KEY_BACKSLASH // 39 ' +#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) +#define ASCII_2A KEY_BACKSLASH + SHIFT_MASK // 42 * +#define ASCII_2B KEY_MINUS // 43 + +#define ASCII_2C KEY_COMMA // 44 , +#define ASCII_2D KEY_SLASH // 45 - +#define ASCII_2E KEY_PERIOD // 46 . +#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / +#define ASCII_30 KEY_0 // 48 0 +#define ASCII_31 KEY_1 // 49 1 +#define ASCII_32 KEY_2 // 50 2 +#define ASCII_33 KEY_3 // 51 3 +#define ASCII_34 KEY_4 // 52 4 +#define ASCII_35 KEY_5 // 53 5 +#define ASCII_36 KEY_6 // 54 6 +#define ASCII_37 KEY_7 // 55 7 +#define ASCII_38 KEY_8 // 55 8 +#define ASCII_39 KEY_9 // 57 9 +#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : +#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; +#define ASCII_3C KEY_NON_US_100 // 60 < +#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = +#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > +#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_2 + ALTGR_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_8 + ALTGR_MASK // 91 [ +#define ASCII_5C KEY_EQUAL // 92 +#define ASCII_5D KEY_9 + ALTGR_MASK // 93 ] +#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ +#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ +#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Y // 121 y +#define ASCII_7A KEY_Z // 122 z +#define ASCII_7B KEY_7 + ALTGR_MASK // 123 { +#define ASCII_7C KEY_TILDE // 124 | +#define ASCII_7D KEY_0 + ALTGR_MASK // 125 } +#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 + +#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space +#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN +#define ISO_8859_1_A3 KEY_3 + ALTGR_MASK // 163 £ Pound Sign +#define ISO_8859_1_A4 KEY_4 + SHIFT_MASK // 164 ¤ Currency Sign +#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR +#define ISO_8859_1_A7 KEY_TILDE + SHIFT_MASK // 167 § SECTION SIGN +#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB KEY_4 // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN +#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN +#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF 0 // 175 ¯ MACRON +#define ISO_8859_1_B0 0 // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 KEY_M + ALTGR_MASK // 181 µ MICRO SIGN +#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT +#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA +#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD KEY_TILDE // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE +#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE +#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE +#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 KEY_LEFT_BRACE + SHIFT_MASK // 197 Å A RING ABOVE +#define ISO_8859_1_C6 KEY_QUOTE + SHIFT_MASK // 198 Æ AE +#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA +#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE +#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE +#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS +#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE +#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE +#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 KEY_D + ALTGR_MASK + SHIFT_MASK // 208 Ð ETH +#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE +#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE +#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE +#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE +#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION +#define ISO_8859_1_D8 KEY_SEMICOLON + SHIFT_MASK // 216 Ø O STROKE +#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE +#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE +#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS +#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE +#define ISO_8859_1_DE KEY_T + ALTGR_MASK + SHIFT_MASK // 222 Þ THORN +#define ISO_8859_1_DF KEY_S + ALTGR_MASK // 223 ß SHARP S +#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE +#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE +#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE +#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS +#define ISO_8859_1_E5 KEY_LEFT_BRACE // 229 å a RING ABOVE +#define ISO_8859_1_E6 KEY_QUOTE // 230 æ ae +#define ISO_8859_1_E7 0 // 231 ç c CEDILLA +#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE +#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE +#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS +#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE +#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE +#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS +#define ISO_8859_1_F0 KEY_D + ALTGR_MASK // 240 ð ETH +#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE +#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE +#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE +#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE +#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS +#define ISO_8859_1_F7 0 // 247 ÷ DIVISION +#define ISO_8859_1_F8 KEY_SEMICOLON // 248 ø o STROKE +#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE +#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE +#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS +#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE +#define ISO_8859_1_FE KEY_T + ALTGR_MASK // 254 þ THORN +#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS +#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign +// not yet implemented +#define UNICODE_EXTRA00 0x20AC +#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign + +#endif // LAYOUT_NORWEGIAN + + + + + + +#ifdef LAYOUT_SWEDISH + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define DEADKEYS_MASK 0x0700 +#define CIRCUMFLEX_BITS 0x0100 +#define ACUTE_ACCENT_BITS 0x0200 +#define GRAVE_ACCENT_BITS 0x0300 +#define TILDE_BITS 0x0400 +#define DIAERESIS_BITS 0x0500 +#define KEYCODE_TYPE uint16_t +#define DEADKEY_CIRCUMFLEX KEY_RIGHT_BRACE + SHIFT_MASK +#define DEADKEY_ACUTE_ACCENT KEY_EQUAL +#define DEADKEY_GRAVE_ACCENT KEY_EQUAL + SHIFT_MASK +#define DEADKEY_TILDE KEY_RIGHT_BRACE + ALTGR_MASK +#define DEADKEY_DIAERESIS KEY_RIGHT_BRACE +#define KEY_NON_US_100 63 + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! +#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " +#define ASCII_23 KEY_3 + SHIFT_MASK // 35 # +#define ASCII_24 KEY_4 + ALTGR_MASK // 36 $ +#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % +#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & +#define ASCII_27 KEY_BACKSLASH // 39 ' +#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) +#define ASCII_2A KEY_BACKSLASH + SHIFT_MASK // 42 * +#define ASCII_2B KEY_MINUS // 43 + +#define ASCII_2C KEY_COMMA // 44 , +#define ASCII_2D KEY_SLASH // 45 - +#define ASCII_2E KEY_PERIOD // 46 . +#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / +#define ASCII_30 KEY_0 // 48 0 +#define ASCII_31 KEY_1 // 49 1 +#define ASCII_32 KEY_2 // 50 2 +#define ASCII_33 KEY_3 // 51 3 +#define ASCII_34 KEY_4 // 52 4 +#define ASCII_35 KEY_5 // 53 5 +#define ASCII_36 KEY_6 // 54 6 +#define ASCII_37 KEY_7 // 55 7 +#define ASCII_38 KEY_8 // 55 8 +#define ASCII_39 KEY_9 // 57 9 +#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : +#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; +#define ASCII_3C KEY_NON_US_100 // 60 < +#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = +#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > +#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_2 + ALTGR_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_8 + ALTGR_MASK // 91 [ +#define ASCII_5C KEY_MINUS + ALTGR_MASK // 92 +#define ASCII_5D KEY_9 + ALTGR_MASK // 93 ] +#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ +#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ +#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Y // 121 y +#define ASCII_7A KEY_Z // 122 z +#define ASCII_7B KEY_7 + ALTGR_MASK // 123 { +#define ASCII_7C KEY_NON_US_100 + ALTGR_MASK // 124 | +#define ASCII_7D KEY_0 + ALTGR_MASK // 125 } +#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 + +#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space +#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN +#define ISO_8859_1_A3 KEY_3 + ALTGR_MASK // 163 £ Pound Sign +#define ISO_8859_1_A4 KEY_4 + SHIFT_MASK // 164 ¤ Currency Sign +#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR +#define ISO_8859_1_A7 KEY_TILDE // 167 § SECTION SIGN +#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB KEY_4 // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN +#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN +#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF 0 // 175 ¯ MACRON +#define ISO_8859_1_B0 0 // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 KEY_M + ALTGR_MASK // 181 µ MICRO SIGN +#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT +#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA +#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD KEY_TILDE + SHIFT_MASK // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE +#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE +#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE +#define ISO_8859_1_C4 KEY_QUOTE + SHIFT_MASK // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 KEY_LEFT_BRACE + SHIFT_MASK // 197 Å A RING ABOVE +#define ISO_8859_1_C6 0 // 198 Æ AE +#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA +#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE +#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE +#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS +#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE +#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE +#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 KEY_D + ALTGR_MASK + SHIFT_MASK // 208 Ð ETH +#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE +#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE +#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE +#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE +#define ISO_8859_1_D6 KEY_SEMICOLON + SHIFT_MASK // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION +#define ISO_8859_1_D8 0 // 216 Ø O STROKE +#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE +#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE +#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS +#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE +#define ISO_8859_1_DE KEY_T + ALTGR_MASK + SHIFT_MASK // 222 Þ THORN +#define ISO_8859_1_DF KEY_S + ALTGR_MASK // 223 ß SHARP S +#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE +#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE +#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE +#define ISO_8859_1_E4 KEY_QUOTE // 228 ä a DIAERESIS +#define ISO_8859_1_E5 KEY_LEFT_BRACE // 229 å a RING ABOVE +#define ISO_8859_1_E6 0 // 230 æ ae +#define ISO_8859_1_E7 0 // 231 ç c CEDILLA +#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE +#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE +#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS +#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE +#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE +#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS +#define ISO_8859_1_F0 KEY_D + ALTGR_MASK // 240 ð ETH +#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE +#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE +#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE +#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE +#define ISO_8859_1_F6 KEY_SEMICOLON // 246 ö o DIAERESIS +#define ISO_8859_1_F7 0 // 247 ÷ DIVISION +#define ISO_8859_1_F8 0 // 248 ø o STROKE +#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE +#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE +#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS +#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE +#define ISO_8859_1_FE KEY_T + ALTGR_MASK // 254 þ THORN +#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS +#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign +// not yet implemented +#define UNICODE_EXTRA00 0x20AC +#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign + +#endif // LAYOUT_SWEDISH + + + + + + +#ifdef LAYOUT_SPANISH + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define DEADKEYS_MASK 0x0700 +#define CIRCUMFLEX_BITS 0x0100 +#define ACUTE_ACCENT_BITS 0x0200 +#define GRAVE_ACCENT_BITS 0x0300 +#define TILDE_BITS 0x0400 +#define DIAERESIS_BITS 0x0500 +#define KEYCODE_TYPE uint16_t +#define DEADKEY_CIRCUMFLEX KEY_LEFT_BRACE + SHIFT_MASK +#define DEADKEY_ACUTE_ACCENT KEY_QUOTE +#define DEADKEY_GRAVE_ACCENT KEY_LEFT_BRACE +#define DEADKEY_TILDE KEY_4 + ALTGR_MASK +#define DEADKEY_DIAERESIS KEY_QUOTE + SHIFT_MASK +#define KEY_NON_US_100 63 + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! +#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " +#define ASCII_23 KEY_3 + ALTGR_MASK // 35 # +#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ +#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % +#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & +#define ASCII_27 KEY_MINUS // 39 ' +#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) +#define ASCII_2A KEY_RIGHT_BRACE + SHIFT_MASK // 42 * +#define ASCII_2B KEY_RIGHT_BRACE // 43 + +#define ASCII_2C KEY_COMMA // 44 , +#define ASCII_2D KEY_SLASH // 45 - +#define ASCII_2E KEY_PERIOD // 46 . +#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / +#define ASCII_30 KEY_0 // 48 0 +#define ASCII_31 KEY_1 // 49 1 +#define ASCII_32 KEY_2 // 50 2 +#define ASCII_33 KEY_3 // 51 3 +#define ASCII_34 KEY_4 // 52 4 +#define ASCII_35 KEY_5 // 53 5 +#define ASCII_36 KEY_6 // 54 6 +#define ASCII_37 KEY_7 // 55 7 +#define ASCII_38 KEY_8 // 55 8 +#define ASCII_39 KEY_9 // 57 9 +#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : +#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; +#define ASCII_3C KEY_NON_US_100 // 60 < +#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = +#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > +#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_2 + ALTGR_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_LEFT_BRACE + ALTGR_MASK // 91 [ +#define ASCII_5C KEY_TILDE + ALTGR_MASK // 92 +#define ASCII_5D KEY_RIGHT_BRACE + ALTGR_MASK // 93 ] +#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ +#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ +#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Y // 121 y +#define ASCII_7A KEY_Z // 122 z +#define ASCII_7B KEY_QUOTE + ALTGR_MASK // 123 { +#define ASCII_7C KEY_1 + ALTGR_MASK // 124 | +#define ASCII_7D KEY_BACKSLASH + ALTGR_MASK // 125 } +#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 + +#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space +#define ISO_8859_1_A1 KEY_EQUAL // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN +#define ISO_8859_1_A3 0 // 163 £ Pound Sign +#define ISO_8859_1_A4 0 // 164 ¤ Currency Sign +#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR +#define ISO_8859_1_A7 0 // 167 § SECTION SIGN +#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA KEY_TILDE + SHIFT_MASK // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC KEY_6 + ALTGR_MASK // 172 ¬ NOT SIGN +#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN +#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF 0 // 175 ¯ MACRON +#define ISO_8859_1_B0 0 // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN +#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 KEY_3 + SHIFT_MASK // 183 · MIDDLE DOT +#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA +#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA KEY_TILDE // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF KEY_EQUAL // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE +#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE +#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE +#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE +#define ISO_8859_1_C6 0 // 198 Æ AE +#define ISO_8859_1_C7 KEY_BACKSLASH + SHIFT_MASK // 199 Ç C CEDILLA +#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE +#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE +#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS +#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE +#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE +#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 0 // 208 Ð ETH +#define ISO_8859_1_D1 KEY_SEMICOLON + SHIFT_MASK // 209 Ñ N TILDE +#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE +#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE +#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE +#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION +#define ISO_8859_1_D8 0 // 216 Ø O STROKE +#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE +#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE +#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS +#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE +#define ISO_8859_1_DE 0 // 222 Þ THORN +#define ISO_8859_1_DF 0 // 223 ß SHARP S +#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE +#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE +#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE +#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS +#define ISO_8859_1_E5 0 // 229 å a RING ABOVE +#define ISO_8859_1_E6 0 // 230 æ ae +#define ISO_8859_1_E7 KEY_BACKSLASH // 231 ç c CEDILLA +#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE +#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE +#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS +#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE +#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE +#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS +#define ISO_8859_1_F0 0 // 240 ð ETH +#define ISO_8859_1_F1 KEY_SEMICOLON // 241 ñ n TILDE +#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE +#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE +#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE +#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS +#define ISO_8859_1_F7 0 // 247 ÷ DIVISION +#define ISO_8859_1_F8 0 // 248 ø o STROKE +#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE +#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE +#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS +#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE +#define ISO_8859_1_FE 0 // 254 þ THORN +#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS +#define UNICODE_20AC KEY_5 + ALTGR_MASK // € Euro Sign +// not yet implemented +#define UNICODE_EXTRA00 0x20AC +#define KEYCODE_EXTRA00 KEY_5 + ALTGR_MASK // 20AC € Euro Sign + +#endif // LAYOUT_SPANISH + + + + +#ifdef LAYOUT_PORTUGUESE + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define DEADKEYS_MASK 0x0700 +#define CIRCUMFLEX_BITS 0x0100 +#define ACUTE_ACCENT_BITS 0x0200 +#define GRAVE_ACCENT_BITS 0x0300 +#define TILDE_BITS 0x0400 +#define DIAERESIS_BITS 0x0500 +#define KEYCODE_TYPE uint16_t +#define DEADKEY_CIRCUMFLEX KEY_BACKSLASH +#define DEADKEY_ACUTE_ACCENT KEY_RIGHT_BRACE + SHIFT_MASK +#define DEADKEY_GRAVE_ACCENT KEY_RIGHT_BRACE + SHIFT_MASK +#define DEADKEY_TILDE KEY_BACKSLASH +#define DEADKEY_DIAERESIS KEY_LEFT_BRACE + SHIFT_MASK +#define KEY_NON_US_100 63 + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! +#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " +#define ASCII_23 KEY_3 + ALTGR_MASK // 35 # +#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ +#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % +#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & +#define ASCII_27 KEY_MINUS // 39 ' +#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) +#define ASCII_2A KEY_LEFT_BRACE + SHIFT_MASK // 42 * +#define ASCII_2B KEY_LEFT_BRACE // 43 + +#define ASCII_2C KEY_COMMA // 44 , +#define ASCII_2D KEY_SLASH // 45 - +#define ASCII_2E KEY_PERIOD // 46 . +#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / +#define ASCII_30 KEY_0 // 48 0 +#define ASCII_31 KEY_1 // 49 1 +#define ASCII_32 KEY_2 // 50 2 +#define ASCII_33 KEY_3 // 51 3 +#define ASCII_34 KEY_4 // 52 4 +#define ASCII_35 KEY_5 // 53 5 +#define ASCII_36 KEY_6 // 54 6 +#define ASCII_37 KEY_7 // 55 7 +#define ASCII_38 KEY_8 // 55 8 +#define ASCII_39 KEY_9 // 57 9 +#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : +#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; +#define ASCII_3C KEY_NON_US_100 // 60 < +#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = +#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > +#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_2 + ALTGR_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_8 + ALTGR_MASK // 91 [ +#define ASCII_5C KEY_TILDE + ALTGR_MASK // 92 +#define ASCII_5D KEY_9 + ALTGR_MASK // 93 ] +#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ +#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ +#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Y // 121 y +#define ASCII_7A KEY_Z // 122 z +#define ASCII_7B KEY_7 + ALTGR_MASK // 123 { +#define ASCII_7C KEY_TILDE + SHIFT_MASK // 124 | +#define ASCII_7D KEY_0 + ALTGR_MASK // 125 } +#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 + +#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space +#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN +#define ISO_8859_1_A3 KEY_3 + ALTGR_MASK // 163 £ Pound Sign +#define ISO_8859_1_A4 0 // 164 ¤ Currency Sign +#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR +#define ISO_8859_1_A7 KEY_4 + ALTGR_MASK // 167 § SECTION SIGN +#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA KEY_QUOTE + SHIFT_MASK // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB KEY_EQUAL // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN +#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN +#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF 0 // 175 ¯ MACRON +#define ISO_8859_1_B0 0 // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN +#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT +#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA +#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA KEY_QUOTE // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB KEY_EQUAL + SHIFT_MASK // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE +#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE +#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE +#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE +#define ISO_8859_1_C6 0 // 198 Æ AE +#define ISO_8859_1_C7 KEY_SEMICOLON + SHIFT_MASK // 199 Ç C CEDILLA +#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE +#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE +#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS +#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE +#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE +#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 0 // 208 Ð ETH +#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE +#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE +#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE +#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE +#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION +#define ISO_8859_1_D8 0 // 216 Ø O STROKE +#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE +#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE +#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS +#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE +#define ISO_8859_1_DE 0 // 222 Þ THORN +#define ISO_8859_1_DF 0 // 223 ß SHARP S +#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE +#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE +#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE +#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS +#define ISO_8859_1_E5 0 // 229 å a RING ABOVE +#define ISO_8859_1_E6 0 // 230 æ ae +#define ISO_8859_1_E7 KEY_SEMICOLON // 231 ç c CEDILLA +#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE +#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE +#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS +#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE +#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE +#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS +#define ISO_8859_1_F0 0 // 240 ð ETH +#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE +#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE +#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE +#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE +#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS +#define ISO_8859_1_F7 0 // 247 ÷ DIVISION +#define ISO_8859_1_F8 0 // 248 ø o STROKE +#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE +#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE +#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS +#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE +#define ISO_8859_1_FE 0 // 254 þ THORN +#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS +#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign +// not yet implemented +#define UNICODE_EXTRA00 0x20AC +#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign + +#endif // LAYOUT_PORTUGUESE + + + + + + + +#ifdef LAYOUT_ITALIAN + +#define SHIFT_MASK 0x40 +#define ALTGR_MASK 0x80 +#define KEYCODE_TYPE uint8_t +#define KEY_NON_US_100 63 + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! +#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " +#define ASCII_23 KEY_QUOTE + ALTGR_MASK // 35 # +#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ +#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % +#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & +#define ASCII_27 KEY_MINUS // 39 ' +#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) +#define ASCII_2A KEY_RIGHT_BRACE + SHIFT_MASK // 42 * +#define ASCII_2B KEY_RIGHT_BRACE // 43 + +#define ASCII_2C KEY_COMMA // 44 , +#define ASCII_2D KEY_SLASH // 45 - +#define ASCII_2E KEY_PERIOD // 46 . +#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / +#define ASCII_30 KEY_0 // 48 0 +#define ASCII_31 KEY_1 // 49 1 +#define ASCII_32 KEY_2 // 50 2 +#define ASCII_33 KEY_3 // 51 3 +#define ASCII_34 KEY_4 // 52 4 +#define ASCII_35 KEY_5 // 53 5 +#define ASCII_36 KEY_6 // 54 6 +#define ASCII_37 KEY_7 // 55 7 +#define ASCII_38 KEY_8 // 55 8 +#define ASCII_39 KEY_9 // 57 9 +#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : +#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; +#define ASCII_3C KEY_NON_US_100 // 60 < +#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = +#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > +#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_SEMICOLON + ALTGR_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_LEFT_BRACE + ALTGR_MASK // 91 [ +#define ASCII_5C KEY_TILDE // 92 +#define ASCII_5D KEY_RIGHT_BRACE + ALTGR_MASK // 93 ] +#define ASCII_5E KEY_EQUAL + SHIFT_MASK // 94 ^ +#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ +#define ASCII_60 0 // 96 ` (how to type this on Italian?) +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Y // 121 y +#define ASCII_7A KEY_Z // 122 z +#define ASCII_7B KEY_LEFT_BRACE + SHIFT_MASK + ALTGR_MASK // 123 { +#define ASCII_7C KEY_TILDE + SHIFT_MASK // 124 | +#define ASCII_7D KEY_RIGHT_BRACE + SHIFT_MASK + ALTGR_MASK // 125 } +#define ASCII_7E 0 // 126 ~ (how to type this on Italian?) +#define ASCII_7F KEY_BACKSPACE // 127 + +#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space +#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 0 // 162 ¢ Cent Sign +#define ISO_8859_1_A3 KEY_3 + SHIFT_MASK // 163 £ Pound Sign +#define ISO_8859_1_A4 0 // 164 ¤ Currency Sign +#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR +#define ISO_8859_1_A7 KEY_BACKSLASH + SHIFT_MASK // 167 § SECTION SIGN +#define ISO_8859_1_A8 0 // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN +#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN +#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF 0 // 175 ¯ MACRON +#define ISO_8859_1_B0 KEY_QUOTE + SHIFT_MASK // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 0 // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN +#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT +#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA +#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 0 // 192 À A GRAVE +#define ISO_8859_1_C1 0 // 193 Á A ACUTE +#define ISO_8859_1_C2 0 // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 0 // 195 Ã A TILDE +#define ISO_8859_1_C4 0 // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE +#define ISO_8859_1_C6 0 // 198 Æ AE +#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA +#define ISO_8859_1_C8 0 // 200 È E GRAVE +#define ISO_8859_1_C9 0 // 201 É E ACUTE +#define ISO_8859_1_CA 0 // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB 0 // 203 Ë E DIAERESIS +#define ISO_8859_1_CC 0 // 204 Ì I GRAVE +#define ISO_8859_1_CD 0 // 205 Í I ACUTE +#define ISO_8859_1_CE 0 // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF 0 // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 0 // 208 Ð ETH +#define ISO_8859_1_D1 0 // 209 Ñ N TILDE +#define ISO_8859_1_D2 0 // 210 Ò O GRAVE +#define ISO_8859_1_D3 0 // 211 Ó O ACUTE +#define ISO_8859_1_D4 0 // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 0 // 213 Õ O TILDE +#define ISO_8859_1_D6 0 // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION +#define ISO_8859_1_D8 0 // 216 Ø O STROKE +#define ISO_8859_1_D9 0 // 217 Ù U GRAVE +#define ISO_8859_1_DA 0 // 218 Ú U ACUTE +#define ISO_8859_1_DB 0 // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC 0 // 220 Ü U DIAERESIS +#define ISO_8859_1_DD 0 // 221 Ý Y ACUTE +#define ISO_8859_1_DE 0 // 222 Þ THORN +#define ISO_8859_1_DF 0 // 223 ß SHARP S +#define ISO_8859_1_E0 KEY_QUOTE // 224 à a GRAVE +#define ISO_8859_1_E1 0 // 225 á a ACUTE +#define ISO_8859_1_E2 0 // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 0 // 227 ã a TILDE +#define ISO_8859_1_E4 0 // 228 ä a DIAERESIS +#define ISO_8859_1_E5 0 // 229 å a RING ABOVE +#define ISO_8859_1_E6 0 // 230 æ ae +#define ISO_8859_1_E7 KEY_SEMICOLON + SHIFT_MASK // 231 ç c CEDILLA +#define ISO_8859_1_E8 KEY_LEFT_BRACE // 232 è e GRAVE +#define ISO_8859_1_E9 KEY_LEFT_BRACE + SHIFT_MASK // 233 é e ACUTE +#define ISO_8859_1_EA 0 // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB 0 // 235 ë e DIAERESIS +#define ISO_8859_1_EC KEY_EQUAL // 236 ì i GRAVE +#define ISO_8859_1_ED 0 // 237 í i ACUTE +#define ISO_8859_1_EE 0 // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF 0 // 239 ï i DIAERESIS +#define ISO_8859_1_F0 0 // 240 ð ETH +#define ISO_8859_1_F1 0 // 241 ñ n TILDE +#define ISO_8859_1_F2 KEY_SEMICOLON // 242 ò o GRAVE +#define ISO_8859_1_F3 0 // 243 ó o ACUTE +#define ISO_8859_1_F4 0 // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 0 // 245 õ o TILDE +#define ISO_8859_1_F6 0 // 246 ö o DIAERESIS +#define ISO_8859_1_F7 0 // 247 ÷ DIVISION +#define ISO_8859_1_F8 0 // 248 ø o STROKE +#define ISO_8859_1_F9 KEY_BACKSLASH // 249 ù u GRAVE +#define ISO_8859_1_FA 0 // 250 ú u ACUTE +#define ISO_8859_1_FB 0 // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC 0 // 252 ü u DIAERESIS +#define ISO_8859_1_FD 0 // 253 ý y ACUTE +#define ISO_8859_1_FE 0 // 254 þ THORN +#define ISO_8859_1_FF 0 // 255 ÿ y DIAERESIS + +#endif // LAYOUT_ITALIAN + + + + +#ifdef LAYOUT_PORTUGUESE_BRAZILIAN + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define DEADKEYS_MASK 0x0700 +#define CIRCUMFLEX_BITS 0x0100 +#define ACUTE_ACCENT_BITS 0x0200 +#define GRAVE_ACCENT_BITS 0x0300 +#define TILDE_BITS 0x0400 +#define DIAERESIS_BITS 0x0500 +#define KEYCODE_TYPE uint16_t +#define DEADKEY_CIRCUMFLEX KEY_QUOTE + SHIFT_MASK +#define DEADKEY_ACUTE_ACCENT KEY_LEFT_BRACE +#define DEADKEY_GRAVE_ACCENT KEY_LEFT_BRACE + SHIFT_MASK +#define DEADKEY_TILDE KEY_QUOTE +#define DEADKEY_DIAERESIS KEY_6 + SHIFT_MASK +#define KEY_NON_US_100 63 + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! +#define ASCII_22 KEY_TILDE + SHIFT_MASK // 34 " +#define ASCII_23 KEY_3 + ALTGR_MASK // 35 # +#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ +#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % +#define ASCII_26 KEY_7 + SHIFT_MASK // 38 & +#define ASCII_27 KEY_TILDE // 39 ' +#define ASCII_28 KEY_9 + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_0 + SHIFT_MASK // 41 ) +#define ASCII_2A KEY_7 + SHIFT_MASK // 42 * +#define ASCII_2B KEY_EQUAL + SHIFT_MASK // 43 + +#define ASCII_2C KEY_COMMA // 44 , +#define ASCII_2D KEY_MINUS // 45 - +#define ASCII_2E KEY_PERIOD // 46 . +#define ASCII_2F KEY_Q + ALTGR_MASK // 47 / +#define ASCII_30 KEY_0 // 48 0 +#define ASCII_31 KEY_1 // 49 1 +#define ASCII_32 KEY_2 // 50 2 +#define ASCII_33 KEY_3 // 51 3 +#define ASCII_34 KEY_4 // 52 4 +#define ASCII_35 KEY_5 // 53 5 +#define ASCII_36 KEY_6 // 54 6 +#define ASCII_37 KEY_7 // 55 7 +#define ASCII_38 KEY_8 // 55 8 +#define ASCII_39 KEY_9 // 57 9 +#define ASCII_3A KEY_SLASH + SHIFT_MASK // 58 : +#define ASCII_3B KEY_SLASH // 59 ; +#define ASCII_3C KEY_COMMA + SHIFT_MASK // 60 < +#define ASCII_3D KEY_EQUAL // 61 = +#define ASCII_3E KEY_PERIOD + SHIFT_MASK // 62 > +#define ASCII_3F KEY_W + ALTGR_MASK // 63 ? +#define ASCII_40 KEY_2 + SHIFT_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_RIGHT_BRACE // 91 [ +#define ASCII_5C KEY_NON_US_100 // 92 +#define ASCII_5D KEY_BACKSLASH // 93 ] +#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ +#define ASCII_5F KEY_MINUS + SHIFT_MASK // 95 _ +#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Y // 121 y +#define ASCII_7A KEY_Z // 122 z +#define ASCII_7B KEY_RIGHT_BRACE + SHIFT_MASK // 123 { +#define ASCII_7C KEY_NON_US_100 + SHIFT_MASK // 124 | +#define ASCII_7D KEY_BACKSLASH + SHIFT_MASK // 125 } +#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 + +#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space +#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 KEY_5 + ALTGR_MASK // 162 ¢ Cent SIGN +#define ISO_8859_1_A3 KEY_4 + ALTGR_MASK // 163 £ Pound Sign +#define ISO_8859_1_A4 0 // 164 ¤ Currency Sign +#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR +#define ISO_8859_1_A7 KEY_EQUAL + ALTGR_MASK // 167 § SECTION SIGN +#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA KEY_RIGHT_BRACE + ALTGR_MASK // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC KEY_6 + ALTGR_MASK // 172 ¬ NOT SIGN +#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN +#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF 0 // 175 ¯ MACRON +#define ISO_8859_1_B0 KEY_E + ALTGR_MASK // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 KEY_2 + ALTGR_MASK // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 KEY_2 + ALTGR_MASK // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN +#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT +#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA +#define ISO_8859_1_B9 KEY_1 + ALTGR_MASK // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA KEY_BACKSLASH + ALTGR_MASK // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE +#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE +#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE +#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE +#define ISO_8859_1_C6 0 // 198 Æ AE +#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA +#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE +#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE +#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS +#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE +#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE +#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 0 // 208 Ð ETH +#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE +#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE +#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE +#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE +#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION +#define ISO_8859_1_D8 0 // 216 Ø O STROKE +#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE +#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE +#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS +#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE +#define ISO_8859_1_DE 0 // 222 Þ THORN +#define ISO_8859_1_DF 0 // 223 ß SHARP S +#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE +#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE +#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE +#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS +#define ISO_8859_1_E5 0 // 229 å a RING ABOVE +#define ISO_8859_1_E6 0 // 230 æ ae +#define ISO_8859_1_E7 0 // 231 ç c CEDILLA +#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE +#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE +#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS +#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE +#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE +#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS +#define ISO_8859_1_F0 0 // 240 ð ETH +#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE +#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE +#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE +#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE +#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS +#define ISO_8859_1_F7 0 // 247 ÷ DIVISION +#define ISO_8859_1_F8 0 // 248 ø o STROKE +#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE +#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE +#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS +#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE +#define ISO_8859_1_FE 0 // 254 þ THORN +#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS + +#endif // LAYOUT_PORTUGUESE_BRAZILIAN + + + +#ifdef LAYOUT_FRENCH_BELGIAN + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define DEADKEYS_MASK 0x0700 +#define CIRCUMFLEX_BITS 0x0100 +#define GRAVE_ACCENT_BITS 0x0200 +#define DIAERESIS_BITS 0x0300 +#define TILDE_BITS 0x0400 +#define ACUTE_ACCENT_BITS 0x0500 +#define KEYCODE_TYPE uint16_t +#define DEADKEY_CIRCUMFLEX KEY_LEFT_BRACE +#define DEADKEY_ACUTE_ACCENT KEY_QUOTE + ALTGR_MASK +#define DEADKEY_GRAVE_ACCENT KEY_BACKSLASH + ALTGR_MASK +#define DEADKEY_DIAERESIS KEY_LEFT_BRACE + SHIFT_MASK +#define DEADKEY_TILDE KEY_SLASH + ALTGR_MASK +#define KEY_NON_US_100 63 + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_8 // 33 ! +#define ASCII_22 KEY_3 // 34 " +#define ASCII_23 KEY_3 + ALTGR_MASK // 35 # +#define ASCII_24 KEY_RIGHT_BRACE // 36 $ +#define ASCII_25 KEY_QUOTE + SHIFT_MASK // 37 % +#define ASCII_26 KEY_1 // 38 & +#define ASCII_27 KEY_4 // 39 ' +#define ASCII_28 KEY_5 // 40 ( +#define ASCII_29 KEY_MINUS // 41 ) +#define ASCII_2A KEY_RIGHT_BRACE + SHIFT_MASK // 42 * +#define ASCII_2B KEY_SLASH + SHIFT_MASK // 43 + +#define ASCII_2C KEY_M // 44 , +#define ASCII_2D KEY_EQUAL // 45 - +#define ASCII_2E KEY_COMMA + SHIFT_MASK // 46 . +#define ASCII_2F KEY_PERIOD + SHIFT_MASK // 47 / +#define ASCII_30 KEY_0 + SHIFT_MASK // 48 0 +#define ASCII_31 KEY_1 + SHIFT_MASK // 49 1 +#define ASCII_32 KEY_2 + SHIFT_MASK // 50 2 +#define ASCII_33 KEY_3 + SHIFT_MASK // 51 3 +#define ASCII_34 KEY_4 + SHIFT_MASK // 52 4 +#define ASCII_35 KEY_5 + SHIFT_MASK // 53 5 +#define ASCII_36 KEY_6 + SHIFT_MASK // 54 6 +#define ASCII_37 KEY_7 + SHIFT_MASK // 55 7 +#define ASCII_38 KEY_8 + SHIFT_MASK // 55 8 +#define ASCII_39 KEY_9 + SHIFT_MASK // 57 9 +#define ASCII_3A KEY_PERIOD // 58 : +#define ASCII_3B KEY_COMMA // 59 ; +#define ASCII_3C KEY_NON_US_100 // 60 < +#define ASCII_3D KEY_SLASH // 61 = +#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > +#define ASCII_3F KEY_M + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_2 + ALTGR_MASK // 64 @ +#define ASCII_41 KEY_Q + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_SEMICOLON + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_A + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_Z + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_W + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_RIGHT_BRACE + ALTGR_MASK // 91 [ +#define ASCII_5C KEY_NON_US_100 + ALTGR_MASK // 92 +#define ASCII_5D KEY_LEFT_BRACE + ALTGR_MASK // 93 ] +#define ASCII_5E KEY_6 + ALTGR_MASK // 94 ^ +#define ASCII_5F KEY_EQUAL + SHIFT_MASK // 95 _ +#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` +#define ASCII_61 KEY_Q // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_SEMICOLON // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_A // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_Z // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Y // 121 y +#define ASCII_7A KEY_W // 122 z +#define ASCII_7B KEY_9 + ALTGR_MASK // 123 { +#define ASCII_7C KEY_1 + ALTGR_MASK // 124 | +#define ASCII_7D KEY_0 + ALTGR_MASK // 125 } +#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 +#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space +#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN +#define ISO_8859_1_A3 KEY_BACKSLASH + SHIFT_MASK // 163 £ Pound Sign +#define ISO_8859_1_A4 0 // 164 ¤ Currency or Euro Sign +#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR +#define ISO_8859_1_A7 KEY_6 // 167 § SECTION SIGN +#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN +#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN +#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF 0 // 175 ¯ MACRON +#define ISO_8859_1_B0 KEY_MINUS + SHIFT_MASK // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 KEY_TILDE // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 KEY_TILDE + SHIFT_MASK // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 KEY_BACKSLASH // 181 µ MICRO SIGN +#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT +#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA +#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_Q + SHIFT_MASK // 192 À A GRAVE +#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_Q + SHIFT_MASK // 193 Á A ACUTE +#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_Q + SHIFT_MASK // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 TILDE_BITS + KEY_Q + SHIFT_MASK // 195 Ã A TILDE +#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_Q + SHIFT_MASK // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE +#define ISO_8859_1_C6 0 // 198 Æ AE +#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA +#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE +#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE +#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS +#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE +#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE +#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 0 // 208 Ð ETH +#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE +#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE +#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE +#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE +#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION +#define ISO_8859_1_D8 0 // 216 Ø O STROKE +#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE +#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE +#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U // 220 Ü U DIAERESIS +#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE +#define ISO_8859_1_DE 0 // 222 Þ THORN +#define ISO_8859_1_DF 0 // 223 ß SHARP S +#define ISO_8859_1_E0 KEY_0 // 224 à a GRAVE +#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_Q // 225 á a ACUTE +#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_Q // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 TILDE_BITS + KEY_Q // 227 ã a TILDE +#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_Q // 228 ä a DIAERESIS +#define ISO_8859_1_E5 0 // 229 å a RING ABOVE +#define ISO_8859_1_E6 0 // 230 æ ae +#define ISO_8859_1_E7 KEY_9 // 231 ç c CEDILLA +#define ISO_8859_1_E8 KEY_7 // 232 è e GRAVE +#define ISO_8859_1_E9 KEY_2 // 233 é e ACUTE +#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS +#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE +#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE +#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS +#define ISO_8859_1_F0 0 // 240 ð ETH +#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE +#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE +#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE +#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE +#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS +#define ISO_8859_1_F7 0 // 247 ÷ DIVISION +#define ISO_8859_1_F8 0 // 248 ø o STROKE +#define ISO_8859_1_F9 KEY_QUOTE // 249 ù u GRAVE - TODO; check FRENCH +#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE +#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS +#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE +#define ISO_8859_1_FE 0 // 254 þ THORN +#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS +#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign +// not yet implemented +#define UNICODE_EXTRA00 0x20AC +#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign + +#endif // LAYOUT_FRENCH_BELGIAN + + + + +#ifdef LAYOUT_GERMAN_SWISS + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define DEADKEYS_MASK 0x0700 +#define CIRCUMFLEX_BITS 0x0100 +#define GRAVE_ACCENT_BITS 0x0200 +#define DIAERESIS_BITS 0x0300 +#define TILDE_BITS 0x0400 +#define ACUTE_ACCENT_BITS 0x0500 +#define KEYCODE_TYPE uint16_t +#define DEADKEY_CIRCUMFLEX KEY_EQUAL +#define DEADKEY_ACUTE_ACCENT KEY_MINUS + ALTGR_MASK +#define DEADKEY_GRAVE_ACCENT KEY_EQUAL + SHIFT_MASK +#define DEADKEY_DIAERESIS KEY_RIGHT_BRACE +#define DEADKEY_TILDE KEY_EQUAL + ALTGR_MASK +#define KEY_NON_US_100 63 + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_RIGHT_BRACE + SHIFT_MASK // 33 ! +#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " +#define ASCII_23 KEY_3 + ALTGR_MASK // 35 # +#define ASCII_24 KEY_BACKSLASH // 36 $ +#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % +#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & +#define ASCII_27 KEY_MINUS // 39 ' +#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) +#define ASCII_2A KEY_3 + SHIFT_MASK // 42 * +#define ASCII_2B KEY_1 + SHIFT_MASK // 43 + +#define ASCII_2C KEY_COMMA // 44 , +#define ASCII_2D KEY_SLASH // 45 - +#define ASCII_2E KEY_PERIOD // 46 . +#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / +#define ASCII_30 KEY_0 // 48 0 +#define ASCII_31 KEY_1 // 49 1 +#define ASCII_32 KEY_2 // 50 2 +#define ASCII_33 KEY_3 // 51 3 +#define ASCII_34 KEY_4 // 52 4 +#define ASCII_35 KEY_5 // 53 5 +#define ASCII_36 KEY_6 // 54 6 +#define ASCII_37 KEY_7 // 55 7 +#define ASCII_38 KEY_8 // 55 8 +#define ASCII_39 KEY_9 // 57 9 +#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : +#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; +#define ASCII_3C KEY_NON_US_100 // 60 < +#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = +#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > +#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_2 + ALTGR_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Z + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Y + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_LEFT_BRACE + ALTGR_MASK // 91 [ +#define ASCII_5C KEY_NON_US_100 + ALTGR_MASK // 92 +#define ASCII_5D KEY_RIGHT_BRACE + ALTGR_MASK // 93 ] +#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ +#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ +#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Z // 121 y +#define ASCII_7A KEY_Y // 122 z +#define ASCII_7B KEY_QUOTE + ALTGR_MASK // 123 { +#define ASCII_7C KEY_7 + ALTGR_MASK // 124 | +#define ASCII_7D KEY_BACKSLASH + ALTGR_MASK // 125 } +#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 +#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space +#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 KEY_8 + ALTGR_MASK // 162 ¢ Cent Sign +#define ISO_8859_1_A3 KEY_BACKSLASH + SHIFT_MASK // 163 £ Pound Sign +#define ISO_8859_1_A4 0 // 164 ¤ Currency Sign +#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 KEY_1 + ALTGR_MASK // 166 ¦ BROKEN BAR +#define ISO_8859_1_A7 KEY_5 + ALTGR_MASK // 167 § SECTION SIGN +#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC KEY_6 + ALTGR_MASK // 172 ¬ NOT SIGN +#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN +#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF 0 // 175 ¯ MACRON +#define ISO_8859_1_B0 KEY_4 + ALTGR_MASK // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN +#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT +#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA +#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE +#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE +#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE +#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE +#define ISO_8859_1_C6 0 // 198 Æ AE +#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA +#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE +#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE +#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS +#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE +#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE +#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 0 // 208 Ð ETH +#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE +#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE +#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE +#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE +#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION +#define ISO_8859_1_D8 0 // 216 Ø O STROKE +#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE +#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE +#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS +#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE +#define ISO_8859_1_DE 0 // 222 Þ THORN +#define ISO_8859_1_DF 0 // 223 ß SHARP S +#define ISO_8859_1_E0 KEY_QUOTE + SHIFT_MASK // 224 à a GRAVE +#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE +#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE +#define ISO_8859_1_E4 KEY_QUOTE // 228 ä a DIAERESIS +#define ISO_8859_1_E5 0 // 229 å a RING ABOVE +#define ISO_8859_1_E6 0 // 230 æ ae +#define ISO_8859_1_E7 KEY_4 + SHIFT_MASK // 231 ç c CEDILLA +#define ISO_8859_1_E8 KEY_LEFT_BRACE + SHIFT_MASK // 232 è e GRAVE +#define ISO_8859_1_E9 KEY_SEMICOLON + SHIFT_MASK // 233 é e ACUTE +#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS TODO: check this +#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE +#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE +#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS +#define ISO_8859_1_F0 0 // 240 ð ETH +#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE +#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE +#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE +#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE +#define ISO_8859_1_F6 KEY_SEMICOLON // 246 ö o DIAERESIS +#define ISO_8859_1_F7 0 // 247 ÷ DIVISION +#define ISO_8859_1_F8 0 // 248 ø o STROKE +#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE +#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE +#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC KEY_LEFT_BRACE // 252 ü u DIAERESIS +#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE +#define ISO_8859_1_FE 0 // 254 þ THORN +#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS +#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign +// not yet implemented +#define UNICODE_EXTRA00 0x20AC +#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign + +#endif // LAYOUT_GERMAN_SWISS + + + + +#ifdef LAYOUT_FRENCH_SWISS + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define DEADKEYS_MASK 0x0700 +#define CIRCUMFLEX_BITS 0x0100 +#define GRAVE_ACCENT_BITS 0x0200 +#define DIAERESIS_BITS 0x0300 +#define TILDE_BITS 0x0400 +#define ACUTE_ACCENT_BITS 0x0500 +#define KEYCODE_TYPE uint16_t +#define DEADKEY_CIRCUMFLEX KEY_EQUAL +#define DEADKEY_ACUTE_ACCENT KEY_MINUS + ALTGR_MASK +#define DEADKEY_GRAVE_ACCENT KEY_EQUAL + SHIFT_MASK +#define DEADKEY_DIAERESIS KEY_RIGHT_BRACE +#define DEADKEY_TILDE KEY_EQUAL + ALTGR_MASK +#define KEY_NON_US_100 63 + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_RIGHT_BRACE + SHIFT_MASK // 33 ! +#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " +#define ASCII_23 KEY_3 + ALTGR_MASK // 35 # +#define ASCII_24 KEY_BACKSLASH // 36 $ +#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % +#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & +#define ASCII_27 KEY_MINUS // 39 ' +#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) +#define ASCII_2A KEY_3 + SHIFT_MASK // 42 * +#define ASCII_2B KEY_1 + SHIFT_MASK // 43 + +#define ASCII_2C KEY_COMMA // 44 , +#define ASCII_2D KEY_SLASH // 45 - +#define ASCII_2E KEY_PERIOD // 46 . +#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / +#define ASCII_30 KEY_0 // 48 0 +#define ASCII_31 KEY_1 // 49 1 +#define ASCII_32 KEY_2 // 50 2 +#define ASCII_33 KEY_3 // 51 3 +#define ASCII_34 KEY_4 // 52 4 +#define ASCII_35 KEY_5 // 53 5 +#define ASCII_36 KEY_6 // 54 6 +#define ASCII_37 KEY_7 // 55 7 +#define ASCII_38 KEY_8 // 55 8 +#define ASCII_39 KEY_9 // 57 9 +#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : +#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; +#define ASCII_3C KEY_NON_US_100 // 60 < +#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = +#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > +#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_2 + ALTGR_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Z + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Y + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_LEFT_BRACE + ALTGR_MASK // 91 [ +#define ASCII_5C KEY_NON_US_100 + ALTGR_MASK // 92 +#define ASCII_5D KEY_RIGHT_BRACE + ALTGR_MASK // 93 ] +#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ +#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ +#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Z // 121 y +#define ASCII_7A KEY_Y // 122 z +#define ASCII_7B KEY_QUOTE + ALTGR_MASK // 123 { +#define ASCII_7C KEY_7 + ALTGR_MASK // 124 | +#define ASCII_7D KEY_BACKSLASH + ALTGR_MASK // 125 } +#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 +#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space +#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 KEY_8 + ALTGR_MASK // 162 ¢ Cent Sign +#define ISO_8859_1_A3 KEY_BACKSLASH + SHIFT_MASK // 163 £ Pound Sign +#define ISO_8859_1_A4 0 // 164 ¤ Currency Sign +#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 KEY_1 + ALTGR_MASK // 166 ¦ BROKEN BAR +#define ISO_8859_1_A7 KEY_5 + ALTGR_MASK // 167 § SECTION SIGN +#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC KEY_6 + ALTGR_MASK // 172 ¬ NOT SIGN +#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN +#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF 0 // 175 ¯ MACRON +#define ISO_8859_1_B0 KEY_4 + ALTGR_MASK // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN +#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT +#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA +#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE +#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE +#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE +#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE +#define ISO_8859_1_C6 0 // 198 Æ AE +#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA +#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE +#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE +#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS +#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE +#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE +#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 0 // 208 Ð ETH +#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE +#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE +#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE +#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE +#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION +#define ISO_8859_1_D8 0 // 216 Ø O STROKE +#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE +#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE +#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS +#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE +#define ISO_8859_1_DE 0 // 222 Þ THORN +#define ISO_8859_1_DF 0 // 223 ß SHARP S +#define ISO_8859_1_E0 KEY_QUOTE // 224 à a GRAVE +#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE +#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE +#define ISO_8859_1_E4 KEY_QUOTE + SHIFT_MASK // 228 ä a DIAERESIS +#define ISO_8859_1_E5 0 // 229 å a RING ABOVE +#define ISO_8859_1_E6 0 // 230 æ ae +#define ISO_8859_1_E7 KEY_4 + SHIFT_MASK // 231 ç c CEDILLA +#define ISO_8859_1_E8 KEY_LEFT_BRACE // 232 è e GRAVE +#define ISO_8859_1_E9 KEY_SEMICOLON // 233 é e ACUTE +#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS +#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE +#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE +#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS +#define ISO_8859_1_F0 0 // 240 ð ETH +#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE +#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE +#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE +#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE +#define ISO_8859_1_F6 KEY_SEMICOLON + SHIFT_MASK // 246 ö o DIAERESIS +#define ISO_8859_1_F7 0 // 247 ÷ DIVISION +#define ISO_8859_1_F8 0 // 248 ø o STROKE +#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE +#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE +#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC KEY_LEFT_BRACE + SHIFT_MASK // 252 ü u DIAERESIS +#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE +#define ISO_8859_1_FE 0 // 254 þ THORN +#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS +#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign +// not yet implemented +#define UNICODE_EXTRA00 0x20AC +#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign + +#endif // LAYOUT_FRENCH_SWISS + + + + + +#ifdef LAYOUT_SPANISH_LATIN_AMERICA + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define DEADKEYS_MASK 0x0700 +#define CIRCUMFLEX_BITS 0x0100 +#define ACUTE_ACCENT_BITS 0x0200 +#define GRAVE_ACCENT_BITS 0x0300 +#define DIAERESIS_BITS 0x0400 +#define KEYCODE_TYPE uint16_t +#define DEADKEY_CIRCUMFLEX KEY_QUOTE + ALTGR_MASK +#define DEADKEY_ACUTE_ACCENT KEY_LEFT_BRACE +#define DEADKEY_GRAVE_ACCENT KEY_BACKSLASH + ALTGR_MASK +#define DEADKEY_DIAERESIS KEY_LEFT_BRACE + SHIFT_MASK +#define KEY_NON_US_100 63 + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! +#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " +#define ASCII_23 KEY_3 + ALTGR_MASK // 35 # +#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ +#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % +#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & +#define ASCII_27 KEY_MINUS // 39 ' +#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) +#define ASCII_2A KEY_RIGHT_BRACE + SHIFT_MASK // 42 * +#define ASCII_2B KEY_RIGHT_BRACE // 43 + +#define ASCII_2C KEY_COMMA // 44 , +#define ASCII_2D KEY_SLASH // 45 - +#define ASCII_2E KEY_PERIOD // 46 . +#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / +#define ASCII_30 KEY_0 // 48 0 +#define ASCII_31 KEY_1 // 49 1 +#define ASCII_32 KEY_2 // 50 2 +#define ASCII_33 KEY_3 // 51 3 +#define ASCII_34 KEY_4 // 52 4 +#define ASCII_35 KEY_5 // 53 5 +#define ASCII_36 KEY_6 // 54 6 +#define ASCII_37 KEY_7 // 55 7 +#define ASCII_38 KEY_8 // 55 8 +#define ASCII_39 KEY_9 // 57 9 +#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : +#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; +#define ASCII_3C KEY_NON_US_100 // 60 < +#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = +#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > +#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_Q + ALTGR_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_QUOTE + SHIFT_MASK // 91 [ +#define ASCII_5C KEY_MINUS + ALTGR_MASK // 92 +#define ASCII_5D KEY_BACKSLASH + SHIFT_MASK // 93 ] +#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ +#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ +#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Y // 121 y +#define ASCII_7A KEY_Z // 122 z +#define ASCII_7B KEY_QUOTE // 123 { +#define ASCII_7C KEY_TILDE // 124 | +#define ASCII_7D KEY_BACKSLASH // 125 } +#define ASCII_7E KEY_RIGHT_BRACE + ALTGR_MASK // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 + +#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space +#define ISO_8859_1_A1 KEY_EQUAL + SHIFT_MASK // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN +#define ISO_8859_1_A3 0 // 163 £ Pound Sign +#define ISO_8859_1_A4 0 // 164 ¤ Currency Sign +#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR +#define ISO_8859_1_A7 0 // 167 § SECTION SIGN +#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC KEY_TILDE + ALTGR_MASK // 172 ¬ NOT SIGN +#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN +#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF 0 // 175 ¯ MACRON +#define ISO_8859_1_B0 KEY_TILDE + SHIFT_MASK // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN +#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT +#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA +#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF KEY_EQUAL // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE +#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE +#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 0 // 195 Ã A TILDE +#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE +#define ISO_8859_1_C6 0 // 198 Æ AE +#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA +#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE +#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE +#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS +#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE +#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE +#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 0 // 208 Ð ETH +#define ISO_8859_1_D1 KEY_SEMICOLON + SHIFT_MASK // 209 Ñ N TILDE +#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE +#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE +#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 0 // 213 Õ O TILDE +#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION +#define ISO_8859_1_D8 0 // 216 Ø O STROKE +#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE +#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE +#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS +#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE +#define ISO_8859_1_DE 0 // 222 Þ THORN +#define ISO_8859_1_DF 0 // 223 ß SHARP S +#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE +#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE +#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 0 // 227 ã a TILDE +#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS +#define ISO_8859_1_E5 0 // 229 å a RING ABOVE +#define ISO_8859_1_E6 0 // 230 æ ae +#define ISO_8859_1_E7 0 // 231 ç c CEDILLA +#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE +#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE +#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS +#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE +#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE +#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS +#define ISO_8859_1_F0 0 // 240 ð ETH +#define ISO_8859_1_F1 KEY_SEMICOLON // 241 ñ n TILDE +#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE +#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE +#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 0 // 245 õ o TILDE +#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS +#define ISO_8859_1_F7 0 // 247 ÷ DIVISION +#define ISO_8859_1_F8 0 // 248 ø o STROKE +#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE +#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE +#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS +#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE +#define ISO_8859_1_FE 0 // 254 þ THORN +#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS + +#endif // LAYOUT_SPANISH_LATIN_AMERICA + + + +#ifdef LAYOUT_IRISH + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define DEADKEYS_MASK 0x0300 +#define GRAVE_ACCENT_BITS 0x0100 +#define ACUTE_ACCENT_BITS 0x0200 +#define KEYCODE_TYPE uint16_t +#define DEADKEY_ACUTE_ACCENT KEY_QUOTE + ALTGR_MASK +#define DEADKEY_GRAVE_ACCENT KEY_TILDE +#define KEY_NON_US_100 63 + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! +#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " +#define ASCII_23 KEY_BACKSPACE // 35 # +#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ +#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % +#define ASCII_26 KEY_7 + SHIFT_MASK // 38 & +#define ASCII_27 KEY_QUOTE // 39 ' +#define ASCII_28 KEY_9 + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_0 + SHIFT_MASK // 41 ) +#define ASCII_2A KEY_8 + SHIFT_MASK // 42 * +#define ASCII_2B KEY_EQUAL + SHIFT_MASK // 43 + +#define ASCII_2C KEY_COMMA // 44 , +#define ASCII_2D KEY_MINUS // 45 - +#define ASCII_2E KEY_PERIOD // 46 . +#define ASCII_2F KEY_SLASH // 47 / +#define ASCII_30 KEY_0 // 48 0 +#define ASCII_31 KEY_1 // 49 1 +#define ASCII_32 KEY_2 // 50 2 +#define ASCII_33 KEY_3 // 51 3 +#define ASCII_34 KEY_4 // 52 4 +#define ASCII_35 KEY_5 // 53 5 +#define ASCII_36 KEY_6 // 54 6 +#define ASCII_37 KEY_7 // 55 7 +#define ASCII_38 KEY_8 // 55 8 +#define ASCII_39 KEY_9 // 57 9 +#define ASCII_3A KEY_SEMICOLON + SHIFT_MASK // 58 : +#define ASCII_3B KEY_SEMICOLON // 59 ; +#define ASCII_3C KEY_COMMA + SHIFT_MASK // 60 < +#define ASCII_3D KEY_EQUAL // 61 = +#define ASCII_3E KEY_PERIOD + SHIFT_MASK // 62 > +#define ASCII_3F KEY_SLASH + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_QUOTE + SHIFT_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_LEFT_BRACE // 91 [ +#define ASCII_5C KEY_NON_US_100 // 92 +#define ASCII_5D KEY_RIGHT_BRACE // 93 ] +#define ASCII_5E KEY_6 + SHIFT_MASK // 94 ^ +#define ASCII_5F KEY_MINUS + SHIFT_MASK // 95 _ +#define ASCII_60 KEY_QUOTE + SHIFT_MASK + ALTGR_MASK // 96 ` +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Y // 121 y +#define ASCII_7A KEY_Z // 122 z +#define ASCII_7B KEY_LEFT_BRACE + SHIFT_MASK // 123 { +#define ASCII_7C KEY_NON_US_100 + SHIFT_MASK // 124 | +#define ASCII_7D KEY_RIGHT_BRACE + SHIFT_MASK // 125 } +#define ASCII_7E KEY_BACKSLASH + SHIFT_MASK // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 + +#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space +#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN +#define ISO_8859_1_A3 KEY_3 + SHIFT_MASK // 163 £ Pound Sign +#define ISO_8859_1_A4 0 // 164 ¤ Currency or Euro Sign +#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 KEY_TILDE + ALTGR_MASK // 166 ¦ BROKEN BAR +#define ISO_8859_1_A7 0 // 167 § SECTION SIGN +#define ISO_8859_1_A8 0 // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC KEY_TILDE + SHIFT_MASK // 172 ¬ NOT SIGN +#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN +#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF 0 // 175 ¯ MACRON +#define ISO_8859_1_B0 0 // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 0 // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN +#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT +#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA +#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A // 192 À A GRAVE +#define ISO_8859_1_C1 KEY_A + ALTGR_MASK + SHIFT_MASK // 193 Á A ACUTE +#define ISO_8859_1_C2 0 // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 0 // 195 Ã A TILDE +#define ISO_8859_1_C4 0 // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE +#define ISO_8859_1_C6 0 // 198 Æ AE +#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA +#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E // 200 È E GRAVE +#define ISO_8859_1_C9 KEY_E + ALTGR_MASK + SHIFT_MASK // 201 É E ACUTE +#define ISO_8859_1_CA 0 // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB 0 // 203 Ë E DIAERESIS +#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I // 204 Ì I GRAVE +#define ISO_8859_1_CD KEY_I + ALTGR_MASK + SHIFT_MASK // 205 Í I ACUTE +#define ISO_8859_1_CE 0 // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF 0 // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 0 // 208 Ð ETH +#define ISO_8859_1_D1 0 // 209 Ñ N TILDE +#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O // 210 Ò O GRAVE +#define ISO_8859_1_D3 KEY_O + ALTGR_MASK + SHIFT_MASK // 211 Ó O ACUTE +#define ISO_8859_1_D4 0 // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 0 // 213 Õ O TILDE +#define ISO_8859_1_D6 0 // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION +#define ISO_8859_1_D8 0 // 216 Ø O STROKE +#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U // 217 Ù U GRAVE +#define ISO_8859_1_DA KEY_U + ALTGR_MASK + SHIFT_MASK // 218 Ú U ACUTE +#define ISO_8859_1_DB 0 // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC 0 // 220 Ü U DIAERESIS +#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE +#define ISO_8859_1_DE 0 // 222 Þ THORN +#define ISO_8859_1_DF 0 // 223 ß SHARP S +#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE +#define ISO_8859_1_E1 KEY_A + ALTGR_MASK // 225 á a ACUTE +#define ISO_8859_1_E2 0 // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 0 // 227 ã a TILDE +#define ISO_8859_1_E4 0 // 228 ä a DIAERESIS +#define ISO_8859_1_E5 0 // 229 å a RING ABOVE +#define ISO_8859_1_E6 0 // 230 æ ae +#define ISO_8859_1_E7 0 // 231 ç c CEDILLA +#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE +#define ISO_8859_1_E9 KEY_E + ALTGR_MASK // 233 é e ACUTE +#define ISO_8859_1_EA 0 // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB 0 // 235 ë e DIAERESIS +#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE +#define ISO_8859_1_ED KEY_I + ALTGR_MASK // 237 í i ACUTE +#define ISO_8859_1_EE 0 // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF 0 // 239 ï i DIAERESIS +#define ISO_8859_1_F0 0 // 240 ð ETH +#define ISO_8859_1_F1 0 // 241 ñ n TILDE +#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE +#define ISO_8859_1_F3 KEY_O + ALTGR_MASK // 243 ó o ACUTE +#define ISO_8859_1_F4 0 // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 0 // 245 õ o TILDE +#define ISO_8859_1_F6 0 // 246 ö o DIAERESIS +#define ISO_8859_1_F7 0 // 247 ÷ DIVISION +#define ISO_8859_1_F8 0 // 248 ø o STROKE +#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE +#define ISO_8859_1_FA KEY_U + ALTGR_MASK // 250 ú u ACUTE +#define ISO_8859_1_FB 0 // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC 0 // 252 ü u DIAERESIS +#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE +#define ISO_8859_1_FE 0 // 254 þ THORN +#define ISO_8859_1_FF 0 // 255 ÿ y DIAERESIS +#define UNICODE_20AC KEY_4 + ALTGR_MASK // € Euro Sign +// not yet implemented +#define UNICODE_EXTRA00 0x20AC +#define KEYCODE_EXTRA00 KEY_4 + ALTGR_MASK // 20AC € Euro Sign + +#endif // LAYOUT_IRISH + + + + +#ifdef LAYOUT_ICELANDIC + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define DEADKEYS_MASK 0x0700 +#define CIRCUMFLEX_BITS 0x0100 +#define ACUTE_ACCENT_BITS 0x0200 +#define GRAVE_ACCENT_BITS 0x0300 +#define DIAERESIS_BITS 0x0400 +#define RING_ABOVE_BITS 0x0500 +#define KEYCODE_TYPE uint16_t +#define DEADKEY_CIRCUMFLEX KEY_QUOTE + ALTGR_MASK +#define DEADKEY_ACUTE_ACCENT KEY_QUOTE +#define DEADKEY_GRAVE_ACCENT KEY_BACKSLASH + ALTGR_MASK +#define DEADKEY_DIAERESIS KEY_TILDE + SHIFT_MASK +#define DEADKEY_RING_ABOVE KEY_TILDE +#define KEY_NON_US_100 63 + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! +#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " +#define ASCII_23 KEY_3 + SHIFT_MASK // 35 # +#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ +#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % +#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & +#define ASCII_27 KEY_QUOTE + SHIFT_MASK // 39 ' +#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) +#define ASCII_2A KEY_BACKSLASH + SHIFT_MASK // 42 * +#define ASCII_2B KEY_BACKSLASH // 43 + +#define ASCII_2C KEY_COMMA // 44 , +#define ASCII_2D KEY_EQUAL // 45 - +#define ASCII_2E KEY_PERIOD // 46 . +#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / +#define ASCII_30 KEY_0 // 48 0 +#define ASCII_31 KEY_1 // 49 1 +#define ASCII_32 KEY_2 // 50 2 +#define ASCII_33 KEY_3 // 51 3 +#define ASCII_34 KEY_4 // 52 4 +#define ASCII_35 KEY_5 // 53 5 +#define ASCII_36 KEY_6 // 54 6 +#define ASCII_37 KEY_7 // 55 7 +#define ASCII_38 KEY_8 // 55 8 +#define ASCII_39 KEY_9 // 57 9 +#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : +#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; +#define ASCII_3C KEY_NON_US_100 // 60 < +#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = +#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > +#define ASCII_3F KEY_RIGHT_BRACE + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_Q + ALTGR_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_8 + ALTGR_MASK // 91 [ +#define ASCII_5C KEY_MINUS + ALTGR_MASK // 92 +#define ASCII_5D KEY_9 + ALTGR_MASK // 93 ] +#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ +#define ASCII_5F KEY_EQUAL + SHIFT_MASK // 95 _ +#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Y // 121 y +#define ASCII_7A KEY_Z // 122 z +#define ASCII_7B KEY_7 + ALTGR_MASK // 123 { +#define ASCII_7C KEY_NON_US_100 + ALTGR_MASK // 124 | +#define ASCII_7D KEY_0 + ALTGR_MASK // 125 } +#define ASCII_7E KEY_RIGHT_BRACE + ALTGR_MASK // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 + +#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space +#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN +#define ISO_8859_1_A3 0 // 163 £ Pound Sign +#define ISO_8859_1_A4 0 // 164 ¤ Currency or Euro Sign +#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR ?? +#define ISO_8859_1_A7 0 // 167 § SECTION SIGN +#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN ?? +#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN +#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF 0 // 175 ¯ MACRON +#define ISO_8859_1_B0 KEY_TILDE + ALTGR_MASK // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 KEY_M + ALTGR_MASK // 181 µ MICRO SIGN +#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT +#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA +#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE +#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + ALTGR_MASK // 193 Á A ACUTE +#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 0 // 195 Ã A TILDE +#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 RING_ABOVE_BITS + KEY_A + SHIFT_MASK // 197 Å A RING ABOVE +#define ISO_8859_1_C6 KEY_SEMICOLON + SHIFT_MASK // 198 Æ AE +#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA +#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE +#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE +#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS +#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE +#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE +#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 KEY_LEFT_BRACE + SHIFT_MASK // 208 Ð ETH +#define ISO_8859_1_D1 0 // 209 Ñ N TILDE +#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE +#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE +#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 0 // 213 Õ O TILDE +#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION +#define ISO_8859_1_D8 0 // 216 Ø O STROKE +#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE +#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE +#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS +#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE +#define ISO_8859_1_DE KEY_SLASH + SHIFT_MASK // 222 Þ THORN +#define ISO_8859_1_DF 0 // 223 ß SHARP S +#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE +#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE +#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 0 // 227 ã a TILDE +#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS +#define ISO_8859_1_E5 RING_ABOVE_BITS + KEY_A // 229 å a RING ABOVE +#define ISO_8859_1_E6 KEY_SEMICOLON // 230 æ ae +#define ISO_8859_1_E7 0 // 231 ç c CEDILLA +#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE +#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE +#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS +#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE +#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE +#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS +#define ISO_8859_1_F0 KEY_LEFT_BRACE // 240 ð ETH +#define ISO_8859_1_F1 0 // 241 ñ n TILDE +#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE +#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE +#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 0 // 245 õ o TILDE +#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS +#define ISO_8859_1_F7 0 // 247 ÷ DIVISION +#define ISO_8859_1_F8 0 // 248 ø o STROKE +#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE +#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE +#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS +#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE +#define ISO_8859_1_FE KEY_SLASH // 254 þ THORN +#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS +#define UNICODE_20AC KEY_5 + ALTGR_MASK // € Euro Sign +// not yet implemented +#define UNICODE_EXTRA00 0x20AC +#define KEYCODE_EXTRA00 KEY_5 + ALTGR_MASK // 20AC € Euro Sign + +#endif // LAYOUT_ICELANDIC + + + +#ifdef LAYOUT_TURKISH +// http://forum.pjrc.com/threads/18781-Turkish-Language-Support + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define DEADKEYS_MASK 0x0700 +#define CIRCUMFLEX_BITS 0x0100 +#define ACUTE_ACCENT_BITS 0x0200 +#define GRAVE_ACCENT_BITS 0x0300 +#define TILDE_BITS 0x0400 +#define DIAERESIS_BITS 0x0500 +#define KEYCODE_TYPE uint16_t +#define DEADKEY_CIRCUMFLEX KEY_3 + SHIFT_MASK +#define DEADKEY_ACUTE_ACCENT KEY_SEMICOLON + ALTGR_MASK +#define DEADKEY_GRAVE_ACCENT KEY_BACKSLASH + ALTGR_MASK +#define DEADKEY_TILDE KEY_RIGHT_BRACE + ALTGR_MASK +#define DEADKEY_DIAERESIS KEY_LEFT_BRACE + ALTGR_MASK + +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! +#define ASCII_22 KEY_TILDE // 34 " +#define ASCII_23 KEY_3 + ALTGR_MASK // 35 # +#define ASCII_24 KEY_4 + ALTGR_MASK // 36 $ +#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % +#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & +#define ASCII_27 KEY_2 + SHIFT_MASK // 39 ' +#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) +#define ASCII_2A KEY_MINUS // 42 * +#define ASCII_2B KEY_4 + SHIFT_MASK // 43 + +#define ASCII_2C KEY_BACKSLASH // 44 , +#define ASCII_2D KEY_EQUAL // 45 - +#define ASCII_2E KEY_SLASH // 46 . +#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / +#define ASCII_30 KEY_0 // 48 0 +#define ASCII_31 KEY_1 // 49 1 +#define ASCII_32 KEY_2 // 50 2 +#define ASCII_33 KEY_3 // 51 3 +#define ASCII_34 KEY_4 // 52 4 +#define ASCII_35 KEY_5 // 53 5 +#define ASCII_36 KEY_6 // 54 6 +#define ASCII_37 KEY_7 // 55 7 +#define ASCII_38 KEY_8 // 55 8 +#define ASCII_39 KEY_9 // 57 9 +#define ASCII_3A KEY_SLASH + SHIFT_MASK // 58 : +#define ASCII_3B KEY_BACKSLASH + SHIFT_MASK // 59 ; +#define ASCII_3C KEY_TILDE + ALTGR_MASK // 60 < +#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = +#define ASCII_3E KEY_1 + ALTGR_MASK // 62 > +#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_Q + ALTGR_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_8 + ALTGR_MASK // 91 [ +#define ASCII_5C KEY_MINUS + ALTGR_MASK // 92 +#define ASCII_5D KEY_9 + ALTGR_MASK // 93 ] +#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ +#define ASCII_5F KEY_EQUAL + SHIFT_MASK // 95 _ +#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_QUOTE // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Y // 121 y +#define ASCII_7A KEY_Z // 122 z +#define ASCII_7B KEY_7 + ALTGR_MASK // 123 { +#define ASCII_7C KEY_EQUAL + ALTGR_MASK // 124 | +#define ASCII_7D KEY_0 + ALTGR_MASK // 125 } +#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ +#define ASCII_7F KEY_BACKSPACE // 127 + +#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space +#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN +#define ISO_8859_1_A3 KEY_2 + ALTGR_MASK // 163 £ Pound Sign +#define ISO_8859_1_A4 0 // 164 ¤ Currency or Euro Sign +#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR ?? +#define ISO_8859_1_A7 0 // 167 § SECTION SIGN +#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN ?? +#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN +#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF 0 // 175 ¯ MACRON +#define ISO_8859_1_B0 0 // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN +#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT +#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA +#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD KEY_5 + ALTGR_MASK // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE +#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE +#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE +#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE +#define ISO_8859_1_C6 KEY_A + ALTGR_MASK // 198 Æ AE +#define ISO_8859_1_C7 KEY_PERIOD + SHIFT_MASK // 199 Ç C CEDILLA +#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE +#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE +#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS +#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE +#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE +#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 0 // 208 Ð ETH +#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE +#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE +#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE +#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE +#define ISO_8859_1_D6 KEY_COMMA + SHIFT_MASK // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION +#define ISO_8859_1_D8 0 // 216 Ø O STROKE +#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE +#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE +#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC KEY_RIGHT_BRACE + SHIFT_MASK // 220 Ü U DIAERESIS +#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE +#define ISO_8859_1_DE 0 // 222 Þ THORN +#define ISO_8859_1_DF KEY_S + ALTGR_MASK // 223 ß SHARP S +#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE +#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE +#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE +#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS +#define ISO_8859_1_E5 0 // 229 å a RING ABOVE +#define ISO_8859_1_E6 0 // 230 æ ae +#define ISO_8859_1_E7 KEY_PERIOD // 231 ç c CEDILLA +#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE +#define ISO_8859_1_E9 KEY_TILDE + SHIFT_MASK // 233 é e ACUTE +#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS +#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE +#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE +#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS +#define ISO_8859_1_F0 0 // 240 ð ETH +#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE +#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE +#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE +#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE +#define ISO_8859_1_F6 KEY_COMMA // 246 ö o DIAERESIS +#define ISO_8859_1_F7 0 // 247 ÷ DIVISION +#define ISO_8859_1_F8 0 // 248 ø o STROKE +#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE +#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE +#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC KEY_RIGHT_BRACE // 252 ü u DIAERESIS +#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE +#define ISO_8859_1_FE 0 // 254 þ THORN +#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS +#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign + +// not yet implemented +#define UNICODE_EXTRA00 0x20AC +#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign +#define UNICODE_EXTRA01 0x011E +#define KEYCODE_EXTRA01 KEY_LEFT_BRACE + SHIFT_MASK // 011E Ğ Latin capital letter G with breve +#define UNICODE_EXTRA02 0x011F +#define KEYCODE_EXTRA02 KEY_LEFT_BRACE // 011F ğ Latin small letter g with breve +#define UNICODE_EXTRA03 0x0130 +#define KEYCODE_EXTRA03 KEY_QUOTE + SHIFT_MASK // 0130 İ Latin captial letter I with dot above +#define UNICODE_EXTRA04 0x0131 +#define KEYCODE_EXTRA04 KEY_I // 0131 ı Latin small letter dotless i +#define UNICODE_EXTRA05 0x015E +#define KEYCODE_EXTRA05 KEY_SEMICOLON + SHIFT_MASK // 015E Ş Latin capital letter S with cedilla +#define UNICODE_EXTRA06 0x0151 +#define KEYCODE_EXTRA06 KEY_SEMICOLON // 0151 ş Latin small letter s with cedilla + +#endif // LAYOUT_TURKISH + + + +#ifdef LAYOUT_CZECH +// http://forum.pjrc.com/threads/24495-Czech-keyboard + +#define SHIFT_MASK 0x0040 +#define ALTGR_MASK 0x0080 +#define DEADKEYS_MASK 0x0F00 +#define ACUTE_ACCENT_BITS 0x0100 // TODO: the Czech might not support some +#define DEGREE_SIGN_BITS 0x0200 // of these deadkeys, perhaps not any??? +#define CARON_BITS 0x0300 +//#define CIRCUMFLEX_BITS 0x0400 +#define BREVE_BITS 0x0500 +#define OGONEK_BITS 0x0600 +//#define GRAVE_ACCENT_BITS 0x0700 +#define DOT_ABOVE_BITS 0x0800 +#define DOUBLE_ACUTE_BITS 0x0900 +//#define DIAERESIS_BITS 0x0A00 +#define CEDILLA_BITS 0x0B00 +#define KEYCODE_TYPE uint16_t +#define DEADKEY_ACUTE_ACCENT KEY_EQUAL // TODO: is it KEY_9 + ALTGR_MASK +#define DEADKEY_DEGREE_SIGN KEY_TILDE + SHIFT_MASK // TODO: is it KEY_5 + ALTGR_MASK +#define DEADKEY_CARON KEY_EQUAL + SHIFT_MASK // TODO: is it KEY_2 + ALTGR_MASK +//#define DEADKEY_CIRCUMFLEX KEY_3 + ALTGR_MASK +#define DEADKEY_BREVE KEY_4 + ALTGR_MASK +#define DEADKEY_OGONEK KEY_6 + ALTGR_MASK +//#define DEADKEY_GRAVE_ACCENT KEY_7 + ALTGR_MASK +#define DEADKEY_DOT_ABOVE KEY_8 + ALTGR_MASK +#define DEADKEY_DOUBLE_ACUTE KEY_0 + ALTGR_MASK +#define DEADKEY_DIAERESIS KEY_MINUS + ALTGR_MASK +#define DEADKEY_CEDILLA KEY_EQUAL + ALTGR_MASK +#define KEY_NON_US_100 63 +#define ASCII_20 KEY_SPACE // 32 +#define ASCII_21 KEY_QUOTE + SHIFT_MASK // 33 ! +#define ASCII_22 KEY_SEMICOLON + SHIFT_MASK // 34 " +#define ASCII_23 KEY_X + ALTGR_MASK // 35 # +#define ASCII_24 KEY_SEMICOLON + ALTGR_MASK // 36 $ +#define ASCII_25 KEY_MINUS + SHIFT_MASK // 37 % +#define ASCII_26 KEY_C + ALTGR_MASK // 38 & +#define ASCII_27 KEY_BACKSLASH + SHIFT_MASK // 39 ' +#define ASCII_28 KEY_RIGHT_BRACE + SHIFT_MASK // 40 ( +#define ASCII_29 KEY_RIGHT_BRACE // 41 ) +#define ASCII_2A KEY_SLASH + ALTGR_MASK // 42 * +#define ASCII_2B KEY_1 // 43 + +#define ASCII_2C KEY_COMMA // 44 , +#define ASCII_2D KEY_SLASH // 45 - +#define ASCII_2E KEY_PERIOD // 46 . +#define ASCII_2F KEY_LEFT_BRACE + SHIFT_MASK // 47 / +#define ASCII_30 KEY_0 + SHIFT_MASK // 48 0 +#define ASCII_31 KEY_1 + SHIFT_MASK // 49 1 +#define ASCII_32 KEY_2 + SHIFT_MASK // 50 2 +#define ASCII_33 KEY_3 + SHIFT_MASK // 51 3 +#define ASCII_34 KEY_4 + SHIFT_MASK // 52 4 +#define ASCII_35 KEY_5 + SHIFT_MASK // 53 5 +#define ASCII_36 KEY_6 + SHIFT_MASK // 54 6 +#define ASCII_37 KEY_7 + SHIFT_MASK // 55 7 +#define ASCII_38 KEY_8 + SHIFT_MASK // 55 8 +#define ASCII_39 KEY_9 + SHIFT_MASK // 57 9 +#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : +#define ASCII_3B KEY_TILDE // 59 ; +#define ASCII_3C KEY_COMMA + ALTGR_MASK // 60 < +#define ASCII_3D KEY_MINUS // 61 = +#define ASCII_3E KEY_PERIOD + ALTGR_MASK // 62 > +#define ASCII_3F KEY_COMMA + SHIFT_MASK // 63 ? +#define ASCII_40 KEY_V + ALTGR_MASK // 64 @ +#define ASCII_41 KEY_A + SHIFT_MASK // 65 A +#define ASCII_42 KEY_B + SHIFT_MASK // 66 B +#define ASCII_43 KEY_C + SHIFT_MASK // 67 C +#define ASCII_44 KEY_D + SHIFT_MASK // 68 D +#define ASCII_45 KEY_E + SHIFT_MASK // 69 E +#define ASCII_46 KEY_F + SHIFT_MASK // 70 F +#define ASCII_47 KEY_G + SHIFT_MASK // 71 G +#define ASCII_48 KEY_H + SHIFT_MASK // 72 H +#define ASCII_49 KEY_I + SHIFT_MASK // 73 I +#define ASCII_4A KEY_J + SHIFT_MASK // 74 J +#define ASCII_4B KEY_K + SHIFT_MASK // 75 K +#define ASCII_4C KEY_L + SHIFT_MASK // 76 L +#define ASCII_4D KEY_M + SHIFT_MASK // 77 M +#define ASCII_4E KEY_N + SHIFT_MASK // 78 N +#define ASCII_4F KEY_O + SHIFT_MASK // 79 O +#define ASCII_50 KEY_P + SHIFT_MASK // 80 P +#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q +#define ASCII_52 KEY_R + SHIFT_MASK // 82 R +#define ASCII_53 KEY_S + SHIFT_MASK // 83 S +#define ASCII_54 KEY_T + SHIFT_MASK // 84 T +#define ASCII_55 KEY_U + SHIFT_MASK // 85 U +#define ASCII_56 KEY_V + SHIFT_MASK // 86 V +#define ASCII_57 KEY_W + SHIFT_MASK // 87 W +#define ASCII_58 KEY_X + SHIFT_MASK // 88 X +#define ASCII_59 KEY_Z + SHIFT_MASK // 89 Y +#define ASCII_5A KEY_Y + SHIFT_MASK // 90 Z +#define ASCII_5B KEY_F + ALTGR_MASK // 91 [ +#define ASCII_5C KEY_NON_US_100 // 92 +#define ASCII_5D KEY_G + ALTGR_MASK // 93 ] +#define ASCII_5E KEY_3 + ALTGR_MASK // 94 ^ TODO: testme +#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ +#define ASCII_60 KEY_7 + ALTGR_MASK // 96 ` TODO: testme +#define ASCII_61 KEY_A // 97 a +#define ASCII_62 KEY_B // 98 b +#define ASCII_63 KEY_C // 99 c +#define ASCII_64 KEY_D // 100 d +#define ASCII_65 KEY_E // 101 e +#define ASCII_66 KEY_F // 102 f +#define ASCII_67 KEY_G // 103 g +#define ASCII_68 KEY_H // 104 h +#define ASCII_69 KEY_I // 105 i +#define ASCII_6A KEY_J // 106 j +#define ASCII_6B KEY_K // 107 k +#define ASCII_6C KEY_L // 108 l +#define ASCII_6D KEY_M // 109 m +#define ASCII_6E KEY_N // 110 n +#define ASCII_6F KEY_O // 111 o +#define ASCII_70 KEY_P // 112 p +#define ASCII_71 KEY_Q // 113 q +#define ASCII_72 KEY_R // 114 r +#define ASCII_73 KEY_S // 115 s +#define ASCII_74 KEY_T // 116 t +#define ASCII_75 KEY_U // 117 u +#define ASCII_76 KEY_V // 118 v +#define ASCII_77 KEY_W // 119 w +#define ASCII_78 KEY_X // 120 x +#define ASCII_79 KEY_Z // 121 y +#define ASCII_7A KEY_Y // 122 z +#define ASCII_7B KEY_B + ALTGR_MASK // 123 { +#define ASCII_7C KEY_NON_US_100 + SHIFT_MASK // 124 | +#define ASCII_7D KEY_N + ALTGR_MASK // 125 } +#define ASCII_7E KEY_1 + ALTGR_MASK // 126 ~ TODO: fixme +#define ASCII_7F KEY_BACKSPACE // 127 +#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space +#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation +#define ISO_8859_1_A2 0 // 162 ¢ Cent Sign +#define ISO_8859_1_A3 0 // 163 £ Pound Sign +#define ISO_8859_1_A4 KEY_BACKSLASH + ALTGR_MASK // 164 ¤ Currency Sign +#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN +#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR +#define ISO_8859_1_A7 KEY_QUOTE // 167 § SECTION SIGN +#define ISO_8859_1_A8 0 // 168 ¨ DIAERESIS +#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN +#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL +#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE +#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN +#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN +#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN +#define ISO_8859_1_AF 0 // 175 ¯ MACRON +#define ISO_8859_1_B0 DEGREE_SIGN_BITS + KEY_SPACE // 176 ° DEGREE SIGN +#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN +#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO +#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE +#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT +#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN +#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN +#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT +#define ISO_8859_1_B8 CEDILLA_BITS + KEY_SPACE // 184 ¸ CEDILLA +#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE +#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL +#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE +#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER +#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF +#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS +#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK +#define ISO_8859_1_C0 0 // 192 À A GRAVE +#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE +#define ISO_8859_1_C2 0 // 194 Â A CIRCUMFLEX +#define ISO_8859_1_C3 0 // 195 Ã A TILDE +#define ISO_8859_1_C4 0 // 196 Ä A DIAERESIS +#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE +#define ISO_8859_1_C6 0 // 198 Æ AE +#define ISO_8859_1_C7 CEDILLA_BITS + KEY_C + SHIFT_MASK // 199 Ç C CEDILLA +#define ISO_8859_1_C8 0 // 200 È E GRAVE +#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE +#define ISO_8859_1_CA 0 // 202 Ê E CIRCUMFLEX +#define ISO_8859_1_CB 0 // 203 Ë E DIAERESIS +#define ISO_8859_1_CC 0 // 204 Ì I GRAVE +#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE +#define ISO_8859_1_CE 0 // 206 Î I CIRCUMFLEX +#define ISO_8859_1_CF 0 // 207 Ï I DIAERESIS +#define ISO_8859_1_D0 0 // 208 Ð ETH +#define ISO_8859_1_D1 0 // 209 Ñ N TILDE +#define ISO_8859_1_D2 0 // 210 Ò O GRAVE +#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE +#define ISO_8859_1_D4 0 // 212 Ô O CIRCUMFLEX +#define ISO_8859_1_D5 0 // 213 Õ O TILDE +#define ISO_8859_1_D6 0 // 214 Ö O DIAERESIS +#define ISO_8859_1_D7 KEY_RIGHT_BRACE + ALTGR_MASK // 215 × MULTIPLICATION +#define ISO_8859_1_D8 0 // 216 Ø O STROKE +#define ISO_8859_1_D9 0 // 217 Ù U GRAVE +#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE +#define ISO_8859_1_DB 0 // 219 Û U CIRCUMFLEX +#define ISO_8859_1_DC 0 // 220 Ü U DIAERESIS +#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Z + SHIFT_MASK // 221 Ý Y ACUTE +#define ISO_8859_1_DE 0 // 222 Þ THORN +#define ISO_8859_1_DF KEY_QUOTE + ALTGR_MASK // 223 ß SHARP S TODO: testme +#define ISO_8859_1_E0 0 // 224 à a GRAVE +#define ISO_8859_1_E1 KEY_8 // 225 á a ACUTE +#define ISO_8859_1_E2 0 // 226 â a CIRCUMFLEX +#define ISO_8859_1_E3 0 // 227 ã a TILDE +#define ISO_8859_1_E4 0 // 228 ä a DIAERESIS +#define ISO_8859_1_E5 0 // 229 å a RING ABOVE +#define ISO_8859_1_E6 0 // 230 æ ae +#define ISO_8859_1_E7 CEDILLA_BITS + KEY_C // 231 ç c CEDILLA +#define ISO_8859_1_E8 0 // 232 è e GRAVE +#define ISO_8859_1_E9 KEY_0 // 233 é e ACUTE +#define ISO_8859_1_EA 0 // 234 ê e CIRCUMFLEX +#define ISO_8859_1_EB 0 // 235 ë e DIAERESIS +#define ISO_8859_1_EC 0 // 236 ì i GRAVE +#define ISO_8859_1_ED KEY_9 // 237 í i ACUTE +#define ISO_8859_1_EE 0 // 238 î i CIRCUMFLEX +#define ISO_8859_1_EF 0 // 239 ï i DIAERESIS +#define ISO_8859_1_F0 0 // 240 ð ETH +#define ISO_8859_1_F1 0 // 241 ñ n TILDE +#define ISO_8859_1_F2 0 // 242 ò o GRAVE +#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE +#define ISO_8859_1_F4 0 // 244 ô o CIRCUMFLEX +#define ISO_8859_1_F5 0 // 245 õ o TILDE +#define ISO_8859_1_F6 0 // 246 ö o DIAERESIS +#define ISO_8859_1_F7 KEY_LEFT_BRACE + ALTGR_MASK // 247 ÷ DIVISION +#define ISO_8859_1_F8 0 // 248 ø o STROKE +#define ISO_8859_1_F9 0 // 249 ù u GRAVE +#define ISO_8859_1_FA KEY_LEFT_BRACE // 250 ú u ACUTE +#define ISO_8859_1_FB 0 // 251 û u CIRCUMFLEX +#define ISO_8859_1_FC 0 // 252 ü u DIAERESIS +#define ISO_8859_1_FD KEY_7 // 253 ý y ACUTE +#define ISO_8859_1_FE 0 // 254 þ THORN +#define ISO_8859_1_FF 0 // 255 ÿ y DIAERESIS +#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign + +#define UNICODE_EXTRA00 0x011B // ě Small Letter E with caron +#define KEYCODE_EXTRA00 KEY_2 +#define UNICODE_EXTRA01 0x0161 // š Small Letter S with caron +#define KEYCODE_EXTRA01 KEY_3 +#define UNICODE_EXTRA02 0x010D // č Small Letter C with caron +#define KEYCODE_EXTRA02 KEY_4 +#define UNICODE_EXTRA03 0x0159 // ř Small Letter R with caron +#define KEYCODE_EXTRA03 KEY_5 +#define UNICODE_EXTRA04 0x017E // ž Small Letter Z with caron +#define KEYCODE_EXTRA04 KEY_6 +#define UNICODE_EXTRA05 0x016F // ů Small Letter U with ring above +#define KEYCODE_EXTRA05 KEY_SEMICOLON +#define UNICODE_EXTRA06 0x0111 // đ Small Letter D with stroke +#define KEYCODE_EXTRA06 KEY_S + ALTGR_MASK +#define UNICODE_EXTRA07 0x0110 // Đ Capital Letter D with stroke +#define KEYCODE_EXTRA07 KEY_D + ALTGR_MASK +#define UNICODE_EXTRA08 0x0142 // ł Small Letter L with stroke +#define KEYCODE_EXTRA08 KEY_K + ALTGR_MASK +#define UNICODE_EXTRA09 0x0141 // Ł Capital Letter L with stroke +#define KEYCODE_EXTRA09 KEY_L + ALTGR_MASK +#define UNICODE_EXTRA0A 0x20AC // € Euro Sign +#define KEYCODE_EXTRA0A KEY_E + ALTGR_MASK + +#endif // LAYOUT_CZECH + + + + + + +extern const KEYCODE_TYPE keycodes_ascii[]; +extern const KEYCODE_TYPE keycodes_iso_8859_1[]; + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif From f088dd46c28130c6d5828bc37ff1cbb104b597f2 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 10 Oct 2015 12:27:30 +0200 Subject: [PATCH 265/602] updated Led Example --- .../examples/KeyboardLed/KeyboardLed.ino | 15 ++++----------- plugins/KeyboardioHID/keywords.txt | 2 ++ 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/plugins/KeyboardioHID/examples/KeyboardLed/KeyboardLed.ino b/plugins/KeyboardioHID/examples/KeyboardLed/KeyboardLed.ino index 06b6d4caba..88df32e394 100644 --- a/plugins/KeyboardioHID/examples/KeyboardLed/KeyboardLed.ino +++ b/plugins/KeyboardioHID/examples/KeyboardLed/KeyboardLed.ino @@ -6,19 +6,12 @@ Press a button to toogle caps lock. Caps lock state is represented by the onboard led. + Leds are only supported on single report HID devices. See HID Project documentation for more information. https://github.com/NicoHood/HID/wiki/Keyboard-API */ -// Choose your favourite keyboard -#define USBKEYBOARD Keyboard - -//#define USBKEYBOARD NKROKeyboard - -//#define USBKEYBOARD TeensyKeyboard -//#define USE_TEENSY_KEYBOARD - #include "HID-Project.h" const int pinLed = LED_BUILTIN; @@ -29,21 +22,21 @@ void setup() { pinMode(pinButton, INPUT_PULLUP); // Sends a clean report to the host. This is important on any Arduino type. - USBKEYBOARD.begin(); + BootKeyboard.begin(); } void loop() { // Update Led equal to the caps lock state. // Keep in mind that on a 16u2 and Arduino Micro HIGH and LOW for TX/RX Leds are inverted. - if (USBKEYBOARD.getLeds() & LED_CAPS_LOCK) + if (BootKeyboard.getLeds() & LED_CAPS_LOCK) digitalWrite(pinLed, HIGH); else digitalWrite(pinLed, LOW); // Trigger caps lock manually via button if (!digitalRead(pinButton)) { - USBKEYBOARD.write(KEY_CAPS_LOCK); + BootKeyboard.write(KEY_CAPS_LOCK); // Simple debounce delay(300); diff --git a/plugins/KeyboardioHID/keywords.txt b/plugins/KeyboardioHID/keywords.txt index 41c51121ab..805d1a4125 100644 --- a/plugins/KeyboardioHID/keywords.txt +++ b/plugins/KeyboardioHID/keywords.txt @@ -60,6 +60,8 @@ USBDevice KEYWORD1 HID KEYWORD1 Keyboard KEYWORD1 Mouse KEYWORD1 +BootKeyboard KEYWORD1 +BootMouse KEYWORD1 RawHID KEYWORD1 System KEYWORD1 Consumer KEYWORD1 From 8af6147b8cdd21696ab40a9568613eaea3233a19 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 10 Oct 2015 12:28:12 +0200 Subject: [PATCH 266/602] Moved HID report descriptors to their implementation --- .../src/HID-APIs/KeyboardAPI.cpp | 12 --- .../KeyboardioHID/src/HID-APIs/KeyboardAPI.h | 80 ------------------- .../src/MultiReport/ImprovedKeyboard.cpp | 36 +++++++++ .../src/SingleReport/BootKeyboard.cpp | 47 +++++++++++ 4 files changed, 83 insertions(+), 92 deletions(-) diff --git a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.cpp b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.cpp index 58cd47674d..1bc6715a06 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.cpp +++ b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.cpp @@ -23,18 +23,6 @@ THE SOFTWARE. #include "KeyboardAPI.h" -const uint8_t _hidReportDescriptorKeyboard[] PROGMEM = { - HID_REPORT_KEYBOARD, -}; - -const uint8_t _hidMultiReportDescriptorKeyboard[] PROGMEM = { - HID_MULTIREPORT_KEYBOARD, -}; - -static_assert(sizeof _hidReportDescriptorKeyboard == HID_REPORT_KEYBOARD_SIZE, "Oops, sizes are not equal."); -static_assert(sizeof _hidMultiReportDescriptorKeyboard == HID_MULTIREPORT_KEYBOARD_SIZE, "Oops, sizes are not equal."); - - void KeyboardAPI::begin(void) { diff --git a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h index 84bfe9a05d..5af66778fd 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h +++ b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h @@ -30,86 +30,6 @@ THE SOFTWARE. #include "HID-Tables.h" //TODO -#define HID_REPORT_KEYBOARD_START \ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 47 */ \ - 0x09, 0x06, /* USAGE (Keyboard) */ \ - 0xa1, 0x01 /* COLLECTION (Application) */ - -#define HID_REPORT_KEYBOARD_REPORTID \ - 0x85, HID_REPORTID_KEYBOARD /* REPORT_ID TODO order important?*/ - -#define HID_REPORT_KEYBOARD_START2 \ - 0x05, 0x07 /* USAGE_PAGE (Keyboard) */ - -#define HID_REPORT_KEYBOARD_MODIFIERS \ - /* Keyboard Modifiers (shift, alt, ...) */ \ - 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) */ - -#define HID_REPORT_KEYBOARD_RESERVED \ - /* Reserved byte TODO consumer and or system?*/ \ - 0x95, 0x01, /* REPORT_COUNT (1) */ \ - 0x75, 0x08, /* REPORT_SIZE (8) */ \ - 0x81, 0x03 /* INPUT (Cnst,Var,Abs) */ \ - -#define HID_REPORT_KEYBOARD_KEYS \ - /* 6 Keyboard keys */ \ - 0x95, 0x06, /* REPORT_COUNT (6) */ \ - 0x75, 0x08, /* REPORT_SIZE (8) */ \ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \ - 0x26, 0xE7, 0x00, /* LOGICAL_MAXIMUM (231) */ \ - 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ \ - 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ \ - 0x29, 0xE7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ \ - 0x81, 0x00 /* INPUT (Data,Ary,Abs) */ - -#define HID_REPORT_KEYBOARD_LEDS \ - /* 5 LEDs for num lock etc */ \ - 0x05, 0x08, /* USAGE_PAGE (LEDs) */ \ - 0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */ \ - 0x29, 0x05, /* USAGE_MAXIMUM (Kana) TODO */ \ - 0x95, 0x05, /* REPORT_COUNT (5) */ \ - 0x75, 0x01, /* REPORT_SIZE (1) */ \ - 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */ \ - /* Reserved 3 bits TODO */ \ - 0x95, 0x01, /* REPORT_COUNT (1) */ \ - 0x75, 0x03, /* REPORT_SIZE (3) */ \ - 0x91, 0x03 /* OUTPUT (Cnst,Var,Abs) */ - -#define HID_REPORT_KEYBOARD_END \ - /* End */ \ - 0xc0 /* END_COLLECTION */ - -#define HID_REPORT_KEYBOARD \ -HID_REPORT_KEYBOARD_START, \ -HID_REPORT_KEYBOARD_START2, \ -HID_REPORT_KEYBOARD_MODIFIERS, \ -HID_REPORT_KEYBOARD_RESERVED, \ -HID_REPORT_KEYBOARD_KEYS, \ -HID_REPORT_KEYBOARD_LEDS, \ -HID_REPORT_KEYBOARD_END - -#define HID_MULTIREPORT_KEYBOARD \ -HID_REPORT_KEYBOARD_START, \ -HID_REPORT_KEYBOARD_REPORTID, \ -HID_REPORT_KEYBOARD_START2, \ -HID_REPORT_KEYBOARD_MODIFIERS, \ -HID_REPORT_KEYBOARD_RESERVED, \ -HID_REPORT_KEYBOARD_KEYS, \ -HID_REPORT_KEYBOARD_END - -#define HID_REPORT_KEYBOARD_SIZE sizeof ((uint8_t[]) {HID_REPORT_KEYBOARD}) -#define HID_MULTIREPORT_KEYBOARD_SIZE sizeof ((uint8_t[]) {HID_MULTIREPORT_KEYBOARD}) - -extern const uint8_t _hidReportDescriptorKeyboard[HID_REPORT_KEYBOARD_SIZE] PROGMEM; -extern const uint8_t _hidMultiReportDescriptorKeyboard[HID_MULTIREPORT_KEYBOARD_SIZE] PROGMEM; - - typedef union{ // Low level key report: up to 6 keys and shift, ctrl etc at once uint8_t whole8[]; diff --git a/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.cpp index 7e391a640f..ff4fecbbd5 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.cpp @@ -23,6 +23,42 @@ THE SOFTWARE. #include "ImprovedKeyboard.h" +static const uint8_t _hidMultiReportDescriptorKeyboard[] PROGMEM = { + // Keyboard + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 47 */ + 0x09, 0x06, /* USAGE (Keyboard) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + 0x85, HID_REPORTID_KEYBOARD, /* REPORT_ID TODO order important? */ + 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ + + /* Keyboard Modifiers (shift, alt, ...) */ + 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) */ + + /* Reserved byte */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ + + /* 6 Keyboard keys */ + 0x95, 0x06, /* REPORT_COUNT (6) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x26, 0xE7, 0x00, /* LOGICAL_MAXIMUM (231) */ + 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ + 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ + 0x29, 0xE7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ + 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ + + /* End */ + 0xc0 /* END_COLLECTION */ +}; + Keyboard_::Keyboard_(void) { static HIDDescriptorListNode node(_hidMultiReportDescriptorKeyboard, sizeof(_hidMultiReportDescriptorKeyboard)); diff --git a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp index 8e6b811e07..96c393f77d 100644 --- a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp @@ -24,6 +24,53 @@ THE SOFTWARE. #include "BootKeyboard.h" #include "HID-Driver.h" +static const uint8_t _hidReportDescriptorKeyboard[] PROGMEM = { + // Keyboard + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 47 */ + 0x09, 0x06, /* USAGE (Keyboard) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ + + /* Keyboard Modifiers (shift, alt, ...) */ + 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) */ + + /* Reserved byte TODO consumer and or system */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ + + /* 5 LEDs for num lock etc, 3 left for advanced, custom usage */ + 0x05, 0x08, /* USAGE_PAGE (LEDs) */ + 0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */ + 0x29, 0x05, /* USAGE_MAXIMUM (Kana) TODO*/ + 0x95, 0x08, /* REPORT_COUNT (8) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */ + /* Reserved 3 bits TODO */ + //0x95, 0x01, /* REPORT_COUNT (1) */ + //0x75, 0x03, /* REPORT_SIZE (3) */ + //0x91, 0x03, /* OUTPUT (Cnst,Var,Abs) */ + + /* 6 Keyboard keys */ + 0x95, 0x06, /* REPORT_COUNT (6) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x26, 0xE7, 0x00, /* LOGICAL_MAXIMUM (231) */ + 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ + 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ + 0x29, 0xE7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ + 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ + + /* End */ + 0xc0 /* END_COLLECTION */ +}; + BootKeyboard_::BootKeyboard_(void) : PUSBListNode(1, 1, epType), protocol(1), idle(1), leds(0) { epType[0] = EP_TYPE_INTERRUPT_IN; From f02a1a94b447f507dcc83a40215051a522c82be7 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 10 Oct 2015 12:58:51 +0200 Subject: [PATCH 267/602] Improved Boot Keyboard, added example HID Driver got removed, now relies on the internal IDE definitions. The PR is opened at Github, but will merged hopefully soon. --- .../examples/BootKeyboard/BootKeyboard.ino | 43 ++++++++++++ plugins/KeyboardioHID/keywords.txt | 3 + plugins/KeyboardioHID/src/HID-Project.h | 1 - .../src/MultiReport/ImprovedKeyboard.h | 2 +- .../src/SingleReport/BootKeyboard.cpp | 3 +- .../src/SingleReport/BootKeyboard.h | 1 + .../src/SingleReport/HID-Driver.h | 65 ------------------- 7 files changed, 49 insertions(+), 69 deletions(-) create mode 100644 plugins/KeyboardioHID/examples/BootKeyboard/BootKeyboard.ino delete mode 100644 plugins/KeyboardioHID/src/SingleReport/HID-Driver.h diff --git a/plugins/KeyboardioHID/examples/BootKeyboard/BootKeyboard.ino b/plugins/KeyboardioHID/examples/BootKeyboard/BootKeyboard.ino new file mode 100644 index 0000000000..4283132fec --- /dev/null +++ b/plugins/KeyboardioHID/examples/BootKeyboard/BootKeyboard.ino @@ -0,0 +1,43 @@ +/* + Copyright (c) 2014-2015 NicoHood + See the readme for credit to other people. + + BootKeyboard example + + Shows that keyboard works even in bios. + Led indicats if we are in bios. + + See HID Project documentation for more information. + https://github.com/NicoHood/HID/wiki/Keyboard-API +*/ + +#include "HID-Project.h" + +const int pinLed = LED_BUILTIN; +const int pinButton = 2; + +void setup() { + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); + + // Sends a clean report to the host. This is important on any Arduino type. + BootKeyboard.begin(); +} + + +void loop() { + // Light led if keyboard uses the boot protocol (normally while in bios) + // Keep in mind that on a 16u2 and Arduino Micro HIGH and LOW for TX/RX Leds are inverted. + if (BootKeyboard.getProtocol() == HID_BOOT_PROTOCOL) + digitalWrite(pinLed, HIGH); + else + digitalWrite(pinLed, LOW); + + // Trigger caps lock manually via button + if (!digitalRead(pinButton)) { + BootKeyboard.write(KEY_ENTER); + + // Simple debounce + delay(300); + } +} diff --git a/plugins/KeyboardioHID/keywords.txt b/plugins/KeyboardioHID/keywords.txt index 805d1a4125..bf69108ac7 100644 --- a/plugins/KeyboardioHID/keywords.txt +++ b/plugins/KeyboardioHID/keywords.txt @@ -74,4 +74,7 @@ AbsoluteMouse KEYWORD1 # Constants (LITERAL1) ####################################### +HID_BOOT_PROTOCOL LITERAL1 +HID_REPORT_PROTOCOL LITERAL1 + #TODO add key definitions like KEY_ENTER diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index 53c953defe..3a0a51c153 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -37,7 +37,6 @@ THE SOFTWARE. #error HID Project can only be used with an USB MCU. #endif - // Include all HID libraries (.a linkage required to work) properly //#include "AbsoluteMouse.h" //#include "ImprovedMouse.h" diff --git a/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.h b/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.h index b6b9ab2882..3e024d8450 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.h @@ -26,8 +26,8 @@ THE SOFTWARE. #include #include "PluggableUSB.h" -#include "HID-Settings.h" #include "HID.h" +#include "HID-Settings.h" #include "../HID-APIs/KeyboardAPI.h" diff --git a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp index 96c393f77d..ee5edf2935 100644 --- a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp @@ -22,7 +22,6 @@ THE SOFTWARE. */ #include "BootKeyboard.h" -#include "HID-Driver.h" static const uint8_t _hidReportDescriptorKeyboard[] PROGMEM = { // Keyboard @@ -81,7 +80,7 @@ int BootKeyboard_::getInterface(uint8_t* interfaceCount) { *interfaceCount += 1; // uses 1 HIDDescriptor hidInterface = { - D_INTERFACE(pluggedInterface, 1, 3, 1, 1), // Boot compatible keyboard + D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_BOOT_INTERFACE, HID_PROTOCOL_KEYBOARD), D_HIDREPORT(sizeof(_hidReportDescriptorKeyboard)), D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) }; diff --git a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h index fdad4f3673..8f2ebddb1d 100644 --- a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h @@ -26,6 +26,7 @@ THE SOFTWARE. #include #include "PluggableUSB.h" +#include "HID.h" #include "HID-Settings.h" #include "../HID-APIs/KeyboardAPI.h" diff --git a/plugins/KeyboardioHID/src/SingleReport/HID-Driver.h b/plugins/KeyboardioHID/src/SingleReport/HID-Driver.h deleted file mode 100644 index 3c36f270fb..0000000000 --- a/plugins/KeyboardioHID/src/SingleReport/HID-Driver.h +++ /dev/null @@ -1,65 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 guard -#pragma once - -// HID 'Driver' -// ------------ -#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 - -#define HID_HID_DESCRIPTOR_TYPE 0x21 -#define HID_REPORT_DESCRIPTOR_TYPE 0x22 -#define HID_PHYSICAL_DESCRIPTOR_TYPE 0x23 - -// Keyboard/Mouse protocols (normal or bios) HID1.11 Page 54 7.2.5 Get_Protocol Request -#define HID_BOOT_PROTOCOL 0 -#define HID_REPORT_PROTOCOL 1 - -typedef struct -{ - uint8_t len; // 9 - uint8_t dtype; // 0x21 - uint8_t addr; - uint8_t versionL; // 0x101 - uint8_t versionH; // 0x101 - uint8_t country; - uint8_t desctype; // 0x22 report - uint8_t descLenL; - uint8_t descLenH; -} HIDDescDescriptor; - -typedef struct -{ - InterfaceDescriptor hid; - HIDDescDescriptor desc; - EndpointDescriptor in; -} HIDDescriptor; - -#define D_HIDREPORT(length) { 9, 0x21, 0x01, 0x01, 0, 1, 0x22, lowByte(length), highByte(length) } - From c6c7268e1af56d1c58074f4fae9343def785a801 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 10 Oct 2015 12:59:57 +0200 Subject: [PATCH 268/602] Added Mouse API --- .../KeyboardioHID/src/HID-APIs/MouseAPI.cpp | 85 ++++++++++ plugins/KeyboardioHID/src/HID-APIs/MouseAPI.h | 148 ++++++++++++++++++ .../src/MultiReport/ImprovedMouse.cpp | 38 +++++ .../src/MultiReport/ImprovedMouse.h | 43 +++++ .../src/SingleReport/BootMouse.cpp | 109 +++++++++++++ .../src/SingleReport/BootMouse.h | 54 +++++++ 6 files changed, 477 insertions(+) create mode 100644 plugins/KeyboardioHID/src/HID-APIs/MouseAPI.cpp create mode 100644 plugins/KeyboardioHID/src/HID-APIs/MouseAPI.h create mode 100644 plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.cpp create mode 100644 plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.h create mode 100644 plugins/KeyboardioHID/src/SingleReport/BootMouse.cpp create mode 100644 plugins/KeyboardioHID/src/SingleReport/BootMouse.h diff --git a/plugins/KeyboardioHID/src/HID-APIs/MouseAPI.cpp b/plugins/KeyboardioHID/src/HID-APIs/MouseAPI.cpp new file mode 100644 index 0000000000..02b0bcd483 --- /dev/null +++ b/plugins/KeyboardioHID/src/HID-APIs/MouseAPI.cpp @@ -0,0 +1,85 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 "MouseAPI.h" + +MouseAPI::MouseAPI(void) : _buttons(0) +{ + // Empty +} + +void MouseAPI::begin(void) +{ + end(); +} + +void MouseAPI::end(void) +{ + _buttons = 0; + move(0, 0, 0); +} + +void MouseAPI::click(uint8_t b) +{ + _buttons = b; + move(0,0,0); + _buttons = 0; + move(0,0,0); +} + +void MouseAPI::move(signed char x, signed char y, signed char wheel) +{ + HID_MouseReport_Data_t report; + report.buttons = _buttons; + report.xAxis = x; + report.yAxis = y; + report.wheel = wheel; + sendReport(&report, sizeof(report)); +} + +void MouseAPI::buttons(uint8_t b) +{ + if (b != _buttons) + { + _buttons = b; + move(0,0,0); + } +} + +void MouseAPI::press(uint8_t b) +{ + buttons(_buttons | b); +} + +void MouseAPI::release(uint8_t b) +{ + buttons(_buttons & ~b); +} + +bool MouseAPI::isPressed(uint8_t b) +{ + if ((b & _buttons) > 0) + return true; + return false; +} + diff --git a/plugins/KeyboardioHID/src/HID-APIs/MouseAPI.h b/plugins/KeyboardioHID/src/HID-APIs/MouseAPI.h new file mode 100644 index 0000000000..d193fd9add --- /dev/null +++ b/plugins/KeyboardioHID/src/HID-APIs/MouseAPI.h @@ -0,0 +1,148 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 guard +#pragma once + +#include +#include "HID-Settings.h" + +static const uint8_t _hidReportDescriptorMouse[] PROGMEM = { + /* Mouse relative */ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 54 */ + 0x09, 0x02, /* USAGE (Mouse) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + + /* 8 Buttons */ + 0x05, 0x09, /* USAGE_PAGE (Button) */ + 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ + 0x29, 0x08, /* USAGE_MAXIMUM (Button 8) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x95, 0x08, /* REPORT_COUNT (8) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + + /* X, Y, Wheel */ + 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) */ + + /* End */ + 0xc0 /* END_COLLECTION */ +}; + +static const uint8_t _hidMultiReportDescriptorMouse[] PROGMEM = { + /* Mouse relative */ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 54 */ + 0x09, 0x02, /* USAGE (Mouse) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + 0x85, HID_REPORTID_MOUSE, /* REPORT_ID */ + + /* 8 Buttons */ + 0x05, 0x09, /* USAGE_PAGE (Button) */ + 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ + 0x29, 0x08, /* USAGE_MAXIMUM (Button 8) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x95, 0x08, /* REPORT_COUNT (8) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + + /* X, Y, Wheel */ + 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) */ + + /* End */ + 0xc0 /* END_COLLECTION */ +}; + +#define MOUSE_LEFT (1 << 0) +#define MOUSE_RIGHT (1 << 1) +#define MOUSE_MIDDLE (1 << 2) +#define MOUSE_PREV (1 << 3) +#define MOUSE_NEXT (1 << 4) +// actually this mouse report has 8 buttons (for smaller descriptor) +// but the last 3 wont do anything from what I tested +#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE | MOUSE_PREV | MOUSE_NEXT) + +typedef union{ + // Mouse report: 8 buttons, position, wheel + uint8_t whole8[]; + uint16_t whole16[]; + uint32_t whole32[]; + struct{ + uint8_t buttons; + int8_t xAxis; + int8_t yAxis; + int8_t wheel; + }; +} HID_MouseReport_Data_t; + +typedef union{ + // BootMouse report: 3 buttons, position + // Wheel is not supported by boot protocol + uint8_t whole8[]; + uint16_t whole16[]; + uint32_t whole32[]; + struct{ + uint8_t buttons; + int8_t xAxis; + int8_t yAxis; + }; +} HID_BootMouseReport_Data_t; + +class MouseAPI +{ +public: + MouseAPI(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 + + // Sending is public in the base class for advanced users. + virtual void sendReport(void* data, int length) = 0; + +private: + uint8_t _buttons; + void buttons(uint8_t b); +}; + + diff --git a/plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.cpp b/plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.cpp new file mode 100644 index 0000000000..d142355a32 --- /dev/null +++ b/plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.cpp @@ -0,0 +1,38 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 "ImprovedMouse.h" + +Mouse_::Mouse_(void) +{ + static HIDDescriptorListNode node(_hidMultiReportDescriptorMouse, sizeof(_hidMultiReportDescriptorMouse)); + HID().AppendDescriptor(&node); +} + +void Mouse_::sendReport(void* data, int length) +{ + HID().SendReport(HID_REPORTID_MOUSE, data, length); +} + +Mouse_ Mouse; + diff --git a/plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.h b/plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.h new file mode 100644 index 0000000000..c8209ebab3 --- /dev/null +++ b/plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.h @@ -0,0 +1,43 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 guard +#pragma once + +#include +#include "PluggableUSB.h" +#include "HID.h" +#include "HID-Settings.h" +#include "../HID-APIs/MouseAPI.h" + + +class Mouse_ : public MouseAPI +{ +public: + Mouse_(void); + +protected: + virtual inline void sendReport(void* data, int length) override; +}; +extern Mouse_ Mouse; + diff --git a/plugins/KeyboardioHID/src/SingleReport/BootMouse.cpp b/plugins/KeyboardioHID/src/SingleReport/BootMouse.cpp new file mode 100644 index 0000000000..64030d88cf --- /dev/null +++ b/plugins/KeyboardioHID/src/SingleReport/BootMouse.cpp @@ -0,0 +1,109 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 "BootMouse.h" + +BootMouse_::BootMouse_(void) : PUSBListNode(1, 1, epType), protocol(1), idle(1) +{ + epType[0] = EP_TYPE_INTERRUPT_IN; + PluggableUSB().plug(this); +} + +int BootMouse_::getInterface(uint8_t* interfaceCount) +{ + *interfaceCount += 1; // uses 1 + HIDDescriptor hidInterface = { + D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_BOOT_INTERFACE, HID_PROTOCOL_MOUSE), + D_HIDREPORT(sizeof(_hidReportDescriptorMouse)), + D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) + }; + return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); +} + +int BootMouse_::getDescriptor(USBSetup& setup) +{ + // Check if this is a HID Class Descriptor request + if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { return 0; } + if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { return 0; } + + // In a HID Class Descriptor wIndex cointains the interface number + if (setup.wIndex != pluggedInterface) { return 0; } + + return USB_SendControl(TRANSFER_PGM, _hidReportDescriptorMouse, sizeof(_hidReportDescriptorMouse)); +} + +bool BootMouse_::setup(USBSetup& setup) +{ + if (pluggedInterface != setup.wIndex) { + return false; + } + + uint8_t request = setup.bRequest; + uint8_t requestType = setup.bmRequestType; + + if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) + { + if (request == HID_GET_REPORT) { + // TODO: HID_GetReport(); + return true; + } + if (request == HID_GET_PROTOCOL) { + // TODO: Send8(protocol); + return true; + } + } + + if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) + { + if (request == HID_SET_PROTOCOL) { + protocol = setup.wValueL; + return true; + } + if (request == HID_SET_IDLE) { + idle = setup.wValueL; + return true; + } + if (request == HID_SET_REPORT) + { + } + } + + return false; +} + +uint8_t BootMouse_::getProtocol(void){ + return protocol; +} + +void BootMouse_::sendReport(void* data, int length){ + if(protocol == HID_BOOT_PROTOCOL){ + USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, sizeof(HID_BootMouseReport_Data_t)); + } + else{ + USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, length); + } +} + +BootMouse_ BootMouse; + + diff --git a/plugins/KeyboardioHID/src/SingleReport/BootMouse.h b/plugins/KeyboardioHID/src/SingleReport/BootMouse.h new file mode 100644 index 0000000000..ff4096d2bd --- /dev/null +++ b/plugins/KeyboardioHID/src/SingleReport/BootMouse.h @@ -0,0 +1,54 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 guard +#pragma once + +#include +#include "PluggableUSB.h" +#include "HID.h" +#include "HID-Settings.h" +#include "../HID-APIs/MouseAPI.h" + + +class BootMouse_ : public PUSBListNode, public MouseAPI +{ +public: + BootMouse_(void); + uint8_t getProtocol(void); + +protected: + // Implementation of the PUSBListNode + int getInterface(uint8_t* interfaceCount); + int getDescriptor(USBSetup& setup); + bool setup(USBSetup& setup); + + uint8_t epType[1]; + uint8_t protocol; + uint8_t idle; + + virtual void sendReport(void* data, int length) override; +}; +extern BootMouse_ BootMouse; + + From 2f2b63f8333c26752b546a15ee43e838027312b6 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 10 Oct 2015 18:59:17 +0200 Subject: [PATCH 269/602] Enabled Mouse API --- .../KeyboardioHID/examples/ImprovedMouse/ImprovedMouse.ino | 4 ++++ plugins/KeyboardioHID/src/HID-Project.h | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/examples/ImprovedMouse/ImprovedMouse.ino b/plugins/KeyboardioHID/examples/ImprovedMouse/ImprovedMouse.ino index 5ccdb96adb..45fcb2122c 100644 --- a/plugins/KeyboardioHID/examples/ImprovedMouse/ImprovedMouse.ino +++ b/plugins/KeyboardioHID/examples/ImprovedMouse/ImprovedMouse.ino @@ -5,6 +5,10 @@ Mouse example Press a button to click or move the mouse. + You may also use BootMouse to enable a bios compatible mouse. + However this is very unusual and not recommended. + Bios mice dont support wheels which can cause problems after a reboot. + See HID Project documentation for more Information. https://github.com/NicoHood/HID/wiki/Mouse-API */ diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index 3a0a51c153..e619901bd0 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -39,7 +39,8 @@ THE SOFTWARE. // Include all HID libraries (.a linkage required to work) properly //#include "AbsoluteMouse.h" -//#include "ImprovedMouse.h" +#include "SingleReport/BootMouse.h" +#include "MultiReport/ImprovedMouse.h" //#include "Consumer.h" //#include "Gamepad.h" //#include "System.h" From 85df80246a14565dd14b66ca23a1b98b430c185f Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 10 Oct 2015 19:37:58 +0200 Subject: [PATCH 270/602] Made SendReport() capaital --- .../src/HID-APIs/KeyboardAPI.cpp | 2 +- .../KeyboardioHID/src/HID-APIs/KeyboardAPI.h | 2 +- .../KeyboardioHID/src/HID-APIs/MouseAPI.cpp | 2 +- plugins/KeyboardioHID/src/HID-APIs/MouseAPI.h | 2 +- .../src/MultiReport/ImprovedKeyboard.cpp | 2 +- .../src/MultiReport/ImprovedKeyboard.h | 2 +- .../src/MultiReport/ImprovedMouse.cpp | 37 ++++++++++++++++++- .../src/MultiReport/ImprovedMouse.h | 2 +- .../src/SingleReport/BootKeyboard.cpp | 2 +- .../src/SingleReport/BootKeyboard.h | 2 +- .../src/SingleReport/BootMouse.cpp | 2 +- .../src/SingleReport/BootMouse.h | 2 +- 12 files changed, 47 insertions(+), 12 deletions(-) diff --git a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.cpp b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.cpp index 1bc6715a06..ccaf1407fd 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.cpp +++ b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.cpp @@ -37,7 +37,7 @@ void KeyboardAPI::end(void) void KeyboardAPI::send_now(void){ - sendReport(&_keyReport, sizeof(_keyReport)); + SendReport(&_keyReport, sizeof(_keyReport)); } diff --git a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h index 5af66778fd..788eb634ce 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h +++ b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h @@ -63,7 +63,7 @@ class KeyboardAPI : public Print size_t removeKeycodeFromReport(uint8_t k); // Sending is public in the base class for advanced users. - virtual void sendReport(void* data, int length) = 0; + virtual void SendReport(void* data, int length) = 0; protected: HID_KeyboardReport_Data_t _keyReport; diff --git a/plugins/KeyboardioHID/src/HID-APIs/MouseAPI.cpp b/plugins/KeyboardioHID/src/HID-APIs/MouseAPI.cpp index 02b0bcd483..6f5a46b737 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/MouseAPI.cpp +++ b/plugins/KeyboardioHID/src/HID-APIs/MouseAPI.cpp @@ -54,7 +54,7 @@ void MouseAPI::move(signed char x, signed char y, signed char wheel) report.xAxis = x; report.yAxis = y; report.wheel = wheel; - sendReport(&report, sizeof(report)); + SendReport(&report, sizeof(report)); } void MouseAPI::buttons(uint8_t b) diff --git a/plugins/KeyboardioHID/src/HID-APIs/MouseAPI.h b/plugins/KeyboardioHID/src/HID-APIs/MouseAPI.h index d193fd9add..8318aea23c 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/MouseAPI.h +++ b/plugins/KeyboardioHID/src/HID-APIs/MouseAPI.h @@ -138,7 +138,7 @@ class MouseAPI bool isPressed(uint8_t b = MOUSE_LEFT); // check LEFT by default // Sending is public in the base class for advanced users. - virtual void sendReport(void* data, int length) = 0; + virtual void SendReport(void* data, int length) = 0; private: uint8_t _buttons; diff --git a/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.cpp index ff4fecbbd5..1e9c0609aa 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.cpp @@ -65,7 +65,7 @@ Keyboard_::Keyboard_(void) HID().AppendDescriptor(&node); } -void Keyboard_::sendReport(void* data, int length) +void Keyboard_::SendReport(void* data, int length) { HID().SendReport(HID_REPORTID_KEYBOARD, data, length); } diff --git a/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.h b/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.h index 3e024d8450..7feca85028 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.h @@ -37,7 +37,7 @@ class Keyboard_ : public KeyboardAPI Keyboard_(void); protected: - virtual inline void sendReport(void* data, int length) override; + virtual inline void SendReport(void* data, int length) override; }; extern Keyboard_ Keyboard; diff --git a/plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.cpp b/plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.cpp index d142355a32..c3b8e5af9b 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.cpp @@ -23,13 +23,48 @@ THE SOFTWARE. #include "ImprovedMouse.h" + +static const uint8_t _hidMultiReportDescriptorMouse[] PROGMEM = { + /* Mouse relative */ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 54 */ + 0x09, 0x02, /* USAGE (Mouse) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + 0x85, HID_REPORTID_MOUSE, /* REPORT_ID */ + + /* 8 Buttons */ + 0x05, 0x09, /* USAGE_PAGE (Button) */ + 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ + 0x29, 0x08, /* USAGE_MAXIMUM (Button 8) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x95, 0x08, /* REPORT_COUNT (8) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + + /* X, Y, Wheel */ + 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) */ + + /* End */ + 0xc0 /* END_COLLECTION */ +}; + + Mouse_::Mouse_(void) { static HIDDescriptorListNode node(_hidMultiReportDescriptorMouse, sizeof(_hidMultiReportDescriptorMouse)); HID().AppendDescriptor(&node); } -void Mouse_::sendReport(void* data, int length) + +void Mouse_::SendReport(void* data, int length) { HID().SendReport(HID_REPORTID_MOUSE, data, length); } diff --git a/plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.h b/plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.h index c8209ebab3..14d83a039e 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.h @@ -37,7 +37,7 @@ class Mouse_ : public MouseAPI Mouse_(void); protected: - virtual inline void sendReport(void* data, int length) override; + virtual inline void SendReport(void* data, int length) override; }; extern Mouse_ Mouse; diff --git a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp index ee5edf2935..393d73082e 100644 --- a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp @@ -151,7 +151,7 @@ uint8_t BootKeyboard_::getProtocol(void){ return protocol; } -void BootKeyboard_::sendReport(void* data, int length){ +void BootKeyboard_::SendReport(void* data, int length){ USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, length); } diff --git a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h index 8f2ebddb1d..f360d934d6 100644 --- a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h @@ -50,7 +50,7 @@ class BootKeyboard_ : public PUSBListNode, public KeyboardAPI uint8_t leds; - virtual void sendReport(void* data, int length) override; + virtual void SendReport(void* data, int length) override; }; extern BootKeyboard_ BootKeyboard; diff --git a/plugins/KeyboardioHID/src/SingleReport/BootMouse.cpp b/plugins/KeyboardioHID/src/SingleReport/BootMouse.cpp index 64030d88cf..076044630e 100644 --- a/plugins/KeyboardioHID/src/SingleReport/BootMouse.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/BootMouse.cpp @@ -95,7 +95,7 @@ uint8_t BootMouse_::getProtocol(void){ return protocol; } -void BootMouse_::sendReport(void* data, int length){ +void BootMouse_::SendReport(void* data, int length){ if(protocol == HID_BOOT_PROTOCOL){ USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, sizeof(HID_BootMouseReport_Data_t)); } diff --git a/plugins/KeyboardioHID/src/SingleReport/BootMouse.h b/plugins/KeyboardioHID/src/SingleReport/BootMouse.h index ff4096d2bd..00462b0f6e 100644 --- a/plugins/KeyboardioHID/src/SingleReport/BootMouse.h +++ b/plugins/KeyboardioHID/src/SingleReport/BootMouse.h @@ -47,7 +47,7 @@ class BootMouse_ : public PUSBListNode, public MouseAPI uint8_t protocol; uint8_t idle; - virtual void sendReport(void* data, int length) override; + virtual void SendReport(void* data, int length) override; }; extern BootMouse_ BootMouse; From 544c2c59ba91928d9c80160dc6263c3bd5af7bdf Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 10 Oct 2015 19:38:16 +0200 Subject: [PATCH 271/602] Moved Mouse report descriptor --- plugins/KeyboardioHID/src/HID-APIs/MouseAPI.h | 62 ------------------- .../src/SingleReport/BootMouse.cpp | 31 ++++++++++ 2 files changed, 31 insertions(+), 62 deletions(-) diff --git a/plugins/KeyboardioHID/src/HID-APIs/MouseAPI.h b/plugins/KeyboardioHID/src/HID-APIs/MouseAPI.h index 8318aea23c..3824d852be 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/MouseAPI.h +++ b/plugins/KeyboardioHID/src/HID-APIs/MouseAPI.h @@ -27,68 +27,6 @@ THE SOFTWARE. #include #include "HID-Settings.h" -static const uint8_t _hidReportDescriptorMouse[] PROGMEM = { - /* Mouse relative */ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 54 */ - 0x09, 0x02, /* USAGE (Mouse) */ - 0xa1, 0x01, /* COLLECTION (Application) */ - - /* 8 Buttons */ - 0x05, 0x09, /* USAGE_PAGE (Button) */ - 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ - 0x29, 0x08, /* USAGE_MAXIMUM (Button 8) */ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ - 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ - 0x95, 0x08, /* REPORT_COUNT (8) */ - 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - - /* X, Y, Wheel */ - 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) */ - - /* End */ - 0xc0 /* END_COLLECTION */ -}; - -static const uint8_t _hidMultiReportDescriptorMouse[] PROGMEM = { - /* Mouse relative */ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 54 */ - 0x09, 0x02, /* USAGE (Mouse) */ - 0xa1, 0x01, /* COLLECTION (Application) */ - 0x85, HID_REPORTID_MOUSE, /* REPORT_ID */ - - /* 8 Buttons */ - 0x05, 0x09, /* USAGE_PAGE (Button) */ - 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ - 0x29, 0x08, /* USAGE_MAXIMUM (Button 8) */ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ - 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ - 0x95, 0x08, /* REPORT_COUNT (8) */ - 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - - /* X, Y, Wheel */ - 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) */ - - /* End */ - 0xc0 /* END_COLLECTION */ -}; #define MOUSE_LEFT (1 << 0) #define MOUSE_RIGHT (1 << 1) diff --git a/plugins/KeyboardioHID/src/SingleReport/BootMouse.cpp b/plugins/KeyboardioHID/src/SingleReport/BootMouse.cpp index 076044630e..980b505d92 100644 --- a/plugins/KeyboardioHID/src/SingleReport/BootMouse.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/BootMouse.cpp @@ -23,6 +23,37 @@ THE SOFTWARE. #include "BootMouse.h" +static const uint8_t _hidReportDescriptorMouse[] PROGMEM = { + /* Mouse relative */ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 54 */ + 0x09, 0x02, /* USAGE (Mouse) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + + /* 8 Buttons */ + 0x05, 0x09, /* USAGE_PAGE (Button) */ + 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ + 0x29, 0x08, /* USAGE_MAXIMUM (Button 8) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x95, 0x08, /* REPORT_COUNT (8) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + + /* X, Y, Wheel */ + 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) */ + + /* End */ + 0xc0 /* END_COLLECTION */ +}; + BootMouse_::BootMouse_(void) : PUSBListNode(1, 1, epType), protocol(1), idle(1) { epType[0] = EP_TYPE_INTERRUPT_IN; From 862b1fcd395ca431c86e41f4fee5e19ad6f3ed9f Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 10 Oct 2015 19:38:33 +0200 Subject: [PATCH 272/602] removed option to deactivate leds Bootkeyboard requires leds, so they are used. This feature isnt bad at all though --- plugins/KeyboardioHID/src/HID-Settings.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/KeyboardioHID/src/HID-Settings.h b/plugins/KeyboardioHID/src/HID-Settings.h index afa38be926..b95de02e30 100644 --- a/plugins/KeyboardioHID/src/HID-Settings.h +++ b/plugins/KeyboardioHID/src/HID-Settings.h @@ -28,8 +28,6 @@ THE SOFTWARE. // Settings //================================================================================ -#define HID_KEYBOARD_LEDS_ENABLED - //#define LAYOUT_US_ENGLISH //#define LAYOUT_CANADIAN_FRENCH //#define LAYOUT_CANADIAN_MULTILINGUAL From 0023f65727c31a1e643e4b013b72c3bc8390e804 Mon Sep 17 00:00:00 2001 From: Nico Date: Sat, 10 Oct 2015 20:08:37 +0200 Subject: [PATCH 273/602] Update Readme.md --- plugins/KeyboardioHID/Readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index c3c92da3c2..71037aa6c6 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -8,8 +8,8 @@ with a lot of new functions like extended HID. It also supports HoodLoader1+2. The idea is to enable enhanced USB functions to almost all 'standard' Arduino boards. **Supported Arduinos (IDE 1.6.6 or higher!):** -* Uno (with HoodLoader2) -* Mega (with HoodLoader2) +* Uno (with [HoodLoader2](https://github.com/NicoHood/HoodLoader2)) +* Mega (with [HoodLoader2](https://github.com/NicoHood/HoodLoader2)) * Leonardo * (Pro)Micro * Any other 8u2/16u2/at90usb8/162/32u2/32u4 compatible board From d15d37153d71bb2d669cf8757e2997592cd99d5b Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 10 Oct 2015 20:57:36 +0200 Subject: [PATCH 274/602] inlined Keyboard implementation --- .../KeyboardioHID/src/HID-APIs/KeyboardAPI.h | 31 ++++++++++--------- .../{KeyboardAPI.cpp => KeyboardAPI.hpp} | 4 +-- 2 files changed, 19 insertions(+), 16 deletions(-) rename plugins/KeyboardioHID/src/HID-APIs/{KeyboardAPI.cpp => KeyboardAPI.hpp} (99%) diff --git a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h index 788eb634ce..fc7eec8f68 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h +++ b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h @@ -46,21 +46,21 @@ class KeyboardAPI : public Print { public: //TODO nkro compatiblity, merge them - void begin(void); - void end(void); - size_t write(uint8_t k); - size_t press(uint8_t k); - size_t release(uint8_t k); - void releaseAll(void); - void send_now(void); + inline void begin(void); + inline void end(void); + inline size_t write(uint8_t k); + inline size_t press(uint8_t k); + inline size_t release(uint8_t k); + inline void releaseAll(void); + inline void send_now(void); - size_t writeKeycode(uint8_t k); - size_t pressKeycode(uint8_t k); - size_t releaseKeycode(uint8_t k); - size_t addKeyToReport(uint8_t k); - size_t addKeycodeToReport(uint8_t k); - size_t removeKeyFromReport(uint8_t k); - size_t removeKeycodeFromReport(uint8_t k); + inline size_t writeKeycode(uint8_t k); + inline size_t pressKeycode(uint8_t k); + inline size_t releaseKeycode(uint8_t k); + inline size_t addKeyToReport(uint8_t k); + inline size_t addKeycodeToReport(uint8_t k); + inline size_t removeKeyFromReport(uint8_t k); + inline size_t removeKeycodeFromReport(uint8_t k); // Sending is public in the base class for advanced users. virtual void SendReport(void* data, int length) = 0; @@ -68,3 +68,6 @@ class KeyboardAPI : public Print protected: HID_KeyboardReport_Data_t _keyReport; }; + +// Implementation is inline +#include "KeyboardAPI.hpp" diff --git a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.cpp b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.hpp similarity index 99% rename from plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.cpp rename to plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.hpp index ccaf1407fd..19abc823d8 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.cpp +++ b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.hpp @@ -21,8 +21,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "KeyboardAPI.h" - +// Include guard +#pragma once void KeyboardAPI::begin(void) { From 44daf55f8408f676d3e8bf9cdf02330aaef9f588 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 11 Oct 2015 09:11:08 +0200 Subject: [PATCH 275/602] Added Absolute mouse --- .../src/HID-APIs/AbsoluteMouseAPI.h | 82 ++++++++++++++ .../src/HID-APIs/AbsoluteMouseAPI.hpp | 106 ++++++++++++++++++ plugins/KeyboardioHID/src/HID-Project.h | 2 +- .../src/MultiReport/AbsoluteMouse.cpp | 79 +++++++++++++ .../src/MultiReport/AbsoluteMouse.h | 43 +++++++ 5 files changed, 311 insertions(+), 1 deletion(-) create mode 100644 plugins/KeyboardioHID/src/HID-APIs/AbsoluteMouseAPI.h create mode 100644 plugins/KeyboardioHID/src/HID-APIs/AbsoluteMouseAPI.hpp create mode 100644 plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp create mode 100644 plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h diff --git a/plugins/KeyboardioHID/src/HID-APIs/AbsoluteMouseAPI.h b/plugins/KeyboardioHID/src/HID-APIs/AbsoluteMouseAPI.h new file mode 100644 index 0000000000..44b6fae8b8 --- /dev/null +++ b/plugins/KeyboardioHID/src/HID-APIs/AbsoluteMouseAPI.h @@ -0,0 +1,82 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 guard +#pragma once + +#include +#include "HID-Settings.h" + +#define MOUSE_LEFT (1 << 0) +#define MOUSE_RIGHT (1 << 1) +#define MOUSE_MIDDLE (1 << 2) +#define MOUSE_PREV (1 << 3) +#define MOUSE_NEXT (1 << 4) +// actually this mouse report has 8 buttons (for smaller descriptor) +// but the last 3 wont do anything from what I tested +#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE | MOUSE_PREV | MOUSE_NEXT) + + +typedef union{ + // Absolute mouse report: 8 buttons, 2 absolute axis, wheel + uint8_t whole8[]; + uint16_t whole16[]; + uint32_t whole32[]; + struct{ + uint8_t buttons; + int16_t xAxis; + int16_t yAxis; + int8_t wheel; + }; +} HID_MouseAbsoluteReport_Data_t; + + +class AbsoluteMouseAPI +{ +private: + int16_t xAxis; + int16_t yAxis; + uint8_t _buttons; + inline void buttons(uint8_t b); + + inline int16_t qadd16(int16_t base, int16_t increment); + +public: + inline AbsoluteMouseAPI(void); + inline void begin(void); + inline void end(void); + + inline void click(uint8_t b = MOUSE_LEFT); + inline void moveTo(int x, int y, signed char wheel = 0); + inline void move(int x, int y, signed char wheel = 0); + inline void press(uint8_t b = MOUSE_LEFT); + inline void release(uint8_t b = MOUSE_LEFT); + inline bool isPressed(uint8_t b = MOUSE_LEFT); + + // Sending is public in the base class for advanced users. + virtual void SendReport(void* data, int length) = 0; +}; + +// Implementation is inline +#include "AbsoluteMouseAPI.hpp" + diff --git a/plugins/KeyboardioHID/src/HID-APIs/AbsoluteMouseAPI.hpp b/plugins/KeyboardioHID/src/HID-APIs/AbsoluteMouseAPI.hpp new file mode 100644 index 0000000000..23f736eac8 --- /dev/null +++ b/plugins/KeyboardioHID/src/HID-APIs/AbsoluteMouseAPI.hpp @@ -0,0 +1,106 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 guard +#pragma once + +void AbsoluteMouseAPI::buttons(uint8_t b){ + if (b != _buttons){ + _buttons = b; + moveTo(xAxis, yAxis, 0); + } +} + +int16_t AbsoluteMouseAPI::qadd16(int16_t base, int16_t increment) { + // Separate between subtracting and adding + if (increment < 0) { + // Subtracting more would cause an undefined overflow + if ((int16_t)0x8000 - increment > base) + base = 0x8000; + else + base += increment; + } + else { + // Adding more would cause an undefined overflow + if ((int16_t)0x7FFF - increment < base) + base = 0x7FFF; + else + base += increment; + } + return base; +} + +AbsoluteMouseAPI::AbsoluteMouseAPI(void): +xAxis(0), yAxis(0), _buttons(0) +{ + // Empty +} + +void AbsoluteMouseAPI::begin(void){ + // release all buttons + end(); +} + +void AbsoluteMouseAPI::end(void){ + _buttons = 0; + moveTo(xAxis, yAxis, 0); +} + +void AbsoluteMouseAPI::click(uint8_t b){ + _buttons = b; + moveTo(xAxis, yAxis, 0); + _buttons = 0; + moveTo(xAxis, yAxis, 0); +} + +void AbsoluteMouseAPI::moveTo(int x, int y, signed char wheel){ + xAxis = x; + yAxis = y; + HID_MouseAbsoluteReport_Data_t report; + report.buttons = _buttons; + report.xAxis = x; + report.yAxis = y; + report.wheel = wheel; + SendReport(&report, sizeof(report)); +} + +void AbsoluteMouseAPI::move(int x, int y, signed char wheel){ + moveTo(qadd16(xAxis, x), qadd16(yAxis, y), wheel); +} + +void AbsoluteMouseAPI::press(uint8_t b){ + // press LEFT by default + buttons(_buttons | b); +} + +void AbsoluteMouseAPI::release(uint8_t b){ + // release LEFT by default + buttons(_buttons & ~b); +} + +bool AbsoluteMouseAPI::isPressed(uint8_t b){ + // check LEFT by default + if ((b & _buttons) > 0) + return true; + return false; +} diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index e619901bd0..199eaefd93 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -38,7 +38,7 @@ THE SOFTWARE. #endif // Include all HID libraries (.a linkage required to work) properly -//#include "AbsoluteMouse.h" +#include "MultiReport/AbsoluteMouse.h" #include "SingleReport/BootMouse.h" #include "MultiReport/ImprovedMouse.h" //#include "Consumer.h" diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp new file mode 100644 index 0000000000..c4e16c509e --- /dev/null +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp @@ -0,0 +1,79 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 "AbsoluteMouse.h" + + +static const uint8_t _hidMultiReportDescriptorAbsoluteMouse[] PROGMEM = { + /* Mouse absolute */ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 54 */ + 0x09, 0x02, /* USAGE (Mouse) */ + 0xA1, 0x01, /* COLLECTION (Application) */ + 0x85, HID_REPORTID_MOUSE_ABSOLUTE, /* REPORT_ID */ + + /* 8 Buttons */ + 0x05, 0x09, /* USAGE_PAGE (Button) */ + 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ + 0x29, 0x08, /* USAGE_MAXIMUM (Button 8) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x95, 0x08, /* REPORT_COUNT (8) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + + /* X, Y */ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x30, /* USAGE (X) */ + 0x09, 0x31, /* USAGE (Y) */ + 0x16, 0x00, 0x80, /* Logical Minimum (-32768) */ + 0x26, 0xFF, 0x7F, /* Logical Maximum (32767) */ + 0x75, 0x10, /* Report Size (16), */ + 0x95, 0x02, /* Report Count (2), */ + 0x81, 0x02, /* Input (Data, Variable, Absolute) */ + + /* Wheel */ + 0x09, 0x38, /* USAGE (Wheel) */ + 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) */ + + /* End */ + 0xc0 /* END_COLLECTION */ +}; + +AbsoluteMouse_::AbsoluteMouse_(void) +{ + static HIDDescriptorListNode node(_hidMultiReportDescriptorAbsoluteMouse, sizeof(_hidMultiReportDescriptorAbsoluteMouse)); + HID().AppendDescriptor(&node); +} + + +void AbsoluteMouse_::SendReport(void* data, int length) +{ + HID().SendReport(HID_REPORTID_MOUSE_ABSOLUTE, data, length); +} + +AbsoluteMouse_ AbsoluteMouse; + diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h new file mode 100644 index 0000000000..be0c2d90aa --- /dev/null +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h @@ -0,0 +1,43 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 guard +#pragma once + +#include +#include "PluggableUSB.h" +#include "HID.h" +#include "HID-Settings.h" +#include "../HID-APIs/AbsoluteMouseAPI.h" + + +class AbsoluteMouse_ : public AbsoluteMouseAPI +{ +public: + AbsoluteMouse_(void); + +protected: + virtual inline void SendReport(void* data, int length) override; +}; +extern AbsoluteMouse_ AbsoluteMouse; + From b0c448a07dc8b01968441a40f9f665f61e40b61b Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 11 Oct 2015 09:17:10 +0200 Subject: [PATCH 276/602] Inlined HID APIs --- plugins/KeyboardioHID/src/HID-APIs/MouseAPI.h | 19 +-- .../HID-APIs/{MouseAPI.cpp => MouseAPI.hpp} | 3 +- .../src/HID-APIs/TeensyKeyboardAPI.h | 129 +++++++----------- ...yKeyboardAPI.cpp => TeensyKeyboardAPI.hpp} | 3 +- 4 files changed, 64 insertions(+), 90 deletions(-) rename plugins/KeyboardioHID/src/HID-APIs/{MouseAPI.cpp => MouseAPI.hpp} (98%) rename plugins/KeyboardioHID/src/HID-APIs/{TeensyKeyboardAPI.cpp => TeensyKeyboardAPI.hpp} (99%) diff --git a/plugins/KeyboardioHID/src/HID-APIs/MouseAPI.h b/plugins/KeyboardioHID/src/HID-APIs/MouseAPI.h index 3824d852be..e50c67ffa9 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/MouseAPI.h +++ b/plugins/KeyboardioHID/src/HID-APIs/MouseAPI.h @@ -66,14 +66,14 @@ typedef union{ class MouseAPI { public: - MouseAPI(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 + inline MouseAPI(void); + inline void begin(void); + inline void end(void); + inline void click(uint8_t b = MOUSE_LEFT); + inline void move(signed char x, signed char y, signed char wheel = 0); + inline void press(uint8_t b = MOUSE_LEFT); // press LEFT by default + inline void release(uint8_t b = MOUSE_LEFT); // release LEFT by default + inline bool isPressed(uint8_t b = MOUSE_LEFT); // check LEFT by default // Sending is public in the base class for advanced users. virtual void SendReport(void* data, int length) = 0; @@ -83,4 +83,5 @@ class MouseAPI void buttons(uint8_t b); }; - +// Implementation is inline +#include "MouseAPI.hpp" diff --git a/plugins/KeyboardioHID/src/HID-APIs/MouseAPI.cpp b/plugins/KeyboardioHID/src/HID-APIs/MouseAPI.hpp similarity index 98% rename from plugins/KeyboardioHID/src/HID-APIs/MouseAPI.cpp rename to plugins/KeyboardioHID/src/HID-APIs/MouseAPI.hpp index 6f5a46b737..55d144dc80 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/MouseAPI.cpp +++ b/plugins/KeyboardioHID/src/HID-APIs/MouseAPI.hpp @@ -21,7 +21,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "MouseAPI.h" +// Include guard +#pragma once MouseAPI::MouseAPI(void) : _buttons(0) { diff --git a/plugins/KeyboardioHID/src/HID-APIs/TeensyKeyboardAPI.h b/plugins/KeyboardioHID/src/HID-APIs/TeensyKeyboardAPI.h index 2aa4f9c235..0e630b3b1a 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/TeensyKeyboardAPI.h +++ b/plugins/KeyboardioHID/src/HID-APIs/TeensyKeyboardAPI.h @@ -28,85 +28,54 @@ THE SOFTWARE. #include "HID-Settings.h" #include "TeensyKeylayouts.h" -#define HID_REPORT_KEYBOARD_START \ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 47 */ \ - 0x09, 0x06, /* USAGE (Keyboard) */ \ - 0xa1, 0x01 /* COLLECTION (Application) */ - -#define HID_REPORT_KEYBOARD_REPORTID \ - 0x85, HID_REPORTID_KEYBOARD /* REPORT_ID TODO order important?*/ - -#define HID_REPORT_KEYBOARD_START2 \ - 0x05, 0x07 /* USAGE_PAGE (Keyboard) */ - -#define HID_REPORT_KEYBOARD_MODIFIERS \ - /* Keyboard Modifiers (shift, alt, ...) */ \ - 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) */ - -#define HID_REPORT_KEYBOARD_RESERVED \ - /* Reserved byte TODO consumer and or system?*/ \ - 0x95, 0x01, /* REPORT_COUNT (1) */ \ - 0x75, 0x08, /* REPORT_SIZE (8) */ \ - 0x81, 0x03 /* INPUT (Cnst,Var,Abs) */ \ - -#define HID_REPORT_KEYBOARD_KEYS \ - /* 6 Keyboard keys */ \ - 0x95, 0x06, /* REPORT_COUNT (6) */ \ - 0x75, 0x08, /* REPORT_SIZE (8) */ \ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \ - 0x26, 0xE7, 0x00, /* LOGICAL_MAXIMUM (231) */ \ - 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ \ - 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ \ - 0x29, 0xE7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ \ - 0x81, 0x00 /* INPUT (Data,Ary,Abs) */ - -#define HID_REPORT_KEYBOARD_LEDS \ - /* 5 LEDs for num lock etc */ \ - 0x05, 0x08, /* USAGE_PAGE (LEDs) */ \ - 0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */ \ - 0x29, 0x05, /* USAGE_MAXIMUM (Kana) TODO */ \ - 0x95, 0x05, /* REPORT_COUNT (5) */ \ - 0x75, 0x01, /* REPORT_SIZE (1) */ \ - 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */ \ - /* Reserved 3 bits TODO */ \ - 0x95, 0x01, /* REPORT_COUNT (1) */ \ - 0x75, 0x03, /* REPORT_SIZE (3) */ \ - 0x91, 0x03 /* OUTPUT (Cnst,Var,Abs) */ - -#define HID_REPORT_KEYBOARD_END \ - /* End */ \ - 0xc0 /* END_COLLECTION */ - -#define HID_REPORT_KEYBOARD \ -HID_REPORT_KEYBOARD_START, \ -HID_REPORT_KEYBOARD_START2, \ -HID_REPORT_KEYBOARD_MODIFIERS, \ -HID_REPORT_KEYBOARD_RESERVED, \ -HID_REPORT_KEYBOARD_KEYS, \ -HID_REPORT_KEYBOARD_LEDS, \ -HID_REPORT_KEYBOARD_END - -#define HID_MULTIREPORT_KEYBOARD \ -HID_REPORT_KEYBOARD_START, \ -HID_REPORT_KEYBOARD_REPORTID, \ -HID_REPORT_KEYBOARD_START2, \ -HID_REPORT_KEYBOARD_MODIFIERS, \ -HID_REPORT_KEYBOARD_RESERVED, \ -HID_REPORT_KEYBOARD_KEYS, \ -HID_REPORT_KEYBOARD_END - -#define HID_REPORT_KEYBOARD_SIZE sizeof ((uint8_t[]) {HID_REPORT_KEYBOARD}) -#define HID_MULTIREPORT_KEYBOARD_SIZE sizeof ((uint8_t[]) {HID_MULTIREPORT_KEYBOARD}) - -extern const uint8_t _hidReportDescriptorKeyboard[HID_REPORT_KEYBOARD_SIZE] PROGMEM; -extern const uint8_t _hidMultiReportDescriptorKeyboard[HID_MULTIREPORT_KEYBOARD_SIZE] PROGMEM; - +// Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60 +static const uint8_t PROGMEM teensykeyboard_hid_report_desc[] = { + 0x05, 0x01, // Usage Page (Generic Desktop), + 0x09, 0x06, // Usage (Keyboard), + 0xA1, 0x01, // Collection (Application), + 0x85, HID_REPORTID_TEENSY_KEYBOARD, // REPORT_ID + 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, 0x08, // Report Count (8), + 0x75, 0x01, // Report Size (1), + 0x15, 0x00, // Logical Minimum (0), + 0x25, 0x01, // Logical Maximum (1), + 0x05, 0x0C, // Usage Page (Consumer), + 0x09, 0xE9, // Usage (Volume Increment), + 0x09, 0xEA, // Usage (Volume Decrement), + 0x09, 0xE2, // Usage (Mute), + 0x09, 0xCD, // Usage (Play/Pause), + 0x09, 0xB5, // Usage (Scan Next Track), + 0x09, 0xB6, // Usage (Scan Previous Track), + 0x09, 0xB7, // Usage (Stop), + 0x09, 0xB8, // Usage (Eject), +// Note: Teensy ledreport was not modified to 8 bit, nor left out when leds are deactivated + 0x81, 0x02, // Input (Data, Variable, Absolute), ;Media keys + 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, 0x7F, // Logical Maximum(104), + 0x05, 0x07, // Usage Page (Key Codes), + 0x19, 0x00, // Usage Minimum (0), + 0x29, 0x7F, // Usage Maximum (104), + 0x81, 0x00, // Input (Data, Array), ;Normal keys + 0xc0 // End Collection +}; typedef union{ // Low level key report: up to 6 keys and shift, ctrl etc at once @@ -160,3 +129,5 @@ class TeensyKeyboardAPI : public Print uint8_t keyboard_report_data[8]; }; +// Implementation is inline +#include "TeensyKeyboardAPI.hpp" diff --git a/plugins/KeyboardioHID/src/HID-APIs/TeensyKeyboardAPI.cpp b/plugins/KeyboardioHID/src/HID-APIs/TeensyKeyboardAPI.hpp similarity index 99% rename from plugins/KeyboardioHID/src/HID-APIs/TeensyKeyboardAPI.cpp rename to plugins/KeyboardioHID/src/HID-APIs/TeensyKeyboardAPI.hpp index 3e2bca4887..e0e756e741 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/TeensyKeyboardAPI.cpp +++ b/plugins/KeyboardioHID/src/HID-APIs/TeensyKeyboardAPI.hpp @@ -21,7 +21,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "TeensyKeyboardAPI.h" +// Include guard +#pragma once // Step #1, decode UTF8 to Unicode code points // From 808add311fb3c8d0cdf97ab6a36b0dfc18c46e26 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 11 Oct 2015 10:14:08 +0200 Subject: [PATCH 277/602] Added System API --- .../KeyboardioHID/src/HID-APIs/SystemAPI.h | 55 ++++++++++++++++ .../KeyboardioHID/src/HID-APIs/SystemAPI.hpp | 63 +++++++++++++++++++ plugins/KeyboardioHID/src/HID-Project.h | 2 +- .../KeyboardioHID/src/MultiReport/System.cpp | 58 +++++++++++++++++ .../KeyboardioHID/src/MultiReport/System.h | 43 +++++++++++++ 5 files changed, 220 insertions(+), 1 deletion(-) create mode 100644 plugins/KeyboardioHID/src/HID-APIs/SystemAPI.h create mode 100644 plugins/KeyboardioHID/src/HID-APIs/SystemAPI.hpp create mode 100644 plugins/KeyboardioHID/src/MultiReport/System.cpp create mode 100644 plugins/KeyboardioHID/src/MultiReport/System.h diff --git a/plugins/KeyboardioHID/src/HID-APIs/SystemAPI.h b/plugins/KeyboardioHID/src/HID-APIs/SystemAPI.h new file mode 100644 index 0000000000..69e483321a --- /dev/null +++ b/plugins/KeyboardioHID/src/HID-APIs/SystemAPI.h @@ -0,0 +1,55 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 guard +#pragma once + +#include +#include "HID-Settings.h" + +#define SYSTEM_POWER_DOWN 0x81 +#define SYSTEM_SLEEP 0x82 +#define SYSTEM_WAKE_UP 0x83 + +typedef union{ + // Every usable system control key possible + uint8_t whole8[]; + uint8_t key; +} HID_SystemControlReport_Data_t; + +class SystemAPI{ +public: + inline SystemAPI(void); + inline void begin(void); + inline void end(void); + inline void write(uint8_t s); + inline void press(uint8_t s); + inline void release(void); + inline void releaseAll(void); + + // Sending is public in the base class for advanced users. + virtual void SendReport(void* data, int length) = 0; +}; + +// Implementation is inline +#include "SystemAPI.hpp" diff --git a/plugins/KeyboardioHID/src/HID-APIs/SystemAPI.hpp b/plugins/KeyboardioHID/src/HID-APIs/SystemAPI.hpp new file mode 100644 index 0000000000..ba9d75c3d9 --- /dev/null +++ b/plugins/KeyboardioHID/src/HID-APIs/SystemAPI.hpp @@ -0,0 +1,63 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 guard +#pragma once + +SystemAPI::SystemAPI(void) +{ + // Empty +} + +void SystemAPI::begin(void){ + // release all buttons + end(); +} + +void SystemAPI::end(void){ + uint8_t _report = 0; + SendReport(&_report, sizeof(_report)); +} + +void SystemAPI::write(uint8_t s){ + press(s); + release(); +} + +void SystemAPI::release(void){ + begin(); +} + +void SystemAPI::releaseAll(void){ + begin(); +} + +void SystemAPI::press(uint8_t s){ +#ifdef USBCON + if (s == SYSTEM_WAKE_UP) + USBDevice.wakeupHost(); + else +#endif + SendReport(&s, sizeof(s)); +} + diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index 199eaefd93..84e897b02e 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -43,7 +43,7 @@ THE SOFTWARE. #include "MultiReport/ImprovedMouse.h" //#include "Consumer.h" //#include "Gamepad.h" -//#include "System.h" +#include "MultiReport/System.h" //#include "RawHID.h" // Include Teensy HID afterwards to overwrite key definitions if used diff --git a/plugins/KeyboardioHID/src/MultiReport/System.cpp b/plugins/KeyboardioHID/src/MultiReport/System.cpp new file mode 100644 index 0000000000..b3e9af55a2 --- /dev/null +++ b/plugins/KeyboardioHID/src/MultiReport/System.cpp @@ -0,0 +1,58 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 "System.h" + + +static const uint8_t _hidMultiReportDescriptorSystem[] PROGMEM = { + //TODO limit to system keys only? + /* System Control (Power Down, Sleep, Wakeup, ...) */ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x80, /* USAGE (System Control) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + 0x85, HID_REPORTID_SYSTEMCONTROL, /* REPORT_ID */ + /* 1 system key */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x26, 0xff, 0x00, /* LOGICAL_MAXIMUM (255) */ + 0x19, 0x00, /* USAGE_MINIMUM (Undefined) */ + 0x29, 0xff, /* USAGE_MAXIMUM (System Menu Down) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ + 0xc0 /* END_COLLECTION */ +}; + +System_::System_(void) +{ + static HIDDescriptorListNode node(_hidMultiReportDescriptorSystem, sizeof(_hidMultiReportDescriptorSystem)); + HID().AppendDescriptor(&node); +} + + +void System_::SendReport(void* data, int length) +{ + HID().SendReport(HID_REPORTID_SYSTEMCONTROL, data, length); +} + +System_ System; + diff --git a/plugins/KeyboardioHID/src/MultiReport/System.h b/plugins/KeyboardioHID/src/MultiReport/System.h new file mode 100644 index 0000000000..a2336e8c10 --- /dev/null +++ b/plugins/KeyboardioHID/src/MultiReport/System.h @@ -0,0 +1,43 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 guard +#pragma once + +#include +#include "PluggableUSB.h" +#include "HID.h" +#include "HID-Settings.h" +#include "../HID-APIs/SystemAPI.h" + + +class System_ : public SystemAPI +{ +public: + System_(void); + +protected: + virtual inline void SendReport(void* data, int length) override; +}; +extern System_ System; + From 5655ea39801a6ae855c9b3e77e2a36f2e4f50d7b Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 11 Oct 2015 10:22:32 +0200 Subject: [PATCH 278/602] Added Consumer API --- .../src/HID-APIs/AbsoluteMouseAPI.h | 2 +- .../KeyboardioHID/src/HID-APIs/ConsumerAPI.h | 94 +++++++++++++++++++ .../src/HID-APIs/ConsumerAPI.hpp | 71 ++++++++++++++ plugins/KeyboardioHID/src/HID-APIs/MouseAPI.h | 2 +- plugins/KeyboardioHID/src/HID-Project.h | 2 +- .../src/MultiReport/Consumer.cpp | 57 +++++++++++ .../KeyboardioHID/src/MultiReport/Consumer.h | 43 +++++++++ 7 files changed, 268 insertions(+), 3 deletions(-) create mode 100644 plugins/KeyboardioHID/src/HID-APIs/ConsumerAPI.h create mode 100644 plugins/KeyboardioHID/src/HID-APIs/ConsumerAPI.hpp create mode 100644 plugins/KeyboardioHID/src/MultiReport/Consumer.cpp create mode 100644 plugins/KeyboardioHID/src/MultiReport/Consumer.h diff --git a/plugins/KeyboardioHID/src/HID-APIs/AbsoluteMouseAPI.h b/plugins/KeyboardioHID/src/HID-APIs/AbsoluteMouseAPI.h index 44b6fae8b8..37a6ee87a8 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/AbsoluteMouseAPI.h +++ b/plugins/KeyboardioHID/src/HID-APIs/AbsoluteMouseAPI.h @@ -53,7 +53,7 @@ typedef union{ class AbsoluteMouseAPI { -private: +protected: int16_t xAxis; int16_t yAxis; uint8_t _buttons; diff --git a/plugins/KeyboardioHID/src/HID-APIs/ConsumerAPI.h b/plugins/KeyboardioHID/src/HID-APIs/ConsumerAPI.h new file mode 100644 index 0000000000..a71b2c584f --- /dev/null +++ b/plugins/KeyboardioHID/src/HID-APIs/ConsumerAPI.h @@ -0,0 +1,94 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 guard +#pragma once + +#include +#include "HID-Settings.h" + +// Media key definitions, see official USB docs for more +#define MEDIA_FAST_FORWARD 0xB3 +#define MEDIA_REWIND 0xB4 +#define MEDIA_NEXT 0xB5 +#define MEDIA_PREVIOUS 0xB6 +#define MEDIA_PREV MEDIA_PREVIOUS +#define MEDIA_STOP 0xB7 +#define MEDIA_PLAY_PAUSE 0xCD + +#define MEDIA_VOLUME_MUTE 0xE2 +#define MEDIA_VOLUME_UP 0xE9 +#define MEDIA_VOLUME_DOWN 0xEA +#define MEDIA_VOL_MUTE MEDIA_VOLUME_MUTE +#define MEDIA_VOL_UP MEDIA_VOLUME_UP +#define MEDIA_VOL_DOWN MEDIA_VOLUME_DOWN + +#define CONSUMER_SCREENSAVER 0x19e + +#define CONSUMER_PROGRAMMABLE_BUTTON_CONFIGURATION 0x182 +#define CONSUMER_CONTROL_CONFIGURATION 0x183 +#define CONSUMER_EMAIL_READER 0x18A +#define CONSUMER_CALCULATOR 0x192 +#define CONSUMER_EXPLORER 0x194 + +#define CONSUMER_BROWSER_HOME 0x223 +#define CONSUMER_BROWSER_BACK 0x224 +#define CONSUMER_BROWSER_FORWARD 0x225 +#define CONSUMER_BROWSER_REFRESH 0x227 +#define CONSUMER_BROWSER_BOOKMARKS 0x22A + + +typedef union { + // Every usable Consumer key possible, up to 4 keys presses possible + uint8_t whole8[]; + uint16_t whole16[]; + uint32_t whole32[]; + struct { + uint16_t key1; + uint16_t key2; + uint16_t key3; + uint16_t key4; + }; +} HID_ConsumerControlReport_Data_t; + +class ConsumerAPI +{ +public: + inline ConsumerAPI(void); + inline void begin(void); + inline void end(void); + inline void write(uint16_t m); + inline void press(uint16_t m); + inline void release(uint16_t m); + inline void releaseAll(void); + + // Sending is public in the base class for advanced users. + virtual void SendReport(void* data, int length) = 0; + +protected: + HID_ConsumerControlReport_Data_t _report; +}; + +// Implementation is inline +#include "ConsumerAPI.hpp" + diff --git a/plugins/KeyboardioHID/src/HID-APIs/ConsumerAPI.hpp b/plugins/KeyboardioHID/src/HID-APIs/ConsumerAPI.hpp new file mode 100644 index 0000000000..55cd864cb5 --- /dev/null +++ b/plugins/KeyboardioHID/src/HID-APIs/ConsumerAPI.hpp @@ -0,0 +1,71 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 guard +#pragma once + +ConsumerAPI::ConsumerAPI(void) +{ + // Empty +} + +void ConsumerAPI::begin(void) { + // release all buttons + end(); +} + +void ConsumerAPI::end(void) { + memset(&_report, 0, sizeof(_report)); + SendReport(&_report, sizeof(_report)); +} + +void ConsumerAPI::write(uint16_t m) { + press(m); + release(m); +} + +void ConsumerAPI::press(uint16_t m) { + // search for a free spot + for (uint8_t i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { + if (_report.whole16[i] == 0x00) { + _report.whole16[i] = m; + break; + } + } + SendReport(&_report, sizeof(_report)); +} + +void ConsumerAPI::release(uint16_t m) { + // search and release the keypress + for (uint8_t i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { + if (_report.whole16[i] == m) { + _report.whole16[i] = 0x00; + // no break to delete multiple keys + } + } + SendReport(&_report, sizeof(_report)); +} + +void ConsumerAPI::releaseAll(void) { + end(); +} diff --git a/plugins/KeyboardioHID/src/HID-APIs/MouseAPI.h b/plugins/KeyboardioHID/src/HID-APIs/MouseAPI.h index e50c67ffa9..1357d14881 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/MouseAPI.h +++ b/plugins/KeyboardioHID/src/HID-APIs/MouseAPI.h @@ -78,7 +78,7 @@ class MouseAPI // Sending is public in the base class for advanced users. virtual void SendReport(void* data, int length) = 0; -private: +protected: uint8_t _buttons; void buttons(uint8_t b); }; diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index 84e897b02e..84cdc5b3ca 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -41,7 +41,7 @@ THE SOFTWARE. #include "MultiReport/AbsoluteMouse.h" #include "SingleReport/BootMouse.h" #include "MultiReport/ImprovedMouse.h" -//#include "Consumer.h" +#include "MultiReport/Consumer.h" //#include "Gamepad.h" #include "MultiReport/System.h" //#include "RawHID.h" diff --git a/plugins/KeyboardioHID/src/MultiReport/Consumer.cpp b/plugins/KeyboardioHID/src/MultiReport/Consumer.cpp new file mode 100644 index 0000000000..7e8a116d3c --- /dev/null +++ b/plugins/KeyboardioHID/src/MultiReport/Consumer.cpp @@ -0,0 +1,57 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 "Consumer.h" + + +static const uint8_t _hidMultiReportDescriptorConsumer[] PROGMEM = { + /* Consumer Control (Sound/Media keys) */ + 0x05, 0x0C, /* usage page (consumer device) */ + 0x09, 0x01, /* usage -- consumer control */ + 0xA1, 0x01, /* collection (application) */ + 0x85, HID_REPORTID_CONSUMERCONTROL, /* report id */ + /* 4 Media Keys */ + 0x15, 0x00, /* logical minimum */ + 0x26, 0xFF, 0x03, /* logical maximum (3ff) */ + 0x19, 0x00, /* usage minimum (0) */ + 0x2A, 0xFF, 0x03, /* usage maximum (3ff) */ + 0x95, 0x04, /* report count (4) */ + 0x75, 0x10, /* report size (16) */ + 0x81, 0x00, /* input */ + 0xC0 /* end collection */ +}; + +Consumer_::Consumer_(void) +{ + static HIDDescriptorListNode node(_hidMultiReportDescriptorConsumer, sizeof(_hidMultiReportDescriptorConsumer)); + HID().AppendDescriptor(&node); +} + + +void Consumer_::SendReport(void* data, int length) +{ + HID().SendReport(HID_REPORTID_CONSUMERCONTROL, data, length); +} + +Consumer_ Consumer; + diff --git a/plugins/KeyboardioHID/src/MultiReport/Consumer.h b/plugins/KeyboardioHID/src/MultiReport/Consumer.h new file mode 100644 index 0000000000..ede2458bce --- /dev/null +++ b/plugins/KeyboardioHID/src/MultiReport/Consumer.h @@ -0,0 +1,43 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 guard +#pragma once + +#include +#include "PluggableUSB.h" +#include "HID.h" +#include "HID-Settings.h" +#include "../HID-APIs/ConsumerAPI.h" + + +class Consumer_ : public ConsumerAPI +{ +public: + Consumer_(void); + +protected: + virtual inline void SendReport(void* data, int length) override; +}; +extern Consumer_ Consumer; + From 2902c25adde4dc39a3016b7237f62be0cc7c7f2e Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 11 Oct 2015 10:42:51 +0200 Subject: [PATCH 279/602] Fixed Consumer warning --- plugins/KeyboardioHID/src/HID-APIs/ConsumerAPI.h | 1 + plugins/KeyboardioHID/src/HID-APIs/ConsumerAPI.hpp | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/plugins/KeyboardioHID/src/HID-APIs/ConsumerAPI.h b/plugins/KeyboardioHID/src/HID-APIs/ConsumerAPI.h index a71b2c584f..50c6a5b1fe 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/ConsumerAPI.h +++ b/plugins/KeyboardioHID/src/HID-APIs/ConsumerAPI.h @@ -63,6 +63,7 @@ typedef union { uint8_t whole8[]; uint16_t whole16[]; uint32_t whole32[]; + uint16_t keys[4]; struct { uint16_t key1; uint16_t key2; diff --git a/plugins/KeyboardioHID/src/HID-APIs/ConsumerAPI.hpp b/plugins/KeyboardioHID/src/HID-APIs/ConsumerAPI.hpp index 55cd864cb5..42f028207c 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/ConsumerAPI.hpp +++ b/plugins/KeyboardioHID/src/HID-APIs/ConsumerAPI.hpp @@ -47,8 +47,8 @@ void ConsumerAPI::write(uint16_t m) { void ConsumerAPI::press(uint16_t m) { // search for a free spot for (uint8_t i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { - if (_report.whole16[i] == 0x00) { - _report.whole16[i] = m; + if (_report.keys[i] == 0x00) { + _report.keys[i] = m; break; } } @@ -58,8 +58,8 @@ void ConsumerAPI::press(uint16_t m) { void ConsumerAPI::release(uint16_t m) { // search and release the keypress for (uint8_t i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { - if (_report.whole16[i] == m) { - _report.whole16[i] = 0x00; + if (_report.keys[i] == m) { + _report.keys[i] = 0x00; // no break to delete multiple keys } } From cbbe0b988efd37f867f4fa1463d919f55edd68c8 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 11 Oct 2015 10:51:34 +0200 Subject: [PATCH 280/602] Added Gamepad API --- .../KeyboardioHID/src/HID-APIs/GamepadAPI.h | 130 ++++++++++++++++++ .../KeyboardioHID/src/HID-APIs/GamepadAPI.hpp | 104 ++++++++++++++ plugins/KeyboardioHID/src/HID-Project.h | 2 +- .../KeyboardioHID/src/MultiReport/Gamepad.cpp | 88 ++++++++++++ .../KeyboardioHID/src/MultiReport/Gamepad.h | 43 ++++++ 5 files changed, 366 insertions(+), 1 deletion(-) create mode 100644 plugins/KeyboardioHID/src/HID-APIs/GamepadAPI.h create mode 100644 plugins/KeyboardioHID/src/HID-APIs/GamepadAPI.hpp create mode 100644 plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp create mode 100644 plugins/KeyboardioHID/src/MultiReport/Gamepad.h diff --git a/plugins/KeyboardioHID/src/HID-APIs/GamepadAPI.h b/plugins/KeyboardioHID/src/HID-APIs/GamepadAPI.h new file mode 100644 index 0000000000..13ea7b55e2 --- /dev/null +++ b/plugins/KeyboardioHID/src/HID-APIs/GamepadAPI.h @@ -0,0 +1,130 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 guard +#pragma once + +#include +#include "HID-Settings.h" + +// Dpad directions +#define GAMEPAD_DPAD_CENTERED 0 +#define GAMEPAD_DPAD_UP 1 +#define GAMEPAD_DPAD_UP_RIGHT 2 +#define GAMEPAD_DPAD_RIGHT 3 +#define GAMEPAD_DPAD_DOWN_RIGHT 4 +#define GAMEPAD_DPAD_DOWN 5 +#define GAMEPAD_DPAD_DOWN_LEFT 6 +#define GAMEPAD_DPAD_LEFT 7 +#define GAMEPAD_DPAD_UP_LEFT 8 + + +typedef union { + // 32 Buttons, 6 Axis, 2 D-Pads + uint8_t whole8[]; + uint16_t whole16[]; + uint32_t whole32[]; + uint32_t buttons; + + struct{ + uint8_t button1 : 1; + uint8_t button2 : 1; + uint8_t button3 : 1; + uint8_t button4 : 1; + uint8_t button5 : 1; + uint8_t button6 : 1; + uint8_t button7 : 1; + uint8_t button8 : 1; + + uint8_t button9 : 1; + uint8_t button10 : 1; + uint8_t button11 : 1; + uint8_t button12 : 1; + uint8_t button13 : 1; + uint8_t button14 : 1; + uint8_t button15 : 1; + uint8_t button16 : 1; + + uint8_t button17 : 1; + uint8_t button18 : 1; + uint8_t button19 : 1; + uint8_t button20 : 1; + uint8_t button21 : 1; + uint8_t button22 : 1; + uint8_t button23 : 1; + uint8_t button24 : 1; + + uint8_t button25 : 1; + uint8_t button26 : 1; + uint8_t button27 : 1; + uint8_t button28 : 1; + uint8_t button29 : 1; + uint8_t button30 : 1; + uint8_t button31 : 1; + uint8_t button32 : 1; + + int16_t xAxis; + int16_t yAxis; + + int16_t rxAxis; + int16_t ryAxis; + + int8_t zAxis; + int8_t rzAxis; + + uint8_t dPad1 : 4; + uint8_t dPad2 : 4; + }; +} HID_GamepadReport_Data_t; + +class GamepadAPI{ +public: + inline GamepadAPI(void); + + inline void begin(void); + inline void end(void); + inline void write(void); + inline void press(uint8_t b); + inline void release(uint8_t b); + inline void releaseAll(void); + + inline void buttons(uint32_t b); + inline void xAxis(int16_t a); + inline void yAxis(int16_t a); + inline void zAxis(int8_t a); + inline void rxAxis(int16_t a); + inline void ryAxis(int16_t a); + inline void rzAxis(int8_t a); + inline void dPad1(int8_t d); + inline void dPad2(int8_t d); + + // Sending is public in the base class for advanced users. + virtual void SendReport(void* data, int length) = 0; + +protected: + HID_GamepadReport_Data_t _report; +}; + +// Implementation is inline +#include "GamepadAPI.hpp" + diff --git a/plugins/KeyboardioHID/src/HID-APIs/GamepadAPI.hpp b/plugins/KeyboardioHID/src/HID-APIs/GamepadAPI.hpp new file mode 100644 index 0000000000..8b025618a3 --- /dev/null +++ b/plugins/KeyboardioHID/src/HID-APIs/GamepadAPI.hpp @@ -0,0 +1,104 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 guard +#pragma once + +GamepadAPI::GamepadAPI(void) +{ + // Empty +} + +void GamepadAPI::begin(void){ + // release all buttons + end(); +} + +void GamepadAPI::end(void){ + memset(&_report, 0, sizeof(_report)); + SendReport(&_report, sizeof(_report)); +} + +void GamepadAPI::write(void){ + SendReport(&_report, sizeof(_report)); +} + + +void GamepadAPI::press(uint8_t b){ + _report.buttons |= (uint32_t)1 << (b - 1); +} + + +void GamepadAPI::release(uint8_t b){ + _report.buttons &= ~((uint32_t)1 << (b - 1)); +} + + +void GamepadAPI::releaseAll(void){ + memset(&_report, 0x00, sizeof(_report)); +} + +void GamepadAPI::buttons(uint32_t b){ + _report.buttons = b; +} + + +void GamepadAPI::xAxis(int16_t a){ + _report.xAxis = a; +} + + +void GamepadAPI::yAxis(int16_t a){ + _report.yAxis = a; +} + + +void GamepadAPI::zAxis(int8_t a){ + _report.zAxis = a; +} + + +void GamepadAPI::rxAxis(int16_t a){ + _report.rxAxis = a; +} + + +void GamepadAPI::ryAxis(int16_t a){ + _report.ryAxis = a; +} + + +void GamepadAPI::rzAxis(int8_t a){ + _report.rzAxis = a; +} + + +void GamepadAPI::dPad1(int8_t d){ + _report.dPad1 = d; +} + + +void GamepadAPI::dPad2(int8_t d){ + _report.dPad2 = d; +} + diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index 84cdc5b3ca..8915693616 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -42,7 +42,7 @@ THE SOFTWARE. #include "SingleReport/BootMouse.h" #include "MultiReport/ImprovedMouse.h" #include "MultiReport/Consumer.h" -//#include "Gamepad.h" +#include "MultiReport/Gamepad.h" #include "MultiReport/System.h" //#include "RawHID.h" diff --git a/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp b/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp new file mode 100644 index 0000000000..5539e5bbee --- /dev/null +++ b/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp @@ -0,0 +1,88 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 "Gamepad.h" + + +static const uint8_t _hidMultiReportDescriptorGamepad[] PROGMEM = { + /* Gamepad with 32 buttons and 6 axis*/ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x04, /* USAGE (Joystick) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + 0x85, HID_REPORTID_GAMEPAD, /* REPORT_ID */ + /* 32 Buttons */ + 0x05, 0x09, /* USAGE_PAGE (Button) */ + 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ + 0x29, 0x20, /* USAGE_MAXIMUM (Button 32) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x95, 0x20, /* REPORT_COUNT (32) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + /* 4 16bit Axis */ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0xa1, 0x00, /* COLLECTION (Physical) */ + 0x09, 0x30, /* USAGE (X) */ + 0x09, 0x31, /* USAGE (Y) */ + 0x09, 0x33, /* USAGE (Rx) */ + 0x09, 0x34, /* USAGE (Ry) */ + 0x16, 0x00, 0x80, /* LOGICAL_MINIMUM (-32768) */ + 0x26, 0xFF, 0x7F, /* LOGICAL_MAXIMUM (32767) */ + 0x75, 0x10, /* REPORT_SIZE (16) */ + 0x95, 0x04, /* REPORT_COUNT (4) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + /* 2 8bit Axis */ + 0x09, 0x32, /* USAGE (Z) */ + 0x09, 0x35, /* USAGE (Rz) */ + 0x15, 0x80, /* LOGICAL_MINIMUM (-128) */ + 0x25, 0x7F, /* LOGICAL_MAXIMUM (127) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x02, /* REPORT_COUNT (2) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + 0xc0, /* END_COLLECTION */ + /* 2 Hat Switches */ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x39, /* USAGE (Hat switch) */ + 0x09, 0x39, /* USAGE (Hat switch) */ + 0x15, 0x01, /* LOGICAL_MINIMUM (1) */ + 0x25, 0x08, /* LOGICAL_MAXIMUM (8) */ + 0x95, 0x02, /* REPORT_COUNT (2) */ + 0x75, 0x04, /* REPORT_SIZE (4) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + 0xc0 /* END_COLLECTION */ +}; + +Gamepad_::Gamepad_(void) +{ + static HIDDescriptorListNode node(_hidMultiReportDescriptorGamepad, sizeof(_hidMultiReportDescriptorGamepad)); + HID().AppendDescriptor(&node); +} + + +void Gamepad_::SendReport(void* data, int length) +{ + HID().SendReport(HID_REPORTID_GAMEPAD, data, length); +} + +Gamepad_ Gamepad; + diff --git a/plugins/KeyboardioHID/src/MultiReport/Gamepad.h b/plugins/KeyboardioHID/src/MultiReport/Gamepad.h new file mode 100644 index 0000000000..dfb21a2ade --- /dev/null +++ b/plugins/KeyboardioHID/src/MultiReport/Gamepad.h @@ -0,0 +1,43 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 guard +#pragma once + +#include +#include "PluggableUSB.h" +#include "HID.h" +#include "HID-Settings.h" +#include "../HID-APIs/GamepadAPI.h" + + +class Gamepad_ : public GamepadAPI +{ +public: + Gamepad_(void); + +protected: + virtual inline void SendReport(void* data, int length) override; +}; +extern Gamepad_ Gamepad; + From 01b5328a6c0022d004c403ccd130eba0fc831664 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 11 Oct 2015 11:00:40 +0200 Subject: [PATCH 281/602] minor --- plugins/KeyboardioHID/src/HID-APIs/GamepadAPI.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/HID-APIs/GamepadAPI.hpp b/plugins/KeyboardioHID/src/HID-APIs/GamepadAPI.hpp index 8b025618a3..880b1ba1a9 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/GamepadAPI.hpp +++ b/plugins/KeyboardioHID/src/HID-APIs/GamepadAPI.hpp @@ -35,7 +35,7 @@ void GamepadAPI::begin(void){ } void GamepadAPI::end(void){ - memset(&_report, 0, sizeof(_report)); + memset(&_report, 0x00, sizeof(_report)); SendReport(&_report, sizeof(_report)); } From e554ae7e472bcbd001286d0d5ce6f078b31f962c Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 11 Oct 2015 11:00:50 +0200 Subject: [PATCH 282/602] Added Single Gamepad (Empty files to show off an arduino bug) --- plugins/KeyboardioHID/src/SingleReport/Gamepad.cpp | 0 plugins/KeyboardioHID/src/SingleReport/Gamepad.h | 0 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 plugins/KeyboardioHID/src/SingleReport/Gamepad.cpp create mode 100644 plugins/KeyboardioHID/src/SingleReport/Gamepad.h diff --git a/plugins/KeyboardioHID/src/SingleReport/Gamepad.cpp b/plugins/KeyboardioHID/src/SingleReport/Gamepad.cpp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/plugins/KeyboardioHID/src/SingleReport/Gamepad.h b/plugins/KeyboardioHID/src/SingleReport/Gamepad.h new file mode 100644 index 0000000000..e69de29bb2 From 39c2d1a96fe6abe197d74b6a09428699179bd90f Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 11 Oct 2015 11:07:29 +0200 Subject: [PATCH 283/602] Added Gamepad API --- .../src/SingleReport/Gamepad.cpp | 150 ++++++++++++++++++ .../KeyboardioHID/src/SingleReport/Gamepad.h | 56 +++++++ 2 files changed, 206 insertions(+) diff --git a/plugins/KeyboardioHID/src/SingleReport/Gamepad.cpp b/plugins/KeyboardioHID/src/SingleReport/Gamepad.cpp index e69de29bb2..2a77166d0e 100644 --- a/plugins/KeyboardioHID/src/SingleReport/Gamepad.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/Gamepad.cpp @@ -0,0 +1,150 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 "Gamepad.h" + +static const uint8_t _hidReportDescriptorGamepad[] PROGMEM = { + /* Gamepad with 32 buttons and 6 axis*/ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x04, /* USAGE (Joystick) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + /* 32 Buttons */ + 0x05, 0x09, /* USAGE_PAGE (Button) */ + 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ + 0x29, 0x20, /* USAGE_MAXIMUM (Button 32) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x95, 0x20, /* REPORT_COUNT (32) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + /* 4 16bit Axis */ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0xa1, 0x00, /* COLLECTION (Physical) */ + 0x09, 0x30, /* USAGE (X) */ + 0x09, 0x31, /* USAGE (Y) */ + 0x09, 0x33, /* USAGE (Rx) */ + 0x09, 0x34, /* USAGE (Ry) */ + 0x16, 0x00, 0x80, /* LOGICAL_MINIMUM (-32768) */ + 0x26, 0xFF, 0x7F, /* LOGICAL_MAXIMUM (32767) */ + 0x75, 0x10, /* REPORT_SIZE (16) */ + 0x95, 0x04, /* REPORT_COUNT (4) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + /* 2 8bit Axis */ + 0x09, 0x32, /* USAGE (Z) */ + 0x09, 0x35, /* USAGE (Rz) */ + 0x15, 0x80, /* LOGICAL_MINIMUM (-128) */ + 0x25, 0x7F, /* LOGICAL_MAXIMUM (127) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x02, /* REPORT_COUNT (2) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + 0xc0, /* END_COLLECTION */ + /* 2 Hat Switches */ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x39, /* USAGE (Hat switch) */ + 0x09, 0x39, /* USAGE (Hat switch) */ + 0x15, 0x01, /* LOGICAL_MINIMUM (1) */ + 0x25, 0x08, /* LOGICAL_MAXIMUM (8) */ + 0x95, 0x02, /* REPORT_COUNT (2) */ + 0x75, 0x04, /* REPORT_SIZE (4) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + 0xc0 /* END_COLLECTION */ +}; + +SingleGamepad_::SingleGamepad_(void) : PUSBListNode(1, 1, epType), protocol(1), idle(1) +{ + epType[0] = EP_TYPE_INTERRUPT_IN; + PluggableUSB().plug(this); +} + +int SingleGamepad_::getInterface(uint8_t* interfaceCount) +{ + *interfaceCount += 1; // uses 1 + HIDDescriptor hidInterface = { + D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE), + D_HIDREPORT(sizeof(_hidReportDescriptorGamepad)), + D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) + }; + return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); +} + +int SingleGamepad_::getDescriptor(USBSetup& setup) +{ + // Check if this is a HID Class Descriptor request + if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { return 0; } + if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { return 0; } + + // In a HID Class Descriptor wIndex cointains the interface number + if (setup.wIndex != pluggedInterface) { return 0; } + + return USB_SendControl(TRANSFER_PGM, _hidReportDescriptorGamepad, sizeof(_hidReportDescriptorGamepad)); +} + +bool SingleGamepad_::setup(USBSetup& setup) +{ + if (pluggedInterface != setup.wIndex) { + return false; + } + + uint8_t request = setup.bRequest; + uint8_t requestType = setup.bmRequestType; + + if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) + { + if (request == HID_GET_REPORT) { + // TODO: HID_GetReport(); + return true; + } + if (request == HID_GET_PROTOCOL) { + // TODO: Send8(protocol); + return true; + } + } + + if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) + { + if (request == HID_SET_PROTOCOL) { + protocol = setup.wValueL; + return true; + } + if (request == HID_SET_IDLE) { + idle = setup.wValueL; + return true; + } + if (request == HID_SET_REPORT) + { + } + } + + return false; +} + +void SingleGamepad_::SendReport(void* data, int length){ + USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, length); +} + +SingleGamepad_ Gamepad1; +SingleGamepad_ Gamepad2; +SingleGamepad_ Gamepad3; +SingleGamepad_ Gamepad4; + + diff --git a/plugins/KeyboardioHID/src/SingleReport/Gamepad.h b/plugins/KeyboardioHID/src/SingleReport/Gamepad.h index e69de29bb2..89d0e3777f 100644 --- a/plugins/KeyboardioHID/src/SingleReport/Gamepad.h +++ b/plugins/KeyboardioHID/src/SingleReport/Gamepad.h @@ -0,0 +1,56 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 guard +#pragma once + +#include +#include "PluggableUSB.h" +#include "HID.h" +#include "HID-Settings.h" +#include "../HID-APIs/GamepadAPI.h" + + +class SingleGamepad_ : public PUSBListNode, public GamepadAPI +{ +public: + SingleGamepad_(void); + +protected: + // Implementation of the PUSBListNode + int getInterface(uint8_t* interfaceCount); + int getDescriptor(USBSetup& setup); + bool setup(USBSetup& setup); + + uint8_t epType[1]; + uint8_t protocol; + uint8_t idle; + + virtual void SendReport(void* data, int length) override; +}; +extern SingleGamepad_ Gamepad1; +extern SingleGamepad_ Gamepad2; +extern SingleGamepad_ Gamepad3; +extern SingleGamepad_ Gamepad4; + + From d8cdfaf1d89c346e271fed10253e461c9185fbaa Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 11 Oct 2015 11:08:37 +0200 Subject: [PATCH 284/602] Fixed Gamepad compile errors --- .../src/SingleReport/{Gamepad.cpp => SingleGamepad.cpp} | 2 +- .../src/SingleReport/{Gamepad.h => SingleGamepad.h} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename plugins/KeyboardioHID/src/SingleReport/{Gamepad.cpp => SingleGamepad.cpp} (99%) rename plugins/KeyboardioHID/src/SingleReport/{Gamepad.h => SingleGamepad.h} (100%) diff --git a/plugins/KeyboardioHID/src/SingleReport/Gamepad.cpp b/plugins/KeyboardioHID/src/SingleReport/SingleGamepad.cpp similarity index 99% rename from plugins/KeyboardioHID/src/SingleReport/Gamepad.cpp rename to plugins/KeyboardioHID/src/SingleReport/SingleGamepad.cpp index 2a77166d0e..136a5aaa26 100644 --- a/plugins/KeyboardioHID/src/SingleReport/Gamepad.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/SingleGamepad.cpp @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "Gamepad.h" +#include "SingleGamepad.h" static const uint8_t _hidReportDescriptorGamepad[] PROGMEM = { /* Gamepad with 32 buttons and 6 axis*/ diff --git a/plugins/KeyboardioHID/src/SingleReport/Gamepad.h b/plugins/KeyboardioHID/src/SingleReport/SingleGamepad.h similarity index 100% rename from plugins/KeyboardioHID/src/SingleReport/Gamepad.h rename to plugins/KeyboardioHID/src/SingleReport/SingleGamepad.h From e034b903591fa36734d107e1ff4f989f64013731 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 11 Oct 2015 11:11:34 +0200 Subject: [PATCH 285/602] Activated Single Gamepad support --- plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino | 3 +++ plugins/KeyboardioHID/keywords.txt | 4 ++++ plugins/KeyboardioHID/src/HID-Project.h | 1 + 3 files changed, 8 insertions(+) diff --git a/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino b/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino index c567c0ae9c..7121859973 100644 --- a/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino +++ b/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino @@ -5,6 +5,9 @@ Gamepad example Press a button and demonstrate Gamepad actions + You can also use Gamepad1,2,3 and 4 as single report. + This will use 1 endpoint for each gamepad. + See HID Project documentation for more infos https://github.com/NicoHood/HID/wiki/Gamepad-API */ diff --git a/plugins/KeyboardioHID/keywords.txt b/plugins/KeyboardioHID/keywords.txt index bf69108ac7..ed8860a582 100644 --- a/plugins/KeyboardioHID/keywords.txt +++ b/plugins/KeyboardioHID/keywords.txt @@ -66,6 +66,10 @@ RawHID KEYWORD1 System KEYWORD1 Consumer KEYWORD1 Gamepad KEYWORD1 +Gamepad1 KEYWORD1 +Gamepad2 KEYWORD1 +Gamepad3 KEYWORD1 +Gamepad4 KEYWORD1 TeensyKeyboard KEYWORD1 NKROKeyboard KEYWORD1 AbsoluteMouse KEYWORD1 diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index 8915693616..25ac9f2dc6 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -42,6 +42,7 @@ THE SOFTWARE. #include "SingleReport/BootMouse.h" #include "MultiReport/ImprovedMouse.h" #include "MultiReport/Consumer.h" +#include "SingleReport/SingleGamepad.h" #include "MultiReport/Gamepad.h" #include "MultiReport/System.h" //#include "RawHID.h" From 9da716748d3f50356ae2f3876ee4103eb113866b Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 11 Oct 2015 12:53:37 +0200 Subject: [PATCH 286/602] Mouse API fix --- plugins/KeyboardioHID/src/HID-APIs/MouseAPI.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/HID-APIs/MouseAPI.h b/plugins/KeyboardioHID/src/HID-APIs/MouseAPI.h index 1357d14881..b72712e4a7 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/MouseAPI.h +++ b/plugins/KeyboardioHID/src/HID-APIs/MouseAPI.h @@ -80,7 +80,7 @@ class MouseAPI protected: uint8_t _buttons; - void buttons(uint8_t b); + inline void buttons(uint8_t b); }; // Implementation is inline From 4aa24693cf82705859012cc1279843552b0a7265 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 11 Oct 2015 13:58:02 +0200 Subject: [PATCH 287/602] Added NKRO keyboard --- .../examples/ImprovedMouse/ImprovedMouse.ino | 2 +- .../examples/NKROKeyboard/NKROKeyboard.ino | 2 + plugins/KeyboardioHID/keywords.txt | 1 + .../src/HID-APIs/NKROKeyboardAPI.h | 78 +++++++ .../src/HID-APIs/NKROKeyboardAPI.hpp | 216 ++++++++++++++++++ plugins/KeyboardioHID/src/HID-Project.h | 3 +- .../src/MultiReport/NKROKeyboard.cpp | 79 +++++++ .../src/MultiReport/NKROKeyboard.h | 43 ++++ .../src/SingleReport/SingleNKROKeyboard.cpp | 161 +++++++++++++ .../src/SingleReport/SingleNKROKeyboard.h | 57 +++++ 10 files changed, 640 insertions(+), 2 deletions(-) create mode 100644 plugins/KeyboardioHID/src/HID-APIs/NKROKeyboardAPI.h create mode 100644 plugins/KeyboardioHID/src/HID-APIs/NKROKeyboardAPI.hpp create mode 100644 plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp create mode 100644 plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h create mode 100644 plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.cpp create mode 100644 plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.h diff --git a/plugins/KeyboardioHID/examples/ImprovedMouse/ImprovedMouse.ino b/plugins/KeyboardioHID/examples/ImprovedMouse/ImprovedMouse.ino index 45fcb2122c..3789431df4 100644 --- a/plugins/KeyboardioHID/examples/ImprovedMouse/ImprovedMouse.ino +++ b/plugins/KeyboardioHID/examples/ImprovedMouse/ImprovedMouse.ino @@ -5,7 +5,7 @@ Mouse example Press a button to click or move the mouse. - You may also use BootMouse to enable a bios compatible mouse. + You may also use BootMouse to enable a bios compatible (single report) mouse. However this is very unusual and not recommended. Bios mice dont support wheels which can cause problems after a reboot. diff --git a/plugins/KeyboardioHID/examples/NKROKeyboard/NKROKeyboard.ino b/plugins/KeyboardioHID/examples/NKROKeyboard/NKROKeyboard.ino index 16cca5f2dd..16cd17f189 100644 --- a/plugins/KeyboardioHID/examples/NKROKeyboard/NKROKeyboard.ino +++ b/plugins/KeyboardioHID/examples/NKROKeyboard/NKROKeyboard.ino @@ -8,6 +8,8 @@ NKRO can push 113 keys at the same time, the other Keyboards only 6 keys + 8 modifiers! + You may also use SingleNKROKeyboard to enable a single report NKROKeyboard. + See HID Project documentation for more information. https://github.com/NicoHood/HID/wiki/Keyboard-API */ diff --git a/plugins/KeyboardioHID/keywords.txt b/plugins/KeyboardioHID/keywords.txt index ed8860a582..0f9d4d46e7 100644 --- a/plugins/KeyboardioHID/keywords.txt +++ b/plugins/KeyboardioHID/keywords.txt @@ -72,6 +72,7 @@ Gamepad3 KEYWORD1 Gamepad4 KEYWORD1 TeensyKeyboard KEYWORD1 NKROKeyboard KEYWORD1 +SingleNKROKeyboard KEYWORD1 AbsoluteMouse KEYWORD1 ####################################### diff --git a/plugins/KeyboardioHID/src/HID-APIs/NKROKeyboardAPI.h b/plugins/KeyboardioHID/src/HID-APIs/NKROKeyboardAPI.h new file mode 100644 index 0000000000..c5a9fec589 --- /dev/null +++ b/plugins/KeyboardioHID/src/HID-APIs/NKROKeyboardAPI.h @@ -0,0 +1,78 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 guard +#pragma once + +#include +#include "HID-Settings.h" +#include "ImprovedKeylayouts.h" +#include "HID-Tables.h" //TODO + +// Max value for USB EP_SIZE 16 +// +1 reportID, +1 modifier, +1 custom key +#define NKRO_KEY_COUNT (8*13) + +typedef union{ + // Modifier + keymap + 1 custom key + uint8_t whole8[]; + uint16_t whole16[]; + uint32_t whole32[]; + struct{ + uint8_t modifiers; + uint8_t keys[NKRO_KEY_COUNT / 8]; + uint8_t key; + }; +} HID_NKROKeyboardReport_Data_t; + + +class NKROKeyboardAPI : public Print +{ +public: + inline NKROKeyboardAPI(void); + inline void begin(void); + inline void end(void); + inline size_t write(uint8_t k); + inline size_t press(uint8_t k); + inline size_t release(uint8_t k); + inline void releaseAll(void); + inline void send_now(void); + + inline size_t writeKeycode(uint8_t k); + inline size_t pressKeycode(uint8_t k); + inline size_t releaseKeycode(uint8_t k); + inline size_t addKeyToReport(uint8_t k); + inline size_t addKeycodeToReport(uint8_t k); + inline size_t removeKeyFromReport(uint8_t k); + inline size_t removeKeycodeFromReport(uint8_t k); + + // Sending is public in the base class for advanced users. + virtual void SendReport(void* data, int length) = 0; + +protected: + HID_NKROKeyboardReport_Data_t _keyReport; +}; + +// Implementation is inline +#include "NKROKeyboardAPI.hpp" + diff --git a/plugins/KeyboardioHID/src/HID-APIs/NKROKeyboardAPI.hpp b/plugins/KeyboardioHID/src/HID-APIs/NKROKeyboardAPI.hpp new file mode 100644 index 0000000000..9d15ed743d --- /dev/null +++ b/plugins/KeyboardioHID/src/HID-APIs/NKROKeyboardAPI.hpp @@ -0,0 +1,216 @@ +/* +Copyright (c) 2015 NicoHood +See the readme for credit to other people. + +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 guard +#pragma once + +NKROKeyboardAPI::NKROKeyboardAPI(void) +{ + // Empty +} + +void NKROKeyboardAPI::begin(void) +{ + releaseAll(); +} + +void NKROKeyboardAPI::end(void) +{ + releaseAll(); +} + +void NKROKeyboardAPI::send_now(void){ + SendReport(&_keyReport, sizeof(_keyReport)); +} + +// 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 NKROKeyboardAPI::press(uint8_t k) +{ + size_t ret = addKeyToReport(k); + if(ret){ + send_now(); + } + return ret; +} + +// 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 NKROKeyboardAPI::release(uint8_t k) +{ + // it's a non-printing key (not a modifier) + if (k >= 136) + k = k - 136; + + // it's a modifier key + else if (k >= 128) + k = k - 128; + + // it's a printing key + else { + k = pgm_read_byte(_asciimap + k); + if (!k) + return 0; + + // it's a capital letter or other character reached with shift + if (k & SHIFT) { + // the left shift modifier + _keyReport.modifiers &= ~(0x02); + k = k ^ SHIFT; + } + } + + removeKeycodeFromReport(k); + send_now(); + + return 1; +} + +void NKROKeyboardAPI::releaseAll(void) +{ + // release all keys + memset(&_keyReport, 0x00, sizeof(_keyReport)); + send_now(); +} + +size_t NKROKeyboardAPI::write(uint8_t c) +{ + uint8_t p = press(c); // Keydown + release(c); // Keyup + return p; // just return the result of press() since release() almost always returns 1 +} + + +// pressKeycode() 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 releaseKeycode(), releaseAll(), or otherwise clear the report and resend. +size_t NKROKeyboardAPI::pressKeycode(uint8_t k) +{ + if (!addKeycodeToReport(k)) { + return 0; + } + send_now(); +} + +size_t NKROKeyboardAPI::addKeyToReport(uint8_t k) +{ + 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; //TODO return 1?? + } else { // it's a printing key + k = pgm_read_byte(_asciimap + k); + if (!k) { + setWriteError(); + return 0; + } + if (k & SHIFT) { // it's a capital letter or other character reached with shift + _keyReport.modifiers |= 0x02; // the left shift modifier + k = k ^ SHIFT; + } + } + + return addKeycodeToReport(k); +} + +size_t NKROKeyboardAPI::addKeycodeToReport(uint8_t k) +{ + // keymap key + if (k < NKRO_KEY_COUNT) + _keyReport.keys[k / 8] |= 1 << (k % 8); + + // it's a modifier key + else if ((k >= HID_KEYBOARD_LEFT_CONTROL) && (k <= HID_KEYBOARD_RIGHT_GUI)) + _keyReport.modifiers |= (0x01 << (k - HID_KEYBOARD_LEFT_CONTROL)); + + // custom key + else + _keyReport.key = k; + + return 1; +} + + +// releaseKeycode() 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. +// When send is set to FALSE (= 0) no sendReport() is executed. This comes in +// handy when combining key releases (e.g. SHIFT+A). +size_t NKROKeyboardAPI::releaseKeycode(uint8_t k) +{ + if (!removeKeycodeFromReport(k)) { + return 0; + } + send_now(); +} + +size_t NKROKeyboardAPI::removeKeyFromReport(uint8_t k) +{ + 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 & SHIFT) { // it's a capital letter or other character reached with shift + _keyReport.modifiers &= ~(0x02); // the left shift modifier + k = k ^ SHIFT; + } + } + + return removeKeycodeFromReport(k); +} + +size_t NKROKeyboardAPI::removeKeycodeFromReport(uint8_t k) +{ + // keymap key + if (k < NKRO_KEY_COUNT) + _keyReport.keys[k / 8] &= ~(1 << (k % 8)); + + // it's a modifier key + else if ((k >= HID_KEYBOARD_LEFT_CONTROL) && (k <= HID_KEYBOARD_RIGHT_GUI)) + _keyReport.modifiers &= ~(0x01 << (k - HID_KEYBOARD_LEFT_CONTROL)); + + // custom key + else + _keyReport.key = 0x00; + + return 1; +} + + +size_t NKROKeyboardAPI::writeKeycode(uint8_t c) +{ + uint8_t p = pressKeycode(c); // Keydown + releaseKeycode(c); // Keyup + return (p); // just return the result of pressKeycode() since release() almost always returns 1 +} diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index 25ac9f2dc6..42f300c20c 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -53,5 +53,6 @@ THE SOFTWARE. #else #include "SingleReport/BootKeyboard.h" #include "MultiReport/ImprovedKeyboard.h" -//#include "NKROKeyboard.h" +#include "SingleReport/SingleNKROKeyboard.h" +#include "MultiReport/NKROKeyboard.h" #endif diff --git a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp new file mode 100644 index 0000000000..f635c9b23e --- /dev/null +++ b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp @@ -0,0 +1,79 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 "NKROKeyboard.h" + +static const uint8_t _hidMultiReportDescriptorNKROKeyboard[] PROGMEM = { + // NKRO Keyboard + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 47 */ + 0x09, 0x06, /* USAGE (Keyboard) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + 0x85, HID_REPORTID_NKRO_KEYBOARD, /* REPORT_ID */ + 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ + + /* Keyboard Modifiers (shift, alt, ...) */ + 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) */ + + /* 104 Keys as bitmap */ + 0x05, 0x07, /* Usage Page (Key Codes) TODO needed?*/ + 0x19, 0x00, /* Usage Minimum (0) */ + 0x29, NKRO_KEY_COUNT - 1, /* Usage Maximum (103) */ + 0x15, 0x00, /* Logical Minimum (0) */ + 0x25, 0x01, /* Logical Maximum (1) */ + 0x75, 0x01, /* Report Size (1) */ + 0x95, NKRO_KEY_COUNT, /* Report Count (104) */ + 0x81, 0x02, /* Input (Data, Variable, Absolute) */ + + /* 1 Custom Keyboard key */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x26, 0xE7, 0x00, /* LOGICAL_MAXIMUM (231) */ + /*0x05, 0x07, USAGE_PAGE (Keyboard) TODO */ + 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ + 0x29, 0xE7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ + 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ + + /* End */ + 0xC0 /* End Collection */ +}; + +NKROKeyboard_::NKROKeyboard_(void) +{ + static HIDDescriptorListNode node(_hidMultiReportDescriptorNKROKeyboard, sizeof(_hidMultiReportDescriptorNKROKeyboard)); + HID().AppendDescriptor(&node); +} + +void NKROKeyboard_::SendReport(void* data, int length) +{ + HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, data, length); +} + +NKROKeyboard_ NKROKeyboard; + diff --git a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h new file mode 100644 index 0000000000..7b94add67a --- /dev/null +++ b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h @@ -0,0 +1,43 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 guard +#pragma once + +#include +#include "PluggableUSB.h" +#include "HID.h" +#include "HID-Settings.h" +#include "../HID-APIs/NKROKeyboardAPI.h" + + +class NKROKeyboard_ : public NKROKeyboardAPI +{ +public: + NKROKeyboard_(void); + +protected: + virtual inline void SendReport(void* data, int length) override; +}; +extern NKROKeyboard_ NKROKeyboard; + diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.cpp b/plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.cpp new file mode 100644 index 0000000000..381ecea344 --- /dev/null +++ b/plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.cpp @@ -0,0 +1,161 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 "SingleNKROKeyboard.h" + +static const uint8_t _hidReportDescriptorNKRO[] PROGMEM = { + // NKRO Keyboard + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 47 */ + 0x09, 0x06, /* USAGE (Keyboard) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ + + /* Keyboard Modifiers (shift, alt, ...) */ + 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) */ + + /* 5 LEDs for num lock etc, 3 left for advanced, custom usage */ + 0x05, 0x08, /* USAGE_PAGE (LEDs) */ + 0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */ + 0x29, 0x05, /* USAGE_MAXIMUM (Kana) */ + 0x95, 0x08, /* REPORT_COUNT (8) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */ + /* Reserved 3 bits */ + //0x95, 0x01, /* REPORT_COUNT (1) */ + //0x75, 0x03, /* REPORT_SIZE (3) */ + //0x91, 0x03, /* OUTPUT (Cnst,Var,Abs) */ + + /* 104 Keys as bitmap */ + 0x05, 0x07, /* Usage Page (Key Codes) */ + 0x19, 0x00, /* Usage Minimum (0) */ + 0x29, NKRO_KEY_COUNT - 1, /* Usage Maximum (103) */ + 0x15, 0x00, /* Logical Minimum (0) */ + 0x25, 0x01, /* Logical Maximum (1) */ + 0x75, 0x01, /* Report Size (1) */ + 0x95, NKRO_KEY_COUNT, /* Report Count (104) */ + 0x81, 0x02, /* Input (Data, Variable, Absolute) */ + + /* 1 Custom Keyboard key */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x26, 0xE7, 0x00, /* LOGICAL_MAXIMUM (231) */ + /*0x05, 0x07, USAGE_PAGE (Keyboard) */ + 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ + 0x29, 0xE7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ + 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ + + /* End */ + 0xC0 /* End Collection */ +}; + +SingleNKROKeyboard_::SingleNKROKeyboard_(void) : PUSBListNode(1, 1, epType), protocol(1), idle(1), leds(0) +{ + epType[0] = EP_TYPE_INTERRUPT_IN; + PluggableUSB().plug(this); +} + +int SingleNKROKeyboard_::getInterface(uint8_t* interfaceCount) +{ + *interfaceCount += 1; // uses 1 + HIDDescriptor hidInterface = { + D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE), + D_HIDREPORT(sizeof(_hidReportDescriptorNKRO)), + D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) + }; + return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); +} + +int SingleNKROKeyboard_::getDescriptor(USBSetup& setup) +{ + // Check if this is a HID Class Descriptor request + if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { return 0; } + if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { return 0; } + + // In a HID Class Descriptor wIndex cointains the interface number + if (setup.wIndex != pluggedInterface) { return 0; } + + return USB_SendControl(TRANSFER_PGM, _hidReportDescriptorNKRO, sizeof(_hidReportDescriptorNKRO)); +} + +bool SingleNKROKeyboard_::setup(USBSetup& setup) +{ + if (pluggedInterface != setup.wIndex) { + return false; + } + + uint8_t request = setup.bRequest; + uint8_t requestType = setup.bmRequestType; + + if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) + { + if (request == HID_GET_REPORT) { + // TODO: HID_GetReport(); + return true; + } + if (request == HID_GET_PROTOCOL) { + // TODO: Send8(protocol); + return true; + } + } + + if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) + { + if (request == HID_SET_PROTOCOL) { + protocol = setup.wValueL; + return true; + } + if (request == HID_SET_IDLE) { + idle = setup.wValueL; + return true; + } + if (request == HID_SET_REPORT) + { + // Check if data has the correct length + auto length = setup.wLength; + if(length == sizeof(leds)){ + USB_RecvControl(&leds, length); + } + } + } + + return false; +} + +uint8_t SingleNKROKeyboard_::getLeds(void){ + return leds; +} + +void SingleNKROKeyboard_::SendReport(void* data, int length){ + USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, length); +} + +SingleNKROKeyboard_ SingleNKROKeyboard; + + diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.h b/plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.h new file mode 100644 index 0000000000..299ed16d23 --- /dev/null +++ b/plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.h @@ -0,0 +1,57 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 guard +#pragma once + +#include +#include "PluggableUSB.h" +#include "HID.h" +#include "HID-Settings.h" +#include "../HID-APIs/NKROKeyboardAPI.h" + + +class SingleNKROKeyboard_ : public PUSBListNode, public NKROKeyboardAPI +{ +public: + SingleNKROKeyboard_(void); + uint8_t getLeds(void); + uint8_t getProtocol(void); + +protected: + // Implementation of the PUSBListNode + int getInterface(uint8_t* interfaceCount); + int getDescriptor(USBSetup& setup); + bool setup(USBSetup& setup); + + uint8_t epType[1]; + uint8_t protocol; + uint8_t idle; + + uint8_t leds; + + virtual void SendReport(void* data, int length) override; +}; +extern SingleNKROKeyboard_ SingleNKROKeyboard; + + From 0bb3da42c043a48c24b1fa16ec09d4caae56836f Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 11 Oct 2015 14:51:18 +0200 Subject: [PATCH 288/602] Added RawHID --- .../KeyboardioHID/src/SingleReport/RawHID.cpp | 125 +++++++++++++ .../KeyboardioHID/src/SingleReport/RawHID.h | 176 ++++++++++++++++++ 2 files changed, 301 insertions(+) create mode 100644 plugins/KeyboardioHID/src/SingleReport/RawHID.cpp create mode 100644 plugins/KeyboardioHID/src/SingleReport/RawHID.h diff --git a/plugins/KeyboardioHID/src/SingleReport/RawHID.cpp b/plugins/KeyboardioHID/src/SingleReport/RawHID.cpp new file mode 100644 index 0000000000..7a4c9ddfa8 --- /dev/null +++ b/plugins/KeyboardioHID/src/SingleReport/RawHID.cpp @@ -0,0 +1,125 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 "RawHID.h" + +static const uint8_t _hidReportDescriptorRawHID[] PROGMEM = { + /* RAW HID */ + 0x06, lowByte(RAWHID_USAGE_PAGE), highByte(RAWHID_USAGE_PAGE), /* 30 */ + 0x0A, lowByte(RAWHID_USAGE), highByte(RAWHID_USAGE), + + 0xA1, 0x01, /* Collection 0x01 */ + // RawHID is not multireport compatible. + // On Linux it might work with some modifications, + // however you are not happy to use it like that. + //0x85, HID_REPORTID_RAWHID, /* REPORT_ID */ + 0x75, 0x08, /* report size = 8 bits */ + 0x15, 0x00, /* logical minimum = 0 */ + 0x26, 0xFF, 0x00, /* logical maximum = 255 */ + + 0x95, RAWHID_TX_SIZE, /* report count TX */ + 0x09, 0x01, /* usage */ + 0x81, 0x02, /* Input (array) */ + + 0x95, RAWHID_RX_SIZE, /* report count RX */ + 0x09, 0x02, /* usage */ + 0x91, 0x02, /* Output (array) */ + 0xC0 /* end collection */ +}; + +RawHID_::RawHID_(void) : PUSBListNode(1, 1, epType), protocol(1), idle(1), dataLength(0) +{ + epType[0] = EP_TYPE_INTERRUPT_IN; + PluggableUSB().plug(this); +} + +int RawHID_::getInterface(uint8_t* interfaceCount) +{ + // TODO add a 2nd OUT endpoint to get more speed??? + // Maybe as optional device + *interfaceCount += 1; // uses 1 + HIDDescriptor hidInterface = { + D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE), + D_HIDREPORT(sizeof(_hidReportDescriptorRawHID)), + D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) + }; + return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); +} + +int RawHID_::getDescriptor(USBSetup& setup) +{ + // Check if this is a HID Class Descriptor request + if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { return 0; } + if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { return 0; } + + // In a HID Class Descriptor wIndex cointains the interface number + if (setup.wIndex != pluggedInterface) { return 0; } + + return USB_SendControl(TRANSFER_PGM, _hidReportDescriptorRawHID, sizeof(_hidReportDescriptorRawHID)); +} + +bool RawHID_::setup(USBSetup& setup) +{ + if (pluggedInterface != setup.wIndex) { + return false; + } + + uint8_t request = setup.bRequest; + uint8_t requestType = setup.bmRequestType; + + if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) + { + if (request == HID_GET_REPORT) { + // TODO: HID_GetReport(); + return true; + } + if (request == HID_GET_PROTOCOL) { + // TODO: Send8(protocol); + return true; + } + } + + if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) + { + if (request == HID_SET_PROTOCOL) { + protocol = setup.wValueL; + return true; + } + if (request == HID_SET_IDLE) { + idle = setup.wValueL; + return true; + } + if (request == HID_SET_REPORT) + { + // TODO + } + } + + return false; +} + +void RawHID_::SendReport(void* data, int length){ + USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, length); +} + +RawHID_ RawHID; diff --git a/plugins/KeyboardioHID/src/SingleReport/RawHID.h b/plugins/KeyboardioHID/src/SingleReport/RawHID.h new file mode 100644 index 0000000000..399039ff18 --- /dev/null +++ b/plugins/KeyboardioHID/src/SingleReport/RawHID.h @@ -0,0 +1,176 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 guard +#pragma once + +#include +#include "PluggableUSB.h" +#include "HID.h" +#include "HID-Settings.h" + +// RawHID might never work with multireports, because of OS problems +// therefore we have to make it a single report with no idea. No other HID device will be supported then. +#undef RAWHID_USAGE_PAGE +#define RAWHID_USAGE_PAGE 0xFFC0 // recommended: 0xFF00 to 0xFFFF + +#undef RAWHID_USAGE +#define RAWHID_USAGE 0x0C00 // recommended: 0x0100 to 0xFFFF + +// Keep one byte offset for the reportID if used +#if (HID_REPORTID_RAWHID) +#define RAWHID_SIZE (USB_EP_SIZE-1) +#else +#define RAWHID_SIZE (USB_EP_SIZE) +#endif + +#undef RAWHID_TX_SIZE +#define RAWHID_TX_SIZE RAWHID_SIZE + +#undef RAWHID_RX_SIZE +#define RAWHID_RX_SIZE RAWHID_SIZE + +typedef union{ + // a RAWHID_TX_SIZE byte buffer for tx + uint8_t whole8[]; + uint16_t whole16[]; + uint32_t whole32[]; + uint8_t buff[RAWHID_TX_SIZE]; +} HID_RawKeyboardTXReport_Data_t; + +typedef union{ + // a RAWHID_TX_SIZE byte buffer for rx + uint8_t whole8[]; + uint16_t whole16[]; + uint32_t whole32[]; + uint8_t buff[RAWHID_RX_SIZE]; +} HID_RawKeyboardRXReport_Data_t; + +class RawHID_ : public PUSBListNode, public Stream +{ +public: + RawHID_(void); + + void begin(void){ + // empty + } + + void end(void){ + // empty + } + + virtual int available(void){ + return dataLength; + } + + virtual int read(){ + if(dataLength){ + // Get next data byte + uint8_t data = *(dataTail - dataLength); + dataLength--; + + // Release buffer if its read fully + if(!dataLength){ + free(dataHead); + } + + return data; + } + return -1; + } + + virtual int peek(){ + if(dataLength){ + return *(dataTail - dataLength); + } + return -1; + } + + virtual void flush(void){ + // Delete all incoming bytes + if(dataLength){ + free(dataHead); + dataLength = 0; + } + } + + using Print::write; + virtual size_t write(uint8_t b){ + return write(&b, 1); + } + + virtual size_t write(uint8_t *buffer, size_t size){ + // TODO this only sends the report ID in the first packat + // TODO this will split the data into USB_EP_SIZE packets + SendReport(buffer, size); + return size; + + size_t bytesleft = size; + // First work through the buffer thats already there + while (bytesleft >= RAWHID_TX_SIZE){ + SendReport(&buffer[size - bytesleft], RAWHID_TX_SIZE); + bytesleft -= RAWHID_TX_SIZE; + } + + // Write down the leftover bytes and fill with zeros + if (bytesleft){ + SendReport(&buffer[size - bytesleft], bytesleft); + } + + return size; + } + + void SendReport(void* data, int length); + +protected: + // Implementation of the PUSBListNode + int getInterface(uint8_t* interfaceCount); + int getDescriptor(USBSetup& setup); + bool setup(USBSetup& setup); + + uint8_t epType[1]; + uint8_t protocol; + uint8_t idle; + + + virtual void setReportData(void* &data, int len){ + // Only overwrite the buffer if its empty. + // This avoids corrupted data while reading. + if(!dataLength){ + // Save new data + dataLength = len; + dataHead = (uint8_t*) data; + dataTail = (uint8_t*)(data) + len; + + // Clear the passed in pointer to not free the data + data = NULL; + } + } + + // Buffer pointers to hold the received data + int dataLength; + uint8_t* dataHead; + uint8_t* dataTail; +}; +extern RawHID_ RawHID; + From a045a05abe835c21febcc6bea5a528338ddb8f83 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Mon, 12 Oct 2015 17:12:09 +0200 Subject: [PATCH 289/602] Rename two class https://github.com/arduino/Arduino/pull/3960 --- plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp | 2 +- plugins/KeyboardioHID/src/MultiReport/Consumer.cpp | 2 +- plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp | 2 +- plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.cpp | 2 +- plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.cpp | 2 +- plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp | 2 +- plugins/KeyboardioHID/src/MultiReport/System.cpp | 2 +- plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp | 2 +- plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h | 2 +- plugins/KeyboardioHID/src/SingleReport/BootMouse.cpp | 2 +- plugins/KeyboardioHID/src/SingleReport/BootMouse.h | 2 +- plugins/KeyboardioHID/src/SingleReport/RawHID.cpp | 2 +- plugins/KeyboardioHID/src/SingleReport/RawHID.h | 2 +- plugins/KeyboardioHID/src/SingleReport/SingleGamepad.cpp | 2 +- plugins/KeyboardioHID/src/SingleReport/SingleGamepad.h | 2 +- plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.cpp | 2 +- plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.h | 2 +- 17 files changed, 17 insertions(+), 17 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp index c4e16c509e..b8179bceb2 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp @@ -65,7 +65,7 @@ static const uint8_t _hidMultiReportDescriptorAbsoluteMouse[] PROGMEM = { AbsoluteMouse_::AbsoluteMouse_(void) { - static HIDDescriptorListNode node(_hidMultiReportDescriptorAbsoluteMouse, sizeof(_hidMultiReportDescriptorAbsoluteMouse)); + static HIDSubDescriptor node(_hidMultiReportDescriptorAbsoluteMouse, sizeof(_hidMultiReportDescriptorAbsoluteMouse)); HID().AppendDescriptor(&node); } diff --git a/plugins/KeyboardioHID/src/MultiReport/Consumer.cpp b/plugins/KeyboardioHID/src/MultiReport/Consumer.cpp index 7e8a116d3c..0fa6841eb5 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Consumer.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Consumer.cpp @@ -43,7 +43,7 @@ static const uint8_t _hidMultiReportDescriptorConsumer[] PROGMEM = { Consumer_::Consumer_(void) { - static HIDDescriptorListNode node(_hidMultiReportDescriptorConsumer, sizeof(_hidMultiReportDescriptorConsumer)); + static HIDSubDescriptor node(_hidMultiReportDescriptorConsumer, sizeof(_hidMultiReportDescriptorConsumer)); HID().AppendDescriptor(&node); } diff --git a/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp b/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp index 5539e5bbee..86b95e6523 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp @@ -74,7 +74,7 @@ static const uint8_t _hidMultiReportDescriptorGamepad[] PROGMEM = { Gamepad_::Gamepad_(void) { - static HIDDescriptorListNode node(_hidMultiReportDescriptorGamepad, sizeof(_hidMultiReportDescriptorGamepad)); + static HIDSubDescriptor node(_hidMultiReportDescriptorGamepad, sizeof(_hidMultiReportDescriptorGamepad)); HID().AppendDescriptor(&node); } diff --git a/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.cpp index 1e9c0609aa..a4d5fc3918 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.cpp @@ -61,7 +61,7 @@ static const uint8_t _hidMultiReportDescriptorKeyboard[] PROGMEM = { Keyboard_::Keyboard_(void) { - static HIDDescriptorListNode node(_hidMultiReportDescriptorKeyboard, sizeof(_hidMultiReportDescriptorKeyboard)); + static HIDSubDescriptor node(_hidMultiReportDescriptorKeyboard, sizeof(_hidMultiReportDescriptorKeyboard)); HID().AppendDescriptor(&node); } diff --git a/plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.cpp b/plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.cpp index c3b8e5af9b..9e4ffebcde 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.cpp @@ -59,7 +59,7 @@ static const uint8_t _hidMultiReportDescriptorMouse[] PROGMEM = { Mouse_::Mouse_(void) { - static HIDDescriptorListNode node(_hidMultiReportDescriptorMouse, sizeof(_hidMultiReportDescriptorMouse)); + static HIDSubDescriptor node(_hidMultiReportDescriptorMouse, sizeof(_hidMultiReportDescriptorMouse)); HID().AppendDescriptor(&node); } diff --git a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp index f635c9b23e..5e341f9890 100644 --- a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp @@ -66,7 +66,7 @@ static const uint8_t _hidMultiReportDescriptorNKROKeyboard[] PROGMEM = { NKROKeyboard_::NKROKeyboard_(void) { - static HIDDescriptorListNode node(_hidMultiReportDescriptorNKROKeyboard, sizeof(_hidMultiReportDescriptorNKROKeyboard)); + static HIDSubDescriptor node(_hidMultiReportDescriptorNKROKeyboard, sizeof(_hidMultiReportDescriptorNKROKeyboard)); HID().AppendDescriptor(&node); } diff --git a/plugins/KeyboardioHID/src/MultiReport/System.cpp b/plugins/KeyboardioHID/src/MultiReport/System.cpp index b3e9af55a2..6ba4ab40a6 100644 --- a/plugins/KeyboardioHID/src/MultiReport/System.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/System.cpp @@ -44,7 +44,7 @@ static const uint8_t _hidMultiReportDescriptorSystem[] PROGMEM = { System_::System_(void) { - static HIDDescriptorListNode node(_hidMultiReportDescriptorSystem, sizeof(_hidMultiReportDescriptorSystem)); + static HIDSubDescriptor node(_hidMultiReportDescriptorSystem, sizeof(_hidMultiReportDescriptorSystem)); HID().AppendDescriptor(&node); } diff --git a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp index 393d73082e..05dd7a2493 100644 --- a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp @@ -70,7 +70,7 @@ static const uint8_t _hidReportDescriptorKeyboard[] PROGMEM = { 0xc0 /* END_COLLECTION */ }; -BootKeyboard_::BootKeyboard_(void) : PUSBListNode(1, 1, epType), protocol(1), idle(1), leds(0) +BootKeyboard_::BootKeyboard_(void) : PluggableUSBModule(1, 1, epType), protocol(1), idle(1), leds(0) { epType[0] = EP_TYPE_INTERRUPT_IN; PluggableUSB().plug(this); diff --git a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h index f360d934d6..b7066f947b 100644 --- a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h @@ -31,7 +31,7 @@ THE SOFTWARE. #include "../HID-APIs/KeyboardAPI.h" -class BootKeyboard_ : public PUSBListNode, public KeyboardAPI +class BootKeyboard_ : public PluggableUSBModule, public KeyboardAPI { public: BootKeyboard_(void); diff --git a/plugins/KeyboardioHID/src/SingleReport/BootMouse.cpp b/plugins/KeyboardioHID/src/SingleReport/BootMouse.cpp index 980b505d92..470c5cd038 100644 --- a/plugins/KeyboardioHID/src/SingleReport/BootMouse.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/BootMouse.cpp @@ -54,7 +54,7 @@ static const uint8_t _hidReportDescriptorMouse[] PROGMEM = { 0xc0 /* END_COLLECTION */ }; -BootMouse_::BootMouse_(void) : PUSBListNode(1, 1, epType), protocol(1), idle(1) +BootMouse_::BootMouse_(void) : PluggableUSBModule(1, 1, epType), protocol(1), idle(1) { epType[0] = EP_TYPE_INTERRUPT_IN; PluggableUSB().plug(this); diff --git a/plugins/KeyboardioHID/src/SingleReport/BootMouse.h b/plugins/KeyboardioHID/src/SingleReport/BootMouse.h index 00462b0f6e..833f22d2d2 100644 --- a/plugins/KeyboardioHID/src/SingleReport/BootMouse.h +++ b/plugins/KeyboardioHID/src/SingleReport/BootMouse.h @@ -31,7 +31,7 @@ THE SOFTWARE. #include "../HID-APIs/MouseAPI.h" -class BootMouse_ : public PUSBListNode, public MouseAPI +class BootMouse_ : public PluggableUSBModule, public MouseAPI { public: BootMouse_(void); diff --git a/plugins/KeyboardioHID/src/SingleReport/RawHID.cpp b/plugins/KeyboardioHID/src/SingleReport/RawHID.cpp index 7a4c9ddfa8..8be96f9b53 100644 --- a/plugins/KeyboardioHID/src/SingleReport/RawHID.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/RawHID.cpp @@ -47,7 +47,7 @@ static const uint8_t _hidReportDescriptorRawHID[] PROGMEM = { 0xC0 /* end collection */ }; -RawHID_::RawHID_(void) : PUSBListNode(1, 1, epType), protocol(1), idle(1), dataLength(0) +RawHID_::RawHID_(void) : PluggableUSBModule(1, 1, epType), protocol(1), idle(1), dataLength(0) { epType[0] = EP_TYPE_INTERRUPT_IN; PluggableUSB().plug(this); diff --git a/plugins/KeyboardioHID/src/SingleReport/RawHID.h b/plugins/KeyboardioHID/src/SingleReport/RawHID.h index 399039ff18..15d8cb6b63 100644 --- a/plugins/KeyboardioHID/src/SingleReport/RawHID.h +++ b/plugins/KeyboardioHID/src/SingleReport/RawHID.h @@ -66,7 +66,7 @@ typedef union{ uint8_t buff[RAWHID_RX_SIZE]; } HID_RawKeyboardRXReport_Data_t; -class RawHID_ : public PUSBListNode, public Stream +class RawHID_ : public PluggableUSBModule, public Stream { public: RawHID_(void); diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleGamepad.cpp b/plugins/KeyboardioHID/src/SingleReport/SingleGamepad.cpp index 136a5aaa26..0791f42800 100644 --- a/plugins/KeyboardioHID/src/SingleReport/SingleGamepad.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/SingleGamepad.cpp @@ -70,7 +70,7 @@ static const uint8_t _hidReportDescriptorGamepad[] PROGMEM = { 0xc0 /* END_COLLECTION */ }; -SingleGamepad_::SingleGamepad_(void) : PUSBListNode(1, 1, epType), protocol(1), idle(1) +SingleGamepad_::SingleGamepad_(void) : PluggableUSBModule(1, 1, epType), protocol(1), idle(1) { epType[0] = EP_TYPE_INTERRUPT_IN; PluggableUSB().plug(this); diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleGamepad.h b/plugins/KeyboardioHID/src/SingleReport/SingleGamepad.h index 89d0e3777f..bca1db598e 100644 --- a/plugins/KeyboardioHID/src/SingleReport/SingleGamepad.h +++ b/plugins/KeyboardioHID/src/SingleReport/SingleGamepad.h @@ -31,7 +31,7 @@ THE SOFTWARE. #include "../HID-APIs/GamepadAPI.h" -class SingleGamepad_ : public PUSBListNode, public GamepadAPI +class SingleGamepad_ : public PluggableUSBModule, public GamepadAPI { public: SingleGamepad_(void); diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.cpp b/plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.cpp index 381ecea344..f88118c0c5 100644 --- a/plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.cpp @@ -75,7 +75,7 @@ static const uint8_t _hidReportDescriptorNKRO[] PROGMEM = { 0xC0 /* End Collection */ }; -SingleNKROKeyboard_::SingleNKROKeyboard_(void) : PUSBListNode(1, 1, epType), protocol(1), idle(1), leds(0) +SingleNKROKeyboard_::SingleNKROKeyboard_(void) : PluggableUSBModule(1, 1, epType), protocol(1), idle(1), leds(0) { epType[0] = EP_TYPE_INTERRUPT_IN; PluggableUSB().plug(this); diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.h b/plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.h index 299ed16d23..131eaa3966 100644 --- a/plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.h +++ b/plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.h @@ -31,7 +31,7 @@ THE SOFTWARE. #include "../HID-APIs/NKROKeyboardAPI.h" -class SingleNKROKeyboard_ : public PUSBListNode, public NKROKeyboardAPI +class SingleNKROKeyboard_ : public PluggableUSBModule, public NKROKeyboardAPI { public: SingleNKROKeyboard_(void); From 2be6a503e8bd872a9ec0bed4ca0f071c0d654da1 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Mon, 12 Oct 2015 18:04:11 +0200 Subject: [PATCH 290/602] Fixed protocol reset on reenumeration --- plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp | 6 +++++- plugins/KeyboardioHID/src/SingleReport/BootMouse.cpp | 6 +++++- plugins/KeyboardioHID/src/SingleReport/RawHID.cpp | 6 +++++- plugins/KeyboardioHID/src/SingleReport/SingleGamepad.cpp | 6 +++++- .../KeyboardioHID/src/SingleReport/SingleNKROKeyboard.cpp | 6 +++++- 5 files changed, 25 insertions(+), 5 deletions(-) diff --git a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp index 05dd7a2493..d29b2d85de 100644 --- a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp @@ -70,7 +70,7 @@ static const uint8_t _hidReportDescriptorKeyboard[] PROGMEM = { 0xc0 /* END_COLLECTION */ }; -BootKeyboard_::BootKeyboard_(void) : PluggableUSBModule(1, 1, epType), protocol(1), idle(1), leds(0) +BootKeyboard_::BootKeyboard_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1), leds(0) { epType[0] = EP_TYPE_INTERRUPT_IN; PluggableUSB().plug(this); @@ -96,6 +96,10 @@ int BootKeyboard_::getDescriptor(USBSetup& setup) // In a HID Class Descriptor wIndex cointains the interface number if (setup.wIndex != pluggedInterface) { return 0; } + // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol + // due to the USB specs, but Windows and Linux just assumes its in report mode. + protocol = HID_REPORT_PROTOCOL; + return USB_SendControl(TRANSFER_PGM, _hidReportDescriptorKeyboard, sizeof(_hidReportDescriptorKeyboard)); } diff --git a/plugins/KeyboardioHID/src/SingleReport/BootMouse.cpp b/plugins/KeyboardioHID/src/SingleReport/BootMouse.cpp index 470c5cd038..27aee631d6 100644 --- a/plugins/KeyboardioHID/src/SingleReport/BootMouse.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/BootMouse.cpp @@ -54,7 +54,7 @@ static const uint8_t _hidReportDescriptorMouse[] PROGMEM = { 0xc0 /* END_COLLECTION */ }; -BootMouse_::BootMouse_(void) : PluggableUSBModule(1, 1, epType), protocol(1), idle(1) +BootMouse_::BootMouse_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1) { epType[0] = EP_TYPE_INTERRUPT_IN; PluggableUSB().plug(this); @@ -80,6 +80,10 @@ int BootMouse_::getDescriptor(USBSetup& setup) // In a HID Class Descriptor wIndex cointains the interface number if (setup.wIndex != pluggedInterface) { return 0; } + // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol + // due to the USB specs, but Windows and Linux just assumes its in report mode. + protocol = HID_REPORT_PROTOCOL; + return USB_SendControl(TRANSFER_PGM, _hidReportDescriptorMouse, sizeof(_hidReportDescriptorMouse)); } diff --git a/plugins/KeyboardioHID/src/SingleReport/RawHID.cpp b/plugins/KeyboardioHID/src/SingleReport/RawHID.cpp index 8be96f9b53..03e854b78d 100644 --- a/plugins/KeyboardioHID/src/SingleReport/RawHID.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/RawHID.cpp @@ -47,7 +47,7 @@ static const uint8_t _hidReportDescriptorRawHID[] PROGMEM = { 0xC0 /* end collection */ }; -RawHID_::RawHID_(void) : PluggableUSBModule(1, 1, epType), protocol(1), idle(1), dataLength(0) +RawHID_::RawHID_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1), dataLength(0) { epType[0] = EP_TYPE_INTERRUPT_IN; PluggableUSB().plug(this); @@ -75,6 +75,10 @@ int RawHID_::getDescriptor(USBSetup& setup) // In a HID Class Descriptor wIndex cointains the interface number if (setup.wIndex != pluggedInterface) { return 0; } + // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol + // due to the USB specs, but Windows and Linux just assumes its in report mode. + protocol = HID_REPORT_PROTOCOL; + return USB_SendControl(TRANSFER_PGM, _hidReportDescriptorRawHID, sizeof(_hidReportDescriptorRawHID)); } diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleGamepad.cpp b/plugins/KeyboardioHID/src/SingleReport/SingleGamepad.cpp index 0791f42800..acb86de0b0 100644 --- a/plugins/KeyboardioHID/src/SingleReport/SingleGamepad.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/SingleGamepad.cpp @@ -70,7 +70,7 @@ static const uint8_t _hidReportDescriptorGamepad[] PROGMEM = { 0xc0 /* END_COLLECTION */ }; -SingleGamepad_::SingleGamepad_(void) : PluggableUSBModule(1, 1, epType), protocol(1), idle(1) +SingleGamepad_::SingleGamepad_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1) { epType[0] = EP_TYPE_INTERRUPT_IN; PluggableUSB().plug(this); @@ -96,6 +96,10 @@ int SingleGamepad_::getDescriptor(USBSetup& setup) // In a HID Class Descriptor wIndex cointains the interface number if (setup.wIndex != pluggedInterface) { return 0; } + // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol + // due to the USB specs, but Windows and Linux just assumes its in report mode. + protocol = HID_REPORT_PROTOCOL; + return USB_SendControl(TRANSFER_PGM, _hidReportDescriptorGamepad, sizeof(_hidReportDescriptorGamepad)); } diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.cpp b/plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.cpp index f88118c0c5..bfb37a6d2f 100644 --- a/plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.cpp @@ -75,7 +75,7 @@ static const uint8_t _hidReportDescriptorNKRO[] PROGMEM = { 0xC0 /* End Collection */ }; -SingleNKROKeyboard_::SingleNKROKeyboard_(void) : PluggableUSBModule(1, 1, epType), protocol(1), idle(1), leds(0) +SingleNKROKeyboard_::SingleNKROKeyboard_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1), leds(0) { epType[0] = EP_TYPE_INTERRUPT_IN; PluggableUSB().plug(this); @@ -101,6 +101,10 @@ int SingleNKROKeyboard_::getDescriptor(USBSetup& setup) // In a HID Class Descriptor wIndex cointains the interface number if (setup.wIndex != pluggedInterface) { return 0; } + // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol + // due to the USB specs, but Windows and Linux just assumes its in report mode. + protocol = HID_REPORT_PROTOCOL; + return USB_SendControl(TRANSFER_PGM, _hidReportDescriptorNKRO, sizeof(_hidReportDescriptorNKRO)); } From da95f77157cb3a564d671dfe5054e3df2c56ae2e Mon Sep 17 00:00:00 2001 From: NicoHood Date: Mon, 12 Oct 2015 21:46:15 +0200 Subject: [PATCH 291/602] Improved HID Report Descriptors --- plugins/KeyboardioHID/src/HID-APIs/TeensyKeyboardAPI.h | 3 ++- .../KeyboardioHID/src/MultiReport/ImprovedKeyboard.cpp | 1 - plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp | 2 -- plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp | 6 +----- .../src/SingleReport/SingleNKROKeyboard.cpp | 9 ++------- 5 files changed, 5 insertions(+), 16 deletions(-) diff --git a/plugins/KeyboardioHID/src/HID-APIs/TeensyKeyboardAPI.h b/plugins/KeyboardioHID/src/HID-APIs/TeensyKeyboardAPI.h index 0e630b3b1a..9282dc4b53 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/TeensyKeyboardAPI.h +++ b/plugins/KeyboardioHID/src/HID-APIs/TeensyKeyboardAPI.h @@ -55,8 +55,9 @@ static const uint8_t PROGMEM teensykeyboard_hid_report_desc[] = { 0x09, 0xB6, // Usage (Scan Previous Track), 0x09, 0xB7, // Usage (Stop), 0x09, 0xB8, // Usage (Eject), -// Note: Teensy ledreport was not modified to 8 bit, nor left out when leds are deactivated 0x81, 0x02, // Input (Data, Variable, Absolute), ;Media keys + + // Note: Teensy ledreport was not modified to 8 bit, nor left out when leds are deactivated 0x95, 0x05, // Report Count (5), 0x75, 0x01, // Report Size (1), 0x05, 0x08, // Usage Page (LEDs), diff --git a/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.cpp index a4d5fc3918..9f4ef2004b 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.cpp @@ -50,7 +50,6 @@ static const uint8_t _hidMultiReportDescriptorKeyboard[] PROGMEM = { 0x75, 0x08, /* REPORT_SIZE (8) */ 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ 0x26, 0xE7, 0x00, /* LOGICAL_MAXIMUM (231) */ - 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ 0x29, 0xE7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ diff --git a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp index 5e341f9890..4accc878d0 100644 --- a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp @@ -41,7 +41,6 @@ static const uint8_t _hidMultiReportDescriptorNKROKeyboard[] PROGMEM = { 0x81, 0x02, /* INPUT (Data,Var,Abs) */ /* 104 Keys as bitmap */ - 0x05, 0x07, /* Usage Page (Key Codes) TODO needed?*/ 0x19, 0x00, /* Usage Minimum (0) */ 0x29, NKRO_KEY_COUNT - 1, /* Usage Maximum (103) */ 0x15, 0x00, /* Logical Minimum (0) */ @@ -55,7 +54,6 @@ static const uint8_t _hidMultiReportDescriptorNKROKeyboard[] PROGMEM = { 0x75, 0x08, /* REPORT_SIZE (8) */ 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ 0x26, 0xE7, 0x00, /* LOGICAL_MAXIMUM (231) */ - /*0x05, 0x07, USAGE_PAGE (Keyboard) TODO */ 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ 0x29, 0xE7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ diff --git a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp index d29b2d85de..c4529718cc 100644 --- a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp @@ -47,14 +47,10 @@ static const uint8_t _hidReportDescriptorKeyboard[] PROGMEM = { /* 5 LEDs for num lock etc, 3 left for advanced, custom usage */ 0x05, 0x08, /* USAGE_PAGE (LEDs) */ 0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */ - 0x29, 0x05, /* USAGE_MAXIMUM (Kana) TODO*/ + 0x29, 0x08, /* USAGE_MAXIMUM (Kana + 3 custom)*/ 0x95, 0x08, /* REPORT_COUNT (8) */ 0x75, 0x01, /* REPORT_SIZE (1) */ 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */ - /* Reserved 3 bits TODO */ - //0x95, 0x01, /* REPORT_COUNT (1) */ - //0x75, 0x03, /* REPORT_SIZE (3) */ - //0x91, 0x03, /* OUTPUT (Cnst,Var,Abs) */ /* 6 Keyboard keys */ 0x95, 0x06, /* REPORT_COUNT (6) */ diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.cpp b/plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.cpp index bfb37a6d2f..c5d5e2414d 100644 --- a/plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.cpp @@ -42,17 +42,13 @@ static const uint8_t _hidReportDescriptorNKRO[] PROGMEM = { /* 5 LEDs for num lock etc, 3 left for advanced, custom usage */ 0x05, 0x08, /* USAGE_PAGE (LEDs) */ 0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */ - 0x29, 0x05, /* USAGE_MAXIMUM (Kana) */ + 0x29, 0x08, /* USAGE_MAXIMUM (Kana + 3 custom)*/ 0x95, 0x08, /* REPORT_COUNT (8) */ 0x75, 0x01, /* REPORT_SIZE (1) */ 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */ - /* Reserved 3 bits */ - //0x95, 0x01, /* REPORT_COUNT (1) */ - //0x75, 0x03, /* REPORT_SIZE (3) */ - //0x91, 0x03, /* OUTPUT (Cnst,Var,Abs) */ /* 104 Keys as bitmap */ - 0x05, 0x07, /* Usage Page (Key Codes) */ + 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ 0x19, 0x00, /* Usage Minimum (0) */ 0x29, NKRO_KEY_COUNT - 1, /* Usage Maximum (103) */ 0x15, 0x00, /* Logical Minimum (0) */ @@ -66,7 +62,6 @@ static const uint8_t _hidReportDescriptorNKRO[] PROGMEM = { 0x75, 0x08, /* REPORT_SIZE (8) */ 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ 0x26, 0xE7, 0x00, /* LOGICAL_MAXIMUM (231) */ - /*0x05, 0x07, USAGE_PAGE (Keyboard) */ 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ 0x29, 0xE7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ From 292cb7041f75a523e0a117e4c1981f1dab6b8f53 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Tue, 13 Oct 2015 18:41:15 +0200 Subject: [PATCH 292/602] Enabled Raw HID --- .../KeyboardioHID/examples/RawHID/RawHID.ino | 71 +------------------ plugins/KeyboardioHID/src/HID-Project.h | 2 +- .../KeyboardioHID/src/SingleReport/RawHID.cpp | 35 ++++++++- .../KeyboardioHID/src/SingleReport/RawHID.h | 18 +---- 4 files changed, 36 insertions(+), 90 deletions(-) diff --git a/plugins/KeyboardioHID/examples/RawHID/RawHID.ino b/plugins/KeyboardioHID/examples/RawHID/RawHID.ino index a6b83f6ef5..6da4f58c1a 100644 --- a/plugins/KeyboardioHID/examples/RawHID/RawHID.ino +++ b/plugins/KeyboardioHID/examples/RawHID/RawHID.ino @@ -19,8 +19,6 @@ const int pinButton = 2; void setup() { pinMode(pinLed, OUTPUT); pinMode(pinButton, INPUT_PULLUP); - Serial.begin(0);//TODO - //Keyboard.begin(); // No begin function needed for RawHID } @@ -28,29 +26,12 @@ void loop() { if (!digitalRead(pinButton)) { digitalWrite(pinLed, HIGH); - // Direct without library. Always send RAWHID_RX_SIZE bytes! - uint8_t buff[RAWHID_TX_SIZE] = {0}; - - // With library - memset(&buff, 42, sizeof(buff)); - RawHID.write(buff, sizeof(buff)); - - // Write a single byte, will fill the rest with zeros - RawHID.write(0xCD); - - // Huge buffer with library, will fill the rest with zeros + // Create buffer and send it uint8_t megabuff[100]; for (int i = 0; i < sizeof(megabuff); i++) megabuff[i] = i; RawHID.write(megabuff, sizeof(megabuff)); - // You can use print too, but better do not use a linefeed. - // A linefeed will send the \r and \n in a separate report. - RawHID.println("Hello World"); - - // Compare print to write: - RawHID.write("Hello World\r\n"); - // Simple debounce delay(300); digitalWrite(pinLed, LOW); @@ -73,53 +54,3 @@ void loop() { digitalWrite(pinLed, LOW); } } - -/* - Expected output: - - // manual with unintialized buff - recv 15 bytes: - 01 55 C1 FF 01 01 01 00 00 01 00 00 01 00 20 - - // filled buff - recv 15 bytes: - 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A - - // single byte filled with zero - recv 15 bytes: - CD 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - - // huge buffer filled with zero at the end - recv 15 bytes: - 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E - - recv 15 bytes: - 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D - - recv 15 bytes: - 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C - - recv 15 bytes: - 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B - - recv 15 bytes: - 3C 3D 3E 3F 00 00 00 00 00 00 00 00 00 00 00 - - // print - recv 15 bytes: - 48 65 6C 6C 6F 20 57 6F 72 6C 64 00 00 00 00 - - //\r - recv 15 bytes: - 0D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - - //\n - recv 15 bytes: - 0A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - - //write - recv 15 bytes: - 48 65 6C 6C 6F 20 57 6F 72 6C 64 0D 0A 00 00 - -*/ - diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index 42f300c20c..f7dce02979 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -45,7 +45,7 @@ THE SOFTWARE. #include "SingleReport/SingleGamepad.h" #include "MultiReport/Gamepad.h" #include "MultiReport/System.h" -//#include "RawHID.h" +#include "SingleReport/RawHID.h" // Include Teensy HID afterwards to overwrite key definitions if used #ifdef USE_TEENSY_KEYBOARD diff --git a/plugins/KeyboardioHID/src/SingleReport/RawHID.cpp b/plugins/KeyboardioHID/src/SingleReport/RawHID.cpp index 03e854b78d..66c9d1b920 100644 --- a/plugins/KeyboardioHID/src/SingleReport/RawHID.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/RawHID.cpp @@ -56,7 +56,7 @@ RawHID_::RawHID_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_P int RawHID_::getInterface(uint8_t* interfaceCount) { // TODO add a 2nd OUT endpoint to get more speed??? - // Maybe as optional device + // Maybe as optional device FastRawHID with different USAGE PAGE *interfaceCount += 1; // uses 1 HIDDescriptor hidInterface = { D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE), @@ -115,7 +115,38 @@ bool RawHID_::setup(USBSetup& setup) } if (request == HID_SET_REPORT) { - // TODO + // Get the data length information and the corresponding bytes + int length = setup.wLength; + + // Ensure that there IS some data + if(length > 0) + { + void* data = malloc(length); + if(data){ + auto recvLength = length; + //TODO loop can be improved maybe? Or does the compiler do this already? + while(recvLength > USB_EP_SIZE){ + USB_RecvControl((uint8_t*)data + (length - recvLength), USB_EP_SIZE); + recvLength -= USB_EP_SIZE; + } + USB_RecvControl((uint8_t*)data + (length - recvLength), recvLength); + + // Only overwrite the buffer if its empty. + // This avoids corrupted data while reading. + if(!dataLength){ + // Save new data + dataLength = length; + dataHead = (uint8_t*) data; + dataTail = (uint8_t*)(data) + length; + + // Clear the passed in pointer to not free the data + data = NULL; + } + } + + // Release data if the pointer still exists + free(data); + } } } diff --git a/plugins/KeyboardioHID/src/SingleReport/RawHID.h b/plugins/KeyboardioHID/src/SingleReport/RawHID.h index 15d8cb6b63..2a365e217a 100644 --- a/plugins/KeyboardioHID/src/SingleReport/RawHID.h +++ b/plugins/KeyboardioHID/src/SingleReport/RawHID.h @@ -120,8 +120,7 @@ class RawHID_ : public PluggableUSBModule, public Stream } virtual size_t write(uint8_t *buffer, size_t size){ - // TODO this only sends the report ID in the first packat - // TODO this will split the data into USB_EP_SIZE packets + // TODO this will split the data into proper USB_EP_SIZE packets already SendReport(buffer, size); return size; @@ -152,21 +151,6 @@ class RawHID_ : public PluggableUSBModule, public Stream uint8_t protocol; uint8_t idle; - - virtual void setReportData(void* &data, int len){ - // Only overwrite the buffer if its empty. - // This avoids corrupted data while reading. - if(!dataLength){ - // Save new data - dataLength = len; - dataHead = (uint8_t*) data; - dataTail = (uint8_t*)(data) + len; - - // Clear the passed in pointer to not free the data - data = NULL; - } - } - // Buffer pointers to hold the received data int dataLength; uint8_t* dataHead; From a11e62baf731c1d95953e62a013edfb988e3549c Mon Sep 17 00:00:00 2001 From: NicoHood Date: Tue, 13 Oct 2015 18:45:48 +0200 Subject: [PATCH 293/602] Added Raw HID test program --- plugins/KeyboardioHID/extras/rawhid/Makefile | 59 +++ plugins/KeyboardioHID/extras/rawhid/hid.h | 6 + .../KeyboardioHID/extras/rawhid/hid_LINUX.c | 381 ++++++++++++++++ .../KeyboardioHID/extras/rawhid/hid_MACOSX.c | 412 ++++++++++++++++++ .../KeyboardioHID/extras/rawhid/hid_WINDOWS.c | 328 ++++++++++++++ .../KeyboardioHID/extras/rawhid/rawhid_test.c | 100 +++++ 6 files changed, 1286 insertions(+) create mode 100644 plugins/KeyboardioHID/extras/rawhid/Makefile create mode 100644 plugins/KeyboardioHID/extras/rawhid/hid.h create mode 100644 plugins/KeyboardioHID/extras/rawhid/hid_LINUX.c create mode 100644 plugins/KeyboardioHID/extras/rawhid/hid_MACOSX.c create mode 100644 plugins/KeyboardioHID/extras/rawhid/hid_WINDOWS.c create mode 100644 plugins/KeyboardioHID/extras/rawhid/rawhid_test.c diff --git a/plugins/KeyboardioHID/extras/rawhid/Makefile b/plugins/KeyboardioHID/extras/rawhid/Makefile new file mode 100644 index 0000000000..62d2d6682c --- /dev/null +++ b/plugins/KeyboardioHID/extras/rawhid/Makefile @@ -0,0 +1,59 @@ + +OS = LINUX +#OS = MACOSX +#OS = WINDOWS + +PROG = rawhid_test + +# To set up Ubuntu Linux to cross compile for Windows: +# +# apt-get install mingw32 mingw32-binutils mingw32-runtime +# +# Just edit the variable above for WINDOWS, then use "make" to build rawhid.exe + +ifeq ($(OS), LINUX) +TARGET = $(PROG) +CC = gcc +STRIP = strip +CFLAGS = -Wall -O2 -DOS_$(OS) +LIBS = -lusb +else ifeq ($(OS), MACOSX) +TARGET = $(PROG).dmg +SDK = /Developer/SDKs/MacOSX10.5.sdk +ARCH = -mmacosx-version-min=10.5 -arch ppc -arch i386 +CC = gcc +STRIP = strip +CFLAGS = -Wall -O2 -DOS_$(OS) -isysroot $(SDK) $(ARCH) +LIBS = $(ARCH) -Wl,-syslibroot,$(SDK) -framework IOKit -framework CoreFoundation +else ifeq ($(OS), WINDOWS) +TARGET = $(PROG).exe +CC = i586-mingw32msvc-gcc +STRIP = i586-mingw32msvc-strip +CFLAGS = -Wall -O2 -DOS_$(OS) +LIBS = -lhid -lsetupapi +endif + +OBJS = $(PROG).o hid.o + + +all: $(TARGET) + +$(PROG): $(OBJS) + $(CC) -o $(PROG) $(OBJS) $(LIBS) + $(STRIP) $(PROG) + +$(PROG).exe: $(PROG) + cp $(PROG) $(PROG).exe + +$(PROG).dmg: $(PROG) + mkdir tmp + cp $(PROG) tmp + hdiutil create -ov -volname "Raw HID Test" -srcfolder tmp $(PROG).dmg + +hid.o: hid_$(OS).c hid.h + $(CC) $(CFLAGS) -c -o $@ $< + +clean: + rm -f *.o $(PROG) $(PROG).exe $(PROG).dmg + rm -rf tmp + diff --git a/plugins/KeyboardioHID/extras/rawhid/hid.h b/plugins/KeyboardioHID/extras/rawhid/hid.h new file mode 100644 index 0000000000..4d837035e1 --- /dev/null +++ b/plugins/KeyboardioHID/extras/rawhid/hid.h @@ -0,0 +1,6 @@ + +int rawhid_open(int max, int vid, int pid, int usage_page, int usage); +int rawhid_recv(int num, void *buf, int len, int timeout); +int rawhid_send(int num, void *buf, int len, int timeout); +void rawhid_close(int num); + diff --git a/plugins/KeyboardioHID/extras/rawhid/hid_LINUX.c b/plugins/KeyboardioHID/extras/rawhid/hid_LINUX.c new file mode 100644 index 0000000000..8e98113e88 --- /dev/null +++ b/plugins/KeyboardioHID/extras/rawhid/hid_LINUX.c @@ -0,0 +1,381 @@ +/* Simple Raw HID functions for Linux - for use with Teensy RawHID example + * http://www.pjrc.com/teensy/rawhid.html + * Copyright (c) 2009 PJRC.COM, LLC + * + * rawhid_open - open 1 or more devices + * rawhid_recv - receive a packet + * rawhid_send - send a packet + * rawhid_close - close a device + * + * 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 description, website URL and 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 + */ + +#include +#include +#include +#include + +#include "hid.h" + + +// On Linux there are several options to access HID devices. +// +// libusb 0.1 - the only way that works well on all distributions +// libusb 1.0 - someday will become standard on most distributions +// hidraw driver - relatively new, not supported on many distributions (yet) +// hiddev driver - old, ubuntu, fedora, others dropping support +// usbfs - low level usb API: http://www.kernel.org/doc/htmldocs/usb.html#usbfs +// +// This code uses libusb 0.1, which is well supported on all linux distributions +// and very stable and widely used by many programs. libusb 0.1 only provides a +// simple synchronous interface, basically the same as this code needs. However, +// if you want non-blocking I/O, libusb 0.1 simply does not provide that. There +// is also no kernel-level buffering, so performance is poor. +// +// UPDATE: As of November 2011, hidraw support seems to be working well in all +// major linux distributions. Embedded and "small" distros, used on ARM boards, +// routers and embedded hardware stil seem to omit the hidraw driver. +// +// The hidraw driver is a great solution. However, it has only been supported +// by relatively recent (in 2009) kernels. Here is a quick survey of the status +// of hidraw support in various distributions as of Sept 2009: +// +// Fedora 11: works, kernel 2.6.29.4 +// Mandiva 2009.1: works, kernel 2.6.29.1 +// Ubuntu 9.10-alpha6: works, kernel 2.6.31 +// Ubuntu 9.04: sysfs attrs chain broken (hidraw root only), 2.6.28 kernel +// openSUSE 11.1: sysfs attrs chain broken (hidraw root only), 2.6.27.7 kernel +// Debian Live, Lenny 5.0.2: sysfs attrs chain broken (hidraw root only), 2.6.26 +// SimplyMEPIS 8.0.10: sysfs attrs chain broken (hidraw root only), 2.6.27 +// Mint 7: sysfs attrs chain broken (hidraw root only), 2.6.28 kernel +// Gentoo 2008.0-r1: sysfs attrs chain broken (hidraw root only), 2.6.24 kernel +// Centos 5: no hidraw or hiddev devices, 2.6.18 kernel +// Slitaz 2.0: no hidraw devices (has hiddev), 2.6.25.5 kernel +// Puppy 4.3: no hidraw devices (has hiddev), 2.6.30.5 kernel +// Damn Small 4.4.10: (would not boot) +// Gentoo 10.0-test20090926: (would not boot) +// PCLinuxOS 2009.2: (would not boot) +// Slackware: (no live cd available? www.slackware-live.org dead) + + + +#define printf(...) // comment this out for lots of info + + +// a list of all opened HID devices, so the caller can +// simply refer to them by number +typedef struct hid_struct hid_t; +static hid_t *first_hid = NULL; +static hid_t *last_hid = NULL; +struct hid_struct { + usb_dev_handle *usb; + int open; + int iface; + int ep_in; + int ep_out; + struct hid_struct *prev; + struct hid_struct *next; +}; + + +// private functions, not intended to be used from outside this file +static void add_hid(hid_t *h); +static hid_t * get_hid(int num); +static void free_all_hid(void); +static void hid_close(hid_t *hid); +static int hid_parse_item(uint32_t *val, uint8_t **data, const uint8_t *end); + + +// rawhid_recv - receive a packet +// Inputs: +// num = device to receive from (zero based) +// buf = buffer to receive packet +// len = buffer's size +// timeout = time to wait, in milliseconds +// Output: +// number of bytes received, or -1 on error +// +int rawhid_recv(int num, void *buf, int len, int timeout) +{ + hid_t *hid; + int r; + + hid = get_hid(num); + if (!hid || !hid->open) return -1; + r = usb_interrupt_read(hid->usb, hid->ep_in, buf, len, timeout); + if (r >= 0) return r; + if (r == -110) return 0; // timeout + return -1; +} + +// rawhid_send - send a packet +// Inputs: +// num = device to transmit to (zero based) +// buf = buffer containing packet to send +// len = number of bytes to transmit +// timeout = time to wait, in milliseconds +// Output: +// number of bytes sent, or -1 on error +// +int rawhid_send(int num, void *buf, int len, int timeout) +{ + hid_t *hid; + + hid = get_hid(num); + if (!hid || !hid->open) return -1; + if (hid->ep_out) { + return usb_interrupt_write(hid->usb, hid->ep_out, buf, len, timeout); + } else { + return usb_control_msg(hid->usb, 0x21, 9, 0, hid->iface, buf, len, timeout); + } +} + +// rawhid_open - open 1 or more devices +// +// Inputs: +// max = maximum number of devices to open +// vid = Vendor ID, or -1 if any +// pid = Product ID, or -1 if any +// usage_page = top level usage page, or -1 if any +// usage = top level usage number, or -1 if any +// Output: +// actual number of devices opened +// +int rawhid_open(int max, int vid, int pid, int usage_page, int usage) +{ + struct usb_bus *bus; + struct usb_device *dev; + struct usb_interface *iface; + struct usb_interface_descriptor *desc; + struct usb_endpoint_descriptor *ep; + usb_dev_handle *u; + uint8_t buf[1024], *p; + int i, n, len, tag, ep_in, ep_out, count=0, claimed; + uint32_t val=0, parsed_usage, parsed_usage_page; + hid_t *hid; + + if (first_hid) free_all_hid(); + printf("rawhid_open, max=%d\n", max); + if (max < 1) return 0; + usb_init(); + usb_find_busses(); + usb_find_devices(); + for (bus = usb_get_busses(); bus; bus = bus->next) { + for (dev = bus->devices; dev; dev = dev->next) { + if (vid > 0 && dev->descriptor.idVendor != vid) continue; + if (pid > 0 && dev->descriptor.idProduct != pid) continue; + if (!dev->config) continue; + if (dev->config->bNumInterfaces < 1) continue; + printf("device: vid=%04X, pic=%04X, with %d iface\n", + dev->descriptor.idVendor, + dev->descriptor.idProduct, + dev->config->bNumInterfaces); + iface = dev->config->interface; + u = NULL; + claimed = 0; + for (i=0; iconfig->bNumInterfaces && iface; i++, iface++) { + desc = iface->altsetting; + if (!desc) continue; + printf(" type %d, %d, %d\n", desc->bInterfaceClass, + desc->bInterfaceSubClass, desc->bInterfaceProtocol); + if (desc->bInterfaceClass != 3) continue; + if (desc->bInterfaceSubClass != 0) continue; + if (desc->bInterfaceProtocol != 0) continue; + ep = desc->endpoint; + ep_in = ep_out = 0; + for (n = 0; n < desc->bNumEndpoints; n++, ep++) { + if (ep->bEndpointAddress & 0x80) { + if (!ep_in) ep_in = ep->bEndpointAddress & 0x7F; + printf(" IN endpoint %d\n", ep_in); + } else { + if (!ep_out) ep_out = ep->bEndpointAddress; + printf(" OUT endpoint %d\n", ep_out); + } + } + if (!ep_in) continue; + if (!u) { + u = usb_open(dev); + if (!u) { + printf(" unable to open device\n"); + break; + } + } + printf(" hid interface (generic)\n"); + if (usb_get_driver_np(u, i, (char *)buf, sizeof(buf)) >= 0) { + printf(" in use by driver \"%s\"\n", buf); + if (usb_detach_kernel_driver_np(u, i) < 0) { + printf(" unable to detach from kernel\n"); + continue; + } + } + if (usb_claim_interface(u, i) < 0) { + printf(" unable claim interface %d\n", i); + continue; + } + len = usb_control_msg(u, 0x81, 6, 0x2200, i, (char *)buf, sizeof(buf), 250); + printf(" descriptor, len=%d\n", len); + if (len < 2) { + usb_release_interface(u, i); + continue; + } + p = buf; + parsed_usage_page = parsed_usage = 0; + while ((tag = hid_parse_item(&val, &p, buf + len)) >= 0) { + printf(" tag: %X, val %X\n", tag, val); + if (tag == 4) parsed_usage_page = val; + if (tag == 8) parsed_usage = val; + if (parsed_usage_page && parsed_usage) break; + } + if ((!parsed_usage_page) || (!parsed_usage) || + (usage_page > 0 && parsed_usage_page != usage_page) || + (usage > 0 && parsed_usage != usage)) { + usb_release_interface(u, i); + continue; + } + hid = (struct hid_struct *)malloc(sizeof(struct hid_struct)); + if (!hid) { + usb_release_interface(u, i); + continue; + } + hid->usb = u; + hid->iface = i; + hid->ep_in = ep_in; + hid->ep_out = ep_out; + hid->open = 1; + add_hid(hid); + claimed++; + count++; + if (count >= max) return count; + } + if (u && !claimed) usb_close(u); + } + } + return count; +} + + +// rawhid_close - close a device +// +// Inputs: +// num = device to close (zero based) +// Output +// (nothing) +// +void rawhid_close(int num) +{ + hid_t *hid; + + hid = get_hid(num); + if (!hid || !hid->open) return; + hid_close(hid); +} + +// Chuck Robey wrote a real HID report parser +// (chuckr@telenix.org) chuckr@chuckr.org +// http://people.freebsd.org/~chuckr/code/python/uhidParser-0.2.tbz +// this tiny thing only needs to extract the top-level usage page +// and usage, and even then is may not be truly correct, but it does +// work with the Teensy Raw HID example. +static int hid_parse_item(uint32_t *val, uint8_t **data, const uint8_t *end) +{ + const uint8_t *p = *data; + uint8_t tag; + int table[4] = {0, 1, 2, 4}; + int len; + + if (p >= end) return -1; + if (p[0] == 0xFE) { + // long item, HID 1.11, 6.2.2.3, page 27 + if (p + 5 >= end || p + p[1] >= end) return -1; + tag = p[2]; + *val = 0; + len = p[1] + 5; + } else { + // short item, HID 1.11, 6.2.2.2, page 26 + tag = p[0] & 0xFC; + len = table[p[0] & 0x03]; + if (p + len + 1 >= end) return -1; + switch (p[0] & 0x03) { + case 3: *val = p[1] | (p[2] << 8) | (p[3] << 16) | (p[4] << 24); break; + case 2: *val = p[1] | (p[2] << 8); break; + case 1: *val = p[1]; break; + case 0: *val = 0; break; + } + } + *data += len + 1; + return tag; +} + + +static void add_hid(hid_t *h) +{ + if (!first_hid || !last_hid) { + first_hid = last_hid = h; + h->next = h->prev = NULL; + return; + } + last_hid->next = h; + h->prev = last_hid; + h->next = NULL; + last_hid = h; +} + + +static hid_t * get_hid(int num) +{ + hid_t *p; + for (p = first_hid; p && num > 0; p = p->next, num--) ; + return p; +} + + +static void free_all_hid(void) +{ + hid_t *p, *q; + + for (p = first_hid; p; p = p->next) { + hid_close(p); + } + p = first_hid; + while (p) { + q = p; + p = p->next; + free(q); + } + first_hid = last_hid = NULL; +} + + +static void hid_close(hid_t *hid) +{ + hid_t *p; + int others=0; + + usb_release_interface(hid->usb, hid->iface); + for (p = first_hid; p; p = p->next) { + if (p->open && p->usb == hid->usb) others++; + } + if (!others) usb_close(hid->usb); + hid->usb = NULL; +} + + + diff --git a/plugins/KeyboardioHID/extras/rawhid/hid_MACOSX.c b/plugins/KeyboardioHID/extras/rawhid/hid_MACOSX.c new file mode 100644 index 0000000000..c5d5d1bbba --- /dev/null +++ b/plugins/KeyboardioHID/extras/rawhid/hid_MACOSX.c @@ -0,0 +1,412 @@ +/* Simple Raw HID functions for Linux - for use with Teensy RawHID example + * http://www.pjrc.com/teensy/rawhid.html + * Copyright (c) 2009 PJRC.COM, LLC + * + * rawhid_open - open 1 or more devices + * rawhid_recv - receive a packet + * rawhid_send - send a packet + * rawhid_close - close a device + * + * 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 description, website URL and 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 + */ + +#include +#include +#include +#include +#include +#include + +#include "hid.h" + +#define BUFFER_SIZE 64 + +#define printf(...) // comment this out to get lots of info printed + + +// a list of all opened HID devices, so the caller can +// simply refer to them by number +typedef struct hid_struct hid_t; +typedef struct buffer_struct buffer_t; +static hid_t *first_hid = NULL; +static hid_t *last_hid = NULL; +struct hid_struct { + IOHIDDeviceRef ref; + int open; + uint8_t buffer[BUFFER_SIZE]; + buffer_t *first_buffer; + buffer_t *last_buffer; + struct hid_struct *prev; + struct hid_struct *next; +}; +struct buffer_struct { + struct buffer_struct *next; + uint32_t len; + uint8_t buf[BUFFER_SIZE]; +}; + +// private functions, not intended to be used from outside this file +static void add_hid(hid_t *); +static hid_t * get_hid(int); +static void free_all_hid(void); +static void hid_close(hid_t *); +static void attach_callback(void *, IOReturn, void *, IOHIDDeviceRef); +static void detach_callback(void *, IOReturn, void *hid_mgr, IOHIDDeviceRef dev); +static void timeout_callback(CFRunLoopTimerRef, void *); +static void input_callback(void *, IOReturn, void *, IOHIDReportType, + uint32_t, uint8_t *, CFIndex); + + + +// rawhid_recv - receive a packet +// Inputs: +// num = device to receive from (zero based) +// buf = buffer to receive packet +// len = buffer's size +// timeout = time to wait, in milliseconds +// Output: +// number of bytes received, or -1 on error +// +int rawhid_recv(int num, void *buf, int len, int timeout) +{ + hid_t *hid; + buffer_t *b; + CFRunLoopTimerRef timer=NULL; + CFRunLoopTimerContext context; + int ret=0, timeout_occurred=0; + + if (len < 1) return 0; + hid = get_hid(num); + if (!hid || !hid->open) return -1; + if ((b = hid->first_buffer) != NULL) { + if (len > b->len) len = b->len; + memcpy(buf, b->buf, len); + hid->first_buffer = b->next; + free(b); + return len; + } + memset(&context, 0, sizeof(context)); + context.info = &timeout_occurred; + timer = CFRunLoopTimerCreate(NULL, CFAbsoluteTimeGetCurrent() + + (double)timeout / 1000.0, 0, 0, 0, timeout_callback, &context); + CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, kCFRunLoopDefaultMode); + while (1) { + CFRunLoopRun(); + if ((b = hid->first_buffer) != NULL) { + if (len > b->len) len = b->len; + memcpy(buf, b->buf, len); + hid->first_buffer = b->next; + free(b); + ret = len; + break; + } + if (!hid->open) { + printf("rawhid_recv, device not open\n"); + ret = -1; + break; + } + if (timeout_occurred) break; + } + CFRunLoopTimerInvalidate(timer); + CFRelease(timer); + return ret; +} + +static void input_callback(void *context, IOReturn ret, void *sender, + IOHIDReportType type, uint32_t id, uint8_t *data, CFIndex len) +{ + buffer_t *n; + hid_t *hid; + + printf("input_callback\n"); + if (ret != kIOReturnSuccess || len < 1) return; + hid = context; + if (!hid || hid->ref != sender) return; + n = (buffer_t *)malloc(sizeof(buffer_t)); + if (!n) return; + if (len > BUFFER_SIZE) len = BUFFER_SIZE; + memcpy(n->buf, data, len); + n->len = len; + n->next = NULL; + if (!hid->first_buffer || !hid->last_buffer) { + hid->first_buffer = hid->last_buffer = n; + } else { + hid->last_buffer->next = n; + hid->last_buffer = n; + } + CFRunLoopStop(CFRunLoopGetCurrent()); +} + +static void timeout_callback(CFRunLoopTimerRef timer, void *info) +{ + printf("timeout_callback\n"); + *(int *)info = 1; + CFRunLoopStop(CFRunLoopGetCurrent()); +} + + +void output_callback(void *context, IOReturn ret, void *sender, + IOHIDReportType type, uint32_t id, uint8_t *data, CFIndex len) +{ + printf("output_callback, r=%d\n", ret); + if (ret == kIOReturnSuccess) { + *(int *)context = len; + } else { + // timeout if not success? + *(int *)context = 0; + } + CFRunLoopStop(CFRunLoopGetCurrent()); +} + + +// rawhid_send - send a packet +// Inputs: +// num = device to transmit to (zero based) +// buf = buffer containing packet to send +// len = number of bytes to transmit +// timeout = time to wait, in milliseconds +// Output: +// number of bytes sent, or -1 on error +// +int rawhid_send(int num, void *buf, int len, int timeout) +{ + hid_t *hid; + int result=-100; + + hid = get_hid(num); + if (!hid || !hid->open) return -1; +#if 1 + #warning "Send timeout not implemented on MACOSX" + IOReturn ret = IOHIDDeviceSetReport(hid->ref, kIOHIDReportTypeOutput, 0, buf, len); + result = (ret == kIOReturnSuccess) ? len : -1; +#endif +#if 0 + // No matter what I tried this never actually sends an output + // report and output_callback never gets called. Why?? + // Did I miss something? This is exactly the same params as + // the sync call that works. Is it an Apple bug? + // (submitted to Apple on 22-sep-2009, problem ID 7245050) + // + IOHIDDeviceScheduleWithRunLoop(hid->ref, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); + // should already be scheduled with run loop by attach_callback, + // sadly this doesn't make any difference either way + + // could this be related? + // http://lists.apple.com/archives/usb/2008/Aug/msg00021.html + // + IOHIDDeviceSetReportWithCallback(hid->ref, kIOHIDReportTypeOutput, + 0, buf, len, (double)timeout / 1000.0, output_callback, &result); + while (1) { + printf("enter run loop (send)\n"); + CFRunLoopRun(); + printf("leave run loop (send)\n"); + if (result > -100) break; + if (!hid->open) { + result = -1; + break; + } + } +#endif + return result; +} + + +// rawhid_open - open 1 or more devices +// +// Inputs: +// max = maximum number of devices to open +// vid = Vendor ID, or -1 if any +// pid = Product ID, or -1 if any +// usage_page = top level usage page, or -1 if any +// usage = top level usage number, or -1 if any +// Output: +// actual number of devices opened +// +int rawhid_open(int max, int vid, int pid, int usage_page, int usage) +{ + static IOHIDManagerRef hid_manager=NULL; + CFMutableDictionaryRef dict; + CFNumberRef num; + IOReturn ret; + hid_t *p; + int count=0; + + if (first_hid) free_all_hid(); + printf("rawhid_open, max=%d\n", max); + if (max < 1) return 0; + // Start the HID Manager + // http://developer.apple.com/technotes/tn2007/tn2187.html + if (!hid_manager) { + hid_manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); + if (hid_manager == NULL || CFGetTypeID(hid_manager) != IOHIDManagerGetTypeID()) { + if (hid_manager) CFRelease(hid_manager); + return 0; + } + } + if (vid > 0 || pid > 0 || usage_page > 0 || usage > 0) { + // Tell the HID Manager what type of devices we want + dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + if (!dict) return 0; + if (vid > 0) { + num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &vid); + CFDictionarySetValue(dict, CFSTR(kIOHIDVendorIDKey), num); + CFRelease(num); + } + if (pid > 0) { + num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &pid); + CFDictionarySetValue(dict, CFSTR(kIOHIDProductIDKey), num); + CFRelease(num); + } + if (usage_page > 0) { + num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usage_page); + CFDictionarySetValue(dict, CFSTR(kIOHIDPrimaryUsagePageKey), num); + CFRelease(num); + } + if (usage > 0) { + num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usage); + CFDictionarySetValue(dict, CFSTR(kIOHIDPrimaryUsageKey), num); + CFRelease(num); + } + IOHIDManagerSetDeviceMatching(hid_manager, dict); + CFRelease(dict); + } else { + IOHIDManagerSetDeviceMatching(hid_manager, NULL); + } + // set up a callbacks for device attach & detach + 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); + return 0; + } + printf("run loop\n"); + // let it do the callback for all devices + while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true) == kCFRunLoopRunHandledSource) ; + // count up how many were added by the callback + for (p = first_hid; p; p = p->next) count++; + return count; +} + + +// rawhid_close - close a device +// +// Inputs: +// num = device to close (zero based) +// Output +// (nothing) +// +void rawhid_close(int num) +{ + hid_t *hid; + + hid = get_hid(num); + if (!hid || !hid->open) return; + hid_close(hid); + hid->open = 0; +} + + +static void add_hid(hid_t *h) +{ + if (!first_hid || !last_hid) { + first_hid = last_hid = h; + h->next = h->prev = NULL; + return; + } + last_hid->next = h; + h->prev = last_hid; + h->next = NULL; + last_hid = h; +} + + +static hid_t * get_hid(int num) +{ + hid_t *p; + for (p = first_hid; p && num > 0; p = p->next, num--) ; + return p; +} + + +static void free_all_hid(void) +{ + hid_t *p, *q; + + for (p = first_hid; p; p = p->next) { + hid_close(p); + } + p = first_hid; + while (p) { + q = p; + p = p->next; + free(q); + } + first_hid = last_hid = NULL; +} + + +static void hid_close(hid_t *hid) +{ + if (!hid || !hid->open || !hid->ref) return; + IOHIDDeviceUnscheduleFromRunLoop(hid->ref, CFRunLoopGetCurrent( ), kCFRunLoopDefaultMode); + IOHIDDeviceClose(hid->ref, kIOHIDOptionsTypeNone); + hid->ref = NULL; +} + +static void detach_callback(void *context, IOReturn r, void *hid_mgr, IOHIDDeviceRef dev) +{ + hid_t *p; + + printf("detach callback\n"); + for (p = first_hid; p; p = p->next) { + if (p->ref == dev) { + p->open = 0; + CFRunLoopStop(CFRunLoopGetCurrent()); + return; + } + } +} + + +static void attach_callback(void *context, IOReturn r, void *hid_mgr, IOHIDDeviceRef dev) +{ + struct hid_struct *h; + + printf("attach callback\n"); + if (IOHIDDeviceOpen(dev, kIOHIDOptionsTypeNone) != kIOReturnSuccess) return; + h = (hid_t *)malloc(sizeof(hid_t)); + if (!h) return; + memset(h, 0, sizeof(hid_t)); + IOHIDDeviceScheduleWithRunLoop(dev, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); + IOHIDDeviceRegisterInputReportCallback(dev, h->buffer, sizeof(h->buffer), + input_callback, h); + h->ref = dev; + h->open = 1; + add_hid(h); +} + + diff --git a/plugins/KeyboardioHID/extras/rawhid/hid_WINDOWS.c b/plugins/KeyboardioHID/extras/rawhid/hid_WINDOWS.c new file mode 100644 index 0000000000..071877341f --- /dev/null +++ b/plugins/KeyboardioHID/extras/rawhid/hid_WINDOWS.c @@ -0,0 +1,328 @@ +/* Simple Raw HID functions for Windows - for use with Teensy RawHID example + * http://www.pjrc.com/teensy/rawhid.html + * Copyright (c) 2009 PJRC.COM, LLC + * + * rawhid_open - open 1 or more devices + * rawhid_recv - receive a packet + * rawhid_send - send a packet + * rawhid_close - close a device + * + * 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 description, website URL and 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 + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "hid.h" + + +// a list of all opened HID devices, so the caller can +// simply refer to them by number +typedef struct hid_struct hid_t; +static hid_t *first_hid = NULL; +static hid_t *last_hid = NULL; +struct hid_struct { + HANDLE handle; + int open; + struct hid_struct *prev; + struct hid_struct *next; +}; +static HANDLE rx_event=NULL; +static HANDLE tx_event=NULL; +static CRITICAL_SECTION rx_mutex; +static CRITICAL_SECTION tx_mutex; + + +// private functions, not intended to be used from outside this file +static void add_hid(hid_t *h); +static hid_t * get_hid(int num); +static void free_all_hid(void); +static void hid_close(hid_t *hid); +void print_win32_err(void); + + + + +// rawhid_recv - receive a packet +// Inputs: +// num = device to receive from (zero based) +// buf = buffer to receive packet +// len = buffer's size +// timeout = time to wait, in milliseconds +// Output: +// number of bytes received, or -1 on error +// +int rawhid_recv(int num, void *buf, int len, int timeout) +{ + hid_t *hid; + unsigned char tmpbuf[516]; + OVERLAPPED ov; + DWORD n, r; + + if (sizeof(tmpbuf) < len + 1) return -1; + hid = get_hid(num); + if (!hid || !hid->open) return -1; + EnterCriticalSection(&rx_mutex); + ResetEvent(&rx_event); + memset(&ov, 0, sizeof(ov)); + ov.hEvent = rx_event; + if (!ReadFile(hid->handle, tmpbuf, len + 1, NULL, &ov)) { + if (GetLastError() != ERROR_IO_PENDING) goto return_error; + r = WaitForSingleObject(rx_event, timeout); + if (r == WAIT_TIMEOUT) goto return_timeout; + if (r != WAIT_OBJECT_0) goto return_error; + } + if (!GetOverlappedResult(hid->handle, &ov, &n, FALSE)) goto return_error; + LeaveCriticalSection(&rx_mutex); + if (n <= 0) return -1; + n--; + if (n > len) n = len; + memcpy(buf, tmpbuf + 1, n); + return n; +return_timeout: + CancelIo(hid->handle); + LeaveCriticalSection(&rx_mutex); + return 0; +return_error: + print_win32_err(); + LeaveCriticalSection(&rx_mutex); + return -1; +} + +// rawhid_send - send a packet +// Inputs: +// num = device to transmit to (zero based) +// buf = buffer containing packet to send +// len = number of bytes to transmit +// timeout = time to wait, in milliseconds +// Output: +// number of bytes sent, or -1 on error +// +int rawhid_send(int num, void *buf, int len, int timeout) +{ + hid_t *hid; + unsigned char tmpbuf[516]; + OVERLAPPED ov; + DWORD n, r; + + if (sizeof(tmpbuf) < len + 1) return -1; + hid = get_hid(num); + if (!hid || !hid->open) return -1; + EnterCriticalSection(&tx_mutex); + ResetEvent(&tx_event); + memset(&ov, 0, sizeof(ov)); + ov.hEvent = tx_event; + tmpbuf[0] = 0; + memcpy(tmpbuf + 1, buf, len); + if (!WriteFile(hid->handle, tmpbuf, len + 1, NULL, &ov)) { + if (GetLastError() != ERROR_IO_PENDING) goto return_error; + r = WaitForSingleObject(tx_event, timeout); + if (r == WAIT_TIMEOUT) goto return_timeout; + if (r != WAIT_OBJECT_0) goto return_error; + } + if (!GetOverlappedResult(hid->handle, &ov, &n, FALSE)) goto return_error; + LeaveCriticalSection(&tx_mutex); + if (n <= 0) return -1; + return n - 1; +return_timeout: + CancelIo(hid->handle); + LeaveCriticalSection(&tx_mutex); + return 0; +return_error: + print_win32_err(); + LeaveCriticalSection(&tx_mutex); + return -1; +} + +// rawhid_open - open 1 or more devices +// +// Inputs: +// max = maximum number of devices to open +// vid = Vendor ID, or -1 if any +// pid = Product ID, or -1 if any +// usage_page = top level usage page, or -1 if any +// usage = top level usage number, or -1 if any +// Output: +// actual number of devices opened +// +int rawhid_open(int max, int vid, int pid, int usage_page, int usage) +{ + GUID guid; + HDEVINFO info; + DWORD index=0, reqd_size; + SP_DEVICE_INTERFACE_DATA iface; + SP_DEVICE_INTERFACE_DETAIL_DATA *details; + HIDD_ATTRIBUTES attrib; + PHIDP_PREPARSED_DATA hid_data; + HIDP_CAPS capabilities; + HANDLE h; + BOOL ret; + hid_t *hid; + int count=0; + + if (first_hid) free_all_hid(); + if (max < 1) return 0; + if (!rx_event) { + rx_event = CreateEvent(NULL, TRUE, TRUE, NULL); + tx_event = CreateEvent(NULL, TRUE, TRUE, NULL); + InitializeCriticalSection(&rx_mutex); + InitializeCriticalSection(&tx_mutex); + } + HidD_GetHidGuid(&guid); + info = SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); + if (info == INVALID_HANDLE_VALUE) return 0; + for (index=0; 1 ;index++) { + iface.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); + ret = SetupDiEnumDeviceInterfaces(info, NULL, &guid, index, &iface); + if (!ret) return count; + SetupDiGetInterfaceDeviceDetail(info, &iface, NULL, 0, &reqd_size, NULL); + details = (SP_DEVICE_INTERFACE_DETAIL_DATA *)malloc(reqd_size); + if (details == NULL) continue; + + memset(details, 0, reqd_size); + details->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); + ret = SetupDiGetDeviceInterfaceDetail(info, &iface, details, + reqd_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); + //printf("vid: %4x\n", attrib.VendorID); + if (!ret || (vid > 0 && attrib.VendorID != vid) || + (pid > 0 && attrib.ProductID != pid) || + !HidD_GetPreparsedData(h, &hid_data)) { + CloseHandle(h); + continue; + } + if (!HidP_GetCaps(hid_data, &capabilities) || + (usage_page > 0 && capabilities.UsagePage != usage_page) || + (usage > 0 && capabilities.Usage != usage)) { + HidD_FreePreparsedData(hid_data); + CloseHandle(h); + continue; + } + HidD_FreePreparsedData(hid_data); + hid = (struct hid_struct *)malloc(sizeof(struct hid_struct)); + if (!hid) { + CloseHandle(h); + continue; + } + hid->handle = h; + hid->open = 1; + add_hid(hid); + count++; + if (count >= max) return count; + } + return count; +} + + +// rawhid_close - close a device +// +// Inputs: +// num = device to close (zero based) +// Output +// (nothing) +// +void rawhid_close(int num) +{ + hid_t *hid; + + hid = get_hid(num); + if (!hid || !hid->open) return; + hid_close(hid); +} + + + +static void add_hid(hid_t *h) +{ + if (!first_hid || !last_hid) { + first_hid = last_hid = h; + h->next = h->prev = NULL; + return; + } + last_hid->next = h; + h->prev = last_hid; + h->next = NULL; + last_hid = h; +} + + +static hid_t * get_hid(int num) +{ + hid_t *p; + for (p = first_hid; p && num > 0; p = p->next, num--) ; + return p; +} + + +static void free_all_hid(void) +{ + hid_t *p, *q; + + for (p = first_hid; p; p = p->next) { + hid_close(p); + } + p = first_hid; + while (p) { + q = p; + p = p->next; + free(q); + } + first_hid = last_hid = NULL; +} + + +static void hid_close(hid_t *hid) +{ + CloseHandle(hid->handle); + hid->handle = NULL; +} + + +void print_win32_err(void) +{ + char buf[256]; + DWORD err; + + err = GetLastError(); + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, + 0, buf, sizeof(buf), NULL); + printf("err %ld: %s\n", err, buf); +} + + + + + diff --git a/plugins/KeyboardioHID/extras/rawhid/rawhid_test.c b/plugins/KeyboardioHID/extras/rawhid/rawhid_test.c new file mode 100644 index 0000000000..7bea89248f --- /dev/null +++ b/plugins/KeyboardioHID/extras/rawhid/rawhid_test.c @@ -0,0 +1,100 @@ +#include +#include +#include + +#if defined(OS_LINUX) || defined(OS_MACOSX) +#include +#include +#elif defined(OS_WINDOWS) +#include +#endif + +#include "hid.h" + + +static char get_keystroke(void); + + +int main() +{ + int i, r, num; + char c, buf[64]; + + // C-based example is 16C0:0480:FFAB:0200 + r = rawhid_open(1, 0x16C0, 0x0480, 0xFFAB, 0x0200); + if (r <= 0) { + // Arduino-based example is 16C0:0486:FFAB:0200 + r = rawhid_open(1, 0x16C0, 0x0486, 0xFFAB, 0x0200); + if (r <= 0) { + printf("no rawhid device found\n"); + return -1; + } + } + printf("found rawhid device\n"); + + while (1) { + // check if any Raw HID packet has arrived + num = rawhid_recv(0, buf, 64, 220); + if (num < 0) { + printf("\nerror reading, device went offline\n"); + rawhid_close(0); + return 0; + } + if (num > 0) { + printf("\nrecv %d bytes:\n", num); + for (i=0; i= 32) { + printf("\ngot key '%c', sending...\n", c); + buf[0] = c; + for (i=1; i<64; i++) { + buf[i] = 0; + } + rawhid_send(0, buf, 64, 100); + } + } +} + +#if defined(OS_LINUX) || defined(OS_MACOSX) +// Linux (POSIX) implementation of _kbhit(). +// Morgan McGuire, morgan@cs.brown.edu +static int _kbhit() { + static const int STDIN = 0; + static int initialized = 0; + int bytesWaiting; + + if (!initialized) { + // Use termios to turn off line buffering + struct termios term; + tcgetattr(STDIN, &term); + term.c_lflag &= ~ICANON; + tcsetattr(STDIN, TCSANOW, &term); + setbuf(stdin, NULL); + initialized = 1; + } + ioctl(STDIN, FIONREAD, &bytesWaiting); + return bytesWaiting; +} +static char _getch(void) { + char c; + if (fread(&c, 1, 1, stdin) < 1) return 0; + return c; +} +#endif + + +static char get_keystroke(void) +{ + if (_kbhit()) { + char c = _getch(); + if (c >= 32) return c; + } + return 0; +} + + From 3359836046f28a9422139e8a9b29af0ef482acc8 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Tue, 13 Oct 2015 18:46:22 +0200 Subject: [PATCH 294/602] Made Raw HID program work with Arduino --- plugins/KeyboardioHID/extras/rawhid/Makefile | 2 +- plugins/KeyboardioHID/extras/rawhid/rawhid_test.c | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/plugins/KeyboardioHID/extras/rawhid/Makefile b/plugins/KeyboardioHID/extras/rawhid/Makefile index 62d2d6682c..c09ecdc8be 100644 --- a/plugins/KeyboardioHID/extras/rawhid/Makefile +++ b/plugins/KeyboardioHID/extras/rawhid/Makefile @@ -7,7 +7,7 @@ PROG = rawhid_test # To set up Ubuntu Linux to cross compile for Windows: # -# apt-get install mingw32 mingw32-binutils mingw32-runtime +# apt-get install mingw32 mingw32-binutils mingw32-runtime libusb-dev # # Just edit the variable above for WINDOWS, then use "make" to build rawhid.exe diff --git a/plugins/KeyboardioHID/extras/rawhid/rawhid_test.c b/plugins/KeyboardioHID/extras/rawhid/rawhid_test.c index 7bea89248f..fc072608da 100644 --- a/plugins/KeyboardioHID/extras/rawhid/rawhid_test.c +++ b/plugins/KeyboardioHID/extras/rawhid/rawhid_test.c @@ -18,13 +18,14 @@ static char get_keystroke(void); int main() { int i, r, num; - char c, buf[64]; + char c, buf[200]; // C-based example is 16C0:0480:FFAB:0200 r = rawhid_open(1, 0x16C0, 0x0480, 0xFFAB, 0x0200); if (r <= 0) { - // Arduino-based example is 16C0:0486:FFAB:0200 - r = rawhid_open(1, 0x16C0, 0x0486, 0xFFAB, 0x0200); + // Arduino-based example is 0x2341:XXXX:FFC0:0C00 + // To keep compatible with other vendors we only use the raw HID number + r = rawhid_open(1, -1, -1, 0xFFC0, 0x0C00); if (r <= 0) { printf("no rawhid device found\n"); return -1; @@ -52,10 +53,10 @@ int main() while ((c = get_keystroke()) >= 32) { printf("\ngot key '%c', sending...\n", c); buf[0] = c; - for (i=1; i<64; i++) { - buf[i] = 0; + for (i=1; i Date: Thu, 15 Oct 2015 19:44:23 +0200 Subject: [PATCH 295/602] Renew Keyboard API --- .../src/HID-APIs/ImprovedKeylayouts.h | 558 ++++++++---------- .../KeyboardioHID/src/HID-APIs/KeyboardAPI.h | 34 +- .../src/HID-APIs/KeyboardAPI.hpp | 327 +++++----- plugins/KeyboardioHID/src/HID-Project.h | 1 + 4 files changed, 432 insertions(+), 488 deletions(-) diff --git a/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h b/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h index 0a5c397abc..bb58b2d6ba 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h +++ b/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h @@ -24,325 +24,265 @@ THE SOFTWARE. // Include guard #pragma once -//================================================================================ -// Key definitions -//================================================================================ - -// Modifiers -#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 +#if !defined(LAYOUT_US_ENGLISH) +#error This API does not support non US english layouts. +#endif -// Normal keys -#define KEY_UP_ARROW (RAW_KEYBOARD_UP_ARROW + 136) -#define KEY_DOWN_ARROW (RAW_KEYBOARD_DOWN_ARROW + 136) -#define KEY_LEFT_ARROW (RAW_KEYBOARD_LEFT_ARROW + 136) -#define KEY_RIGHT_ARROW (RAW_KEYBOARD_RIGHT_ARROW + 136) -#define KEY_BACKSPACE (RAW_KEYBOARD_BACKSPACE + 136) -#define KEY_TAB (RAW_KEYBOARD_TAB + 136) +// Key alias #define KEY_RETURN KEY_ENTER -#define KEY_ENTER (RAW_KEYBOARD_ENTER + 136) -#define KEY_ESC (RAW_KEYBOARD_ESC + 136) -#define KEY_INSERT (RAW_KEYBOARD_INSERT + 136) -#define KEY_DELETE (RAW_KEYBOARD_DELETE + 136) -#define KEY_PAGE_UP (RAW_KEYBOARD_PAGE_UP + 136) -#define KEY_PAGE_DOWN (RAW_KEYBOARD_PAGE_DOWN + 136) -#define KEY_HOME (RAW_KEYBOARD_HOME + 136) -#define KEY_END (RAW_KEYBOARD_END + 136) -#define KEY_CAPS_LOCK (RAW_KEYBOARD_CAPS_LOCK + 136) -#define KEY_F1 (RAW_KEYBOARD_F1 + 136) -#define KEY_F2 (RAW_KEYBOARD_F2 + 136) -#define KEY_F3 (RAW_KEYBOARD_F3 + 136) -#define KEY_F4 (RAW_KEYBOARD_F4 + 136) -#define KEY_F5 (RAW_KEYBOARD_F5 + 136) -#define KEY_F6 (RAW_KEYBOARD_F6 + 136) -#define KEY_F7 (RAW_KEYBOARD_F7 + 136) -#define KEY_F8 (RAW_KEYBOARD_F8 + 136) -#define KEY_F9 (RAW_KEYBOARD_F9 + 136) -#define KEY_F10 (RAW_KEYBOARD_F10 + 136) -#define KEY_F11 (RAW_KEYBOARD_F11 + 136) -#define KEY_F12 (RAW_KEYBOARD_F12 + 136) - - -// New key definitions -#define KEY_PRINT (RAW_KEYBOARD_PRINT + 136) -#define KEY_NUM_LOCK (RAW_KEYBOARD_NUM_LOCK + 136) -#define KEY_SCROLL_LOCK (RAW_KEYBOARD_SCROLL_LOCK + 136) -#define KEY_PAUSE (RAW_KEYBOARD_PAUSE + 136) -#define KEY_MENU (RAW_KEYBOARD_MENU + 136) -#define KEY_SPACE ' ' #define KEY_LEFT_WINDOWS KEY_LEFT_GUI #define KEY_RIGHT_WINDOWS KEY_RIGHT_GUI #define KEY_PRINTSCREEN KEY_PRINT -// Keyboard Leds -#define LED_NUM_LOCK 0x01 -#define LED_CAPS_LOCK 0x02 -#define LED_SCROLL_LOCK 0x04 - -//================================================================================ -// LAYOUT_US_ENGLISH -//================================================================================ - -#if !defined(LAYOUT_US_ENGLISH) && !defined(LAYOUT_UNITED_KINGDOM) -#error This API does not support non english layouts. Please select an US or UK Keyboard. -#endif - -#define RAW_KEYBOARD_LEFT_CTRL (1 << 0) -#define RAW_KEYBOARD_LEFT_SHIFT (1 << 1) -#define RAW_KEYBOARD_LEFT_ALT (1 << 2) -#define RAW_KEYBOARD_LEFT_GUI (1 << 3) -#define RAW_KEYBOARD_RIGHT_CTRL (1 << 4) -#define RAW_KEYBOARD_RIGHT_SHIFT (1 << 5) -#define RAW_KEYBOARD_RIGHT_ALT (1 << 6) -#define RAW_KEYBOARD_RIGHT_GUI (1 << 7) - -#define RAW_KEYBOARD_KEY(key) ((key>='a' && key<='z') ? (0x04 + key-'a') :\ -(key>='A' && key<='Z') ? (0x04 + key-'A') : (key>='1' && key<='9') ? (0x1E + key-'1') : 0x27) +enum KeyboardModifier : uint8_t { + KEY_LEFT_CTRL = (1 << 0), + KEY_LEFT_SHIFT = (1 << 1), + KEY_LEFT_ALT = (1 << 2), + KEY_LEFT_GUI = (1 << 3), + KEY_RIGHT_CTRL = (1 << 4), + KEY_RIGHT_SHIFT = (1 << 5), + KEY_RIGHT_ALT = (1 << 6), + KEY_RIGHT_GUI = (1 << 7), +}; -#define RAW_KEYBOARD_A ( 4 ) -#define RAW_KEYBOARD_B ( 5 ) -#define RAW_KEYBOARD_C ( 6 ) -#define RAW_KEYBOARD_D ( 7 ) -#define RAW_KEYBOARD_E ( 8 ) -#define RAW_KEYBOARD_F ( 9 ) -#define RAW_KEYBOARD_G ( 10 ) -#define RAW_KEYBOARD_H ( 11 ) -#define RAW_KEYBOARD_I ( 12 ) -#define RAW_KEYBOARD_J ( 13 ) -#define RAW_KEYBOARD_K ( 14 ) -#define RAW_KEYBOARD_L ( 15 ) -#define RAW_KEYBOARD_M ( 16 ) -#define RAW_KEYBOARD_N ( 17 ) -#define RAW_KEYBOARD_O ( 18 ) -#define RAW_KEYBOARD_P ( 19 ) -#define RAW_KEYBOARD_Q ( 20 ) -#define RAW_KEYBOARD_R ( 21 ) -#define RAW_KEYBOARD_S ( 22 ) -#define RAW_KEYBOARD_T ( 23 ) -#define RAW_KEYBOARD_U ( 24 ) -#define RAW_KEYBOARD_V ( 25 ) -#define RAW_KEYBOARD_W ( 26 ) -#define RAW_KEYBOARD_X ( 27 ) -#define RAW_KEYBOARD_Y ( 28 ) -#define RAW_KEYBOARD_Z ( 29 ) -#define RAW_KEYBOARD_1 ( 30 ) -#define RAW_KEYBOARD_2 ( 31 ) -#define RAW_KEYBOARD_3 ( 32 ) -#define RAW_KEYBOARD_4 ( 33 ) -#define RAW_KEYBOARD_5 ( 34 ) -#define RAW_KEYBOARD_6 ( 35 ) -#define RAW_KEYBOARD_7 ( 36 ) -#define RAW_KEYBOARD_8 ( 37 ) -#define RAW_KEYBOARD_9 ( 38 ) -#define RAW_KEYBOARD_0 ( 39 ) -#define RAW_KEYBOARD_ENTER ( 40 ) -#define RAW_KEYBOARD_ESC ( 41 ) -#define RAW_KEYBOARD_BACKSPACE ( 42 ) -#define RAW_KEYBOARD_TAB ( 43 ) -#define RAW_KEYBOARD_SPACE ( 44 ) -#define RAW_KEYBOARD_MINUS ( 45 ) -#define RAW_KEYBOARD_EQUAL ( 46 ) -#define RAW_KEYBOARD_LEFT_BRACE ( 47 ) -#define RAW_KEYBOARD_RIGHT_BRACE ( 48 ) -#define RAW_KEYBOARD_BACKSLASH ( 49 ) -#define RAW_KEYBOARD_NON_US_NUM ( 50 ) -#define RAW_KEYBOARD_SEMICOLON ( 51 ) -#define RAW_KEYBOARD_QUOTE ( 52 ) -#define RAW_KEYBOARD_TILDE ( 53 ) -#define RAW_KEYBOARD_COMMA ( 54 ) -#define RAW_KEYBOARD_PERIOD ( 55 ) -#define RAW_KEYBOARD_SLASH ( 56 ) +enum KeyboardKeycode : uint8_t { + KEY_RESERVED = 0, + KEY_ERRORROLLOVER = 1, + KEY_POSTFAIL = 2, + KEY_ERRORUNDEFINED = 3, + KEY_A = 4, + KEY_B = 5, + KEY_C = 6, + KEY_D = 7, + KEY_E = 8, + KEY_F = 9, + KEY_G = 10, + KEY_H = 11, + KEY_I = 12, + KEY_J = 13, + KEY_K = 14, + KEY_L = 15, + KEY_M = 16, + KEY_N = 17, + KEY_O = 18, + KEY_P = 19, + KEY_Q = 20, + KEY_R = 21, + KEY_S = 22, + KEY_T = 23, + KEY_U = 24, + KEY_V = 25, + KEY_W = 26, + KEY_X = 27, + KEY_Y = 28, + KEY_Z = 29, + KEY_1 = 30, + KEY_2 = 31, + KEY_3 = 32, + KEY_4 = 33, + KEY_5 = 34, + KEY_6 = 35, + KEY_7 = 36, + KEY_8 = 37, + KEY_9 = 38, + KEY_0 = 39, + KEY_ENTER = 40, + KEY_ESC = 41, + KEY_BACKSPACE = 42, + KEY_TAB = 43, + KEY_SPACE = 44, + KEY_MINUS = 45, + KEY_EQUAL = 46, + KEY_LEFT_BRACE = 47, + KEY_RIGHT_BRACE = 48, + KEY_BACKSLASH = 49, + KEY_NON_US_NUM = 50, + KEY_SEMICOLON = 51, + KEY_QUOTE = 52, + KEY_TILDE = 53, + KEY_COMMA = 54, + KEY_PERIOD = 55, + KEY_SLASH = 56, + KEY_CAPS_LOCK = 0x39, + KEY_F1 = 0x3A, + KEY_F2 = 0x3B, + KEY_F3 = 0x3C, + KEY_F4 = 0x3D, + KEY_F5 = 0x3E, + KEY_F6 = 0x3F, + KEY_F7 = 0x40, + KEY_F8 = 0x41, + KEY_F9 = 0x42, + KEY_F10 = 0x43, + KEY_F11 = 0x44, + KEY_F12 = 0x45, + KEY_PRINT = 0x46, + KEY_SCROLL_LOCK = 0x47, + KEY_PAUSE = 0x48, + KEY_INSERT = 0x49, + KEY_HOME = 0x4A, + KEY_PAGE_UP = 0x4B, + KEY_DELETE = 0x4C, + KEY_END = 0x4D, + KEY_PAGE_DOWN = 0x4E, + KEY_RIGHT_ARROW = 0x4F, + KEY_LEFT_ARROW = 0x50, + KEY_DOWN_ARROW = 0x51, + KEY_UP_ARROW = 0x52, + KEY_NUM_LOCK = 0x53, + + KEY_NON_US = 0x64, + KEY_MENU = 0x65, + KEY_POWER = 0x66, + + KEY_VOLUME_MUTE = 0x7F, + KEY_VOLUME_UP = 0x80, + KEY_VOLUME_DOWN = 0x81, +}; -#define RAW_KEYBOARD_CAPS_LOCK 0x39 -#define RAW_KEYBOARD_F1 0x3A -#define RAW_KEYBOARD_F2 0x3B -#define RAW_KEYBOARD_F3 0x3C -#define RAW_KEYBOARD_F4 0x3D -#define RAW_KEYBOARD_F5 0x3E -#define RAW_KEYBOARD_F6 0x3F -#define RAW_KEYBOARD_F7 0x40 -#define RAW_KEYBOARD_F8 0x41 -#define RAW_KEYBOARD_F9 0x42 -#define RAW_KEYBOARD_F10 0x43 -#define RAW_KEYBOARD_F11 0x44 -#define RAW_KEYBOARD_F12 0x45 -#define RAW_KEYBOARD_PRINT 0x46 -#define RAW_KEYBOARD_SCROLL_LOCK 0x47 -#define RAW_KEYBOARD_PAUSE 0x48 -#define RAW_KEYBOARD_INSERT 0x49 -#define RAW_KEYBOARD_HOME 0x4A -#define RAW_KEYBOARD_PAGE_UP 0x4B -#define RAW_KEYBOARD_DELETE 0x4C -#define RAW_KEYBOARD_END 0x4D -#define RAW_KEYBOARD_PAGE_DOWN 0x4E -#define RAW_KEYBOARD_RIGHT_ARROW 0x4F -#define RAW_KEYBOARD_LEFT_ARROW 0x50 -#define RAW_KEYBOARD_DOWN_ARROW 0x51 -#define RAW_KEYBOARD_UP_ARROW 0x52 -#define RAW_KEYBOARD_NUM_LOCK 0x53 -#define RAW_KEYBOARD_NON_US 0x64 -#define RAW_KEYBOARD_MENU 0x65 +// Keyboard Leds +enum KeyboardLeds : uint8_t { + LED_NUM_LOCK = (1 << 0), + LED_CAPS_LOCK = (1 << 1), + LED_SCROLL_LOCK = (1 << 2), + LED_COMPOSE = (1 << 3), + LED_KANA = (1 << 4), + LED_POWER = (1 << 5), + LED_SHIFT = (1 << 6), + LED_DO_NOT_DISTURB = (1 << 7), +}; #define SHIFT 0x80 -static const uint8_t _asciimap[128] PROGMEM = +static const uint8_t _asciimap[] PROGMEM = { - 0x00, // NUL - 0x00, // SOH - 0x00, // STX - 0x00, // ETX - 0x00, // EOT - 0x00, // ENQ - 0x00, // ACK - 0x00, // BEL - RAW_KEYBOARD_BACKSPACE, // BS Backspace - RAW_KEYBOARD_TAB, // TAB Tab - RAW_KEYBOARD_ENTER, // 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 + KEY_RESERVED, // NUL + KEY_RESERVED, // SOH + KEY_RESERVED, // STX + KEY_RESERVED, // ETX + KEY_RESERVED, // EOT + KEY_RESERVED, // ENQ + KEY_RESERVED, // ACK + KEY_RESERVED, // BEL + KEY_BACKSPACE, // BS Backspace + KEY_TAB, // TAB Tab + KEY_ENTER, // LF Enter + KEY_RESERVED, // VT + KEY_RESERVED, // FF + KEY_RESERVED, // CR + KEY_RESERVED, // SO + KEY_RESERVED, // SI + KEY_RESERVED, // DEL + KEY_RESERVED, // DC1 + KEY_RESERVED, // DC2 + KEY_RESERVED, // DC3 + KEY_RESERVED, // DC4 + KEY_RESERVED, // NAK + KEY_RESERVED, // SYN + KEY_RESERVED, // ETB + KEY_RESERVED, // CAN + KEY_RESERVED, // EM + KEY_RESERVED, // SUB + KEY_RESERVED, // ESC + KEY_RESERVED, // FS + KEY_RESERVED, // GS + KEY_RESERVED, // RS + KEY_RESERVED, // US - RAW_KEYBOARD_SPACE, // ' ' - RAW_KEYBOARD_1|SHIFT, // ! -#ifdef LAYOUT_UNITED_KINGDOM - RAW_KEYBOARD_2|SHIFT, // " -#else - RAW_KEYBOARD_QUOTE|SHIFT, // " -#endif -#ifdef LAYOUT_UNITED_KINGDOM - RAW_KEYBOARD_BACKSLASH -#else - RAW_KEYBOARD_3|SHIFT, // # -#endif - RAW_KEYBOARD_4|SHIFT, // $ - RAW_KEYBOARD_5|SHIFT, // % - RAW_KEYBOARD_7|SHIFT, // & - RAW_KEYBOARD_QUOTE, // ' - RAW_KEYBOARD_9|SHIFT, // ( - RAW_KEYBOARD_0|SHIFT, // ) - RAW_KEYBOARD_8|SHIFT, // * - RAW_KEYBOARD_EQUAL|SHIFT, // + - RAW_KEYBOARD_COMMA, // , - RAW_KEYBOARD_MINUS, // - - RAW_KEYBOARD_PERIOD, // . - RAW_KEYBOARD_SLASH, // / - RAW_KEYBOARD_0, // 0 - RAW_KEYBOARD_1, // 1 - RAW_KEYBOARD_2, // 2 - RAW_KEYBOARD_3, // 3 - RAW_KEYBOARD_4, // 4 - RAW_KEYBOARD_5, // 5 - RAW_KEYBOARD_6, // 6 - RAW_KEYBOARD_7, // 7 - RAW_KEYBOARD_8, // 8 - RAW_KEYBOARD_9, // 9 - RAW_KEYBOARD_SEMICOLON|SHIFT, // : - RAW_KEYBOARD_SEMICOLON, // ; - RAW_KEYBOARD_COMMA|SHIFT, // < - RAW_KEYBOARD_EQUAL, // = - RAW_KEYBOARD_PERIOD|SHIFT, // > - RAW_KEYBOARD_SLASH|SHIFT, // ? -#ifdef LAYOUT_UNITED_KINGDOM - RAW_KEYBOARD_QUOTE|SHIFT, // @ -#else - RAW_KEYBOARD_2|SHIFT, // @ -#endif - RAW_KEYBOARD_A|SHIFT, // A - RAW_KEYBOARD_B|SHIFT, // B - RAW_KEYBOARD_C|SHIFT, // C - RAW_KEYBOARD_D|SHIFT, // D - RAW_KEYBOARD_E|SHIFT, // E - RAW_KEYBOARD_F|SHIFT, // F - RAW_KEYBOARD_G|SHIFT, // G - RAW_KEYBOARD_H|SHIFT, // H - RAW_KEYBOARD_I|SHIFT, // I - RAW_KEYBOARD_J|SHIFT, // J - RAW_KEYBOARD_K|SHIFT, // K - RAW_KEYBOARD_L|SHIFT, // L - RAW_KEYBOARD_M|SHIFT, // M - RAW_KEYBOARD_N|SHIFT, // N - RAW_KEYBOARD_O|SHIFT, // O - RAW_KEYBOARD_P|SHIFT, // P - RAW_KEYBOARD_Q|SHIFT, // Q - RAW_KEYBOARD_R|SHIFT, // R - RAW_KEYBOARD_S|SHIFT, // S - RAW_KEYBOARD_T|SHIFT, // T - RAW_KEYBOARD_U|SHIFT, // U - RAW_KEYBOARD_V|SHIFT, // V - RAW_KEYBOARD_W|SHIFT, // W - RAW_KEYBOARD_X|SHIFT, // X - RAW_KEYBOARD_Y|SHIFT, // Y - RAW_KEYBOARD_Z|SHIFT, // Z - RAW_KEYBOARD_LEFT_BRACE, // [ -#ifdef LAYOUT_UNITED_KINGDOM - RAW_KEYBOARD_NON_US, // bslash -#else - RAW_KEYBOARD_BACKSLASH, // bslash -#endif - RAW_KEYBOARD_RIGHT_BRACE, // ] - RAW_KEYBOARD_6|SHIFT, // ^ - RAW_KEYBOARD_MINUS|SHIFT, // _ - RAW_KEYBOARD_TILDE, // ` - RAW_KEYBOARD_A, // a - RAW_KEYBOARD_B, // b - RAW_KEYBOARD_C, // c - RAW_KEYBOARD_D, // d - RAW_KEYBOARD_E, // e - RAW_KEYBOARD_F, // f - RAW_KEYBOARD_G, // g - RAW_KEYBOARD_H, // h - RAW_KEYBOARD_I, // i - RAW_KEYBOARD_J, // j - RAW_KEYBOARD_K, // k - RAW_KEYBOARD_L, // l - RAW_KEYBOARD_M, // m - RAW_KEYBOARD_N, // n - RAW_KEYBOARD_O, // o - RAW_KEYBOARD_P, // p - RAW_KEYBOARD_Q, // q - RAW_KEYBOARD_R, // r - RAW_KEYBOARD_S, // s - RAW_KEYBOARD_T, // t - RAW_KEYBOARD_U, // u - RAW_KEYBOARD_V, // v - RAW_KEYBOARD_W, // w - RAW_KEYBOARD_X, // x - RAW_KEYBOARD_Y, // y - RAW_KEYBOARD_Z, // z - RAW_KEYBOARD_LEFT_BRACE|SHIFT, // { -#ifdef LAYOUT_UNITED_KINGDOM - RAW_KEYBOARD_NON_US|SHIFT, // | -#else - RAW_KEYBOARD_BACKSLASH|SHIFT, // | -#endif - RAW_KEYBOARD_RIGHT_BRACE|SHIFT, // } -#ifdef LAYOUT_UNITED_KINGDOM - RAW_KEYBOARD_BACKSLASH|SHIFT, // ~ -#else - RAW_KEYBOARD_TILDE|SHIFT, // ~ -#endif - 0x00 // DEL + KEY_SPACE, // ' ' Space + KEY_1|SHIFT, // ! + KEY_QUOTE|SHIFT, // " + KEY_3|SHIFT, // # + KEY_4|SHIFT, // $ + KEY_5|SHIFT, // % + KEY_7|SHIFT, // & + KEY_QUOTE, // ' + KEY_9|SHIFT, // ( + KEY_0|SHIFT, // ) + KEY_8|SHIFT, // * + KEY_EQUAL|SHIFT, // + + KEY_COMMA, // , + KEY_MINUS, // - + KEY_PERIOD, // . + KEY_SLASH, // / + KEY_0, // 0 + KEY_1, // 1 + KEY_2, // 2 + KEY_3, // 3 + KEY_4, // 4 + KEY_5, // 5 + KEY_6, // 6 + KEY_7, // 7 + KEY_8, // 8 + KEY_9, // 9 + KEY_SEMICOLON|SHIFT, // : + KEY_SEMICOLON, // ; + KEY_COMMA|SHIFT, // < + KEY_EQUAL, // = + KEY_PERIOD|SHIFT, // > + KEY_SLASH|SHIFT, // ? + KEY_2|SHIFT, // @ + KEY_A|SHIFT, // A + KEY_B|SHIFT, // B + KEY_C|SHIFT, // C + KEY_D|SHIFT, // D + KEY_E|SHIFT, // E + KEY_F|SHIFT, // F + KEY_G|SHIFT, // G + KEY_H|SHIFT, // H + KEY_I|SHIFT, // I + KEY_J|SHIFT, // J + KEY_K|SHIFT, // K + KEY_L|SHIFT, // L + KEY_M|SHIFT, // M + KEY_N|SHIFT, // N + KEY_O|SHIFT, // O + KEY_P|SHIFT, // P + KEY_Q|SHIFT, // Q + KEY_R|SHIFT, // R + KEY_S|SHIFT, // S + KEY_T|SHIFT, // T + KEY_U|SHIFT, // U + KEY_V|SHIFT, // V + KEY_W|SHIFT, // W + KEY_X|SHIFT, // X + KEY_Y|SHIFT, // Y + KEY_Z|SHIFT, // Z + KEY_LEFT_BRACE, // [ + KEY_BACKSLASH, // bslash + KEY_RIGHT_BRACE, // ] + KEY_6|SHIFT, // ^ + KEY_MINUS|SHIFT, // _ + KEY_TILDE, // ` + KEY_A, // a + KEY_B, // b + KEY_C, // c + KEY_D, // d + KEY_E, // e + KEY_F, // f + KEY_G, // g + KEY_H, // h + KEY_I, // i + KEY_J, // j + KEY_K, // k + KEY_L, // l + KEY_M, // m + KEY_N, // n + KEY_O, // o + KEY_P, // p + KEY_Q, // q + KEY_R, // r + KEY_S, // s + KEY_T, // t + KEY_U, // u + KEY_V, // v + KEY_W, // w + KEY_X, // x + KEY_Y, // y + KEY_Z, // z + KEY_LEFT_BRACE|SHIFT, // { + KEY_BACKSLASH|SHIFT, // | + KEY_RIGHT_BRACE|SHIFT, // } + KEY_TILDE|SHIFT, // ~ + KEY_RESERVED // DEL }; + diff --git a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h index fc7eec8f68..6a229f0506 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h +++ b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h @@ -29,7 +29,6 @@ THE SOFTWARE. #include "ImprovedKeylayouts.h" #include "HID-Tables.h" //TODO - typedef union{ // Low level key report: up to 6 keys and shift, ctrl etc at once uint8_t whole8[]; @@ -48,19 +47,36 @@ class KeyboardAPI : public Print //TODO nkro compatiblity, merge them inline void begin(void); inline void end(void); + inline size_t write(uint8_t k); + inline size_t write(KeyboardKeycode k); + inline size_t write(KeyboardModifier k); + inline size_t press(uint8_t k); + inline size_t press(KeyboardKeycode k); + inline size_t press(KeyboardModifier k); + inline size_t release(uint8_t k); + inline size_t release(KeyboardKeycode k); + inline size_t release(KeyboardModifier k); + + inline size_t add(uint8_t k); + inline size_t add(KeyboardKeycode k); + inline size_t add(KeyboardModifier k); + + inline size_t remove(uint8_t k); + inline size_t remove(KeyboardKeycode k); + inline size_t remove(KeyboardModifier k); + + // TODO media, system + inline void setMedia(uint8_t m){ + _keyReport.reserved = m; + send_now(); + } + inline void releaseAll(void); + inline void removeAll(void); inline void send_now(void); - - inline size_t writeKeycode(uint8_t k); - inline size_t pressKeycode(uint8_t k); - inline size_t releaseKeycode(uint8_t k); - inline size_t addKeyToReport(uint8_t k); - inline size_t addKeycodeToReport(uint8_t k); - inline size_t removeKeyFromReport(uint8_t k); - inline size_t removeKeycodeFromReport(uint8_t k); // Sending is public in the base class for advanced users. virtual void SendReport(void* data, int length) = 0; diff --git a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.hpp b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.hpp index 19abc823d8..fba968dcdc 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.hpp +++ b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.hpp @@ -36,232 +36,219 @@ void KeyboardAPI::end(void) } -void KeyboardAPI::send_now(void){ - SendReport(&_keyReport, sizeof(_keyReport)); +// TODO template?? +size_t KeyboardAPI::write(uint8_t k) +{ + // Press and release key (if press was successfull) + auto ret = press(k); + if(ret){ + release(k); + } + return ret; +} + + +size_t KeyboardAPI::write(KeyboardKeycode k) +{ + // Press and release key (if press was successfull) + auto ret = press(k); + if(ret){ + release(k); + } + return ret; +} + + +size_t KeyboardAPI::write(KeyboardModifier k) +{ + // Press and release key (if press was successfull) + auto ret = press(k); + if(ret){ + release(k); + } + return ret; } -// 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 KeyboardAPI::press(uint8_t k) { - // TODO improve the whole mechanism - size_t ret = addKeyToReport(k); + // Press key and send report to host + auto ret = add(k); if(ret){ send_now(); } return ret; } -// 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 KeyboardAPI::release(uint8_t k) + +size_t KeyboardAPI::press(KeyboardKeycode 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 & SHIFT) { // it's a capital letter or other character reached with shift - _keyReport.modifiers &= ~(0x02); // the left shift modifier - k = k ^ SHIFT; - } - } - - // 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; - } + // Press key and send report to host + auto ret = add(k); + if(ret){ + send_now(); } - - send_now(); - return 1; + return ret; } -void KeyboardAPI::releaseAll(void) + +size_t KeyboardAPI::press(KeyboardModifier k) { - // release all keys - memset(&_keyReport, 0x00, sizeof(_keyReport)); - send_now(); + // Press modifier key and send report to host + auto ret = add(k); + if(ret){ + send_now(); + } + return ret; } -size_t KeyboardAPI::write(uint8_t c) -{ - uint8_t p = press(c); // Keydown - release(c); // Keyup - return p; // just return the result of press() since release() almost always returns 1 -} -// pressKeycode() 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 releaseKeycode(), releaseAll(), or otherwise clear the report and resend. -size_t KeyboardAPI::pressKeycode(uint8_t k) +size_t KeyboardAPI::add(uint8_t k) { - if (!addKeycodeToReport(k)) { + // Ignore invalid input + if(k >= sizeof(_asciimap)){ + setWriteError(); return 0; } - send_now(); - return 1; + + // Read key from ascii lookup table + k = pgm_read_byte(_asciimap + k); + auto ret = add(KeyboardKeycode(k & ~SHIFT)); + + // Only press shift and send if keycode was successfully added + if(ret && k & SHIFT){ + add(KEY_LEFT_SHIFT); + } + return ret; } -size_t KeyboardAPI::addKeyToReport(uint8_t k) + +size_t KeyboardAPI::add(KeyboardKeycode k) { - 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 & SHIFT) { // it's a capital letter or other character reached with shift - _keyReport.modifiers |= 0x02; // the left shift modifier - k = k ^ SHIFT; + // Add k to the key report only if it's not already present + // and if there is an empty slot. + for (uint8_t i = 0; i < sizeof(_keyReport.keys); i++) + { + // Is key already in the list or did we found an empty slot? + auto key = _keyReport.keys[i]; + if (key == uint8_t(k) || key == 0) { + _keyReport.keys[i] = k; + return 1; } } - - return addKeycodeToReport(k); + + // No empty key position was found + setWriteError(); + return 0; } -size_t KeyboardAPI::addKeycodeToReport(uint8_t k) + +size_t KeyboardAPI::add(KeyboardModifier k) { - uint8_t index = 0; - uint8_t done = 0; + // Add modifier key + _keyReport.modifiers |= k; + return 1; +} - if ((k >= HID_KEYBOARD_LEFT_CONTROL) && (k <= HID_KEYBOARD_RIGHT_GUI)) { - // it's a modifier key - _keyReport.modifiers |= (0x01 << (k - HID_KEYBOARD_LEFT_CONTROL)); + +size_t KeyboardAPI::release(uint8_t k) +{ + // Release key and send report to host + auto ret = remove(k); + if(ret){ + send_now(); } - else { - // it's some other key: - // Add k to the key report only if it's not already present - // and if there is an empty slot. - for (index = 0; index < sizeof(_keyReport.keys); index++) { - if (_keyReport.keys[index] != k) { // is k already in list? - if (0 == _keyReport.keys[index]) { // have we found an empty slot? - _keyReport.keys[index] = k; - done = 1; - break; - } - } - else { - done = 1; - break; - } + return ret; +} - } - // use separate variable to check if slot was found - // for style reasons - we do not know how the compiler - // handles the for() index when it leaves the loop - if (0 == done) { - setWriteError(); - return 0; - } +size_t KeyboardAPI::release(KeyboardKeycode k) +{ + // Release key and send report to host + auto ret = remove(k); + if(ret){ + send_now(); } + return ret; +} - return 1; + +size_t KeyboardAPI::release(KeyboardModifier k) +{ + // Release modifier key and send report to host + auto ret = remove(k); + if(ret){ + send_now(); + } + return ret; } -// releaseKeycode() 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. -// When send is set to FALSE (= 0) no sendReport() is executed. This comes in -// handy when combining key releases (e.g. SHIFT+A). -size_t KeyboardAPI::releaseKeycode(uint8_t k) +size_t KeyboardAPI::remove(uint8_t k) { - if (!removeKeycodeFromReport(k)) { + // Ignore invalid input + if(k >= sizeof(_asciimap)){ return 0; } - send_now(); - return 1; + + // Read key from ascii lookup table + k = pgm_read_byte(_asciimap + k); + auto ret = remove(KeyboardKeycode(k & ~SHIFT)); + + // Always try to release shift (if used) + if(k & SHIFT){ + ret |= remove(KEY_LEFT_SHIFT); + } + return ret; } -size_t KeyboardAPI::removeKeyFromReport(uint8_t k) + +size_t KeyboardAPI::remove(KeyboardKeycode k) { - 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 & SHIFT) { // it's a capital letter or other character reached with shift - _keyReport.modifiers &= ~(0x02); // the left shift modifier - k = k ^ SHIFT; + // Test the key report to see if k is present. Clear it if it exists. + for (uint8_t i = 0; i < 6; i++) { + if (_keyReport.keys[i] == k) { + _keyReport.keys[i] = 0x00; + return 1; } } - return removeKeycodeFromReport(k); + // No pressed key was found + return 0; } -size_t KeyboardAPI::removeKeycodeFromReport(uint8_t k) -{ - uint8_t indexA; - uint8_t indexB; - uint8_t count; - if ((k >= HID_KEYBOARD_LEFT_CONTROL) && (k <= HID_KEYBOARD_RIGHT_GUI)) { - // it's a modifier key - _keyReport.modifiers = _keyReport.modifiers & (~(0x01 << (k - HID_KEYBOARD_LEFT_CONTROL))); +size_t KeyboardAPI::remove(KeyboardModifier k) +{ + // Release modifier key + auto oldModifier = _keyReport.modifiers; + _keyReport.modifiers &= ~k; + + // Check if we actually released a key + if(_keyReport.modifiers != oldModifier){ + return 1; } - else { - // it's some other key: - // 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 (indexA = 0; indexA < sizeof(_keyReport.keys); indexA++) { - if (_keyReport.keys[indexA] == k) { - _keyReport.keys[indexA] = 0; - } - } + return 0; +} - // finally rearrange the keys list so that the free (= 0x00) are at the - // end of the keys list - some implementations stop for keys at the - // first occurence of an 0x00 in the keys list - // so (0x00)(0x01)(0x00)(0x03)(0x02)(0x00) becomes - // (0x01)(0x03)(0x02)(0x00)(0x00)(0x00) - count = 0; // holds the number of zeros we've found - indexA = 0; - while ((indexA + count) < sizeof(_keyReport.keys)) { - if (0 == _keyReport.keys[indexA]) { - count++; // one more zero - for (indexB = indexA; indexB < sizeof(_keyReport.keys) - count; indexB++) { - _keyReport.keys[indexB] = _keyReport.keys[indexB + 1]; - } - _keyReport.keys[sizeof(_keyReport.keys) - count] = 0; - } - else { - indexA++; // one more non-zero - } - } - } - return 1; +void KeyboardAPI::releaseAll(void) +{ + // Release all keys + removeAll(); + send_now(); } -size_t KeyboardAPI::writeKeycode(uint8_t c) +void KeyboardAPI::removeAll(void) { - uint8_t p = pressKeycode(c); // Keydown - releaseKeycode(c); // Keyup - return (p); // just return the result of pressKeycode() since release() almost always returns 1 + // Release all keys + memset(&_keyReport, 0x00, sizeof(_keyReport)); } + + +void KeyboardAPI::send_now(void){ + SendReport(&_keyReport, sizeof(_keyReport)); +} + + diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index f7dce02979..f6b3d6c1cc 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -48,6 +48,7 @@ THE SOFTWARE. #include "SingleReport/RawHID.h" // Include Teensy HID afterwards to overwrite key definitions if used +// TODO include Teensy API if non english keyboard layout was used #ifdef USE_TEENSY_KEYBOARD //#include "TeensyKeyboard.h" #else From bfd1bf444656229e4b97ce22ae378f952df29a74 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Fri, 23 Oct 2015 18:49:54 +0200 Subject: [PATCH 296/602] Added all keyboard keycodes --- plugins/KeyboardioHID/Readme.md | 2 + .../src/HID-APIs/ImprovedKeylayouts.h | 152 ++++++++++++++++-- 2 files changed, 144 insertions(+), 10 deletions(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 71037aa6c6..dfaa9b6016 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -91,6 +91,8 @@ Version History * Added a few key definitions * Uses .alinkage custom IDE option * Added BootKeyboard support (BIOS compatibility) +* KEY_MENU switched to KEY_APPLICATION +* KEY_RETURN is not KEY_ENTER anymore! 2.3 Release (never released) * Updated Libraries diff --git a/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h b/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h index bb58b2d6ba..894c379d88 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h +++ b/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h @@ -28,21 +28,18 @@ THE SOFTWARE. #error This API does not support non US english layouts. #endif -// Key alias -#define KEY_RETURN KEY_ENTER -#define KEY_LEFT_WINDOWS KEY_LEFT_GUI -#define KEY_RIGHT_WINDOWS KEY_RIGHT_GUI -#define KEY_PRINTSCREEN KEY_PRINT - +// Hut1_12v2.pdf enum KeyboardModifier : uint8_t { KEY_LEFT_CTRL = (1 << 0), KEY_LEFT_SHIFT = (1 << 1), KEY_LEFT_ALT = (1 << 2), KEY_LEFT_GUI = (1 << 3), + KEY_LEFT_WINDOWS = (1 << 3), // Alias KEY_RIGHT_CTRL = (1 << 4), KEY_RIGHT_SHIFT = (1 << 5), KEY_RIGHT_ALT = (1 << 6), KEY_RIGHT_GUI = (1 << 7), + KEY_RIGHT_WINDOWS = (1 << 7), // Alias }; enum KeyboardKeycode : uint8_t { @@ -117,6 +114,7 @@ enum KeyboardKeycode : uint8_t { KEY_F11 = 0x44, KEY_F12 = 0x45, KEY_PRINT = 0x46, + KEY_PRINTSCREEN = 0x46, // Alias KEY_SCROLL_LOCK = 0x47, KEY_PAUSE = 0x48, KEY_INSERT = 0x49, @@ -130,14 +128,148 @@ enum KeyboardKeycode : uint8_t { KEY_DOWN_ARROW = 0x51, KEY_UP_ARROW = 0x52, KEY_NUM_LOCK = 0x53, - + KEYPAD_SLASH = 0x54, + KEYPAD_ASTERICS = 0x55, + KEYPAD_MINUS = 0x56, + KEYPAD_PLUS = 0x57, + KEYPAD_ENTER = 0x59, + KEYPAD_1 = 0x59, + KEYPAD_2 = 0x5A, + KEYPAD_3 = 0x5B, + KEYPAD_4 = 0x5C, + KEYPAD_5 = 0x5D, + KEYPAD_6 = 0x5E, + KEYPAD_7 = 0x5F, + KEYPAD_8 = 0x60, + KEYPAD_9 = 0x61, + KEYPAD_0 = 0x62, + KEYPAD_DOT = 0x63, KEY_NON_US = 0x64, - KEY_MENU = 0x65, - KEY_POWER = 0x66, + KEY_APPLICATION = 0x65, // Context menu/right click - KEY_VOLUME_MUTE = 0x7F, + // Most of the following keys will only work with Linux or not at all. + // F13+ keys are mostly used for laptop functions like ECO key. + KEY_POWER = 0x66, + KEY_PAD_EQUAL = 0x67, + KEY_F13 = 0x68, + KEY_F14 = 0x69, + KEY_F15 = 0x6A, + KEY_F16 = 0x6B, + KEY_F17 = 0x6C, + KEY_F18 = 0x6D, + KEY_F19 = 0x6E, + KEY_F20 = 0x6F, + KEY_F21 = 0x70, + KEY_F22 = 0x71, + KEY_F23 = 0x72, + KEY_F24 = 0x73, + KEY_EXECUTE = 0x74, + KEY_HELP = 0x75, + KEY_MENU = 0x76, + KEY_SELECT = 0x77, + KEY_STOP = 0x78, + KEY_AGAIN = 0x79, + KEY_UNDO = 0x7A, + KEY_CUT = 0x7B, + KEY_COPY = 0x7C, + KEY_PASTE = 0x7D, + KEY_FIND = 0x7E, + KEY_MUTE = 0x7F, + KEY_VOLUME_MUTE = 0x7F, // Alias KEY_VOLUME_UP = 0x80, KEY_VOLUME_DOWN = 0x81, + KEY_LOCKING_CAPS_LOCK = 0x82, + KEY_LOCKING_NUM_LOCK = 0x83, + KEY_LOCKING_SCROLL_LOCK = 0x84, + KEYPAD_COMMA = 0x85, + KEYPAD_EQUAL_SIGN = 0x86, // Dont confuse with KEYPAD_EQUAL + KEY_INTERNATIONAL1 = 0x87, + KEY_INTERNATIONAL2 = 0x88, + KEY_INTERNATIONAL3 = 0x89, + KEY_INTERNATIONAL4 = 0x8A, + KEY_INTERNATIONAL5 = 0x8B, + KEY_INTERNATIONAL6 = 0x8C, + KEY_INTERNATIONAL7 = 0x8D, + KEY_INTERNATIONAL8 = 0x8E, + KEY_INTERNATIONAL9 = 0x8F, + KEY_LANG1 = 0x90, + KEY_LANG2 = 0x91, + KEY_LANG3 = 0x92, + KEY_LANG4 = 0x93, + KEY_LANG5 = 0x94, + KEY_LANG6 = 0x95, + KEY_LANG7 = 0x96, + KEY_LANG8 = 0x97, + KEY_LANG9 = 0x98, + KEY_ALTERNATE_ERASE = 0x99, + KEY_SYSREQ_ATTENTION = 0x9A, + KEY_CANCEL = 0x9B, + KEY_CLEAR = 0x9C, + KEY_PRIOR = 0x9D, + KEY_RETURN = 0x9E, // Do not confuse this with KEY_ENTER + KEY_SEPARATOR = 0x9F, + KEY_OUT = 0xA0, + KEY_OPER = 0xA1, + KEY_CLEAR_AGAIN = 0xA2, + KEY_CRSEL_PROPS = 0xA3, + KEY_EXSEL = 0xA4, + + KEY_PAD_00 = 0xB0, + KEY_PAD_000 = 0xB1, + KEY_THOUSANDS_SEPARATOR = 0xB2, + KEY_DECIMAL_SEPARATOR = 0xB3, + KEY_CURRENCY_UNIT = 0xB4, + KEY_CURRENCY_SUB_UNIT = 0xB5, + KEYPAD_LEFT_BRACE = 0xB6, + KEYPAD_RIGHT_BRACE = 0xB7, + KEYPAD_LEFT_CURLY_BRACE = 0xB8, + KEYPAD_RIGHT_CURLY_BRACE = 0xB9, + KEYPAD_TAB = 0xBA, + KEYPAD_BACKSPACE = 0xBB, + KEYPAD_A = 0xBC, + KEYPAD_B = 0xBD, + KEYPAD_C = 0xBE, + KEYPAD_D = 0xBF, + KEYPAD_E = 0xC0, + KEYPAD_F = 0xC1, + KEYPAD_XOR = 0xC2, + KEYPAD_CARET = 0xC3, + KEYPAD_PERCENT = 0xC4, + KEYPAD_LEFT_ANGLE = 0xC5, + KEYPAD_RIGHT_ANGLE = 0xC6, + KEYPAD_AMPERSAND = 0xC7, + KEYPAD_DOUBLE_AMPERSAND = 0xC8, + KEYPAD_PIPE = 0xC9, + KEYPAD_DOUBLE_PIPE = 0xCA, + KEYPAD_COLON = 0xCB, + KEYPAD_POUND = 0xCC, + KEYPAD_SPACE = 0xCD, + KEYPAD_AT = 0xCE, + KEYPAD_EXCLAMATION = 0xCF, + KEYPAD_MEMORY_STORE = 0xD0, + KEYPAD_MEMORY_RECALL = 0xD1, + KEYPAD_MEMORY_CLEAR = 0xD2, + KEYPAD_MEMORY_ADD = 0xD3, + KEYPAD_MEMORY_SUBTRACT = 0xD4, + KEYPAD_MEMORY_MULTIPLY = 0xD5, + KEYPAD_MEMORY_DIVIDE = 0xD6, + KEYPAD_PLUS_MINUS = 0xD7, + KEYPAD_CLEAR = 0xD8, + KEYPAD_CLEAR_ENTRY = 0xD9, + KEYPAD_BINARY = 0xDA, + KEYPAD_OCTAL = 0xDB, + KEYPAD_DECIMAL = 0xDC, + KEYPAD_HEXADECIMAL = 0xDD, + + // Used in KeyboardModifier enum directly + //KEY_LEFT_CTRL = 0xE0, + //KEY_LEFT_SHIFT = 0xE1, + //KEY_LEFT_ALT = 0xE2, + //KEY_LEFT_GUI = 0xE3, + //KEY_RIGHT_CTRL = 0xE4, + //KEY_RIGHT_SHIFT = 0xE5, + //KEY_RIGHT_ALT = 0xE6, + //KEY_RIGHT_GUI = 0xE7, }; // Keyboard Leds From d34e2c5bb0878bba09507b2fddbde41a46d15169 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Fri, 23 Oct 2015 20:49:11 +0200 Subject: [PATCH 297/602] Added Keyboard API templates --- .../KeyboardioHID/src/HID-APIs/KeyboardAPI.h | 18 ++--- .../src/HID-APIs/KeyboardAPI.hpp | 78 +++---------------- 2 files changed, 19 insertions(+), 77 deletions(-) diff --git a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h index 6a229f0506..707a056edb 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h +++ b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h @@ -48,17 +48,17 @@ class KeyboardAPI : public Print inline void begin(void); inline void end(void); - inline size_t write(uint8_t k); - inline size_t write(KeyboardKeycode k); - inline size_t write(KeyboardModifier k); - inline size_t press(uint8_t k); - inline size_t press(KeyboardKeycode k); - inline size_t press(KeyboardModifier k); + template + inline size_t write(TYPE k); + inline virtual size_t write(uint8_t k) override; - inline size_t release(uint8_t k); - inline size_t release(KeyboardKeycode k); - inline size_t release(KeyboardModifier k); + + template + inline size_t press(TYPE k); + + template + inline size_t release(TYPE k); inline size_t add(uint8_t k); inline size_t add(KeyboardKeycode k); diff --git a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.hpp b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.hpp index fba968dcdc..0315f5d7e4 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.hpp +++ b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.hpp @@ -36,8 +36,8 @@ void KeyboardAPI::end(void) } -// TODO template?? -size_t KeyboardAPI::write(uint8_t k) +template +size_t KeyboardAPI::write(TYPE k) { // Press and release key (if press was successfull) auto ret = press(k); @@ -48,29 +48,14 @@ size_t KeyboardAPI::write(uint8_t k) } -size_t KeyboardAPI::write(KeyboardKeycode k) -{ - // Press and release key (if press was successfull) - auto ret = press(k); - if(ret){ - release(k); - } - return ret; -} - - -size_t KeyboardAPI::write(KeyboardModifier k) +size_t KeyboardAPI::write(uint8_t k) { - // Press and release key (if press was successfull) - auto ret = press(k); - if(ret){ - release(k); - } - return ret; + return write(k); } -size_t KeyboardAPI::press(uint8_t k) +template +size_t KeyboardAPI::press(TYPE k) { // Press key and send report to host auto ret = add(k); @@ -81,21 +66,11 @@ size_t KeyboardAPI::press(uint8_t k) } -size_t KeyboardAPI::press(KeyboardKeycode k) +template +size_t KeyboardAPI::release(TYPE k) { - // Press key and send report to host - auto ret = add(k); - if(ret){ - send_now(); - } - return ret; -} - - -size_t KeyboardAPI::press(KeyboardModifier k) -{ - // Press modifier key and send report to host - auto ret = add(k); + // Release key and send report to host + auto ret = remove(k); if(ret){ send_now(); } @@ -151,39 +126,6 @@ size_t KeyboardAPI::add(KeyboardModifier k) } -size_t KeyboardAPI::release(uint8_t k) -{ - // Release key and send report to host - auto ret = remove(k); - if(ret){ - send_now(); - } - return ret; -} - - -size_t KeyboardAPI::release(KeyboardKeycode k) -{ - // Release key and send report to host - auto ret = remove(k); - if(ret){ - send_now(); - } - return ret; -} - - -size_t KeyboardAPI::release(KeyboardModifier k) -{ - // Release modifier key and send report to host - auto ret = remove(k); - if(ret){ - send_now(); - } - return ret; -} - - size_t KeyboardAPI::remove(uint8_t k) { // Ignore invalid input From e235e7e14fbb770c3cf9343e3eb6c7f6ea037a78 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Fri, 23 Oct 2015 20:50:00 +0200 Subject: [PATCH 298/602] Added Consumer Keys to keyboard reserved report byte --- .../src/MultiReport/ImprovedKeyboard.cpp | 10 ++++++++-- .../KeyboardioHID/src/SingleReport/BootKeyboard.cpp | 11 ++++++++--- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.cpp index 9f4ef2004b..d77472b371 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.cpp @@ -40,12 +40,18 @@ static const uint8_t _hidMultiReportDescriptorKeyboard[] PROGMEM = { 0x95, 0x08, /* REPORT_COUNT (8) */ 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - /* Reserved byte */ + /* Reserved byte, used for consumer reports, only works with linux */ + 0x05, 0x0C, /* Usage Page (Consumer) */ 0x95, 0x01, /* REPORT_COUNT (1) */ 0x75, 0x08, /* REPORT_SIZE (8) */ - 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x26, 0xFF, 0x00, /* LOGICAL_MAXIMUM (255) */ + 0x19, 0x00, /* USAGE_MINIMUM (0) */ + 0x29, 0xFF, /* USAGE_MAXIMUM (255) */ + 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ /* 6 Keyboard keys */ + 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ 0x95, 0x06, /* REPORT_COUNT (6) */ 0x75, 0x08, /* REPORT_SIZE (8) */ 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ diff --git a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp index c4529718cc..f8d0f240b0 100644 --- a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp @@ -39,10 +39,15 @@ static const uint8_t _hidReportDescriptorKeyboard[] PROGMEM = { 0x95, 0x08, /* REPORT_COUNT (8) */ 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - /* Reserved byte TODO consumer and or system */ + /* Reserved byte, used for consumer reports, only works with linux */ + 0x05, 0x0C, /* Usage Page (Consumer) */ 0x95, 0x01, /* REPORT_COUNT (1) */ 0x75, 0x08, /* REPORT_SIZE (8) */ - 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x26, 0xFF, 0x00, /* LOGICAL_MAXIMUM (255) */ + 0x19, 0x00, /* USAGE_MINIMUM (0) */ + 0x29, 0xFF, /* USAGE_MAXIMUM (255) */ + 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ /* 5 LEDs for num lock etc, 3 left for advanced, custom usage */ 0x05, 0x08, /* USAGE_PAGE (LEDs) */ @@ -53,11 +58,11 @@ static const uint8_t _hidReportDescriptorKeyboard[] PROGMEM = { 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */ /* 6 Keyboard keys */ + 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ 0x95, 0x06, /* REPORT_COUNT (6) */ 0x75, 0x08, /* REPORT_SIZE (8) */ 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ 0x26, 0xE7, 0x00, /* LOGICAL_MAXIMUM (231) */ - 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ 0x29, 0xE7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ From e2b279a6035091c65bc6609f842d138efa547b7b Mon Sep 17 00:00:00 2001 From: NicoHood Date: Fri, 23 Oct 2015 20:50:47 +0200 Subject: [PATCH 299/602] Updated Keyboard definitions once again --- .../KeyboardioHID/src/HID-APIs/HID-Tables.h | 225 ---------------- .../src/HID-APIs/ImprovedKeylayouts.h | 241 +++++++++++++++++- .../KeyboardioHID/src/HID-APIs/KeyboardAPI.h | 1 - 3 files changed, 233 insertions(+), 234 deletions(-) diff --git a/plugins/KeyboardioHID/src/HID-APIs/HID-Tables.h b/plugins/KeyboardioHID/src/HID-APIs/HID-Tables.h index bc56d52843..b62be3aa81 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/HID-Tables.h +++ b/plugins/KeyboardioHID/src/HID-APIs/HID-Tables.h @@ -63,231 +63,6 @@ #define HID_SYSTEM_DISPLAY_SWAP_PRIMARY_SLASH_SECONDARY 0xB6 // HID type OSC #define HID_SYSTEM_DISPLAY_LCD_AUTOSCALE 0xB7 // HID type OSC -// Keyboard HID mappings - -// Reserved (no_event_indicated) 0x00 -#define HID_KEYBOARD_ERROR_ROLLOVER 0x01 -#define HID_KEYBOARD_POST_FAIL 0x02 -#define HID_KEYBOARD_ERROR_UNDEFINED 0x03 -#define HID_KEYBOARD_A_AND_A 0x04 -#define HID_KEYBOARD_B_AND_B 0x05 -#define HID_KEYBOARD_C_AND_C 0x06 -#define HID_KEYBOARD_D_AND_D 0x07 -#define HID_KEYBOARD_E_AND_E 0x08 -#define HID_KEYBOARD_F_AND_F 0x09 -#define HID_KEYBOARD_G_AND_G 0x0A -#define HID_KEYBOARD_H_AND_H 0x0B -#define HID_KEYBOARD_I_AND_I 0x0C -#define HID_KEYBOARD_J_AND_J 0x0D -#define HID_KEYBOARD_K_AND_K 0x0E -#define HID_KEYBOARD_L_AND_L 0x0F -#define HID_KEYBOARD_M_AND_M 0x10 -#define HID_KEYBOARD_N_AND_N 0x11 -#define HID_KEYBOARD_O_AND_O 0x12 -#define HID_KEYBOARD_P_AND_P 0x13 -#define HID_KEYBOARD_Q_AND_Q 0x14 -#define HID_KEYBOARD_R_AND_R 0x15 -#define HID_KEYBOARD_S_AND_S 0x16 -#define HID_KEYBOARD_T_AND_T 0x17 -#define HID_KEYBOARD_U_AND_U 0x18 -#define HID_KEYBOARD_V_AND_V 0x19 -#define HID_KEYBOARD_W_AND_W 0x1A -#define HID_KEYBOARD_X_AND_X 0x1B -#define HID_KEYBOARD_Y_AND_Y 0x1C -#define HID_KEYBOARD_Z_AND_Z 0x1D -#define HID_KEYBOARD_1_AND_EXCLAMATION_POINT 0x1E -#define HID_KEYBOARD_2_AND_AT 0x1F -#define HID_KEYBOARD_3_AND_POUND 0x20 -#define HID_KEYBOARD_4_AND_DOLLAR 0x21 -#define HID_KEYBOARD_5_AND_PERCENT 0x22 -#define HID_KEYBOARD_6_AND_CARAT 0x23 -#define HID_KEYBOARD_7_AND_AMPERSAND 0x24 -#define HID_KEYBOARD_8_AND_ASTERISK 0x25 -#define HID_KEYBOARD_9_AND_LEFT_PAREN 0x26 -#define HID_KEYBOARD_0_AND_RIGHT_PAREN 0x27 -#define HID_KEYBOARD_ENTER 0x28 // (MARKED AS ENTER_SLASH_RETURN) -#define HID_KEYBOARD_ESCAPE 0x29 -#define HID_KEYBOARD_DELETE 0x2A // (BACKSPACE) -#define HID_KEYBOARD_TAB 0x2B -#define HID_KEYBOARD_SPACEBAR 0x2C -#define HID_KEYBOARD_MINUS_AND_UNDERSCORE 0x2D // (UNDERSCORE) -#define HID_KEYBOARD_EQUALS_AND_PLUS 0x2E -#define HID_KEYBOARD_LEFT_BRACKET_AND_LEFT_CURLY_BRACE 0x2F -#define HID_KEYBOARD_RIGHT_BRACKET_AND_RIGHT_CURLY_BRACE 0x30 -#define HID_KEYBOARD_BACKSLASH_AND_PIPE 0x31 -#define HID_KEYBOARD_NON_US_POUND_AND_TILDE 0x32 -#define HID_KEYBOARD_SEMICOLON_AND_COLON 0x33 -#define HID_KEYBOARD_QUOTE_AND_DOUBLEQUOTE 0x34 -#define HID_KEYBOARD_GRAVE_ACCENT_AND_TILDE 0x35 -#define HID_KEYBOARD_COMMA_AND_LESS_THAN 0x36 -#define HID_KEYBOARD_PERIOD_AND_GREATER_THAN 0x37 -#define HID_KEYBOARD_SLASH_AND_QUESTION_MARK 0x38 -#define HID_KEYBOARD_CAPS_LOCK 0x39 -#define HID_KEYBOARD_F1 0x3A -#define HID_KEYBOARD_F2 0x3B -#define HID_KEYBOARD_F3 0x3C -#define HID_KEYBOARD_F4 0x3D -#define HID_KEYBOARD_F5 0x3E -#define HID_KEYBOARD_F6 0x3F -#define HID_KEYBOARD_F7 0x40 -#define HID_KEYBOARD_F8 0x41 -#define HID_KEYBOARD_F9 0x42 -#define HID_KEYBOARD_F10 0x43 -#define HID_KEYBOARD_F11 0x44 -#define HID_KEYBOARD_F12 0x45 -#define HID_KEYBOARD_PRINTSCREEN 0x46 -#define HID_KEYBOARD_SCROLL_LOCK 0x47 -#define HID_KEYBOARD_PAUSE 0x48 -#define HID_KEYBOARD_INSERT 0x49 -#define HID_KEYBOARD_HOME 0x4A -#define HID_KEYBOARD_PAGE_UP 0x4B -#define HID_KEYBOARD_DELETE_FORWARD 0x4C -#define HID_KEYBOARD_END 0x4D -#define HID_KEYBOARD_PAGE_DOWN 0x4E -#define HID_KEYBOARD_RIGHTARROW 0x4F -#define HID_KEYBOARD_LEFTARROW 0x50 -#define HID_KEYBOARD_DOWNARROW 0x51 -#define HID_KEYBOARD_UPARROW 0x52 -#define HID_KEYPAD_NUM_LOCK_AND_CLEAR 0x53 -#define HID_KEYPAD_DIVIDE 0x54 -#define HID_KEYPAD_MULTIPLY 0x55 -#define HID_KEYPAD_SUBTRACT 0x56 -#define HID_KEYPAD_ADD 0x57 -#define HID_KEYPAD_ENTER 0x58 -#define HID_KEYPAD_1_AND_END 0x59 -#define HID_KEYPAD_2_AND_DOWN_ARROW 0x5A -#define HID_KEYPAD_3_AND_PAGE_DOWN 0x5B -#define HID_KEYPAD_4_AND_LEFT_ARROW 0x5C -#define HID_KEYPAD_5 0x5D -#define HID_KEYPAD_6_AND_RIGHT_ARROW 0x5E -#define HID_KEYPAD_7_AND_HOME 0x5F -#define HID_KEYPAD_8_AND_UP_ARROW 0x60 -#define HID_KEYPAD_9_AND_PAGE_UP 0x61 -#define HID_KEYPAD_0_AND_INSERT 0x62 -#define HID_KEYPAD_PERIOD_AND_DELETE 0x63 -#define HID_KEYBOARD_NON_US_BACKSLASH_AND_PIPE 0x64 -#define HID_KEYBOARD_APPLICATION 0x65 -#define HID_KEYBOARD_POWER 0x66 -#define HID_KEYPAD_EQUALS 0x67 -#define HID_KEYBOARD_F13 0x68 -#define HID_KEYBOARD_F14 0x69 -#define HID_KEYBOARD_F15 0x6A -#define HID_KEYBOARD_F16 0x6B -#define HID_KEYBOARD_F17 0x6C -#define HID_KEYBOARD_F18 0x6D -#define HID_KEYBOARD_F19 0x6E -#define HID_KEYBOARD_F20 0x6F -#define HID_KEYBOARD_F21 0x70 -#define HID_KEYBOARD_F22 0x71 -#define HID_KEYBOARD_F23 0x72 -#define HID_KEYBOARD_F24 0x73 -#define HID_KEYBOARD_EXECUTE 0x74 -#define HID_KEYBOARD_HELP 0x75 -#define HID_KEYBOARD_MENU 0x76 -#define HID_KEYBOARD_SELECT 0x77 -#define HID_KEYBOARD_STOP 0x78 -#define HID_KEYBOARD_AGAIN 0x79 -#define HID_KEYBOARD_UNDO 0x7A -#define HID_KEYBOARD_CUT 0x7B -#define HID_KEYBOARD_COPY 0x7C -#define HID_KEYBOARD_PASTE 0x7D -#define HID_KEYBOARD_FIND 0x7E -#define HID_KEYBOARD_MUTE 0x7F -#define HID_KEYBOARD_VOLUME_UP 0x80 -#define HID_KEYBOARD_VOLUME_DOWN 0x81 -#define HID_KEYBOARD_LOCKING_CAPS_LOCK 0x82 -#define HID_KEYBOARD_LOCKING_NUM_LOCK 0x83 -#define HID_KEYBOARD_LOCKING_SCROLL_LOCK 0x84 -#define HID_KEYPAD_COMMA 0x85 -#define HID_KEYPAD_EQUAL_SIGN 0x86 -#define HID_KEYBOARD_INTERNATIONAL1 0x87 -#define HID_KEYBOARD_INTERNATIONAL2 0x88 -#define HID_KEYBOARD_INTERNATIONAL3 0x89 -#define HID_KEYBOARD_INTERNATIONAL4 0x8A -#define HID_KEYBOARD_INTERNATIONAL5 0x8B -#define HID_KEYBOARD_INTERNATIONAL6 0x8C -#define HID_KEYBOARD_INTERNATIONAL7 0x8D -#define HID_KEYBOARD_INTERNATIONAL8 0x8E -#define HID_KEYBOARD_INTERNATIONAL9 0x8F -#define HID_KEYBOARD_LANG1 0x90 -#define HID_KEYBOARD_LANG2 0x91 -#define HID_KEYBOARD_LANG3 0x92 -#define HID_KEYBOARD_LANG4 0x93 -#define HID_KEYBOARD_LANG5 0x94 -#define HID_KEYBOARD_LANG6 0x95 -#define HID_KEYBOARD_LANG7 0x96 -#define HID_KEYBOARD_LANG8 0x97 -#define HID_KEYBOARD_LANG9 0x98 -#define HID_KEYBOARD_ALTERNATE_ERASE 0x99 -#define HID_KEYBOARD_SYSREQ_SLASH_ATTENTION 0x9A -#define HID_KEYBOARD_CANCEL 0x9B -#define HID_KEYBOARD_CLEAR 0x9C -#define HID_KEYBOARD_PRIOR 0x9D -#define HID_KEYBOARD_RETURN 0x9E -#define HID_KEYBOARD_SEPARATOR 0x9F -#define HID_KEYBOARD_OUT 0xA0 -#define HID_KEYBOARD_OPER 0xA1 -#define HID_KEYBOARD_CLEAR_SLASH_AGAIN 0xA2 -#define HID_KEYBOARD_CRSEL_SLASH_PROPS 0xA3 -#define HID_KEYBOARD_EXSEL 0xA4 -// Reserved 0xA5-AF -#define HID_KEYPAD_00 0xB0 -#define HID_KEYPAD_000 0xB1 -#define HID_THOUSANDS_SEPARATOR 0xB2 -#define HID_DECIMAL_SEPARATOR 0xB3 -#define HID_CURRENCY_UNIT 0xB4 -#define HID_CURRENCY_SUBUNIT 0xB5 -#define HID_KEYPAD_LEFT_PAREN 0xB6 -#define HID_KEYPAD_RIGHT_PAREN 0xB7 -#define HID_KEYPAD_LEFT_CURLY_BRACE 0xB8 -#define HID_KEYPAD_RIGHT_CURLY_BRACE 0xB9 -#define HID_KEYPAD_TAB 0xBA -#define HID_KEYPAD_BACKSPACE 0xBB -#define HID_KEYPAD_A 0xBC -#define HID_KEYPAD_B 0xBD -#define HID_KEYPAD_C 0xBE -#define HID_KEYPAD_D 0xBF -#define HID_KEYPAD_E 0xC0 -#define HID_KEYPAD_F 0xC1 -#define HID_KEYPAD_XOR 0xC2 -#define HID_KEYPAD_CARAT 0xC3 -#define HID_KEYPAD_PERCENT 0xC4 -#define HID_KEYPAD_LESS_THAN 0xC5 -#define HID_KEYPAD_GREATER_THAN 0xC6 -#define HID_KEYPAD_AMPERSAND 0xC7 -#define HID_KEYPAD_DOUBLEAMPERSAND 0xC8 -#define HID_KEYPAD_PIPE 0xC9 -#define HID_KEYPAD_DOUBLEPIPE 0xCA -#define HID_KEYPAD_COLON 0xCB -#define HID_KEYPAD_POUND_SIGN 0xCC -#define HID_KEYPAD_SPACE 0xCD -#define HID_KEYPAD_AT_SIGN 0xCE -#define HID_KEYPAD_EXCLAMATION_POINT 0xCF -#define HID_KEYPAD_MEMORY_STORE 0xD0 -#define HID_KEYPAD_MEMORY_RECALL 0xD1 -#define HID_KEYPAD_MEMORY_CLEAR 0xD2 -#define HID_KEYPAD_MEMORY_ADD 0xD3 -#define HID_KEYPAD_MEMORY_SUBTRACT 0xD4 -#define HID_KEYPAD_MEMORY_MULTIPLY 0xD5 -#define HID_KEYPAD_MEMORY_DIVIDE 0xD6 -#define HID_KEYPAD_PLUS_SLASH_MINUS 0xD7 -#define HID_KEYPAD_CLEAR 0xD8 -#define HID_KEYPAD_CLEAR_ENTRY 0xD9 -#define HID_KEYPAD_BINARY 0xDA -#define HID_KEYPAD_OCTAL 0xDB -#define HID_KEYPAD_DECIMAL 0xDC -#define HID_KEYPAD_HEXADECIMAL 0xDD - -// 0xDE-0xDF - RESERVED -#define HID_KEYBOARD_LEFT_CONTROL 0xE0 -#define HID_KEYBOARD_LEFT_SHIFT 0xE1 -#define HID_KEYBOARD_LEFT_ALT 0xE2 -#define HID_KEYBOARD_LEFT_GUI 0xE3 -#define HID_KEYBOARD_RIGHT_CONTROL 0xE4 -#define HID_KEYBOARD_RIGHT_SHIFT 0xE5 -#define HID_KEYBOARD_RIGHT_ALT 0xE6 -#define HID_KEYBOARD_RIGHT_GUI 0xE7 - // Consumer_Page_(0x0C) 0x15 #define HID_CONSUMER_NUMERIC_KEY_PAD 0x02 // HID type NARY diff --git a/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h b/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h index 894c379d88..7645ec8344 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h +++ b/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h @@ -44,9 +44,9 @@ enum KeyboardModifier : uint8_t { enum KeyboardKeycode : uint8_t { KEY_RESERVED = 0, - KEY_ERRORROLLOVER = 1, - KEY_POSTFAIL = 2, - KEY_ERRORUNDEFINED = 3, + KEY_ERROR_ROLLOVER = 1, + KEY_POST_FAIL = 2, + KEY_ERROR_UNDEFINED = 3, KEY_A = 4, KEY_B = 5, KEY_C = 6, @@ -128,10 +128,10 @@ enum KeyboardKeycode : uint8_t { KEY_DOWN_ARROW = 0x51, KEY_UP_ARROW = 0x52, KEY_NUM_LOCK = 0x53, - KEYPAD_SLASH = 0x54, - KEYPAD_ASTERICS = 0x55, - KEYPAD_MINUS = 0x56, - KEYPAD_PLUS = 0x57, + KEYPAD_DIVIDE = 0x54, + KEYPAD_MULTIPLY = 0x55, + KEYPAD_SUBTRACT = 0x56, + KEYPAD_ADD = 0x57, KEYPAD_ENTER = 0x59, KEYPAD_1 = 0x59, KEYPAD_2 = 0x5A, @@ -150,7 +150,7 @@ enum KeyboardKeycode : uint8_t { // Most of the following keys will only work with Linux or not at all. // F13+ keys are mostly used for laptop functions like ECO key. KEY_POWER = 0x66, - KEY_PAD_EQUAL = 0x67, + KEY_PAD_EQUALS = 0x67, // Dont confuse with KEYPAD_EQUAL_SIGN KEY_F13 = 0x68, KEY_F14 = 0x69, KEY_F15 = 0x6A, @@ -270,6 +270,231 @@ enum KeyboardKeycode : uint8_t { //KEY_RIGHT_SHIFT = 0xE5, //KEY_RIGHT_ALT = 0xE6, //KEY_RIGHT_GUI = 0xE7, + + // Keyboard HID mappings + + // Reserved (no_event_indicated) + HID_KEYBOARD_ERROR_ROLLOVER = 0x01, + HID_KEYBOARD_POST_FAIL = 0x02, + HID_KEYBOARD_ERROR_UNDEFINED = 0x03, + HID_KEYBOARD_A_AND_A = 0x04, + HID_KEYBOARD_B_AND_B = 0x05, + HID_KEYBOARD_C_AND_C = 0x06, + HID_KEYBOARD_D_AND_D = 0x07, + HID_KEYBOARD_E_AND_E = 0x08, + HID_KEYBOARD_F_AND_F = 0x09, + HID_KEYBOARD_G_AND_G = 0x0A, + HID_KEYBOARD_H_AND_H = 0x0B, + HID_KEYBOARD_I_AND_I = 0x0C, + HID_KEYBOARD_J_AND_J = 0x0D, + HID_KEYBOARD_K_AND_K = 0x0E, + HID_KEYBOARD_L_AND_L = 0x0F, + HID_KEYBOARD_M_AND_M = 0x10, + HID_KEYBOARD_N_AND_N = 0x11, + HID_KEYBOARD_O_AND_O = 0x12, + HID_KEYBOARD_P_AND_P = 0x13, + HID_KEYBOARD_Q_AND_Q = 0x14, + HID_KEYBOARD_R_AND_R = 0x15, + HID_KEYBOARD_S_AND_S = 0x16, + HID_KEYBOARD_T_AND_T = 0x17, + HID_KEYBOARD_U_AND_U = 0x18, + HID_KEYBOARD_V_AND_V = 0x19, + HID_KEYBOARD_W_AND_W = 0x1A, + HID_KEYBOARD_X_AND_X = 0x1B, + HID_KEYBOARD_Y_AND_Y = 0x1C, + HID_KEYBOARD_Z_AND_Z = 0x1D, + HID_KEYBOARD_1_AND_EXCLAMATION_POINT = 0x1E, + HID_KEYBOARD_2_AND_AT = 0x1F, + HID_KEYBOARD_3_AND_POUND = 0x20, + HID_KEYBOARD_4_AND_DOLLAR = 0x21, + HID_KEYBOARD_5_AND_PERCENT = 0x22, + HID_KEYBOARD_6_AND_CARAT = 0x23, + HID_KEYBOARD_7_AND_AMPERSAND = 0x24, + HID_KEYBOARD_8_AND_ASTERISK = 0x25, + HID_KEYBOARD_9_AND_LEFT_PAREN = 0x26, + HID_KEYBOARD_0_AND_RIGHT_PAREN = 0x27, + HID_KEYBOARD_ENTER = 0x28, // (MARKED AS ENTER_SLASH_RETURN) + HID_KEYBOARD_ESCAPE = 0x29, + HID_KEYBOARD_DELETE = 0x2A, // (BACKSPACE) + HID_KEYBOARD_TAB = 0x2B, + HID_KEYBOARD_SPACEBAR = 0x2C, + HID_KEYBOARD_MINUS_AND_UNDERSCORE = 0x2D, // (UNDERSCORE) + HID_KEYBOARD_EQUALS_AND_PLUS = 0x2E, + HID_KEYBOARD_LEFT_BRACKET_AND_LEFT_CURLY_BRACE = 0x2F, + HID_KEYBOARD_RIGHT_BRACKET_AND_RIGHT_CURLY_BRACE = 0x30, + HID_KEYBOARD_BACKSLASH_AND_PIPE = 0x31, + HID_KEYBOARD_NON_US_POUND_AND_TILDE = 0x32, + HID_KEYBOARD_SEMICOLON_AND_COLON = 0x33, + HID_KEYBOARD_QUOTE_AND_DOUBLEQUOTE = 0x34, + HID_KEYBOARD_GRAVE_ACCENT_AND_TILDE = 0x35, + HID_KEYBOARD_COMMA_AND_LESS_THAN = 0x36, + HID_KEYBOARD_PERIOD_AND_GREATER_THAN = 0x37, + HID_KEYBOARD_SLASH_AND_QUESTION_MARK = 0x38, + HID_KEYBOARD_CAPS_LOCK = 0x39, + HID_KEYBOARD_F1 = 0x3A, + HID_KEYBOARD_F2 = 0x3B, + HID_KEYBOARD_F3 = 0x3C, + HID_KEYBOARD_F4 = 0x3D, + HID_KEYBOARD_F5 = 0x3E, + HID_KEYBOARD_F6 = 0x3F, + HID_KEYBOARD_F7 = 0x40, + HID_KEYBOARD_F8 = 0x41, + HID_KEYBOARD_F9 = 0x42, + HID_KEYBOARD_F10 = 0x43, + HID_KEYBOARD_F11 = 0x44, + HID_KEYBOARD_F12 = 0x45, + HID_KEYBOARD_PRINTSCREEN = 0x46, + HID_KEYBOARD_SCROLL_LOCK = 0x47, + HID_KEYBOARD_PAUSE = 0x48, + HID_KEYBOARD_INSERT = 0x49, + HID_KEYBOARD_HOME = 0x4A, + HID_KEYBOARD_PAGE_UP = 0x4B, + HID_KEYBOARD_DELETE_FORWARD = 0x4C, + HID_KEYBOARD_END = 0x4D, + HID_KEYBOARD_PAGE_DOWN = 0x4E, + HID_KEYBOARD_RIGHTARROW = 0x4F, + HID_KEYBOARD_LEFTARROW = 0x50, + HID_KEYBOARD_DOWNARROW = 0x51, + HID_KEYBOARD_UPARROW = 0x52, + HID_KEYPAD_NUM_LOCK_AND_CLEAR = 0x53, + HID_KEYPAD_DIVIDE = 0x54, + HID_KEYPAD_MULTIPLY = 0x55, + HID_KEYPAD_SUBTRACT = 0x56, + HID_KEYPAD_ADD = 0x57, + HID_KEYPAD_ENTER = 0x58, + HID_KEYPAD_1_AND_END = 0x59, + HID_KEYPAD_2_AND_DOWN_ARROW = 0x5A, + HID_KEYPAD_3_AND_PAGE_DOWN = 0x5B, + HID_KEYPAD_4_AND_LEFT_ARROW = 0x5C, + HID_KEYPAD_5 = 0x5D, + HID_KEYPAD_6_AND_RIGHT_ARROW = 0x5E, + HID_KEYPAD_7_AND_HOME = 0x5F, + HID_KEYPAD_8_AND_UP_ARROW = 0x60, + HID_KEYPAD_9_AND_PAGE_UP = 0x61, + HID_KEYPAD_0_AND_INSERT = 0x62, + HID_KEYPAD_PERIOD_AND_DELETE = 0x63, + HID_KEYBOARD_NON_US_BACKSLASH_AND_PIPE = 0x64, + HID_KEYBOARD_APPLICATION = 0x65, + HID_KEYBOARD_POWER = 0x66, + HID_KEYPAD_EQUALS = 0x67, + HID_KEYBOARD_F13 = 0x68, + HID_KEYBOARD_F14 = 0x69, + HID_KEYBOARD_F15 = 0x6A, + HID_KEYBOARD_F16 = 0x6B, + HID_KEYBOARD_F17 = 0x6C, + HID_KEYBOARD_F18 = 0x6D, + HID_KEYBOARD_F19 = 0x6E, + HID_KEYBOARD_F20 = 0x6F, + HID_KEYBOARD_F21 = 0x70, + HID_KEYBOARD_F22 = 0x71, + HID_KEYBOARD_F23 = 0x72, + HID_KEYBOARD_F24 = 0x73, + HID_KEYBOARD_EXECUTE = 0x74, + HID_KEYBOARD_HELP = 0x75, + HID_KEYBOARD_MENU = 0x76, + HID_KEYBOARD_SELECT = 0x77, + HID_KEYBOARD_STOP = 0x78, + HID_KEYBOARD_AGAIN = 0x79, + HID_KEYBOARD_UNDO = 0x7A, + HID_KEYBOARD_CUT = 0x7B, + HID_KEYBOARD_COPY = 0x7C, + HID_KEYBOARD_PASTE = 0x7D, + HID_KEYBOARD_FIND = 0x7E, + HID_KEYBOARD_MUTE = 0x7F, + HID_KEYBOARD_VOLUME_UP = 0x80, + HID_KEYBOARD_VOLUME_DOWN = 0x81, + HID_KEYBOARD_LOCKING_CAPS_LOCK = 0x82, + HID_KEYBOARD_LOCKING_NUM_LOCK = 0x83, + HID_KEYBOARD_LOCKING_SCROLL_LOCK = 0x84, + HID_KEYPAD_COMMA = 0x85, + HID_KEYPAD_EQUAL_SIGN = 0x86, + HID_KEYBOARD_INTERNATIONAL1 = 0x87, + HID_KEYBOARD_INTERNATIONAL2 = 0x88, + HID_KEYBOARD_INTERNATIONAL3 = 0x89, + HID_KEYBOARD_INTERNATIONAL4 = 0x8A, + HID_KEYBOARD_INTERNATIONAL5 = 0x8B, + HID_KEYBOARD_INTERNATIONAL6 = 0x8C, + HID_KEYBOARD_INTERNATIONAL7 = 0x8D, + HID_KEYBOARD_INTERNATIONAL8 = 0x8E, + HID_KEYBOARD_INTERNATIONAL9 = 0x8F, + HID_KEYBOARD_LANG1 = 0x90, + HID_KEYBOARD_LANG2 = 0x91, + HID_KEYBOARD_LANG3 = 0x92, + HID_KEYBOARD_LANG4 = 0x93, + HID_KEYBOARD_LANG5 = 0x94, + HID_KEYBOARD_LANG6 = 0x95, + HID_KEYBOARD_LANG7 = 0x96, + HID_KEYBOARD_LANG8 = 0x97, + HID_KEYBOARD_LANG9 = 0x98, + HID_KEYBOARD_ALTERNATE_ERASE = 0x99, + HID_KEYBOARD_SYSREQ_SLASH_ATTENTION = 0x9A, + HID_KEYBOARD_CANCEL = 0x9B, + HID_KEYBOARD_CLEAR = 0x9C, + HID_KEYBOARD_PRIOR = 0x9D, + HID_KEYBOARD_RETURN = 0x9E, + HID_KEYBOARD_SEPARATOR = 0x9F, + HID_KEYBOARD_OUT = 0xA0, + HID_KEYBOARD_OPER = 0xA1, + HID_KEYBOARD_CLEAR_SLASH_AGAIN = 0xA2, + HID_KEYBOARD_CRSEL_SLASH_PROPS = 0xA3, + HID_KEYBOARD_EXSEL = 0xA4, + // Reserved 0xA5-AF + HID_KEYPAD_00 = 0xB0, + HID_KEYPAD_000 = 0xB1, + HID_THOUSANDS_SEPARATOR = 0xB2, + HID_DECIMAL_SEPARATOR = 0xB3, + HID_CURRENCY_UNIT = 0xB4, + HID_CURRENCY_SUBUNIT = 0xB5, + HID_KEYPAD_LEFT_PAREN = 0xB6, + HID_KEYPAD_RIGHT_PAREN = 0xB7, + HID_KEYPAD_LEFT_CURLY_BRACE = 0xB8, + HID_KEYPAD_RIGHT_CURLY_BRACE = 0xB9, + HID_KEYPAD_TAB = 0xBA, + HID_KEYPAD_BACKSPACE = 0xBB, + HID_KEYPAD_A = 0xBC, + HID_KEYPAD_B = 0xBD, + HID_KEYPAD_C = 0xBE, + HID_KEYPAD_D = 0xBF, + HID_KEYPAD_E = 0xC0, + HID_KEYPAD_F = 0xC1, + HID_KEYPAD_XOR = 0xC2, + HID_KEYPAD_CARAT = 0xC3, + HID_KEYPAD_PERCENT = 0xC4, + HID_KEYPAD_LESS_THAN = 0xC5, + HID_KEYPAD_GREATER_THAN = 0xC6, + HID_KEYPAD_AMPERSAND = 0xC7, + HID_KEYPAD_DOUBLEAMPERSAND = 0xC8, + HID_KEYPAD_PIPE = 0xC9, + HID_KEYPAD_DOUBLEPIPE = 0xCA, + HID_KEYPAD_COLON = 0xCB, + HID_KEYPAD_POUND_SIGN = 0xCC, + HID_KEYPAD_SPACE = 0xCD, + HID_KEYPAD_AT_SIGN = 0xCE, + HID_KEYPAD_EXCLAMATION_POINT = 0xCF, + HID_KEYPAD_MEMORY_STORE = 0xD0, + HID_KEYPAD_MEMORY_RECALL = 0xD1, + HID_KEYPAD_MEMORY_CLEAR = 0xD2, + HID_KEYPAD_MEMORY_ADD = 0xD3, + HID_KEYPAD_MEMORY_SUBTRACT = 0xD4, + HID_KEYPAD_MEMORY_MULTIPLY = 0xD5, + HID_KEYPAD_MEMORY_DIVIDE = 0xD6, + HID_KEYPAD_PLUS_SLASH_MINUS = 0xD7, + HID_KEYPAD_CLEAR = 0xD8, + HID_KEYPAD_CLEAR_ENTRY = 0xD9, + HID_KEYPAD_BINARY = 0xDA, + HID_KEYPAD_OCTAL = 0xDB, + HID_KEYPAD_DECIMAL = 0xDC, + HID_KEYPAD_HEXADECIMAL = 0xDD, + + // 0xDE-0xDF - RESERVED + HID_KEYBOARD_LEFT_CONTROL = 0xE0, + HID_KEYBOARD_LEFT_SHIFT = 0xE1, + HID_KEYBOARD_LEFT_ALT = 0xE2, + HID_KEYBOARD_LEFT_GUI = 0xE3, + HID_KEYBOARD_RIGHT_CONTROL = 0xE4, + HID_KEYBOARD_RIGHT_SHIFT = 0xE5, + HID_KEYBOARD_RIGHT_ALT = 0xE6, + HID_KEYBOARD_RIGHT_GUI = 0xE7, }; // Keyboard Leds diff --git a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h index 707a056edb..f646984658 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h +++ b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h @@ -27,7 +27,6 @@ THE SOFTWARE. #include #include "HID-Settings.h" #include "ImprovedKeylayouts.h" -#include "HID-Tables.h" //TODO typedef union{ // Low level key report: up to 6 keys and shift, ctrl etc at once From 8253a90cc81eafa94b0ebfd0f81a3e34468f7056 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Fri, 23 Oct 2015 22:14:04 +0200 Subject: [PATCH 300/602] Revert "Added Keyboard API templates" This reverts commit d34e2c5bb0878bba09507b2fddbde41a46d15169. If not the right types are used (for example int) this adds some overhead. Nice to have, but better keep it simple --- .../KeyboardioHID/src/HID-APIs/KeyboardAPI.h | 18 ++--- .../src/HID-APIs/KeyboardAPI.hpp | 78 ++++++++++++++++--- 2 files changed, 77 insertions(+), 19 deletions(-) diff --git a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h index f646984658..6a8df49536 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h +++ b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h @@ -47,17 +47,17 @@ class KeyboardAPI : public Print inline void begin(void); inline void end(void); + inline size_t write(uint8_t k); + inline size_t write(KeyboardKeycode k); + inline size_t write(KeyboardModifier k); - template - inline size_t write(TYPE k); - inline virtual size_t write(uint8_t k) override; + inline size_t press(uint8_t k); + inline size_t press(KeyboardKeycode k); + inline size_t press(KeyboardModifier k); - - template - inline size_t press(TYPE k); - - template - inline size_t release(TYPE k); + inline size_t release(uint8_t k); + inline size_t release(KeyboardKeycode k); + inline size_t release(KeyboardModifier k); inline size_t add(uint8_t k); inline size_t add(KeyboardKeycode k); diff --git a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.hpp b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.hpp index 0315f5d7e4..fba968dcdc 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.hpp +++ b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.hpp @@ -36,8 +36,8 @@ void KeyboardAPI::end(void) } -template -size_t KeyboardAPI::write(TYPE k) +// TODO template?? +size_t KeyboardAPI::write(uint8_t k) { // Press and release key (if press was successfull) auto ret = press(k); @@ -48,14 +48,29 @@ size_t KeyboardAPI::write(TYPE k) } -size_t KeyboardAPI::write(uint8_t k) +size_t KeyboardAPI::write(KeyboardKeycode k) { - return write(k); + // Press and release key (if press was successfull) + auto ret = press(k); + if(ret){ + release(k); + } + return ret; +} + + +size_t KeyboardAPI::write(KeyboardModifier k) +{ + // Press and release key (if press was successfull) + auto ret = press(k); + if(ret){ + release(k); + } + return ret; } -template -size_t KeyboardAPI::press(TYPE k) +size_t KeyboardAPI::press(uint8_t k) { // Press key and send report to host auto ret = add(k); @@ -66,11 +81,21 @@ size_t KeyboardAPI::press(TYPE k) } -template -size_t KeyboardAPI::release(TYPE k) +size_t KeyboardAPI::press(KeyboardKeycode k) { - // Release key and send report to host - auto ret = remove(k); + // Press key and send report to host + auto ret = add(k); + if(ret){ + send_now(); + } + return ret; +} + + +size_t KeyboardAPI::press(KeyboardModifier k) +{ + // Press modifier key and send report to host + auto ret = add(k); if(ret){ send_now(); } @@ -126,6 +151,39 @@ size_t KeyboardAPI::add(KeyboardModifier k) } +size_t KeyboardAPI::release(uint8_t k) +{ + // Release key and send report to host + auto ret = remove(k); + if(ret){ + send_now(); + } + return ret; +} + + +size_t KeyboardAPI::release(KeyboardKeycode k) +{ + // Release key and send report to host + auto ret = remove(k); + if(ret){ + send_now(); + } + return ret; +} + + +size_t KeyboardAPI::release(KeyboardModifier k) +{ + // Release modifier key and send report to host + auto ret = remove(k); + if(ret){ + send_now(); + } + return ret; +} + + size_t KeyboardAPI::remove(uint8_t k) { // Ignore invalid input From 6c7859386b1c64644efb61b5ca180e16b2d26d07 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Fri, 23 Oct 2015 22:37:38 +0200 Subject: [PATCH 301/602] Updated Key definitions for Ubuntu usage --- .../src/HID-APIs/ImprovedKeylayouts.h | 210 +++++++++--------- 1 file changed, 105 insertions(+), 105 deletions(-) diff --git a/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h b/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h index 7645ec8344..dcfb625a24 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h +++ b/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h @@ -149,117 +149,117 @@ enum KeyboardKeycode : uint8_t { // Most of the following keys will only work with Linux or not at all. // F13+ keys are mostly used for laptop functions like ECO key. - KEY_POWER = 0x66, + KEY_POWER = 0x66, // PowerOff (Ubuntu) KEY_PAD_EQUALS = 0x67, // Dont confuse with KEYPAD_EQUAL_SIGN - KEY_F13 = 0x68, - KEY_F14 = 0x69, - KEY_F15 = 0x6A, - KEY_F16 = 0x6B, - KEY_F17 = 0x6C, - KEY_F18 = 0x6D, - KEY_F19 = 0x6E, - KEY_F20 = 0x6F, - KEY_F21 = 0x70, - KEY_F22 = 0x71, - KEY_F23 = 0x72, - KEY_F24 = 0x73, - KEY_EXECUTE = 0x74, - KEY_HELP = 0x75, - KEY_MENU = 0x76, - KEY_SELECT = 0x77, - KEY_STOP = 0x78, - KEY_AGAIN = 0x79, - KEY_UNDO = 0x7A, - KEY_CUT = 0x7B, - KEY_COPY = 0x7C, - KEY_PASTE = 0x7D, - KEY_FIND = 0x7E, + KEY_F13 = 0x68, // Tools (Ubunutu) + KEY_F14 = 0x69, // Launch5 (Ubuntu), Laptop ECO button + KEY_F15 = 0x6A, // Launch6 (Ubuntu) + KEY_F16 = 0x6B, // Launch7 (Ubuntu) + KEY_F17 = 0x6C, // Launch8 (Ubuntu) + KEY_F18 = 0x6D, // Launch9 (Ubuntu) + KEY_F19 = 0x6E, // Disabled (Ubuntu) + KEY_F20 = 0x6F, // AudioMicMute (Ubuntu) + KEY_F21 = 0x70, // Touchpad toggle (Ubuntu) + KEY_F22 = 0x71, // TouchpadOn (Ubuntu) + KEY_F23 = 0x72, // TouchpadOff Ubuntu) + KEY_F24 = 0x73, // Disabled (Ubuntu) + KEY_EXECUTE = 0x74, // Open (Ubuntu) + KEY_HELP = 0x75, // Help (Ubuntu) + KEY_MENU = 0x76, // Disabled (Ubuntu) + KEY_SELECT = 0x77, // Disabled (Ubuntu) + KEY_STOP = 0x78, // Cancel (Ubuntu) + KEY_AGAIN = 0x79, // Redo (Ubuntu) + KEY_UNDO = 0x7A, // Undo (Ubuntu) + KEY_CUT = 0x7B, // Cut (Ubuntu) + KEY_COPY = 0x7C, // Copy (Ubuntu) + KEY_PASTE = 0x7D, // Paste (Ubuntu) + KEY_FIND = 0x7E, // Find (Ubuntu) KEY_MUTE = 0x7F, KEY_VOLUME_MUTE = 0x7F, // Alias KEY_VOLUME_UP = 0x80, KEY_VOLUME_DOWN = 0x81, - KEY_LOCKING_CAPS_LOCK = 0x82, - KEY_LOCKING_NUM_LOCK = 0x83, - KEY_LOCKING_SCROLL_LOCK = 0x84, - KEYPAD_COMMA = 0x85, - KEYPAD_EQUAL_SIGN = 0x86, // Dont confuse with KEYPAD_EQUAL - KEY_INTERNATIONAL1 = 0x87, - KEY_INTERNATIONAL2 = 0x88, - KEY_INTERNATIONAL3 = 0x89, - KEY_INTERNATIONAL4 = 0x8A, - KEY_INTERNATIONAL5 = 0x8B, - KEY_INTERNATIONAL6 = 0x8C, - KEY_INTERNATIONAL7 = 0x8D, - KEY_INTERNATIONAL8 = 0x8E, - KEY_INTERNATIONAL9 = 0x8F, - KEY_LANG1 = 0x90, - KEY_LANG2 = 0x91, - KEY_LANG3 = 0x92, - KEY_LANG4 = 0x93, - KEY_LANG5 = 0x94, - KEY_LANG6 = 0x95, - KEY_LANG7 = 0x96, - KEY_LANG8 = 0x97, - KEY_LANG9 = 0x98, - KEY_ALTERNATE_ERASE = 0x99, - KEY_SYSREQ_ATTENTION = 0x9A, - KEY_CANCEL = 0x9B, - KEY_CLEAR = 0x9C, - KEY_PRIOR = 0x9D, - KEY_RETURN = 0x9E, // Do not confuse this with KEY_ENTER - KEY_SEPARATOR = 0x9F, - KEY_OUT = 0xA0, - KEY_OPER = 0xA1, - KEY_CLEAR_AGAIN = 0xA2, - KEY_CRSEL_PROPS = 0xA3, - KEY_EXSEL = 0xA4, + KEY_LOCKING_CAPS_LOCK = 0x82, // Disabled (Ubuntu) + KEY_LOCKING_NUM_LOCK = 0x83, // Disabled (Ubuntu) + KEY_LOCKING_SCROLL_LOCK = 0x84, // Disabled (Ubuntu) + KEYPAD_COMMA = 0x85, // . + KEYPAD_EQUAL_SIGN = 0x86, // Disabled (Ubuntu), Dont confuse with KEYPAD_EQUAL + KEY_INTERNATIONAL1 = 0x87, // Disabled (Ubuntu) + KEY_INTERNATIONAL2 = 0x88, // Hiragana Katakana (Ubuntu) + KEY_INTERNATIONAL3 = 0x89, // Disabled (Ubuntu) + KEY_INTERNATIONAL4 = 0x8A, // Henkan (Ubuntu) + KEY_INTERNATIONAL5 = 0x8B, // Muhenkan (Ubuntu) + KEY_INTERNATIONAL6 = 0x8C, // Disabled (Ubuntu) + KEY_INTERNATIONAL7 = 0x8D, // Disabled (Ubuntu) + KEY_INTERNATIONAL8 = 0x8E, // Disabled (Ubuntu) + KEY_INTERNATIONAL9 = 0x8F, // Disabled (Ubuntu) + KEY_LANG1 = 0x90, // Disabled (Ubuntu) + KEY_LANG2 = 0x91, // Disabled (Ubuntu) + KEY_LANG3 = 0x92, // Katana (Ubuntu) + KEY_LANG4 = 0x93, // Hiragana (Ubuntu) + KEY_LANG5 = 0x94, // Disabled (Ubuntu) + KEY_LANG6 = 0x95, // Disabled (Ubuntu) + KEY_LANG7 = 0x96, // Disabled (Ubuntu) + KEY_LANG8 = 0x97, // Disabled (Ubuntu) + KEY_LANG9 = 0x98, // Disabled (Ubuntu) + KEY_ALTERNATE_ERASE = 0x99, // Disabled (Ubuntu) + KEY_SYSREQ_ATTENTION = 0x9A, // Disabled (Ubuntu) + KEY_CANCEL = 0x9B, // Disabled (Ubuntu) + KEY_CLEAR = 0x9C, // Delete (Ubuntu) + KEY_PRIOR = 0x9D, // Disabled (Ubuntu) + KEY_RETURN = 0x9E, // Disabled (Ubuntu), Do not confuse this with KEY_ENTER + KEY_SEPARATOR = 0x9F, // Disabled (Ubuntu) + KEY_OUT = 0xA0, // Disabled (Ubuntu) + KEY_OPER = 0xA1, // Disabled (Ubuntu) + KEY_CLEAR_AGAIN = 0xA2, // Disabled (Ubuntu) + KEY_CRSEL_PROPS = 0xA3, // Disabled (Ubuntu) + KEY_EXSEL = 0xA4, // Disabled (Ubuntu) - KEY_PAD_00 = 0xB0, - KEY_PAD_000 = 0xB1, - KEY_THOUSANDS_SEPARATOR = 0xB2, - KEY_DECIMAL_SEPARATOR = 0xB3, - KEY_CURRENCY_UNIT = 0xB4, - KEY_CURRENCY_SUB_UNIT = 0xB5, - KEYPAD_LEFT_BRACE = 0xB6, - KEYPAD_RIGHT_BRACE = 0xB7, - KEYPAD_LEFT_CURLY_BRACE = 0xB8, - KEYPAD_RIGHT_CURLY_BRACE = 0xB9, - KEYPAD_TAB = 0xBA, - KEYPAD_BACKSPACE = 0xBB, - KEYPAD_A = 0xBC, - KEYPAD_B = 0xBD, - KEYPAD_C = 0xBE, - KEYPAD_D = 0xBF, - KEYPAD_E = 0xC0, - KEYPAD_F = 0xC1, - KEYPAD_XOR = 0xC2, - KEYPAD_CARET = 0xC3, - KEYPAD_PERCENT = 0xC4, - KEYPAD_LEFT_ANGLE = 0xC5, - KEYPAD_RIGHT_ANGLE = 0xC6, - KEYPAD_AMPERSAND = 0xC7, - KEYPAD_DOUBLE_AMPERSAND = 0xC8, - KEYPAD_PIPE = 0xC9, - KEYPAD_DOUBLE_PIPE = 0xCA, - KEYPAD_COLON = 0xCB, - KEYPAD_POUND = 0xCC, - KEYPAD_SPACE = 0xCD, - KEYPAD_AT = 0xCE, - KEYPAD_EXCLAMATION = 0xCF, - KEYPAD_MEMORY_STORE = 0xD0, - KEYPAD_MEMORY_RECALL = 0xD1, - KEYPAD_MEMORY_CLEAR = 0xD2, - KEYPAD_MEMORY_ADD = 0xD3, - KEYPAD_MEMORY_SUBTRACT = 0xD4, - KEYPAD_MEMORY_MULTIPLY = 0xD5, - KEYPAD_MEMORY_DIVIDE = 0xD6, - KEYPAD_PLUS_MINUS = 0xD7, - KEYPAD_CLEAR = 0xD8, - KEYPAD_CLEAR_ENTRY = 0xD9, - KEYPAD_BINARY = 0xDA, - KEYPAD_OCTAL = 0xDB, - KEYPAD_DECIMAL = 0xDC, - KEYPAD_HEXADECIMAL = 0xDD, + KEY_PAD_00 = 0xB0, // Disabled (Ubuntu) + KEY_PAD_000 = 0xB1, // Disabled (Ubuntu) + KEY_THOUSANDS_SEPARATOR = 0xB2, // Disabled (Ubuntu) + KEY_DECIMAL_SEPARATOR = 0xB3, // Disabled (Ubuntu) + KEY_CURRENCY_UNIT = 0xB4, // Disabled (Ubuntu) + KEY_CURRENCY_SUB_UNIT = 0xB5, // Disabled (Ubuntu) + KEYPAD_LEFT_BRACE = 0xB6, // ( + KEYPAD_RIGHT_BRACE = 0xB7, // ) + KEYPAD_LEFT_CURLY_BRACE = 0xB8, // Disabled (Ubuntu) + KEYPAD_RIGHT_CURLY_BRACE = 0xB9, // Disabled (Ubuntu) + KEYPAD_TAB = 0xBA, // Disabled (Ubuntu) + KEYPAD_BACKSPACE = 0xBB, // Disabled (Ubuntu) + KEYPAD_A = 0xBC, // Disabled (Ubuntu) + KEYPAD_B = 0xBD, // Disabled (Ubuntu) + KEYPAD_C = 0xBE, // Disabled (Ubuntu) + KEYPAD_D = 0xBF, // Disabled (Ubuntu) + KEYPAD_E = 0xC0, // Disabled (Ubuntu) + KEYPAD_F = 0xC1, // Disabled (Ubuntu) + KEYPAD_XOR = 0xC2, // Disabled (Ubuntu) + KEYPAD_CARET = 0xC3, // Disabled (Ubuntu) + KEYPAD_PERCENT = 0xC4, // Disabled (Ubuntu) + KEYPAD_LESS_THAN = 0xC5, // Disabled (Ubuntu) + KEYPAD_GREATER_THAN = 0xC6, // Disabled (Ubuntu) + KEYPAD_AMPERSAND = 0xC7, // Disabled (Ubuntu) + KEYPAD_DOUBLEAMPERSAND = 0xC8, // Disabled (Ubuntu) + KEYPAD_PIPE = 0xC9, // Disabled (Ubuntu) + KEYPAD_DOUBLEPIPE = 0xCA, // Disabled (Ubuntu) + KEYPAD_COLON = 0xCB, // Disabled (Ubuntu) + KEYPAD_POUND_SIGN = 0xCC, // Disabled (Ubuntu) + KEYPAD_SPACE = 0xCD, // Disabled (Ubuntu) + KEYPAD_AT_SIGN = 0xCE, // Disabled (Ubuntu) + KEYPAD_EXCLAMATION_POINT = 0xCF, // Disabled (Ubuntu) + KEYPAD_MEMORY_STORE = 0xD0, // Disabled (Ubuntu) + KEYPAD_MEMORY_RECALL = 0xD1, // Disabled (Ubuntu) + KEYPAD_MEMORY_CLEAR = 0xD2, // Disabled (Ubuntu) + KEYPAD_MEMORY_ADD = 0xD3, // Disabled (Ubuntu) + KEYPAD_MEMORY_SUBTRACT = 0xD4, // Disabled (Ubuntu) + KEYPAD_MEMORY_MULTIPLY = 0xD5, // Disabled (Ubuntu) + KEYPAD_MEMORY_DIVIDE = 0xD6, // Disabled (Ubuntu) + KEYPAD_PLUS_MINUS = 0xD7, // Disabled (Ubuntu) + KEYPAD_CLEAR = 0xD8, // Delete (Ubuntu) + KEYPAD_CLEAR_ENTRY = 0xD9, // Disabled (Ubuntu) + KEYPAD_BINARY = 0xDA, // Disabled (Ubuntu) + KEYPAD_OCTAL = 0xDB, // Disabled (Ubuntu) + KEYPAD_DECIMAL = 0xDC, // Disabled (Ubuntu) + KEYPAD_HEXADECIMAL = 0xDD, // Disabled (Ubuntu) // Used in KeyboardModifier enum directly //KEY_LEFT_CTRL = 0xE0, From 014e4e3394d23d0dcb84ae2fe8fe59303de66d4e Mon Sep 17 00:00:00 2001 From: NicoHood Date: Fri, 23 Oct 2015 22:59:11 +0200 Subject: [PATCH 302/602] Removed wrong statement --- plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h b/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h index dcfb625a24..7574a8d638 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h +++ b/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h @@ -152,7 +152,7 @@ enum KeyboardKeycode : uint8_t { KEY_POWER = 0x66, // PowerOff (Ubuntu) KEY_PAD_EQUALS = 0x67, // Dont confuse with KEYPAD_EQUAL_SIGN KEY_F13 = 0x68, // Tools (Ubunutu) - KEY_F14 = 0x69, // Launch5 (Ubuntu), Laptop ECO button + KEY_F14 = 0x69, // Launch5 (Ubuntu) KEY_F15 = 0x6A, // Launch6 (Ubuntu) KEY_F16 = 0x6B, // Launch7 (Ubuntu) KEY_F17 = 0x6C, // Launch8 (Ubuntu) From b4d37eeac9b69447e06e583a61914ae0223acb75 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 24 Oct 2015 10:16:00 +0200 Subject: [PATCH 303/602] Updated Keyboard examples --- .../examples/BootKeyboard/BootKeyboard.ino | 2 +- .../ImprovedKeyboard/ImprovedKeyboard.ino | 48 +++++++++++++++++++ .../examples/NKROKeyboard/NKROKeyboard.ino | 2 +- 3 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 plugins/KeyboardioHID/examples/ImprovedKeyboard/ImprovedKeyboard.ino diff --git a/plugins/KeyboardioHID/examples/BootKeyboard/BootKeyboard.ino b/plugins/KeyboardioHID/examples/BootKeyboard/BootKeyboard.ino index 4283132fec..bf0be40ccc 100644 --- a/plugins/KeyboardioHID/examples/BootKeyboard/BootKeyboard.ino +++ b/plugins/KeyboardioHID/examples/BootKeyboard/BootKeyboard.ino @@ -8,7 +8,7 @@ Led indicats if we are in bios. See HID Project documentation for more information. - https://github.com/NicoHood/HID/wiki/Keyboard-API + https://github.com/NicoHood/HID/wiki/Keyboard-API#boot-keyboard */ #include "HID-Project.h" diff --git a/plugins/KeyboardioHID/examples/ImprovedKeyboard/ImprovedKeyboard.ino b/plugins/KeyboardioHID/examples/ImprovedKeyboard/ImprovedKeyboard.ino new file mode 100644 index 0000000000..23fb0faacd --- /dev/null +++ b/plugins/KeyboardioHID/examples/ImprovedKeyboard/ImprovedKeyboard.ino @@ -0,0 +1,48 @@ +/* + Copyright (c) 2014-2015 NicoHood + See the readme for credit to other people. + + Improved Keyboard example + + Shows how to use the new Keyboard API. + + See HID Project documentation for more information. + https://github.com/NicoHood/HID/wiki/Keyboard-API#improved-keyboard +*/ + +#include "HID-Project.h" + +const int pinLed = LED_BUILTIN; +const int pinButton = 2; + +void setup() { + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); + + // Sends a clean report to the host. This is important on any Arduino type. + Keyboard.begin(); +} + + +void loop() { + // Trigger caps lock manually via button + if (!digitalRead(pinButton)) { + digitalWrite(pinLed, HIGH); + + // Use the default print functions + Keyboard.println("Hello World!"); + + // Press a single character, special non ascii characters wont work. + //Keyboard.write('a'); + + // Write single keys, do not use a number here! + //Keyboard.write(KEY_ENTER); + + // If you really wish to press a RAW keycode without the name use this: + //Keyboard.write(KeyboardKeycode(40)); + + // Simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } +} diff --git a/plugins/KeyboardioHID/examples/NKROKeyboard/NKROKeyboard.ino b/plugins/KeyboardioHID/examples/NKROKeyboard/NKROKeyboard.ino index 16cd17f189..aae4d13273 100644 --- a/plugins/KeyboardioHID/examples/NKROKeyboard/NKROKeyboard.ino +++ b/plugins/KeyboardioHID/examples/NKROKeyboard/NKROKeyboard.ino @@ -11,7 +11,7 @@ You may also use SingleNKROKeyboard to enable a single report NKROKeyboard. See HID Project documentation for more information. - https://github.com/NicoHood/HID/wiki/Keyboard-API + https://github.com/NicoHood/HID/wiki/Keyboard-API#nkro-keyboard */ #include "HID-Project.h" From d9977c5e00add95672e5c361170ce61f5b970f7e Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 24 Oct 2015 10:16:19 +0200 Subject: [PATCH 304/602] Moved Consumer keys inside enum --- .../KeyboardioHID/src/HID-APIs/ConsumerAPI.h | 462 ++++++++++++++++-- .../src/HID-APIs/ConsumerAPI.hpp | 10 +- .../KeyboardioHID/src/HID-APIs/HID-Tables.h | 380 -------------- 3 files changed, 430 insertions(+), 422 deletions(-) diff --git a/plugins/KeyboardioHID/src/HID-APIs/ConsumerAPI.h b/plugins/KeyboardioHID/src/HID-APIs/ConsumerAPI.h index 50c6a5b1fe..66f65a37d0 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/ConsumerAPI.h +++ b/plugins/KeyboardioHID/src/HID-APIs/ConsumerAPI.h @@ -27,35 +27,423 @@ THE SOFTWARE. #include #include "HID-Settings.h" -// Media key definitions, see official USB docs for more -#define MEDIA_FAST_FORWARD 0xB3 -#define MEDIA_REWIND 0xB4 -#define MEDIA_NEXT 0xB5 -#define MEDIA_PREVIOUS 0xB6 -#define MEDIA_PREV MEDIA_PREVIOUS -#define MEDIA_STOP 0xB7 -#define MEDIA_PLAY_PAUSE 0xCD - -#define MEDIA_VOLUME_MUTE 0xE2 -#define MEDIA_VOLUME_UP 0xE9 -#define MEDIA_VOLUME_DOWN 0xEA -#define MEDIA_VOL_MUTE MEDIA_VOLUME_MUTE -#define MEDIA_VOL_UP MEDIA_VOLUME_UP -#define MEDIA_VOL_DOWN MEDIA_VOLUME_DOWN - -#define CONSUMER_SCREENSAVER 0x19e - -#define CONSUMER_PROGRAMMABLE_BUTTON_CONFIGURATION 0x182 -#define CONSUMER_CONTROL_CONFIGURATION 0x183 -#define CONSUMER_EMAIL_READER 0x18A -#define CONSUMER_CALCULATOR 0x192 -#define CONSUMER_EXPLORER 0x194 - -#define CONSUMER_BROWSER_HOME 0x223 -#define CONSUMER_BROWSER_BACK 0x224 -#define CONSUMER_BROWSER_FORWARD 0x225 -#define CONSUMER_BROWSER_REFRESH 0x227 -#define CONSUMER_BROWSER_BOOKMARKS 0x22A +enum ConsumerKeycode : uint16_t { + // Some keys might only work with linux + CONSUMER_POWER = 0x30, + CONSUMER_SLEEP = 0x32, + + MEDIA_FAST_FORWARD = 0xB3, + MEDIA_REWIND = 0xB4, + MEDIA_NEXT = 0xB5, + MEDIA_PREVIOUS = 0xB6, + MEDIA_PREV = 0xB6, // Alias + MEDIA_STOP = 0xB7, + MEDIA_PLAY_PAUSE = 0xCD, + + MEDIA_VOLUME_MUTE = 0xE2, + MEDIA_VOL_MUTE = 0xE2, // Alias + MEDIA_VOLUME_UP = 0xE9, + MEDIA_VOL_UP = 0xE9, // Alias + MEDIA_VOLUME_DOWN = 0xEA, + MEDIA_VOL_DOWN = 0xEA, // Alias + + CONSUMER_SCREENSAVER = 0x19e, + + CONSUMER_PROGRAMMABLE_BUTTON_CONFIGURATION = 0x182, + CONSUMER_CONTROL_CONFIGURATION = 0x183, + CONSUMER_EMAIL_READER = 0x18A, + CONSUMER_CALCULATOR = 0x192, + CONSUMER_EXPLORER = 0x194, + + CONSUMER_BROWSER_HOME = 0x223, + CONSUMER_BROWSER_BACK = 0x224, + CONSUMER_BROWSER_FORWARD = 0x225, + CONSUMER_BROWSER_REFRESH = 0x227, + CONSUMER_BROWSER_BOOKMARKS = 0x22A, + + + // Consumer_Page_(0x0C) 0x15 + HID_CONSUMER_UNASSIGNED = 0x00, + HID_CONSUMER_NUMERIC_KEY_PAD = 0x02, // HID type NARY + HID_CONSUMER_PROGRAMMABLE_BUTTONS = 0x03, // HID type NARY + HID_CONSUMER_MICROPHONE_CA = 0x04, + HID_CONSUMER_HEADPHONE_CA = 0x05, + HID_CONSUMER_GRAPHIC_EQUALIZER_CA = 0x06, + // Reserved = 0x07-1F + HID_CONSUMER_PLUS_10 = 0x20, // HID type OSC + HID_CONSUMER_PLUS_100 = 0x21, // HID type OSC + HID_CONSUMER_AM_SLASH_PM = 0x22, // HID type OSC + // Reserved = 0x23-3F + HID_CONSUMER_POWER = 0x30, // HID type OOC + HID_CONSUMER_RESET = 0x31, // HID type OSC + HID_CONSUMER_SLEEP = 0x32, // HID type OSC + HID_CONSUMER_SLEEP_AFTER = 0x33, // HID type OSC + HID_CONSUMER_SLEEP_MODE = 0x34, // HID type RTC + HID_CONSUMER_ILLUMINATION = 0x35, // HID type OOC + HID_CONSUMER_FUNCTION_BUTTONS = 0x36, // HID type NARY + // Reserved = 0x37-3F + HID_CONSUMER_MENU = 0x40, // HID type OOC + HID_CONSUMER_MENU_PICK = 0x41, // HID type OSC + HID_CONSUMER_MENU_UP = 0x42, // HID type OSC + HID_CONSUMER_MENU_DOWN = 0x43, // HID type OSC + HID_CONSUMER_MENU_LEFT = 0x44, // HID type OSC + HID_CONSUMER_MENU_RIGHT = 0x45, // HID type OSC + HID_CONSUMER_MENU_ESCAPE = 0x46, // HID type OSC + HID_CONSUMER_MENU_VALUE_INCREASE = 0x47, // HID type OSC + HID_CONSUMER_MENU_VALUE_DECREASE = 0x48, // HID type OSC + // Reserved 0x49-5F + HID_CONSUMER_DATA_ON_SCREEN = 0x60, // HID type OOC + HID_CONSUMER_CLOSED_CAPTION = 0x61, // HID type OOC + HID_CONSUMER_CLOSED_CAPTION_SELECT = 0x62, // HID type OSC + HID_CONSUMER_VCR_SLASH_TV = 0x63, // HID type OOC + HID_CONSUMER_BROADCAST_MODE = 0x64, // HID type OSC + HID_CONSUMER_SNAPSHOT = 0x65, // HID type OSC + HID_CONSUMER_STILL = 0x66, // HID type OSC + // Reserved 0x67-7F + HID_CONSUMER_SELECTION = 0x80, // HID type NARY + HID_CONSUMER_ASSIGN_SELECTION = 0x81, // HID type OSC + HID_CONSUMER_MODE_STEP = 0x82, // HID type OSC + HID_CONSUMER_RECALL_LAST = 0x83, // HID type OSC + HID_CONSUMER_ENTER_CHANNEL = 0x84, // HID type OSC + HID_CONSUMER_ORDER_MOVIE = 0x85, // HID type OSC + HID_CONSUMER_CHANNEL = 0x86, // HID type LC + HID_CONSUMER_MEDIA_SELECTION = 0x87, // HID type NARY + HID_CONSUMER_MEDIA_SELECT_COMPUTER = 0x88, // HID type SEL + HID_CONSUMER_MEDIA_SELECT_TV = 0x89, // HID type SEL + HID_CONSUMER_MEDIA_SELECT_WWW = 0x8A, // HID type SEL + HID_CONSUMER_MEDIA_SELECT_DVD = 0x8B, // HID type SEL + HID_CONSUMER_MEDIA_SELECT_TELEPHONE = 0x8C, // HID type SEL + HID_CONSUMER_MEDIA_SELECT_PROGRAM_GUIDE = 0x8D, // HID type SEL + HID_CONSUMER_MEDIA_SELECT_VIDEO_PHONE = 0x8E, // HID type SEL + HID_CONSUMER_MEDIA_SELECT_GAMES = 0x8F, // HID type SEL + HID_CONSUMER_MEDIA_SELECT_MESSAGES = 0x90, // HID type SEL + HID_CONSUMER_MEDIA_SELECT_CD = 0x91, // HID type SEL + HID_CONSUMER_MEDIA_SELECT_VCR = 0x92, // HID type SEL + HID_CONSUMER_MEDIA_SELECT_TUNER = 0x93, // HID type SEL + HID_CONSUMER_QUIT = 0x94, // HID type OSC + HID_CONSUMER_HELP = 0x95, // HID type OOC + HID_CONSUMER_MEDIA_SELECT_TAPE = 0x96, // HID type SEL + HID_CONSUMER_MEDIA_SELECT_CABLE = 0x97, // HID type SEL + HID_CONSUMER_MEDIA_SELECT_SATELLITE = 0x98, // HID type SEL + HID_CONSUMER_MEDIA_SELECT_SECURITY = 0x99, // HID type SEL + HID_CONSUMER_MEDIA_SELECT_HOME = 0x9A, // HID type SEL + HID_CONSUMER_MEDIA_SELECT_CALL = 0x9B, // HID type SEL + HID_CONSUMER_CHANNEL_INCREMENT = 0x9C, // HID type OSC + HID_CONSUMER_CHANNEL_DECREMENT = 0x9D, // HID type OSC + HID_CONSUMER_MEDIA_SELECT_SAP = 0x9E, // HID type SEL + // Reserved 0x9F + HID_CONSUMER_VCR_PLUS = 0xA0, // HID type OSC + HID_CONSUMER_ONCE = 0xA1, // HID type OSC + HID_CONSUMER_DAILY = 0xA2, // HID type OSC + HID_CONSUMER_WEEKLY = 0xA3, // HID type OSC + HID_CONSUMER_MONTHLY = 0xA4, // HID type OSC + // Reserved 0xA5-AF + HID_CONSUMER_PLAY = 0xB0, // HID type OOC + HID_CONSUMER_PAUSE = 0xB1, // HID type OOC + HID_CONSUMER_RECORD = 0xB2, // HID type OOC + HID_CONSUMER_FAST_FORWARD = 0xB3, // HID type OOC + HID_CONSUMER_REWIND = 0xB4, // HID type OOC + HID_CONSUMER_SCAN_NEXT_TRACK = 0xB5, // HID type OSC + HID_CONSUMER_SCAN_PREVIOUS_TRACK = 0xB6, // HID type OSC + HID_CONSUMER_STOP = 0xB7, // HID type OSC + HID_CONSUMER_EJECT = 0xB8, // HID type OSC + HID_CONSUMER_RANDOM_PLAY = 0xB9, // HID type OOC + HID_CONSUMER_SELECT_DISC = 0xBA, // HID type NARY + HID_CONSUMER_ENTER_DISC_MC = 0xBB, + HID_CONSUMER_REPEAT = 0xBC, // HID type OSC + HID_CONSUMER_TRACKING = 0xBD, // HID type LC + HID_CONSUMER_TRACK_NORMAL = 0xBE, // HID type OSC + HID_CONSUMER_SLOW_TRACKING = 0xBF, // HID type LC + HID_CONSUMER_FRAME_FORWARD = 0xC0, // HID type RTC + HID_CONSUMER_FRAME_BACK = 0xC1, // HID type RTC + HID_CONSUMER_MARK = 0xC2, // HID type OSC + HID_CONSUMER_CLEAR_MARK = 0xC3, // HID type OSC + HID_CONSUMER_REPEAT_FROM_MARK = 0xC4, // HID type OOC + HID_CONSUMER_RETURN_TO_MARK = 0xC5, // HID type OSC + HID_CONSUMER_SEARCH_MARK_FORWARD = 0xC6, // HID type OSC + HID_CONSUMER_SEARCH_MARK_BACKWARDS = 0xC7, // HID type OSC + HID_CONSUMER_COUNTER_RESET = 0xC8, // HID type OSC + HID_CONSUMER_SHOW_COUNTER = 0xC9, // HID type OSC + HID_CONSUMER_TRACKING_INCREMENT = 0xCA, // HID type RTC + HID_CONSUMER_TRACKING_DECREMENT = 0xCB, // HID type RTC + HID_CONSUMER_STOP_SLASH_EJECT = 0xCC, // HID type OSC + HID_CONSUMER_PLAY_SLASH_PAUSE = 0xCD, // HID type OSC + HID_CONSUMER_PLAY_SLASH_SKIP = 0xCE, // HID type OSC + // Reserved 0xCF-DF + HID_CONSUMER_VOLUME = 0xE0, // HID type LC + HID_CONSUMER_BALANCE = 0xE1, // HID type LC + HID_CONSUMER_MUTE = 0xE2, // HID type OOC + HID_CONSUMER_BASS = 0xE3, // HID type LC + HID_CONSUMER_TREBLE = 0xE4, // HID type LC + HID_CONSUMER_BASS_BOOST = 0xE5, // HID type OOC + HID_CONSUMER_SURROUND_MODE = 0xE6, // HID type OSC + HID_CONSUMER_LOUDNESS = 0xE7, // HID type OOC + HID_CONSUMER_MPX = 0xE8, // HID type OOC + HID_CONSUMER_VOLUME_INCREMENT = 0xE9, // HID type RTC + HID_CONSUMER_VOLUME_DECREMENT = 0xEA, // HID type RTC + // Reserved 0xEB-EF + HID_CONSUMER_SPEED_SELECT = 0xF0, // HID type OSC + HID_CONSUMER_PLAYBACK_SPEED = 0xF1, // HID type NARY + HID_CONSUMER_STANDARD_PLAY = 0xF2, // HID type SEL + HID_CONSUMER_LONG_PLAY = 0xF3, // HID type SEL + HID_CONSUMER_EXTENDED_PLAY = 0xF4, // HID type SEL + HID_CONSUMER_SLOW = 0xF5, // HID type OSC + // Reserved 0xF6-FF + HID_CONSUMER_FAN_ENABLE = 0x100, // HID type OOC + HID_CONSUMER_FAN_SPEED = 0x101, // HID type LC + HID_CONSUMER_LIGHT_ENABLE = 0x102, // HID type OOC + HID_CONSUMER_LIGHT_ILLUMINATION_LEVEL = 0x103, // HID type LC + HID_CONSUMER_CLIMATE_CONTROL_ENABLE = 0x104, // HID type OOC + HID_CONSUMER_ROOM_TEMPERATURE = 0x105, // HID type LC + HID_CONSUMER_SECURITY_ENABLE = 0x106, // HID type OOC + HID_CONSUMER_FIRE_ALARM = 0x107, // HID type OSC + HID_CONSUMER_POLICE_ALARM = 0x108, // HID type OSC + HID_CONSUMER_PROXIMITY = 0x109, // HID type LC + HID_CONSUMER_MOTION = 0x10A, // HID type OSC + HID_CONSUMER_DURESS_ALARM = 0x10B, // HID type OSC + HID_CONSUMER_HOLDUP_ALARM = 0x10C, // HID type OSC + HID_CONSUMER_MEDICAL_ALARM = 0x10D, // HID type OSC + // Reserved 0x10E-14F + HID_CONSUMER_BALANCE_RIGHT = 0x150, // HID type RTC + HID_CONSUMER_BALANCE_LEFT = 0x151, // HID type RTC + HID_CONSUMER_BASS_INCREMENT = 0x152, // HID type RTC + HID_CONSUMER_BASS_DECREMENT = 0x153, // HID type RTC + HID_CONSUMER_TREBLE_INCREMENT = 0x154, // HID type RTC + HID_CONSUMER_TREBLE_DECREMENT = 0x155, // HID type RTC + // Reserved 0x156-15F + HID_CONSUMER_SPEAKER_SYSTEM = 0x160, // HID type CL + HID_CONSUMER_CHANNEL_LEFT = 0x161, // HID type CL + HID_CONSUMER_CHANNEL_RIGHT = 0x162, // HID type CL + HID_CONSUMER_CHANNEL_CENTER = 0x163, // HID type CL + HID_CONSUMER_CHANNEL_FRONT = 0x164, // HID type CL + HID_CONSUMER_CHANNEL_CENTER_FRONT = 0x165, // HID type CL + HID_CONSUMER_CHANNEL_SIDE = 0x166, // HID type CL + HID_CONSUMER_CHANNEL_SURROUND = 0x167, // HID type CL + HID_CONSUMER_CHANNEL_LOW_FREQUENCY_ENHANCEMENT = 0x168, // HID type CL + HID_CONSUMER_CHANNEL_TOP = 0x169, // HID type CL + HID_CONSUMER_CHANNEL_UNKNOWN = 0x16A, // HID type CL + // Reserved 0x16B-16F + HID_CONSUMER_SUB_CHANNEL = 0x170, // HID type LC + HID_CONSUMER_SUB_CHANNEL_INCREMENT = 0x171, // HID type OSC + HID_CONSUMER_SUB_CHANNEL_DECREMENT = 0x172, // HID type OSC + HID_CONSUMER_ALTERNATE_AUDIO_INCREMENT = 0x173, // HID type OSC + HID_CONSUMER_ALTERNATE_AUDIO_DECREMENT = 0x174, // HID type OSC + // Reserved 0x175-17F + HID_CONSUMER_APPLICATION_LAUNCH_BUTTONS = 0x180, // HID type NARY + HID_CONSUMER_AL_LAUNCH_BUTTON_CONFIGURATION_TOOL = 0x181, // HID type SEL + HID_CONSUMER_AL_PROGRAMMABLE_BUTTON_CONFIGURATION = 0x182, // HID type SEL + HID_CONSUMER_AL_CONSUMER_CONTROL_CONFIGURATION = 0x183, // HID type SEL + HID_CONSUMER_AL_WORD_PROCESSOR = 0x184, // HID type SEL + HID_CONSUMER_AL_TEXT_EDITOR = 0x185, // HID type SEL + HID_CONSUMER_AL_SPREADSHEET = 0x186, // HID type SEL + HID_CONSUMER_AL_GRAPHICS_EDITOR = 0x187, // HID type SEL + HID_CONSUMER_AL_PRESENTATION_APP = 0x188, // HID type SEL + HID_CONSUMER_AL_DATABASE_APP = 0x189, // HID type SEL + HID_CONSUMER_AL_EMAIL_READER = 0x18A, // HID type SEL + HID_CONSUMER_AL_NEWSREADER = 0x18B, // HID type SEL + HID_CONSUMER_AL_VOICEMAIL = 0x18C, // HID type SEL + HID_CONSUMER_AL_CONTACTS_SLASH_ADDRESS_BOOK = 0x18D, // HID type SEL + HID_CONSUMER_AL_CALENDAR_SLASH_SCHEDULE = 0x18E, // HID type SEL + HID_CONSUMER_AL_TASK_SLASH_PROJECT_MANAGER = 0x18F, // HID type SEL + HID_CONSUMER_AL_LOG_SLASH_JOURNAL_SLASH_TIMECARD = 0x190, // HID type SEL + HID_CONSUMER_AL_CHECKBOOK_SLASH_FINANCE = 0x191, // HID type SEL + HID_CONSUMER_AL_CALCULATOR = 0x192, // HID type SEL + HID_CONSUMER_AL_A_SLASH_V_CAPTURE_SLASH_PLAYBACK = 0x193, // HID type SEL + HID_CONSUMER_AL_LOCAL_MACHINE_BROWSER = 0x194, // HID type SEL + HID_CONSUMER_AL_LAN_SLASH_WAN_BROWSER = 0x195, // HID type SEL + HID_CONSUMER_AL_INTERNET_BROWSER = 0x196, // HID type SEL + HID_CONSUMER_AL_REMOTE_NETWORKING_SLASH_ISP_CONNECT = 0x197, // HID type SEL + HID_CONSUMER_AL_NETWORK_CONFERENCE = 0x198, // HID type SEL + HID_CONSUMER_AL_NETWORK_CHAT = 0x199, // HID type SEL + HID_CONSUMER_AL_TELEPHONY_SLASH_DIALER = 0x19A, // HID type SEL + HID_CONSUMER_AL_LOGON = 0x19B, // HID type SEL + HID_CONSUMER_AL_LOGOFF = 0x19C, // HID type SEL + HID_CONSUMER_AL_LOGON_SLASH_LOGOFF = 0x19D, // HID type SEL + HID_CONSUMER_AL_TERMINAL_LOCK_SLASH_SCREENSAVER = 0x19E, // HID type SEL + HID_CONSUMER_AL_CONTROL_PANEL = 0x19F, // HID type SEL + HID_CONSUMER_AL_COMMAND_LINE_PROCESSOR_SLASH_RUN = 0x1A0, // HID type SEL + HID_CONSUMER_AL_PROCESS_SLASH_TASK_MANAGER = 0x1A1, // HID type SEL + HID_CONSUMER_AL_SELECT_TASK_SLASH_APPLICATION = 0x1A2, // HID type SEL + HID_CONSUMER_AL_NEXT_TASK_SLASH_APPLICATION = 0x1A3, // HID type SEL + HID_CONSUMER_AL_PREVIOUS_TASK_SLASH_APPLICATION = 0x1A4, // HID type SEL + HID_CONSUMER_AL_PREEMPTIVE_HALT_TASK_SLASH_APPLICATION = 0x1A5, // HID type SEL + HID_CONSUMER_AL_INTEGRATED_HELP_CENTER = 0x1A6, // HID type SEL + HID_CONSUMER_AL_DOCUMENTS = 0x1A7, // HID type SEL + HID_CONSUMER_AL_THESAURUS = 0x1A8, // HID type SEL + HID_CONSUMER_AL_DICTIONARY = 0x1A9, // HID type SEL + HID_CONSUMER_AL_DESKTOP = 0x1AA, // HID type SEL + HID_CONSUMER_AL_SPELL_CHECK = 0x1AB, // HID type SEL + HID_CONSUMER_AL_GRAMMAR_CHECK = 0x1AC, // HID type SEL + HID_CONSUMER_AL_WIRELESS_STATUS = 0x1AD, // HID type SEL + HID_CONSUMER_AL_KEYBOARD_LAYOUT = 0x1AE, // HID type SEL + HID_CONSUMER_AL_VIRUS_PROTECTION = 0x1AF, // HID type SEL + HID_CONSUMER_AL_ENCRYPTION = 0x1B0, // HID type SEL + HID_CONSUMER_AL_SCREEN_SAVER = 0x1B1, // HID type SEL + HID_CONSUMER_AL_ALARMS = 0x1B2, // HID type SEL + HID_CONSUMER_AL_CLOCK = 0x1B3, // HID type SEL + HID_CONSUMER_AL_FILE_BROWSER = 0x1B4, // HID type SEL + HID_CONSUMER_AL_POWER_STATUS = 0x1B5, // HID type SEL + HID_CONSUMER_AL_IMAGE_BROWSER = 0x1B6, // HID type SEL + HID_CONSUMER_AL_AUDIO_BROWSER = 0x1B7, // HID type SEL + HID_CONSUMER_AL_MOVIE_BROWSER = 0x1B8, // HID type SEL + HID_CONSUMER_AL_DIGITAL_RIGHTS_MANAGER = 0x1B9, // HID type SEL + HID_CONSUMER_AL_DIGITAL_WALLET = 0x1BA, // HID type SEL + // _Reserved 0x1BB + HID_CONSUMER_AL_INSTANT_MESSAGING = 0x1BC, // HID type SEL + HID_CONSUMER_AL_OEM_FEATURES_SLASH__TIPS_SLASH_TUTORIAL_BROWSER = 0x1BD, // HID type SEL + HID_CONSUMER_AL_OEM_HELP = 0x1BE, // HID type SEL + HID_CONSUMER_AL_ONLINE_COMMUNITY = 0x1BF, // HID type SEL + HID_CONSUMER_AL_ENTERTAINMENT_CONTENT_BROWSER = 0x1C0, // HID type SEL + HID_CONSUMER_AL_ONLINE_SHOPPING_BROWSER = 0x1C1, // HID type SEL + HID_CONSUMER_AL_SMARTCARD_INFORMATION_SLASH_HELP = 0x1C2, // HID type SEL + HID_CONSUMER_AL_MARKET_MONITOR_SLASH_FINANCE_BROWSER = 0x1C3, // HID type SEL + HID_CONSUMER_AL_CUSTOMIZED_CORPORATE_NEWS_BROWSER = 0x1C4, // HID type SEL + HID_CONSUMER_AL_ONLINE_ACTIVITY_BROWSER = 0x1C5, // HID type SEL + HID_CONSUMER_AL_RESEARCH_SLASH_SEARCH_BROWSER = 0x1C6, // HID type SEL + HID_CONSUMER_AL_AUDIO_PLAYER = 0x1C7, // HID type SEL + // Reserved 0x1C8-1FF + HID_CONSUMER_GENERIC_GUI_APPLICATION_CONTROLS = 0x200, // HID type NARY + HID_CONSUMER_AC_NEW = 0x201, // HID type SEL + HID_CONSUMER_AC_OPEN = 0x202, // HID type SEL + HID_CONSUMER_AC_CLOSE = 0x203, // HID type SEL + HID_CONSUMER_AC_EXIT = 0x204, // HID type SEL + HID_CONSUMER_AC_MAXIMIZE = 0x205, // HID type SEL + HID_CONSUMER_AC_MINIMIZE = 0x206, // HID type SEL + HID_CONSUMER_AC_SAVE = 0x207, // HID type SEL + HID_CONSUMER_AC_PRINT = 0x208, // HID type SEL + HID_CONSUMER_AC_PROPERTIES = 0x209, // HID type SEL + HID_CONSUMER_AC_UNDO = 0x21A, // HID type SEL + HID_CONSUMER_AC_COPY = 0x21B, // HID type SEL + HID_CONSUMER_AC_CUT = 0x21C, // HID type SEL + HID_CONSUMER_AC_PASTE = 0x21D, // HID type SEL + HID_CONSUMER_AC_SELECT_ALL = 0x21E, // HID type SEL + HID_CONSUMER_AC_FIND = 0x21F, // HID type SEL + HID_CONSUMER_AC_FIND_AND_REPLACE = 0x220, // HID type SEL + HID_CONSUMER_AC_SEARCH = 0x221, // HID type SEL + HID_CONSUMER_AC_GO_TO = 0x222, // HID type SEL + HID_CONSUMER_AC_HOME = 0x223, // HID type SEL + HID_CONSUMER_AC_BACK = 0x224, // HID type SEL + HID_CONSUMER_AC_FORWARD = 0x225, // HID type SEL + HID_CONSUMER_AC_STOP = 0x226, // HID type SEL + HID_CONSUMER_AC_REFRESH = 0x227, // HID type SEL + HID_CONSUMER_AC_PREVIOUS_LINK = 0x228, // HID type SEL + HID_CONSUMER_AC_NEXT_LINK = 0x229, // HID type SEL + HID_CONSUMER_AC_BOOKMARKS = 0x22A, // HID type SEL + HID_CONSUMER_AC_HISTORY = 0x22B, // HID type SEL + HID_CONSUMER_AC_SUBSCRIPTIONS = 0x22C, // HID type SEL + HID_CONSUMER_AC_ZOOM_IN = 0x22D, // HID type SEL + HID_CONSUMER_AC_ZOOM_OUT = 0x22E, // HID type SEL + HID_CONSUMER_AC_ZOOM = 0x22F, // HID type LC + HID_CONSUMER_AC_FULL_SCREEN_VIEW = 0x230, // HID type SEL + HID_CONSUMER_AC_NORMAL_VIEW = 0x231, // HID type SEL + HID_CONSUMER_AC_VIEW_TOGGLE = 0x232, // HID type SEL + HID_CONSUMER_AC_SCROLL_UP = 0x233, // HID type SEL + HID_CONSUMER_AC_SCROLL_DOWN = 0x234, // HID type SEL + HID_CONSUMER_AC_SCROLL = 0x235, // HID type LC + HID_CONSUMER_AC_PAN_LEFT = 0x236, // HID type SEL + HID_CONSUMER_AC_PAN_RIGHT = 0x237, // HID type SEL + HID_CONSUMER_AC_PAN = 0x238, // HID type LC + HID_CONSUMER_AC_NEW_WINDOW = 0x239, // HID type SEL + HID_CONSUMER_AC_TILE_HORIZONTALLY = 0x23A, // HID type SEL + HID_CONSUMER_AC_TILE_VERTICALLY = 0x23B, // HID type SEL + HID_CONSUMER_AC_FORMAT = 0x23C, // HID type SEL + HID_CONSUMER_AC_EDIT = 0x23D, // HID type SEL + HID_CONSUMER_AC_BOLD = 0x23E, // HID type SEL + HID_CONSUMER_AC_ITALICS = 0x23F, // HID type SEL + HID_CONSUMER_AC_UNDERLINE = 0x240, // HID type SEL + HID_CONSUMER_AC_STRIKETHROUGH = 0x241, // HID type SEL + HID_CONSUMER_AC_SUBSCRIPT = 0x242, // HID type SEL + HID_CONSUMER_AC_SUPERSCRIPT = 0x243, // HID type SEL + HID_CONSUMER_AC_ALL_CAPS = 0x244, // HID type SEL + HID_CONSUMER_AC_ROTATE = 0x245, // HID type SEL + HID_CONSUMER_AC_RESIZE = 0x246, // HID type SEL + HID_CONSUMER_AC_FLIP_HORIZONTAL = 0x247, // HID type SEL + HID_CONSUMER_AC_FLIP_VERTICAL = 0x248, // HID type SEL + HID_CONSUMER_AC_MIRROR_HORIZONTAL = 0x249, // HID type SEL + HID_CONSUMER_AC_MIRROR_VERTICAL = 0x24A, // HID type SEL + HID_CONSUMER_AC_FONT_SELECT = 0x24B, // HID type SEL + HID_CONSUMER_AC_FONT_COLOR = 0x24C, // HID type SEL + HID_CONSUMER_AC_FONT_SIZE = 0x24D, // HID type SEL + HID_CONSUMER_AC_JUSTIFY_LEFT = 0x24E, // HID type SEL + HID_CONSUMER_AC_JUSTIFY_CENTER_H = 0x24F, // HID type SEL + HID_CONSUMER_AC_JUSTIFY_RIGHT = 0x250, // HID type SEL + HID_CONSUMER_AC_JUSTIFY_BLOCK_H = 0x251, // HID type SEL + HID_CONSUMER_AC_JUSTIFY_TOP = 0x252, // HID type SEL + HID_CONSUMER_AC_JUSTIFY_CENTER_V = 0x253, // HID type SEL + HID_CONSUMER_AC_JUSTIFY_BOTTOM = 0x254, // HID type SEL + HID_CONSUMER_AC_JUSTIFY_BLOCK_V = 0x255, // HID type SEL + HID_CONSUMER_AC_INDENT_DECREASE = 0x256, // HID type SEL + HID_CONSUMER_AC_INDENT_INCREASE = 0x257, // HID type SEL + HID_CONSUMER_AC_NUMBERED_LIST = 0x258, // HID type SEL + HID_CONSUMER_AC_RESTART_NUMBERING = 0x259, // HID type SEL + HID_CONSUMER_AC_BULLETED_LIST = 0x25A, // HID type SEL + HID_CONSUMER_AC_PROMOTE = 0x25B, // HID type SEL + HID_CONSUMER_AC_DEMOTE = 0x25C, // HID type SEL + HID_CONSUMER_AC_YES = 0x25D, // HID type SEL + HID_CONSUMER_AC_NO = 0x25E, // HID type SEL + HID_CONSUMER_AC_CANCEL = 0x25F, // HID type SEL + HID_CONSUMER_AC_CATALOG = 0x260, // HID type SEL + HID_CONSUMER_AC_BUY_SLASH_CHECKOUT = 0x261, // HID type SEL + HID_CONSUMER_AC_ADD_TO_CART = 0x262, // HID type SEL + HID_CONSUMER_AC_EXPAND = 0x263, // HID type SEL + HID_CONSUMER_AC_EXPAND_ALL = 0x264, // HID type SEL + HID_CONSUMER_AC_COLLAPSE = 0x265, // HID type SEL + HID_CONSUMER_AC_COLLAPSE_ALL = 0x266, // HID type SEL + HID_CONSUMER_AC_PRINT_PREVIEW = 0x267, // HID type SEL + HID_CONSUMER_AC_PASTE_SPECIAL = 0x268, // HID type SEL + HID_CONSUMER_AC_INSERT_MODE = 0x269, // HID type SEL + HID_CONSUMER_AC_DELETE = 0x26A, // HID type SEL + HID_CONSUMER_AC_LOCK = 0x26B, // HID type SEL + HID_CONSUMER_AC_UNLOCK = 0x26C, // HID type SEL + HID_CONSUMER_AC_PROTECT = 0x26D, // HID type SEL + HID_CONSUMER_AC_UNPROTECT = 0x26E, // HID type SEL + HID_CONSUMER_AC_ATTACH_COMMENT = 0x26F, // HID type SEL + HID_CONSUMER_AC_DELETE_COMMENT = 0x270, // HID type SEL + HID_CONSUMER_AC_VIEW_COMMENT = 0x271, // HID type SEL + HID_CONSUMER_AC_SELECT_WORD = 0x272, // HID type SEL + HID_CONSUMER_AC_SELECT_SENTENCE = 0x273, // HID type SEL + HID_CONSUMER_AC_SELECT_PARAGRAPH = 0x274, // HID type SEL + HID_CONSUMER_AC_SELECT_COLUMN = 0x275, // HID type SEL + HID_CONSUMER_AC_SELECT_ROW = 0x276, // HID type SEL + HID_CONSUMER_AC_SELECT_TABLE = 0x277, // HID type SEL + HID_CONSUMER_AC_SELECT_OBJECT = 0x278, // HID type SEL + HID_CONSUMER_AC_REDO_SLASH_REPEAT = 0x279, // HID type SEL + HID_CONSUMER_AC_SORT = 0x27A, // HID type SEL + HID_CONSUMER_AC_SORT_ASCENDING = 0x27B, // HID type SEL + HID_CONSUMER_AC_SORT_DESCENDING = 0x27C, // HID type SEL + HID_CONSUMER_AC_FILTER = 0x27D, // HID type SEL + HID_CONSUMER_AC_SET_CLOCK = 0x27E, // HID type SEL + HID_CONSUMER_AC_VIEW_CLOCK = 0x27F, // HID type SEL + HID_CONSUMER_AC_SELECT_TIME_ZONE = 0x280, // HID type SEL + HID_CONSUMER_AC_EDIT_TIME_ZONES = 0x281, // HID type SEL + HID_CONSUMER_AC_SET_ALARM = 0x282, // HID type SEL + HID_CONSUMER_AC_CLEAR_ALARM = 0x283, // HID type SEL + HID_CONSUMER_AC_SNOOZE_ALARM = 0x284, // HID type SEL + HID_CONSUMER_AC_RESET_ALARM = 0x285, // HID type SEL + HID_CONSUMER_AC_SYNCHRONIZE = 0x286, // HID type SEL + HID_CONSUMER_AC_SEND_SLASH_RECEIVE = 0x287, // HID type SEL + HID_CONSUMER_AC_SEND_TO = 0x288, // HID type SEL + HID_CONSUMER_AC_REPLY = 0x289, // HID type SEL + HID_CONSUMER_AC_REPLY_ALL = 0x28A, // HID type SEL + HID_CONSUMER_AC_FORWARD_MSG = 0x28B, // HID type SEL + HID_CONSUMER_AC_SEND = 0x28C, // HID type SEL + HID_CONSUMER_AC_ATTACH_FILE = 0x28D, // HID type SEL + HID_CONSUMER_AC_UPLOAD = 0x28E, // HID type SEL + HID_CONSUMER_AC_DOWNLOAD_SAVE_TARGET_AS = 0x28F, // HID type SEL + HID_CONSUMER_AC_SET_BORDERS = 0x290, // HID type SEL + HID_CONSUMER_AC_INSERT_ROW = 0x291, // HID type SEL + HID_CONSUMER_AC_INSERT_COLUMN = 0x292, // HID type SEL + HID_CONSUMER_AC_INSERT_FILE = 0x293, // HID type SEL + HID_CONSUMER_AC_INSERT_PICTURE = 0x294, // HID type SEL + HID_CONSUMER_AC_INSERT_OBJECT = 0x295, // HID type SEL + HID_CONSUMER_AC_INSERT_SYMBOL = 0x296, // HID type SEL + HID_CONSUMER_AC_SAVE_AND_CLOSE = 0x297, // HID type SEL + HID_CONSUMER_AC_RENAME = 0x298, // HID type SEL + HID_CONSUMER_AC_MERGE = 0x299, // HID type SEL + HID_CONSUMER_AC_SPLIT = 0x29A, // HID type SEL + HID_CONSUMER_AC_DISRIBUTE_HORIZONTALLY = 0x29B, // HID type SEL + HID_CONSUMER_AC_DISTRIBUTE_VERTICALLY = 0x29C, // HID type SEL +}; typedef union { @@ -63,12 +451,12 @@ typedef union { uint8_t whole8[]; uint16_t whole16[]; uint32_t whole32[]; - uint16_t keys[4]; + ConsumerKeycode keys[4]; struct { - uint16_t key1; - uint16_t key2; - uint16_t key3; - uint16_t key4; + ConsumerKeycode key1; + ConsumerKeycode key2; + ConsumerKeycode key3; + ConsumerKeycode key4; }; } HID_ConsumerControlReport_Data_t; @@ -78,9 +466,9 @@ class ConsumerAPI inline ConsumerAPI(void); inline void begin(void); inline void end(void); - inline void write(uint16_t m); - inline void press(uint16_t m); - inline void release(uint16_t m); + inline void write(ConsumerKeycode m); + inline void press(ConsumerKeycode m); + inline void release(ConsumerKeycode m); inline void releaseAll(void); // Sending is public in the base class for advanced users. diff --git a/plugins/KeyboardioHID/src/HID-APIs/ConsumerAPI.hpp b/plugins/KeyboardioHID/src/HID-APIs/ConsumerAPI.hpp index 42f028207c..5e529c5630 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/ConsumerAPI.hpp +++ b/plugins/KeyboardioHID/src/HID-APIs/ConsumerAPI.hpp @@ -39,15 +39,15 @@ void ConsumerAPI::end(void) { SendReport(&_report, sizeof(_report)); } -void ConsumerAPI::write(uint16_t m) { +void ConsumerAPI::write(ConsumerKeycode m) { press(m); release(m); } -void ConsumerAPI::press(uint16_t m) { +void ConsumerAPI::press(ConsumerKeycode m) { // search for a free spot for (uint8_t i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { - if (_report.keys[i] == 0x00) { + if (_report.keys[i] == HID_CONSUMER_UNASSIGNED) { _report.keys[i] = m; break; } @@ -55,11 +55,11 @@ void ConsumerAPI::press(uint16_t m) { SendReport(&_report, sizeof(_report)); } -void ConsumerAPI::release(uint16_t m) { +void ConsumerAPI::release(ConsumerKeycode m) { // search and release the keypress for (uint8_t i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { if (_report.keys[i] == m) { - _report.keys[i] = 0x00; + _report.keys[i] = HID_CONSUMER_UNASSIGNED; // no break to delete multiple keys } } diff --git a/plugins/KeyboardioHID/src/HID-APIs/HID-Tables.h b/plugins/KeyboardioHID/src/HID-APIs/HID-Tables.h index b62be3aa81..553373ad83 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/HID-Tables.h +++ b/plugins/KeyboardioHID/src/HID-APIs/HID-Tables.h @@ -64,383 +64,3 @@ #define HID_SYSTEM_DISPLAY_LCD_AUTOSCALE 0xB7 // HID type OSC -// Consumer_Page_(0x0C) 0x15 -#define HID_CONSUMER_NUMERIC_KEY_PAD 0x02 // HID type NARY -#define HID_CONSUMER_PROGRAMMABLE_BUTTONS 0x03 // HID type NARY -#define HID_CONSUMER_MICROPHONE_CA 0x04 -#define HID_CONSUMER_HEADPHONE_CA 0x05 -#define HID_CONSUMER_GRAPHIC_EQUALIZER_CA 0x06 -// Reserved 0x07-1F -#define HID_CONSUMER_PLUS_10 0x20 // HID type OSC -#define HID_CONSUMER_PLUS_100 0x21 // HID type OSC -#define HID_CONSUMER_AM_SLASH_PM 0x22 // HID type OSC -// Reserved 0x23-3F -#define HID_CONSUMER_POWER 0x30 // HID type OOC -#define HID_CONSUMER_RESET 0x31 // HID type OSC -#define HID_CONSUMER_SLEEP 0x32 // HID type OSC -#define HID_CONSUMER_SLEEP_AFTER 0x33 // HID type OSC -#define HID_CONSUMER_SLEEP_MODE 0x34 // HID type RTC -#define HID_CONSUMER_ILLUMINATION 0x35 // HID type OOC -#define HID_CONSUMER_FUNCTION_BUTTONS 0x36 // HID type NARY -// Reserved 0x37-3F -#define HID_CONSUMER_MENU 0x40 // HID type OOC -#define HID_CONSUMER_MENU_PICK 0x41 // HID type OSC -#define HID_CONSUMER_MENU_UP 0x42 // HID type OSC -#define HID_CONSUMER_MENU_DOWN 0x43 // HID type OSC -#define HID_CONSUMER_MENU_LEFT 0x44 // HID type OSC -#define HID_CONSUMER_MENU_RIGHT 0x45 // HID type OSC -#define HID_CONSUMER_MENU_ESCAPE 0x46 // HID type OSC -#define HID_CONSUMER_MENU_VALUE_INCREASE 0x47 // HID type OSC -#define HID_CONSUMER_MENU_VALUE_DECREASE 0x48 // HID type OSC -// Reserved 0x49-5F -#define HID_CONSUMER_DATA_ON_SCREEN 0x60 // HID type OOC -#define HID_CONSUMER_CLOSED_CAPTION 0x61 // HID type OOC -#define HID_CONSUMER_CLOSED_CAPTION_SELECT 0x62 // HID type OSC -#define HID_CONSUMER_VCR_SLASH_TV 0x63 // HID type OOC -#define HID_CONSUMER_BROADCAST_MODE 0x64 // HID type OSC -#define HID_CONSUMER_SNAPSHOT 0x65 // HID type OSC -#define HID_CONSUMER_STILL 0x66 // HID type OSC -// Reserved 0x67-7F -#define HID_CONSUMER_SELECTION 0x80 // HID type NARY -#define HID_CONSUMER_ASSIGN_SELECTION 0x81 // HID type OSC -#define HID_CONSUMER_MODE_STEP 0x82 // HID type OSC -#define HID_CONSUMER_RECALL_LAST 0x83 // HID type OSC -#define HID_CONSUMER_ENTER_CHANNEL 0x84 // HID type OSC -#define HID_CONSUMER_ORDER_MOVIE 0x85 // HID type OSC -#define HID_CONSUMER_CHANNEL 0x86 // HID type LC -#define HID_CONSUMER_MEDIA_SELECTION 0x87 // HID type NARY -#define HID_CONSUMER_MEDIA_SELECT_COMPUTER 0x88 // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_TV 0x89 // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_WWW 0x8A // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_DVD 0x8B // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_TELEPHONE 0x8C // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_PROGRAM_GUIDE 0x8D // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_VIDEO_PHONE 0x8E // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_GAMES 0x8F // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_MESSAGES 0x90 // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_CD 0x91 // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_VCR 0x92 // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_TUNER 0x93 // HID type SEL -#define HID_CONSUMER_QUIT 0x94 // HID type OSC -#define HID_CONSUMER_HELP 0x95 // HID type OOC -#define HID_CONSUMER_MEDIA_SELECT_TAPE 0x96 // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_CABLE 0x97 // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_SATELLITE 0x98 // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_SECURITY 0x99 // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_HOME 0x9A // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_CALL 0x9B // HID type SEL -#define HID_CONSUMER_CHANNEL_INCREMENT 0x9C // HID type OSC -#define HID_CONSUMER_CHANNEL_DECREMENT 0x9D // HID type OSC -#define HID_CONSUMER_MEDIA_SELECT_SAP 0x9E // HID type SEL -// Reserved 0x9F -#define HID_CONSUMER_VCR_PLUS 0xA0 // HID type OSC -#define HID_CONSUMER_ONCE 0xA1 // HID type OSC -#define HID_CONSUMER_DAILY 0xA2 // HID type OSC -#define HID_CONSUMER_WEEKLY 0xA3 // HID type OSC -#define HID_CONSUMER_MONTHLY 0xA4 // HID type OSC -// Reserved 0xA5-AF -#define HID_CONSUMER_PLAY 0xB0 // HID type OOC -#define HID_CONSUMER_PAUSE 0xB1 // HID type OOC -#define HID_CONSUMER_RECORD 0xB2 // HID type OOC -#define HID_CONSUMER_FAST_FORWARD 0xB3 // HID type OOC -#define HID_CONSUMER_REWIND 0xB4 // HID type OOC -#define HID_CONSUMER_SCAN_NEXT_TRACK 0xB5 // HID type OSC -#define HID_CONSUMER_SCAN_PREVIOUS_TRACK 0xB6 // HID type OSC -#define HID_CONSUMER_STOP 0xB7 // HID type OSC -#define HID_CONSUMER_EJECT 0xB8 // HID type OSC -#define HID_CONSUMER_RANDOM_PLAY 0xB9 // HID type OOC -#define HID_CONSUMER_SELECT_DISC 0xBA // HID type NARY -#define HID_CONSUMER_ENTER_DISC_MC 0xBB -#define HID_CONSUMER_REPEAT 0xBC // HID type OSC -#define HID_CONSUMER_TRACKING 0xBD // HID type LC -#define HID_CONSUMER_TRACK_NORMAL 0xBE // HID type OSC -#define HID_CONSUMER_SLOW_TRACKING 0xBF // HID type LC -#define HID_CONSUMER_FRAME_FORWARD 0xC0 // HID type RTC -#define HID_CONSUMER_FRAME_BACK 0xC1 // HID type RTC -#define HID_CONSUMER_MARK 0xC2 // HID type OSC -#define HID_CONSUMER_CLEAR_MARK 0xC3 // HID type OSC -#define HID_CONSUMER_REPEAT_FROM_MARK 0xC4 // HID type OOC -#define HID_CONSUMER_RETURN_TO_MARK 0xC5 // HID type OSC -#define HID_CONSUMER_SEARCH_MARK_FORWARD 0xC6 // HID type OSC -#define HID_CONSUMER_SEARCH_MARK_BACKWARDS 0xC7 // HID type OSC -#define HID_CONSUMER_COUNTER_RESET 0xC8 // HID type OSC -#define HID_CONSUMER_SHOW_COUNTER 0xC9 // HID type OSC -#define HID_CONSUMER_TRACKING_INCREMENT 0xCA // HID type RTC -#define HID_CONSUMER_TRACKING_DECREMENT 0xCB // HID type RTC -#define HID_CONSUMER_STOP_SLASH_EJECT 0xCC // HID type OSC -#define HID_CONSUMER_PLAY_SLASH_PAUSE 0xCD // HID type OSC -#define HID_CONSUMER_PLAY_SLASH_SKIP 0xCE // HID type OSC -// Reserved 0xCF-DF -#define HID_CONSUMER_VOLUME 0xE0 // HID type LC -#define HID_CONSUMER_BALANCE 0xE1 // HID type LC -#define HID_CONSUMER_MUTE 0xE2 // HID type OOC -#define HID_CONSUMER_BASS 0xE3 // HID type LC -#define HID_CONSUMER_TREBLE 0xE4 // HID type LC -#define HID_CONSUMER_BASS_BOOST 0xE5 // HID type OOC -#define HID_CONSUMER_SURROUND_MODE 0xE6 // HID type OSC -#define HID_CONSUMER_LOUDNESS 0xE7 // HID type OOC -#define HID_CONSUMER_MPX 0xE8 // HID type OOC -#define HID_CONSUMER_VOLUME_INCREMENT 0xE9 // HID type RTC -#define HID_CONSUMER_VOLUME_DECREMENT 0xEA // HID type RTC -// Reserved 0xEB-EF -#define HID_CONSUMER_SPEED_SELECT 0xF0 // HID type OSC -#define HID_CONSUMER_PLAYBACK_SPEED 0xF1 // HID type NARY -#define HID_CONSUMER_STANDARD_PLAY 0xF2 // HID type SEL -#define HID_CONSUMER_LONG_PLAY 0xF3 // HID type SEL -#define HID_CONSUMER_EXTENDED_PLAY 0xF4 // HID type SEL -#define HID_CONSUMER_SLOW 0xF5 // HID type OSC -// Reserved 0xF6-FF -#define HID_CONSUMER_FAN_ENABLE 0x100 // HID type OOC -#define HID_CONSUMER_FAN_SPEED 0x101 // HID type LC -#define HID_CONSUMER_LIGHT_ENABLE 0x102 // HID type OOC -#define HID_CONSUMER_LIGHT_ILLUMINATION_LEVEL 0x103 // HID type LC -#define HID_CONSUMER_CLIMATE_CONTROL_ENABLE 0x104 // HID type OOC -#define HID_CONSUMER_ROOM_TEMPERATURE 0x105 // HID type LC -#define HID_CONSUMER_SECURITY_ENABLE 0x106 // HID type OOC -#define HID_CONSUMER_FIRE_ALARM 0x107 // HID type OSC -#define HID_CONSUMER_POLICE_ALARM 0x108 // HID type OSC -#define HID_CONSUMER_PROXIMITY 0x109 // HID type LC -#define HID_CONSUMER_MOTION 0x10A // HID type OSC -#define HID_CONSUMER_DURESS_ALARM 0x10B // HID type OSC -#define HID_CONSUMER_HOLDUP_ALARM 0x10C // HID type OSC -#define HID_CONSUMER_MEDICAL_ALARM 0x10D // HID type OSC -// Reserved 0x10E-14F -#define HID_CONSUMER_BALANCE_RIGHT 0x150 // HID type RTC -#define HID_CONSUMER_BALANCE_LEFT 0x151 // HID type RTC -#define HID_CONSUMER_BASS_INCREMENT 0x152 // HID type RTC -#define HID_CONSUMER_BASS_DECREMENT 0x153 // HID type RTC -#define HID_CONSUMER_TREBLE_INCREMENT 0x154 // HID type RTC -#define HID_CONSUMER_TREBLE_DECREMENT 0x155 // HID type RTC -// Reserved 0x156-15F -#define HID_CONSUMER_SPEAKER_SYSTEM 0x160 // HID type CL -#define HID_CONSUMER_CHANNEL_LEFT 0x161 // HID type CL -#define HID_CONSUMER_CHANNEL_RIGHT 0x162 // HID type CL -#define HID_CONSUMER_CHANNEL_CENTER 0x163 // HID type CL -#define HID_CONSUMER_CHANNEL_FRONT 0x164 // HID type CL -#define HID_CONSUMER_CHANNEL_CENTER_FRONT 0x165 // HID type CL -#define HID_CONSUMER_CHANNEL_SIDE 0x166 // HID type CL -#define HID_CONSUMER_CHANNEL_SURROUND 0x167 // HID type CL -#define HID_CONSUMER_CHANNEL_LOW_FREQUENCY_ENHANCEMENT 0x168 // HID type CL -#define HID_CONSUMER_CHANNEL_TOP 0x169 // HID type CL -#define HID_CONSUMER_CHANNEL_UNKNOWN 0x16A // HID type CL -// Reserved 0x16B-16F -#define HID_CONSUMER_SUB_CHANNEL 0x170 // HID type LC -#define HID_CONSUMER_SUB_CHANNEL_INCREMENT 0x171 // HID type OSC -#define HID_CONSUMER_SUB_CHANNEL_DECREMENT 0x172 // HID type OSC -#define HID_CONSUMER_ALTERNATE_AUDIO_INCREMENT 0x173 // HID type OSC -#define HID_CONSUMER_ALTERNATE_AUDIO_DECREMENT 0x174 // HID type OSC -// Reserved 0x175-17F -#define HID_CONSUMER_APPLICATION_LAUNCH_BUTTONS 0x180 // HID type NARY -#define HID_CONSUMER_AL_LAUNCH_BUTTON_CONFIGURATION_TOOL 0x181 // HID type SEL -#define HID_CONSUMER_AL_PROGRAMMABLE_BUTTON_CONFIGURATION 0x182 // HID type SEL -#define HID_CONSUMER_AL_CONSUMER_CONTROL_CONFIGURATION 0x183 // HID type SEL -#define HID_CONSUMER_AL_WORD_PROCESSOR 0x184 // HID type SEL -#define HID_CONSUMER_AL_TEXT_EDITOR 0x185 // HID type SEL -#define HID_CONSUMER_AL_SPREADSHEET 0x186 // HID type SEL -#define HID_CONSUMER_AL_GRAPHICS_EDITOR 0x187 // HID type SEL -#define HID_CONSUMER_AL_PRESENTATION_APP 0x188 // HID type SEL -#define HID_CONSUMER_AL_DATABASE_APP 0x189 // HID type SEL -#define HID_CONSUMER_AL_EMAIL_READER 0x18A // HID type SEL -#define HID_CONSUMER_AL_NEWSREADER 0x18B // HID type SEL -#define HID_CONSUMER_AL_VOICEMAIL 0x18C // HID type SEL -#define HID_CONSUMER_AL_CONTACTS_SLASH_ADDRESS_BOOK 0x18D // HID type SEL -#define HID_CONSUMER_AL_CALENDAR_SLASH_SCHEDULE 0x18E // HID type SEL -#define HID_CONSUMER_AL_TASK_SLASH_PROJECT_MANAGER 0x18F // HID type SEL -#define HID_CONSUMER_AL_LOG_SLASH_JOURNAL_SLASH_TIMECARD 0x190 // HID type SEL -#define HID_CONSUMER_AL_CHECKBOOK_SLASH_FINANCE 0x191 // HID type SEL -#define HID_CONSUMER_AL_CALCULATOR 0x192 // HID type SEL -#define HID_CONSUMER_AL_A_SLASH_V_CAPTURE_SLASH_PLAYBACK 0x193 // HID type SEL -#define HID_CONSUMER_AL_LOCAL_MACHINE_BROWSER 0x194 // HID type SEL -#define HID_CONSUMER_AL_LAN_SLASH_WAN_BROWSER 0x195 // HID type SEL -#define HID_CONSUMER_AL_INTERNET_BROWSER 0x196 // HID type SEL -#define HID_CONSUMER_AL_REMOTE_NETWORKING_SLASH_ISP_CONNECT 0x197 // HID type SEL -#define HID_CONSUMER_AL_NETWORK_CONFERENCE 0x198 // HID type SEL -#define HID_CONSUMER_AL_NETWORK_CHAT 0x199 // HID type SEL -#define HID_CONSUMER_AL_TELEPHONY_SLASH_DIALER 0x19A // HID type SEL -#define HID_CONSUMER_AL_LOGON 0x19B // HID type SEL -#define HID_CONSUMER_AL_LOGOFF 0x19C // HID type SEL -#define HID_CONSUMER_AL_LOGON_SLASH_LOGOFF 0x19D // HID type SEL -#define HID_CONSUMER_AL_TERMINAL_LOCK_SLASH_SCREENSAVER 0x19E // HID type SEL -#define HID_CONSUMER_AL_CONTROL_PANEL 0x19F // HID type SEL -#define HID_CONSUMER_AL_COMMAND_LINE_PROCESSOR_SLASH_RUN 0x1A0 // HID type SEL -#define HID_CONSUMER_AL_PROCESS_SLASH_TASK_MANAGER 0x1A1 // HID type SEL -#define HID_CONSUMER_AL_SELECT_TASK_SLASH_APPLICATION 0x1A2 // HID type SEL -#define HID_CONSUMER_AL_NEXT_TASK_SLASH_APPLICATION 0x1A3 // HID type SEL -#define HID_CONSUMER_AL_PREVIOUS_TASK_SLASH_APPLICATION 0x1A4 // HID type SEL -#define HID_CONSUMER_AL_PREEMPTIVE_HALT_TASK_SLASH_APPLICATION 0x1A5 // HID type SEL -#define HID_CONSUMER_AL_INTEGRATED_HELP_CENTER 0x1A6 // HID type SEL -#define HID_CONSUMER_AL_DOCUMENTS 0x1A7 // HID type SEL -#define HID_CONSUMER_AL_THESAURUS 0x1A8 // HID type SEL -#define HID_CONSUMER_AL_DICTIONARY 0x1A9 // HID type SEL -#define HID_CONSUMER_AL_DESKTOP 0x1AA // HID type SEL -#define HID_CONSUMER_AL_SPELL_CHECK 0x1AB // HID type SEL -#define HID_CONSUMER_AL_GRAMMAR_CHECK 0x1AC // HID type SEL -#define HID_CONSUMER_AL_WIRELESS_STATUS 0x1AD // HID type SEL -#define HID_CONSUMER_AL_KEYBOARD_LAYOUT 0x1AE // HID type SEL -#define HID_CONSUMER_AL_VIRUS_PROTECTION 0x1AF // HID type SEL -#define HID_CONSUMER_AL_ENCRYPTION 0x1B0 // HID type SEL -#define HID_CONSUMER_AL_SCREEN_SAVER 0x1B1 // HID type SEL -#define HID_CONSUMER_AL_ALARMS 0x1B2 // HID type SEL -#define HID_CONSUMER_AL_CLOCK 0x1B3 // HID type SEL -#define HID_CONSUMER_AL_FILE_BROWSER 0x1B4 // HID type SEL -#define HID_CONSUMER_AL_POWER_STATUS 0x1B5 // HID type SEL -#define HID_CONSUMER_AL_IMAGE_BROWSER 0x1B6 // HID type SEL -#define HID_CONSUMER_AL_AUDIO_BROWSER 0x1B7 // HID type SEL -#define HID_CONSUMER_AL_MOVIE_BROWSER 0x1B8 // HID type SEL -#define HID_CONSUMER_AL_DIGITAL_RIGHTS_MANAGER 0x1B9 // HID type SEL -#define HID_CONSUMER_AL_DIGITAL_WALLET 0x1BA // HID type SEL -// _Reserved 0x1BB -#define HID_CONSUMER_AL_INSTANT_MESSAGING 0x1BC // HID type SEL -#define HID_CONSUMER_AL_OEM_FEATURES_SLASH__TIPS_SLASH_TUTORIAL_BROWSER 0x1BD // HID type SEL -#define HID_CONSUMER_AL_OEM_HELP 0x1BE // HID type SEL -#define HID_CONSUMER_AL_ONLINE_COMMUNITY 0x1BF // HID type SEL -#define HID_CONSUMER_AL_ENTERTAINMENT_CONTENT_BROWSER 0x1C0 // HID type SEL -#define HID_CONSUMER_AL_ONLINE_SHOPPING_BROWSER 0x1C1 // HID type SEL -#define HID_CONSUMER_AL_SMARTCARD_INFORMATION_SLASH_HELP 0x1C2 // HID type SEL -#define HID_CONSUMER_AL_MARKET_MONITOR_SLASH_FINANCE_BROWSER 0x1C3 // HID type SEL -#define HID_CONSUMER_AL_CUSTOMIZED_CORPORATE_NEWS_BROWSER 0x1C4 // HID type SEL -#define HID_CONSUMER_AL_ONLINE_ACTIVITY_BROWSER 0x1C5 // HID type SEL -#define HID_CONSUMER_AL_RESEARCH_SLASH_SEARCH_BROWSER 0x1C6 // HID type SEL -#define HID_CONSUMER_AL_AUDIO_PLAYER 0x1C7 // HID type SEL -// Reserved 0x1C8-1FF -#define HID_CONSUMER_GENERIC_GUI_APPLICATION_CONTROLS 0x200 // HID type NARY -#define HID_CONSUMER_AC_NEW 0x201 // HID type SEL -#define HID_CONSUMER_AC_OPEN 0x202 // HID type SEL -#define HID_CONSUMER_AC_CLOSE 0x203 // HID type SEL -#define HID_CONSUMER_AC_EXIT 0x204 // HID type SEL -#define HID_CONSUMER_AC_MAXIMIZE 0x205 // HID type SEL -#define HID_CONSUMER_AC_MINIMIZE 0x206 // HID type SEL -#define HID_CONSUMER_AC_SAVE 0x207 // HID type SEL -#define HID_CONSUMER_AC_PRINT 0x208 // HID type SEL -#define HID_CONSUMER_AC_PROPERTIES 0x209 // HID type SEL -#define HID_CONSUMER_AC_UNDO 0x21A // HID type SEL -#define HID_CONSUMER_AC_COPY 0x21B // HID type SEL -#define HID_CONSUMER_AC_CUT 0x21C // HID type SEL -#define HID_CONSUMER_AC_PASTE 0x21D // HID type SEL -#define HID_CONSUMER_AC_SELECT_ALL 0x21E // HID type SEL -#define HID_CONSUMER_AC_FIND 0x21F // HID type SEL -#define HID_CONSUMER_AC_FIND_AND_REPLACE 0x220 // HID type SEL -#define HID_CONSUMER_AC_SEARCH 0x221 // HID type SEL -#define HID_CONSUMER_AC_GO_TO 0x222 // HID type SEL -#define HID_CONSUMER_AC_HOME 0x223 // HID type SEL -#define HID_CONSUMER_AC_BACK 0x224 // HID type SEL -#define HID_CONSUMER_AC_FORWARD 0x225 // HID type SEL -#define HID_CONSUMER_AC_STOP 0x226 // HID type SEL -#define HID_CONSUMER_AC_REFRESH 0x227 // HID type SEL -#define HID_CONSUMER_AC_PREVIOUS_LINK 0x228 // HID type SEL -#define HID_CONSUMER_AC_NEXT_LINK 0x229 // HID type SEL -#define HID_CONSUMER_AC_BOOKMARKS 0x22A // HID type SEL -#define HID_CONSUMER_AC_HISTORY 0x22B // HID type SEL -#define HID_CONSUMER_AC_SUBSCRIPTIONS 0x22C // HID type SEL -#define HID_CONSUMER_AC_ZOOM_IN 0x22D // HID type SEL -#define HID_CONSUMER_AC_ZOOM_OUT 0x22E // HID type SEL -#define HID_CONSUMER_AC_ZOOM 0x22F // HID type LC -#define HID_CONSUMER_AC_FULL_SCREEN_VIEW 0x230 // HID type SEL -#define HID_CONSUMER_AC_NORMAL_VIEW 0x231 // HID type SEL -#define HID_CONSUMER_AC_VIEW_TOGGLE 0x232 // HID type SEL -#define HID_CONSUMER_AC_SCROLL_UP 0x233 // HID type SEL -#define HID_CONSUMER_AC_SCROLL_DOWN 0x234 // HID type SEL -#define HID_CONSUMER_AC_SCROLL 0x235 // HID type LC -#define HID_CONSUMER_AC_PAN_LEFT 0x236 // HID type SEL -#define HID_CONSUMER_AC_PAN_RIGHT 0x237 // HID type SEL -#define HID_CONSUMER_AC_PAN 0x238 // HID type LC -#define HID_CONSUMER_AC_NEW_WINDOW 0x239 // HID type SEL -#define HID_CONSUMER_AC_TILE_HORIZONTALLY 0x23A // HID type SEL -#define HID_CONSUMER_AC_TILE_VERTICALLY 0x23B // HID type SEL -#define HID_CONSUMER_AC_FORMAT 0x23C // HID type SEL -#define HID_CONSUMER_AC_EDIT 0x23D // HID type SEL -#define HID_CONSUMER_AC_BOLD 0x23E // HID type SEL -#define HID_CONSUMER_AC_ITALICS 0x23F // HID type SEL -#define HID_CONSUMER_AC_UNDERLINE 0x240 // HID type SEL -#define HID_CONSUMER_AC_STRIKETHROUGH 0x241 // HID type SEL -#define HID_CONSUMER_AC_SUBSCRIPT 0x242 // HID type SEL -#define HID_CONSUMER_AC_SUPERSCRIPT 0x243 // HID type SEL -#define HID_CONSUMER_AC_ALL_CAPS 0x244 // HID type SEL -#define HID_CONSUMER_AC_ROTATE 0x245 // HID type SEL -#define HID_CONSUMER_AC_RESIZE 0x246 // HID type SEL -#define HID_CONSUMER_AC_FLIP_HORIZONTAL 0x247 // HID type SEL -#define HID_CONSUMER_AC_FLIP_VERTICAL 0x248 // HID type SEL -#define HID_CONSUMER_AC_MIRROR_HORIZONTAL 0x249 // HID type SEL -#define HID_CONSUMER_AC_MIRROR_VERTICAL 0x24A // HID type SEL -#define HID_CONSUMER_AC_FONT_SELECT 0x24B // HID type SEL -#define HID_CONSUMER_AC_FONT_COLOR 0x24C // HID type SEL -#define HID_CONSUMER_AC_FONT_SIZE 0x24D // HID type SEL -#define HID_CONSUMER_AC_JUSTIFY_LEFT 0x24E // HID type SEL -#define HID_CONSUMER_AC_JUSTIFY_CENTER_H 0x24F // HID type SEL -#define HID_CONSUMER_AC_JUSTIFY_RIGHT 0x250 // HID type SEL -#define HID_CONSUMER_AC_JUSTIFY_BLOCK_H 0x251 // HID type SEL -#define HID_CONSUMER_AC_JUSTIFY_TOP 0x252 // HID type SEL -#define HID_CONSUMER_AC_JUSTIFY_CENTER_V 0x253 // HID type SEL -#define HID_CONSUMER_AC_JUSTIFY_BOTTOM 0x254 // HID type SEL -#define HID_CONSUMER_AC_JUSTIFY_BLOCK_V 0x255 // HID type SEL -#define HID_CONSUMER_AC_INDENT_DECREASE 0x256 // HID type SEL -#define HID_CONSUMER_AC_INDENT_INCREASE 0x257 // HID type SEL -#define HID_CONSUMER_AC_NUMBERED_LIST 0x258 // HID type SEL -#define HID_CONSUMER_AC_RESTART_NUMBERING 0x259 // HID type SEL -#define HID_CONSUMER_AC_BULLETED_LIST 0x25A // HID type SEL -#define HID_CONSUMER_AC_PROMOTE 0x25B // HID type SEL -#define HID_CONSUMER_AC_DEMOTE 0x25C // HID type SEL -#define HID_CONSUMER_AC_YES 0x25D // HID type SEL -#define HID_CONSUMER_AC_NO 0x25E // HID type SEL -#define HID_CONSUMER_AC_CANCEL 0x25F // HID type SEL -#define HID_CONSUMER_AC_CATALOG 0x260 // HID type SEL -#define HID_CONSUMER_AC_BUY_SLASH_CHECKOUT 0x261 // HID type SEL -#define HID_CONSUMER_AC_ADD_TO_CART 0x262 // HID type SEL -#define HID_CONSUMER_AC_EXPAND 0x263 // HID type SEL -#define HID_CONSUMER_AC_EXPAND_ALL 0x264 // HID type SEL -#define HID_CONSUMER_AC_COLLAPSE 0x265 // HID type SEL -#define HID_CONSUMER_AC_COLLAPSE_ALL 0x266 // HID type SEL -#define HID_CONSUMER_AC_PRINT_PREVIEW 0x267 // HID type SEL -#define HID_CONSUMER_AC_PASTE_SPECIAL 0x268 // HID type SEL -#define HID_CONSUMER_AC_INSERT_MODE 0x269 // HID type SEL -#define HID_CONSUMER_AC_DELETE 0x26A // HID type SEL -#define HID_CONSUMER_AC_LOCK 0x26B // HID type SEL -#define HID_CONSUMER_AC_UNLOCK 0x26C // HID type SEL -#define HID_CONSUMER_AC_PROTECT 0x26D // HID type SEL -#define HID_CONSUMER_AC_UNPROTECT 0x26E // HID type SEL -#define HID_CONSUMER_AC_ATTACH_COMMENT 0x26F // HID type SEL -#define HID_CONSUMER_AC_DELETE_COMMENT 0x270 // HID type SEL -#define HID_CONSUMER_AC_VIEW_COMMENT 0x271 // HID type SEL -#define HID_CONSUMER_AC_SELECT_WORD 0x272 // HID type SEL -#define HID_CONSUMER_AC_SELECT_SENTENCE 0x273 // HID type SEL -#define HID_CONSUMER_AC_SELECT_PARAGRAPH 0x274 // HID type SEL -#define HID_CONSUMER_AC_SELECT_COLUMN 0x275 // HID type SEL -#define HID_CONSUMER_AC_SELECT_ROW 0x276 // HID type SEL -#define HID_CONSUMER_AC_SELECT_TABLE 0x277 // HID type SEL -#define HID_CONSUMER_AC_SELECT_OBJECT 0x278 // HID type SEL -#define HID_CONSUMER_AC_REDO_SLASH_REPEAT 0x279 // HID type SEL -#define HID_CONSUMER_AC_SORT 0x27A // HID type SEL -#define HID_CONSUMER_AC_SORT_ASCENDING 0x27B // HID type SEL -#define HID_CONSUMER_AC_SORT_DESCENDING 0x27C // HID type SEL -#define HID_CONSUMER_AC_FILTER 0x27D // HID type SEL -#define HID_CONSUMER_AC_SET_CLOCK 0x27E // HID type SEL -#define HID_CONSUMER_AC_VIEW_CLOCK 0x27F // HID type SEL -#define HID_CONSUMER_AC_SELECT_TIME_ZONE 0x280 // HID type SEL -#define HID_CONSUMER_AC_EDIT_TIME_ZONES 0x281 // HID type SEL -#define HID_CONSUMER_AC_SET_ALARM 0x282 // HID type SEL -#define HID_CONSUMER_AC_CLEAR_ALARM 0x283 // HID type SEL -#define HID_CONSUMER_AC_SNOOZE_ALARM 0x284 // HID type SEL -#define HID_CONSUMER_AC_RESET_ALARM 0x285 // HID type SEL -#define HID_CONSUMER_AC_SYNCHRONIZE 0x286 // HID type SEL -#define HID_CONSUMER_AC_SEND_SLASH_RECEIVE 0x287 // HID type SEL -#define HID_CONSUMER_AC_SEND_TO 0x288 // HID type SEL -#define HID_CONSUMER_AC_REPLY 0x289 // HID type SEL -#define HID_CONSUMER_AC_REPLY_ALL 0x28A // HID type SEL -#define HID_CONSUMER_AC_FORWARD_MSG 0x28B // HID type SEL -#define HID_CONSUMER_AC_SEND 0x28C // HID type SEL -#define HID_CONSUMER_AC_ATTACH_FILE 0x28D // HID type SEL -#define HID_CONSUMER_AC_UPLOAD 0x28E // HID type SEL -#define HID_CONSUMER_AC_DOWNLOAD_(SAVE_TARGET_AS) 0x28F // HID type SEL -#define HID_CONSUMER_AC_SET_BORDERS 0x290 // HID type SEL -#define HID_CONSUMER_AC_INSERT_ROW 0x291 // HID type SEL -#define HID_CONSUMER_AC_INSERT_COLUMN 0x292 // HID type SEL -#define HID_CONSUMER_AC_INSERT_FILE 0x293 // HID type SEL -#define HID_CONSUMER_AC_INSERT_PICTURE 0x294 // HID type SEL -#define HID_CONSUMER_AC_INSERT_OBJECT 0x295 // HID type SEL -#define HID_CONSUMER_AC_INSERT_SYMBOL 0x296 // HID type SEL -#define HID_CONSUMER_AC_SAVE_AND_CLOSE 0x297 // HID type SEL -#define HID_CONSUMER_AC_RENAME 0x298 // HID type SEL -#define HID_CONSUMER_AC_MERGE 0x299 // HID type SEL -#define HID_CONSUMER_AC_SPLIT 0x29A // HID type SEL -#define HID_CONSUMER_AC_DISRIBUTE_HORIZONTALLY 0x29B // HID type SEL -#define HID_CONSUMER_AC_DISTRIBUTE_VERTICALLY 0x29C // HID type SEL From 703b44ee99839c3330e3ab8134fafdcb1fb271a6 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 24 Oct 2015 11:10:42 +0200 Subject: [PATCH 305/602] Added Consumer Keys to Keyboard API --- plugins/KeyboardioHID/Readme.md | 2 - .../ImprovedKeyboard/ImprovedKeyboard.ino | 17 +++++ .../src/HID-APIs/ImprovedKeylayouts.h | 6 +- .../KeyboardioHID/src/HID-APIs/KeyboardAPI.h | 16 ++-- .../src/HID-APIs/KeyboardAPI.hpp | 74 ++++++++++++++++++- 5 files changed, 100 insertions(+), 15 deletions(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index dfaa9b6016..71037aa6c6 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -91,8 +91,6 @@ Version History * Added a few key definitions * Uses .alinkage custom IDE option * Added BootKeyboard support (BIOS compatibility) -* KEY_MENU switched to KEY_APPLICATION -* KEY_RETURN is not KEY_ENTER anymore! 2.3 Release (never released) * Updated Libraries diff --git a/plugins/KeyboardioHID/examples/ImprovedKeyboard/ImprovedKeyboard.ino b/plugins/KeyboardioHID/examples/ImprovedKeyboard/ImprovedKeyboard.ino index 23fb0faacd..37bcf3e219 100644 --- a/plugins/KeyboardioHID/examples/ImprovedKeyboard/ImprovedKeyboard.ino +++ b/plugins/KeyboardioHID/examples/ImprovedKeyboard/ImprovedKeyboard.ino @@ -38,9 +38,26 @@ void loop() { // Write single keys, do not use a number here! //Keyboard.write(KEY_ENTER); + // If you really wish to press a RAW keycode without the name use this: //Keyboard.write(KeyboardKeycode(40)); + // Use (a limited number of) consumer keys. + // Only works with the lower 255 keys and on linux only. + //Keyboard.write(MEDIA_PLAY_PAUSE); + + // Linux also supports several system function via consumer report. + //Keyboard.write(CONSUMER_POWER); + //Keyboard.write(CONSUMER_SLEEP); + + // You can also use some special keyboard keys on linux. + //Keyboard.write(KEY_POWER); + //Keyboard.write(KEY_F13); + + // You can wakeup you PC from sleep. + // This might be not supported on all hardware, but on all OS types. + //Keyboard.wakeupHost(); + // Simple debounce delay(300); digitalWrite(pinLed, LOW); diff --git a/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h b/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h index 7574a8d638..1c9c5a3584 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h +++ b/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h @@ -133,6 +133,7 @@ enum KeyboardKeycode : uint8_t { KEYPAD_SUBTRACT = 0x56, KEYPAD_ADD = 0x57, KEYPAD_ENTER = 0x59, + KEY_RETURN = 0x59, // Alias KEYPAD_1 = 0x59, KEYPAD_2 = 0x5A, KEYPAD_3 = 0x5B, @@ -146,6 +147,7 @@ enum KeyboardKeycode : uint8_t { KEYPAD_DOT = 0x63, KEY_NON_US = 0x64, KEY_APPLICATION = 0x65, // Context menu/right click + KEY_MENU = 0x65, // Alias // Most of the following keys will only work with Linux or not at all. // F13+ keys are mostly used for laptop functions like ECO key. @@ -165,7 +167,7 @@ enum KeyboardKeycode : uint8_t { KEY_F24 = 0x73, // Disabled (Ubuntu) KEY_EXECUTE = 0x74, // Open (Ubuntu) KEY_HELP = 0x75, // Help (Ubuntu) - KEY_MENU = 0x76, // Disabled (Ubuntu) + KEY_MENU2 = 0x76, // Disabled (Ubuntu) KEY_SELECT = 0x77, // Disabled (Ubuntu) KEY_STOP = 0x78, // Cancel (Ubuntu) KEY_AGAIN = 0x79, // Redo (Ubuntu) @@ -206,7 +208,7 @@ enum KeyboardKeycode : uint8_t { KEY_CANCEL = 0x9B, // Disabled (Ubuntu) KEY_CLEAR = 0x9C, // Delete (Ubuntu) KEY_PRIOR = 0x9D, // Disabled (Ubuntu) - KEY_RETURN = 0x9E, // Disabled (Ubuntu), Do not confuse this with KEY_ENTER + KEY_RETURN2 = 0x9E, // Disabled (Ubuntu), Do not confuse this with KEY_ENTER KEY_SEPARATOR = 0x9F, // Disabled (Ubuntu) KEY_OUT = 0xA0, // Disabled (Ubuntu) KEY_OPER = 0xA1, // Disabled (Ubuntu) diff --git a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h index 6a8df49536..1c6f5e3567 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h +++ b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h @@ -27,6 +27,7 @@ THE SOFTWARE. #include #include "HID-Settings.h" #include "ImprovedKeylayouts.h" +#include "ConsumerAPI.h" typedef union{ // Low level key report: up to 6 keys and shift, ctrl etc at once @@ -36,46 +37,45 @@ typedef union{ struct{ uint8_t modifiers; uint8_t reserved; - uint8_t keys[6]; + KeyboardKeycode keys[6]; }; } HID_KeyboardReport_Data_t; class KeyboardAPI : public Print { public: -//TODO nkro compatiblity, merge them inline void begin(void); inline void end(void); inline size_t write(uint8_t k); inline size_t write(KeyboardKeycode k); inline size_t write(KeyboardModifier k); + inline size_t write(ConsumerKeycode k); inline size_t press(uint8_t k); inline size_t press(KeyboardKeycode k); inline size_t press(KeyboardModifier k); + inline size_t press(ConsumerKeycode k); inline size_t release(uint8_t k); inline size_t release(KeyboardKeycode k); inline size_t release(KeyboardModifier k); + inline size_t release(ConsumerKeycode k); inline size_t add(uint8_t k); inline size_t add(KeyboardKeycode k); inline size_t add(KeyboardModifier k); + inline size_t add(ConsumerKeycode k); inline size_t remove(uint8_t k); inline size_t remove(KeyboardKeycode k); inline size_t remove(KeyboardModifier k); - - // TODO media, system - inline void setMedia(uint8_t m){ - _keyReport.reserved = m; - send_now(); - } + inline size_t remove(ConsumerKeycode k); inline void releaseAll(void); inline void removeAll(void); inline void send_now(void); + inline void wakeupHost(void); // Sending is public in the base class for advanced users. virtual void SendReport(void* data, int length) = 0; diff --git a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.hpp b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.hpp index fba968dcdc..648613356d 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.hpp +++ b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.hpp @@ -36,7 +36,6 @@ void KeyboardAPI::end(void) } -// TODO template?? size_t KeyboardAPI::write(uint8_t k) { // Press and release key (if press was successfull) @@ -70,6 +69,17 @@ size_t KeyboardAPI::write(KeyboardModifier k) } +size_t KeyboardAPI::write(ConsumerKeycode k) +{ + // Press and release key (if press was successfull) + auto ret = press(k); + if(ret){ + release(k); + } + return ret; +} + + size_t KeyboardAPI::press(uint8_t k) { // Press key and send report to host @@ -103,6 +113,17 @@ size_t KeyboardAPI::press(KeyboardModifier k) } +size_t KeyboardAPI::press(ConsumerKeycode k) +{ + // Press key and send report to host + auto ret = add(k); + if(ret){ + send_now(); + } + return ret; +} + + size_t KeyboardAPI::add(uint8_t k) { // Ignore invalid input @@ -131,7 +152,7 @@ size_t KeyboardAPI::add(KeyboardKeycode k) { // Is key already in the list or did we found an empty slot? auto key = _keyReport.keys[i]; - if (key == uint8_t(k) || key == 0) { + if (key == uint8_t(k) || key == KEY_RESERVED) { _keyReport.keys[i] = k; return 1; } @@ -151,6 +172,21 @@ size_t KeyboardAPI::add(KeyboardModifier k) } +size_t KeyboardAPI::add(ConsumerKeycode k) +{ + if(k > 0xFF){ + // No 2 byte keys are supported + setWriteError(); + return 0; + } + + // Place the key inside the reserved keyreport position. + // This does not work on Windows. + _keyReport.reserved = k; + return 1; +} + + size_t KeyboardAPI::release(uint8_t k) { // Release key and send report to host @@ -184,6 +220,17 @@ size_t KeyboardAPI::release(KeyboardModifier k) } +size_t KeyboardAPI::release(ConsumerKeycode k) +{ + // Release key and send report to host + auto ret = remove(k); + if(ret){ + send_now(); + } + return ret; +} + + size_t KeyboardAPI::remove(uint8_t k) { // Ignore invalid input @@ -208,7 +255,7 @@ size_t KeyboardAPI::remove(KeyboardKeycode k) // Test the key report to see if k is present. Clear it if it exists. for (uint8_t i = 0; i < 6; i++) { if (_keyReport.keys[i] == k) { - _keyReport.keys[i] = 0x00; + _keyReport.keys[i] = KEY_RESERVED; return 1; } } @@ -232,6 +279,20 @@ size_t KeyboardAPI::remove(KeyboardModifier k) } +size_t KeyboardAPI::remove(ConsumerKeycode k) +{ + if(k > 0xFF){ + // No 2 byte keys are supported + return 0; + } + + // Always release the key, to make it simpler releasing a consumer key + // without releasing all other normal keyboard keys. + _keyReport.reserved = HID_CONSUMER_UNASSIGNED; + return 1; +} + + void KeyboardAPI::releaseAll(void) { // Release all keys @@ -252,3 +313,10 @@ void KeyboardAPI::send_now(void){ } +void KeyboardAPI::wakeupHost(void){ +#ifdef USBCON + USBDevice.wakeupHost(); +#endif +} + + From 92ce558fcb5bf0a604eef884ffd6745d77ecc775 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 24 Oct 2015 18:41:34 +0200 Subject: [PATCH 306/602] Fixed KEY_RETURN --- plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h b/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h index 1c9c5a3584..1b9363b65d 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h +++ b/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h @@ -84,6 +84,7 @@ enum KeyboardKeycode : uint8_t { KEY_9 = 38, KEY_0 = 39, KEY_ENTER = 40, + KEY_RETURN = 40, // Alias KEY_ESC = 41, KEY_BACKSPACE = 42, KEY_TAB = 43, @@ -132,8 +133,7 @@ enum KeyboardKeycode : uint8_t { KEYPAD_MULTIPLY = 0x55, KEYPAD_SUBTRACT = 0x56, KEYPAD_ADD = 0x57, - KEYPAD_ENTER = 0x59, - KEY_RETURN = 0x59, // Alias + KEYPAD_ENTER = 0x58, KEYPAD_1 = 0x59, KEYPAD_2 = 0x5A, KEYPAD_3 = 0x5B, From 37c5703ba4b6ea169056fdc045b035f3a5257fc7 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 25 Oct 2015 08:33:23 +0100 Subject: [PATCH 307/602] Improved Keyboard API a bit --- .../src/HID-APIs/ImprovedKeylayouts.h | 4 ++ .../KeyboardioHID/src/HID-APIs/KeyboardAPI.h | 8 ++-- .../src/HID-APIs/KeyboardAPI.hpp | 48 ++++++++++++------- .../src/HID-APIs/TeensyKeylayouts.h | 2 - .../src/MultiReport/ImprovedKeyboard.cpp | 4 +- .../src/MultiReport/ImprovedKeyboard.h | 2 +- .../src/SingleReport/BootKeyboard.cpp | 4 +- .../src/SingleReport/BootKeyboard.h | 2 +- 8 files changed, 45 insertions(+), 29 deletions(-) diff --git a/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h b/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h index 1b9363b65d..1f0eb8ad51 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h +++ b/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h @@ -128,6 +128,10 @@ enum KeyboardKeycode : uint8_t { KEY_LEFT_ARROW = 0x50, KEY_DOWN_ARROW = 0x51, KEY_UP_ARROW = 0x52, + KEY_RIGHT = 0x4F, // Alias + KEY_LEFT = 0x50, // Alias + KEY_DOWN = 0x51, // Alias + KEY_UP = 0x52, // Alias KEY_NUM_LOCK = 0x53, KEYPAD_DIVIDE = 0x54, KEYPAD_MULTIPLY = 0x55, diff --git a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h index 1c6f5e3567..1a96dde66f 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h +++ b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h @@ -72,13 +72,13 @@ class KeyboardAPI : public Print inline size_t remove(KeyboardModifier k); inline size_t remove(ConsumerKeycode k); - inline void releaseAll(void); - inline void removeAll(void); - inline void send_now(void); + inline size_t releaseAll(void); + inline size_t removeAll(void); + inline int send(void); inline void wakeupHost(void); // Sending is public in the base class for advanced users. - virtual void SendReport(void* data, int length) = 0; + virtual int SendReport(void* data, int length) = 0; protected: HID_KeyboardReport_Data_t _keyReport; diff --git a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.hpp b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.hpp index 648613356d..b28eea5388 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.hpp +++ b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.hpp @@ -85,7 +85,7 @@ size_t KeyboardAPI::press(uint8_t k) // Press key and send report to host auto ret = add(k); if(ret){ - send_now(); + send(); } return ret; } @@ -96,7 +96,7 @@ size_t KeyboardAPI::press(KeyboardKeycode k) // Press key and send report to host auto ret = add(k); if(ret){ - send_now(); + send(); } return ret; } @@ -107,7 +107,7 @@ size_t KeyboardAPI::press(KeyboardModifier k) // Press modifier key and send report to host auto ret = add(k); if(ret){ - send_now(); + send(); } return ret; } @@ -118,7 +118,7 @@ size_t KeyboardAPI::press(ConsumerKeycode k) // Press key and send report to host auto ret = add(k); if(ret){ - send_now(); + send(); } return ret; } @@ -174,8 +174,8 @@ size_t KeyboardAPI::add(KeyboardModifier k) size_t KeyboardAPI::add(ConsumerKeycode k) { + // No 2 byte keys are supported if(k > 0xFF){ - // No 2 byte keys are supported setWriteError(); return 0; } @@ -192,7 +192,7 @@ size_t KeyboardAPI::release(uint8_t k) // Release key and send report to host auto ret = remove(k); if(ret){ - send_now(); + send(); } return ret; } @@ -203,7 +203,7 @@ size_t KeyboardAPI::release(KeyboardKeycode k) // Release key and send report to host auto ret = remove(k); if(ret){ - send_now(); + send(); } return ret; } @@ -214,7 +214,7 @@ size_t KeyboardAPI::release(KeyboardModifier k) // Release modifier key and send report to host auto ret = remove(k); if(ret){ - send_now(); + send(); } return ret; } @@ -225,7 +225,7 @@ size_t KeyboardAPI::release(ConsumerKeycode k) // Release key and send report to host auto ret = remove(k); if(ret){ - send_now(); + send(); } return ret; } @@ -281,8 +281,8 @@ size_t KeyboardAPI::remove(KeyboardModifier k) size_t KeyboardAPI::remove(ConsumerKeycode k) { + // No 2 byte keys are supported if(k > 0xFF){ - // No 2 byte keys are supported return 0; } @@ -293,23 +293,37 @@ size_t KeyboardAPI::remove(ConsumerKeycode k) } -void KeyboardAPI::releaseAll(void) +size_t KeyboardAPI::releaseAll(void) { // Release all keys - removeAll(); - send_now(); + auto ret = removeAll(); + if(ret){ + send(); + } + return ret; } -void KeyboardAPI::removeAll(void) +size_t KeyboardAPI::removeAll(void) { // Release all keys - memset(&_keyReport, 0x00, sizeof(_keyReport)); + uint8_t ret = 0; + for (uint8_t i = 0; i < sizeof(_keyReport.keys); i++) + { + // Is a key in the list or did we found an empty slot? + if(_keyReport.keys[i]){ + ret++; + } + + _keyReport.keys[i] = KEY_RESERVED; + } + return ret; } -void KeyboardAPI::send_now(void){ - SendReport(&_keyReport, sizeof(_keyReport)); +int KeyboardAPI::send(void){ + // TODO set write error if usb send fails/disconnected? + return SendReport(&_keyReport, sizeof(_keyReport)); } diff --git a/plugins/KeyboardioHID/src/HID-APIs/TeensyKeylayouts.h b/plugins/KeyboardioHID/src/HID-APIs/TeensyKeylayouts.h index f91749a923..c6d8c913ef 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/TeensyKeylayouts.h +++ b/plugins/KeyboardioHID/src/HID-APIs/TeensyKeylayouts.h @@ -550,8 +550,6 @@ extern "C"{ #define SHIFT_MASK 0x0040 #define ALTGR_MASK 0x0080 #define DEADKEYS_MASK 0x0700 -#define SHIFT_MASK 0x0100 -#define ALTGR_MASK 0x0200 #define CIRCUMFLEX_BITS 0x0300 #define ACUTE_ACCENT_BITS 0x0400 #define GRAVE_ACCENT_BITS 0x0500 diff --git a/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.cpp index d77472b371..3ca0ae90dd 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.cpp @@ -70,9 +70,9 @@ Keyboard_::Keyboard_(void) HID().AppendDescriptor(&node); } -void Keyboard_::SendReport(void* data, int length) +int Keyboard_::SendReport(void* data, int length) { - HID().SendReport(HID_REPORTID_KEYBOARD, data, length); + return HID().SendReport(HID_REPORTID_KEYBOARD, data, length); } Keyboard_ Keyboard; diff --git a/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.h b/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.h index 7feca85028..86ff6c95ff 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.h @@ -37,7 +37,7 @@ class Keyboard_ : public KeyboardAPI Keyboard_(void); protected: - virtual inline void SendReport(void* data, int length) override; + virtual inline int SendReport(void* data, int length) override; }; extern Keyboard_ Keyboard; diff --git a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp index f8d0f240b0..bcc6904b79 100644 --- a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp @@ -156,8 +156,8 @@ uint8_t BootKeyboard_::getProtocol(void){ return protocol; } -void BootKeyboard_::SendReport(void* data, int length){ - USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, length); +int BootKeyboard_::SendReport(void* data, int length){ + return USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, length); } BootKeyboard_ BootKeyboard; diff --git a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h index b7066f947b..484b0d17ae 100644 --- a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h @@ -50,7 +50,7 @@ class BootKeyboard_ : public PluggableUSBModule, public KeyboardAPI uint8_t leds; - virtual void SendReport(void* data, int length) override; + virtual int SendReport(void* data, int length) override; }; extern BootKeyboard_ BootKeyboard; From 1ebb20d80fa77be14886e7bacd22f119cb068919 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 25 Oct 2015 12:49:59 +0100 Subject: [PATCH 308/602] Minor fix --- plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.hpp b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.hpp index b28eea5388..65e75ca2de 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.hpp +++ b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.hpp @@ -253,7 +253,7 @@ size_t KeyboardAPI::remove(uint8_t k) size_t KeyboardAPI::remove(KeyboardKeycode k) { // Test the key report to see if k is present. Clear it if it exists. - for (uint8_t i = 0; i < 6; i++) { + for (uint8_t i = 0; i < sizeof(_keyReport.keys); i++) { if (_keyReport.keys[i] == k) { _keyReport.keys[i] = KEY_RESERVED; return 1; From 91e2a62e8698d71a6a9a6f887dc4cd89ae287d12 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 25 Oct 2015 14:26:55 +0100 Subject: [PATCH 309/602] Made Keyboard API a lot more flexible --- .../src/HID-APIs/ImprovedKeylayouts.h | 32 +- .../KeyboardioHID/src/HID-APIs/KeyboardAPI.h | 76 +++-- .../src/HID-APIs/KeyboardAPI.hpp | 287 +++++++----------- .../src/MultiReport/ImprovedKeyboard.cpp | 8 +- .../src/MultiReport/ImprovedKeyboard.h | 5 +- .../src/SingleReport/BootKeyboard.cpp | 9 +- .../src/SingleReport/BootKeyboard.h | 5 +- 7 files changed, 197 insertions(+), 225 deletions(-) diff --git a/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h b/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h index 1f0eb8ad51..6c6f3e58a4 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h +++ b/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h @@ -29,19 +29,6 @@ THE SOFTWARE. #endif // Hut1_12v2.pdf -enum KeyboardModifier : uint8_t { - KEY_LEFT_CTRL = (1 << 0), - KEY_LEFT_SHIFT = (1 << 1), - KEY_LEFT_ALT = (1 << 2), - KEY_LEFT_GUI = (1 << 3), - KEY_LEFT_WINDOWS = (1 << 3), // Alias - KEY_RIGHT_CTRL = (1 << 4), - KEY_RIGHT_SHIFT = (1 << 5), - KEY_RIGHT_ALT = (1 << 6), - KEY_RIGHT_GUI = (1 << 7), - KEY_RIGHT_WINDOWS = (1 << 7), // Alias -}; - enum KeyboardKeycode : uint8_t { KEY_RESERVED = 0, KEY_ERROR_ROLLOVER = 1, @@ -267,15 +254,16 @@ enum KeyboardKeycode : uint8_t { KEYPAD_DECIMAL = 0xDC, // Disabled (Ubuntu) KEYPAD_HEXADECIMAL = 0xDD, // Disabled (Ubuntu) - // Used in KeyboardModifier enum directly - //KEY_LEFT_CTRL = 0xE0, - //KEY_LEFT_SHIFT = 0xE1, - //KEY_LEFT_ALT = 0xE2, - //KEY_LEFT_GUI = 0xE3, - //KEY_RIGHT_CTRL = 0xE4, - //KEY_RIGHT_SHIFT = 0xE5, - //KEY_RIGHT_ALT = 0xE6, - //KEY_RIGHT_GUI = 0xE7, + KEY_LEFT_CTRL = 0xE0, + KEY_LEFT_SHIFT = 0xE1, + KEY_LEFT_ALT = 0xE2, + KEY_LEFT_GUI = 0xE3, + KEY_LEFT_WINDOWS = 0xE3, // Alias + KEY_RIGHT_CTRL = 0xE4, + KEY_RIGHT_SHIFT = 0xE5, + KEY_RIGHT_ALT = 0xE6, + KEY_RIGHT_GUI = 0xE7, + KEY_RIGHT_WINDOWS = 0xE7, // Alias // Keyboard HID mappings diff --git a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h index 1a96dde66f..7689a86d42 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h +++ b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h @@ -37,52 +37,76 @@ typedef union{ struct{ uint8_t modifiers; uint8_t reserved; - KeyboardKeycode keys[6]; + KeyboardKeycode keycodes[6]; }; + uint8_t keys[8]; } HID_KeyboardReport_Data_t; + class KeyboardAPI : public Print { public: inline void begin(void); inline void end(void); - inline size_t write(uint8_t k); + // Raw Keycode API functions inline size_t write(KeyboardKeycode k); - inline size_t write(KeyboardModifier k); - inline size_t write(ConsumerKeycode k); - - inline size_t press(uint8_t k); inline size_t press(KeyboardKeycode k); - inline size_t press(KeyboardModifier k); - inline size_t press(ConsumerKeycode k); - - inline size_t release(uint8_t k); inline size_t release(KeyboardKeycode k); - inline size_t release(KeyboardModifier k); - inline size_t release(ConsumerKeycode k); - - inline size_t add(uint8_t k); + inline size_t remove(KeyboardKeycode k); inline size_t add(KeyboardKeycode k); - inline size_t add(KeyboardModifier k); - inline size_t add(ConsumerKeycode k); + inline size_t releaseAll(void); + //press(uint8_t key, uint8_t modifier) TODO variadic template + // Print API functions + inline virtual size_t write(uint8_t k) override; + inline size_t press(uint8_t k); + inline size_t release(uint8_t k); + inline size_t add(uint8_t k); inline size_t remove(uint8_t k); - inline size_t remove(KeyboardKeycode k); - inline size_t remove(KeyboardModifier k); + + // Needs to be implemented in a lower level + virtual size_t removeAll(void) = 0; + virtual int send(void) = 0; + +private: + virtual size_t set(KeyboardKeycode k, bool s) = 0; + inline size_t set(uint8_t k, bool s); +}; + +class DefaultKeyboardAPI : public KeyboardAPI +{ +public: + // Implement adding/removing key functions + inline virtual size_t removeAll(void) override; + + // Add special consumer key API for the reserved byte + inline size_t write(ConsumerKeycode k); + inline size_t press(ConsumerKeycode k); inline size_t remove(ConsumerKeycode k); - - inline size_t releaseAll(void); - inline size_t removeAll(void); - inline int send(void); - inline void wakeupHost(void); + inline size_t add(ConsumerKeycode k); + inline size_t release(ConsumerKeycode k); + + // Also use the base class functions + // http://en.cppreference.com/w/cpp/language/using_declaration + using KeyboardAPI::write; + using KeyboardAPI::press; + using KeyboardAPI::remove; + using KeyboardAPI::add; + using KeyboardAPI::release; + + // Needs to be implemented in a lower level + virtual int send(void) = 0; - // Sending is public in the base class for advanced users. - virtual int SendReport(void* data, int length) = 0; - protected: HID_KeyboardReport_Data_t _keyReport; + +private: + inline virtual size_t set(KeyboardKeycode k, bool s) override; }; +//TODO NKRO API + + // Implementation is inline #include "KeyboardAPI.hpp" diff --git a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.hpp b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.hpp index 65e75ca2de..c363c468f2 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.hpp +++ b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.hpp @@ -24,9 +24,14 @@ THE SOFTWARE. // Include guard #pragma once + void KeyboardAPI::begin(void) { - releaseAll(); + // Force API to send a clean report. + // This is important for and HID bridge where the receiver stays on, + // while the sender is resetted. + removeAll(); + send(); } @@ -36,7 +41,7 @@ void KeyboardAPI::end(void) } -size_t KeyboardAPI::write(uint8_t k) +size_t KeyboardAPI::write(KeyboardKeycode k) { // Press and release key (if press was successfull) auto ret = press(k); @@ -47,43 +52,46 @@ size_t KeyboardAPI::write(uint8_t k) } -size_t KeyboardAPI::write(KeyboardKeycode k) -{ - // Press and release key (if press was successfull) - auto ret = press(k); +size_t KeyboardAPI::press(KeyboardKeycode k) +{ + // Press key and send report to host + auto ret = add(k); if(ret){ - release(k); + send(); } return ret; } -size_t KeyboardAPI::write(KeyboardModifier k) -{ - // Press and release key (if press was successfull) - auto ret = press(k); +size_t KeyboardAPI::release(KeyboardKeycode k) +{ + // Release key and send report to host + auto ret = remove(k); if(ret){ - release(k); + send(); } return ret; } -size_t KeyboardAPI::write(ConsumerKeycode k) +size_t KeyboardAPI::add(KeyboardKeycode k) { - // Press and release key (if press was successfull) - auto ret = press(k); - if(ret){ - release(k); - } - return ret; + // Add key to report + return set(k, true); } -size_t KeyboardAPI::press(uint8_t k) +size_t KeyboardAPI::remove(KeyboardKeycode k) { - // Press key and send report to host - auto ret = add(k); + // Remove key from report + return set(k, false); +} + + +size_t KeyboardAPI::releaseAll(void) +{ + // Release all keys + auto ret = removeAll(); if(ret){ send(); } @@ -91,20 +99,20 @@ size_t KeyboardAPI::press(uint8_t k) } -size_t KeyboardAPI::press(KeyboardKeycode k) -{ - // Press key and send report to host - auto ret = add(k); +size_t KeyboardAPI::write(uint8_t k) +{ + // Press and release key (if press was successfull) + auto ret = press(k); if(ret){ - send(); + release(k); } return ret; } -size_t KeyboardAPI::press(KeyboardModifier k) +size_t KeyboardAPI::press(uint8_t k) { - // Press modifier key and send report to host + // Press key and send report to host auto ret = add(k); if(ret){ send(); @@ -113,10 +121,10 @@ size_t KeyboardAPI::press(KeyboardModifier k) } -size_t KeyboardAPI::press(ConsumerKeycode k) +size_t KeyboardAPI::release(uint8_t k) { - // Press key and send report to host - auto ret = add(k); + // Release key and send report to host + auto ret = remove(k); if(ret){ send(); } @@ -126,6 +134,19 @@ size_t KeyboardAPI::press(ConsumerKeycode k) size_t KeyboardAPI::add(uint8_t k) { + // Add key to report + return set(k, true); +} + + +size_t KeyboardAPI::remove(uint8_t k) +{ + // Remove key from report + return set(k, false); +} + + +size_t KeyboardAPI::set(uint8_t k, bool s){ // Ignore invalid input if(k >= sizeof(_asciimap)){ setWriteError(); @@ -134,85 +155,89 @@ size_t KeyboardAPI::add(uint8_t k) // Read key from ascii lookup table k = pgm_read_byte(_asciimap + k); - auto ret = add(KeyboardKeycode(k & ~SHIFT)); + auto ret = set(KeyboardKeycode(k & ~SHIFT), s); - // Only press shift and send if keycode was successfully added - if(ret && k & SHIFT){ - add(KEY_LEFT_SHIFT); + // Only add shift if keycode was successfully added before. + // Always try to release shift (if used). + if((k & SHIFT) && (ret || !s)){ + ret |= set(KEY_LEFT_SHIFT, s); } return ret; } -size_t KeyboardAPI::add(KeyboardKeycode k) +size_t DefaultKeyboardAPI::set(KeyboardKeycode k, bool s) { - // Add k to the key report only if it's not already present - // and if there is an empty slot. - for (uint8_t i = 0; i < sizeof(_keyReport.keys); i++) + // It's a modifier key + if(k >= KEY_LEFT_CTRL && k <= KEY_RIGHT_GUI) { - // Is key already in the list or did we found an empty slot? - auto key = _keyReport.keys[i]; - if (key == uint8_t(k) || key == KEY_RESERVED) { - _keyReport.keys[i] = k; - return 1; + // Convert key into bitfield (0 - 7) + k = KeyboardKeycode(uint8_t(k) - uint8_t(KEY_LEFT_CTRL)); + if(s){ + _keyReport.modifiers = (1 << k); + } + else{ + _keyReport.modifiers &= ~(1 << k); + } + return 1; + } + // Its a normal key + else{ + // Add k to the key report only if it's not already present + // and if there is an empty slot. Remove the first available key. + for (uint8_t i = 0; i < sizeof(_keyReport.keycodes); i++) + { + auto key = _keyReport.keycodes[i]; + + // Is key already in the list or did we found an empty slot? + if (s && (key == uint8_t(k) || key == KEY_RESERVED)) { + _keyReport.keycodes[i] = k; + return 1; + } + + // Test the key report to see if k is present. Clear it if it exists. + if (!s && (key == k)) { + _keyReport.keycodes[i] = KEY_RESERVED; + return 1; + } } } - // No empty key position was found - setWriteError(); + // No empty/pressed key was found return 0; } - -size_t KeyboardAPI::add(KeyboardModifier k) +size_t DefaultKeyboardAPI::removeAll(void) { - // Add modifier key - _keyReport.modifiers |= k; - return 1; -} - - -size_t KeyboardAPI::add(ConsumerKeycode k) -{ - // No 2 byte keys are supported - if(k > 0xFF){ - setWriteError(); - return 0; - } - - // Place the key inside the reserved keyreport position. - // This does not work on Windows. - _keyReport.reserved = k; - return 1; -} - - -size_t KeyboardAPI::release(uint8_t k) -{ - // Release key and send report to host - auto ret = remove(k); - if(ret){ - send(); + // Release all keys + uint8_t ret = 0; + for (uint8_t i = 0; i < sizeof(_keyReport.keys); i++) + { + // Is a key in the list or did we found an empty slot? + if(_keyReport.keys[i]){ + ret++; + } + _keyReport.keys[i] = 0x00; } return ret; } -size_t KeyboardAPI::release(KeyboardKeycode k) +size_t DefaultKeyboardAPI::write(ConsumerKeycode k) { - // Release key and send report to host - auto ret = remove(k); + // Press and release key (if press was successfull) + auto ret = press(k); if(ret){ - send(); + release(k); } return ret; } -size_t KeyboardAPI::release(KeyboardModifier k) +size_t DefaultKeyboardAPI::press(ConsumerKeycode k) { - // Release modifier key and send report to host - auto ret = remove(k); + // Press key and send report to host + auto ret = add(k); if(ret){ send(); } @@ -220,7 +245,7 @@ size_t KeyboardAPI::release(KeyboardModifier k) } -size_t KeyboardAPI::release(ConsumerKeycode k) +size_t DefaultKeyboardAPI::release(ConsumerKeycode k) { // Release key and send report to host auto ret = remove(k); @@ -231,55 +256,22 @@ size_t KeyboardAPI::release(ConsumerKeycode k) } -size_t KeyboardAPI::remove(uint8_t k) +size_t DefaultKeyboardAPI::add(ConsumerKeycode k) { - // Ignore invalid input - if(k >= sizeof(_asciimap)){ + // No 2 byte keys are supported + if(k > 0xFF){ + setWriteError(); return 0; } - - // Read key from ascii lookup table - k = pgm_read_byte(_asciimap + k); - auto ret = remove(KeyboardKeycode(k & ~SHIFT)); - - // Always try to release shift (if used) - if(k & SHIFT){ - ret |= remove(KEY_LEFT_SHIFT); - } - return ret; -} - - -size_t KeyboardAPI::remove(KeyboardKeycode k) -{ - // Test the key report to see if k is present. Clear it if it exists. - for (uint8_t i = 0; i < sizeof(_keyReport.keys); i++) { - if (_keyReport.keys[i] == k) { - _keyReport.keys[i] = KEY_RESERVED; - return 1; - } - } - - // No pressed key was found - return 0; -} - - -size_t KeyboardAPI::remove(KeyboardModifier k) -{ - // Release modifier key - auto oldModifier = _keyReport.modifiers; - _keyReport.modifiers &= ~k; - // Check if we actually released a key - if(_keyReport.modifiers != oldModifier){ - return 1; - } - return 0; + // Place the key inside the reserved keyreport position. + // This does not work on Windows. + _keyReport.reserved = k; + return 1; } -size_t KeyboardAPI::remove(ConsumerKeycode k) +size_t DefaultKeyboardAPI::remove(ConsumerKeycode k) { // No 2 byte keys are supported if(k > 0xFF){ @@ -291,46 +283,3 @@ size_t KeyboardAPI::remove(ConsumerKeycode k) _keyReport.reserved = HID_CONSUMER_UNASSIGNED; return 1; } - - -size_t KeyboardAPI::releaseAll(void) -{ - // Release all keys - auto ret = removeAll(); - if(ret){ - send(); - } - return ret; -} - - -size_t KeyboardAPI::removeAll(void) -{ - // Release all keys - uint8_t ret = 0; - for (uint8_t i = 0; i < sizeof(_keyReport.keys); i++) - { - // Is a key in the list or did we found an empty slot? - if(_keyReport.keys[i]){ - ret++; - } - - _keyReport.keys[i] = KEY_RESERVED; - } - return ret; -} - - -int KeyboardAPI::send(void){ - // TODO set write error if usb send fails/disconnected? - return SendReport(&_keyReport, sizeof(_keyReport)); -} - - -void KeyboardAPI::wakeupHost(void){ -#ifdef USBCON - USBDevice.wakeupHost(); -#endif -} - - diff --git a/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.cpp index 3ca0ae90dd..3b42a9e090 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.cpp @@ -70,9 +70,13 @@ Keyboard_::Keyboard_(void) HID().AppendDescriptor(&node); } -int Keyboard_::SendReport(void* data, int length) +int Keyboard_::send(void) { - return HID().SendReport(HID_REPORTID_KEYBOARD, data, length); + return HID().SendReport(HID_REPORTID_KEYBOARD, &_keyReport, sizeof(_keyReport)); +} + +void Keyboard_::wakeupHost(void){ + USBDevice.wakeupHost(); } Keyboard_ Keyboard; diff --git a/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.h b/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.h index 86ff6c95ff..3dc8f47d0b 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.h @@ -31,13 +31,14 @@ THE SOFTWARE. #include "../HID-APIs/KeyboardAPI.h" -class Keyboard_ : public KeyboardAPI +class Keyboard_ : public DefaultKeyboardAPI { public: Keyboard_(void); + void wakeupHost(void); protected: - virtual inline int SendReport(void* data, int length) override; + virtual inline int send(void) override; }; extern Keyboard_ Keyboard; diff --git a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp index bcc6904b79..0b4378ab22 100644 --- a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp @@ -156,10 +156,15 @@ uint8_t BootKeyboard_::getProtocol(void){ return protocol; } -int BootKeyboard_::SendReport(void* data, int length){ - return USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, length); +int BootKeyboard_::send(void){ + return USB_Send(pluggedEndpoint | TRANSFER_RELEASE, &_keyReport, sizeof(_keyReport)); } +void BootKeyboard_::wakeupHost(void){ + USBDevice.wakeupHost(); +} + + BootKeyboard_ BootKeyboard; diff --git a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h index 484b0d17ae..3c6227315a 100644 --- a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h @@ -31,12 +31,13 @@ THE SOFTWARE. #include "../HID-APIs/KeyboardAPI.h" -class BootKeyboard_ : public PluggableUSBModule, public KeyboardAPI +class BootKeyboard_ : public PluggableUSBModule, public DefaultKeyboardAPI { public: BootKeyboard_(void); uint8_t getLeds(void); uint8_t getProtocol(void); + void wakeupHost(void); protected: // Implementation of the PUSBListNode @@ -50,7 +51,7 @@ class BootKeyboard_ : public PluggableUSBModule, public KeyboardAPI uint8_t leds; - virtual int SendReport(void* data, int length) override; + virtual int send(void) override; }; extern BootKeyboard_ BootKeyboard; From a30e2275868a32399bc6be770dc4a8379971e69b Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 25 Oct 2015 15:02:41 +0100 Subject: [PATCH 310/602] Moved DefaultKeyboardAPI into separate file --- .../src/HID-APIs/DefaultKeyboardAPI.h | 77 ++++++++++ .../src/HID-APIs/DefaultKeyboardAPI.hpp | 144 ++++++++++++++++++ .../KeyboardioHID/src/HID-APIs/KeyboardAPI.h | 47 ------ .../src/HID-APIs/KeyboardAPI.hpp | 118 -------------- .../src/MultiReport/ImprovedKeyboard.h | 2 +- .../src/SingleReport/BootKeyboard.h | 2 +- 6 files changed, 223 insertions(+), 167 deletions(-) create mode 100644 plugins/KeyboardioHID/src/HID-APIs/DefaultKeyboardAPI.h create mode 100644 plugins/KeyboardioHID/src/HID-APIs/DefaultKeyboardAPI.hpp diff --git a/plugins/KeyboardioHID/src/HID-APIs/DefaultKeyboardAPI.h b/plugins/KeyboardioHID/src/HID-APIs/DefaultKeyboardAPI.h new file mode 100644 index 0000000000..b586b09b9f --- /dev/null +++ b/plugins/KeyboardioHID/src/HID-APIs/DefaultKeyboardAPI.h @@ -0,0 +1,77 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 guard +#pragma once + +#include "KeyboardAPI.h" +#include "ConsumerAPI.h" + +typedef union{ + // Low level key report: up to 6 keys and shift, ctrl etc at once + uint8_t whole8[]; + uint16_t whole16[]; + uint32_t whole32[]; + struct{ + uint8_t modifiers; + uint8_t reserved; + KeyboardKeycode keycodes[6]; + }; + uint8_t keys[8]; +} HID_KeyboardReport_Data_t; + + +class DefaultKeyboardAPI : public KeyboardAPI +{ +public: + // Add special consumer key API for the reserved byte + inline size_t write(ConsumerKeycode k); + inline size_t press(ConsumerKeycode k); + inline size_t release(ConsumerKeycode k); + inline size_t add(ConsumerKeycode k); + inline size_t remove(ConsumerKeycode k); + + // Also use the base class functions + // http://en.cppreference.com/w/cpp/language/using_declaration + using KeyboardAPI::write; + using KeyboardAPI::press; + using KeyboardAPI::release; + using KeyboardAPI::add; + using KeyboardAPI::remove; + + // Implement adding/removing key functions + inline virtual size_t removeAll(void) override; + + // Needs to be implemented in a lower level + virtual int send(void) = 0; + +protected: + HID_KeyboardReport_Data_t _keyReport; + +private: + inline virtual size_t set(KeyboardKeycode k, bool s) override; +}; + +// Implementation is inline +#include "DefaultKeyboardAPI.hpp" + diff --git a/plugins/KeyboardioHID/src/HID-APIs/DefaultKeyboardAPI.hpp b/plugins/KeyboardioHID/src/HID-APIs/DefaultKeyboardAPI.hpp new file mode 100644 index 0000000000..7ca2071309 --- /dev/null +++ b/plugins/KeyboardioHID/src/HID-APIs/DefaultKeyboardAPI.hpp @@ -0,0 +1,144 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 guard +#pragma once + + +size_t DefaultKeyboardAPI::set(KeyboardKeycode k, bool s) +{ + // It's a modifier key + if(k >= KEY_LEFT_CTRL && k <= KEY_RIGHT_GUI) + { + // Convert key into bitfield (0 - 7) + k = KeyboardKeycode(uint8_t(k) - uint8_t(KEY_LEFT_CTRL)); + if(s){ + _keyReport.modifiers = (1 << k); + } + else{ + _keyReport.modifiers &= ~(1 << k); + } + return 1; + } + // Its a normal key + else{ + // Add k to the key report only if it's not already present + // and if there is an empty slot. Remove the first available key. + for (uint8_t i = 0; i < sizeof(_keyReport.keycodes); i++) + { + auto key = _keyReport.keycodes[i]; + + // Is key already in the list or did we found an empty slot? + if (s && (key == uint8_t(k) || key == KEY_RESERVED)) { + _keyReport.keycodes[i] = k; + return 1; + } + + // Test the key report to see if k is present. Clear it if it exists. + if (!s && (key == k)) { + _keyReport.keycodes[i] = KEY_RESERVED; + return 1; + } + } + } + + // No empty/pressed key was found + return 0; +} + +size_t DefaultKeyboardAPI::removeAll(void) +{ + // Release all keys + size_t ret = 0; + for (uint8_t i = 0; i < sizeof(_keyReport.keys); i++) + { + // Is a key in the list or did we found an empty slot? + if(_keyReport.keys[i]){ + ret++; + } + _keyReport.keys[i] = 0x00; + } + return ret; +} + + +size_t DefaultKeyboardAPI::write(ConsumerKeycode k) +{ + // Press and release key (if press was successfull) + auto ret = press(k); + if(ret){ + release(k); + } + return ret; +} + + +size_t DefaultKeyboardAPI::press(ConsumerKeycode k) +{ + // Press key and send report to host + auto ret = add(k); + if(ret){ + send(); + } + return ret; +} + + +size_t DefaultKeyboardAPI::release(ConsumerKeycode k) +{ + // Release key and send report to host + auto ret = remove(k); + if(ret){ + send(); + } + return ret; +} + + +size_t DefaultKeyboardAPI::add(ConsumerKeycode k) +{ + // No 2 byte keys are supported + if(k > 0xFF){ + setWriteError(); + return 0; + } + + // Place the key inside the reserved keyreport position. + // This does not work on Windows. + _keyReport.reserved = k; + return 1; +} + + +size_t DefaultKeyboardAPI::remove(ConsumerKeycode k) +{ + // No 2 byte keys are supported + if(k > 0xFF){ + return 0; + } + + // Always release the key, to make it simpler releasing a consumer key + // without releasing all other normal keyboard keys. + _keyReport.reserved = HID_CONSUMER_UNASSIGNED; + return 1; +} diff --git a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h index 7689a86d42..81a589fb10 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h +++ b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h @@ -27,20 +27,6 @@ THE SOFTWARE. #include #include "HID-Settings.h" #include "ImprovedKeylayouts.h" -#include "ConsumerAPI.h" - -typedef union{ - // Low level key report: up to 6 keys and shift, ctrl etc at once - uint8_t whole8[]; - uint16_t whole16[]; - uint32_t whole32[]; - struct{ - uint8_t modifiers; - uint8_t reserved; - KeyboardKeycode keycodes[6]; - }; - uint8_t keys[8]; -} HID_KeyboardReport_Data_t; class KeyboardAPI : public Print @@ -74,39 +60,6 @@ class KeyboardAPI : public Print inline size_t set(uint8_t k, bool s); }; -class DefaultKeyboardAPI : public KeyboardAPI -{ -public: - // Implement adding/removing key functions - inline virtual size_t removeAll(void) override; - - // Add special consumer key API for the reserved byte - inline size_t write(ConsumerKeycode k); - inline size_t press(ConsumerKeycode k); - inline size_t remove(ConsumerKeycode k); - inline size_t add(ConsumerKeycode k); - inline size_t release(ConsumerKeycode k); - - // Also use the base class functions - // http://en.cppreference.com/w/cpp/language/using_declaration - using KeyboardAPI::write; - using KeyboardAPI::press; - using KeyboardAPI::remove; - using KeyboardAPI::add; - using KeyboardAPI::release; - - // Needs to be implemented in a lower level - virtual int send(void) = 0; - -protected: - HID_KeyboardReport_Data_t _keyReport; - -private: - inline virtual size_t set(KeyboardKeycode k, bool s) override; -}; - -//TODO NKRO API - // Implementation is inline #include "KeyboardAPI.hpp" diff --git a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.hpp b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.hpp index c363c468f2..2cbe6fcb79 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.hpp +++ b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.hpp @@ -165,121 +165,3 @@ size_t KeyboardAPI::set(uint8_t k, bool s){ return ret; } - -size_t DefaultKeyboardAPI::set(KeyboardKeycode k, bool s) -{ - // It's a modifier key - if(k >= KEY_LEFT_CTRL && k <= KEY_RIGHT_GUI) - { - // Convert key into bitfield (0 - 7) - k = KeyboardKeycode(uint8_t(k) - uint8_t(KEY_LEFT_CTRL)); - if(s){ - _keyReport.modifiers = (1 << k); - } - else{ - _keyReport.modifiers &= ~(1 << k); - } - return 1; - } - // Its a normal key - else{ - // Add k to the key report only if it's not already present - // and if there is an empty slot. Remove the first available key. - for (uint8_t i = 0; i < sizeof(_keyReport.keycodes); i++) - { - auto key = _keyReport.keycodes[i]; - - // Is key already in the list or did we found an empty slot? - if (s && (key == uint8_t(k) || key == KEY_RESERVED)) { - _keyReport.keycodes[i] = k; - return 1; - } - - // Test the key report to see if k is present. Clear it if it exists. - if (!s && (key == k)) { - _keyReport.keycodes[i] = KEY_RESERVED; - return 1; - } - } - } - - // No empty/pressed key was found - return 0; -} - -size_t DefaultKeyboardAPI::removeAll(void) -{ - // Release all keys - uint8_t ret = 0; - for (uint8_t i = 0; i < sizeof(_keyReport.keys); i++) - { - // Is a key in the list or did we found an empty slot? - if(_keyReport.keys[i]){ - ret++; - } - _keyReport.keys[i] = 0x00; - } - return ret; -} - - -size_t DefaultKeyboardAPI::write(ConsumerKeycode k) -{ - // Press and release key (if press was successfull) - auto ret = press(k); - if(ret){ - release(k); - } - return ret; -} - - -size_t DefaultKeyboardAPI::press(ConsumerKeycode k) -{ - // Press key and send report to host - auto ret = add(k); - if(ret){ - send(); - } - return ret; -} - - -size_t DefaultKeyboardAPI::release(ConsumerKeycode k) -{ - // Release key and send report to host - auto ret = remove(k); - if(ret){ - send(); - } - return ret; -} - - -size_t DefaultKeyboardAPI::add(ConsumerKeycode k) -{ - // No 2 byte keys are supported - if(k > 0xFF){ - setWriteError(); - return 0; - } - - // Place the key inside the reserved keyreport position. - // This does not work on Windows. - _keyReport.reserved = k; - return 1; -} - - -size_t DefaultKeyboardAPI::remove(ConsumerKeycode k) -{ - // No 2 byte keys are supported - if(k > 0xFF){ - return 0; - } - - // Always release the key, to make it simpler releasing a consumer key - // without releasing all other normal keyboard keys. - _keyReport.reserved = HID_CONSUMER_UNASSIGNED; - return 1; -} diff --git a/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.h b/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.h index 3dc8f47d0b..d9185cf27e 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.h @@ -28,7 +28,7 @@ THE SOFTWARE. #include "PluggableUSB.h" #include "HID.h" #include "HID-Settings.h" -#include "../HID-APIs/KeyboardAPI.h" +#include "../HID-APIs/DefaultKeyboardAPI.h" class Keyboard_ : public DefaultKeyboardAPI diff --git a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h index 3c6227315a..4d83e722e2 100644 --- a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h @@ -28,7 +28,7 @@ THE SOFTWARE. #include "PluggableUSB.h" #include "HID.h" #include "HID-Settings.h" -#include "../HID-APIs/KeyboardAPI.h" +#include "../HID-APIs/DefaultKeyboardAPI.h" class BootKeyboard_ : public PluggableUSBModule, public DefaultKeyboardAPI From 74541f90340abec4a5892ebf2abf6eaaed06ca01 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 25 Oct 2015 15:07:10 +0100 Subject: [PATCH 311/602] Added 2 consumer key definitions --- plugins/KeyboardioHID/src/HID-APIs/ConsumerAPI.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/KeyboardioHID/src/HID-APIs/ConsumerAPI.h b/plugins/KeyboardioHID/src/HID-APIs/ConsumerAPI.h index 66f65a37d0..33558b65ae 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/ConsumerAPI.h +++ b/plugins/KeyboardioHID/src/HID-APIs/ConsumerAPI.h @@ -32,6 +32,7 @@ enum ConsumerKeycode : uint16_t { CONSUMER_POWER = 0x30, CONSUMER_SLEEP = 0x32, + MEDIA_RECORD = 0xB2, MEDIA_FAST_FORWARD = 0xB3, MEDIA_REWIND = 0xB4, MEDIA_NEXT = 0xB5, @@ -39,6 +40,7 @@ enum ConsumerKeycode : uint16_t { MEDIA_PREV = 0xB6, // Alias MEDIA_STOP = 0xB7, MEDIA_PLAY_PAUSE = 0xCD, + MEDIA_PAUSE = 0xB0, MEDIA_VOLUME_MUTE = 0xE2, MEDIA_VOL_MUTE = 0xE2, // Alias From 40694d396215d1d0e809b27cd164e8f80fae7e72 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 25 Oct 2015 15:07:57 +0100 Subject: [PATCH 312/602] Updated NKRO API to new Keyboard API style --- .../src/HID-APIs/NKROKeyboardAPI.h | 37 +-- .../src/HID-APIs/NKROKeyboardAPI.hpp | 224 ++++-------------- .../src/MultiReport/NKROKeyboard.cpp | 4 +- .../src/MultiReport/NKROKeyboard.h | 2 +- .../src/SingleReport/SingleNKROKeyboard.cpp | 4 +- .../src/SingleReport/SingleNKROKeyboard.h | 2 +- 6 files changed, 69 insertions(+), 204 deletions(-) diff --git a/plugins/KeyboardioHID/src/HID-APIs/NKROKeyboardAPI.h b/plugins/KeyboardioHID/src/HID-APIs/NKROKeyboardAPI.h index c5a9fec589..7dafbd7a04 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/NKROKeyboardAPI.h +++ b/plugins/KeyboardioHID/src/HID-APIs/NKROKeyboardAPI.h @@ -24,10 +24,7 @@ THE SOFTWARE. // Include guard #pragma once -#include -#include "HID-Settings.h" -#include "ImprovedKeylayouts.h" -#include "HID-Tables.h" //TODO +#include "KeyboardAPI.h" // Max value for USB EP_SIZE 16 // +1 reportID, +1 modifier, +1 custom key @@ -43,34 +40,24 @@ typedef union{ uint8_t keys[NKRO_KEY_COUNT / 8]; uint8_t key; }; + uint8_t allkeys[2 + NKRO_KEY_COUNT / 8]; } HID_NKROKeyboardReport_Data_t; -class NKROKeyboardAPI : public Print +class NKROKeyboardAPI : public KeyboardAPI { public: - inline NKROKeyboardAPI(void); - inline void begin(void); - inline void end(void); - inline size_t write(uint8_t k); - inline size_t press(uint8_t k); - inline size_t release(uint8_t k); - inline void releaseAll(void); - inline void send_now(void); + // Implement adding/removing key functions + inline virtual size_t removeAll(void) override; + + // Needs to be implemented in a lower level + virtual int send(void) = 0; - inline size_t writeKeycode(uint8_t k); - inline size_t pressKeycode(uint8_t k); - inline size_t releaseKeycode(uint8_t k); - inline size_t addKeyToReport(uint8_t k); - inline size_t addKeycodeToReport(uint8_t k); - inline size_t removeKeyFromReport(uint8_t k); - inline size_t removeKeycodeFromReport(uint8_t k); - - // Sending is public in the base class for advanced users. - virtual void SendReport(void* data, int length) = 0; - protected: - HID_NKROKeyboardReport_Data_t _keyReport; + HID_NKROKeyboardReport_Data_t _keyReport; + +private: + inline virtual size_t set(KeyboardKeycode k, bool s) override; }; // Implementation is inline diff --git a/plugins/KeyboardioHID/src/HID-APIs/NKROKeyboardAPI.hpp b/plugins/KeyboardioHID/src/HID-APIs/NKROKeyboardAPI.hpp index 9d15ed743d..fe9e6d6355 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/NKROKeyboardAPI.hpp +++ b/plugins/KeyboardioHID/src/HID-APIs/NKROKeyboardAPI.hpp @@ -24,193 +24,71 @@ THE SOFTWARE. // Include guard #pragma once -NKROKeyboardAPI::NKROKeyboardAPI(void) -{ - // Empty -} - -void NKROKeyboardAPI::begin(void) -{ - releaseAll(); -} - -void NKROKeyboardAPI::end(void) -{ - releaseAll(); -} - -void NKROKeyboardAPI::send_now(void){ - SendReport(&_keyReport, sizeof(_keyReport)); -} - -// 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 NKROKeyboardAPI::press(uint8_t k) -{ - size_t ret = addKeyToReport(k); - if(ret){ - send_now(); - } - return ret; -} -// 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 NKROKeyboardAPI::release(uint8_t k) +size_t NKROKeyboardAPI::set(KeyboardKeycode k, bool s) { - // it's a non-printing key (not a modifier) - if (k >= 136) - k = k - 136; - - // it's a modifier key - else if (k >= 128) - k = k - 128; - - // it's a printing key - else { - k = pgm_read_byte(_asciimap + k); - if (!k) - return 0; - - // it's a capital letter or other character reached with shift - if (k & SHIFT) { - // the left shift modifier - _keyReport.modifiers &= ~(0x02); - k = k ^ SHIFT; + // Press keymap key + if (k < NKRO_KEY_COUNT){ + uint8_t bit = 1 << (uint8_t(k) % 8); + if(s){ + _keyReport.keys[k / 8] |= bit; } + else{ + _keyReport.keys[k / 8] &= ~bit; + } + return 1; } - removeKeycodeFromReport(k); - send_now(); - - return 1; -} - -void NKROKeyboardAPI::releaseAll(void) -{ - // release all keys - memset(&_keyReport, 0x00, sizeof(_keyReport)); - send_now(); -} - -size_t NKROKeyboardAPI::write(uint8_t c) -{ - uint8_t p = press(c); // Keydown - release(c); // Keyup - return p; // just return the result of press() since release() almost always returns 1 -} - - -// pressKeycode() 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 releaseKeycode(), releaseAll(), or otherwise clear the report and resend. -size_t NKROKeyboardAPI::pressKeycode(uint8_t k) -{ - if (!addKeycodeToReport(k)) { - return 0; - } - send_now(); -} - -size_t NKROKeyboardAPI::addKeyToReport(uint8_t k) -{ - 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; //TODO return 1?? - } else { // it's a printing key - k = pgm_read_byte(_asciimap + k); - if (!k) { - setWriteError(); - return 0; + // It's a modifier key + else if(k >= KEY_LEFT_CTRL && k <= KEY_RIGHT_GUI) + { + // Convert key into bitfield (0 - 7) + k = KeyboardKeycode(uint8_t(k) - uint8_t(KEY_LEFT_CTRL)); + if(s){ + _keyReport.modifiers = (1 << k); } - if (k & SHIFT) { // it's a capital letter or other character reached with shift - _keyReport.modifiers |= 0x02; // the left shift modifier - k = k ^ SHIFT; + else{ + _keyReport.modifiers &= ~(1 << k); } + return 1; } - - return addKeycodeToReport(k); -} - -size_t NKROKeyboardAPI::addKeycodeToReport(uint8_t k) -{ - // keymap key - if (k < NKRO_KEY_COUNT) - _keyReport.keys[k / 8] |= 1 << (k % 8); - - // it's a modifier key - else if ((k >= HID_KEYBOARD_LEFT_CONTROL) && (k <= HID_KEYBOARD_RIGHT_GUI)) - _keyReport.modifiers |= (0x01 << (k - HID_KEYBOARD_LEFT_CONTROL)); - - // custom key - else - _keyReport.key = k; - - return 1; -} - - -// releaseKeycode() 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. -// When send is set to FALSE (= 0) no sendReport() is executed. This comes in -// handy when combining key releases (e.g. SHIFT+A). -size_t NKROKeyboardAPI::releaseKeycode(uint8_t k) -{ - if (!removeKeycodeFromReport(k)) { - return 0; - } - send_now(); -} - -size_t NKROKeyboardAPI::removeKeyFromReport(uint8_t k) -{ - 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; + + // Its a custom key (outside our keymap) + else{ + // Add k to the key report only if it's not already present + // and if there is an empty slot. Remove the first available key. + auto key = _keyReport.key; + + // Is key already in the list or did we found an empty slot? + if (s && (key == uint8_t(k) || key == KEY_RESERVED)) { + _keyReport.key = k; + return 1; } - if (k & SHIFT) { // it's a capital letter or other character reached with shift - _keyReport.modifiers &= ~(0x02); // the left shift modifier - k = k ^ SHIFT; + + // Test the key report to see if k is present. Clear it if it exists. + if (!s && (key == k)) { + _keyReport.key = KEY_RESERVED; + return 1; } } - return removeKeycodeFromReport(k); + // No empty/pressed key was found + return 0; } -size_t NKROKeyboardAPI::removeKeycodeFromReport(uint8_t k) +size_t NKROKeyboardAPI::removeAll(void) { - // keymap key - if (k < NKRO_KEY_COUNT) - _keyReport.keys[k / 8] &= ~(1 << (k % 8)); - - // it's a modifier key - else if ((k >= HID_KEYBOARD_LEFT_CONTROL) && (k <= HID_KEYBOARD_RIGHT_GUI)) - _keyReport.modifiers &= ~(0x01 << (k - HID_KEYBOARD_LEFT_CONTROL)); - - // custom key - else - _keyReport.key = 0x00; - - return 1; + // Release all keys + size_t ret = 0; + for (uint8_t i = 0; i < sizeof(_keyReport.allkeys); i++) + { + // Is a key in the list or did we found an empty slot? + //TODO count every bit? + if(_keyReport.allkeys[i]){ + ret++; + } + _keyReport.allkeys[i] = 0x00; + } + return ret; } - -size_t NKROKeyboardAPI::writeKeycode(uint8_t c) -{ - uint8_t p = pressKeycode(c); // Keydown - releaseKeycode(c); // Keyup - return (p); // just return the result of pressKeycode() since release() almost always returns 1 -} diff --git a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp index 4accc878d0..27c2148721 100644 --- a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp @@ -68,9 +68,9 @@ NKROKeyboard_::NKROKeyboard_(void) HID().AppendDescriptor(&node); } -void NKROKeyboard_::SendReport(void* data, int length) +int NKROKeyboard_::send(void) { - HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, data, length); + return HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &_keyReport, sizeof(_keyReport)); } NKROKeyboard_ NKROKeyboard; diff --git a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h index 7b94add67a..933c12762f 100644 --- a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h @@ -37,7 +37,7 @@ class NKROKeyboard_ : public NKROKeyboardAPI NKROKeyboard_(void); protected: - virtual inline void SendReport(void* data, int length) override; + virtual inline int send(void) override; }; extern NKROKeyboard_ NKROKeyboard; diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.cpp b/plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.cpp index c5d5e2414d..ab7c269258 100644 --- a/plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.cpp @@ -151,8 +151,8 @@ uint8_t SingleNKROKeyboard_::getLeds(void){ return leds; } -void SingleNKROKeyboard_::SendReport(void* data, int length){ - USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, length); +int SingleNKROKeyboard_::send(void){ + return USB_Send(pluggedEndpoint | TRANSFER_RELEASE, &_keyReport, sizeof(_keyReport)); } SingleNKROKeyboard_ SingleNKROKeyboard; diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.h b/plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.h index 131eaa3966..422a47b3e3 100644 --- a/plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.h +++ b/plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.h @@ -50,7 +50,7 @@ class SingleNKROKeyboard_ : public PluggableUSBModule, public NKROKeyboardAPI uint8_t leds; - virtual void SendReport(void* data, int length) override; + virtual inline int send(void) override; }; extern SingleNKROKeyboard_ SingleNKROKeyboard; From b0d57f0977dddea02b398228d268a699de7a2e77 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 25 Oct 2015 15:19:11 +0100 Subject: [PATCH 313/602] Added NKRO key bit count --- plugins/KeyboardioHID/src/HID-APIs/NKROKeyboardAPI.hpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/plugins/KeyboardioHID/src/HID-APIs/NKROKeyboardAPI.hpp b/plugins/KeyboardioHID/src/HID-APIs/NKROKeyboardAPI.hpp index fe9e6d6355..44e04b3752 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/NKROKeyboardAPI.hpp +++ b/plugins/KeyboardioHID/src/HID-APIs/NKROKeyboardAPI.hpp @@ -83,10 +83,14 @@ size_t NKROKeyboardAPI::removeAll(void) for (uint8_t i = 0; i < sizeof(_keyReport.allkeys); i++) { // Is a key in the list or did we found an empty slot? - //TODO count every bit? - if(_keyReport.allkeys[i]){ - ret++; + auto bits = _keyReport.allkeys[i]; + do { + if(bits & 0x01){ + ret++; + } + bits >>=1; } + while(bits); _keyReport.allkeys[i] = 0x00; } return ret; From 6d854212b79fdea7fcd6578d8bb39f56b9c75116 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Fri, 6 Nov 2015 19:01:52 +0100 Subject: [PATCH 314/602] Minor changes --- plugins/KeyboardioHID/Readme.md | 1 + plugins/KeyboardioHID/src/HID-Project.h | 13 ++++--------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 71037aa6c6..476d730ce8 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -13,6 +13,7 @@ The idea is to enable enhanced USB functions to almost all 'standard' Arduino bo * Leonardo * (Pro)Micro * Any other 8u2/16u2/at90usb8/162/32u2/32u4 compatible board +* No SAM/ARM support (Due, Zero etc) **Supported HID devices:** * Keyboard with Leds out (modifiers + 6 keys pressed at the same time) diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index f6b3d6c1cc..0a0dde7c06 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -27,8 +27,6 @@ THE SOFTWARE. // Software version #define HID_PROJECT_VERSION 240 -#include //TODO - #if ARDUINO < 10606 #error HID Project requires Arduino IDE 1.6.6 or greater. Please update your IDE. #endif @@ -46,14 +44,11 @@ THE SOFTWARE. #include "MultiReport/Gamepad.h" #include "MultiReport/System.h" #include "SingleReport/RawHID.h" - -// Include Teensy HID afterwards to overwrite key definitions if used -// TODO include Teensy API if non english keyboard layout was used -#ifdef USE_TEENSY_KEYBOARD -//#include "TeensyKeyboard.h" -#else #include "SingleReport/BootKeyboard.h" #include "MultiReport/ImprovedKeyboard.h" #include "SingleReport/SingleNKROKeyboard.h" #include "MultiReport/NKROKeyboard.h" -#endif + +// Include Teensy HID afterwards to overwrite key definitions if used +// TODO include Teensy API if non english keyboard layout was used + From dc1f6773288ee59a69ebd664ec5ffb3bab7f7dd5 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Fri, 6 Nov 2015 19:05:04 +0100 Subject: [PATCH 315/602] Bootkeyboard send protocol and idle time Idle time will not change (is not implemented) So it is unsure what the host will do --- plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp index 0b4378ab22..debadb38b4 100644 --- a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp @@ -120,7 +120,11 @@ bool BootKeyboard_::setup(USBSetup& setup) return true; } if (request == HID_GET_PROTOCOL) { - // TODO: Send8(protocol); + UEDATX = protocol; + return true; + } + if (request == HID_GET_IDLE) { + UEDATX = idle; return true; } } From eee7876f5129f9ffeff5c65204690a7a0541105d Mon Sep 17 00:00:00 2001 From: NicoHood Date: Fri, 6 Nov 2015 21:04:40 +0100 Subject: [PATCH 316/602] Updated RawHID, added Event function Found a comprimiss between interrupt processing, prebuffering and processing long data inputs as well. --- .../KeyboardioHID/examples/RawHID/RawHID.ino | 69 ++++++++++++++++--- plugins/KeyboardioHID/src/HID-Project.h | 3 + plugins/KeyboardioHID/src/HID-Settings.h | 2 +- .../KeyboardioHID/src/SingleReport/RawHID.cpp | 65 +++++++++-------- .../KeyboardioHID/src/SingleReport/RawHID.h | 31 ++++----- 5 files changed, 111 insertions(+), 59 deletions(-) diff --git a/plugins/KeyboardioHID/examples/RawHID/RawHID.ino b/plugins/KeyboardioHID/examples/RawHID/RawHID.ino index 6da4f58c1a..04ff20983a 100644 --- a/plugins/KeyboardioHID/examples/RawHID/RawHID.ino +++ b/plugins/KeyboardioHID/examples/RawHID/RawHID.ino @@ -7,6 +7,12 @@ Shows how to send bytes via RawHID. Press a button to send some example values. + Every received data is mirrored to the host. + The use of the RawHIDEvent() function is shown too. + + This sketch only tries to show the possiblities + and is not perfect.You might want to use RawHID differently. + See HID Project documentation for more information. https://github.com/NicoHood/HID/wiki/RawHID-API */ @@ -16,20 +22,26 @@ const int pinLed = LED_BUILTIN; const int pinButton = 2; +uint8_t data[255]; +volatile size_t len = 0; + void setup() { pinMode(pinLed, OUTPUT); pinMode(pinButton, INPUT_PULLUP); - // No begin function needed for RawHID + + // No begin/end function required for RawHID } void loop() { + // Send data to the host if (!digitalRead(pinButton)) { digitalWrite(pinLed, HIGH); - // Create buffer and send it + // Create buffer with numbers and send it uint8_t megabuff[100]; - for (int i = 0; i < sizeof(megabuff); i++) + for (uint8_t i = 0; i < sizeof(megabuff); i++) { megabuff[i] = i; + } RawHID.write(megabuff, sizeof(megabuff)); // Simple debounce @@ -37,20 +49,55 @@ void loop() { digitalWrite(pinLed, LOW); } - uint8_t len = RawHID.available(); + + // This will miss longer RawHID data transmissions + // and return an error to the host if data was missed. + // Only use this for non changing/less important data. + // Or you can use this if the event aborted on a full buffer. + // Please note, that all data after this full buffer is missed anyways. + auto bytesAvailable = RawHID.available(); + while (bytesAvailable--) { + if (len < sizeof(data)) { + data[len++] = RawHID.read(); + } + } + + // Process data from the host if (len) { digitalWrite(pinLed, HIGH); + // Disable interrupts while processing the data + uint8_t oldSREG = SREG; + cli(); + // Mirror the incoming data from the host back - uint8_t buff[len + 1]; - buff[0] = len; - for (int i = 1; i < sizeof(buff); i++) { - buff[i] = RawHID.read(); - } - RawHID.write(buff, len); + RawHID.write(data, len); + len = 0; - // Simple debounce + SREG = oldSREG; + + // Simple debounce for led delay(300); digitalWrite(pinLed, LOW); } } + +void RawHIDEvent(void) { + // This event is called via interrupt. + // Do not use print inside, or other long function calls! + // If you not use this event function, + // you might miss some data in the loop, + // if the host sends too fast or too much data at once. + + auto bytesAvailable = RawHID.available(); + while (bytesAvailable--) { + // Only add data to the buffer if its not full. + // If it is, no more event will occur + // and the data should be discarded + // or read (as shown) in the loop above. + if (len < sizeof(data)) { + data[len++] = RawHID.read(); + } + } +} + diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index 0a0dde7c06..8b5aaf205a 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -27,6 +27,9 @@ THE SOFTWARE. // Software version #define HID_PROJECT_VERSION 240 +// TODO remove https://github.com/arduino/arduino-builder/issues/33 +#include + #if ARDUINO < 10606 #error HID Project requires Arduino IDE 1.6.6 or greater. Please update your IDE. #endif diff --git a/plugins/KeyboardioHID/src/HID-Settings.h b/plugins/KeyboardioHID/src/HID-Settings.h index b95de02e30..692186bd9f 100644 --- a/plugins/KeyboardioHID/src/HID-Settings.h +++ b/plugins/KeyboardioHID/src/HID-Settings.h @@ -82,7 +82,7 @@ THE SOFTWARE. #ifndef HID_REPORTID_RAWHID // This will not work properly in most cases. // The number is just kept from the old number counting. -#define HID_REPORTID_RAWHID 3 +//#define HID_REPORTID_RAWHID 3 #endif #ifndef HID_REPORTID_CONSUMERCONTROL diff --git a/plugins/KeyboardioHID/src/SingleReport/RawHID.cpp b/plugins/KeyboardioHID/src/SingleReport/RawHID.cpp index 66c9d1b920..3cafe96125 100644 --- a/plugins/KeyboardioHID/src/SingleReport/RawHID.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/RawHID.cpp @@ -47,6 +47,12 @@ static const uint8_t _hidReportDescriptorRawHID[] PROGMEM = { 0xC0 /* end collection */ }; +// Weak implementation of the Event function +void RawHIDEvent(void) __attribute__ ((weak)); +void RawHIDEvent(void){ + // Empty +} + RawHID_::RawHID_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1), dataLength(0) { epType[0] = EP_TYPE_INTERRUPT_IN; @@ -55,7 +61,6 @@ RawHID_::RawHID_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_P int RawHID_::getInterface(uint8_t* interfaceCount) { - // TODO add a 2nd OUT endpoint to get more speed??? // Maybe as optional device FastRawHID with different USAGE PAGE *interfaceCount += 1; // uses 1 HIDDescriptor hidInterface = { @@ -117,36 +122,40 @@ bool RawHID_::setup(USBSetup& setup) { // Get the data length information and the corresponding bytes int length = setup.wLength; - - // Ensure that there IS some data - if(length > 0) + while(length) { - void* data = malloc(length); - if(data){ - auto recvLength = length; - //TODO loop can be improved maybe? Or does the compiler do this already? - while(recvLength > USB_EP_SIZE){ - USB_RecvControl((uint8_t*)data + (length - recvLength), USB_EP_SIZE); - recvLength -= USB_EP_SIZE; - } - USB_RecvControl((uint8_t*)data + (length - recvLength), recvLength); - - // Only overwrite the buffer if its empty. - // This avoids corrupted data while reading. - if(!dataLength){ - // Save new data - dataLength = length; - dataHead = (uint8_t*) data; - dataTail = (uint8_t*)(data) + length; - - // Clear the passed in pointer to not free the data - data = NULL; - } + // Dont receive more than the USB EP has to offer + // TODO use fixed 64 because control EP always have 64 bytes even on 16 u2. Test! + auto recvLength = length; + if(recvLength > USB_EP_SIZE){ + recvLength = USB_EP_SIZE; + } + if(recvLength > int(sizeof(data))){ + recvLength = int(sizeof(data)); + } + length -= recvLength; + + // Only receive data if the last one was read fully. + // Discard data if it wasnt read yet. + // To not miss any data you can use the (weak) event function. + if(!dataLength) + { + // Write data to fit to the end (not the beginning) of the array + USB_RecvControl(data + (sizeof(data) - recvLength), recvLength); + dataLength = recvLength; + RawHIDEvent(); + } + // Do not read the data, flag an error to the USB Host + // TODO always return no error, even if data was discarded? -> use break then + else{ + return false; } - - // Release data if the pointer still exists - free(data); } + + // Flag no error + // TODO this is required to get hyperion working + // however this blocks the CDC serial!? + return true; } } diff --git a/plugins/KeyboardioHID/src/SingleReport/RawHID.h b/plugins/KeyboardioHID/src/SingleReport/RawHID.h index 2a365e217a..5f2249cf97 100644 --- a/plugins/KeyboardioHID/src/SingleReport/RawHID.h +++ b/plugins/KeyboardioHID/src/SingleReport/RawHID.h @@ -40,6 +40,8 @@ THE SOFTWARE. // Keep one byte offset for the reportID if used #if (HID_REPORTID_RAWHID) #define RAWHID_SIZE (USB_EP_SIZE-1) +#error RAWHID does not work properly with a report ID and multiple reports. +#error Please remove this manually if you know what you are doing. #else #define RAWHID_SIZE (USB_EP_SIZE) #endif @@ -84,36 +86,28 @@ class RawHID_ : public PluggableUSBModule, public Stream } virtual int read(){ - if(dataLength){ - // Get next data byte - uint8_t data = *(dataTail - dataLength); - dataLength--; - - // Release buffer if its read fully - if(!dataLength){ - free(dataHead); - } - - return data; + // Check if we have data available + if(dataLength) + { + // Get next data byte (from the start to the end) + return data[sizeof(data) - dataLength--]; } return -1; } virtual int peek(){ + // Check if we have data available if(dataLength){ - return *(dataTail - dataLength); + return data[sizeof(data) - dataLength]; } return -1; } virtual void flush(void){ - // Delete all incoming bytes - if(dataLength){ - free(dataHead); - dataLength = 0; - } + // Writing will always flush by the USB driver } + // Wrapper for a single byte using Print::write; virtual size_t write(uint8_t b){ return write(&b, 1); @@ -153,8 +147,7 @@ class RawHID_ : public PluggableUSBModule, public Stream // Buffer pointers to hold the received data int dataLength; - uint8_t* dataHead; - uint8_t* dataTail; + uint8_t data[RAWHID_RX_SIZE]; }; extern RawHID_ RawHID; From 236321927796215dab6bdb4450583c8623907b37 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Fri, 6 Nov 2015 21:25:14 +0100 Subject: [PATCH 317/602] Added Single Consumer API --- .../examples/Consumer/Consumer.ino | 2 + plugins/KeyboardioHID/keywords.txt | 1 + plugins/KeyboardioHID/src/HID-Project.h | 1 + .../src/SingleReport/SingleConsumer.cpp | 121 ++++++++++++++++++ .../src/SingleReport/SingleConsumer.h | 55 ++++++++ 5 files changed, 180 insertions(+) create mode 100644 plugins/KeyboardioHID/src/SingleReport/SingleConsumer.cpp create mode 100644 plugins/KeyboardioHID/src/SingleReport/SingleConsumer.h diff --git a/plugins/KeyboardioHID/examples/Consumer/Consumer.ino b/plugins/KeyboardioHID/examples/Consumer/Consumer.ino index 0c566e960c..b3d254c64c 100644 --- a/plugins/KeyboardioHID/examples/Consumer/Consumer.ino +++ b/plugins/KeyboardioHID/examples/Consumer/Consumer.ino @@ -5,6 +5,8 @@ Consumer example Press a button to play/pause music player + You may also use SingleConsumer to use a single report. + See HID Project documentation for more Consumer keys. https://github.com/NicoHood/HID/wiki/Consumer-API */ diff --git a/plugins/KeyboardioHID/keywords.txt b/plugins/KeyboardioHID/keywords.txt index 0f9d4d46e7..a37f8fe3f1 100644 --- a/plugins/KeyboardioHID/keywords.txt +++ b/plugins/KeyboardioHID/keywords.txt @@ -65,6 +65,7 @@ BootMouse KEYWORD1 RawHID KEYWORD1 System KEYWORD1 Consumer KEYWORD1 +SingleConsumer KEYWORD1 Gamepad KEYWORD1 Gamepad1 KEYWORD1 Gamepad2 KEYWORD1 diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index 8b5aaf205a..cda54782f3 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -42,6 +42,7 @@ THE SOFTWARE. #include "MultiReport/AbsoluteMouse.h" #include "SingleReport/BootMouse.h" #include "MultiReport/ImprovedMouse.h" +#include "SingleReport/SingleConsumer.h" #include "MultiReport/Consumer.h" #include "SingleReport/SingleGamepad.h" #include "MultiReport/Gamepad.h" diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleConsumer.cpp b/plugins/KeyboardioHID/src/SingleReport/SingleConsumer.cpp new file mode 100644 index 0000000000..c85827584b --- /dev/null +++ b/plugins/KeyboardioHID/src/SingleReport/SingleConsumer.cpp @@ -0,0 +1,121 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 "SingleConsumer.h" + +static const uint8_t _hidSingleReportDescriptorConsumer[] PROGMEM = { + /* Consumer Control (Sound/Media keys) */ + 0x05, 0x0C, /* usage page (consumer device) */ + 0x09, 0x01, /* usage -- consumer control */ + 0xA1, 0x01, /* collection (application) */ + /* 4 Media Keys */ + 0x15, 0x00, /* logical minimum */ + 0x26, 0xFF, 0x03, /* logical maximum (3ff) */ + 0x19, 0x00, /* usage minimum (0) */ + 0x2A, 0xFF, 0x03, /* usage maximum (3ff) */ + 0x95, 0x04, /* report count (4) */ + 0x75, 0x10, /* report size (16) */ + 0x81, 0x00, /* input */ + 0xC0 /* end collection */ +}; + +SingleConsumer_::SingleConsumer_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1) +{ + epType[0] = EP_TYPE_INTERRUPT_IN; + PluggableUSB().plug(this); +} + +int SingleConsumer_::getInterface(uint8_t* interfaceCount) +{ + *interfaceCount += 1; // uses 1 + HIDDescriptor hidInterface = { + D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE), + D_HIDREPORT(sizeof(_hidSingleReportDescriptorConsumer)), + D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) + }; + return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); +} + +int SingleConsumer_::getDescriptor(USBSetup& setup) +{ + // Check if this is a HID Class Descriptor request + if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { return 0; } + if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { return 0; } + + // In a HID Class Descriptor wIndex cointains the interface number + if (setup.wIndex != pluggedInterface) { return 0; } + + // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol + // due to the USB specs, but Windows and Linux just assumes its in report mode. + protocol = HID_REPORT_PROTOCOL; + + return USB_SendControl(TRANSFER_PGM, _hidSingleReportDescriptorConsumer, sizeof(_hidSingleReportDescriptorConsumer)); +} + +bool SingleConsumer_::setup(USBSetup& setup) +{ + if (pluggedInterface != setup.wIndex) { + return false; + } + + uint8_t request = setup.bRequest; + uint8_t requestType = setup.bmRequestType; + + if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) + { + if (request == HID_GET_REPORT) { + // TODO: HID_GetReport(); + return true; + } + if (request == HID_GET_PROTOCOL) { + // TODO: Send8(protocol); + return true; + } + } + + if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) + { + if (request == HID_SET_PROTOCOL) { + protocol = setup.wValueL; + return true; + } + if (request == HID_SET_IDLE) { + idle = setup.wValueL; + return true; + } + if (request == HID_SET_REPORT) + { + } + } + + return false; +} + +void SingleConsumer_::SendReport(void* data, int length) +{ + USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, length); +} + +SingleConsumer_ SingleConsumer; + + diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleConsumer.h b/plugins/KeyboardioHID/src/SingleReport/SingleConsumer.h new file mode 100644 index 0000000000..c7a8a43604 --- /dev/null +++ b/plugins/KeyboardioHID/src/SingleReport/SingleConsumer.h @@ -0,0 +1,55 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 guard +#pragma once + +#include +#include "PluggableUSB.h" +#include "HID.h" +#include "HID-Settings.h" +#include "../HID-APIs/ConsumerAPI.h" + + +class SingleConsumer_ : public PluggableUSBModule, public ConsumerAPI +{ +public: + SingleConsumer_(void); + uint8_t getLeds(void); + uint8_t getProtocol(void); + +protected: + // Implementation of the PUSBListNode + int getInterface(uint8_t* interfaceCount); + int getDescriptor(USBSetup& setup); + bool setup(USBSetup& setup); + + uint8_t epType[1]; + uint8_t protocol; + uint8_t idle; + + virtual inline void SendReport(void* data, int length) override; +}; +extern SingleConsumer_ SingleConsumer; + + From 4c3296de1b246d245cf97075cefdfadceee56273 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Fri, 6 Nov 2015 21:31:06 +0100 Subject: [PATCH 318/602] Added Single System Support --- .../KeyboardioHID/examples/System/System.ino | 20 +-- plugins/KeyboardioHID/keywords.txt | 1 + plugins/KeyboardioHID/src/HID-Project.h | 1 + .../src/SingleReport/SingleSystem.cpp | 123 ++++++++++++++++++ .../src/SingleReport/SingleSystem.h | 55 ++++++++ 5 files changed, 191 insertions(+), 9 deletions(-) create mode 100644 plugins/KeyboardioHID/src/SingleReport/SingleSystem.cpp create mode 100644 plugins/KeyboardioHID/src/SingleReport/SingleSystem.h diff --git a/plugins/KeyboardioHID/examples/System/System.ino b/plugins/KeyboardioHID/examples/System/System.ino index 696a82af10..c2cde3a6a7 100644 --- a/plugins/KeyboardioHID/examples/System/System.ino +++ b/plugins/KeyboardioHID/examples/System/System.ino @@ -1,12 +1,14 @@ /* - Copyright (c) 2014-2015 NicoHood - See the readme for credit to other people. - - System example - Press a button to put pc into sleep/shut it down or wake it up again. - - See HID Project documentation for more Consumer keys. - https://github.com/NicoHood/HID/wiki/System-API + Copyright (c) 2014-2015 NicoHood + See the readme for credit to other people. + + System example + Press a button to put pc into sleep/shut it down or wake it up again. + + You may also use SingleSystem to use a single report. + + See HID Project documentation for more Consumer keys. + https://github.com/NicoHood/HID/wiki/System-API */ #include "HID-Project.h" @@ -37,7 +39,7 @@ void loop() { delay(300); digitalWrite(pinLed, LOW); } - + if (!digitalRead(pinButtonW)) { digitalWrite(pinLed, HIGH); diff --git a/plugins/KeyboardioHID/keywords.txt b/plugins/KeyboardioHID/keywords.txt index a37f8fe3f1..977bcdb955 100644 --- a/plugins/KeyboardioHID/keywords.txt +++ b/plugins/KeyboardioHID/keywords.txt @@ -64,6 +64,7 @@ BootKeyboard KEYWORD1 BootMouse KEYWORD1 RawHID KEYWORD1 System KEYWORD1 +SingleSystem KEYWORD1 Consumer KEYWORD1 SingleConsumer KEYWORD1 Gamepad KEYWORD1 diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index cda54782f3..cccc3efd6e 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -46,6 +46,7 @@ THE SOFTWARE. #include "MultiReport/Consumer.h" #include "SingleReport/SingleGamepad.h" #include "MultiReport/Gamepad.h" +#include "SingleReport/SingleSystem.h" #include "MultiReport/System.h" #include "SingleReport/RawHID.h" #include "SingleReport/BootKeyboard.h" diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleSystem.cpp b/plugins/KeyboardioHID/src/SingleReport/SingleSystem.cpp new file mode 100644 index 0000000000..6d99dd5d25 --- /dev/null +++ b/plugins/KeyboardioHID/src/SingleReport/SingleSystem.cpp @@ -0,0 +1,123 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 "SingleSystem.h" + +static const uint8_t _hidSingleReportDescriptorSystem[] PROGMEM = { + //TODO limit to system keys only? + /* System Control (Power Down, Sleep, Wakeup, ...) */ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x80, /* USAGE (System Control) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + /* 1 system key */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x26, 0xff, 0x00, /* LOGICAL_MAXIMUM (255) */ + 0x19, 0x00, /* USAGE_MINIMUM (Undefined) */ + 0x29, 0xff, /* USAGE_MAXIMUM (System Menu Down) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ + 0xc0 /* END_COLLECTION */ +}; + + +SingleSystem_::SingleSystem_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1) +{ + epType[0] = EP_TYPE_INTERRUPT_IN; + PluggableUSB().plug(this); +} + +int SingleSystem_::getInterface(uint8_t* interfaceCount) +{ + *interfaceCount += 1; // uses 1 + HIDDescriptor hidInterface = { + D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE), + D_HIDREPORT(sizeof(_hidSingleReportDescriptorSystem)), + D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) + }; + return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); +} + +int SingleSystem_::getDescriptor(USBSetup& setup) +{ + // Check if this is a HID Class Descriptor request + if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { return 0; } + if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { return 0; } + + // In a HID Class Descriptor wIndex cointains the interface number + if (setup.wIndex != pluggedInterface) { return 0; } + + // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol + // due to the USB specs, but Windows and Linux just assumes its in report mode. + protocol = HID_REPORT_PROTOCOL; + + return USB_SendControl(TRANSFER_PGM, _hidSingleReportDescriptorSystem, sizeof(_hidSingleReportDescriptorSystem)); +} + +bool SingleSystem_::setup(USBSetup& setup) +{ + if (pluggedInterface != setup.wIndex) { + return false; + } + + uint8_t request = setup.bRequest; + uint8_t requestType = setup.bmRequestType; + + if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) + { + if (request == HID_GET_REPORT) { + // TODO: HID_GetReport(); + return true; + } + if (request == HID_GET_PROTOCOL) { + // TODO: Send8(protocol); + return true; + } + } + + if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) + { + if (request == HID_SET_PROTOCOL) { + protocol = setup.wValueL; + return true; + } + if (request == HID_SET_IDLE) { + idle = setup.wValueL; + return true; + } + if (request == HID_SET_REPORT) + { + } + } + + return false; +} + +void SingleSystem_::SendReport(void* data, int length) +{ + USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, length); +} + +SingleSystem_ SingleSystem; + + diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleSystem.h b/plugins/KeyboardioHID/src/SingleReport/SingleSystem.h new file mode 100644 index 0000000000..01ca15ca80 --- /dev/null +++ b/plugins/KeyboardioHID/src/SingleReport/SingleSystem.h @@ -0,0 +1,55 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 guard +#pragma once + +#include +#include "PluggableUSB.h" +#include "HID.h" +#include "HID-Settings.h" +#include "../HID-APIs/SystemAPI.h" + + +class SingleSystem_ : public PluggableUSBModule, public SystemAPI +{ +public: + SingleSystem_(void); + uint8_t getLeds(void); + uint8_t getProtocol(void); + +protected: + // Implementation of the PUSBListNode + int getInterface(uint8_t* interfaceCount); + int getDescriptor(USBSetup& setup); + bool setup(USBSetup& setup); + + uint8_t epType[1]; + uint8_t protocol; + uint8_t idle; + + virtual inline void SendReport(void* data, int length) override; +}; +extern SingleSystem_ SingleSystem; + + From 1d079bf74ea680d4ddb57858d02acc406e164817 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Fri, 6 Nov 2015 21:36:46 +0100 Subject: [PATCH 319/602] Moved System Key definitions into enum, removed HID Tables fully now --- .../KeyboardioHID/src/HID-APIs/HID-Tables.h | 66 ------------------- .../KeyboardioHID/src/HID-APIs/SystemAPI.h | 53 +++++++++++++-- .../KeyboardioHID/src/HID-APIs/SystemAPI.hpp | 6 +- 3 files changed, 51 insertions(+), 74 deletions(-) delete mode 100644 plugins/KeyboardioHID/src/HID-APIs/HID-Tables.h diff --git a/plugins/KeyboardioHID/src/HID-APIs/HID-Tables.h b/plugins/KeyboardioHID/src/HID-APIs/HID-Tables.h deleted file mode 100644 index 553373ad83..0000000000 --- a/plugins/KeyboardioHID/src/HID-APIs/HID-Tables.h +++ /dev/null @@ -1,66 +0,0 @@ -// These mappings were extracted and transcribed from -// http://www.usb.org_SLASH_developers_SLASH_devclass_docs_SLASH_Hut1_12v2.pdf -// -// In most cases, I've preserved the "official" USB Implementers forum -// "Usage Name", though I've standardized some abbreviations and spacing -// that were inconsistent in the original specification. Non alpha-numeric -// characters in symbol names were converted into those characters' names. -// -// To match Arduino code style, all hid usage names are fully upper case. -// -// Not every HID usage listed in this file is currently supported by Arduino -// In particular, any System Control or Consumer Control entry that doesn't -// have a comment indicating that it's "HID type OSC" will require additional -// code in the Arduino core to work. -// -// Non-working usages are listed here in the interest of not having to manually -// convert more usage names each and every time our HID stack gets a little bit -// better. -// -// -// -- Jesse Vincent , January 2014 - -#pragma once - -// System control mappings - -#define HID_SYSTEM_POWER_DOWN 0x81 // HID type OSC -#define HID_SYSTEM_SLEEP 0x82 // HID type OSC -#define HID_SYSTEM_WAKE_UP 0x83 // HID type OSC -#define HID_SYSTEM_CONTEXT_MENU 0x84 // HID type OSC -#define HID_SYSTEM_MAIN_MENU 0x85 // HID type OSC -#define HID_SYSTEM_APP_MENU 0x86 // HID type OSC -#define HID_SYSTEM_MENU_HELP 0x87 // HID type OSC -#define HID_SYSTEM_MENU_EXIT 0x88 // HID type OSC -#define HID_SYSTEM_MENU_SELECT 0x89 // HID type OSC -#define HID_SYSTEM_MENU_RIGHT 0x8A // HID type RTC -#define HID_SYSTEM_MENU_LEFT 0x8B // HID type RTC -#define HID_SYSTEM_MENU_UP 0x8C // HID type RTC -#define HID_SYSTEM_MENU_DOWN 0x8D // HID type RTC -#define HID_SYSTEM_COLD_RESTART 0x8E // HID type OSC -#define HID_SYSTEM_WARM_RESTART 0x8F // HID type OSC -#define HID_D_PAD_UP 0x90 // HID type OOC -#define HID_D_PAD_DOWN 0x91 // HID type OOC -#define HID_D_PAD_RIGHT 0x92 // HID type OOC -#define HID_D_PAD_LEFT 0x93 // HID type OOC -// 0x94-0x9F are reserved -#define HID_SYSTEM_DOCK 0xA0 // HID type OSC -#define HID_SYSTEM_UNDOCK 0xA1 // HID type OSC -#define HID_SYSTEM_SETUP 0xA2 // HID type OSC -#define HID_SYSTEM_BREAK 0xA3 // HID type OSC -#define HID_SYSTEM_DEBUGGER_BREAK 0xA4 // HID type OSC -#define HID_APPLICATION_BREAK 0xA5 // HID type OSC -#define HID_APPLICATION_DEBUGGER_BREAK 0xA6 // HID type OSC -#define HID_SYSTEM_SPEAKER_MUTE 0xA7 // HID type OSC -#define HID_SYSTEM_HIBERNATE 0xA8 // HID type OSC -// 0xA9-0xAF are reserved -#define HID_SYSTEM_DISPLAY_INVERT 0xB0 // HID type OSC -#define HID_SYSTEM_DISPLAY_INTERNAL 0xB1 // HID type OSC -#define HID_SYSTEM_DISPLAY_EXTERNAL 0xB2 // HID type OSC -#define HID_SYSTEM_DISPLAY_BOTH 0xB3 // HID type OSC -#define HID_SYSTEM_DISPLAY_DUAL 0xB4 // HID type OSC -#define HID_SYSTEM_DISPLAY_TOGGLE_INT_SLASH_EXT 0xB5 // HID type OSC -#define HID_SYSTEM_DISPLAY_SWAP_PRIMARY_SLASH_SECONDARY 0xB6 // HID type OSC -#define HID_SYSTEM_DISPLAY_LCD_AUTOSCALE 0xB7 // HID type OSC - - diff --git a/plugins/KeyboardioHID/src/HID-APIs/SystemAPI.h b/plugins/KeyboardioHID/src/HID-APIs/SystemAPI.h index 69e483321a..e27abacdff 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/SystemAPI.h +++ b/plugins/KeyboardioHID/src/HID-APIs/SystemAPI.h @@ -27,9 +27,52 @@ THE SOFTWARE. #include #include "HID-Settings.h" -#define SYSTEM_POWER_DOWN 0x81 -#define SYSTEM_SLEEP 0x82 -#define SYSTEM_WAKE_UP 0x83 +enum SystemKeycode : uint8_t { + SYSTEM_POWER_DOWN = 0x81, + SYSTEM_SLEEP = 0x82, + SYSTEM_WAKE_UP = 0x83, + + // System control mappings + HID_SYSTEM_UNASSIGNED = 0x00, + HID_SYSTEM_POWER_DOWN = 0x81, // HID type OSC + HID_SYSTEM_SLEEP = 0x82, // HID type OSC + HID_SYSTEM_WAKE_UP = 0x83, // HID type OSC + HID_SYSTEM_CONTEXT_MENU = 0x84, // HID type OSC + HID_SYSTEM_MAIN_MENU = 0x85, // HID type OSC + HID_SYSTEM_APP_MENU = 0x86, // HID type OSC + HID_SYSTEM_MENU_HELP = 0x87, // HID type OSC + HID_SYSTEM_MENU_EXIT = 0x88, // HID type OSC + HID_SYSTEM_MENU_SELECT = 0x89, // HID type OSC + HID_SYSTEM_MENU_RIGHT = 0x8A, // HID type RTC + HID_SYSTEM_MENU_LEFT = 0x8B, // HID type RTC + HID_SYSTEM_MENU_UP = 0x8C, // HID type RTC + HID_SYSTEM_MENU_DOWN = 0x8D, // HID type RTC + HID_SYSTEM_COLD_RESTART = 0x8E, // HID type OSC + HID_SYSTEM_WARM_RESTART = 0x8F, // HID type OSC + HID_D_PAD_UP = 0x90, // HID type OOC + HID_D_PAD_DOWN = 0x91, // HID type OOC + HID_D_PAD_RIGHT = 0x92, // HID type OOC + HID_D_PAD_LEFT = 0x93, // HID type OOC + // 0x94-0x9F are reserved + HID_SYSTEM_DOCK = 0xA0, // HID type OSC + HID_SYSTEM_UNDOCK = 0xA1, // HID type OSC + HID_SYSTEM_SETUP = 0xA2, // HID type OSC + HID_SYSTEM_BREAK = 0xA3, // HID type OSC + HID_SYSTEM_DEBUGGER_BREAK = 0xA4, // HID type OSC + HID_APPLICATION_BREAK = 0xA5, // HID type OSC + HID_APPLICATION_DEBUGGER_BREAK = 0xA6, // HID type OSC + HID_SYSTEM_SPEAKER_MUTE = 0xA7, // HID type OSC + HID_SYSTEM_HIBERNATE = 0xA8, // HID type OSC + // 0xA9-0xAF are reserved + HID_SYSTEM_DISPLAY_INVERT = 0xB0, // HID type OSC + HID_SYSTEM_DISPLAY_INTERNAL = 0xB1, // HID type OSC + HID_SYSTEM_DISPLAY_EXTERNAL = 0xB2, // HID type OSC + HID_SYSTEM_DISPLAY_BOTH = 0xB3, // HID type OSC + HID_SYSTEM_DISPLAY_DUAL = 0xB4, // HID type OSC + HID_SYSTEM_DISPLAY_TOGGLE_INT_SLASH_EXT = 0xB5, // HID type OSC + HID_SYSTEM_DISPLAY_SWAP_PRIMARY_SLASH_SECONDARY = 0xB6, // HID type OSC + HID_SYSTEM_DISPLAY_LCD_AUTOSCALE = 0xB7, // HID type OSC +}; typedef union{ // Every usable system control key possible @@ -42,8 +85,8 @@ class SystemAPI{ inline SystemAPI(void); inline void begin(void); inline void end(void); - inline void write(uint8_t s); - inline void press(uint8_t s); + inline void write(SystemKeycode s); + inline void press(SystemKeycode s); inline void release(void); inline void releaseAll(void); diff --git a/plugins/KeyboardioHID/src/HID-APIs/SystemAPI.hpp b/plugins/KeyboardioHID/src/HID-APIs/SystemAPI.hpp index ba9d75c3d9..edb9775343 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/SystemAPI.hpp +++ b/plugins/KeyboardioHID/src/HID-APIs/SystemAPI.hpp @@ -35,11 +35,11 @@ void SystemAPI::begin(void){ } void SystemAPI::end(void){ - uint8_t _report = 0; + SystemKeycode _report = HID_SYSTEM_UNASSIGNED; SendReport(&_report, sizeof(_report)); } -void SystemAPI::write(uint8_t s){ +void SystemAPI::write(SystemKeycode s){ press(s); release(); } @@ -52,7 +52,7 @@ void SystemAPI::releaseAll(void){ begin(); } -void SystemAPI::press(uint8_t s){ +void SystemAPI::press(SystemKeycode s){ #ifdef USBCON if (s == SYSTEM_WAKE_UP) USBDevice.wakeupHost(); From 6377ace48e8aeade0bfe582b3260953fa9013bfd Mon Sep 17 00:00:00 2001 From: NicoHood Date: Fri, 6 Nov 2015 21:40:51 +0100 Subject: [PATCH 320/602] Added Single Absolute Mouse API --- .../examples/AbsoluteMouse/AbsoluteMouse.ino | 2 + plugins/KeyboardioHID/keywords.txt | 1 + plugins/KeyboardioHID/src/HID-Project.h | 1 + .../src/SingleReport/SingleAbsoluteMouse.cpp | 144 ++++++++++++++++++ .../src/SingleReport/SingleAbsoluteMouse.h | 55 +++++++ 5 files changed, 203 insertions(+) create mode 100644 plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp create mode 100644 plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h diff --git a/plugins/KeyboardioHID/examples/AbsoluteMouse/AbsoluteMouse.ino b/plugins/KeyboardioHID/examples/AbsoluteMouse/AbsoluteMouse.ino index 872ee63eb6..3cf052ca3d 100644 --- a/plugins/KeyboardioHID/examples/AbsoluteMouse/AbsoluteMouse.ino +++ b/plugins/KeyboardioHID/examples/AbsoluteMouse/AbsoluteMouse.ino @@ -5,6 +5,8 @@ AbsoluteMouse example Press a button to click, moveTo the mouse. + You may also use SingleAbsoluteMouse to use a single report. + See HID Project documentation for more infos https://github.com/NicoHood/HID/wiki/Mouse-API https://github.com/NicoHood/HID/wiki/AbsoluteMouse-API diff --git a/plugins/KeyboardioHID/keywords.txt b/plugins/KeyboardioHID/keywords.txt index 977bcdb955..a6e5bf0d62 100644 --- a/plugins/KeyboardioHID/keywords.txt +++ b/plugins/KeyboardioHID/keywords.txt @@ -76,6 +76,7 @@ TeensyKeyboard KEYWORD1 NKROKeyboard KEYWORD1 SingleNKROKeyboard KEYWORD1 AbsoluteMouse KEYWORD1 +SingleAbsoluteMouse KEYWORD1 ####################################### # Constants (LITERAL1) diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index cccc3efd6e..1e7414b5ce 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -39,6 +39,7 @@ THE SOFTWARE. #endif // Include all HID libraries (.a linkage required to work) properly +#include "SingleReport/SingleAbsoluteMouse.h" #include "MultiReport/AbsoluteMouse.h" #include "SingleReport/BootMouse.h" #include "MultiReport/ImprovedMouse.h" diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp new file mode 100644 index 0000000000..bad902c487 --- /dev/null +++ b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp @@ -0,0 +1,144 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 "SingleAbsoluteMouse.h" + +static const uint8_t _hidSingleReportDescriptorAbsoluteMouse[] PROGMEM = { + /* Mouse absolute */ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 54 */ + 0x09, 0x02, /* USAGE (Mouse) */ + 0xA1, 0x01, /* COLLECTION (Application) */ + + /* 8 Buttons */ + 0x05, 0x09, /* USAGE_PAGE (Button) */ + 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ + 0x29, 0x08, /* USAGE_MAXIMUM (Button 8) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x95, 0x08, /* REPORT_COUNT (8) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + + /* X, Y */ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x30, /* USAGE (X) */ + 0x09, 0x31, /* USAGE (Y) */ + 0x16, 0x00, 0x80, /* Logical Minimum (-32768) */ + 0x26, 0xFF, 0x7F, /* Logical Maximum (32767) */ + 0x75, 0x10, /* Report Size (16), */ + 0x95, 0x02, /* Report Count (2), */ + 0x81, 0x02, /* Input (Data, Variable, Absolute) */ + + /* Wheel */ + 0x09, 0x38, /* USAGE (Wheel) */ + 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) */ + + /* End */ + 0xc0 /* END_COLLECTION */ +}; + + +SingleAbsoluteMouse_::SingleAbsoluteMouse_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1) +{ + epType[0] = EP_TYPE_INTERRUPT_IN; + PluggableUSB().plug(this); +} + +int SingleAbsoluteMouse_::getInterface(uint8_t* interfaceCount) +{ + *interfaceCount += 1; // uses 1 + HIDDescriptor hidInterface = { + D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE), + D_HIDREPORT(sizeof(_hidSingleReportDescriptorAbsoluteMouse)), + D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) + }; + return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); +} + +int SingleAbsoluteMouse_::getDescriptor(USBSetup& setup) +{ + // Check if this is a HID Class Descriptor request + if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { return 0; } + if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { return 0; } + + // In a HID Class Descriptor wIndex cointains the interface number + if (setup.wIndex != pluggedInterface) { return 0; } + + // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol + // due to the USB specs, but Windows and Linux just assumes its in report mode. + protocol = HID_REPORT_PROTOCOL; + + return USB_SendControl(TRANSFER_PGM, _hidSingleReportDescriptorAbsoluteMouse, sizeof(_hidSingleReportDescriptorAbsoluteMouse)); +} + +bool SingleAbsoluteMouse_::setup(USBSetup& setup) +{ + if (pluggedInterface != setup.wIndex) { + return false; + } + + uint8_t request = setup.bRequest; + uint8_t requestType = setup.bmRequestType; + + if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) + { + if (request == HID_GET_REPORT) { + // TODO: HID_GetReport(); + return true; + } + if (request == HID_GET_PROTOCOL) { + // TODO: Send8(protocol); + return true; + } + } + + if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) + { + if (request == HID_SET_PROTOCOL) { + protocol = setup.wValueL; + return true; + } + if (request == HID_SET_IDLE) { + idle = setup.wValueL; + return true; + } + if (request == HID_SET_REPORT) + { + } + } + + return false; +} + +void SingleAbsoluteMouse_::SendReport(void* data, int length) +{ + USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, length); +} + +SingleAbsoluteMouse_ SingleAbsoluteMouse; + + diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h new file mode 100644 index 0000000000..2a13fe9464 --- /dev/null +++ b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h @@ -0,0 +1,55 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 guard +#pragma once + +#include +#include "PluggableUSB.h" +#include "HID.h" +#include "HID-Settings.h" +#include "../HID-APIs/AbsoluteMouseAPI.h" + + +class SingleAbsoluteMouse_ : public PluggableUSBModule, public AbsoluteMouseAPI +{ +public: + SingleAbsoluteMouse_(void); + uint8_t getLeds(void); + uint8_t getProtocol(void); + +protected: + // Implementation of the PUSBListNode + int getInterface(uint8_t* interfaceCount); + int getDescriptor(USBSetup& setup); + bool setup(USBSetup& setup); + + uint8_t epType[1]; + uint8_t protocol; + uint8_t idle; + + virtual inline void SendReport(void* data, int length) override; +}; +extern SingleAbsoluteMouse_ SingleAbsoluteMouse; + + From 67ad5f3a26a5e433733cdc5004e6d7ef9778167a Mon Sep 17 00:00:00 2001 From: NicoHood Date: Fri, 6 Nov 2015 21:53:46 +0100 Subject: [PATCH 321/602] Readme --- plugins/KeyboardioHID/Readme.md | 46 +++++++++++++-------------------- 1 file changed, 18 insertions(+), 28 deletions(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 476d730ce8..78ea006aeb 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -16,15 +16,17 @@ The idea is to enable enhanced USB functions to almost all 'standard' Arduino bo * No SAM/ARM support (Due, Zero etc) **Supported HID devices:** -* Keyboard with Leds out (modifiers + 6 keys pressed at the same time) -* Teensy Keyboard with different keyboard layouts (german, french and many more) -* BootKeyboard protocol for Improved/Teensy Keyboard (works under BIOS) +* Keyboard with Leds out (8 modifiers + 6 keys pressed at the same time, + 1 limited linux consumer key) +* ~~Teensy Keyboard with different keyboard layouts (german, french and many more)~~ soon * NKRO Keyboard with Leds out (press up to 113 keys at the same time) * Mouse (5 buttons, move, wheel) +* BootKeyboard/BootMouse BIOS protocol support * Absolute Mouse * Consumer/Media Keys (4 keys for music player, web browser and more) * System Key (for PC standby/shutdown) * Gamepad (32 buttons, 4 16bit axis, 2 8bit axis, 2 D-Pads) +* RawHID +* Each device is available as single or multi report device (except RawHID) See the [wiki](https://github.com/NicoHood/HID/wiki/Features) for more information about features etc. @@ -34,13 +36,14 @@ Download You have 3 versions you can download: * The master includes all fixes to the current stable release. Download it by clicking download at the right. +You might need to get the latest hourly build of the Arduino IDE to use the current master. Use the [online Wiki](https://github.com/NicoHood/HID/wiki) to get the newest documentation. * Download an offline version in [releases](https://github.com/NicoHood/HID/releases). It's a snapshot of the current stable release but might have missed some updates that the current master branch has included. This also includes an offline version of the wiki. Offline versions will be available after some time when the official release is out. -* Select [branch 'dev'](https://github.com/NicoHood/HID/tree/dev) to test the bleeding edge of this software. It might not work at all or has a lot of debugging stuff in it. -If the dev version gets near to a new release a note will be placed here, that you can test the new dev beta. -Currently there is no beta available. +* Select [branch 'dev'](https://github.com/NicoHood/HID/tree/dev) to test the bleeding edge of this software. +It might not work at all or has a lot of debugging stuff in it. An hourly IDE build is highly suggested. +If the dev version gets near to a new release a big banner will be placed at the top. Wiki @@ -59,39 +62,26 @@ You can contact me on my wordpress blog in the contact section. www.nicohood.de -TODO -==== - -Under Construction. This is a todo list for myself. - -``` -Keyboard Layout for different Languages -Clean up USB Core code from fixed values. Use better understandable definitions -Magic key fix for 32u4? - -Check Keyboard keycode function again -Generalize HID key definitions via HIDTables for example? - -Test with Android phone (HL1) -improve keywords.txt -``` - - Version History =============== ``` 2.4 Release (xx.xx.2015) * Added Arduino IDE 1.6.6 compatibility with Pluggable HID -* Improved Pluggable HID (have its own modifed copy now) -* Changed USB-Core into a simple library, only possible with Pluggable HID +* Improved Pluggable HID (see Arduyuino changelog for my improvements) +* Changed USB-Core into a simple library, only made possible with Pluggable HID * Removed HID presets in boards menu (like mouse + keyboard + consumer + system) * Added Teensy Keyboard * Added NKRO Keyboard * Added Led report for Keyboard -* Added HID out report in general (RAW HID preparation) +* Added 1 Linux consumer key for keyboard +* Added BootKeyboard/Mouse support (BIOS compatibility) +* Added RawHID * Added a few key definitions +* Renew whole Keyboard API and its definitions via enum * Uses .alinkage custom IDE option -* Added BootKeyboard support (BIOS compatibility) +* Improved and updated examples +* A lot of other minor and major fixes I missed to mention. + 2.3 Release (never released) * Updated Libraries From 5dfd5bb269cb17117962bcbca2827c4848d3af32 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Fri, 6 Nov 2015 22:51:54 +0100 Subject: [PATCH 322/602] Release 2.4 --- plugins/KeyboardioHID/Readme.md | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 78ea006aeb..84ac634436 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -30,22 +30,6 @@ The idea is to enable enhanced USB functions to almost all 'standard' Arduino bo See the [wiki](https://github.com/NicoHood/HID/wiki/Features) for more information about features etc. - -Download -======== - -You have 3 versions you can download: -* The master includes all fixes to the current stable release. Download it by clicking download at the right. -You might need to get the latest hourly build of the Arduino IDE to use the current master. -Use the [online Wiki](https://github.com/NicoHood/HID/wiki) to get the newest documentation. -* Download an offline version in [releases](https://github.com/NicoHood/HID/releases). -It's a snapshot of the current stable release but might have missed some updates that the current master branch has included. -This also includes an offline version of the wiki. Offline versions will be available after some time when the official release is out. -* Select [branch 'dev'](https://github.com/NicoHood/HID/tree/dev) to test the bleeding edge of this software. -It might not work at all or has a lot of debugging stuff in it. An hourly IDE build is highly suggested. -If the dev version gets near to a new release a big banner will be placed at the top. - - Wiki ==== @@ -65,12 +49,11 @@ www.nicohood.de Version History =============== ``` -2.4 Release (xx.xx.2015) +2.4 Release (06.11.2015) * Added Arduino IDE 1.6.6 compatibility with Pluggable HID * Improved Pluggable HID (see Arduyuino changelog for my improvements) * Changed USB-Core into a simple library, only made possible with Pluggable HID * Removed HID presets in boards menu (like mouse + keyboard + consumer + system) -* Added Teensy Keyboard * Added NKRO Keyboard * Added Led report for Keyboard * Added 1 Linux consumer key for keyboard @@ -82,7 +65,6 @@ Version History * Improved and updated examples * A lot of other minor and major fixes I missed to mention. - 2.3 Release (never released) * Updated Libraries * Updated Arduino Core From b2455aa8cddbc4805b1162c76437c66f5a5596af Mon Sep 17 00:00:00 2001 From: NicoHood Date: Fri, 6 Nov 2015 23:09:56 +0100 Subject: [PATCH 323/602] bumped version number to 2.5 --- plugins/KeyboardioHID/Readme.md | 4 +- plugins/KeyboardioHID/library.properties | 2 +- .../package_NicoHood_HID_index.json | 45 ------------------- plugins/KeyboardioHID/src/HID-Project.h | 2 +- 4 files changed, 5 insertions(+), 48 deletions(-) delete mode 100644 plugins/KeyboardioHID/package_NicoHood_HID_index.json diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 84ac634436..da5c97d19c 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -1,4 +1,4 @@ -Arduino HID Project 2.4 +Arduino HID Project 2.5 ======================= ![Header Picture](header.jpg) @@ -49,6 +49,8 @@ www.nicohood.de Version History =============== ``` +2.5 Release (xx.xx.2015) + 2.4 Release (06.11.2015) * Added Arduino IDE 1.6.6 compatibility with Pluggable HID * Improved Pluggable HID (see Arduyuino changelog for my improvements) diff --git a/plugins/KeyboardioHID/library.properties b/plugins/KeyboardioHID/library.properties index d984e65717..7c0c59e6b4 100644 --- a/plugins/KeyboardioHID/library.properties +++ b/plugins/KeyboardioHID/library.properties @@ -1,5 +1,5 @@ name=HID-Project -version=2.4 +version=2.5 author=NicoHood maintainer=NicoHood sentence=Extended HID Functions for Arduino diff --git a/plugins/KeyboardioHID/package_NicoHood_HID_index.json b/plugins/KeyboardioHID/package_NicoHood_HID_index.json deleted file mode 100644 index d1722971a3..0000000000 --- a/plugins/KeyboardioHID/package_NicoHood_HID_index.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "packages": [ - { - "name": "HID", - "maintainer": "NicoHood", - "websiteURL": "https://github.com/NicoHood/HID", - "email": "", - "help": { - "online": "" - }, - "platforms": [ - { - "name": "HID Project", - "architecture": "avr", - "version": "2.2", - "category": "HID", - "help": { - "online": "" - }, - "url": "https://github.com/NicoHood/HID/releases/download/2.2/2.2-boards_manager.zip", - "archiveFileName": "2.2-boards_manager.zip", - "checksum": "SHA-256:9c86ee28a7ce9fe33e8b07ec643316131e0031b0d22e63bb398902a5fdadbca9", - "size": "351303", - "boards": [ - {"name": "Arduino Leonardo"}, - {"name": "Arduino Micro"} - ], - "toolsDependencies": [ - { - "packager": "arduino", - "name": "avr-gcc", - "version": "4.8.1-arduino5" - }, - { - "packager": "arduino", - "name": "avrdude", - "version": "6.0.1-arduino5" - } - ] - } - ], - "tools": [] - } - ] -} diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index 1e7414b5ce..ff592d384f 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -25,7 +25,7 @@ THE SOFTWARE. #pragma once // Software version -#define HID_PROJECT_VERSION 240 +#define HID_PROJECT_VERSION 250 // TODO remove https://github.com/arduino/arduino-builder/issues/33 #include From b96eb029d0ab6200132828dd09ad462b7c378f90 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 7 Nov 2015 10:54:50 +0100 Subject: [PATCH 324/602] Added sequence ID (aka num) to RawHID --- plugins/KeyboardioHID/examples/RawHID/RawHID.ino | 2 +- plugins/KeyboardioHID/src/SingleReport/RawHID.cpp | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/plugins/KeyboardioHID/examples/RawHID/RawHID.ino b/plugins/KeyboardioHID/examples/RawHID/RawHID.ino index 04ff20983a..24677ceab5 100644 --- a/plugins/KeyboardioHID/examples/RawHID/RawHID.ino +++ b/plugins/KeyboardioHID/examples/RawHID/RawHID.ino @@ -82,7 +82,7 @@ void loop() { } } -void RawHIDEvent(void) { +void RawHIDEvent(uint8_t num) { // This event is called via interrupt. // Do not use print inside, or other long function calls! // If you not use this event function, diff --git a/plugins/KeyboardioHID/src/SingleReport/RawHID.cpp b/plugins/KeyboardioHID/src/SingleReport/RawHID.cpp index 3cafe96125..2f81830993 100644 --- a/plugins/KeyboardioHID/src/SingleReport/RawHID.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/RawHID.cpp @@ -48,8 +48,8 @@ static const uint8_t _hidReportDescriptorRawHID[] PROGMEM = { }; // Weak implementation of the Event function -void RawHIDEvent(void) __attribute__ ((weak)); -void RawHIDEvent(void){ +void RawHIDEvent(uint8_t num) __attribute__ ((weak)); +void RawHIDEvent(uint8_t num){ // Empty } @@ -122,6 +122,7 @@ bool RawHID_::setup(USBSetup& setup) { // Get the data length information and the corresponding bytes int length = setup.wLength; + uint8_t num = 0; while(length) { // Dont receive more than the USB EP has to offer @@ -143,7 +144,7 @@ bool RawHID_::setup(USBSetup& setup) // Write data to fit to the end (not the beginning) of the array USB_RecvControl(data + (sizeof(data) - recvLength), recvLength); dataLength = recvLength; - RawHIDEvent(); + RawHIDEvent(num++); } // Do not read the data, flag an error to the USB Host // TODO always return no error, even if data was discarded? -> use break then From c2523673af02f8c154ffdd8c9cb4a995a407ecc0 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 7 Nov 2015 11:09:51 +0100 Subject: [PATCH 325/602] Improved library.properties --- plugins/KeyboardioHID/library.properties | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/KeyboardioHID/library.properties b/plugins/KeyboardioHID/library.properties index 7c0c59e6b4..1bfd8b4bc1 100644 --- a/plugins/KeyboardioHID/library.properties +++ b/plugins/KeyboardioHID/library.properties @@ -3,8 +3,8 @@ version=2.5 author=NicoHood maintainer=NicoHood sentence=Extended HID Functions for Arduino -paragraph=Includes Consumer, System and Gamepad. Also compatible with Arduino Uno/Mega via HoodLoader2. -category=Device Control +paragraph=Includes BootKeyboard/Mouse, Consumer, System, Gamepad, RawHID and more features. Also compatible with Arduino Uno/Mega via HoodLoader2. +category=Communication url=https://github.com/NicoHood/HID -architectures=* +architectures=avr dot_a_linkage=true From 0f31f5400cb0b082fb0f10ed29215331cc130956 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 7 Nov 2015 23:32:02 +0100 Subject: [PATCH 326/602] Added Feature Report function to BootKeyboard This may be added to other HID Devices as well, but Keyboard makes the most sense. --- .../src/SingleReport/BootKeyboard.cpp | 38 +++++++++++++++++-- .../src/SingleReport/BootKeyboard.h | 25 ++++++++++++ 2 files changed, 59 insertions(+), 4 deletions(-) diff --git a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp index debadb38b4..8d63c3cb53 100644 --- a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp @@ -120,10 +120,12 @@ bool BootKeyboard_::setup(USBSetup& setup) return true; } if (request == HID_GET_PROTOCOL) { + // TODO improve UEDATX = protocol; return true; } if (request == HID_GET_IDLE) { + // TODO improve UEDATX = idle; return true; } @@ -141,10 +143,38 @@ bool BootKeyboard_::setup(USBSetup& setup) } if (request == HID_SET_REPORT) { - // Check if data has the correct length - auto length = setup.wLength; - if(length == sizeof(leds)){ - USB_RecvControl(&leds, length); + // Check if data has the correct length afterwards + int length = setup.wLength; + + // Feature (set feature report) + if(setup.wValueH == HID_REPORT_TYPE_FEATURE){ + // No need to check for negative featureLength values, + // except the host tries to send more then 32k bytes. + // We dont have that much ram anyways. + if (length == featureLength) { + USB_RecvControl(featureReport, featureLength); + + // Block until data is read (make length negative) + disableFeatureReport(); + return true; + } + } + + // Output (set led states) + else if(setup.wValueH == HID_REPORT_TYPE_OUTPUT){ + if(length == sizeof(leds)){ + USB_RecvControl(&leds, length); + return true; + } + } + + // Input (set HID report) + else if(setup.wValueH == HID_REPORT_TYPE_INPUT) + { + if(length == sizeof(_keyReport)){ + USB_RecvControl(&_keyReport, length); + return true; + } } } } diff --git a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h index 4d83e722e2..221272d726 100644 --- a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h @@ -38,6 +38,28 @@ class BootKeyboard_ : public PluggableUSBModule, public DefaultKeyboardAPI uint8_t getLeds(void); uint8_t getProtocol(void); void wakeupHost(void); + + void setFeatureReport(void* report, int length){ + if(length > 0){ + featureReport = (uint8_t*)report; + featureLength = length; + } + } + + int availableFeatureReport(void){ + if(featureLength < 0){ + return featureLength & ~0x8000; + } + return 0; + } + + void enableFeatureReport(void){ + featureLength &= ~0x8000; + } + + void disableFeatureReport(void){ + featureLength |= 0x8000; + } protected: // Implementation of the PUSBListNode @@ -51,6 +73,9 @@ class BootKeyboard_ : public PluggableUSBModule, public DefaultKeyboardAPI uint8_t leds; + uint8_t* featureReport; + int featureLength; + virtual int send(void) override; }; extern BootKeyboard_ BootKeyboard; From 013f31334204513e177005a9795dc7a268781484 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 7 Nov 2015 23:35:23 +0100 Subject: [PATCH 327/602] Updated Keyboard keywords.txt --- plugins/KeyboardioHID/keywords.txt | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/plugins/KeyboardioHID/keywords.txt b/plugins/KeyboardioHID/keywords.txt index a6e5bf0d62..e5ce27925b 100644 --- a/plugins/KeyboardioHID/keywords.txt +++ b/plugins/KeyboardioHID/keywords.txt @@ -22,13 +22,10 @@ moveTo KEYWORD2 isPressed KEYWORD2 getLeds KEYWORD2 -pressKeycode KEYWORD2 -releaseKeycode KEYWORD2 -writeKeycode KEYWORD2 -addKeyToReport KEYWORD2 -addKeycodeToReport KEYWORD2 -removeKeyFromReport KEYWORD2 -removeKeycodeFromReport KEYWORD2 +setFeatureReport KEYWORD2 +availableFeatureReport KEYWORD2 +enableFeatureReport KEYWORD2 +disableFeatureReport KEYWORD2 write_unicode KEYWORD2 set_modifier KEYWORD2 From 98a18da879c83c9dc38e8c3e0a5c12de3892e108 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 7 Nov 2015 23:46:58 +0100 Subject: [PATCH 328/602] Added Feature Report example + disabled by default --- .../KeyboardFeatureReport.ino | 80 +++++++++++++++++++ .../src/SingleReport/BootKeyboard.h | 3 + 2 files changed, 83 insertions(+) create mode 100644 plugins/KeyboardioHID/examples/KeyboardFeatureReport/KeyboardFeatureReport.ino diff --git a/plugins/KeyboardioHID/examples/KeyboardFeatureReport/KeyboardFeatureReport.ino b/plugins/KeyboardioHID/examples/KeyboardFeatureReport/KeyboardFeatureReport.ino new file mode 100644 index 0000000000..f7148ea234 --- /dev/null +++ b/plugins/KeyboardioHID/examples/KeyboardFeatureReport/KeyboardFeatureReport.ino @@ -0,0 +1,80 @@ +/* + Copyright (c) 2014-2015 NicoHood + See the readme for credit to other people. + + KeyboardFeatureReport example + + Shows how to use BootKeyboard with a modified Hyperion Lightpack device. + Might only work under linux. + + See HID Project documentation for more information. + https://github.com/NicoHood/HID/wiki/RawHID-API + https://github.com/NicoHood/HID/wiki/Keyboard-API#boot-keyboard +*/ + +#include "HID-Project.h" + +const int pinLed = LED_BUILTIN; + + +// FastLED +#include "FastLED.h" + +#define LED_PINS MOSI, SCK // DATA_PIN, or DATA_PIN, CLOCK_PIN +#define COLOR_ORDER RGB +#define CHIPSET WS2801 // WS2811, LPD8806, etc +#define NUM_LEDS 25 + +#define BRIGHTNESS 255 // Reduce power consumption +#define LED_DITHER 255 // Try 0 to disable flickering +#define CORRECTION TypicalLEDStrip + +CRGB leds[NUM_LEDS]; // Define the array of leds + +void setup() { + // FastLED setup + FastLED.addLeds(leds, NUM_LEDS).setCorrection(CORRECTION); + FastLED.setBrightness(BRIGHTNESS); + FastLED.setDither(LED_DITHER); + + // Startup animation + fill_solid(leds, NUM_LEDS, CRGB::Red); + FastLED.show(); + delay(500); + fill_solid(leds, NUM_LEDS, CRGB::Green); + FastLED.show(); + delay(500); + fill_solid(leds, NUM_LEDS, CRGB::Blue); + FastLED.show(); + delay(500); + FastLED.clear(); + FastLED.show(); + + pinMode(pinLed, OUTPUT); + + // Sends a clean report to the host. This is important on any Arduino type. + BootKeyboard.begin(); + + // Let the feature report data directly point at the led array + BootKeyboard.setFeatureReport(leds, sizeof(leds)); + BootKeyboard.enableFeatureReport(); +} + +void loop() { + // Check if there is new feature request data from the keyboard + if (BootKeyboard.availableFeatureReport()) + { + digitalWrite(pinLed, HIGH); + + // Update leds, do not update in the loop, to avoid corrupted data. + // For example if you write (0, 0, 0) and the interrupt + // changes the data to (255, 255, 255) you might get (0, 255, 255). + // Using a duplicated led array in cli() context would also work. + FastLED.show(); + + // Release data to let the USB interrupt overwrite it again + BootKeyboard.enableFeatureReport(); + + digitalWrite(pinLed, LOW); + } +} diff --git a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h index 221272d726..d5c9ff01ed 100644 --- a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h @@ -43,6 +43,9 @@ class BootKeyboard_ : public PluggableUSBModule, public DefaultKeyboardAPI if(length > 0){ featureReport = (uint8_t*)report; featureLength = length; + + // Disable feature report by default + disableFeatureReport(); } } From 9a264da5a0578ffa6fdcb80712605ee27c81cae7 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 8 Nov 2015 00:13:42 +0100 Subject: [PATCH 329/602] Added featureReport data to constructor --- plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp index 8d63c3cb53..c13250399d 100644 --- a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp @@ -71,7 +71,7 @@ static const uint8_t _hidReportDescriptorKeyboard[] PROGMEM = { 0xc0 /* END_COLLECTION */ }; -BootKeyboard_::BootKeyboard_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1), leds(0) +BootKeyboard_::BootKeyboard_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1), leds(0), featureReport(NULL), featureLength(0) { epType[0] = EP_TYPE_INTERRUPT_IN; PluggableUSB().plug(this); From 16d11af4d52f8a0e867a911f0a454523c25b5317 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 8 Nov 2015 19:09:23 +0100 Subject: [PATCH 330/602] Fixed RawHID linux send function. --- plugins/KeyboardioHID/extras/rawhid/hid_LINUX.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/extras/rawhid/hid_LINUX.c b/plugins/KeyboardioHID/extras/rawhid/hid_LINUX.c index 8e98113e88..799797ecb0 100644 --- a/plugins/KeyboardioHID/extras/rawhid/hid_LINUX.c +++ b/plugins/KeyboardioHID/extras/rawhid/hid_LINUX.c @@ -144,7 +144,7 @@ int rawhid_send(int num, void *buf, int len, int timeout) if (hid->ep_out) { return usb_interrupt_write(hid->usb, hid->ep_out, buf, len, timeout); } else { - return usb_control_msg(hid->usb, 0x21, 9, 0, hid->iface, buf, len, timeout); + return usb_control_msg(hid->usb, 0x21, 9, 0x0200, hid->iface, buf, len, timeout); } } From 5e28cb7036bbfa4fc516f87ba7d0d39575d95015 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 8 Nov 2015 20:05:53 +0100 Subject: [PATCH 331/602] Updated RawHID with new, more intuitive API --- .../KeyboardioHID/examples/RawHID/RawHID.ino | 70 +++++----------- .../KeyboardioHID/src/SingleReport/RawHID.cpp | 65 +++++---------- .../KeyboardioHID/src/SingleReport/RawHID.h | 83 ++++++++++++------- 3 files changed, 96 insertions(+), 122 deletions(-) diff --git a/plugins/KeyboardioHID/examples/RawHID/RawHID.ino b/plugins/KeyboardioHID/examples/RawHID/RawHID.ino index 24677ceab5..0ab8c45969 100644 --- a/plugins/KeyboardioHID/examples/RawHID/RawHID.ino +++ b/plugins/KeyboardioHID/examples/RawHID/RawHID.ino @@ -7,11 +7,7 @@ Shows how to send bytes via RawHID. Press a button to send some example values. - Every received data is mirrored to the host. - The use of the RawHIDEvent() function is shown too. - - This sketch only tries to show the possiblities - and is not perfect.You might want to use RawHID differently. + Every received data is mirrored to the host via Serial. See HID Project documentation for more information. https://github.com/NicoHood/HID/wiki/RawHID-API @@ -22,14 +18,22 @@ const int pinLed = LED_BUILTIN; const int pinButton = 2; -uint8_t data[255]; -volatile size_t len = 0; +// Buffer to hold RawHID data. +// If host tries to send more data than this, +// it will respond with an error. +// If the data is not read until the host sends the next data +// it will also respond with an error and the data will be lost. +uint8_t rawhidData[255]; void setup() { pinMode(pinLed, OUTPUT); pinMode(pinButton, INPUT_PULLUP); - // No begin/end function required for RawHID + Serial.begin(115200); + + // Set the RawHID OUT report array. + // Feature reports are also (parallel) possible, see the other example for this. + RawHID.begin(rawhidData, sizeof(rawhidData)); } void loop() { @@ -50,54 +54,18 @@ void loop() { } - // This will miss longer RawHID data transmissions - // and return an error to the host if data was missed. - // Only use this for non changing/less important data. - // Or you can use this if the event aborted on a full buffer. - // Please note, that all data after this full buffer is missed anyways. + // Check if there is new data from the RawHID device auto bytesAvailable = RawHID.available(); - while (bytesAvailable--) { - if (len < sizeof(data)) { - data[len++] = RawHID.read(); - } - } - - // Process data from the host - if (len) { + if (bytesAvailable) + { digitalWrite(pinLed, HIGH); - // Disable interrupts while processing the data - uint8_t oldSREG = SREG; - cli(); - - // Mirror the incoming data from the host back - RawHID.write(data, len); - len = 0; - - SREG = oldSREG; + // Mirror data via Serial + while (bytesAvailable--) { + Serial.println(RawHID.read()); + } - // Simple debounce for led - delay(300); digitalWrite(pinLed, LOW); } } -void RawHIDEvent(uint8_t num) { - // This event is called via interrupt. - // Do not use print inside, or other long function calls! - // If you not use this event function, - // you might miss some data in the loop, - // if the host sends too fast or too much data at once. - - auto bytesAvailable = RawHID.available(); - while (bytesAvailable--) { - // Only add data to the buffer if its not full. - // If it is, no more event will occur - // and the data should be discarded - // or read (as shown) in the loop above. - if (len < sizeof(data)) { - data[len++] = RawHID.read(); - } - } -} - diff --git a/plugins/KeyboardioHID/src/SingleReport/RawHID.cpp b/plugins/KeyboardioHID/src/SingleReport/RawHID.cpp index 2f81830993..d4aa4d1d42 100644 --- a/plugins/KeyboardioHID/src/SingleReport/RawHID.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/RawHID.cpp @@ -47,13 +47,7 @@ static const uint8_t _hidReportDescriptorRawHID[] PROGMEM = { 0xC0 /* end collection */ }; -// Weak implementation of the Event function -void RawHIDEvent(uint8_t num) __attribute__ ((weak)); -void RawHIDEvent(uint8_t num){ - // Empty -} - -RawHID_::RawHID_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1), dataLength(0) +RawHID_::RawHID_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1), dataLength(0), dataAvailable(0), featureReport(NULL), featureLength(0) { epType[0] = EP_TYPE_INTERRUPT_IN; PluggableUSB().plug(this); @@ -120,51 +114,36 @@ bool RawHID_::setup(USBSetup& setup) } if (request == HID_SET_REPORT) { - // Get the data length information and the corresponding bytes + // Check if data has the correct length afterwards int length = setup.wLength; - uint8_t num = 0; - while(length) - { - // Dont receive more than the USB EP has to offer - // TODO use fixed 64 because control EP always have 64 bytes even on 16 u2. Test! - auto recvLength = length; - if(recvLength > USB_EP_SIZE){ - recvLength = USB_EP_SIZE; - } - if(recvLength > int(sizeof(data))){ - recvLength = int(sizeof(data)); + + // Feature (set feature report) + if(setup.wValueH == HID_REPORT_TYPE_FEATURE){ + // No need to check for negative featureLength values, + // except the host tries to send more then 32k bytes. + // We dont have that much ram anyways. + if (length == featureLength) { + USB_RecvControl(featureReport, featureLength); + + // Block until data is read (make length negative) + disableFeatureReport(); + return true; } - length -= recvLength; - - // Only receive data if the last one was read fully. - // Discard data if it wasnt read yet. - // To not miss any data you can use the (weak) event function. - if(!dataLength) - { + } + + // Output (set out report) + else if(setup.wValueH == HID_REPORT_TYPE_OUTPUT){ + if(!dataAvailable && length <= dataLength){ // Write data to fit to the end (not the beginning) of the array - USB_RecvControl(data + (sizeof(data) - recvLength), recvLength); - dataLength = recvLength; - RawHIDEvent(num++); - } - // Do not read the data, flag an error to the USB Host - // TODO always return no error, even if data was discarded? -> use break then - else{ - return false; + USB_RecvControl(data + dataLength - length, length); + dataAvailable = length; + return true; } } - - // Flag no error - // TODO this is required to get hyperion working - // however this blocks the CDC serial!? - return true; } } return false; } -void RawHID_::SendReport(void* data, int length){ - USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, length); -} - RawHID_ RawHID; diff --git a/plugins/KeyboardioHID/src/SingleReport/RawHID.h b/plugins/KeyboardioHID/src/SingleReport/RawHID.h index 5f2249cf97..9ccc43e224 100644 --- a/plugins/KeyboardioHID/src/SingleReport/RawHID.h +++ b/plugins/KeyboardioHID/src/SingleReport/RawHID.h @@ -73,32 +73,73 @@ class RawHID_ : public PluggableUSBModule, public Stream public: RawHID_(void); - void begin(void){ - // empty + void setFeatureReport(void* report, int length){ + if(length > 0){ + featureReport = (uint8_t*)report; + featureLength = length; + + // Disable feature report by default + disableFeatureReport(); + } + } + + int availableFeatureReport(void){ + if(featureLength < 0){ + return featureLength & ~0x8000; + } + return 0; + } + + void enableFeatureReport(void){ + featureLength &= ~0x8000; + } + + void disableFeatureReport(void){ + featureLength |= 0x8000; + } + + void begin(void* report, int length){ + if(length > 0){ + data = (uint8_t*)report; + dataLength = length; + dataAvailable = 0; + } } void end(void){ - // empty + disable(); + dataLength = 0; + } + + void enable(void){ + dataAvailable = 0; + } + + void disable(void){ + dataAvailable = -1; } virtual int available(void){ - return dataLength; + if(dataAvailable < 0){ + return 0; + } + return dataAvailable; } virtual int read(){ // Check if we have data available - if(dataLength) + if(dataAvailable > 0) { // Get next data byte (from the start to the end) - return data[sizeof(data) - dataLength--]; + return data[dataLength - dataAvailable--]; } return -1; } virtual int peek(){ // Check if we have data available - if(dataLength){ - return data[sizeof(data) - dataLength]; + if(dataAvailable > 0){ + return data[dataLength - dataAvailable]; } return -1; } @@ -114,27 +155,9 @@ class RawHID_ : public PluggableUSBModule, public Stream } virtual size_t write(uint8_t *buffer, size_t size){ - // TODO this will split the data into proper USB_EP_SIZE packets already - SendReport(buffer, size); - return size; - - size_t bytesleft = size; - // First work through the buffer thats already there - while (bytesleft >= RAWHID_TX_SIZE){ - SendReport(&buffer[size - bytesleft], RAWHID_TX_SIZE); - bytesleft -= RAWHID_TX_SIZE; - } - - // Write down the leftover bytes and fill with zeros - if (bytesleft){ - SendReport(&buffer[size - bytesleft], bytesleft); - } - - return size; + return USB_Send(pluggedEndpoint | TRANSFER_RELEASE, buffer, size); } - void SendReport(void* data, int length); - protected: // Implementation of the PUSBListNode int getInterface(uint8_t* interfaceCount); @@ -147,7 +170,11 @@ class RawHID_ : public PluggableUSBModule, public Stream // Buffer pointers to hold the received data int dataLength; - uint8_t data[RAWHID_RX_SIZE]; + int dataAvailable; + uint8_t* data; + + uint8_t* featureReport; + int featureLength; }; extern RawHID_ RawHID; From 6db1d685a919eaaa828e4eb5097af1cdfa5394e2 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 8 Nov 2015 20:06:17 +0100 Subject: [PATCH 332/602] minor keyboard feature request fixes --- .../examples/KeyboardFeatureReport/KeyboardFeatureReport.ino | 4 ++++ plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp | 1 + 2 files changed, 5 insertions(+) diff --git a/plugins/KeyboardioHID/examples/KeyboardFeatureReport/KeyboardFeatureReport.ino b/plugins/KeyboardioHID/examples/KeyboardFeatureReport/KeyboardFeatureReport.ino index f7148ea234..5946924206 100644 --- a/plugins/KeyboardioHID/examples/KeyboardFeatureReport/KeyboardFeatureReport.ino +++ b/plugins/KeyboardioHID/examples/KeyboardFeatureReport/KeyboardFeatureReport.ino @@ -5,7 +5,11 @@ KeyboardFeatureReport example Shows how to use BootKeyboard with a modified Hyperion Lightpack device. + This example also works with RawHID. Might only work under linux. + https://github.com/tvdzwan/hyperion/pull/407 + https://github.com/tvdzwan/hyperion/wiki + https://github.com/FastLED/FastLED See HID Project documentation for more information. https://github.com/NicoHood/HID/wiki/RawHID-API diff --git a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp index c13250399d..0261b411f3 100644 --- a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp @@ -158,6 +158,7 @@ bool BootKeyboard_::setup(USBSetup& setup) disableFeatureReport(); return true; } + // TODO fake clear data? } // Output (set led states) From b04c8e20781e4e65150cf3b5e61c2e8e39e0a82e Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 8 Nov 2015 20:06:46 +0100 Subject: [PATCH 333/602] Added RawHID Hyperion Paintpack example --- .../RawHIDPaintpack/RawHIDPaintpack.ino | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 plugins/KeyboardioHID/examples/RawHIDPaintpack/RawHIDPaintpack.ino diff --git a/plugins/KeyboardioHID/examples/RawHIDPaintpack/RawHIDPaintpack.ino b/plugins/KeyboardioHID/examples/RawHIDPaintpack/RawHIDPaintpack.ino new file mode 100644 index 0000000000..40e540d443 --- /dev/null +++ b/plugins/KeyboardioHID/examples/RawHIDPaintpack/RawHIDPaintpack.ino @@ -0,0 +1,92 @@ +/* + Copyright (c) 2014-2015 NicoHood + See the readme for credit to other people. + + RawHIDPaintpack example + + Shows how to use RawHID with the Hyperion Lightpack device. + https://github.com/tvdzwan/hyperion/wiki + https://github.com/FastLED/FastLED + + See HID Project documentation for more information. + https://github.com/NicoHood/HID/wiki/RawHID-API + https://github.com/NicoHood/HID/wiki/Keyboard-API#boot-keyboard +*/ + +#include "HID-Project.h" + +const int pinLed = LED_BUILTIN; + + +// FastLED +#include "FastLED.h" + +#define LED_PINS MOSI, SCK // DATA_PIN, or DATA_PIN, CLOCK_PIN +#define COLOR_ORDER RGB +#define CHIPSET WS2801 // WS2811, LPD8806, etc +#define NUM_LEDS 25 + +#define BRIGHTNESS 255 // Reduce power consumption +#define LED_DITHER 255 // Try 0 to disable flickering +#define CORRECTION TypicalLEDStrip + +CRGB leds[NUM_LEDS]; // Define the array of leds +uint8_t rawhidData[sizeof(leds) + 2]; + +void setup() { + // FastLED setup + FastLED.addLeds(leds, NUM_LEDS).setCorrection(CORRECTION); + FastLED.setBrightness(BRIGHTNESS); + FastLED.setDither(LED_DITHER); + + // Startup animation + fill_solid(leds, NUM_LEDS, CRGB::Red); + FastLED.show(); + delay(500); + fill_solid(leds, NUM_LEDS, CRGB::Green); + FastLED.show(); + delay(500); + fill_solid(leds, NUM_LEDS, CRGB::Blue); + FastLED.show(); + delay(500); + FastLED.clear(); + FastLED.show(); + + pinMode(pinLed, OUTPUT); + + // Set the RawHID OUT report array. + // Feature reports are also (parallel) possible, see the other example for this. + RawHID.begin(rawhidData, sizeof(rawhidData)); +} + +void loop() { + // Check if there is new data from the RawHID device + auto bytesAvailable = RawHID.available(); + if (bytesAvailable == sizeof(rawhidData)) + { + digitalWrite(pinLed, HIGH); + + // Check header for errors + if (RawHID.read() != 3) { + return; + } + if (RawHID.read() != 0) { + return; + } + + // Write data to led array + uint8_t* ptr = (uint8_t*)leds; + for (int i = 0; i < sizeof(leds); i++) { + *ptr = RawHID.read(); + ptr++; + } + + // Update leds, do not update in the loop, to avoid corrupted data. + // For example if you write (0, 0, 0) and the interrupt + // changes the data to (255, 255, 255) you might get (0, 255, 255). + // Using a duplicated led array in cli() context would also work. + FastLED.show(); + + digitalWrite(pinLed, LOW); + } +} From cb628dc61839596ebe0fde5bcbfae5a1154dcb27 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 8 Nov 2015 20:09:45 +0100 Subject: [PATCH 334/602] Moved some examples into separate folder --- .../examples/{ => Keyboard}/BootKeyboard/BootKeyboard.ino | 0 .../examples/{ => Keyboard}/ImprovedKeyboard/ImprovedKeyboard.ino | 0 .../examples/{ => Keyboard}/KeyboardLed/KeyboardLed.ino | 0 .../examples/{ => Keyboard}/NKROKeyboard/NKROKeyboard.ino | 0 .../examples/{ => Keyboard}/TeensyKeyboard/TeensyKeyboard.ino | 0 .../examples/{ => Mouse}/AbsoluteMouse/AbsoluteMouse.ino | 0 .../examples/{ => Mouse}/ImprovedMouse/ImprovedMouse.ino | 0 .../{ => RawHID}/KeyboardFeatureReport/KeyboardFeatureReport.ino | 0 plugins/KeyboardioHID/examples/RawHID/{ => RawHID}/RawHID.ino | 0 .../examples/{ => RawHID}/RawHIDPaintpack/RawHIDPaintpack.ino | 0 10 files changed, 0 insertions(+), 0 deletions(-) rename plugins/KeyboardioHID/examples/{ => Keyboard}/BootKeyboard/BootKeyboard.ino (100%) rename plugins/KeyboardioHID/examples/{ => Keyboard}/ImprovedKeyboard/ImprovedKeyboard.ino (100%) rename plugins/KeyboardioHID/examples/{ => Keyboard}/KeyboardLed/KeyboardLed.ino (100%) rename plugins/KeyboardioHID/examples/{ => Keyboard}/NKROKeyboard/NKROKeyboard.ino (100%) rename plugins/KeyboardioHID/examples/{ => Keyboard}/TeensyKeyboard/TeensyKeyboard.ino (100%) rename plugins/KeyboardioHID/examples/{ => Mouse}/AbsoluteMouse/AbsoluteMouse.ino (100%) rename plugins/KeyboardioHID/examples/{ => Mouse}/ImprovedMouse/ImprovedMouse.ino (100%) rename plugins/KeyboardioHID/examples/{ => RawHID}/KeyboardFeatureReport/KeyboardFeatureReport.ino (100%) rename plugins/KeyboardioHID/examples/RawHID/{ => RawHID}/RawHID.ino (100%) rename plugins/KeyboardioHID/examples/{ => RawHID}/RawHIDPaintpack/RawHIDPaintpack.ino (100%) diff --git a/plugins/KeyboardioHID/examples/BootKeyboard/BootKeyboard.ino b/plugins/KeyboardioHID/examples/Keyboard/BootKeyboard/BootKeyboard.ino similarity index 100% rename from plugins/KeyboardioHID/examples/BootKeyboard/BootKeyboard.ino rename to plugins/KeyboardioHID/examples/Keyboard/BootKeyboard/BootKeyboard.ino diff --git a/plugins/KeyboardioHID/examples/ImprovedKeyboard/ImprovedKeyboard.ino b/plugins/KeyboardioHID/examples/Keyboard/ImprovedKeyboard/ImprovedKeyboard.ino similarity index 100% rename from plugins/KeyboardioHID/examples/ImprovedKeyboard/ImprovedKeyboard.ino rename to plugins/KeyboardioHID/examples/Keyboard/ImprovedKeyboard/ImprovedKeyboard.ino diff --git a/plugins/KeyboardioHID/examples/KeyboardLed/KeyboardLed.ino b/plugins/KeyboardioHID/examples/Keyboard/KeyboardLed/KeyboardLed.ino similarity index 100% rename from plugins/KeyboardioHID/examples/KeyboardLed/KeyboardLed.ino rename to plugins/KeyboardioHID/examples/Keyboard/KeyboardLed/KeyboardLed.ino diff --git a/plugins/KeyboardioHID/examples/NKROKeyboard/NKROKeyboard.ino b/plugins/KeyboardioHID/examples/Keyboard/NKROKeyboard/NKROKeyboard.ino similarity index 100% rename from plugins/KeyboardioHID/examples/NKROKeyboard/NKROKeyboard.ino rename to plugins/KeyboardioHID/examples/Keyboard/NKROKeyboard/NKROKeyboard.ino diff --git a/plugins/KeyboardioHID/examples/TeensyKeyboard/TeensyKeyboard.ino b/plugins/KeyboardioHID/examples/Keyboard/TeensyKeyboard/TeensyKeyboard.ino similarity index 100% rename from plugins/KeyboardioHID/examples/TeensyKeyboard/TeensyKeyboard.ino rename to plugins/KeyboardioHID/examples/Keyboard/TeensyKeyboard/TeensyKeyboard.ino diff --git a/plugins/KeyboardioHID/examples/AbsoluteMouse/AbsoluteMouse.ino b/plugins/KeyboardioHID/examples/Mouse/AbsoluteMouse/AbsoluteMouse.ino similarity index 100% rename from plugins/KeyboardioHID/examples/AbsoluteMouse/AbsoluteMouse.ino rename to plugins/KeyboardioHID/examples/Mouse/AbsoluteMouse/AbsoluteMouse.ino diff --git a/plugins/KeyboardioHID/examples/ImprovedMouse/ImprovedMouse.ino b/plugins/KeyboardioHID/examples/Mouse/ImprovedMouse/ImprovedMouse.ino similarity index 100% rename from plugins/KeyboardioHID/examples/ImprovedMouse/ImprovedMouse.ino rename to plugins/KeyboardioHID/examples/Mouse/ImprovedMouse/ImprovedMouse.ino diff --git a/plugins/KeyboardioHID/examples/KeyboardFeatureReport/KeyboardFeatureReport.ino b/plugins/KeyboardioHID/examples/RawHID/KeyboardFeatureReport/KeyboardFeatureReport.ino similarity index 100% rename from plugins/KeyboardioHID/examples/KeyboardFeatureReport/KeyboardFeatureReport.ino rename to plugins/KeyboardioHID/examples/RawHID/KeyboardFeatureReport/KeyboardFeatureReport.ino diff --git a/plugins/KeyboardioHID/examples/RawHID/RawHID.ino b/plugins/KeyboardioHID/examples/RawHID/RawHID/RawHID.ino similarity index 100% rename from plugins/KeyboardioHID/examples/RawHID/RawHID.ino rename to plugins/KeyboardioHID/examples/RawHID/RawHID/RawHID.ino diff --git a/plugins/KeyboardioHID/examples/RawHIDPaintpack/RawHIDPaintpack.ino b/plugins/KeyboardioHID/examples/RawHID/RawHIDPaintpack/RawHIDPaintpack.ino similarity index 100% rename from plugins/KeyboardioHID/examples/RawHIDPaintpack/RawHIDPaintpack.ino rename to plugins/KeyboardioHID/examples/RawHID/RawHIDPaintpack/RawHIDPaintpack.ino From a5ffb620c7bfd7e5489df6377c079cf273dd6063 Mon Sep 17 00:00:00 2001 From: Nico Date: Tue, 10 Nov 2015 07:25:40 +0100 Subject: [PATCH 335/602] Delete .development --- plugins/KeyboardioHID/.development | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 plugins/KeyboardioHID/.development diff --git a/plugins/KeyboardioHID/.development b/plugins/KeyboardioHID/.development deleted file mode 100644 index e69de29bb2..0000000000 From 02da01bb919e3a374ec11760e1faf4ab67c7a156 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Mon, 30 Nov 2015 17:55:27 +0100 Subject: [PATCH 336/602] Removed unnecessary Arduino include --- plugins/KeyboardioHID/src/HID-Project.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index ff592d384f..1858f0b9ac 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -27,9 +27,6 @@ THE SOFTWARE. // Software version #define HID_PROJECT_VERSION 250 -// TODO remove https://github.com/arduino/arduino-builder/issues/33 -#include - #if ARDUINO < 10606 #error HID Project requires Arduino IDE 1.6.6 or greater. Please update your IDE. #endif From 436711e09627ae1313088eba30dbe7a32b208b0c Mon Sep 17 00:00:00 2001 From: NicoHood Date: Mon, 30 Nov 2015 17:59:50 +0100 Subject: [PATCH 337/602] Fix NKRO example issue #64 --- plugins/KeyboardioHID/keywords.txt | 4 +++- plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.h | 3 +-- plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h | 3 +-- plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h | 4 ++-- plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.h | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/plugins/KeyboardioHID/keywords.txt b/plugins/KeyboardioHID/keywords.txt index e5ce27925b..873224af71 100644 --- a/plugins/KeyboardioHID/keywords.txt +++ b/plugins/KeyboardioHID/keywords.txt @@ -13,6 +13,8 @@ begin KEYWORD2 end KEYWORD2 press KEYWORD2 +add KEYWORD2 +remove KEYWORD2 release KEYWORD2 releaseAll KEYWORD2 @@ -36,7 +38,7 @@ set_key4 KEYWORD2 set_key5 KEYWORD2 set_key6 KEYWORD2 set_media KEYWORD2 -send_now KEYWORD2 +send KEYWORD2 buttons KEYWORD2 xAxis KEYWORD2 diff --git a/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.h b/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.h index d9185cf27e..d59486c272 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.h @@ -37,8 +37,7 @@ class Keyboard_ : public DefaultKeyboardAPI Keyboard_(void); void wakeupHost(void); -protected: - virtual inline int send(void) override; + virtual inline int send(void) final; }; extern Keyboard_ Keyboard; diff --git a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h index 933c12762f..ef5c9b4d4b 100644 --- a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h @@ -36,8 +36,7 @@ class NKROKeyboard_ : public NKROKeyboardAPI public: NKROKeyboard_(void); -protected: - virtual inline int send(void) override; + virtual int send(void) final; }; extern NKROKeyboard_ NKROKeyboard; diff --git a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h index d5c9ff01ed..cd28a8f62d 100644 --- a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h @@ -63,6 +63,8 @@ class BootKeyboard_ : public PluggableUSBModule, public DefaultKeyboardAPI void disableFeatureReport(void){ featureLength |= 0x8000; } + + virtual int send(void) final; protected: // Implementation of the PUSBListNode @@ -78,8 +80,6 @@ class BootKeyboard_ : public PluggableUSBModule, public DefaultKeyboardAPI uint8_t* featureReport; int featureLength; - - virtual int send(void) override; }; extern BootKeyboard_ BootKeyboard; diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.h b/plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.h index 422a47b3e3..d5f2ead6e7 100644 --- a/plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.h +++ b/plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.h @@ -37,6 +37,8 @@ class SingleNKROKeyboard_ : public PluggableUSBModule, public NKROKeyboardAPI SingleNKROKeyboard_(void); uint8_t getLeds(void); uint8_t getProtocol(void); + + virtual int send(void) final; protected: // Implementation of the PUSBListNode @@ -49,8 +51,6 @@ class SingleNKROKeyboard_ : public PluggableUSBModule, public NKROKeyboardAPI uint8_t idle; uint8_t leds; - - virtual inline int send(void) override; }; extern SingleNKROKeyboard_ SingleNKROKeyboard; From ca28732187da46823328869f770b17995b2c4427 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Mon, 30 Nov 2015 18:05:56 +0100 Subject: [PATCH 338/602] Changed version number to 2.4.1 --- plugins/KeyboardioHID/Readme.md | 10 +++++++--- plugins/KeyboardioHID/library.properties | 2 +- plugins/KeyboardioHID/src/HID-Project.h | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index da5c97d19c..ad1a29d7cf 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -1,5 +1,5 @@ -Arduino HID Project 2.5 -======================= +Arduino HID Project 2.4.1 +========================= ![Header Picture](header.jpg) @@ -49,7 +49,11 @@ www.nicohood.de Version History =============== ``` -2.5 Release (xx.xx.2015) +2.4.1 Release (xx.xx.2015) +* RawHID Improvements +* Added Keyboard Feature Report +* NKRO and Keyboard API fixes +* Arduino library manager fix 2.4 Release (06.11.2015) * Added Arduino IDE 1.6.6 compatibility with Pluggable HID diff --git a/plugins/KeyboardioHID/library.properties b/plugins/KeyboardioHID/library.properties index 1bfd8b4bc1..0dd202d31a 100644 --- a/plugins/KeyboardioHID/library.properties +++ b/plugins/KeyboardioHID/library.properties @@ -1,5 +1,5 @@ name=HID-Project -version=2.5 +version=2.4.1 author=NicoHood maintainer=NicoHood sentence=Extended HID Functions for Arduino diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index 1858f0b9ac..ff008b12b2 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -25,7 +25,7 @@ THE SOFTWARE. #pragma once // Software version -#define HID_PROJECT_VERSION 250 +#define HID_PROJECT_VERSION 241 #if ARDUINO < 10606 #error HID Project requires Arduino IDE 1.6.6 or greater. Please update your IDE. From 107f36acb202006dba533b7f5edd5c47b48ead38 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sat, 5 Dec 2015 08:00:04 +0100 Subject: [PATCH 339/602] Added 1.6.7 as requirement --- plugins/KeyboardioHID/src/HID-Project.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index ff008b12b2..5393c3471c 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -27,8 +27,8 @@ THE SOFTWARE. // Software version #define HID_PROJECT_VERSION 241 -#if ARDUINO < 10606 -#error HID Project requires Arduino IDE 1.6.6 or greater. Please update your IDE. +#if ARDUINO < 10607 +#error HID Project requires Arduino IDE 1.6.7 or greater. Please update your IDE. #endif #if !defined(USBCON) From f25d0d8a16f0f9f7bca0d4d6333df0dba376e31a Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Mon, 7 Dec 2015 14:57:16 -0800 Subject: [PATCH 340/602] include HID macros nico has submitted upstream --- plugins/KeyboardioHID/src/HID-Settings.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/plugins/KeyboardioHID/src/HID-Settings.h b/plugins/KeyboardioHID/src/HID-Settings.h index 692186bd9f..29a5f1b141 100644 --- a/plugins/KeyboardioHID/src/HID-Settings.h +++ b/plugins/KeyboardioHID/src/HID-Settings.h @@ -108,3 +108,10 @@ THE SOFTWARE. #ifndef HID_REPORTID_TEENSY_KEYBOARD #define HID_REPORTID_TEENSY_KEYBOARD 9 #endif + + +// Nico has submitted these definitions upstream, but they're not merged yet +// HID Request Type HID1.11 Page 51 7.2.1 Get_Report Request +#define HID_REPORT_TYPE_INPUT 1 +#define HID_REPORT_TYPE_OUTPUT 2 +#define HID_REPORT_TYPE_FEATURE 3 From 925cb181a99cc7d308a14bc7799871eb4f8061aa Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Wed, 9 Dec 2015 13:08:44 -0800 Subject: [PATCH 341/602] Remove the TeensyKeyboard driver --- plugins/KeyboardioHID/Readme.md | 212 +- .../TeensyKeyboard/TeensyKeyboard.ino | 52 - plugins/KeyboardioHID/keywords.txt | 1 - .../src/HID-APIs/TeensyKeyboardAPI.h | 134 - .../src/HID-APIs/TeensyKeyboardAPI.hpp | 442 -- .../src/HID-APIs/TeensyKeylayouts.h | 5418 ----------------- plugins/KeyboardioHID/src/HID-Project.h | 7 +- plugins/KeyboardioHID/src/HID-Settings.h | 4 - 8 files changed, 7 insertions(+), 6263 deletions(-) delete mode 100644 plugins/KeyboardioHID/examples/Keyboard/TeensyKeyboard/TeensyKeyboard.ino delete mode 100644 plugins/KeyboardioHID/src/HID-APIs/TeensyKeyboardAPI.h delete mode 100644 plugins/KeyboardioHID/src/HID-APIs/TeensyKeyboardAPI.hpp delete mode 100644 plugins/KeyboardioHID/src/HID-APIs/TeensyKeylayouts.h diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index ad1a29d7cf..fa774a4c9d 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -1,7 +1,8 @@ -Arduino HID Project 2.4.1 +Keyboardio USB HID Driver ========================= -![Header Picture](header.jpg) +Based on Nico Hood's HID-Project. Please don't contact Nico with issues in this library. + This project went through a lot of phases and has now reached a new Arduino ~~USB-Core~~ Library with a lot of new functions like extended HID. It also supports HoodLoader1+2. @@ -17,7 +18,6 @@ The idea is to enable enhanced USB functions to almost all 'standard' Arduino bo **Supported HID devices:** * Keyboard with Leds out (8 modifiers + 6 keys pressed at the same time, + 1 limited linux consumer key) -* ~~Teensy Keyboard with different keyboard layouts (german, french and many more)~~ soon * NKRO Keyboard with Leds out (press up to 113 keys at the same time) * Mouse (5 buttons, move, wheel) * BootKeyboard/BootMouse BIOS protocol support @@ -38,209 +38,3 @@ All documentation moved to the [wiki page](https://github.com/NicoHood/HID/wiki) An offline snapshot is available in [releases](https://github.com/NicoHood/HID/releases). -Contact -======= - -You can contact me on my wordpress blog in the contact section. - -www.nicohood.de - - -Version History -=============== -``` -2.4.1 Release (xx.xx.2015) -* RawHID Improvements -* Added Keyboard Feature Report -* NKRO and Keyboard API fixes -* Arduino library manager fix - -2.4 Release (06.11.2015) -* Added Arduino IDE 1.6.6 compatibility with Pluggable HID -* Improved Pluggable HID (see Arduyuino changelog for my improvements) -* Changed USB-Core into a simple library, only made possible with Pluggable HID -* Removed HID presets in boards menu (like mouse + keyboard + consumer + system) -* Added NKRO Keyboard -* Added Led report for Keyboard -* Added 1 Linux consumer key for keyboard -* Added BootKeyboard/Mouse support (BIOS compatibility) -* Added RawHID -* Added a few key definitions -* Renew whole Keyboard API and its definitions via enum -* Uses .alinkage custom IDE option -* Improved and updated examples -* A lot of other minor and major fixes I missed to mention. - -2.3 Release (never released) -* Updated Libraries -* Updated Arduino Core -* Added Minor Consumer definitions -* Fixed platforms.txt -* SERIAL_RX_BUFFER_SIZE reverted to 16 (TODO add -D to build option) - -2.2 Release (12.04.2015) -* added experimental, not finished nor documented HID-Bridge between 16u2 and 328/2560 -* increased HW Serial1 RX buffer size from 16 to 32 (TX still 16) -* added colour highlighting (through HID-Bridge library) -* removed fixed size in report buffers -* used HID_KeyboardReport_Data_t now in Keyboard API -* Arduino as ISP fix for 328 -* Upload verification on USB hubs fix for HL2.0.4 -* No USB workaround for Leonardo integrated into variants -* Changed USB Wakeup in System API -* Consumer Key fix (issue #3) -* Gamepad fix (issue #14) -* Added Keycode example -* Mouse press + release fix - -2.1 Release (28.01.2015) -* Reworked the whole USB-Core from scratch -* Uses less flash if HID or Serial is not used -* Extended and compacter(flash) HID Report Descriptors -* Fixed USB Device Descriptor -* Added u2 compatibility with smaller USB_EP_SIZE (16u2 etc) -* Added Serial Event for LineEncoding and LineState -* Added Serial Function to get dtr state, line encoding etc -* Added Keyboard Led Out report to get Led states (for numlock etc) -* Made CDC-Core independent from USB-Core -* Made HID-Core independent from USB-Core -* Made HID-API independent from HID-Core -* Removed not needed virtual functions in Keyboard -* Made HID Reports and its IDs replaceable via pins_Arduino.h -* Added Absolute Mouse -* Removed uint8_t USBPutChar(uint8_t c); in HID.cpp -* Made void Recv(volatile u8* data, u8 count) in USBCore.cpp static inline -* HID-APIs sends a clean report on begin() and end() now. -* Removed virtual functions in Keyboard API -* Added Keycode functions in Keyboard API -* Inlined a lot of the HID API functions to save flash -* Added Gamepad -* Added RawHID API (but RawHID itself isnt working still) -* Added USB Wakeup support -* Separated USB-Core in its own folder -* Added HID Tables -* USB-Serial now fully reprogrammable -* Easy USB-Core selection via Tools->USB-Core -* Added Arduino as ISP fix for 32u4 and 16u2 -* Moved documentation to the wiki -* Added AVR libraries to the core with the better SoftSerial - -2.0 Release (29.11.2014) -* Added HoodLoader2 -* Separated HoodLoader1&2 more -* Added u2 series for USB-Core -* Extended USB core and fixed minor things for the u2 series -* Added Led Out report. -* Added CDC Line state -* Reworked the whole library structure again - -1.8 Beta Release (26.08.2014) -* Changes in the Hoodloader1: - * **Huge improvements**, see Hoodloader1 repository - * Reworked the whole library, easy installation now - * HID fixes for Media Keys/Ubuntu - * Removed Joystick, added 4 Gamepads - -1.7.3 Beta Release (10.08.2014) -* Changes in the Hoodloader1: - * Fixed HID flush bug (1.6 - 1.7.2) - -1.7.2 Beta Release (10.08.2014) -* Changes in the Hoodloader1: - * Added Lite version for 8u2 - * Added Versions that show up as Uno/Mega (not recommended) - * Makefile and structure changes - -1.7.1 Beta Release (10.08.2014) -* Changes in the Hoodloader1: - * Fixed HID deactivation bug - -1.7 Beta Release (10.08.2014) -* Changes in the Hoodloader1: - * Works as ISP now. See Hoodloader1 Repository for more information. - * Exceeded 8kb limit. For flashing a 8u2 use v1.6 please! -* Changed Readme text - -1.6 Beta Release (09.08.2014) -* Bugfixes in the Hoodloader1: - * Changed HID management (not blocking that much, faster) - * added RawHID in/out (HID to Serial) -* Added RawHID Class and example - -1.5 Beta Release (21.07.2014) -* Moved Hoodloader1 source to a separate Github page -* Bugfixes in the Hoodloader: - * Firmware is still available here - * Overall a lot of ram improvements, now with a big global union of ram - * Removed USBtoUSART buffer (not needed, saved 128/500 bytes) - * Removed Lite version because of better ram usage not needed - * Separated different modes better to not cause any errors in default mode - * Improved the deactivate option - * Integrated NHP directly - * Replaced LightweightRingbuffer with native Lufa Ringbuffer - * Improved writing to CDC Host - * Fixed a bug in checkNHPProtocol: & needs to be a == - * General structure changes - * Improved stability - * Fixed Arduino as ISP bug - -1.4.1 Beta Release (10.07.2014) -* #define Bugfix in USBAPI.h - -1.4 Beta Release (10.07.2014) -* Bugfixes in the Hoodloader1: - * Added Lite Version with less ram usage - * Changed PIDs, edited driver file -* merged v1.0.x and v1.5.x together (both are compatible!) -* added IDE v1.5.7 support -* added Tutorials - -1.3 Beta Release (01.07.2014) -* Bugfixes in the Hoodloader1: - * Improved ram usage -* **Important NHP fix inside the HID Class for Uno/Mega** - -1.2 Beta Release (22.06.2014) -* Added 1.0.x/1.5.x support -* Bugfixes in the Hoodloader1: - * Sometimes HID Devices weren't updating - when using more than 1 Device (set forcewrite to true) - * Fast updates crashed the bootloader - (too much ram usage, set CDC buffer from 128b to 100b each) -* Minor file structure changes - -1.1 Beta Release (05.06.2014) -* Added Leonardo/Micro support -* Included NicoHoodProtocol -* Minor fixes - -1.0 Beta Release (03.06.2014) -``` - - -Licence and Copyright -===================== -If you use this library for any cool project let me know! - -``` -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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. -``` diff --git a/plugins/KeyboardioHID/examples/Keyboard/TeensyKeyboard/TeensyKeyboard.ino b/plugins/KeyboardioHID/examples/Keyboard/TeensyKeyboard/TeensyKeyboard.ino deleted file mode 100644 index 0f17282fc5..0000000000 --- a/plugins/KeyboardioHID/examples/Keyboard/TeensyKeyboard/TeensyKeyboard.ino +++ /dev/null @@ -1,52 +0,0 @@ -/* - Copyright (c) 2014 NicoHood - See the readme for credit to other people. - - Teens Keyboard example - Press a button to write some text to your PC. - - You can change the keyboard layout to a different language. - - See official and HID Project documentation for more infos - https://github.com/NicoHood/HID/wiki/Keyboard-API -*/ - -// Add this before you include the HID-Project. -// This is required because the Teensy uses different KEY definitions. -#define USE_TEENSY_KEYBOARD -#include "HID-Project.h" - -const int pinLed = LED_BUILTIN; -const int pinButton = 2; - -void setup() { - pinMode(pinLed, OUTPUT); - pinMode(pinButton, INPUT_PULLUP); - - // Sends a clean report to the host. This is important on any Arduino type. - TeensyKeyboard.begin(); -} - - -void loop() { - if (!digitalRead(pinButton)) { - digitalWrite(pinLed, HIGH); - - // Similar the official library, pretty much self explaining - TeensyKeyboard.println(F("This message was sent with my Arduino.")); - TeensyKeyboard.println(F("Lowercase: abcdefghijklmnopqrstuvwxyz")); - TeensyKeyboard.println(F("Uppercase: ABCDEFGHIJKLMNOPQRSTUVWXYZ")); - - // For a single keypress use press() and release() - TeensyKeyboard.press(KEY_ENTER); - TeensyKeyboard.releaseAll(); - - // Do NOT use write(). See documentation for more help. - //TeensyKeyboard.write(KEY_ENTER); - - // Simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } -} - diff --git a/plugins/KeyboardioHID/keywords.txt b/plugins/KeyboardioHID/keywords.txt index 873224af71..fb6c8a7cd5 100644 --- a/plugins/KeyboardioHID/keywords.txt +++ b/plugins/KeyboardioHID/keywords.txt @@ -71,7 +71,6 @@ Gamepad1 KEYWORD1 Gamepad2 KEYWORD1 Gamepad3 KEYWORD1 Gamepad4 KEYWORD1 -TeensyKeyboard KEYWORD1 NKROKeyboard KEYWORD1 SingleNKROKeyboard KEYWORD1 AbsoluteMouse KEYWORD1 diff --git a/plugins/KeyboardioHID/src/HID-APIs/TeensyKeyboardAPI.h b/plugins/KeyboardioHID/src/HID-APIs/TeensyKeyboardAPI.h deleted file mode 100644 index 9282dc4b53..0000000000 --- a/plugins/KeyboardioHID/src/HID-APIs/TeensyKeyboardAPI.h +++ /dev/null @@ -1,134 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 guard -#pragma once - -#include -#include "HID-Settings.h" -#include "TeensyKeylayouts.h" - -// Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60 -static const uint8_t PROGMEM teensykeyboard_hid_report_desc[] = { - 0x05, 0x01, // Usage Page (Generic Desktop), - 0x09, 0x06, // Usage (Keyboard), - 0xA1, 0x01, // Collection (Application), - 0x85, HID_REPORTID_TEENSY_KEYBOARD, // REPORT_ID - 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, 0x08, // Report Count (8), - 0x75, 0x01, // Report Size (1), - 0x15, 0x00, // Logical Minimum (0), - 0x25, 0x01, // Logical Maximum (1), - 0x05, 0x0C, // Usage Page (Consumer), - 0x09, 0xE9, // Usage (Volume Increment), - 0x09, 0xEA, // Usage (Volume Decrement), - 0x09, 0xE2, // Usage (Mute), - 0x09, 0xCD, // Usage (Play/Pause), - 0x09, 0xB5, // Usage (Scan Next Track), - 0x09, 0xB6, // Usage (Scan Previous Track), - 0x09, 0xB7, // Usage (Stop), - 0x09, 0xB8, // Usage (Eject), - 0x81, 0x02, // Input (Data, Variable, Absolute), ;Media keys - - // Note: Teensy ledreport was not modified to 8 bit, nor left out when leds are deactivated - 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, 0x7F, // Logical Maximum(104), - 0x05, 0x07, // Usage Page (Key Codes), - 0x19, 0x00, // Usage Minimum (0), - 0x29, 0x7F, // Usage Maximum (104), - 0x81, 0x00, // Input (Data, Array), ;Normal keys - 0xc0 // End Collection -}; - -typedef union{ - // Low level key report: up to 6 keys and shift, ctrl etc at once - uint8_t whole8[]; - uint16_t whole16[]; - uint32_t whole32[]; - struct{ - uint8_t modifiers; - uint8_t reserved; - uint8_t keys[6]; - }; -} HID_KeyboardReport_Data_t; - -class TeensyKeyboardAPI : public Print -{ - public: - TeensyKeyboardAPI(void) { } - - void begin(void) { } - void end(void) { } - virtual size_t write(uint8_t); - using Print::write; - inline void write_unicode(uint16_t unicode) { write_keycode(unicode_to_keycode(unicode)); } - void set_modifier(uint8_t); - void set_key1(uint8_t); - void set_key2(uint8_t); - void set_key3(uint8_t); - void set_key4(uint8_t); - void set_key5(uint8_t); - void set_key6(uint8_t); - void set_media(uint8_t); - void send_now(void); - void press(uint16_t n); - void release(uint16_t n); - void releaseAll(void); - - // Sending is public in the base class for advanced users. - virtual void sendReport(void* data, int length) = 0; - -private: - KEYCODE_TYPE unicode_to_keycode(uint16_t unicode); - KEYCODE_TYPE deadkey_to_keycode(KEYCODE_TYPE keycode); - uint8_t keycode_to_modifier(KEYCODE_TYPE keycode); - uint8_t keycode_to_key(KEYCODE_TYPE keycode); - void presskey(uint8_t key, uint8_t modifier); - void releasekey(uint8_t key, uint8_t modifier); - void write_keycode(KEYCODE_TYPE key); - void write_key(KEYCODE_TYPE code); - uint8_t utf8_state; - uint16_t unicode_wchar; - uint8_t keyboard_report_data[8]; -}; - -// Implementation is inline -#include "TeensyKeyboardAPI.hpp" diff --git a/plugins/KeyboardioHID/src/HID-APIs/TeensyKeyboardAPI.hpp b/plugins/KeyboardioHID/src/HID-APIs/TeensyKeyboardAPI.hpp deleted file mode 100644 index e0e756e741..0000000000 --- a/plugins/KeyboardioHID/src/HID-APIs/TeensyKeyboardAPI.hpp +++ /dev/null @@ -1,442 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 guard -#pragma once - -// Step #1, decode UTF8 to Unicode code points -// -size_t TeensyKeyboardAPI::write(uint8_t c) -{ - if (c < 0x80) { - // single byte encoded, 0x00 to 0x7F - utf8_state = 0; - write_unicode(c); - } else if (c < 0xC0) { - // 2nd, 3rd or 4th byte, 0x80 to 0xBF - c &= 0x3F; - if (utf8_state == 1) { - utf8_state = 0; - write_unicode(unicode_wchar | c); - } else if (utf8_state == 2) { - unicode_wchar |= ((uint16_t)c << 6); - utf8_state = 1; - } - } else if (c < 0xE0) { - // begin 2 byte sequence, 0xC2 to 0xDF - // or illegal 2 byte sequence, 0xC0 to 0xC1 - unicode_wchar = (uint16_t)(c & 0x1F) << 6; - utf8_state = 1; - } else if (c < 0xF0) { - // begin 3 byte sequence, 0xE0 to 0xEF - unicode_wchar = (uint16_t)(c & 0x0F) << 12; - utf8_state = 2; - } else { - // begin 4 byte sequence (not supported), 0xF0 to 0xF4 - // or illegal, 0xF5 to 0xFF - utf8_state = 255; - } - return 1; -} - - -// Step #2: translate Unicode code point to keystroke sequence -// -KEYCODE_TYPE TeensyKeyboardAPI::unicode_to_keycode(uint16_t cpoint) -{ - // Unicode code points beyond U+FFFF are not supported - // technically this input should probably be called UCS-2 - if (cpoint < 32) { - if (cpoint == 10) return KEY_ENTER & 0x3FFF; - return 0; - } - if (cpoint < 128) { - if (sizeof(KEYCODE_TYPE) == 1) { - return pgm_read_byte(keycodes_ascii + (cpoint - 0x20)); - } else if (sizeof(KEYCODE_TYPE) == 2) { - return pgm_read_word(keycodes_ascii + (cpoint - 0x20)); - } - return 0; - } - #ifdef ISO_8859_1_A0 - if (cpoint <= 0xA0) return 0; - if (cpoint < 0x100) { - if (sizeof(KEYCODE_TYPE) == 1) { - return pgm_read_byte(keycodes_iso_8859_1 + (cpoint - 0xA0)); - } else if (sizeof(KEYCODE_TYPE) == 2) { - return pgm_read_word(keycodes_iso_8859_1 + (cpoint - 0xA0)); - } - return 0; - } - #endif - //#ifdef UNICODE_20AC - //if (cpoint == 0x20AC) return UNICODE_20AC & 0x3FFF; - //#endif - #ifdef KEYCODE_EXTRA00 - if (cpoint == UNICODE_EXTRA00) return KEYCODE_EXTRA00 & 0x3FFF; - #endif - #ifdef KEYCODE_EXTRA01 - if (cpoint == UNICODE_EXTRA01) return KEYCODE_EXTRA01 & 0x3FFF; - #endif - #ifdef KEYCODE_EXTRA02 - if (cpoint == UNICODE_EXTRA02) return KEYCODE_EXTRA02 & 0x3FFF; - #endif - #ifdef KEYCODE_EXTRA03 - if (cpoint == UNICODE_EXTRA03) return KEYCODE_EXTRA03 & 0x3FFF; - #endif - #ifdef KEYCODE_EXTRA04 - if (cpoint == UNICODE_EXTRA04) return KEYCODE_EXTRA04 & 0x3FFF; - #endif - #ifdef KEYCODE_EXTRA05 - if (cpoint == UNICODE_EXTRA05) return KEYCODE_EXTRA05 & 0x3FFF; - #endif - #ifdef KEYCODE_EXTRA06 - if (cpoint == UNICODE_EXTRA06) return KEYCODE_EXTRA06 & 0x3FFF; - #endif - #ifdef KEYCODE_EXTRA07 - if (cpoint == UNICODE_EXTRA07) return KEYCODE_EXTRA07 & 0x3FFF; - #endif - #ifdef KEYCODE_EXTRA08 - if (cpoint == UNICODE_EXTRA08) return KEYCODE_EXTRA08 & 0x3FFF; - #endif - #ifdef KEYCODE_EXTRA09 - if (cpoint == UNICODE_EXTRA09) return KEYCODE_EXTRA09 & 0x3FFF; - #endif - return 0; -} - -// Step #3: execute keystroke sequence -// -void TeensyKeyboardAPI::write_keycode(KEYCODE_TYPE keycode) -{ - if (!keycode) return; - #ifdef DEADKEYS_MASK - KEYCODE_TYPE deadkeycode = deadkey_to_keycode(keycode); - if (deadkeycode) write_key(deadkeycode); - #endif - write_key(keycode); -} - -KEYCODE_TYPE TeensyKeyboardAPI::deadkey_to_keycode(KEYCODE_TYPE keycode) -{ - #ifdef DEADKEYS_MASK - keycode &= DEADKEYS_MASK; - if (keycode == 0) return 0; - #ifdef ACUTE_ACCENT_BITS - if (keycode == ACUTE_ACCENT_BITS) return DEADKEY_ACUTE_ACCENT; - #endif - #ifdef CEDILLA_BITS - if (keycode == CEDILLA_BITS) return DEADKEY_CEDILLA; - #endif - #ifdef CIRCUMFLEX_BITS - if (keycode == CIRCUMFLEX_BITS) return DEADKEY_CIRCUMFLEX; - #endif - #ifdef DIAERESIS_BITS - if (keycode == DIAERESIS_BITS) return DEADKEY_DIAERESIS; - #endif - #ifdef GRAVE_ACCENT_BITS - if (keycode == GRAVE_ACCENT_BITS) return DEADKEY_GRAVE_ACCENT; - #endif - #ifdef TILDE_BITS - if (keycode == TILDE_BITS) return DEADKEY_TILDE; - #endif - #ifdef RING_ABOVE_BITS - if (keycode == RING_ABOVE_BITS) return DEADKEY_RING_ABOVE; - #endif - #endif // DEADKEYS_MASK - return 0; -} - -// Step #4: do each keystroke -// -void TeensyKeyboardAPI::write_key(KEYCODE_TYPE keycode) -{ - keyboard_report_data[0] = keycode_to_modifier(keycode); - keyboard_report_data[1] = 0; - keyboard_report_data[2] = keycode_to_key(keycode); - keyboard_report_data[3] = 0; - keyboard_report_data[4] = 0; - keyboard_report_data[5] = 0; - keyboard_report_data[6] = 0; - keyboard_report_data[7] = 0; - send_now(); - keyboard_report_data[0] = 0; - keyboard_report_data[2] = 0; - send_now(); -} - -uint8_t TeensyKeyboardAPI::keycode_to_modifier(KEYCODE_TYPE keycode) -{ - uint8_t modifier=0; - - #ifdef SHIFT_MASK - if (keycode & SHIFT_MASK) modifier |= MODIFIERKEY_SHIFT; - #endif - #ifdef ALTGR_MASK - if (keycode & ALTGR_MASK) modifier |= MODIFIERKEY_RIGHT_ALT; - #endif - #ifdef RCTRL_MASK - if (keycode & RCTRL_MASK) modifier |= MODIFIERKEY_RIGHT_CTRL; - #endif - return modifier; -} - -uint8_t TeensyKeyboardAPI::keycode_to_key(KEYCODE_TYPE keycode) -{ - uint8_t key = keycode & 0x3F; - #ifdef KEY_NON_US_100 - if (key == KEY_NON_US_100) key = 100; - #endif - return key; -} - - - -void TeensyKeyboardAPI::set_modifier(uint8_t c) -{ - keyboard_report_data[0] = c; -} -void TeensyKeyboardAPI::set_key1(uint8_t c) -{ - keyboard_report_data[2] = c; -} -void TeensyKeyboardAPI::set_key2(uint8_t c) -{ - keyboard_report_data[3] = c; -} -void TeensyKeyboardAPI::set_key3(uint8_t c) -{ - keyboard_report_data[4] = c; -} -void TeensyKeyboardAPI::set_key4(uint8_t c) -{ - keyboard_report_data[5] = c; -} -void TeensyKeyboardAPI::set_key5(uint8_t c) -{ - keyboard_report_data[6] = c; -} -void TeensyKeyboardAPI::set_key6(uint8_t c) -{ - keyboard_report_data[7] = c; -} -void TeensyKeyboardAPI::set_media(uint8_t c) -{ - keyboard_report_data[1] = c; -} - - -void TeensyKeyboardAPI::send_now(void) -{ - sendReport(keyboard_report_data, sizeof(keyboard_report_data)); -} - - -void TeensyKeyboardAPI::press(uint16_t n) -{ - uint8_t key, mod, msb, modrestore=0; - - msb = n >> 8; - if (msb >= 0xC2 && msb <= 0xDF) { - n = (n & 0x3F) | ((uint16_t)(msb & 0x1F) << 6); - } else - if (msb == 0x80) { - presskey(0, n); - return; - } else - if (msb == 0x40) { - presskey(n, 0); - return; - } - KEYCODE_TYPE keycode = unicode_to_keycode(n); - if (!keycode) return; - #ifdef DEADKEYS_MASK - KEYCODE_TYPE deadkeycode = deadkey_to_keycode(keycode); - if (deadkeycode) { - modrestore = keyboard_report_data[0]; - if (modrestore) { - keyboard_report_data[0] = 0; - send_now(); - } - // TODO: test if operating systems recognize - // deadkey sequences when other keys are held - mod = keycode_to_modifier(deadkeycode); - key = keycode_to_key(deadkeycode); - presskey(key, mod); - releasekey(key, mod); - } - #endif - mod = keycode_to_modifier(keycode); - key = keycode_to_key(keycode); - presskey(key, mod | modrestore); -} - -void TeensyKeyboardAPI::release(uint16_t n) -{ - uint8_t key, mod, msb; - - msb = n >> 8; - if (msb >= 0xC2 && msb <= 0xDF) { - n = (n & 0x3F) | ((uint16_t)(msb & 0x1F) << 6); - } else - if (msb == 0x80) { - releasekey(0, n); - return; - } else - if (msb == 0x40) { - releasekey(n, 0); - return; - } - KEYCODE_TYPE keycode = unicode_to_keycode(n); - if (!keycode) return; - mod = keycode_to_modifier(keycode); - key = keycode_to_key(keycode); - releasekey(key, mod); -} - -void TeensyKeyboardAPI::presskey(uint8_t key, uint8_t modifier) -{ - bool send_required = false; - uint8_t i; - - if (modifier) { - if ((keyboard_report_data[0] & modifier) != modifier) { - keyboard_report_data[0] |= modifier; - send_required = true; - } - } - if (key) { - for (i=2; i < 8; i++) { - if (keyboard_report_data[i] == key) goto end; - } - for (i=2; i < 8; i++) { - if (keyboard_report_data[i] == 0) { - keyboard_report_data[i] = key; - send_required = true; - goto end; - } - } - } - end: - if (send_required) send_now(); -} - -void TeensyKeyboardAPI::releasekey(uint8_t key, uint8_t modifier) -{ - bool send_required = false; - uint8_t i; - - if (modifier) { - if ((keyboard_report_data[0] & modifier) != 0) { - keyboard_report_data[0] &= ~modifier; - send_required = true; - } - } - if (key) { - for (i=2; i < 8; i++) { - if (keyboard_report_data[i] == key) { - keyboard_report_data[i] = 0; - send_required = true; - } - } - } - if (send_required) send_now(); -} - -void TeensyKeyboardAPI::releaseAll(void) -{ - uint8_t i, anybits; - - anybits = keyboard_report_data[0]; - for (i=2; i < 8; i++) { - anybits |= keyboard_report_data[i]; - keyboard_report_data[i] = 0; - } - if (!anybits) return; - keyboard_report_data[0] = 0; - send_now(); -} - -#include -#include - -#ifdef M -#undef M -#endif -#define M(n) ((n) & 0x3FFF) - -const KEYCODE_TYPE PROGMEM keycodes_ascii[] = { - M(ASCII_20), M(ASCII_21), M(ASCII_22), M(ASCII_23), - M(ASCII_24), M(ASCII_25), M(ASCII_26), M(ASCII_27), - M(ASCII_28), M(ASCII_29), M(ASCII_2A), M(ASCII_2B), - M(ASCII_2C), M(ASCII_2D), M(ASCII_2E), M(ASCII_2F), - M(ASCII_30), M(ASCII_31), M(ASCII_32), M(ASCII_33), - M(ASCII_34), M(ASCII_35), M(ASCII_36), M(ASCII_37), - M(ASCII_38), M(ASCII_39), M(ASCII_3A), M(ASCII_3B), - M(ASCII_3C), M(ASCII_3D), M(ASCII_3E), M(ASCII_3F), - M(ASCII_40), M(ASCII_41), M(ASCII_42), M(ASCII_43), - M(ASCII_44), M(ASCII_45), M(ASCII_46), M(ASCII_47), - M(ASCII_48), M(ASCII_49), M(ASCII_4A), M(ASCII_4B), - M(ASCII_4C), M(ASCII_4D), M(ASCII_4E), M(ASCII_4F), - M(ASCII_50), M(ASCII_51), M(ASCII_52), M(ASCII_53), - M(ASCII_54), M(ASCII_55), M(ASCII_56), M(ASCII_57), - M(ASCII_58), M(ASCII_59), M(ASCII_5A), M(ASCII_5B), - M(ASCII_5C), M(ASCII_5D), M(ASCII_5E), M(ASCII_5F), - M(ASCII_60), M(ASCII_61), M(ASCII_62), M(ASCII_63), - M(ASCII_64), M(ASCII_65), M(ASCII_66), M(ASCII_67), - M(ASCII_68), M(ASCII_69), M(ASCII_6A), M(ASCII_6B), - M(ASCII_6C), M(ASCII_6D), M(ASCII_6E), M(ASCII_6F), - M(ASCII_70), M(ASCII_71), M(ASCII_72), M(ASCII_73), - M(ASCII_74), M(ASCII_75), M(ASCII_76), M(ASCII_77), - M(ASCII_78), M(ASCII_79), M(ASCII_7A), M(ASCII_7B), - M(ASCII_7C), M(ASCII_7D), M(ASCII_7E), M(ASCII_7F) -}; - -#ifdef ISO_8859_1_A0 -const KEYCODE_TYPE PROGMEM keycodes_iso_8859_1[] = { - M(ISO_8859_1_A0), M(ISO_8859_1_A1), M(ISO_8859_1_A2), M(ISO_8859_1_A3), - M(ISO_8859_1_A4), M(ISO_8859_1_A5), M(ISO_8859_1_A6), M(ISO_8859_1_A7), - M(ISO_8859_1_A8), M(ISO_8859_1_A9), M(ISO_8859_1_AA), M(ISO_8859_1_AB), - M(ISO_8859_1_AC), M(ISO_8859_1_AD), M(ISO_8859_1_AE), M(ISO_8859_1_AF), - M(ISO_8859_1_B0), M(ISO_8859_1_B1), M(ISO_8859_1_B2), M(ISO_8859_1_B3), - M(ISO_8859_1_B4), M(ISO_8859_1_B5), M(ISO_8859_1_B6), M(ISO_8859_1_B7), - M(ISO_8859_1_B8), M(ISO_8859_1_B9), M(ISO_8859_1_BA), M(ISO_8859_1_BB), - M(ISO_8859_1_BC), M(ISO_8859_1_BD), M(ISO_8859_1_BE), M(ISO_8859_1_BF), - M(ISO_8859_1_C0), M(ISO_8859_1_C1), M(ISO_8859_1_C2), M(ISO_8859_1_C3), - M(ISO_8859_1_C4), M(ISO_8859_1_C5), M(ISO_8859_1_C6), M(ISO_8859_1_C7), - M(ISO_8859_1_C8), M(ISO_8859_1_C9), M(ISO_8859_1_CA), M(ISO_8859_1_CB), - M(ISO_8859_1_CC), M(ISO_8859_1_CD), M(ISO_8859_1_CE), M(ISO_8859_1_CF), - M(ISO_8859_1_D0), M(ISO_8859_1_D1), M(ISO_8859_1_D2), M(ISO_8859_1_D3), - M(ISO_8859_1_D4), M(ISO_8859_1_D5), M(ISO_8859_1_D6), M(ISO_8859_1_D7), - M(ISO_8859_1_D8), M(ISO_8859_1_D9), M(ISO_8859_1_DA), M(ISO_8859_1_DB), - M(ISO_8859_1_DC), M(ISO_8859_1_DD), M(ISO_8859_1_DE), M(ISO_8859_1_DF), - M(ISO_8859_1_E0), M(ISO_8859_1_E1), M(ISO_8859_1_E2), M(ISO_8859_1_E3), - M(ISO_8859_1_E4), M(ISO_8859_1_E5), M(ISO_8859_1_E6), M(ISO_8859_1_E7), - M(ISO_8859_1_E8), M(ISO_8859_1_E9), M(ISO_8859_1_EA), M(ISO_8859_1_EB), - M(ISO_8859_1_EC), M(ISO_8859_1_ED), M(ISO_8859_1_EE), M(ISO_8859_1_EF), - M(ISO_8859_1_F0), M(ISO_8859_1_F1), M(ISO_8859_1_F2), M(ISO_8859_1_F3), - M(ISO_8859_1_F4), M(ISO_8859_1_F5), M(ISO_8859_1_F6), M(ISO_8859_1_F7), - M(ISO_8859_1_F8), M(ISO_8859_1_F9), M(ISO_8859_1_FA), M(ISO_8859_1_FB), - M(ISO_8859_1_FC), M(ISO_8859_1_FD), M(ISO_8859_1_FE), M(ISO_8859_1_FF) -}; -#endif // ISO_8859_1_A0 diff --git a/plugins/KeyboardioHID/src/HID-APIs/TeensyKeylayouts.h b/plugins/KeyboardioHID/src/HID-APIs/TeensyKeylayouts.h deleted file mode 100644 index c6d8c913ef..0000000000 --- a/plugins/KeyboardioHID/src/HID-APIs/TeensyKeylayouts.h +++ /dev/null @@ -1,5418 +0,0 @@ -/* 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. - */ - - -#ifndef KEYLAYOUTS_H__ -#define KEYLAYOUTS_H__ - -#include -#include - -#ifdef __cplusplus -extern "C"{ -#endif - -//#define LAYOUT_US_ENGLISH -//#define LAYOUT_CANADIAN_FRENCH -//#define LAYOUT_CANADIAN_MULTILINGUAL -//#define LAYOUT_DANISH -//#define LAYOUT_FINNISH -//#define LAYOUT_FRENCH -//#define LAYOUT_FRENCH_BELGIAN -//#define LAYOUT_FRENCH_SWISS -//#define LAYOUT_GERMAN -//#define LAYOUT_GERMAN_MAC -//#define LAYOUT_GERMAN_SWISS -//#define LAYOUT_ICELANDIC -//#define LAYOUT_IRISH -//#define LAYOUT_ITALIAN -//#define LAYOUT_NORWEGIAN -//#define LAYOUT_PORTUGUESE -//#define LAYOUT_PORTUGUESE_BRAZILIAN -//#define LAYOUT_SPANISH -//#define LAYOUT_SPANISH_LATIN_AMERICA -//#define LAYOUT_SWEDISH -//#define LAYOUT_TURKISH -//#define LAYOUT_UNITED_KINGDOM -//#define LAYOUT_US_INTERNATIONAL - -// http://en.wikipedia.org/wiki/Keyboard_layout - - -#define MODIFIERKEY_CTRL ( 0x01 | 0x8000 ) -#define MODIFIERKEY_SHIFT ( 0x02 | 0x8000 ) -#define MODIFIERKEY_ALT ( 0x04 | 0x8000 ) -#define MODIFIERKEY_GUI ( 0x08 | 0x8000 ) -#define MODIFIERKEY_LEFT_CTRL ( 0x01 | 0x8000 ) -#define MODIFIERKEY_LEFT_SHIFT ( 0x02 | 0x8000 ) -#define MODIFIERKEY_LEFT_ALT ( 0x04 | 0x8000 ) -#define MODIFIERKEY_LEFT_GUI ( 0x08 | 0x8000 ) -#define MODIFIERKEY_RIGHT_CTRL ( 0x10 | 0x8000 ) -#define MODIFIERKEY_RIGHT_SHIFT ( 0x20 | 0x8000 ) -#define MODIFIERKEY_RIGHT_ALT ( 0x40 | 0x8000 ) -#define MODIFIERKEY_RIGHT_GUI ( 0x80 | 0x8000 ) - -#define KEY_MEDIA_VOLUME_INC 0x01 -#define KEY_MEDIA_VOLUME_DEC 0x02 -#define KEY_MEDIA_MUTE 0x04 -#define KEY_MEDIA_PLAY_PAUSE 0x08 -#define KEY_MEDIA_NEXT_TRACK 0x10 -#define KEY_MEDIA_PREV_TRACK 0x20 -#define KEY_MEDIA_STOP 0x40 -#define KEY_MEDIA_EJECT 0x80 - -#define KEY_A ( 4 | 0x4000 ) -#define KEY_B ( 5 | 0x4000 ) -#define KEY_C ( 6 | 0x4000 ) -#define KEY_D ( 7 | 0x4000 ) -#define KEY_E ( 8 | 0x4000 ) -#define KEY_F ( 9 | 0x4000 ) -#define KEY_G ( 10 | 0x4000 ) -#define KEY_H ( 11 | 0x4000 ) -#define KEY_I ( 12 | 0x4000 ) -#define KEY_J ( 13 | 0x4000 ) -#define KEY_K ( 14 | 0x4000 ) -#define KEY_L ( 15 | 0x4000 ) -#define KEY_M ( 16 | 0x4000 ) -#define KEY_N ( 17 | 0x4000 ) -#define KEY_O ( 18 | 0x4000 ) -#define KEY_P ( 19 | 0x4000 ) -#define KEY_Q ( 20 | 0x4000 ) -#define KEY_R ( 21 | 0x4000 ) -#define KEY_S ( 22 | 0x4000 ) -#define KEY_T ( 23 | 0x4000 ) -#define KEY_U ( 24 | 0x4000 ) -#define KEY_V ( 25 | 0x4000 ) -#define KEY_W ( 26 | 0x4000 ) -#define KEY_X ( 27 | 0x4000 ) -#define KEY_Y ( 28 | 0x4000 ) -#define KEY_Z ( 29 | 0x4000 ) -#define KEY_1 ( 30 | 0x4000 ) -#define KEY_2 ( 31 | 0x4000 ) -#define KEY_3 ( 32 | 0x4000 ) -#define KEY_4 ( 33 | 0x4000 ) -#define KEY_5 ( 34 | 0x4000 ) -#define KEY_6 ( 35 | 0x4000 ) -#define KEY_7 ( 36 | 0x4000 ) -#define KEY_8 ( 37 | 0x4000 ) -#define KEY_9 ( 38 | 0x4000 ) -#define KEY_0 ( 39 | 0x4000 ) -#define KEY_ENTER ( 40 | 0x4000 ) -#define KEY_ESC ( 41 | 0x4000 ) -#define KEY_BACKSPACE ( 42 | 0x4000 ) -#define KEY_TAB ( 43 | 0x4000 ) -#define KEY_SPACE ( 44 | 0x4000 ) -#define KEY_MINUS ( 45 | 0x4000 ) -#define KEY_EQUAL ( 46 | 0x4000 ) -#define KEY_LEFT_BRACE ( 47 | 0x4000 ) -#define KEY_RIGHT_BRACE ( 48 | 0x4000 ) -#define KEY_BACKSLASH ( 49 | 0x4000 ) -#define KEY_NON_US_NUM ( 50 | 0x4000 ) -#define KEY_SEMICOLON ( 51 | 0x4000 ) -#define KEY_QUOTE ( 52 | 0x4000 ) -#define KEY_TILDE ( 53 | 0x4000 ) -#define KEY_COMMA ( 54 | 0x4000 ) -#define KEY_PERIOD ( 55 | 0x4000 ) -#define KEY_SLASH ( 56 | 0x4000 ) -#define KEY_CAPS_LOCK ( 57 | 0x4000 ) -#define KEY_F1 ( 58 | 0x4000 ) -#define KEY_F2 ( 59 | 0x4000 ) -#define KEY_F3 ( 60 | 0x4000 ) -#define KEY_F4 ( 61 | 0x4000 ) -#define KEY_F5 ( 62 | 0x4000 ) -#define KEY_F6 ( 63 | 0x4000 ) -#define KEY_F7 ( 64 | 0x4000 ) -#define KEY_F8 ( 65 | 0x4000 ) -#define KEY_F9 ( 66 | 0x4000 ) -#define KEY_F10 ( 67 | 0x4000 ) -#define KEY_F11 ( 68 | 0x4000 ) -#define KEY_F12 ( 69 | 0x4000 ) -#define KEY_PRINTSCREEN ( 70 | 0x4000 ) -#define KEY_SCROLL_LOCK ( 71 | 0x4000 ) -#define KEY_PAUSE ( 72 | 0x4000 ) -#define KEY_INSERT ( 73 | 0x4000 ) -#define KEY_HOME ( 74 | 0x4000 ) -#define KEY_PAGE_UP ( 75 | 0x4000 ) -#define KEY_DELETE ( 76 | 0x4000 ) -#define KEY_END ( 77 | 0x4000 ) -#define KEY_PAGE_DOWN ( 78 | 0x4000 ) -#define KEY_RIGHT ( 79 | 0x4000 ) -#define KEY_LEFT ( 80 | 0x4000 ) -#define KEY_DOWN ( 81 | 0x4000 ) -#define KEY_UP ( 82 | 0x4000 ) -#define KEY_NUM_LOCK ( 83 | 0x4000 ) -#define KEYPAD_SLASH ( 84 | 0x4000 ) -#define KEYPAD_ASTERIX ( 85 | 0x4000 ) -#define KEYPAD_MINUS ( 86 | 0x4000 ) -#define KEYPAD_PLUS ( 87 | 0x4000 ) -#define KEYPAD_ENTER ( 88 | 0x4000 ) -#define KEYPAD_1 ( 89 | 0x4000 ) -#define KEYPAD_2 ( 90 | 0x4000 ) -#define KEYPAD_3 ( 91 | 0x4000 ) -#define KEYPAD_4 ( 92 | 0x4000 ) -#define KEYPAD_5 ( 93 | 0x4000 ) -#define KEYPAD_6 ( 94 | 0x4000 ) -#define KEYPAD_7 ( 95 | 0x4000 ) -#define KEYPAD_8 ( 96 | 0x4000 ) -#define KEYPAD_9 ( 97 | 0x4000 ) -#define KEYPAD_0 ( 98 | 0x4000 ) -#define KEYPAD_PERIOD ( 99 | 0x4000 ) -#define KEY_MENU ( 101 | 0x4000 ) -#define KEY_F13 ( 104 | 0x4000 ) -#define KEY_F14 ( 105 | 0x4000 ) -#define KEY_F15 ( 106 | 0x4000 ) -#define KEY_F16 ( 107 | 0x4000 ) -#define KEY_F17 ( 108 | 0x4000 ) -#define KEY_F18 ( 109 | 0x4000 ) -#define KEY_F19 ( 110 | 0x4000 ) -#define KEY_F20 ( 111 | 0x4000 ) -#define KEY_F21 ( 112 | 0x4000 ) -#define KEY_F22 ( 113 | 0x4000 ) -#define KEY_F23 ( 114 | 0x4000 ) -#define KEY_F24 ( 115 | 0x4000 ) - - -// for compatibility with Leonardo's slightly different names -#define KEY_UP_ARROW KEY_UP -#define KEY_DOWN_ARROW KEY_DOWN -#define KEY_LEFT_ARROW KEY_LEFT -#define KEY_RIGHT_ARROW KEY_RIGHT -#define KEY_RETURN KEY_ENTER -#define KEY_LEFT_CTRL MODIFIERKEY_LEFT_CTRL -#define KEY_LEFT_SHIFT MODIFIERKEY_LEFT_SHIFT -#define KEY_LEFT_ALT MODIFIERKEY_LEFT_ALT -#define KEY_LEFT_GUI MODIFIERKEY_LEFT_GUI -#define KEY_RIGHT_CTRL MODIFIERKEY_RIGHT_CTRL -#define KEY_RIGHT_SHIFT MODIFIERKEY_RIGHT_SHIFT -#define KEY_RIGHT_ALT MODIFIERKEY_RIGHT_ALT -#define KEY_RIGHT_GUI MODIFIERKEY_RIGHT_GUI - - -// Everything below this line is not intended for use in "normal" programs. -// These private symbols populate lookup tables, which are used to translate -// ascii and UTF8 unicode into keystroke sequences. - - -#ifdef LAYOUT_US_ENGLISH - -#define SHIFT_MASK 0x40 -#define KEYCODE_TYPE uint8_t - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! -#define ASCII_22 KEY_QUOTE + SHIFT_MASK // 34 " -#define ASCII_23 KEY_3 + SHIFT_MASK // 35 # -#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ -#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % -#define ASCII_26 KEY_7 + SHIFT_MASK // 38 & -#define ASCII_27 KEY_QUOTE // 39 ' -#define ASCII_28 KEY_9 + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_0 + SHIFT_MASK // 41 ) -#define ASCII_2A KEY_8 + SHIFT_MASK // 42 * -#define ASCII_2B KEY_EQUAL + SHIFT_MASK // 43 + -#define ASCII_2C KEY_COMMA // 44 , -#define ASCII_2D KEY_MINUS // 45 - -#define ASCII_2E KEY_PERIOD // 46 . -#define ASCII_2F KEY_SLASH // 47 / -#define ASCII_30 KEY_0 // 48 0 -#define ASCII_31 KEY_1 // 49 1 -#define ASCII_32 KEY_2 // 50 2 -#define ASCII_33 KEY_3 // 51 3 -#define ASCII_34 KEY_4 // 52 4 -#define ASCII_35 KEY_5 // 53 5 -#define ASCII_36 KEY_6 // 54 6 -#define ASCII_37 KEY_7 // 55 7 -#define ASCII_38 KEY_8 // 55 8 -#define ASCII_39 KEY_9 // 57 9 -#define ASCII_3A KEY_SEMICOLON + SHIFT_MASK // 58 : -#define ASCII_3B KEY_SEMICOLON // 59 ; -#define ASCII_3C KEY_COMMA + SHIFT_MASK // 60 < -#define ASCII_3D KEY_EQUAL // 61 = -#define ASCII_3E KEY_PERIOD + SHIFT_MASK // 62 > -#define ASCII_3F KEY_SLASH + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_2 + SHIFT_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_LEFT_BRACE // 91 [ -#define ASCII_5C KEY_BACKSLASH // 92 -#define ASCII_5D KEY_RIGHT_BRACE // 93 ] -#define ASCII_5E KEY_6 + SHIFT_MASK // 94 ^ -#define ASCII_5F KEY_MINUS + SHIFT_MASK // 95 _ -#define ASCII_60 KEY_TILDE // 96 ` -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Y // 121 y -#define ASCII_7A KEY_Z // 122 z -#define ASCII_7B KEY_LEFT_BRACE + SHIFT_MASK // 123 { -#define ASCII_7C KEY_BACKSLASH + SHIFT_MASK // 124 | -#define ASCII_7D KEY_RIGHT_BRACE + SHIFT_MASK // 125 } -#define ASCII_7E KEY_TILDE + SHIFT_MASK // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 - -#endif // LAYOUT_US_ENGLISH - - - - -#ifdef LAYOUT_US_INTERNATIONAL - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define DEADKEYS_MASK 0x0700 -#define CIRCUMFLEX_BITS 0x0100 -#define ACUTE_ACCENT_BITS 0x0200 -#define GRAVE_ACCENT_BITS 0x0300 -#define TILDE_BITS 0x0400 -#define DIAERESIS_BITS 0x0500 -#define KEYCODE_TYPE uint16_t -#define DEADKEY_CIRCUMFLEX KEY_6 + SHIFT_MASK -#define DEADKEY_ACUTE_ACCENT KEY_QUOTE -#define DEADKEY_GRAVE_ACCENT KEY_TILDE -#define DEADKEY_TILDE KEY_TILDE + SHIFT_MASK -#define DEADKEY_DIAERESIS KEY_QUOTE + SHIFT_MASK - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! -#define ASCII_22 DIAERESIS_BITS + KEY_SPACE // 34 " -#define ASCII_23 KEY_3 + SHIFT_MASK // 35 # -#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ -#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % -#define ASCII_26 KEY_7 + SHIFT_MASK // 38 & -#define ASCII_27 ACUTE_ACCENT_BITS + KEY_SPACE // 39 ' -#define ASCII_28 KEY_9 + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_0 + SHIFT_MASK // 41 ) -#define ASCII_2A KEY_8 + SHIFT_MASK // 42 * -#define ASCII_2B KEY_EQUAL + SHIFT_MASK // 43 + -#define ASCII_2C KEY_COMMA // 44 , -#define ASCII_2D KEY_MINUS // 45 - -#define ASCII_2E KEY_PERIOD // 46 . -#define ASCII_2F KEY_SLASH // 47 / -#define ASCII_30 KEY_0 // 48 0 -#define ASCII_31 KEY_1 // 49 1 -#define ASCII_32 KEY_2 // 50 2 -#define ASCII_33 KEY_3 // 51 3 -#define ASCII_34 KEY_4 // 52 4 -#define ASCII_35 KEY_5 // 53 5 -#define ASCII_36 KEY_6 // 54 6 -#define ASCII_37 KEY_7 // 55 7 -#define ASCII_38 KEY_8 // 55 8 -#define ASCII_39 KEY_9 // 57 9 -#define ASCII_3A KEY_SEMICOLON + SHIFT_MASK // 58 : -#define ASCII_3B KEY_SEMICOLON // 59 ; -#define ASCII_3C KEY_COMMA + SHIFT_MASK // 60 < -#define ASCII_3D KEY_EQUAL // 61 = -#define ASCII_3E KEY_PERIOD + SHIFT_MASK // 62 > -#define ASCII_3F KEY_SLASH + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_2 + SHIFT_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_LEFT_BRACE // 91 [ -#define ASCII_5C KEY_BACKSLASH // 92 -#define ASCII_5D KEY_RIGHT_BRACE // 93 ] -#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ -#define ASCII_5F KEY_MINUS + SHIFT_MASK // 95 _ -#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Y // 121 y -#define ASCII_7A KEY_Z // 122 z -#define ASCII_7B KEY_LEFT_BRACE + SHIFT_MASK // 123 { -#define ASCII_7C KEY_BACKSLASH + SHIFT_MASK // 124 | -#define ASCII_7D KEY_RIGHT_BRACE + SHIFT_MASK // 125 } -#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 -#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space -#define ISO_8859_1_A1 KEY_1 + ALTGR_MASK // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 KEY_C + ALTGR_MASK + SHIFT_MASK // 162 ¢ Cent SIGN -#define ISO_8859_1_A3 KEY_4 + ALTGR_MASK + SHIFT_MASK // 163 £ Pound Sign -#define ISO_8859_1_A4 KEY_4 + ALTGR_MASK // 164 ¤ Currency or Euro Sign -#define ISO_8859_1_A5 KEY_MINUS + ALTGR_MASK // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 KEY_BACKSLASH + ALTGR_MASK + SHIFT_MASK // 166 ¦ BROKEN BAR ?? -#define ISO_8859_1_A7 KEY_S + ALTGR_MASK + SHIFT_MASK // 167 § SECTION SIGN -#define ISO_8859_1_A8 KEY_QUOTE + ALTGR_MASK + SHIFT_MASK // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 KEY_C + ALTGR_MASK // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB KEY_LEFT_BRACE + ALTGR_MASK // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC KEY_BACKSLASH + ALTGR_MASK // 172 ¬ NOT SIGN ?? -#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN -#define ISO_8859_1_AE KEY_R + ALTGR_MASK // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF 0 // 175 ¯ MACRON -#define ISO_8859_1_B0 KEY_SEMICOLON + ALTGR_MASK + SHIFT_MASK // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 KEY_2 + ALTGR_MASK // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 KEY_3 + ALTGR_MASK // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 KEY_QUOTE + ALTGR_MASK // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 KEY_M + ALTGR_MASK // 181 µ MICRO SIGN -#define ISO_8859_1_B6 KEY_SEMICOLON + ALTGR_MASK // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT -#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA -#define ISO_8859_1_B9 KEY_1 + ALTGR_MASK + SHIFT_MASK // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB KEY_RIGHT_BRACE + ALTGR_MASK // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC KEY_6 + ALTGR_MASK // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD KEY_7 + ALTGR_MASK // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE KEY_8 + ALTGR_MASK // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF KEY_SLASH + ALTGR_MASK // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE -#define ISO_8859_1_C1 KEY_A + ALTGR_MASK + SHIFT_MASK // 193 Á A ACUTE -#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE -#define ISO_8859_1_C4 KEY_Q + ALTGR_MASK + SHIFT_MASK // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 KEY_W + ALTGR_MASK + SHIFT_MASK // 197 Å A RING ABOVE -#define ISO_8859_1_C6 KEY_Z + ALTGR_MASK + SHIFT_MASK // 198 Æ AE -#define ISO_8859_1_C7 KEY_COMMA + ALTGR_MASK + SHIFT_MASK // 199 Ç C CEDILLA -#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE -#define ISO_8859_1_C9 KEY_E + ALTGR_MASK + SHIFT_MASK // 201 É E ACUTE -#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS -#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE -#define ISO_8859_1_CD KEY_I + ALTGR_MASK + SHIFT_MASK // 205 Í I ACUTE -#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 KEY_D + ALTGR_MASK + SHIFT_MASK // 208 Ð ETH -#define ISO_8859_1_D1 KEY_N + ALTGR_MASK + SHIFT_MASK // 209 Ñ N TILDE -#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE -#define ISO_8859_1_D3 KEY_O + ALTGR_MASK + SHIFT_MASK // 211 Ó O ACUTE -#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE -#define ISO_8859_1_D6 KEY_P + ALTGR_MASK + SHIFT_MASK // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 KEY_EQUAL + ALTGR_MASK // 215 × MULTIPLICATION -#define ISO_8859_1_D8 KEY_L + ALTGR_MASK + SHIFT_MASK // 216 Ø O STROKE -#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE -#define ISO_8859_1_DA KEY_U + ALTGR_MASK + SHIFT_MASK // 218 Ú U ACUTE -#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC KEY_Y + ALTGR_MASK + SHIFT_MASK // 220 Ü U DIAERESIS -#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE -#define ISO_8859_1_DE KEY_T + ALTGR_MASK + SHIFT_MASK // 222 Þ THORN -#define ISO_8859_1_DF KEY_S + ALTGR_MASK // 223 ß SHARP S -#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE -#define ISO_8859_1_E1 KEY_A + ALTGR_MASK // 225 á a ACUTE -#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE -#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS -#define ISO_8859_1_E5 KEY_W + ALTGR_MASK // 229 å a RING ABOVE -#define ISO_8859_1_E6 KEY_Z + ALTGR_MASK // 230 æ ae -#define ISO_8859_1_E7 KEY_COMMA + ALTGR_MASK // 231 ç c CEDILLA -#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE -#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE -#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS -#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE -#define ISO_8859_1_ED KEY_I + ALTGR_MASK // 237 í i ACUTE -#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS -#define ISO_8859_1_F0 KEY_D + ALTGR_MASK // 240 ð ETH -#define ISO_8859_1_F1 KEY_N + ALTGR_MASK // 241 ñ n TILDE -#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE -#define ISO_8859_1_F3 KEY_O + ALTGR_MASK // 243 ó o ACUTE -#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE -#define ISO_8859_1_F6 KEY_P + ALTGR_MASK // 246 ö o DIAERESIS -#define ISO_8859_1_F7 KEY_EQUAL + ALTGR_MASK + SHIFT_MASK // 247 ÷ DIVISION -#define ISO_8859_1_F8 KEY_L + ALTGR_MASK // 248 ø o STROKE -#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE -#define ISO_8859_1_FA KEY_U + ALTGR_MASK // 250 ú u ACUTE -#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC KEY_Y + ALTGR_MASK // 252 ü u DIAERESIS -#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE -#define ISO_8859_1_FE KEY_T + ALTGR_MASK // 254 þ THORN -#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS -#define UNICODE_20AC KEY_5 + ALTGR_MASK // € Euro Sign -// not yet implemented -#define UNICODE_EXTRA00 0x20AC -#define KEYCODE_EXTRA00 KEY_5 + ALTGR_MASK // 20AC € Euro Sign - -#endif // LAYOUT_US_INTERNATIONAL - - - -#ifdef LAYOUT_GERMAN - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define DEADKEYS_MASK 0x0700 -#define CIRCUMFLEX_BITS 0x0300 -#define ACUTE_ACCENT_BITS 0x0400 -#define GRAVE_ACCENT_BITS 0x0500 -#define KEYCODE_TYPE uint16_t -#define DEADKEY_CIRCUMFLEX KEY_TILDE -//#define DEADKEY_CIRCUMFLEX KEY_NON_US_100 -#define DEADKEY_ACUTE_ACCENT KEY_EQUAL -#define DEADKEY_GRAVE_ACCENT KEY_EQUAL + SHIFT_MASK -#define KEY_NON_US_100 63 - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! -#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " -#define ASCII_23 KEY_BACKSLASH // 35 # ?? -#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ -#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % -#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & -#define ASCII_27 KEY_BACKSLASH + SHIFT_MASK // 39 ' -#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) -#define ASCII_2A KEY_RIGHT_BRACE + SHIFT_MASK // 42 * -#define ASCII_2B KEY_RIGHT_BRACE // 43 + -#define ASCII_2C KEY_COMMA // 44 , -#define ASCII_2D KEY_SLASH // 45 - -#define ASCII_2E KEY_PERIOD // 46 . -#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / -#define ASCII_30 KEY_0 // 48 0 -#define ASCII_31 KEY_1 // 49 1 -#define ASCII_32 KEY_2 // 50 2 -#define ASCII_33 KEY_3 // 51 3 -#define ASCII_34 KEY_4 // 52 4 -#define ASCII_35 KEY_5 // 53 5 -#define ASCII_36 KEY_6 // 54 6 -#define ASCII_37 KEY_7 // 55 7 -#define ASCII_38 KEY_8 // 55 8 -#define ASCII_39 KEY_9 // 57 9 -#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : -#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; -#define ASCII_3C KEY_NON_US_100 // 60 < -#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = -#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > -#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_Q + ALTGR_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Z + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Y + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_8 + ALTGR_MASK // 91 [ -#define ASCII_5C KEY_MINUS + ALTGR_MASK // 92 -#define ASCII_5D KEY_9 + ALTGR_MASK // 93 ] -#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ -#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ -#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Z // 121 y -#define ASCII_7A KEY_Y // 122 z -#define ASCII_7B KEY_7 + ALTGR_MASK // 123 { -#define ASCII_7C KEY_NON_US_100 + ALTGR_MASK // 124 | -#define ASCII_7D KEY_0 + ALTGR_MASK // 125 } -#define ASCII_7E KEY_RIGHT_BRACE + ALTGR_MASK // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 -#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space -#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 0 // 162 ¢ Cent Sign -#define ISO_8859_1_A3 0 // 163 £ Pound Sign -#define ISO_8859_1_A4 KEY_E + ALTGR_MASK // 164 ¤ Currency Sign -#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR -#define ISO_8859_1_A7 KEY_3 + SHIFT_MASK // 167 § SECTION SIGN -#define ISO_8859_1_A8 0 // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN -#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN -#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF 0 // 175 ¯ MACRON -#define ISO_8859_1_B0 KEY_TILDE + SHIFT_MASK // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 KEY_2 + ALTGR_MASK // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 KEY_3 + ALTGR_MASK // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 0 // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 KEY_M + ALTGR_MASK // 181 µ MICRO SIGN -#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT -#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA -#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE -#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE -#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 0 // 195 Ã A TILDE -#define ISO_8859_1_C4 KEY_QUOTE + SHIFT_MASK // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE -#define ISO_8859_1_C6 0 // 198 Æ AE -#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA -#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE -#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE -#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB 0 // 203 Ë E DIAERESIS -#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE -#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE -#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF 0 // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 0 // 208 Ð ETH -#define ISO_8859_1_D1 0 // 209 Ñ N TILDE -#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE -#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE -#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 0 // 213 Õ O TILDE -#define ISO_8859_1_D6 KEY_SEMICOLON + SHIFT_MASK // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION -#define ISO_8859_1_D8 0 // 216 Ø O STROKE -#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE -#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE -#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC KEY_LEFT_BRACE + SHIFT_MASK // 220 Ü U DIAERESIS -#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Z + SHIFT_MASK // 221 Ý Y ACUTE -#define ISO_8859_1_DE 0 // 222 Þ THORN -#define ISO_8859_1_DF KEY_MINUS // 223 ß SHARP S -#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE -#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE -#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 0 // 227 ã a TILDE -#define ISO_8859_1_E4 KEY_QUOTE // 228 ä a DIAERESIS -#define ISO_8859_1_E5 0 // 229 å a RING ABOVE -#define ISO_8859_1_E6 0 // 230 æ ae -#define ISO_8859_1_E7 0 // 231 ç c CEDILLA -#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE -#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE -#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB 0 // 235 ë e DIAERESIS -#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE -#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE -#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF 0 // 239 ï i DIAERESIS -#define ISO_8859_1_F0 0 // 240 ð ETH -#define ISO_8859_1_F1 0 // 241 ñ n TILDE -#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE -#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE -#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 0 // 245 õ o TILDE -#define ISO_8859_1_F6 KEY_SEMICOLON // 246 ö o DIAERESIS -#define ISO_8859_1_F7 0 // 247 ÷ DIVISION -#define ISO_8859_1_F8 0 // 248 ø o STROKE -#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE -#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE -#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC KEY_LEFT_BRACE // 252 ü u DIAERESIS -#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Z // 253 ý y ACUTE -#define ISO_8859_1_FE 0 // 254 þ THORN -#define ISO_8859_1_FF 0 // 255 ÿ y DIAERESIS -#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign -// not yet implemented -#define UNICODE_EXTRA00 0x20AC -#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign - -#endif // LAYOUT_GERMAN - - - -#ifdef LAYOUT_GERMAN_MAC - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define DEADKEYS_MASK 0x0700 -#define ACUTE_ACCENT_BITS 0x0100 -#define GRAVE_ACCENT_BITS 0x0200 -#define CIRCUMFLEX_BITS 0x0300 -#define DIAERESIS_BITS 0x0400 -#define TILDE_BITS 0x0500 -#define KEYCODE_TYPE uint16_t -#define DEADKEY_ACUTE_ACCENT KEY_EQUAL -#define DEADKEY_GRAVE_ACCENT KEY_EQUAL + SHIFT_MASK -#define DEADKEY_CIRCUMFLEX KEY_6 + SHIFT_MASK + ALTGR_MASK -#define DEADKEY_DIAERESIS KEY_U + ALTGR_MASK -#define DEADKEY_TILDE KEY_N + ALTGR_MASK -#define KEY_NON_US_100 63 - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! -#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " -#define ASCII_23 KEY_BACKSLASH // 35 # ?? -#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ -#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % -#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & -#define ASCII_27 KEY_BACKSLASH + SHIFT_MASK // 39 ' -#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) -#define ASCII_2A KEY_RIGHT_BRACE + SHIFT_MASK // 42 * -#define ASCII_2B KEY_RIGHT_BRACE // 43 + -#define ASCII_2C KEY_COMMA // 44 , -#define ASCII_2D KEY_SLASH // 45 - -#define ASCII_2E KEY_PERIOD // 46 . -#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / -#define ASCII_30 KEY_0 // 48 0 -#define ASCII_31 KEY_1 // 49 1 -#define ASCII_32 KEY_2 // 50 2 -#define ASCII_33 KEY_3 // 51 3 -#define ASCII_34 KEY_4 // 52 4 -#define ASCII_35 KEY_5 // 53 5 -#define ASCII_36 KEY_6 // 54 6 -#define ASCII_37 KEY_7 // 55 7 -#define ASCII_38 KEY_8 // 55 8 -#define ASCII_39 KEY_9 // 57 9 -#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : -#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; -#define ASCII_3C KEY_TILDE // 60 < -#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = -#define ASCII_3E KEY_TILDE + SHIFT_MASK // 62 > -#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_Q + ALTGR_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Z + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Y + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_5 + ALTGR_MASK // 91 [ -#define ASCII_5C KEY_7 + ALTGR_MASK + SHIFT_MASK // 92 -#define ASCII_5D KEY_6 + ALTGR_MASK // 93 ] -#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ -#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ -#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Z // 121 y -#define ASCII_7A KEY_Y // 122 z -#define ASCII_7B KEY_8 + ALTGR_MASK // 123 { -#define ASCII_7C KEY_7 + ALTGR_MASK // 124 | -#define ASCII_7D KEY_9 + ALTGR_MASK // 125 } -#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 -#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space -#define ISO_8859_1_A1 KEY_1 + ALTGR_MASK // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 KEY_4 + ALTGR_MASK // 162 ¢ Cent Sign -#define ISO_8859_1_A3 KEY_4 + SHIFT_MASK + ALTGR_MASK // 163 £ Pound Sign -#define ISO_8859_1_A4 KEY_E + ALTGR_MASK // 164 ¤ Currency Sign -#define ISO_8859_1_A5 KEY_Z + ALTGR_MASK // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR -#define ISO_8859_1_A7 KEY_3 + SHIFT_MASK // 167 § SECTION SIGN -#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 KEY_G + ALTGR_MASK // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA KEY_H + ALTGR_MASK // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB KEY_Q + ALTGR_MASK // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN -#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN -#define ISO_8859_1_AE KEY_R + ALTGR_MASK // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF KEY_0 + SHIFT_MASK + ALTGR_MASK // 175 ¯ MACRON -#define ISO_8859_1_B0 KEY_LEFT_BRACE + ALTGR_MASK + SHIFT_MASK// 176 ° DEGREE SIGN -#define ISO_8859_1_B1 KEY_RIGHT_BRACE + ALTGR_MASK // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 KEY_M + ALTGR_MASK // 181 µ MICRO SIGN -#define ISO_8859_1_B6 KEY_3 + ALTGR_MASK // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 KEY_9 + SHIFT_MASK + ALTGR_MASK // 183 · MIDDLE DOT -#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA -#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA KEY_J + ALTGR_MASK // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB KEY_Q + SHIFT_MASK + ALTGR_MASK // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF KEY_MINUS + ALTGR_MASK // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE -#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE -#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE -#define ISO_8859_1_C4 KEY_QUOTE + SHIFT_MASK // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 KEY_A + ALTGR_MASK + SHIFT_MASK // 197 Å A RING ABOVE -#define ISO_8859_1_C6 KEY_QUOTE + ALTGR_MASK + SHIFT_MASK // 198 Æ AE -#define ISO_8859_1_C7 KEY_C + ALTGR_MASK + SHIFT_MASK // 199 Ç C CEDILLA -#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE -#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE -#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS -#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE -#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE -#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 0 // 208 Ð ETH -#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE -#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE -#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE -#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE -#define ISO_8859_1_D6 KEY_SEMICOLON + SHIFT_MASK // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION -#define ISO_8859_1_D8 KEY_O + ALTGR_MASK + SHIFT_MASK // 216 Ø O STROKE -#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE -#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE -#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC KEY_LEFT_BRACE + SHIFT_MASK // 220 Ü U DIAERESIS -#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Z + SHIFT_MASK // 221 Ý Y ACUTE -#define ISO_8859_1_DE 0 // 222 Þ THORN -#define ISO_8859_1_DF KEY_MINUS // 223 ß SHARP S -#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE -#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE -#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE -#define ISO_8859_1_E4 KEY_QUOTE // 228 ä a DIAERESIS -#define ISO_8859_1_E5 KEY_A + ALTGR_MASK // 229 å a RING ABOVE -#define ISO_8859_1_E6 KEY_QUOTE + ALTGR_MASK // 230 æ ae -#define ISO_8859_1_E7 KEY_C + ALTGR_MASK // 231 ç c CEDILLA -#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE -#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE -#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS -#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE -#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE -#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS -#define ISO_8859_1_F0 0 // 240 ð ETH -#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE -#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE -#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE -#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE -#define ISO_8859_1_F6 KEY_SEMICOLON // 246 ö o DIAERESIS -#define ISO_8859_1_F7 0 // 247 ÷ DIVISION -#define ISO_8859_1_F8 KEY_O + ALTGR_MASK // 248 ø o STROKE -#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE -#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE -#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC KEY_LEFT_BRACE // 252 ü u DIAERESIS -#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Z // 253 ý y ACUTE -#define ISO_8859_1_FE 0 // 254 þ THORN -#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Z // 255 ÿ y DIAERESIS -#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign -// not yet implemented -#define UNICODE_EXTRA00 0x20AC -#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign - -#endif // LAYOUT_GERMAN_MAC - - - - - - -#ifdef LAYOUT_CANADIAN_FRENCH - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define DEADKEYS_MASK 0x0700 -#define CIRCUMFLEX_BITS 0x0100 -#define ACUTE_ACCENT_BITS 0x0200 -#define GRAVE_ACCENT_BITS 0x0300 -#define DIAERESIS_BITS 0x0400 -#define CEDILLA_BITS 0x0500 - -#define KEYCODE_TYPE uint16_t -#define DEADKEY_CIRCUMFLEX KEY_LEFT_BRACE -#define DEADKEY_ACUTE_ACCENT KEY_SLASH + ALTGR_MASK -#define DEADKEY_GRAVE_ACCENT KEY_QUOTE -#define DEADKEY_DIAERESIS KEY_RIGHT_BRACE + SHIFT_MASK -#define DEADKEY_CEDILLA KEY_RIGHT_BRACE -#define KEY_NON_US_100 63 - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! -#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " -#define ASCII_23 KEY_TILDE + SHIFT_MASK // 35 # -#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ -#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % -#define ASCII_26 KEY_7 + SHIFT_MASK // 38 & -#define ASCII_27 KEY_COMMA + SHIFT_MASK // 39 ' -//#define ASCII_27 ACUTE_ACCENT_BITS + KEY_SPACE // 39 ' -#define ASCII_28 KEY_9 + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_0 + SHIFT_MASK // 41 ) -#define ASCII_2A KEY_8 + SHIFT_MASK // 42 * -#define ASCII_2B KEY_EQUAL + SHIFT_MASK // 43 + -#define ASCII_2C KEY_COMMA // 44 , -#define ASCII_2D KEY_MINUS // 45 - -#define ASCII_2E KEY_PERIOD // 46 . -#define ASCII_2F KEY_3 + SHIFT_MASK // 47 / -#define ASCII_30 KEY_0 // 48 0 -#define ASCII_31 KEY_1 // 49 1 -#define ASCII_32 KEY_2 // 50 2 -#define ASCII_33 KEY_3 // 51 3 -#define ASCII_34 KEY_4 // 52 4 -#define ASCII_35 KEY_5 // 53 5 -#define ASCII_36 KEY_6 // 54 6 -#define ASCII_37 KEY_7 // 55 7 -#define ASCII_38 KEY_8 // 55 8 -#define ASCII_39 KEY_9 // 57 9 -#define ASCII_3A KEY_SEMICOLON + SHIFT_MASK // 58 : -#define ASCII_3B KEY_SEMICOLON // 59 ; -#define ASCII_3C KEY_BACKSLASH // 60 < -#define ASCII_3D KEY_EQUAL // 61 = -#define ASCII_3E KEY_BACKSLASH + SHIFT_MASK // 62 > -#define ASCII_3F KEY_6 + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_2 + ALTGR_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_LEFT_BRACE + ALTGR_MASK // 91 [ -#define ASCII_5C KEY_TILDE + ALTGR_MASK // 92 -#define ASCII_5D KEY_RIGHT_BRACE + ALTGR_MASK // 93 ] -#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ -#define ASCII_5F KEY_MINUS + SHIFT_MASK // 95 _ -#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Y // 121 y -#define ASCII_7A KEY_Z // 122 z -#define ASCII_7B KEY_QUOTE + ALTGR_MASK // 123 { -#define ASCII_7C KEY_TILDE + SHIFT_MASK // 124 | -#define ASCII_7D KEY_BACKSLASH + ALTGR_MASK // 125 } -#define ASCII_7E KEY_SEMICOLON + ALTGR_MASK // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 -#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space -#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 KEY_4 + ALTGR_MASK // 162 ¢ Cent SIGN -#define ISO_8859_1_A3 KEY_3 + ALTGR_MASK // 163 £ Pound Sign -#define ISO_8859_1_A4 KEY_5 + ALTGR_MASK // 164 ¤ Currency or Euro Sign -#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 KEY_7 + ALTGR_MASK // 166 ¦ BROKEN BAR -#define ISO_8859_1_A7 KEY_O + ALTGR_MASK // 167 § SECTION SIGN -#define ISO_8859_1_A8 0 // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB KEY_NON_US_100 // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC KEY_6 + ALTGR_MASK // 172 ¬ NOT SIGN -#define ISO_8859_1_AD KEY_PERIOD + ALTGR_MASK // 173 SOFT HYPHEN -#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF KEY_COMMA + ALTGR_MASK // 175 ¯ MACRON -#define ISO_8859_1_B0 KEY_NON_US_100 + ALTGR_MASK // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 KEY_1 + ALTGR_MASK // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 KEY_8 + ALTGR_MASK // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 KEY_9 + ALTGR_MASK // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 0 // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 KEY_M + ALTGR_MASK // 181 µ MICRO SIGN -#define ISO_8859_1_B6 KEY_P + ALTGR_MASK // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT -#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA -#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB KEY_NON_US_100 + SHIFT_MASK // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC KEY_0 + ALTGR_MASK // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD KEY_MINUS + ALTGR_MASK // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE KEY_EQUAL + ALTGR_MASK // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE -#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE -#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 0 // 195 Ã A TILDE -#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE -#define ISO_8859_1_C6 0 // 198 Æ AE -#define ISO_8859_1_C7 CEDILLA_BITS + KEY_C + SHIFT_MASK // 199 Ç C CEDILLA -#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE -#define ISO_8859_1_C9 KEY_SLASH + SHIFT_MASK // 201 É E ACUTE -#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS -#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE -#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE -#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 0 // 208 Ð ETH -#define ISO_8859_1_D1 0 // 209 Ñ N TILDE -#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE -#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE -#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 0 // 213 Õ O TILDE -#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION -#define ISO_8859_1_D8 0 // 216 Ø O STROKE -#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE -#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE -#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U // 220 Ü U DIAERESIS -#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE -#define ISO_8859_1_DE 0 // 222 Þ THORN -#define ISO_8859_1_DF 0 // 223 ß SHARP S -#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE -#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE -#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 0 // 227 ã a TILDE -#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS -#define ISO_8859_1_E5 0 // 229 å a RING ABOVE -#define ISO_8859_1_E6 0 // 230 æ ae -#define ISO_8859_1_E7 CEDILLA_BITS + KEY_C // 231 ç c CEDILLA -#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE -#define ISO_8859_1_E9 KEY_SLASH // 233 é e ACUTE -#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS -#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE -#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE -#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS -#define ISO_8859_1_F0 0 // 240 ð ETH -#define ISO_8859_1_F1 0 // 241 ñ n TILDE -#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE -#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE -#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 0 // 245 õ o TILDE -#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS -#define ISO_8859_1_F7 0 // 247 ÷ DIVISION -#define ISO_8859_1_F8 0 // 248 ø o STROKE -#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE -#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE -#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS -#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE -#define ISO_8859_1_FE 0 // 254 þ THORN -#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS - -#endif // LAYOUT_CANADIAN_FRENCH - - - -#ifdef LAYOUT_CANADIAN_MULTILINGUAL - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define RCTRL_MASK 0x0800 -#define DEADKEYS_MASK 0x0700 -#define CIRCUMFLEX_BITS 0x0100 -#define DIAERESIS_BITS 0x0200 -#define ACUTE_ACCENT_BITS 0x0300 -#define CEDILLA_BITS 0x0400 -#define GRAVE_ACCENT_BITS 0x0500 -#define TILDE_BITS 0x0600 -#define RING_ABOVE_BITS 0x0700 -#define KEYCODE_TYPE uint16_t -#define DEADKEY_CIRCUMFLEX KEY_LEFT_BRACE -#define DEADKEY_DIAERESIS KEY_LEFT_BRACE + SHIFT_MASK -#define DEADKEY_ACUTE_ACCENT KEY_SEMICOLON + RCTRL_MASK -#define DEADKEY_CEDILLA KEY_EQUAL + RCTRL_MASK -#define DEADKEY_GRAVE_ACCENT KEY_LEFT_BRACE + ALTGR_MASK -#define DEADKEY_TILDE KEY_RIGHT_BRACE + ALTGR_MASK -#define DEADKEY_RING_ABOVE KEY_LEFT_BRACE + SHIFT_MASK + RCTRL_MASK -#define KEY_NON_US_100 63 - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! -#define ASCII_22 KEY_PERIOD + SHIFT_MASK // 34 " -#define ASCII_23 KEY_3 + SHIFT_MASK // 35 # -#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ -#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % -#define ASCII_26 KEY_7 + SHIFT_MASK // 38 & -#define ASCII_27 KEY_COMMA + SHIFT_MASK // 39 ' -#define ASCII_28 KEY_9 + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_0 + SHIFT_MASK // 41 ) -#define ASCII_2A KEY_8 + SHIFT_MASK // 42 * -#define ASCII_2B KEY_EQUAL + SHIFT_MASK // 43 + -#define ASCII_2C KEY_COMMA // 44 , -#define ASCII_2D KEY_MINUS // 45 - -#define ASCII_2E KEY_PERIOD // 46 . -#define ASCII_2F KEY_TILDE // 47 / -#define ASCII_30 KEY_0 // 48 0 -#define ASCII_31 KEY_1 // 49 1 -#define ASCII_32 KEY_2 // 50 2 -#define ASCII_33 KEY_3 // 51 3 -#define ASCII_34 KEY_4 // 52 4 -#define ASCII_35 KEY_5 // 53 5 -#define ASCII_36 KEY_6 // 54 6 -#define ASCII_37 KEY_7 // 55 7 -#define ASCII_38 KEY_8 // 55 8 -#define ASCII_39 KEY_9 // 57 9 -#define ASCII_3A KEY_SEMICOLON + SHIFT_MASK // 58 : -#define ASCII_3B KEY_SEMICOLON // 59 ; -#define ASCII_3C KEY_COMMA + ALTGR_MASK // 60 < -#define ASCII_3D KEY_EQUAL // 61 = -#define ASCII_3E KEY_PERIOD + ALTGR_MASK // 62 > -#define ASCII_3F KEY_6 + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_2 + SHIFT_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_9 + ALTGR_MASK // 91 [ -#define ASCII_5C KEY_TILDE + SHIFT_MASK // 92 -#define ASCII_5D KEY_0 + ALTGR_MASK // 93 ] -#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ -#define ASCII_5F KEY_MINUS + SHIFT_MASK // 95 _ -#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Y // 121 y -#define ASCII_7A KEY_Z // 122 z -#define ASCII_7B KEY_7 + ALTGR_MASK // 123 { -#define ASCII_7C KEY_TILDE + ALTGR_MASK // 124 | -#define ASCII_7D KEY_8 + ALTGR_MASK // 125 } -#define ASCII_7E KEY_RIGHT_BRACE + RCTRL_MASK // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 -#define ISO_8859_1_A0 KEY_SPACE + ALTGR_MASK // 160 Nonbreakng Space -#define ISO_8859_1_A1 KEY_1 + SHIFT_MASK + RCTRL_MASK // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 KEY_C + RCTRL_MASK // 162 ¢ Cent SIGN -#define ISO_8859_1_A3 KEY_3 + SHIFT_MASK + RCTRL_MASK // 163 £ Pound Sign -#define ISO_8859_1_A4 KEY_4 + SHIFT_MASK + RCTRL_MASK // 164 ¤ Currency or Euro Sign -#define ISO_8859_1_A5 KEY_Y + SHIFT_MASK + RCTRL_MASK // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 KEY_NON_US_100 + SHIFT_MASK + RCTRL_MASK// 166 ¦ BROKEN BAR -#define ISO_8859_1_A7 KEY_S + SHIFT_MASK + RCTRL_MASK // 167 § SECTION SIGN -#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 KEY_C + SHIFT_MASK + RCTRL_MASK // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA KEY_F + SHIFT_MASK + RCTRL_MASK // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB KEY_Z + ALTGR_MASK // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC KEY_EQUAL + ALTGR_MASK // 172 ¬ NOT SIGN -#define ISO_8859_1_AD KEY_TILDE + SHIFT_MASK + RCTRL_MASK // 173 SOFT HYPHEN -#define ISO_8859_1_AE KEY_R + SHIFT_MASK + RCTRL_MASK // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF 0 // special dead key - no implemented // 175 ¯ MACRON -#define ISO_8859_1_B0 KEY_SEMICOLON + ALTGR_MASK // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 KEY_9 + SHIFT_MASK + RCTRL_MASK // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 KEY_2 + RCTRL_MASK // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 KEY_3 + RCTRL_MASK // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 KEY_M + RCTRL_MASK // 181 µ MICRO SIGN -#define ISO_8859_1_B6 KEY_R + RCTRL_MASK // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT -#define ISO_8859_1_B8 CEDILLA_BITS + KEY_SPACE // 184 ¸ CEDILLA -#define ISO_8859_1_B9 KEY_1 + RCTRL_MASK // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA KEY_M + SHIFT_MASK + RCTRL_MASK // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB KEY_X + ALTGR_MASK // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC KEY_4 + RCTRL_MASK // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD KEY_5 + RCTRL_MASK // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE KEY_6 + RCTRL_MASK // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF KEY_MINUS + SHIFT_MASK + RCTRL_MASK // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 KEY_BACKSLASH + SHIFT_MASK // 192 À A GRAVE -#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE -#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE -#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 RING_ABOVE_BITS + KEY_A + SHIFT_MASK // 197 Å A RING ABOVE -#define ISO_8859_1_C6 KEY_A + SHIFT_MASK + RCTRL_MASK // 198 Æ AE -#define ISO_8859_1_C7 KEY_RIGHT_BRACE + SHIFT_MASK // 199 Ç C CEDILLA -#define ISO_8859_1_C8 KEY_QUOTE + SHIFT_MASK // 200 È E GRAVE -#define ISO_8859_1_C9 KEY_SLASH + SHIFT_MASK // 201 É E ACUTE -#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS -#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE -#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE -#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 KEY_D + SHIFT_MASK + RCTRL_MASK // 208 Ð ETH -#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE -#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE -#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE -#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE -#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 KEY_COMMA + SHIFT_MASK + RCTRL_MASK // 215 × MULTIPLICATION -#define ISO_8859_1_D8 KEY_O + SHIFT_MASK + RCTRL_MASK // 216 Ø O STROKE -#define ISO_8859_1_D9 KEY_NON_US_100 + SHIFT_MASK // 217 Ù U GRAVE -#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE -#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U // 220 Ü U DIAERESIS -#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE -#define ISO_8859_1_DE KEY_P + RCTRL_MASK + SHIFT_MASK // 222 Þ THORN -#define ISO_8859_1_DF KEY_S + RCTRL_MASK // 223 ß SHARP S -#define ISO_8859_1_E0 KEY_BACKSLASH // 224 à a GRAVE -#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE -#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE -#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS -#define ISO_8859_1_E5 RING_ABOVE_BITS + KEY_A // 229 å a RING ABOVE -#define ISO_8859_1_E6 KEY_A + RCTRL_MASK // 230 æ ae -#define ISO_8859_1_E7 KEY_RIGHT_BRACE // 231 ç c CEDILLA -#define ISO_8859_1_E8 KEY_QUOTE // 232 è e GRAVE -#define ISO_8859_1_E9 KEY_SLASH // 233 é e ACUTE -#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS -#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE -#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE -#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS -#define ISO_8859_1_F0 KEY_D + RCTRL_MASK // 240 ð ETH -#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE -#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE -#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE -#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE -#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS -#define ISO_8859_1_F7 KEY_PERIOD + SHIFT_MASK + RCTRL_MASK // 247 ÷ DIVISION -#define ISO_8859_1_F8 KEY_O + RCTRL_MASK // 248 ø o STROKE -#define ISO_8859_1_F9 KEY_NON_US_100 // 249 ù u GRAVE -#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE -#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS -#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE -#define ISO_8859_1_FE KEY_P + RCTRL_MASK // 254 þ THORN -#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS - -#endif // LAYOUT_CANADIAN_MULTILINGUAL - - - - - - -#ifdef LAYOUT_UNITED_KINGDOM - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define KEYCODE_TYPE uint8_t -#define KEY_NON_US_100 63 - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! -#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " -#define ASCII_23 KEY_BACKSPACE // 35 # -#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ -#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % -#define ASCII_26 KEY_7 + SHIFT_MASK // 38 & -#define ASCII_27 KEY_QUOTE // 39 ' -#define ASCII_28 KEY_9 + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_0 + SHIFT_MASK // 41 ) -#define ASCII_2A KEY_8 + SHIFT_MASK // 42 * -#define ASCII_2B KEY_EQUAL + SHIFT_MASK // 43 + -#define ASCII_2C KEY_COMMA // 44 , -#define ASCII_2D KEY_MINUS // 45 - -#define ASCII_2E KEY_PERIOD // 46 . -#define ASCII_2F KEY_SLASH // 47 / -#define ASCII_30 KEY_0 // 48 0 -#define ASCII_31 KEY_1 // 49 1 -#define ASCII_32 KEY_2 // 50 2 -#define ASCII_33 KEY_3 // 51 3 -#define ASCII_34 KEY_4 // 52 4 -#define ASCII_35 KEY_5 // 53 5 -#define ASCII_36 KEY_6 // 54 6 -#define ASCII_37 KEY_7 // 55 7 -#define ASCII_38 KEY_8 // 55 8 -#define ASCII_39 KEY_9 // 57 9 -#define ASCII_3A KEY_SEMICOLON + SHIFT_MASK // 58 : -#define ASCII_3B KEY_SEMICOLON // 59 ; -#define ASCII_3C KEY_COMMA + SHIFT_MASK // 60 < -#define ASCII_3D KEY_EQUAL // 61 = -#define ASCII_3E KEY_PERIOD + SHIFT_MASK // 62 > -#define ASCII_3F KEY_SLASH + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_QUOTE + SHIFT_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_LEFT_BRACE // 91 [ -#define ASCII_5C KEY_NON_US_100 // 92 -#define ASCII_5D KEY_RIGHT_BRACE // 93 ] -#define ASCII_5E KEY_6 + SHIFT_MASK // 94 ^ -#define ASCII_5F KEY_MINUS + SHIFT_MASK // 95 _ -#define ASCII_60 KEY_TILDE // 96 ` -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Y // 121 y -#define ASCII_7A KEY_Z // 122 z -#define ASCII_7B KEY_LEFT_BRACE + SHIFT_MASK // 123 { -#define ASCII_7C KEY_NON_US_100 + SHIFT_MASK // 124 | -#define ASCII_7D KEY_RIGHT_BRACE + SHIFT_MASK // 125 } -#define ASCII_7E KEY_BACKSLASH + SHIFT_MASK // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 - -#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space -#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN -#define ISO_8859_1_A3 KEY_3 + SHIFT_MASK // 163 £ Pound Sign -#define ISO_8859_1_A4 0 // 164 ¤ Currency or Euro Sign -#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 KEY_TILDE + ALTGR_MASK // 166 ¦ BROKEN BAR -#define ISO_8859_1_A7 0 // 167 § SECTION SIGN -#define ISO_8859_1_A8 0 // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC KEY_TILDE + SHIFT_MASK // 172 ¬ NOT SIGN -#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN -#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF 0 // 175 ¯ MACRON -#define ISO_8859_1_B0 0 // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 0 // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN -#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT -#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA -#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 0 // 192 À A GRAVE -#define ISO_8859_1_C1 KEY_A + ALTGR_MASK + SHIFT_MASK // 193 Á A ACUTE -#define ISO_8859_1_C2 0 // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 0 // 195 Ã A TILDE -#define ISO_8859_1_C4 0 // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE -#define ISO_8859_1_C6 0 // 198 Æ AE -#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA -#define ISO_8859_1_C8 0 // 200 È E GRAVE -#define ISO_8859_1_C9 KEY_E + ALTGR_MASK + SHIFT_MASK // 201 É E ACUTE -#define ISO_8859_1_CA 0 // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB 0 // 203 Ë E DIAERESIS -#define ISO_8859_1_CC 0 // 204 Ì I GRAVE -#define ISO_8859_1_CD KEY_I + ALTGR_MASK + SHIFT_MASK // 205 Í I ACUTE -#define ISO_8859_1_CE 0 // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF 0 // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 0 // 208 Ð ETH -#define ISO_8859_1_D1 0 // 209 Ñ N TILDE -#define ISO_8859_1_D2 0 // 210 Ò O GRAVE -#define ISO_8859_1_D3 KEY_O + ALTGR_MASK + SHIFT_MASK // 211 Ó O ACUTE -#define ISO_8859_1_D4 0 // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 0 // 213 Õ O TILDE -#define ISO_8859_1_D6 0 // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION -#define ISO_8859_1_D8 0 // 216 Ø O STROKE -#define ISO_8859_1_D9 0 // 217 Ù U GRAVE -#define ISO_8859_1_DA KEY_U + ALTGR_MASK + SHIFT_MASK // 218 Ú U ACUTE -#define ISO_8859_1_DB 0 // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC 0 // 220 Ü U DIAERESIS -#define ISO_8859_1_DD 0 // 221 Ý Y ACUTE -#define ISO_8859_1_DE 0 // 222 Þ THORN -#define ISO_8859_1_DF 0 // 223 ß SHARP S -#define ISO_8859_1_E0 0 // 224 à a GRAVE -#define ISO_8859_1_E1 KEY_A + ALTGR_MASK // 225 á a ACUTE -#define ISO_8859_1_E2 0 // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 0 // 227 ã a TILDE -#define ISO_8859_1_E4 0 // 228 ä a DIAERESIS -#define ISO_8859_1_E5 0 // 229 å a RING ABOVE -#define ISO_8859_1_E6 0 // 230 æ ae -#define ISO_8859_1_E7 0 // 231 ç c CEDILLA -#define ISO_8859_1_E8 0 // 232 è e GRAVE -#define ISO_8859_1_E9 KEY_E + ALTGR_MASK // 233 é e ACUTE -#define ISO_8859_1_EA 0 // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB 0 // 235 ë e DIAERESIS -#define ISO_8859_1_EC 0 // 236 ì i GRAVE -#define ISO_8859_1_ED KEY_I + ALTGR_MASK // 237 í i ACUTE -#define ISO_8859_1_EE 0 // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF 0 // 239 ï i DIAERESIS -#define ISO_8859_1_F0 0 // 240 ð ETH -#define ISO_8859_1_F1 0 // 241 ñ n TILDE -#define ISO_8859_1_F2 0 // 242 ò o GRAVE -#define ISO_8859_1_F3 KEY_O + ALTGR_MASK // 243 ó o ACUTE -#define ISO_8859_1_F4 0 // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 0 // 245 õ o TILDE -#define ISO_8859_1_F6 0 // 246 ö o DIAERESIS -#define ISO_8859_1_F7 0 // 247 ÷ DIVISION -#define ISO_8859_1_F8 0 // 248 ø o STROKE -#define ISO_8859_1_F9 0 // 249 ù u GRAVE -#define ISO_8859_1_FA KEY_U + ALTGR_MASK // 250 ú u ACUTE -#define ISO_8859_1_FB 0 // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC 0 // 252 ü u DIAERESIS -#define ISO_8859_1_FD 0 // 253 ý y ACUTE -#define ISO_8859_1_FE 0 // 254 þ THORN -#define ISO_8859_1_FF 0 // 255 ÿ y DIAERESIS -#define UNICODE_20AC KEY_4 + ALTGR_MASK // € Euro Sign -// not yet implemented -#define UNICODE_EXTRA00 0x20AC -#define KEYCODE_EXTRA00 KEY_4 + ALTGR_MASK // 20AC € Euro Sign - -#endif // LAYOUT_UNITED_KINGDOM - - - -#ifdef LAYOUT_FINNISH - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define DEADKEYS_MASK 0x0700 -#define CIRCUMFLEX_BITS 0x0100 -#define ACUTE_ACCENT_BITS 0x0200 -#define GRAVE_ACCENT_BITS 0x0300 -#define TILDE_BITS 0x0400 -#define DIAERESIS_BITS 0x0500 -#define KEYCODE_TYPE uint16_t -#define DEADKEY_CIRCUMFLEX KEY_RIGHT_BRACE + SHIFT_MASK -#define DEADKEY_ACUTE_ACCENT KEY_EQUAL -#define DEADKEY_GRAVE_ACCENT KEY_EQUAL + SHIFT_MASK -#define DEADKEY_TILDE KEY_RIGHT_BRACE + ALTGR_MASK -#define DEADKEY_DIAERESIS KEY_RIGHT_BRACE -#define KEY_NON_US_100 63 - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! -#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " -#define ASCII_23 KEY_3 + SHIFT_MASK // 35 # -#define ASCII_24 KEY_4 + ALTGR_MASK // 36 $ -#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % -#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & -#define ASCII_27 KEY_BACKSLASH // 39 ' -#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) -#define ASCII_2A KEY_BACKSLASH + SHIFT_MASK // 42 * -#define ASCII_2B KEY_MINUS // 43 + -#define ASCII_2C KEY_COMMA // 44 , -#define ASCII_2D KEY_SLASH // 45 - -#define ASCII_2E KEY_PERIOD // 46 . -#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / -#define ASCII_30 KEY_0 // 48 0 -#define ASCII_31 KEY_1 // 49 1 -#define ASCII_32 KEY_2 // 50 2 -#define ASCII_33 KEY_3 // 51 3 -#define ASCII_34 KEY_4 // 52 4 -#define ASCII_35 KEY_5 // 53 5 -#define ASCII_36 KEY_6 // 54 6 -#define ASCII_37 KEY_7 // 55 7 -#define ASCII_38 KEY_8 // 55 8 -#define ASCII_39 KEY_9 // 57 9 -#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : -#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; -#define ASCII_3C KEY_NON_US_100 // 60 < -#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = -#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > -#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_2 + ALTGR_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_8 + ALTGR_MASK // 91 [ -#define ASCII_5C KEY_MINUS + ALTGR_MASK // 92 -#define ASCII_5D KEY_9 + ALTGR_MASK // 93 ] -#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ -#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ -#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Y // 121 y -#define ASCII_7A KEY_Z // 122 z -#define ASCII_7B KEY_7 + ALTGR_MASK // 123 { -#define ASCII_7C KEY_NON_US_100 + ALTGR_MASK // 124 | -#define ASCII_7D KEY_0 + ALTGR_MASK // 125 } -#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 -#define ISO_8859_1_A0 KEY_SPACE + ALTGR_MASK // 160 Nonbreakng Space -#define ISO_8859_1_A1 KEY_1 + SHIFT_MASK + ALTGR_MASK // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN -#define ISO_8859_1_A3 KEY_3 + ALTGR_MASK // 163 £ Pound Sign -#define ISO_8859_1_A4 KEY_4 + SHIFT_MASK // 164 ¤ Currency or Euro Sign -#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR -#define ISO_8859_1_A7 KEY_TILDE // 167 § SECTION SIGN -#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB KEY_4 + ALTGR_MASK + SHIFT_MASK // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN -#define ISO_8859_1_AD KEY_SLASH + ALTGR_MASK // 173 SOFT HYPHEN -#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF 0 // 175 ¯ MACRON -#define ISO_8859_1_B0 KEY_0 + ALTGR_MASK + SHIFT_MASK // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 KEY_M + ALTGR_MASK // 181 µ MICRO SIGN -#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 KEY_X + ALTGR_MASK + SHIFT_MASK // 183 · MIDDLE DOT -#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA -#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB KEY_3 + ALTGR_MASK + SHIFT_MASK // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD KEY_TILDE + SHIFT_MASK // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF KEY_MINUS + ALTGR_MASK + SHIFT_MASK // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE -#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE -#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE -#define ISO_8859_1_C4 KEY_QUOTE + SHIFT_MASK // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 KEY_LEFT_BRACE + SHIFT_MASK // 197 Å A RING ABOVE -#define ISO_8859_1_C6 KEY_QUOTE + ALTGR_MASK + SHIFT_MASK // 198 Æ AE -#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA -#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE -#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE -#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS -#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE -#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE -#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 KEY_D + ALTGR_MASK + SHIFT_MASK // 208 Ð ETH -#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE -#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE -#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE -#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE -#define ISO_8859_1_D6 KEY_SEMICOLON + SHIFT_MASK // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 KEY_X + ALTGR_MASK // 215 × MULTIPLICATION -#define ISO_8859_1_D8 KEY_SEMICOLON + ALTGR_MASK + SHIFT_MASK // 216 Ø O STROKE -#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE -#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE -#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS -#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE -#define ISO_8859_1_DE KEY_T + ALTGR_MASK + SHIFT_MASK // 222 Þ THORN -#define ISO_8859_1_DF KEY_S + ALTGR_MASK // 223 ß SHARP S -#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE -#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE -#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE -#define ISO_8859_1_E4 KEY_QUOTE // 228 ä a DIAERESIS -#define ISO_8859_1_E5 KEY_LEFT_BRACE // 229 å a RING ABOVE -#define ISO_8859_1_E6 KEY_QUOTE + ALTGR_MASK // 230 æ ae -#define ISO_8859_1_E7 0 // 231 ç c CEDILLA -#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE -#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE -#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS -#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE -#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE -#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS -#define ISO_8859_1_F0 KEY_D + ALTGR_MASK // 240 ð ETH -#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE -#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE -#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE -#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE -#define ISO_8859_1_F6 KEY_SEMICOLON // 246 ö o DIAERESIS -#define ISO_8859_1_F7 0 // 247 ÷ DIVISION -#define ISO_8859_1_F8 KEY_SEMICOLON + ALTGR_MASK // 248 ø o STROKE -#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE -#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE -#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS -#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE -#define ISO_8859_1_FE KEY_T + ALTGR_MASK // 254 þ THORN -#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS -#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign -// not yet implemented -#define UNICODE_EXTRA00 0x20AC -#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign -// TODO: Finnish Multilingual layout can type many more glyphs -// but we currently don't have tables tables to store them... - -#endif // LAYOUT_FINNISH - - - - - - - -#ifdef LAYOUT_FRENCH - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define DEADKEYS_MASK 0x0700 -#define CIRCUMFLEX_BITS 0x0100 -#define GRAVE_ACCENT_BITS 0x0200 -#define DIAERESIS_BITS 0x0300 -#define TILDE_BITS 0x0400 -#define KEYCODE_TYPE uint16_t -#define DEADKEY_CIRCUMFLEX KEY_LEFT_BRACE -#define DEADKEY_GRAVE_ACCENT KEY_7 + ALTGR_MASK -#define DEADKEY_DIAERESIS KEY_LEFT_BRACE + SHIFT_MASK -#define DEADKEY_TILDE KEY_2 + ALTGR_MASK -#define KEY_NON_US_100 63 - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_SLASH // 33 ! -#define ASCII_22 KEY_3 // 34 " -#define ASCII_23 KEY_3 + ALTGR_MASK // 35 # -#define ASCII_24 KEY_RIGHT_BRACE // 36 $ -#define ASCII_25 KEY_QUOTE + SHIFT_MASK // 37 % -#define ASCII_26 KEY_1 // 38 & -#define ASCII_27 KEY_4 // 39 ' -#define ASCII_28 KEY_5 // 40 ( -#define ASCII_29 KEY_MINUS // 41 ) -#define ASCII_2A KEY_BACKSLASH // 42 * -#define ASCII_2B KEY_EQUAL + SHIFT_MASK // 43 + -#define ASCII_2C KEY_M // 44 , -#define ASCII_2D KEY_6 // 45 - -#define ASCII_2E KEY_COMMA + SHIFT_MASK // 46 . -#define ASCII_2F KEY_PERIOD + SHIFT_MASK // 47 / -#define ASCII_30 KEY_0 + SHIFT_MASK // 48 0 -#define ASCII_31 KEY_1 + SHIFT_MASK // 49 1 -#define ASCII_32 KEY_2 + SHIFT_MASK // 50 2 -#define ASCII_33 KEY_3 + SHIFT_MASK // 51 3 -#define ASCII_34 KEY_4 + SHIFT_MASK // 52 4 -#define ASCII_35 KEY_5 + SHIFT_MASK // 53 5 -#define ASCII_36 KEY_6 + SHIFT_MASK // 54 6 -#define ASCII_37 KEY_7 + SHIFT_MASK // 55 7 -#define ASCII_38 KEY_8 + SHIFT_MASK // 55 8 -#define ASCII_39 KEY_9 + SHIFT_MASK // 57 9 -#define ASCII_3A KEY_PERIOD // 58 : -#define ASCII_3B KEY_COMMA // 59 ; -#define ASCII_3C KEY_NON_US_100 // 60 < -#define ASCII_3D KEY_EQUAL // 61 = -#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > -#define ASCII_3F KEY_M + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_0 + ALTGR_MASK // 64 @ -#define ASCII_41 KEY_Q + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_SEMICOLON + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_A + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_Z + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_W + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_5 + ALTGR_MASK // 91 [ -#define ASCII_5C KEY_8 + ALTGR_MASK // 92 -#define ASCII_5D KEY_MINUS + ALTGR_MASK // 93 ] -#define ASCII_5E KEY_9 + ALTGR_MASK // 94 ^ -#define ASCII_5F KEY_8 // 95 _ -#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` -#define ASCII_61 KEY_Q // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_SEMICOLON // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_A // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_Z // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Y // 121 y -#define ASCII_7A KEY_W // 122 z -#define ASCII_7B KEY_4 + ALTGR_MASK // 123 { -#define ASCII_7C KEY_6 + ALTGR_MASK // 124 | -#define ASCII_7D KEY_EQUAL + ALTGR_MASK // 125 } -#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 -#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space -#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN -#define ISO_8859_1_A3 KEY_RIGHT_BRACE + SHIFT_MASK // 163 £ Pound Sign -#define ISO_8859_1_A4 KEY_RIGHT_BRACE + ALTGR_MASK // 164 ¤ Currency or Euro Sign -#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR -#define ISO_8859_1_A7 KEY_SLASH + SHIFT_MASK // 167 § SECTION SIGN -#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN -#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN -#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF 0 // 175 ¯ MACRON -#define ISO_8859_1_B0 KEY_MINUS + SHIFT_MASK // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 KEY_TILDE // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 0 // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 KEY_BACKSLASH + SHIFT_MASK // 181 µ MICRO SIGN -#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT -#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA -#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_Q + SHIFT_MASK // 192 À A GRAVE -#define ISO_8859_1_C1 0 // 193 Á A ACUTE -#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_Q + SHIFT_MASK // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 TILDE_BITS + KEY_Q + SHIFT_MASK // 195 Ã A TILDE -#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_Q + SHIFT_MASK // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE -#define ISO_8859_1_C6 0 // 198 Æ AE -#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA -#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE -#define ISO_8859_1_C9 0 // 201 É E ACUTE -#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS -#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE -#define ISO_8859_1_CD 0 // 205 Í I ACUTE -#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 0 // 208 Ð ETH -#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE -#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE -#define ISO_8859_1_D3 0 // 211 Ó O ACUTE -#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE -#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION -#define ISO_8859_1_D8 0 // 216 Ø O STROKE -#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE -#define ISO_8859_1_DA 0 // 218 Ú U ACUTE -#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U // 220 Ü U DIAERESIS -#define ISO_8859_1_DD 0 // 221 Ý Y ACUTE -#define ISO_8859_1_DE 0 // 222 Þ THORN -#define ISO_8859_1_DF 0 // 223 ß SHARP S -#define ISO_8859_1_E0 KEY_0 // 224 à a GRAVE -#define ISO_8859_1_E1 0 // 225 á a ACUTE -#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_Q // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 TILDE_BITS + KEY_Q // 227 ã a TILDE -#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_Q // 228 ä a DIAERESIS -#define ISO_8859_1_E5 0 // 229 å a RING ABOVE -#define ISO_8859_1_E6 0 // 230 æ ae -#define ISO_8859_1_E7 KEY_9 // 231 ç c CEDILLA -#define ISO_8859_1_E8 KEY_7 // 232 è e GRAVE -#define ISO_8859_1_E9 KEY_2 // 233 é e ACUTE -#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS -#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE -#define ISO_8859_1_ED 0 // 237 í i ACUTE -#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS -#define ISO_8859_1_F0 0 // 240 ð ETH -#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE -#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE -#define ISO_8859_1_F3 0 // 243 ó o ACUTE -#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE -#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS -#define ISO_8859_1_F7 0 // 247 ÷ DIVISION -#define ISO_8859_1_F8 0 // 248 ø o STROKE -#define ISO_8859_1_F9 KEY_SEMICOLON // 249 ù u GRAVE -#define ISO_8859_1_FA 0 // 250 ú u ACUTE -#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS -#define ISO_8859_1_FD 0 // 253 ý y ACUTE -#define ISO_8859_1_FE 0 // 254 þ THORN -#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS -#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign -// not yet implemented -#define UNICODE_EXTRA00 0x20AC -#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign - -#endif // LAYOUT_FRENCH - - - - - -#ifdef LAYOUT_DANISH - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define DEADKEYS_MASK 0x0700 -#define CIRCUMFLEX_BITS 0x0100 -#define ACUTE_ACCENT_BITS 0x0200 -#define GRAVE_ACCENT_BITS 0x0300 -#define TILDE_BITS 0x0400 -#define DIAERESIS_BITS 0x0500 -#define KEYCODE_TYPE uint16_t -#define DEADKEY_CIRCUMFLEX KEY_RIGHT_BRACE + SHIFT_MASK -#define DEADKEY_ACUTE_ACCENT KEY_EQUAL -#define DEADKEY_GRAVE_ACCENT KEY_EQUAL + SHIFT_MASK -#define DEADKEY_TILDE KEY_RIGHT_BRACE + ALTGR_MASK -#define DEADKEY_DIAERESIS KEY_RIGHT_BRACE -#define KEY_NON_US_100 63 - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! -#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " -#define ASCII_23 KEY_3 + SHIFT_MASK // 35 # -#define ASCII_24 KEY_4 + ALTGR_MASK // 36 $ -#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % -#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & -#define ASCII_27 KEY_BACKSLASH // 39 ' -#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) -#define ASCII_2A KEY_BACKSLASH + SHIFT_MASK // 42 * -#define ASCII_2B KEY_MINUS // 43 + -#define ASCII_2C KEY_COMMA // 44 , -#define ASCII_2D KEY_SLASH // 45 - -#define ASCII_2E KEY_PERIOD // 46 . -#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / -#define ASCII_30 KEY_0 // 48 0 -#define ASCII_31 KEY_1 // 49 1 -#define ASCII_32 KEY_2 // 50 2 -#define ASCII_33 KEY_3 // 51 3 -#define ASCII_34 KEY_4 // 52 4 -#define ASCII_35 KEY_5 // 53 5 -#define ASCII_36 KEY_6 // 54 6 -#define ASCII_37 KEY_7 // 55 7 -#define ASCII_38 KEY_8 // 55 8 -#define ASCII_39 KEY_9 // 57 9 -#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : -#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; -#define ASCII_3C KEY_NON_US_100 // 60 < -#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = -#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > -#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_2 + ALTGR_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_8 + ALTGR_MASK // 91 [ -#define ASCII_5C KEY_NON_US_100 + ALTGR_MASK // 92 -#define ASCII_5D KEY_9 + ALTGR_MASK // 93 ] -#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ -#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ -#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Y // 121 y -#define ASCII_7A KEY_Z // 122 z -#define ASCII_7B KEY_7 + ALTGR_MASK // 123 { -#define ASCII_7C KEY_EQUAL + ALTGR_MASK // 124 | -#define ASCII_7D KEY_0 + ALTGR_MASK // 125 } -#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 - -#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space -#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN -#define ISO_8859_1_A3 KEY_3 + ALTGR_MASK // 163 £ Pound Sign -#define ISO_8859_1_A4 KEY_4 + SHIFT_MASK // 164 ¤ Currency Sign -#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR -#define ISO_8859_1_A7 KEY_TILDE + SHIFT_MASK // 167 § SECTION SIGN -#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB KEY_4 // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN -#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN -#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF 0 // 175 ¯ MACRON -#define ISO_8859_1_B0 0 // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 KEY_M + ALTGR_MASK // 181 µ MICRO SIGN -#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT -#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA -#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD KEY_TILDE // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE -#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE -#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE -#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 KEY_LEFT_BRACE + SHIFT_MASK // 197 Å A RING ABOVE -#define ISO_8859_1_C6 KEY_SEMICOLON + SHIFT_MASK // 198 Æ AE -#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA -#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE -#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE -#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS -#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE -#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE -#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 KEY_D + ALTGR_MASK + SHIFT_MASK // 208 Ð ETH -#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE -#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE -#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE -#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE -#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION -#define ISO_8859_1_D8 KEY_QUOTE + SHIFT_MASK // 216 Ø O STROKE -#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE -#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE -#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS -#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE -#define ISO_8859_1_DE KEY_T + ALTGR_MASK + SHIFT_MASK // 222 Þ THORN -#define ISO_8859_1_DF KEY_S + ALTGR_MASK // 223 ß SHARP S -#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE -#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE -#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE -#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS -#define ISO_8859_1_E5 KEY_LEFT_BRACE // 229 å a RING ABOVE -#define ISO_8859_1_E6 KEY_SEMICOLON // 230 æ ae -#define ISO_8859_1_E7 0 // 231 ç c CEDILLA -#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE -#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE -#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS -#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE -#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE -#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS -#define ISO_8859_1_F0 KEY_D + ALTGR_MASK // 240 ð ETH -#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE -#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE -#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE -#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE -#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS -#define ISO_8859_1_F7 0 // 247 ÷ DIVISION -#define ISO_8859_1_F8 KEY_QUOTE // 248 ø o STROKE -#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE -#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE -#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS -#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE -#define ISO_8859_1_FE KEY_T + ALTGR_MASK // 254 þ THORN -#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS -#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign -// not yet implemented -#define UNICODE_EXTRA00 0x20AC -#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign - -#endif // LAYOUT_DANISH - - - - - -#ifdef LAYOUT_NORWEGIAN - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define DEADKEYS_MASK 0x0700 -#define CIRCUMFLEX_BITS 0x0100 -#define ACUTE_ACCENT_BITS 0x0200 -#define GRAVE_ACCENT_BITS 0x0300 -#define TILDE_BITS 0x0400 -#define DIAERESIS_BITS 0x0500 -#define KEYCODE_TYPE uint16_t -#define DEADKEY_CIRCUMFLEX KEY_RIGHT_BRACE + SHIFT_MASK -#define DEADKEY_ACUTE_ACCENT KEY_EQUAL + ALTGR_MASK -#define DEADKEY_GRAVE_ACCENT KEY_EQUAL + SHIFT_MASK -#define DEADKEY_TILDE KEY_RIGHT_BRACE + ALTGR_MASK -#define DEADKEY_DIAERESIS KEY_RIGHT_BRACE -#define KEY_NON_US_100 63 - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! -#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " -#define ASCII_23 KEY_3 + SHIFT_MASK // 35 # -#define ASCII_24 KEY_4 + ALTGR_MASK // 36 $ -#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % -#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & -#define ASCII_27 KEY_BACKSLASH // 39 ' -#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) -#define ASCII_2A KEY_BACKSLASH + SHIFT_MASK // 42 * -#define ASCII_2B KEY_MINUS // 43 + -#define ASCII_2C KEY_COMMA // 44 , -#define ASCII_2D KEY_SLASH // 45 - -#define ASCII_2E KEY_PERIOD // 46 . -#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / -#define ASCII_30 KEY_0 // 48 0 -#define ASCII_31 KEY_1 // 49 1 -#define ASCII_32 KEY_2 // 50 2 -#define ASCII_33 KEY_3 // 51 3 -#define ASCII_34 KEY_4 // 52 4 -#define ASCII_35 KEY_5 // 53 5 -#define ASCII_36 KEY_6 // 54 6 -#define ASCII_37 KEY_7 // 55 7 -#define ASCII_38 KEY_8 // 55 8 -#define ASCII_39 KEY_9 // 57 9 -#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : -#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; -#define ASCII_3C KEY_NON_US_100 // 60 < -#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = -#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > -#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_2 + ALTGR_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_8 + ALTGR_MASK // 91 [ -#define ASCII_5C KEY_EQUAL // 92 -#define ASCII_5D KEY_9 + ALTGR_MASK // 93 ] -#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ -#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ -#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Y // 121 y -#define ASCII_7A KEY_Z // 122 z -#define ASCII_7B KEY_7 + ALTGR_MASK // 123 { -#define ASCII_7C KEY_TILDE // 124 | -#define ASCII_7D KEY_0 + ALTGR_MASK // 125 } -#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 - -#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space -#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN -#define ISO_8859_1_A3 KEY_3 + ALTGR_MASK // 163 £ Pound Sign -#define ISO_8859_1_A4 KEY_4 + SHIFT_MASK // 164 ¤ Currency Sign -#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR -#define ISO_8859_1_A7 KEY_TILDE + SHIFT_MASK // 167 § SECTION SIGN -#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB KEY_4 // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN -#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN -#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF 0 // 175 ¯ MACRON -#define ISO_8859_1_B0 0 // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 KEY_M + ALTGR_MASK // 181 µ MICRO SIGN -#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT -#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA -#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD KEY_TILDE // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE -#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE -#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE -#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 KEY_LEFT_BRACE + SHIFT_MASK // 197 Å A RING ABOVE -#define ISO_8859_1_C6 KEY_QUOTE + SHIFT_MASK // 198 Æ AE -#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA -#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE -#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE -#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS -#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE -#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE -#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 KEY_D + ALTGR_MASK + SHIFT_MASK // 208 Ð ETH -#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE -#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE -#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE -#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE -#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION -#define ISO_8859_1_D8 KEY_SEMICOLON + SHIFT_MASK // 216 Ø O STROKE -#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE -#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE -#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS -#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE -#define ISO_8859_1_DE KEY_T + ALTGR_MASK + SHIFT_MASK // 222 Þ THORN -#define ISO_8859_1_DF KEY_S + ALTGR_MASK // 223 ß SHARP S -#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE -#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE -#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE -#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS -#define ISO_8859_1_E5 KEY_LEFT_BRACE // 229 å a RING ABOVE -#define ISO_8859_1_E6 KEY_QUOTE // 230 æ ae -#define ISO_8859_1_E7 0 // 231 ç c CEDILLA -#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE -#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE -#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS -#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE -#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE -#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS -#define ISO_8859_1_F0 KEY_D + ALTGR_MASK // 240 ð ETH -#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE -#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE -#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE -#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE -#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS -#define ISO_8859_1_F7 0 // 247 ÷ DIVISION -#define ISO_8859_1_F8 KEY_SEMICOLON // 248 ø o STROKE -#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE -#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE -#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS -#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE -#define ISO_8859_1_FE KEY_T + ALTGR_MASK // 254 þ THORN -#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS -#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign -// not yet implemented -#define UNICODE_EXTRA00 0x20AC -#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign - -#endif // LAYOUT_NORWEGIAN - - - - - - -#ifdef LAYOUT_SWEDISH - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define DEADKEYS_MASK 0x0700 -#define CIRCUMFLEX_BITS 0x0100 -#define ACUTE_ACCENT_BITS 0x0200 -#define GRAVE_ACCENT_BITS 0x0300 -#define TILDE_BITS 0x0400 -#define DIAERESIS_BITS 0x0500 -#define KEYCODE_TYPE uint16_t -#define DEADKEY_CIRCUMFLEX KEY_RIGHT_BRACE + SHIFT_MASK -#define DEADKEY_ACUTE_ACCENT KEY_EQUAL -#define DEADKEY_GRAVE_ACCENT KEY_EQUAL + SHIFT_MASK -#define DEADKEY_TILDE KEY_RIGHT_BRACE + ALTGR_MASK -#define DEADKEY_DIAERESIS KEY_RIGHT_BRACE -#define KEY_NON_US_100 63 - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! -#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " -#define ASCII_23 KEY_3 + SHIFT_MASK // 35 # -#define ASCII_24 KEY_4 + ALTGR_MASK // 36 $ -#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % -#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & -#define ASCII_27 KEY_BACKSLASH // 39 ' -#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) -#define ASCII_2A KEY_BACKSLASH + SHIFT_MASK // 42 * -#define ASCII_2B KEY_MINUS // 43 + -#define ASCII_2C KEY_COMMA // 44 , -#define ASCII_2D KEY_SLASH // 45 - -#define ASCII_2E KEY_PERIOD // 46 . -#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / -#define ASCII_30 KEY_0 // 48 0 -#define ASCII_31 KEY_1 // 49 1 -#define ASCII_32 KEY_2 // 50 2 -#define ASCII_33 KEY_3 // 51 3 -#define ASCII_34 KEY_4 // 52 4 -#define ASCII_35 KEY_5 // 53 5 -#define ASCII_36 KEY_6 // 54 6 -#define ASCII_37 KEY_7 // 55 7 -#define ASCII_38 KEY_8 // 55 8 -#define ASCII_39 KEY_9 // 57 9 -#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : -#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; -#define ASCII_3C KEY_NON_US_100 // 60 < -#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = -#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > -#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_2 + ALTGR_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_8 + ALTGR_MASK // 91 [ -#define ASCII_5C KEY_MINUS + ALTGR_MASK // 92 -#define ASCII_5D KEY_9 + ALTGR_MASK // 93 ] -#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ -#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ -#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Y // 121 y -#define ASCII_7A KEY_Z // 122 z -#define ASCII_7B KEY_7 + ALTGR_MASK // 123 { -#define ASCII_7C KEY_NON_US_100 + ALTGR_MASK // 124 | -#define ASCII_7D KEY_0 + ALTGR_MASK // 125 } -#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 - -#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space -#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN -#define ISO_8859_1_A3 KEY_3 + ALTGR_MASK // 163 £ Pound Sign -#define ISO_8859_1_A4 KEY_4 + SHIFT_MASK // 164 ¤ Currency Sign -#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR -#define ISO_8859_1_A7 KEY_TILDE // 167 § SECTION SIGN -#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB KEY_4 // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN -#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN -#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF 0 // 175 ¯ MACRON -#define ISO_8859_1_B0 0 // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 KEY_M + ALTGR_MASK // 181 µ MICRO SIGN -#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT -#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA -#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD KEY_TILDE + SHIFT_MASK // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE -#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE -#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE -#define ISO_8859_1_C4 KEY_QUOTE + SHIFT_MASK // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 KEY_LEFT_BRACE + SHIFT_MASK // 197 Å A RING ABOVE -#define ISO_8859_1_C6 0 // 198 Æ AE -#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA -#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE -#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE -#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS -#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE -#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE -#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 KEY_D + ALTGR_MASK + SHIFT_MASK // 208 Ð ETH -#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE -#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE -#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE -#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE -#define ISO_8859_1_D6 KEY_SEMICOLON + SHIFT_MASK // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION -#define ISO_8859_1_D8 0 // 216 Ø O STROKE -#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE -#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE -#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS -#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE -#define ISO_8859_1_DE KEY_T + ALTGR_MASK + SHIFT_MASK // 222 Þ THORN -#define ISO_8859_1_DF KEY_S + ALTGR_MASK // 223 ß SHARP S -#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE -#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE -#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE -#define ISO_8859_1_E4 KEY_QUOTE // 228 ä a DIAERESIS -#define ISO_8859_1_E5 KEY_LEFT_BRACE // 229 å a RING ABOVE -#define ISO_8859_1_E6 0 // 230 æ ae -#define ISO_8859_1_E7 0 // 231 ç c CEDILLA -#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE -#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE -#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS -#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE -#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE -#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS -#define ISO_8859_1_F0 KEY_D + ALTGR_MASK // 240 ð ETH -#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE -#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE -#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE -#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE -#define ISO_8859_1_F6 KEY_SEMICOLON // 246 ö o DIAERESIS -#define ISO_8859_1_F7 0 // 247 ÷ DIVISION -#define ISO_8859_1_F8 0 // 248 ø o STROKE -#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE -#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE -#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS -#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE -#define ISO_8859_1_FE KEY_T + ALTGR_MASK // 254 þ THORN -#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS -#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign -// not yet implemented -#define UNICODE_EXTRA00 0x20AC -#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign - -#endif // LAYOUT_SWEDISH - - - - - - -#ifdef LAYOUT_SPANISH - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define DEADKEYS_MASK 0x0700 -#define CIRCUMFLEX_BITS 0x0100 -#define ACUTE_ACCENT_BITS 0x0200 -#define GRAVE_ACCENT_BITS 0x0300 -#define TILDE_BITS 0x0400 -#define DIAERESIS_BITS 0x0500 -#define KEYCODE_TYPE uint16_t -#define DEADKEY_CIRCUMFLEX KEY_LEFT_BRACE + SHIFT_MASK -#define DEADKEY_ACUTE_ACCENT KEY_QUOTE -#define DEADKEY_GRAVE_ACCENT KEY_LEFT_BRACE -#define DEADKEY_TILDE KEY_4 + ALTGR_MASK -#define DEADKEY_DIAERESIS KEY_QUOTE + SHIFT_MASK -#define KEY_NON_US_100 63 - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! -#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " -#define ASCII_23 KEY_3 + ALTGR_MASK // 35 # -#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ -#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % -#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & -#define ASCII_27 KEY_MINUS // 39 ' -#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) -#define ASCII_2A KEY_RIGHT_BRACE + SHIFT_MASK // 42 * -#define ASCII_2B KEY_RIGHT_BRACE // 43 + -#define ASCII_2C KEY_COMMA // 44 , -#define ASCII_2D KEY_SLASH // 45 - -#define ASCII_2E KEY_PERIOD // 46 . -#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / -#define ASCII_30 KEY_0 // 48 0 -#define ASCII_31 KEY_1 // 49 1 -#define ASCII_32 KEY_2 // 50 2 -#define ASCII_33 KEY_3 // 51 3 -#define ASCII_34 KEY_4 // 52 4 -#define ASCII_35 KEY_5 // 53 5 -#define ASCII_36 KEY_6 // 54 6 -#define ASCII_37 KEY_7 // 55 7 -#define ASCII_38 KEY_8 // 55 8 -#define ASCII_39 KEY_9 // 57 9 -#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : -#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; -#define ASCII_3C KEY_NON_US_100 // 60 < -#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = -#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > -#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_2 + ALTGR_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_LEFT_BRACE + ALTGR_MASK // 91 [ -#define ASCII_5C KEY_TILDE + ALTGR_MASK // 92 -#define ASCII_5D KEY_RIGHT_BRACE + ALTGR_MASK // 93 ] -#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ -#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ -#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Y // 121 y -#define ASCII_7A KEY_Z // 122 z -#define ASCII_7B KEY_QUOTE + ALTGR_MASK // 123 { -#define ASCII_7C KEY_1 + ALTGR_MASK // 124 | -#define ASCII_7D KEY_BACKSLASH + ALTGR_MASK // 125 } -#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 - -#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space -#define ISO_8859_1_A1 KEY_EQUAL // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN -#define ISO_8859_1_A3 0 // 163 £ Pound Sign -#define ISO_8859_1_A4 0 // 164 ¤ Currency Sign -#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR -#define ISO_8859_1_A7 0 // 167 § SECTION SIGN -#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA KEY_TILDE + SHIFT_MASK // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC KEY_6 + ALTGR_MASK // 172 ¬ NOT SIGN -#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN -#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF 0 // 175 ¯ MACRON -#define ISO_8859_1_B0 0 // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN -#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 KEY_3 + SHIFT_MASK // 183 · MIDDLE DOT -#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA -#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA KEY_TILDE // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF KEY_EQUAL // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE -#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE -#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE -#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE -#define ISO_8859_1_C6 0 // 198 Æ AE -#define ISO_8859_1_C7 KEY_BACKSLASH + SHIFT_MASK // 199 Ç C CEDILLA -#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE -#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE -#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS -#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE -#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE -#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 0 // 208 Ð ETH -#define ISO_8859_1_D1 KEY_SEMICOLON + SHIFT_MASK // 209 Ñ N TILDE -#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE -#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE -#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE -#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION -#define ISO_8859_1_D8 0 // 216 Ø O STROKE -#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE -#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE -#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS -#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE -#define ISO_8859_1_DE 0 // 222 Þ THORN -#define ISO_8859_1_DF 0 // 223 ß SHARP S -#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE -#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE -#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE -#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS -#define ISO_8859_1_E5 0 // 229 å a RING ABOVE -#define ISO_8859_1_E6 0 // 230 æ ae -#define ISO_8859_1_E7 KEY_BACKSLASH // 231 ç c CEDILLA -#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE -#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE -#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS -#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE -#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE -#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS -#define ISO_8859_1_F0 0 // 240 ð ETH -#define ISO_8859_1_F1 KEY_SEMICOLON // 241 ñ n TILDE -#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE -#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE -#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE -#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS -#define ISO_8859_1_F7 0 // 247 ÷ DIVISION -#define ISO_8859_1_F8 0 // 248 ø o STROKE -#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE -#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE -#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS -#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE -#define ISO_8859_1_FE 0 // 254 þ THORN -#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS -#define UNICODE_20AC KEY_5 + ALTGR_MASK // € Euro Sign -// not yet implemented -#define UNICODE_EXTRA00 0x20AC -#define KEYCODE_EXTRA00 KEY_5 + ALTGR_MASK // 20AC € Euro Sign - -#endif // LAYOUT_SPANISH - - - - -#ifdef LAYOUT_PORTUGUESE - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define DEADKEYS_MASK 0x0700 -#define CIRCUMFLEX_BITS 0x0100 -#define ACUTE_ACCENT_BITS 0x0200 -#define GRAVE_ACCENT_BITS 0x0300 -#define TILDE_BITS 0x0400 -#define DIAERESIS_BITS 0x0500 -#define KEYCODE_TYPE uint16_t -#define DEADKEY_CIRCUMFLEX KEY_BACKSLASH -#define DEADKEY_ACUTE_ACCENT KEY_RIGHT_BRACE + SHIFT_MASK -#define DEADKEY_GRAVE_ACCENT KEY_RIGHT_BRACE + SHIFT_MASK -#define DEADKEY_TILDE KEY_BACKSLASH -#define DEADKEY_DIAERESIS KEY_LEFT_BRACE + SHIFT_MASK -#define KEY_NON_US_100 63 - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! -#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " -#define ASCII_23 KEY_3 + ALTGR_MASK // 35 # -#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ -#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % -#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & -#define ASCII_27 KEY_MINUS // 39 ' -#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) -#define ASCII_2A KEY_LEFT_BRACE + SHIFT_MASK // 42 * -#define ASCII_2B KEY_LEFT_BRACE // 43 + -#define ASCII_2C KEY_COMMA // 44 , -#define ASCII_2D KEY_SLASH // 45 - -#define ASCII_2E KEY_PERIOD // 46 . -#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / -#define ASCII_30 KEY_0 // 48 0 -#define ASCII_31 KEY_1 // 49 1 -#define ASCII_32 KEY_2 // 50 2 -#define ASCII_33 KEY_3 // 51 3 -#define ASCII_34 KEY_4 // 52 4 -#define ASCII_35 KEY_5 // 53 5 -#define ASCII_36 KEY_6 // 54 6 -#define ASCII_37 KEY_7 // 55 7 -#define ASCII_38 KEY_8 // 55 8 -#define ASCII_39 KEY_9 // 57 9 -#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : -#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; -#define ASCII_3C KEY_NON_US_100 // 60 < -#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = -#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > -#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_2 + ALTGR_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_8 + ALTGR_MASK // 91 [ -#define ASCII_5C KEY_TILDE + ALTGR_MASK // 92 -#define ASCII_5D KEY_9 + ALTGR_MASK // 93 ] -#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ -#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ -#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Y // 121 y -#define ASCII_7A KEY_Z // 122 z -#define ASCII_7B KEY_7 + ALTGR_MASK // 123 { -#define ASCII_7C KEY_TILDE + SHIFT_MASK // 124 | -#define ASCII_7D KEY_0 + ALTGR_MASK // 125 } -#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 - -#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space -#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN -#define ISO_8859_1_A3 KEY_3 + ALTGR_MASK // 163 £ Pound Sign -#define ISO_8859_1_A4 0 // 164 ¤ Currency Sign -#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR -#define ISO_8859_1_A7 KEY_4 + ALTGR_MASK // 167 § SECTION SIGN -#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA KEY_QUOTE + SHIFT_MASK // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB KEY_EQUAL // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN -#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN -#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF 0 // 175 ¯ MACRON -#define ISO_8859_1_B0 0 // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN -#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT -#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA -#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA KEY_QUOTE // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB KEY_EQUAL + SHIFT_MASK // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE -#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE -#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE -#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE -#define ISO_8859_1_C6 0 // 198 Æ AE -#define ISO_8859_1_C7 KEY_SEMICOLON + SHIFT_MASK // 199 Ç C CEDILLA -#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE -#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE -#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS -#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE -#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE -#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 0 // 208 Ð ETH -#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE -#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE -#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE -#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE -#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION -#define ISO_8859_1_D8 0 // 216 Ø O STROKE -#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE -#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE -#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS -#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE -#define ISO_8859_1_DE 0 // 222 Þ THORN -#define ISO_8859_1_DF 0 // 223 ß SHARP S -#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE -#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE -#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE -#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS -#define ISO_8859_1_E5 0 // 229 å a RING ABOVE -#define ISO_8859_1_E6 0 // 230 æ ae -#define ISO_8859_1_E7 KEY_SEMICOLON // 231 ç c CEDILLA -#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE -#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE -#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS -#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE -#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE -#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS -#define ISO_8859_1_F0 0 // 240 ð ETH -#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE -#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE -#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE -#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE -#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS -#define ISO_8859_1_F7 0 // 247 ÷ DIVISION -#define ISO_8859_1_F8 0 // 248 ø o STROKE -#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE -#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE -#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS -#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE -#define ISO_8859_1_FE 0 // 254 þ THORN -#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS -#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign -// not yet implemented -#define UNICODE_EXTRA00 0x20AC -#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign - -#endif // LAYOUT_PORTUGUESE - - - - - - - -#ifdef LAYOUT_ITALIAN - -#define SHIFT_MASK 0x40 -#define ALTGR_MASK 0x80 -#define KEYCODE_TYPE uint8_t -#define KEY_NON_US_100 63 - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! -#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " -#define ASCII_23 KEY_QUOTE + ALTGR_MASK // 35 # -#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ -#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % -#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & -#define ASCII_27 KEY_MINUS // 39 ' -#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) -#define ASCII_2A KEY_RIGHT_BRACE + SHIFT_MASK // 42 * -#define ASCII_2B KEY_RIGHT_BRACE // 43 + -#define ASCII_2C KEY_COMMA // 44 , -#define ASCII_2D KEY_SLASH // 45 - -#define ASCII_2E KEY_PERIOD // 46 . -#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / -#define ASCII_30 KEY_0 // 48 0 -#define ASCII_31 KEY_1 // 49 1 -#define ASCII_32 KEY_2 // 50 2 -#define ASCII_33 KEY_3 // 51 3 -#define ASCII_34 KEY_4 // 52 4 -#define ASCII_35 KEY_5 // 53 5 -#define ASCII_36 KEY_6 // 54 6 -#define ASCII_37 KEY_7 // 55 7 -#define ASCII_38 KEY_8 // 55 8 -#define ASCII_39 KEY_9 // 57 9 -#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : -#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; -#define ASCII_3C KEY_NON_US_100 // 60 < -#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = -#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > -#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_SEMICOLON + ALTGR_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_LEFT_BRACE + ALTGR_MASK // 91 [ -#define ASCII_5C KEY_TILDE // 92 -#define ASCII_5D KEY_RIGHT_BRACE + ALTGR_MASK // 93 ] -#define ASCII_5E KEY_EQUAL + SHIFT_MASK // 94 ^ -#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ -#define ASCII_60 0 // 96 ` (how to type this on Italian?) -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Y // 121 y -#define ASCII_7A KEY_Z // 122 z -#define ASCII_7B KEY_LEFT_BRACE + SHIFT_MASK + ALTGR_MASK // 123 { -#define ASCII_7C KEY_TILDE + SHIFT_MASK // 124 | -#define ASCII_7D KEY_RIGHT_BRACE + SHIFT_MASK + ALTGR_MASK // 125 } -#define ASCII_7E 0 // 126 ~ (how to type this on Italian?) -#define ASCII_7F KEY_BACKSPACE // 127 - -#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space -#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 0 // 162 ¢ Cent Sign -#define ISO_8859_1_A3 KEY_3 + SHIFT_MASK // 163 £ Pound Sign -#define ISO_8859_1_A4 0 // 164 ¤ Currency Sign -#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR -#define ISO_8859_1_A7 KEY_BACKSLASH + SHIFT_MASK // 167 § SECTION SIGN -#define ISO_8859_1_A8 0 // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN -#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN -#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF 0 // 175 ¯ MACRON -#define ISO_8859_1_B0 KEY_QUOTE + SHIFT_MASK // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 0 // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN -#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT -#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA -#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 0 // 192 À A GRAVE -#define ISO_8859_1_C1 0 // 193 Á A ACUTE -#define ISO_8859_1_C2 0 // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 0 // 195 Ã A TILDE -#define ISO_8859_1_C4 0 // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE -#define ISO_8859_1_C6 0 // 198 Æ AE -#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA -#define ISO_8859_1_C8 0 // 200 È E GRAVE -#define ISO_8859_1_C9 0 // 201 É E ACUTE -#define ISO_8859_1_CA 0 // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB 0 // 203 Ë E DIAERESIS -#define ISO_8859_1_CC 0 // 204 Ì I GRAVE -#define ISO_8859_1_CD 0 // 205 Í I ACUTE -#define ISO_8859_1_CE 0 // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF 0 // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 0 // 208 Ð ETH -#define ISO_8859_1_D1 0 // 209 Ñ N TILDE -#define ISO_8859_1_D2 0 // 210 Ò O GRAVE -#define ISO_8859_1_D3 0 // 211 Ó O ACUTE -#define ISO_8859_1_D4 0 // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 0 // 213 Õ O TILDE -#define ISO_8859_1_D6 0 // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION -#define ISO_8859_1_D8 0 // 216 Ø O STROKE -#define ISO_8859_1_D9 0 // 217 Ù U GRAVE -#define ISO_8859_1_DA 0 // 218 Ú U ACUTE -#define ISO_8859_1_DB 0 // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC 0 // 220 Ü U DIAERESIS -#define ISO_8859_1_DD 0 // 221 Ý Y ACUTE -#define ISO_8859_1_DE 0 // 222 Þ THORN -#define ISO_8859_1_DF 0 // 223 ß SHARP S -#define ISO_8859_1_E0 KEY_QUOTE // 224 à a GRAVE -#define ISO_8859_1_E1 0 // 225 á a ACUTE -#define ISO_8859_1_E2 0 // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 0 // 227 ã a TILDE -#define ISO_8859_1_E4 0 // 228 ä a DIAERESIS -#define ISO_8859_1_E5 0 // 229 å a RING ABOVE -#define ISO_8859_1_E6 0 // 230 æ ae -#define ISO_8859_1_E7 KEY_SEMICOLON + SHIFT_MASK // 231 ç c CEDILLA -#define ISO_8859_1_E8 KEY_LEFT_BRACE // 232 è e GRAVE -#define ISO_8859_1_E9 KEY_LEFT_BRACE + SHIFT_MASK // 233 é e ACUTE -#define ISO_8859_1_EA 0 // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB 0 // 235 ë e DIAERESIS -#define ISO_8859_1_EC KEY_EQUAL // 236 ì i GRAVE -#define ISO_8859_1_ED 0 // 237 í i ACUTE -#define ISO_8859_1_EE 0 // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF 0 // 239 ï i DIAERESIS -#define ISO_8859_1_F0 0 // 240 ð ETH -#define ISO_8859_1_F1 0 // 241 ñ n TILDE -#define ISO_8859_1_F2 KEY_SEMICOLON // 242 ò o GRAVE -#define ISO_8859_1_F3 0 // 243 ó o ACUTE -#define ISO_8859_1_F4 0 // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 0 // 245 õ o TILDE -#define ISO_8859_1_F6 0 // 246 ö o DIAERESIS -#define ISO_8859_1_F7 0 // 247 ÷ DIVISION -#define ISO_8859_1_F8 0 // 248 ø o STROKE -#define ISO_8859_1_F9 KEY_BACKSLASH // 249 ù u GRAVE -#define ISO_8859_1_FA 0 // 250 ú u ACUTE -#define ISO_8859_1_FB 0 // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC 0 // 252 ü u DIAERESIS -#define ISO_8859_1_FD 0 // 253 ý y ACUTE -#define ISO_8859_1_FE 0 // 254 þ THORN -#define ISO_8859_1_FF 0 // 255 ÿ y DIAERESIS - -#endif // LAYOUT_ITALIAN - - - - -#ifdef LAYOUT_PORTUGUESE_BRAZILIAN - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define DEADKEYS_MASK 0x0700 -#define CIRCUMFLEX_BITS 0x0100 -#define ACUTE_ACCENT_BITS 0x0200 -#define GRAVE_ACCENT_BITS 0x0300 -#define TILDE_BITS 0x0400 -#define DIAERESIS_BITS 0x0500 -#define KEYCODE_TYPE uint16_t -#define DEADKEY_CIRCUMFLEX KEY_QUOTE + SHIFT_MASK -#define DEADKEY_ACUTE_ACCENT KEY_LEFT_BRACE -#define DEADKEY_GRAVE_ACCENT KEY_LEFT_BRACE + SHIFT_MASK -#define DEADKEY_TILDE KEY_QUOTE -#define DEADKEY_DIAERESIS KEY_6 + SHIFT_MASK -#define KEY_NON_US_100 63 - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! -#define ASCII_22 KEY_TILDE + SHIFT_MASK // 34 " -#define ASCII_23 KEY_3 + ALTGR_MASK // 35 # -#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ -#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % -#define ASCII_26 KEY_7 + SHIFT_MASK // 38 & -#define ASCII_27 KEY_TILDE // 39 ' -#define ASCII_28 KEY_9 + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_0 + SHIFT_MASK // 41 ) -#define ASCII_2A KEY_7 + SHIFT_MASK // 42 * -#define ASCII_2B KEY_EQUAL + SHIFT_MASK // 43 + -#define ASCII_2C KEY_COMMA // 44 , -#define ASCII_2D KEY_MINUS // 45 - -#define ASCII_2E KEY_PERIOD // 46 . -#define ASCII_2F KEY_Q + ALTGR_MASK // 47 / -#define ASCII_30 KEY_0 // 48 0 -#define ASCII_31 KEY_1 // 49 1 -#define ASCII_32 KEY_2 // 50 2 -#define ASCII_33 KEY_3 // 51 3 -#define ASCII_34 KEY_4 // 52 4 -#define ASCII_35 KEY_5 // 53 5 -#define ASCII_36 KEY_6 // 54 6 -#define ASCII_37 KEY_7 // 55 7 -#define ASCII_38 KEY_8 // 55 8 -#define ASCII_39 KEY_9 // 57 9 -#define ASCII_3A KEY_SLASH + SHIFT_MASK // 58 : -#define ASCII_3B KEY_SLASH // 59 ; -#define ASCII_3C KEY_COMMA + SHIFT_MASK // 60 < -#define ASCII_3D KEY_EQUAL // 61 = -#define ASCII_3E KEY_PERIOD + SHIFT_MASK // 62 > -#define ASCII_3F KEY_W + ALTGR_MASK // 63 ? -#define ASCII_40 KEY_2 + SHIFT_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_RIGHT_BRACE // 91 [ -#define ASCII_5C KEY_NON_US_100 // 92 -#define ASCII_5D KEY_BACKSLASH // 93 ] -#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ -#define ASCII_5F KEY_MINUS + SHIFT_MASK // 95 _ -#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Y // 121 y -#define ASCII_7A KEY_Z // 122 z -#define ASCII_7B KEY_RIGHT_BRACE + SHIFT_MASK // 123 { -#define ASCII_7C KEY_NON_US_100 + SHIFT_MASK // 124 | -#define ASCII_7D KEY_BACKSLASH + SHIFT_MASK // 125 } -#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 - -#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space -#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 KEY_5 + ALTGR_MASK // 162 ¢ Cent SIGN -#define ISO_8859_1_A3 KEY_4 + ALTGR_MASK // 163 £ Pound Sign -#define ISO_8859_1_A4 0 // 164 ¤ Currency Sign -#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR -#define ISO_8859_1_A7 KEY_EQUAL + ALTGR_MASK // 167 § SECTION SIGN -#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA KEY_RIGHT_BRACE + ALTGR_MASK // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC KEY_6 + ALTGR_MASK // 172 ¬ NOT SIGN -#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN -#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF 0 // 175 ¯ MACRON -#define ISO_8859_1_B0 KEY_E + ALTGR_MASK // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 KEY_2 + ALTGR_MASK // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 KEY_2 + ALTGR_MASK // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN -#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT -#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA -#define ISO_8859_1_B9 KEY_1 + ALTGR_MASK // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA KEY_BACKSLASH + ALTGR_MASK // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE -#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE -#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE -#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE -#define ISO_8859_1_C6 0 // 198 Æ AE -#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA -#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE -#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE -#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS -#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE -#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE -#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 0 // 208 Ð ETH -#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE -#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE -#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE -#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE -#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION -#define ISO_8859_1_D8 0 // 216 Ø O STROKE -#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE -#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE -#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS -#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE -#define ISO_8859_1_DE 0 // 222 Þ THORN -#define ISO_8859_1_DF 0 // 223 ß SHARP S -#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE -#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE -#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE -#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS -#define ISO_8859_1_E5 0 // 229 å a RING ABOVE -#define ISO_8859_1_E6 0 // 230 æ ae -#define ISO_8859_1_E7 0 // 231 ç c CEDILLA -#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE -#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE -#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS -#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE -#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE -#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS -#define ISO_8859_1_F0 0 // 240 ð ETH -#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE -#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE -#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE -#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE -#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS -#define ISO_8859_1_F7 0 // 247 ÷ DIVISION -#define ISO_8859_1_F8 0 // 248 ø o STROKE -#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE -#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE -#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS -#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE -#define ISO_8859_1_FE 0 // 254 þ THORN -#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS - -#endif // LAYOUT_PORTUGUESE_BRAZILIAN - - - -#ifdef LAYOUT_FRENCH_BELGIAN - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define DEADKEYS_MASK 0x0700 -#define CIRCUMFLEX_BITS 0x0100 -#define GRAVE_ACCENT_BITS 0x0200 -#define DIAERESIS_BITS 0x0300 -#define TILDE_BITS 0x0400 -#define ACUTE_ACCENT_BITS 0x0500 -#define KEYCODE_TYPE uint16_t -#define DEADKEY_CIRCUMFLEX KEY_LEFT_BRACE -#define DEADKEY_ACUTE_ACCENT KEY_QUOTE + ALTGR_MASK -#define DEADKEY_GRAVE_ACCENT KEY_BACKSLASH + ALTGR_MASK -#define DEADKEY_DIAERESIS KEY_LEFT_BRACE + SHIFT_MASK -#define DEADKEY_TILDE KEY_SLASH + ALTGR_MASK -#define KEY_NON_US_100 63 - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_8 // 33 ! -#define ASCII_22 KEY_3 // 34 " -#define ASCII_23 KEY_3 + ALTGR_MASK // 35 # -#define ASCII_24 KEY_RIGHT_BRACE // 36 $ -#define ASCII_25 KEY_QUOTE + SHIFT_MASK // 37 % -#define ASCII_26 KEY_1 // 38 & -#define ASCII_27 KEY_4 // 39 ' -#define ASCII_28 KEY_5 // 40 ( -#define ASCII_29 KEY_MINUS // 41 ) -#define ASCII_2A KEY_RIGHT_BRACE + SHIFT_MASK // 42 * -#define ASCII_2B KEY_SLASH + SHIFT_MASK // 43 + -#define ASCII_2C KEY_M // 44 , -#define ASCII_2D KEY_EQUAL // 45 - -#define ASCII_2E KEY_COMMA + SHIFT_MASK // 46 . -#define ASCII_2F KEY_PERIOD + SHIFT_MASK // 47 / -#define ASCII_30 KEY_0 + SHIFT_MASK // 48 0 -#define ASCII_31 KEY_1 + SHIFT_MASK // 49 1 -#define ASCII_32 KEY_2 + SHIFT_MASK // 50 2 -#define ASCII_33 KEY_3 + SHIFT_MASK // 51 3 -#define ASCII_34 KEY_4 + SHIFT_MASK // 52 4 -#define ASCII_35 KEY_5 + SHIFT_MASK // 53 5 -#define ASCII_36 KEY_6 + SHIFT_MASK // 54 6 -#define ASCII_37 KEY_7 + SHIFT_MASK // 55 7 -#define ASCII_38 KEY_8 + SHIFT_MASK // 55 8 -#define ASCII_39 KEY_9 + SHIFT_MASK // 57 9 -#define ASCII_3A KEY_PERIOD // 58 : -#define ASCII_3B KEY_COMMA // 59 ; -#define ASCII_3C KEY_NON_US_100 // 60 < -#define ASCII_3D KEY_SLASH // 61 = -#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > -#define ASCII_3F KEY_M + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_2 + ALTGR_MASK // 64 @ -#define ASCII_41 KEY_Q + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_SEMICOLON + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_A + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_Z + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_W + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_RIGHT_BRACE + ALTGR_MASK // 91 [ -#define ASCII_5C KEY_NON_US_100 + ALTGR_MASK // 92 -#define ASCII_5D KEY_LEFT_BRACE + ALTGR_MASK // 93 ] -#define ASCII_5E KEY_6 + ALTGR_MASK // 94 ^ -#define ASCII_5F KEY_EQUAL + SHIFT_MASK // 95 _ -#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` -#define ASCII_61 KEY_Q // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_SEMICOLON // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_A // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_Z // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Y // 121 y -#define ASCII_7A KEY_W // 122 z -#define ASCII_7B KEY_9 + ALTGR_MASK // 123 { -#define ASCII_7C KEY_1 + ALTGR_MASK // 124 | -#define ASCII_7D KEY_0 + ALTGR_MASK // 125 } -#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 -#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space -#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN -#define ISO_8859_1_A3 KEY_BACKSLASH + SHIFT_MASK // 163 £ Pound Sign -#define ISO_8859_1_A4 0 // 164 ¤ Currency or Euro Sign -#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR -#define ISO_8859_1_A7 KEY_6 // 167 § SECTION SIGN -#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN -#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN -#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF 0 // 175 ¯ MACRON -#define ISO_8859_1_B0 KEY_MINUS + SHIFT_MASK // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 KEY_TILDE // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 KEY_TILDE + SHIFT_MASK // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 KEY_BACKSLASH // 181 µ MICRO SIGN -#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT -#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA -#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_Q + SHIFT_MASK // 192 À A GRAVE -#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_Q + SHIFT_MASK // 193 Á A ACUTE -#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_Q + SHIFT_MASK // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 TILDE_BITS + KEY_Q + SHIFT_MASK // 195 Ã A TILDE -#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_Q + SHIFT_MASK // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE -#define ISO_8859_1_C6 0 // 198 Æ AE -#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA -#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE -#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE -#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS -#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE -#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE -#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 0 // 208 Ð ETH -#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE -#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE -#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE -#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE -#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION -#define ISO_8859_1_D8 0 // 216 Ø O STROKE -#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE -#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE -#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U // 220 Ü U DIAERESIS -#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE -#define ISO_8859_1_DE 0 // 222 Þ THORN -#define ISO_8859_1_DF 0 // 223 ß SHARP S -#define ISO_8859_1_E0 KEY_0 // 224 à a GRAVE -#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_Q // 225 á a ACUTE -#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_Q // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 TILDE_BITS + KEY_Q // 227 ã a TILDE -#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_Q // 228 ä a DIAERESIS -#define ISO_8859_1_E5 0 // 229 å a RING ABOVE -#define ISO_8859_1_E6 0 // 230 æ ae -#define ISO_8859_1_E7 KEY_9 // 231 ç c CEDILLA -#define ISO_8859_1_E8 KEY_7 // 232 è e GRAVE -#define ISO_8859_1_E9 KEY_2 // 233 é e ACUTE -#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS -#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE -#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE -#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS -#define ISO_8859_1_F0 0 // 240 ð ETH -#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE -#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE -#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE -#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE -#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS -#define ISO_8859_1_F7 0 // 247 ÷ DIVISION -#define ISO_8859_1_F8 0 // 248 ø o STROKE -#define ISO_8859_1_F9 KEY_QUOTE // 249 ù u GRAVE - TODO; check FRENCH -#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE -#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS -#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE -#define ISO_8859_1_FE 0 // 254 þ THORN -#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS -#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign -// not yet implemented -#define UNICODE_EXTRA00 0x20AC -#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign - -#endif // LAYOUT_FRENCH_BELGIAN - - - - -#ifdef LAYOUT_GERMAN_SWISS - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define DEADKEYS_MASK 0x0700 -#define CIRCUMFLEX_BITS 0x0100 -#define GRAVE_ACCENT_BITS 0x0200 -#define DIAERESIS_BITS 0x0300 -#define TILDE_BITS 0x0400 -#define ACUTE_ACCENT_BITS 0x0500 -#define KEYCODE_TYPE uint16_t -#define DEADKEY_CIRCUMFLEX KEY_EQUAL -#define DEADKEY_ACUTE_ACCENT KEY_MINUS + ALTGR_MASK -#define DEADKEY_GRAVE_ACCENT KEY_EQUAL + SHIFT_MASK -#define DEADKEY_DIAERESIS KEY_RIGHT_BRACE -#define DEADKEY_TILDE KEY_EQUAL + ALTGR_MASK -#define KEY_NON_US_100 63 - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_RIGHT_BRACE + SHIFT_MASK // 33 ! -#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " -#define ASCII_23 KEY_3 + ALTGR_MASK // 35 # -#define ASCII_24 KEY_BACKSLASH // 36 $ -#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % -#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & -#define ASCII_27 KEY_MINUS // 39 ' -#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) -#define ASCII_2A KEY_3 + SHIFT_MASK // 42 * -#define ASCII_2B KEY_1 + SHIFT_MASK // 43 + -#define ASCII_2C KEY_COMMA // 44 , -#define ASCII_2D KEY_SLASH // 45 - -#define ASCII_2E KEY_PERIOD // 46 . -#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / -#define ASCII_30 KEY_0 // 48 0 -#define ASCII_31 KEY_1 // 49 1 -#define ASCII_32 KEY_2 // 50 2 -#define ASCII_33 KEY_3 // 51 3 -#define ASCII_34 KEY_4 // 52 4 -#define ASCII_35 KEY_5 // 53 5 -#define ASCII_36 KEY_6 // 54 6 -#define ASCII_37 KEY_7 // 55 7 -#define ASCII_38 KEY_8 // 55 8 -#define ASCII_39 KEY_9 // 57 9 -#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : -#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; -#define ASCII_3C KEY_NON_US_100 // 60 < -#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = -#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > -#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_2 + ALTGR_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Z + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Y + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_LEFT_BRACE + ALTGR_MASK // 91 [ -#define ASCII_5C KEY_NON_US_100 + ALTGR_MASK // 92 -#define ASCII_5D KEY_RIGHT_BRACE + ALTGR_MASK // 93 ] -#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ -#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ -#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Z // 121 y -#define ASCII_7A KEY_Y // 122 z -#define ASCII_7B KEY_QUOTE + ALTGR_MASK // 123 { -#define ASCII_7C KEY_7 + ALTGR_MASK // 124 | -#define ASCII_7D KEY_BACKSLASH + ALTGR_MASK // 125 } -#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 -#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space -#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 KEY_8 + ALTGR_MASK // 162 ¢ Cent Sign -#define ISO_8859_1_A3 KEY_BACKSLASH + SHIFT_MASK // 163 £ Pound Sign -#define ISO_8859_1_A4 0 // 164 ¤ Currency Sign -#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 KEY_1 + ALTGR_MASK // 166 ¦ BROKEN BAR -#define ISO_8859_1_A7 KEY_5 + ALTGR_MASK // 167 § SECTION SIGN -#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC KEY_6 + ALTGR_MASK // 172 ¬ NOT SIGN -#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN -#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF 0 // 175 ¯ MACRON -#define ISO_8859_1_B0 KEY_4 + ALTGR_MASK // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN -#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT -#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA -#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE -#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE -#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE -#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE -#define ISO_8859_1_C6 0 // 198 Æ AE -#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA -#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE -#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE -#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS -#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE -#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE -#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 0 // 208 Ð ETH -#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE -#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE -#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE -#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE -#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION -#define ISO_8859_1_D8 0 // 216 Ø O STROKE -#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE -#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE -#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS -#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE -#define ISO_8859_1_DE 0 // 222 Þ THORN -#define ISO_8859_1_DF 0 // 223 ß SHARP S -#define ISO_8859_1_E0 KEY_QUOTE + SHIFT_MASK // 224 à a GRAVE -#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE -#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE -#define ISO_8859_1_E4 KEY_QUOTE // 228 ä a DIAERESIS -#define ISO_8859_1_E5 0 // 229 å a RING ABOVE -#define ISO_8859_1_E6 0 // 230 æ ae -#define ISO_8859_1_E7 KEY_4 + SHIFT_MASK // 231 ç c CEDILLA -#define ISO_8859_1_E8 KEY_LEFT_BRACE + SHIFT_MASK // 232 è e GRAVE -#define ISO_8859_1_E9 KEY_SEMICOLON + SHIFT_MASK // 233 é e ACUTE -#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS TODO: check this -#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE -#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE -#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS -#define ISO_8859_1_F0 0 // 240 ð ETH -#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE -#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE -#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE -#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE -#define ISO_8859_1_F6 KEY_SEMICOLON // 246 ö o DIAERESIS -#define ISO_8859_1_F7 0 // 247 ÷ DIVISION -#define ISO_8859_1_F8 0 // 248 ø o STROKE -#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE -#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE -#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC KEY_LEFT_BRACE // 252 ü u DIAERESIS -#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE -#define ISO_8859_1_FE 0 // 254 þ THORN -#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS -#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign -// not yet implemented -#define UNICODE_EXTRA00 0x20AC -#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign - -#endif // LAYOUT_GERMAN_SWISS - - - - -#ifdef LAYOUT_FRENCH_SWISS - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define DEADKEYS_MASK 0x0700 -#define CIRCUMFLEX_BITS 0x0100 -#define GRAVE_ACCENT_BITS 0x0200 -#define DIAERESIS_BITS 0x0300 -#define TILDE_BITS 0x0400 -#define ACUTE_ACCENT_BITS 0x0500 -#define KEYCODE_TYPE uint16_t -#define DEADKEY_CIRCUMFLEX KEY_EQUAL -#define DEADKEY_ACUTE_ACCENT KEY_MINUS + ALTGR_MASK -#define DEADKEY_GRAVE_ACCENT KEY_EQUAL + SHIFT_MASK -#define DEADKEY_DIAERESIS KEY_RIGHT_BRACE -#define DEADKEY_TILDE KEY_EQUAL + ALTGR_MASK -#define KEY_NON_US_100 63 - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_RIGHT_BRACE + SHIFT_MASK // 33 ! -#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " -#define ASCII_23 KEY_3 + ALTGR_MASK // 35 # -#define ASCII_24 KEY_BACKSLASH // 36 $ -#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % -#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & -#define ASCII_27 KEY_MINUS // 39 ' -#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) -#define ASCII_2A KEY_3 + SHIFT_MASK // 42 * -#define ASCII_2B KEY_1 + SHIFT_MASK // 43 + -#define ASCII_2C KEY_COMMA // 44 , -#define ASCII_2D KEY_SLASH // 45 - -#define ASCII_2E KEY_PERIOD // 46 . -#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / -#define ASCII_30 KEY_0 // 48 0 -#define ASCII_31 KEY_1 // 49 1 -#define ASCII_32 KEY_2 // 50 2 -#define ASCII_33 KEY_3 // 51 3 -#define ASCII_34 KEY_4 // 52 4 -#define ASCII_35 KEY_5 // 53 5 -#define ASCII_36 KEY_6 // 54 6 -#define ASCII_37 KEY_7 // 55 7 -#define ASCII_38 KEY_8 // 55 8 -#define ASCII_39 KEY_9 // 57 9 -#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : -#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; -#define ASCII_3C KEY_NON_US_100 // 60 < -#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = -#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > -#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_2 + ALTGR_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Z + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Y + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_LEFT_BRACE + ALTGR_MASK // 91 [ -#define ASCII_5C KEY_NON_US_100 + ALTGR_MASK // 92 -#define ASCII_5D KEY_RIGHT_BRACE + ALTGR_MASK // 93 ] -#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ -#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ -#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Z // 121 y -#define ASCII_7A KEY_Y // 122 z -#define ASCII_7B KEY_QUOTE + ALTGR_MASK // 123 { -#define ASCII_7C KEY_7 + ALTGR_MASK // 124 | -#define ASCII_7D KEY_BACKSLASH + ALTGR_MASK // 125 } -#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 -#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space -#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 KEY_8 + ALTGR_MASK // 162 ¢ Cent Sign -#define ISO_8859_1_A3 KEY_BACKSLASH + SHIFT_MASK // 163 £ Pound Sign -#define ISO_8859_1_A4 0 // 164 ¤ Currency Sign -#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 KEY_1 + ALTGR_MASK // 166 ¦ BROKEN BAR -#define ISO_8859_1_A7 KEY_5 + ALTGR_MASK // 167 § SECTION SIGN -#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC KEY_6 + ALTGR_MASK // 172 ¬ NOT SIGN -#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN -#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF 0 // 175 ¯ MACRON -#define ISO_8859_1_B0 KEY_4 + ALTGR_MASK // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN -#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT -#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA -#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE -#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE -#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE -#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE -#define ISO_8859_1_C6 0 // 198 Æ AE -#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA -#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE -#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE -#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS -#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE -#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE -#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 0 // 208 Ð ETH -#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE -#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE -#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE -#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE -#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION -#define ISO_8859_1_D8 0 // 216 Ø O STROKE -#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE -#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE -#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS -#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE -#define ISO_8859_1_DE 0 // 222 Þ THORN -#define ISO_8859_1_DF 0 // 223 ß SHARP S -#define ISO_8859_1_E0 KEY_QUOTE // 224 à a GRAVE -#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE -#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE -#define ISO_8859_1_E4 KEY_QUOTE + SHIFT_MASK // 228 ä a DIAERESIS -#define ISO_8859_1_E5 0 // 229 å a RING ABOVE -#define ISO_8859_1_E6 0 // 230 æ ae -#define ISO_8859_1_E7 KEY_4 + SHIFT_MASK // 231 ç c CEDILLA -#define ISO_8859_1_E8 KEY_LEFT_BRACE // 232 è e GRAVE -#define ISO_8859_1_E9 KEY_SEMICOLON // 233 é e ACUTE -#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS -#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE -#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE -#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS -#define ISO_8859_1_F0 0 // 240 ð ETH -#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE -#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE -#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE -#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE -#define ISO_8859_1_F6 KEY_SEMICOLON + SHIFT_MASK // 246 ö o DIAERESIS -#define ISO_8859_1_F7 0 // 247 ÷ DIVISION -#define ISO_8859_1_F8 0 // 248 ø o STROKE -#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE -#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE -#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC KEY_LEFT_BRACE + SHIFT_MASK // 252 ü u DIAERESIS -#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE -#define ISO_8859_1_FE 0 // 254 þ THORN -#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS -#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign -// not yet implemented -#define UNICODE_EXTRA00 0x20AC -#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign - -#endif // LAYOUT_FRENCH_SWISS - - - - - -#ifdef LAYOUT_SPANISH_LATIN_AMERICA - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define DEADKEYS_MASK 0x0700 -#define CIRCUMFLEX_BITS 0x0100 -#define ACUTE_ACCENT_BITS 0x0200 -#define GRAVE_ACCENT_BITS 0x0300 -#define DIAERESIS_BITS 0x0400 -#define KEYCODE_TYPE uint16_t -#define DEADKEY_CIRCUMFLEX KEY_QUOTE + ALTGR_MASK -#define DEADKEY_ACUTE_ACCENT KEY_LEFT_BRACE -#define DEADKEY_GRAVE_ACCENT KEY_BACKSLASH + ALTGR_MASK -#define DEADKEY_DIAERESIS KEY_LEFT_BRACE + SHIFT_MASK -#define KEY_NON_US_100 63 - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! -#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " -#define ASCII_23 KEY_3 + ALTGR_MASK // 35 # -#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ -#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % -#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & -#define ASCII_27 KEY_MINUS // 39 ' -#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) -#define ASCII_2A KEY_RIGHT_BRACE + SHIFT_MASK // 42 * -#define ASCII_2B KEY_RIGHT_BRACE // 43 + -#define ASCII_2C KEY_COMMA // 44 , -#define ASCII_2D KEY_SLASH // 45 - -#define ASCII_2E KEY_PERIOD // 46 . -#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / -#define ASCII_30 KEY_0 // 48 0 -#define ASCII_31 KEY_1 // 49 1 -#define ASCII_32 KEY_2 // 50 2 -#define ASCII_33 KEY_3 // 51 3 -#define ASCII_34 KEY_4 // 52 4 -#define ASCII_35 KEY_5 // 53 5 -#define ASCII_36 KEY_6 // 54 6 -#define ASCII_37 KEY_7 // 55 7 -#define ASCII_38 KEY_8 // 55 8 -#define ASCII_39 KEY_9 // 57 9 -#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : -#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; -#define ASCII_3C KEY_NON_US_100 // 60 < -#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = -#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > -#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_Q + ALTGR_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_QUOTE + SHIFT_MASK // 91 [ -#define ASCII_5C KEY_MINUS + ALTGR_MASK // 92 -#define ASCII_5D KEY_BACKSLASH + SHIFT_MASK // 93 ] -#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ -#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ -#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Y // 121 y -#define ASCII_7A KEY_Z // 122 z -#define ASCII_7B KEY_QUOTE // 123 { -#define ASCII_7C KEY_TILDE // 124 | -#define ASCII_7D KEY_BACKSLASH // 125 } -#define ASCII_7E KEY_RIGHT_BRACE + ALTGR_MASK // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 - -#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space -#define ISO_8859_1_A1 KEY_EQUAL + SHIFT_MASK // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN -#define ISO_8859_1_A3 0 // 163 £ Pound Sign -#define ISO_8859_1_A4 0 // 164 ¤ Currency Sign -#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR -#define ISO_8859_1_A7 0 // 167 § SECTION SIGN -#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC KEY_TILDE + ALTGR_MASK // 172 ¬ NOT SIGN -#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN -#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF 0 // 175 ¯ MACRON -#define ISO_8859_1_B0 KEY_TILDE + SHIFT_MASK // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN -#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT -#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA -#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF KEY_EQUAL // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE -#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE -#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 0 // 195 Ã A TILDE -#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE -#define ISO_8859_1_C6 0 // 198 Æ AE -#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA -#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE -#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE -#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS -#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE -#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE -#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 0 // 208 Ð ETH -#define ISO_8859_1_D1 KEY_SEMICOLON + SHIFT_MASK // 209 Ñ N TILDE -#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE -#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE -#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 0 // 213 Õ O TILDE -#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION -#define ISO_8859_1_D8 0 // 216 Ø O STROKE -#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE -#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE -#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS -#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE -#define ISO_8859_1_DE 0 // 222 Þ THORN -#define ISO_8859_1_DF 0 // 223 ß SHARP S -#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE -#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE -#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 0 // 227 ã a TILDE -#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS -#define ISO_8859_1_E5 0 // 229 å a RING ABOVE -#define ISO_8859_1_E6 0 // 230 æ ae -#define ISO_8859_1_E7 0 // 231 ç c CEDILLA -#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE -#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE -#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS -#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE -#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE -#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS -#define ISO_8859_1_F0 0 // 240 ð ETH -#define ISO_8859_1_F1 KEY_SEMICOLON // 241 ñ n TILDE -#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE -#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE -#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 0 // 245 õ o TILDE -#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS -#define ISO_8859_1_F7 0 // 247 ÷ DIVISION -#define ISO_8859_1_F8 0 // 248 ø o STROKE -#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE -#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE -#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS -#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE -#define ISO_8859_1_FE 0 // 254 þ THORN -#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS - -#endif // LAYOUT_SPANISH_LATIN_AMERICA - - - -#ifdef LAYOUT_IRISH - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define DEADKEYS_MASK 0x0300 -#define GRAVE_ACCENT_BITS 0x0100 -#define ACUTE_ACCENT_BITS 0x0200 -#define KEYCODE_TYPE uint16_t -#define DEADKEY_ACUTE_ACCENT KEY_QUOTE + ALTGR_MASK -#define DEADKEY_GRAVE_ACCENT KEY_TILDE -#define KEY_NON_US_100 63 - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! -#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " -#define ASCII_23 KEY_BACKSPACE // 35 # -#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ -#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % -#define ASCII_26 KEY_7 + SHIFT_MASK // 38 & -#define ASCII_27 KEY_QUOTE // 39 ' -#define ASCII_28 KEY_9 + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_0 + SHIFT_MASK // 41 ) -#define ASCII_2A KEY_8 + SHIFT_MASK // 42 * -#define ASCII_2B KEY_EQUAL + SHIFT_MASK // 43 + -#define ASCII_2C KEY_COMMA // 44 , -#define ASCII_2D KEY_MINUS // 45 - -#define ASCII_2E KEY_PERIOD // 46 . -#define ASCII_2F KEY_SLASH // 47 / -#define ASCII_30 KEY_0 // 48 0 -#define ASCII_31 KEY_1 // 49 1 -#define ASCII_32 KEY_2 // 50 2 -#define ASCII_33 KEY_3 // 51 3 -#define ASCII_34 KEY_4 // 52 4 -#define ASCII_35 KEY_5 // 53 5 -#define ASCII_36 KEY_6 // 54 6 -#define ASCII_37 KEY_7 // 55 7 -#define ASCII_38 KEY_8 // 55 8 -#define ASCII_39 KEY_9 // 57 9 -#define ASCII_3A KEY_SEMICOLON + SHIFT_MASK // 58 : -#define ASCII_3B KEY_SEMICOLON // 59 ; -#define ASCII_3C KEY_COMMA + SHIFT_MASK // 60 < -#define ASCII_3D KEY_EQUAL // 61 = -#define ASCII_3E KEY_PERIOD + SHIFT_MASK // 62 > -#define ASCII_3F KEY_SLASH + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_QUOTE + SHIFT_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_LEFT_BRACE // 91 [ -#define ASCII_5C KEY_NON_US_100 // 92 -#define ASCII_5D KEY_RIGHT_BRACE // 93 ] -#define ASCII_5E KEY_6 + SHIFT_MASK // 94 ^ -#define ASCII_5F KEY_MINUS + SHIFT_MASK // 95 _ -#define ASCII_60 KEY_QUOTE + SHIFT_MASK + ALTGR_MASK // 96 ` -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Y // 121 y -#define ASCII_7A KEY_Z // 122 z -#define ASCII_7B KEY_LEFT_BRACE + SHIFT_MASK // 123 { -#define ASCII_7C KEY_NON_US_100 + SHIFT_MASK // 124 | -#define ASCII_7D KEY_RIGHT_BRACE + SHIFT_MASK // 125 } -#define ASCII_7E KEY_BACKSLASH + SHIFT_MASK // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 - -#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space -#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN -#define ISO_8859_1_A3 KEY_3 + SHIFT_MASK // 163 £ Pound Sign -#define ISO_8859_1_A4 0 // 164 ¤ Currency or Euro Sign -#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 KEY_TILDE + ALTGR_MASK // 166 ¦ BROKEN BAR -#define ISO_8859_1_A7 0 // 167 § SECTION SIGN -#define ISO_8859_1_A8 0 // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC KEY_TILDE + SHIFT_MASK // 172 ¬ NOT SIGN -#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN -#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF 0 // 175 ¯ MACRON -#define ISO_8859_1_B0 0 // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 0 // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN -#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT -#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA -#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A // 192 À A GRAVE -#define ISO_8859_1_C1 KEY_A + ALTGR_MASK + SHIFT_MASK // 193 Á A ACUTE -#define ISO_8859_1_C2 0 // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 0 // 195 Ã A TILDE -#define ISO_8859_1_C4 0 // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE -#define ISO_8859_1_C6 0 // 198 Æ AE -#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA -#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E // 200 È E GRAVE -#define ISO_8859_1_C9 KEY_E + ALTGR_MASK + SHIFT_MASK // 201 É E ACUTE -#define ISO_8859_1_CA 0 // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB 0 // 203 Ë E DIAERESIS -#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I // 204 Ì I GRAVE -#define ISO_8859_1_CD KEY_I + ALTGR_MASK + SHIFT_MASK // 205 Í I ACUTE -#define ISO_8859_1_CE 0 // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF 0 // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 0 // 208 Ð ETH -#define ISO_8859_1_D1 0 // 209 Ñ N TILDE -#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O // 210 Ò O GRAVE -#define ISO_8859_1_D3 KEY_O + ALTGR_MASK + SHIFT_MASK // 211 Ó O ACUTE -#define ISO_8859_1_D4 0 // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 0 // 213 Õ O TILDE -#define ISO_8859_1_D6 0 // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION -#define ISO_8859_1_D8 0 // 216 Ø O STROKE -#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U // 217 Ù U GRAVE -#define ISO_8859_1_DA KEY_U + ALTGR_MASK + SHIFT_MASK // 218 Ú U ACUTE -#define ISO_8859_1_DB 0 // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC 0 // 220 Ü U DIAERESIS -#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE -#define ISO_8859_1_DE 0 // 222 Þ THORN -#define ISO_8859_1_DF 0 // 223 ß SHARP S -#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE -#define ISO_8859_1_E1 KEY_A + ALTGR_MASK // 225 á a ACUTE -#define ISO_8859_1_E2 0 // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 0 // 227 ã a TILDE -#define ISO_8859_1_E4 0 // 228 ä a DIAERESIS -#define ISO_8859_1_E5 0 // 229 å a RING ABOVE -#define ISO_8859_1_E6 0 // 230 æ ae -#define ISO_8859_1_E7 0 // 231 ç c CEDILLA -#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE -#define ISO_8859_1_E9 KEY_E + ALTGR_MASK // 233 é e ACUTE -#define ISO_8859_1_EA 0 // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB 0 // 235 ë e DIAERESIS -#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE -#define ISO_8859_1_ED KEY_I + ALTGR_MASK // 237 í i ACUTE -#define ISO_8859_1_EE 0 // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF 0 // 239 ï i DIAERESIS -#define ISO_8859_1_F0 0 // 240 ð ETH -#define ISO_8859_1_F1 0 // 241 ñ n TILDE -#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE -#define ISO_8859_1_F3 KEY_O + ALTGR_MASK // 243 ó o ACUTE -#define ISO_8859_1_F4 0 // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 0 // 245 õ o TILDE -#define ISO_8859_1_F6 0 // 246 ö o DIAERESIS -#define ISO_8859_1_F7 0 // 247 ÷ DIVISION -#define ISO_8859_1_F8 0 // 248 ø o STROKE -#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE -#define ISO_8859_1_FA KEY_U + ALTGR_MASK // 250 ú u ACUTE -#define ISO_8859_1_FB 0 // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC 0 // 252 ü u DIAERESIS -#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE -#define ISO_8859_1_FE 0 // 254 þ THORN -#define ISO_8859_1_FF 0 // 255 ÿ y DIAERESIS -#define UNICODE_20AC KEY_4 + ALTGR_MASK // € Euro Sign -// not yet implemented -#define UNICODE_EXTRA00 0x20AC -#define KEYCODE_EXTRA00 KEY_4 + ALTGR_MASK // 20AC € Euro Sign - -#endif // LAYOUT_IRISH - - - - -#ifdef LAYOUT_ICELANDIC - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define DEADKEYS_MASK 0x0700 -#define CIRCUMFLEX_BITS 0x0100 -#define ACUTE_ACCENT_BITS 0x0200 -#define GRAVE_ACCENT_BITS 0x0300 -#define DIAERESIS_BITS 0x0400 -#define RING_ABOVE_BITS 0x0500 -#define KEYCODE_TYPE uint16_t -#define DEADKEY_CIRCUMFLEX KEY_QUOTE + ALTGR_MASK -#define DEADKEY_ACUTE_ACCENT KEY_QUOTE -#define DEADKEY_GRAVE_ACCENT KEY_BACKSLASH + ALTGR_MASK -#define DEADKEY_DIAERESIS KEY_TILDE + SHIFT_MASK -#define DEADKEY_RING_ABOVE KEY_TILDE -#define KEY_NON_US_100 63 - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! -#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " -#define ASCII_23 KEY_3 + SHIFT_MASK // 35 # -#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $ -#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % -#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & -#define ASCII_27 KEY_QUOTE + SHIFT_MASK // 39 ' -#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) -#define ASCII_2A KEY_BACKSLASH + SHIFT_MASK // 42 * -#define ASCII_2B KEY_BACKSLASH // 43 + -#define ASCII_2C KEY_COMMA // 44 , -#define ASCII_2D KEY_EQUAL // 45 - -#define ASCII_2E KEY_PERIOD // 46 . -#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / -#define ASCII_30 KEY_0 // 48 0 -#define ASCII_31 KEY_1 // 49 1 -#define ASCII_32 KEY_2 // 50 2 -#define ASCII_33 KEY_3 // 51 3 -#define ASCII_34 KEY_4 // 52 4 -#define ASCII_35 KEY_5 // 53 5 -#define ASCII_36 KEY_6 // 54 6 -#define ASCII_37 KEY_7 // 55 7 -#define ASCII_38 KEY_8 // 55 8 -#define ASCII_39 KEY_9 // 57 9 -#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : -#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ; -#define ASCII_3C KEY_NON_US_100 // 60 < -#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = -#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 > -#define ASCII_3F KEY_RIGHT_BRACE + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_Q + ALTGR_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_8 + ALTGR_MASK // 91 [ -#define ASCII_5C KEY_MINUS + ALTGR_MASK // 92 -#define ASCII_5D KEY_9 + ALTGR_MASK // 93 ] -#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ -#define ASCII_5F KEY_EQUAL + SHIFT_MASK // 95 _ -#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Y // 121 y -#define ASCII_7A KEY_Z // 122 z -#define ASCII_7B KEY_7 + ALTGR_MASK // 123 { -#define ASCII_7C KEY_NON_US_100 + ALTGR_MASK // 124 | -#define ASCII_7D KEY_0 + ALTGR_MASK // 125 } -#define ASCII_7E KEY_RIGHT_BRACE + ALTGR_MASK // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 - -#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space -#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN -#define ISO_8859_1_A3 0 // 163 £ Pound Sign -#define ISO_8859_1_A4 0 // 164 ¤ Currency or Euro Sign -#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR ?? -#define ISO_8859_1_A7 0 // 167 § SECTION SIGN -#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN ?? -#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN -#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF 0 // 175 ¯ MACRON -#define ISO_8859_1_B0 KEY_TILDE + ALTGR_MASK // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 KEY_M + ALTGR_MASK // 181 µ MICRO SIGN -#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT -#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA -#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE -#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + ALTGR_MASK // 193 Á A ACUTE -#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 0 // 195 Ã A TILDE -#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 RING_ABOVE_BITS + KEY_A + SHIFT_MASK // 197 Å A RING ABOVE -#define ISO_8859_1_C6 KEY_SEMICOLON + SHIFT_MASK // 198 Æ AE -#define ISO_8859_1_C7 0 // 199 Ç C CEDILLA -#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE -#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE -#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS -#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE -#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE -#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 KEY_LEFT_BRACE + SHIFT_MASK // 208 Ð ETH -#define ISO_8859_1_D1 0 // 209 Ñ N TILDE -#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE -#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE -#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 0 // 213 Õ O TILDE -#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION -#define ISO_8859_1_D8 0 // 216 Ø O STROKE -#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE -#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE -#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS -#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE -#define ISO_8859_1_DE KEY_SLASH + SHIFT_MASK // 222 Þ THORN -#define ISO_8859_1_DF 0 // 223 ß SHARP S -#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE -#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE -#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 0 // 227 ã a TILDE -#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS -#define ISO_8859_1_E5 RING_ABOVE_BITS + KEY_A // 229 å a RING ABOVE -#define ISO_8859_1_E6 KEY_SEMICOLON // 230 æ ae -#define ISO_8859_1_E7 0 // 231 ç c CEDILLA -#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE -#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE -#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS -#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE -#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE -#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS -#define ISO_8859_1_F0 KEY_LEFT_BRACE // 240 ð ETH -#define ISO_8859_1_F1 0 // 241 ñ n TILDE -#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE -#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE -#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 0 // 245 õ o TILDE -#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS -#define ISO_8859_1_F7 0 // 247 ÷ DIVISION -#define ISO_8859_1_F8 0 // 248 ø o STROKE -#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE -#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE -#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS -#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE -#define ISO_8859_1_FE KEY_SLASH // 254 þ THORN -#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS -#define UNICODE_20AC KEY_5 + ALTGR_MASK // € Euro Sign -// not yet implemented -#define UNICODE_EXTRA00 0x20AC -#define KEYCODE_EXTRA00 KEY_5 + ALTGR_MASK // 20AC € Euro Sign - -#endif // LAYOUT_ICELANDIC - - - -#ifdef LAYOUT_TURKISH -// http://forum.pjrc.com/threads/18781-Turkish-Language-Support - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define DEADKEYS_MASK 0x0700 -#define CIRCUMFLEX_BITS 0x0100 -#define ACUTE_ACCENT_BITS 0x0200 -#define GRAVE_ACCENT_BITS 0x0300 -#define TILDE_BITS 0x0400 -#define DIAERESIS_BITS 0x0500 -#define KEYCODE_TYPE uint16_t -#define DEADKEY_CIRCUMFLEX KEY_3 + SHIFT_MASK -#define DEADKEY_ACUTE_ACCENT KEY_SEMICOLON + ALTGR_MASK -#define DEADKEY_GRAVE_ACCENT KEY_BACKSLASH + ALTGR_MASK -#define DEADKEY_TILDE KEY_RIGHT_BRACE + ALTGR_MASK -#define DEADKEY_DIAERESIS KEY_LEFT_BRACE + ALTGR_MASK - -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! -#define ASCII_22 KEY_TILDE // 34 " -#define ASCII_23 KEY_3 + ALTGR_MASK // 35 # -#define ASCII_24 KEY_4 + ALTGR_MASK // 36 $ -#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % -#define ASCII_26 KEY_6 + SHIFT_MASK // 38 & -#define ASCII_27 KEY_2 + SHIFT_MASK // 39 ' -#define ASCII_28 KEY_8 + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_9 + SHIFT_MASK // 41 ) -#define ASCII_2A KEY_MINUS // 42 * -#define ASCII_2B KEY_4 + SHIFT_MASK // 43 + -#define ASCII_2C KEY_BACKSLASH // 44 , -#define ASCII_2D KEY_EQUAL // 45 - -#define ASCII_2E KEY_SLASH // 46 . -#define ASCII_2F KEY_7 + SHIFT_MASK // 47 / -#define ASCII_30 KEY_0 // 48 0 -#define ASCII_31 KEY_1 // 49 1 -#define ASCII_32 KEY_2 // 50 2 -#define ASCII_33 KEY_3 // 51 3 -#define ASCII_34 KEY_4 // 52 4 -#define ASCII_35 KEY_5 // 53 5 -#define ASCII_36 KEY_6 // 54 6 -#define ASCII_37 KEY_7 // 55 7 -#define ASCII_38 KEY_8 // 55 8 -#define ASCII_39 KEY_9 // 57 9 -#define ASCII_3A KEY_SLASH + SHIFT_MASK // 58 : -#define ASCII_3B KEY_BACKSLASH + SHIFT_MASK // 59 ; -#define ASCII_3C KEY_TILDE + ALTGR_MASK // 60 < -#define ASCII_3D KEY_0 + SHIFT_MASK // 61 = -#define ASCII_3E KEY_1 + ALTGR_MASK // 62 > -#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_Q + ALTGR_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Y + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Z + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_8 + ALTGR_MASK // 91 [ -#define ASCII_5C KEY_MINUS + ALTGR_MASK // 92 -#define ASCII_5D KEY_9 + ALTGR_MASK // 93 ] -#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^ -#define ASCII_5F KEY_EQUAL + SHIFT_MASK // 95 _ -#define ASCII_60 GRAVE_ACCENT_BITS + KEY_SPACE // 96 ` -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_QUOTE // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Y // 121 y -#define ASCII_7A KEY_Z // 122 z -#define ASCII_7B KEY_7 + ALTGR_MASK // 123 { -#define ASCII_7C KEY_EQUAL + ALTGR_MASK // 124 | -#define ASCII_7D KEY_0 + ALTGR_MASK // 125 } -#define ASCII_7E TILDE_BITS + KEY_SPACE // 126 ~ -#define ASCII_7F KEY_BACKSPACE // 127 - -#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space -#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 0 // 162 ¢ Cent SIGN -#define ISO_8859_1_A3 KEY_2 + ALTGR_MASK // 163 £ Pound Sign -#define ISO_8859_1_A4 0 // 164 ¤ Currency or Euro Sign -#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR ?? -#define ISO_8859_1_A7 0 // 167 § SECTION SIGN -#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN ?? -#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN -#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF 0 // 175 ¯ MACRON -#define ISO_8859_1_B0 0 // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN -#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT -#define ISO_8859_1_B8 0 // 184 ¸ CEDILLA -#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD KEY_5 + ALTGR_MASK // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK // 192 À A GRAVE -#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE -#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 TILDE_BITS + KEY_A + SHIFT_MASK // 195 Ã A TILDE -#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE -#define ISO_8859_1_C6 KEY_A + ALTGR_MASK // 198 Æ AE -#define ISO_8859_1_C7 KEY_PERIOD + SHIFT_MASK // 199 Ç C CEDILLA -#define ISO_8859_1_C8 GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK // 200 È E GRAVE -#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE -#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS -#define ISO_8859_1_CC GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK // 204 Ì I GRAVE -#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE -#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 0 // 208 Ð ETH -#define ISO_8859_1_D1 TILDE_BITS + KEY_N + SHIFT_MASK // 209 Ñ N TILDE -#define ISO_8859_1_D2 GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK // 210 Ò O GRAVE -#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE -#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 TILDE_BITS + KEY_O + SHIFT_MASK // 213 Õ O TILDE -#define ISO_8859_1_D6 KEY_COMMA + SHIFT_MASK // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 0 // 215 × MULTIPLICATION -#define ISO_8859_1_D8 0 // 216 Ø O STROKE -#define ISO_8859_1_D9 GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK // 217 Ù U GRAVE -#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE -#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC KEY_RIGHT_BRACE + SHIFT_MASK // 220 Ü U DIAERESIS -#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK // 221 Ý Y ACUTE -#define ISO_8859_1_DE 0 // 222 Þ THORN -#define ISO_8859_1_DF KEY_S + ALTGR_MASK // 223 ß SHARP S -#define ISO_8859_1_E0 GRAVE_ACCENT_BITS + KEY_A // 224 à a GRAVE -#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE -#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 TILDE_BITS + KEY_A // 227 ã a TILDE -#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS -#define ISO_8859_1_E5 0 // 229 å a RING ABOVE -#define ISO_8859_1_E6 0 // 230 æ ae -#define ISO_8859_1_E7 KEY_PERIOD // 231 ç c CEDILLA -#define ISO_8859_1_E8 GRAVE_ACCENT_BITS + KEY_E // 232 è e GRAVE -#define ISO_8859_1_E9 KEY_TILDE + SHIFT_MASK // 233 é e ACUTE -#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS -#define ISO_8859_1_EC GRAVE_ACCENT_BITS + KEY_I // 236 ì i GRAVE -#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE -#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS -#define ISO_8859_1_F0 0 // 240 ð ETH -#define ISO_8859_1_F1 TILDE_BITS + KEY_N // 241 ñ n TILDE -#define ISO_8859_1_F2 GRAVE_ACCENT_BITS + KEY_O // 242 ò o GRAVE -#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE -#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 TILDE_BITS + KEY_O // 245 õ o TILDE -#define ISO_8859_1_F6 KEY_COMMA // 246 ö o DIAERESIS -#define ISO_8859_1_F7 0 // 247 ÷ DIVISION -#define ISO_8859_1_F8 0 // 248 ø o STROKE -#define ISO_8859_1_F9 GRAVE_ACCENT_BITS + KEY_U // 249 ù u GRAVE -#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE -#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC KEY_RIGHT_BRACE // 252 ü u DIAERESIS -#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Y // 253 ý y ACUTE -#define ISO_8859_1_FE 0 // 254 þ THORN -#define ISO_8859_1_FF DIAERESIS_BITS + KEY_Y // 255 ÿ y DIAERESIS -#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign - -// not yet implemented -#define UNICODE_EXTRA00 0x20AC -#define KEYCODE_EXTRA00 KEY_E + ALTGR_MASK // 20AC € Euro Sign -#define UNICODE_EXTRA01 0x011E -#define KEYCODE_EXTRA01 KEY_LEFT_BRACE + SHIFT_MASK // 011E Ğ Latin capital letter G with breve -#define UNICODE_EXTRA02 0x011F -#define KEYCODE_EXTRA02 KEY_LEFT_BRACE // 011F ğ Latin small letter g with breve -#define UNICODE_EXTRA03 0x0130 -#define KEYCODE_EXTRA03 KEY_QUOTE + SHIFT_MASK // 0130 İ Latin captial letter I with dot above -#define UNICODE_EXTRA04 0x0131 -#define KEYCODE_EXTRA04 KEY_I // 0131 ı Latin small letter dotless i -#define UNICODE_EXTRA05 0x015E -#define KEYCODE_EXTRA05 KEY_SEMICOLON + SHIFT_MASK // 015E Ş Latin capital letter S with cedilla -#define UNICODE_EXTRA06 0x0151 -#define KEYCODE_EXTRA06 KEY_SEMICOLON // 0151 ş Latin small letter s with cedilla - -#endif // LAYOUT_TURKISH - - - -#ifdef LAYOUT_CZECH -// http://forum.pjrc.com/threads/24495-Czech-keyboard - -#define SHIFT_MASK 0x0040 -#define ALTGR_MASK 0x0080 -#define DEADKEYS_MASK 0x0F00 -#define ACUTE_ACCENT_BITS 0x0100 // TODO: the Czech might not support some -#define DEGREE_SIGN_BITS 0x0200 // of these deadkeys, perhaps not any??? -#define CARON_BITS 0x0300 -//#define CIRCUMFLEX_BITS 0x0400 -#define BREVE_BITS 0x0500 -#define OGONEK_BITS 0x0600 -//#define GRAVE_ACCENT_BITS 0x0700 -#define DOT_ABOVE_BITS 0x0800 -#define DOUBLE_ACUTE_BITS 0x0900 -//#define DIAERESIS_BITS 0x0A00 -#define CEDILLA_BITS 0x0B00 -#define KEYCODE_TYPE uint16_t -#define DEADKEY_ACUTE_ACCENT KEY_EQUAL // TODO: is it KEY_9 + ALTGR_MASK -#define DEADKEY_DEGREE_SIGN KEY_TILDE + SHIFT_MASK // TODO: is it KEY_5 + ALTGR_MASK -#define DEADKEY_CARON KEY_EQUAL + SHIFT_MASK // TODO: is it KEY_2 + ALTGR_MASK -//#define DEADKEY_CIRCUMFLEX KEY_3 + ALTGR_MASK -#define DEADKEY_BREVE KEY_4 + ALTGR_MASK -#define DEADKEY_OGONEK KEY_6 + ALTGR_MASK -//#define DEADKEY_GRAVE_ACCENT KEY_7 + ALTGR_MASK -#define DEADKEY_DOT_ABOVE KEY_8 + ALTGR_MASK -#define DEADKEY_DOUBLE_ACUTE KEY_0 + ALTGR_MASK -#define DEADKEY_DIAERESIS KEY_MINUS + ALTGR_MASK -#define DEADKEY_CEDILLA KEY_EQUAL + ALTGR_MASK -#define KEY_NON_US_100 63 -#define ASCII_20 KEY_SPACE // 32 -#define ASCII_21 KEY_QUOTE + SHIFT_MASK // 33 ! -#define ASCII_22 KEY_SEMICOLON + SHIFT_MASK // 34 " -#define ASCII_23 KEY_X + ALTGR_MASK // 35 # -#define ASCII_24 KEY_SEMICOLON + ALTGR_MASK // 36 $ -#define ASCII_25 KEY_MINUS + SHIFT_MASK // 37 % -#define ASCII_26 KEY_C + ALTGR_MASK // 38 & -#define ASCII_27 KEY_BACKSLASH + SHIFT_MASK // 39 ' -#define ASCII_28 KEY_RIGHT_BRACE + SHIFT_MASK // 40 ( -#define ASCII_29 KEY_RIGHT_BRACE // 41 ) -#define ASCII_2A KEY_SLASH + ALTGR_MASK // 42 * -#define ASCII_2B KEY_1 // 43 + -#define ASCII_2C KEY_COMMA // 44 , -#define ASCII_2D KEY_SLASH // 45 - -#define ASCII_2E KEY_PERIOD // 46 . -#define ASCII_2F KEY_LEFT_BRACE + SHIFT_MASK // 47 / -#define ASCII_30 KEY_0 + SHIFT_MASK // 48 0 -#define ASCII_31 KEY_1 + SHIFT_MASK // 49 1 -#define ASCII_32 KEY_2 + SHIFT_MASK // 50 2 -#define ASCII_33 KEY_3 + SHIFT_MASK // 51 3 -#define ASCII_34 KEY_4 + SHIFT_MASK // 52 4 -#define ASCII_35 KEY_5 + SHIFT_MASK // 53 5 -#define ASCII_36 KEY_6 + SHIFT_MASK // 54 6 -#define ASCII_37 KEY_7 + SHIFT_MASK // 55 7 -#define ASCII_38 KEY_8 + SHIFT_MASK // 55 8 -#define ASCII_39 KEY_9 + SHIFT_MASK // 57 9 -#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 : -#define ASCII_3B KEY_TILDE // 59 ; -#define ASCII_3C KEY_COMMA + ALTGR_MASK // 60 < -#define ASCII_3D KEY_MINUS // 61 = -#define ASCII_3E KEY_PERIOD + ALTGR_MASK // 62 > -#define ASCII_3F KEY_COMMA + SHIFT_MASK // 63 ? -#define ASCII_40 KEY_V + ALTGR_MASK // 64 @ -#define ASCII_41 KEY_A + SHIFT_MASK // 65 A -#define ASCII_42 KEY_B + SHIFT_MASK // 66 B -#define ASCII_43 KEY_C + SHIFT_MASK // 67 C -#define ASCII_44 KEY_D + SHIFT_MASK // 68 D -#define ASCII_45 KEY_E + SHIFT_MASK // 69 E -#define ASCII_46 KEY_F + SHIFT_MASK // 70 F -#define ASCII_47 KEY_G + SHIFT_MASK // 71 G -#define ASCII_48 KEY_H + SHIFT_MASK // 72 H -#define ASCII_49 KEY_I + SHIFT_MASK // 73 I -#define ASCII_4A KEY_J + SHIFT_MASK // 74 J -#define ASCII_4B KEY_K + SHIFT_MASK // 75 K -#define ASCII_4C KEY_L + SHIFT_MASK // 76 L -#define ASCII_4D KEY_M + SHIFT_MASK // 77 M -#define ASCII_4E KEY_N + SHIFT_MASK // 78 N -#define ASCII_4F KEY_O + SHIFT_MASK // 79 O -#define ASCII_50 KEY_P + SHIFT_MASK // 80 P -#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q -#define ASCII_52 KEY_R + SHIFT_MASK // 82 R -#define ASCII_53 KEY_S + SHIFT_MASK // 83 S -#define ASCII_54 KEY_T + SHIFT_MASK // 84 T -#define ASCII_55 KEY_U + SHIFT_MASK // 85 U -#define ASCII_56 KEY_V + SHIFT_MASK // 86 V -#define ASCII_57 KEY_W + SHIFT_MASK // 87 W -#define ASCII_58 KEY_X + SHIFT_MASK // 88 X -#define ASCII_59 KEY_Z + SHIFT_MASK // 89 Y -#define ASCII_5A KEY_Y + SHIFT_MASK // 90 Z -#define ASCII_5B KEY_F + ALTGR_MASK // 91 [ -#define ASCII_5C KEY_NON_US_100 // 92 -#define ASCII_5D KEY_G + ALTGR_MASK // 93 ] -#define ASCII_5E KEY_3 + ALTGR_MASK // 94 ^ TODO: testme -#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ -#define ASCII_60 KEY_7 + ALTGR_MASK // 96 ` TODO: testme -#define ASCII_61 KEY_A // 97 a -#define ASCII_62 KEY_B // 98 b -#define ASCII_63 KEY_C // 99 c -#define ASCII_64 KEY_D // 100 d -#define ASCII_65 KEY_E // 101 e -#define ASCII_66 KEY_F // 102 f -#define ASCII_67 KEY_G // 103 g -#define ASCII_68 KEY_H // 104 h -#define ASCII_69 KEY_I // 105 i -#define ASCII_6A KEY_J // 106 j -#define ASCII_6B KEY_K // 107 k -#define ASCII_6C KEY_L // 108 l -#define ASCII_6D KEY_M // 109 m -#define ASCII_6E KEY_N // 110 n -#define ASCII_6F KEY_O // 111 o -#define ASCII_70 KEY_P // 112 p -#define ASCII_71 KEY_Q // 113 q -#define ASCII_72 KEY_R // 114 r -#define ASCII_73 KEY_S // 115 s -#define ASCII_74 KEY_T // 116 t -#define ASCII_75 KEY_U // 117 u -#define ASCII_76 KEY_V // 118 v -#define ASCII_77 KEY_W // 119 w -#define ASCII_78 KEY_X // 120 x -#define ASCII_79 KEY_Z // 121 y -#define ASCII_7A KEY_Y // 122 z -#define ASCII_7B KEY_B + ALTGR_MASK // 123 { -#define ASCII_7C KEY_NON_US_100 + SHIFT_MASK // 124 | -#define ASCII_7D KEY_N + ALTGR_MASK // 125 } -#define ASCII_7E KEY_1 + ALTGR_MASK // 126 ~ TODO: fixme -#define ASCII_7F KEY_BACKSPACE // 127 -#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space -#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation -#define ISO_8859_1_A2 0 // 162 ¢ Cent Sign -#define ISO_8859_1_A3 0 // 163 £ Pound Sign -#define ISO_8859_1_A4 KEY_BACKSLASH + ALTGR_MASK // 164 ¤ Currency Sign -#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN -#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR -#define ISO_8859_1_A7 KEY_QUOTE // 167 § SECTION SIGN -#define ISO_8859_1_A8 0 // 168 ¨ DIAERESIS -#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN -#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL -#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE -#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN -#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN -#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN -#define ISO_8859_1_AF 0 // 175 ¯ MACRON -#define ISO_8859_1_B0 DEGREE_SIGN_BITS + KEY_SPACE // 176 ° DEGREE SIGN -#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN -#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO -#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE -#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT -#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN -#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN -#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT -#define ISO_8859_1_B8 CEDILLA_BITS + KEY_SPACE // 184 ¸ CEDILLA -#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE -#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL -#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE -#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER -#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF -#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS -#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK -#define ISO_8859_1_C0 0 // 192 À A GRAVE -#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE -#define ISO_8859_1_C2 0 // 194 Â A CIRCUMFLEX -#define ISO_8859_1_C3 0 // 195 Ã A TILDE -#define ISO_8859_1_C4 0 // 196 Ä A DIAERESIS -#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE -#define ISO_8859_1_C6 0 // 198 Æ AE -#define ISO_8859_1_C7 CEDILLA_BITS + KEY_C + SHIFT_MASK // 199 Ç C CEDILLA -#define ISO_8859_1_C8 0 // 200 È E GRAVE -#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE -#define ISO_8859_1_CA 0 // 202 Ê E CIRCUMFLEX -#define ISO_8859_1_CB 0 // 203 Ë E DIAERESIS -#define ISO_8859_1_CC 0 // 204 Ì I GRAVE -#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE -#define ISO_8859_1_CE 0 // 206 Î I CIRCUMFLEX -#define ISO_8859_1_CF 0 // 207 Ï I DIAERESIS -#define ISO_8859_1_D0 0 // 208 Ð ETH -#define ISO_8859_1_D1 0 // 209 Ñ N TILDE -#define ISO_8859_1_D2 0 // 210 Ò O GRAVE -#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE -#define ISO_8859_1_D4 0 // 212 Ô O CIRCUMFLEX -#define ISO_8859_1_D5 0 // 213 Õ O TILDE -#define ISO_8859_1_D6 0 // 214 Ö O DIAERESIS -#define ISO_8859_1_D7 KEY_RIGHT_BRACE + ALTGR_MASK // 215 × MULTIPLICATION -#define ISO_8859_1_D8 0 // 216 Ø O STROKE -#define ISO_8859_1_D9 0 // 217 Ù U GRAVE -#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE -#define ISO_8859_1_DB 0 // 219 Û U CIRCUMFLEX -#define ISO_8859_1_DC 0 // 220 Ü U DIAERESIS -#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Z + SHIFT_MASK // 221 Ý Y ACUTE -#define ISO_8859_1_DE 0 // 222 Þ THORN -#define ISO_8859_1_DF KEY_QUOTE + ALTGR_MASK // 223 ß SHARP S TODO: testme -#define ISO_8859_1_E0 0 // 224 à a GRAVE -#define ISO_8859_1_E1 KEY_8 // 225 á a ACUTE -#define ISO_8859_1_E2 0 // 226 â a CIRCUMFLEX -#define ISO_8859_1_E3 0 // 227 ã a TILDE -#define ISO_8859_1_E4 0 // 228 ä a DIAERESIS -#define ISO_8859_1_E5 0 // 229 å a RING ABOVE -#define ISO_8859_1_E6 0 // 230 æ ae -#define ISO_8859_1_E7 CEDILLA_BITS + KEY_C // 231 ç c CEDILLA -#define ISO_8859_1_E8 0 // 232 è e GRAVE -#define ISO_8859_1_E9 KEY_0 // 233 é e ACUTE -#define ISO_8859_1_EA 0 // 234 ê e CIRCUMFLEX -#define ISO_8859_1_EB 0 // 235 ë e DIAERESIS -#define ISO_8859_1_EC 0 // 236 ì i GRAVE -#define ISO_8859_1_ED KEY_9 // 237 í i ACUTE -#define ISO_8859_1_EE 0 // 238 î i CIRCUMFLEX -#define ISO_8859_1_EF 0 // 239 ï i DIAERESIS -#define ISO_8859_1_F0 0 // 240 ð ETH -#define ISO_8859_1_F1 0 // 241 ñ n TILDE -#define ISO_8859_1_F2 0 // 242 ò o GRAVE -#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE -#define ISO_8859_1_F4 0 // 244 ô o CIRCUMFLEX -#define ISO_8859_1_F5 0 // 245 õ o TILDE -#define ISO_8859_1_F6 0 // 246 ö o DIAERESIS -#define ISO_8859_1_F7 KEY_LEFT_BRACE + ALTGR_MASK // 247 ÷ DIVISION -#define ISO_8859_1_F8 0 // 248 ø o STROKE -#define ISO_8859_1_F9 0 // 249 ù u GRAVE -#define ISO_8859_1_FA KEY_LEFT_BRACE // 250 ú u ACUTE -#define ISO_8859_1_FB 0 // 251 û u CIRCUMFLEX -#define ISO_8859_1_FC 0 // 252 ü u DIAERESIS -#define ISO_8859_1_FD KEY_7 // 253 ý y ACUTE -#define ISO_8859_1_FE 0 // 254 þ THORN -#define ISO_8859_1_FF 0 // 255 ÿ y DIAERESIS -#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign - -#define UNICODE_EXTRA00 0x011B // ě Small Letter E with caron -#define KEYCODE_EXTRA00 KEY_2 -#define UNICODE_EXTRA01 0x0161 // š Small Letter S with caron -#define KEYCODE_EXTRA01 KEY_3 -#define UNICODE_EXTRA02 0x010D // č Small Letter C with caron -#define KEYCODE_EXTRA02 KEY_4 -#define UNICODE_EXTRA03 0x0159 // ř Small Letter R with caron -#define KEYCODE_EXTRA03 KEY_5 -#define UNICODE_EXTRA04 0x017E // ž Small Letter Z with caron -#define KEYCODE_EXTRA04 KEY_6 -#define UNICODE_EXTRA05 0x016F // ů Small Letter U with ring above -#define KEYCODE_EXTRA05 KEY_SEMICOLON -#define UNICODE_EXTRA06 0x0111 // đ Small Letter D with stroke -#define KEYCODE_EXTRA06 KEY_S + ALTGR_MASK -#define UNICODE_EXTRA07 0x0110 // Đ Capital Letter D with stroke -#define KEYCODE_EXTRA07 KEY_D + ALTGR_MASK -#define UNICODE_EXTRA08 0x0142 // ł Small Letter L with stroke -#define KEYCODE_EXTRA08 KEY_K + ALTGR_MASK -#define UNICODE_EXTRA09 0x0141 // Ł Capital Letter L with stroke -#define KEYCODE_EXTRA09 KEY_L + ALTGR_MASK -#define UNICODE_EXTRA0A 0x20AC // € Euro Sign -#define KEYCODE_EXTRA0A KEY_E + ALTGR_MASK - -#endif // LAYOUT_CZECH - - - - - - -extern const KEYCODE_TYPE keycodes_ascii[]; -extern const KEYCODE_TYPE keycodes_iso_8859_1[]; - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index 5393c3471c..506785bdff 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -35,6 +35,10 @@ THE SOFTWARE. #error HID Project can only be used with an USB MCU. #endif + + + + // Include all HID libraries (.a linkage required to work) properly #include "SingleReport/SingleAbsoluteMouse.h" #include "MultiReport/AbsoluteMouse.h" @@ -52,6 +56,3 @@ THE SOFTWARE. #include "SingleReport/SingleNKROKeyboard.h" #include "MultiReport/NKROKeyboard.h" -// Include Teensy HID afterwards to overwrite key definitions if used -// TODO include Teensy API if non english keyboard layout was used - diff --git a/plugins/KeyboardioHID/src/HID-Settings.h b/plugins/KeyboardioHID/src/HID-Settings.h index 29a5f1b141..4b908839c9 100644 --- a/plugins/KeyboardioHID/src/HID-Settings.h +++ b/plugins/KeyboardioHID/src/HID-Settings.h @@ -105,10 +105,6 @@ THE SOFTWARE. #define HID_REPORTID_NKRO_KEYBOARD 8 #endif -#ifndef HID_REPORTID_TEENSY_KEYBOARD -#define HID_REPORTID_TEENSY_KEYBOARD 9 -#endif - // Nico has submitted these definitions upstream, but they're not merged yet // HID Request Type HID1.11 Page 51 7.2.1 Get_Report Request From fa899cab489774e17d09645c50ba14c4e1b977c0 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Wed, 9 Dec 2015 13:17:03 -0800 Subject: [PATCH 342/602] Remove irrelevant image --- plugins/KeyboardioHID/header.jpg | Bin 150263 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 plugins/KeyboardioHID/header.jpg diff --git a/plugins/KeyboardioHID/header.jpg b/plugins/KeyboardioHID/header.jpg deleted file mode 100644 index d87032a640a9052d4cd80c2b450a8dc27659d8a1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 150263 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 JJ%|06_&>z+PgDQ^ From b21b42486a4d67639e137adfa60769117091eb6d Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Wed, 9 Dec 2015 13:18:49 -0800 Subject: [PATCH 343/602] Update library properties, so nobody bothers Nico with our version --- plugins/KeyboardioHID/library.properties | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/KeyboardioHID/library.properties b/plugins/KeyboardioHID/library.properties index 0dd202d31a..2aa38571b6 100644 --- a/plugins/KeyboardioHID/library.properties +++ b/plugins/KeyboardioHID/library.properties @@ -1,10 +1,10 @@ name=HID-Project -version=2.4.1 -author=NicoHood -maintainer=NicoHood -sentence=Extended HID Functions for Arduino -paragraph=Includes BootKeyboard/Mouse, Consumer, System, Gamepad, RawHID and more features. Also compatible with Arduino Uno/Mega via HoodLoader2. +version=0.0.1 +author=Jesse Vincent +maintainer=Jesse Vincent +sentence=HID Driver for keyboardio keyboards. +paragraph=Includes BootKeyboard/Mouse, Consumer, System, Gamepad, RawHID and more features. Based on Nico Hood's HID-Project category=Communication -url=https://github.com/NicoHood/HID +url=https://github.com/keyboardio/HID architectures=avr dot_a_linkage=true From 7aa817a45e889d80687ba0d43b47dfcf5680a6c1 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Wed, 9 Dec 2015 13:20:58 -0800 Subject: [PATCH 344/602] Remove the old stub support for alternative key layouts --- .../src/HID-APIs/ImprovedKeylayouts.h | 4 -- plugins/KeyboardioHID/src/HID-Settings.h | 45 ------------------- 2 files changed, 49 deletions(-) diff --git a/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h b/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h index 6c6f3e58a4..ee4854d7b5 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h +++ b/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h @@ -24,10 +24,6 @@ THE SOFTWARE. // Include guard #pragma once -#if !defined(LAYOUT_US_ENGLISH) -#error This API does not support non US english layouts. -#endif - // Hut1_12v2.pdf enum KeyboardKeycode : uint8_t { KEY_RESERVED = 0, diff --git a/plugins/KeyboardioHID/src/HID-Settings.h b/plugins/KeyboardioHID/src/HID-Settings.h index 4b908839c9..dcb16ae053 100644 --- a/plugins/KeyboardioHID/src/HID-Settings.h +++ b/plugins/KeyboardioHID/src/HID-Settings.h @@ -24,51 +24,6 @@ THE SOFTWARE. // Include guard #pragma once -//================================================================================ -// Settings -//================================================================================ - -//#define LAYOUT_US_ENGLISH -//#define LAYOUT_CANADIAN_FRENCH -//#define LAYOUT_CANADIAN_MULTILINGUAL -//#define LAYOUT_DANISH -//#define LAYOUT_FINNISH -//#define LAYOUT_FRENCH -//#define LAYOUT_FRENCH_BELGIAN -//#define LAYOUT_FRENCH_SWISS -//#define LAYOUT_GERMAN -//#define LAYOUT_GERMAN_MAC -//#define LAYOUT_GERMAN_SWISS -//#define LAYOUT_ICELANDIC -//#define LAYOUT_IRISH -//#define LAYOUT_ITALIAN -//#define LAYOUT_NORWEGIAN -//#define LAYOUT_PORTUGUESE -//#define LAYOUT_PORTUGUESE_BRAZILIAN -//#define LAYOUT_SPANISH -//#define LAYOUT_SPANISH_LATIN_AMERICA -//#define LAYOUT_SWEDISH -//#define LAYOUT_TURKISH -//#define LAYOUT_UNITED_KINGDOM -//#define LAYOUT_US_INTERNATIONAL - -//================================================================================ -// Definitions and Helpers -//================================================================================ - -// Default US keyboard layout -#if !defined(LAYOUT_CANADIAN_FRENCH) && !defined(LAYOUT_CANADIAN_MULTILINGUAL) \ -&& !defined(LAYOUT_DANISH) && !defined(LAYOUT_FINNISH) && !defined(LAYOUT_FRENCH) \ -&& !defined(LAYOUT_FRENCH_BELGIAN) && !defined(LAYOUT_FRENCH_SWISS) && !defined(LAYOUT_GERMAN) \ -&& !defined(LAYOUT_GERMAN_MAC) && !defined(LAYOUT_GERMAN_SWISS) && !defined(LAYOUT_ICELANDIC) \ -&& !defined(LAYOUT_IRISH) && !defined(LAYOUT_ITALIAN) && !defined(LAYOUT_NORWEGIAN) \ -&& !defined(LAYOUT_PORTUGUESE) && !defined(LAYOUT_PORTUGUESE_BRAZILIAN) \ -&& !defined(LAYOUT_SPANISH) && !defined(LAYOUT_SPANISH_LATIN_AMERICA) \ -&& !defined(LAYOUT_SWEDISH) && !defined(LAYOUT_TURKISH) && !defined(LAYOUT_UNITED_KINGDOM) \ -&& !defined(LAYOUT_US_INTERNATIONAL) && !defined(LAYOUT_US_ENGLISH) -#define LAYOUT_US_ENGLISH -#endif - #define HID_REPORTID_NONE 0 #ifndef HID_REPORTID_MOUSE From ffbbd0800fbc8d02151bcb18886fb2730ea8377b Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Wed, 9 Dec 2015 13:30:20 -0800 Subject: [PATCH 345/602] Remove the 'SingleReport variants of everything we'll be using as a compound report --- .../examples/Consumer/Consumer.ino | 2 - .../Keyboard/NKROKeyboard/NKROKeyboard.ino | 1 - .../Mouse/AbsoluteMouse/AbsoluteMouse.ino | 2 - .../KeyboardioHID/examples/System/System.ino | 1 - plugins/KeyboardioHID/keywords.txt | 4 - plugins/KeyboardioHID/src/HID-Project.h | 11 +- .../src/SingleReport/SingleAbsoluteMouse.cpp | 144 ---------------- .../src/SingleReport/SingleAbsoluteMouse.h | 55 ------ .../src/SingleReport/SingleConsumer.cpp | 121 ------------- .../src/SingleReport/SingleConsumer.h | 55 ------ .../src/SingleReport/SingleGamepad.cpp | 154 ----------------- .../src/SingleReport/SingleGamepad.h | 56 ------ .../src/SingleReport/SingleNKROKeyboard.cpp | 160 ------------------ .../src/SingleReport/SingleNKROKeyboard.h | 57 ------- .../src/SingleReport/SingleSystem.cpp | 123 -------------- .../src/SingleReport/SingleSystem.h | 55 ------ 16 files changed, 3 insertions(+), 998 deletions(-) delete mode 100644 plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp delete mode 100644 plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h delete mode 100644 plugins/KeyboardioHID/src/SingleReport/SingleConsumer.cpp delete mode 100644 plugins/KeyboardioHID/src/SingleReport/SingleConsumer.h delete mode 100644 plugins/KeyboardioHID/src/SingleReport/SingleGamepad.cpp delete mode 100644 plugins/KeyboardioHID/src/SingleReport/SingleGamepad.h delete mode 100644 plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.cpp delete mode 100644 plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.h delete mode 100644 plugins/KeyboardioHID/src/SingleReport/SingleSystem.cpp delete mode 100644 plugins/KeyboardioHID/src/SingleReport/SingleSystem.h diff --git a/plugins/KeyboardioHID/examples/Consumer/Consumer.ino b/plugins/KeyboardioHID/examples/Consumer/Consumer.ino index b3d254c64c..0c566e960c 100644 --- a/plugins/KeyboardioHID/examples/Consumer/Consumer.ino +++ b/plugins/KeyboardioHID/examples/Consumer/Consumer.ino @@ -5,8 +5,6 @@ Consumer example Press a button to play/pause music player - You may also use SingleConsumer to use a single report. - See HID Project documentation for more Consumer keys. https://github.com/NicoHood/HID/wiki/Consumer-API */ diff --git a/plugins/KeyboardioHID/examples/Keyboard/NKROKeyboard/NKROKeyboard.ino b/plugins/KeyboardioHID/examples/Keyboard/NKROKeyboard/NKROKeyboard.ino index 9381ffc966..56327875a9 100644 --- a/plugins/KeyboardioHID/examples/Keyboard/NKROKeyboard/NKROKeyboard.ino +++ b/plugins/KeyboardioHID/examples/Keyboard/NKROKeyboard/NKROKeyboard.ino @@ -8,7 +8,6 @@ NKRO can push 113 keys at the same time, the other Keyboards only 6 keys + 8 modifiers! - You may also use SingleNKROKeyboard to enable a single report NKROKeyboard. See HID Project documentation for more information. https://github.com/NicoHood/HID/wiki/Keyboard-API#nkro-keyboard diff --git a/plugins/KeyboardioHID/examples/Mouse/AbsoluteMouse/AbsoluteMouse.ino b/plugins/KeyboardioHID/examples/Mouse/AbsoluteMouse/AbsoluteMouse.ino index 3cf052ca3d..872ee63eb6 100644 --- a/plugins/KeyboardioHID/examples/Mouse/AbsoluteMouse/AbsoluteMouse.ino +++ b/plugins/KeyboardioHID/examples/Mouse/AbsoluteMouse/AbsoluteMouse.ino @@ -5,8 +5,6 @@ AbsoluteMouse example Press a button to click, moveTo the mouse. - You may also use SingleAbsoluteMouse to use a single report. - See HID Project documentation for more infos https://github.com/NicoHood/HID/wiki/Mouse-API https://github.com/NicoHood/HID/wiki/AbsoluteMouse-API diff --git a/plugins/KeyboardioHID/examples/System/System.ino b/plugins/KeyboardioHID/examples/System/System.ino index c2cde3a6a7..b68c288fd2 100644 --- a/plugins/KeyboardioHID/examples/System/System.ino +++ b/plugins/KeyboardioHID/examples/System/System.ino @@ -5,7 +5,6 @@ System example Press a button to put pc into sleep/shut it down or wake it up again. - You may also use SingleSystem to use a single report. See HID Project documentation for more Consumer keys. https://github.com/NicoHood/HID/wiki/System-API diff --git a/plugins/KeyboardioHID/keywords.txt b/plugins/KeyboardioHID/keywords.txt index fb6c8a7cd5..a12017b90d 100644 --- a/plugins/KeyboardioHID/keywords.txt +++ b/plugins/KeyboardioHID/keywords.txt @@ -63,18 +63,14 @@ BootKeyboard KEYWORD1 BootMouse KEYWORD1 RawHID KEYWORD1 System KEYWORD1 -SingleSystem KEYWORD1 Consumer KEYWORD1 -SingleConsumer KEYWORD1 Gamepad KEYWORD1 Gamepad1 KEYWORD1 Gamepad2 KEYWORD1 Gamepad3 KEYWORD1 Gamepad4 KEYWORD1 NKROKeyboard KEYWORD1 -SingleNKROKeyboard KEYWORD1 AbsoluteMouse KEYWORD1 -SingleAbsoluteMouse KEYWORD1 ####################################### # Constants (LITERAL1) diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index 506785bdff..69ca8f8162 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -40,19 +40,14 @@ THE SOFTWARE. // Include all HID libraries (.a linkage required to work) properly -#include "SingleReport/SingleAbsoluteMouse.h" -#include "MultiReport/AbsoluteMouse.h" #include "SingleReport/BootMouse.h" +#include "SingleReport/RawHID.h" +#include "SingleReport/BootKeyboard.h" +#include "MultiReport/AbsoluteMouse.h" #include "MultiReport/ImprovedMouse.h" -#include "SingleReport/SingleConsumer.h" #include "MultiReport/Consumer.h" -#include "SingleReport/SingleGamepad.h" #include "MultiReport/Gamepad.h" -#include "SingleReport/SingleSystem.h" #include "MultiReport/System.h" -#include "SingleReport/RawHID.h" -#include "SingleReport/BootKeyboard.h" #include "MultiReport/ImprovedKeyboard.h" -#include "SingleReport/SingleNKROKeyboard.h" #include "MultiReport/NKROKeyboard.h" diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp deleted file mode 100644 index bad902c487..0000000000 --- a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 "SingleAbsoluteMouse.h" - -static const uint8_t _hidSingleReportDescriptorAbsoluteMouse[] PROGMEM = { - /* Mouse absolute */ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 54 */ - 0x09, 0x02, /* USAGE (Mouse) */ - 0xA1, 0x01, /* COLLECTION (Application) */ - - /* 8 Buttons */ - 0x05, 0x09, /* USAGE_PAGE (Button) */ - 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ - 0x29, 0x08, /* USAGE_MAXIMUM (Button 8) */ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ - 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ - 0x95, 0x08, /* REPORT_COUNT (8) */ - 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - - /* X, Y */ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ - 0x09, 0x30, /* USAGE (X) */ - 0x09, 0x31, /* USAGE (Y) */ - 0x16, 0x00, 0x80, /* Logical Minimum (-32768) */ - 0x26, 0xFF, 0x7F, /* Logical Maximum (32767) */ - 0x75, 0x10, /* Report Size (16), */ - 0x95, 0x02, /* Report Count (2), */ - 0x81, 0x02, /* Input (Data, Variable, Absolute) */ - - /* Wheel */ - 0x09, 0x38, /* USAGE (Wheel) */ - 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) */ - - /* End */ - 0xc0 /* END_COLLECTION */ -}; - - -SingleAbsoluteMouse_::SingleAbsoluteMouse_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1) -{ - epType[0] = EP_TYPE_INTERRUPT_IN; - PluggableUSB().plug(this); -} - -int SingleAbsoluteMouse_::getInterface(uint8_t* interfaceCount) -{ - *interfaceCount += 1; // uses 1 - HIDDescriptor hidInterface = { - D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE), - D_HIDREPORT(sizeof(_hidSingleReportDescriptorAbsoluteMouse)), - D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) - }; - return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); -} - -int SingleAbsoluteMouse_::getDescriptor(USBSetup& setup) -{ - // Check if this is a HID Class Descriptor request - if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { return 0; } - if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { return 0; } - - // In a HID Class Descriptor wIndex cointains the interface number - if (setup.wIndex != pluggedInterface) { return 0; } - - // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol - // due to the USB specs, but Windows and Linux just assumes its in report mode. - protocol = HID_REPORT_PROTOCOL; - - return USB_SendControl(TRANSFER_PGM, _hidSingleReportDescriptorAbsoluteMouse, sizeof(_hidSingleReportDescriptorAbsoluteMouse)); -} - -bool SingleAbsoluteMouse_::setup(USBSetup& setup) -{ - if (pluggedInterface != setup.wIndex) { - return false; - } - - uint8_t request = setup.bRequest; - uint8_t requestType = setup.bmRequestType; - - if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) - { - if (request == HID_GET_REPORT) { - // TODO: HID_GetReport(); - return true; - } - if (request == HID_GET_PROTOCOL) { - // TODO: Send8(protocol); - return true; - } - } - - if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) - { - if (request == HID_SET_PROTOCOL) { - protocol = setup.wValueL; - return true; - } - if (request == HID_SET_IDLE) { - idle = setup.wValueL; - return true; - } - if (request == HID_SET_REPORT) - { - } - } - - return false; -} - -void SingleAbsoluteMouse_::SendReport(void* data, int length) -{ - USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, length); -} - -SingleAbsoluteMouse_ SingleAbsoluteMouse; - - diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h deleted file mode 100644 index 2a13fe9464..0000000000 --- a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 guard -#pragma once - -#include -#include "PluggableUSB.h" -#include "HID.h" -#include "HID-Settings.h" -#include "../HID-APIs/AbsoluteMouseAPI.h" - - -class SingleAbsoluteMouse_ : public PluggableUSBModule, public AbsoluteMouseAPI -{ -public: - SingleAbsoluteMouse_(void); - uint8_t getLeds(void); - uint8_t getProtocol(void); - -protected: - // Implementation of the PUSBListNode - int getInterface(uint8_t* interfaceCount); - int getDescriptor(USBSetup& setup); - bool setup(USBSetup& setup); - - uint8_t epType[1]; - uint8_t protocol; - uint8_t idle; - - virtual inline void SendReport(void* data, int length) override; -}; -extern SingleAbsoluteMouse_ SingleAbsoluteMouse; - - diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleConsumer.cpp b/plugins/KeyboardioHID/src/SingleReport/SingleConsumer.cpp deleted file mode 100644 index c85827584b..0000000000 --- a/plugins/KeyboardioHID/src/SingleReport/SingleConsumer.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 "SingleConsumer.h" - -static const uint8_t _hidSingleReportDescriptorConsumer[] PROGMEM = { - /* Consumer Control (Sound/Media keys) */ - 0x05, 0x0C, /* usage page (consumer device) */ - 0x09, 0x01, /* usage -- consumer control */ - 0xA1, 0x01, /* collection (application) */ - /* 4 Media Keys */ - 0x15, 0x00, /* logical minimum */ - 0x26, 0xFF, 0x03, /* logical maximum (3ff) */ - 0x19, 0x00, /* usage minimum (0) */ - 0x2A, 0xFF, 0x03, /* usage maximum (3ff) */ - 0x95, 0x04, /* report count (4) */ - 0x75, 0x10, /* report size (16) */ - 0x81, 0x00, /* input */ - 0xC0 /* end collection */ -}; - -SingleConsumer_::SingleConsumer_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1) -{ - epType[0] = EP_TYPE_INTERRUPT_IN; - PluggableUSB().plug(this); -} - -int SingleConsumer_::getInterface(uint8_t* interfaceCount) -{ - *interfaceCount += 1; // uses 1 - HIDDescriptor hidInterface = { - D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE), - D_HIDREPORT(sizeof(_hidSingleReportDescriptorConsumer)), - D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) - }; - return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); -} - -int SingleConsumer_::getDescriptor(USBSetup& setup) -{ - // Check if this is a HID Class Descriptor request - if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { return 0; } - if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { return 0; } - - // In a HID Class Descriptor wIndex cointains the interface number - if (setup.wIndex != pluggedInterface) { return 0; } - - // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol - // due to the USB specs, but Windows and Linux just assumes its in report mode. - protocol = HID_REPORT_PROTOCOL; - - return USB_SendControl(TRANSFER_PGM, _hidSingleReportDescriptorConsumer, sizeof(_hidSingleReportDescriptorConsumer)); -} - -bool SingleConsumer_::setup(USBSetup& setup) -{ - if (pluggedInterface != setup.wIndex) { - return false; - } - - uint8_t request = setup.bRequest; - uint8_t requestType = setup.bmRequestType; - - if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) - { - if (request == HID_GET_REPORT) { - // TODO: HID_GetReport(); - return true; - } - if (request == HID_GET_PROTOCOL) { - // TODO: Send8(protocol); - return true; - } - } - - if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) - { - if (request == HID_SET_PROTOCOL) { - protocol = setup.wValueL; - return true; - } - if (request == HID_SET_IDLE) { - idle = setup.wValueL; - return true; - } - if (request == HID_SET_REPORT) - { - } - } - - return false; -} - -void SingleConsumer_::SendReport(void* data, int length) -{ - USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, length); -} - -SingleConsumer_ SingleConsumer; - - diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleConsumer.h b/plugins/KeyboardioHID/src/SingleReport/SingleConsumer.h deleted file mode 100644 index c7a8a43604..0000000000 --- a/plugins/KeyboardioHID/src/SingleReport/SingleConsumer.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 guard -#pragma once - -#include -#include "PluggableUSB.h" -#include "HID.h" -#include "HID-Settings.h" -#include "../HID-APIs/ConsumerAPI.h" - - -class SingleConsumer_ : public PluggableUSBModule, public ConsumerAPI -{ -public: - SingleConsumer_(void); - uint8_t getLeds(void); - uint8_t getProtocol(void); - -protected: - // Implementation of the PUSBListNode - int getInterface(uint8_t* interfaceCount); - int getDescriptor(USBSetup& setup); - bool setup(USBSetup& setup); - - uint8_t epType[1]; - uint8_t protocol; - uint8_t idle; - - virtual inline void SendReport(void* data, int length) override; -}; -extern SingleConsumer_ SingleConsumer; - - diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleGamepad.cpp b/plugins/KeyboardioHID/src/SingleReport/SingleGamepad.cpp deleted file mode 100644 index acb86de0b0..0000000000 --- a/plugins/KeyboardioHID/src/SingleReport/SingleGamepad.cpp +++ /dev/null @@ -1,154 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 "SingleGamepad.h" - -static const uint8_t _hidReportDescriptorGamepad[] PROGMEM = { - /* Gamepad with 32 buttons and 6 axis*/ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ - 0x09, 0x04, /* USAGE (Joystick) */ - 0xa1, 0x01, /* COLLECTION (Application) */ - /* 32 Buttons */ - 0x05, 0x09, /* USAGE_PAGE (Button) */ - 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ - 0x29, 0x20, /* USAGE_MAXIMUM (Button 32) */ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ - 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ - 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x95, 0x20, /* REPORT_COUNT (32) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - /* 4 16bit Axis */ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ - 0xa1, 0x00, /* COLLECTION (Physical) */ - 0x09, 0x30, /* USAGE (X) */ - 0x09, 0x31, /* USAGE (Y) */ - 0x09, 0x33, /* USAGE (Rx) */ - 0x09, 0x34, /* USAGE (Ry) */ - 0x16, 0x00, 0x80, /* LOGICAL_MINIMUM (-32768) */ - 0x26, 0xFF, 0x7F, /* LOGICAL_MAXIMUM (32767) */ - 0x75, 0x10, /* REPORT_SIZE (16) */ - 0x95, 0x04, /* REPORT_COUNT (4) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - /* 2 8bit Axis */ - 0x09, 0x32, /* USAGE (Z) */ - 0x09, 0x35, /* USAGE (Rz) */ - 0x15, 0x80, /* LOGICAL_MINIMUM (-128) */ - 0x25, 0x7F, /* LOGICAL_MAXIMUM (127) */ - 0x75, 0x08, /* REPORT_SIZE (8) */ - 0x95, 0x02, /* REPORT_COUNT (2) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - 0xc0, /* END_COLLECTION */ - /* 2 Hat Switches */ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ - 0x09, 0x39, /* USAGE (Hat switch) */ - 0x09, 0x39, /* USAGE (Hat switch) */ - 0x15, 0x01, /* LOGICAL_MINIMUM (1) */ - 0x25, 0x08, /* LOGICAL_MAXIMUM (8) */ - 0x95, 0x02, /* REPORT_COUNT (2) */ - 0x75, 0x04, /* REPORT_SIZE (4) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - 0xc0 /* END_COLLECTION */ -}; - -SingleGamepad_::SingleGamepad_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1) -{ - epType[0] = EP_TYPE_INTERRUPT_IN; - PluggableUSB().plug(this); -} - -int SingleGamepad_::getInterface(uint8_t* interfaceCount) -{ - *interfaceCount += 1; // uses 1 - HIDDescriptor hidInterface = { - D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE), - D_HIDREPORT(sizeof(_hidReportDescriptorGamepad)), - D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) - }; - return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); -} - -int SingleGamepad_::getDescriptor(USBSetup& setup) -{ - // Check if this is a HID Class Descriptor request - if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { return 0; } - if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { return 0; } - - // In a HID Class Descriptor wIndex cointains the interface number - if (setup.wIndex != pluggedInterface) { return 0; } - - // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol - // due to the USB specs, but Windows and Linux just assumes its in report mode. - protocol = HID_REPORT_PROTOCOL; - - return USB_SendControl(TRANSFER_PGM, _hidReportDescriptorGamepad, sizeof(_hidReportDescriptorGamepad)); -} - -bool SingleGamepad_::setup(USBSetup& setup) -{ - if (pluggedInterface != setup.wIndex) { - return false; - } - - uint8_t request = setup.bRequest; - uint8_t requestType = setup.bmRequestType; - - if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) - { - if (request == HID_GET_REPORT) { - // TODO: HID_GetReport(); - return true; - } - if (request == HID_GET_PROTOCOL) { - // TODO: Send8(protocol); - return true; - } - } - - if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) - { - if (request == HID_SET_PROTOCOL) { - protocol = setup.wValueL; - return true; - } - if (request == HID_SET_IDLE) { - idle = setup.wValueL; - return true; - } - if (request == HID_SET_REPORT) - { - } - } - - return false; -} - -void SingleGamepad_::SendReport(void* data, int length){ - USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, length); -} - -SingleGamepad_ Gamepad1; -SingleGamepad_ Gamepad2; -SingleGamepad_ Gamepad3; -SingleGamepad_ Gamepad4; - - diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleGamepad.h b/plugins/KeyboardioHID/src/SingleReport/SingleGamepad.h deleted file mode 100644 index bca1db598e..0000000000 --- a/plugins/KeyboardioHID/src/SingleReport/SingleGamepad.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 guard -#pragma once - -#include -#include "PluggableUSB.h" -#include "HID.h" -#include "HID-Settings.h" -#include "../HID-APIs/GamepadAPI.h" - - -class SingleGamepad_ : public PluggableUSBModule, public GamepadAPI -{ -public: - SingleGamepad_(void); - -protected: - // Implementation of the PUSBListNode - int getInterface(uint8_t* interfaceCount); - int getDescriptor(USBSetup& setup); - bool setup(USBSetup& setup); - - uint8_t epType[1]; - uint8_t protocol; - uint8_t idle; - - virtual void SendReport(void* data, int length) override; -}; -extern SingleGamepad_ Gamepad1; -extern SingleGamepad_ Gamepad2; -extern SingleGamepad_ Gamepad3; -extern SingleGamepad_ Gamepad4; - - diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.cpp b/plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.cpp deleted file mode 100644 index ab7c269258..0000000000 --- a/plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 "SingleNKROKeyboard.h" - -static const uint8_t _hidReportDescriptorNKRO[] PROGMEM = { - // NKRO Keyboard - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 47 */ - 0x09, 0x06, /* USAGE (Keyboard) */ - 0xa1, 0x01, /* COLLECTION (Application) */ - 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ - - /* Keyboard Modifiers (shift, alt, ...) */ - 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) */ - - /* 5 LEDs for num lock etc, 3 left for advanced, custom usage */ - 0x05, 0x08, /* USAGE_PAGE (LEDs) */ - 0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */ - 0x29, 0x08, /* USAGE_MAXIMUM (Kana + 3 custom)*/ - 0x95, 0x08, /* REPORT_COUNT (8) */ - 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */ - - /* 104 Keys as bitmap */ - 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ - 0x19, 0x00, /* Usage Minimum (0) */ - 0x29, NKRO_KEY_COUNT - 1, /* Usage Maximum (103) */ - 0x15, 0x00, /* Logical Minimum (0) */ - 0x25, 0x01, /* Logical Maximum (1) */ - 0x75, 0x01, /* Report Size (1) */ - 0x95, NKRO_KEY_COUNT, /* Report Count (104) */ - 0x81, 0x02, /* Input (Data, Variable, Absolute) */ - - /* 1 Custom Keyboard key */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0x75, 0x08, /* REPORT_SIZE (8) */ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ - 0x26, 0xE7, 0x00, /* LOGICAL_MAXIMUM (231) */ - 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ - 0x29, 0xE7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ - 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ - - /* End */ - 0xC0 /* End Collection */ -}; - -SingleNKROKeyboard_::SingleNKROKeyboard_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1), leds(0) -{ - epType[0] = EP_TYPE_INTERRUPT_IN; - PluggableUSB().plug(this); -} - -int SingleNKROKeyboard_::getInterface(uint8_t* interfaceCount) -{ - *interfaceCount += 1; // uses 1 - HIDDescriptor hidInterface = { - D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE), - D_HIDREPORT(sizeof(_hidReportDescriptorNKRO)), - D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) - }; - return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); -} - -int SingleNKROKeyboard_::getDescriptor(USBSetup& setup) -{ - // Check if this is a HID Class Descriptor request - if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { return 0; } - if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { return 0; } - - // In a HID Class Descriptor wIndex cointains the interface number - if (setup.wIndex != pluggedInterface) { return 0; } - - // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol - // due to the USB specs, but Windows and Linux just assumes its in report mode. - protocol = HID_REPORT_PROTOCOL; - - return USB_SendControl(TRANSFER_PGM, _hidReportDescriptorNKRO, sizeof(_hidReportDescriptorNKRO)); -} - -bool SingleNKROKeyboard_::setup(USBSetup& setup) -{ - if (pluggedInterface != setup.wIndex) { - return false; - } - - uint8_t request = setup.bRequest; - uint8_t requestType = setup.bmRequestType; - - if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) - { - if (request == HID_GET_REPORT) { - // TODO: HID_GetReport(); - return true; - } - if (request == HID_GET_PROTOCOL) { - // TODO: Send8(protocol); - return true; - } - } - - if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) - { - if (request == HID_SET_PROTOCOL) { - protocol = setup.wValueL; - return true; - } - if (request == HID_SET_IDLE) { - idle = setup.wValueL; - return true; - } - if (request == HID_SET_REPORT) - { - // Check if data has the correct length - auto length = setup.wLength; - if(length == sizeof(leds)){ - USB_RecvControl(&leds, length); - } - } - } - - return false; -} - -uint8_t SingleNKROKeyboard_::getLeds(void){ - return leds; -} - -int SingleNKROKeyboard_::send(void){ - return USB_Send(pluggedEndpoint | TRANSFER_RELEASE, &_keyReport, sizeof(_keyReport)); -} - -SingleNKROKeyboard_ SingleNKROKeyboard; - - diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.h b/plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.h deleted file mode 100644 index d5f2ead6e7..0000000000 --- a/plugins/KeyboardioHID/src/SingleReport/SingleNKROKeyboard.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 guard -#pragma once - -#include -#include "PluggableUSB.h" -#include "HID.h" -#include "HID-Settings.h" -#include "../HID-APIs/NKROKeyboardAPI.h" - - -class SingleNKROKeyboard_ : public PluggableUSBModule, public NKROKeyboardAPI -{ -public: - SingleNKROKeyboard_(void); - uint8_t getLeds(void); - uint8_t getProtocol(void); - - virtual int send(void) final; - -protected: - // Implementation of the PUSBListNode - int getInterface(uint8_t* interfaceCount); - int getDescriptor(USBSetup& setup); - bool setup(USBSetup& setup); - - uint8_t epType[1]; - uint8_t protocol; - uint8_t idle; - - uint8_t leds; -}; -extern SingleNKROKeyboard_ SingleNKROKeyboard; - - diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleSystem.cpp b/plugins/KeyboardioHID/src/SingleReport/SingleSystem.cpp deleted file mode 100644 index 6d99dd5d25..0000000000 --- a/plugins/KeyboardioHID/src/SingleReport/SingleSystem.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 "SingleSystem.h" - -static const uint8_t _hidSingleReportDescriptorSystem[] PROGMEM = { - //TODO limit to system keys only? - /* System Control (Power Down, Sleep, Wakeup, ...) */ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ - 0x09, 0x80, /* USAGE (System Control) */ - 0xa1, 0x01, /* COLLECTION (Application) */ - /* 1 system key */ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ - 0x26, 0xff, 0x00, /* LOGICAL_MAXIMUM (255) */ - 0x19, 0x00, /* USAGE_MINIMUM (Undefined) */ - 0x29, 0xff, /* USAGE_MAXIMUM (System Menu Down) */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0x75, 0x08, /* REPORT_SIZE (8) */ - 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ - 0xc0 /* END_COLLECTION */ -}; - - -SingleSystem_::SingleSystem_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1) -{ - epType[0] = EP_TYPE_INTERRUPT_IN; - PluggableUSB().plug(this); -} - -int SingleSystem_::getInterface(uint8_t* interfaceCount) -{ - *interfaceCount += 1; // uses 1 - HIDDescriptor hidInterface = { - D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE), - D_HIDREPORT(sizeof(_hidSingleReportDescriptorSystem)), - D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) - }; - return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); -} - -int SingleSystem_::getDescriptor(USBSetup& setup) -{ - // Check if this is a HID Class Descriptor request - if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { return 0; } - if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { return 0; } - - // In a HID Class Descriptor wIndex cointains the interface number - if (setup.wIndex != pluggedInterface) { return 0; } - - // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol - // due to the USB specs, but Windows and Linux just assumes its in report mode. - protocol = HID_REPORT_PROTOCOL; - - return USB_SendControl(TRANSFER_PGM, _hidSingleReportDescriptorSystem, sizeof(_hidSingleReportDescriptorSystem)); -} - -bool SingleSystem_::setup(USBSetup& setup) -{ - if (pluggedInterface != setup.wIndex) { - return false; - } - - uint8_t request = setup.bRequest; - uint8_t requestType = setup.bmRequestType; - - if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) - { - if (request == HID_GET_REPORT) { - // TODO: HID_GetReport(); - return true; - } - if (request == HID_GET_PROTOCOL) { - // TODO: Send8(protocol); - return true; - } - } - - if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) - { - if (request == HID_SET_PROTOCOL) { - protocol = setup.wValueL; - return true; - } - if (request == HID_SET_IDLE) { - idle = setup.wValueL; - return true; - } - if (request == HID_SET_REPORT) - { - } - } - - return false; -} - -void SingleSystem_::SendReport(void* data, int length) -{ - USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, length); -} - -SingleSystem_ SingleSystem; - - diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleSystem.h b/plugins/KeyboardioHID/src/SingleReport/SingleSystem.h deleted file mode 100644 index 01ca15ca80..0000000000 --- a/plugins/KeyboardioHID/src/SingleReport/SingleSystem.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 guard -#pragma once - -#include -#include "PluggableUSB.h" -#include "HID.h" -#include "HID-Settings.h" -#include "../HID-APIs/SystemAPI.h" - - -class SingleSystem_ : public PluggableUSBModule, public SystemAPI -{ -public: - SingleSystem_(void); - uint8_t getLeds(void); - uint8_t getProtocol(void); - -protected: - // Implementation of the PUSBListNode - int getInterface(uint8_t* interfaceCount); - int getDescriptor(USBSetup& setup); - bool setup(USBSetup& setup); - - uint8_t epType[1]; - uint8_t protocol; - uint8_t idle; - - virtual inline void SendReport(void* data, int length) override; -}; -extern SingleSystem_ SingleSystem; - - From 61b1d3fd02e6e34f38698de70ed40d08d2cd0eee Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Wed, 9 Dec 2015 18:02:48 -0800 Subject: [PATCH 346/602] Remove the 'ImprovedKeyboard" class. We only want NKROKeyboard and BootKeyboard --- plugins/KeyboardioHID/src/HID-Project.h | 1 - .../src/MultiReport/ImprovedKeyboard.cpp | 83 ------------------- .../src/MultiReport/ImprovedKeyboard.h | 43 ---------- 3 files changed, 127 deletions(-) delete mode 100644 plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.cpp delete mode 100644 plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.h diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index 69ca8f8162..a2a6b9c39d 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -48,6 +48,5 @@ THE SOFTWARE. #include "MultiReport/Consumer.h" #include "MultiReport/Gamepad.h" #include "MultiReport/System.h" -#include "MultiReport/ImprovedKeyboard.h" #include "MultiReport/NKROKeyboard.h" diff --git a/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.cpp deleted file mode 100644 index 3b42a9e090..0000000000 --- a/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 "ImprovedKeyboard.h" - -static const uint8_t _hidMultiReportDescriptorKeyboard[] PROGMEM = { - // Keyboard - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 47 */ - 0x09, 0x06, /* USAGE (Keyboard) */ - 0xa1, 0x01, /* COLLECTION (Application) */ - 0x85, HID_REPORTID_KEYBOARD, /* REPORT_ID TODO order important? */ - 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ - - /* Keyboard Modifiers (shift, alt, ...) */ - 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) */ - - /* Reserved byte, used for consumer reports, only works with linux */ - 0x05, 0x0C, /* Usage Page (Consumer) */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0x75, 0x08, /* REPORT_SIZE (8) */ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ - 0x26, 0xFF, 0x00, /* LOGICAL_MAXIMUM (255) */ - 0x19, 0x00, /* USAGE_MINIMUM (0) */ - 0x29, 0xFF, /* USAGE_MAXIMUM (255) */ - 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ - - /* 6 Keyboard keys */ - 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ - 0x95, 0x06, /* REPORT_COUNT (6) */ - 0x75, 0x08, /* REPORT_SIZE (8) */ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ - 0x26, 0xE7, 0x00, /* LOGICAL_MAXIMUM (231) */ - 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ - 0x29, 0xE7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ - 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ - - /* End */ - 0xc0 /* END_COLLECTION */ -}; - -Keyboard_::Keyboard_(void) -{ - static HIDSubDescriptor node(_hidMultiReportDescriptorKeyboard, sizeof(_hidMultiReportDescriptorKeyboard)); - HID().AppendDescriptor(&node); -} - -int Keyboard_::send(void) -{ - return HID().SendReport(HID_REPORTID_KEYBOARD, &_keyReport, sizeof(_keyReport)); -} - -void Keyboard_::wakeupHost(void){ - USBDevice.wakeupHost(); -} - -Keyboard_ Keyboard; - diff --git a/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.h b/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.h deleted file mode 100644 index d59486c272..0000000000 --- a/plugins/KeyboardioHID/src/MultiReport/ImprovedKeyboard.h +++ /dev/null @@ -1,43 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 guard -#pragma once - -#include -#include "PluggableUSB.h" -#include "HID.h" -#include "HID-Settings.h" -#include "../HID-APIs/DefaultKeyboardAPI.h" - - -class Keyboard_ : public DefaultKeyboardAPI -{ -public: - Keyboard_(void); - void wakeupHost(void); - - virtual inline int send(void) final; -}; -extern Keyboard_ Keyboard; - From 2e0b1e78586e3ecaf1d8f23b14f9e3462e01cfdd Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Wed, 9 Dec 2015 18:07:00 -0800 Subject: [PATCH 347/602] Rename DefaultKeyboard to BootKeyboard, since that's the onlything that uses the API --- .../{DefaultKeyboardAPI.h => BootKeyboardAPI.h} | 4 ++-- ...{DefaultKeyboardAPI.hpp => BootKeyboardAPI.hpp} | 14 +++++++------- .../KeyboardioHID/src/SingleReport/BootKeyboard.h | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) rename plugins/KeyboardioHID/src/HID-APIs/{DefaultKeyboardAPI.h => BootKeyboardAPI.h} (96%) rename plugins/KeyboardioHID/src/HID-APIs/{DefaultKeyboardAPI.hpp => BootKeyboardAPI.hpp} (89%) diff --git a/plugins/KeyboardioHID/src/HID-APIs/DefaultKeyboardAPI.h b/plugins/KeyboardioHID/src/HID-APIs/BootKeyboardAPI.h similarity index 96% rename from plugins/KeyboardioHID/src/HID-APIs/DefaultKeyboardAPI.h rename to plugins/KeyboardioHID/src/HID-APIs/BootKeyboardAPI.h index b586b09b9f..bbf1ebd473 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/DefaultKeyboardAPI.h +++ b/plugins/KeyboardioHID/src/HID-APIs/BootKeyboardAPI.h @@ -41,7 +41,7 @@ typedef union{ } HID_KeyboardReport_Data_t; -class DefaultKeyboardAPI : public KeyboardAPI +class BootKeyboardAPI : public KeyboardAPI { public: // Add special consumer key API for the reserved byte @@ -73,5 +73,5 @@ class DefaultKeyboardAPI : public KeyboardAPI }; // Implementation is inline -#include "DefaultKeyboardAPI.hpp" +#include "BootKeyboardAPI.hpp" diff --git a/plugins/KeyboardioHID/src/HID-APIs/DefaultKeyboardAPI.hpp b/plugins/KeyboardioHID/src/HID-APIs/BootKeyboardAPI.hpp similarity index 89% rename from plugins/KeyboardioHID/src/HID-APIs/DefaultKeyboardAPI.hpp rename to plugins/KeyboardioHID/src/HID-APIs/BootKeyboardAPI.hpp index 7ca2071309..d20718d711 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/DefaultKeyboardAPI.hpp +++ b/plugins/KeyboardioHID/src/HID-APIs/BootKeyboardAPI.hpp @@ -25,7 +25,7 @@ THE SOFTWARE. #pragma once -size_t DefaultKeyboardAPI::set(KeyboardKeycode k, bool s) +size_t BootKeyboardAPI::set(KeyboardKeycode k, bool s) { // It's a modifier key if(k >= KEY_LEFT_CTRL && k <= KEY_RIGHT_GUI) @@ -66,7 +66,7 @@ size_t DefaultKeyboardAPI::set(KeyboardKeycode k, bool s) return 0; } -size_t DefaultKeyboardAPI::removeAll(void) +size_t BootKeyboardAPI::removeAll(void) { // Release all keys size_t ret = 0; @@ -82,7 +82,7 @@ size_t DefaultKeyboardAPI::removeAll(void) } -size_t DefaultKeyboardAPI::write(ConsumerKeycode k) +size_t BootKeyboardAPI::write(ConsumerKeycode k) { // Press and release key (if press was successfull) auto ret = press(k); @@ -93,7 +93,7 @@ size_t DefaultKeyboardAPI::write(ConsumerKeycode k) } -size_t DefaultKeyboardAPI::press(ConsumerKeycode k) +size_t BootKeyboardAPI::press(ConsumerKeycode k) { // Press key and send report to host auto ret = add(k); @@ -104,7 +104,7 @@ size_t DefaultKeyboardAPI::press(ConsumerKeycode k) } -size_t DefaultKeyboardAPI::release(ConsumerKeycode k) +size_t BootKeyboardAPI::release(ConsumerKeycode k) { // Release key and send report to host auto ret = remove(k); @@ -115,7 +115,7 @@ size_t DefaultKeyboardAPI::release(ConsumerKeycode k) } -size_t DefaultKeyboardAPI::add(ConsumerKeycode k) +size_t BootKeyboardAPI::add(ConsumerKeycode k) { // No 2 byte keys are supported if(k > 0xFF){ @@ -130,7 +130,7 @@ size_t DefaultKeyboardAPI::add(ConsumerKeycode k) } -size_t DefaultKeyboardAPI::remove(ConsumerKeycode k) +size_t BootKeyboardAPI::remove(ConsumerKeycode k) { // No 2 byte keys are supported if(k > 0xFF){ diff --git a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h index cd28a8f62d..511b3ba5a2 100644 --- a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h @@ -28,10 +28,10 @@ THE SOFTWARE. #include "PluggableUSB.h" #include "HID.h" #include "HID-Settings.h" -#include "../HID-APIs/DefaultKeyboardAPI.h" +#include "../HID-APIs/BootKeyboardAPI.h" -class BootKeyboard_ : public PluggableUSBModule, public DefaultKeyboardAPI +class BootKeyboard_ : public PluggableUSBModule, public BootKeyboardAPI { public: BootKeyboard_(void); From 1eba96824b439e0259361f110b061b50ab24e387 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Wed, 9 Dec 2015 18:20:23 -0800 Subject: [PATCH 348/602] Removed the BootKeyboardAPI layer of indirection --- .../src/HID-APIs/BootKeyboardAPI.h | 77 ---------- .../src/HID-APIs/BootKeyboardAPI.hpp | 144 ------------------ .../src/SingleReport/BootKeyboard.cpp | 122 ++++++++++++++- .../src/SingleReport/BootKeyboard.h | 47 +++++- 4 files changed, 166 insertions(+), 224 deletions(-) delete mode 100644 plugins/KeyboardioHID/src/HID-APIs/BootKeyboardAPI.h delete mode 100644 plugins/KeyboardioHID/src/HID-APIs/BootKeyboardAPI.hpp diff --git a/plugins/KeyboardioHID/src/HID-APIs/BootKeyboardAPI.h b/plugins/KeyboardioHID/src/HID-APIs/BootKeyboardAPI.h deleted file mode 100644 index bbf1ebd473..0000000000 --- a/plugins/KeyboardioHID/src/HID-APIs/BootKeyboardAPI.h +++ /dev/null @@ -1,77 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 guard -#pragma once - -#include "KeyboardAPI.h" -#include "ConsumerAPI.h" - -typedef union{ - // Low level key report: up to 6 keys and shift, ctrl etc at once - uint8_t whole8[]; - uint16_t whole16[]; - uint32_t whole32[]; - struct{ - uint8_t modifiers; - uint8_t reserved; - KeyboardKeycode keycodes[6]; - }; - uint8_t keys[8]; -} HID_KeyboardReport_Data_t; - - -class BootKeyboardAPI : public KeyboardAPI -{ -public: - // Add special consumer key API for the reserved byte - inline size_t write(ConsumerKeycode k); - inline size_t press(ConsumerKeycode k); - inline size_t release(ConsumerKeycode k); - inline size_t add(ConsumerKeycode k); - inline size_t remove(ConsumerKeycode k); - - // Also use the base class functions - // http://en.cppreference.com/w/cpp/language/using_declaration - using KeyboardAPI::write; - using KeyboardAPI::press; - using KeyboardAPI::release; - using KeyboardAPI::add; - using KeyboardAPI::remove; - - // Implement adding/removing key functions - inline virtual size_t removeAll(void) override; - - // Needs to be implemented in a lower level - virtual int send(void) = 0; - -protected: - HID_KeyboardReport_Data_t _keyReport; - -private: - inline virtual size_t set(KeyboardKeycode k, bool s) override; -}; - -// Implementation is inline -#include "BootKeyboardAPI.hpp" - diff --git a/plugins/KeyboardioHID/src/HID-APIs/BootKeyboardAPI.hpp b/plugins/KeyboardioHID/src/HID-APIs/BootKeyboardAPI.hpp deleted file mode 100644 index d20718d711..0000000000 --- a/plugins/KeyboardioHID/src/HID-APIs/BootKeyboardAPI.hpp +++ /dev/null @@ -1,144 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 guard -#pragma once - - -size_t BootKeyboardAPI::set(KeyboardKeycode k, bool s) -{ - // It's a modifier key - if(k >= KEY_LEFT_CTRL && k <= KEY_RIGHT_GUI) - { - // Convert key into bitfield (0 - 7) - k = KeyboardKeycode(uint8_t(k) - uint8_t(KEY_LEFT_CTRL)); - if(s){ - _keyReport.modifiers = (1 << k); - } - else{ - _keyReport.modifiers &= ~(1 << k); - } - return 1; - } - // Its a normal key - else{ - // Add k to the key report only if it's not already present - // and if there is an empty slot. Remove the first available key. - for (uint8_t i = 0; i < sizeof(_keyReport.keycodes); i++) - { - auto key = _keyReport.keycodes[i]; - - // Is key already in the list or did we found an empty slot? - if (s && (key == uint8_t(k) || key == KEY_RESERVED)) { - _keyReport.keycodes[i] = k; - return 1; - } - - // Test the key report to see if k is present. Clear it if it exists. - if (!s && (key == k)) { - _keyReport.keycodes[i] = KEY_RESERVED; - return 1; - } - } - } - - // No empty/pressed key was found - return 0; -} - -size_t BootKeyboardAPI::removeAll(void) -{ - // Release all keys - size_t ret = 0; - for (uint8_t i = 0; i < sizeof(_keyReport.keys); i++) - { - // Is a key in the list or did we found an empty slot? - if(_keyReport.keys[i]){ - ret++; - } - _keyReport.keys[i] = 0x00; - } - return ret; -} - - -size_t BootKeyboardAPI::write(ConsumerKeycode k) -{ - // Press and release key (if press was successfull) - auto ret = press(k); - if(ret){ - release(k); - } - return ret; -} - - -size_t BootKeyboardAPI::press(ConsumerKeycode k) -{ - // Press key and send report to host - auto ret = add(k); - if(ret){ - send(); - } - return ret; -} - - -size_t BootKeyboardAPI::release(ConsumerKeycode k) -{ - // Release key and send report to host - auto ret = remove(k); - if(ret){ - send(); - } - return ret; -} - - -size_t BootKeyboardAPI::add(ConsumerKeycode k) -{ - // No 2 byte keys are supported - if(k > 0xFF){ - setWriteError(); - return 0; - } - - // Place the key inside the reserved keyreport position. - // This does not work on Windows. - _keyReport.reserved = k; - return 1; -} - - -size_t BootKeyboardAPI::remove(ConsumerKeycode k) -{ - // No 2 byte keys are supported - if(k > 0xFF){ - return 0; - } - - // Always release the key, to make it simpler releasing a consumer key - // without releasing all other normal keyboard keys. - _keyReport.reserved = HID_CONSUMER_UNASSIGNED; - return 1; -} diff --git a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp index 0261b411f3..2cec858314 100644 --- a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp @@ -200,6 +200,126 @@ void BootKeyboard_::wakeupHost(void){ } -BootKeyboard_ BootKeyboard; + + +size_t BootKeyboard_::set(KeyboardKeycode k, bool s) +{ + // It's a modifier key + if(k >= KEY_LEFT_CTRL && k <= KEY_RIGHT_GUI) + { + // Convert key into bitfield (0 - 7) + k = KeyboardKeycode(uint8_t(k) - uint8_t(KEY_LEFT_CTRL)); + if(s){ + _keyReport.modifiers = (1 << k); + } + else{ + _keyReport.modifiers &= ~(1 << k); + } + return 1; + } + // Its a normal key + else{ + // Add k to the key report only if it's not already present + // and if there is an empty slot. Remove the first available key. + for (uint8_t i = 0; i < sizeof(_keyReport.keycodes); i++) + { + auto key = _keyReport.keycodes[i]; + + // Is key already in the list or did we found an empty slot? + if (s && (key == uint8_t(k) || key == KEY_RESERVED)) { + _keyReport.keycodes[i] = k; + return 1; + } + + // Test the key report to see if k is present. Clear it if it exists. + if (!s && (key == k)) { + _keyReport.keycodes[i] = KEY_RESERVED; + return 1; + } + } + } + + // No empty/pressed key was found + return 0; +} + +size_t BootKeyboard_::removeAll(void) +{ + // Release all keys + size_t ret = 0; + for (uint8_t i = 0; i < sizeof(_keyReport.keys); i++) + { + // Is a key in the list or did we found an empty slot? + if(_keyReport.keys[i]){ + ret++; + } + _keyReport.keys[i] = 0x00; + } + return ret; +} + + +size_t BootKeyboard_::write(ConsumerKeycode k) +{ + // Press and release key (if press was successfull) + auto ret = press(k); + if(ret){ + release(k); + } + return ret; +} + + +size_t BootKeyboard_::press(ConsumerKeycode k) +{ + // Press key and send report to host + auto ret = add(k); + if(ret){ + send(); + } + return ret; +} + + +size_t BootKeyboard_::release(ConsumerKeycode k) +{ + // Release key and send report to host + auto ret = remove(k); + if(ret){ + send(); + } + return ret; +} + + +size_t BootKeyboard_::add(ConsumerKeycode k) +{ + // No 2 byte keys are supported + if(k > 0xFF){ + setWriteError(); + return 0; + } + + // Place the key inside the reserved keyreport position. + // This does not work on Windows. + _keyReport.reserved = k; + return 1; +} + + +size_t BootKeyboard_::remove(ConsumerKeycode k) +{ + // No 2 byte keys are supported + if(k > 0xFF){ + return 0; + } + + // Always release the key, to make it simpler releasing a consumer key + // without releasing all other normal keyboard keys. + _keyReport.reserved = HID_CONSUMER_UNASSIGNED; + return 1; +} + +BootKeyboard_ BootKeyboard; diff --git a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h index 511b3ba5a2..14156b42ad 100644 --- a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h @@ -28,13 +28,52 @@ THE SOFTWARE. #include "PluggableUSB.h" #include "HID.h" #include "HID-Settings.h" -#include "../HID-APIs/BootKeyboardAPI.h" +#include "../HID-APIs/KeyboardAPI.h" +#include "../HID-APIs/ConsumerAPI.h" -class BootKeyboard_ : public PluggableUSBModule, public BootKeyboardAPI +typedef union{ + // Low level key report: up to 6 keys and shift, ctrl etc at once + uint8_t whole8[]; + uint16_t whole16[]; + uint32_t whole32[]; + struct{ + uint8_t modifiers; + uint8_t reserved; + KeyboardKeycode keycodes[6]; + }; + uint8_t keys[8]; +} HID_KeyboardReport_Data_t; + + +class BootKeyboard_ : public PluggableUSBModule, public KeyboardAPI { public: BootKeyboard_(void); + + // Add special consumer key API for the reserved byte + inline size_t write(ConsumerKeycode k); + inline size_t press(ConsumerKeycode k); + inline size_t release(ConsumerKeycode k); + inline size_t add(ConsumerKeycode k); + inline size_t remove(ConsumerKeycode k); + + // Also use the base class functions + // http://en.cppreference.com/w/cpp/language/using_declaration + using KeyboardAPI::write; + using KeyboardAPI::press; + using KeyboardAPI::release; + using KeyboardAPI::add; + using KeyboardAPI::remove; + + // Implement adding/removing key functions + inline virtual size_t removeAll(void) override; + + // Needs to be implemented in a lower level + virtual int send(void) = 0; + + + uint8_t getLeds(void); uint8_t getProtocol(void); void wakeupHost(void); @@ -67,6 +106,8 @@ class BootKeyboard_ : public PluggableUSBModule, public BootKeyboardAPI virtual int send(void) final; protected: + HID_KeyboardReport_Data_t _keyReport; + // Implementation of the PUSBListNode int getInterface(uint8_t* interfaceCount); int getDescriptor(USBSetup& setup); @@ -80,6 +121,8 @@ class BootKeyboard_ : public PluggableUSBModule, public BootKeyboardAPI uint8_t* featureReport; int featureLength; +private: + inline virtual size_t set(KeyboardKeycode k, bool s) override; }; extern BootKeyboard_ BootKeyboard; From 81650f1f324638ee138c5b9a1c7fb6d73e4fc205 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Wed, 9 Dec 2015 19:05:09 -0800 Subject: [PATCH 349/602] Remove API indirection for AbsoluteMouse --- .../src/HID-APIs/AbsoluteMouseAPI.h | 82 -------------- .../src/HID-APIs/AbsoluteMouseAPI.hpp | 106 ------------------ .../src/MultiReport/AbsoluteMouse.cpp | 83 ++++++++++++++ .../src/MultiReport/AbsoluteMouse.h | 52 ++++++++- 4 files changed, 133 insertions(+), 190 deletions(-) delete mode 100644 plugins/KeyboardioHID/src/HID-APIs/AbsoluteMouseAPI.h delete mode 100644 plugins/KeyboardioHID/src/HID-APIs/AbsoluteMouseAPI.hpp diff --git a/plugins/KeyboardioHID/src/HID-APIs/AbsoluteMouseAPI.h b/plugins/KeyboardioHID/src/HID-APIs/AbsoluteMouseAPI.h deleted file mode 100644 index 37a6ee87a8..0000000000 --- a/plugins/KeyboardioHID/src/HID-APIs/AbsoluteMouseAPI.h +++ /dev/null @@ -1,82 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 guard -#pragma once - -#include -#include "HID-Settings.h" - -#define MOUSE_LEFT (1 << 0) -#define MOUSE_RIGHT (1 << 1) -#define MOUSE_MIDDLE (1 << 2) -#define MOUSE_PREV (1 << 3) -#define MOUSE_NEXT (1 << 4) -// actually this mouse report has 8 buttons (for smaller descriptor) -// but the last 3 wont do anything from what I tested -#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE | MOUSE_PREV | MOUSE_NEXT) - - -typedef union{ - // Absolute mouse report: 8 buttons, 2 absolute axis, wheel - uint8_t whole8[]; - uint16_t whole16[]; - uint32_t whole32[]; - struct{ - uint8_t buttons; - int16_t xAxis; - int16_t yAxis; - int8_t wheel; - }; -} HID_MouseAbsoluteReport_Data_t; - - -class AbsoluteMouseAPI -{ -protected: - int16_t xAxis; - int16_t yAxis; - uint8_t _buttons; - inline void buttons(uint8_t b); - - inline int16_t qadd16(int16_t base, int16_t increment); - -public: - inline AbsoluteMouseAPI(void); - inline void begin(void); - inline void end(void); - - inline void click(uint8_t b = MOUSE_LEFT); - inline void moveTo(int x, int y, signed char wheel = 0); - inline void move(int x, int y, signed char wheel = 0); - inline void press(uint8_t b = MOUSE_LEFT); - inline void release(uint8_t b = MOUSE_LEFT); - inline bool isPressed(uint8_t b = MOUSE_LEFT); - - // Sending is public in the base class for advanced users. - virtual void SendReport(void* data, int length) = 0; -}; - -// Implementation is inline -#include "AbsoluteMouseAPI.hpp" - diff --git a/plugins/KeyboardioHID/src/HID-APIs/AbsoluteMouseAPI.hpp b/plugins/KeyboardioHID/src/HID-APIs/AbsoluteMouseAPI.hpp deleted file mode 100644 index 23f736eac8..0000000000 --- a/plugins/KeyboardioHID/src/HID-APIs/AbsoluteMouseAPI.hpp +++ /dev/null @@ -1,106 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 guard -#pragma once - -void AbsoluteMouseAPI::buttons(uint8_t b){ - if (b != _buttons){ - _buttons = b; - moveTo(xAxis, yAxis, 0); - } -} - -int16_t AbsoluteMouseAPI::qadd16(int16_t base, int16_t increment) { - // Separate between subtracting and adding - if (increment < 0) { - // Subtracting more would cause an undefined overflow - if ((int16_t)0x8000 - increment > base) - base = 0x8000; - else - base += increment; - } - else { - // Adding more would cause an undefined overflow - if ((int16_t)0x7FFF - increment < base) - base = 0x7FFF; - else - base += increment; - } - return base; -} - -AbsoluteMouseAPI::AbsoluteMouseAPI(void): -xAxis(0), yAxis(0), _buttons(0) -{ - // Empty -} - -void AbsoluteMouseAPI::begin(void){ - // release all buttons - end(); -} - -void AbsoluteMouseAPI::end(void){ - _buttons = 0; - moveTo(xAxis, yAxis, 0); -} - -void AbsoluteMouseAPI::click(uint8_t b){ - _buttons = b; - moveTo(xAxis, yAxis, 0); - _buttons = 0; - moveTo(xAxis, yAxis, 0); -} - -void AbsoluteMouseAPI::moveTo(int x, int y, signed char wheel){ - xAxis = x; - yAxis = y; - HID_MouseAbsoluteReport_Data_t report; - report.buttons = _buttons; - report.xAxis = x; - report.yAxis = y; - report.wheel = wheel; - SendReport(&report, sizeof(report)); -} - -void AbsoluteMouseAPI::move(int x, int y, signed char wheel){ - moveTo(qadd16(xAxis, x), qadd16(yAxis, y), wheel); -} - -void AbsoluteMouseAPI::press(uint8_t b){ - // press LEFT by default - buttons(_buttons | b); -} - -void AbsoluteMouseAPI::release(uint8_t b){ - // release LEFT by default - buttons(_buttons & ~b); -} - -bool AbsoluteMouseAPI::isPressed(uint8_t b){ - // check LEFT by default - if ((b & _buttons) > 0) - return true; - return false; -} diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp index b8179bceb2..d5705eadea 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp @@ -75,5 +75,88 @@ void AbsoluteMouse_::SendReport(void* data, int length) HID().SendReport(HID_REPORTID_MOUSE_ABSOLUTE, data, length); } + +void AbsoluteMouse_::buttons(uint8_t b){ + if (b != _buttons){ + _buttons = b; + moveTo(xAxis, yAxis, 0); + } +} + +int16_t AbsoluteMouse_::qadd16(int16_t base, int16_t increment) { + // Separate between subtracting and adding + if (increment < 0) { + // Subtracting more would cause an undefined overflow + if ((int16_t)0x8000 - increment > base) + base = 0x8000; + else + base += increment; + } + else { + // Adding more would cause an undefined overflow + if ((int16_t)0x7FFF - increment < base) + base = 0x7FFF; + else + base += increment; + } + return base; +} + +AbsoluteMouse_::AbsoluteMouseAPI(void): +xAxis(0), yAxis(0), _buttons(0) +{ + // Empty +} + +void AbsoluteMouse_::begin(void){ + // release all buttons + end(); +} + +void AbsoluteMouse_::end(void){ + _buttons = 0; + moveTo(xAxis, yAxis, 0); +} + +void AbsoluteMouse_::click(uint8_t b){ + _buttons = b; + moveTo(xAxis, yAxis, 0); + _buttons = 0; + moveTo(xAxis, yAxis, 0); +} + +void AbsoluteMouse_::moveTo(int x, int y, signed char wheel){ + xAxis = x; + yAxis = y; + HID_MouseAbsoluteReport_Data_t report; + report.buttons = _buttons; + report.xAxis = x; + report.yAxis = y; + report.wheel = wheel; + SendReport(&report, sizeof(report)); +} + +void AbsoluteMouse_::move(int x, int y, signed char wheel){ + moveTo(qadd16(xAxis, x), qadd16(yAxis, y), wheel); +} + +void AbsoluteMouse_::press(uint8_t b){ + // press LEFT by default + buttons(_buttons | b); +} + +void AbsoluteMouse_::release(uint8_t b){ + // release LEFT by default + buttons(_buttons & ~b); +} + +bool AbsoluteMouse_::isPressed(uint8_t b){ + // check LEFT by default + if ((b & _buttons) > 0) + return true; + return false; +} + + AbsoluteMouse_ AbsoluteMouse; diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h index be0c2d90aa..1be3d765eb 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h @@ -28,16 +28,64 @@ THE SOFTWARE. #include "PluggableUSB.h" #include "HID.h" #include "HID-Settings.h" -#include "../HID-APIs/AbsoluteMouseAPI.h" +#define MOUSE_LEFT (1 << 0) +#define MOUSE_RIGHT (1 << 1) +#define MOUSE_MIDDLE (1 << 2) +#define MOUSE_PREV (1 << 3) +#define MOUSE_NEXT (1 << 4) +// actually this mouse report has 8 buttons (for smaller descriptor) +// but the last 3 wont do anything from what I tested +#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE | MOUSE_PREV | MOUSE_NEXT) -class AbsoluteMouse_ : public AbsoluteMouseAPI + + +typedef union{ + // Absolute mouse report: 8 buttons, 2 absolute axis, wheel + uint8_t whole8[]; + uint16_t whole16[]; + uint32_t whole32[]; + struct{ + uint8_t buttons; + int16_t xAxis; + int16_t yAxis; + int8_t wheel; + }; +} HID_MouseAbsoluteReport_Data_t; + +class AbsoluteMouse_ { public: AbsoluteMouse_(void); protected: virtual inline void SendReport(void* data, int length) override; + int16_t xAxis; + int16_t yAxis; + uint8_t _buttons; + inline void buttons(uint8_t b); + + inline int16_t qadd16(int16_t base, int16_t increment); + +public: + AbsoluteMouse_(void); + inline void begin(void); + inline void end(void); + + inline void click(uint8_t b = MOUSE_LEFT); + inline void moveTo(int x, int y, signed char wheel = 0); + inline void move(int x, int y, signed char wheel = 0); + inline void press(uint8_t b = MOUSE_LEFT); + inline void release(uint8_t b = MOUSE_LEFT); + inline bool isPressed(uint8_t b = MOUSE_LEFT); + + // Sending is public in the base class for advanced users. + virtual void SendReport(void* data, int length) = 0; + + + }; + + extern AbsoluteMouse_ AbsoluteMouse; From 53332a410fa14f9fd094ae2686f939fabad4eb0b Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Wed, 9 Dec 2015 19:05:23 -0800 Subject: [PATCH 350/602] Fixup mis-refactor of boot keyboard --- plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h index 14156b42ad..327ed098dd 100644 --- a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h @@ -69,8 +69,7 @@ class BootKeyboard_ : public PluggableUSBModule, public KeyboardAPI // Implement adding/removing key functions inline virtual size_t removeAll(void) override; - // Needs to be implemented in a lower level - virtual int send(void) = 0; + int send(void); @@ -103,7 +102,6 @@ class BootKeyboard_ : public PluggableUSBModule, public KeyboardAPI featureLength |= 0x8000; } - virtual int send(void) final; protected: HID_KeyboardReport_Data_t _keyReport; From c906ea1080a7897229f7d821931d76fe340c8bd9 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Wed, 9 Dec 2015 19:06:32 -0800 Subject: [PATCH 351/602] fixup mismerge of AbsoluteMouse --- plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp index d5705eadea..1424af4010 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp @@ -102,7 +102,6 @@ int16_t AbsoluteMouse_::qadd16(int16_t base, int16_t increment) { return base; } -AbsoluteMouse_::AbsoluteMouseAPI(void): xAxis(0), yAxis(0), _buttons(0) { // Empty From e906014309ee3db64da77884f30258ce44069afc Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Wed, 9 Dec 2015 19:13:58 -0800 Subject: [PATCH 352/602] Remove layer of indirection from SystemControl --- .../KeyboardioHID/src/HID-APIs/SystemAPI.h | 98 ------------------- .../KeyboardioHID/src/HID-APIs/SystemAPI.hpp | 63 ------------ .../KeyboardioHID/src/MultiReport/System.cpp | 45 +++++++++ .../KeyboardioHID/src/MultiReport/System.h | 68 ++++++++++++- 4 files changed, 110 insertions(+), 164 deletions(-) delete mode 100644 plugins/KeyboardioHID/src/HID-APIs/SystemAPI.h delete mode 100644 plugins/KeyboardioHID/src/HID-APIs/SystemAPI.hpp diff --git a/plugins/KeyboardioHID/src/HID-APIs/SystemAPI.h b/plugins/KeyboardioHID/src/HID-APIs/SystemAPI.h deleted file mode 100644 index e27abacdff..0000000000 --- a/plugins/KeyboardioHID/src/HID-APIs/SystemAPI.h +++ /dev/null @@ -1,98 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 guard -#pragma once - -#include -#include "HID-Settings.h" - -enum SystemKeycode : uint8_t { - SYSTEM_POWER_DOWN = 0x81, - SYSTEM_SLEEP = 0x82, - SYSTEM_WAKE_UP = 0x83, - - // System control mappings - HID_SYSTEM_UNASSIGNED = 0x00, - HID_SYSTEM_POWER_DOWN = 0x81, // HID type OSC - HID_SYSTEM_SLEEP = 0x82, // HID type OSC - HID_SYSTEM_WAKE_UP = 0x83, // HID type OSC - HID_SYSTEM_CONTEXT_MENU = 0x84, // HID type OSC - HID_SYSTEM_MAIN_MENU = 0x85, // HID type OSC - HID_SYSTEM_APP_MENU = 0x86, // HID type OSC - HID_SYSTEM_MENU_HELP = 0x87, // HID type OSC - HID_SYSTEM_MENU_EXIT = 0x88, // HID type OSC - HID_SYSTEM_MENU_SELECT = 0x89, // HID type OSC - HID_SYSTEM_MENU_RIGHT = 0x8A, // HID type RTC - HID_SYSTEM_MENU_LEFT = 0x8B, // HID type RTC - HID_SYSTEM_MENU_UP = 0x8C, // HID type RTC - HID_SYSTEM_MENU_DOWN = 0x8D, // HID type RTC - HID_SYSTEM_COLD_RESTART = 0x8E, // HID type OSC - HID_SYSTEM_WARM_RESTART = 0x8F, // HID type OSC - HID_D_PAD_UP = 0x90, // HID type OOC - HID_D_PAD_DOWN = 0x91, // HID type OOC - HID_D_PAD_RIGHT = 0x92, // HID type OOC - HID_D_PAD_LEFT = 0x93, // HID type OOC - // 0x94-0x9F are reserved - HID_SYSTEM_DOCK = 0xA0, // HID type OSC - HID_SYSTEM_UNDOCK = 0xA1, // HID type OSC - HID_SYSTEM_SETUP = 0xA2, // HID type OSC - HID_SYSTEM_BREAK = 0xA3, // HID type OSC - HID_SYSTEM_DEBUGGER_BREAK = 0xA4, // HID type OSC - HID_APPLICATION_BREAK = 0xA5, // HID type OSC - HID_APPLICATION_DEBUGGER_BREAK = 0xA6, // HID type OSC - HID_SYSTEM_SPEAKER_MUTE = 0xA7, // HID type OSC - HID_SYSTEM_HIBERNATE = 0xA8, // HID type OSC - // 0xA9-0xAF are reserved - HID_SYSTEM_DISPLAY_INVERT = 0xB0, // HID type OSC - HID_SYSTEM_DISPLAY_INTERNAL = 0xB1, // HID type OSC - HID_SYSTEM_DISPLAY_EXTERNAL = 0xB2, // HID type OSC - HID_SYSTEM_DISPLAY_BOTH = 0xB3, // HID type OSC - HID_SYSTEM_DISPLAY_DUAL = 0xB4, // HID type OSC - HID_SYSTEM_DISPLAY_TOGGLE_INT_SLASH_EXT = 0xB5, // HID type OSC - HID_SYSTEM_DISPLAY_SWAP_PRIMARY_SLASH_SECONDARY = 0xB6, // HID type OSC - HID_SYSTEM_DISPLAY_LCD_AUTOSCALE = 0xB7, // HID type OSC -}; - -typedef union{ - // Every usable system control key possible - uint8_t whole8[]; - uint8_t key; -} HID_SystemControlReport_Data_t; - -class SystemAPI{ -public: - inline SystemAPI(void); - inline void begin(void); - inline void end(void); - inline void write(SystemKeycode s); - inline void press(SystemKeycode s); - inline void release(void); - inline void releaseAll(void); - - // Sending is public in the base class for advanced users. - virtual void SendReport(void* data, int length) = 0; -}; - -// Implementation is inline -#include "SystemAPI.hpp" diff --git a/plugins/KeyboardioHID/src/HID-APIs/SystemAPI.hpp b/plugins/KeyboardioHID/src/HID-APIs/SystemAPI.hpp deleted file mode 100644 index edb9775343..0000000000 --- a/plugins/KeyboardioHID/src/HID-APIs/SystemAPI.hpp +++ /dev/null @@ -1,63 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 guard -#pragma once - -SystemAPI::SystemAPI(void) -{ - // Empty -} - -void SystemAPI::begin(void){ - // release all buttons - end(); -} - -void SystemAPI::end(void){ - SystemKeycode _report = HID_SYSTEM_UNASSIGNED; - SendReport(&_report, sizeof(_report)); -} - -void SystemAPI::write(SystemKeycode s){ - press(s); - release(); -} - -void SystemAPI::release(void){ - begin(); -} - -void SystemAPI::releaseAll(void){ - begin(); -} - -void SystemAPI::press(SystemKeycode s){ -#ifdef USBCON - if (s == SYSTEM_WAKE_UP) - USBDevice.wakeupHost(); - else -#endif - SendReport(&s, sizeof(s)); -} - diff --git a/plugins/KeyboardioHID/src/MultiReport/System.cpp b/plugins/KeyboardioHID/src/MultiReport/System.cpp index 6ba4ab40a6..e1717423f5 100644 --- a/plugins/KeyboardioHID/src/MultiReport/System.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/System.cpp @@ -48,6 +48,38 @@ System_::System_(void) HID().AppendDescriptor(&node); } +void System_::begin(void){ + // release all buttons + end(); +} + +void System_::end(void){ + SystemKeycode _report = HID_SYSTEM_UNASSIGNED; + SendReport(&_report, sizeof(_report)); +} + +void System_::write(SystemKeycode s){ + press(s); + release(); +} + +void System_::release(void){ + begin(); +} + +void System_::releaseAll(void){ + begin(); +} + +void System_::press(SystemKeycode s){ +#ifdef USBCON + if (s == SYSTEM_WAKE_UP) + USBDevice.wakeupHost(); + else +#endif + SendReport(&s, sizeof(s)); +} + void System_::SendReport(void* data, int length) { @@ -56,3 +88,16 @@ void System_::SendReport(void* data, int length) System_ System; + + + + + + + + + + + + + diff --git a/plugins/KeyboardioHID/src/MultiReport/System.h b/plugins/KeyboardioHID/src/MultiReport/System.h index a2336e8c10..f344a2462f 100644 --- a/plugins/KeyboardioHID/src/MultiReport/System.h +++ b/plugins/KeyboardioHID/src/MultiReport/System.h @@ -28,16 +28,78 @@ THE SOFTWARE. #include "PluggableUSB.h" #include "HID.h" #include "HID-Settings.h" -#include "../HID-APIs/SystemAPI.h" +enum SystemKeycode : uint8_t { + SYSTEM_POWER_DOWN = 0x81, + SYSTEM_SLEEP = 0x82, + SYSTEM_WAKE_UP = 0x83, -class System_ : public SystemAPI + // System control mappings + HID_SYSTEM_UNASSIGNED = 0x00, + HID_SYSTEM_POWER_DOWN = 0x81, // HID type OSC + HID_SYSTEM_SLEEP = 0x82, // HID type OSC + HID_SYSTEM_WAKE_UP = 0x83, // HID type OSC + HID_SYSTEM_CONTEXT_MENU = 0x84, // HID type OSC + HID_SYSTEM_MAIN_MENU = 0x85, // HID type OSC + HID_SYSTEM_APP_MENU = 0x86, // HID type OSC + HID_SYSTEM_MENU_HELP = 0x87, // HID type OSC + HID_SYSTEM_MENU_EXIT = 0x88, // HID type OSC + HID_SYSTEM_MENU_SELECT = 0x89, // HID type OSC + HID_SYSTEM_MENU_RIGHT = 0x8A, // HID type RTC + HID_SYSTEM_MENU_LEFT = 0x8B, // HID type RTC + HID_SYSTEM_MENU_UP = 0x8C, // HID type RTC + HID_SYSTEM_MENU_DOWN = 0x8D, // HID type RTC + HID_SYSTEM_COLD_RESTART = 0x8E, // HID type OSC + HID_SYSTEM_WARM_RESTART = 0x8F, // HID type OSC + HID_D_PAD_UP = 0x90, // HID type OOC + HID_D_PAD_DOWN = 0x91, // HID type OOC + HID_D_PAD_RIGHT = 0x92, // HID type OOC + HID_D_PAD_LEFT = 0x93, // HID type OOC + // 0x94-0x9F are reserved + HID_SYSTEM_DOCK = 0xA0, // HID type OSC + HID_SYSTEM_UNDOCK = 0xA1, // HID type OSC + HID_SYSTEM_SETUP = 0xA2, // HID type OSC + HID_SYSTEM_BREAK = 0xA3, // HID type OSC + HID_SYSTEM_DEBUGGER_BREAK = 0xA4, // HID type OSC + HID_APPLICATION_BREAK = 0xA5, // HID type OSC + HID_APPLICATION_DEBUGGER_BREAK = 0xA6, // HID type OSC + HID_SYSTEM_SPEAKER_MUTE = 0xA7, // HID type OSC + HID_SYSTEM_HIBERNATE = 0xA8, // HID type OSC + // 0xA9-0xAF are reserved + HID_SYSTEM_DISPLAY_INVERT = 0xB0, // HID type OSC + HID_SYSTEM_DISPLAY_INTERNAL = 0xB1, // HID type OSC + HID_SYSTEM_DISPLAY_EXTERNAL = 0xB2, // HID type OSC + HID_SYSTEM_DISPLAY_BOTH = 0xB3, // HID type OSC + HID_SYSTEM_DISPLAY_DUAL = 0xB4, // HID type OSC + HID_SYSTEM_DISPLAY_TOGGLE_INT_SLASH_EXT = 0xB5, // HID type OSC + HID_SYSTEM_DISPLAY_SWAP_PRIMARY_SLASH_SECONDARY = 0xB6, // HID type OSC + HID_SYSTEM_DISPLAY_LCD_AUTOSCALE = 0xB7, // HID type OSC +}; + +typedef union{ + // Every usable system control key possible + uint8_t whole8[]; + uint8_t key; +} HID_SystemControlReport_Data_t; + + +class System_ { public: + inline void begin(void); + inline void end(void); + inline void write(SystemKeycode s); + inline void press(SystemKeycode s); + inline void release(void); + inline void releaseAll(void); + virtual void SendReport(void* data, int length) = 0; + System_(void); protected: - virtual inline void SendReport(void* data, int length) override; }; + + + extern System_ System; From 3298da97860df176b5cffa972964d42aa5b2d1ed Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Wed, 9 Dec 2015 19:20:50 -0800 Subject: [PATCH 353/602] Remove layer of indirection from NKROKeyboard --- .../src/HID-APIs/NKROKeyboardAPI.h | 65 ------------ .../src/HID-APIs/NKROKeyboardAPI.hpp | 98 ------------------- .../src/MultiReport/NKROKeyboard.cpp | 71 ++++++++++++++ .../src/MultiReport/NKROKeyboard.h | 34 ++++++- 4 files changed, 102 insertions(+), 166 deletions(-) delete mode 100644 plugins/KeyboardioHID/src/HID-APIs/NKROKeyboardAPI.h delete mode 100644 plugins/KeyboardioHID/src/HID-APIs/NKROKeyboardAPI.hpp diff --git a/plugins/KeyboardioHID/src/HID-APIs/NKROKeyboardAPI.h b/plugins/KeyboardioHID/src/HID-APIs/NKROKeyboardAPI.h deleted file mode 100644 index 7dafbd7a04..0000000000 --- a/plugins/KeyboardioHID/src/HID-APIs/NKROKeyboardAPI.h +++ /dev/null @@ -1,65 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 guard -#pragma once - -#include "KeyboardAPI.h" - -// Max value for USB EP_SIZE 16 -// +1 reportID, +1 modifier, +1 custom key -#define NKRO_KEY_COUNT (8*13) - -typedef union{ - // Modifier + keymap + 1 custom key - uint8_t whole8[]; - uint16_t whole16[]; - uint32_t whole32[]; - struct{ - uint8_t modifiers; - uint8_t keys[NKRO_KEY_COUNT / 8]; - uint8_t key; - }; - uint8_t allkeys[2 + NKRO_KEY_COUNT / 8]; -} HID_NKROKeyboardReport_Data_t; - - -class NKROKeyboardAPI : public KeyboardAPI -{ -public: - // Implement adding/removing key functions - inline virtual size_t removeAll(void) override; - - // Needs to be implemented in a lower level - virtual int send(void) = 0; - -protected: - HID_NKROKeyboardReport_Data_t _keyReport; - -private: - inline virtual size_t set(KeyboardKeycode k, bool s) override; -}; - -// Implementation is inline -#include "NKROKeyboardAPI.hpp" - diff --git a/plugins/KeyboardioHID/src/HID-APIs/NKROKeyboardAPI.hpp b/plugins/KeyboardioHID/src/HID-APIs/NKROKeyboardAPI.hpp deleted file mode 100644 index 44e04b3752..0000000000 --- a/plugins/KeyboardioHID/src/HID-APIs/NKROKeyboardAPI.hpp +++ /dev/null @@ -1,98 +0,0 @@ -/* -Copyright (c) 2015 NicoHood -See the readme for credit to other people. - -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 guard -#pragma once - - -size_t NKROKeyboardAPI::set(KeyboardKeycode k, bool s) -{ - // Press keymap key - if (k < NKRO_KEY_COUNT){ - uint8_t bit = 1 << (uint8_t(k) % 8); - if(s){ - _keyReport.keys[k / 8] |= bit; - } - else{ - _keyReport.keys[k / 8] &= ~bit; - } - return 1; - } - - // It's a modifier key - else if(k >= KEY_LEFT_CTRL && k <= KEY_RIGHT_GUI) - { - // Convert key into bitfield (0 - 7) - k = KeyboardKeycode(uint8_t(k) - uint8_t(KEY_LEFT_CTRL)); - if(s){ - _keyReport.modifiers = (1 << k); - } - else{ - _keyReport.modifiers &= ~(1 << k); - } - return 1; - } - - // Its a custom key (outside our keymap) - else{ - // Add k to the key report only if it's not already present - // and if there is an empty slot. Remove the first available key. - auto key = _keyReport.key; - - // Is key already in the list or did we found an empty slot? - if (s && (key == uint8_t(k) || key == KEY_RESERVED)) { - _keyReport.key = k; - return 1; - } - - // Test the key report to see if k is present. Clear it if it exists. - if (!s && (key == k)) { - _keyReport.key = KEY_RESERVED; - return 1; - } - } - - // No empty/pressed key was found - return 0; -} - -size_t NKROKeyboardAPI::removeAll(void) -{ - // Release all keys - size_t ret = 0; - for (uint8_t i = 0; i < sizeof(_keyReport.allkeys); i++) - { - // Is a key in the list or did we found an empty slot? - auto bits = _keyReport.allkeys[i]; - do { - if(bits & 0x01){ - ret++; - } - bits >>=1; - } - while(bits); - _keyReport.allkeys[i] = 0x00; - } - return ret; -} - diff --git a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp index 27c2148721..6667baecb2 100644 --- a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp @@ -73,5 +73,76 @@ int NKROKeyboard_::send(void) return HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &_keyReport, sizeof(_keyReport)); } +size_t NKROKeyboard_::set(KeyboardKeycode k, bool s) +{ + // Press keymap key + if (k < NKRO_KEY_COUNT){ + uint8_t bit = 1 << (uint8_t(k) % 8); + if(s){ + _keyReport.keys[k / 8] |= bit; + } + else{ + _keyReport.keys[k / 8] &= ~bit; + } + return 1; + } + + // It's a modifier key + else if(k >= KEY_LEFT_CTRL && k <= KEY_RIGHT_GUI) + { + // Convert key into bitfield (0 - 7) + k = KeyboardKeycode(uint8_t(k) - uint8_t(KEY_LEFT_CTRL)); + if(s){ + _keyReport.modifiers = (1 << k); + } + else{ + _keyReport.modifiers &= ~(1 << k); + } + return 1; + } + + // Its a custom key (outside our keymap) + else{ + // Add k to the key report only if it's not already present + // and if there is an empty slot. Remove the first available key. + auto key = _keyReport.key; + + // Is key already in the list or did we found an empty slot? + if (s && (key == uint8_t(k) || key == KEY_RESERVED)) { + _keyReport.key = k; + return 1; + } + + // Test the key report to see if k is present. Clear it if it exists. + if (!s && (key == k)) { + _keyReport.key = KEY_RESERVED; + return 1; + } + } + + // No empty/pressed key was found + return 0; +} + +size_t NKROKeyboard_::removeAll(void) +{ + // Release all keys + size_t ret = 0; + for (uint8_t i = 0; i < sizeof(_keyReport.allkeys); i++) + { + // Is a key in the list or did we found an empty slot? + auto bits = _keyReport.allkeys[i]; + do { + if(bits & 0x01){ + ret++; + } + bits >>=1; + } + while(bits); + _keyReport.allkeys[i] = 0x00; + } + return ret; +} + NKROKeyboard_ NKROKeyboard; diff --git a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h index ef5c9b4d4b..61221c6eaf 100644 --- a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h @@ -28,15 +28,43 @@ THE SOFTWARE. #include "PluggableUSB.h" #include "HID.h" #include "HID-Settings.h" -#include "../HID-APIs/NKROKeyboardAPI.h" +#include "../HID-APIs/KeyboardAPI.h" -class NKROKeyboard_ : public NKROKeyboardAPI +// Max value for USB EP_SIZE 16 +// +1 reportID, +1 modifier, +1 custom key +#define NKRO_KEY_COUNT (8*13) + +typedef union{ + // Modifier + keymap + 1 custom key + uint8_t whole8[]; + uint16_t whole16[]; + uint32_t whole32[]; + struct{ + uint8_t modifiers; + uint8_t keys[NKRO_KEY_COUNT / 8]; + uint8_t key; + }; + uint8_t allkeys[2 + NKRO_KEY_COUNT / 8]; +} HID_NKROKeyboardReport_Data_t; + + + +class NKROKeyboard_ : public KeyboardAPI { public: NKROKeyboard_(void); + // Implement adding/removing key functions + inline virtual size_t removeAll(void) override; + + // Needs to be implemented in a lower level + virtual int send(void) = 0; +protected: + HID_NKROKeyboardReport_Data_t _keyReport; + +private: + inline virtual size_t set(KeyboardKeycode k, bool s) override; - virtual int send(void) final; }; extern NKROKeyboard_ NKROKeyboard; From 751b234ff5ee9c83174b112816b74fd1dfd8f096 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Wed, 9 Dec 2015 19:36:08 -0800 Subject: [PATCH 354/602] Remove indirection from Gamepad code --- .../KeyboardioHID/src/HID-APIs/GamepadAPI.h | 130 ------------------ .../KeyboardioHID/src/HID-APIs/GamepadAPI.hpp | 104 -------------- .../KeyboardioHID/src/MultiReport/Gamepad.cpp | 74 ++++++++++ .../KeyboardioHID/src/MultiReport/Gamepad.h | 92 ++++++++++++- 4 files changed, 164 insertions(+), 236 deletions(-) delete mode 100644 plugins/KeyboardioHID/src/HID-APIs/GamepadAPI.h delete mode 100644 plugins/KeyboardioHID/src/HID-APIs/GamepadAPI.hpp diff --git a/plugins/KeyboardioHID/src/HID-APIs/GamepadAPI.h b/plugins/KeyboardioHID/src/HID-APIs/GamepadAPI.h deleted file mode 100644 index 13ea7b55e2..0000000000 --- a/plugins/KeyboardioHID/src/HID-APIs/GamepadAPI.h +++ /dev/null @@ -1,130 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 guard -#pragma once - -#include -#include "HID-Settings.h" - -// Dpad directions -#define GAMEPAD_DPAD_CENTERED 0 -#define GAMEPAD_DPAD_UP 1 -#define GAMEPAD_DPAD_UP_RIGHT 2 -#define GAMEPAD_DPAD_RIGHT 3 -#define GAMEPAD_DPAD_DOWN_RIGHT 4 -#define GAMEPAD_DPAD_DOWN 5 -#define GAMEPAD_DPAD_DOWN_LEFT 6 -#define GAMEPAD_DPAD_LEFT 7 -#define GAMEPAD_DPAD_UP_LEFT 8 - - -typedef union { - // 32 Buttons, 6 Axis, 2 D-Pads - uint8_t whole8[]; - uint16_t whole16[]; - uint32_t whole32[]; - uint32_t buttons; - - struct{ - uint8_t button1 : 1; - uint8_t button2 : 1; - uint8_t button3 : 1; - uint8_t button4 : 1; - uint8_t button5 : 1; - uint8_t button6 : 1; - uint8_t button7 : 1; - uint8_t button8 : 1; - - uint8_t button9 : 1; - uint8_t button10 : 1; - uint8_t button11 : 1; - uint8_t button12 : 1; - uint8_t button13 : 1; - uint8_t button14 : 1; - uint8_t button15 : 1; - uint8_t button16 : 1; - - uint8_t button17 : 1; - uint8_t button18 : 1; - uint8_t button19 : 1; - uint8_t button20 : 1; - uint8_t button21 : 1; - uint8_t button22 : 1; - uint8_t button23 : 1; - uint8_t button24 : 1; - - uint8_t button25 : 1; - uint8_t button26 : 1; - uint8_t button27 : 1; - uint8_t button28 : 1; - uint8_t button29 : 1; - uint8_t button30 : 1; - uint8_t button31 : 1; - uint8_t button32 : 1; - - int16_t xAxis; - int16_t yAxis; - - int16_t rxAxis; - int16_t ryAxis; - - int8_t zAxis; - int8_t rzAxis; - - uint8_t dPad1 : 4; - uint8_t dPad2 : 4; - }; -} HID_GamepadReport_Data_t; - -class GamepadAPI{ -public: - inline GamepadAPI(void); - - inline void begin(void); - inline void end(void); - inline void write(void); - inline void press(uint8_t b); - inline void release(uint8_t b); - inline void releaseAll(void); - - inline void buttons(uint32_t b); - inline void xAxis(int16_t a); - inline void yAxis(int16_t a); - inline void zAxis(int8_t a); - inline void rxAxis(int16_t a); - inline void ryAxis(int16_t a); - inline void rzAxis(int8_t a); - inline void dPad1(int8_t d); - inline void dPad2(int8_t d); - - // Sending is public in the base class for advanced users. - virtual void SendReport(void* data, int length) = 0; - -protected: - HID_GamepadReport_Data_t _report; -}; - -// Implementation is inline -#include "GamepadAPI.hpp" - diff --git a/plugins/KeyboardioHID/src/HID-APIs/GamepadAPI.hpp b/plugins/KeyboardioHID/src/HID-APIs/GamepadAPI.hpp deleted file mode 100644 index 880b1ba1a9..0000000000 --- a/plugins/KeyboardioHID/src/HID-APIs/GamepadAPI.hpp +++ /dev/null @@ -1,104 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 guard -#pragma once - -GamepadAPI::GamepadAPI(void) -{ - // Empty -} - -void GamepadAPI::begin(void){ - // release all buttons - end(); -} - -void GamepadAPI::end(void){ - memset(&_report, 0x00, sizeof(_report)); - SendReport(&_report, sizeof(_report)); -} - -void GamepadAPI::write(void){ - SendReport(&_report, sizeof(_report)); -} - - -void GamepadAPI::press(uint8_t b){ - _report.buttons |= (uint32_t)1 << (b - 1); -} - - -void GamepadAPI::release(uint8_t b){ - _report.buttons &= ~((uint32_t)1 << (b - 1)); -} - - -void GamepadAPI::releaseAll(void){ - memset(&_report, 0x00, sizeof(_report)); -} - -void GamepadAPI::buttons(uint32_t b){ - _report.buttons = b; -} - - -void GamepadAPI::xAxis(int16_t a){ - _report.xAxis = a; -} - - -void GamepadAPI::yAxis(int16_t a){ - _report.yAxis = a; -} - - -void GamepadAPI::zAxis(int8_t a){ - _report.zAxis = a; -} - - -void GamepadAPI::rxAxis(int16_t a){ - _report.rxAxis = a; -} - - -void GamepadAPI::ryAxis(int16_t a){ - _report.ryAxis = a; -} - - -void GamepadAPI::rzAxis(int8_t a){ - _report.rzAxis = a; -} - - -void GamepadAPI::dPad1(int8_t d){ - _report.dPad1 = d; -} - - -void GamepadAPI::dPad2(int8_t d){ - _report.dPad2 = d; -} - diff --git a/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp b/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp index 86b95e6523..21ee7fd569 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp @@ -79,6 +79,80 @@ Gamepad_::Gamepad_(void) } +void Gamepad_begin(void){ + // release all buttons + end(); +} + +void Gamepad_end(void){ + memset(&_report, 0x00, sizeof(_report)); + SendReport(&_report, sizeof(_report)); +} + +void Gamepad_write(void){ + SendReport(&_report, sizeof(_report)); +} + + +void Gamepad_press(uint8_t b){ + _report.buttons |= (uint32_t)1 << (b - 1); +} + + +void Gamepad_release(uint8_t b){ + _report.buttons &= ~((uint32_t)1 << (b - 1)); +} + + +void Gamepad_releaseAll(void){ + memset(&_report, 0x00, sizeof(_report)); +} + +void Gamepad_buttons(uint32_t b){ + _report.buttons = b; +} + + +void Gamepad_xAxis(int16_t a){ + _report.xAxis = a; +} + + +void Gamepad_yAxis(int16_t a){ + _report.yAxis = a; +} + + +void Gamepad_zAxis(int8_t a){ + _report.zAxis = a; +} + + +void Gamepad_rxAxis(int16_t a){ + _report.rxAxis = a; +} + + +void Gamepad_ryAxis(int16_t a){ + _report.ryAxis = a; +} + + +void Gamepad_rzAxis(int8_t a){ + _report.rzAxis = a; +} + + +void Gamepad_dPad1(int8_t d){ + _report.dPad1 = d; +} + + +void Gamepad_dPad2(int8_t d){ + _report.dPad2 = d; +} + + void Gamepad_::SendReport(void* data, int length) { HID().SendReport(HID_REPORTID_GAMEPAD, data, length); diff --git a/plugins/KeyboardioHID/src/MultiReport/Gamepad.h b/plugins/KeyboardioHID/src/MultiReport/Gamepad.h index dfb21a2ade..fcaed927a3 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Gamepad.h +++ b/plugins/KeyboardioHID/src/MultiReport/Gamepad.h @@ -30,14 +30,102 @@ THE SOFTWARE. #include "HID-Settings.h" #include "../HID-APIs/GamepadAPI.h" +// Dpad directions +#define GAMEPAD_DPAD_CENTERED 0 +#define GAMEPAD_DPAD_UP 1 +#define GAMEPAD_DPAD_UP_RIGHT 2 +#define GAMEPAD_DPAD_RIGHT 3 +#define GAMEPAD_DPAD_DOWN_RIGHT 4 +#define GAMEPAD_DPAD_DOWN 5 +#define GAMEPAD_DPAD_DOWN_LEFT 6 +#define GAMEPAD_DPAD_LEFT 7 +#define GAMEPAD_DPAD_UP_LEFT 8 + + +typedef union { + // 32 Buttons, 6 Axis, 2 D-Pads + uint8_t whole8[]; + uint16_t whole16[]; + uint32_t whole32[]; + uint32_t buttons; + + struct{ + uint8_t button1 : 1; + uint8_t button2 : 1; + uint8_t button3 : 1; + uint8_t button4 : 1; + uint8_t button5 : 1; + uint8_t button6 : 1; + uint8_t button7 : 1; + uint8_t button8 : 1; + + uint8_t button9 : 1; + uint8_t button10 : 1; + uint8_t button11 : 1; + uint8_t button12 : 1; + uint8_t button13 : 1; + uint8_t button14 : 1; + uint8_t button15 : 1; + uint8_t button16 : 1; + + uint8_t button17 : 1; + uint8_t button18 : 1; + uint8_t button19 : 1; + uint8_t button20 : 1; + uint8_t button21 : 1; + uint8_t button22 : 1; + uint8_t button23 : 1; + uint8_t button24 : 1; + + uint8_t button25 : 1; + uint8_t button26 : 1; + uint8_t button27 : 1; + uint8_t button28 : 1; + uint8_t button29 : 1; + uint8_t button30 : 1; + uint8_t button31 : 1; + uint8_t button32 : 1; + + int16_t xAxis; + int16_t yAxis; + + int16_t rxAxis; + int16_t ryAxis; + + int8_t zAxis; + int8_t rzAxis; + + uint8_t dPad1 : 4; + uint8_t dPad2 : 4; + }; +} HID_GamepadReport_Data_t; class Gamepad_ : public GamepadAPI { public: Gamepad_(void); -protected: - virtual inline void SendReport(void* data, int length) override; + inline void begin(void); + inline void end(void); + inline void write(void); + inline void press(uint8_t b); + inline void release(uint8_t b); + inline void releaseAll(void); + + inline void buttons(uint32_t b); + inline void xAxis(int16_t a); + inline void yAxis(int16_t a); + inline void zAxis(int8_t a); + inline void rxAxis(int16_t a); + inline void ryAxis(int16_t a); + inline void rzAxis(int8_t a); + inline void dPad1(int8_t d); + inline void dPad2(int8_t d); + + // Sending is public in the base class for advanced users. + virtual void SendReport(void* data, int length) = 0; +protected: + HID_GamepadReport_Data_t _report; }; extern Gamepad_ Gamepad; From 7e4b0569faee932e3b96b6fac8d11f7f0b852e4f Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Wed, 9 Dec 2015 19:47:57 -0800 Subject: [PATCH 355/602] Remove Boot Protocol Mouse;Remove MouseAPI layer of indirection --- plugins/KeyboardioHID/src/HID-APIs/MouseAPI.h | 87 ----------- .../KeyboardioHID/src/HID-APIs/MouseAPI.hpp | 86 ----------- plugins/KeyboardioHID/src/HID-Project.h | 1 - .../src/MultiReport/ImprovedMouse.cpp | 56 +++++++ .../src/MultiReport/ImprovedMouse.h | 39 ++++- .../src/SingleReport/BootMouse.cpp | 144 ------------------ .../src/SingleReport/BootMouse.h | 54 ------- 7 files changed, 91 insertions(+), 376 deletions(-) delete mode 100644 plugins/KeyboardioHID/src/HID-APIs/MouseAPI.h delete mode 100644 plugins/KeyboardioHID/src/HID-APIs/MouseAPI.hpp delete mode 100644 plugins/KeyboardioHID/src/SingleReport/BootMouse.cpp delete mode 100644 plugins/KeyboardioHID/src/SingleReport/BootMouse.h diff --git a/plugins/KeyboardioHID/src/HID-APIs/MouseAPI.h b/plugins/KeyboardioHID/src/HID-APIs/MouseAPI.h deleted file mode 100644 index b72712e4a7..0000000000 --- a/plugins/KeyboardioHID/src/HID-APIs/MouseAPI.h +++ /dev/null @@ -1,87 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 guard -#pragma once - -#include -#include "HID-Settings.h" - - -#define MOUSE_LEFT (1 << 0) -#define MOUSE_RIGHT (1 << 1) -#define MOUSE_MIDDLE (1 << 2) -#define MOUSE_PREV (1 << 3) -#define MOUSE_NEXT (1 << 4) -// actually this mouse report has 8 buttons (for smaller descriptor) -// but the last 3 wont do anything from what I tested -#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE | MOUSE_PREV | MOUSE_NEXT) - -typedef union{ - // Mouse report: 8 buttons, position, wheel - uint8_t whole8[]; - uint16_t whole16[]; - uint32_t whole32[]; - struct{ - uint8_t buttons; - int8_t xAxis; - int8_t yAxis; - int8_t wheel; - }; -} HID_MouseReport_Data_t; - -typedef union{ - // BootMouse report: 3 buttons, position - // Wheel is not supported by boot protocol - uint8_t whole8[]; - uint16_t whole16[]; - uint32_t whole32[]; - struct{ - uint8_t buttons; - int8_t xAxis; - int8_t yAxis; - }; -} HID_BootMouseReport_Data_t; - -class MouseAPI -{ -public: - inline MouseAPI(void); - inline void begin(void); - inline void end(void); - inline void click(uint8_t b = MOUSE_LEFT); - inline void move(signed char x, signed char y, signed char wheel = 0); - inline void press(uint8_t b = MOUSE_LEFT); // press LEFT by default - inline void release(uint8_t b = MOUSE_LEFT); // release LEFT by default - inline bool isPressed(uint8_t b = MOUSE_LEFT); // check LEFT by default - - // Sending is public in the base class for advanced users. - virtual void SendReport(void* data, int length) = 0; - -protected: - uint8_t _buttons; - inline void buttons(uint8_t b); -}; - -// Implementation is inline -#include "MouseAPI.hpp" diff --git a/plugins/KeyboardioHID/src/HID-APIs/MouseAPI.hpp b/plugins/KeyboardioHID/src/HID-APIs/MouseAPI.hpp deleted file mode 100644 index 55d144dc80..0000000000 --- a/plugins/KeyboardioHID/src/HID-APIs/MouseAPI.hpp +++ /dev/null @@ -1,86 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 guard -#pragma once - -MouseAPI::MouseAPI(void) : _buttons(0) -{ - // Empty -} - -void MouseAPI::begin(void) -{ - end(); -} - -void MouseAPI::end(void) -{ - _buttons = 0; - move(0, 0, 0); -} - -void MouseAPI::click(uint8_t b) -{ - _buttons = b; - move(0,0,0); - _buttons = 0; - move(0,0,0); -} - -void MouseAPI::move(signed char x, signed char y, signed char wheel) -{ - HID_MouseReport_Data_t report; - report.buttons = _buttons; - report.xAxis = x; - report.yAxis = y; - report.wheel = wheel; - SendReport(&report, sizeof(report)); -} - -void MouseAPI::buttons(uint8_t b) -{ - if (b != _buttons) - { - _buttons = b; - move(0,0,0); - } -} - -void MouseAPI::press(uint8_t b) -{ - buttons(_buttons | b); -} - -void MouseAPI::release(uint8_t b) -{ - buttons(_buttons & ~b); -} - -bool MouseAPI::isPressed(uint8_t b) -{ - if ((b & _buttons) > 0) - return true; - return false; -} - diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index a2a6b9c39d..5aed2be64b 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -40,7 +40,6 @@ THE SOFTWARE. // Include all HID libraries (.a linkage required to work) properly -#include "SingleReport/BootMouse.h" #include "SingleReport/RawHID.h" #include "SingleReport/BootKeyboard.h" #include "MultiReport/AbsoluteMouse.h" diff --git a/plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.cpp b/plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.cpp index 9e4ffebcde..54bb1db110 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.cpp @@ -63,6 +63,61 @@ Mouse_::Mouse_(void) HID().AppendDescriptor(&node); } +void Mouse_::begin(void) +{ + end(); +} + +void Mouse_::end(void) +{ + _buttons = 0; + move(0, 0, 0); +} + +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) +{ + HID_MouseReport_Data_t report; + report.buttons = _buttons; + report.xAxis = x; + report.yAxis = y; + report.wheel = wheel; + SendReport(&report, sizeof(report)); +} + +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; +} + void Mouse_::SendReport(void* data, int length) { @@ -71,3 +126,4 @@ void Mouse_::SendReport(void* data, int length) Mouse_ Mouse; + diff --git a/plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.h b/plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.h index 14d83a039e..fca4925ae8 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.h @@ -28,16 +28,47 @@ THE SOFTWARE. #include "PluggableUSB.h" #include "HID.h" #include "HID-Settings.h" -#include "../HID-APIs/MouseAPI.h" +#define MOUSE_LEFT (1 << 0) +#define MOUSE_RIGHT (1 << 1) +#define MOUSE_MIDDLE (1 << 2) +#define MOUSE_PREV (1 << 3) +#define MOUSE_NEXT (1 << 4) +// actually this mouse report has 8 buttons (for smaller descriptor) +// but the last 3 wont do anything from what I tested +#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE | MOUSE_PREV | MOUSE_NEXT) -class Mouse_ : public MouseAPI +typedef union{ + // Mouse report: 8 buttons, position, wheel + uint8_t whole8[]; + uint16_t whole16[]; + uint32_t whole32[]; + struct{ + uint8_t buttons; + int8_t xAxis; + int8_t yAxis; + int8_t wheel; + }; +} HID_MouseReport_Data_t; + + +class Mouse_ { public: Mouse_(void); + inline void begin(void); + inline void end(void); + inline void click(uint8_t b = MOUSE_LEFT); + inline void move(signed char x, signed char y, signed char wheel = 0); + inline void press(uint8_t b = MOUSE_LEFT); // press LEFT by default + inline void release(uint8_t b = MOUSE_LEFT); // release LEFT by default + inline bool isPressed(uint8_t b = MOUSE_LEFT); // check LEFT by default + + // Sending is public in the base class for advanced users. + virtual void SendReport(void* data, int length) = 0; protected: - virtual inline void SendReport(void* data, int length) override; + uint8_t _buttons; + inline void buttons(uint8_t b); }; extern Mouse_ Mouse; - diff --git a/plugins/KeyboardioHID/src/SingleReport/BootMouse.cpp b/plugins/KeyboardioHID/src/SingleReport/BootMouse.cpp deleted file mode 100644 index 27aee631d6..0000000000 --- a/plugins/KeyboardioHID/src/SingleReport/BootMouse.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 "BootMouse.h" - -static const uint8_t _hidReportDescriptorMouse[] PROGMEM = { - /* Mouse relative */ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 54 */ - 0x09, 0x02, /* USAGE (Mouse) */ - 0xa1, 0x01, /* COLLECTION (Application) */ - - /* 8 Buttons */ - 0x05, 0x09, /* USAGE_PAGE (Button) */ - 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ - 0x29, 0x08, /* USAGE_MAXIMUM (Button 8) */ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ - 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ - 0x95, 0x08, /* REPORT_COUNT (8) */ - 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - - /* X, Y, Wheel */ - 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) */ - - /* End */ - 0xc0 /* END_COLLECTION */ -}; - -BootMouse_::BootMouse_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1) -{ - epType[0] = EP_TYPE_INTERRUPT_IN; - PluggableUSB().plug(this); -} - -int BootMouse_::getInterface(uint8_t* interfaceCount) -{ - *interfaceCount += 1; // uses 1 - HIDDescriptor hidInterface = { - D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_BOOT_INTERFACE, HID_PROTOCOL_MOUSE), - D_HIDREPORT(sizeof(_hidReportDescriptorMouse)), - D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) - }; - return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); -} - -int BootMouse_::getDescriptor(USBSetup& setup) -{ - // Check if this is a HID Class Descriptor request - if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { return 0; } - if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { return 0; } - - // In a HID Class Descriptor wIndex cointains the interface number - if (setup.wIndex != pluggedInterface) { return 0; } - - // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol - // due to the USB specs, but Windows and Linux just assumes its in report mode. - protocol = HID_REPORT_PROTOCOL; - - return USB_SendControl(TRANSFER_PGM, _hidReportDescriptorMouse, sizeof(_hidReportDescriptorMouse)); -} - -bool BootMouse_::setup(USBSetup& setup) -{ - if (pluggedInterface != setup.wIndex) { - return false; - } - - uint8_t request = setup.bRequest; - uint8_t requestType = setup.bmRequestType; - - if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) - { - if (request == HID_GET_REPORT) { - // TODO: HID_GetReport(); - return true; - } - if (request == HID_GET_PROTOCOL) { - // TODO: Send8(protocol); - return true; - } - } - - if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) - { - if (request == HID_SET_PROTOCOL) { - protocol = setup.wValueL; - return true; - } - if (request == HID_SET_IDLE) { - idle = setup.wValueL; - return true; - } - if (request == HID_SET_REPORT) - { - } - } - - return false; -} - -uint8_t BootMouse_::getProtocol(void){ - return protocol; -} - -void BootMouse_::SendReport(void* data, int length){ - if(protocol == HID_BOOT_PROTOCOL){ - USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, sizeof(HID_BootMouseReport_Data_t)); - } - else{ - USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, length); - } -} - -BootMouse_ BootMouse; - - diff --git a/plugins/KeyboardioHID/src/SingleReport/BootMouse.h b/plugins/KeyboardioHID/src/SingleReport/BootMouse.h deleted file mode 100644 index 833f22d2d2..0000000000 --- a/plugins/KeyboardioHID/src/SingleReport/BootMouse.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 guard -#pragma once - -#include -#include "PluggableUSB.h" -#include "HID.h" -#include "HID-Settings.h" -#include "../HID-APIs/MouseAPI.h" - - -class BootMouse_ : public PluggableUSBModule, public MouseAPI -{ -public: - BootMouse_(void); - uint8_t getProtocol(void); - -protected: - // Implementation of the PUSBListNode - int getInterface(uint8_t* interfaceCount); - int getDescriptor(USBSetup& setup); - bool setup(USBSetup& setup); - - uint8_t epType[1]; - uint8_t protocol; - uint8_t idle; - - virtual void SendReport(void* data, int length) override; -}; -extern BootMouse_ BootMouse; - - From e34251862336434b22f46ae352345b5ccae22b74 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Wed, 9 Dec 2015 19:57:23 -0800 Subject: [PATCH 356/602] Remove consumer control from BootKeyboard (Other than the HID descriptor) --- .../src/SingleReport/BootKeyboard.cpp | 63 +------------------ .../src/SingleReport/BootKeyboard.h | 8 --- 2 files changed, 1 insertion(+), 70 deletions(-) diff --git a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp index 2cec858314..12a75a6dd5 100644 --- a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp @@ -40,6 +40,7 @@ static const uint8_t _hidReportDescriptorKeyboard[] PROGMEM = { 0x81, 0x02, /* INPUT (Data,Var,Abs) */ /* Reserved byte, used for consumer reports, only works with linux */ + /* NOT CURRENTLY USED BY THIS IMPLEMENTATION */ 0x05, 0x0C, /* Usage Page (Consumer) */ 0x95, 0x01, /* REPORT_COUNT (1) */ 0x75, 0x08, /* REPORT_SIZE (8) */ @@ -260,66 +261,4 @@ size_t BootKeyboard_::removeAll(void) return ret; } - -size_t BootKeyboard_::write(ConsumerKeycode k) -{ - // Press and release key (if press was successfull) - auto ret = press(k); - if(ret){ - release(k); - } - return ret; -} - - -size_t BootKeyboard_::press(ConsumerKeycode k) -{ - // Press key and send report to host - auto ret = add(k); - if(ret){ - send(); - } - return ret; -} - - -size_t BootKeyboard_::release(ConsumerKeycode k) -{ - // Release key and send report to host - auto ret = remove(k); - if(ret){ - send(); - } - return ret; -} - - -size_t BootKeyboard_::add(ConsumerKeycode k) -{ - // No 2 byte keys are supported - if(k > 0xFF){ - setWriteError(); - return 0; - } - - // Place the key inside the reserved keyreport position. - // This does not work on Windows. - _keyReport.reserved = k; - return 1; -} - - -size_t BootKeyboard_::remove(ConsumerKeycode k) -{ - // No 2 byte keys are supported - if(k > 0xFF){ - return 0; - } - - // Always release the key, to make it simpler releasing a consumer key - // without releasing all other normal keyboard keys. - _keyReport.reserved = HID_CONSUMER_UNASSIGNED; - return 1; -} - BootKeyboard_ BootKeyboard; diff --git a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h index 327ed098dd..f64a7f6c9d 100644 --- a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h @@ -29,7 +29,6 @@ THE SOFTWARE. #include "HID.h" #include "HID-Settings.h" #include "../HID-APIs/KeyboardAPI.h" -#include "../HID-APIs/ConsumerAPI.h" typedef union{ @@ -51,13 +50,6 @@ class BootKeyboard_ : public PluggableUSBModule, public KeyboardAPI public: BootKeyboard_(void); - // Add special consumer key API for the reserved byte - inline size_t write(ConsumerKeycode k); - inline size_t press(ConsumerKeycode k); - inline size_t release(ConsumerKeycode k); - inline size_t add(ConsumerKeycode k); - inline size_t remove(ConsumerKeycode k); - // Also use the base class functions // http://en.cppreference.com/w/cpp/language/using_declaration using KeyboardAPI::write; From 27cc64f0f7596d00eff35f6b991e483e4f185f66 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Wed, 9 Dec 2015 20:06:27 -0800 Subject: [PATCH 357/602] Remove layer of indirection for ConsumerControl --- .../KeyboardioHID/src/HID-APIs/ConsumerAPI.h | 485 ------------------ .../src/HID-APIs/ConsumerAPI.hpp | 71 --- .../src/MultiReport/Consumer.cpp | 42 ++ .../KeyboardioHID/src/MultiReport/Consumer.h | 450 +++++++++++++++- 4 files changed, 489 insertions(+), 559 deletions(-) delete mode 100644 plugins/KeyboardioHID/src/HID-APIs/ConsumerAPI.h delete mode 100644 plugins/KeyboardioHID/src/HID-APIs/ConsumerAPI.hpp diff --git a/plugins/KeyboardioHID/src/HID-APIs/ConsumerAPI.h b/plugins/KeyboardioHID/src/HID-APIs/ConsumerAPI.h deleted file mode 100644 index 33558b65ae..0000000000 --- a/plugins/KeyboardioHID/src/HID-APIs/ConsumerAPI.h +++ /dev/null @@ -1,485 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 guard -#pragma once - -#include -#include "HID-Settings.h" - -enum ConsumerKeycode : uint16_t { - // Some keys might only work with linux - CONSUMER_POWER = 0x30, - CONSUMER_SLEEP = 0x32, - - MEDIA_RECORD = 0xB2, - MEDIA_FAST_FORWARD = 0xB3, - MEDIA_REWIND = 0xB4, - MEDIA_NEXT = 0xB5, - MEDIA_PREVIOUS = 0xB6, - MEDIA_PREV = 0xB6, // Alias - MEDIA_STOP = 0xB7, - MEDIA_PLAY_PAUSE = 0xCD, - MEDIA_PAUSE = 0xB0, - - MEDIA_VOLUME_MUTE = 0xE2, - MEDIA_VOL_MUTE = 0xE2, // Alias - MEDIA_VOLUME_UP = 0xE9, - MEDIA_VOL_UP = 0xE9, // Alias - MEDIA_VOLUME_DOWN = 0xEA, - MEDIA_VOL_DOWN = 0xEA, // Alias - - CONSUMER_SCREENSAVER = 0x19e, - - CONSUMER_PROGRAMMABLE_BUTTON_CONFIGURATION = 0x182, - CONSUMER_CONTROL_CONFIGURATION = 0x183, - CONSUMER_EMAIL_READER = 0x18A, - CONSUMER_CALCULATOR = 0x192, - CONSUMER_EXPLORER = 0x194, - - CONSUMER_BROWSER_HOME = 0x223, - CONSUMER_BROWSER_BACK = 0x224, - CONSUMER_BROWSER_FORWARD = 0x225, - CONSUMER_BROWSER_REFRESH = 0x227, - CONSUMER_BROWSER_BOOKMARKS = 0x22A, - - - // Consumer_Page_(0x0C) 0x15 - HID_CONSUMER_UNASSIGNED = 0x00, - HID_CONSUMER_NUMERIC_KEY_PAD = 0x02, // HID type NARY - HID_CONSUMER_PROGRAMMABLE_BUTTONS = 0x03, // HID type NARY - HID_CONSUMER_MICROPHONE_CA = 0x04, - HID_CONSUMER_HEADPHONE_CA = 0x05, - HID_CONSUMER_GRAPHIC_EQUALIZER_CA = 0x06, - // Reserved = 0x07-1F - HID_CONSUMER_PLUS_10 = 0x20, // HID type OSC - HID_CONSUMER_PLUS_100 = 0x21, // HID type OSC - HID_CONSUMER_AM_SLASH_PM = 0x22, // HID type OSC - // Reserved = 0x23-3F - HID_CONSUMER_POWER = 0x30, // HID type OOC - HID_CONSUMER_RESET = 0x31, // HID type OSC - HID_CONSUMER_SLEEP = 0x32, // HID type OSC - HID_CONSUMER_SLEEP_AFTER = 0x33, // HID type OSC - HID_CONSUMER_SLEEP_MODE = 0x34, // HID type RTC - HID_CONSUMER_ILLUMINATION = 0x35, // HID type OOC - HID_CONSUMER_FUNCTION_BUTTONS = 0x36, // HID type NARY - // Reserved = 0x37-3F - HID_CONSUMER_MENU = 0x40, // HID type OOC - HID_CONSUMER_MENU_PICK = 0x41, // HID type OSC - HID_CONSUMER_MENU_UP = 0x42, // HID type OSC - HID_CONSUMER_MENU_DOWN = 0x43, // HID type OSC - HID_CONSUMER_MENU_LEFT = 0x44, // HID type OSC - HID_CONSUMER_MENU_RIGHT = 0x45, // HID type OSC - HID_CONSUMER_MENU_ESCAPE = 0x46, // HID type OSC - HID_CONSUMER_MENU_VALUE_INCREASE = 0x47, // HID type OSC - HID_CONSUMER_MENU_VALUE_DECREASE = 0x48, // HID type OSC - // Reserved 0x49-5F - HID_CONSUMER_DATA_ON_SCREEN = 0x60, // HID type OOC - HID_CONSUMER_CLOSED_CAPTION = 0x61, // HID type OOC - HID_CONSUMER_CLOSED_CAPTION_SELECT = 0x62, // HID type OSC - HID_CONSUMER_VCR_SLASH_TV = 0x63, // HID type OOC - HID_CONSUMER_BROADCAST_MODE = 0x64, // HID type OSC - HID_CONSUMER_SNAPSHOT = 0x65, // HID type OSC - HID_CONSUMER_STILL = 0x66, // HID type OSC - // Reserved 0x67-7F - HID_CONSUMER_SELECTION = 0x80, // HID type NARY - HID_CONSUMER_ASSIGN_SELECTION = 0x81, // HID type OSC - HID_CONSUMER_MODE_STEP = 0x82, // HID type OSC - HID_CONSUMER_RECALL_LAST = 0x83, // HID type OSC - HID_CONSUMER_ENTER_CHANNEL = 0x84, // HID type OSC - HID_CONSUMER_ORDER_MOVIE = 0x85, // HID type OSC - HID_CONSUMER_CHANNEL = 0x86, // HID type LC - HID_CONSUMER_MEDIA_SELECTION = 0x87, // HID type NARY - HID_CONSUMER_MEDIA_SELECT_COMPUTER = 0x88, // HID type SEL - HID_CONSUMER_MEDIA_SELECT_TV = 0x89, // HID type SEL - HID_CONSUMER_MEDIA_SELECT_WWW = 0x8A, // HID type SEL - HID_CONSUMER_MEDIA_SELECT_DVD = 0x8B, // HID type SEL - HID_CONSUMER_MEDIA_SELECT_TELEPHONE = 0x8C, // HID type SEL - HID_CONSUMER_MEDIA_SELECT_PROGRAM_GUIDE = 0x8D, // HID type SEL - HID_CONSUMER_MEDIA_SELECT_VIDEO_PHONE = 0x8E, // HID type SEL - HID_CONSUMER_MEDIA_SELECT_GAMES = 0x8F, // HID type SEL - HID_CONSUMER_MEDIA_SELECT_MESSAGES = 0x90, // HID type SEL - HID_CONSUMER_MEDIA_SELECT_CD = 0x91, // HID type SEL - HID_CONSUMER_MEDIA_SELECT_VCR = 0x92, // HID type SEL - HID_CONSUMER_MEDIA_SELECT_TUNER = 0x93, // HID type SEL - HID_CONSUMER_QUIT = 0x94, // HID type OSC - HID_CONSUMER_HELP = 0x95, // HID type OOC - HID_CONSUMER_MEDIA_SELECT_TAPE = 0x96, // HID type SEL - HID_CONSUMER_MEDIA_SELECT_CABLE = 0x97, // HID type SEL - HID_CONSUMER_MEDIA_SELECT_SATELLITE = 0x98, // HID type SEL - HID_CONSUMER_MEDIA_SELECT_SECURITY = 0x99, // HID type SEL - HID_CONSUMER_MEDIA_SELECT_HOME = 0x9A, // HID type SEL - HID_CONSUMER_MEDIA_SELECT_CALL = 0x9B, // HID type SEL - HID_CONSUMER_CHANNEL_INCREMENT = 0x9C, // HID type OSC - HID_CONSUMER_CHANNEL_DECREMENT = 0x9D, // HID type OSC - HID_CONSUMER_MEDIA_SELECT_SAP = 0x9E, // HID type SEL - // Reserved 0x9F - HID_CONSUMER_VCR_PLUS = 0xA0, // HID type OSC - HID_CONSUMER_ONCE = 0xA1, // HID type OSC - HID_CONSUMER_DAILY = 0xA2, // HID type OSC - HID_CONSUMER_WEEKLY = 0xA3, // HID type OSC - HID_CONSUMER_MONTHLY = 0xA4, // HID type OSC - // Reserved 0xA5-AF - HID_CONSUMER_PLAY = 0xB0, // HID type OOC - HID_CONSUMER_PAUSE = 0xB1, // HID type OOC - HID_CONSUMER_RECORD = 0xB2, // HID type OOC - HID_CONSUMER_FAST_FORWARD = 0xB3, // HID type OOC - HID_CONSUMER_REWIND = 0xB4, // HID type OOC - HID_CONSUMER_SCAN_NEXT_TRACK = 0xB5, // HID type OSC - HID_CONSUMER_SCAN_PREVIOUS_TRACK = 0xB6, // HID type OSC - HID_CONSUMER_STOP = 0xB7, // HID type OSC - HID_CONSUMER_EJECT = 0xB8, // HID type OSC - HID_CONSUMER_RANDOM_PLAY = 0xB9, // HID type OOC - HID_CONSUMER_SELECT_DISC = 0xBA, // HID type NARY - HID_CONSUMER_ENTER_DISC_MC = 0xBB, - HID_CONSUMER_REPEAT = 0xBC, // HID type OSC - HID_CONSUMER_TRACKING = 0xBD, // HID type LC - HID_CONSUMER_TRACK_NORMAL = 0xBE, // HID type OSC - HID_CONSUMER_SLOW_TRACKING = 0xBF, // HID type LC - HID_CONSUMER_FRAME_FORWARD = 0xC0, // HID type RTC - HID_CONSUMER_FRAME_BACK = 0xC1, // HID type RTC - HID_CONSUMER_MARK = 0xC2, // HID type OSC - HID_CONSUMER_CLEAR_MARK = 0xC3, // HID type OSC - HID_CONSUMER_REPEAT_FROM_MARK = 0xC4, // HID type OOC - HID_CONSUMER_RETURN_TO_MARK = 0xC5, // HID type OSC - HID_CONSUMER_SEARCH_MARK_FORWARD = 0xC6, // HID type OSC - HID_CONSUMER_SEARCH_MARK_BACKWARDS = 0xC7, // HID type OSC - HID_CONSUMER_COUNTER_RESET = 0xC8, // HID type OSC - HID_CONSUMER_SHOW_COUNTER = 0xC9, // HID type OSC - HID_CONSUMER_TRACKING_INCREMENT = 0xCA, // HID type RTC - HID_CONSUMER_TRACKING_DECREMENT = 0xCB, // HID type RTC - HID_CONSUMER_STOP_SLASH_EJECT = 0xCC, // HID type OSC - HID_CONSUMER_PLAY_SLASH_PAUSE = 0xCD, // HID type OSC - HID_CONSUMER_PLAY_SLASH_SKIP = 0xCE, // HID type OSC - // Reserved 0xCF-DF - HID_CONSUMER_VOLUME = 0xE0, // HID type LC - HID_CONSUMER_BALANCE = 0xE1, // HID type LC - HID_CONSUMER_MUTE = 0xE2, // HID type OOC - HID_CONSUMER_BASS = 0xE3, // HID type LC - HID_CONSUMER_TREBLE = 0xE4, // HID type LC - HID_CONSUMER_BASS_BOOST = 0xE5, // HID type OOC - HID_CONSUMER_SURROUND_MODE = 0xE6, // HID type OSC - HID_CONSUMER_LOUDNESS = 0xE7, // HID type OOC - HID_CONSUMER_MPX = 0xE8, // HID type OOC - HID_CONSUMER_VOLUME_INCREMENT = 0xE9, // HID type RTC - HID_CONSUMER_VOLUME_DECREMENT = 0xEA, // HID type RTC - // Reserved 0xEB-EF - HID_CONSUMER_SPEED_SELECT = 0xF0, // HID type OSC - HID_CONSUMER_PLAYBACK_SPEED = 0xF1, // HID type NARY - HID_CONSUMER_STANDARD_PLAY = 0xF2, // HID type SEL - HID_CONSUMER_LONG_PLAY = 0xF3, // HID type SEL - HID_CONSUMER_EXTENDED_PLAY = 0xF4, // HID type SEL - HID_CONSUMER_SLOW = 0xF5, // HID type OSC - // Reserved 0xF6-FF - HID_CONSUMER_FAN_ENABLE = 0x100, // HID type OOC - HID_CONSUMER_FAN_SPEED = 0x101, // HID type LC - HID_CONSUMER_LIGHT_ENABLE = 0x102, // HID type OOC - HID_CONSUMER_LIGHT_ILLUMINATION_LEVEL = 0x103, // HID type LC - HID_CONSUMER_CLIMATE_CONTROL_ENABLE = 0x104, // HID type OOC - HID_CONSUMER_ROOM_TEMPERATURE = 0x105, // HID type LC - HID_CONSUMER_SECURITY_ENABLE = 0x106, // HID type OOC - HID_CONSUMER_FIRE_ALARM = 0x107, // HID type OSC - HID_CONSUMER_POLICE_ALARM = 0x108, // HID type OSC - HID_CONSUMER_PROXIMITY = 0x109, // HID type LC - HID_CONSUMER_MOTION = 0x10A, // HID type OSC - HID_CONSUMER_DURESS_ALARM = 0x10B, // HID type OSC - HID_CONSUMER_HOLDUP_ALARM = 0x10C, // HID type OSC - HID_CONSUMER_MEDICAL_ALARM = 0x10D, // HID type OSC - // Reserved 0x10E-14F - HID_CONSUMER_BALANCE_RIGHT = 0x150, // HID type RTC - HID_CONSUMER_BALANCE_LEFT = 0x151, // HID type RTC - HID_CONSUMER_BASS_INCREMENT = 0x152, // HID type RTC - HID_CONSUMER_BASS_DECREMENT = 0x153, // HID type RTC - HID_CONSUMER_TREBLE_INCREMENT = 0x154, // HID type RTC - HID_CONSUMER_TREBLE_DECREMENT = 0x155, // HID type RTC - // Reserved 0x156-15F - HID_CONSUMER_SPEAKER_SYSTEM = 0x160, // HID type CL - HID_CONSUMER_CHANNEL_LEFT = 0x161, // HID type CL - HID_CONSUMER_CHANNEL_RIGHT = 0x162, // HID type CL - HID_CONSUMER_CHANNEL_CENTER = 0x163, // HID type CL - HID_CONSUMER_CHANNEL_FRONT = 0x164, // HID type CL - HID_CONSUMER_CHANNEL_CENTER_FRONT = 0x165, // HID type CL - HID_CONSUMER_CHANNEL_SIDE = 0x166, // HID type CL - HID_CONSUMER_CHANNEL_SURROUND = 0x167, // HID type CL - HID_CONSUMER_CHANNEL_LOW_FREQUENCY_ENHANCEMENT = 0x168, // HID type CL - HID_CONSUMER_CHANNEL_TOP = 0x169, // HID type CL - HID_CONSUMER_CHANNEL_UNKNOWN = 0x16A, // HID type CL - // Reserved 0x16B-16F - HID_CONSUMER_SUB_CHANNEL = 0x170, // HID type LC - HID_CONSUMER_SUB_CHANNEL_INCREMENT = 0x171, // HID type OSC - HID_CONSUMER_SUB_CHANNEL_DECREMENT = 0x172, // HID type OSC - HID_CONSUMER_ALTERNATE_AUDIO_INCREMENT = 0x173, // HID type OSC - HID_CONSUMER_ALTERNATE_AUDIO_DECREMENT = 0x174, // HID type OSC - // Reserved 0x175-17F - HID_CONSUMER_APPLICATION_LAUNCH_BUTTONS = 0x180, // HID type NARY - HID_CONSUMER_AL_LAUNCH_BUTTON_CONFIGURATION_TOOL = 0x181, // HID type SEL - HID_CONSUMER_AL_PROGRAMMABLE_BUTTON_CONFIGURATION = 0x182, // HID type SEL - HID_CONSUMER_AL_CONSUMER_CONTROL_CONFIGURATION = 0x183, // HID type SEL - HID_CONSUMER_AL_WORD_PROCESSOR = 0x184, // HID type SEL - HID_CONSUMER_AL_TEXT_EDITOR = 0x185, // HID type SEL - HID_CONSUMER_AL_SPREADSHEET = 0x186, // HID type SEL - HID_CONSUMER_AL_GRAPHICS_EDITOR = 0x187, // HID type SEL - HID_CONSUMER_AL_PRESENTATION_APP = 0x188, // HID type SEL - HID_CONSUMER_AL_DATABASE_APP = 0x189, // HID type SEL - HID_CONSUMER_AL_EMAIL_READER = 0x18A, // HID type SEL - HID_CONSUMER_AL_NEWSREADER = 0x18B, // HID type SEL - HID_CONSUMER_AL_VOICEMAIL = 0x18C, // HID type SEL - HID_CONSUMER_AL_CONTACTS_SLASH_ADDRESS_BOOK = 0x18D, // HID type SEL - HID_CONSUMER_AL_CALENDAR_SLASH_SCHEDULE = 0x18E, // HID type SEL - HID_CONSUMER_AL_TASK_SLASH_PROJECT_MANAGER = 0x18F, // HID type SEL - HID_CONSUMER_AL_LOG_SLASH_JOURNAL_SLASH_TIMECARD = 0x190, // HID type SEL - HID_CONSUMER_AL_CHECKBOOK_SLASH_FINANCE = 0x191, // HID type SEL - HID_CONSUMER_AL_CALCULATOR = 0x192, // HID type SEL - HID_CONSUMER_AL_A_SLASH_V_CAPTURE_SLASH_PLAYBACK = 0x193, // HID type SEL - HID_CONSUMER_AL_LOCAL_MACHINE_BROWSER = 0x194, // HID type SEL - HID_CONSUMER_AL_LAN_SLASH_WAN_BROWSER = 0x195, // HID type SEL - HID_CONSUMER_AL_INTERNET_BROWSER = 0x196, // HID type SEL - HID_CONSUMER_AL_REMOTE_NETWORKING_SLASH_ISP_CONNECT = 0x197, // HID type SEL - HID_CONSUMER_AL_NETWORK_CONFERENCE = 0x198, // HID type SEL - HID_CONSUMER_AL_NETWORK_CHAT = 0x199, // HID type SEL - HID_CONSUMER_AL_TELEPHONY_SLASH_DIALER = 0x19A, // HID type SEL - HID_CONSUMER_AL_LOGON = 0x19B, // HID type SEL - HID_CONSUMER_AL_LOGOFF = 0x19C, // HID type SEL - HID_CONSUMER_AL_LOGON_SLASH_LOGOFF = 0x19D, // HID type SEL - HID_CONSUMER_AL_TERMINAL_LOCK_SLASH_SCREENSAVER = 0x19E, // HID type SEL - HID_CONSUMER_AL_CONTROL_PANEL = 0x19F, // HID type SEL - HID_CONSUMER_AL_COMMAND_LINE_PROCESSOR_SLASH_RUN = 0x1A0, // HID type SEL - HID_CONSUMER_AL_PROCESS_SLASH_TASK_MANAGER = 0x1A1, // HID type SEL - HID_CONSUMER_AL_SELECT_TASK_SLASH_APPLICATION = 0x1A2, // HID type SEL - HID_CONSUMER_AL_NEXT_TASK_SLASH_APPLICATION = 0x1A3, // HID type SEL - HID_CONSUMER_AL_PREVIOUS_TASK_SLASH_APPLICATION = 0x1A4, // HID type SEL - HID_CONSUMER_AL_PREEMPTIVE_HALT_TASK_SLASH_APPLICATION = 0x1A5, // HID type SEL - HID_CONSUMER_AL_INTEGRATED_HELP_CENTER = 0x1A6, // HID type SEL - HID_CONSUMER_AL_DOCUMENTS = 0x1A7, // HID type SEL - HID_CONSUMER_AL_THESAURUS = 0x1A8, // HID type SEL - HID_CONSUMER_AL_DICTIONARY = 0x1A9, // HID type SEL - HID_CONSUMER_AL_DESKTOP = 0x1AA, // HID type SEL - HID_CONSUMER_AL_SPELL_CHECK = 0x1AB, // HID type SEL - HID_CONSUMER_AL_GRAMMAR_CHECK = 0x1AC, // HID type SEL - HID_CONSUMER_AL_WIRELESS_STATUS = 0x1AD, // HID type SEL - HID_CONSUMER_AL_KEYBOARD_LAYOUT = 0x1AE, // HID type SEL - HID_CONSUMER_AL_VIRUS_PROTECTION = 0x1AF, // HID type SEL - HID_CONSUMER_AL_ENCRYPTION = 0x1B0, // HID type SEL - HID_CONSUMER_AL_SCREEN_SAVER = 0x1B1, // HID type SEL - HID_CONSUMER_AL_ALARMS = 0x1B2, // HID type SEL - HID_CONSUMER_AL_CLOCK = 0x1B3, // HID type SEL - HID_CONSUMER_AL_FILE_BROWSER = 0x1B4, // HID type SEL - HID_CONSUMER_AL_POWER_STATUS = 0x1B5, // HID type SEL - HID_CONSUMER_AL_IMAGE_BROWSER = 0x1B6, // HID type SEL - HID_CONSUMER_AL_AUDIO_BROWSER = 0x1B7, // HID type SEL - HID_CONSUMER_AL_MOVIE_BROWSER = 0x1B8, // HID type SEL - HID_CONSUMER_AL_DIGITAL_RIGHTS_MANAGER = 0x1B9, // HID type SEL - HID_CONSUMER_AL_DIGITAL_WALLET = 0x1BA, // HID type SEL - // _Reserved 0x1BB - HID_CONSUMER_AL_INSTANT_MESSAGING = 0x1BC, // HID type SEL - HID_CONSUMER_AL_OEM_FEATURES_SLASH__TIPS_SLASH_TUTORIAL_BROWSER = 0x1BD, // HID type SEL - HID_CONSUMER_AL_OEM_HELP = 0x1BE, // HID type SEL - HID_CONSUMER_AL_ONLINE_COMMUNITY = 0x1BF, // HID type SEL - HID_CONSUMER_AL_ENTERTAINMENT_CONTENT_BROWSER = 0x1C0, // HID type SEL - HID_CONSUMER_AL_ONLINE_SHOPPING_BROWSER = 0x1C1, // HID type SEL - HID_CONSUMER_AL_SMARTCARD_INFORMATION_SLASH_HELP = 0x1C2, // HID type SEL - HID_CONSUMER_AL_MARKET_MONITOR_SLASH_FINANCE_BROWSER = 0x1C3, // HID type SEL - HID_CONSUMER_AL_CUSTOMIZED_CORPORATE_NEWS_BROWSER = 0x1C4, // HID type SEL - HID_CONSUMER_AL_ONLINE_ACTIVITY_BROWSER = 0x1C5, // HID type SEL - HID_CONSUMER_AL_RESEARCH_SLASH_SEARCH_BROWSER = 0x1C6, // HID type SEL - HID_CONSUMER_AL_AUDIO_PLAYER = 0x1C7, // HID type SEL - // Reserved 0x1C8-1FF - HID_CONSUMER_GENERIC_GUI_APPLICATION_CONTROLS = 0x200, // HID type NARY - HID_CONSUMER_AC_NEW = 0x201, // HID type SEL - HID_CONSUMER_AC_OPEN = 0x202, // HID type SEL - HID_CONSUMER_AC_CLOSE = 0x203, // HID type SEL - HID_CONSUMER_AC_EXIT = 0x204, // HID type SEL - HID_CONSUMER_AC_MAXIMIZE = 0x205, // HID type SEL - HID_CONSUMER_AC_MINIMIZE = 0x206, // HID type SEL - HID_CONSUMER_AC_SAVE = 0x207, // HID type SEL - HID_CONSUMER_AC_PRINT = 0x208, // HID type SEL - HID_CONSUMER_AC_PROPERTIES = 0x209, // HID type SEL - HID_CONSUMER_AC_UNDO = 0x21A, // HID type SEL - HID_CONSUMER_AC_COPY = 0x21B, // HID type SEL - HID_CONSUMER_AC_CUT = 0x21C, // HID type SEL - HID_CONSUMER_AC_PASTE = 0x21D, // HID type SEL - HID_CONSUMER_AC_SELECT_ALL = 0x21E, // HID type SEL - HID_CONSUMER_AC_FIND = 0x21F, // HID type SEL - HID_CONSUMER_AC_FIND_AND_REPLACE = 0x220, // HID type SEL - HID_CONSUMER_AC_SEARCH = 0x221, // HID type SEL - HID_CONSUMER_AC_GO_TO = 0x222, // HID type SEL - HID_CONSUMER_AC_HOME = 0x223, // HID type SEL - HID_CONSUMER_AC_BACK = 0x224, // HID type SEL - HID_CONSUMER_AC_FORWARD = 0x225, // HID type SEL - HID_CONSUMER_AC_STOP = 0x226, // HID type SEL - HID_CONSUMER_AC_REFRESH = 0x227, // HID type SEL - HID_CONSUMER_AC_PREVIOUS_LINK = 0x228, // HID type SEL - HID_CONSUMER_AC_NEXT_LINK = 0x229, // HID type SEL - HID_CONSUMER_AC_BOOKMARKS = 0x22A, // HID type SEL - HID_CONSUMER_AC_HISTORY = 0x22B, // HID type SEL - HID_CONSUMER_AC_SUBSCRIPTIONS = 0x22C, // HID type SEL - HID_CONSUMER_AC_ZOOM_IN = 0x22D, // HID type SEL - HID_CONSUMER_AC_ZOOM_OUT = 0x22E, // HID type SEL - HID_CONSUMER_AC_ZOOM = 0x22F, // HID type LC - HID_CONSUMER_AC_FULL_SCREEN_VIEW = 0x230, // HID type SEL - HID_CONSUMER_AC_NORMAL_VIEW = 0x231, // HID type SEL - HID_CONSUMER_AC_VIEW_TOGGLE = 0x232, // HID type SEL - HID_CONSUMER_AC_SCROLL_UP = 0x233, // HID type SEL - HID_CONSUMER_AC_SCROLL_DOWN = 0x234, // HID type SEL - HID_CONSUMER_AC_SCROLL = 0x235, // HID type LC - HID_CONSUMER_AC_PAN_LEFT = 0x236, // HID type SEL - HID_CONSUMER_AC_PAN_RIGHT = 0x237, // HID type SEL - HID_CONSUMER_AC_PAN = 0x238, // HID type LC - HID_CONSUMER_AC_NEW_WINDOW = 0x239, // HID type SEL - HID_CONSUMER_AC_TILE_HORIZONTALLY = 0x23A, // HID type SEL - HID_CONSUMER_AC_TILE_VERTICALLY = 0x23B, // HID type SEL - HID_CONSUMER_AC_FORMAT = 0x23C, // HID type SEL - HID_CONSUMER_AC_EDIT = 0x23D, // HID type SEL - HID_CONSUMER_AC_BOLD = 0x23E, // HID type SEL - HID_CONSUMER_AC_ITALICS = 0x23F, // HID type SEL - HID_CONSUMER_AC_UNDERLINE = 0x240, // HID type SEL - HID_CONSUMER_AC_STRIKETHROUGH = 0x241, // HID type SEL - HID_CONSUMER_AC_SUBSCRIPT = 0x242, // HID type SEL - HID_CONSUMER_AC_SUPERSCRIPT = 0x243, // HID type SEL - HID_CONSUMER_AC_ALL_CAPS = 0x244, // HID type SEL - HID_CONSUMER_AC_ROTATE = 0x245, // HID type SEL - HID_CONSUMER_AC_RESIZE = 0x246, // HID type SEL - HID_CONSUMER_AC_FLIP_HORIZONTAL = 0x247, // HID type SEL - HID_CONSUMER_AC_FLIP_VERTICAL = 0x248, // HID type SEL - HID_CONSUMER_AC_MIRROR_HORIZONTAL = 0x249, // HID type SEL - HID_CONSUMER_AC_MIRROR_VERTICAL = 0x24A, // HID type SEL - HID_CONSUMER_AC_FONT_SELECT = 0x24B, // HID type SEL - HID_CONSUMER_AC_FONT_COLOR = 0x24C, // HID type SEL - HID_CONSUMER_AC_FONT_SIZE = 0x24D, // HID type SEL - HID_CONSUMER_AC_JUSTIFY_LEFT = 0x24E, // HID type SEL - HID_CONSUMER_AC_JUSTIFY_CENTER_H = 0x24F, // HID type SEL - HID_CONSUMER_AC_JUSTIFY_RIGHT = 0x250, // HID type SEL - HID_CONSUMER_AC_JUSTIFY_BLOCK_H = 0x251, // HID type SEL - HID_CONSUMER_AC_JUSTIFY_TOP = 0x252, // HID type SEL - HID_CONSUMER_AC_JUSTIFY_CENTER_V = 0x253, // HID type SEL - HID_CONSUMER_AC_JUSTIFY_BOTTOM = 0x254, // HID type SEL - HID_CONSUMER_AC_JUSTIFY_BLOCK_V = 0x255, // HID type SEL - HID_CONSUMER_AC_INDENT_DECREASE = 0x256, // HID type SEL - HID_CONSUMER_AC_INDENT_INCREASE = 0x257, // HID type SEL - HID_CONSUMER_AC_NUMBERED_LIST = 0x258, // HID type SEL - HID_CONSUMER_AC_RESTART_NUMBERING = 0x259, // HID type SEL - HID_CONSUMER_AC_BULLETED_LIST = 0x25A, // HID type SEL - HID_CONSUMER_AC_PROMOTE = 0x25B, // HID type SEL - HID_CONSUMER_AC_DEMOTE = 0x25C, // HID type SEL - HID_CONSUMER_AC_YES = 0x25D, // HID type SEL - HID_CONSUMER_AC_NO = 0x25E, // HID type SEL - HID_CONSUMER_AC_CANCEL = 0x25F, // HID type SEL - HID_CONSUMER_AC_CATALOG = 0x260, // HID type SEL - HID_CONSUMER_AC_BUY_SLASH_CHECKOUT = 0x261, // HID type SEL - HID_CONSUMER_AC_ADD_TO_CART = 0x262, // HID type SEL - HID_CONSUMER_AC_EXPAND = 0x263, // HID type SEL - HID_CONSUMER_AC_EXPAND_ALL = 0x264, // HID type SEL - HID_CONSUMER_AC_COLLAPSE = 0x265, // HID type SEL - HID_CONSUMER_AC_COLLAPSE_ALL = 0x266, // HID type SEL - HID_CONSUMER_AC_PRINT_PREVIEW = 0x267, // HID type SEL - HID_CONSUMER_AC_PASTE_SPECIAL = 0x268, // HID type SEL - HID_CONSUMER_AC_INSERT_MODE = 0x269, // HID type SEL - HID_CONSUMER_AC_DELETE = 0x26A, // HID type SEL - HID_CONSUMER_AC_LOCK = 0x26B, // HID type SEL - HID_CONSUMER_AC_UNLOCK = 0x26C, // HID type SEL - HID_CONSUMER_AC_PROTECT = 0x26D, // HID type SEL - HID_CONSUMER_AC_UNPROTECT = 0x26E, // HID type SEL - HID_CONSUMER_AC_ATTACH_COMMENT = 0x26F, // HID type SEL - HID_CONSUMER_AC_DELETE_COMMENT = 0x270, // HID type SEL - HID_CONSUMER_AC_VIEW_COMMENT = 0x271, // HID type SEL - HID_CONSUMER_AC_SELECT_WORD = 0x272, // HID type SEL - HID_CONSUMER_AC_SELECT_SENTENCE = 0x273, // HID type SEL - HID_CONSUMER_AC_SELECT_PARAGRAPH = 0x274, // HID type SEL - HID_CONSUMER_AC_SELECT_COLUMN = 0x275, // HID type SEL - HID_CONSUMER_AC_SELECT_ROW = 0x276, // HID type SEL - HID_CONSUMER_AC_SELECT_TABLE = 0x277, // HID type SEL - HID_CONSUMER_AC_SELECT_OBJECT = 0x278, // HID type SEL - HID_CONSUMER_AC_REDO_SLASH_REPEAT = 0x279, // HID type SEL - HID_CONSUMER_AC_SORT = 0x27A, // HID type SEL - HID_CONSUMER_AC_SORT_ASCENDING = 0x27B, // HID type SEL - HID_CONSUMER_AC_SORT_DESCENDING = 0x27C, // HID type SEL - HID_CONSUMER_AC_FILTER = 0x27D, // HID type SEL - HID_CONSUMER_AC_SET_CLOCK = 0x27E, // HID type SEL - HID_CONSUMER_AC_VIEW_CLOCK = 0x27F, // HID type SEL - HID_CONSUMER_AC_SELECT_TIME_ZONE = 0x280, // HID type SEL - HID_CONSUMER_AC_EDIT_TIME_ZONES = 0x281, // HID type SEL - HID_CONSUMER_AC_SET_ALARM = 0x282, // HID type SEL - HID_CONSUMER_AC_CLEAR_ALARM = 0x283, // HID type SEL - HID_CONSUMER_AC_SNOOZE_ALARM = 0x284, // HID type SEL - HID_CONSUMER_AC_RESET_ALARM = 0x285, // HID type SEL - HID_CONSUMER_AC_SYNCHRONIZE = 0x286, // HID type SEL - HID_CONSUMER_AC_SEND_SLASH_RECEIVE = 0x287, // HID type SEL - HID_CONSUMER_AC_SEND_TO = 0x288, // HID type SEL - HID_CONSUMER_AC_REPLY = 0x289, // HID type SEL - HID_CONSUMER_AC_REPLY_ALL = 0x28A, // HID type SEL - HID_CONSUMER_AC_FORWARD_MSG = 0x28B, // HID type SEL - HID_CONSUMER_AC_SEND = 0x28C, // HID type SEL - HID_CONSUMER_AC_ATTACH_FILE = 0x28D, // HID type SEL - HID_CONSUMER_AC_UPLOAD = 0x28E, // HID type SEL - HID_CONSUMER_AC_DOWNLOAD_SAVE_TARGET_AS = 0x28F, // HID type SEL - HID_CONSUMER_AC_SET_BORDERS = 0x290, // HID type SEL - HID_CONSUMER_AC_INSERT_ROW = 0x291, // HID type SEL - HID_CONSUMER_AC_INSERT_COLUMN = 0x292, // HID type SEL - HID_CONSUMER_AC_INSERT_FILE = 0x293, // HID type SEL - HID_CONSUMER_AC_INSERT_PICTURE = 0x294, // HID type SEL - HID_CONSUMER_AC_INSERT_OBJECT = 0x295, // HID type SEL - HID_CONSUMER_AC_INSERT_SYMBOL = 0x296, // HID type SEL - HID_CONSUMER_AC_SAVE_AND_CLOSE = 0x297, // HID type SEL - HID_CONSUMER_AC_RENAME = 0x298, // HID type SEL - HID_CONSUMER_AC_MERGE = 0x299, // HID type SEL - HID_CONSUMER_AC_SPLIT = 0x29A, // HID type SEL - HID_CONSUMER_AC_DISRIBUTE_HORIZONTALLY = 0x29B, // HID type SEL - HID_CONSUMER_AC_DISTRIBUTE_VERTICALLY = 0x29C, // HID type SEL -}; - - -typedef union { - // Every usable Consumer key possible, up to 4 keys presses possible - uint8_t whole8[]; - uint16_t whole16[]; - uint32_t whole32[]; - ConsumerKeycode keys[4]; - struct { - ConsumerKeycode key1; - ConsumerKeycode key2; - ConsumerKeycode key3; - ConsumerKeycode key4; - }; -} HID_ConsumerControlReport_Data_t; - -class ConsumerAPI -{ -public: - inline ConsumerAPI(void); - inline void begin(void); - inline void end(void); - inline void write(ConsumerKeycode m); - inline void press(ConsumerKeycode m); - inline void release(ConsumerKeycode m); - inline void releaseAll(void); - - // Sending is public in the base class for advanced users. - virtual void SendReport(void* data, int length) = 0; - -protected: - HID_ConsumerControlReport_Data_t _report; -}; - -// Implementation is inline -#include "ConsumerAPI.hpp" - diff --git a/plugins/KeyboardioHID/src/HID-APIs/ConsumerAPI.hpp b/plugins/KeyboardioHID/src/HID-APIs/ConsumerAPI.hpp deleted file mode 100644 index 5e529c5630..0000000000 --- a/plugins/KeyboardioHID/src/HID-APIs/ConsumerAPI.hpp +++ /dev/null @@ -1,71 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 guard -#pragma once - -ConsumerAPI::ConsumerAPI(void) -{ - // Empty -} - -void ConsumerAPI::begin(void) { - // release all buttons - end(); -} - -void ConsumerAPI::end(void) { - memset(&_report, 0, sizeof(_report)); - SendReport(&_report, sizeof(_report)); -} - -void ConsumerAPI::write(ConsumerKeycode m) { - press(m); - release(m); -} - -void ConsumerAPI::press(ConsumerKeycode m) { - // search for a free spot - for (uint8_t i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { - if (_report.keys[i] == HID_CONSUMER_UNASSIGNED) { - _report.keys[i] = m; - break; - } - } - SendReport(&_report, sizeof(_report)); -} - -void ConsumerAPI::release(ConsumerKeycode m) { - // search and release the keypress - for (uint8_t i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { - if (_report.keys[i] == m) { - _report.keys[i] = HID_CONSUMER_UNASSIGNED; - // no break to delete multiple keys - } - } - SendReport(&_report, sizeof(_report)); -} - -void ConsumerAPI::releaseAll(void) { - end(); -} diff --git a/plugins/KeyboardioHID/src/MultiReport/Consumer.cpp b/plugins/KeyboardioHID/src/MultiReport/Consumer.cpp index 0fa6841eb5..addafbda27 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Consumer.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Consumer.cpp @@ -47,6 +47,46 @@ Consumer_::Consumer_(void) HID().AppendDescriptor(&node); } +void Consumer_::begin(void) { + // release all buttons + end(); +} + +void Consumer_::end(void) { + memset(&_report, 0, sizeof(_report)); + SendReport(&_report, sizeof(_report)); +} + +void Consumer_::write(ConsumerKeycode m) { + press(m); + release(m); +} + +void Consumer_::press(ConsumerKeycode m) { + // search for a free spot + for (uint8_t i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { + if (_report.keys[i] == HID_CONSUMER_UNASSIGNED) { + _report.keys[i] = m; + break; + } + } + SendReport(&_report, sizeof(_report)); +} + +void Consumer_::release(ConsumerKeycode m) { + // search and release the keypress + for (uint8_t i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { + if (_report.keys[i] == m) { + _report.keys[i] = HID_CONSUMER_UNASSIGNED; + // no break to delete multiple keys + } + } + SendReport(&_report, sizeof(_report)); +} + +void Consumer_::releaseAll(void) { + end(); +} void Consumer_::SendReport(void* data, int length) { @@ -55,3 +95,5 @@ void Consumer_::SendReport(void* data, int length) Consumer_ Consumer; + + diff --git a/plugins/KeyboardioHID/src/MultiReport/Consumer.h b/plugins/KeyboardioHID/src/MultiReport/Consumer.h index ede2458bce..269576cdac 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Consumer.h +++ b/plugins/KeyboardioHID/src/MultiReport/Consumer.h @@ -30,14 +30,458 @@ THE SOFTWARE. #include "HID-Settings.h" #include "../HID-APIs/ConsumerAPI.h" +enum ConsumerKeycode : uint16_t { + // Some keys might only work with linux + CONSUMER_POWER = 0x30, + CONSUMER_SLEEP = 0x32, -class Consumer_ : public ConsumerAPI + MEDIA_RECORD = 0xB2, + MEDIA_FAST_FORWARD = 0xB3, + MEDIA_REWIND = 0xB4, + MEDIA_NEXT = 0xB5, + MEDIA_PREVIOUS = 0xB6, + MEDIA_PREV = 0xB6, // Alias + MEDIA_STOP = 0xB7, + MEDIA_PLAY_PAUSE = 0xCD, + MEDIA_PAUSE = 0xB0, + + MEDIA_VOLUME_MUTE = 0xE2, + MEDIA_VOL_MUTE = 0xE2, // Alias + MEDIA_VOLUME_UP = 0xE9, + MEDIA_VOL_UP = 0xE9, // Alias + MEDIA_VOLUME_DOWN = 0xEA, + MEDIA_VOL_DOWN = 0xEA, // Alias + + CONSUMER_SCREENSAVER = 0x19e, + + CONSUMER_PROGRAMMABLE_BUTTON_CONFIGURATION = 0x182, + CONSUMER_CONTROL_CONFIGURATION = 0x183, + CONSUMER_EMAIL_READER = 0x18A, + CONSUMER_CALCULATOR = 0x192, + CONSUMER_EXPLORER = 0x194, + + CONSUMER_BROWSER_HOME = 0x223, + CONSUMER_BROWSER_BACK = 0x224, + CONSUMER_BROWSER_FORWARD = 0x225, + CONSUMER_BROWSER_REFRESH = 0x227, + CONSUMER_BROWSER_BOOKMARKS = 0x22A, + + + // Consumer_Page_(0x0C) 0x15 + HID_CONSUMER_UNASSIGNED = 0x00, + HID_CONSUMER_NUMERIC_KEY_PAD = 0x02, // HID type NARY + HID_CONSUMER_PROGRAMMABLE_BUTTONS = 0x03, // HID type NARY + HID_CONSUMER_MICROPHONE_CA = 0x04, + HID_CONSUMER_HEADPHONE_CA = 0x05, + HID_CONSUMER_GRAPHIC_EQUALIZER_CA = 0x06, + // Reserved = 0x07-1F + HID_CONSUMER_PLUS_10 = 0x20, // HID type OSC + HID_CONSUMER_PLUS_100 = 0x21, // HID type OSC + HID_CONSUMER_AM_SLASH_PM = 0x22, // HID type OSC + // Reserved = 0x23-3F + HID_CONSUMER_POWER = 0x30, // HID type OOC + HID_CONSUMER_RESET = 0x31, // HID type OSC + HID_CONSUMER_SLEEP = 0x32, // HID type OSC + HID_CONSUMER_SLEEP_AFTER = 0x33, // HID type OSC + HID_CONSUMER_SLEEP_MODE = 0x34, // HID type RTC + HID_CONSUMER_ILLUMINATION = 0x35, // HID type OOC + HID_CONSUMER_FUNCTION_BUTTONS = 0x36, // HID type NARY + // Reserved = 0x37-3F + HID_CONSUMER_MENU = 0x40, // HID type OOC + HID_CONSUMER_MENU_PICK = 0x41, // HID type OSC + HID_CONSUMER_MENU_UP = 0x42, // HID type OSC + HID_CONSUMER_MENU_DOWN = 0x43, // HID type OSC + HID_CONSUMER_MENU_LEFT = 0x44, // HID type OSC + HID_CONSUMER_MENU_RIGHT = 0x45, // HID type OSC + HID_CONSUMER_MENU_ESCAPE = 0x46, // HID type OSC + HID_CONSUMER_MENU_VALUE_INCREASE = 0x47, // HID type OSC + HID_CONSUMER_MENU_VALUE_DECREASE = 0x48, // HID type OSC + // Reserved 0x49-5F + HID_CONSUMER_DATA_ON_SCREEN = 0x60, // HID type OOC + HID_CONSUMER_CLOSED_CAPTION = 0x61, // HID type OOC + HID_CONSUMER_CLOSED_CAPTION_SELECT = 0x62, // HID type OSC + HID_CONSUMER_VCR_SLASH_TV = 0x63, // HID type OOC + HID_CONSUMER_BROADCAST_MODE = 0x64, // HID type OSC + HID_CONSUMER_SNAPSHOT = 0x65, // HID type OSC + HID_CONSUMER_STILL = 0x66, // HID type OSC + // Reserved 0x67-7F + HID_CONSUMER_SELECTION = 0x80, // HID type NARY + HID_CONSUMER_ASSIGN_SELECTION = 0x81, // HID type OSC + HID_CONSUMER_MODE_STEP = 0x82, // HID type OSC + HID_CONSUMER_RECALL_LAST = 0x83, // HID type OSC + HID_CONSUMER_ENTER_CHANNEL = 0x84, // HID type OSC + HID_CONSUMER_ORDER_MOVIE = 0x85, // HID type OSC + HID_CONSUMER_CHANNEL = 0x86, // HID type LC + HID_CONSUMER_MEDIA_SELECTION = 0x87, // HID type NARY + HID_CONSUMER_MEDIA_SELECT_COMPUTER = 0x88, // HID type SEL + HID_CONSUMER_MEDIA_SELECT_TV = 0x89, // HID type SEL + HID_CONSUMER_MEDIA_SELECT_WWW = 0x8A, // HID type SEL + HID_CONSUMER_MEDIA_SELECT_DVD = 0x8B, // HID type SEL + HID_CONSUMER_MEDIA_SELECT_TELEPHONE = 0x8C, // HID type SEL + HID_CONSUMER_MEDIA_SELECT_PROGRAM_GUIDE = 0x8D, // HID type SEL + HID_CONSUMER_MEDIA_SELECT_VIDEO_PHONE = 0x8E, // HID type SEL + HID_CONSUMER_MEDIA_SELECT_GAMES = 0x8F, // HID type SEL + HID_CONSUMER_MEDIA_SELECT_MESSAGES = 0x90, // HID type SEL + HID_CONSUMER_MEDIA_SELECT_CD = 0x91, // HID type SEL + HID_CONSUMER_MEDIA_SELECT_VCR = 0x92, // HID type SEL + HID_CONSUMER_MEDIA_SELECT_TUNER = 0x93, // HID type SEL + HID_CONSUMER_QUIT = 0x94, // HID type OSC + HID_CONSUMER_HELP = 0x95, // HID type OOC + HID_CONSUMER_MEDIA_SELECT_TAPE = 0x96, // HID type SEL + HID_CONSUMER_MEDIA_SELECT_CABLE = 0x97, // HID type SEL + HID_CONSUMER_MEDIA_SELECT_SATELLITE = 0x98, // HID type SEL + HID_CONSUMER_MEDIA_SELECT_SECURITY = 0x99, // HID type SEL + HID_CONSUMER_MEDIA_SELECT_HOME = 0x9A, // HID type SEL + HID_CONSUMER_MEDIA_SELECT_CALL = 0x9B, // HID type SEL + HID_CONSUMER_CHANNEL_INCREMENT = 0x9C, // HID type OSC + HID_CONSUMER_CHANNEL_DECREMENT = 0x9D, // HID type OSC + HID_CONSUMER_MEDIA_SELECT_SAP = 0x9E, // HID type SEL + // Reserved 0x9F + HID_CONSUMER_VCR_PLUS = 0xA0, // HID type OSC + HID_CONSUMER_ONCE = 0xA1, // HID type OSC + HID_CONSUMER_DAILY = 0xA2, // HID type OSC + HID_CONSUMER_WEEKLY = 0xA3, // HID type OSC + HID_CONSUMER_MONTHLY = 0xA4, // HID type OSC + // Reserved 0xA5-AF + HID_CONSUMER_PLAY = 0xB0, // HID type OOC + HID_CONSUMER_PAUSE = 0xB1, // HID type OOC + HID_CONSUMER_RECORD = 0xB2, // HID type OOC + HID_CONSUMER_FAST_FORWARD = 0xB3, // HID type OOC + HID_CONSUMER_REWIND = 0xB4, // HID type OOC + HID_CONSUMER_SCAN_NEXT_TRACK = 0xB5, // HID type OSC + HID_CONSUMER_SCAN_PREVIOUS_TRACK = 0xB6, // HID type OSC + HID_CONSUMER_STOP = 0xB7, // HID type OSC + HID_CONSUMER_EJECT = 0xB8, // HID type OSC + HID_CONSUMER_RANDOM_PLAY = 0xB9, // HID type OOC + HID_CONSUMER_SELECT_DISC = 0xBA, // HID type NARY + HID_CONSUMER_ENTER_DISC_MC = 0xBB, + HID_CONSUMER_REPEAT = 0xBC, // HID type OSC + HID_CONSUMER_TRACKING = 0xBD, // HID type LC + HID_CONSUMER_TRACK_NORMAL = 0xBE, // HID type OSC + HID_CONSUMER_SLOW_TRACKING = 0xBF, // HID type LC + HID_CONSUMER_FRAME_FORWARD = 0xC0, // HID type RTC + HID_CONSUMER_FRAME_BACK = 0xC1, // HID type RTC + HID_CONSUMER_MARK = 0xC2, // HID type OSC + HID_CONSUMER_CLEAR_MARK = 0xC3, // HID type OSC + HID_CONSUMER_REPEAT_FROM_MARK = 0xC4, // HID type OOC + HID_CONSUMER_RETURN_TO_MARK = 0xC5, // HID type OSC + HID_CONSUMER_SEARCH_MARK_FORWARD = 0xC6, // HID type OSC + HID_CONSUMER_SEARCH_MARK_BACKWARDS = 0xC7, // HID type OSC + HID_CONSUMER_COUNTER_RESET = 0xC8, // HID type OSC + HID_CONSUMER_SHOW_COUNTER = 0xC9, // HID type OSC + HID_CONSUMER_TRACKING_INCREMENT = 0xCA, // HID type RTC + HID_CONSUMER_TRACKING_DECREMENT = 0xCB, // HID type RTC + HID_CONSUMER_STOP_SLASH_EJECT = 0xCC, // HID type OSC + HID_CONSUMER_PLAY_SLASH_PAUSE = 0xCD, // HID type OSC + HID_CONSUMER_PLAY_SLASH_SKIP = 0xCE, // HID type OSC + // Reserved 0xCF-DF + HID_CONSUMER_VOLUME = 0xE0, // HID type LC + HID_CONSUMER_BALANCE = 0xE1, // HID type LC + HID_CONSUMER_MUTE = 0xE2, // HID type OOC + HID_CONSUMER_BASS = 0xE3, // HID type LC + HID_CONSUMER_TREBLE = 0xE4, // HID type LC + HID_CONSUMER_BASS_BOOST = 0xE5, // HID type OOC + HID_CONSUMER_SURROUND_MODE = 0xE6, // HID type OSC + HID_CONSUMER_LOUDNESS = 0xE7, // HID type OOC + HID_CONSUMER_MPX = 0xE8, // HID type OOC + HID_CONSUMER_VOLUME_INCREMENT = 0xE9, // HID type RTC + HID_CONSUMER_VOLUME_DECREMENT = 0xEA, // HID type RTC + // Reserved 0xEB-EF + HID_CONSUMER_SPEED_SELECT = 0xF0, // HID type OSC + HID_CONSUMER_PLAYBACK_SPEED = 0xF1, // HID type NARY + HID_CONSUMER_STANDARD_PLAY = 0xF2, // HID type SEL + HID_CONSUMER_LONG_PLAY = 0xF3, // HID type SEL + HID_CONSUMER_EXTENDED_PLAY = 0xF4, // HID type SEL + HID_CONSUMER_SLOW = 0xF5, // HID type OSC + // Reserved 0xF6-FF + HID_CONSUMER_FAN_ENABLE = 0x100, // HID type OOC + HID_CONSUMER_FAN_SPEED = 0x101, // HID type LC + HID_CONSUMER_LIGHT_ENABLE = 0x102, // HID type OOC + HID_CONSUMER_LIGHT_ILLUMINATION_LEVEL = 0x103, // HID type LC + HID_CONSUMER_CLIMATE_CONTROL_ENABLE = 0x104, // HID type OOC + HID_CONSUMER_ROOM_TEMPERATURE = 0x105, // HID type LC + HID_CONSUMER_SECURITY_ENABLE = 0x106, // HID type OOC + HID_CONSUMER_FIRE_ALARM = 0x107, // HID type OSC + HID_CONSUMER_POLICE_ALARM = 0x108, // HID type OSC + HID_CONSUMER_PROXIMITY = 0x109, // HID type LC + HID_CONSUMER_MOTION = 0x10A, // HID type OSC + HID_CONSUMER_DURESS_ALARM = 0x10B, // HID type OSC + HID_CONSUMER_HOLDUP_ALARM = 0x10C, // HID type OSC + HID_CONSUMER_MEDICAL_ALARM = 0x10D, // HID type OSC + // Reserved 0x10E-14F + HID_CONSUMER_BALANCE_RIGHT = 0x150, // HID type RTC + HID_CONSUMER_BALANCE_LEFT = 0x151, // HID type RTC + HID_CONSUMER_BASS_INCREMENT = 0x152, // HID type RTC + HID_CONSUMER_BASS_DECREMENT = 0x153, // HID type RTC + HID_CONSUMER_TREBLE_INCREMENT = 0x154, // HID type RTC + HID_CONSUMER_TREBLE_DECREMENT = 0x155, // HID type RTC + // Reserved 0x156-15F + HID_CONSUMER_SPEAKER_SYSTEM = 0x160, // HID type CL + HID_CONSUMER_CHANNEL_LEFT = 0x161, // HID type CL + HID_CONSUMER_CHANNEL_RIGHT = 0x162, // HID type CL + HID_CONSUMER_CHANNEL_CENTER = 0x163, // HID type CL + HID_CONSUMER_CHANNEL_FRONT = 0x164, // HID type CL + HID_CONSUMER_CHANNEL_CENTER_FRONT = 0x165, // HID type CL + HID_CONSUMER_CHANNEL_SIDE = 0x166, // HID type CL + HID_CONSUMER_CHANNEL_SURROUND = 0x167, // HID type CL + HID_CONSUMER_CHANNEL_LOW_FREQUENCY_ENHANCEMENT = 0x168, // HID type CL + HID_CONSUMER_CHANNEL_TOP = 0x169, // HID type CL + HID_CONSUMER_CHANNEL_UNKNOWN = 0x16A, // HID type CL + // Reserved 0x16B-16F + HID_CONSUMER_SUB_CHANNEL = 0x170, // HID type LC + HID_CONSUMER_SUB_CHANNEL_INCREMENT = 0x171, // HID type OSC + HID_CONSUMER_SUB_CHANNEL_DECREMENT = 0x172, // HID type OSC + HID_CONSUMER_ALTERNATE_AUDIO_INCREMENT = 0x173, // HID type OSC + HID_CONSUMER_ALTERNATE_AUDIO_DECREMENT = 0x174, // HID type OSC + // Reserved 0x175-17F + HID_CONSUMER_APPLICATION_LAUNCH_BUTTONS = 0x180, // HID type NARY + HID_CONSUMER_AL_LAUNCH_BUTTON_CONFIGURATION_TOOL = 0x181, // HID type SEL + HID_CONSUMER_AL_PROGRAMMABLE_BUTTON_CONFIGURATION = 0x182, // HID type SEL + HID_CONSUMER_AL_CONSUMER_CONTROL_CONFIGURATION = 0x183, // HID type SEL + HID_CONSUMER_AL_WORD_PROCESSOR = 0x184, // HID type SEL + HID_CONSUMER_AL_TEXT_EDITOR = 0x185, // HID type SEL + HID_CONSUMER_AL_SPREADSHEET = 0x186, // HID type SEL + HID_CONSUMER_AL_GRAPHICS_EDITOR = 0x187, // HID type SEL + HID_CONSUMER_AL_PRESENTATION_APP = 0x188, // HID type SEL + HID_CONSUMER_AL_DATABASE_APP = 0x189, // HID type SEL + HID_CONSUMER_AL_EMAIL_READER = 0x18A, // HID type SEL + HID_CONSUMER_AL_NEWSREADER = 0x18B, // HID type SEL + HID_CONSUMER_AL_VOICEMAIL = 0x18C, // HID type SEL + HID_CONSUMER_AL_CONTACTS_SLASH_ADDRESS_BOOK = 0x18D, // HID type SEL + HID_CONSUMER_AL_CALENDAR_SLASH_SCHEDULE = 0x18E, // HID type SEL + HID_CONSUMER_AL_TASK_SLASH_PROJECT_MANAGER = 0x18F, // HID type SEL + HID_CONSUMER_AL_LOG_SLASH_JOURNAL_SLASH_TIMECARD = 0x190, // HID type SEL + HID_CONSUMER_AL_CHECKBOOK_SLASH_FINANCE = 0x191, // HID type SEL + HID_CONSUMER_AL_CALCULATOR = 0x192, // HID type SEL + HID_CONSUMER_AL_A_SLASH_V_CAPTURE_SLASH_PLAYBACK = 0x193, // HID type SEL + HID_CONSUMER_AL_LOCAL_MACHINE_BROWSER = 0x194, // HID type SEL + HID_CONSUMER_AL_LAN_SLASH_WAN_BROWSER = 0x195, // HID type SEL + HID_CONSUMER_AL_INTERNET_BROWSER = 0x196, // HID type SEL + HID_CONSUMER_AL_REMOTE_NETWORKING_SLASH_ISP_CONNECT = 0x197, // HID type SEL + HID_CONSUMER_AL_NETWORK_CONFERENCE = 0x198, // HID type SEL + HID_CONSUMER_AL_NETWORK_CHAT = 0x199, // HID type SEL + HID_CONSUMER_AL_TELEPHONY_SLASH_DIALER = 0x19A, // HID type SEL + HID_CONSUMER_AL_LOGON = 0x19B, // HID type SEL + HID_CONSUMER_AL_LOGOFF = 0x19C, // HID type SEL + HID_CONSUMER_AL_LOGON_SLASH_LOGOFF = 0x19D, // HID type SEL + HID_CONSUMER_AL_TERMINAL_LOCK_SLASH_SCREENSAVER = 0x19E, // HID type SEL + HID_CONSUMER_AL_CONTROL_PANEL = 0x19F, // HID type SEL + HID_CONSUMER_AL_COMMAND_LINE_PROCESSOR_SLASH_RUN = 0x1A0, // HID type SEL + HID_CONSUMER_AL_PROCESS_SLASH_TASK_MANAGER = 0x1A1, // HID type SEL + HID_CONSUMER_AL_SELECT_TASK_SLASH_APPLICATION = 0x1A2, // HID type SEL + HID_CONSUMER_AL_NEXT_TASK_SLASH_APPLICATION = 0x1A3, // HID type SEL + HID_CONSUMER_AL_PREVIOUS_TASK_SLASH_APPLICATION = 0x1A4, // HID type SEL + HID_CONSUMER_AL_PREEMPTIVE_HALT_TASK_SLASH_APPLICATION = 0x1A5, // HID type SEL + HID_CONSUMER_AL_INTEGRATED_HELP_CENTER = 0x1A6, // HID type SEL + HID_CONSUMER_AL_DOCUMENTS = 0x1A7, // HID type SEL + HID_CONSUMER_AL_THESAURUS = 0x1A8, // HID type SEL + HID_CONSUMER_AL_DICTIONARY = 0x1A9, // HID type SEL + HID_CONSUMER_AL_DESKTOP = 0x1AA, // HID type SEL + HID_CONSUMER_AL_SPELL_CHECK = 0x1AB, // HID type SEL + HID_CONSUMER_AL_GRAMMAR_CHECK = 0x1AC, // HID type SEL + HID_CONSUMER_AL_WIRELESS_STATUS = 0x1AD, // HID type SEL + HID_CONSUMER_AL_KEYBOARD_LAYOUT = 0x1AE, // HID type SEL + HID_CONSUMER_AL_VIRUS_PROTECTION = 0x1AF, // HID type SEL + HID_CONSUMER_AL_ENCRYPTION = 0x1B0, // HID type SEL + HID_CONSUMER_AL_SCREEN_SAVER = 0x1B1, // HID type SEL + HID_CONSUMER_AL_ALARMS = 0x1B2, // HID type SEL + HID_CONSUMER_AL_CLOCK = 0x1B3, // HID type SEL + HID_CONSUMER_AL_FILE_BROWSER = 0x1B4, // HID type SEL + HID_CONSUMER_AL_POWER_STATUS = 0x1B5, // HID type SEL + HID_CONSUMER_AL_IMAGE_BROWSER = 0x1B6, // HID type SEL + HID_CONSUMER_AL_AUDIO_BROWSER = 0x1B7, // HID type SEL + HID_CONSUMER_AL_MOVIE_BROWSER = 0x1B8, // HID type SEL + HID_CONSUMER_AL_DIGITAL_RIGHTS_MANAGER = 0x1B9, // HID type SEL + HID_CONSUMER_AL_DIGITAL_WALLET = 0x1BA, // HID type SEL + // _Reserved 0x1BB + HID_CONSUMER_AL_INSTANT_MESSAGING = 0x1BC, // HID type SEL + HID_CONSUMER_AL_OEM_FEATURES_SLASH__TIPS_SLASH_TUTORIAL_BROWSER = 0x1BD, // HID type SEL + HID_CONSUMER_AL_OEM_HELP = 0x1BE, // HID type SEL + HID_CONSUMER_AL_ONLINE_COMMUNITY = 0x1BF, // HID type SEL + HID_CONSUMER_AL_ENTERTAINMENT_CONTENT_BROWSER = 0x1C0, // HID type SEL + HID_CONSUMER_AL_ONLINE_SHOPPING_BROWSER = 0x1C1, // HID type SEL + HID_CONSUMER_AL_SMARTCARD_INFORMATION_SLASH_HELP = 0x1C2, // HID type SEL + HID_CONSUMER_AL_MARKET_MONITOR_SLASH_FINANCE_BROWSER = 0x1C3, // HID type SEL + HID_CONSUMER_AL_CUSTOMIZED_CORPORATE_NEWS_BROWSER = 0x1C4, // HID type SEL + HID_CONSUMER_AL_ONLINE_ACTIVITY_BROWSER = 0x1C5, // HID type SEL + HID_CONSUMER_AL_RESEARCH_SLASH_SEARCH_BROWSER = 0x1C6, // HID type SEL + HID_CONSUMER_AL_AUDIO_PLAYER = 0x1C7, // HID type SEL + // Reserved 0x1C8-1FF + HID_CONSUMER_GENERIC_GUI_APPLICATION_CONTROLS = 0x200, // HID type NARY + HID_CONSUMER_AC_NEW = 0x201, // HID type SEL + HID_CONSUMER_AC_OPEN = 0x202, // HID type SEL + HID_CONSUMER_AC_CLOSE = 0x203, // HID type SEL + HID_CONSUMER_AC_EXIT = 0x204, // HID type SEL + HID_CONSUMER_AC_MAXIMIZE = 0x205, // HID type SEL + HID_CONSUMER_AC_MINIMIZE = 0x206, // HID type SEL + HID_CONSUMER_AC_SAVE = 0x207, // HID type SEL + HID_CONSUMER_AC_PRINT = 0x208, // HID type SEL + HID_CONSUMER_AC_PROPERTIES = 0x209, // HID type SEL + HID_CONSUMER_AC_UNDO = 0x21A, // HID type SEL + HID_CONSUMER_AC_COPY = 0x21B, // HID type SEL + HID_CONSUMER_AC_CUT = 0x21C, // HID type SEL + HID_CONSUMER_AC_PASTE = 0x21D, // HID type SEL + HID_CONSUMER_AC_SELECT_ALL = 0x21E, // HID type SEL + HID_CONSUMER_AC_FIND = 0x21F, // HID type SEL + HID_CONSUMER_AC_FIND_AND_REPLACE = 0x220, // HID type SEL + HID_CONSUMER_AC_SEARCH = 0x221, // HID type SEL + HID_CONSUMER_AC_GO_TO = 0x222, // HID type SEL + HID_CONSUMER_AC_HOME = 0x223, // HID type SEL + HID_CONSUMER_AC_BACK = 0x224, // HID type SEL + HID_CONSUMER_AC_FORWARD = 0x225, // HID type SEL + HID_CONSUMER_AC_STOP = 0x226, // HID type SEL + HID_CONSUMER_AC_REFRESH = 0x227, // HID type SEL + HID_CONSUMER_AC_PREVIOUS_LINK = 0x228, // HID type SEL + HID_CONSUMER_AC_NEXT_LINK = 0x229, // HID type SEL + HID_CONSUMER_AC_BOOKMARKS = 0x22A, // HID type SEL + HID_CONSUMER_AC_HISTORY = 0x22B, // HID type SEL + HID_CONSUMER_AC_SUBSCRIPTIONS = 0x22C, // HID type SEL + HID_CONSUMER_AC_ZOOM_IN = 0x22D, // HID type SEL + HID_CONSUMER_AC_ZOOM_OUT = 0x22E, // HID type SEL + HID_CONSUMER_AC_ZOOM = 0x22F, // HID type LC + HID_CONSUMER_AC_FULL_SCREEN_VIEW = 0x230, // HID type SEL + HID_CONSUMER_AC_NORMAL_VIEW = 0x231, // HID type SEL + HID_CONSUMER_AC_VIEW_TOGGLE = 0x232, // HID type SEL + HID_CONSUMER_AC_SCROLL_UP = 0x233, // HID type SEL + HID_CONSUMER_AC_SCROLL_DOWN = 0x234, // HID type SEL + HID_CONSUMER_AC_SCROLL = 0x235, // HID type LC + HID_CONSUMER_AC_PAN_LEFT = 0x236, // HID type SEL + HID_CONSUMER_AC_PAN_RIGHT = 0x237, // HID type SEL + HID_CONSUMER_AC_PAN = 0x238, // HID type LC + HID_CONSUMER_AC_NEW_WINDOW = 0x239, // HID type SEL + HID_CONSUMER_AC_TILE_HORIZONTALLY = 0x23A, // HID type SEL + HID_CONSUMER_AC_TILE_VERTICALLY = 0x23B, // HID type SEL + HID_CONSUMER_AC_FORMAT = 0x23C, // HID type SEL + HID_CONSUMER_AC_EDIT = 0x23D, // HID type SEL + HID_CONSUMER_AC_BOLD = 0x23E, // HID type SEL + HID_CONSUMER_AC_ITALICS = 0x23F, // HID type SEL + HID_CONSUMER_AC_UNDERLINE = 0x240, // HID type SEL + HID_CONSUMER_AC_STRIKETHROUGH = 0x241, // HID type SEL + HID_CONSUMER_AC_SUBSCRIPT = 0x242, // HID type SEL + HID_CONSUMER_AC_SUPERSCRIPT = 0x243, // HID type SEL + HID_CONSUMER_AC_ALL_CAPS = 0x244, // HID type SEL + HID_CONSUMER_AC_ROTATE = 0x245, // HID type SEL + HID_CONSUMER_AC_RESIZE = 0x246, // HID type SEL + HID_CONSUMER_AC_FLIP_HORIZONTAL = 0x247, // HID type SEL + HID_CONSUMER_AC_FLIP_VERTICAL = 0x248, // HID type SEL + HID_CONSUMER_AC_MIRROR_HORIZONTAL = 0x249, // HID type SEL + HID_CONSUMER_AC_MIRROR_VERTICAL = 0x24A, // HID type SEL + HID_CONSUMER_AC_FONT_SELECT = 0x24B, // HID type SEL + HID_CONSUMER_AC_FONT_COLOR = 0x24C, // HID type SEL + HID_CONSUMER_AC_FONT_SIZE = 0x24D, // HID type SEL + HID_CONSUMER_AC_JUSTIFY_LEFT = 0x24E, // HID type SEL + HID_CONSUMER_AC_JUSTIFY_CENTER_H = 0x24F, // HID type SEL + HID_CONSUMER_AC_JUSTIFY_RIGHT = 0x250, // HID type SEL + HID_CONSUMER_AC_JUSTIFY_BLOCK_H = 0x251, // HID type SEL + HID_CONSUMER_AC_JUSTIFY_TOP = 0x252, // HID type SEL + HID_CONSUMER_AC_JUSTIFY_CENTER_V = 0x253, // HID type SEL + HID_CONSUMER_AC_JUSTIFY_BOTTOM = 0x254, // HID type SEL + HID_CONSUMER_AC_JUSTIFY_BLOCK_V = 0x255, // HID type SEL + HID_CONSUMER_AC_INDENT_DECREASE = 0x256, // HID type SEL + HID_CONSUMER_AC_INDENT_INCREASE = 0x257, // HID type SEL + HID_CONSUMER_AC_NUMBERED_LIST = 0x258, // HID type SEL + HID_CONSUMER_AC_RESTART_NUMBERING = 0x259, // HID type SEL + HID_CONSUMER_AC_BULLETED_LIST = 0x25A, // HID type SEL + HID_CONSUMER_AC_PROMOTE = 0x25B, // HID type SEL + HID_CONSUMER_AC_DEMOTE = 0x25C, // HID type SEL + HID_CONSUMER_AC_YES = 0x25D, // HID type SEL + HID_CONSUMER_AC_NO = 0x25E, // HID type SEL + HID_CONSUMER_AC_CANCEL = 0x25F, // HID type SEL + HID_CONSUMER_AC_CATALOG = 0x260, // HID type SEL + HID_CONSUMER_AC_BUY_SLASH_CHECKOUT = 0x261, // HID type SEL + HID_CONSUMER_AC_ADD_TO_CART = 0x262, // HID type SEL + HID_CONSUMER_AC_EXPAND = 0x263, // HID type SEL + HID_CONSUMER_AC_EXPAND_ALL = 0x264, // HID type SEL + HID_CONSUMER_AC_COLLAPSE = 0x265, // HID type SEL + HID_CONSUMER_AC_COLLAPSE_ALL = 0x266, // HID type SEL + HID_CONSUMER_AC_PRINT_PREVIEW = 0x267, // HID type SEL + HID_CONSUMER_AC_PASTE_SPECIAL = 0x268, // HID type SEL + HID_CONSUMER_AC_INSERT_MODE = 0x269, // HID type SEL + HID_CONSUMER_AC_DELETE = 0x26A, // HID type SEL + HID_CONSUMER_AC_LOCK = 0x26B, // HID type SEL + HID_CONSUMER_AC_UNLOCK = 0x26C, // HID type SEL + HID_CONSUMER_AC_PROTECT = 0x26D, // HID type SEL + HID_CONSUMER_AC_UNPROTECT = 0x26E, // HID type SEL + HID_CONSUMER_AC_ATTACH_COMMENT = 0x26F, // HID type SEL + HID_CONSUMER_AC_DELETE_COMMENT = 0x270, // HID type SEL + HID_CONSUMER_AC_VIEW_COMMENT = 0x271, // HID type SEL + HID_CONSUMER_AC_SELECT_WORD = 0x272, // HID type SEL + HID_CONSUMER_AC_SELECT_SENTENCE = 0x273, // HID type SEL + HID_CONSUMER_AC_SELECT_PARAGRAPH = 0x274, // HID type SEL + HID_CONSUMER_AC_SELECT_COLUMN = 0x275, // HID type SEL + HID_CONSUMER_AC_SELECT_ROW = 0x276, // HID type SEL + HID_CONSUMER_AC_SELECT_TABLE = 0x277, // HID type SEL + HID_CONSUMER_AC_SELECT_OBJECT = 0x278, // HID type SEL + HID_CONSUMER_AC_REDO_SLASH_REPEAT = 0x279, // HID type SEL + HID_CONSUMER_AC_SORT = 0x27A, // HID type SEL + HID_CONSUMER_AC_SORT_ASCENDING = 0x27B, // HID type SEL + HID_CONSUMER_AC_SORT_DESCENDING = 0x27C, // HID type SEL + HID_CONSUMER_AC_FILTER = 0x27D, // HID type SEL + HID_CONSUMER_AC_SET_CLOCK = 0x27E, // HID type SEL + HID_CONSUMER_AC_VIEW_CLOCK = 0x27F, // HID type SEL + HID_CONSUMER_AC_SELECT_TIME_ZONE = 0x280, // HID type SEL + HID_CONSUMER_AC_EDIT_TIME_ZONES = 0x281, // HID type SEL + HID_CONSUMER_AC_SET_ALARM = 0x282, // HID type SEL + HID_CONSUMER_AC_CLEAR_ALARM = 0x283, // HID type SEL + HID_CONSUMER_AC_SNOOZE_ALARM = 0x284, // HID type SEL + HID_CONSUMER_AC_RESET_ALARM = 0x285, // HID type SEL + HID_CONSUMER_AC_SYNCHRONIZE = 0x286, // HID type SEL + HID_CONSUMER_AC_SEND_SLASH_RECEIVE = 0x287, // HID type SEL + HID_CONSUMER_AC_SEND_TO = 0x288, // HID type SEL + HID_CONSUMER_AC_REPLY = 0x289, // HID type SEL + HID_CONSUMER_AC_REPLY_ALL = 0x28A, // HID type SEL + HID_CONSUMER_AC_FORWARD_MSG = 0x28B, // HID type SEL + HID_CONSUMER_AC_SEND = 0x28C, // HID type SEL + HID_CONSUMER_AC_ATTACH_FILE = 0x28D, // HID type SEL + HID_CONSUMER_AC_UPLOAD = 0x28E, // HID type SEL + HID_CONSUMER_AC_DOWNLOAD_SAVE_TARGET_AS = 0x28F, // HID type SEL + HID_CONSUMER_AC_SET_BORDERS = 0x290, // HID type SEL + HID_CONSUMER_AC_INSERT_ROW = 0x291, // HID type SEL + HID_CONSUMER_AC_INSERT_COLUMN = 0x292, // HID type SEL + HID_CONSUMER_AC_INSERT_FILE = 0x293, // HID type SEL + HID_CONSUMER_AC_INSERT_PICTURE = 0x294, // HID type SEL + HID_CONSUMER_AC_INSERT_OBJECT = 0x295, // HID type SEL + HID_CONSUMER_AC_INSERT_SYMBOL = 0x296, // HID type SEL + HID_CONSUMER_AC_SAVE_AND_CLOSE = 0x297, // HID type SEL + HID_CONSUMER_AC_RENAME = 0x298, // HID type SEL + HID_CONSUMER_AC_MERGE = 0x299, // HID type SEL + HID_CONSUMER_AC_SPLIT = 0x29A, // HID type SEL + HID_CONSUMER_AC_DISRIBUTE_HORIZONTALLY = 0x29B, // HID type SEL + HID_CONSUMER_AC_DISTRIBUTE_VERTICALLY = 0x29C, // HID type SEL +}; + + +typedef union { + // Every usable Consumer key possible, up to 4 keys presses possible + uint8_t whole8[]; + uint16_t whole16[]; + uint32_t whole32[]; + ConsumerKeycode keys[4]; + struct { + ConsumerKeycode key1; + ConsumerKeycode key2; + ConsumerKeycode key3; + ConsumerKeycode key4; + }; +} HID_ConsumerControlReport_Data_t; + + +class Consumer_ { public: Consumer_(void); + inline void begin(void); + inline void end(void); + inline void write(ConsumerKeycode m); + inline void press(ConsumerKeycode m); + inline void release(ConsumerKeycode m); + inline void releaseAll(void); + + // Sending is public in the base class for advanced users. + virtual void SendReport(void* data, int length) = 0; + protected: - virtual inline void SendReport(void* data, int length) override; + HID_ConsumerControlReport_Data_t _report; }; extern Consumer_ Consumer; - From 4a126cb9427f1d9f6f5b5f26649544748945ac0e Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Wed, 9 Dec 2015 20:14:00 -0800 Subject: [PATCH 358/602] Fixup 'extra' includes --- plugins/KeyboardioHID/src/MultiReport/Consumer.h | 1 - plugins/KeyboardioHID/src/MultiReport/Gamepad.h | 1 - 2 files changed, 2 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/Consumer.h b/plugins/KeyboardioHID/src/MultiReport/Consumer.h index 269576cdac..fefc06d9e5 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Consumer.h +++ b/plugins/KeyboardioHID/src/MultiReport/Consumer.h @@ -28,7 +28,6 @@ THE SOFTWARE. #include "PluggableUSB.h" #include "HID.h" #include "HID-Settings.h" -#include "../HID-APIs/ConsumerAPI.h" enum ConsumerKeycode : uint16_t { // Some keys might only work with linux diff --git a/plugins/KeyboardioHID/src/MultiReport/Gamepad.h b/plugins/KeyboardioHID/src/MultiReport/Gamepad.h index fcaed927a3..cf830d8fcd 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Gamepad.h +++ b/plugins/KeyboardioHID/src/MultiReport/Gamepad.h @@ -28,7 +28,6 @@ THE SOFTWARE. #include "PluggableUSB.h" #include "HID.h" #include "HID-Settings.h" -#include "../HID-APIs/GamepadAPI.h" // Dpad directions #define GAMEPAD_DPAD_CENTERED 0 From 12a3b954f0dcd0802ab436794c2fa6d35991991d Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Wed, 9 Dec 2015 20:21:39 -0800 Subject: [PATCH 359/602] Remove RawHID implementation. It's not yet working upstream and isn't part of the Model 01's design. --- .../KeyboardFeatureReport.ino | 84 ---- .../examples/RawHID/RawHID/RawHID.ino | 71 --- .../RawHIDPaintpack/RawHIDPaintpack.ino | 92 ---- plugins/KeyboardioHID/extras/rawhid/Makefile | 59 --- plugins/KeyboardioHID/extras/rawhid/hid.h | 6 - .../KeyboardioHID/extras/rawhid/hid_LINUX.c | 381 ---------------- .../KeyboardioHID/extras/rawhid/hid_MACOSX.c | 412 ------------------ .../KeyboardioHID/extras/rawhid/hid_WINDOWS.c | 328 -------------- .../KeyboardioHID/extras/rawhid/rawhid_test.c | 101 ----- .../KeyboardioHID/src/SingleReport/RawHID.cpp | 149 ------- .../KeyboardioHID/src/SingleReport/RawHID.h | 180 -------- 11 files changed, 1863 deletions(-) delete mode 100644 plugins/KeyboardioHID/examples/RawHID/KeyboardFeatureReport/KeyboardFeatureReport.ino delete mode 100644 plugins/KeyboardioHID/examples/RawHID/RawHID/RawHID.ino delete mode 100644 plugins/KeyboardioHID/examples/RawHID/RawHIDPaintpack/RawHIDPaintpack.ino delete mode 100644 plugins/KeyboardioHID/extras/rawhid/Makefile delete mode 100644 plugins/KeyboardioHID/extras/rawhid/hid.h delete mode 100644 plugins/KeyboardioHID/extras/rawhid/hid_LINUX.c delete mode 100644 plugins/KeyboardioHID/extras/rawhid/hid_MACOSX.c delete mode 100644 plugins/KeyboardioHID/extras/rawhid/hid_WINDOWS.c delete mode 100644 plugins/KeyboardioHID/extras/rawhid/rawhid_test.c delete mode 100644 plugins/KeyboardioHID/src/SingleReport/RawHID.cpp delete mode 100644 plugins/KeyboardioHID/src/SingleReport/RawHID.h diff --git a/plugins/KeyboardioHID/examples/RawHID/KeyboardFeatureReport/KeyboardFeatureReport.ino b/plugins/KeyboardioHID/examples/RawHID/KeyboardFeatureReport/KeyboardFeatureReport.ino deleted file mode 100644 index 5946924206..0000000000 --- a/plugins/KeyboardioHID/examples/RawHID/KeyboardFeatureReport/KeyboardFeatureReport.ino +++ /dev/null @@ -1,84 +0,0 @@ -/* - Copyright (c) 2014-2015 NicoHood - See the readme for credit to other people. - - KeyboardFeatureReport example - - Shows how to use BootKeyboard with a modified Hyperion Lightpack device. - This example also works with RawHID. - Might only work under linux. - https://github.com/tvdzwan/hyperion/pull/407 - https://github.com/tvdzwan/hyperion/wiki - https://github.com/FastLED/FastLED - - See HID Project documentation for more information. - https://github.com/NicoHood/HID/wiki/RawHID-API - https://github.com/NicoHood/HID/wiki/Keyboard-API#boot-keyboard -*/ - -#include "HID-Project.h" - -const int pinLed = LED_BUILTIN; - - -// FastLED -#include "FastLED.h" - -#define LED_PINS MOSI, SCK // DATA_PIN, or DATA_PIN, CLOCK_PIN -#define COLOR_ORDER RGB -#define CHIPSET WS2801 // WS2811, LPD8806, etc -#define NUM_LEDS 25 - -#define BRIGHTNESS 255 // Reduce power consumption -#define LED_DITHER 255 // Try 0 to disable flickering -#define CORRECTION TypicalLEDStrip - -CRGB leds[NUM_LEDS]; // Define the array of leds - -void setup() { - // FastLED setup - FastLED.addLeds(leds, NUM_LEDS).setCorrection(CORRECTION); - FastLED.setBrightness(BRIGHTNESS); - FastLED.setDither(LED_DITHER); - - // Startup animation - fill_solid(leds, NUM_LEDS, CRGB::Red); - FastLED.show(); - delay(500); - fill_solid(leds, NUM_LEDS, CRGB::Green); - FastLED.show(); - delay(500); - fill_solid(leds, NUM_LEDS, CRGB::Blue); - FastLED.show(); - delay(500); - FastLED.clear(); - FastLED.show(); - - pinMode(pinLed, OUTPUT); - - // Sends a clean report to the host. This is important on any Arduino type. - BootKeyboard.begin(); - - // Let the feature report data directly point at the led array - BootKeyboard.setFeatureReport(leds, sizeof(leds)); - BootKeyboard.enableFeatureReport(); -} - -void loop() { - // Check if there is new feature request data from the keyboard - if (BootKeyboard.availableFeatureReport()) - { - digitalWrite(pinLed, HIGH); - - // Update leds, do not update in the loop, to avoid corrupted data. - // For example if you write (0, 0, 0) and the interrupt - // changes the data to (255, 255, 255) you might get (0, 255, 255). - // Using a duplicated led array in cli() context would also work. - FastLED.show(); - - // Release data to let the USB interrupt overwrite it again - BootKeyboard.enableFeatureReport(); - - digitalWrite(pinLed, LOW); - } -} diff --git a/plugins/KeyboardioHID/examples/RawHID/RawHID/RawHID.ino b/plugins/KeyboardioHID/examples/RawHID/RawHID/RawHID.ino deleted file mode 100644 index 0ab8c45969..0000000000 --- a/plugins/KeyboardioHID/examples/RawHID/RawHID/RawHID.ino +++ /dev/null @@ -1,71 +0,0 @@ -/* - Copyright (c) 2014-2015 NicoHood - See the readme for credit to other people. - - Advanced RawHID example - - Shows how to send bytes via RawHID. - Press a button to send some example values. - - Every received data is mirrored to the host via Serial. - - See HID Project documentation for more information. - https://github.com/NicoHood/HID/wiki/RawHID-API -*/ - -#include "HID-Project.h" - -const int pinLed = LED_BUILTIN; -const int pinButton = 2; - -// Buffer to hold RawHID data. -// If host tries to send more data than this, -// it will respond with an error. -// If the data is not read until the host sends the next data -// it will also respond with an error and the data will be lost. -uint8_t rawhidData[255]; - -void setup() { - pinMode(pinLed, OUTPUT); - pinMode(pinButton, INPUT_PULLUP); - - Serial.begin(115200); - - // Set the RawHID OUT report array. - // Feature reports are also (parallel) possible, see the other example for this. - RawHID.begin(rawhidData, sizeof(rawhidData)); -} - -void loop() { - // Send data to the host - if (!digitalRead(pinButton)) { - digitalWrite(pinLed, HIGH); - - // Create buffer with numbers and send it - uint8_t megabuff[100]; - for (uint8_t i = 0; i < sizeof(megabuff); i++) { - megabuff[i] = i; - } - RawHID.write(megabuff, sizeof(megabuff)); - - // Simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } - - - // Check if there is new data from the RawHID device - auto bytesAvailable = RawHID.available(); - if (bytesAvailable) - { - digitalWrite(pinLed, HIGH); - - // Mirror data via Serial - while (bytesAvailable--) { - Serial.println(RawHID.read()); - } - - digitalWrite(pinLed, LOW); - } -} - diff --git a/plugins/KeyboardioHID/examples/RawHID/RawHIDPaintpack/RawHIDPaintpack.ino b/plugins/KeyboardioHID/examples/RawHID/RawHIDPaintpack/RawHIDPaintpack.ino deleted file mode 100644 index 40e540d443..0000000000 --- a/plugins/KeyboardioHID/examples/RawHID/RawHIDPaintpack/RawHIDPaintpack.ino +++ /dev/null @@ -1,92 +0,0 @@ -/* - Copyright (c) 2014-2015 NicoHood - See the readme for credit to other people. - - RawHIDPaintpack example - - Shows how to use RawHID with the Hyperion Lightpack device. - https://github.com/tvdzwan/hyperion/wiki - https://github.com/FastLED/FastLED - - See HID Project documentation for more information. - https://github.com/NicoHood/HID/wiki/RawHID-API - https://github.com/NicoHood/HID/wiki/Keyboard-API#boot-keyboard -*/ - -#include "HID-Project.h" - -const int pinLed = LED_BUILTIN; - - -// FastLED -#include "FastLED.h" - -#define LED_PINS MOSI, SCK // DATA_PIN, or DATA_PIN, CLOCK_PIN -#define COLOR_ORDER RGB -#define CHIPSET WS2801 // WS2811, LPD8806, etc -#define NUM_LEDS 25 - -#define BRIGHTNESS 255 // Reduce power consumption -#define LED_DITHER 255 // Try 0 to disable flickering -#define CORRECTION TypicalLEDStrip - -CRGB leds[NUM_LEDS]; // Define the array of leds -uint8_t rawhidData[sizeof(leds) + 2]; - -void setup() { - // FastLED setup - FastLED.addLeds(leds, NUM_LEDS).setCorrection(CORRECTION); - FastLED.setBrightness(BRIGHTNESS); - FastLED.setDither(LED_DITHER); - - // Startup animation - fill_solid(leds, NUM_LEDS, CRGB::Red); - FastLED.show(); - delay(500); - fill_solid(leds, NUM_LEDS, CRGB::Green); - FastLED.show(); - delay(500); - fill_solid(leds, NUM_LEDS, CRGB::Blue); - FastLED.show(); - delay(500); - FastLED.clear(); - FastLED.show(); - - pinMode(pinLed, OUTPUT); - - // Set the RawHID OUT report array. - // Feature reports are also (parallel) possible, see the other example for this. - RawHID.begin(rawhidData, sizeof(rawhidData)); -} - -void loop() { - // Check if there is new data from the RawHID device - auto bytesAvailable = RawHID.available(); - if (bytesAvailable == sizeof(rawhidData)) - { - digitalWrite(pinLed, HIGH); - - // Check header for errors - if (RawHID.read() != 3) { - return; - } - if (RawHID.read() != 0) { - return; - } - - // Write data to led array - uint8_t* ptr = (uint8_t*)leds; - for (int i = 0; i < sizeof(leds); i++) { - *ptr = RawHID.read(); - ptr++; - } - - // Update leds, do not update in the loop, to avoid corrupted data. - // For example if you write (0, 0, 0) and the interrupt - // changes the data to (255, 255, 255) you might get (0, 255, 255). - // Using a duplicated led array in cli() context would also work. - FastLED.show(); - - digitalWrite(pinLed, LOW); - } -} diff --git a/plugins/KeyboardioHID/extras/rawhid/Makefile b/plugins/KeyboardioHID/extras/rawhid/Makefile deleted file mode 100644 index c09ecdc8be..0000000000 --- a/plugins/KeyboardioHID/extras/rawhid/Makefile +++ /dev/null @@ -1,59 +0,0 @@ - -OS = LINUX -#OS = MACOSX -#OS = WINDOWS - -PROG = rawhid_test - -# To set up Ubuntu Linux to cross compile for Windows: -# -# apt-get install mingw32 mingw32-binutils mingw32-runtime libusb-dev -# -# Just edit the variable above for WINDOWS, then use "make" to build rawhid.exe - -ifeq ($(OS), LINUX) -TARGET = $(PROG) -CC = gcc -STRIP = strip -CFLAGS = -Wall -O2 -DOS_$(OS) -LIBS = -lusb -else ifeq ($(OS), MACOSX) -TARGET = $(PROG).dmg -SDK = /Developer/SDKs/MacOSX10.5.sdk -ARCH = -mmacosx-version-min=10.5 -arch ppc -arch i386 -CC = gcc -STRIP = strip -CFLAGS = -Wall -O2 -DOS_$(OS) -isysroot $(SDK) $(ARCH) -LIBS = $(ARCH) -Wl,-syslibroot,$(SDK) -framework IOKit -framework CoreFoundation -else ifeq ($(OS), WINDOWS) -TARGET = $(PROG).exe -CC = i586-mingw32msvc-gcc -STRIP = i586-mingw32msvc-strip -CFLAGS = -Wall -O2 -DOS_$(OS) -LIBS = -lhid -lsetupapi -endif - -OBJS = $(PROG).o hid.o - - -all: $(TARGET) - -$(PROG): $(OBJS) - $(CC) -o $(PROG) $(OBJS) $(LIBS) - $(STRIP) $(PROG) - -$(PROG).exe: $(PROG) - cp $(PROG) $(PROG).exe - -$(PROG).dmg: $(PROG) - mkdir tmp - cp $(PROG) tmp - hdiutil create -ov -volname "Raw HID Test" -srcfolder tmp $(PROG).dmg - -hid.o: hid_$(OS).c hid.h - $(CC) $(CFLAGS) -c -o $@ $< - -clean: - rm -f *.o $(PROG) $(PROG).exe $(PROG).dmg - rm -rf tmp - diff --git a/plugins/KeyboardioHID/extras/rawhid/hid.h b/plugins/KeyboardioHID/extras/rawhid/hid.h deleted file mode 100644 index 4d837035e1..0000000000 --- a/plugins/KeyboardioHID/extras/rawhid/hid.h +++ /dev/null @@ -1,6 +0,0 @@ - -int rawhid_open(int max, int vid, int pid, int usage_page, int usage); -int rawhid_recv(int num, void *buf, int len, int timeout); -int rawhid_send(int num, void *buf, int len, int timeout); -void rawhid_close(int num); - diff --git a/plugins/KeyboardioHID/extras/rawhid/hid_LINUX.c b/plugins/KeyboardioHID/extras/rawhid/hid_LINUX.c deleted file mode 100644 index 799797ecb0..0000000000 --- a/plugins/KeyboardioHID/extras/rawhid/hid_LINUX.c +++ /dev/null @@ -1,381 +0,0 @@ -/* Simple Raw HID functions for Linux - for use with Teensy RawHID example - * http://www.pjrc.com/teensy/rawhid.html - * Copyright (c) 2009 PJRC.COM, LLC - * - * rawhid_open - open 1 or more devices - * rawhid_recv - receive a packet - * rawhid_send - send a packet - * rawhid_close - close a device - * - * 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 description, website URL and 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 - */ - -#include -#include -#include -#include - -#include "hid.h" - - -// On Linux there are several options to access HID devices. -// -// libusb 0.1 - the only way that works well on all distributions -// libusb 1.0 - someday will become standard on most distributions -// hidraw driver - relatively new, not supported on many distributions (yet) -// hiddev driver - old, ubuntu, fedora, others dropping support -// usbfs - low level usb API: http://www.kernel.org/doc/htmldocs/usb.html#usbfs -// -// This code uses libusb 0.1, which is well supported on all linux distributions -// and very stable and widely used by many programs. libusb 0.1 only provides a -// simple synchronous interface, basically the same as this code needs. However, -// if you want non-blocking I/O, libusb 0.1 simply does not provide that. There -// is also no kernel-level buffering, so performance is poor. -// -// UPDATE: As of November 2011, hidraw support seems to be working well in all -// major linux distributions. Embedded and "small" distros, used on ARM boards, -// routers and embedded hardware stil seem to omit the hidraw driver. -// -// The hidraw driver is a great solution. However, it has only been supported -// by relatively recent (in 2009) kernels. Here is a quick survey of the status -// of hidraw support in various distributions as of Sept 2009: -// -// Fedora 11: works, kernel 2.6.29.4 -// Mandiva 2009.1: works, kernel 2.6.29.1 -// Ubuntu 9.10-alpha6: works, kernel 2.6.31 -// Ubuntu 9.04: sysfs attrs chain broken (hidraw root only), 2.6.28 kernel -// openSUSE 11.1: sysfs attrs chain broken (hidraw root only), 2.6.27.7 kernel -// Debian Live, Lenny 5.0.2: sysfs attrs chain broken (hidraw root only), 2.6.26 -// SimplyMEPIS 8.0.10: sysfs attrs chain broken (hidraw root only), 2.6.27 -// Mint 7: sysfs attrs chain broken (hidraw root only), 2.6.28 kernel -// Gentoo 2008.0-r1: sysfs attrs chain broken (hidraw root only), 2.6.24 kernel -// Centos 5: no hidraw or hiddev devices, 2.6.18 kernel -// Slitaz 2.0: no hidraw devices (has hiddev), 2.6.25.5 kernel -// Puppy 4.3: no hidraw devices (has hiddev), 2.6.30.5 kernel -// Damn Small 4.4.10: (would not boot) -// Gentoo 10.0-test20090926: (would not boot) -// PCLinuxOS 2009.2: (would not boot) -// Slackware: (no live cd available? www.slackware-live.org dead) - - - -#define printf(...) // comment this out for lots of info - - -// a list of all opened HID devices, so the caller can -// simply refer to them by number -typedef struct hid_struct hid_t; -static hid_t *first_hid = NULL; -static hid_t *last_hid = NULL; -struct hid_struct { - usb_dev_handle *usb; - int open; - int iface; - int ep_in; - int ep_out; - struct hid_struct *prev; - struct hid_struct *next; -}; - - -// private functions, not intended to be used from outside this file -static void add_hid(hid_t *h); -static hid_t * get_hid(int num); -static void free_all_hid(void); -static void hid_close(hid_t *hid); -static int hid_parse_item(uint32_t *val, uint8_t **data, const uint8_t *end); - - -// rawhid_recv - receive a packet -// Inputs: -// num = device to receive from (zero based) -// buf = buffer to receive packet -// len = buffer's size -// timeout = time to wait, in milliseconds -// Output: -// number of bytes received, or -1 on error -// -int rawhid_recv(int num, void *buf, int len, int timeout) -{ - hid_t *hid; - int r; - - hid = get_hid(num); - if (!hid || !hid->open) return -1; - r = usb_interrupt_read(hid->usb, hid->ep_in, buf, len, timeout); - if (r >= 0) return r; - if (r == -110) return 0; // timeout - return -1; -} - -// rawhid_send - send a packet -// Inputs: -// num = device to transmit to (zero based) -// buf = buffer containing packet to send -// len = number of bytes to transmit -// timeout = time to wait, in milliseconds -// Output: -// number of bytes sent, or -1 on error -// -int rawhid_send(int num, void *buf, int len, int timeout) -{ - hid_t *hid; - - hid = get_hid(num); - if (!hid || !hid->open) return -1; - if (hid->ep_out) { - return usb_interrupt_write(hid->usb, hid->ep_out, buf, len, timeout); - } else { - return usb_control_msg(hid->usb, 0x21, 9, 0x0200, hid->iface, buf, len, timeout); - } -} - -// rawhid_open - open 1 or more devices -// -// Inputs: -// max = maximum number of devices to open -// vid = Vendor ID, or -1 if any -// pid = Product ID, or -1 if any -// usage_page = top level usage page, or -1 if any -// usage = top level usage number, or -1 if any -// Output: -// actual number of devices opened -// -int rawhid_open(int max, int vid, int pid, int usage_page, int usage) -{ - struct usb_bus *bus; - struct usb_device *dev; - struct usb_interface *iface; - struct usb_interface_descriptor *desc; - struct usb_endpoint_descriptor *ep; - usb_dev_handle *u; - uint8_t buf[1024], *p; - int i, n, len, tag, ep_in, ep_out, count=0, claimed; - uint32_t val=0, parsed_usage, parsed_usage_page; - hid_t *hid; - - if (first_hid) free_all_hid(); - printf("rawhid_open, max=%d\n", max); - if (max < 1) return 0; - usb_init(); - usb_find_busses(); - usb_find_devices(); - for (bus = usb_get_busses(); bus; bus = bus->next) { - for (dev = bus->devices; dev; dev = dev->next) { - if (vid > 0 && dev->descriptor.idVendor != vid) continue; - if (pid > 0 && dev->descriptor.idProduct != pid) continue; - if (!dev->config) continue; - if (dev->config->bNumInterfaces < 1) continue; - printf("device: vid=%04X, pic=%04X, with %d iface\n", - dev->descriptor.idVendor, - dev->descriptor.idProduct, - dev->config->bNumInterfaces); - iface = dev->config->interface; - u = NULL; - claimed = 0; - for (i=0; iconfig->bNumInterfaces && iface; i++, iface++) { - desc = iface->altsetting; - if (!desc) continue; - printf(" type %d, %d, %d\n", desc->bInterfaceClass, - desc->bInterfaceSubClass, desc->bInterfaceProtocol); - if (desc->bInterfaceClass != 3) continue; - if (desc->bInterfaceSubClass != 0) continue; - if (desc->bInterfaceProtocol != 0) continue; - ep = desc->endpoint; - ep_in = ep_out = 0; - for (n = 0; n < desc->bNumEndpoints; n++, ep++) { - if (ep->bEndpointAddress & 0x80) { - if (!ep_in) ep_in = ep->bEndpointAddress & 0x7F; - printf(" IN endpoint %d\n", ep_in); - } else { - if (!ep_out) ep_out = ep->bEndpointAddress; - printf(" OUT endpoint %d\n", ep_out); - } - } - if (!ep_in) continue; - if (!u) { - u = usb_open(dev); - if (!u) { - printf(" unable to open device\n"); - break; - } - } - printf(" hid interface (generic)\n"); - if (usb_get_driver_np(u, i, (char *)buf, sizeof(buf)) >= 0) { - printf(" in use by driver \"%s\"\n", buf); - if (usb_detach_kernel_driver_np(u, i) < 0) { - printf(" unable to detach from kernel\n"); - continue; - } - } - if (usb_claim_interface(u, i) < 0) { - printf(" unable claim interface %d\n", i); - continue; - } - len = usb_control_msg(u, 0x81, 6, 0x2200, i, (char *)buf, sizeof(buf), 250); - printf(" descriptor, len=%d\n", len); - if (len < 2) { - usb_release_interface(u, i); - continue; - } - p = buf; - parsed_usage_page = parsed_usage = 0; - while ((tag = hid_parse_item(&val, &p, buf + len)) >= 0) { - printf(" tag: %X, val %X\n", tag, val); - if (tag == 4) parsed_usage_page = val; - if (tag == 8) parsed_usage = val; - if (parsed_usage_page && parsed_usage) break; - } - if ((!parsed_usage_page) || (!parsed_usage) || - (usage_page > 0 && parsed_usage_page != usage_page) || - (usage > 0 && parsed_usage != usage)) { - usb_release_interface(u, i); - continue; - } - hid = (struct hid_struct *)malloc(sizeof(struct hid_struct)); - if (!hid) { - usb_release_interface(u, i); - continue; - } - hid->usb = u; - hid->iface = i; - hid->ep_in = ep_in; - hid->ep_out = ep_out; - hid->open = 1; - add_hid(hid); - claimed++; - count++; - if (count >= max) return count; - } - if (u && !claimed) usb_close(u); - } - } - return count; -} - - -// rawhid_close - close a device -// -// Inputs: -// num = device to close (zero based) -// Output -// (nothing) -// -void rawhid_close(int num) -{ - hid_t *hid; - - hid = get_hid(num); - if (!hid || !hid->open) return; - hid_close(hid); -} - -// Chuck Robey wrote a real HID report parser -// (chuckr@telenix.org) chuckr@chuckr.org -// http://people.freebsd.org/~chuckr/code/python/uhidParser-0.2.tbz -// this tiny thing only needs to extract the top-level usage page -// and usage, and even then is may not be truly correct, but it does -// work with the Teensy Raw HID example. -static int hid_parse_item(uint32_t *val, uint8_t **data, const uint8_t *end) -{ - const uint8_t *p = *data; - uint8_t tag; - int table[4] = {0, 1, 2, 4}; - int len; - - if (p >= end) return -1; - if (p[0] == 0xFE) { - // long item, HID 1.11, 6.2.2.3, page 27 - if (p + 5 >= end || p + p[1] >= end) return -1; - tag = p[2]; - *val = 0; - len = p[1] + 5; - } else { - // short item, HID 1.11, 6.2.2.2, page 26 - tag = p[0] & 0xFC; - len = table[p[0] & 0x03]; - if (p + len + 1 >= end) return -1; - switch (p[0] & 0x03) { - case 3: *val = p[1] | (p[2] << 8) | (p[3] << 16) | (p[4] << 24); break; - case 2: *val = p[1] | (p[2] << 8); break; - case 1: *val = p[1]; break; - case 0: *val = 0; break; - } - } - *data += len + 1; - return tag; -} - - -static void add_hid(hid_t *h) -{ - if (!first_hid || !last_hid) { - first_hid = last_hid = h; - h->next = h->prev = NULL; - return; - } - last_hid->next = h; - h->prev = last_hid; - h->next = NULL; - last_hid = h; -} - - -static hid_t * get_hid(int num) -{ - hid_t *p; - for (p = first_hid; p && num > 0; p = p->next, num--) ; - return p; -} - - -static void free_all_hid(void) -{ - hid_t *p, *q; - - for (p = first_hid; p; p = p->next) { - hid_close(p); - } - p = first_hid; - while (p) { - q = p; - p = p->next; - free(q); - } - first_hid = last_hid = NULL; -} - - -static void hid_close(hid_t *hid) -{ - hid_t *p; - int others=0; - - usb_release_interface(hid->usb, hid->iface); - for (p = first_hid; p; p = p->next) { - if (p->open && p->usb == hid->usb) others++; - } - if (!others) usb_close(hid->usb); - hid->usb = NULL; -} - - - diff --git a/plugins/KeyboardioHID/extras/rawhid/hid_MACOSX.c b/plugins/KeyboardioHID/extras/rawhid/hid_MACOSX.c deleted file mode 100644 index c5d5d1bbba..0000000000 --- a/plugins/KeyboardioHID/extras/rawhid/hid_MACOSX.c +++ /dev/null @@ -1,412 +0,0 @@ -/* Simple Raw HID functions for Linux - for use with Teensy RawHID example - * http://www.pjrc.com/teensy/rawhid.html - * Copyright (c) 2009 PJRC.COM, LLC - * - * rawhid_open - open 1 or more devices - * rawhid_recv - receive a packet - * rawhid_send - send a packet - * rawhid_close - close a device - * - * 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 description, website URL and 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 - */ - -#include -#include -#include -#include -#include -#include - -#include "hid.h" - -#define BUFFER_SIZE 64 - -#define printf(...) // comment this out to get lots of info printed - - -// a list of all opened HID devices, so the caller can -// simply refer to them by number -typedef struct hid_struct hid_t; -typedef struct buffer_struct buffer_t; -static hid_t *first_hid = NULL; -static hid_t *last_hid = NULL; -struct hid_struct { - IOHIDDeviceRef ref; - int open; - uint8_t buffer[BUFFER_SIZE]; - buffer_t *first_buffer; - buffer_t *last_buffer; - struct hid_struct *prev; - struct hid_struct *next; -}; -struct buffer_struct { - struct buffer_struct *next; - uint32_t len; - uint8_t buf[BUFFER_SIZE]; -}; - -// private functions, not intended to be used from outside this file -static void add_hid(hid_t *); -static hid_t * get_hid(int); -static void free_all_hid(void); -static void hid_close(hid_t *); -static void attach_callback(void *, IOReturn, void *, IOHIDDeviceRef); -static void detach_callback(void *, IOReturn, void *hid_mgr, IOHIDDeviceRef dev); -static void timeout_callback(CFRunLoopTimerRef, void *); -static void input_callback(void *, IOReturn, void *, IOHIDReportType, - uint32_t, uint8_t *, CFIndex); - - - -// rawhid_recv - receive a packet -// Inputs: -// num = device to receive from (zero based) -// buf = buffer to receive packet -// len = buffer's size -// timeout = time to wait, in milliseconds -// Output: -// number of bytes received, or -1 on error -// -int rawhid_recv(int num, void *buf, int len, int timeout) -{ - hid_t *hid; - buffer_t *b; - CFRunLoopTimerRef timer=NULL; - CFRunLoopTimerContext context; - int ret=0, timeout_occurred=0; - - if (len < 1) return 0; - hid = get_hid(num); - if (!hid || !hid->open) return -1; - if ((b = hid->first_buffer) != NULL) { - if (len > b->len) len = b->len; - memcpy(buf, b->buf, len); - hid->first_buffer = b->next; - free(b); - return len; - } - memset(&context, 0, sizeof(context)); - context.info = &timeout_occurred; - timer = CFRunLoopTimerCreate(NULL, CFAbsoluteTimeGetCurrent() + - (double)timeout / 1000.0, 0, 0, 0, timeout_callback, &context); - CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, kCFRunLoopDefaultMode); - while (1) { - CFRunLoopRun(); - if ((b = hid->first_buffer) != NULL) { - if (len > b->len) len = b->len; - memcpy(buf, b->buf, len); - hid->first_buffer = b->next; - free(b); - ret = len; - break; - } - if (!hid->open) { - printf("rawhid_recv, device not open\n"); - ret = -1; - break; - } - if (timeout_occurred) break; - } - CFRunLoopTimerInvalidate(timer); - CFRelease(timer); - return ret; -} - -static void input_callback(void *context, IOReturn ret, void *sender, - IOHIDReportType type, uint32_t id, uint8_t *data, CFIndex len) -{ - buffer_t *n; - hid_t *hid; - - printf("input_callback\n"); - if (ret != kIOReturnSuccess || len < 1) return; - hid = context; - if (!hid || hid->ref != sender) return; - n = (buffer_t *)malloc(sizeof(buffer_t)); - if (!n) return; - if (len > BUFFER_SIZE) len = BUFFER_SIZE; - memcpy(n->buf, data, len); - n->len = len; - n->next = NULL; - if (!hid->first_buffer || !hid->last_buffer) { - hid->first_buffer = hid->last_buffer = n; - } else { - hid->last_buffer->next = n; - hid->last_buffer = n; - } - CFRunLoopStop(CFRunLoopGetCurrent()); -} - -static void timeout_callback(CFRunLoopTimerRef timer, void *info) -{ - printf("timeout_callback\n"); - *(int *)info = 1; - CFRunLoopStop(CFRunLoopGetCurrent()); -} - - -void output_callback(void *context, IOReturn ret, void *sender, - IOHIDReportType type, uint32_t id, uint8_t *data, CFIndex len) -{ - printf("output_callback, r=%d\n", ret); - if (ret == kIOReturnSuccess) { - *(int *)context = len; - } else { - // timeout if not success? - *(int *)context = 0; - } - CFRunLoopStop(CFRunLoopGetCurrent()); -} - - -// rawhid_send - send a packet -// Inputs: -// num = device to transmit to (zero based) -// buf = buffer containing packet to send -// len = number of bytes to transmit -// timeout = time to wait, in milliseconds -// Output: -// number of bytes sent, or -1 on error -// -int rawhid_send(int num, void *buf, int len, int timeout) -{ - hid_t *hid; - int result=-100; - - hid = get_hid(num); - if (!hid || !hid->open) return -1; -#if 1 - #warning "Send timeout not implemented on MACOSX" - IOReturn ret = IOHIDDeviceSetReport(hid->ref, kIOHIDReportTypeOutput, 0, buf, len); - result = (ret == kIOReturnSuccess) ? len : -1; -#endif -#if 0 - // No matter what I tried this never actually sends an output - // report and output_callback never gets called. Why?? - // Did I miss something? This is exactly the same params as - // the sync call that works. Is it an Apple bug? - // (submitted to Apple on 22-sep-2009, problem ID 7245050) - // - IOHIDDeviceScheduleWithRunLoop(hid->ref, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); - // should already be scheduled with run loop by attach_callback, - // sadly this doesn't make any difference either way - - // could this be related? - // http://lists.apple.com/archives/usb/2008/Aug/msg00021.html - // - IOHIDDeviceSetReportWithCallback(hid->ref, kIOHIDReportTypeOutput, - 0, buf, len, (double)timeout / 1000.0, output_callback, &result); - while (1) { - printf("enter run loop (send)\n"); - CFRunLoopRun(); - printf("leave run loop (send)\n"); - if (result > -100) break; - if (!hid->open) { - result = -1; - break; - } - } -#endif - return result; -} - - -// rawhid_open - open 1 or more devices -// -// Inputs: -// max = maximum number of devices to open -// vid = Vendor ID, or -1 if any -// pid = Product ID, or -1 if any -// usage_page = top level usage page, or -1 if any -// usage = top level usage number, or -1 if any -// Output: -// actual number of devices opened -// -int rawhid_open(int max, int vid, int pid, int usage_page, int usage) -{ - static IOHIDManagerRef hid_manager=NULL; - CFMutableDictionaryRef dict; - CFNumberRef num; - IOReturn ret; - hid_t *p; - int count=0; - - if (first_hid) free_all_hid(); - printf("rawhid_open, max=%d\n", max); - if (max < 1) return 0; - // Start the HID Manager - // http://developer.apple.com/technotes/tn2007/tn2187.html - if (!hid_manager) { - hid_manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); - if (hid_manager == NULL || CFGetTypeID(hid_manager) != IOHIDManagerGetTypeID()) { - if (hid_manager) CFRelease(hid_manager); - return 0; - } - } - if (vid > 0 || pid > 0 || usage_page > 0 || usage > 0) { - // Tell the HID Manager what type of devices we want - dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - if (!dict) return 0; - if (vid > 0) { - num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &vid); - CFDictionarySetValue(dict, CFSTR(kIOHIDVendorIDKey), num); - CFRelease(num); - } - if (pid > 0) { - num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &pid); - CFDictionarySetValue(dict, CFSTR(kIOHIDProductIDKey), num); - CFRelease(num); - } - if (usage_page > 0) { - num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usage_page); - CFDictionarySetValue(dict, CFSTR(kIOHIDPrimaryUsagePageKey), num); - CFRelease(num); - } - if (usage > 0) { - num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usage); - CFDictionarySetValue(dict, CFSTR(kIOHIDPrimaryUsageKey), num); - CFRelease(num); - } - IOHIDManagerSetDeviceMatching(hid_manager, dict); - CFRelease(dict); - } else { - IOHIDManagerSetDeviceMatching(hid_manager, NULL); - } - // set up a callbacks for device attach & detach - 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); - return 0; - } - printf("run loop\n"); - // let it do the callback for all devices - while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true) == kCFRunLoopRunHandledSource) ; - // count up how many were added by the callback - for (p = first_hid; p; p = p->next) count++; - return count; -} - - -// rawhid_close - close a device -// -// Inputs: -// num = device to close (zero based) -// Output -// (nothing) -// -void rawhid_close(int num) -{ - hid_t *hid; - - hid = get_hid(num); - if (!hid || !hid->open) return; - hid_close(hid); - hid->open = 0; -} - - -static void add_hid(hid_t *h) -{ - if (!first_hid || !last_hid) { - first_hid = last_hid = h; - h->next = h->prev = NULL; - return; - } - last_hid->next = h; - h->prev = last_hid; - h->next = NULL; - last_hid = h; -} - - -static hid_t * get_hid(int num) -{ - hid_t *p; - for (p = first_hid; p && num > 0; p = p->next, num--) ; - return p; -} - - -static void free_all_hid(void) -{ - hid_t *p, *q; - - for (p = first_hid; p; p = p->next) { - hid_close(p); - } - p = first_hid; - while (p) { - q = p; - p = p->next; - free(q); - } - first_hid = last_hid = NULL; -} - - -static void hid_close(hid_t *hid) -{ - if (!hid || !hid->open || !hid->ref) return; - IOHIDDeviceUnscheduleFromRunLoop(hid->ref, CFRunLoopGetCurrent( ), kCFRunLoopDefaultMode); - IOHIDDeviceClose(hid->ref, kIOHIDOptionsTypeNone); - hid->ref = NULL; -} - -static void detach_callback(void *context, IOReturn r, void *hid_mgr, IOHIDDeviceRef dev) -{ - hid_t *p; - - printf("detach callback\n"); - for (p = first_hid; p; p = p->next) { - if (p->ref == dev) { - p->open = 0; - CFRunLoopStop(CFRunLoopGetCurrent()); - return; - } - } -} - - -static void attach_callback(void *context, IOReturn r, void *hid_mgr, IOHIDDeviceRef dev) -{ - struct hid_struct *h; - - printf("attach callback\n"); - if (IOHIDDeviceOpen(dev, kIOHIDOptionsTypeNone) != kIOReturnSuccess) return; - h = (hid_t *)malloc(sizeof(hid_t)); - if (!h) return; - memset(h, 0, sizeof(hid_t)); - IOHIDDeviceScheduleWithRunLoop(dev, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); - IOHIDDeviceRegisterInputReportCallback(dev, h->buffer, sizeof(h->buffer), - input_callback, h); - h->ref = dev; - h->open = 1; - add_hid(h); -} - - diff --git a/plugins/KeyboardioHID/extras/rawhid/hid_WINDOWS.c b/plugins/KeyboardioHID/extras/rawhid/hid_WINDOWS.c deleted file mode 100644 index 071877341f..0000000000 --- a/plugins/KeyboardioHID/extras/rawhid/hid_WINDOWS.c +++ /dev/null @@ -1,328 +0,0 @@ -/* Simple Raw HID functions for Windows - for use with Teensy RawHID example - * http://www.pjrc.com/teensy/rawhid.html - * Copyright (c) 2009 PJRC.COM, LLC - * - * rawhid_open - open 1 or more devices - * rawhid_recv - receive a packet - * rawhid_send - send a packet - * rawhid_close - close a device - * - * 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 description, website URL and 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 - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "hid.h" - - -// a list of all opened HID devices, so the caller can -// simply refer to them by number -typedef struct hid_struct hid_t; -static hid_t *first_hid = NULL; -static hid_t *last_hid = NULL; -struct hid_struct { - HANDLE handle; - int open; - struct hid_struct *prev; - struct hid_struct *next; -}; -static HANDLE rx_event=NULL; -static HANDLE tx_event=NULL; -static CRITICAL_SECTION rx_mutex; -static CRITICAL_SECTION tx_mutex; - - -// private functions, not intended to be used from outside this file -static void add_hid(hid_t *h); -static hid_t * get_hid(int num); -static void free_all_hid(void); -static void hid_close(hid_t *hid); -void print_win32_err(void); - - - - -// rawhid_recv - receive a packet -// Inputs: -// num = device to receive from (zero based) -// buf = buffer to receive packet -// len = buffer's size -// timeout = time to wait, in milliseconds -// Output: -// number of bytes received, or -1 on error -// -int rawhid_recv(int num, void *buf, int len, int timeout) -{ - hid_t *hid; - unsigned char tmpbuf[516]; - OVERLAPPED ov; - DWORD n, r; - - if (sizeof(tmpbuf) < len + 1) return -1; - hid = get_hid(num); - if (!hid || !hid->open) return -1; - EnterCriticalSection(&rx_mutex); - ResetEvent(&rx_event); - memset(&ov, 0, sizeof(ov)); - ov.hEvent = rx_event; - if (!ReadFile(hid->handle, tmpbuf, len + 1, NULL, &ov)) { - if (GetLastError() != ERROR_IO_PENDING) goto return_error; - r = WaitForSingleObject(rx_event, timeout); - if (r == WAIT_TIMEOUT) goto return_timeout; - if (r != WAIT_OBJECT_0) goto return_error; - } - if (!GetOverlappedResult(hid->handle, &ov, &n, FALSE)) goto return_error; - LeaveCriticalSection(&rx_mutex); - if (n <= 0) return -1; - n--; - if (n > len) n = len; - memcpy(buf, tmpbuf + 1, n); - return n; -return_timeout: - CancelIo(hid->handle); - LeaveCriticalSection(&rx_mutex); - return 0; -return_error: - print_win32_err(); - LeaveCriticalSection(&rx_mutex); - return -1; -} - -// rawhid_send - send a packet -// Inputs: -// num = device to transmit to (zero based) -// buf = buffer containing packet to send -// len = number of bytes to transmit -// timeout = time to wait, in milliseconds -// Output: -// number of bytes sent, or -1 on error -// -int rawhid_send(int num, void *buf, int len, int timeout) -{ - hid_t *hid; - unsigned char tmpbuf[516]; - OVERLAPPED ov; - DWORD n, r; - - if (sizeof(tmpbuf) < len + 1) return -1; - hid = get_hid(num); - if (!hid || !hid->open) return -1; - EnterCriticalSection(&tx_mutex); - ResetEvent(&tx_event); - memset(&ov, 0, sizeof(ov)); - ov.hEvent = tx_event; - tmpbuf[0] = 0; - memcpy(tmpbuf + 1, buf, len); - if (!WriteFile(hid->handle, tmpbuf, len + 1, NULL, &ov)) { - if (GetLastError() != ERROR_IO_PENDING) goto return_error; - r = WaitForSingleObject(tx_event, timeout); - if (r == WAIT_TIMEOUT) goto return_timeout; - if (r != WAIT_OBJECT_0) goto return_error; - } - if (!GetOverlappedResult(hid->handle, &ov, &n, FALSE)) goto return_error; - LeaveCriticalSection(&tx_mutex); - if (n <= 0) return -1; - return n - 1; -return_timeout: - CancelIo(hid->handle); - LeaveCriticalSection(&tx_mutex); - return 0; -return_error: - print_win32_err(); - LeaveCriticalSection(&tx_mutex); - return -1; -} - -// rawhid_open - open 1 or more devices -// -// Inputs: -// max = maximum number of devices to open -// vid = Vendor ID, or -1 if any -// pid = Product ID, or -1 if any -// usage_page = top level usage page, or -1 if any -// usage = top level usage number, or -1 if any -// Output: -// actual number of devices opened -// -int rawhid_open(int max, int vid, int pid, int usage_page, int usage) -{ - GUID guid; - HDEVINFO info; - DWORD index=0, reqd_size; - SP_DEVICE_INTERFACE_DATA iface; - SP_DEVICE_INTERFACE_DETAIL_DATA *details; - HIDD_ATTRIBUTES attrib; - PHIDP_PREPARSED_DATA hid_data; - HIDP_CAPS capabilities; - HANDLE h; - BOOL ret; - hid_t *hid; - int count=0; - - if (first_hid) free_all_hid(); - if (max < 1) return 0; - if (!rx_event) { - rx_event = CreateEvent(NULL, TRUE, TRUE, NULL); - tx_event = CreateEvent(NULL, TRUE, TRUE, NULL); - InitializeCriticalSection(&rx_mutex); - InitializeCriticalSection(&tx_mutex); - } - HidD_GetHidGuid(&guid); - info = SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); - if (info == INVALID_HANDLE_VALUE) return 0; - for (index=0; 1 ;index++) { - iface.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); - ret = SetupDiEnumDeviceInterfaces(info, NULL, &guid, index, &iface); - if (!ret) return count; - SetupDiGetInterfaceDeviceDetail(info, &iface, NULL, 0, &reqd_size, NULL); - details = (SP_DEVICE_INTERFACE_DETAIL_DATA *)malloc(reqd_size); - if (details == NULL) continue; - - memset(details, 0, reqd_size); - details->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); - ret = SetupDiGetDeviceInterfaceDetail(info, &iface, details, - reqd_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); - //printf("vid: %4x\n", attrib.VendorID); - if (!ret || (vid > 0 && attrib.VendorID != vid) || - (pid > 0 && attrib.ProductID != pid) || - !HidD_GetPreparsedData(h, &hid_data)) { - CloseHandle(h); - continue; - } - if (!HidP_GetCaps(hid_data, &capabilities) || - (usage_page > 0 && capabilities.UsagePage != usage_page) || - (usage > 0 && capabilities.Usage != usage)) { - HidD_FreePreparsedData(hid_data); - CloseHandle(h); - continue; - } - HidD_FreePreparsedData(hid_data); - hid = (struct hid_struct *)malloc(sizeof(struct hid_struct)); - if (!hid) { - CloseHandle(h); - continue; - } - hid->handle = h; - hid->open = 1; - add_hid(hid); - count++; - if (count >= max) return count; - } - return count; -} - - -// rawhid_close - close a device -// -// Inputs: -// num = device to close (zero based) -// Output -// (nothing) -// -void rawhid_close(int num) -{ - hid_t *hid; - - hid = get_hid(num); - if (!hid || !hid->open) return; - hid_close(hid); -} - - - -static void add_hid(hid_t *h) -{ - if (!first_hid || !last_hid) { - first_hid = last_hid = h; - h->next = h->prev = NULL; - return; - } - last_hid->next = h; - h->prev = last_hid; - h->next = NULL; - last_hid = h; -} - - -static hid_t * get_hid(int num) -{ - hid_t *p; - for (p = first_hid; p && num > 0; p = p->next, num--) ; - return p; -} - - -static void free_all_hid(void) -{ - hid_t *p, *q; - - for (p = first_hid; p; p = p->next) { - hid_close(p); - } - p = first_hid; - while (p) { - q = p; - p = p->next; - free(q); - } - first_hid = last_hid = NULL; -} - - -static void hid_close(hid_t *hid) -{ - CloseHandle(hid->handle); - hid->handle = NULL; -} - - -void print_win32_err(void) -{ - char buf[256]; - DWORD err; - - err = GetLastError(); - FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, - 0, buf, sizeof(buf), NULL); - printf("err %ld: %s\n", err, buf); -} - - - - - diff --git a/plugins/KeyboardioHID/extras/rawhid/rawhid_test.c b/plugins/KeyboardioHID/extras/rawhid/rawhid_test.c deleted file mode 100644 index fc072608da..0000000000 --- a/plugins/KeyboardioHID/extras/rawhid/rawhid_test.c +++ /dev/null @@ -1,101 +0,0 @@ -#include -#include -#include - -#if defined(OS_LINUX) || defined(OS_MACOSX) -#include -#include -#elif defined(OS_WINDOWS) -#include -#endif - -#include "hid.h" - - -static char get_keystroke(void); - - -int main() -{ - int i, r, num; - char c, buf[200]; - - // C-based example is 16C0:0480:FFAB:0200 - r = rawhid_open(1, 0x16C0, 0x0480, 0xFFAB, 0x0200); - if (r <= 0) { - // Arduino-based example is 0x2341:XXXX:FFC0:0C00 - // To keep compatible with other vendors we only use the raw HID number - r = rawhid_open(1, -1, -1, 0xFFC0, 0x0C00); - if (r <= 0) { - printf("no rawhid device found\n"); - return -1; - } - } - printf("found rawhid device\n"); - - while (1) { - // check if any Raw HID packet has arrived - num = rawhid_recv(0, buf, 64, 220); - if (num < 0) { - printf("\nerror reading, device went offline\n"); - rawhid_close(0); - return 0; - } - if (num > 0) { - printf("\nrecv %d bytes:\n", num); - for (i=0; i= 32) { - printf("\ngot key '%c', sending...\n", c); - buf[0] = c; - for (i=1; i= 32) return c; - } - return 0; -} - - diff --git a/plugins/KeyboardioHID/src/SingleReport/RawHID.cpp b/plugins/KeyboardioHID/src/SingleReport/RawHID.cpp deleted file mode 100644 index d4aa4d1d42..0000000000 --- a/plugins/KeyboardioHID/src/SingleReport/RawHID.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 "RawHID.h" - -static const uint8_t _hidReportDescriptorRawHID[] PROGMEM = { - /* RAW HID */ - 0x06, lowByte(RAWHID_USAGE_PAGE), highByte(RAWHID_USAGE_PAGE), /* 30 */ - 0x0A, lowByte(RAWHID_USAGE), highByte(RAWHID_USAGE), - - 0xA1, 0x01, /* Collection 0x01 */ - // RawHID is not multireport compatible. - // On Linux it might work with some modifications, - // however you are not happy to use it like that. - //0x85, HID_REPORTID_RAWHID, /* REPORT_ID */ - 0x75, 0x08, /* report size = 8 bits */ - 0x15, 0x00, /* logical minimum = 0 */ - 0x26, 0xFF, 0x00, /* logical maximum = 255 */ - - 0x95, RAWHID_TX_SIZE, /* report count TX */ - 0x09, 0x01, /* usage */ - 0x81, 0x02, /* Input (array) */ - - 0x95, RAWHID_RX_SIZE, /* report count RX */ - 0x09, 0x02, /* usage */ - 0x91, 0x02, /* Output (array) */ - 0xC0 /* end collection */ -}; - -RawHID_::RawHID_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1), dataLength(0), dataAvailable(0), featureReport(NULL), featureLength(0) -{ - epType[0] = EP_TYPE_INTERRUPT_IN; - PluggableUSB().plug(this); -} - -int RawHID_::getInterface(uint8_t* interfaceCount) -{ - // Maybe as optional device FastRawHID with different USAGE PAGE - *interfaceCount += 1; // uses 1 - HIDDescriptor hidInterface = { - D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE), - D_HIDREPORT(sizeof(_hidReportDescriptorRawHID)), - D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) - }; - return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); -} - -int RawHID_::getDescriptor(USBSetup& setup) -{ - // Check if this is a HID Class Descriptor request - if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { return 0; } - if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { return 0; } - - // In a HID Class Descriptor wIndex cointains the interface number - if (setup.wIndex != pluggedInterface) { return 0; } - - // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol - // due to the USB specs, but Windows and Linux just assumes its in report mode. - protocol = HID_REPORT_PROTOCOL; - - return USB_SendControl(TRANSFER_PGM, _hidReportDescriptorRawHID, sizeof(_hidReportDescriptorRawHID)); -} - -bool RawHID_::setup(USBSetup& setup) -{ - if (pluggedInterface != setup.wIndex) { - return false; - } - - uint8_t request = setup.bRequest; - uint8_t requestType = setup.bmRequestType; - - if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) - { - if (request == HID_GET_REPORT) { - // TODO: HID_GetReport(); - return true; - } - if (request == HID_GET_PROTOCOL) { - // TODO: Send8(protocol); - return true; - } - } - - if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) - { - if (request == HID_SET_PROTOCOL) { - protocol = setup.wValueL; - return true; - } - if (request == HID_SET_IDLE) { - idle = setup.wValueL; - return true; - } - if (request == HID_SET_REPORT) - { - // Check if data has the correct length afterwards - int length = setup.wLength; - - // Feature (set feature report) - if(setup.wValueH == HID_REPORT_TYPE_FEATURE){ - // No need to check for negative featureLength values, - // except the host tries to send more then 32k bytes. - // We dont have that much ram anyways. - if (length == featureLength) { - USB_RecvControl(featureReport, featureLength); - - // Block until data is read (make length negative) - disableFeatureReport(); - return true; - } - } - - // Output (set out report) - else if(setup.wValueH == HID_REPORT_TYPE_OUTPUT){ - if(!dataAvailable && length <= dataLength){ - // Write data to fit to the end (not the beginning) of the array - USB_RecvControl(data + dataLength - length, length); - dataAvailable = length; - return true; - } - } - } - } - - return false; -} - -RawHID_ RawHID; diff --git a/plugins/KeyboardioHID/src/SingleReport/RawHID.h b/plugins/KeyboardioHID/src/SingleReport/RawHID.h deleted file mode 100644 index 9ccc43e224..0000000000 --- a/plugins/KeyboardioHID/src/SingleReport/RawHID.h +++ /dev/null @@ -1,180 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 guard -#pragma once - -#include -#include "PluggableUSB.h" -#include "HID.h" -#include "HID-Settings.h" - -// RawHID might never work with multireports, because of OS problems -// therefore we have to make it a single report with no idea. No other HID device will be supported then. -#undef RAWHID_USAGE_PAGE -#define RAWHID_USAGE_PAGE 0xFFC0 // recommended: 0xFF00 to 0xFFFF - -#undef RAWHID_USAGE -#define RAWHID_USAGE 0x0C00 // recommended: 0x0100 to 0xFFFF - -// Keep one byte offset for the reportID if used -#if (HID_REPORTID_RAWHID) -#define RAWHID_SIZE (USB_EP_SIZE-1) -#error RAWHID does not work properly with a report ID and multiple reports. -#error Please remove this manually if you know what you are doing. -#else -#define RAWHID_SIZE (USB_EP_SIZE) -#endif - -#undef RAWHID_TX_SIZE -#define RAWHID_TX_SIZE RAWHID_SIZE - -#undef RAWHID_RX_SIZE -#define RAWHID_RX_SIZE RAWHID_SIZE - -typedef union{ - // a RAWHID_TX_SIZE byte buffer for tx - uint8_t whole8[]; - uint16_t whole16[]; - uint32_t whole32[]; - uint8_t buff[RAWHID_TX_SIZE]; -} HID_RawKeyboardTXReport_Data_t; - -typedef union{ - // a RAWHID_TX_SIZE byte buffer for rx - uint8_t whole8[]; - uint16_t whole16[]; - uint32_t whole32[]; - uint8_t buff[RAWHID_RX_SIZE]; -} HID_RawKeyboardRXReport_Data_t; - -class RawHID_ : public PluggableUSBModule, public Stream -{ -public: - RawHID_(void); - - void setFeatureReport(void* report, int length){ - if(length > 0){ - featureReport = (uint8_t*)report; - featureLength = length; - - // Disable feature report by default - disableFeatureReport(); - } - } - - int availableFeatureReport(void){ - if(featureLength < 0){ - return featureLength & ~0x8000; - } - return 0; - } - - void enableFeatureReport(void){ - featureLength &= ~0x8000; - } - - void disableFeatureReport(void){ - featureLength |= 0x8000; - } - - void begin(void* report, int length){ - if(length > 0){ - data = (uint8_t*)report; - dataLength = length; - dataAvailable = 0; - } - } - - void end(void){ - disable(); - dataLength = 0; - } - - void enable(void){ - dataAvailable = 0; - } - - void disable(void){ - dataAvailable = -1; - } - - virtual int available(void){ - if(dataAvailable < 0){ - return 0; - } - return dataAvailable; - } - - virtual int read(){ - // Check if we have data available - if(dataAvailable > 0) - { - // Get next data byte (from the start to the end) - return data[dataLength - dataAvailable--]; - } - return -1; - } - - virtual int peek(){ - // Check if we have data available - if(dataAvailable > 0){ - return data[dataLength - dataAvailable]; - } - return -1; - } - - virtual void flush(void){ - // Writing will always flush by the USB driver - } - - // Wrapper for a single byte - using Print::write; - virtual size_t write(uint8_t b){ - return write(&b, 1); - } - - virtual size_t write(uint8_t *buffer, size_t size){ - return USB_Send(pluggedEndpoint | TRANSFER_RELEASE, buffer, size); - } - -protected: - // Implementation of the PUSBListNode - int getInterface(uint8_t* interfaceCount); - int getDescriptor(USBSetup& setup); - bool setup(USBSetup& setup); - - uint8_t epType[1]; - uint8_t protocol; - uint8_t idle; - - // Buffer pointers to hold the received data - int dataLength; - int dataAvailable; - uint8_t* data; - - uint8_t* featureReport; - int featureLength; -}; -extern RawHID_ RawHID; - From f0779a390f4d4e608398125b33aa9205e516b613 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Wed, 9 Dec 2015 20:27:54 -0800 Subject: [PATCH 360/602] Remove ImprovedKeyboard sample code --- .../ImprovedKeyboard/ImprovedKeyboard.ino | 65 ------------------- 1 file changed, 65 deletions(-) delete mode 100644 plugins/KeyboardioHID/examples/Keyboard/ImprovedKeyboard/ImprovedKeyboard.ino diff --git a/plugins/KeyboardioHID/examples/Keyboard/ImprovedKeyboard/ImprovedKeyboard.ino b/plugins/KeyboardioHID/examples/Keyboard/ImprovedKeyboard/ImprovedKeyboard.ino deleted file mode 100644 index 37bcf3e219..0000000000 --- a/plugins/KeyboardioHID/examples/Keyboard/ImprovedKeyboard/ImprovedKeyboard.ino +++ /dev/null @@ -1,65 +0,0 @@ -/* - Copyright (c) 2014-2015 NicoHood - See the readme for credit to other people. - - Improved Keyboard example - - Shows how to use the new Keyboard API. - - See HID Project documentation for more information. - https://github.com/NicoHood/HID/wiki/Keyboard-API#improved-keyboard -*/ - -#include "HID-Project.h" - -const int pinLed = LED_BUILTIN; -const int pinButton = 2; - -void setup() { - pinMode(pinLed, OUTPUT); - pinMode(pinButton, INPUT_PULLUP); - - // Sends a clean report to the host. This is important on any Arduino type. - Keyboard.begin(); -} - - -void loop() { - // Trigger caps lock manually via button - if (!digitalRead(pinButton)) { - digitalWrite(pinLed, HIGH); - - // Use the default print functions - Keyboard.println("Hello World!"); - - // Press a single character, special non ascii characters wont work. - //Keyboard.write('a'); - - // Write single keys, do not use a number here! - //Keyboard.write(KEY_ENTER); - - - // If you really wish to press a RAW keycode without the name use this: - //Keyboard.write(KeyboardKeycode(40)); - - // Use (a limited number of) consumer keys. - // Only works with the lower 255 keys and on linux only. - //Keyboard.write(MEDIA_PLAY_PAUSE); - - // Linux also supports several system function via consumer report. - //Keyboard.write(CONSUMER_POWER); - //Keyboard.write(CONSUMER_SLEEP); - - // You can also use some special keyboard keys on linux. - //Keyboard.write(KEY_POWER); - //Keyboard.write(KEY_F13); - - // You can wakeup you PC from sleep. - // This might be not supported on all hardware, but on all OS types. - //Keyboard.wakeupHost(); - - // Simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } -} From d129dc177f8c4032b13ad107d85ba93afc795dae Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Wed, 9 Dec 2015 20:40:31 -0800 Subject: [PATCH 361/602] Lift currently unused list of keyboard LEDs intto KeyboardAPI.h --- .../KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h | 12 ------------ plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h | 12 ++++++++++++ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h b/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h index ee4854d7b5..26d03f81f1 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h +++ b/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h @@ -487,18 +487,6 @@ enum KeyboardKeycode : uint8_t { HID_KEYBOARD_RIGHT_GUI = 0xE7, }; -// Keyboard Leds -enum KeyboardLeds : uint8_t { - LED_NUM_LOCK = (1 << 0), - LED_CAPS_LOCK = (1 << 1), - LED_SCROLL_LOCK = (1 << 2), - LED_COMPOSE = (1 << 3), - LED_KANA = (1 << 4), - LED_POWER = (1 << 5), - LED_SHIFT = (1 << 6), - LED_DO_NOT_DISTURB = (1 << 7), -}; - #define SHIFT 0x80 static const uint8_t _asciimap[] PROGMEM = { diff --git a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h index 81a589fb10..1eb8db5372 100644 --- a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h +++ b/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h @@ -28,6 +28,18 @@ THE SOFTWARE. #include "HID-Settings.h" #include "ImprovedKeylayouts.h" +// Keyboard Leds +enum KeyboardLeds : uint8_t { + LED_NUM_LOCK = (1 << 0), + LED_CAPS_LOCK = (1 << 1), + LED_SCROLL_LOCK = (1 << 2), + LED_COMPOSE = (1 << 3), + LED_KANA = (1 << 4), + LED_POWER = (1 << 5), + LED_SHIFT = (1 << 6), + LED_DO_NOT_DISTURB = (1 << 7), +}; + class KeyboardAPI : public Print { From 794214af8ca2e9e31a770ffae93d99c2db585943 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Thu, 10 Dec 2015 16:44:28 -0800 Subject: [PATCH 362/602] Rename 'SingleReport' to 'BootKeyboard' --- .../src/{SingleReport => BootKeyboard}/BootKeyboard.cpp | 0 .../src/{SingleReport => BootKeyboard}/BootKeyboard.h | 0 plugins/KeyboardioHID/src/HID-Project.h | 3 +-- 3 files changed, 1 insertion(+), 2 deletions(-) rename plugins/KeyboardioHID/src/{SingleReport => BootKeyboard}/BootKeyboard.cpp (100%) rename plugins/KeyboardioHID/src/{SingleReport => BootKeyboard}/BootKeyboard.h (100%) diff --git a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp similarity index 100% rename from plugins/KeyboardioHID/src/SingleReport/BootKeyboard.cpp rename to plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp diff --git a/plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h similarity index 100% rename from plugins/KeyboardioHID/src/SingleReport/BootKeyboard.h rename to plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index 5aed2be64b..92f920974b 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -40,8 +40,7 @@ THE SOFTWARE. // Include all HID libraries (.a linkage required to work) properly -#include "SingleReport/RawHID.h" -#include "SingleReport/BootKeyboard.h" +#include "BootKeyboard/BootKeyboard.h" #include "MultiReport/AbsoluteMouse.h" #include "MultiReport/ImprovedMouse.h" #include "MultiReport/Consumer.h" From ceede09ae9ae77c11c1cc670f5194692d2e5e918 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Thu, 10 Dec 2015 16:45:43 -0800 Subject: [PATCH 363/602] Rename HID-APIs to KeyboardCore, which is what it now is --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h | 2 +- .../src/{HID-APIs => KeyboardCore}/ImprovedKeylayouts.h | 0 .../KeyboardioHID/src/{HID-APIs => KeyboardCore}/KeyboardAPI.h | 0 .../src/{HID-APIs => KeyboardCore}/KeyboardAPI.hpp | 0 plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h | 2 +- 5 files changed, 2 insertions(+), 2 deletions(-) rename plugins/KeyboardioHID/src/{HID-APIs => KeyboardCore}/ImprovedKeylayouts.h (100%) rename plugins/KeyboardioHID/src/{HID-APIs => KeyboardCore}/KeyboardAPI.h (100%) rename plugins/KeyboardioHID/src/{HID-APIs => KeyboardCore}/KeyboardAPI.hpp (100%) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index f64a7f6c9d..e2716eecb9 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -28,7 +28,7 @@ THE SOFTWARE. #include "PluggableUSB.h" #include "HID.h" #include "HID-Settings.h" -#include "../HID-APIs/KeyboardAPI.h" +#include "../KeyboardCore/KeyboardAPI.h" typedef union{ diff --git a/plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h b/plugins/KeyboardioHID/src/KeyboardCore/ImprovedKeylayouts.h similarity index 100% rename from plugins/KeyboardioHID/src/HID-APIs/ImprovedKeylayouts.h rename to plugins/KeyboardioHID/src/KeyboardCore/ImprovedKeylayouts.h diff --git a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h b/plugins/KeyboardioHID/src/KeyboardCore/KeyboardAPI.h similarity index 100% rename from plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.h rename to plugins/KeyboardioHID/src/KeyboardCore/KeyboardAPI.h diff --git a/plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.hpp b/plugins/KeyboardioHID/src/KeyboardCore/KeyboardAPI.hpp similarity index 100% rename from plugins/KeyboardioHID/src/HID-APIs/KeyboardAPI.hpp rename to plugins/KeyboardioHID/src/KeyboardCore/KeyboardAPI.hpp diff --git a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h index 61221c6eaf..5cbc5c03b2 100644 --- a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h @@ -29,7 +29,7 @@ THE SOFTWARE. #include "HID.h" #include "HID-Settings.h" -#include "../HID-APIs/KeyboardAPI.h" +#include "../KeyboardCore/KeyboardAPI.h" // Max value for USB EP_SIZE 16 // +1 reportID, +1 modifier, +1 custom key From 11ec002c4ba3d86fac328d8e2c9cddf846b062b4 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Thu, 10 Dec 2015 16:56:13 -0800 Subject: [PATCH 364/602] Add HIDTables from the old Keyboardio HID Keyboard implemenntation --- .../src/KeyboardCore/HIDTables.h | 677 ++++++++++++++++++ 1 file changed, 677 insertions(+) create mode 100644 plugins/KeyboardioHID/src/KeyboardCore/HIDTables.h diff --git a/plugins/KeyboardioHID/src/KeyboardCore/HIDTables.h b/plugins/KeyboardioHID/src/KeyboardCore/HIDTables.h new file mode 100644 index 0000000000..8092e1fbf8 --- /dev/null +++ b/plugins/KeyboardioHID/src/KeyboardCore/HIDTables.h @@ -0,0 +1,677 @@ +#ifndef __HIDTables__ +#define HID___HIDTables__ + + +// These mappings were extracted and transcribed from +// http://www.usb.org_SLASH_developers_SLASH_devclass_docs_SLASH_Hut1_12v2.pdf +// +// In most cases, I've preserved the "official" USB Implementers forum +// "Usage Name", though I've standardized some abbreviations and spacing +// that were inconsistent in the original specification. Non alpha-numeric +// characters in symbol names were converted into those characters' names. +// +// To match Arduino code style, all hid usage names are fully upper case. +// +// Not every HID usage listed in this file is currently supported by Arduino +// In particular, any System Control or Consumer Control entry that doesn't +// have a comment indicating that it's "HID type OSC" will require additional +// code in the Arduino core to work. +// +// Non-working usages are listed here in the interest of not having to manually +// convert more usage names each and every time our HID stack gets a little bit +// better. +// +// +// -- Jesse Vincent , January 2014 + + + +// System control mappings + +#define HID_SYSTEM_POWER_DOWN 0x81 // HID type OSC +#define HID_SYSTEM_SLEEP 0x82 // HID type OSC +#define HID_SYSTEM_WAKE_UP 0x83 // HID type OSC +#define HID_SYSTEM_CONTEXT_MENU 0x84 // HID type OSC +#define HID_SYSTEM_MAIN_MENU 0x85 // HID type OSC +#define HID_SYSTEM_APP_MENU 0x86 // HID type OSC +#define HID_SYSTEM_MENU_HELP 0x87 // HID type OSC +#define HID_SYSTEM_MENU_EXIT 0x88 // HID type OSC +#define HID_SYSTEM_MENU_SELECT 0x89 // HID type OSC +#define HID_SYSTEM_MENU_RIGHT 0x8A // HID type RTC +#define HID_SYSTEM_MENU_LEFT 0x8B // HID type RTC +#define HID_SYSTEM_MENU_UP 0x8C // HID type RTC +#define HID_SYSTEM_MENU_DOWN 0x8D // HID type RTC +#define HID_SYSTEM_COLD_RESTART 0x8E // HID type OSC +#define HID_SYSTEM_WARM_RESTART 0x8F // HID type OSC +#define HID_D_PAD_UP 0x90 // HID type OOC +#define HID_D_PAD_DOWN 0x91 // HID type OOC +#define HID_D_PAD_RIGHT 0x92 // HID type OOC +#define HID_D_PAD_LEFT 0x93 // HID type OOC +// 0x94-0x9F are reserved +#define HID_SYSTEM_DOCK 0xA0 // HID type OSC +#define HID_SYSTEM_UNDOCK 0xA1 // HID type OSC +#define HID_SYSTEM_SETUP 0xA2 // HID type OSC +#define HID_SYSTEM_BREAK 0xA3 // HID type OSC +#define HID_SYSTEM_DEBUGGER_BREAK 0xA4 // HID type OSC +#define HID_APPLICATION_BREAK 0xA5 // HID type OSC +#define HID_APPLICATION_DEBUGGER_BREAK 0xA6 // HID type OSC +#define HID_SYSTEM_SPEAKER_MUTE 0xA7 // HID type OSC +#define HID_SYSTEM_HIBERNATE 0xA8 // HID type OSC +// 0xA9-0xAF are reserved +#define HID_SYSTEM_DISPLAY_INVERT 0xB0 // HID type OSC +#define HID_SYSTEM_DISPLAY_INTERNAL 0xB1 // HID type OSC +#define HID_SYSTEM_DISPLAY_EXTERNAL 0xB2 // HID type OSC +#define HID_SYSTEM_DISPLAY_BOTH 0xB3 // HID type OSC +#define HID_SYSTEM_DISPLAY_DUAL 0xB4 // HID type OSC +#define HID_SYSTEM_DISPLAY_TOGGLE_INT_SLASH_EXT 0xB5 // HID type OSC +#define HID_SYSTEM_DISPLAY_SWAP_PRIMARY_SLASH_SECONDARY 0xB6 // HID type OSC +#define HID_SYSTEM_DISPLAY_LCD_AUTOSCALE 0xB7 // HID type OSC + +// Keyboard HID mappings + +// Reserved (no_event_indicated) 0x00 +#define HID_KEYBOARD_ERROR_ROLLOVER 0x01 +#define HID_KEYBOARD_POST_FAIL 0x02 +#define HID_KEYBOARD_ERROR_UNDEFINED 0x03 +#define HID_KEYBOARD_A_AND_A 0x04 +#define HID_KEYBOARD_B_AND_B 0x05 +#define HID_KEYBOARD_C_AND_C 0x06 +#define HID_KEYBOARD_D_AND_D 0x07 +#define HID_KEYBOARD_E_AND_E 0x08 +#define HID_KEYBOARD_F_AND_F 0x09 +#define HID_KEYBOARD_G_AND_G 0x0A +#define HID_KEYBOARD_H_AND_H 0x0B +#define HID_KEYBOARD_I_AND_I 0x0C +#define HID_KEYBOARD_J_AND_J 0x0D +#define HID_KEYBOARD_K_AND_K 0x0E +#define HID_KEYBOARD_L_AND_L 0x0F +#define HID_KEYBOARD_M_AND_M 0x10 +#define HID_KEYBOARD_N_AND_N 0x11 +#define HID_KEYBOARD_O_AND_O 0x12 +#define HID_KEYBOARD_P_AND_P 0x13 +#define HID_KEYBOARD_Q_AND_Q 0x14 +#define HID_KEYBOARD_R_AND_R 0x15 +#define HID_KEYBOARD_S_AND_S 0x16 +#define HID_KEYBOARD_T_AND_T 0x17 +#define HID_KEYBOARD_U_AND_U 0x18 +#define HID_KEYBOARD_V_AND_V 0x19 +#define HID_KEYBOARD_W_AND_W 0x1A +#define HID_KEYBOARD_X_AND_X 0x1B +#define HID_KEYBOARD_Y_AND_Y 0x1C +#define HID_KEYBOARD_Z_AND_Z 0x1D +#define HID_KEYBOARD_1_AND_EXCLAMATION_POINT 0x1E +#define HID_KEYBOARD_2_AND_AT 0x1F +#define HID_KEYBOARD_3_AND_POUND 0x20 +#define HID_KEYBOARD_4_AND_DOLLAR 0x21 +#define HID_KEYBOARD_5_AND_PERCENT 0x22 +#define HID_KEYBOARD_6_AND_CARAT 0x23 +#define HID_KEYBOARD_7_AND_AMPERSAND 0x24 +#define HID_KEYBOARD_8_AND_ASTERISK 0x25 +#define HID_KEYBOARD_9_AND_LEFT_PAREN 0x26 +#define HID_KEYBOARD_0_AND_RIGHT_PAREN 0x27 +#define HID_KEYBOARD_ENTER 0x28 // (MARKED AS ENTER_SLASH_RETURN) +#define HID_KEYBOARD_ESCAPE 0x29 +#define HID_KEYBOARD_DELETE 0x2A // (BACKSPACE) +#define HID_KEYBOARD_TAB 0x2B +#define HID_KEYBOARD_SPACEBAR 0x2C +#define HID_KEYBOARD_MINUS_AND_UNDERSCORE 0x2D // (UNDERSCORE) +#define HID_KEYBOARD_EQUALS_AND_PLUS 0x2E +#define HID_KEYBOARD_LEFT_BRACKET_AND_LEFT_CURLY_BRACE 0x2F +#define HID_KEYBOARD_RIGHT_BRACKET_AND_RIGHT_CURLY_BRACE 0x30 +#define HID_KEYBOARD_BACKSLASH_AND_PIPE 0x31 +#define HID_KEYBOARD_NON_US_POUND_AND_TILDE 0x32 +#define HID_KEYBOARD_SEMICOLON_AND_COLON 0x33 +#define HID_KEYBOARD_QUOTE_AND_DOUBLEQUOTE 0x34 +#define HID_KEYBOARD_GRAVE_ACCENT_AND_TILDE 0x35 +#define HID_KEYBOARD_COMMA_AND_LESS_THAN 0x36 +#define HID_KEYBOARD_PERIOD_AND_GREATER_THAN 0x37 +#define HID_KEYBOARD_SLASH_AND_QUESTION_MARK 0x38 +#define HID_KEYBOARD_CAPS_LOCK 0x39 +#define HID_KEYBOARD_F1 0x3A +#define HID_KEYBOARD_F2 0x3B +#define HID_KEYBOARD_F3 0x3C +#define HID_KEYBOARD_F4 0x3D +#define HID_KEYBOARD_F5 0x3E +#define HID_KEYBOARD_F6 0x3F +#define HID_KEYBOARD_F7 0x40 +#define HID_KEYBOARD_F8 0x41 +#define HID_KEYBOARD_F9 0x42 +#define HID_KEYBOARD_F10 0x43 +#define HID_KEYBOARD_F11 0x44 +#define HID_KEYBOARD_F12 0x45 +#define HID_KEYBOARD_PRINTSCREEN 0x46 +#define HID_KEYBOARD_SCROLL_LOCK 0x47 +#define HID_KEYBOARD_PAUSE 0x48 +#define HID_KEYBOARD_INSERT 0x49 +#define HID_KEYBOARD_HOME 0x4A +#define HID_KEYBOARD_PAGE_UP 0x4B +#define HID_KEYBOARD_DELETE_FORWARD 0x4C +#define HID_KEYBOARD_END 0x4D +#define HID_KEYBOARD_PAGE_DOWN 0x4E +#define HID_KEYBOARD_RIGHTARROW 0x4F +#define HID_KEYBOARD_LEFTARROW 0x50 +#define HID_KEYBOARD_DOWNARROW 0x51 +#define HID_KEYBOARD_UPARROW 0x52 +#define HID_KEYPAD_NUM_LOCK_AND_CLEAR 0x53 +#define HID_KEYPAD_DIVIDE 0x54 +#define HID_KEYPAD_MULTIPLY 0x55 +#define HID_KEYPAD_SUBTRACT 0x56 +#define HID_KEYPAD_ADD 0x57 +#define HID_KEYPAD_ENTER 0x58 +#define HID_KEYPAD_1_AND_END 0x59 +#define HID_KEYPAD_2_AND_DOWN_ARROW 0x5A +#define HID_KEYPAD_3_AND_PAGE_DOWN 0x5B +#define HID_KEYPAD_4_AND_LEFT_ARROW 0x5C +#define HID_KEYPAD_5 0x5D +#define HID_KEYPAD_6_AND_RIGHT_ARROW 0x5E +#define HID_KEYPAD_7_AND_HOME 0x5F +#define HID_KEYPAD_8_AND_UP_ARROW 0x60 +#define HID_KEYPAD_9_AND_PAGE_UP 0x61 +#define HID_KEYPAD_0_AND_INSERT 0x62 +#define HID_KEYPAD_PERIOD_AND_DELETE 0x63 +#define HID_KEYBOARD_NON_US_BACKSLASH_AND_PIPE 0x64 +#define HID_KEYBOARD_APPLICATION 0x65 +#define HID_KEYBOARD_POWER 0x66 +#define HID_KEYPAD_EQUALS 0x67 +#define HID_KEYBOARD_F13 0x68 +#define HID_KEYBOARD_F14 0x69 +#define HID_KEYBOARD_F15 0x6A +#define HID_KEYBOARD_F16 0x6B +#define HID_KEYBOARD_F17 0x6C +#define HID_KEYBOARD_F18 0x6D +#define HID_KEYBOARD_F19 0x6E +#define HID_KEYBOARD_F20 0x6F +#define HID_KEYBOARD_F21 0x70 +#define HID_KEYBOARD_F22 0x71 +#define HID_KEYBOARD_F23 0x72 +#define HID_KEYBOARD_F24 0x73 +#define HID_KEYBOARD_EXECUTE 0x74 +#define HID_KEYBOARD_HELP 0x75 +#define HID_KEYBOARD_MENU 0x76 +#define HID_KEYBOARD_SELECT 0x77 +#define HID_KEYBOARD_STOP 0x78 +#define HID_KEYBOARD_AGAIN 0x79 +#define HID_KEYBOARD_UNDO 0x7A +#define HID_KEYBOARD_CUT 0x7B +#define HID_KEYBOARD_COPY 0x7C +#define HID_KEYBOARD_PASTE 0x7D +#define HID_KEYBOARD_FIND 0x7E +#define HID_KEYBOARD_MUTE 0x7F +#define HID_KEYBOARD_VOLUME_UP 0x80 +#define HID_KEYBOARD_VOLUME_DOWN 0x81 +#define HID_KEYBOARD_LOCKING_CAPS_LOCK 0x82 +#define HID_KEYBOARD_LOCKING_NUM_LOCK 0x83 +#define HID_KEYBOARD_LOCKING_SCROLL_LOCK 0x84 +#define HID_KEYPAD_COMMA 0x85 +#define HID_KEYPAD_EQUAL_SIGN 0x86 +#define HID_KEYBOARD_INTERNATIONAL1 0x87 +#define HID_KEYBOARD_INTERNATIONAL2 0x88 +#define HID_KEYBOARD_INTERNATIONAL3 0x89 +#define HID_KEYBOARD_INTERNATIONAL4 0x8A +#define HID_KEYBOARD_INTERNATIONAL5 0x8B +#define HID_KEYBOARD_INTERNATIONAL6 0x8C +#define HID_KEYBOARD_INTERNATIONAL7 0x8D +#define HID_KEYBOARD_INTERNATIONAL8 0x8E +#define HID_KEYBOARD_INTERNATIONAL9 0x8F +#define HID_KEYBOARD_LANG1 0x90 +#define HID_KEYBOARD_LANG2 0x91 +#define HID_KEYBOARD_LANG3 0x92 +#define HID_KEYBOARD_LANG4 0x93 +#define HID_KEYBOARD_LANG5 0x94 +#define HID_KEYBOARD_LANG6 0x95 +#define HID_KEYBOARD_LANG7 0x96 +#define HID_KEYBOARD_LANG8 0x97 +#define HID_KEYBOARD_LANG9 0x98 +#define HID_KEYBOARD_ALTERNATE_ERASE 0x99 +#define HID_KEYBOARD_SYSREQ_SLASH_ATTENTION 0x9A +#define HID_KEYBOARD_CANCEL 0x9B +#define HID_KEYBOARD_CLEAR 0x9C +#define HID_KEYBOARD_PRIOR 0x9D +#define HID_KEYBOARD_RETURN 0x9E +#define HID_KEYBOARD_SEPARATOR 0x9F +#define HID_KEYBOARD_OUT 0xA0 +#define HID_KEYBOARD_OPER 0xA1 +#define HID_KEYBOARD_CLEAR_SLASH_AGAIN 0xA2 +#define HID_KEYBOARD_CRSEL_SLASH_PROPS 0xA3 +#define HID_KEYBOARD_EXSEL 0xA4 +// Reserved 0xA5-AF +#define HID_KEYPAD_00 0xB0 +#define HID_KEYPAD_000 0xB1 +#define HID_THOUSANDS_SEPARATOR 0xB2 +#define HID_DECIMAL_SEPARATOR 0xB3 +#define HID_CURRENCY_UNIT 0xB4 +#define HID_CURRENCY_SUBUNIT 0xB5 +#define HID_KEYPAD_LEFT_PAREN 0xB6 +#define HID_KEYPAD_RIGHT_PAREN 0xB7 +#define HID_KEYPAD_LEFT_CURLY_BRACE 0xB8 +#define HID_KEYPAD_RIGHT_CURLY_BRACE 0xB9 +#define HID_KEYPAD_TAB 0xBA +#define HID_KEYPAD_BACKSPACE 0xBB +#define HID_KEYPAD_A 0xBC +#define HID_KEYPAD_B 0xBD +#define HID_KEYPAD_C 0xBE +#define HID_KEYPAD_D 0xBF +#define HID_KEYPAD_E 0xC0 +#define HID_KEYPAD_F 0xC1 +#define HID_KEYPAD_XOR 0xC2 +#define HID_KEYPAD_CARAT 0xC3 +#define HID_KEYPAD_PERCENT 0xC4 +#define HID_KEYPAD_LESS_THAN 0xC5 +#define HID_KEYPAD_GREATER_THAN 0xC6 +#define HID_KEYPAD_AMPERSAND 0xC7 +#define HID_KEYPAD_DOUBLEAMPERSAND 0xC8 +#define HID_KEYPAD_PIPE 0xC9 +#define HID_KEYPAD_DOUBLEPIPE 0xCA +#define HID_KEYPAD_COLON 0xCB +#define HID_KEYPAD_POUND_SIGN 0xCC +#define HID_KEYPAD_SPACE 0xCD +#define HID_KEYPAD_AT_SIGN 0xCE +#define HID_KEYPAD_EXCLAMATION_POINT 0xCF +#define HID_KEYPAD_MEMORY_STORE 0xD0 +#define HID_KEYPAD_MEMORY_RECALL 0xD1 +#define HID_KEYPAD_MEMORY_CLEAR 0xD2 +#define HID_KEYPAD_MEMORY_ADD 0xD3 +#define HID_KEYPAD_MEMORY_SUBTRACT 0xD4 +#define HID_KEYPAD_MEMORY_MULTIPLY 0xD5 +#define HID_KEYPAD_MEMORY_DIVIDE 0xD6 +#define HID_KEYPAD_PLUS_SLASH_MINUS 0xD7 +#define HID_KEYPAD_CLEAR 0xD8 +#define HID_KEYPAD_CLEAR_ENTRY 0xD9 +#define HID_KEYPAD_BINARY 0xDA +#define HID_KEYPAD_OCTAL 0xDB +#define HID_KEYPAD_DECIMAL 0xDC +#define HID_KEYPAD_HEXADECIMAL 0xDD + +// 0xDE-0xDF - RESERVED +#define HID_KEYBOARD_LEFT_CONTROL 0xE0 +#define HID_KEYBOARD_LEFT_SHIFT 0xE1 +#define HID_KEYBOARD_LEFT_ALT 0xE2 +#define HID_KEYBOARD_LEFT_GUI 0xE3 +#define HID_KEYBOARD_RIGHT_CONTROL 0xE4 +#define HID_KEYBOARD_RIGHT_SHIFT 0xE5 +#define HID_KEYBOARD_RIGHT_ALT 0xE6 +#define HID_KEYBOARD_RIGHT_GUI 0xE7 + + +// Consumer_Page_(0x0C) 0x15 +#define HID_CONSUMER_NUMERIC_KEY_PAD 0x02 // HID type NARY +#define HID_CONSUMER_PROGRAMMABLE_BUTTONS 0x03 // HID type NARY +#define HID_CONSUMER_MICROPHONE_CA 0x04 +#define HID_CONSUMER_HEADPHONE_CA 0x05 +#define HID_CONSUMER_GRAPHIC_EQUALIZER_CA 0x06 +// Reserved 0x07-1F +#define HID_CONSUMER_PLUS_10 0x20 // HID type OSC +#define HID_CONSUMER_PLUS_100 0x21 // HID type OSC +#define HID_CONSUMER_AM_SLASH_PM 0x22 // HID type OSC +// Reserved 0x23-3F +#define HID_CONSUMER_POWER 0x30 // HID type OOC +#define HID_CONSUMER_RESET 0x31 // HID type OSC +#define HID_CONSUMER_SLEEP 0x32 // HID type OSC +#define HID_CONSUMER_SLEEP_AFTER 0x33 // HID type OSC +#define HID_CONSUMER_SLEEP_MODE 0x34 // HID type RTC +#define HID_CONSUMER_ILLUMINATION 0x35 // HID type OOC +#define HID_CONSUMER_FUNCTION_BUTTONS 0x36 // HID type NARY +// Reserved 0x37-3F +#define HID_CONSUMER_MENU 0x40 // HID type OOC +#define HID_CONSUMER_MENU_PICK 0x41 // HID type OSC +#define HID_CONSUMER_MENU_UP 0x42 // HID type OSC +#define HID_CONSUMER_MENU_DOWN 0x43 // HID type OSC +#define HID_CONSUMER_MENU_LEFT 0x44 // HID type OSC +#define HID_CONSUMER_MENU_RIGHT 0x45 // HID type OSC +#define HID_CONSUMER_MENU_ESCAPE 0x46 // HID type OSC +#define HID_CONSUMER_MENU_VALUE_INCREASE 0x47 // HID type OSC +#define HID_CONSUMER_MENU_VALUE_DECREASE 0x48 // HID type OSC +// Reserved 0x49-5F +#define HID_CONSUMER_DATA_ON_SCREEN 0x60 // HID type OOC +#define HID_CONSUMER_CLOSED_CAPTION 0x61 // HID type OOC +#define HID_CONSUMER_CLOSED_CAPTION_SELECT 0x62 // HID type OSC +#define HID_CONSUMER_VCR_SLASH_TV 0x63 // HID type OOC +#define HID_CONSUMER_BROADCAST_MODE 0x64 // HID type OSC +#define HID_CONSUMER_SNAPSHOT 0x65 // HID type OSC +#define HID_CONSUMER_STILL 0x66 // HID type OSC +// Reserved 0x67-7F +#define HID_CONSUMER_SELECTION 0x80 // HID type NARY +#define HID_CONSUMER_ASSIGN_SELECTION 0x81 // HID type OSC +#define HID_CONSUMER_MODE_STEP 0x82 // HID type OSC +#define HID_CONSUMER_RECALL_LAST 0x83 // HID type OSC +#define HID_CONSUMER_ENTER_CHANNEL 0x84 // HID type OSC +#define HID_CONSUMER_ORDER_MOVIE 0x85 // HID type OSC +#define HID_CONSUMER_CHANNEL 0x86 // HID type LC +#define HID_CONSUMER_MEDIA_SELECTION 0x87 // HID type NARY +#define HID_CONSUMER_MEDIA_SELECT_COMPUTER 0x88 // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_TV 0x89 // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_WWW 0x8A // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_DVD 0x8B // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_TELEPHONE 0x8C // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_PROGRAM_GUIDE 0x8D // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_VIDEO_PHONE 0x8E // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_GAMES 0x8F // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_MESSAGES 0x90 // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_CD 0x91 // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_VCR 0x92 // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_TUNER 0x93 // HID type SEL +#define HID_CONSUMER_QUIT 0x94 // HID type OSC +#define HID_CONSUMER_HELP 0x95 // HID type OOC +#define HID_CONSUMER_MEDIA_SELECT_TAPE 0x96 // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_CABLE 0x97 // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_SATELLITE 0x98 // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_SECURITY 0x99 // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_HOME 0x9A // HID type SEL +#define HID_CONSUMER_MEDIA_SELECT_CALL 0x9B // HID type SEL +#define HID_CONSUMER_CHANNEL_INCREMENT 0x9C // HID type OSC +#define HID_CONSUMER_CHANNEL_DECREMENT 0x9D // HID type OSC +#define HID_CONSUMER_MEDIA_SELECT_SAP 0x9E // HID type SEL +// Reserved 0x9F +#define HID_CONSUMER_VCR_PLUS 0xA0 // HID type OSC +#define HID_CONSUMER_ONCE 0xA1 // HID type OSC +#define HID_CONSUMER_DAILY 0xA2 // HID type OSC +#define HID_CONSUMER_WEEKLY 0xA3 // HID type OSC +#define HID_CONSUMER_MONTHLY 0xA4 // HID type OSC +// Reserved 0xA5-AF +#define HID_CONSUMER_PLAY 0xB0 // HID type OOC +#define HID_CONSUMER_PAUSE 0xB1 // HID type OOC +#define HID_CONSUMER_RECORD 0xB2 // HID type OOC +#define HID_CONSUMER_FAST_FORWARD 0xB3 // HID type OOC +#define HID_CONSUMER_REWIND 0xB4 // HID type OOC +#define HID_CONSUMER_SCAN_NEXT_TRACK 0xB5 // HID type OSC +#define HID_CONSUMER_SCAN_PREVIOUS_TRACK 0xB6 // HID type OSC +#define HID_CONSUMER_STOP 0xB7 // HID type OSC +#define HID_CONSUMER_EJECT 0xB8 // HID type OSC +#define HID_CONSUMER_RANDOM_PLAY 0xB9 // HID type OOC +#define HID_CONSUMER_SELECT_DISC 0xBA // HID type NARY +#define HID_CONSUMER_ENTER_DISC_MC 0xBB +#define HID_CONSUMER_REPEAT 0xBC // HID type OSC +#define HID_CONSUMER_TRACKING 0xBD // HID type LC +#define HID_CONSUMER_TRACK_NORMAL 0xBE // HID type OSC +#define HID_CONSUMER_SLOW_TRACKING 0xBF // HID type LC +#define HID_CONSUMER_FRAME_FORWARD 0xC0 // HID type RTC +#define HID_CONSUMER_FRAME_BACK 0xC1 // HID type RTC +#define HID_CONSUMER_MARK 0xC2 // HID type OSC +#define HID_CONSUMER_CLEAR_MARK 0xC3 // HID type OSC +#define HID_CONSUMER_REPEAT_FROM_MARK 0xC4 // HID type OOC +#define HID_CONSUMER_RETURN_TO_MARK 0xC5 // HID type OSC +#define HID_CONSUMER_SEARCH_MARK_FORWARD 0xC6 // HID type OSC +#define HID_CONSUMER_SEARCH_MARK_BACKWARDS 0xC7 // HID type OSC +#define HID_CONSUMER_COUNTER_RESET 0xC8 // HID type OSC +#define HID_CONSUMER_SHOW_COUNTER 0xC9 // HID type OSC +#define HID_CONSUMER_TRACKING_INCREMENT 0xCA // HID type RTC +#define HID_CONSUMER_TRACKING_DECREMENT 0xCB // HID type RTC +#define HID_CONSUMER_STOP_SLASH_EJECT 0xCC // HID type OSC +#define HID_CONSUMER_PLAY_SLASH_PAUSE 0xCD // HID type OSC +#define HID_CONSUMER_PLAY_SLASH_SKIP 0xCE // HID type OSC +// Reserved 0xCF-DF +#define HID_CONSUMER_VOLUME 0xE0 // HID type LC +#define HID_CONSUMER_BALANCE 0xE1 // HID type LC +#define HID_CONSUMER_MUTE 0xE2 // HID type OOC +#define HID_CONSUMER_BASS 0xE3 // HID type LC +#define HID_CONSUMER_TREBLE 0xE4 // HID type LC +#define HID_CONSUMER_BASS_BOOST 0xE5 // HID type OOC +#define HID_CONSUMER_SURROUND_MODE 0xE6 // HID type OSC +#define HID_CONSUMER_LOUDNESS 0xE7 // HID type OOC +#define HID_CONSUMER_MPX 0xE8 // HID type OOC +#define HID_CONSUMER_VOLUME_INCREMENT 0xE9 // HID type RTC +#define HID_CONSUMER_VOLUME_DECREMENT 0xEA // HID type RTC +// Reserved 0xEB-EF +#define HID_CONSUMER_SPEED_SELECT 0xF0 // HID type OSC +#define HID_CONSUMER_PLAYBACK_SPEED 0xF1 // HID type NARY +#define HID_CONSUMER_STANDARD_PLAY 0xF2 // HID type SEL +#define HID_CONSUMER_LONG_PLAY 0xF3 // HID type SEL +#define HID_CONSUMER_EXTENDED_PLAY 0xF4 // HID type SEL +#define HID_CONSUMER_SLOW 0xF5 // HID type OSC +// Reserved 0xF6-FF +#define HID_CONSUMER_FAN_ENABLE 0x100 // HID type OOC +#define HID_CONSUMER_FAN_SPEED 0x101 // HID type LC +#define HID_CONSUMER_LIGHT_ENABLE 0x102 // HID type OOC +#define HID_CONSUMER_LIGHT_ILLUMINATION_LEVEL 0x103 // HID type LC +#define HID_CONSUMER_CLIMATE_CONTROL_ENABLE 0x104 // HID type OOC +#define HID_CONSUMER_ROOM_TEMPERATURE 0x105 // HID type LC +#define HID_CONSUMER_SECURITY_ENABLE 0x106 // HID type OOC +#define HID_CONSUMER_FIRE_ALARM 0x107 // HID type OSC +#define HID_CONSUMER_POLICE_ALARM 0x108 // HID type OSC +#define HID_CONSUMER_PROXIMITY 0x109 // HID type LC +#define HID_CONSUMER_MOTION 0x10A // HID type OSC +#define HID_CONSUMER_DURESS_ALARM 0x10B // HID type OSC +#define HID_CONSUMER_HOLDUP_ALARM 0x10C // HID type OSC +#define HID_CONSUMER_MEDICAL_ALARM 0x10D // HID type OSC +// Reserved 0x10E-14F +#define HID_CONSUMER_BALANCE_RIGHT 0x150 // HID type RTC +#define HID_CONSUMER_BALANCE_LEFT 0x151 // HID type RTC +#define HID_CONSUMER_BASS_INCREMENT 0x152 // HID type RTC +#define HID_CONSUMER_BASS_DECREMENT 0x153 // HID type RTC +#define HID_CONSUMER_TREBLE_INCREMENT 0x154 // HID type RTC +#define HID_CONSUMER_TREBLE_DECREMENT 0x155 // HID type RTC +// Reserved 0x156-15F +#define HID_CONSUMER_SPEAKER_SYSTEM 0x160 // HID type CL +#define HID_CONSUMER_CHANNEL_LEFT 0x161 // HID type CL +#define HID_CONSUMER_CHANNEL_RIGHT 0x162 // HID type CL +#define HID_CONSUMER_CHANNEL_CENTER 0x163 // HID type CL +#define HID_CONSUMER_CHANNEL_FRONT 0x164 // HID type CL +#define HID_CONSUMER_CHANNEL_CENTER_FRONT 0x165 // HID type CL +#define HID_CONSUMER_CHANNEL_SIDE 0x166 // HID type CL +#define HID_CONSUMER_CHANNEL_SURROUND 0x167 // HID type CL +#define HID_CONSUMER_CHANNEL_LOW_FREQUENCY_ENHANCEMENT 0x168 // HID type CL +#define HID_CONSUMER_CHANNEL_TOP 0x169 // HID type CL +#define HID_CONSUMER_CHANNEL_UNKNOWN 0x16A // HID type CL +// Reserved 0x16B-16F +#define HID_CONSUMER_SUB-CHANNEL 0x170 // HID type LC +#define HID_CONSUMER_SUB-CHANNEL_INCREMENT 0x171 // HID type OSC +#define HID_CONSUMER_SUB-CHANNEL_DECREMENT 0x172 // HID type OSC +#define HID_CONSUMER_ALTERNATE_AUDIO_INCREMENT 0x173 // HID type OSC +#define HID_CONSUMER_ALTERNATE_AUDIO_DECREMENT 0x174 // HID type OSC +// Reserved 0x175-17F +#define HID_CONSUMER_APPLICATION_LAUNCH_BUTTONS 0x180 // HID type NARY +#define HID_CONSUMER_AL_LAUNCH_BUTTON_CONFIGURATION_TOOL 0x181 // HID type SEL +#define HID_CONSUMER_AL_PROGRAMMABLE_BUTTON_CONFIGURATION 0x182 // HID type SEL +#define HID_CONSUMER_AL_CONSUMER_CONTROL_CONFIGURATION 0x183 // HID type SEL +#define HID_CONSUMER_AL_WORD_PROCESSOR 0x184 // HID type SEL +#define HID_CONSUMER_AL_TEXT_EDITOR 0x185 // HID type SEL +#define HID_CONSUMER_AL_SPREADSHEET 0x186 // HID type SEL +#define HID_CONSUMER_AL_GRAPHICS_EDITOR 0x187 // HID type SEL +#define HID_CONSUMER_AL_PRESENTATION_APP 0x188 // HID type SEL +#define HID_CONSUMER_AL_DATABASE_APP 0x189 // HID type SEL +#define HID_CONSUMER_AL_EMAIL_READER 0x18A // HID type SEL +#define HID_CONSUMER_AL_NEWSREADER 0x18B // HID type SEL +#define HID_CONSUMER_AL_VOICEMAIL 0x18C // HID type SEL +#define HID_CONSUMER_AL_CONTACTS_SLASH_ADDRESS_BOOK 0x18D // HID type SEL +#define HID_CONSUMER_AL_CALENDAR_SLASH_SCHEDULE 0x18E // HID type SEL +#define HID_CONSUMER_AL_TASK_SLASH_PROJECT_MANAGER 0x18F // HID type SEL +#define HID_CONSUMER_AL_LOG_SLASH_JOURNAL_SLASH_TIMECARD 0x190 // HID type SEL +#define HID_CONSUMER_AL_CHECKBOOK_SLASH_FINANCE 0x191 // HID type SEL +#define HID_CONSUMER_AL_CALCULATOR 0x192 // HID type SEL +#define HID_CONSUMER_AL_A_SLASH_V_CAPTURE_SLASH_PLAYBACK 0x193 // HID type SEL +#define HID_CONSUMER_AL_LOCAL_MACHINE_BROWSER 0x194 // HID type SEL +#define HID_CONSUMER_AL_LAN_SLASH_WAN_BROWSER 0x195 // HID type SEL +#define HID_CONSUMER_AL_INTERNET_BROWSER 0x196 // HID type SEL +#define HID_CONSUMER_AL_REMOTE_NETWORKING_SLASH_ISP_CONNECT 0x197 // HID type SEL +#define HID_CONSUMER_AL_NETWORK_CONFERENCE 0x198 // HID type SEL +#define HID_CONSUMER_AL_NETWORK_CHAT 0x199 // HID type SEL +#define HID_CONSUMER_AL_TELEPHONY_SLASH_DIALER 0x19A // HID type SEL +#define HID_CONSUMER_AL_LOGON 0x19B // HID type SEL +#define HID_CONSUMER_AL_LOGOFF 0x19C // HID type SEL +#define HID_CONSUMER_AL_LOGON_SLASH_LOGOFF 0x19D // HID type SEL +#define HID_CONSUMER_AL_TERMINAL_LOCK_SLASH_SCREENSAVER 0x19E // HID type SEL +#define HID_CONSUMER_AL_CONTROL_PANEL 0x19F // HID type SEL +#define HID_CONSUMER_AL_COMMAND_LINE_PROCESSOR_SLASH_RUN 0x1A0 // HID type SEL +#define HID_CONSUMER_AL_PROCESS_SLASH_TASK_MANAGER 0x1A1 // HID type SEL +#define HID_CONSUMER_AL_SELECT_TASK_SLASH_APPLICATION 0x1A2 // HID type SEL +#define HID_CONSUMER_AL_NEXT_TASK_SLASH_APPLICATION 0x1A3 // HID type SEL +#define HID_CONSUMER_AL_PREVIOUS_TASK_SLASH_APPLICATION 0x1A4 // HID type SEL +#define HID_CONSUMER_AL_PREEMPTIVE_HALT_TASK_SLASH_APPLICATION 0x1A5 // HID type SEL +#define HID_CONSUMER_AL_INTEGRATED_HELP_CENTER 0x1A6 // HID type SEL +#define HID_CONSUMER_AL_DOCUMENTS 0x1A7 // HID type SEL +#define HID_CONSUMER_AL_THESAURUS 0x1A8 // HID type SEL +#define HID_CONSUMER_AL_DICTIONARY 0x1A9 // HID type SEL +#define HID_CONSUMER_AL_DESKTOP 0x1AA // HID type SEL +#define HID_CONSUMER_AL_SPELL_CHECK 0x1AB // HID type SEL +#define HID_CONSUMER_AL_GRAMMAR_CHECK 0x1AC // HID type SEL +#define HID_CONSUMER_AL_WIRELESS_STATUS 0x1AD // HID type SEL +#define HID_CONSUMER_AL_KEYBOARD_LAYOUT 0x1AE // HID type SEL +#define HID_CONSUMER_AL_VIRUS_PROTECTION 0x1AF // HID type SEL +#define HID_CONSUMER_AL_ENCRYPTION 0x1B0 // HID type SEL +#define HID_CONSUMER_AL_SCREEN_SAVER 0x1B1 // HID type SEL +#define HID_CONSUMER_AL_ALARMS 0x1B2 // HID type SEL +#define HID_CONSUMER_AL_CLOCK 0x1B3 // HID type SEL +#define HID_CONSUMER_AL_FILE_BROWSER 0x1B4 // HID type SEL +#define HID_CONSUMER_AL_POWER_STATUS 0x1B5 // HID type SEL +#define HID_CONSUMER_AL_IMAGE_BROWSER 0x1B6 // HID type SEL +#define HID_CONSUMER_AL_AUDIO_BROWSER 0x1B7 // HID type SEL +#define HID_CONSUMER_AL_MOVIE_BROWSER 0x1B8 // HID type SEL +#define HID_CONSUMER_AL_DIGITAL_RIGHTS_MANAGER 0x1B9 // HID type SEL +#define HID_CONSUMER_AL_DIGITAL_WALLET 0x1BA // HID type SEL +// _Reserved 0x1BB +#define HID_CONSUMER_AL_INSTANT_MESSAGING 0x1BC // HID type SEL +#define HID_CONSUMER_AL_OEM_FEATURES_SLASH__TIPS_SLASH_TUTORIAL_BROWSER 0x1BD // HID type SEL +#define HID_CONSUMER_AL_OEM_HELP 0x1BE // HID type SEL +#define HID_CONSUMER_AL_ONLINE_COMMUNITY 0x1BF // HID type SEL +#define HID_CONSUMER_AL_ENTERTAINMENT_CONTENT_BROWSER 0x1C0 // HID type SEL +#define HID_CONSUMER_AL_ONLINE_SHOPPING_BROWSER 0x1C1 // HID type SEL +#define HID_CONSUMER_AL_SMARTCARD_INFORMATION_SLASH_HELP 0x1C2 // HID type SEL +#define HID_CONSUMER_AL_MARKET_MONITOR_SLASH_FINANCE_BROWSER 0x1C3 // HID type SEL +#define HID_CONSUMER_AL_CUSTOMIZED_CORPORATE_NEWS_BROWSER 0x1C4 // HID type SEL +#define HID_CONSUMER_AL_ONLINE_ACTIVITY_BROWSER 0x1C5 // HID type SEL +#define HID_CONSUMER_AL_RESEARCH_SLASH_SEARCH_BROWSER 0x1C6 // HID type SEL +#define HID_CONSUMER_AL_AUDIO_PLAYER 0x1C7 // HID type SEL +// Reserved 0x1C8-1FF +#define HID_CONSUMER_GENERIC_GUI_APPLICATION_CONTROLS 0x200 // HID type NARY +#define HID_CONSUMER_AC_NEW 0x201 // HID type SEL +#define HID_CONSUMER_AC_OPEN 0x202 // HID type SEL +#define HID_CONSUMER_AC_CLOSE 0x203 // HID type SEL +#define HID_CONSUMER_AC_EXIT 0x204 // HID type SEL +#define HID_CONSUMER_AC_MAXIMIZE 0x205 // HID type SEL +#define HID_CONSUMER_AC_MINIMIZE 0x206 // HID type SEL +#define HID_CONSUMER_AC_SAVE 0x207 // HID type SEL +#define HID_CONSUMER_AC_PRINT 0x208 // HID type SEL +#define HID_CONSUMER_AC_PROPERTIES 0x209 // HID type SEL +#define HID_CONSUMER_AC_UNDO 0x21A // HID type SEL +#define HID_CONSUMER_AC_COPY 0x21B // HID type SEL +#define HID_CONSUMER_AC_CUT 0x21C // HID type SEL +#define HID_CONSUMER_AC_PASTE 0x21D // HID type SEL +#define HID_CONSUMER_AC_SELECT_ALL 0x21E // HID type SEL +#define HID_CONSUMER_AC_FIND 0x21F // HID type SEL +#define HID_CONSUMER_AC_FIND_AND_REPLACE 0x220 // HID type SEL +#define HID_CONSUMER_AC_SEARCH 0x221 // HID type SEL +#define HID_CONSUMER_AC_GO_TO 0x222 // HID type SEL +#define HID_CONSUMER_AC_HOME 0x223 // HID type SEL +#define HID_CONSUMER_AC_BACK 0x224 // HID type SEL +#define HID_CONSUMER_AC_FORWARD 0x225 // HID type SEL +#define HID_CONSUMER_AC_STOP 0x226 // HID type SEL +#define HID_CONSUMER_AC_REFRESH 0x227 // HID type SEL +#define HID_CONSUMER_AC_PREVIOUS_LINK 0x228 // HID type SEL +#define HID_CONSUMER_AC_NEXT_LINK 0x229 // HID type SEL +#define HID_CONSUMER_AC_BOOKMARKS 0x22A // HID type SEL +#define HID_CONSUMER_AC_HISTORY 0x22B // HID type SEL +#define HID_CONSUMER_AC_SUBSCRIPTIONS 0x22C // HID type SEL +#define HID_CONSUMER_AC_ZOOM_IN 0x22D // HID type SEL +#define HID_CONSUMER_AC_ZOOM_OUT 0x22E // HID type SEL +#define HID_CONSUMER_AC_ZOOM 0x22F // HID type LC +#define HID_CONSUMER_AC_FULL_SCREEN_VIEW 0x230 // HID type SEL +#define HID_CONSUMER_AC_NORMAL_VIEW 0x231 // HID type SEL +#define HID_CONSUMER_AC_VIEW_TOGGLE 0x232 // HID type SEL +#define HID_CONSUMER_AC_SCROLL_UP 0x233 // HID type SEL +#define HID_CONSUMER_AC_SCROLL_DOWN 0x234 // HID type SEL +#define HID_CONSUMER_AC_SCROLL 0x235 // HID type LC +#define HID_CONSUMER_AC_PAN_LEFT 0x236 // HID type SEL +#define HID_CONSUMER_AC_PAN_RIGHT 0x237 // HID type SEL +#define HID_CONSUMER_AC_PAN 0x238 // HID type LC +#define HID_CONSUMER_AC_NEW_WINDOW 0x239 // HID type SEL +#define HID_CONSUMER_AC_TILE_HORIZONTALLY 0x23A // HID type SEL +#define HID_CONSUMER_AC_TILE_VERTICALLY 0x23B // HID type SEL +#define HID_CONSUMER_AC_FORMAT 0x23C // HID type SEL +#define HID_CONSUMER_AC_EDIT 0x23D // HID type SEL +#define HID_CONSUMER_AC_BOLD 0x23E // HID type SEL +#define HID_CONSUMER_AC_ITALICS 0x23F // HID type SEL +#define HID_CONSUMER_AC_UNDERLINE 0x240 // HID type SEL +#define HID_CONSUMER_AC_STRIKETHROUGH 0x241 // HID type SEL +#define HID_CONSUMER_AC_SUBSCRIPT 0x242 // HID type SEL +#define HID_CONSUMER_AC_SUPERSCRIPT 0x243 // HID type SEL +#define HID_CONSUMER_AC_ALL_CAPS 0x244 // HID type SEL +#define HID_CONSUMER_AC_ROTATE 0x245 // HID type SEL +#define HID_CONSUMER_AC_RESIZE 0x246 // HID type SEL +#define HID_CONSUMER_AC_FLIP_HORIZONTAL 0x247 // HID type SEL +#define HID_CONSUMER_AC_FLIP_VERTICAL 0x248 // HID type SEL +#define HID_CONSUMER_AC_MIRROR_HORIZONTAL 0x249 // HID type SEL +#define HID_CONSUMER_AC_MIRROR_VERTICAL 0x24A // HID type SEL +#define HID_CONSUMER_AC_FONT_SELECT 0x24B // HID type SEL +#define HID_CONSUMER_AC_FONT_COLOR 0x24C // HID type SEL +#define HID_CONSUMER_AC_FONT_SIZE 0x24D // HID type SEL +#define HID_CONSUMER_AC_JUSTIFY_LEFT 0x24E // HID type SEL +#define HID_CONSUMER_AC_JUSTIFY_CENTER_H 0x24F // HID type SEL +#define HID_CONSUMER_AC_JUSTIFY_RIGHT 0x250 // HID type SEL +#define HID_CONSUMER_AC_JUSTIFY_BLOCK_H 0x251 // HID type SEL +#define HID_CONSUMER_AC_JUSTIFY_TOP 0x252 // HID type SEL +#define HID_CONSUMER_AC_JUSTIFY_CENTER_V 0x253 // HID type SEL +#define HID_CONSUMER_AC_JUSTIFY_BOTTOM 0x254 // HID type SEL +#define HID_CONSUMER_AC_JUSTIFY_BLOCK_V 0x255 // HID type SEL +#define HID_CONSUMER_AC_INDENT_DECREASE 0x256 // HID type SEL +#define HID_CONSUMER_AC_INDENT_INCREASE 0x257 // HID type SEL +#define HID_CONSUMER_AC_NUMBERED_LIST 0x258 // HID type SEL +#define HID_CONSUMER_AC_RESTART_NUMBERING 0x259 // HID type SEL +#define HID_CONSUMER_AC_BULLETED_LIST 0x25A // HID type SEL +#define HID_CONSUMER_AC_PROMOTE 0x25B // HID type SEL +#define HID_CONSUMER_AC_DEMOTE 0x25C // HID type SEL +#define HID_CONSUMER_AC_YES 0x25D // HID type SEL +#define HID_CONSUMER_AC_NO 0x25E // HID type SEL +#define HID_CONSUMER_AC_CANCEL 0x25F // HID type SEL +#define HID_CONSUMER_AC_CATALOG 0x260 // HID type SEL +#define HID_CONSUMER_AC_BUY_SLASH_CHECKOUT 0x261 // HID type SEL +#define HID_CONSUMER_AC_ADD_TO_CART 0x262 // HID type SEL +#define HID_CONSUMER_AC_EXPAND 0x263 // HID type SEL +#define HID_CONSUMER_AC_EXPAND_ALL 0x264 // HID type SEL +#define HID_CONSUMER_AC_COLLAPSE 0x265 // HID type SEL +#define HID_CONSUMER_AC_COLLAPSE_ALL 0x266 // HID type SEL +#define HID_CONSUMER_AC_PRINT_PREVIEW 0x267 // HID type SEL +#define HID_CONSUMER_AC_PASTE_SPECIAL 0x268 // HID type SEL +#define HID_CONSUMER_AC_INSERT_MODE 0x269 // HID type SEL +#define HID_CONSUMER_AC_DELETE 0x26A // HID type SEL +#define HID_CONSUMER_AC_LOCK 0x26B // HID type SEL +#define HID_CONSUMER_AC_UNLOCK 0x26C // HID type SEL +#define HID_CONSUMER_AC_PROTECT 0x26D // HID type SEL +#define HID_CONSUMER_AC_UNPROTECT 0x26E // HID type SEL +#define HID_CONSUMER_AC_ATTACH_COMMENT 0x26F // HID type SEL +#define HID_CONSUMER_AC_DELETE_COMMENT 0x270 // HID type SEL +#define HID_CONSUMER_AC_VIEW_COMMENT 0x271 // HID type SEL +#define HID_CONSUMER_AC_SELECT_WORD 0x272 // HID type SEL +#define HID_CONSUMER_AC_SELECT_SENTENCE 0x273 // HID type SEL +#define HID_CONSUMER_AC_SELECT_PARAGRAPH 0x274 // HID type SEL +#define HID_CONSUMER_AC_SELECT_COLUMN 0x275 // HID type SEL +#define HID_CONSUMER_AC_SELECT_ROW 0x276 // HID type SEL +#define HID_CONSUMER_AC_SELECT_TABLE 0x277 // HID type SEL +#define HID_CONSUMER_AC_SELECT_OBJECT 0x278 // HID type SEL +#define HID_CONSUMER_AC_REDO_SLASH_REPEAT 0x279 // HID type SEL +#define HID_CONSUMER_AC_SORT 0x27A // HID type SEL +#define HID_CONSUMER_AC_SORT_ASCENDING 0x27B // HID type SEL +#define HID_CONSUMER_AC_SORT_DESCENDING 0x27C // HID type SEL +#define HID_CONSUMER_AC_FILTER 0x27D // HID type SEL +#define HID_CONSUMER_AC_SET_CLOCK 0x27E // HID type SEL +#define HID_CONSUMER_AC_VIEW_CLOCK 0x27F // HID type SEL +#define HID_CONSUMER_AC_SELECT_TIME_ZONE 0x280 // HID type SEL +#define HID_CONSUMER_AC_EDIT_TIME_ZONES 0x281 // HID type SEL +#define HID_CONSUMER_AC_SET_ALARM 0x282 // HID type SEL +#define HID_CONSUMER_AC_CLEAR_ALARM 0x283 // HID type SEL +#define HID_CONSUMER_AC_SNOOZE_ALARM 0x284 // HID type SEL +#define HID_CONSUMER_AC_RESET_ALARM 0x285 // HID type SEL +#define HID_CONSUMER_AC_SYNCHRONIZE 0x286 // HID type SEL +#define HID_CONSUMER_AC_SEND_SLASH_RECEIVE 0x287 // HID type SEL +#define HID_CONSUMER_AC_SEND_TO 0x288 // HID type SEL +#define HID_CONSUMER_AC_REPLY 0x289 // HID type SEL +#define HID_CONSUMER_AC_REPLY_ALL 0x28A // HID type SEL +#define HID_CONSUMER_AC_FORWARD_MSG 0x28B // HID type SEL +#define HID_CONSUMER_AC_SEND 0x28C // HID type SEL +#define HID_CONSUMER_AC_ATTACH_FILE 0x28D // HID type SEL +#define HID_CONSUMER_AC_UPLOAD 0x28E // HID type SEL +#define HID_CONSUMER_AC_DOWNLOAD_(SAVE_TARGET_AS) 0x28F // HID type SEL +#define HID_CONSUMER_AC_SET_BORDERS 0x290 // HID type SEL +#define HID_CONSUMER_AC_INSERT_ROW 0x291 // HID type SEL +#define HID_CONSUMER_AC_INSERT_COLUMN 0x292 // HID type SEL +#define HID_CONSUMER_AC_INSERT_FILE 0x293 // HID type SEL +#define HID_CONSUMER_AC_INSERT_PICTURE 0x294 // HID type SEL +#define HID_CONSUMER_AC_INSERT_OBJECT 0x295 // HID type SEL +#define HID_CONSUMER_AC_INSERT_SYMBOL 0x296 // HID type SEL +#define HID_CONSUMER_AC_SAVE_AND_CLOSE 0x297 // HID type SEL +#define HID_CONSUMER_AC_RENAME 0x298 // HID type SEL +#define HID_CONSUMER_AC_MERGE 0x299 // HID type SEL +#define HID_CONSUMER_AC_SPLIT 0x29A // HID type SEL +#define HID_CONSUMER_AC_DISRIBUTE_HORIZONTALLY 0x29B // HID type SEL +#define HID_CONSUMER_AC_DISTRIBUTE_VERTICALLY 0x29C // HID type SEL + +#endif // __HIDTables__ From 454a9514ebf9e100b37d0f0cc9ced2fbbdf7c99a Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Thu, 10 Dec 2015 23:33:35 -0800 Subject: [PATCH 365/602] Remove old asciimap (now that we're only going to use the actual key defines) --- .../src/KeyboardCore/ImprovedKeylayouts.h | 135 ------------------ 1 file changed, 135 deletions(-) diff --git a/plugins/KeyboardioHID/src/KeyboardCore/ImprovedKeylayouts.h b/plugins/KeyboardioHID/src/KeyboardCore/ImprovedKeylayouts.h index 26d03f81f1..6ce103dfbd 100644 --- a/plugins/KeyboardioHID/src/KeyboardCore/ImprovedKeylayouts.h +++ b/plugins/KeyboardioHID/src/KeyboardCore/ImprovedKeylayouts.h @@ -486,138 +486,3 @@ enum KeyboardKeycode : uint8_t { HID_KEYBOARD_RIGHT_ALT = 0xE6, HID_KEYBOARD_RIGHT_GUI = 0xE7, }; - -#define SHIFT 0x80 -static const uint8_t _asciimap[] PROGMEM = -{ - KEY_RESERVED, // NUL - KEY_RESERVED, // SOH - KEY_RESERVED, // STX - KEY_RESERVED, // ETX - KEY_RESERVED, // EOT - KEY_RESERVED, // ENQ - KEY_RESERVED, // ACK - KEY_RESERVED, // BEL - KEY_BACKSPACE, // BS Backspace - KEY_TAB, // TAB Tab - KEY_ENTER, // LF Enter - KEY_RESERVED, // VT - KEY_RESERVED, // FF - KEY_RESERVED, // CR - KEY_RESERVED, // SO - KEY_RESERVED, // SI - KEY_RESERVED, // DEL - KEY_RESERVED, // DC1 - KEY_RESERVED, // DC2 - KEY_RESERVED, // DC3 - KEY_RESERVED, // DC4 - KEY_RESERVED, // NAK - KEY_RESERVED, // SYN - KEY_RESERVED, // ETB - KEY_RESERVED, // CAN - KEY_RESERVED, // EM - KEY_RESERVED, // SUB - KEY_RESERVED, // ESC - KEY_RESERVED, // FS - KEY_RESERVED, // GS - KEY_RESERVED, // RS - KEY_RESERVED, // US - - KEY_SPACE, // ' ' Space - KEY_1|SHIFT, // ! - KEY_QUOTE|SHIFT, // " - KEY_3|SHIFT, // # - KEY_4|SHIFT, // $ - KEY_5|SHIFT, // % - KEY_7|SHIFT, // & - KEY_QUOTE, // ' - KEY_9|SHIFT, // ( - KEY_0|SHIFT, // ) - KEY_8|SHIFT, // * - KEY_EQUAL|SHIFT, // + - KEY_COMMA, // , - KEY_MINUS, // - - KEY_PERIOD, // . - KEY_SLASH, // / - KEY_0, // 0 - KEY_1, // 1 - KEY_2, // 2 - KEY_3, // 3 - KEY_4, // 4 - KEY_5, // 5 - KEY_6, // 6 - KEY_7, // 7 - KEY_8, // 8 - KEY_9, // 9 - KEY_SEMICOLON|SHIFT, // : - KEY_SEMICOLON, // ; - KEY_COMMA|SHIFT, // < - KEY_EQUAL, // = - KEY_PERIOD|SHIFT, // > - KEY_SLASH|SHIFT, // ? - KEY_2|SHIFT, // @ - KEY_A|SHIFT, // A - KEY_B|SHIFT, // B - KEY_C|SHIFT, // C - KEY_D|SHIFT, // D - KEY_E|SHIFT, // E - KEY_F|SHIFT, // F - KEY_G|SHIFT, // G - KEY_H|SHIFT, // H - KEY_I|SHIFT, // I - KEY_J|SHIFT, // J - KEY_K|SHIFT, // K - KEY_L|SHIFT, // L - KEY_M|SHIFT, // M - KEY_N|SHIFT, // N - KEY_O|SHIFT, // O - KEY_P|SHIFT, // P - KEY_Q|SHIFT, // Q - KEY_R|SHIFT, // R - KEY_S|SHIFT, // S - KEY_T|SHIFT, // T - KEY_U|SHIFT, // U - KEY_V|SHIFT, // V - KEY_W|SHIFT, // W - KEY_X|SHIFT, // X - KEY_Y|SHIFT, // Y - KEY_Z|SHIFT, // Z - KEY_LEFT_BRACE, // [ - KEY_BACKSLASH, // bslash - KEY_RIGHT_BRACE, // ] - KEY_6|SHIFT, // ^ - KEY_MINUS|SHIFT, // _ - KEY_TILDE, // ` - KEY_A, // a - KEY_B, // b - KEY_C, // c - KEY_D, // d - KEY_E, // e - KEY_F, // f - KEY_G, // g - KEY_H, // h - KEY_I, // i - KEY_J, // j - KEY_K, // k - KEY_L, // l - KEY_M, // m - KEY_N, // n - KEY_O, // o - KEY_P, // p - KEY_Q, // q - KEY_R, // r - KEY_S, // s - KEY_T, // t - KEY_U, // u - KEY_V, // v - KEY_W, // w - KEY_X, // x - KEY_Y, // y - KEY_Z, // z - KEY_LEFT_BRACE|SHIFT, // { - KEY_BACKSLASH|SHIFT, // | - KEY_RIGHT_BRACE|SHIFT, // } - KEY_TILDE|SHIFT, // ~ - KEY_RESERVED // DEL -}; - From 20a5493692dc07750b373209edfba57c055b7933 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 12:47:34 -0800 Subject: [PATCH 366/602] Replacing the "release" -> "remove" delegated API with just using "release" --- plugins/KeyboardioHID/keywords.txt | 2 -- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp | 2 +- plugins/KeyboardioHID/src/KeyboardCore/KeyboardAPI.hpp | 2 +- plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp | 3 ++- plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h | 2 +- 5 files changed, 5 insertions(+), 6 deletions(-) diff --git a/plugins/KeyboardioHID/keywords.txt b/plugins/KeyboardioHID/keywords.txt index a12017b90d..e7cc7c2003 100644 --- a/plugins/KeyboardioHID/keywords.txt +++ b/plugins/KeyboardioHID/keywords.txt @@ -13,8 +13,6 @@ begin KEYWORD2 end KEYWORD2 press KEYWORD2 -add KEYWORD2 -remove KEYWORD2 release KEYWORD2 releaseAll KEYWORD2 diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 12a75a6dd5..e58750c01a 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -246,7 +246,7 @@ size_t BootKeyboard_::set(KeyboardKeycode k, bool s) return 0; } -size_t BootKeyboard_::removeAll(void) +void BootKeyboard_::releaseAll(void) { // Release all keys size_t ret = 0; diff --git a/plugins/KeyboardioHID/src/KeyboardCore/KeyboardAPI.hpp b/plugins/KeyboardioHID/src/KeyboardCore/KeyboardAPI.hpp index 2cbe6fcb79..8b51910ffa 100644 --- a/plugins/KeyboardioHID/src/KeyboardCore/KeyboardAPI.hpp +++ b/plugins/KeyboardioHID/src/KeyboardCore/KeyboardAPI.hpp @@ -30,8 +30,8 @@ void KeyboardAPI::begin(void) // Force API to send a clean report. // This is important for and HID bridge where the receiver stays on, // while the sender is resetted. - removeAll(); send(); + releaseAll(); } diff --git a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp index 6667baecb2..ea31797c55 100644 --- a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp @@ -124,7 +124,8 @@ size_t NKROKeyboard_::set(KeyboardKeycode k, bool s) return 0; } -size_t NKROKeyboard_::removeAll(void) +// TODO: replace this with a mmap interface +size_t NKROKeyboard_::releaseAll(void) { // Release all keys size_t ret = 0; diff --git a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h index 5cbc5c03b2..0100365ee0 100644 --- a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h @@ -55,7 +55,7 @@ class NKROKeyboard_ : public KeyboardAPI public: NKROKeyboard_(void); // Implement adding/removing key functions - inline virtual size_t removeAll(void) override; + inline virtual size_t releaseAll(void) override; // Needs to be implemented in a lower level virtual int send(void) = 0; From b1493c23d053c0567411b4d58996a54d90eb4966 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 12:49:15 -0800 Subject: [PATCH 367/602] Migrate boot keyboard implementation into bootkeyboard --- .../src/BootKeyboard/BootKeyboard.cpp | 152 ++++++++++++------ .../src/BootKeyboard/BootKeyboard.h | 16 +- 2 files changed, 106 insertions(+), 62 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index e58750c01a..9a5ad0f6d9 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -105,6 +105,25 @@ int BootKeyboard_::getDescriptor(USBSetup& setup) return USB_SendControl(TRANSFER_PGM, _hidReportDescriptorKeyboard, sizeof(_hidReportDescriptorKeyboard)); } + +void BootKeyboard_::begin(void) +{ + // Force API to send a clean report. + // This is important for and HID bridge where the receiver stays on, + // while the sender is resetted. + releaseAll(); + sendReport(); +} + + +void BootKeyboard_::end(void) +{ + releaseAll(); + sendReport(); +} + + + bool BootKeyboard_::setup(USBSetup& setup) { if (pluggedInterface != setup.wIndex) { @@ -192,7 +211,7 @@ uint8_t BootKeyboard_::getProtocol(void){ return protocol; } -int BootKeyboard_::send(void){ +int BootKeyboard_::sendReport(void){ return USB_Send(pluggedEndpoint | TRANSFER_RELEASE, &_keyReport, sizeof(_keyReport)); } @@ -201,64 +220,97 @@ void BootKeyboard_::wakeupHost(void){ } - - - - -size_t BootKeyboard_::set(KeyboardKeycode k, bool s) -{ - // It's a modifier key - if(k >= KEY_LEFT_CTRL && k <= KEY_RIGHT_GUI) - { - // Convert key into bitfield (0 - 7) - k = KeyboardKeycode(uint8_t(k) - uint8_t(KEY_LEFT_CTRL)); - if(s){ - _keyReport.modifiers = (1 << k); - } - else{ - _keyReport.modifiers &= ~(1 << k); - } - return 1; - } - // Its a normal key - else{ - // Add k to the key report only if it's not already present - // and if there is an empty slot. Remove the first available key. + bool BootKeyboard_::press(uint8_t k) + { + uint8_t done = 0; + + if ((k >= HID_KEYBOARD_LEFT_CONTROL) && (k <= HID_KEYBOARD_RIGHT_GUI)) { + // it's a modifier key + _keyReport.modifiers |= (0x01 << (k - HID_KEYBOARD_LEFT_CONTROL)); + } else { + // it's some other key: + // Add k to the key report only if it's not already present + // and if there is an empty slot. for (uint8_t i = 0; i < sizeof(_keyReport.keycodes); i++) - { - auto key = _keyReport.keycodes[i]; - - // Is key already in the list or did we found an empty slot? - if (s && (key == uint8_t(k) || key == KEY_RESERVED)) { - _keyReport.keycodes[i] = k; - return 1; + { + if (_keyReport.keys[i] != k) { // is k already in list? + if (0 == _keyReport.keys[i]) { // have we found an empty slot? + _keyReport.keys[i] = k; + done = 1; + break; + } + } else { + done = 1; + break; + } + } + // use separate variable to check if slot was found + // for style reasons - we do not know how the compiler + // handles the for() index when it leaves the loop + if (0 == done) { + setWriteError(); + return 0; + } + } + return 1; + } + + + + +bool BootKeyboard_::release(uint8_t k) +{ + uint8_t i; + uint8_t count; + + if ((k >= HID_KEYBOARD_LEFT_CONTROL) && (k <= HID_KEYBOARD_RIGHT_GUI)) { + // it's a modifier key + _keyReport.modifiers = _keyReport.modifiers & (~(0x01 << (k - HID_KEYBOARD_LEFT_CONTROL))); + } else { + // it's some other key: + // 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 < sizeof(_keyReport.keycodes); i++) + { + if (_keyReport.keys[i] == k) { + _keyReport.keys[i] = 0; } - - // Test the key report to see if k is present. Clear it if it exists. - if (!s && (key == k)) { - _keyReport.keycodes[i] = KEY_RESERVED; - return 1; + } + + // finally rearrange the keys list so that the free (= 0x00) are at the + // end of the keys list - some implementations stop for keys at the + // first occurence of an 0x00 in the keys list + // so (0x00)(0x01)(0x00)(0x03)(0x02)(0x00) becomes + // (0x01)(0x03)(0x02)(0x00)(0x00)(0x00) + count = 0; // holds the number of zeros we've found + i = 0; + while ((i + count) < sizeof(_keyReport.keycodes)) { + if (0 == _keyReport.keys[i]) { + count++; // one more zero + for (uint8_t j = i; j < sizeof(_keyReport.keycodes)-count; j++) { + _keyReport.keys[j] = _keyReport.keys[j+1]; + } + _keyReport.keys[sizeof(_keyReport.keycodes)-count] = 0; + } else { + i++; // one more non-zero } } - } + } - // No empty/pressed key was found - return 0; + return 1; } + + + + + + + void BootKeyboard_::releaseAll(void) { - // Release all keys - size_t ret = 0; - for (uint8_t i = 0; i < sizeof(_keyReport.keys); i++) - { - // Is a key in the list or did we found an empty slot? - if(_keyReport.keys[i]){ - ret++; - } - _keyReport.keys[i] = 0x00; - } - return ret; + memset(&_keyReport, 0x00, sizeof(_keyReport)); } + BootKeyboard_ BootKeyboard; diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index e2716eecb9..42cb629a76 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -49,19 +49,11 @@ class BootKeyboard_ : public PluggableUSBModule, public KeyboardAPI { public: BootKeyboard_(void); + size_t press(uint8_t); + size_t release(uint8_t); + size_t releaseAll(void); - // Also use the base class functions - // http://en.cppreference.com/w/cpp/language/using_declaration - using KeyboardAPI::write; - using KeyboardAPI::press; - using KeyboardAPI::release; - using KeyboardAPI::add; - using KeyboardAPI::remove; - - // Implement adding/removing key functions - inline virtual size_t removeAll(void) override; - - int send(void); + int sendReport(void); From 00e2e30520a51b8930f3c09d59c1df28f60f05f8 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 13:00:26 -0800 Subject: [PATCH 368/602] Port some docs from the old Keybordio keyboard driver --- .../KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 9a5ad0f6d9..ec3403fb9c 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -220,6 +220,12 @@ void BootKeyboard_::wakeupHost(void){ } +// 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. + + bool BootKeyboard_::press(uint8_t k) { uint8_t done = 0; @@ -256,7 +262,9 @@ void BootKeyboard_::wakeupHost(void){ } - +// 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. bool BootKeyboard_::release(uint8_t k) { From 3aa88144beb117a0986bb93ff5e8ab6c1019d34d Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 13:01:17 -0800 Subject: [PATCH 369/602] minor whitespace cleanup --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index ec3403fb9c..531fbd1a05 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -308,13 +308,6 @@ bool BootKeyboard_::release(uint8_t k) return 1; } - - - - - - - void BootKeyboard_::releaseAll(void) { memset(&_keyReport, 0x00, sizeof(_keyReport)); From 9b1de1c4edc2f853984f622e6d48e4e066e20a7c Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 13:01:37 -0800 Subject: [PATCH 370/602] boot keyboard api cleanup --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index 42cb629a76..c1ee7c588d 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -45,7 +45,7 @@ typedef union{ } HID_KeyboardReport_Data_t; -class BootKeyboard_ : public PluggableUSBModule, public KeyboardAPI +class BootKeyboard_ : public PluggableUSBModule { public: BootKeyboard_(void); @@ -103,8 +103,6 @@ class BootKeyboard_ : public PluggableUSBModule, public KeyboardAPI uint8_t* featureReport; int featureLength; -private: - inline virtual size_t set(KeyboardKeycode k, bool s) override; }; extern BootKeyboard_ BootKeyboard; From 3a1f8e44039897a0dd31f4414f7874b736d43ca9 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 13:02:47 -0800 Subject: [PATCH 371/602] Point at the HID tables we actually use for the BootKeyboard code now --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index c1ee7c588d..904a60a259 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -28,7 +28,7 @@ THE SOFTWARE. #include "PluggableUSB.h" #include "HID.h" #include "HID-Settings.h" -#include "../KeyboardCore/KeyboardAPI.h" +#include "../KeyboardCore/HIDTables.h" typedef union{ From 03568e51485f5290e28be404c25261c7b1e873a2 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 13:04:24 -0800 Subject: [PATCH 372/602] Replacing send with sendReport for consistency and clarity --- plugins/KeyboardioHID/src/KeyboardCore/KeyboardAPI.h | 2 +- plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp | 2 +- plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/plugins/KeyboardioHID/src/KeyboardCore/KeyboardAPI.h b/plugins/KeyboardioHID/src/KeyboardCore/KeyboardAPI.h index 1eb8db5372..a31e5c5512 100644 --- a/plugins/KeyboardioHID/src/KeyboardCore/KeyboardAPI.h +++ b/plugins/KeyboardioHID/src/KeyboardCore/KeyboardAPI.h @@ -65,7 +65,7 @@ class KeyboardAPI : public Print // Needs to be implemented in a lower level virtual size_t removeAll(void) = 0; - virtual int send(void) = 0; + virtual int sendReport(void) = 0; private: virtual size_t set(KeyboardKeycode k, bool s) = 0; diff --git a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp index ea31797c55..b23ff7a4b8 100644 --- a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp @@ -68,7 +68,7 @@ NKROKeyboard_::NKROKeyboard_(void) HID().AppendDescriptor(&node); } -int NKROKeyboard_::send(void) +int NKROKeyboard_::sendReport(void) { return HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &_keyReport, sizeof(_keyReport)); } diff --git a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h index 0100365ee0..38a0abf033 100644 --- a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h @@ -57,8 +57,7 @@ class NKROKeyboard_ : public KeyboardAPI // Implement adding/removing key functions inline virtual size_t releaseAll(void) override; - // Needs to be implemented in a lower level - virtual int send(void) = 0; + virtual int sendReport(void) = 0; protected: HID_NKROKeyboardReport_Data_t _keyReport; From 45ff7dad5006335c816fc6012e6a47f60b34f2bd Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 13:16:11 -0800 Subject: [PATCH 373/602] partial removal of old keycode based interface --- plugins/KeyboardioHID/src/KeyboardCore/KeyboardAPI.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/plugins/KeyboardioHID/src/KeyboardCore/KeyboardAPI.h b/plugins/KeyboardioHID/src/KeyboardCore/KeyboardAPI.h index a31e5c5512..76e6866135 100644 --- a/plugins/KeyboardioHID/src/KeyboardCore/KeyboardAPI.h +++ b/plugins/KeyboardioHID/src/KeyboardCore/KeyboardAPI.h @@ -47,13 +47,6 @@ class KeyboardAPI : public Print inline void begin(void); inline void end(void); - // Raw Keycode API functions - inline size_t write(KeyboardKeycode k); - inline size_t press(KeyboardKeycode k); - inline size_t release(KeyboardKeycode k); - inline size_t remove(KeyboardKeycode k); - inline size_t add(KeyboardKeycode k); - inline size_t releaseAll(void); //press(uint8_t key, uint8_t modifier) TODO variadic template // Print API functions From 8ba12296f6c672c9a0fbcca69887d3dbd6094668 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 13:17:20 -0800 Subject: [PATCH 374/602] Lift 'begin' and 'end' from KeyboardCore to NKROKeyboard, since it was the last useful shared code --- .../src/MultiReport/NKROKeyboard.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp index b23ff7a4b8..b99ef9cea3 100644 --- a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp @@ -68,6 +68,24 @@ NKROKeyboard_::NKROKeyboard_(void) HID().AppendDescriptor(&node); } +void NKROKeyboard_::begin(void) +{ + // Force API to send a clean report. + // This is important for and HID bridge where the receiver stays on, + // while the sender is resetted. + releaseAll(); + sendReport(); +} + + +void NKROKeyboard_::end(void) +{ + releaseAll(); + sendReport(); +} + + + int NKROKeyboard_::sendReport(void) { return HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &_keyReport, sizeof(_keyReport)); From a383389f345f41f699bce798da3ca17ce6cf97b6 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 17:16:07 -0800 Subject: [PATCH 375/602] Remove now-unused KeyboardAPI --- .../src/KeyboardCore/KeyboardAPI.h | 70 -------- .../src/KeyboardCore/KeyboardAPI.hpp | 167 ------------------ 2 files changed, 237 deletions(-) delete mode 100644 plugins/KeyboardioHID/src/KeyboardCore/KeyboardAPI.h delete mode 100644 plugins/KeyboardioHID/src/KeyboardCore/KeyboardAPI.hpp diff --git a/plugins/KeyboardioHID/src/KeyboardCore/KeyboardAPI.h b/plugins/KeyboardioHID/src/KeyboardCore/KeyboardAPI.h deleted file mode 100644 index 76e6866135..0000000000 --- a/plugins/KeyboardioHID/src/KeyboardCore/KeyboardAPI.h +++ /dev/null @@ -1,70 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 guard -#pragma once - -#include -#include "HID-Settings.h" -#include "ImprovedKeylayouts.h" - -// Keyboard Leds -enum KeyboardLeds : uint8_t { - LED_NUM_LOCK = (1 << 0), - LED_CAPS_LOCK = (1 << 1), - LED_SCROLL_LOCK = (1 << 2), - LED_COMPOSE = (1 << 3), - LED_KANA = (1 << 4), - LED_POWER = (1 << 5), - LED_SHIFT = (1 << 6), - LED_DO_NOT_DISTURB = (1 << 7), -}; - - -class KeyboardAPI : public Print -{ -public: - inline void begin(void); - inline void end(void); - - //press(uint8_t key, uint8_t modifier) TODO variadic template - - // Print API functions - inline virtual size_t write(uint8_t k) override; - inline size_t press(uint8_t k); - inline size_t release(uint8_t k); - inline size_t add(uint8_t k); - inline size_t remove(uint8_t k); - - // Needs to be implemented in a lower level - virtual size_t removeAll(void) = 0; - virtual int sendReport(void) = 0; - -private: - virtual size_t set(KeyboardKeycode k, bool s) = 0; - inline size_t set(uint8_t k, bool s); -}; - - -// Implementation is inline -#include "KeyboardAPI.hpp" diff --git a/plugins/KeyboardioHID/src/KeyboardCore/KeyboardAPI.hpp b/plugins/KeyboardioHID/src/KeyboardCore/KeyboardAPI.hpp deleted file mode 100644 index 8b51910ffa..0000000000 --- a/plugins/KeyboardioHID/src/KeyboardCore/KeyboardAPI.hpp +++ /dev/null @@ -1,167 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 guard -#pragma once - - -void KeyboardAPI::begin(void) -{ - // Force API to send a clean report. - // This is important for and HID bridge where the receiver stays on, - // while the sender is resetted. - send(); - releaseAll(); -} - - -void KeyboardAPI::end(void) -{ - releaseAll(); -} - - -size_t KeyboardAPI::write(KeyboardKeycode k) -{ - // Press and release key (if press was successfull) - auto ret = press(k); - if(ret){ - release(k); - } - return ret; -} - - -size_t KeyboardAPI::press(KeyboardKeycode k) -{ - // Press key and send report to host - auto ret = add(k); - if(ret){ - send(); - } - return ret; -} - - -size_t KeyboardAPI::release(KeyboardKeycode k) -{ - // Release key and send report to host - auto ret = remove(k); - if(ret){ - send(); - } - return ret; -} - - -size_t KeyboardAPI::add(KeyboardKeycode k) -{ - // Add key to report - return set(k, true); -} - - -size_t KeyboardAPI::remove(KeyboardKeycode k) -{ - // Remove key from report - return set(k, false); -} - - -size_t KeyboardAPI::releaseAll(void) -{ - // Release all keys - auto ret = removeAll(); - if(ret){ - send(); - } - return ret; -} - - -size_t KeyboardAPI::write(uint8_t k) -{ - // Press and release key (if press was successfull) - auto ret = press(k); - if(ret){ - release(k); - } - return ret; -} - - -size_t KeyboardAPI::press(uint8_t k) -{ - // Press key and send report to host - auto ret = add(k); - if(ret){ - send(); - } - return ret; -} - - -size_t KeyboardAPI::release(uint8_t k) -{ - // Release key and send report to host - auto ret = remove(k); - if(ret){ - send(); - } - return ret; -} - - -size_t KeyboardAPI::add(uint8_t k) -{ - // Add key to report - return set(k, true); -} - - -size_t KeyboardAPI::remove(uint8_t k) -{ - // Remove key from report - return set(k, false); -} - - -size_t KeyboardAPI::set(uint8_t k, bool s){ - // Ignore invalid input - if(k >= sizeof(_asciimap)){ - setWriteError(); - return 0; - } - - // Read key from ascii lookup table - k = pgm_read_byte(_asciimap + k); - auto ret = set(KeyboardKeycode(k & ~SHIFT), s); - - // Only add shift if keycode was successfully added before. - // Always try to release shift (if used). - if((k & SHIFT) && (ret || !s)){ - ret |= set(KEY_LEFT_SHIFT, s); - } - return ret; -} - From 4d22689bc66cdeada9a5754974932a974a01176a Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 17:17:42 -0800 Subject: [PATCH 376/602] split 'set' into 'press' and 'release' as separate functions --- .../src/MultiReport/NKROKeyboard.cpp | 49 +++++++++++++------ 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp index b99ef9cea3..81d73cea6e 100644 --- a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp @@ -91,17 +91,12 @@ int NKROKeyboard_::sendReport(void) return HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &_keyReport, sizeof(_keyReport)); } -size_t NKROKeyboard_::set(KeyboardKeycode k, bool s) +size_t NKROKeyboard_::press(KeyboardKeycode k) { // Press keymap key if (k < NKRO_KEY_COUNT){ uint8_t bit = 1 << (uint8_t(k) % 8); - if(s){ - _keyReport.keys[k / 8] |= bit; - } - else{ - _keyReport.keys[k / 8] &= ~bit; - } + _keyReport.keys[k / 8] |= bit; return 1; } @@ -110,12 +105,7 @@ size_t NKROKeyboard_::set(KeyboardKeycode k, bool s) { // Convert key into bitfield (0 - 7) k = KeyboardKeycode(uint8_t(k) - uint8_t(KEY_LEFT_CTRL)); - if(s){ - _keyReport.modifiers = (1 << k); - } - else{ - _keyReport.modifiers &= ~(1 << k); - } + _keyReport.modifiers = (1 << k); return 1; } @@ -126,13 +116,42 @@ size_t NKROKeyboard_::set(KeyboardKeycode k, bool s) auto key = _keyReport.key; // Is key already in the list or did we found an empty slot? - if (s && (key == uint8_t(k) || key == KEY_RESERVED)) { + if ((key == uint8_t(k) || key == KEY_RESERVED)) { _keyReport.key = k; return 1; } + } + + // No empty/pressed key was found + return 0; +} + +size_t NKROKeyboard_::release(KeyboardKeycode k) +{ + // Press keymap key + if (k < NKRO_KEY_COUNT){ + uint8_t bit = 1 << (uint8_t(k) % 8); + _keyReport.keys[k / 8] &= ~bit; + return 1; + } + + // It's a modifier key + else if(k >= KEY_LEFT_CTRL && k <= KEY_RIGHT_GUI) + { + // Convert key into bitfield (0 - 7) + k = KeyboardKeycode(uint8_t(k) - uint8_t(KEY_LEFT_CTRL)); + _keyReport.modifiers &= ~(1 << k); + return 1; + } + + // Its a custom key (outside our keymap) + else{ + // Add k to the key report only if it's not already present + // and if there is an empty slot. Remove the first available key. + auto key = _keyReport.key; // Test the key report to see if k is present. Clear it if it exists. - if (!s && (key == k)) { + if (key == k) { _keyReport.key = KEY_RESERVED; return 1; } From 91388c263c1f251ec830c5a32999a1f344a6113f Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 17:19:42 -0800 Subject: [PATCH 377/602] Remove dependence on outdated KeyboardCore class --- .../KeyboardioHID/src/MultiReport/NKROKeyboard.h | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h index 38a0abf033..b954d45e01 100644 --- a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h @@ -29,7 +29,7 @@ THE SOFTWARE. #include "HID.h" #include "HID-Settings.h" -#include "../KeyboardCore/KeyboardAPI.h" +#include "../KeyboardCore/HIDTables.h" // Max value for USB EP_SIZE 16 // +1 reportID, +1 modifier, +1 custom key @@ -50,13 +50,16 @@ typedef union{ -class NKROKeyboard_ : public KeyboardAPI +class NKROKeyboard_ { public: NKROKeyboard_(void); - // Implement adding/removing key functions - inline virtual size_t releaseAll(void) override; - + inline void begin(void); + inline void end(void); + + inline size_t press(uint8_t k); + inline size_t release(uint8_t k); + inline size_t releaseAll(void); virtual int sendReport(void) = 0; protected: HID_NKROKeyboardReport_Data_t _keyReport; From f693084cec411d96bfdd4b730d43dee1acfe2e28 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 17:22:18 -0800 Subject: [PATCH 378/602] Lift HIDTables out of now empty directory --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h | 2 +- plugins/KeyboardioHID/src/{KeyboardCore => }/HIDTables.h | 0 plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename plugins/KeyboardioHID/src/{KeyboardCore => }/HIDTables.h (100%) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index 904a60a259..af97bf0265 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -28,7 +28,7 @@ THE SOFTWARE. #include "PluggableUSB.h" #include "HID.h" #include "HID-Settings.h" -#include "../KeyboardCore/HIDTables.h" +#include "HIDTables.h" typedef union{ diff --git a/plugins/KeyboardioHID/src/KeyboardCore/HIDTables.h b/plugins/KeyboardioHID/src/HIDTables.h similarity index 100% rename from plugins/KeyboardioHID/src/KeyboardCore/HIDTables.h rename to plugins/KeyboardioHID/src/HIDTables.h diff --git a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h index b954d45e01..d97ff65245 100644 --- a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h @@ -29,7 +29,7 @@ THE SOFTWARE. #include "HID.h" #include "HID-Settings.h" -#include "../KeyboardCore/HIDTables.h" +#include "HIDTables.h" // Max value for USB EP_SIZE 16 // +1 reportID, +1 modifier, +1 custom key From 416f9db46404f52c43494cbc44ae89af3a7d86ab Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 17:23:08 -0800 Subject: [PATCH 379/602] Restore lost LED definition --- plugins/KeyboardioHID/src/HID-Project.h | 2 +- plugins/KeyboardioHID/src/LEDs.h | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 plugins/KeyboardioHID/src/LEDs.h diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index 92f920974b..00c1053ee8 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -36,7 +36,7 @@ THE SOFTWARE. #endif - +#include "LEDs.h" // Include all HID libraries (.a linkage required to work) properly diff --git a/plugins/KeyboardioHID/src/LEDs.h b/plugins/KeyboardioHID/src/LEDs.h new file mode 100644 index 0000000000..8cf81dc2a4 --- /dev/null +++ b/plugins/KeyboardioHID/src/LEDs.h @@ -0,0 +1,14 @@ +#pragma once + +// Keyboard Leds +enum KeyboardLeds : uint8_t { + LED_NUM_LOCK = (1 << 0), + LED_CAPS_LOCK = (1 << 1), + LED_SCROLL_LOCK = (1 << 2), + LED_COMPOSE = (1 << 3), + LED_KANA = (1 << 4), + LED_POWER = (1 << 5), + LED_SHIFT = (1 << 6), + LED_DO_NOT_DISTURB = (1 << 7), +}; + From a01781e1df7e09fa26a6a3f913229f576358d824 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 17:26:11 -0800 Subject: [PATCH 380/602] remove definition of obsolete API --- plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h index d97ff65245..0216535037 100644 --- a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h @@ -64,9 +64,6 @@ class NKROKeyboard_ protected: HID_NKROKeyboardReport_Data_t _keyReport; -private: - inline virtual size_t set(KeyboardKeycode k, bool s) override; - }; extern NKROKeyboard_ NKROKeyboard; From bb3fbaae1ddc882384c67d40a76cbe62531b6c17 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 17:34:49 -0800 Subject: [PATCH 381/602] Switch to new HID Table definitions of the modifier keys. --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp | 6 +++--- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h | 1 + plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp | 8 ++++---- plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h | 1 + 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 531fbd1a05..9a32206561 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -230,9 +230,9 @@ void BootKeyboard_::wakeupHost(void){ { uint8_t done = 0; - if ((k >= HID_KEYBOARD_LEFT_CONTROL) && (k <= HID_KEYBOARD_RIGHT_GUI)) { + if ((k >= HID_KEYBOARD_FIRST_MODIFIER) && (k <= HID_KEYBOARD_LAST_MODIFIER)) { // it's a modifier key - _keyReport.modifiers |= (0x01 << (k - HID_KEYBOARD_LEFT_CONTROL)); + _keyReport.modifiers |= (0x01 << (k - HID_KEYBOARD_FIRST_MODIFIER)); } else { // it's some other key: // Add k to the key report only if it's not already present @@ -271,7 +271,7 @@ bool BootKeyboard_::release(uint8_t k) uint8_t i; uint8_t count; - if ((k >= HID_KEYBOARD_LEFT_CONTROL) && (k <= HID_KEYBOARD_RIGHT_GUI)) { + if ((k >= HID_KEYBOARD_FIRST_MODIFIER) && (k <= HID_KEYBOARD_LAST_MODIFIER)) { // it's a modifier key _keyReport.modifiers = _keyReport.modifiers & (~(0x01 << (k - HID_KEYBOARD_LEFT_CONTROL))); } else { diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index af97bf0265..873b62b168 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -29,6 +29,7 @@ THE SOFTWARE. #include "HID.h" #include "HID-Settings.h" #include "HIDTables.h" +#include "HIDAliases.h" typedef union{ diff --git a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp index 81d73cea6e..0b0b949499 100644 --- a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp @@ -101,10 +101,10 @@ size_t NKROKeyboard_::press(KeyboardKeycode k) } // It's a modifier key - else if(k >= KEY_LEFT_CTRL && k <= KEY_RIGHT_GUI) + else if(k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { // Convert key into bitfield (0 - 7) - k = KeyboardKeycode(uint8_t(k) - uint8_t(KEY_LEFT_CTRL)); + k = uint8_t(k) - uint8_t(HID_KEYBOARD_FIRST_MODIFIER); _keyReport.modifiers = (1 << k); return 1; } @@ -136,10 +136,10 @@ size_t NKROKeyboard_::release(KeyboardKeycode k) } // It's a modifier key - else if(k >= KEY_LEFT_CTRL && k <= KEY_RIGHT_GUI) + else if(k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { // Convert key into bitfield (0 - 7) - k = KeyboardKeycode(uint8_t(k) - uint8_t(KEY_LEFT_CTRL)); + k = k - HID_KEYBOARD_FIRST_MODIFIER; _keyReport.modifiers &= ~(1 << k); return 1; } diff --git a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h index 0216535037..094f2ed58f 100644 --- a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h @@ -30,6 +30,7 @@ THE SOFTWARE. #include "HID-Settings.h" #include "HIDTables.h" +#include "HIDAliases.h" // Max value for USB EP_SIZE 16 // +1 reportID, +1 modifier, +1 custom key From f32bd436a76deed2b175419ef537cf64bba33909 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 17:35:27 -0800 Subject: [PATCH 382/602] further removal of KeyboardKeycode data type --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h | 2 +- plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index 873b62b168..55bd95421f 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -40,7 +40,7 @@ typedef union{ struct{ uint8_t modifiers; uint8_t reserved; - KeyboardKeycode keycodes[6]; + uint8_t keycodes[6]; }; uint8_t keys[8]; } HID_KeyboardReport_Data_t; diff --git a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp index 0b0b949499..126e16ae8a 100644 --- a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp @@ -91,7 +91,7 @@ int NKROKeyboard_::sendReport(void) return HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &_keyReport, sizeof(_keyReport)); } -size_t NKROKeyboard_::press(KeyboardKeycode k) +size_t NKROKeyboard_::press(uint8_t k) { // Press keymap key if (k < NKRO_KEY_COUNT){ From 6767110e2ef5a0f2b293f374460daf3d345a1522 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 17:35:41 -0800 Subject: [PATCH 383/602] Get rid of usages of KEY_RESERVED being overloaded as 'no key' --- plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp index 126e16ae8a..bfce4a22eb 100644 --- a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp @@ -116,7 +116,7 @@ size_t NKROKeyboard_::press(uint8_t k) auto key = _keyReport.key; // Is key already in the list or did we found an empty slot? - if ((key == uint8_t(k) || key == KEY_RESERVED)) { + if ((key == uint8_t(k) || key == 0x00)) { _keyReport.key = k; return 1; } @@ -152,7 +152,7 @@ size_t NKROKeyboard_::release(KeyboardKeycode k) // Test the key report to see if k is present. Clear it if it exists. if (key == k) { - _keyReport.key = KEY_RESERVED; + _keyReport.key = 0x00; return 1; } } From 164a19d4a3fb08e8c9b209b0196a2ca5df76dee4 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 17:36:47 -0800 Subject: [PATCH 384/602] Add a new header file for convenient alternate HID table points with "nontraditional" names --- plugins/KeyboardioHID/src/HIDAliases.h | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 plugins/KeyboardioHID/src/HIDAliases.h diff --git a/plugins/KeyboardioHID/src/HIDAliases.h b/plugins/KeyboardioHID/src/HIDAliases.h new file mode 100644 index 0000000000..35b66795a3 --- /dev/null +++ b/plugins/KeyboardioHID/src/HIDAliases.h @@ -0,0 +1,6 @@ +#pragma once + +#include "HIDTables.h" + +#define HID_KEYBOARD_FIRST_MODIFIER HID_KEYBOARD_LEFT_CONTROL +#define HID_KEYBOARD_LAST_MODIFIER HID_KEYBOARD_RIGHT_CONTROL \ No newline at end of file From 845b0a7e311fbcce78aba7bb0bc4b8f9b74460f5 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 17:45:27 -0800 Subject: [PATCH 385/602] In a stunning display of usefulness, this recently added abstraction let me fix a bug in five places with a one line change. --- plugins/KeyboardioHID/src/HIDAliases.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/HIDAliases.h b/plugins/KeyboardioHID/src/HIDAliases.h index 35b66795a3..dbc0e79917 100644 --- a/plugins/KeyboardioHID/src/HIDAliases.h +++ b/plugins/KeyboardioHID/src/HIDAliases.h @@ -3,4 +3,4 @@ #include "HIDTables.h" #define HID_KEYBOARD_FIRST_MODIFIER HID_KEYBOARD_LEFT_CONTROL -#define HID_KEYBOARD_LAST_MODIFIER HID_KEYBOARD_RIGHT_CONTROL \ No newline at end of file +#define HID_KEYBOARD_LAST_MODIFIER HID_KEYBOARD_RIGHT_GUI \ No newline at end of file From b4ee301f7021e62538b1ad64203a6623b6599808 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 17:46:13 -0800 Subject: [PATCH 386/602] Fix the multiple-inclusion guard --- plugins/KeyboardioHID/src/HIDTables.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/HIDTables.h b/plugins/KeyboardioHID/src/HIDTables.h index 8092e1fbf8..b929869783 100644 --- a/plugins/KeyboardioHID/src/HIDTables.h +++ b/plugins/KeyboardioHID/src/HIDTables.h @@ -1,5 +1,5 @@ #ifndef __HIDTables__ -#define HID___HIDTables__ +#define __HIDTables__ // These mappings were extracted and transcribed from From efbf89e48914274e36c37c0401025255bb9e8473 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 17:46:43 -0800 Subject: [PATCH 387/602] Fix cut and paste errors discovered when testing refactored code --- plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h | 3 +-- plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.h | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h index 1be3d765eb..772a52d60d 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h @@ -59,7 +59,6 @@ class AbsoluteMouse_ AbsoluteMouse_(void); protected: - virtual inline void SendReport(void* data, int length) override; int16_t xAxis; int16_t yAxis; uint8_t _buttons; @@ -80,7 +79,7 @@ class AbsoluteMouse_ inline bool isPressed(uint8_t b = MOUSE_LEFT); // Sending is public in the base class for advanced users. - virtual void SendReport(void* data, int length) = 0; + inline void SendReport(void* data, int length); diff --git a/plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.h b/plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.h index fca4925ae8..0ed46b6992 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.h @@ -64,8 +64,7 @@ class Mouse_ inline void release(uint8_t b = MOUSE_LEFT); // release LEFT by default inline bool isPressed(uint8_t b = MOUSE_LEFT); // check LEFT by default - // Sending is public in the base class for advanced users. - virtual void SendReport(void* data, int length) = 0; + inline void SendReport(void* data, int length); protected: uint8_t _buttons; From 82e33cd79ca3fab336329ace19732401088fe07d Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 17:49:17 -0800 Subject: [PATCH 388/602] Fix another cut and paste error from the great reflattening of the code --- .../src/MultiReport/AbsoluteMouse.h | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h index 772a52d60d..8c71fca8c5 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h @@ -55,17 +55,6 @@ typedef union{ class AbsoluteMouse_ { -public: - AbsoluteMouse_(void); - -protected: - int16_t xAxis; - int16_t yAxis; - uint8_t _buttons; - inline void buttons(uint8_t b); - - inline int16_t qadd16(int16_t base, int16_t increment); - public: AbsoluteMouse_(void); inline void begin(void); @@ -81,6 +70,14 @@ class AbsoluteMouse_ // Sending is public in the base class for advanced users. inline void SendReport(void* data, int length); +protected: + int16_t xAxis; + int16_t yAxis; + uint8_t _buttons; + inline void buttons(uint8_t b); + + inline int16_t qadd16(int16_t base, int16_t increment); + }; From 4e07c5a3beb4b8fab05dbbfb04a1eee0f2fe2d05 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 17:55:30 -0800 Subject: [PATCH 389/602] Port Consumer Control implementation to using raw keycodes as uint16_ts --- .../src/MultiReport/Consumer.cpp | 10 +- .../KeyboardioHID/src/MultiReport/Consumer.h | 437 +----------------- 2 files changed, 13 insertions(+), 434 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/Consumer.cpp b/plugins/KeyboardioHID/src/MultiReport/Consumer.cpp index addafbda27..645ea88721 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Consumer.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Consumer.cpp @@ -57,15 +57,15 @@ void Consumer_::end(void) { SendReport(&_report, sizeof(_report)); } -void Consumer_::write(ConsumerKeycode m) { +void Consumer_::write(uint16_t m) { press(m); release(m); } -void Consumer_::press(ConsumerKeycode m) { +void Consumer_::press(uint16_t m) { // search for a free spot for (uint8_t i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { - if (_report.keys[i] == HID_CONSUMER_UNASSIGNED) { + if (_report.keys[i] == 0x00) { _report.keys[i] = m; break; } @@ -73,11 +73,11 @@ void Consumer_::press(ConsumerKeycode m) { SendReport(&_report, sizeof(_report)); } -void Consumer_::release(ConsumerKeycode m) { +void Consumer_::release(uint16_t m) { // search and release the keypress for (uint8_t i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { if (_report.keys[i] == m) { - _report.keys[i] = HID_CONSUMER_UNASSIGNED; + _report.keys[i] = 0x00; // no break to delete multiple keys } } diff --git a/plugins/KeyboardioHID/src/MultiReport/Consumer.h b/plugins/KeyboardioHID/src/MultiReport/Consumer.h index fefc06d9e5..c6e9ec405a 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Consumer.h +++ b/plugins/KeyboardioHID/src/MultiReport/Consumer.h @@ -29,438 +29,17 @@ THE SOFTWARE. #include "HID.h" #include "HID-Settings.h" -enum ConsumerKeycode : uint16_t { - // Some keys might only work with linux - CONSUMER_POWER = 0x30, - CONSUMER_SLEEP = 0x32, - - MEDIA_RECORD = 0xB2, - MEDIA_FAST_FORWARD = 0xB3, - MEDIA_REWIND = 0xB4, - MEDIA_NEXT = 0xB5, - MEDIA_PREVIOUS = 0xB6, - MEDIA_PREV = 0xB6, // Alias - MEDIA_STOP = 0xB7, - MEDIA_PLAY_PAUSE = 0xCD, - MEDIA_PAUSE = 0xB0, - - MEDIA_VOLUME_MUTE = 0xE2, - MEDIA_VOL_MUTE = 0xE2, // Alias - MEDIA_VOLUME_UP = 0xE9, - MEDIA_VOL_UP = 0xE9, // Alias - MEDIA_VOLUME_DOWN = 0xEA, - MEDIA_VOL_DOWN = 0xEA, // Alias - - CONSUMER_SCREENSAVER = 0x19e, - - CONSUMER_PROGRAMMABLE_BUTTON_CONFIGURATION = 0x182, - CONSUMER_CONTROL_CONFIGURATION = 0x183, - CONSUMER_EMAIL_READER = 0x18A, - CONSUMER_CALCULATOR = 0x192, - CONSUMER_EXPLORER = 0x194, - - CONSUMER_BROWSER_HOME = 0x223, - CONSUMER_BROWSER_BACK = 0x224, - CONSUMER_BROWSER_FORWARD = 0x225, - CONSUMER_BROWSER_REFRESH = 0x227, - CONSUMER_BROWSER_BOOKMARKS = 0x22A, - - - // Consumer_Page_(0x0C) 0x15 - HID_CONSUMER_UNASSIGNED = 0x00, - HID_CONSUMER_NUMERIC_KEY_PAD = 0x02, // HID type NARY - HID_CONSUMER_PROGRAMMABLE_BUTTONS = 0x03, // HID type NARY - HID_CONSUMER_MICROPHONE_CA = 0x04, - HID_CONSUMER_HEADPHONE_CA = 0x05, - HID_CONSUMER_GRAPHIC_EQUALIZER_CA = 0x06, - // Reserved = 0x07-1F - HID_CONSUMER_PLUS_10 = 0x20, // HID type OSC - HID_CONSUMER_PLUS_100 = 0x21, // HID type OSC - HID_CONSUMER_AM_SLASH_PM = 0x22, // HID type OSC - // Reserved = 0x23-3F - HID_CONSUMER_POWER = 0x30, // HID type OOC - HID_CONSUMER_RESET = 0x31, // HID type OSC - HID_CONSUMER_SLEEP = 0x32, // HID type OSC - HID_CONSUMER_SLEEP_AFTER = 0x33, // HID type OSC - HID_CONSUMER_SLEEP_MODE = 0x34, // HID type RTC - HID_CONSUMER_ILLUMINATION = 0x35, // HID type OOC - HID_CONSUMER_FUNCTION_BUTTONS = 0x36, // HID type NARY - // Reserved = 0x37-3F - HID_CONSUMER_MENU = 0x40, // HID type OOC - HID_CONSUMER_MENU_PICK = 0x41, // HID type OSC - HID_CONSUMER_MENU_UP = 0x42, // HID type OSC - HID_CONSUMER_MENU_DOWN = 0x43, // HID type OSC - HID_CONSUMER_MENU_LEFT = 0x44, // HID type OSC - HID_CONSUMER_MENU_RIGHT = 0x45, // HID type OSC - HID_CONSUMER_MENU_ESCAPE = 0x46, // HID type OSC - HID_CONSUMER_MENU_VALUE_INCREASE = 0x47, // HID type OSC - HID_CONSUMER_MENU_VALUE_DECREASE = 0x48, // HID type OSC - // Reserved 0x49-5F - HID_CONSUMER_DATA_ON_SCREEN = 0x60, // HID type OOC - HID_CONSUMER_CLOSED_CAPTION = 0x61, // HID type OOC - HID_CONSUMER_CLOSED_CAPTION_SELECT = 0x62, // HID type OSC - HID_CONSUMER_VCR_SLASH_TV = 0x63, // HID type OOC - HID_CONSUMER_BROADCAST_MODE = 0x64, // HID type OSC - HID_CONSUMER_SNAPSHOT = 0x65, // HID type OSC - HID_CONSUMER_STILL = 0x66, // HID type OSC - // Reserved 0x67-7F - HID_CONSUMER_SELECTION = 0x80, // HID type NARY - HID_CONSUMER_ASSIGN_SELECTION = 0x81, // HID type OSC - HID_CONSUMER_MODE_STEP = 0x82, // HID type OSC - HID_CONSUMER_RECALL_LAST = 0x83, // HID type OSC - HID_CONSUMER_ENTER_CHANNEL = 0x84, // HID type OSC - HID_CONSUMER_ORDER_MOVIE = 0x85, // HID type OSC - HID_CONSUMER_CHANNEL = 0x86, // HID type LC - HID_CONSUMER_MEDIA_SELECTION = 0x87, // HID type NARY - HID_CONSUMER_MEDIA_SELECT_COMPUTER = 0x88, // HID type SEL - HID_CONSUMER_MEDIA_SELECT_TV = 0x89, // HID type SEL - HID_CONSUMER_MEDIA_SELECT_WWW = 0x8A, // HID type SEL - HID_CONSUMER_MEDIA_SELECT_DVD = 0x8B, // HID type SEL - HID_CONSUMER_MEDIA_SELECT_TELEPHONE = 0x8C, // HID type SEL - HID_CONSUMER_MEDIA_SELECT_PROGRAM_GUIDE = 0x8D, // HID type SEL - HID_CONSUMER_MEDIA_SELECT_VIDEO_PHONE = 0x8E, // HID type SEL - HID_CONSUMER_MEDIA_SELECT_GAMES = 0x8F, // HID type SEL - HID_CONSUMER_MEDIA_SELECT_MESSAGES = 0x90, // HID type SEL - HID_CONSUMER_MEDIA_SELECT_CD = 0x91, // HID type SEL - HID_CONSUMER_MEDIA_SELECT_VCR = 0x92, // HID type SEL - HID_CONSUMER_MEDIA_SELECT_TUNER = 0x93, // HID type SEL - HID_CONSUMER_QUIT = 0x94, // HID type OSC - HID_CONSUMER_HELP = 0x95, // HID type OOC - HID_CONSUMER_MEDIA_SELECT_TAPE = 0x96, // HID type SEL - HID_CONSUMER_MEDIA_SELECT_CABLE = 0x97, // HID type SEL - HID_CONSUMER_MEDIA_SELECT_SATELLITE = 0x98, // HID type SEL - HID_CONSUMER_MEDIA_SELECT_SECURITY = 0x99, // HID type SEL - HID_CONSUMER_MEDIA_SELECT_HOME = 0x9A, // HID type SEL - HID_CONSUMER_MEDIA_SELECT_CALL = 0x9B, // HID type SEL - HID_CONSUMER_CHANNEL_INCREMENT = 0x9C, // HID type OSC - HID_CONSUMER_CHANNEL_DECREMENT = 0x9D, // HID type OSC - HID_CONSUMER_MEDIA_SELECT_SAP = 0x9E, // HID type SEL - // Reserved 0x9F - HID_CONSUMER_VCR_PLUS = 0xA0, // HID type OSC - HID_CONSUMER_ONCE = 0xA1, // HID type OSC - HID_CONSUMER_DAILY = 0xA2, // HID type OSC - HID_CONSUMER_WEEKLY = 0xA3, // HID type OSC - HID_CONSUMER_MONTHLY = 0xA4, // HID type OSC - // Reserved 0xA5-AF - HID_CONSUMER_PLAY = 0xB0, // HID type OOC - HID_CONSUMER_PAUSE = 0xB1, // HID type OOC - HID_CONSUMER_RECORD = 0xB2, // HID type OOC - HID_CONSUMER_FAST_FORWARD = 0xB3, // HID type OOC - HID_CONSUMER_REWIND = 0xB4, // HID type OOC - HID_CONSUMER_SCAN_NEXT_TRACK = 0xB5, // HID type OSC - HID_CONSUMER_SCAN_PREVIOUS_TRACK = 0xB6, // HID type OSC - HID_CONSUMER_STOP = 0xB7, // HID type OSC - HID_CONSUMER_EJECT = 0xB8, // HID type OSC - HID_CONSUMER_RANDOM_PLAY = 0xB9, // HID type OOC - HID_CONSUMER_SELECT_DISC = 0xBA, // HID type NARY - HID_CONSUMER_ENTER_DISC_MC = 0xBB, - HID_CONSUMER_REPEAT = 0xBC, // HID type OSC - HID_CONSUMER_TRACKING = 0xBD, // HID type LC - HID_CONSUMER_TRACK_NORMAL = 0xBE, // HID type OSC - HID_CONSUMER_SLOW_TRACKING = 0xBF, // HID type LC - HID_CONSUMER_FRAME_FORWARD = 0xC0, // HID type RTC - HID_CONSUMER_FRAME_BACK = 0xC1, // HID type RTC - HID_CONSUMER_MARK = 0xC2, // HID type OSC - HID_CONSUMER_CLEAR_MARK = 0xC3, // HID type OSC - HID_CONSUMER_REPEAT_FROM_MARK = 0xC4, // HID type OOC - HID_CONSUMER_RETURN_TO_MARK = 0xC5, // HID type OSC - HID_CONSUMER_SEARCH_MARK_FORWARD = 0xC6, // HID type OSC - HID_CONSUMER_SEARCH_MARK_BACKWARDS = 0xC7, // HID type OSC - HID_CONSUMER_COUNTER_RESET = 0xC8, // HID type OSC - HID_CONSUMER_SHOW_COUNTER = 0xC9, // HID type OSC - HID_CONSUMER_TRACKING_INCREMENT = 0xCA, // HID type RTC - HID_CONSUMER_TRACKING_DECREMENT = 0xCB, // HID type RTC - HID_CONSUMER_STOP_SLASH_EJECT = 0xCC, // HID type OSC - HID_CONSUMER_PLAY_SLASH_PAUSE = 0xCD, // HID type OSC - HID_CONSUMER_PLAY_SLASH_SKIP = 0xCE, // HID type OSC - // Reserved 0xCF-DF - HID_CONSUMER_VOLUME = 0xE0, // HID type LC - HID_CONSUMER_BALANCE = 0xE1, // HID type LC - HID_CONSUMER_MUTE = 0xE2, // HID type OOC - HID_CONSUMER_BASS = 0xE3, // HID type LC - HID_CONSUMER_TREBLE = 0xE4, // HID type LC - HID_CONSUMER_BASS_BOOST = 0xE5, // HID type OOC - HID_CONSUMER_SURROUND_MODE = 0xE6, // HID type OSC - HID_CONSUMER_LOUDNESS = 0xE7, // HID type OOC - HID_CONSUMER_MPX = 0xE8, // HID type OOC - HID_CONSUMER_VOLUME_INCREMENT = 0xE9, // HID type RTC - HID_CONSUMER_VOLUME_DECREMENT = 0xEA, // HID type RTC - // Reserved 0xEB-EF - HID_CONSUMER_SPEED_SELECT = 0xF0, // HID type OSC - HID_CONSUMER_PLAYBACK_SPEED = 0xF1, // HID type NARY - HID_CONSUMER_STANDARD_PLAY = 0xF2, // HID type SEL - HID_CONSUMER_LONG_PLAY = 0xF3, // HID type SEL - HID_CONSUMER_EXTENDED_PLAY = 0xF4, // HID type SEL - HID_CONSUMER_SLOW = 0xF5, // HID type OSC - // Reserved 0xF6-FF - HID_CONSUMER_FAN_ENABLE = 0x100, // HID type OOC - HID_CONSUMER_FAN_SPEED = 0x101, // HID type LC - HID_CONSUMER_LIGHT_ENABLE = 0x102, // HID type OOC - HID_CONSUMER_LIGHT_ILLUMINATION_LEVEL = 0x103, // HID type LC - HID_CONSUMER_CLIMATE_CONTROL_ENABLE = 0x104, // HID type OOC - HID_CONSUMER_ROOM_TEMPERATURE = 0x105, // HID type LC - HID_CONSUMER_SECURITY_ENABLE = 0x106, // HID type OOC - HID_CONSUMER_FIRE_ALARM = 0x107, // HID type OSC - HID_CONSUMER_POLICE_ALARM = 0x108, // HID type OSC - HID_CONSUMER_PROXIMITY = 0x109, // HID type LC - HID_CONSUMER_MOTION = 0x10A, // HID type OSC - HID_CONSUMER_DURESS_ALARM = 0x10B, // HID type OSC - HID_CONSUMER_HOLDUP_ALARM = 0x10C, // HID type OSC - HID_CONSUMER_MEDICAL_ALARM = 0x10D, // HID type OSC - // Reserved 0x10E-14F - HID_CONSUMER_BALANCE_RIGHT = 0x150, // HID type RTC - HID_CONSUMER_BALANCE_LEFT = 0x151, // HID type RTC - HID_CONSUMER_BASS_INCREMENT = 0x152, // HID type RTC - HID_CONSUMER_BASS_DECREMENT = 0x153, // HID type RTC - HID_CONSUMER_TREBLE_INCREMENT = 0x154, // HID type RTC - HID_CONSUMER_TREBLE_DECREMENT = 0x155, // HID type RTC - // Reserved 0x156-15F - HID_CONSUMER_SPEAKER_SYSTEM = 0x160, // HID type CL - HID_CONSUMER_CHANNEL_LEFT = 0x161, // HID type CL - HID_CONSUMER_CHANNEL_RIGHT = 0x162, // HID type CL - HID_CONSUMER_CHANNEL_CENTER = 0x163, // HID type CL - HID_CONSUMER_CHANNEL_FRONT = 0x164, // HID type CL - HID_CONSUMER_CHANNEL_CENTER_FRONT = 0x165, // HID type CL - HID_CONSUMER_CHANNEL_SIDE = 0x166, // HID type CL - HID_CONSUMER_CHANNEL_SURROUND = 0x167, // HID type CL - HID_CONSUMER_CHANNEL_LOW_FREQUENCY_ENHANCEMENT = 0x168, // HID type CL - HID_CONSUMER_CHANNEL_TOP = 0x169, // HID type CL - HID_CONSUMER_CHANNEL_UNKNOWN = 0x16A, // HID type CL - // Reserved 0x16B-16F - HID_CONSUMER_SUB_CHANNEL = 0x170, // HID type LC - HID_CONSUMER_SUB_CHANNEL_INCREMENT = 0x171, // HID type OSC - HID_CONSUMER_SUB_CHANNEL_DECREMENT = 0x172, // HID type OSC - HID_CONSUMER_ALTERNATE_AUDIO_INCREMENT = 0x173, // HID type OSC - HID_CONSUMER_ALTERNATE_AUDIO_DECREMENT = 0x174, // HID type OSC - // Reserved 0x175-17F - HID_CONSUMER_APPLICATION_LAUNCH_BUTTONS = 0x180, // HID type NARY - HID_CONSUMER_AL_LAUNCH_BUTTON_CONFIGURATION_TOOL = 0x181, // HID type SEL - HID_CONSUMER_AL_PROGRAMMABLE_BUTTON_CONFIGURATION = 0x182, // HID type SEL - HID_CONSUMER_AL_CONSUMER_CONTROL_CONFIGURATION = 0x183, // HID type SEL - HID_CONSUMER_AL_WORD_PROCESSOR = 0x184, // HID type SEL - HID_CONSUMER_AL_TEXT_EDITOR = 0x185, // HID type SEL - HID_CONSUMER_AL_SPREADSHEET = 0x186, // HID type SEL - HID_CONSUMER_AL_GRAPHICS_EDITOR = 0x187, // HID type SEL - HID_CONSUMER_AL_PRESENTATION_APP = 0x188, // HID type SEL - HID_CONSUMER_AL_DATABASE_APP = 0x189, // HID type SEL - HID_CONSUMER_AL_EMAIL_READER = 0x18A, // HID type SEL - HID_CONSUMER_AL_NEWSREADER = 0x18B, // HID type SEL - HID_CONSUMER_AL_VOICEMAIL = 0x18C, // HID type SEL - HID_CONSUMER_AL_CONTACTS_SLASH_ADDRESS_BOOK = 0x18D, // HID type SEL - HID_CONSUMER_AL_CALENDAR_SLASH_SCHEDULE = 0x18E, // HID type SEL - HID_CONSUMER_AL_TASK_SLASH_PROJECT_MANAGER = 0x18F, // HID type SEL - HID_CONSUMER_AL_LOG_SLASH_JOURNAL_SLASH_TIMECARD = 0x190, // HID type SEL - HID_CONSUMER_AL_CHECKBOOK_SLASH_FINANCE = 0x191, // HID type SEL - HID_CONSUMER_AL_CALCULATOR = 0x192, // HID type SEL - HID_CONSUMER_AL_A_SLASH_V_CAPTURE_SLASH_PLAYBACK = 0x193, // HID type SEL - HID_CONSUMER_AL_LOCAL_MACHINE_BROWSER = 0x194, // HID type SEL - HID_CONSUMER_AL_LAN_SLASH_WAN_BROWSER = 0x195, // HID type SEL - HID_CONSUMER_AL_INTERNET_BROWSER = 0x196, // HID type SEL - HID_CONSUMER_AL_REMOTE_NETWORKING_SLASH_ISP_CONNECT = 0x197, // HID type SEL - HID_CONSUMER_AL_NETWORK_CONFERENCE = 0x198, // HID type SEL - HID_CONSUMER_AL_NETWORK_CHAT = 0x199, // HID type SEL - HID_CONSUMER_AL_TELEPHONY_SLASH_DIALER = 0x19A, // HID type SEL - HID_CONSUMER_AL_LOGON = 0x19B, // HID type SEL - HID_CONSUMER_AL_LOGOFF = 0x19C, // HID type SEL - HID_CONSUMER_AL_LOGON_SLASH_LOGOFF = 0x19D, // HID type SEL - HID_CONSUMER_AL_TERMINAL_LOCK_SLASH_SCREENSAVER = 0x19E, // HID type SEL - HID_CONSUMER_AL_CONTROL_PANEL = 0x19F, // HID type SEL - HID_CONSUMER_AL_COMMAND_LINE_PROCESSOR_SLASH_RUN = 0x1A0, // HID type SEL - HID_CONSUMER_AL_PROCESS_SLASH_TASK_MANAGER = 0x1A1, // HID type SEL - HID_CONSUMER_AL_SELECT_TASK_SLASH_APPLICATION = 0x1A2, // HID type SEL - HID_CONSUMER_AL_NEXT_TASK_SLASH_APPLICATION = 0x1A3, // HID type SEL - HID_CONSUMER_AL_PREVIOUS_TASK_SLASH_APPLICATION = 0x1A4, // HID type SEL - HID_CONSUMER_AL_PREEMPTIVE_HALT_TASK_SLASH_APPLICATION = 0x1A5, // HID type SEL - HID_CONSUMER_AL_INTEGRATED_HELP_CENTER = 0x1A6, // HID type SEL - HID_CONSUMER_AL_DOCUMENTS = 0x1A7, // HID type SEL - HID_CONSUMER_AL_THESAURUS = 0x1A8, // HID type SEL - HID_CONSUMER_AL_DICTIONARY = 0x1A9, // HID type SEL - HID_CONSUMER_AL_DESKTOP = 0x1AA, // HID type SEL - HID_CONSUMER_AL_SPELL_CHECK = 0x1AB, // HID type SEL - HID_CONSUMER_AL_GRAMMAR_CHECK = 0x1AC, // HID type SEL - HID_CONSUMER_AL_WIRELESS_STATUS = 0x1AD, // HID type SEL - HID_CONSUMER_AL_KEYBOARD_LAYOUT = 0x1AE, // HID type SEL - HID_CONSUMER_AL_VIRUS_PROTECTION = 0x1AF, // HID type SEL - HID_CONSUMER_AL_ENCRYPTION = 0x1B0, // HID type SEL - HID_CONSUMER_AL_SCREEN_SAVER = 0x1B1, // HID type SEL - HID_CONSUMER_AL_ALARMS = 0x1B2, // HID type SEL - HID_CONSUMER_AL_CLOCK = 0x1B3, // HID type SEL - HID_CONSUMER_AL_FILE_BROWSER = 0x1B4, // HID type SEL - HID_CONSUMER_AL_POWER_STATUS = 0x1B5, // HID type SEL - HID_CONSUMER_AL_IMAGE_BROWSER = 0x1B6, // HID type SEL - HID_CONSUMER_AL_AUDIO_BROWSER = 0x1B7, // HID type SEL - HID_CONSUMER_AL_MOVIE_BROWSER = 0x1B8, // HID type SEL - HID_CONSUMER_AL_DIGITAL_RIGHTS_MANAGER = 0x1B9, // HID type SEL - HID_CONSUMER_AL_DIGITAL_WALLET = 0x1BA, // HID type SEL - // _Reserved 0x1BB - HID_CONSUMER_AL_INSTANT_MESSAGING = 0x1BC, // HID type SEL - HID_CONSUMER_AL_OEM_FEATURES_SLASH__TIPS_SLASH_TUTORIAL_BROWSER = 0x1BD, // HID type SEL - HID_CONSUMER_AL_OEM_HELP = 0x1BE, // HID type SEL - HID_CONSUMER_AL_ONLINE_COMMUNITY = 0x1BF, // HID type SEL - HID_CONSUMER_AL_ENTERTAINMENT_CONTENT_BROWSER = 0x1C0, // HID type SEL - HID_CONSUMER_AL_ONLINE_SHOPPING_BROWSER = 0x1C1, // HID type SEL - HID_CONSUMER_AL_SMARTCARD_INFORMATION_SLASH_HELP = 0x1C2, // HID type SEL - HID_CONSUMER_AL_MARKET_MONITOR_SLASH_FINANCE_BROWSER = 0x1C3, // HID type SEL - HID_CONSUMER_AL_CUSTOMIZED_CORPORATE_NEWS_BROWSER = 0x1C4, // HID type SEL - HID_CONSUMER_AL_ONLINE_ACTIVITY_BROWSER = 0x1C5, // HID type SEL - HID_CONSUMER_AL_RESEARCH_SLASH_SEARCH_BROWSER = 0x1C6, // HID type SEL - HID_CONSUMER_AL_AUDIO_PLAYER = 0x1C7, // HID type SEL - // Reserved 0x1C8-1FF - HID_CONSUMER_GENERIC_GUI_APPLICATION_CONTROLS = 0x200, // HID type NARY - HID_CONSUMER_AC_NEW = 0x201, // HID type SEL - HID_CONSUMER_AC_OPEN = 0x202, // HID type SEL - HID_CONSUMER_AC_CLOSE = 0x203, // HID type SEL - HID_CONSUMER_AC_EXIT = 0x204, // HID type SEL - HID_CONSUMER_AC_MAXIMIZE = 0x205, // HID type SEL - HID_CONSUMER_AC_MINIMIZE = 0x206, // HID type SEL - HID_CONSUMER_AC_SAVE = 0x207, // HID type SEL - HID_CONSUMER_AC_PRINT = 0x208, // HID type SEL - HID_CONSUMER_AC_PROPERTIES = 0x209, // HID type SEL - HID_CONSUMER_AC_UNDO = 0x21A, // HID type SEL - HID_CONSUMER_AC_COPY = 0x21B, // HID type SEL - HID_CONSUMER_AC_CUT = 0x21C, // HID type SEL - HID_CONSUMER_AC_PASTE = 0x21D, // HID type SEL - HID_CONSUMER_AC_SELECT_ALL = 0x21E, // HID type SEL - HID_CONSUMER_AC_FIND = 0x21F, // HID type SEL - HID_CONSUMER_AC_FIND_AND_REPLACE = 0x220, // HID type SEL - HID_CONSUMER_AC_SEARCH = 0x221, // HID type SEL - HID_CONSUMER_AC_GO_TO = 0x222, // HID type SEL - HID_CONSUMER_AC_HOME = 0x223, // HID type SEL - HID_CONSUMER_AC_BACK = 0x224, // HID type SEL - HID_CONSUMER_AC_FORWARD = 0x225, // HID type SEL - HID_CONSUMER_AC_STOP = 0x226, // HID type SEL - HID_CONSUMER_AC_REFRESH = 0x227, // HID type SEL - HID_CONSUMER_AC_PREVIOUS_LINK = 0x228, // HID type SEL - HID_CONSUMER_AC_NEXT_LINK = 0x229, // HID type SEL - HID_CONSUMER_AC_BOOKMARKS = 0x22A, // HID type SEL - HID_CONSUMER_AC_HISTORY = 0x22B, // HID type SEL - HID_CONSUMER_AC_SUBSCRIPTIONS = 0x22C, // HID type SEL - HID_CONSUMER_AC_ZOOM_IN = 0x22D, // HID type SEL - HID_CONSUMER_AC_ZOOM_OUT = 0x22E, // HID type SEL - HID_CONSUMER_AC_ZOOM = 0x22F, // HID type LC - HID_CONSUMER_AC_FULL_SCREEN_VIEW = 0x230, // HID type SEL - HID_CONSUMER_AC_NORMAL_VIEW = 0x231, // HID type SEL - HID_CONSUMER_AC_VIEW_TOGGLE = 0x232, // HID type SEL - HID_CONSUMER_AC_SCROLL_UP = 0x233, // HID type SEL - HID_CONSUMER_AC_SCROLL_DOWN = 0x234, // HID type SEL - HID_CONSUMER_AC_SCROLL = 0x235, // HID type LC - HID_CONSUMER_AC_PAN_LEFT = 0x236, // HID type SEL - HID_CONSUMER_AC_PAN_RIGHT = 0x237, // HID type SEL - HID_CONSUMER_AC_PAN = 0x238, // HID type LC - HID_CONSUMER_AC_NEW_WINDOW = 0x239, // HID type SEL - HID_CONSUMER_AC_TILE_HORIZONTALLY = 0x23A, // HID type SEL - HID_CONSUMER_AC_TILE_VERTICALLY = 0x23B, // HID type SEL - HID_CONSUMER_AC_FORMAT = 0x23C, // HID type SEL - HID_CONSUMER_AC_EDIT = 0x23D, // HID type SEL - HID_CONSUMER_AC_BOLD = 0x23E, // HID type SEL - HID_CONSUMER_AC_ITALICS = 0x23F, // HID type SEL - HID_CONSUMER_AC_UNDERLINE = 0x240, // HID type SEL - HID_CONSUMER_AC_STRIKETHROUGH = 0x241, // HID type SEL - HID_CONSUMER_AC_SUBSCRIPT = 0x242, // HID type SEL - HID_CONSUMER_AC_SUPERSCRIPT = 0x243, // HID type SEL - HID_CONSUMER_AC_ALL_CAPS = 0x244, // HID type SEL - HID_CONSUMER_AC_ROTATE = 0x245, // HID type SEL - HID_CONSUMER_AC_RESIZE = 0x246, // HID type SEL - HID_CONSUMER_AC_FLIP_HORIZONTAL = 0x247, // HID type SEL - HID_CONSUMER_AC_FLIP_VERTICAL = 0x248, // HID type SEL - HID_CONSUMER_AC_MIRROR_HORIZONTAL = 0x249, // HID type SEL - HID_CONSUMER_AC_MIRROR_VERTICAL = 0x24A, // HID type SEL - HID_CONSUMER_AC_FONT_SELECT = 0x24B, // HID type SEL - HID_CONSUMER_AC_FONT_COLOR = 0x24C, // HID type SEL - HID_CONSUMER_AC_FONT_SIZE = 0x24D, // HID type SEL - HID_CONSUMER_AC_JUSTIFY_LEFT = 0x24E, // HID type SEL - HID_CONSUMER_AC_JUSTIFY_CENTER_H = 0x24F, // HID type SEL - HID_CONSUMER_AC_JUSTIFY_RIGHT = 0x250, // HID type SEL - HID_CONSUMER_AC_JUSTIFY_BLOCK_H = 0x251, // HID type SEL - HID_CONSUMER_AC_JUSTIFY_TOP = 0x252, // HID type SEL - HID_CONSUMER_AC_JUSTIFY_CENTER_V = 0x253, // HID type SEL - HID_CONSUMER_AC_JUSTIFY_BOTTOM = 0x254, // HID type SEL - HID_CONSUMER_AC_JUSTIFY_BLOCK_V = 0x255, // HID type SEL - HID_CONSUMER_AC_INDENT_DECREASE = 0x256, // HID type SEL - HID_CONSUMER_AC_INDENT_INCREASE = 0x257, // HID type SEL - HID_CONSUMER_AC_NUMBERED_LIST = 0x258, // HID type SEL - HID_CONSUMER_AC_RESTART_NUMBERING = 0x259, // HID type SEL - HID_CONSUMER_AC_BULLETED_LIST = 0x25A, // HID type SEL - HID_CONSUMER_AC_PROMOTE = 0x25B, // HID type SEL - HID_CONSUMER_AC_DEMOTE = 0x25C, // HID type SEL - HID_CONSUMER_AC_YES = 0x25D, // HID type SEL - HID_CONSUMER_AC_NO = 0x25E, // HID type SEL - HID_CONSUMER_AC_CANCEL = 0x25F, // HID type SEL - HID_CONSUMER_AC_CATALOG = 0x260, // HID type SEL - HID_CONSUMER_AC_BUY_SLASH_CHECKOUT = 0x261, // HID type SEL - HID_CONSUMER_AC_ADD_TO_CART = 0x262, // HID type SEL - HID_CONSUMER_AC_EXPAND = 0x263, // HID type SEL - HID_CONSUMER_AC_EXPAND_ALL = 0x264, // HID type SEL - HID_CONSUMER_AC_COLLAPSE = 0x265, // HID type SEL - HID_CONSUMER_AC_COLLAPSE_ALL = 0x266, // HID type SEL - HID_CONSUMER_AC_PRINT_PREVIEW = 0x267, // HID type SEL - HID_CONSUMER_AC_PASTE_SPECIAL = 0x268, // HID type SEL - HID_CONSUMER_AC_INSERT_MODE = 0x269, // HID type SEL - HID_CONSUMER_AC_DELETE = 0x26A, // HID type SEL - HID_CONSUMER_AC_LOCK = 0x26B, // HID type SEL - HID_CONSUMER_AC_UNLOCK = 0x26C, // HID type SEL - HID_CONSUMER_AC_PROTECT = 0x26D, // HID type SEL - HID_CONSUMER_AC_UNPROTECT = 0x26E, // HID type SEL - HID_CONSUMER_AC_ATTACH_COMMENT = 0x26F, // HID type SEL - HID_CONSUMER_AC_DELETE_COMMENT = 0x270, // HID type SEL - HID_CONSUMER_AC_VIEW_COMMENT = 0x271, // HID type SEL - HID_CONSUMER_AC_SELECT_WORD = 0x272, // HID type SEL - HID_CONSUMER_AC_SELECT_SENTENCE = 0x273, // HID type SEL - HID_CONSUMER_AC_SELECT_PARAGRAPH = 0x274, // HID type SEL - HID_CONSUMER_AC_SELECT_COLUMN = 0x275, // HID type SEL - HID_CONSUMER_AC_SELECT_ROW = 0x276, // HID type SEL - HID_CONSUMER_AC_SELECT_TABLE = 0x277, // HID type SEL - HID_CONSUMER_AC_SELECT_OBJECT = 0x278, // HID type SEL - HID_CONSUMER_AC_REDO_SLASH_REPEAT = 0x279, // HID type SEL - HID_CONSUMER_AC_SORT = 0x27A, // HID type SEL - HID_CONSUMER_AC_SORT_ASCENDING = 0x27B, // HID type SEL - HID_CONSUMER_AC_SORT_DESCENDING = 0x27C, // HID type SEL - HID_CONSUMER_AC_FILTER = 0x27D, // HID type SEL - HID_CONSUMER_AC_SET_CLOCK = 0x27E, // HID type SEL - HID_CONSUMER_AC_VIEW_CLOCK = 0x27F, // HID type SEL - HID_CONSUMER_AC_SELECT_TIME_ZONE = 0x280, // HID type SEL - HID_CONSUMER_AC_EDIT_TIME_ZONES = 0x281, // HID type SEL - HID_CONSUMER_AC_SET_ALARM = 0x282, // HID type SEL - HID_CONSUMER_AC_CLEAR_ALARM = 0x283, // HID type SEL - HID_CONSUMER_AC_SNOOZE_ALARM = 0x284, // HID type SEL - HID_CONSUMER_AC_RESET_ALARM = 0x285, // HID type SEL - HID_CONSUMER_AC_SYNCHRONIZE = 0x286, // HID type SEL - HID_CONSUMER_AC_SEND_SLASH_RECEIVE = 0x287, // HID type SEL - HID_CONSUMER_AC_SEND_TO = 0x288, // HID type SEL - HID_CONSUMER_AC_REPLY = 0x289, // HID type SEL - HID_CONSUMER_AC_REPLY_ALL = 0x28A, // HID type SEL - HID_CONSUMER_AC_FORWARD_MSG = 0x28B, // HID type SEL - HID_CONSUMER_AC_SEND = 0x28C, // HID type SEL - HID_CONSUMER_AC_ATTACH_FILE = 0x28D, // HID type SEL - HID_CONSUMER_AC_UPLOAD = 0x28E, // HID type SEL - HID_CONSUMER_AC_DOWNLOAD_SAVE_TARGET_AS = 0x28F, // HID type SEL - HID_CONSUMER_AC_SET_BORDERS = 0x290, // HID type SEL - HID_CONSUMER_AC_INSERT_ROW = 0x291, // HID type SEL - HID_CONSUMER_AC_INSERT_COLUMN = 0x292, // HID type SEL - HID_CONSUMER_AC_INSERT_FILE = 0x293, // HID type SEL - HID_CONSUMER_AC_INSERT_PICTURE = 0x294, // HID type SEL - HID_CONSUMER_AC_INSERT_OBJECT = 0x295, // HID type SEL - HID_CONSUMER_AC_INSERT_SYMBOL = 0x296, // HID type SEL - HID_CONSUMER_AC_SAVE_AND_CLOSE = 0x297, // HID type SEL - HID_CONSUMER_AC_RENAME = 0x298, // HID type SEL - HID_CONSUMER_AC_MERGE = 0x299, // HID type SEL - HID_CONSUMER_AC_SPLIT = 0x29A, // HID type SEL - HID_CONSUMER_AC_DISRIBUTE_HORIZONTALLY = 0x29B, // HID type SEL - HID_CONSUMER_AC_DISTRIBUTE_VERTICALLY = 0x29C, // HID type SEL -}; - - typedef union { // Every usable Consumer key possible, up to 4 keys presses possible uint8_t whole8[]; uint16_t whole16[]; uint32_t whole32[]; - ConsumerKeycode keys[4]; + uint16_t keys[4]; struct { - ConsumerKeycode key1; - ConsumerKeycode key2; - ConsumerKeycode key3; - ConsumerKeycode key4; + uint16_t key1; + uint16_t key2; + uint16_t key3; + uint16_t key4; }; } HID_ConsumerControlReport_Data_t; @@ -471,9 +50,9 @@ class Consumer_ Consumer_(void); inline void begin(void); inline void end(void); - inline void write(ConsumerKeycode m); - inline void press(ConsumerKeycode m); - inline void release(ConsumerKeycode m); + inline void write(uint16_t m); + inline void press(uint16_t m); + inline void release(uint16_t m); inline void releaseAll(void); // Sending is public in the base class for advanced users. From ea912110d6993a420606cbf4142e6c5b0b1ef460 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 17:55:52 -0800 Subject: [PATCH 390/602] sendReport isn't virtual anymore --- plugins/KeyboardioHID/src/MultiReport/Consumer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/Consumer.h b/plugins/KeyboardioHID/src/MultiReport/Consumer.h index c6e9ec405a..395d289aa6 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Consumer.h +++ b/plugins/KeyboardioHID/src/MultiReport/Consumer.h @@ -56,7 +56,7 @@ class Consumer_ inline void releaseAll(void); // Sending is public in the base class for advanced users. - virtual void SendReport(void* data, int length) = 0; + void SendReport(void* data, int length); protected: From ad83db4f7e99c486db7167f9125b90ebc233e585 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 17:57:28 -0800 Subject: [PATCH 391/602] Fix cut and paste errors from the great flattening of the gamepad api --- plugins/KeyboardioHID/src/MultiReport/Gamepad.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/Gamepad.h b/plugins/KeyboardioHID/src/MultiReport/Gamepad.h index cf830d8fcd..a9f2ac90a6 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Gamepad.h +++ b/plugins/KeyboardioHID/src/MultiReport/Gamepad.h @@ -99,7 +99,7 @@ typedef union { }; } HID_GamepadReport_Data_t; -class Gamepad_ : public GamepadAPI +class Gamepad_ { public: Gamepad_(void); @@ -121,8 +121,7 @@ class Gamepad_ : public GamepadAPI inline void dPad1(int8_t d); inline void dPad2(int8_t d); - // Sending is public in the base class for advanced users. - virtual void SendReport(void* data, int length) = 0; + inline void SendReport(void* data, int length); protected: HID_GamepadReport_Data_t _report; }; From b0ed1cdc413fa21a4c693de7cacb3645756f04b8 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 19:48:55 -0800 Subject: [PATCH 392/602] correct prototype of BootKeyboard::press --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 9a32206561..1dae3f6c08 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -226,7 +226,7 @@ void BootKeyboard_::wakeupHost(void){ // call release(), releaseAll(), or otherwise clear the report and resend. - bool BootKeyboard_::press(uint8_t k) + size_t BootKeyboard_::press(uint8_t k) { uint8_t done = 0; From 0dcfb8e32f0965b419d13bf67acb94390ca2a1fa Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 19:49:15 -0800 Subject: [PATCH 393/602] remove call to undefined setWriteError function --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 1dae3f6c08..212043ab11 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -254,7 +254,6 @@ void BootKeyboard_::wakeupHost(void){ // for style reasons - we do not know how the compiler // handles the for() index when it leaves the loop if (0 == done) { - setWriteError(); return 0; } } From f7d0fe8722562852fd81c205ac53fc3fee2ced92 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 19:50:00 -0800 Subject: [PATCH 394/602] BootKeyboard API fixup --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 212043ab11..c8ac3c7682 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -265,7 +265,7 @@ void BootKeyboard_::wakeupHost(void){ // sends the report. This tells the OS the key is no longer pressed and that // it shouldn't be repeated any more. -bool BootKeyboard_::release(uint8_t k) +size_t BootKeyboard_::release(uint8_t k) { uint8_t i; uint8_t count; @@ -307,7 +307,7 @@ bool BootKeyboard_::release(uint8_t k) return 1; } -void BootKeyboard_::releaseAll(void) +size_t BootKeyboard_::releaseAll(void) { memset(&_keyReport, 0x00, sizeof(_keyReport)); } From 9976b72f9c6ea736f02659ddc54f060e267c159f Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 19:50:48 -0800 Subject: [PATCH 395/602] Remove old custom SystemControl keycode table --- .../KeyboardioHID/src/MultiReport/System.cpp | 8 ++- .../KeyboardioHID/src/MultiReport/System.h | 52 ++----------------- 2 files changed, 6 insertions(+), 54 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/System.cpp b/plugins/KeyboardioHID/src/MultiReport/System.cpp index e1717423f5..fb7d70ea71 100644 --- a/plugins/KeyboardioHID/src/MultiReport/System.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/System.cpp @@ -58,7 +58,7 @@ void System_::end(void){ SendReport(&_report, sizeof(_report)); } -void System_::write(SystemKeycode s){ +void System_::write(uint8_t s){ press(s); release(); } @@ -71,12 +71,10 @@ void System_::releaseAll(void){ begin(); } -void System_::press(SystemKeycode s){ -#ifdef USBCON - if (s == SYSTEM_WAKE_UP) +void System_::press(uint8_t s){ + if (s == HID_SYSTEM_WAKE_UP) USBDevice.wakeupHost(); else -#endif SendReport(&s, sizeof(s)); } diff --git a/plugins/KeyboardioHID/src/MultiReport/System.h b/plugins/KeyboardioHID/src/MultiReport/System.h index f344a2462f..e9a3338a11 100644 --- a/plugins/KeyboardioHID/src/MultiReport/System.h +++ b/plugins/KeyboardioHID/src/MultiReport/System.h @@ -28,53 +28,7 @@ THE SOFTWARE. #include "PluggableUSB.h" #include "HID.h" #include "HID-Settings.h" - -enum SystemKeycode : uint8_t { - SYSTEM_POWER_DOWN = 0x81, - SYSTEM_SLEEP = 0x82, - SYSTEM_WAKE_UP = 0x83, - - // System control mappings - HID_SYSTEM_UNASSIGNED = 0x00, - HID_SYSTEM_POWER_DOWN = 0x81, // HID type OSC - HID_SYSTEM_SLEEP = 0x82, // HID type OSC - HID_SYSTEM_WAKE_UP = 0x83, // HID type OSC - HID_SYSTEM_CONTEXT_MENU = 0x84, // HID type OSC - HID_SYSTEM_MAIN_MENU = 0x85, // HID type OSC - HID_SYSTEM_APP_MENU = 0x86, // HID type OSC - HID_SYSTEM_MENU_HELP = 0x87, // HID type OSC - HID_SYSTEM_MENU_EXIT = 0x88, // HID type OSC - HID_SYSTEM_MENU_SELECT = 0x89, // HID type OSC - HID_SYSTEM_MENU_RIGHT = 0x8A, // HID type RTC - HID_SYSTEM_MENU_LEFT = 0x8B, // HID type RTC - HID_SYSTEM_MENU_UP = 0x8C, // HID type RTC - HID_SYSTEM_MENU_DOWN = 0x8D, // HID type RTC - HID_SYSTEM_COLD_RESTART = 0x8E, // HID type OSC - HID_SYSTEM_WARM_RESTART = 0x8F, // HID type OSC - HID_D_PAD_UP = 0x90, // HID type OOC - HID_D_PAD_DOWN = 0x91, // HID type OOC - HID_D_PAD_RIGHT = 0x92, // HID type OOC - HID_D_PAD_LEFT = 0x93, // HID type OOC - // 0x94-0x9F are reserved - HID_SYSTEM_DOCK = 0xA0, // HID type OSC - HID_SYSTEM_UNDOCK = 0xA1, // HID type OSC - HID_SYSTEM_SETUP = 0xA2, // HID type OSC - HID_SYSTEM_BREAK = 0xA3, // HID type OSC - HID_SYSTEM_DEBUGGER_BREAK = 0xA4, // HID type OSC - HID_APPLICATION_BREAK = 0xA5, // HID type OSC - HID_APPLICATION_DEBUGGER_BREAK = 0xA6, // HID type OSC - HID_SYSTEM_SPEAKER_MUTE = 0xA7, // HID type OSC - HID_SYSTEM_HIBERNATE = 0xA8, // HID type OSC - // 0xA9-0xAF are reserved - HID_SYSTEM_DISPLAY_INVERT = 0xB0, // HID type OSC - HID_SYSTEM_DISPLAY_INTERNAL = 0xB1, // HID type OSC - HID_SYSTEM_DISPLAY_EXTERNAL = 0xB2, // HID type OSC - HID_SYSTEM_DISPLAY_BOTH = 0xB3, // HID type OSC - HID_SYSTEM_DISPLAY_DUAL = 0xB4, // HID type OSC - HID_SYSTEM_DISPLAY_TOGGLE_INT_SLASH_EXT = 0xB5, // HID type OSC - HID_SYSTEM_DISPLAY_SWAP_PRIMARY_SLASH_SECONDARY = 0xB6, // HID type OSC - HID_SYSTEM_DISPLAY_LCD_AUTOSCALE = 0xB7, // HID type OSC -}; +#include "HIDTables.h" typedef union{ // Every usable system control key possible @@ -88,8 +42,8 @@ class System_ public: inline void begin(void); inline void end(void); - inline void write(SystemKeycode s); - inline void press(SystemKeycode s); + inline void write(uint8_t s); + inline void press(uint8_t s); inline void release(void); inline void releaseAll(void); virtual void SendReport(void* data, int length) = 0; From 1791a4064838a5adab3bd1172323090b08be2934 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 19:51:16 -0800 Subject: [PATCH 396/602] remove overloaded use of "no key defined" macro --- plugins/KeyboardioHID/src/MultiReport/System.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/System.cpp b/plugins/KeyboardioHID/src/MultiReport/System.cpp index fb7d70ea71..abc00db089 100644 --- a/plugins/KeyboardioHID/src/MultiReport/System.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/System.cpp @@ -54,7 +54,7 @@ void System_::begin(void){ } void System_::end(void){ - SystemKeycode _report = HID_SYSTEM_UNASSIGNED; + uint8_t _report = 0x00; SendReport(&_report, sizeof(_report)); } From 7be82975041a455f54d17e67052aca9e838c8fb5 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 19:51:44 -0800 Subject: [PATCH 397/602] SystemControl's SendReport isn't virtual --- plugins/KeyboardioHID/src/MultiReport/System.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/System.h b/plugins/KeyboardioHID/src/MultiReport/System.h index e9a3338a11..19d6138f0f 100644 --- a/plugins/KeyboardioHID/src/MultiReport/System.h +++ b/plugins/KeyboardioHID/src/MultiReport/System.h @@ -46,7 +46,7 @@ class System_ inline void press(uint8_t s); inline void release(void); inline void releaseAll(void); - virtual void SendReport(void* data, int length) = 0; + inline void SendReport(void* data, int length); System_(void); From c53fe73c27b9b3105331447da16b607900d78a2b Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 19:52:21 -0800 Subject: [PATCH 398/602] Add a "write" method to BootKeyboard that presses and releases a key --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp | 8 ++++++++ plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h | 1 + 2 files changed, 9 insertions(+) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index c8ac3c7682..8b557c4e97 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -307,6 +307,14 @@ size_t BootKeyboard_::release(uint8_t k) return 1; } + +size_t BootKeyboard_::write(uint8_t keycode) { + press(keycode); + sendReport(); + release(keycode); + sendReport(); +} + size_t BootKeyboard_::releaseAll(void) { memset(&_keyReport, 0x00, sizeof(_keyReport)); diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index 55bd95421f..99cbf39ccc 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -51,6 +51,7 @@ class BootKeyboard_ : public PluggableUSBModule public: BootKeyboard_(void); size_t press(uint8_t); + size_t write(uint8_t); size_t release(uint8_t); size_t releaseAll(void); From 0676cd35dae3184333b4b5273ecbc567c4c4f540 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 19:52:57 -0800 Subject: [PATCH 399/602] Export bootkeyboard's "begin" and "end" methods --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index 99cbf39ccc..826ca80243 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -51,6 +51,8 @@ class BootKeyboard_ : public PluggableUSBModule public: BootKeyboard_(void); size_t press(uint8_t); + void begin(void); + void end(void); size_t write(uint8_t); size_t release(uint8_t); size_t releaseAll(void); From 8a3379f29e19cce4fa43fac0d45d9d3606c2f9eb Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 19:53:59 -0800 Subject: [PATCH 400/602] NKROKeyboard release takes a boring uint8_t --- plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp index bfce4a22eb..2516ad3ee9 100644 --- a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp @@ -126,7 +126,7 @@ size_t NKROKeyboard_::press(uint8_t k) return 0; } -size_t NKROKeyboard_::release(KeyboardKeycode k) +size_t NKROKeyboard_::release(uint8_t k) { // Press keymap key if (k < NKRO_KEY_COUNT){ From 0a8cd9cc29a4ae55eb3cc098be457e2715b2b104 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 19:54:30 -0800 Subject: [PATCH 401/602] NKROKeyboard's 'sendReport' isn't virtual --- plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h index 094f2ed58f..c75f0ddf80 100644 --- a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h @@ -61,7 +61,7 @@ class NKROKeyboard_ inline size_t press(uint8_t k); inline size_t release(uint8_t k); inline size_t releaseAll(void); - virtual int sendReport(void) = 0; + inline int sendReport(void); protected: HID_NKROKeyboardReport_Data_t _keyReport; From 162a6aff9768c76638716057cb873f2fa773a7be Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 19:54:46 -0800 Subject: [PATCH 402/602] fixups from AbsoluteMouse flattening --- plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp index 1424af4010..fd0337612b 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp @@ -102,11 +102,6 @@ int16_t AbsoluteMouse_::qadd16(int16_t base, int16_t increment) { return base; } -xAxis(0), yAxis(0), _buttons(0) -{ - // Empty -} - void AbsoluteMouse_::begin(void){ // release all buttons end(); From 1e486193d76a7cc77735399192a9586af6e86ec8 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 19:55:00 -0800 Subject: [PATCH 403/602] typo fixes from Gamepad flattening --- .../KeyboardioHID/src/MultiReport/Gamepad.cpp | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp b/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp index 21ee7fd569..e97ae8270a 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp @@ -79,76 +79,76 @@ Gamepad_::Gamepad_(void) } -void Gamepad_begin(void){ +void Gamepad_::begin(void){ // release all buttons end(); } -void Gamepad_end(void){ +void Gamepad_::end(void){ memset(&_report, 0x00, sizeof(_report)); SendReport(&_report, sizeof(_report)); } -void Gamepad_write(void){ +void Gamepad_::write(void){ SendReport(&_report, sizeof(_report)); } -void Gamepad_press(uint8_t b){ +void Gamepad_::press(uint8_t b){ _report.buttons |= (uint32_t)1 << (b - 1); } -void Gamepad_release(uint8_t b){ +void Gamepad_::release(uint8_t b){ _report.buttons &= ~((uint32_t)1 << (b - 1)); } -void Gamepad_releaseAll(void){ +void Gamepad_::releaseAll(void){ memset(&_report, 0x00, sizeof(_report)); } -void Gamepad_buttons(uint32_t b){ +void Gamepad_::buttons(uint32_t b){ _report.buttons = b; } -void Gamepad_xAxis(int16_t a){ +void Gamepad_::xAxis(int16_t a){ _report.xAxis = a; } -void Gamepad_yAxis(int16_t a){ +void Gamepad_::yAxis(int16_t a){ _report.yAxis = a; } -void Gamepad_zAxis(int8_t a){ +void Gamepad_::zAxis(int8_t a){ _report.zAxis = a; } -void Gamepad_rxAxis(int16_t a){ +void Gamepad_::rxAxis(int16_t a){ _report.rxAxis = a; } -void Gamepad_ryAxis(int16_t a){ +void Gamepad_::ryAxis(int16_t a){ _report.ryAxis = a; } -void Gamepad_rzAxis(int8_t a){ +void Gamepad_::rzAxis(int8_t a){ _report.rzAxis = a; } -void Gamepad_dPad1(int8_t d){ +void Gamepad_::dPad1(int8_t d){ _report.dPad1 = d; } -void Gamepad_dPad2(int8_t d){ +void Gamepad_::dPad2(int8_t d){ _report.dPad2 = d; } From 606643bad24d7219e0b1e8c8c8b63068877f0302 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 21:09:34 -0800 Subject: [PATCH 404/602] Fixing a missing macro replacement --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 8b557c4e97..c83d9911d2 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -272,7 +272,7 @@ size_t BootKeyboard_::release(uint8_t k) if ((k >= HID_KEYBOARD_FIRST_MODIFIER) && (k <= HID_KEYBOARD_LAST_MODIFIER)) { // it's a modifier key - _keyReport.modifiers = _keyReport.modifiers & (~(0x01 << (k - HID_KEYBOARD_LEFT_CONTROL))); + _keyReport.modifiers = _keyReport.modifiers & (~(0x01 << (k - HID_KEYBOARD_LAST_MODIFIER))); } else { // it's some other key: // Test the key report to see if k is present. Clear it if it exists. From 3439f87ccaf18e23b2ece9a1ad2bf81cb23c26fd Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 21:10:09 -0800 Subject: [PATCH 405/602] Add easier to type HID keyboard aliases --- plugins/KeyboardioHID/src/HIDAliases.h | 154 ++++++++++++++++++++++++- 1 file changed, 153 insertions(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/HIDAliases.h b/plugins/KeyboardioHID/src/HIDAliases.h index dbc0e79917..6cee7cb7a8 100644 --- a/plugins/KeyboardioHID/src/HIDAliases.h +++ b/plugins/KeyboardioHID/src/HIDAliases.h @@ -3,4 +3,156 @@ #include "HIDTables.h" #define HID_KEYBOARD_FIRST_MODIFIER HID_KEYBOARD_LEFT_CONTROL -#define HID_KEYBOARD_LAST_MODIFIER HID_KEYBOARD_RIGHT_GUI \ No newline at end of file +#define HID_KEYBOARD_LAST_MODIFIER HID_KEYBOARD_RIGHT_GUI + + + +#define KEY_A HID_KEYBOARD_A_AND_A +#define KEY_B HID_KEYBOARD_B_AND_B +#define KEY_C HID_KEYBOARD_C_AND_C +#define KEY_D HID_KEYBOARD_D_AND_D +#define KEY_E HID_KEYBOARD_E_AND_E +#define KEY_F HID_KEYBOARD_F_AND_F +#define KEY_G HID_KEYBOARD_G_AND_G +#define KEY_H HID_KEYBOARD_H_AND_H +#define KEY_I HID_KEYBOARD_I_AND_I +#define KEY_J HID_KEYBOARD_J_AND_J +#define KEY_K HID_KEYBOARD_K_AND_K +#define KEY_L HID_KEYBOARD_L_AND_L +#define KEY_M HID_KEYBOARD_M_AND_M +#define KEY_N HID_KEYBOARD_N_AND_N +#define KEY_O HID_KEYBOARD_O_AND_O +#define KEY_P HID_KEYBOARD_P_AND_P +#define KEY_Q HID_KEYBOARD_Q_AND_Q +#define KEY_R HID_KEYBOARD_R_AND_R +#define KEY_S HID_KEYBOARD_S_AND_S +#define KEY_T HID_KEYBOARD_T_AND_T +#define KEY_U HID_KEYBOARD_U_AND_U +#define KEY_V HID_KEYBOARD_V_AND_V +#define KEY_W HID_KEYBOARD_W_AND_W +#define KEY_X HID_KEYBOARD_X_AND_X +#define KEY_Y HID_KEYBOARD_Y_AND_Y +#define KEY_Z HID_KEYBOARD_Z_AND_Z +#define KEY_1 HID_KEYBOARD_1_AND_EXCLAMATION_POINT +#define KEY_2 HID_KEYBOARD_2_AND_AT +#define KEY_3 HID_KEYBOARD_3_AND_POUND +#define KEY_4 HID_KEYBOARD_4_AND_DOLLAR +#define KEY_5 HID_KEYBOARD_5_AND_PERCENT +#define KEY_6 HID_KEYBOARD_6_AND_CARAT +#define KEY_7 HID_KEYBOARD_7_AND_AMPERSAND +#define KEY_8 HID_KEYBOARD_8_AND_ASTERISK +#define KEY_9 HID_KEYBOARD_9_AND_LEFT_PAREN +#define KEY_0 HID_KEYBOARD_0_AND_RIGHT_PAREN +#define KEY_ENTER HID_KEYBOARD_ENTER // (MARKED AS ENTER_SLASH_RETURN) +#define KEY_ESC HID_KEYBOARD_ESCAPE +#define KEY_DEL HID_KEYBOARD_DELETE // (BACKSPACE) +#define KEY_TAB HID_KEYBOARD_TAB +#define KEY_SPACE HID_KEYBOARD_SPACEBAR +#define KEY_MINUS HID_KEYBOARD_MINUS_AND_UNDERSCORE // (UNDERSCORE) +#define KEY_EQUALS HID_KEYBOARD_EQUALS_AND_PLUS +#define KEY_L_BRACKET HID_KEYBOARD_LEFT_BRACKET_AND_LEFT_CURLY_BRACE +#define KEY_R_BRACKET HID_KEYBOARD_RIGHT_BRACKET_AND_RIGHT_CURLY_BRACE +#define KEY_BACKSLASH HID_KEYBOARD_BACKSLASH_AND_PIPE +#define KEY_GBP HID_KEYBOARD_NON_US_POUND_AND_TILDE +#define KEY_SEMICOLON HID_KEYBOARD_SEMICOLON_AND_COLON +#define KEY_QUOTE HID_KEYBOARD_QUOTE_AND_DOUBLEQUOTE +#define KEY_GRAVE HID_KEYBOARD_GRAVE_ACCENT_AND_TILDE +#define KEY_COMMA HID_KEYBOARD_COMMA_AND_LESS_THAN +#define KEY_PERIOD HID_KEYBOARD_PERIOD_AND_GREATER_THAN +#define KEY_SLASH HID_KEYBOARD_SLASH_AND_QUESTION_MARK +#define KEY_CAPS HID_KEYBOARD_CAPS_LOCK +#define KEY_F1 HID_KEYBOARD_F1 +#define KEY_F2 HID_KEYBOARD_F2 +#define KEY_F3 HID_KEYBOARD_F3 +#define KEY_F4 HID_KEYBOARD_F4 +#define KEY_F5 HID_KEYBOARD_F5 +#define KEY_F6 HID_KEYBOARD_F6 +#define KEY_F7 HID_KEYBOARD_F7 +#define KEY_F8 HID_KEYBOARD_F8 +#define KEY_F9 HID_KEYBOARD_F9 +#define KEY_F10 HID_KEYBOARD_F10 +#define KEY_F11 HID_KEYBOARD_F11 +#define KEY_F12 HID_KEYBOARD_F12 +#define KEY_PRINTSCR HID_KEYBOARD_PRINTSCREEN +#define KEY_SCROLLLK HID_KEYBOARD_SCROLL_LOCK +#define KEY_PAUSE HID_KEYBOARD_PAUSE +#define KEY_INS HID_KEYBOARD_INSERT +#define KEY_HOME HID_KEYBOARD_HOME +#define KEY_PGUP HID_KEYBOARD_PAGE_UP +#define KEY_DEL_FWD HID_KEYBOARD_DELETE_FORWARD +#define KEY_END HID_KEYBOARD_END +#define KEY_PGDN HID_KEYBOARD_PAGE_DOWN +#define KEY_RARROW HID_KEYBOARD_RIGHTARROW +#define KEY_LARROW HID_KEYBOARD_LEFTARROW +#define KEY_DARROW HID_KEYBOARD_DOWNARROW +#define KEY_UARROW HID_KEYBOARD_UPARROW +#define KEY_BACKSLASH HID_KEYBOARD_NON_US_BACKSLASH_AND_PIPE +#define KEY_APP HID_KEYBOARD_APPLICATION +#define KEY_PWR HID_KEYBOARD_POWER +#define KEY_F13 HID_KEYBOARD_F13 +#define KEY_F14 HID_KEYBOARD_F14 +#define KEY_F15 HID_KEYBOARD_F15 +#define KEY_F16 HID_KEYBOARD_F16 +#define KEY_F17 HID_KEYBOARD_F17 +#define KEY_F18 HID_KEYBOARD_F18 +#define KEY_F19 HID_KEYBOARD_F19 +#define KEY_F20 HID_KEYBOARD_F20 +#define KEY_F21 HID_KEYBOARD_F21 +#define KEY_F22 HID_KEYBOARD_F22 +#define KEY_F23 HID_KEYBOARD_F23 +#define KEY_F24 HID_KEYBOARD_F24 +#define KEY_EXEC HID_KEYBOARD_EXECUTE +#define KEY_HELP HID_KEYBOARD_HELP +#define KEY_MENU HID_KEYBOARD_MENU +#define KEY_SEL HID_KEYBOARD_SELECT +#define KEY_STOP HID_KEYBOARD_STOP +#define KEY_AGAIN HID_KEYBOARD_AGAIN +#define KEY_UNDO HID_KEYBOARD_UNDO +#define KEY_CUT HID_KEYBOARD_CUT +#define KEY_COPY HID_KEYBOARD_COPY +#define KEY_PASTE HID_KEYBOARD_PASTE +#define KEY_FIND HID_KEYBOARD_FIND +#define KEY_MUTE HID_KEYBOARD_MUTE +#define KEY_VOLUP HID_KEYBOARD_VOLUME_UP +#define KEY_VOLDN HID_KEYBOARD_VOLUME_DOWN +#define KEY_CAPSLOCK HID_KEYBOARD_LOCKING_CAPS_LOCK +#define KEY_NUMLOCK HID_KEYBOARD_LOCKING_NUM_LOCK +#define KEY_SCROLLLOCK HID_KEYBOARD_LOCKING_SCROLL_LOCK +#define KEY_INT1 HID_KEYBOARD_INTERNATIONAL1 +#define KEY_INT2 HID_KEYBOARD_INTERNATIONAL2 +#define KEY_INT3 HID_KEYBOARD_INTERNATIONAL3 +#define KEY_INT4 HID_KEYBOARD_INTERNATIONAL4 +#define KEY_INT5 HID_KEYBOARD_INTERNATIONAL5 +#define KEY_INT6 HID_KEYBOARD_INTERNATIONAL6 +#define KEY_INT7 HID_KEYBOARD_INTERNATIONAL7 +#define KEY_INT8 HID_KEYBOARD_INTERNATIONAL8 +#define KEY_INT9 HID_KEYBOARD_INTERNATIONAL9 +#define KEY_LANG1 HID_KEYBOARD_LANG1 +#define KEY_LANG2 HID_KEYBOARD_LANG2 +#define KEY_LANG3 HID_KEYBOARD_LANG3 +#define KEY_LANG4 HID_KEYBOARD_LANG4 +#define KEY_LANG5 HID_KEYBOARD_LANG5 +#define KEY_LANG6 HID_KEYBOARD_LANG6 +#define KEY_LANG7 HID_KEYBOARD_LANG7 +#define KEY_LANG8 HID_KEYBOARD_LANG8 +#define KEY_LANG9 HID_KEYBOARD_LANG9 +#define KEY_ALTDEL HID_KEYBOARD_ALTERNATE_ERASE +#define KEY_SYSREQ HID_KEYBOARD_SYSREQ_SLASH_ATTENTION +#define KEY_CANCEL HID_KEYBOARD_CANCEL +#define KEY_CLEAR HID_KEYBOARD_CLEAR +#define KEY_PRIOR HID_KEYBOARD_PRIOR +#define KEY_RETURN HID_KEYBOARD_RETURN +#define KEY_SEPARATOR HID_KEYBOARD_SEPARATOR +#define KEY_OUT HID_KEYBOARD_OUT +#define KEY_OPER HID_KEYBOARD_OPER +#define KEY_CLEAR HID_KEYBOARD_CLEAR_SLASH_AGAIN +#define KEY_CRSEL HID_KEYBOARD_CRSEL_SLASH_PROPS +#define KEY_EXSEL HID_KEYBOARD_EXSEL +#define KEY_LCTRL HID_KEYBOARD_LEFT_CONTROL +#define KEY_LSHIFT HID_KEYBOARD_LEFT_SHIFT +#define KEY_LALT HID_KEYBOARD_LEFT_ALT +#define KEY_LGUI HID_KEYBOARD_LEFT_GUI +#define KEY_RCTRL HID_KEYBOARD_RIGHT_CONTROL +#define KEY_RSHIFT HID_KEYBOARD_RIGHT_SHIFT +#define KEY_RALT HID_KEYBOARD_RIGHT_ALT +#define KEY_RGUI HID_KEYBOARD_RIGHT_GUI \ No newline at end of file From 74b1f604f15b16e47febe3686cee5fd16b370847 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 21:11:45 -0800 Subject: [PATCH 406/602] Remove the old ImprovedLayouts definitions we're not using anymore --- .../src/KeyboardCore/ImprovedKeylayouts.h | 488 ------------------ 1 file changed, 488 deletions(-) delete mode 100644 plugins/KeyboardioHID/src/KeyboardCore/ImprovedKeylayouts.h diff --git a/plugins/KeyboardioHID/src/KeyboardCore/ImprovedKeylayouts.h b/plugins/KeyboardioHID/src/KeyboardCore/ImprovedKeylayouts.h deleted file mode 100644 index 6ce103dfbd..0000000000 --- a/plugins/KeyboardioHID/src/KeyboardCore/ImprovedKeylayouts.h +++ /dev/null @@ -1,488 +0,0 @@ -/* -Copyright (c) 2014-2015 NicoHood -See the readme for credit to other people. - -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 guard -#pragma once - -// Hut1_12v2.pdf -enum KeyboardKeycode : uint8_t { - KEY_RESERVED = 0, - KEY_ERROR_ROLLOVER = 1, - KEY_POST_FAIL = 2, - KEY_ERROR_UNDEFINED = 3, - KEY_A = 4, - KEY_B = 5, - KEY_C = 6, - KEY_D = 7, - KEY_E = 8, - KEY_F = 9, - KEY_G = 10, - KEY_H = 11, - KEY_I = 12, - KEY_J = 13, - KEY_K = 14, - KEY_L = 15, - KEY_M = 16, - KEY_N = 17, - KEY_O = 18, - KEY_P = 19, - KEY_Q = 20, - KEY_R = 21, - KEY_S = 22, - KEY_T = 23, - KEY_U = 24, - KEY_V = 25, - KEY_W = 26, - KEY_X = 27, - KEY_Y = 28, - KEY_Z = 29, - KEY_1 = 30, - KEY_2 = 31, - KEY_3 = 32, - KEY_4 = 33, - KEY_5 = 34, - KEY_6 = 35, - KEY_7 = 36, - KEY_8 = 37, - KEY_9 = 38, - KEY_0 = 39, - KEY_ENTER = 40, - KEY_RETURN = 40, // Alias - KEY_ESC = 41, - KEY_BACKSPACE = 42, - KEY_TAB = 43, - KEY_SPACE = 44, - KEY_MINUS = 45, - KEY_EQUAL = 46, - KEY_LEFT_BRACE = 47, - KEY_RIGHT_BRACE = 48, - KEY_BACKSLASH = 49, - KEY_NON_US_NUM = 50, - KEY_SEMICOLON = 51, - KEY_QUOTE = 52, - KEY_TILDE = 53, - KEY_COMMA = 54, - KEY_PERIOD = 55, - KEY_SLASH = 56, - KEY_CAPS_LOCK = 0x39, - KEY_F1 = 0x3A, - KEY_F2 = 0x3B, - KEY_F3 = 0x3C, - KEY_F4 = 0x3D, - KEY_F5 = 0x3E, - KEY_F6 = 0x3F, - KEY_F7 = 0x40, - KEY_F8 = 0x41, - KEY_F9 = 0x42, - KEY_F10 = 0x43, - KEY_F11 = 0x44, - KEY_F12 = 0x45, - KEY_PRINT = 0x46, - KEY_PRINTSCREEN = 0x46, // Alias - KEY_SCROLL_LOCK = 0x47, - KEY_PAUSE = 0x48, - KEY_INSERT = 0x49, - KEY_HOME = 0x4A, - KEY_PAGE_UP = 0x4B, - KEY_DELETE = 0x4C, - KEY_END = 0x4D, - KEY_PAGE_DOWN = 0x4E, - KEY_RIGHT_ARROW = 0x4F, - KEY_LEFT_ARROW = 0x50, - KEY_DOWN_ARROW = 0x51, - KEY_UP_ARROW = 0x52, - KEY_RIGHT = 0x4F, // Alias - KEY_LEFT = 0x50, // Alias - KEY_DOWN = 0x51, // Alias - KEY_UP = 0x52, // Alias - KEY_NUM_LOCK = 0x53, - KEYPAD_DIVIDE = 0x54, - KEYPAD_MULTIPLY = 0x55, - KEYPAD_SUBTRACT = 0x56, - KEYPAD_ADD = 0x57, - KEYPAD_ENTER = 0x58, - KEYPAD_1 = 0x59, - KEYPAD_2 = 0x5A, - KEYPAD_3 = 0x5B, - KEYPAD_4 = 0x5C, - KEYPAD_5 = 0x5D, - KEYPAD_6 = 0x5E, - KEYPAD_7 = 0x5F, - KEYPAD_8 = 0x60, - KEYPAD_9 = 0x61, - KEYPAD_0 = 0x62, - KEYPAD_DOT = 0x63, - KEY_NON_US = 0x64, - KEY_APPLICATION = 0x65, // Context menu/right click - KEY_MENU = 0x65, // Alias - - // Most of the following keys will only work with Linux or not at all. - // F13+ keys are mostly used for laptop functions like ECO key. - KEY_POWER = 0x66, // PowerOff (Ubuntu) - KEY_PAD_EQUALS = 0x67, // Dont confuse with KEYPAD_EQUAL_SIGN - KEY_F13 = 0x68, // Tools (Ubunutu) - KEY_F14 = 0x69, // Launch5 (Ubuntu) - KEY_F15 = 0x6A, // Launch6 (Ubuntu) - KEY_F16 = 0x6B, // Launch7 (Ubuntu) - KEY_F17 = 0x6C, // Launch8 (Ubuntu) - KEY_F18 = 0x6D, // Launch9 (Ubuntu) - KEY_F19 = 0x6E, // Disabled (Ubuntu) - KEY_F20 = 0x6F, // AudioMicMute (Ubuntu) - KEY_F21 = 0x70, // Touchpad toggle (Ubuntu) - KEY_F22 = 0x71, // TouchpadOn (Ubuntu) - KEY_F23 = 0x72, // TouchpadOff Ubuntu) - KEY_F24 = 0x73, // Disabled (Ubuntu) - KEY_EXECUTE = 0x74, // Open (Ubuntu) - KEY_HELP = 0x75, // Help (Ubuntu) - KEY_MENU2 = 0x76, // Disabled (Ubuntu) - KEY_SELECT = 0x77, // Disabled (Ubuntu) - KEY_STOP = 0x78, // Cancel (Ubuntu) - KEY_AGAIN = 0x79, // Redo (Ubuntu) - KEY_UNDO = 0x7A, // Undo (Ubuntu) - KEY_CUT = 0x7B, // Cut (Ubuntu) - KEY_COPY = 0x7C, // Copy (Ubuntu) - KEY_PASTE = 0x7D, // Paste (Ubuntu) - KEY_FIND = 0x7E, // Find (Ubuntu) - KEY_MUTE = 0x7F, - KEY_VOLUME_MUTE = 0x7F, // Alias - KEY_VOLUME_UP = 0x80, - KEY_VOLUME_DOWN = 0x81, - KEY_LOCKING_CAPS_LOCK = 0x82, // Disabled (Ubuntu) - KEY_LOCKING_NUM_LOCK = 0x83, // Disabled (Ubuntu) - KEY_LOCKING_SCROLL_LOCK = 0x84, // Disabled (Ubuntu) - KEYPAD_COMMA = 0x85, // . - KEYPAD_EQUAL_SIGN = 0x86, // Disabled (Ubuntu), Dont confuse with KEYPAD_EQUAL - KEY_INTERNATIONAL1 = 0x87, // Disabled (Ubuntu) - KEY_INTERNATIONAL2 = 0x88, // Hiragana Katakana (Ubuntu) - KEY_INTERNATIONAL3 = 0x89, // Disabled (Ubuntu) - KEY_INTERNATIONAL4 = 0x8A, // Henkan (Ubuntu) - KEY_INTERNATIONAL5 = 0x8B, // Muhenkan (Ubuntu) - KEY_INTERNATIONAL6 = 0x8C, // Disabled (Ubuntu) - KEY_INTERNATIONAL7 = 0x8D, // Disabled (Ubuntu) - KEY_INTERNATIONAL8 = 0x8E, // Disabled (Ubuntu) - KEY_INTERNATIONAL9 = 0x8F, // Disabled (Ubuntu) - KEY_LANG1 = 0x90, // Disabled (Ubuntu) - KEY_LANG2 = 0x91, // Disabled (Ubuntu) - KEY_LANG3 = 0x92, // Katana (Ubuntu) - KEY_LANG4 = 0x93, // Hiragana (Ubuntu) - KEY_LANG5 = 0x94, // Disabled (Ubuntu) - KEY_LANG6 = 0x95, // Disabled (Ubuntu) - KEY_LANG7 = 0x96, // Disabled (Ubuntu) - KEY_LANG8 = 0x97, // Disabled (Ubuntu) - KEY_LANG9 = 0x98, // Disabled (Ubuntu) - KEY_ALTERNATE_ERASE = 0x99, // Disabled (Ubuntu) - KEY_SYSREQ_ATTENTION = 0x9A, // Disabled (Ubuntu) - KEY_CANCEL = 0x9B, // Disabled (Ubuntu) - KEY_CLEAR = 0x9C, // Delete (Ubuntu) - KEY_PRIOR = 0x9D, // Disabled (Ubuntu) - KEY_RETURN2 = 0x9E, // Disabled (Ubuntu), Do not confuse this with KEY_ENTER - KEY_SEPARATOR = 0x9F, // Disabled (Ubuntu) - KEY_OUT = 0xA0, // Disabled (Ubuntu) - KEY_OPER = 0xA1, // Disabled (Ubuntu) - KEY_CLEAR_AGAIN = 0xA2, // Disabled (Ubuntu) - KEY_CRSEL_PROPS = 0xA3, // Disabled (Ubuntu) - KEY_EXSEL = 0xA4, // Disabled (Ubuntu) - - KEY_PAD_00 = 0xB0, // Disabled (Ubuntu) - KEY_PAD_000 = 0xB1, // Disabled (Ubuntu) - KEY_THOUSANDS_SEPARATOR = 0xB2, // Disabled (Ubuntu) - KEY_DECIMAL_SEPARATOR = 0xB3, // Disabled (Ubuntu) - KEY_CURRENCY_UNIT = 0xB4, // Disabled (Ubuntu) - KEY_CURRENCY_SUB_UNIT = 0xB5, // Disabled (Ubuntu) - KEYPAD_LEFT_BRACE = 0xB6, // ( - KEYPAD_RIGHT_BRACE = 0xB7, // ) - KEYPAD_LEFT_CURLY_BRACE = 0xB8, // Disabled (Ubuntu) - KEYPAD_RIGHT_CURLY_BRACE = 0xB9, // Disabled (Ubuntu) - KEYPAD_TAB = 0xBA, // Disabled (Ubuntu) - KEYPAD_BACKSPACE = 0xBB, // Disabled (Ubuntu) - KEYPAD_A = 0xBC, // Disabled (Ubuntu) - KEYPAD_B = 0xBD, // Disabled (Ubuntu) - KEYPAD_C = 0xBE, // Disabled (Ubuntu) - KEYPAD_D = 0xBF, // Disabled (Ubuntu) - KEYPAD_E = 0xC0, // Disabled (Ubuntu) - KEYPAD_F = 0xC1, // Disabled (Ubuntu) - KEYPAD_XOR = 0xC2, // Disabled (Ubuntu) - KEYPAD_CARET = 0xC3, // Disabled (Ubuntu) - KEYPAD_PERCENT = 0xC4, // Disabled (Ubuntu) - KEYPAD_LESS_THAN = 0xC5, // Disabled (Ubuntu) - KEYPAD_GREATER_THAN = 0xC6, // Disabled (Ubuntu) - KEYPAD_AMPERSAND = 0xC7, // Disabled (Ubuntu) - KEYPAD_DOUBLEAMPERSAND = 0xC8, // Disabled (Ubuntu) - KEYPAD_PIPE = 0xC9, // Disabled (Ubuntu) - KEYPAD_DOUBLEPIPE = 0xCA, // Disabled (Ubuntu) - KEYPAD_COLON = 0xCB, // Disabled (Ubuntu) - KEYPAD_POUND_SIGN = 0xCC, // Disabled (Ubuntu) - KEYPAD_SPACE = 0xCD, // Disabled (Ubuntu) - KEYPAD_AT_SIGN = 0xCE, // Disabled (Ubuntu) - KEYPAD_EXCLAMATION_POINT = 0xCF, // Disabled (Ubuntu) - KEYPAD_MEMORY_STORE = 0xD0, // Disabled (Ubuntu) - KEYPAD_MEMORY_RECALL = 0xD1, // Disabled (Ubuntu) - KEYPAD_MEMORY_CLEAR = 0xD2, // Disabled (Ubuntu) - KEYPAD_MEMORY_ADD = 0xD3, // Disabled (Ubuntu) - KEYPAD_MEMORY_SUBTRACT = 0xD4, // Disabled (Ubuntu) - KEYPAD_MEMORY_MULTIPLY = 0xD5, // Disabled (Ubuntu) - KEYPAD_MEMORY_DIVIDE = 0xD6, // Disabled (Ubuntu) - KEYPAD_PLUS_MINUS = 0xD7, // Disabled (Ubuntu) - KEYPAD_CLEAR = 0xD8, // Delete (Ubuntu) - KEYPAD_CLEAR_ENTRY = 0xD9, // Disabled (Ubuntu) - KEYPAD_BINARY = 0xDA, // Disabled (Ubuntu) - KEYPAD_OCTAL = 0xDB, // Disabled (Ubuntu) - KEYPAD_DECIMAL = 0xDC, // Disabled (Ubuntu) - KEYPAD_HEXADECIMAL = 0xDD, // Disabled (Ubuntu) - - KEY_LEFT_CTRL = 0xE0, - KEY_LEFT_SHIFT = 0xE1, - KEY_LEFT_ALT = 0xE2, - KEY_LEFT_GUI = 0xE3, - KEY_LEFT_WINDOWS = 0xE3, // Alias - KEY_RIGHT_CTRL = 0xE4, - KEY_RIGHT_SHIFT = 0xE5, - KEY_RIGHT_ALT = 0xE6, - KEY_RIGHT_GUI = 0xE7, - KEY_RIGHT_WINDOWS = 0xE7, // Alias - - // Keyboard HID mappings - - // Reserved (no_event_indicated) - HID_KEYBOARD_ERROR_ROLLOVER = 0x01, - HID_KEYBOARD_POST_FAIL = 0x02, - HID_KEYBOARD_ERROR_UNDEFINED = 0x03, - HID_KEYBOARD_A_AND_A = 0x04, - HID_KEYBOARD_B_AND_B = 0x05, - HID_KEYBOARD_C_AND_C = 0x06, - HID_KEYBOARD_D_AND_D = 0x07, - HID_KEYBOARD_E_AND_E = 0x08, - HID_KEYBOARD_F_AND_F = 0x09, - HID_KEYBOARD_G_AND_G = 0x0A, - HID_KEYBOARD_H_AND_H = 0x0B, - HID_KEYBOARD_I_AND_I = 0x0C, - HID_KEYBOARD_J_AND_J = 0x0D, - HID_KEYBOARD_K_AND_K = 0x0E, - HID_KEYBOARD_L_AND_L = 0x0F, - HID_KEYBOARD_M_AND_M = 0x10, - HID_KEYBOARD_N_AND_N = 0x11, - HID_KEYBOARD_O_AND_O = 0x12, - HID_KEYBOARD_P_AND_P = 0x13, - HID_KEYBOARD_Q_AND_Q = 0x14, - HID_KEYBOARD_R_AND_R = 0x15, - HID_KEYBOARD_S_AND_S = 0x16, - HID_KEYBOARD_T_AND_T = 0x17, - HID_KEYBOARD_U_AND_U = 0x18, - HID_KEYBOARD_V_AND_V = 0x19, - HID_KEYBOARD_W_AND_W = 0x1A, - HID_KEYBOARD_X_AND_X = 0x1B, - HID_KEYBOARD_Y_AND_Y = 0x1C, - HID_KEYBOARD_Z_AND_Z = 0x1D, - HID_KEYBOARD_1_AND_EXCLAMATION_POINT = 0x1E, - HID_KEYBOARD_2_AND_AT = 0x1F, - HID_KEYBOARD_3_AND_POUND = 0x20, - HID_KEYBOARD_4_AND_DOLLAR = 0x21, - HID_KEYBOARD_5_AND_PERCENT = 0x22, - HID_KEYBOARD_6_AND_CARAT = 0x23, - HID_KEYBOARD_7_AND_AMPERSAND = 0x24, - HID_KEYBOARD_8_AND_ASTERISK = 0x25, - HID_KEYBOARD_9_AND_LEFT_PAREN = 0x26, - HID_KEYBOARD_0_AND_RIGHT_PAREN = 0x27, - HID_KEYBOARD_ENTER = 0x28, // (MARKED AS ENTER_SLASH_RETURN) - HID_KEYBOARD_ESCAPE = 0x29, - HID_KEYBOARD_DELETE = 0x2A, // (BACKSPACE) - HID_KEYBOARD_TAB = 0x2B, - HID_KEYBOARD_SPACEBAR = 0x2C, - HID_KEYBOARD_MINUS_AND_UNDERSCORE = 0x2D, // (UNDERSCORE) - HID_KEYBOARD_EQUALS_AND_PLUS = 0x2E, - HID_KEYBOARD_LEFT_BRACKET_AND_LEFT_CURLY_BRACE = 0x2F, - HID_KEYBOARD_RIGHT_BRACKET_AND_RIGHT_CURLY_BRACE = 0x30, - HID_KEYBOARD_BACKSLASH_AND_PIPE = 0x31, - HID_KEYBOARD_NON_US_POUND_AND_TILDE = 0x32, - HID_KEYBOARD_SEMICOLON_AND_COLON = 0x33, - HID_KEYBOARD_QUOTE_AND_DOUBLEQUOTE = 0x34, - HID_KEYBOARD_GRAVE_ACCENT_AND_TILDE = 0x35, - HID_KEYBOARD_COMMA_AND_LESS_THAN = 0x36, - HID_KEYBOARD_PERIOD_AND_GREATER_THAN = 0x37, - HID_KEYBOARD_SLASH_AND_QUESTION_MARK = 0x38, - HID_KEYBOARD_CAPS_LOCK = 0x39, - HID_KEYBOARD_F1 = 0x3A, - HID_KEYBOARD_F2 = 0x3B, - HID_KEYBOARD_F3 = 0x3C, - HID_KEYBOARD_F4 = 0x3D, - HID_KEYBOARD_F5 = 0x3E, - HID_KEYBOARD_F6 = 0x3F, - HID_KEYBOARD_F7 = 0x40, - HID_KEYBOARD_F8 = 0x41, - HID_KEYBOARD_F9 = 0x42, - HID_KEYBOARD_F10 = 0x43, - HID_KEYBOARD_F11 = 0x44, - HID_KEYBOARD_F12 = 0x45, - HID_KEYBOARD_PRINTSCREEN = 0x46, - HID_KEYBOARD_SCROLL_LOCK = 0x47, - HID_KEYBOARD_PAUSE = 0x48, - HID_KEYBOARD_INSERT = 0x49, - HID_KEYBOARD_HOME = 0x4A, - HID_KEYBOARD_PAGE_UP = 0x4B, - HID_KEYBOARD_DELETE_FORWARD = 0x4C, - HID_KEYBOARD_END = 0x4D, - HID_KEYBOARD_PAGE_DOWN = 0x4E, - HID_KEYBOARD_RIGHTARROW = 0x4F, - HID_KEYBOARD_LEFTARROW = 0x50, - HID_KEYBOARD_DOWNARROW = 0x51, - HID_KEYBOARD_UPARROW = 0x52, - HID_KEYPAD_NUM_LOCK_AND_CLEAR = 0x53, - HID_KEYPAD_DIVIDE = 0x54, - HID_KEYPAD_MULTIPLY = 0x55, - HID_KEYPAD_SUBTRACT = 0x56, - HID_KEYPAD_ADD = 0x57, - HID_KEYPAD_ENTER = 0x58, - HID_KEYPAD_1_AND_END = 0x59, - HID_KEYPAD_2_AND_DOWN_ARROW = 0x5A, - HID_KEYPAD_3_AND_PAGE_DOWN = 0x5B, - HID_KEYPAD_4_AND_LEFT_ARROW = 0x5C, - HID_KEYPAD_5 = 0x5D, - HID_KEYPAD_6_AND_RIGHT_ARROW = 0x5E, - HID_KEYPAD_7_AND_HOME = 0x5F, - HID_KEYPAD_8_AND_UP_ARROW = 0x60, - HID_KEYPAD_9_AND_PAGE_UP = 0x61, - HID_KEYPAD_0_AND_INSERT = 0x62, - HID_KEYPAD_PERIOD_AND_DELETE = 0x63, - HID_KEYBOARD_NON_US_BACKSLASH_AND_PIPE = 0x64, - HID_KEYBOARD_APPLICATION = 0x65, - HID_KEYBOARD_POWER = 0x66, - HID_KEYPAD_EQUALS = 0x67, - HID_KEYBOARD_F13 = 0x68, - HID_KEYBOARD_F14 = 0x69, - HID_KEYBOARD_F15 = 0x6A, - HID_KEYBOARD_F16 = 0x6B, - HID_KEYBOARD_F17 = 0x6C, - HID_KEYBOARD_F18 = 0x6D, - HID_KEYBOARD_F19 = 0x6E, - HID_KEYBOARD_F20 = 0x6F, - HID_KEYBOARD_F21 = 0x70, - HID_KEYBOARD_F22 = 0x71, - HID_KEYBOARD_F23 = 0x72, - HID_KEYBOARD_F24 = 0x73, - HID_KEYBOARD_EXECUTE = 0x74, - HID_KEYBOARD_HELP = 0x75, - HID_KEYBOARD_MENU = 0x76, - HID_KEYBOARD_SELECT = 0x77, - HID_KEYBOARD_STOP = 0x78, - HID_KEYBOARD_AGAIN = 0x79, - HID_KEYBOARD_UNDO = 0x7A, - HID_KEYBOARD_CUT = 0x7B, - HID_KEYBOARD_COPY = 0x7C, - HID_KEYBOARD_PASTE = 0x7D, - HID_KEYBOARD_FIND = 0x7E, - HID_KEYBOARD_MUTE = 0x7F, - HID_KEYBOARD_VOLUME_UP = 0x80, - HID_KEYBOARD_VOLUME_DOWN = 0x81, - HID_KEYBOARD_LOCKING_CAPS_LOCK = 0x82, - HID_KEYBOARD_LOCKING_NUM_LOCK = 0x83, - HID_KEYBOARD_LOCKING_SCROLL_LOCK = 0x84, - HID_KEYPAD_COMMA = 0x85, - HID_KEYPAD_EQUAL_SIGN = 0x86, - HID_KEYBOARD_INTERNATIONAL1 = 0x87, - HID_KEYBOARD_INTERNATIONAL2 = 0x88, - HID_KEYBOARD_INTERNATIONAL3 = 0x89, - HID_KEYBOARD_INTERNATIONAL4 = 0x8A, - HID_KEYBOARD_INTERNATIONAL5 = 0x8B, - HID_KEYBOARD_INTERNATIONAL6 = 0x8C, - HID_KEYBOARD_INTERNATIONAL7 = 0x8D, - HID_KEYBOARD_INTERNATIONAL8 = 0x8E, - HID_KEYBOARD_INTERNATIONAL9 = 0x8F, - HID_KEYBOARD_LANG1 = 0x90, - HID_KEYBOARD_LANG2 = 0x91, - HID_KEYBOARD_LANG3 = 0x92, - HID_KEYBOARD_LANG4 = 0x93, - HID_KEYBOARD_LANG5 = 0x94, - HID_KEYBOARD_LANG6 = 0x95, - HID_KEYBOARD_LANG7 = 0x96, - HID_KEYBOARD_LANG8 = 0x97, - HID_KEYBOARD_LANG9 = 0x98, - HID_KEYBOARD_ALTERNATE_ERASE = 0x99, - HID_KEYBOARD_SYSREQ_SLASH_ATTENTION = 0x9A, - HID_KEYBOARD_CANCEL = 0x9B, - HID_KEYBOARD_CLEAR = 0x9C, - HID_KEYBOARD_PRIOR = 0x9D, - HID_KEYBOARD_RETURN = 0x9E, - HID_KEYBOARD_SEPARATOR = 0x9F, - HID_KEYBOARD_OUT = 0xA0, - HID_KEYBOARD_OPER = 0xA1, - HID_KEYBOARD_CLEAR_SLASH_AGAIN = 0xA2, - HID_KEYBOARD_CRSEL_SLASH_PROPS = 0xA3, - HID_KEYBOARD_EXSEL = 0xA4, - // Reserved 0xA5-AF - HID_KEYPAD_00 = 0xB0, - HID_KEYPAD_000 = 0xB1, - HID_THOUSANDS_SEPARATOR = 0xB2, - HID_DECIMAL_SEPARATOR = 0xB3, - HID_CURRENCY_UNIT = 0xB4, - HID_CURRENCY_SUBUNIT = 0xB5, - HID_KEYPAD_LEFT_PAREN = 0xB6, - HID_KEYPAD_RIGHT_PAREN = 0xB7, - HID_KEYPAD_LEFT_CURLY_BRACE = 0xB8, - HID_KEYPAD_RIGHT_CURLY_BRACE = 0xB9, - HID_KEYPAD_TAB = 0xBA, - HID_KEYPAD_BACKSPACE = 0xBB, - HID_KEYPAD_A = 0xBC, - HID_KEYPAD_B = 0xBD, - HID_KEYPAD_C = 0xBE, - HID_KEYPAD_D = 0xBF, - HID_KEYPAD_E = 0xC0, - HID_KEYPAD_F = 0xC1, - HID_KEYPAD_XOR = 0xC2, - HID_KEYPAD_CARAT = 0xC3, - HID_KEYPAD_PERCENT = 0xC4, - HID_KEYPAD_LESS_THAN = 0xC5, - HID_KEYPAD_GREATER_THAN = 0xC6, - HID_KEYPAD_AMPERSAND = 0xC7, - HID_KEYPAD_DOUBLEAMPERSAND = 0xC8, - HID_KEYPAD_PIPE = 0xC9, - HID_KEYPAD_DOUBLEPIPE = 0xCA, - HID_KEYPAD_COLON = 0xCB, - HID_KEYPAD_POUND_SIGN = 0xCC, - HID_KEYPAD_SPACE = 0xCD, - HID_KEYPAD_AT_SIGN = 0xCE, - HID_KEYPAD_EXCLAMATION_POINT = 0xCF, - HID_KEYPAD_MEMORY_STORE = 0xD0, - HID_KEYPAD_MEMORY_RECALL = 0xD1, - HID_KEYPAD_MEMORY_CLEAR = 0xD2, - HID_KEYPAD_MEMORY_ADD = 0xD3, - HID_KEYPAD_MEMORY_SUBTRACT = 0xD4, - HID_KEYPAD_MEMORY_MULTIPLY = 0xD5, - HID_KEYPAD_MEMORY_DIVIDE = 0xD6, - HID_KEYPAD_PLUS_SLASH_MINUS = 0xD7, - HID_KEYPAD_CLEAR = 0xD8, - HID_KEYPAD_CLEAR_ENTRY = 0xD9, - HID_KEYPAD_BINARY = 0xDA, - HID_KEYPAD_OCTAL = 0xDB, - HID_KEYPAD_DECIMAL = 0xDC, - HID_KEYPAD_HEXADECIMAL = 0xDD, - - // 0xDE-0xDF - RESERVED - HID_KEYBOARD_LEFT_CONTROL = 0xE0, - HID_KEYBOARD_LEFT_SHIFT = 0xE1, - HID_KEYBOARD_LEFT_ALT = 0xE2, - HID_KEYBOARD_LEFT_GUI = 0xE3, - HID_KEYBOARD_RIGHT_CONTROL = 0xE4, - HID_KEYBOARD_RIGHT_SHIFT = 0xE5, - HID_KEYBOARD_RIGHT_ALT = 0xE6, - HID_KEYBOARD_RIGHT_GUI = 0xE7, -}; From a69ea221dc2242871571bc8fce00daaa6a44a52d Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 21:28:28 -0800 Subject: [PATCH 407/602] Previous refactoring accidentally used .keys instead of .keycodes. --- .../src/BootKeyboard/BootKeyboard.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index c83d9911d2..cf465eabfa 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -239,9 +239,9 @@ void BootKeyboard_::wakeupHost(void){ // and if there is an empty slot. for (uint8_t i = 0; i < sizeof(_keyReport.keycodes); i++) { - if (_keyReport.keys[i] != k) { // is k already in list? - if (0 == _keyReport.keys[i]) { // have we found an empty slot? - _keyReport.keys[i] = k; + if (_keyReport.keycodes[i] != k) { // is k already in list? + if (0 == _keyReport.keycodes[i]) { // have we found an empty slot? + _keyReport.keycodes[i] = k; done = 1; break; } @@ -279,8 +279,8 @@ size_t BootKeyboard_::release(uint8_t k) // Check all positions in case the key is present more than once (which it shouldn't be) for (i = 0; i < sizeof(_keyReport.keycodes); i++) { - if (_keyReport.keys[i] == k) { - _keyReport.keys[i] = 0; + if (_keyReport.keycodes[i] == k) { + _keyReport.keycodes[i] = 0; } } @@ -292,12 +292,12 @@ size_t BootKeyboard_::release(uint8_t k) count = 0; // holds the number of zeros we've found i = 0; while ((i + count) < sizeof(_keyReport.keycodes)) { - if (0 == _keyReport.keys[i]) { + if (0 == _keyReport.keycodes[i]) { count++; // one more zero for (uint8_t j = i; j < sizeof(_keyReport.keycodes)-count; j++) { - _keyReport.keys[j] = _keyReport.keys[j+1]; + _keyReport.keycodes[j] = _keyReport.keycodes[j+1]; } - _keyReport.keys[sizeof(_keyReport.keycodes)-count] = 0; + _keyReport.keycodes[sizeof(_keyReport.keycodes)-count] = 0; } else { i++; // one more non-zero } From 077c80045d2eac5f8d7ea0f7faeec3a833c0e2e8 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 21:41:36 -0800 Subject: [PATCH 408/602] Unified code style with Artistic Style Version 2.05.1 find src -type f |xargs -n 1 astyle --style=google --- .../src/BootKeyboard/BootKeyboard.cpp | 409 +++++++++--------- .../src/BootKeyboard/BootKeyboard.h | 71 ++- plugins/KeyboardioHID/src/HIDTables.h | 10 +- plugins/KeyboardioHID/src/LEDs.h | 16 +- .../src/MultiReport/AbsoluteMouse.cpp | 141 +++--- .../src/MultiReport/AbsoluteMouse.h | 69 ++- .../src/MultiReport/Consumer.cpp | 86 ++-- .../KeyboardioHID/src/MultiReport/Consumer.h | 49 +-- .../KeyboardioHID/src/MultiReport/Gamepad.cpp | 166 ++++--- .../KeyboardioHID/src/MultiReport/Gamepad.h | 155 ++++--- .../src/MultiReport/ImprovedMouse.cpp | 83 ++-- .../src/MultiReport/ImprovedMouse.h | 51 ++- .../src/MultiReport/NKROKeyboard.cpp | 213 +++++---- .../src/MultiReport/NKROKeyboard.h | 45 +- .../KeyboardioHID/src/MultiReport/System.cpp | 78 ++-- .../KeyboardioHID/src/MultiReport/System.h | 31 +- 16 files changed, 813 insertions(+), 860 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index cf465eabfa..dda6aef484 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -36,12 +36,12 @@ static const uint8_t _hidReportDescriptorKeyboard[] PROGMEM = { 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x95, 0x08, /* REPORT_COUNT (8) */ + 0x95, 0x08, /* REPORT_COUNT (8) */ 0x81, 0x02, /* INPUT (Data,Var,Abs) */ /* Reserved byte, used for consumer reports, only works with linux */ /* NOT CURRENTLY USED BY THIS IMPLEMENTATION */ - 0x05, 0x0C, /* Usage Page (Consumer) */ + 0x05, 0x0C, /* Usage Page (Consumer) */ 0x95, 0x01, /* REPORT_COUNT (1) */ 0x75, 0x08, /* REPORT_SIZE (8) */ 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ @@ -50,13 +50,13 @@ static const uint8_t _hidReportDescriptorKeyboard[] PROGMEM = { 0x29, 0xFF, /* USAGE_MAXIMUM (255) */ 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ - /* 5 LEDs for num lock etc, 3 left for advanced, custom usage */ - 0x05, 0x08, /* USAGE_PAGE (LEDs) */ - 0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */ - 0x29, 0x08, /* USAGE_MAXIMUM (Kana + 3 custom)*/ - 0x95, 0x08, /* REPORT_COUNT (8) */ - 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */ + /* 5 LEDs for num lock etc, 3 left for advanced, custom usage */ + 0x05, 0x08, /* USAGE_PAGE (LEDs) */ + 0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */ + 0x29, 0x08, /* USAGE_MAXIMUM (Kana + 3 custom)*/ + 0x95, 0x08, /* REPORT_COUNT (8) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */ /* 6 Keyboard keys */ 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ @@ -72,239 +72,231 @@ static const uint8_t _hidReportDescriptorKeyboard[] PROGMEM = { 0xc0 /* END_COLLECTION */ }; -BootKeyboard_::BootKeyboard_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1), leds(0), featureReport(NULL), featureLength(0) -{ - epType[0] = EP_TYPE_INTERRUPT_IN; - PluggableUSB().plug(this); +BootKeyboard_::BootKeyboard_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1), leds(0), featureReport(NULL), featureLength(0) { + epType[0] = EP_TYPE_INTERRUPT_IN; + PluggableUSB().plug(this); } -int BootKeyboard_::getInterface(uint8_t* interfaceCount) -{ - *interfaceCount += 1; // uses 1 - HIDDescriptor hidInterface = { - D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_BOOT_INTERFACE, HID_PROTOCOL_KEYBOARD), - D_HIDREPORT(sizeof(_hidReportDescriptorKeyboard)), - D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) - }; - return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); +int BootKeyboard_::getInterface(uint8_t* interfaceCount) { + *interfaceCount += 1; // uses 1 + HIDDescriptor hidInterface = { + D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_BOOT_INTERFACE, HID_PROTOCOL_KEYBOARD), + D_HIDREPORT(sizeof(_hidReportDescriptorKeyboard)), + D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) + }; + return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); } -int BootKeyboard_::getDescriptor(USBSetup& setup) -{ - // Check if this is a HID Class Descriptor request - if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { return 0; } - if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { return 0; } - - // In a HID Class Descriptor wIndex cointains the interface number - if (setup.wIndex != pluggedInterface) { return 0; } - - // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol - // due to the USB specs, but Windows and Linux just assumes its in report mode. - protocol = HID_REPORT_PROTOCOL; - - return USB_SendControl(TRANSFER_PGM, _hidReportDescriptorKeyboard, sizeof(_hidReportDescriptorKeyboard)); +int BootKeyboard_::getDescriptor(USBSetup& setup) { + // Check if this is a HID Class Descriptor request + if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { + return 0; + } + if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { + return 0; + } + + // In a HID Class Descriptor wIndex cointains the interface number + if (setup.wIndex != pluggedInterface) { + return 0; + } + + // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol + // due to the USB specs, but Windows and Linux just assumes its in report mode. + protocol = HID_REPORT_PROTOCOL; + + return USB_SendControl(TRANSFER_PGM, _hidReportDescriptorKeyboard, sizeof(_hidReportDescriptorKeyboard)); } -void BootKeyboard_::begin(void) -{ - // Force API to send a clean report. - // This is important for and HID bridge where the receiver stays on, - // while the sender is resetted. - releaseAll(); - sendReport(); +void BootKeyboard_::begin(void) { + // Force API to send a clean report. + // This is important for and HID bridge where the receiver stays on, + // while the sender is resetted. + releaseAll(); + sendReport(); } -void BootKeyboard_::end(void) -{ - releaseAll(); - sendReport(); +void BootKeyboard_::end(void) { + releaseAll(); + sendReport(); } -bool BootKeyboard_::setup(USBSetup& setup) -{ - if (pluggedInterface != setup.wIndex) { - return false; - } - - uint8_t request = setup.bRequest; - uint8_t requestType = setup.bmRequestType; - - if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) - { - if (request == HID_GET_REPORT) { - // TODO: HID_GetReport(); - return true; - } - if (request == HID_GET_PROTOCOL) { - // TODO improve - UEDATX = protocol; - return true; - } - if (request == HID_GET_IDLE) { - // TODO improve - UEDATX = idle; - return true; - } - } - - if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) - { - if (request == HID_SET_PROTOCOL) { - protocol = setup.wValueL; - return true; - } - if (request == HID_SET_IDLE) { - idle = setup.wValueL; - return true; - } - if (request == HID_SET_REPORT) - { - // Check if data has the correct length afterwards - int length = setup.wLength; - - // Feature (set feature report) - if(setup.wValueH == HID_REPORT_TYPE_FEATURE){ - // No need to check for negative featureLength values, - // except the host tries to send more then 32k bytes. - // We dont have that much ram anyways. - if (length == featureLength) { - USB_RecvControl(featureReport, featureLength); - - // Block until data is read (make length negative) - disableFeatureReport(); - return true; - } - // TODO fake clear data? - } - - // Output (set led states) - else if(setup.wValueH == HID_REPORT_TYPE_OUTPUT){ - if(length == sizeof(leds)){ - USB_RecvControl(&leds, length); - return true; - } - } - - // Input (set HID report) - else if(setup.wValueH == HID_REPORT_TYPE_INPUT) - { - if(length == sizeof(_keyReport)){ - USB_RecvControl(&_keyReport, length); - return true; - } - } - } - } - - return false; +bool BootKeyboard_::setup(USBSetup& setup) { + if (pluggedInterface != setup.wIndex) { + return false; + } + + uint8_t request = setup.bRequest; + uint8_t requestType = setup.bmRequestType; + + if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) { + if (request == HID_GET_REPORT) { + // TODO: HID_GetReport(); + return true; + } + if (request == HID_GET_PROTOCOL) { + // TODO improve + UEDATX = protocol; + return true; + } + if (request == HID_GET_IDLE) { + // TODO improve + UEDATX = idle; + return true; + } + } + + if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) { + if (request == HID_SET_PROTOCOL) { + protocol = setup.wValueL; + return true; + } + if (request == HID_SET_IDLE) { + idle = setup.wValueL; + return true; + } + if (request == HID_SET_REPORT) { + // Check if data has the correct length afterwards + int length = setup.wLength; + + // Feature (set feature report) + if(setup.wValueH == HID_REPORT_TYPE_FEATURE) { + // No need to check for negative featureLength values, + // except the host tries to send more then 32k bytes. + // We dont have that much ram anyways. + if (length == featureLength) { + USB_RecvControl(featureReport, featureLength); + + // Block until data is read (make length negative) + disableFeatureReport(); + return true; + } + // TODO fake clear data? + } + + // Output (set led states) + else if(setup.wValueH == HID_REPORT_TYPE_OUTPUT) { + if(length == sizeof(leds)) { + USB_RecvControl(&leds, length); + return true; + } + } + + // Input (set HID report) + else if(setup.wValueH == HID_REPORT_TYPE_INPUT) { + if(length == sizeof(_keyReport)) { + USB_RecvControl(&_keyReport, length); + return true; + } + } + } + } + + return false; } -uint8_t BootKeyboard_::getLeds(void){ +uint8_t BootKeyboard_::getLeds(void) { return leds; } -uint8_t BootKeyboard_::getProtocol(void){ +uint8_t BootKeyboard_::getProtocol(void) { return protocol; } -int BootKeyboard_::sendReport(void){ - return USB_Send(pluggedEndpoint | TRANSFER_RELEASE, &_keyReport, sizeof(_keyReport)); +int BootKeyboard_::sendReport(void) { + return USB_Send(pluggedEndpoint | TRANSFER_RELEASE, &_keyReport, sizeof(_keyReport)); } -void BootKeyboard_::wakeupHost(void){ - USBDevice.wakeupHost(); +void BootKeyboard_::wakeupHost(void) { + USBDevice.wakeupHost(); } // 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 BootKeyboard_::press(uint8_t k) - { - uint8_t done = 0; - - if ((k >= HID_KEYBOARD_FIRST_MODIFIER) && (k <= HID_KEYBOARD_LAST_MODIFIER)) { - // it's a modifier key - _keyReport.modifiers |= (0x01 << (k - HID_KEYBOARD_FIRST_MODIFIER)); - } else { - // it's some other key: - // Add k to the key report only if it's not already present - // and if there is an empty slot. - for (uint8_t i = 0; i < sizeof(_keyReport.keycodes); i++) - { - if (_keyReport.keycodes[i] != k) { // is k already in list? - if (0 == _keyReport.keycodes[i]) { // have we found an empty slot? - _keyReport.keycodes[i] = k; - done = 1; - break; - } - } else { - done = 1; - break; - } - } - // use separate variable to check if slot was found - // for style reasons - we do not know how the compiler - // handles the for() index when it leaves the loop - if (0 == done) { - return 0; - } - } - return 1; - } +// 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 BootKeyboard_::press(uint8_t k) { + uint8_t done = 0; + + if ((k >= HID_KEYBOARD_FIRST_MODIFIER) && (k <= HID_KEYBOARD_LAST_MODIFIER)) { + // it's a modifier key + _keyReport.modifiers |= (0x01 << (k - HID_KEYBOARD_FIRST_MODIFIER)); + } else { + // it's some other key: + // Add k to the key report only if it's not already present + // and if there is an empty slot. + for (uint8_t i = 0; i < sizeof(_keyReport.keycodes); i++) { + if (_keyReport.keycodes[i] != k) { // is k already in list? + if (0 == _keyReport.keycodes[i]) { // have we found an empty slot? + _keyReport.keycodes[i] = k; + done = 1; + break; + } + } else { + done = 1; + break; + } + } + // use separate variable to check if slot was found + // for style reasons - we do not know how the compiler + // handles the for() index when it leaves the loop + if (0 == done) { + return 0; + } + } + 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 BootKeyboard_::release(uint8_t k) -{ - uint8_t i; - uint8_t count; - - if ((k >= HID_KEYBOARD_FIRST_MODIFIER) && (k <= HID_KEYBOARD_LAST_MODIFIER)) { - // it's a modifier key - _keyReport.modifiers = _keyReport.modifiers & (~(0x01 << (k - HID_KEYBOARD_LAST_MODIFIER))); - } else { - // it's some other key: - // 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 < sizeof(_keyReport.keycodes); i++) - { +size_t BootKeyboard_::release(uint8_t k) { + uint8_t i; + uint8_t count; + + if ((k >= HID_KEYBOARD_FIRST_MODIFIER) && (k <= HID_KEYBOARD_LAST_MODIFIER)) { + // it's a modifier key + _keyReport.modifiers = _keyReport.modifiers & (~(0x01 << (k - HID_KEYBOARD_LAST_MODIFIER))); + } else { + // it's some other key: + // 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 < sizeof(_keyReport.keycodes); i++) { if (_keyReport.keycodes[i] == k) { - _keyReport.keycodes[i] = 0; - } - } - - // finally rearrange the keys list so that the free (= 0x00) are at the - // end of the keys list - some implementations stop for keys at the - // first occurence of an 0x00 in the keys list - // so (0x00)(0x01)(0x00)(0x03)(0x02)(0x00) becomes - // (0x01)(0x03)(0x02)(0x00)(0x00)(0x00) - count = 0; // holds the number of zeros we've found - i = 0; - while ((i + count) < sizeof(_keyReport.keycodes)) { - if (0 == _keyReport.keycodes[i]) { - count++; // one more zero - for (uint8_t j = i; j < sizeof(_keyReport.keycodes)-count; j++) { - _keyReport.keycodes[j] = _keyReport.keycodes[j+1]; - } - _keyReport.keycodes[sizeof(_keyReport.keycodes)-count] = 0; - } else { - i++; // one more non-zero - } - } - } - - return 1; + _keyReport.keycodes[i] = 0; + } + } + + // finally rearrange the keys list so that the free (= 0x00) are at the + // end of the keys list - some implementations stop for keys at the + // first occurence of an 0x00 in the keys list + // so (0x00)(0x01)(0x00)(0x03)(0x02)(0x00) becomes + // (0x01)(0x03)(0x02)(0x00)(0x00)(0x00) + count = 0; // holds the number of zeros we've found + i = 0; + while ((i + count) < sizeof(_keyReport.keycodes)) { + if (0 == _keyReport.keycodes[i]) { + count++; // one more zero + for (uint8_t j = i; j < sizeof(_keyReport.keycodes)-count; j++) { + _keyReport.keycodes[j] = _keyReport.keycodes[j+1]; + } + _keyReport.keycodes[sizeof(_keyReport.keycodes)-count] = 0; + } else { + i++; // one more non-zero + } + } + } + + return 1; } @@ -315,8 +307,7 @@ size_t BootKeyboard_::write(uint8_t keycode) { sendReport(); } -size_t BootKeyboard_::releaseAll(void) -{ +size_t BootKeyboard_::releaseAll(void) { memset(&_keyReport, 0x00, sizeof(_keyReport)); } diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index 826ca80243..5e58d66919 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -32,79 +32,78 @@ THE SOFTWARE. #include "HIDAliases.h" -typedef union{ - // Low level key report: up to 6 keys and shift, ctrl etc at once - uint8_t whole8[]; - uint16_t whole16[]; - uint32_t whole32[]; - struct{ - uint8_t modifiers; - uint8_t reserved; - uint8_t keycodes[6]; - }; - uint8_t keys[8]; +typedef union { + // Low level key report: up to 6 keys and shift, ctrl etc at once + uint8_t whole8[]; + uint16_t whole16[]; + uint32_t whole32[]; + struct { + uint8_t modifiers; + uint8_t reserved; + uint8_t keycodes[6]; + }; + uint8_t keys[8]; } HID_KeyboardReport_Data_t; -class BootKeyboard_ : public PluggableUSBModule -{ -public: +class BootKeyboard_ : public PluggableUSBModule { + public: BootKeyboard_(void); - size_t press(uint8_t); - void begin(void); - void end(void); + size_t press(uint8_t); + void begin(void); + void end(void); size_t write(uint8_t); - size_t release(uint8_t); - size_t releaseAll(void); + size_t release(uint8_t); + size_t releaseAll(void); - int sendReport(void); + int sendReport(void); uint8_t getLeds(void); uint8_t getProtocol(void); void wakeupHost(void); - - void setFeatureReport(void* report, int length){ - if(length > 0){ + + void setFeatureReport(void* report, int length) { + if(length > 0) { featureReport = (uint8_t*)report; featureLength = length; - + // Disable feature report by default disableFeatureReport(); } } - - int availableFeatureReport(void){ - if(featureLength < 0){ + + int availableFeatureReport(void) { + if(featureLength < 0) { return featureLength & ~0x8000; } return 0; } - - void enableFeatureReport(void){ + + void enableFeatureReport(void) { featureLength &= ~0x8000; } - - void disableFeatureReport(void){ + + void disableFeatureReport(void) { featureLength |= 0x8000; } - -protected: + + protected: HID_KeyboardReport_Data_t _keyReport; // Implementation of the PUSBListNode int getInterface(uint8_t* interfaceCount); int getDescriptor(USBSetup& setup); bool setup(USBSetup& setup); - + uint8_t epType[1]; uint8_t protocol; uint8_t idle; - + uint8_t leds; - + uint8_t* featureReport; int featureLength; }; diff --git a/plugins/KeyboardioHID/src/HIDTables.h b/plugins/KeyboardioHID/src/HIDTables.h index b929869783..2282be11a4 100644 --- a/plugins/KeyboardioHID/src/HIDTables.h +++ b/plugins/KeyboardioHID/src/HIDTables.h @@ -2,21 +2,21 @@ #define __HIDTables__ -// These mappings were extracted and transcribed from +// These mappings were extracted and transcribed from // http://www.usb.org_SLASH_developers_SLASH_devclass_docs_SLASH_Hut1_12v2.pdf // -// In most cases, I've preserved the "official" USB Implementers forum +// In most cases, I've preserved the "official" USB Implementers forum // "Usage Name", though I've standardized some abbreviations and spacing -// that were inconsistent in the original specification. Non alpha-numeric +// that were inconsistent in the original specification. Non alpha-numeric // characters in symbol names were converted into those characters' names. // // To match Arduino code style, all hid usage names are fully upper case. // // Not every HID usage listed in this file is currently supported by Arduino -// In particular, any System Control or Consumer Control entry that doesn't +// In particular, any System Control or Consumer Control entry that doesn't // have a comment indicating that it's "HID type OSC" will require additional // code in the Arduino core to work. -// +// // Non-working usages are listed here in the interest of not having to manually // convert more usage names each and every time our HID stack gets a little bit // better. diff --git a/plugins/KeyboardioHID/src/LEDs.h b/plugins/KeyboardioHID/src/LEDs.h index 8cf81dc2a4..ccdef1f4af 100644 --- a/plugins/KeyboardioHID/src/LEDs.h +++ b/plugins/KeyboardioHID/src/LEDs.h @@ -2,13 +2,13 @@ // Keyboard Leds enum KeyboardLeds : uint8_t { - LED_NUM_LOCK = (1 << 0), - LED_CAPS_LOCK = (1 << 1), - LED_SCROLL_LOCK = (1 << 2), - LED_COMPOSE = (1 << 3), - LED_KANA = (1 << 4), - LED_POWER = (1 << 5), - LED_SHIFT = (1 << 6), - LED_DO_NOT_DISTURB = (1 << 7), + LED_NUM_LOCK = (1 << 0), + LED_CAPS_LOCK = (1 << 1), + LED_SCROLL_LOCK = (1 << 2), + LED_COMPOSE = (1 << 3), + LED_KANA = (1 << 4), + LED_POWER = (1 << 5), + LED_SHIFT = (1 << 6), + LED_DO_NOT_DISTURB = (1 << 7), }; diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp index fd0337612b..125d42f813 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp @@ -25,13 +25,13 @@ THE SOFTWARE. static const uint8_t _hidMultiReportDescriptorAbsoluteMouse[] PROGMEM = { - /* Mouse absolute */ + /* Mouse absolute */ 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 54 */ 0x09, 0x02, /* USAGE (Mouse) */ 0xA1, 0x01, /* COLLECTION (Application) */ 0x85, HID_REPORTID_MOUSE_ABSOLUTE, /* REPORT_ID */ - /* 8 Buttons */ + /* 8 Buttons */ 0x05, 0x09, /* USAGE_PAGE (Button) */ 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ 0x29, 0x08, /* USAGE_MAXIMUM (Button 8) */ @@ -41,17 +41,17 @@ static const uint8_t _hidMultiReportDescriptorAbsoluteMouse[] PROGMEM = { 0x75, 0x01, /* REPORT_SIZE (1) */ 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - /* X, Y */ + /* X, Y */ 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ 0x09, 0x30, /* USAGE (X) */ 0x09, 0x31, /* USAGE (Y) */ - 0x16, 0x00, 0x80, /* Logical Minimum (-32768) */ - 0x26, 0xFF, 0x7F, /* Logical Maximum (32767) */ - 0x75, 0x10, /* Report Size (16), */ - 0x95, 0x02, /* Report Count (2), */ - 0x81, 0x02, /* Input (Data, Variable, Absolute) */ + 0x16, 0x00, 0x80, /* Logical Minimum (-32768) */ + 0x26, 0xFF, 0x7F, /* Logical Maximum (32767) */ + 0x75, 0x10, /* Report Size (16), */ + 0x95, 0x02, /* Report Count (2), */ + 0x81, 0x02, /* Input (Data, Variable, Absolute) */ - /* Wheel */ + /* Wheel */ 0x09, 0x38, /* USAGE (Wheel) */ 0x15, 0x81, /* LOGICAL_MINIMUM (-127) */ 0x25, 0x7f, /* LOGICAL_MAXIMUM (127) */ @@ -59,96 +59,93 @@ static const uint8_t _hidMultiReportDescriptorAbsoluteMouse[] PROGMEM = { 0x95, 0x01, /* REPORT_COUNT (1) */ 0x81, 0x06, /* INPUT (Data,Var,Rel) */ - /* End */ - 0xc0 /* END_COLLECTION */ + /* End */ + 0xc0 /* END_COLLECTION */ }; -AbsoluteMouse_::AbsoluteMouse_(void) -{ - static HIDSubDescriptor node(_hidMultiReportDescriptorAbsoluteMouse, sizeof(_hidMultiReportDescriptorAbsoluteMouse)); - HID().AppendDescriptor(&node); +AbsoluteMouse_::AbsoluteMouse_(void) { + static HIDSubDescriptor node(_hidMultiReportDescriptorAbsoluteMouse, sizeof(_hidMultiReportDescriptorAbsoluteMouse)); + HID().AppendDescriptor(&node); } -void AbsoluteMouse_::SendReport(void* data, int length) -{ - HID().SendReport(HID_REPORTID_MOUSE_ABSOLUTE, data, length); +void AbsoluteMouse_::SendReport(void* data, int length) { + HID().SendReport(HID_REPORTID_MOUSE_ABSOLUTE, data, length); } -void AbsoluteMouse_::buttons(uint8_t b){ - if (b != _buttons){ - _buttons = b; - moveTo(xAxis, yAxis, 0); - } +void AbsoluteMouse_::buttons(uint8_t b) { + if (b != _buttons) { + _buttons = b; + moveTo(xAxis, yAxis, 0); + } } int16_t AbsoluteMouse_::qadd16(int16_t base, int16_t increment) { - // Separate between subtracting and adding - if (increment < 0) { - // Subtracting more would cause an undefined overflow - if ((int16_t)0x8000 - increment > base) - base = 0x8000; - else - base += increment; - } - else { - // Adding more would cause an undefined overflow - if ((int16_t)0x7FFF - increment < base) - base = 0x7FFF; - else - base += increment; - } - return base; + // Separate between subtracting and adding + if (increment < 0) { + // Subtracting more would cause an undefined overflow + if ((int16_t)0x8000 - increment > base) + base = 0x8000; + else + base += increment; + } else { + // Adding more would cause an undefined overflow + if ((int16_t)0x7FFF - increment < base) + base = 0x7FFF; + else + base += increment; + } + return base; } -void AbsoluteMouse_::begin(void){ - // release all buttons - end(); +void AbsoluteMouse_::begin(void) { + // release all buttons + end(); } -void AbsoluteMouse_::end(void){ - _buttons = 0; - moveTo(xAxis, yAxis, 0); +void AbsoluteMouse_::end(void) { + _buttons = 0; + moveTo(xAxis, yAxis, 0); } -void AbsoluteMouse_::click(uint8_t b){ - _buttons = b; - moveTo(xAxis, yAxis, 0); - _buttons = 0; - moveTo(xAxis, yAxis, 0); +void AbsoluteMouse_::click(uint8_t b) { + _buttons = b; + moveTo(xAxis, yAxis, 0); + _buttons = 0; + moveTo(xAxis, yAxis, 0); } -void AbsoluteMouse_::moveTo(int x, int y, signed char wheel){ - xAxis = x; - yAxis = y; - HID_MouseAbsoluteReport_Data_t report; - report.buttons = _buttons; - report.xAxis = x; - report.yAxis = y; - report.wheel = wheel; - SendReport(&report, sizeof(report)); +void AbsoluteMouse_::moveTo(int x, int y, signed char wheel) { + xAxis = x; + yAxis = y; + HID_MouseAbsoluteReport_Data_t report; + report.buttons = _buttons; + report.xAxis = x; + report.yAxis = y; + report.wheel = wheel; + SendReport(&report, sizeof(report)); } -void AbsoluteMouse_::move(int x, int y, signed char wheel){ - moveTo(qadd16(xAxis, x), qadd16(yAxis, y), wheel); +void AbsoluteMouse_::move(int x, int y, signed char wheel) { + moveTo(qadd16(xAxis, x), qadd16(yAxis, y), wheel); } -void AbsoluteMouse_::press(uint8_t b){ - // press LEFT by default - buttons(_buttons | b); +void AbsoluteMouse_::press(uint8_t b) { + // press LEFT by default + buttons(_buttons | b); } -void AbsoluteMouse_::release(uint8_t b){ - // release LEFT by default - buttons(_buttons & ~b); +void AbsoluteMouse_::release(uint8_t b) { + // release LEFT by default + buttons(_buttons & ~b); } -bool AbsoluteMouse_::isPressed(uint8_t b){ - // check LEFT by default - if ((b & _buttons) > 0) - return true; - return false; +bool AbsoluteMouse_::isPressed(uint8_t b) { + // check LEFT by default + if ((b & _buttons) > 0) + return true; + return false; } diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h index 8c71fca8c5..82a99b7f26 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h @@ -40,43 +40,42 @@ THE SOFTWARE. -typedef union{ - // Absolute mouse report: 8 buttons, 2 absolute axis, wheel - uint8_t whole8[]; - uint16_t whole16[]; - uint32_t whole32[]; - struct{ - uint8_t buttons; - int16_t xAxis; - int16_t yAxis; - int8_t wheel; - }; +typedef union { + // Absolute mouse report: 8 buttons, 2 absolute axis, wheel + uint8_t whole8[]; + uint16_t whole16[]; + uint32_t whole32[]; + struct { + uint8_t buttons; + int16_t xAxis; + int16_t yAxis; + int8_t wheel; + }; } HID_MouseAbsoluteReport_Data_t; -class AbsoluteMouse_ -{ -public: - AbsoluteMouse_(void); - inline void begin(void); - inline void end(void); - - inline void click(uint8_t b = MOUSE_LEFT); - inline void moveTo(int x, int y, signed char wheel = 0); - inline void move(int x, int y, signed char wheel = 0); - inline void press(uint8_t b = MOUSE_LEFT); - inline void release(uint8_t b = MOUSE_LEFT); - inline bool isPressed(uint8_t b = MOUSE_LEFT); - - // Sending is public in the base class for advanced users. - inline void SendReport(void* data, int length); - -protected: - int16_t xAxis; - int16_t yAxis; - uint8_t _buttons; - inline void buttons(uint8_t b); - - inline int16_t qadd16(int16_t base, int16_t increment); +class AbsoluteMouse_ { + public: + AbsoluteMouse_(void); + inline void begin(void); + inline void end(void); + + inline void click(uint8_t b = MOUSE_LEFT); + inline void moveTo(int x, int y, signed char wheel = 0); + inline void move(int x, int y, signed char wheel = 0); + inline void press(uint8_t b = MOUSE_LEFT); + inline void release(uint8_t b = MOUSE_LEFT); + inline bool isPressed(uint8_t b = MOUSE_LEFT); + + // Sending is public in the base class for advanced users. + inline void SendReport(void* data, int length); + + protected: + int16_t xAxis; + int16_t yAxis; + uint8_t _buttons; + inline void buttons(uint8_t b); + + inline int16_t qadd16(int16_t base, int16_t increment); diff --git a/plugins/KeyboardioHID/src/MultiReport/Consumer.cpp b/plugins/KeyboardioHID/src/MultiReport/Consumer.cpp index 645ea88721..47bec50508 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Consumer.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Consumer.cpp @@ -25,72 +25,70 @@ THE SOFTWARE. static const uint8_t _hidMultiReportDescriptorConsumer[] PROGMEM = { - /* Consumer Control (Sound/Media keys) */ - 0x05, 0x0C, /* usage page (consumer device) */ - 0x09, 0x01, /* usage -- consumer control */ - 0xA1, 0x01, /* collection (application) */ - 0x85, HID_REPORTID_CONSUMERCONTROL, /* report id */ - /* 4 Media Keys */ - 0x15, 0x00, /* logical minimum */ - 0x26, 0xFF, 0x03, /* logical maximum (3ff) */ - 0x19, 0x00, /* usage minimum (0) */ - 0x2A, 0xFF, 0x03, /* usage maximum (3ff) */ - 0x95, 0x04, /* report count (4) */ - 0x75, 0x10, /* report size (16) */ - 0x81, 0x00, /* input */ - 0xC0 /* end collection */ + /* Consumer Control (Sound/Media keys) */ + 0x05, 0x0C, /* usage page (consumer device) */ + 0x09, 0x01, /* usage -- consumer control */ + 0xA1, 0x01, /* collection (application) */ + 0x85, HID_REPORTID_CONSUMERCONTROL, /* report id */ + /* 4 Media Keys */ + 0x15, 0x00, /* logical minimum */ + 0x26, 0xFF, 0x03, /* logical maximum (3ff) */ + 0x19, 0x00, /* usage minimum (0) */ + 0x2A, 0xFF, 0x03, /* usage maximum (3ff) */ + 0x95, 0x04, /* report count (4) */ + 0x75, 0x10, /* report size (16) */ + 0x81, 0x00, /* input */ + 0xC0 /* end collection */ }; -Consumer_::Consumer_(void) -{ - static HIDSubDescriptor node(_hidMultiReportDescriptorConsumer, sizeof(_hidMultiReportDescriptorConsumer)); - HID().AppendDescriptor(&node); +Consumer_::Consumer_(void) { + static HIDSubDescriptor node(_hidMultiReportDescriptorConsumer, sizeof(_hidMultiReportDescriptorConsumer)); + HID().AppendDescriptor(&node); } void Consumer_::begin(void) { - // release all buttons - end(); + // release all buttons + end(); } void Consumer_::end(void) { - memset(&_report, 0, sizeof(_report)); - SendReport(&_report, sizeof(_report)); + memset(&_report, 0, sizeof(_report)); + SendReport(&_report, sizeof(_report)); } void Consumer_::write(uint16_t m) { - press(m); - release(m); + press(m); + release(m); } void Consumer_::press(uint16_t m) { - // search for a free spot - for (uint8_t i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { - if (_report.keys[i] == 0x00) { - _report.keys[i] = m; - break; - } - } - SendReport(&_report, sizeof(_report)); + // search for a free spot + for (uint8_t i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { + if (_report.keys[i] == 0x00) { + _report.keys[i] = m; + break; + } + } + SendReport(&_report, sizeof(_report)); } void Consumer_::release(uint16_t m) { - // search and release the keypress - for (uint8_t i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { - if (_report.keys[i] == m) { - _report.keys[i] = 0x00; - // no break to delete multiple keys - } - } - SendReport(&_report, sizeof(_report)); + // search and release the keypress + for (uint8_t i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { + if (_report.keys[i] == m) { + _report.keys[i] = 0x00; + // no break to delete multiple keys + } + } + SendReport(&_report, sizeof(_report)); } void Consumer_::releaseAll(void) { - end(); + end(); } -void Consumer_::SendReport(void* data, int length) -{ - HID().SendReport(HID_REPORTID_CONSUMERCONTROL, data, length); +void Consumer_::SendReport(void* data, int length) { + HID().SendReport(HID_REPORTID_CONSUMERCONTROL, data, length); } Consumer_ Consumer; diff --git a/plugins/KeyboardioHID/src/MultiReport/Consumer.h b/plugins/KeyboardioHID/src/MultiReport/Consumer.h index 395d289aa6..c261a530de 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Consumer.h +++ b/plugins/KeyboardioHID/src/MultiReport/Consumer.h @@ -30,36 +30,35 @@ THE SOFTWARE. #include "HID-Settings.h" typedef union { - // Every usable Consumer key possible, up to 4 keys presses possible - uint8_t whole8[]; - uint16_t whole16[]; - uint32_t whole32[]; - uint16_t keys[4]; - struct { - uint16_t key1; - uint16_t key2; - uint16_t key3; - uint16_t key4; - }; + // Every usable Consumer key possible, up to 4 keys presses possible + uint8_t whole8[]; + uint16_t whole16[]; + uint32_t whole32[]; + uint16_t keys[4]; + struct { + uint16_t key1; + uint16_t key2; + uint16_t key3; + uint16_t key4; + }; } HID_ConsumerControlReport_Data_t; -class Consumer_ -{ -public: +class Consumer_ { + public: Consumer_(void); - inline void begin(void); - inline void end(void); - inline void write(uint16_t m); - inline void press(uint16_t m); - inline void release(uint16_t m); - inline void releaseAll(void); - - // Sending is public in the base class for advanced users. - void SendReport(void* data, int length); + inline void begin(void); + inline void end(void); + inline void write(uint16_t m); + inline void press(uint16_t m); + inline void release(uint16_t m); + inline void releaseAll(void); + // Sending is public in the base class for advanced users. + void SendReport(void* data, int length); -protected: - HID_ConsumerControlReport_Data_t _report; + + protected: + HID_ConsumerControlReport_Data_t _report; }; extern Consumer_ Consumer; diff --git a/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp b/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp index e97ae8270a..c4e2eefa1f 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp @@ -25,137 +25,135 @@ THE SOFTWARE. static const uint8_t _hidMultiReportDescriptorGamepad[] PROGMEM = { - /* Gamepad with 32 buttons and 6 axis*/ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ - 0x09, 0x04, /* USAGE (Joystick) */ - 0xa1, 0x01, /* COLLECTION (Application) */ - 0x85, HID_REPORTID_GAMEPAD, /* REPORT_ID */ - /* 32 Buttons */ - 0x05, 0x09, /* USAGE_PAGE (Button) */ - 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ - 0x29, 0x20, /* USAGE_MAXIMUM (Button 32) */ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ - 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ - 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x95, 0x20, /* REPORT_COUNT (32) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - /* 4 16bit Axis */ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ - 0xa1, 0x00, /* COLLECTION (Physical) */ - 0x09, 0x30, /* USAGE (X) */ - 0x09, 0x31, /* USAGE (Y) */ - 0x09, 0x33, /* USAGE (Rx) */ - 0x09, 0x34, /* USAGE (Ry) */ - 0x16, 0x00, 0x80, /* LOGICAL_MINIMUM (-32768) */ - 0x26, 0xFF, 0x7F, /* LOGICAL_MAXIMUM (32767) */ - 0x75, 0x10, /* REPORT_SIZE (16) */ - 0x95, 0x04, /* REPORT_COUNT (4) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - /* 2 8bit Axis */ - 0x09, 0x32, /* USAGE (Z) */ - 0x09, 0x35, /* USAGE (Rz) */ - 0x15, 0x80, /* LOGICAL_MINIMUM (-128) */ - 0x25, 0x7F, /* LOGICAL_MAXIMUM (127) */ - 0x75, 0x08, /* REPORT_SIZE (8) */ - 0x95, 0x02, /* REPORT_COUNT (2) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - 0xc0, /* END_COLLECTION */ - /* 2 Hat Switches */ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ - 0x09, 0x39, /* USAGE (Hat switch) */ - 0x09, 0x39, /* USAGE (Hat switch) */ - 0x15, 0x01, /* LOGICAL_MINIMUM (1) */ - 0x25, 0x08, /* LOGICAL_MAXIMUM (8) */ - 0x95, 0x02, /* REPORT_COUNT (2) */ - 0x75, 0x04, /* REPORT_SIZE (4) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - 0xc0 /* END_COLLECTION */ + /* Gamepad with 32 buttons and 6 axis*/ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x04, /* USAGE (Joystick) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + 0x85, HID_REPORTID_GAMEPAD, /* REPORT_ID */ + /* 32 Buttons */ + 0x05, 0x09, /* USAGE_PAGE (Button) */ + 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ + 0x29, 0x20, /* USAGE_MAXIMUM (Button 32) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x95, 0x20, /* REPORT_COUNT (32) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + /* 4 16bit Axis */ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0xa1, 0x00, /* COLLECTION (Physical) */ + 0x09, 0x30, /* USAGE (X) */ + 0x09, 0x31, /* USAGE (Y) */ + 0x09, 0x33, /* USAGE (Rx) */ + 0x09, 0x34, /* USAGE (Ry) */ + 0x16, 0x00, 0x80, /* LOGICAL_MINIMUM (-32768) */ + 0x26, 0xFF, 0x7F, /* LOGICAL_MAXIMUM (32767) */ + 0x75, 0x10, /* REPORT_SIZE (16) */ + 0x95, 0x04, /* REPORT_COUNT (4) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + /* 2 8bit Axis */ + 0x09, 0x32, /* USAGE (Z) */ + 0x09, 0x35, /* USAGE (Rz) */ + 0x15, 0x80, /* LOGICAL_MINIMUM (-128) */ + 0x25, 0x7F, /* LOGICAL_MAXIMUM (127) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x02, /* REPORT_COUNT (2) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + 0xc0, /* END_COLLECTION */ + /* 2 Hat Switches */ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x39, /* USAGE (Hat switch) */ + 0x09, 0x39, /* USAGE (Hat switch) */ + 0x15, 0x01, /* LOGICAL_MINIMUM (1) */ + 0x25, 0x08, /* LOGICAL_MAXIMUM (8) */ + 0x95, 0x02, /* REPORT_COUNT (2) */ + 0x75, 0x04, /* REPORT_SIZE (4) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + 0xc0 /* END_COLLECTION */ }; -Gamepad_::Gamepad_(void) -{ - static HIDSubDescriptor node(_hidMultiReportDescriptorGamepad, sizeof(_hidMultiReportDescriptorGamepad)); - HID().AppendDescriptor(&node); +Gamepad_::Gamepad_(void) { + static HIDSubDescriptor node(_hidMultiReportDescriptorGamepad, sizeof(_hidMultiReportDescriptorGamepad)); + HID().AppendDescriptor(&node); } -void Gamepad_::begin(void){ - // release all buttons - end(); +void Gamepad_::begin(void) { + // release all buttons + end(); } -void Gamepad_::end(void){ - memset(&_report, 0x00, sizeof(_report)); - SendReport(&_report, sizeof(_report)); +void Gamepad_::end(void) { + memset(&_report, 0x00, sizeof(_report)); + SendReport(&_report, sizeof(_report)); } -void Gamepad_::write(void){ - SendReport(&_report, sizeof(_report)); +void Gamepad_::write(void) { + SendReport(&_report, sizeof(_report)); } -void Gamepad_::press(uint8_t b){ - _report.buttons |= (uint32_t)1 << (b - 1); +void Gamepad_::press(uint8_t b) { + _report.buttons |= (uint32_t)1 << (b - 1); } -void Gamepad_::release(uint8_t b){ - _report.buttons &= ~((uint32_t)1 << (b - 1)); +void Gamepad_::release(uint8_t b) { + _report.buttons &= ~((uint32_t)1 << (b - 1)); } -void Gamepad_::releaseAll(void){ - memset(&_report, 0x00, sizeof(_report)); +void Gamepad_::releaseAll(void) { + memset(&_report, 0x00, sizeof(_report)); } -void Gamepad_::buttons(uint32_t b){ - _report.buttons = b; +void Gamepad_::buttons(uint32_t b) { + _report.buttons = b; } -void Gamepad_::xAxis(int16_t a){ - _report.xAxis = a; +void Gamepad_::xAxis(int16_t a) { + _report.xAxis = a; } -void Gamepad_::yAxis(int16_t a){ - _report.yAxis = a; +void Gamepad_::yAxis(int16_t a) { + _report.yAxis = a; } -void Gamepad_::zAxis(int8_t a){ - _report.zAxis = a; +void Gamepad_::zAxis(int8_t a) { + _report.zAxis = a; } -void Gamepad_::rxAxis(int16_t a){ - _report.rxAxis = a; +void Gamepad_::rxAxis(int16_t a) { + _report.rxAxis = a; } -void Gamepad_::ryAxis(int16_t a){ - _report.ryAxis = a; +void Gamepad_::ryAxis(int16_t a) { + _report.ryAxis = a; } -void Gamepad_::rzAxis(int8_t a){ - _report.rzAxis = a; +void Gamepad_::rzAxis(int8_t a) { + _report.rzAxis = a; } -void Gamepad_::dPad1(int8_t d){ - _report.dPad1 = d; +void Gamepad_::dPad1(int8_t d) { + _report.dPad1 = d; } -void Gamepad_::dPad2(int8_t d){ - _report.dPad2 = d; +void Gamepad_::dPad2(int8_t d) { + _report.dPad2 = d; } -void Gamepad_::SendReport(void* data, int length) -{ - HID().SendReport(HID_REPORTID_GAMEPAD, data, length); +void Gamepad_::SendReport(void* data, int length) { + HID().SendReport(HID_REPORTID_GAMEPAD, data, length); } Gamepad_ Gamepad; diff --git a/plugins/KeyboardioHID/src/MultiReport/Gamepad.h b/plugins/KeyboardioHID/src/MultiReport/Gamepad.h index a9f2ac90a6..5384f71202 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Gamepad.h +++ b/plugins/KeyboardioHID/src/MultiReport/Gamepad.h @@ -42,88 +42,87 @@ THE SOFTWARE. typedef union { - // 32 Buttons, 6 Axis, 2 D-Pads - uint8_t whole8[]; - uint16_t whole16[]; - uint32_t whole32[]; - uint32_t buttons; - - struct{ - uint8_t button1 : 1; - uint8_t button2 : 1; - uint8_t button3 : 1; - uint8_t button4 : 1; - uint8_t button5 : 1; - uint8_t button6 : 1; - uint8_t button7 : 1; - uint8_t button8 : 1; - - uint8_t button9 : 1; - uint8_t button10 : 1; - uint8_t button11 : 1; - uint8_t button12 : 1; - uint8_t button13 : 1; - uint8_t button14 : 1; - uint8_t button15 : 1; - uint8_t button16 : 1; - - uint8_t button17 : 1; - uint8_t button18 : 1; - uint8_t button19 : 1; - uint8_t button20 : 1; - uint8_t button21 : 1; - uint8_t button22 : 1; - uint8_t button23 : 1; - uint8_t button24 : 1; - - uint8_t button25 : 1; - uint8_t button26 : 1; - uint8_t button27 : 1; - uint8_t button28 : 1; - uint8_t button29 : 1; - uint8_t button30 : 1; - uint8_t button31 : 1; - uint8_t button32 : 1; - - int16_t xAxis; - int16_t yAxis; - - int16_t rxAxis; - int16_t ryAxis; - - int8_t zAxis; - int8_t rzAxis; - - uint8_t dPad1 : 4; - uint8_t dPad2 : 4; - }; + // 32 Buttons, 6 Axis, 2 D-Pads + uint8_t whole8[]; + uint16_t whole16[]; + uint32_t whole32[]; + uint32_t buttons; + + struct { + uint8_t button1 : 1; + uint8_t button2 : 1; + uint8_t button3 : 1; + uint8_t button4 : 1; + uint8_t button5 : 1; + uint8_t button6 : 1; + uint8_t button7 : 1; + uint8_t button8 : 1; + + uint8_t button9 : 1; + uint8_t button10 : 1; + uint8_t button11 : 1; + uint8_t button12 : 1; + uint8_t button13 : 1; + uint8_t button14 : 1; + uint8_t button15 : 1; + uint8_t button16 : 1; + + uint8_t button17 : 1; + uint8_t button18 : 1; + uint8_t button19 : 1; + uint8_t button20 : 1; + uint8_t button21 : 1; + uint8_t button22 : 1; + uint8_t button23 : 1; + uint8_t button24 : 1; + + uint8_t button25 : 1; + uint8_t button26 : 1; + uint8_t button27 : 1; + uint8_t button28 : 1; + uint8_t button29 : 1; + uint8_t button30 : 1; + uint8_t button31 : 1; + uint8_t button32 : 1; + + int16_t xAxis; + int16_t yAxis; + + int16_t rxAxis; + int16_t ryAxis; + + int8_t zAxis; + int8_t rzAxis; + + uint8_t dPad1 : 4; + uint8_t dPad2 : 4; + }; } HID_GamepadReport_Data_t; -class Gamepad_ -{ -public: +class Gamepad_ { + public: Gamepad_(void); - inline void begin(void); - inline void end(void); - inline void write(void); - inline void press(uint8_t b); - inline void release(uint8_t b); - inline void releaseAll(void); - - inline void buttons(uint32_t b); - inline void xAxis(int16_t a); - inline void yAxis(int16_t a); - inline void zAxis(int8_t a); - inline void rxAxis(int16_t a); - inline void ryAxis(int16_t a); - inline void rzAxis(int8_t a); - inline void dPad1(int8_t d); - inline void dPad2(int8_t d); - - inline void SendReport(void* data, int length); -protected: - HID_GamepadReport_Data_t _report; + inline void begin(void); + inline void end(void); + inline void write(void); + inline void press(uint8_t b); + inline void release(uint8_t b); + inline void releaseAll(void); + + inline void buttons(uint32_t b); + inline void xAxis(int16_t a); + inline void yAxis(int16_t a); + inline void zAxis(int8_t a); + inline void rxAxis(int16_t a); + inline void ryAxis(int16_t a); + inline void rzAxis(int8_t a); + inline void dPad1(int8_t d); + inline void dPad2(int8_t d); + + inline void SendReport(void* data, int length); + protected: + HID_GamepadReport_Data_t _report; }; extern Gamepad_ Gamepad; diff --git a/plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.cpp b/plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.cpp index 54bb1db110..ec355b0a96 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.cpp @@ -25,13 +25,13 @@ THE SOFTWARE. static const uint8_t _hidMultiReportDescriptorMouse[] PROGMEM = { - /* Mouse relative */ + /* Mouse relative */ 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 54 */ 0x09, 0x02, /* USAGE (Mouse) */ 0xa1, 0x01, /* COLLECTION (Application) */ 0x85, HID_REPORTID_MOUSE, /* REPORT_ID */ - /* 8 Buttons */ + /* 8 Buttons */ 0x05, 0x09, /* USAGE_PAGE (Button) */ 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ 0x29, 0x08, /* USAGE_MAXIMUM (Button 8) */ @@ -41,7 +41,7 @@ static const uint8_t _hidMultiReportDescriptorMouse[] PROGMEM = { 0x75, 0x01, /* REPORT_SIZE (1) */ 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - /* X, Y, Wheel */ + /* X, Y, Wheel */ 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ 0x09, 0x30, /* USAGE (X) */ 0x09, 0x31, /* USAGE (Y) */ @@ -52,76 +52,65 @@ static const uint8_t _hidMultiReportDescriptorMouse[] PROGMEM = { 0x95, 0x03, /* REPORT_COUNT (3) */ 0x81, 0x06, /* INPUT (Data,Var,Rel) */ - /* End */ + /* End */ 0xc0 /* END_COLLECTION */ }; -Mouse_::Mouse_(void) -{ - static HIDSubDescriptor node(_hidMultiReportDescriptorMouse, sizeof(_hidMultiReportDescriptorMouse)); - HID().AppendDescriptor(&node); +Mouse_::Mouse_(void) { + static HIDSubDescriptor node(_hidMultiReportDescriptorMouse, sizeof(_hidMultiReportDescriptorMouse)); + HID().AppendDescriptor(&node); } -void Mouse_::begin(void) -{ +void Mouse_::begin(void) { end(); } -void Mouse_::end(void) -{ +void Mouse_::end(void) { _buttons = 0; move(0, 0, 0); } -void Mouse_::click(uint8_t b) -{ - _buttons = b; - move(0,0,0); - _buttons = 0; - move(0,0,0); +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) -{ - HID_MouseReport_Data_t report; - report.buttons = _buttons; - report.xAxis = x; - report.yAxis = y; - report.wheel = wheel; - SendReport(&report, sizeof(report)); +void Mouse_::move(signed char x, signed char y, signed char wheel) { + HID_MouseReport_Data_t report; + report.buttons = _buttons; + report.xAxis = x; + report.yAxis = y; + report.wheel = wheel; + SendReport(&report, sizeof(report)); } -void Mouse_::buttons(uint8_t b) -{ - if (b != _buttons) - { - _buttons = b; - move(0,0,0); - } +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_::press(uint8_t b) { + buttons(_buttons | b); } -void Mouse_::release(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; +bool Mouse_::isPressed(uint8_t b) { + if ((b & _buttons) > 0) + return true; + return false; } -void Mouse_::SendReport(void* data, int length) -{ - HID().SendReport(HID_REPORTID_MOUSE, data, length); +void Mouse_::SendReport(void* data, int length) { + HID().SendReport(HID_REPORTID_MOUSE, data, length); } Mouse_ Mouse; diff --git a/plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.h b/plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.h index 0ed46b6992..e1e7acd5be 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.h @@ -38,36 +38,35 @@ THE SOFTWARE. // but the last 3 wont do anything from what I tested #define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE | MOUSE_PREV | MOUSE_NEXT) -typedef union{ - // Mouse report: 8 buttons, position, wheel - uint8_t whole8[]; - uint16_t whole16[]; - uint32_t whole32[]; - struct{ - uint8_t buttons; - int8_t xAxis; - int8_t yAxis; - int8_t wheel; - }; +typedef union { + // Mouse report: 8 buttons, position, wheel + uint8_t whole8[]; + uint16_t whole16[]; + uint32_t whole32[]; + struct { + uint8_t buttons; + int8_t xAxis; + int8_t yAxis; + int8_t wheel; + }; } HID_MouseReport_Data_t; -class Mouse_ -{ -public: +class Mouse_ { + public: Mouse_(void); - inline void begin(void); - inline void end(void); - inline void click(uint8_t b = MOUSE_LEFT); - inline void move(signed char x, signed char y, signed char wheel = 0); - inline void press(uint8_t b = MOUSE_LEFT); // press LEFT by default - inline void release(uint8_t b = MOUSE_LEFT); // release LEFT by default - inline bool isPressed(uint8_t b = MOUSE_LEFT); // check LEFT by default - - inline void SendReport(void* data, int length); + inline void begin(void); + inline void end(void); + inline void click(uint8_t b = MOUSE_LEFT); + inline void move(signed char x, signed char y, signed char wheel = 0); + inline void press(uint8_t b = MOUSE_LEFT); // press LEFT by default + inline void release(uint8_t b = MOUSE_LEFT); // release LEFT by default + inline bool isPressed(uint8_t b = MOUSE_LEFT); // check LEFT by default -protected: - uint8_t _buttons; - inline void buttons(uint8_t b); + inline void SendReport(void* data, int length); + + protected: + uint8_t _buttons; + inline void buttons(uint8_t b); }; extern Mouse_ Mouse; diff --git a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp index 2516ad3ee9..de774016b9 100644 --- a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp @@ -37,17 +37,17 @@ static const uint8_t _hidMultiReportDescriptorNKROKeyboard[] PROGMEM = { 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x95, 0x08, /* REPORT_COUNT (8) */ + 0x95, 0x08, /* REPORT_COUNT (8) */ 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - /* 104 Keys as bitmap */ - 0x19, 0x00, /* Usage Minimum (0) */ - 0x29, NKRO_KEY_COUNT - 1, /* Usage Maximum (103) */ - 0x15, 0x00, /* Logical Minimum (0) */ - 0x25, 0x01, /* Logical Maximum (1) */ - 0x75, 0x01, /* Report Size (1) */ - 0x95, NKRO_KEY_COUNT, /* Report Count (104) */ - 0x81, 0x02, /* Input (Data, Variable, Absolute) */ + /* 104 Keys as bitmap */ + 0x19, 0x00, /* Usage Minimum (0) */ + 0x29, NKRO_KEY_COUNT - 1, /* Usage Maximum (103) */ + 0x15, 0x00, /* Logical Minimum (0) */ + 0x25, 0x01, /* Logical Maximum (1) */ + 0x75, 0x01, /* Report Size (1) */ + 0x95, NKRO_KEY_COUNT, /* Report Count (104) */ + 0x81, 0x02, /* Input (Data, Variable, Absolute) */ /* 1 Custom Keyboard key */ 0x95, 0x01, /* REPORT_COUNT (1) */ @@ -59,127 +59,116 @@ static const uint8_t _hidMultiReportDescriptorNKROKeyboard[] PROGMEM = { 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ /* End */ - 0xC0 /* End Collection */ + 0xC0 /* End Collection */ }; -NKROKeyboard_::NKROKeyboard_(void) -{ - static HIDSubDescriptor node(_hidMultiReportDescriptorNKROKeyboard, sizeof(_hidMultiReportDescriptorNKROKeyboard)); - HID().AppendDescriptor(&node); +NKROKeyboard_::NKROKeyboard_(void) { + static HIDSubDescriptor node(_hidMultiReportDescriptorNKROKeyboard, sizeof(_hidMultiReportDescriptorNKROKeyboard)); + HID().AppendDescriptor(&node); } -void NKROKeyboard_::begin(void) -{ - // Force API to send a clean report. - // This is important for and HID bridge where the receiver stays on, - // while the sender is resetted. - releaseAll(); - sendReport(); +void NKROKeyboard_::begin(void) { + // Force API to send a clean report. + // This is important for and HID bridge where the receiver stays on, + // while the sender is resetted. + releaseAll(); + sendReport(); } -void NKROKeyboard_::end(void) -{ - releaseAll(); - sendReport(); +void NKROKeyboard_::end(void) { + releaseAll(); + sendReport(); } -int NKROKeyboard_::sendReport(void) -{ - return HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &_keyReport, sizeof(_keyReport)); +int NKROKeyboard_::sendReport(void) { + return HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &_keyReport, sizeof(_keyReport)); } -size_t NKROKeyboard_::press(uint8_t k) -{ - // Press keymap key - if (k < NKRO_KEY_COUNT){ - uint8_t bit = 1 << (uint8_t(k) % 8); - _keyReport.keys[k / 8] |= bit; - return 1; - } - - // It's a modifier key - else if(k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) - { - // Convert key into bitfield (0 - 7) - k = uint8_t(k) - uint8_t(HID_KEYBOARD_FIRST_MODIFIER); - _keyReport.modifiers = (1 << k); - return 1; - } - - // Its a custom key (outside our keymap) - else{ - // Add k to the key report only if it's not already present - // and if there is an empty slot. Remove the first available key. - auto key = _keyReport.key; - - // Is key already in the list or did we found an empty slot? - if ((key == uint8_t(k) || key == 0x00)) { - _keyReport.key = k; - return 1; - } - } - - // No empty/pressed key was found - return 0; +size_t NKROKeyboard_::press(uint8_t k) { + // Press keymap key + if (k < NKRO_KEY_COUNT) { + uint8_t bit = 1 << (uint8_t(k) % 8); + _keyReport.keys[k / 8] |= bit; + return 1; + } + + // It's a modifier key + else if(k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { + // Convert key into bitfield (0 - 7) + k = uint8_t(k) - uint8_t(HID_KEYBOARD_FIRST_MODIFIER); + _keyReport.modifiers = (1 << k); + return 1; + } + + // Its a custom key (outside our keymap) + else { + // Add k to the key report only if it's not already present + // and if there is an empty slot. Remove the first available key. + auto key = _keyReport.key; + + // Is key already in the list or did we found an empty slot? + if ((key == uint8_t(k) || key == 0x00)) { + _keyReport.key = k; + return 1; + } + } + + // No empty/pressed key was found + return 0; } -size_t NKROKeyboard_::release(uint8_t k) -{ - // Press keymap key - if (k < NKRO_KEY_COUNT){ - uint8_t bit = 1 << (uint8_t(k) % 8); - _keyReport.keys[k / 8] &= ~bit; - return 1; - } - - // It's a modifier key - else if(k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) - { - // Convert key into bitfield (0 - 7) - k = k - HID_KEYBOARD_FIRST_MODIFIER; - _keyReport.modifiers &= ~(1 << k); - return 1; - } - - // Its a custom key (outside our keymap) - else{ - // Add k to the key report only if it's not already present - // and if there is an empty slot. Remove the first available key. - auto key = _keyReport.key; - - // Test the key report to see if k is present. Clear it if it exists. - if (key == k) { - _keyReport.key = 0x00; - return 1; - } - } - - // No empty/pressed key was found - return 0; +size_t NKROKeyboard_::release(uint8_t k) { + // Press keymap key + if (k < NKRO_KEY_COUNT) { + uint8_t bit = 1 << (uint8_t(k) % 8); + _keyReport.keys[k / 8] &= ~bit; + return 1; + } + + // It's a modifier key + else if(k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { + // Convert key into bitfield (0 - 7) + k = k - HID_KEYBOARD_FIRST_MODIFIER; + _keyReport.modifiers &= ~(1 << k); + return 1; + } + + // Its a custom key (outside our keymap) + else { + // Add k to the key report only if it's not already present + // and if there is an empty slot. Remove the first available key. + auto key = _keyReport.key; + + // Test the key report to see if k is present. Clear it if it exists. + if (key == k) { + _keyReport.key = 0x00; + return 1; + } + } + + // No empty/pressed key was found + return 0; } // TODO: replace this with a mmap interface -size_t NKROKeyboard_::releaseAll(void) -{ - // Release all keys - size_t ret = 0; - for (uint8_t i = 0; i < sizeof(_keyReport.allkeys); i++) - { - // Is a key in the list or did we found an empty slot? - auto bits = _keyReport.allkeys[i]; - do { - if(bits & 0x01){ - ret++; - } - bits >>=1; - } - while(bits); - _keyReport.allkeys[i] = 0x00; - } - return ret; +size_t NKROKeyboard_::releaseAll(void) { + // Release all keys + size_t ret = 0; + for (uint8_t i = 0; i < sizeof(_keyReport.allkeys); i++) { + // Is a key in the list or did we found an empty slot? + auto bits = _keyReport.allkeys[i]; + do { + if(bits & 0x01) { + ret++; + } + bits >>=1; + } while(bits); + _keyReport.allkeys[i] = 0x00; + } + return ret; } NKROKeyboard_ NKROKeyboard; diff --git a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h index c75f0ddf80..0867c3b526 100644 --- a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h @@ -36,34 +36,33 @@ THE SOFTWARE. // +1 reportID, +1 modifier, +1 custom key #define NKRO_KEY_COUNT (8*13) -typedef union{ - // Modifier + keymap + 1 custom key - uint8_t whole8[]; - uint16_t whole16[]; - uint32_t whole32[]; - struct{ - uint8_t modifiers; - uint8_t keys[NKRO_KEY_COUNT / 8]; - uint8_t key; - }; - uint8_t allkeys[2 + NKRO_KEY_COUNT / 8]; +typedef union { + // Modifier + keymap + 1 custom key + uint8_t whole8[]; + uint16_t whole16[]; + uint32_t whole32[]; + struct { + uint8_t modifiers; + uint8_t keys[NKRO_KEY_COUNT / 8]; + uint8_t key; + }; + uint8_t allkeys[2 + NKRO_KEY_COUNT / 8]; } HID_NKROKeyboardReport_Data_t; -class NKROKeyboard_ -{ -public: +class NKROKeyboard_ { + public: NKROKeyboard_(void); - inline void begin(void); - inline void end(void); - - inline size_t press(uint8_t k); - inline size_t release(uint8_t k); - inline size_t releaseAll(void); - inline int sendReport(void); -protected: - HID_NKROKeyboardReport_Data_t _keyReport; + inline void begin(void); + inline void end(void); + + inline size_t press(uint8_t k); + inline size_t release(uint8_t k); + inline size_t releaseAll(void); + inline int sendReport(void); + protected: + HID_NKROKeyboardReport_Data_t _keyReport; }; extern NKROKeyboard_ NKROKeyboard; diff --git a/plugins/KeyboardioHID/src/MultiReport/System.cpp b/plugins/KeyboardioHID/src/MultiReport/System.cpp index abc00db089..394145a729 100644 --- a/plugins/KeyboardioHID/src/MultiReport/System.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/System.cpp @@ -25,63 +25,61 @@ THE SOFTWARE. static const uint8_t _hidMultiReportDescriptorSystem[] PROGMEM = { - //TODO limit to system keys only? - /* System Control (Power Down, Sleep, Wakeup, ...) */ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ - 0x09, 0x80, /* USAGE (System Control) */ - 0xa1, 0x01, /* COLLECTION (Application) */ - 0x85, HID_REPORTID_SYSTEMCONTROL, /* REPORT_ID */ - /* 1 system key */ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ - 0x26, 0xff, 0x00, /* LOGICAL_MAXIMUM (255) */ - 0x19, 0x00, /* USAGE_MINIMUM (Undefined) */ - 0x29, 0xff, /* USAGE_MAXIMUM (System Menu Down) */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0x75, 0x08, /* REPORT_SIZE (8) */ - 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ - 0xc0 /* END_COLLECTION */ + //TODO limit to system keys only? + /* System Control (Power Down, Sleep, Wakeup, ...) */ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x80, /* USAGE (System Control) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + 0x85, HID_REPORTID_SYSTEMCONTROL, /* REPORT_ID */ + /* 1 system key */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x26, 0xff, 0x00, /* LOGICAL_MAXIMUM (255) */ + 0x19, 0x00, /* USAGE_MINIMUM (Undefined) */ + 0x29, 0xff, /* USAGE_MAXIMUM (System Menu Down) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ + 0xc0 /* END_COLLECTION */ }; -System_::System_(void) -{ - static HIDSubDescriptor node(_hidMultiReportDescriptorSystem, sizeof(_hidMultiReportDescriptorSystem)); - HID().AppendDescriptor(&node); +System_::System_(void) { + static HIDSubDescriptor node(_hidMultiReportDescriptorSystem, sizeof(_hidMultiReportDescriptorSystem)); + HID().AppendDescriptor(&node); } -void System_::begin(void){ - // release all buttons - end(); +void System_::begin(void) { + // release all buttons + end(); } -void System_::end(void){ - uint8_t _report = 0x00; - SendReport(&_report, sizeof(_report)); +void System_::end(void) { + uint8_t _report = 0x00; + SendReport(&_report, sizeof(_report)); } -void System_::write(uint8_t s){ - press(s); - release(); +void System_::write(uint8_t s) { + press(s); + release(); } -void System_::release(void){ - begin(); +void System_::release(void) { + begin(); } -void System_::releaseAll(void){ - begin(); +void System_::releaseAll(void) { + begin(); } -void System_::press(uint8_t s){ - if (s == HID_SYSTEM_WAKE_UP) - USBDevice.wakeupHost(); - else - SendReport(&s, sizeof(s)); +void System_::press(uint8_t s) { + if (s == HID_SYSTEM_WAKE_UP) + USBDevice.wakeupHost(); + else + SendReport(&s, sizeof(s)); } -void System_::SendReport(void* data, int length) -{ - HID().SendReport(HID_REPORTID_SYSTEMCONTROL, data, length); +void System_::SendReport(void* data, int length) { + HID().SendReport(HID_REPORTID_SYSTEMCONTROL, data, length); } System_ System; diff --git a/plugins/KeyboardioHID/src/MultiReport/System.h b/plugins/KeyboardioHID/src/MultiReport/System.h index 19d6138f0f..228a16323e 100644 --- a/plugins/KeyboardioHID/src/MultiReport/System.h +++ b/plugins/KeyboardioHID/src/MultiReport/System.h @@ -30,27 +30,26 @@ THE SOFTWARE. #include "HID-Settings.h" #include "HIDTables.h" -typedef union{ - // Every usable system control key possible - uint8_t whole8[]; - uint8_t key; +typedef union { + // Every usable system control key possible + uint8_t whole8[]; + uint8_t key; } HID_SystemControlReport_Data_t; -class System_ -{ -public: - inline void begin(void); - inline void end(void); - inline void write(uint8_t s); - inline void press(uint8_t s); - inline void release(void); - inline void releaseAll(void); - inline void SendReport(void* data, int length); - +class System_ { + public: + inline void begin(void); + inline void end(void); + inline void write(uint8_t s); + inline void press(uint8_t s); + inline void release(void); + inline void releaseAll(void); + inline void SendReport(void* data, int length); + System_(void); -protected: + protected: }; From d990a54381624b9aaedbc378c1a73eddd935ea17 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 23:13:18 -0800 Subject: [PATCH 409/602] Fix a couple bad HID Aliases --- plugins/KeyboardioHID/src/HIDAliases.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/KeyboardioHID/src/HIDAliases.h b/plugins/KeyboardioHID/src/HIDAliases.h index 6cee7cb7a8..accc54726c 100644 --- a/plugins/KeyboardioHID/src/HIDAliases.h +++ b/plugins/KeyboardioHID/src/HIDAliases.h @@ -45,7 +45,7 @@ #define KEY_0 HID_KEYBOARD_0_AND_RIGHT_PAREN #define KEY_ENTER HID_KEYBOARD_ENTER // (MARKED AS ENTER_SLASH_RETURN) #define KEY_ESC HID_KEYBOARD_ESCAPE -#define KEY_DEL HID_KEYBOARD_DELETE // (BACKSPACE) +#define KEY_BACKSPACE HID_KEYBOARD_DELETE // (BACKSPACE) #define KEY_TAB HID_KEYBOARD_TAB #define KEY_SPACE HID_KEYBOARD_SPACEBAR #define KEY_MINUS HID_KEYBOARD_MINUS_AND_UNDERSCORE // (UNDERSCORE) @@ -86,7 +86,7 @@ #define KEY_LARROW HID_KEYBOARD_LEFTARROW #define KEY_DARROW HID_KEYBOARD_DOWNARROW #define KEY_UARROW HID_KEYBOARD_UPARROW -#define KEY_BACKSLASH HID_KEYBOARD_NON_US_BACKSLASH_AND_PIPE +#define KEY_NONUS_BACKSLASH HID_KEYBOARD_NON_US_BACKSLASH_AND_PIPE #define KEY_APP HID_KEYBOARD_APPLICATION #define KEY_PWR HID_KEYBOARD_POWER #define KEY_F13 HID_KEYBOARD_F13 From 386280f2e09b7cdaf2f3c1d36e9fa526a7e9ff0b Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 23:26:00 -0800 Subject: [PATCH 410/602] Now that we have a working ASCII map, port it to both keyboard variants. We finally have code that could sort of use the KeyboardAPI abstraction from Nico's original code, but there's not a lot of it --- plugins/KeyboardioHID/src/ASCIIMap.h | 138 ++++++++++++++++++ .../src/BootKeyboard/BootKeyboard.cpp | 21 ++- .../src/BootKeyboard/BootKeyboard.h | 2 +- .../src/MultiReport/NKROKeyboard.cpp | 19 +++ .../src/MultiReport/NKROKeyboard.h | 3 + 5 files changed, 175 insertions(+), 8 deletions(-) create mode 100644 plugins/KeyboardioHID/src/ASCIIMap.h diff --git a/plugins/KeyboardioHID/src/ASCIIMap.h b/plugins/KeyboardioHID/src/ASCIIMap.h new file mode 100644 index 0000000000..325e00f09b --- /dev/null +++ b/plugins/KeyboardioHID/src/ASCIIMap.h @@ -0,0 +1,138 @@ +#pragma once + +// Abuse the upper half of the ascii range to indicate +// shifted characters + +#define SHIFT 0x80 +#define NO_KEY 0x00 +static const uint8_t _asciimap[] PROGMEM = { + NO_KEY, // NUL + NO_KEY, // SOH + NO_KEY, // STX + NO_KEY, // ETX + NO_KEY, // EOT + NO_KEY, // ENQ + NO_KEY, // ACK + NO_KEY, // BEL + KEY_BACKSPACE, // BS Backspace + KEY_TAB, // TAB Tab + KEY_ENTER, // LF Enter + NO_KEY, // VT + NO_KEY, // FF + NO_KEY, // CR + NO_KEY, // SO + NO_KEY, // SI + NO_KEY, // DEL + NO_KEY, // DC1 + NO_KEY, // DC2 + NO_KEY, // DC3 + NO_KEY, // DC4 + NO_KEY, // NAK + NO_KEY, // SYN + NO_KEY, // ETB + NO_KEY, // CAN + NO_KEY, // EM + NO_KEY, // SUB + NO_KEY, // ESC + NO_KEY, // FS + NO_KEY, // GS + NO_KEY, // RS + NO_KEY, // US + + KEY_SPACE, // ' ' Space + KEY_1|SHIFT, // ! + KEY_QUOTE|SHIFT, // " + KEY_3|SHIFT, // # + KEY_4|SHIFT, // $ + KEY_5|SHIFT, // % + KEY_7|SHIFT, // & + KEY_QUOTE, // ' + KEY_9|SHIFT, // ( + KEY_0|SHIFT, // ) + KEY_8|SHIFT, // * + KEY_EQUALS|SHIFT, // + + KEY_COMMA, // , + KEY_MINUS, // - + KEY_PERIOD, // . + KEY_SLASH, // / + KEY_0, // 0 + KEY_1, // 1 + KEY_2, // 2 + KEY_3, // 3 + KEY_4, // 4 + KEY_5, // 5 + KEY_6, // 6 + KEY_7, // 7 + KEY_8, // 8 + KEY_9, // 9 + KEY_SEMICOLON|SHIFT, // : + KEY_SEMICOLON, // ; + KEY_COMMA|SHIFT, // < + KEY_EQUALS, // = + KEY_PERIOD|SHIFT, // > + KEY_SLASH|SHIFT, // ? + KEY_2|SHIFT, // @ + KEY_A|SHIFT, // A + KEY_B|SHIFT, // B + KEY_C|SHIFT, // C + KEY_D|SHIFT, // D + KEY_E|SHIFT, // E + KEY_F|SHIFT, // F + KEY_G|SHIFT, // G + KEY_H|SHIFT, // H + KEY_I|SHIFT, // I + KEY_J|SHIFT, // J + KEY_K|SHIFT, // K + KEY_L|SHIFT, // L + KEY_M|SHIFT, // M + KEY_N|SHIFT, // N + KEY_O|SHIFT, // O + KEY_P|SHIFT, // P + KEY_Q|SHIFT, // Q + KEY_R|SHIFT, // R + KEY_S|SHIFT, // S + KEY_T|SHIFT, // T + KEY_U|SHIFT, // U + KEY_V|SHIFT, // V + KEY_W|SHIFT, // W + KEY_X|SHIFT, // X + KEY_Y|SHIFT, // Y + KEY_Z|SHIFT, // Z + KEY_L_BRACKET, // [ + KEY_BACKSLASH, // bslash + KEY_R_BRACKET, // ] + KEY_6|SHIFT, // ^ + KEY_MINUS|SHIFT, // _ + KEY_GRAVE, // ` + KEY_A, // a + KEY_B, // b + KEY_C, // c + KEY_D, // d + KEY_E, // e + KEY_F, // f + KEY_G, // g + KEY_H, // h + KEY_I, // i + KEY_J, // j + KEY_K, // k + KEY_L, // l + KEY_M, // m + KEY_N, // n + KEY_O, // o + KEY_P, // p + KEY_Q, // q + KEY_R, // r + KEY_S, // s + KEY_T, // t + KEY_U, // u + KEY_V, // v + KEY_W, // w + KEY_X, // x + KEY_Y, // y + KEY_Z, // z + KEY_L_BRACKET|SHIFT, // { + KEY_BACKSLASH|SHIFT, // | + KEY_R_BRACKET|SHIFT, // } + KEY_GRAVE|SHIFT, // ~ + NO_KEY // DEL +}; diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index dda6aef484..90d901ae6d 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -300,16 +300,23 @@ size_t BootKeyboard_::release(uint8_t k) { } -size_t BootKeyboard_::write(uint8_t keycode) { - press(keycode); - sendReport(); - release(keycode); - sendReport(); -} - size_t BootKeyboard_::releaseAll(void) { memset(&_keyReport, 0x00, sizeof(_keyReport)); } +size_t BootKeyboard_::write(uint8_t k) { + if(k >= sizeof(_asciimap)) // Ignore invalid input + return 0; + + // Read key from ascii lookup table + k = pgm_read_byte(_asciimap + k); + + if(k & SHIFT) + press(HID_KEYBOARD_LEFT_SHIFT); + press(k & ~SHIFT); + sendReport(); + releaseAll(); + sendReport(); +} BootKeyboard_ BootKeyboard; diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index 5e58d66919..9b9bd7d709 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -30,7 +30,7 @@ THE SOFTWARE. #include "HID-Settings.h" #include "HIDTables.h" #include "HIDAliases.h" - +#include "ASCIIMap.h" typedef union { // Low level key report: up to 6 keys and shift, ctrl etc at once diff --git a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp index de774016b9..6841b485c4 100644 --- a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp @@ -171,5 +171,24 @@ size_t NKROKeyboard_::releaseAll(void) { return ret; } + + +size_t NKROKeyboard_::write(uint8_t k) { + if(k >= sizeof(_asciimap)) // Ignore invalid input + return 0; + + // Read key from ascii lookup table + k = pgm_read_byte(_asciimap + k); + + if(k & SHIFT) + press(HID_KEYBOARD_LEFT_SHIFT); + press(k & ~SHIFT); + sendReport(); + releaseAll(); + sendReport(); +} + + + NKROKeyboard_ NKROKeyboard; diff --git a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h index 0867c3b526..0e6d6e66c2 100644 --- a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h @@ -31,6 +31,7 @@ THE SOFTWARE. #include "HIDTables.h" #include "HIDAliases.h" +#include "ASCIIMap.h" // Max value for USB EP_SIZE 16 // +1 reportID, +1 modifier, +1 custom key @@ -61,6 +62,8 @@ class NKROKeyboard_ { inline size_t release(uint8_t k); inline size_t releaseAll(void); inline int sendReport(void); + size_t write(uint8_t k); + protected: HID_NKROKeyboardReport_Data_t _keyReport; From 10be36c949b337e1192bb82f719b8e119481b12d Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 11 Dec 2015 23:43:48 -0800 Subject: [PATCH 411/602] Now that we support 'write' again, expose the full Print API again --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h | 2 +- plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index 9b9bd7d709..2be8cdfb71 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -46,7 +46,7 @@ typedef union { } HID_KeyboardReport_Data_t; -class BootKeyboard_ : public PluggableUSBModule { +class BootKeyboard_ : public Print, PluggableUSBModule { public: BootKeyboard_(void); size_t press(uint8_t); diff --git a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h index 0e6d6e66c2..e5a587d06b 100644 --- a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h @@ -52,7 +52,7 @@ typedef union { -class NKROKeyboard_ { +class NKROKeyboard_ : public Print { public: NKROKeyboard_(void); inline void begin(void); From 98f8826448fbc086fafc5c3b193e5f504e5a8ba9 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Sat, 12 Dec 2015 00:01:08 -0800 Subject: [PATCH 412/602] de-inlineify nkrokeyboard API. Basic functionality is happy --- plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h index e5a587d06b..74185b6314 100644 --- a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h @@ -55,13 +55,13 @@ typedef union { class NKROKeyboard_ : public Print { public: NKROKeyboard_(void); - inline void begin(void); - inline void end(void); + void begin(void); + void end(void); - inline size_t press(uint8_t k); - inline size_t release(uint8_t k); - inline size_t releaseAll(void); - inline int sendReport(void); + size_t press(uint8_t k); + size_t release(uint8_t k); + size_t releaseAll(void); + int sendReport(void); size_t write(uint8_t k); protected: From 30a1528fc3d2259126368791430ea56d91c26719 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Sat, 12 Dec 2015 00:10:13 -0800 Subject: [PATCH 413/602] Rename ImprovedMouse just to Mouse --- plugins/KeyboardioHID/src/HID-Project.h | 2 +- .../src/MultiReport/{ImprovedMouse.cpp => Mouse.cpp} | 2 +- .../KeyboardioHID/src/MultiReport/{ImprovedMouse.h => Mouse.h} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename plugins/KeyboardioHID/src/MultiReport/{ImprovedMouse.cpp => Mouse.cpp} (99%) rename plugins/KeyboardioHID/src/MultiReport/{ImprovedMouse.h => Mouse.h} (100%) diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index 00c1053ee8..fde43a603d 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -42,7 +42,7 @@ THE SOFTWARE. // Include all HID libraries (.a linkage required to work) properly #include "BootKeyboard/BootKeyboard.h" #include "MultiReport/AbsoluteMouse.h" -#include "MultiReport/ImprovedMouse.h" +#include "MultiReport/Mouse.h" #include "MultiReport/Consumer.h" #include "MultiReport/Gamepad.h" #include "MultiReport/System.h" diff --git a/plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.cpp b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp similarity index 99% rename from plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.cpp rename to plugins/KeyboardioHID/src/MultiReport/Mouse.cpp index ec355b0a96..d0d9198475 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "ImprovedMouse.h" +#include "Mouse.h" static const uint8_t _hidMultiReportDescriptorMouse[] PROGMEM = { diff --git a/plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.h b/plugins/KeyboardioHID/src/MultiReport/Mouse.h similarity index 100% rename from plugins/KeyboardioHID/src/MultiReport/ImprovedMouse.h rename to plugins/KeyboardioHID/src/MultiReport/Mouse.h From f69af68cd3c874b9f4e8a68c4a37d9ee6ee2fc35 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Sat, 12 Dec 2015 00:17:30 -0800 Subject: [PATCH 414/602] Rename Consumer to ConsumerControl --- .../examples/Consumer/Consumer.ino | 4 ++-- plugins/KeyboardioHID/keywords.txt | 2 +- plugins/KeyboardioHID/src/HID-Project.h | 2 +- .../{Consumer.cpp => ConsumerControl.cpp} | 20 +++++++++---------- .../{Consumer.h => ConsumerControl.h} | 6 +++--- 5 files changed, 17 insertions(+), 17 deletions(-) rename plugins/KeyboardioHID/src/MultiReport/{Consumer.cpp => ConsumerControl.cpp} (87%) rename plugins/KeyboardioHID/src/MultiReport/{Consumer.h => ConsumerControl.h} (95%) diff --git a/plugins/KeyboardioHID/examples/Consumer/Consumer.ino b/plugins/KeyboardioHID/examples/Consumer/Consumer.ino index 0c566e960c..f211c499ab 100644 --- a/plugins/KeyboardioHID/examples/Consumer/Consumer.ino +++ b/plugins/KeyboardioHID/examples/Consumer/Consumer.ino @@ -19,7 +19,7 @@ void setup() { pinMode(pinButton, INPUT_PULLUP); // Sends a clean report to the host. This is important on any Arduino type. - Consumer.begin(); + ConsumerControl.begin(); } void loop() { @@ -27,7 +27,7 @@ void loop() { digitalWrite(pinLed, HIGH); // See HID Project documentation for more Consumer keys - Consumer.write(MEDIA_PLAY_PAUSE); + ConsumerControl.write(MEDIA_PLAY_PAUSE); // Simple debounce delay(300); diff --git a/plugins/KeyboardioHID/keywords.txt b/plugins/KeyboardioHID/keywords.txt index e7cc7c2003..3e69452313 100644 --- a/plugins/KeyboardioHID/keywords.txt +++ b/plugins/KeyboardioHID/keywords.txt @@ -61,7 +61,7 @@ BootKeyboard KEYWORD1 BootMouse KEYWORD1 RawHID KEYWORD1 System KEYWORD1 -Consumer KEYWORD1 +ConsumerControl KEYWORD1 Gamepad KEYWORD1 Gamepad1 KEYWORD1 Gamepad2 KEYWORD1 diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index fde43a603d..1e56d40e52 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -43,7 +43,7 @@ THE SOFTWARE. #include "BootKeyboard/BootKeyboard.h" #include "MultiReport/AbsoluteMouse.h" #include "MultiReport/Mouse.h" -#include "MultiReport/Consumer.h" +#include "MultiReport/ConsumerControl.h" #include "MultiReport/Gamepad.h" #include "MultiReport/System.h" #include "MultiReport/NKROKeyboard.h" diff --git a/plugins/KeyboardioHID/src/MultiReport/Consumer.cpp b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp similarity index 87% rename from plugins/KeyboardioHID/src/MultiReport/Consumer.cpp rename to plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp index 47bec50508..e160870b4c 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Consumer.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "Consumer.h" +#include "ConsumerControl.h" static const uint8_t _hidMultiReportDescriptorConsumer[] PROGMEM = { @@ -41,27 +41,27 @@ static const uint8_t _hidMultiReportDescriptorConsumer[] PROGMEM = { 0xC0 /* end collection */ }; -Consumer_::Consumer_(void) { +ConsumerControl_::ConsumerControl_(void) { static HIDSubDescriptor node(_hidMultiReportDescriptorConsumer, sizeof(_hidMultiReportDescriptorConsumer)); HID().AppendDescriptor(&node); } -void Consumer_::begin(void) { +void ConsumerControl_::begin(void) { // release all buttons end(); } -void Consumer_::end(void) { +void ConsumerControl_::end(void) { memset(&_report, 0, sizeof(_report)); SendReport(&_report, sizeof(_report)); } -void Consumer_::write(uint16_t m) { +void ConsumerControl_::write(uint16_t m) { press(m); release(m); } -void Consumer_::press(uint16_t m) { +void ConsumerControl_::press(uint16_t m) { // search for a free spot for (uint8_t i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { if (_report.keys[i] == 0x00) { @@ -72,7 +72,7 @@ void Consumer_::press(uint16_t m) { SendReport(&_report, sizeof(_report)); } -void Consumer_::release(uint16_t m) { +void ConsumerControl_::release(uint16_t m) { // search and release the keypress for (uint8_t i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { if (_report.keys[i] == m) { @@ -83,15 +83,15 @@ void Consumer_::release(uint16_t m) { SendReport(&_report, sizeof(_report)); } -void Consumer_::releaseAll(void) { +void ConsumerControl_::releaseAll(void) { end(); } -void Consumer_::SendReport(void* data, int length) { +void ConsumerControl_::SendReport(void* data, int length) { HID().SendReport(HID_REPORTID_CONSUMERCONTROL, data, length); } -Consumer_ Consumer; +ConsumerControl_ ConsumerControl; diff --git a/plugins/KeyboardioHID/src/MultiReport/Consumer.h b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h similarity index 95% rename from plugins/KeyboardioHID/src/MultiReport/Consumer.h rename to plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h index c261a530de..46e6f2fa73 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Consumer.h +++ b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h @@ -44,9 +44,9 @@ typedef union { } HID_ConsumerControlReport_Data_t; -class Consumer_ { +class ConsumerControl_ { public: - Consumer_(void); + ConsumerControl_(void); inline void begin(void); inline void end(void); inline void write(uint16_t m); @@ -61,4 +61,4 @@ class Consumer_ { protected: HID_ConsumerControlReport_Data_t _report; }; -extern Consumer_ Consumer; +extern ConsumerControl_ ConsumerControl; From ba1f0f6899e4de6dd30d5b1d5c6961a0fbe6d828 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Sat, 12 Dec 2015 00:43:02 -0800 Subject: [PATCH 415/602] Rename System to SystemControl --- .../KeyboardioHID/examples/System/System.ino | 8 ++++---- plugins/KeyboardioHID/keywords.txt | 2 +- plugins/KeyboardioHID/src/HID-Project.h | 2 +- .../{System.cpp => SystemControl.cpp} | 20 +++++++++---------- .../MultiReport/{System.h => SystemControl.h} | 6 +++--- 5 files changed, 19 insertions(+), 19 deletions(-) rename plugins/KeyboardioHID/src/MultiReport/{System.cpp => SystemControl.cpp} (86%) rename plugins/KeyboardioHID/src/MultiReport/{System.h => SystemControl.h} (95%) diff --git a/plugins/KeyboardioHID/examples/System/System.ino b/plugins/KeyboardioHID/examples/System/System.ino index b68c288fd2..9746b909d4 100644 --- a/plugins/KeyboardioHID/examples/System/System.ino +++ b/plugins/KeyboardioHID/examples/System/System.ino @@ -23,7 +23,7 @@ void setup() { pinMode(pinButtonW, INPUT_PULLUP); // Sends a clean report to the host. This is important on any Arduino type. - System.begin(); + SystemControl.begin(); } void loop() { @@ -31,8 +31,8 @@ void loop() { digitalWrite(pinLed, HIGH); // Puts PC into sleep mode/shuts it down - System.write(SYSTEM_SLEEP); - //System.write(SYSTEM_POWER_DOWN); + SystemControl.write(SYSTEM_SLEEP); + //SystemControl.write(SYSTEM_POWER_DOWN); // Simple debounce delay(300); @@ -44,7 +44,7 @@ void loop() { // Try to wake up the PC // This might fail on some PCs/Laptops where USB wakeup is not supported - System.write(SYSTEM_WAKE_UP); + SystemControl.write(SYSTEM_WAKE_UP); // Simple debounce delay(300); diff --git a/plugins/KeyboardioHID/keywords.txt b/plugins/KeyboardioHID/keywords.txt index 3e69452313..1048e47f52 100644 --- a/plugins/KeyboardioHID/keywords.txt +++ b/plugins/KeyboardioHID/keywords.txt @@ -60,7 +60,7 @@ Mouse KEYWORD1 BootKeyboard KEYWORD1 BootMouse KEYWORD1 RawHID KEYWORD1 -System KEYWORD1 +SystemControl KEYWORD1 ConsumerControl KEYWORD1 Gamepad KEYWORD1 Gamepad1 KEYWORD1 diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index 1e56d40e52..e5709389ca 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -45,6 +45,6 @@ THE SOFTWARE. #include "MultiReport/Mouse.h" #include "MultiReport/ConsumerControl.h" #include "MultiReport/Gamepad.h" -#include "MultiReport/System.h" +#include "MultiReport/SystemControl.h" #include "MultiReport/NKROKeyboard.h" diff --git a/plugins/KeyboardioHID/src/MultiReport/System.cpp b/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp similarity index 86% rename from plugins/KeyboardioHID/src/MultiReport/System.cpp rename to plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp index 394145a729..277b2a5fd6 100644 --- a/plugins/KeyboardioHID/src/MultiReport/System.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "System.h" +#include "SystemControl.h" static const uint8_t _hidMultiReportDescriptorSystem[] PROGMEM = { @@ -42,35 +42,35 @@ static const uint8_t _hidMultiReportDescriptorSystem[] PROGMEM = { 0xc0 /* END_COLLECTION */ }; -System_::System_(void) { +SystemControl_::SystemControl_(void) { static HIDSubDescriptor node(_hidMultiReportDescriptorSystem, sizeof(_hidMultiReportDescriptorSystem)); HID().AppendDescriptor(&node); } -void System_::begin(void) { +void SystemControl_::begin(void) { // release all buttons end(); } -void System_::end(void) { +void SystemControl_::end(void) { uint8_t _report = 0x00; SendReport(&_report, sizeof(_report)); } -void System_::write(uint8_t s) { +void SystemControl_::write(uint8_t s) { press(s); release(); } -void System_::release(void) { +void SystemControl_::release(void) { begin(); } -void System_::releaseAll(void) { +void SystemControl_::releaseAll(void) { begin(); } -void System_::press(uint8_t s) { +void SystemControl_::press(uint8_t s) { if (s == HID_SYSTEM_WAKE_UP) USBDevice.wakeupHost(); else @@ -78,11 +78,11 @@ void System_::press(uint8_t s) { } -void System_::SendReport(void* data, int length) { +void SystemControl_::SendReport(void* data, int length) { HID().SendReport(HID_REPORTID_SYSTEMCONTROL, data, length); } -System_ System; +SystemControl_ SystemControl; diff --git a/plugins/KeyboardioHID/src/MultiReport/System.h b/plugins/KeyboardioHID/src/MultiReport/SystemControl.h similarity index 95% rename from plugins/KeyboardioHID/src/MultiReport/System.h rename to plugins/KeyboardioHID/src/MultiReport/SystemControl.h index 228a16323e..e65ae36367 100644 --- a/plugins/KeyboardioHID/src/MultiReport/System.h +++ b/plugins/KeyboardioHID/src/MultiReport/SystemControl.h @@ -37,7 +37,7 @@ typedef union { } HID_SystemControlReport_Data_t; -class System_ { +class SystemControl_ { public: inline void begin(void); inline void end(void); @@ -47,12 +47,12 @@ class System_ { inline void releaseAll(void); inline void SendReport(void* data, int length); - System_(void); + SystemControl_(void); protected: }; -extern System_ System; +extern SystemControl_ SystemControl; From 414d2fc3015404eb842728178f140288dc4eb7cb Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Sat, 12 Dec 2015 00:44:04 -0800 Subject: [PATCH 416/602] Remove unused keywords --- plugins/KeyboardioHID/keywords.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/plugins/KeyboardioHID/keywords.txt b/plugins/KeyboardioHID/keywords.txt index 1048e47f52..23767d1a84 100644 --- a/plugins/KeyboardioHID/keywords.txt +++ b/plugins/KeyboardioHID/keywords.txt @@ -55,11 +55,7 @@ dPad2 KEYWORD2 USBDevice KEYWORD1 HID KEYWORD1 -Keyboard KEYWORD1 -Mouse KEYWORD1 BootKeyboard KEYWORD1 -BootMouse KEYWORD1 -RawHID KEYWORD1 SystemControl KEYWORD1 ConsumerControl KEYWORD1 Gamepad KEYWORD1 From ed900034b6ac330f4fefb2cd33a97e27465f1787 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Sat, 12 Dec 2015 00:54:32 -0800 Subject: [PATCH 417/602] NKROKeyboard becomes just "Keyboard" as NKRO is just one feature --- .../NKROKeyboard.ino => NKRO/NKRO.ino} | 26 +++++++++---------- plugins/KeyboardioHID/keywords.txt | 2 +- plugins/KeyboardioHID/src/HID-Project.h | 2 +- .../{NKROKeyboard.cpp => Keyboard.cpp} | 24 ++++++++--------- .../{NKROKeyboard.h => Keyboard.h} | 10 +++---- 5 files changed, 32 insertions(+), 32 deletions(-) rename plugins/KeyboardioHID/examples/Keyboard/{NKROKeyboard/NKROKeyboard.ino => NKRO/NKRO.ino} (73%) rename plugins/KeyboardioHID/src/MultiReport/{NKROKeyboard.cpp => Keyboard.cpp} (91%) rename plugins/KeyboardioHID/src/MultiReport/{NKROKeyboard.h => Keyboard.h} (91%) diff --git a/plugins/KeyboardioHID/examples/Keyboard/NKROKeyboard/NKROKeyboard.ino b/plugins/KeyboardioHID/examples/Keyboard/NKRO/NKRO.ino similarity index 73% rename from plugins/KeyboardioHID/examples/Keyboard/NKROKeyboard/NKROKeyboard.ino rename to plugins/KeyboardioHID/examples/Keyboard/NKRO/NKRO.ino index 56327875a9..a427e015d9 100644 --- a/plugins/KeyboardioHID/examples/Keyboard/NKROKeyboard/NKROKeyboard.ino +++ b/plugins/KeyboardioHID/examples/Keyboard/NKRO/NKRO.ino @@ -2,7 +2,7 @@ Copyright (c) 2014-2015 NicoHood See the readme for credit to other people. - NKROKeyboard example + NKRO Keyboard example Press a button to hold a lot of keys at the same time. NKRO can push 113 keys at the same time, @@ -23,7 +23,7 @@ void setup() { pinMode(pinButton, INPUT_PULLUP); // Sends a clean report to the host. This is important on any Arduino type. - NKROKeyboard.begin(); + Keyboard.begin(); } void loop() { @@ -34,17 +34,17 @@ void loop() { // Do not press to many at once or some OS will have problems. // Note that the resulting pressed order might differ, // because all keys are pressed at the same time. - NKROKeyboard.add('0'); - NKROKeyboard.add('1'); - NKROKeyboard.add('2'); - NKROKeyboard.add('3'); - NKROKeyboard.add('4'); - NKROKeyboard.add('5'); - NKROKeyboard.add('6'); - NKROKeyboard.add('7'); - NKROKeyboard.add('8'); - NKROKeyboard.add('9'); - NKROKeyboard.send(); + NKROKeyboard.press(KEY_0); + NKROKeyboard.press(KEY_1); + NKROKeyboard.press(KEY_2); + NKROKeyboard.press(KEY_3); + NKROKeyboard.press(KEY_4); + NKROKeyboard.press(KEY_5); + NKROKeyboard.press(KEY_6); + NKROKeyboard.press(KEY_7); + NKROKeyboard.press(KEY_8); + NKROKeyboard.press(KEY_9); + NKROKeyboard.sendReport(); // Release all keys and hit enter NKROKeyboard.releaseAll(); diff --git a/plugins/KeyboardioHID/keywords.txt b/plugins/KeyboardioHID/keywords.txt index 23767d1a84..862e8e0afa 100644 --- a/plugins/KeyboardioHID/keywords.txt +++ b/plugins/KeyboardioHID/keywords.txt @@ -63,7 +63,7 @@ Gamepad1 KEYWORD1 Gamepad2 KEYWORD1 Gamepad3 KEYWORD1 Gamepad4 KEYWORD1 -NKROKeyboard KEYWORD1 +Keyboard KEYWORD1 AbsoluteMouse KEYWORD1 ####################################### diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index e5709389ca..1919b853c2 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -46,5 +46,5 @@ THE SOFTWARE. #include "MultiReport/ConsumerControl.h" #include "MultiReport/Gamepad.h" #include "MultiReport/SystemControl.h" -#include "MultiReport/NKROKeyboard.h" +#include "MultiReport/Keyboard.h" diff --git a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp similarity index 91% rename from plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp rename to plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index 6841b485c4..1019bf47e9 100644 --- a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -21,9 +21,9 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "NKROKeyboard.h" +#include "Keyboard.h" -static const uint8_t _hidMultiReportDescriptorNKROKeyboard[] PROGMEM = { +static const uint8_t _hidMultiReportDescriptorKeyboard[] PROGMEM = { // NKRO Keyboard 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 47 */ 0x09, 0x06, /* USAGE (Keyboard) */ @@ -62,12 +62,12 @@ static const uint8_t _hidMultiReportDescriptorNKROKeyboard[] PROGMEM = { 0xC0 /* End Collection */ }; -NKROKeyboard_::NKROKeyboard_(void) { - static HIDSubDescriptor node(_hidMultiReportDescriptorNKROKeyboard, sizeof(_hidMultiReportDescriptorNKROKeyboard)); +Keyboard_::Keyboard_(void) { + static HIDSubDescriptor node(_hidMultiReportDescriptorKeyboard, sizeof(_hidMultiReportDescriptorKeyboard)); HID().AppendDescriptor(&node); } -void NKROKeyboard_::begin(void) { +void Keyboard_::begin(void) { // Force API to send a clean report. // This is important for and HID bridge where the receiver stays on, // while the sender is resetted. @@ -76,18 +76,18 @@ void NKROKeyboard_::begin(void) { } -void NKROKeyboard_::end(void) { +void Keyboard_::end(void) { releaseAll(); sendReport(); } -int NKROKeyboard_::sendReport(void) { +int Keyboard_::sendReport(void) { return HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &_keyReport, sizeof(_keyReport)); } -size_t NKROKeyboard_::press(uint8_t k) { +size_t Keyboard_::press(uint8_t k) { // Press keymap key if (k < NKRO_KEY_COUNT) { uint8_t bit = 1 << (uint8_t(k) % 8); @@ -120,7 +120,7 @@ size_t NKROKeyboard_::press(uint8_t k) { return 0; } -size_t NKROKeyboard_::release(uint8_t k) { +size_t Keyboard_::release(uint8_t k) { // Press keymap key if (k < NKRO_KEY_COUNT) { uint8_t bit = 1 << (uint8_t(k) % 8); @@ -154,7 +154,7 @@ size_t NKROKeyboard_::release(uint8_t k) { } // TODO: replace this with a mmap interface -size_t NKROKeyboard_::releaseAll(void) { +size_t Keyboard_::releaseAll(void) { // Release all keys size_t ret = 0; for (uint8_t i = 0; i < sizeof(_keyReport.allkeys); i++) { @@ -173,7 +173,7 @@ size_t NKROKeyboard_::releaseAll(void) { -size_t NKROKeyboard_::write(uint8_t k) { +size_t Keyboard_::write(uint8_t k) { if(k >= sizeof(_asciimap)) // Ignore invalid input return 0; @@ -190,5 +190,5 @@ size_t NKROKeyboard_::write(uint8_t k) { -NKROKeyboard_ NKROKeyboard; +Keyboard_ Keyboard; diff --git a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h similarity index 91% rename from plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h rename to plugins/KeyboardioHID/src/MultiReport/Keyboard.h index 74185b6314..e0956d1501 100644 --- a/plugins/KeyboardioHID/src/MultiReport/NKROKeyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h @@ -48,13 +48,13 @@ typedef union { uint8_t key; }; uint8_t allkeys[2 + NKRO_KEY_COUNT / 8]; -} HID_NKROKeyboardReport_Data_t; +} HID_KeyboardReport_Data_t; -class NKROKeyboard_ : public Print { +class Keyboard_ : public Print { public: - NKROKeyboard_(void); + Keyboard_(void); void begin(void); void end(void); @@ -65,8 +65,8 @@ class NKROKeyboard_ : public Print { size_t write(uint8_t k); protected: - HID_NKROKeyboardReport_Data_t _keyReport; + HID_KeyboardReport_Data_t _keyReport; }; -extern NKROKeyboard_ NKROKeyboard; +extern Keyboard_ Keyboard; From 05ff3cad9cfb00aa4ae19b2b6daaed34d9ed1e82 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Sun, 13 Dec 2015 13:17:17 -0800 Subject: [PATCH 418/602] Added a 'make astyle' target --- plugins/KeyboardioHID/src/Makefile | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 plugins/KeyboardioHID/src/Makefile diff --git a/plugins/KeyboardioHID/src/Makefile b/plugins/KeyboardioHID/src/Makefile new file mode 100644 index 0000000000..6e45fb6a6d --- /dev/null +++ b/plugins/KeyboardioHID/src/Makefile @@ -0,0 +1,3 @@ +astyle: + find . -type f -name \*.cpp |xargs -n 1 astyle --style=google + find . -type f -name \*.h |xargs -n 1 astyle --style=google From 11958122f474e8de66fdf9b96b0fab509b21faa6 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Sun, 13 Dec 2015 13:33:49 -0800 Subject: [PATCH 419/602] Linting turned up a stray - in some cpp macros --- plugins/KeyboardioHID/src/HIDTables.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/KeyboardioHID/src/HIDTables.h b/plugins/KeyboardioHID/src/HIDTables.h index 2282be11a4..63c733ef56 100644 --- a/plugins/KeyboardioHID/src/HIDTables.h +++ b/plugins/KeyboardioHID/src/HIDTables.h @@ -453,9 +453,9 @@ #define HID_CONSUMER_CHANNEL_TOP 0x169 // HID type CL #define HID_CONSUMER_CHANNEL_UNKNOWN 0x16A // HID type CL // Reserved 0x16B-16F -#define HID_CONSUMER_SUB-CHANNEL 0x170 // HID type LC -#define HID_CONSUMER_SUB-CHANNEL_INCREMENT 0x171 // HID type OSC -#define HID_CONSUMER_SUB-CHANNEL_DECREMENT 0x172 // HID type OSC +#define HID_CONSUMER_SUB_CHANNEL 0x170 // HID type LC +#define HID_CONSUMER_SUB_CHANNEL_INCREMENT 0x171 // HID type OSC +#define HID_CONSUMER_SUB_CHANNEL_DECREMENT 0x172 // HID type OSC #define HID_CONSUMER_ALTERNATE_AUDIO_INCREMENT 0x173 // HID type OSC #define HID_CONSUMER_ALTERNATE_AUDIO_DECREMENT 0x174 // HID type OSC // Reserved 0x175-17F From 3d28252116bd3282a1e5d527c3c10c2d0ca20dd8 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Sun, 13 Dec 2015 15:54:39 -0800 Subject: [PATCH 420/602] Add a note about how to check that my HID macros aren't nutso --- plugins/KeyboardioHID/doc/notes | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 plugins/KeyboardioHID/doc/notes diff --git a/plugins/KeyboardioHID/doc/notes b/plugins/KeyboardioHID/doc/notes new file mode 100644 index 0000000000..48df9dbc32 --- /dev/null +++ b/plugins/KeyboardioHID/doc/notes @@ -0,0 +1,3 @@ +To expand the macros in a c++ source file on OSX: + +gcc -D __AVR_ATmega32U4__ -DF_CPU=16000000L -O -I/Applications/Arduino.app/Contents/Java/hardware/arduino/avr/cores/arduino/ -I /Applications/Arduino.app/Contents/Java/hardware/tools/avr/avr/include/ -I/Applications/Arduino.app/Contents/Java/hardware/arduino/avr/variants/leonardo -I/Applications/Arduino.app/Contents/Java/hardware/arduino/avr/libraries/HID/ -I. -E $FILE From eb5fc7a6baf8afdea0883ce237fab81fadd2d065 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Sun, 13 Dec 2015 15:54:49 -0800 Subject: [PATCH 421/602] Upon closer reading of the spec, it's totally right to define a "no event" keycode at 0x00 --- plugins/KeyboardioHID/src/HIDTables.h | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/KeyboardioHID/src/HIDTables.h b/plugins/KeyboardioHID/src/HIDTables.h index 63c733ef56..91be6aa1ed 100644 --- a/plugins/KeyboardioHID/src/HIDTables.h +++ b/plugins/KeyboardioHID/src/HIDTables.h @@ -70,6 +70,7 @@ // Keyboard HID mappings // Reserved (no_event_indicated) 0x00 +#define HID_KEYBOARD_NO_EVENT 0x00 #define HID_KEYBOARD_ERROR_ROLLOVER 0x01 #define HID_KEYBOARD_POST_FAIL 0x02 #define HID_KEYBOARD_ERROR_UNDEFINED 0x03 From 78c4abcb42368af9c078624ecd4622eb191eb575 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Sun, 13 Dec 2015 15:55:31 -0800 Subject: [PATCH 422/602] Correct a duplicate macro in HIDAliases --- plugins/KeyboardioHID/src/HIDAliases.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/HIDAliases.h b/plugins/KeyboardioHID/src/HIDAliases.h index accc54726c..733c7b9083 100644 --- a/plugins/KeyboardioHID/src/HIDAliases.h +++ b/plugins/KeyboardioHID/src/HIDAliases.h @@ -145,7 +145,7 @@ #define KEY_SEPARATOR HID_KEYBOARD_SEPARATOR #define KEY_OUT HID_KEYBOARD_OUT #define KEY_OPER HID_KEYBOARD_OPER -#define KEY_CLEAR HID_KEYBOARD_CLEAR_SLASH_AGAIN +#define KEY_CLEAR_AGAIN HID_KEYBOARD_CLEAR_SLASH_AGAIN #define KEY_CRSEL HID_KEYBOARD_CRSEL_SLASH_PROPS #define KEY_EXSEL HID_KEYBOARD_EXSEL #define KEY_LCTRL HID_KEYBOARD_LEFT_CONTROL From 0975a1768a75d5a943f9a90cad100232a29cb46e Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Sun, 13 Dec 2015 15:56:17 -0800 Subject: [PATCH 423/602] Add my nascent HID Descriptor primitive colleciton --- .../KeyboardioHID/src/DescriptorPrimitives.h | 116 ++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 plugins/KeyboardioHID/src/DescriptorPrimitives.h diff --git a/plugins/KeyboardioHID/src/DescriptorPrimitives.h b/plugins/KeyboardioHID/src/DescriptorPrimitives.h new file mode 100644 index 0000000000..8a8ea74616 --- /dev/null +++ b/plugins/KeyboardioHID/src/DescriptorPrimitives.h @@ -0,0 +1,116 @@ +#pragma once + +#define _MULTIBYTE(n) (n + 0x01) + +#define _USAGE_PAGE 0x05 +#define _USAGE 0x09 + + +#define _REPORT_ID 0x85 + +#define _USAGE_MINIMUM 0x19 +#define _USAGE_MAXIMUM 0x29 + +#define _LOGICAL_MINIMUM 0x15 +#define _LOGICAL_MAXIMUM 0x25 + +#define _REPORT_SIZE 0x75 +#define _REPORT_COUNT 0x95 + + +// USB HID DCD 1.11 section 6.2.2.4 - Main items +// +// each of these are the type description + 0x01 for a single byte item +#define _INPUT 0x81 +#define _OUTPUT 0x91 +#define _FEATURE 0xb1 +#define _COLLECTION 0xa1 +#define _END_COLLECTION 0xc0 + +// The bits that make up inputs, outputs and features + +// Bit 0 +#define _DATA 0b00000000 +#define _CONSTANT 0b00000001 +// Bit 1 +#define _ARRAY 0b00000000 +#define _VARIABLE 0b00000010 +// Bit 2 +#define _ABSOLUTE 0b00000000 +#define _RELATIVE 0b00000100 +// Bit 3 +#define _NO_WRAP 0b00000000 +#define _WRAP 0b00001000 +// Bit 4 +#define _LINEAR 0b00000000 +#define _NON_LINEAR 0b00010000 +// Bit 5 +#define _PREFERRED_STATE 0b00000000 +#define _NO_PREFERRED 0b00100000 +// Bit 6 +#define _NO_NULL_POSITION 0b00000000 +#define _NULL_STATE 0b01000000 +// Bit 7 +#define _NON_VOLATILE 0b00000000 +#define _VOLATILE 0b01000000 + +// Bit 8 +#define _BIT_FIELD 0b00000000 +#define _BUFFERED_BYTES 0b10000000 + + + +// Collection types + + +#define _PHYSYICAL 0x00 // (group of axes) +#define _APPLICATION 0x01 // (mouse, keyboard) +#define _LOGICAL 0x02// (interrelated data) +#define _REPORT 0x03 +#define _NAMED_ARRAY 0x04 +#define _USAGE_SWITCH 0x05 +#define _USAGE_MODIFIER 0x06 +// 0x07-0x7f - Reserved +// 0x80-0xff - Vendor define + + +#define _PAGE_GENERIC_DESKTOP 0x01 +#define _PAGE_SIMULATION 0x02 +#define _PAGE_VR 0x03 +#define _PAGE_SPORT 0x04 +#define _PAGE_GAME 0x05 +#define _PAGE_GENERIC_DEVICE 0x06 +#define _PAGE_KEYBOARD 0x07 +#define _PAGE_LEDS 0x08 +#define _PAGE_BUTTON 0x09 +#define _PAGE_ORDINAL 0x0A +#define _PAGE_TELEPHONY 0x0B +#define _PAGE_CONSUMER 0x0C +#define _PAGE_DIGITIZER 0x0D +#define _PAGE_RESERVED 0x0E +#define _PAGE_PID 0x0F +#define _PAGE_UNICODE 0x10 +// 0x11-13 RESERVED +#define _PAGE_ALPHANUMERIC_DISPLAY 0x14 +#define _PAGE_MEDICAL_INSTRUMENTS 0x40 +// 0x80-83 MONITOR +// 0x84-87 POWER +#define _PAGE_BAR_CODE_SCANNER 0x8C +#define _PAGE_SCALE 0x8D +#define _PAGE_MSR 0x8E +// 0x8F RESERVED POINT OF SALE +#define _PAGE_CAMERA_CONTROL 0x90 +#define _PAGE_ARCADE 0x91 + + +// Generic Desktop Usages HUT Section 4 p27 + + +#define _USAGE_POINTER 0x01 +#define _USAGE_MOUSE 0x02 +// 0x03 is reserved +#define _USAGE_JOYSTICK 0x04 +#define _USAGE_GAMEPAD 0x05 +#define _USAGE_KEYBOARD 0x06 +#define _USAGE_KEYPAD 0x07 +#define _USAGE_MULITAXIS 0x08 \ No newline at end of file From a61e1754439a26c56d1b3876d009e474b1fd0f66 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Sun, 13 Dec 2015 15:56:50 -0800 Subject: [PATCH 424/602] Convert the NKRO Keyboard's descriptor to use my primitive library --- .../src/MultiReport/Keyboard.cpp | 55 ++++++++++--------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index 1019bf47e9..3382bccc92 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -22,44 +22,45 @@ THE SOFTWARE. */ #include "Keyboard.h" +#include "DescriptorPrimitives.h" static const uint8_t _hidMultiReportDescriptorKeyboard[] PROGMEM = { // NKRO Keyboard - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 47 */ - 0x09, 0x06, /* USAGE (Keyboard) */ - 0xa1, 0x01, /* COLLECTION (Application) */ - 0x85, HID_REPORTID_NKRO_KEYBOARD, /* REPORT_ID */ - 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ + _USAGE_PAGE, _PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) 47 */ + _USAGE, _USAGE_KEYBOARD, /* USAGE (Keyboard) */ + _COLLECTION, _APPLICATION, /* COLLECTION (Application) */ + _REPORT_ID, HID_REPORTID_NKRO_KEYBOARD, /* REPORT_ID */ + _USAGE_PAGE, _PAGE_KEYBOARD, /* USAGE_PAGE (Keyboard) */ /* Keyboard Modifiers (shift, alt, ...) */ - 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) */ + _USAGE_MINIMUM, HID_KEYBOARD_LEFT_CONTROL, /* USAGE_MINIMUM (Keyboard LeftControl) */ + _USAGE_MAXIMUM, HID_KEYBOARD_RIGHT_GUI, /* USAGE_MAXIMUM (Keyboard Right GUI) */ + _LOGICAL_MINIMUM, 0x00, /* LOGICAL_MINIMUM (0) */ + _LOGICAL_MAXIMUM, 0x01, /* LOGICAL_MAXIMUM (1) */ + _REPORT_SIZE, 0x01, /* REPORT_SIZE (1) */ + _REPORT_COUNT, 0x08, /* REPORT_COUNT (8) */ + _INPUT, (_DATA|_VARIABLE|_ABSOLUTE), /* INPUT (Data,Var,Abs) */ /* 104 Keys as bitmap */ - 0x19, 0x00, /* Usage Minimum (0) */ - 0x29, NKRO_KEY_COUNT - 1, /* Usage Maximum (103) */ - 0x15, 0x00, /* Logical Minimum (0) */ - 0x25, 0x01, /* Logical Maximum (1) */ - 0x75, 0x01, /* Report Size (1) */ - 0x95, NKRO_KEY_COUNT, /* Report Count (104) */ - 0x81, 0x02, /* Input (Data, Variable, Absolute) */ + _USAGE_MINIMUM, HID_KEYBOARD_NO_EVENT, /* Usage Minimum (0) */ + _USAGE_MAXIMUM, NKRO_KEY_COUNT - 1, /* Usage Maximum (103) */ + _LOGICAL_MINIMUM, 0x00, /* Logical Minimum (0) */ + _LOGICAL_MAXIMUM, 0x01, /* Logical Maximum (1) */ + _REPORT_SIZE, 0x01, /* Report Size (1) */ + _REPORT_COUNT, NKRO_KEY_COUNT, /* Report Count (104) */ + _INPUT, (_DATA|_VARIABLE|_ABSOLUTE), /* Input (Data, Variable, Absolute) */ /* 1 Custom Keyboard key */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0x75, 0x08, /* REPORT_SIZE (8) */ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ - 0x26, 0xE7, 0x00, /* LOGICAL_MAXIMUM (231) */ - 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ - 0x29, 0xE7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ - 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ + _REPORT_COUNT, 0x01, /* REPORT_COUNT (1) */ + _REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ + _LOGICAL_MINIMUM, HID_KEYBOARD_NO_EVENT, /* LOGICAL_MINIMUM (0) */ + _MULTIBYTE(_LOGICAL_MAXIMUM), HID_KEYBOARD_RIGHT_GUI, 0x00, /* LOGICAL_MAXIMUM (231) */ + _USAGE_MINIMUM, HID_KEYBOARD_NO_EVENT, /* USAGE_MINIMUM (Reserved (no event indicated)) */ + _USAGE_MAXIMUM, HID_KEYBOARD_RIGHT_GUI, /* USAGE_MAXIMUM (Keyboard Right GUI) */ + _INPUT, (_DATA|_ARRAY|_ABSOLUTE), /* INPUT (Data,Ary,Abs) */ /* End */ - 0xC0 /* End Collection */ + _END_COLLECTION /* End Collection */ }; Keyboard_::Keyboard_(void) { From 23f784afd0b9e7e0ce46de014b9ea3dd9fda9420 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Sun, 13 Dec 2015 16:07:54 -0800 Subject: [PATCH 425/602] Add a note that a comment in the old implementation is not true for our use case --- plugins/KeyboardioHID/src/MultiReport/Keyboard.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h index e0956d1501..11a0014672 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h @@ -33,7 +33,12 @@ THE SOFTWARE. #include "HIDAliases.h" #include "ASCIIMap.h" -// Max value for USB EP_SIZE 16 +// We have a max USB_EP_SIZE of 64 on the 32u4. The previous implementation +// was built around the assumption that it needed to work on simpler, more +// resource constrained MCUs, so it was careful to fit everything into a 16 byte +// endpoint size. As we improve our implementation, we can bump it up a bit. + +// Put another way, this comment is now incorrect: Max value for USB EP_SIZE 16 // +1 reportID, +1 modifier, +1 custom key #define NKRO_KEY_COUNT (8*13) From ef77a3f596750d960f8279669e09f053fb160551 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Sun, 13 Dec 2015 17:15:49 -0800 Subject: [PATCH 426/602] Remove the custom 'one key keyboard for things outside the boaring 104 key keymap' --- .../src/MultiReport/Keyboard.cpp | 36 ++----------------- .../KeyboardioHID/src/MultiReport/Keyboard.h | 1 - 2 files changed, 2 insertions(+), 35 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index 3382bccc92..7550e0f7c0 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -24,6 +24,8 @@ THE SOFTWARE. #include "Keyboard.h" #include "DescriptorPrimitives.h" +// USB Code not within 4-49 (0x4-0x31), 51-155 (0x33-0x9B), 157-164 (0x9D-0xA4), +// 176-221 (0xB0-0xDD) or 224-231 (0xE0-0xE7) NKRO Mode static const uint8_t _hidMultiReportDescriptorKeyboard[] PROGMEM = { // NKRO Keyboard _USAGE_PAGE, _PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) 47 */ @@ -50,14 +52,6 @@ static const uint8_t _hidMultiReportDescriptorKeyboard[] PROGMEM = { _REPORT_COUNT, NKRO_KEY_COUNT, /* Report Count (104) */ _INPUT, (_DATA|_VARIABLE|_ABSOLUTE), /* Input (Data, Variable, Absolute) */ - /* 1 Custom Keyboard key */ - _REPORT_COUNT, 0x01, /* REPORT_COUNT (1) */ - _REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ - _LOGICAL_MINIMUM, HID_KEYBOARD_NO_EVENT, /* LOGICAL_MINIMUM (0) */ - _MULTIBYTE(_LOGICAL_MAXIMUM), HID_KEYBOARD_RIGHT_GUI, 0x00, /* LOGICAL_MAXIMUM (231) */ - _USAGE_MINIMUM, HID_KEYBOARD_NO_EVENT, /* USAGE_MINIMUM (Reserved (no event indicated)) */ - _USAGE_MAXIMUM, HID_KEYBOARD_RIGHT_GUI, /* USAGE_MAXIMUM (Keyboard Right GUI) */ - _INPUT, (_DATA|_ARRAY|_ABSOLUTE), /* INPUT (Data,Ary,Abs) */ /* End */ _END_COLLECTION /* End Collection */ @@ -104,19 +98,6 @@ size_t Keyboard_::press(uint8_t k) { return 1; } - // Its a custom key (outside our keymap) - else { - // Add k to the key report only if it's not already present - // and if there is an empty slot. Remove the first available key. - auto key = _keyReport.key; - - // Is key already in the list or did we found an empty slot? - if ((key == uint8_t(k) || key == 0x00)) { - _keyReport.key = k; - return 1; - } - } - // No empty/pressed key was found return 0; } @@ -137,19 +118,6 @@ size_t Keyboard_::release(uint8_t k) { return 1; } - // Its a custom key (outside our keymap) - else { - // Add k to the key report only if it's not already present - // and if there is an empty slot. Remove the first available key. - auto key = _keyReport.key; - - // Test the key report to see if k is present. Clear it if it exists. - if (key == k) { - _keyReport.key = 0x00; - return 1; - } - } - // No empty/pressed key was found return 0; } diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h index 11a0014672..5597778af2 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h @@ -50,7 +50,6 @@ typedef union { struct { uint8_t modifiers; uint8_t keys[NKRO_KEY_COUNT / 8]; - uint8_t key; }; uint8_t allkeys[2 + NKRO_KEY_COUNT / 8]; } HID_KeyboardReport_Data_t; From b17f2ab52c9e1b6540dd277dddaec9632a5e071b Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Sun, 13 Dec 2015 17:26:17 -0800 Subject: [PATCH 427/602] Rename the boot keyboard's report data structure away from conflicting with the NKROKeyboard's --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index 2be8cdfb71..e26f7431d1 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -43,7 +43,7 @@ typedef union { uint8_t keycodes[6]; }; uint8_t keys[8]; -} HID_KeyboardReport_Data_t; +} HID_BootKeyboardReport_Data_t; class BootKeyboard_ : public Print, PluggableUSBModule { @@ -91,7 +91,7 @@ class BootKeyboard_ : public Print, PluggableUSBModule { protected: - HID_KeyboardReport_Data_t _keyReport; + HID_BootKeyboardReport_Data_t _keyReport; // Implementation of the PUSBListNode int getInterface(uint8_t* interfaceCount); From b6e9f93a26940afb36391ba8223f3d72078cf266 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Sun, 13 Dec 2015 22:05:00 -0800 Subject: [PATCH 428/602] Snapshot - functionality is happy on OSX, but not yet on linux or windows --- plugins/KeyboardioHID/src/HIDAliases.h | 2 + .../src/MultiReport/Keyboard.cpp | 109 +++++++++++++----- .../KeyboardioHID/src/MultiReport/Keyboard.h | 15 +-- 3 files changed, 84 insertions(+), 42 deletions(-) diff --git a/plugins/KeyboardioHID/src/HIDAliases.h b/plugins/KeyboardioHID/src/HIDAliases.h index 733c7b9083..d8a96890da 100644 --- a/plugins/KeyboardioHID/src/HIDAliases.h +++ b/plugins/KeyboardioHID/src/HIDAliases.h @@ -2,6 +2,8 @@ #include "HIDTables.h" +#define HID_FIRST_KEY HID_KEYBOARD_NO_EVENT +#define HID_LAST_KEY HID_KEYPAD_HEXADECIMAL #define HID_KEYBOARD_FIRST_MODIFIER HID_KEYBOARD_LEFT_CONTROL #define HID_KEYBOARD_LAST_MODIFIER HID_KEYBOARD_RIGHT_GUI diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index 7550e0f7c0..41e939d697 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -24,37 +24,84 @@ THE SOFTWARE. #include "Keyboard.h" #include "DescriptorPrimitives.h" -// USB Code not within 4-49 (0x4-0x31), 51-155 (0x33-0x9B), 157-164 (0x9D-0xA4), -// 176-221 (0xB0-0xDD) or 224-231 (0xE0-0xE7) NKRO Mode static const uint8_t _hidMultiReportDescriptorKeyboard[] PROGMEM = { // NKRO Keyboard - _USAGE_PAGE, _PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) 47 */ - _USAGE, _USAGE_KEYBOARD, /* USAGE (Keyboard) */ - _COLLECTION, _APPLICATION, /* COLLECTION (Application) */ - _REPORT_ID, HID_REPORTID_NKRO_KEYBOARD, /* REPORT_ID */ - _USAGE_PAGE, _PAGE_KEYBOARD, /* USAGE_PAGE (Keyboard) */ - - /* Keyboard Modifiers (shift, alt, ...) */ - _USAGE_MINIMUM, HID_KEYBOARD_LEFT_CONTROL, /* USAGE_MINIMUM (Keyboard LeftControl) */ - _USAGE_MAXIMUM, HID_KEYBOARD_RIGHT_GUI, /* USAGE_MAXIMUM (Keyboard Right GUI) */ - _LOGICAL_MINIMUM, 0x00, /* LOGICAL_MINIMUM (0) */ - _LOGICAL_MAXIMUM, 0x01, /* LOGICAL_MAXIMUM (1) */ - _REPORT_SIZE, 0x01, /* REPORT_SIZE (1) */ - _REPORT_COUNT, 0x08, /* REPORT_COUNT (8) */ - _INPUT, (_DATA|_VARIABLE|_ABSOLUTE), /* INPUT (Data,Var,Abs) */ - - /* 104 Keys as bitmap */ - _USAGE_MINIMUM, HID_KEYBOARD_NO_EVENT, /* Usage Minimum (0) */ - _USAGE_MAXIMUM, NKRO_KEY_COUNT - 1, /* Usage Maximum (103) */ - _LOGICAL_MINIMUM, 0x00, /* Logical Minimum (0) */ - _LOGICAL_MAXIMUM, 0x01, /* Logical Maximum (1) */ - _REPORT_SIZE, 0x01, /* Report Size (1) */ - _REPORT_COUNT, NKRO_KEY_COUNT, /* Report Count (104) */ - _INPUT, (_DATA|_VARIABLE|_ABSOLUTE), /* Input (Data, Variable, Absolute) */ - - - /* End */ - _END_COLLECTION /* End Collection */ + _USAGE_PAGE, _PAGE_GENERIC_DESKTOP, + _USAGE, _USAGE_KEYBOARD, + _COLLECTION, _APPLICATION, + _REPORT_ID, HID_REPORTID_NKRO_KEYBOARD, + _USAGE_PAGE, _PAGE_KEYBOARD, + + + /* Key modifier byte */ + _USAGE_MINIMUM, HID_KEYBOARD_FIRST_MODIFIER, + _USAGE_MAXIMUM, HID_KEYBOARD_LAST_MODIFIER, + _LOGICAL_MINIMUM, 0x00, + _LOGICAL_MAXIMUM, 0x01, + _REPORT_SIZE, 0x01, + _REPORT_COUNT, 0x08, + _INPUT, (_DATA|_VARIABLE|_ABSOLUTE), + +// USB Code not within 4-49 (0x4-0x31), 51-155 (0x33-0x9B), 157-164 (0x9D-0xA4), +// 176-221 (0xB0-0xDD) or 224-231 (0xE0-0xE7) NKRO Mode + /* NKRO Keyboard */ + + // Padding 3 bits + // To skip HID_KEYBOARD_NON_US_POUND_AND_TILDE, which causes + // Linux to choke on our driver. + _REPORT_SIZE, 0x04, + _REPORT_COUNT, 0x01, + _INPUT, (_CONSTANT), + + + _USAGE_MINIMUM, HID_KEYBOARD_A_AND_A, + _USAGE_MAXIMUM, HID_KEYBOARD_BACKSLASH_AND_PIPE, + _LOGICAL_MINIMUM, 0x00, + _LOGICAL_MAXIMUM, 0x01, + _REPORT_SIZE, 0x01, + _REPORT_COUNT, (HID_KEYBOARD_BACKSLASH_AND_PIPE - HID_KEYBOARD_A_AND_A)+1, + _INPUT, (_DATA|_VARIABLE|_ABSOLUTE), + + // Padding 1 bit. + // To skip HID_KEYBOARD_NON_US_POUND_AND_TILDE, which causes + // Linux to choke on our driver. + _REPORT_SIZE, 0x01, + _REPORT_COUNT, 0x01, + _INPUT, (_CONSTANT), + + + _USAGE_MINIMUM, HID_KEYBOARD_SEMICOLON_AND_COLON, + _USAGE_MAXIMUM, HID_KEYBOARD_CANCEL, + _LOGICAL_MINIMUM, 0x00, + _LOGICAL_MAXIMUM, 0x01, + _REPORT_SIZE, 0x01, + _REPORT_COUNT, (HID_KEYBOARD_CANCEL-HID_KEYBOARD_SEMICOLON_AND_COLON) +1, + _INPUT, (_DATA|_VARIABLE|_ABSOLUTE), + + + // Padding 1 bit. + // To skip HID_KEYBOARD_CLEAR, which causes + // Linux to choke on our driver. + _REPORT_SIZE, 0x01, + _REPORT_COUNT, 0x01, + _INPUT, (_CONSTANT), + + _USAGE_MINIMUM, HID_KEYBOARD_PRIOR, + _USAGE_MAXIMUM, HID_KEYPAD_HEXADECIMAL, + _LOGICAL_MINIMUM, 0x00, + _LOGICAL_MAXIMUM, 0x01, + _REPORT_SIZE, 0x01, + _REPORT_COUNT, (HID_KEYPAD_HEXADECIMAL - HID_KEYBOARD_PRIOR ) +1 , + _INPUT, (_DATA|_VARIABLE|_ABSOLUTE), + + + // Padding (w bits) + _REPORT_SIZE, 0x02, + _REPORT_COUNT, 0x01, + _INPUT, (_CONSTANT), + + _END_COLLECTION, + }; Keyboard_::Keyboard_(void) { @@ -84,7 +131,7 @@ int Keyboard_::sendReport(void) { size_t Keyboard_::press(uint8_t k) { // Press keymap key - if (k < NKRO_KEY_COUNT) { + if (k <= HID_KEYPAD_HEXADECIMAL ) { uint8_t bit = 1 << (uint8_t(k) % 8); _keyReport.keys[k / 8] |= bit; return 1; @@ -104,7 +151,7 @@ size_t Keyboard_::press(uint8_t k) { size_t Keyboard_::release(uint8_t k) { // Press keymap key - if (k < NKRO_KEY_COUNT) { + if (k <= HID_KEYPAD_HEXADECIMAL) { uint8_t bit = 1 << (uint8_t(k) % 8); _keyReport.keys[k / 8] &= ~bit; return 1; diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h index 5597778af2..c7e0469b43 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h @@ -33,25 +33,18 @@ THE SOFTWARE. #include "HIDAliases.h" #include "ASCIIMap.h" -// We have a max USB_EP_SIZE of 64 on the 32u4. The previous implementation -// was built around the assumption that it needed to work on simpler, more -// resource constrained MCUs, so it was careful to fit everything into a 16 byte -// endpoint size. As we improve our implementation, we can bump it up a bit. - -// Put another way, this comment is now incorrect: Max value for USB EP_SIZE 16 -// +1 reportID, +1 modifier, +1 custom key -#define NKRO_KEY_COUNT (8*13) +#define KEY_BYTES 28 typedef union { - // Modifier + keymap + 1 custom key + // Modifiers + keymap uint8_t whole8[]; uint16_t whole16[]; uint32_t whole32[]; struct { uint8_t modifiers; - uint8_t keys[NKRO_KEY_COUNT / 8]; + uint8_t keys[KEY_BYTES ]; }; - uint8_t allkeys[2 + NKRO_KEY_COUNT / 8]; + uint8_t allkeys[1 + KEY_BYTES]; } HID_KeyboardReport_Data_t; From a04f57f7f2abd5a5374f13c0196e45810d4533ed Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Mon, 14 Dec 2015 13:01:39 -0800 Subject: [PATCH 429/602] clean up and optimize .releaseAll() --- .../src/BootKeyboard/BootKeyboard.cpp | 2 +- .../KeyboardioHID/src/MultiReport/Keyboard.cpp | 15 +-------------- 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 90d901ae6d..23928e63b8 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -301,7 +301,7 @@ size_t BootKeyboard_::release(uint8_t k) { size_t BootKeyboard_::releaseAll(void) { - memset(&_keyReport, 0x00, sizeof(_keyReport)); + memset(&_keyReport.keys, 0x00, sizeof(_keyReport.keys)); } size_t BootKeyboard_::write(uint8_t k) { diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index 41e939d697..8ebc740673 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -169,22 +169,9 @@ size_t Keyboard_::release(uint8_t k) { return 0; } -// TODO: replace this with a mmap interface size_t Keyboard_::releaseAll(void) { // Release all keys - size_t ret = 0; - for (uint8_t i = 0; i < sizeof(_keyReport.allkeys); i++) { - // Is a key in the list or did we found an empty slot? - auto bits = _keyReport.allkeys[i]; - do { - if(bits & 0x01) { - ret++; - } - bits >>=1; - } while(bits); - _keyReport.allkeys[i] = 0x00; - } - return ret; + memset(&_keyReport.allkeys, 0x00, sizeof(_keyReport.allkeys)); } From 856f48058441c7d14a10f52b0bffe5d326c91f8c Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Mon, 14 Dec 2015 13:02:02 -0800 Subject: [PATCH 430/602] Remove unecessary casts. --- plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index 8ebc740673..c705319882 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -130,7 +130,7 @@ int Keyboard_::sendReport(void) { } size_t Keyboard_::press(uint8_t k) { - // Press keymap key + // If the key is in the range of 'printable' keys if (k <= HID_KEYPAD_HEXADECIMAL ) { uint8_t bit = 1 << (uint8_t(k) % 8); _keyReport.keys[k / 8] |= bit; @@ -140,7 +140,7 @@ size_t Keyboard_::press(uint8_t k) { // It's a modifier key else if(k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { // Convert key into bitfield (0 - 7) - k = uint8_t(k) - uint8_t(HID_KEYBOARD_FIRST_MODIFIER); + k = k - HID_KEYBOARD_FIRST_MODIFIER; _keyReport.modifiers = (1 << k); return 1; } @@ -150,9 +150,9 @@ size_t Keyboard_::press(uint8_t k) { } size_t Keyboard_::release(uint8_t k) { - // Press keymap key + // If we're releasing a printable key if (k <= HID_KEYPAD_HEXADECIMAL) { - uint8_t bit = 1 << (uint8_t(k) % 8); + uint8_t bit = 1 << (k % 8); _keyReport.keys[k / 8] &= ~bit; return 1; } From beac4708098b75f12a8f9844001f2a2186a8f7de Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Mon, 14 Dec 2015 15:18:35 -0800 Subject: [PATCH 431/602] HID descriptor macros --- .../src/MultiReport/ConsumerControl.cpp | 26 +++++------ .../KeyboardioHID/src/MultiReport/Mouse.cpp | 46 +++++++++---------- .../src/MultiReport/SystemControl.cpp | 26 +++++------ 3 files changed, 49 insertions(+), 49 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp index e160870b4c..f1b478864c 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp @@ -22,23 +22,23 @@ THE SOFTWARE. */ #include "ConsumerControl.h" - +#include "DescriptorPrimitives.h" static const uint8_t _hidMultiReportDescriptorConsumer[] PROGMEM = { /* Consumer Control (Sound/Media keys) */ - 0x05, 0x0C, /* usage page (consumer device) */ - 0x09, 0x01, /* usage -- consumer control */ - 0xA1, 0x01, /* collection (application) */ - 0x85, HID_REPORTID_CONSUMERCONTROL, /* report id */ + _USAGE_PAGE, 0x0C, /* usage page (consumer device) */ + _USAGE, 0x01, /* usage -- consumer control */ + _COLLECTION, _APPLICATION, /* collection (application) */ + _REPORT_ID, HID_REPORTID_CONSUMERCONTROL, /* report id */ /* 4 Media Keys */ - 0x15, 0x00, /* logical minimum */ - 0x26, 0xFF, 0x03, /* logical maximum (3ff) */ - 0x19, 0x00, /* usage minimum (0) */ - 0x2A, 0xFF, 0x03, /* usage maximum (3ff) */ - 0x95, 0x04, /* report count (4) */ - 0x75, 0x10, /* report size (16) */ - 0x81, 0x00, /* input */ - 0xC0 /* end collection */ + _LOGICAL_MINIMUM, 0x00, /* logical minimum */ + _MULTIBYTE(_LOGICAL_MAXIMUM), 0xFF, 0x03, /* logical maximum (3ff) */ + _USAGE_MINIMUM, 0x00, /* usage minimum (0) */ + _MULTIBYTE(_USAGE_MAXIMUM), 0xFF, 0x03, /* usage maximum (3ff) */ + _REPORT_COUNT, 0x04, /* report count (4) */ + _REPORT_SIZE, 0x10, /* report size (16) */ + _INPUT, 0x00, /* input */ + _END_COLLECTION /* end collection */ }; ConsumerControl_::ConsumerControl_(void) { diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp index d0d9198475..396c0bc307 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp @@ -22,38 +22,38 @@ THE SOFTWARE. */ #include "Mouse.h" - +#include "DescriptorPrimitives.h" static const uint8_t _hidMultiReportDescriptorMouse[] PROGMEM = { /* Mouse relative */ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 54 */ - 0x09, 0x02, /* USAGE (Mouse) */ - 0xa1, 0x01, /* COLLECTION (Application) */ - 0x85, HID_REPORTID_MOUSE, /* REPORT_ID */ + _USAGE_PAGE, _PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) 54 */ + _USAGE, _USAGE_MOUSE, /* USAGE (Mouse) */ + _COLLECTION, _APPLICATION, /* COLLECTION (Application) */ + _REPORT_ID, HID_REPORTID_MOUSE, /* REPORT_ID */ /* 8 Buttons */ - 0x05, 0x09, /* USAGE_PAGE (Button) */ - 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ - 0x29, 0x08, /* USAGE_MAXIMUM (Button 8) */ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ - 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ - 0x95, 0x08, /* REPORT_COUNT (8) */ - 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + _USAGE_PAGE, _PAGE_BUTTON, /* USAGE_PAGE (Button) */ + _USAGE_MINIMUM, 0x01, /* USAGE_MINIMUM (Button 1) */ + _USAGE_MAXIMUM, 0x08, /* USAGE_MAXIMUM (Button 8) */ + _LOGICAL_MINIMUM, 0x00, /* LOGICAL_MINIMUM (0) */ + _LOGICAL_MAXIMUM, 0x01, /* LOGICAL_MAXIMUM (1) */ + _REPORT_COUNT, 0x08, /* REPORT_COUNT (8) */ + _REPORT_SIZE, 0x01, /* REPORT_SIZE (1) */ + _INPUT, (_DATA|_VARIABLE|_ABSOLUTE), /* INPUT (Data,Var,Abs) */ /* X, Y, Wheel */ - 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) */ + _USAGE_PAGE, _PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ + _USAGE, 0x30, /* USAGE (X) */ + _USAGE, 0x31, /* USAGE (Y) */ + _USAGE, 0x38, /* USAGE (Wheel) */ + _LOGICAL_MINIMUM, 0x81, /* LOGICAL_MINIMUM (-127) */ + _LOGICAL_MAXIMUM, 0x7f, /* LOGICAL_MAXIMUM (127) */ + _REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ + _REPORT_COUNT, 0x03, /* REPORT_COUNT (3) */ + _INPUT, (_DATA|_VARIABLE|_RELATIVE), /* INPUT (Data,Var,Rel) */ /* End */ - 0xc0 /* END_COLLECTION */ + _END_COLLECTION /* END_COLLECTION */ }; diff --git a/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp b/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp index 277b2a5fd6..7d45e6cc96 100644 --- a/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp @@ -22,24 +22,24 @@ THE SOFTWARE. */ #include "SystemControl.h" - +#include "DescriptorPrimitives.h" static const uint8_t _hidMultiReportDescriptorSystem[] PROGMEM = { //TODO limit to system keys only? /* System Control (Power Down, Sleep, Wakeup, ...) */ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ - 0x09, 0x80, /* USAGE (System Control) */ - 0xa1, 0x01, /* COLLECTION (Application) */ - 0x85, HID_REPORTID_SYSTEMCONTROL, /* REPORT_ID */ + _USAGE_PAGE, _PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ + _USAGE, 0x80, /* USAGE (System Control) */ + _COLLECTION, _APPLICATION, /* COLLECTION (Application) */ + _REPORT_ID, HID_REPORTID_SYSTEMCONTROL, /* REPORT_ID */ /* 1 system key */ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ - 0x26, 0xff, 0x00, /* LOGICAL_MAXIMUM (255) */ - 0x19, 0x00, /* USAGE_MINIMUM (Undefined) */ - 0x29, 0xff, /* USAGE_MAXIMUM (System Menu Down) */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0x75, 0x08, /* REPORT_SIZE (8) */ - 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ - 0xc0 /* END_COLLECTION */ + _LOGICAL_MINIMUM, 0x00, /* LOGICAL_MINIMUM (0) */ + _MULTIBYTE(_LOGICAL_MAXIMUM), 0xff, 0x00, /* LOGICAL_MAXIMUM (255) */ + _USAGE_MINIMUM, 0x00, /* USAGE_MINIMUM (Undefined) */ + _USAGE_MAXIMUM, 0xff, /* USAGE_MAXIMUM (System Menu Down) */ + _REPORT_COUNT, 0x01, /* REPORT_COUNT (1) */ + _REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ + _INPUT, (_DATA|_ARRAY|_ABSOLUTE), /* INPUT (Data,Ary,Abs) */ + _END_COLLECTION /* END_COLLECTION */ }; SystemControl_::SystemControl_(void) { From 9cbb1278d36b8570552503e2c5dd9d6b10f811e0 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Wed, 16 Dec 2015 22:50:00 -0800 Subject: [PATCH 432/602] Typo fix --- plugins/KeyboardioHID/src/DescriptorPrimitives.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/DescriptorPrimitives.h b/plugins/KeyboardioHID/src/DescriptorPrimitives.h index 8a8ea74616..310d7fa89e 100644 --- a/plugins/KeyboardioHID/src/DescriptorPrimitives.h +++ b/plugins/KeyboardioHID/src/DescriptorPrimitives.h @@ -63,7 +63,7 @@ // Collection types -#define _PHYSYICAL 0x00 // (group of axes) +#define _PHYSICAL 0x00 // (group of axes) #define _APPLICATION 0x01 // (mouse, keyboard) #define _LOGICAL 0x02// (interrelated data) #define _REPORT 0x03 From 4730a1cdbca155021bae43ccf7fb50c30fc30e7a Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Wed, 16 Dec 2015 22:50:12 -0800 Subject: [PATCH 433/602] Porting more hid descriptors to the new descriptor macros --- .../src/MultiReport/AbsoluteMouse.cpp | 56 ++++++------- .../KeyboardioHID/src/MultiReport/Gamepad.cpp | 83 ++++++++++--------- 2 files changed, 70 insertions(+), 69 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp index 125d42f813..ce47450c75 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp @@ -22,45 +22,45 @@ THE SOFTWARE. */ #include "AbsoluteMouse.h" - +#include "DescriptorPrimitives.h" static const uint8_t _hidMultiReportDescriptorAbsoluteMouse[] PROGMEM = { /* Mouse absolute */ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 54 */ - 0x09, 0x02, /* USAGE (Mouse) */ - 0xA1, 0x01, /* COLLECTION (Application) */ - 0x85, HID_REPORTID_MOUSE_ABSOLUTE, /* REPORT_ID */ + _USAGE_PAGE, _PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) 54 */ + _USAGE, _USAGE_MOUSE, /* USAGE (Mouse) */ + _COLLECTION, _APPLICATION, /* COLLECTION (Application) */ + _REPORT_ID, HID_REPORTID_MOUSE_ABSOLUTE, /* REPORT_ID */ /* 8 Buttons */ - 0x05, 0x09, /* USAGE_PAGE (Button) */ - 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ - 0x29, 0x08, /* USAGE_MAXIMUM (Button 8) */ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ - 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ - 0x95, 0x08, /* REPORT_COUNT (8) */ - 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + _USAGE_PAGE, _PAGE_BUTTON, /* USAGE_PAGE (Button) */ + _USAGE_MINIMUM, 0x01, /* USAGE_MINIMUM (Button 1) */ + _USAGE_MAXIMUM, 0x08, /* USAGE_MAXIMUM (Button 8) */ + _LOGICAL_MINIMUM, 0x00, /* LOGICAL_MINIMUM (0) */ + _LOGICAL_MAXIMUM, 0x01, /* LOGICAL_MAXIMUM (1) */ + _REPORT_COUNT, 0x08, /* REPORT_COUNT (8) */ + _REPORT_SIZE, 0x01, /* REPORT_SIZE (1) */ + _INPUT, (_DATA|_VARIABLE|_ABSOLUTE), /* X, Y */ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ - 0x09, 0x30, /* USAGE (X) */ - 0x09, 0x31, /* USAGE (Y) */ - 0x16, 0x00, 0x80, /* Logical Minimum (-32768) */ - 0x26, 0xFF, 0x7F, /* Logical Maximum (32767) */ - 0x75, 0x10, /* Report Size (16), */ - 0x95, 0x02, /* Report Count (2), */ - 0x81, 0x02, /* Input (Data, Variable, Absolute) */ + _USAGE_PAGE, _PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ + _USAGE, 0x30, /* USAGE (X) */ + _USAGE, 0x31, /* USAGE (Y) */ + _MULTIBYTE(_LOGICAL_MINIMUM), 0x00, 0x80, /* Logical Minimum (-32768) */ + _MULTIBYTE(_LOGICAL_MAXIMUM), 0xFF, 0x7F, /* Logical Maximum (32767) */ + _REPORT_SIZE, 0x10, /* Report Size (16), */ + _REPORT_COUNT, 0x02, /* Report Count (2), */ + _INPUT, (_DATA|_VARIABLE|_ABSOLUTE), /* Input (Data, Variable, Absolute) */ /* Wheel */ - 0x09, 0x38, /* USAGE (Wheel) */ - 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) */ + _USAGE, 0x38, /* USAGE (Wheel) */ + _LOGICAL_MINIMUM, 0x81, /* LOGICAL_MINIMUM (-127) */ + _LOGICAL_MAXIMUM, 0x7f, /* LOGICAL_MAXIMUM (127) */ + _REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ + _REPORT_COUNT, 0x01, /* REPORT_COUNT (1) */ + _INPUT, (_DATA|_VARIABLE|_RELATIVE), /* End */ - 0xc0 /* END_COLLECTION */ + _END_COLLECTION }; AbsoluteMouse_::AbsoluteMouse_(void) { diff --git a/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp b/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp index c4e2eefa1f..3575459268 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp @@ -22,54 +22,55 @@ THE SOFTWARE. */ #include "Gamepad.h" - +#include "DescriptorPrimitives.h" static const uint8_t _hidMultiReportDescriptorGamepad[] PROGMEM = { /* Gamepad with 32 buttons and 6 axis*/ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ - 0x09, 0x04, /* USAGE (Joystick) */ - 0xa1, 0x01, /* COLLECTION (Application) */ - 0x85, HID_REPORTID_GAMEPAD, /* REPORT_ID */ + _USAGE_PAGE, _PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ + _USAGE, _USAGE_JOYSTICK, /* USAGE (Joystick) */ + _COLLECTION, _APPLICATION, /* COLLECTION (Application) */ + _REPORT_ID, HID_REPORTID_GAMEPAD, /* REPORT_ID */ /* 32 Buttons */ - 0x05, 0x09, /* USAGE_PAGE (Button) */ - 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ - 0x29, 0x20, /* USAGE_MAXIMUM (Button 32) */ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ - 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ - 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x95, 0x20, /* REPORT_COUNT (32) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + _USAGE_PAGE, _PAGE_BUTTON, /* USAGE_PAGE (Button) */ + _USAGE_MINIMUM, 0x01, /* USAGE_MINIMUM (Button 1) */ + _USAGE_MAXIMUM, 0x20, /* USAGE_MAXIMUM (Button 32) */ + _LOGICAL_MINIMUM, 0x00, /* _LOGICAL_MINIMUM (0) */ + _LOGICAL_MAXIMUM, 0x01, /* _LOGICAL_MAXIMUM (1) */ + _REPORT_SIZE, 0x01, /* REPORT_SIZE (1) */ + _REPORT_COUNT, 0x20, /* REPORT_COUNT (32) */ + _INPUT, (_DATA|_VARIABLE|_ABSOLUTE), /* INPUT (Data,Var,Abs) */ /* 4 16bit Axis */ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ - 0xa1, 0x00, /* COLLECTION (Physical) */ - 0x09, 0x30, /* USAGE (X) */ - 0x09, 0x31, /* USAGE (Y) */ - 0x09, 0x33, /* USAGE (Rx) */ - 0x09, 0x34, /* USAGE (Ry) */ - 0x16, 0x00, 0x80, /* LOGICAL_MINIMUM (-32768) */ - 0x26, 0xFF, 0x7F, /* LOGICAL_MAXIMUM (32767) */ - 0x75, 0x10, /* REPORT_SIZE (16) */ - 0x95, 0x04, /* REPORT_COUNT (4) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + _USAGE_PAGE, _PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ + _COLLECTION, _PHYSICAL, /* COLLECTION (Physical) */ + _USAGE, 0x30, /* USAGE (X) */ + _USAGE, 0x31, /* USAGE (Y) */ + _USAGE, 0x33, /* USAGE (Rx) */ + _USAGE, 0x34, /* USAGE (Ry) */ + _MULTIBYTE(_LOGICAL_MINIMUM), 0x00, 0x80, /* _LOGICAL_MINIMUM (-32768) */ + _MULTIBYTE(_LOGICAL_MAXIMUM), 0xFF, 0x7F, /* _LOGICAL_MAXIMUM (32767) */ + _REPORT_SIZE, 0x10, /* REPORT_SIZE (16) */ + _REPORT_COUNT, 0x04, /* REPORT_COUNT (4) */ + _INPUT, (_DATA|_VARIABLE|_ABSOLUTE), /* INPUT (Data,Var,Abs) */ /* 2 8bit Axis */ - 0x09, 0x32, /* USAGE (Z) */ - 0x09, 0x35, /* USAGE (Rz) */ - 0x15, 0x80, /* LOGICAL_MINIMUM (-128) */ - 0x25, 0x7F, /* LOGICAL_MAXIMUM (127) */ - 0x75, 0x08, /* REPORT_SIZE (8) */ - 0x95, 0x02, /* REPORT_COUNT (2) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - 0xc0, /* END_COLLECTION */ + _USAGE, 0x32, /* USAGE (Z) */ + _USAGE, 0x35, /* USAGE (Rz) */ + _LOGICAL_MINIMUM, 0x80, /* _LOGICAL_MINIMUM (-128) */ + _LOGICAL_MAXIMUM, 0x7F, /* _LOGICAL_MAXIMUM (127) */ + _REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ + _REPORT_COUNT, 0x02, /* REPORT_COUNT (2) */ + _INPUT, (_DATA|_VARIABLE|_ABSOLUTE), /* INPUT (Data,Var,Abs) */ + _END_COLLECTION, /* END_COLLECTION */ + /* 2 Hat Switches */ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ - 0x09, 0x39, /* USAGE (Hat switch) */ - 0x09, 0x39, /* USAGE (Hat switch) */ - 0x15, 0x01, /* LOGICAL_MINIMUM (1) */ - 0x25, 0x08, /* LOGICAL_MAXIMUM (8) */ - 0x95, 0x02, /* REPORT_COUNT (2) */ - 0x75, 0x04, /* REPORT_SIZE (4) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - 0xc0 /* END_COLLECTION */ + _USAGE_PAGE, _PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ + _USAGE, 0x39, /* USAGE (Hat switch) */ + _USAGE, 0x39, /* USAGE (Hat switch) */ + _LOGICAL_MINIMUM, 0x01, /* _LOGICAL_MINIMUM (1) */ + _LOGICAL_MAXIMUM, 0x08, /* _LOGICAL_MAXIMUM (8) */ + _REPORT_COUNT, 0x02, /* REPORT_COUNT (2) */ + _REPORT_SIZE, 0x04, /* REPORT_SIZE (4) */ + _INPUT, (_DATA|_VARIABLE|_ABSOLUTE), /* INPUT (Data,Var,Abs) */ + _END_COLLECTION /* END_COLLECTION */ }; Gamepad_::Gamepad_(void) { From 3bbd8e60d11873736071586d4ec5590f7ff308fe Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Tue, 19 Jan 2016 18:20:28 -0800 Subject: [PATCH 434/602] bad logic for adding modifiers. Backport from Nico's branch --- plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index c705319882..d65f63dc1a 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -141,7 +141,7 @@ size_t Keyboard_::press(uint8_t k) { else if(k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { // Convert key into bitfield (0 - 7) k = k - HID_KEYBOARD_FIRST_MODIFIER; - _keyReport.modifiers = (1 << k); + _keyReport.modifiers |= (1 << k); return 1; } From a4dbfea70d999d1c680b379a2777619685100c44 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Tue, 19 Jan 2016 19:12:38 -0800 Subject: [PATCH 435/602] Remove 'inline' function descriptions that just don't play nice --- .../src/MultiReport/AbsoluteMouse.h | 22 ++++++------ .../src/MultiReport/ConsumerControl.h | 12 +++---- .../KeyboardioHID/src/MultiReport/Gamepad.h | 36 +++++++++---------- plugins/KeyboardioHID/src/MultiReport/Mouse.h | 18 +++++----- .../src/MultiReport/SystemControl.h | 14 ++++---- 5 files changed, 51 insertions(+), 51 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h index 82a99b7f26..c44c9afc1c 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h @@ -56,26 +56,26 @@ typedef union { class AbsoluteMouse_ { public: AbsoluteMouse_(void); - inline void begin(void); - inline void end(void); + void begin(void); + void end(void); - inline void click(uint8_t b = MOUSE_LEFT); - inline void moveTo(int x, int y, signed char wheel = 0); - inline void move(int x, int y, signed char wheel = 0); - inline void press(uint8_t b = MOUSE_LEFT); - inline void release(uint8_t b = MOUSE_LEFT); - inline bool isPressed(uint8_t b = MOUSE_LEFT); + void click(uint8_t b = MOUSE_LEFT); + void moveTo(int x, int y, signed char wheel = 0); + void move(int x, int y, signed char wheel = 0); + void press(uint8_t b = MOUSE_LEFT); + void release(uint8_t b = MOUSE_LEFT); + bool isPressed(uint8_t b = MOUSE_LEFT); // Sending is public in the base class for advanced users. - inline void SendReport(void* data, int length); + void SendReport(void* data, int length); protected: int16_t xAxis; int16_t yAxis; uint8_t _buttons; - inline void buttons(uint8_t b); + void buttons(uint8_t b); - inline int16_t qadd16(int16_t base, int16_t increment); + int16_t qadd16(int16_t base, int16_t increment); diff --git a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h index 46e6f2fa73..2e330c4a25 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h +++ b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h @@ -47,12 +47,12 @@ typedef union { class ConsumerControl_ { public: ConsumerControl_(void); - inline void begin(void); - inline void end(void); - inline void write(uint16_t m); - inline void press(uint16_t m); - inline void release(uint16_t m); - inline void releaseAll(void); + void begin(void); + void end(void); + void write(uint16_t m); + void press(uint16_t m); + void release(uint16_t m); + void releaseAll(void); // Sending is public in the base class for advanced users. void SendReport(void* data, int length); diff --git a/plugins/KeyboardioHID/src/MultiReport/Gamepad.h b/plugins/KeyboardioHID/src/MultiReport/Gamepad.h index 5384f71202..556d43f9df 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Gamepad.h +++ b/plugins/KeyboardioHID/src/MultiReport/Gamepad.h @@ -103,24 +103,24 @@ class Gamepad_ { public: Gamepad_(void); - inline void begin(void); - inline void end(void); - inline void write(void); - inline void press(uint8_t b); - inline void release(uint8_t b); - inline void releaseAll(void); - - inline void buttons(uint32_t b); - inline void xAxis(int16_t a); - inline void yAxis(int16_t a); - inline void zAxis(int8_t a); - inline void rxAxis(int16_t a); - inline void ryAxis(int16_t a); - inline void rzAxis(int8_t a); - inline void dPad1(int8_t d); - inline void dPad2(int8_t d); - - inline void SendReport(void* data, int length); + void begin(void); + void end(void); + void write(void); + void press(uint8_t b); + void release(uint8_t b); + void releaseAll(void); + + void buttons(uint32_t b); + void xAxis(int16_t a); + void yAxis(int16_t a); + void zAxis(int8_t a); + void rxAxis(int16_t a); + void ryAxis(int16_t a); + void rzAxis(int8_t a); + void dPad1(int8_t d); + void dPad2(int8_t d); + + void SendReport(void* data, int length); protected: HID_GamepadReport_Data_t _report; }; diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.h b/plugins/KeyboardioHID/src/MultiReport/Mouse.h index e1e7acd5be..82fb29c526 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.h @@ -55,18 +55,18 @@ typedef union { class Mouse_ { public: Mouse_(void); - inline void begin(void); - inline void end(void); - inline void click(uint8_t b = MOUSE_LEFT); - inline void move(signed char x, signed char y, signed char wheel = 0); - inline void press(uint8_t b = MOUSE_LEFT); // press LEFT by default - inline void release(uint8_t b = MOUSE_LEFT); // release LEFT by default - inline bool isPressed(uint8_t b = MOUSE_LEFT); // check LEFT by default + 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 - inline void SendReport(void* data, int length); + void SendReport(void* data, int length); protected: uint8_t _buttons; - inline void buttons(uint8_t b); + void buttons(uint8_t b); }; extern Mouse_ Mouse; diff --git a/plugins/KeyboardioHID/src/MultiReport/SystemControl.h b/plugins/KeyboardioHID/src/MultiReport/SystemControl.h index e65ae36367..57c2a8256a 100644 --- a/plugins/KeyboardioHID/src/MultiReport/SystemControl.h +++ b/plugins/KeyboardioHID/src/MultiReport/SystemControl.h @@ -39,13 +39,13 @@ typedef union { class SystemControl_ { public: - inline void begin(void); - inline void end(void); - inline void write(uint8_t s); - inline void press(uint8_t s); - inline void release(void); - inline void releaseAll(void); - inline void SendReport(void* data, int length); + void begin(void); + void end(void); + void write(uint8_t s); + void press(uint8_t s); + void release(void); + void releaseAll(void); + void SendReport(void* data, int length); SystemControl_(void); From c842ded1577abf6330cd9a6ec6376d6f28d1889e Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Tue, 19 Jan 2016 19:13:02 -0800 Subject: [PATCH 436/602] Reorder imports --- plugins/KeyboardioHID/src/HID-Project.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/HID-Project.h index 1919b853c2..f88565ef31 100644 --- a/plugins/KeyboardioHID/src/HID-Project.h +++ b/plugins/KeyboardioHID/src/HID-Project.h @@ -40,7 +40,6 @@ THE SOFTWARE. // Include all HID libraries (.a linkage required to work) properly -#include "BootKeyboard/BootKeyboard.h" #include "MultiReport/AbsoluteMouse.h" #include "MultiReport/Mouse.h" #include "MultiReport/ConsumerControl.h" @@ -48,3 +47,4 @@ THE SOFTWARE. #include "MultiReport/SystemControl.h" #include "MultiReport/Keyboard.h" +#include "BootKeyboard/BootKeyboard.h" From a9fbedae765b889c6294884b7716eea143a1e102 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Tue, 19 Jan 2016 19:19:38 -0800 Subject: [PATCH 437/602] Remove now-incorrect content from the README --- plugins/KeyboardioHID/Readme.md | 28 ++-------------------------- 1 file changed, 2 insertions(+), 26 deletions(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index fa774a4c9d..54760a64bc 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -4,37 +4,13 @@ Keyboardio USB HID Driver Based on Nico Hood's HID-Project. Please don't contact Nico with issues in this library. -This project went through a lot of phases and has now reached a new Arduino ~~USB-Core~~ Library -with a lot of new functions like extended HID. It also supports HoodLoader1+2. -The idea is to enable enhanced USB functions to almost all 'standard' Arduino boards. - -**Supported Arduinos (IDE 1.6.6 or higher!):** -* Uno (with [HoodLoader2](https://github.com/NicoHood/HoodLoader2)) -* Mega (with [HoodLoader2](https://github.com/NicoHood/HoodLoader2)) -* Leonardo -* (Pro)Micro -* Any other 8u2/16u2/at90usb8/162/32u2/32u4 compatible board -* No SAM/ARM support (Due, Zero etc) **Supported HID devices:** -* Keyboard with Leds out (8 modifiers + 6 keys pressed at the same time, + 1 limited linux consumer key) -* NKRO Keyboard with Leds out (press up to 113 keys at the same time) +* Boot Keyboard +* NKRO Keyboard (press up to 113 keys at the same time) * Mouse (5 buttons, move, wheel) -* BootKeyboard/BootMouse BIOS protocol support * Absolute Mouse * Consumer/Media Keys (4 keys for music player, web browser and more) * System Key (for PC standby/shutdown) * Gamepad (32 buttons, 4 16bit axis, 2 8bit axis, 2 D-Pads) -* RawHID -* Each device is available as single or multi report device (except RawHID) - -See the [wiki](https://github.com/NicoHood/HID/wiki/Features) for more information about features etc. - -Wiki -==== - -All documentation moved to the [wiki page](https://github.com/NicoHood/HID/wiki). - -An offline snapshot is available in [releases](https://github.com/NicoHood/HID/releases). - From a3846a6d88c5b70e1d78b53af5a30c8afb1a296a Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Tue, 19 Jan 2016 19:20:48 -0800 Subject: [PATCH 438/602] update library properties to better match library --- plugins/KeyboardioHID/library.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/KeyboardioHID/library.properties b/plugins/KeyboardioHID/library.properties index 2aa38571b6..9f2345c611 100644 --- a/plugins/KeyboardioHID/library.properties +++ b/plugins/KeyboardioHID/library.properties @@ -1,9 +1,9 @@ -name=HID-Project +name=KeyboardioHID version=0.0.1 author=Jesse Vincent maintainer=Jesse Vincent sentence=HID Driver for keyboardio keyboards. -paragraph=Includes BootKeyboard/Mouse, Consumer, System, Gamepad, RawHID and more features. Based on Nico Hood's HID-Project +paragraph=Includes Boot Keyboard, NKRO Keyboard, Mouse, ConsumerControl, SystemControl, Gamepad. Based on Nico Hood's HID-Project category=Communication url=https://github.com/keyboardio/HID architectures=avr From 6683a95b549ae79252c4edebbead7df30081edcf Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Thu, 21 Jan 2016 21:07:31 -0800 Subject: [PATCH 439/602] Add some missing spaces on arrow key definiitons --- plugins/KeyboardioHID/src/HIDAliases.h | 8 ++++---- plugins/KeyboardioHID/src/HIDTables.h | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/plugins/KeyboardioHID/src/HIDAliases.h b/plugins/KeyboardioHID/src/HIDAliases.h index d8a96890da..86394fbe45 100644 --- a/plugins/KeyboardioHID/src/HIDAliases.h +++ b/plugins/KeyboardioHID/src/HIDAliases.h @@ -84,10 +84,10 @@ #define KEY_DEL_FWD HID_KEYBOARD_DELETE_FORWARD #define KEY_END HID_KEYBOARD_END #define KEY_PGDN HID_KEYBOARD_PAGE_DOWN -#define KEY_RARROW HID_KEYBOARD_RIGHTARROW -#define KEY_LARROW HID_KEYBOARD_LEFTARROW -#define KEY_DARROW HID_KEYBOARD_DOWNARROW -#define KEY_UARROW HID_KEYBOARD_UPARROW +#define KEY_RARROW HID_KEYBOARD_RIGHT_ARROW +#define KEY_LARROW HID_KEYBOARD_LEFT_ARROW +#define KEY_DARROW HID_KEYBOARD_DOWN_ARROW +#define KEY_UARROW HID_KEYBOARD_UP_ARROW #define KEY_NONUS_BACKSLASH HID_KEYBOARD_NON_US_BACKSLASH_AND_PIPE #define KEY_APP HID_KEYBOARD_APPLICATION #define KEY_PWR HID_KEYBOARD_POWER diff --git a/plugins/KeyboardioHID/src/HIDTables.h b/plugins/KeyboardioHID/src/HIDTables.h index 91be6aa1ed..e3ff74d312 100644 --- a/plugins/KeyboardioHID/src/HIDTables.h +++ b/plugins/KeyboardioHID/src/HIDTables.h @@ -149,10 +149,10 @@ #define HID_KEYBOARD_DELETE_FORWARD 0x4C #define HID_KEYBOARD_END 0x4D #define HID_KEYBOARD_PAGE_DOWN 0x4E -#define HID_KEYBOARD_RIGHTARROW 0x4F -#define HID_KEYBOARD_LEFTARROW 0x50 -#define HID_KEYBOARD_DOWNARROW 0x51 -#define HID_KEYBOARD_UPARROW 0x52 +#define HID_KEYBOARD_RIGHT_ARROW 0x4F +#define HID_KEYBOARD_LEFT_ARROW 0x50 +#define HID_KEYBOARD_DOWN_ARROW 0x51 +#define HID_KEYBOARD_UP_ARROW 0x52 #define HID_KEYPAD_NUM_LOCK_AND_CLEAR 0x53 #define HID_KEYPAD_DIVIDE 0x54 #define HID_KEYPAD_MULTIPLY 0x55 From d59626fa244f1fee9ae61584e292ff57e4eb49b3 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 22 Jan 2016 01:32:10 -0800 Subject: [PATCH 440/602] releaseAll has no return value. Fix its prototype to show that --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp | 2 +- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h | 2 +- plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp | 2 +- plugins/KeyboardioHID/src/MultiReport/Keyboard.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 23928e63b8..1265f9669d 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -300,7 +300,7 @@ size_t BootKeyboard_::release(uint8_t k) { } -size_t BootKeyboard_::releaseAll(void) { +void BootKeyboard_::releaseAll(void) { memset(&_keyReport.keys, 0x00, sizeof(_keyReport.keys)); } diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index e26f7431d1..d0e4281bf7 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -54,7 +54,7 @@ class BootKeyboard_ : public Print, PluggableUSBModule { void end(void); size_t write(uint8_t); size_t release(uint8_t); - size_t releaseAll(void); + void releaseAll(void); int sendReport(void); diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index d65f63dc1a..8c328610e0 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -169,7 +169,7 @@ size_t Keyboard_::release(uint8_t k) { return 0; } -size_t Keyboard_::releaseAll(void) { +void Keyboard_::releaseAll(void) { // Release all keys memset(&_keyReport.allkeys, 0x00, sizeof(_keyReport.allkeys)); } diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h index c7e0469b43..b70cbc8f0b 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h @@ -57,7 +57,7 @@ class Keyboard_ : public Print { size_t press(uint8_t k); size_t release(uint8_t k); - size_t releaseAll(void); + void releaseAll(void); int sendReport(void); size_t write(uint8_t k); From 1f3cebcb66c9029aee25186c566416d0230fb2bd Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 22 Jan 2016 01:51:31 -0800 Subject: [PATCH 441/602] Return a value on success in write(); --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp | 1 + plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 1265f9669d..ca78c49c58 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -317,6 +317,7 @@ size_t BootKeyboard_::write(uint8_t k) { sendReport(); releaseAll(); sendReport(); + return 1; } BootKeyboard_ BootKeyboard; diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index 8c328610e0..23face943f 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -189,6 +189,7 @@ size_t Keyboard_::write(uint8_t k) { sendReport(); releaseAll(); sendReport(); + return 1; } From 20b19d1476e4fe2d16bd3ecde26bae9bf74ea1a7 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 29 Jan 2016 18:36:20 -0800 Subject: [PATCH 442/602] Rename the KeyboardioHID top-level header to the name of the project --- plugins/KeyboardioHID/examples/Consumer/Consumer.ino | 2 +- plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino | 2 +- .../examples/Keyboard/BootKeyboard/BootKeyboard.ino | 2 +- .../KeyboardioHID/examples/Keyboard/KeyboardLed/KeyboardLed.ino | 2 +- plugins/KeyboardioHID/examples/Keyboard/NKRO/NKRO.ino | 2 +- .../examples/Mouse/AbsoluteMouse/AbsoluteMouse.ino | 2 +- .../examples/Mouse/ImprovedMouse/ImprovedMouse.ino | 2 +- plugins/KeyboardioHID/examples/System/System.ino | 2 +- plugins/KeyboardioHID/keywords.txt | 2 +- plugins/KeyboardioHID/src/{HID-Project.h => KeyboardioHID.h} | 0 10 files changed, 9 insertions(+), 9 deletions(-) rename plugins/KeyboardioHID/src/{HID-Project.h => KeyboardioHID.h} (100%) diff --git a/plugins/KeyboardioHID/examples/Consumer/Consumer.ino b/plugins/KeyboardioHID/examples/Consumer/Consumer.ino index f211c499ab..a38109b9ac 100644 --- a/plugins/KeyboardioHID/examples/Consumer/Consumer.ino +++ b/plugins/KeyboardioHID/examples/Consumer/Consumer.ino @@ -9,7 +9,7 @@ https://github.com/NicoHood/HID/wiki/Consumer-API */ -#include "HID-Project.h" +#include "KeyboardioHID.h" const int pinLed = LED_BUILTIN; const int pinButton = 2; diff --git a/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino b/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino index 7121859973..541bba9172 100644 --- a/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino +++ b/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino @@ -12,7 +12,7 @@ https://github.com/NicoHood/HID/wiki/Gamepad-API */ -#include "HID-Project.h" +#include "KeyboardioHID.h" const int pinLed = LED_BUILTIN; const int pinButton = 2; diff --git a/plugins/KeyboardioHID/examples/Keyboard/BootKeyboard/BootKeyboard.ino b/plugins/KeyboardioHID/examples/Keyboard/BootKeyboard/BootKeyboard.ino index bf0be40ccc..f7cccb64c6 100644 --- a/plugins/KeyboardioHID/examples/Keyboard/BootKeyboard/BootKeyboard.ino +++ b/plugins/KeyboardioHID/examples/Keyboard/BootKeyboard/BootKeyboard.ino @@ -11,7 +11,7 @@ https://github.com/NicoHood/HID/wiki/Keyboard-API#boot-keyboard */ -#include "HID-Project.h" +#include "KeyboardioHID.h" const int pinLed = LED_BUILTIN; const int pinButton = 2; diff --git a/plugins/KeyboardioHID/examples/Keyboard/KeyboardLed/KeyboardLed.ino b/plugins/KeyboardioHID/examples/Keyboard/KeyboardLed/KeyboardLed.ino index 88df32e394..1e527c7ab1 100644 --- a/plugins/KeyboardioHID/examples/Keyboard/KeyboardLed/KeyboardLed.ino +++ b/plugins/KeyboardioHID/examples/Keyboard/KeyboardLed/KeyboardLed.ino @@ -12,7 +12,7 @@ https://github.com/NicoHood/HID/wiki/Keyboard-API */ -#include "HID-Project.h" +#include "KeyboardioHID.h" const int pinLed = LED_BUILTIN; const int pinButton = 2; diff --git a/plugins/KeyboardioHID/examples/Keyboard/NKRO/NKRO.ino b/plugins/KeyboardioHID/examples/Keyboard/NKRO/NKRO.ino index a427e015d9..42d06b5ff2 100644 --- a/plugins/KeyboardioHID/examples/Keyboard/NKRO/NKRO.ino +++ b/plugins/KeyboardioHID/examples/Keyboard/NKRO/NKRO.ino @@ -13,7 +13,7 @@ https://github.com/NicoHood/HID/wiki/Keyboard-API#nkro-keyboard */ -#include "HID-Project.h" +#include "KeyboardioHID.h" const int pinLed = LED_BUILTIN; const int pinButton = 2; diff --git a/plugins/KeyboardioHID/examples/Mouse/AbsoluteMouse/AbsoluteMouse.ino b/plugins/KeyboardioHID/examples/Mouse/AbsoluteMouse/AbsoluteMouse.ino index 872ee63eb6..6c67a41f3f 100644 --- a/plugins/KeyboardioHID/examples/Mouse/AbsoluteMouse/AbsoluteMouse.ino +++ b/plugins/KeyboardioHID/examples/Mouse/AbsoluteMouse/AbsoluteMouse.ino @@ -10,7 +10,7 @@ https://github.com/NicoHood/HID/wiki/AbsoluteMouse-API */ -#include "HID-Project.h" +#include "KeyboardioHID.h" const int pinLed = LED_BUILTIN; const int pinButtonClick = 2; diff --git a/plugins/KeyboardioHID/examples/Mouse/ImprovedMouse/ImprovedMouse.ino b/plugins/KeyboardioHID/examples/Mouse/ImprovedMouse/ImprovedMouse.ino index 3789431df4..378b06ea85 100644 --- a/plugins/KeyboardioHID/examples/Mouse/ImprovedMouse/ImprovedMouse.ino +++ b/plugins/KeyboardioHID/examples/Mouse/ImprovedMouse/ImprovedMouse.ino @@ -13,7 +13,7 @@ https://github.com/NicoHood/HID/wiki/Mouse-API */ -#include "HID-Project.h" +#include "KeyboardioHID.h" const int pinLed = LED_BUILTIN; const int pinButtonClick = 2; diff --git a/plugins/KeyboardioHID/examples/System/System.ino b/plugins/KeyboardioHID/examples/System/System.ino index 9746b909d4..31d7bce50a 100644 --- a/plugins/KeyboardioHID/examples/System/System.ino +++ b/plugins/KeyboardioHID/examples/System/System.ino @@ -10,7 +10,7 @@ https://github.com/NicoHood/HID/wiki/System-API */ -#include "HID-Project.h" +#include "KeyboardioHID.h" const int pinLed = LED_BUILTIN; const int pinButtonS = 2; diff --git a/plugins/KeyboardioHID/keywords.txt b/plugins/KeyboardioHID/keywords.txt index 862e8e0afa..fd3d69dd46 100644 --- a/plugins/KeyboardioHID/keywords.txt +++ b/plugins/KeyboardioHID/keywords.txt @@ -1,5 +1,5 @@ ####################################### -# Syntax Coloring Map For HID-Project +# Syntax Coloring Map For KeyboardioHID ####################################### ####################################### diff --git a/plugins/KeyboardioHID/src/HID-Project.h b/plugins/KeyboardioHID/src/KeyboardioHID.h similarity index 100% rename from plugins/KeyboardioHID/src/HID-Project.h rename to plugins/KeyboardioHID/src/KeyboardioHID.h From 4427779ff74d3fb43846b33bc0c8af6eda702121 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Sun, 31 Jan 2016 20:41:07 -0800 Subject: [PATCH 443/602] Switch to using unsigned 0-65536 coordinates for absolute mouse --- .../examples/Mouse/AbsoluteMouse/AbsoluteMouse.ino | 6 +++--- plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/KeyboardioHID/examples/Mouse/AbsoluteMouse/AbsoluteMouse.ino b/plugins/KeyboardioHID/examples/Mouse/AbsoluteMouse/AbsoluteMouse.ino index 6c67a41f3f..a4b38a9beb 100644 --- a/plugins/KeyboardioHID/examples/Mouse/AbsoluteMouse/AbsoluteMouse.ino +++ b/plugins/KeyboardioHID/examples/Mouse/AbsoluteMouse/AbsoluteMouse.ino @@ -44,10 +44,10 @@ void loop() { if (!digitalRead(pinButtonCenter)) { digitalWrite(pinLed, HIGH); - // Move to coordinate (16bit signed, -32768 - 32767) + // Move to coordinate (16bit unsigned, 0 - 65535) // Moving to the same position twice will not work! // X and Y start in the upper left corner. - AbsoluteMouse.moveTo(0, 0); + AbsoluteMouse.moveTo(32767,32767); // Simple debounce delay(300); @@ -58,7 +58,7 @@ void loop() { digitalWrite(pinLed, HIGH); // Move relative to last coordinate - AbsoluteMouse.move(1000, 1000); + AbsoluteMouse.move(33767, 33767); // Simple debounce delay(300); diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp index ce47450c75..774798cad0 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp @@ -45,8 +45,8 @@ static const uint8_t _hidMultiReportDescriptorAbsoluteMouse[] PROGMEM = { _USAGE_PAGE, _PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ _USAGE, 0x30, /* USAGE (X) */ _USAGE, 0x31, /* USAGE (Y) */ - _MULTIBYTE(_LOGICAL_MINIMUM), 0x00, 0x80, /* Logical Minimum (-32768) */ - _MULTIBYTE(_LOGICAL_MAXIMUM), 0xFF, 0x7F, /* Logical Maximum (32767) */ + _MULTIBYTE(_LOGICAL_MINIMUM), 0x00, 0x00, /* Logical Minimum (0) */ + _MULTIBYTE(_LOGICAL_MAXIMUM), 0xFF, 0xFF, /* Logical Maximum (65535) */ _REPORT_SIZE, 0x10, /* Report Size (16), */ _REPORT_COUNT, 0x02, /* Report Count (2), */ _INPUT, (_DATA|_VARIABLE|_ABSOLUTE), /* Input (Data, Variable, Absolute) */ From 0f06f8ff43a4b6c80c20670d3fab49429571d51c Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Sun, 31 Jan 2016 21:20:33 -0800 Subject: [PATCH 444/602] Revert "Switch to using unsigned 0-65536 coordinates for absolute mouse" This reverts commit 4427779ff74d3fb43846b33bc0c8af6eda702121. --- .../examples/Mouse/AbsoluteMouse/AbsoluteMouse.ino | 6 +++--- plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/KeyboardioHID/examples/Mouse/AbsoluteMouse/AbsoluteMouse.ino b/plugins/KeyboardioHID/examples/Mouse/AbsoluteMouse/AbsoluteMouse.ino index a4b38a9beb..6c67a41f3f 100644 --- a/plugins/KeyboardioHID/examples/Mouse/AbsoluteMouse/AbsoluteMouse.ino +++ b/plugins/KeyboardioHID/examples/Mouse/AbsoluteMouse/AbsoluteMouse.ino @@ -44,10 +44,10 @@ void loop() { if (!digitalRead(pinButtonCenter)) { digitalWrite(pinLed, HIGH); - // Move to coordinate (16bit unsigned, 0 - 65535) + // Move to coordinate (16bit signed, -32768 - 32767) // Moving to the same position twice will not work! // X and Y start in the upper left corner. - AbsoluteMouse.moveTo(32767,32767); + AbsoluteMouse.moveTo(0, 0); // Simple debounce delay(300); @@ -58,7 +58,7 @@ void loop() { digitalWrite(pinLed, HIGH); // Move relative to last coordinate - AbsoluteMouse.move(33767, 33767); + AbsoluteMouse.move(1000, 1000); // Simple debounce delay(300); diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp index 774798cad0..ce47450c75 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp @@ -45,8 +45,8 @@ static const uint8_t _hidMultiReportDescriptorAbsoluteMouse[] PROGMEM = { _USAGE_PAGE, _PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ _USAGE, 0x30, /* USAGE (X) */ _USAGE, 0x31, /* USAGE (Y) */ - _MULTIBYTE(_LOGICAL_MINIMUM), 0x00, 0x00, /* Logical Minimum (0) */ - _MULTIBYTE(_LOGICAL_MAXIMUM), 0xFF, 0xFF, /* Logical Maximum (65535) */ + _MULTIBYTE(_LOGICAL_MINIMUM), 0x00, 0x80, /* Logical Minimum (-32768) */ + _MULTIBYTE(_LOGICAL_MAXIMUM), 0xFF, 0x7F, /* Logical Maximum (32767) */ _REPORT_SIZE, 0x10, /* Report Size (16), */ _REPORT_COUNT, 0x02, /* Report Count (2), */ _INPUT, (_DATA|_VARIABLE|_ABSOLUTE), /* Input (Data, Variable, Absolute) */ From 6c564bc6657d5ef9be29b6bb4db17a0a53bc018a Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Sun, 31 Jan 2016 21:33:01 -0800 Subject: [PATCH 445/602] The previous value hadn't actually wrapped around --- plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp index ce47450c75..e359b41563 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp @@ -45,7 +45,7 @@ static const uint8_t _hidMultiReportDescriptorAbsoluteMouse[] PROGMEM = { _USAGE_PAGE, _PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ _USAGE, 0x30, /* USAGE (X) */ _USAGE, 0x31, /* USAGE (Y) */ - _MULTIBYTE(_LOGICAL_MINIMUM), 0x00, 0x80, /* Logical Minimum (-32768) */ + _MULTIBYTE(_LOGICAL_MINIMUM), 0x00, 0x81, /* Logical Minimum (-32767) */ _MULTIBYTE(_LOGICAL_MAXIMUM), 0xFF, 0x7F, /* Logical Maximum (32767) */ _REPORT_SIZE, 0x10, /* Report Size (16), */ _REPORT_COUNT, 0x02, /* Report Count (2), */ From b9b75ed3987c3b4c98f031a79499c4153d4d49c0 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Sun, 31 Jan 2016 21:34:04 -0800 Subject: [PATCH 446/602] Explicitly specify that moveTo takes 16 bit parameters --- plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp | 2 +- plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp index e359b41563..38c14104e9 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp @@ -116,7 +116,7 @@ void AbsoluteMouse_::click(uint8_t b) { moveTo(xAxis, yAxis, 0); } -void AbsoluteMouse_::moveTo(int x, int y, signed char wheel) { +void AbsoluteMouse_::moveTo(int16_t x, int16_t y, signed char wheel) { xAxis = x; yAxis = y; HID_MouseAbsoluteReport_Data_t report; diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h index c44c9afc1c..de385cd58c 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h @@ -60,7 +60,7 @@ class AbsoluteMouse_ { void end(void); void click(uint8_t b = MOUSE_LEFT); - void moveTo(int x, int y, signed char wheel = 0); + void moveTo(int16_t x, int16_t y, signed char wheel = 0); void move(int x, int y, signed char wheel = 0); void press(uint8_t b = MOUSE_LEFT); void release(uint8_t b = MOUSE_LEFT); From 98c6c20b81ec3ed4eb5f8a63c6c1589e17931c6b Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Sun, 31 Jan 2016 22:14:38 -0800 Subject: [PATCH 447/602] Switch to an 0-32767 space for the AbsoluteMouse. Seems to behave more reiably --- .../KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp | 6 +++--- plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp index 38c14104e9..e017095eee 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp @@ -45,8 +45,8 @@ static const uint8_t _hidMultiReportDescriptorAbsoluteMouse[] PROGMEM = { _USAGE_PAGE, _PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ _USAGE, 0x30, /* USAGE (X) */ _USAGE, 0x31, /* USAGE (Y) */ - _MULTIBYTE(_LOGICAL_MINIMUM), 0x00, 0x81, /* Logical Minimum (-32767) */ - _MULTIBYTE(_LOGICAL_MAXIMUM), 0xFF, 0x7F, /* Logical Maximum (32767) */ + _MULTIBYTE(_LOGICAL_MINIMUM), 0x00, 0x00, /* Logical Minimum (0) */ + _MULTIBYTE(_LOGICAL_MAXIMUM), 0xFF, 0x7f, /* Logical Maximum (32767) */ _REPORT_SIZE, 0x10, /* Report Size (16), */ _REPORT_COUNT, 0x02, /* Report Count (2), */ _INPUT, (_DATA|_VARIABLE|_ABSOLUTE), /* Input (Data, Variable, Absolute) */ @@ -116,7 +116,7 @@ void AbsoluteMouse_::click(uint8_t b) { moveTo(xAxis, yAxis, 0); } -void AbsoluteMouse_::moveTo(int16_t x, int16_t y, signed char wheel) { +void AbsoluteMouse_::moveTo(uint16_t x, uint16_t y, signed char wheel) { xAxis = x; yAxis = y; HID_MouseAbsoluteReport_Data_t report; diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h index de385cd58c..2253dcb3eb 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h @@ -47,8 +47,8 @@ typedef union { uint32_t whole32[]; struct { uint8_t buttons; - int16_t xAxis; - int16_t yAxis; + uint16_t xAxis; + uint16_t yAxis; int8_t wheel; }; } HID_MouseAbsoluteReport_Data_t; @@ -60,7 +60,7 @@ class AbsoluteMouse_ { void end(void); void click(uint8_t b = MOUSE_LEFT); - void moveTo(int16_t x, int16_t y, signed char wheel = 0); + void moveTo(uint16_t x, uint16_t y, signed char wheel = 0); void move(int x, int y, signed char wheel = 0); void press(uint8_t b = MOUSE_LEFT); void release(uint8_t b = MOUSE_LEFT); @@ -70,8 +70,8 @@ class AbsoluteMouse_ { void SendReport(void* data, int length); protected: - int16_t xAxis; - int16_t yAxis; + uint16_t xAxis; + uint16_t yAxis; uint8_t _buttons; void buttons(uint8_t b); From 735aa036d8f66593c73892afc01aee5d2a1f772c Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 19 Feb 2016 15:57:00 -0800 Subject: [PATCH 448/602] [travis] Add build infrastructure that proves our sample code is made of lies --- plugins/KeyboardioHID/.travis.yml | 31 ++++++++++++++++++++++++ plugins/KeyboardioHID/Makefile | 39 +++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 plugins/KeyboardioHID/.travis.yml create mode 100644 plugins/KeyboardioHID/Makefile diff --git a/plugins/KeyboardioHID/.travis.yml b/plugins/KeyboardioHID/.travis.yml new file mode 100644 index 0000000000..04acae1c3c --- /dev/null +++ b/plugins/KeyboardioHID/.travis.yml @@ -0,0 +1,31 @@ +language: c +before_install: +- pushd .. +- wget http://downloads.arduino.cc/arduino-1.6.7-linux64.tar.xz +- tar xf arduino-1.6.7-linux64.tar.xz +- popd +script: +- make smoke ARDUINO_PATH=../arduino-1.6.7 ARDUINO_LOCAL_LIB_PATH=. SKETCH=examples/Consumer/Consumer.ino +- make smoke ARDUINO_PATH=../arduino-1.6.7 ARDUINO_LOCAL_LIB_PATH=. SKETCH=examples/Gamepad/Gamepad.ino +- make smoke ARDUINO_PATH=../arduino-1.6.7 ARDUINO_LOCAL_LIB_PATH=. SKETCH=examples/Keyboard/BootKeyboard/BootKeyboard.ino +- make smoke ARDUINO_PATH=../arduino-1.6.7 ARDUINO_LOCAL_LIB_PATH=. SKETCH=examples/Keyboard/KeyboardLed/KeyboardLed.ino +- make smoke ARDUINO_PATH=../arduino-1.6.7 ARDUINO_LOCAL_LIB_PATH=. SKETCH=examples/Keyboard/NKRO/NKRO.ino +- make smoke ARDUINO_PATH=../arduino-1.6.7 ARDUINO_LOCAL_LIB_PATH=. SKETCH=examples/Mouse/AbsoluteMouse/AbsoluteMouse.ino +- make smoke ARDUINO_PATH=../arduino-1.6.7 ARDUINO_LOCAL_LIB_PATH=. SKETCH=examples/Mouse/ImprovedMouse/ImprovedMouse.ino +- make smoke ARDUINO_PATH=../arduino-1.6.7 ARDUINO_LOCAL_LIB_PATH=. SKETCH=examples/System/System.ino + +notifications: + irc: + channels: + - "chat.freenode.net#keyboardio" + use_notice: true + skip_join: true + template: + - "%{repository_name}/%{branch} %{commit} by %{author}: %{commit_subject} %{build_url} %{message}" + email: + on_success: change + on_failure: change + slack: + secure: geVAHVhYQ5bY7ja5vx1Tgxc5y64WLuXVEWKmw4LqiThFYCjtpdWkHGiZJfhUwkVI11u5w8w1FUmrB7ZP4EUGoXhCK/z1mvVMVJ9+fS+WoaqcTHFJi0hGbvXaFPD7QA+ef7TLrFcU643kf6KHN/P+dVVndLyhctXZqOZHHwXmKZNMt8qM5Gh5h41HOi0YjT9yFafSU0qf5jphF5qvjlxKsVJF+WxtMSU4xMYxzq7rf80bPi2pu4ijgqR5+Haaa71DJ1V2TA4wZ+BFTBo2YUJIGZ8qDlqmb7RdF/u72G/8HbT/Hzj55blrpBXU/BPkokGOPJlIGHPV76ESpJI0ZUILRifmkZY6ylMjl/hutDYPNjhMq8Z/UKSLN6pJQAq0PjqAoHCtPsXTbRMT0lhVt2itkCPwAXVgszTrE6INsNylY/soaDu66Sjmz2zQH8sC6hbL8SrZ0xGs1Q+e3q5WMETPIAS9f4n2YCxkIz4ORoL9IrOXUcebVNriiWKzOBt6bleWPJlGc6yVYkkUhvURH+jEp6v2Y5SqsaJVTD3I5Gq/H/0PJBtPdzu470yQ3/FD4g6M0AmWx8DCuvl1O295QOZbUtujpIowTm7PynFrAgW3ptSidjzWjzZaHc0iQJBiNi86dg3GomoEEOPzx8hnX7fhFgsR+Ixqfzx0srrQYqleQGY= +cache: + ccache: true diff --git a/plugins/KeyboardioHID/Makefile b/plugins/KeyboardioHID/Makefile new file mode 100644 index 0000000000..4f317f2f28 --- /dev/null +++ b/plugins/KeyboardioHID/Makefile @@ -0,0 +1,39 @@ +# Arduino Make file. Refer to https://github.com/sudar/Arduino-Makefile + +#BOARD_TAG = keyboardio +BOARD = model01 +MCU = atmega32u4 + +ARDUINO_LIBS = + +ARDUINO_PATH=/Applications/Arduino.app/Contents/Java/ +ARDUINO_TOOLS_PATH=$(ARDUINO_PATH)/hardware/tools +FQBN=arduino:avr:leonardo +BUILD_PATH := $(shell mktemp -d 2>/dev/null || mktemp -d -t 'build') +ARDUINO_LOCAL_LIB_PATH=~/Documents/Arduino/libraries +ARDUINO_IDE_VERSION=100607 +VERBOSE := #-verbose +SKETCH_BASENAME = `basename "${SKETCH}"` + +smoke: compile size + +astyle: + find . -type f -name \*.cpp |xargs -n 1 astyle --style=google + find . -type f -name \*.ino |xargs -n 1 astyle --style=google + find . -type f -name \*.h |xargs -n 1 astyle --style=google + + +compile: + $(ARDUINO_PATH)/arduino-builder \ + -hardware $(ARDUINO_PATH)/hardware \ + -tools $(ARDUINO_TOOLS_PATH) \ + -tools $(ARDUINO_PATH)/tools-builder \ + -fqbn $(FQBN) \ + -libraries $(ARDUINO_LOCAL_LIB_PATH) \ + $(VERBOSE) \ + -build-path $(BUILD_PATH) \ + -ide-version $(ARDUINO_IDE_VERSION) \ + $(SKETCH) + +size: compile + $(ARDUINO_TOOLS_PATH)/avr/bin/avr-size -C --mcu=$(MCU) $(BUILD_PATH)/$(SKETCH_BASENAME).elf From 5e76cf166c2b74182510f6952ebb7b133a646f16 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 19 Feb 2016 16:00:27 -0800 Subject: [PATCH 449/602] [travis] The local lib path is up one level --- plugins/KeyboardioHID/.travis.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/plugins/KeyboardioHID/.travis.yml b/plugins/KeyboardioHID/.travis.yml index 04acae1c3c..a6ac5c0f9a 100644 --- a/plugins/KeyboardioHID/.travis.yml +++ b/plugins/KeyboardioHID/.travis.yml @@ -5,14 +5,14 @@ before_install: - tar xf arduino-1.6.7-linux64.tar.xz - popd script: -- make smoke ARDUINO_PATH=../arduino-1.6.7 ARDUINO_LOCAL_LIB_PATH=. SKETCH=examples/Consumer/Consumer.ino -- make smoke ARDUINO_PATH=../arduino-1.6.7 ARDUINO_LOCAL_LIB_PATH=. SKETCH=examples/Gamepad/Gamepad.ino -- make smoke ARDUINO_PATH=../arduino-1.6.7 ARDUINO_LOCAL_LIB_PATH=. SKETCH=examples/Keyboard/BootKeyboard/BootKeyboard.ino -- make smoke ARDUINO_PATH=../arduino-1.6.7 ARDUINO_LOCAL_LIB_PATH=. SKETCH=examples/Keyboard/KeyboardLed/KeyboardLed.ino -- make smoke ARDUINO_PATH=../arduino-1.6.7 ARDUINO_LOCAL_LIB_PATH=. SKETCH=examples/Keyboard/NKRO/NKRO.ino -- make smoke ARDUINO_PATH=../arduino-1.6.7 ARDUINO_LOCAL_LIB_PATH=. SKETCH=examples/Mouse/AbsoluteMouse/AbsoluteMouse.ino -- make smoke ARDUINO_PATH=../arduino-1.6.7 ARDUINO_LOCAL_LIB_PATH=. SKETCH=examples/Mouse/ImprovedMouse/ImprovedMouse.ino -- make smoke ARDUINO_PATH=../arduino-1.6.7 ARDUINO_LOCAL_LIB_PATH=. SKETCH=examples/System/System.ino +- make smoke ARDUINO_PATH=../arduino-1.6.7 ARDUINO_LOCAL_LIB_PATH=.. SKETCH=examples/Consumer/Consumer.ino +- make smoke ARDUINO_PATH=../arduino-1.6.7 ARDUINO_LOCAL_LIB_PATH=.. SKETCH=examples/Gamepad/Gamepad.ino +- make smoke ARDUINO_PATH=../arduino-1.6.7 ARDUINO_LOCAL_LIB_PATH=.. SKETCH=examples/Keyboard/BootKeyboard/BootKeyboard.ino +- make smoke ARDUINO_PATH=../arduino-1.6.7 ARDUINO_LOCAL_LIB_PATH=.. SKETCH=examples/Keyboard/KeyboardLed/KeyboardLed.ino +- make smoke ARDUINO_PATH=../arduino-1.6.7 ARDUINO_LOCAL_LIB_PATH=.. SKETCH=examples/Keyboard/NKRO/NKRO.ino +- make smoke ARDUINO_PATH=../arduino-1.6.7 ARDUINO_LOCAL_LIB_PATH=.. SKETCH=examples/Mouse/AbsoluteMouse/AbsoluteMouse.ino +- make smoke ARDUINO_PATH=../arduino-1.6.7 ARDUINO_LOCAL_LIB_PATH=.. SKETCH=examples/Mouse/ImprovedMouse/ImprovedMouse.ino +- make smoke ARDUINO_PATH=../arduino-1.6.7 ARDUINO_LOCAL_LIB_PATH=.. SKETCH=examples/System/System.ino notifications: irc: From f2f3ee4f70393348bd4c2a45f088adf54132b5a3 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 19 Feb 2016 16:46:29 -0800 Subject: [PATCH 450/602] Update examples so they compile --- .../examples/Consumer/Consumer.ino | 2 +- .../Keyboard/KeyboardLed/KeyboardLed.ino | 2 +- .../examples/Keyboard/NKRO/NKRO.ino | 26 +++++++++---------- .../KeyboardioHID/examples/System/System.ino | 6 ++--- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/plugins/KeyboardioHID/examples/Consumer/Consumer.ino b/plugins/KeyboardioHID/examples/Consumer/Consumer.ino index a38109b9ac..b7ae7c9653 100644 --- a/plugins/KeyboardioHID/examples/Consumer/Consumer.ino +++ b/plugins/KeyboardioHID/examples/Consumer/Consumer.ino @@ -27,7 +27,7 @@ void loop() { digitalWrite(pinLed, HIGH); // See HID Project documentation for more Consumer keys - ConsumerControl.write(MEDIA_PLAY_PAUSE); + ConsumerControl.write(HID_CONSUMER_PLAY_SLASH_PAUSE); // Simple debounce delay(300); diff --git a/plugins/KeyboardioHID/examples/Keyboard/KeyboardLed/KeyboardLed.ino b/plugins/KeyboardioHID/examples/Keyboard/KeyboardLed/KeyboardLed.ino index 1e527c7ab1..0bc5301de7 100644 --- a/plugins/KeyboardioHID/examples/Keyboard/KeyboardLed/KeyboardLed.ino +++ b/plugins/KeyboardioHID/examples/Keyboard/KeyboardLed/KeyboardLed.ino @@ -36,7 +36,7 @@ void loop() { // Trigger caps lock manually via button if (!digitalRead(pinButton)) { - BootKeyboard.write(KEY_CAPS_LOCK); + BootKeyboard.write(HID_KEYBOARD_CAPS_LOCK); // Simple debounce delay(300); diff --git a/plugins/KeyboardioHID/examples/Keyboard/NKRO/NKRO.ino b/plugins/KeyboardioHID/examples/Keyboard/NKRO/NKRO.ino index 42d06b5ff2..903d3a7a68 100644 --- a/plugins/KeyboardioHID/examples/Keyboard/NKRO/NKRO.ino +++ b/plugins/KeyboardioHID/examples/Keyboard/NKRO/NKRO.ino @@ -34,21 +34,21 @@ void loop() { // Do not press to many at once or some OS will have problems. // Note that the resulting pressed order might differ, // because all keys are pressed at the same time. - NKROKeyboard.press(KEY_0); - NKROKeyboard.press(KEY_1); - NKROKeyboard.press(KEY_2); - NKROKeyboard.press(KEY_3); - NKROKeyboard.press(KEY_4); - NKROKeyboard.press(KEY_5); - NKROKeyboard.press(KEY_6); - NKROKeyboard.press(KEY_7); - NKROKeyboard.press(KEY_8); - NKROKeyboard.press(KEY_9); - NKROKeyboard.sendReport(); + Keyboard.press(KEY_0); + Keyboard.press(KEY_1); + Keyboard.press(KEY_2); + Keyboard.press(KEY_3); + Keyboard.press(KEY_4); + Keyboard.press(KEY_5); + Keyboard.press(KEY_6); + Keyboard.press(KEY_7); + Keyboard.press(KEY_8); + Keyboard.press(KEY_9); + Keyboard.sendReport(); // Release all keys and hit enter - NKROKeyboard.releaseAll(); - NKROKeyboard.println(); + Keyboard.releaseAll(); + Keyboard.println(); // Simple debounce delay(300); diff --git a/plugins/KeyboardioHID/examples/System/System.ino b/plugins/KeyboardioHID/examples/System/System.ino index 31d7bce50a..29587a81ea 100644 --- a/plugins/KeyboardioHID/examples/System/System.ino +++ b/plugins/KeyboardioHID/examples/System/System.ino @@ -31,8 +31,8 @@ void loop() { digitalWrite(pinLed, HIGH); // Puts PC into sleep mode/shuts it down - SystemControl.write(SYSTEM_SLEEP); - //SystemControl.write(SYSTEM_POWER_DOWN); + SystemControl.write(HID_SYSTEM_SLEEP); + //SystemControl.write(HID_SYSTEM_POWER_DOWN); // Simple debounce delay(300); @@ -44,7 +44,7 @@ void loop() { // Try to wake up the PC // This might fail on some PCs/Laptops where USB wakeup is not supported - SystemControl.write(SYSTEM_WAKE_UP); + SystemControl.write(HID_SYSTEM_WAKE_UP); // Simple debounce delay(300); From a651fc3c6ae7bf861ed7c1f3d80e94428a418037 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 19 Feb 2016 16:47:14 -0800 Subject: [PATCH 451/602] Update makefile and travis config to automatically smoke all examples --- plugins/KeyboardioHID/.travis.yml | 9 +-------- plugins/KeyboardioHID/Makefile | 15 ++++++++------- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/plugins/KeyboardioHID/.travis.yml b/plugins/KeyboardioHID/.travis.yml index a6ac5c0f9a..c2ad5fca9c 100644 --- a/plugins/KeyboardioHID/.travis.yml +++ b/plugins/KeyboardioHID/.travis.yml @@ -5,14 +5,7 @@ before_install: - tar xf arduino-1.6.7-linux64.tar.xz - popd script: -- make smoke ARDUINO_PATH=../arduino-1.6.7 ARDUINO_LOCAL_LIB_PATH=.. SKETCH=examples/Consumer/Consumer.ino -- make smoke ARDUINO_PATH=../arduino-1.6.7 ARDUINO_LOCAL_LIB_PATH=.. SKETCH=examples/Gamepad/Gamepad.ino -- make smoke ARDUINO_PATH=../arduino-1.6.7 ARDUINO_LOCAL_LIB_PATH=.. SKETCH=examples/Keyboard/BootKeyboard/BootKeyboard.ino -- make smoke ARDUINO_PATH=../arduino-1.6.7 ARDUINO_LOCAL_LIB_PATH=.. SKETCH=examples/Keyboard/KeyboardLed/KeyboardLed.ino -- make smoke ARDUINO_PATH=../arduino-1.6.7 ARDUINO_LOCAL_LIB_PATH=.. SKETCH=examples/Keyboard/NKRO/NKRO.ino -- make smoke ARDUINO_PATH=../arduino-1.6.7 ARDUINO_LOCAL_LIB_PATH=.. SKETCH=examples/Mouse/AbsoluteMouse/AbsoluteMouse.ino -- make smoke ARDUINO_PATH=../arduino-1.6.7 ARDUINO_LOCAL_LIB_PATH=.. SKETCH=examples/Mouse/ImprovedMouse/ImprovedMouse.ino -- make smoke ARDUINO_PATH=../arduino-1.6.7 ARDUINO_LOCAL_LIB_PATH=.. SKETCH=examples/System/System.ino +- make smoke ARDUINO_PATH=../arduino-1.6.7 ARDUINO_LOCAL_LIB_PATH=.. notifications: irc: diff --git a/plugins/KeyboardioHID/Makefile b/plugins/KeyboardioHID/Makefile index 4f317f2f28..ca6bb3bd7d 100644 --- a/plugins/KeyboardioHID/Makefile +++ b/plugins/KeyboardioHID/Makefile @@ -13,17 +13,20 @@ BUILD_PATH := $(shell mktemp -d 2>/dev/null || mktemp -d -t 'build') ARDUINO_LOCAL_LIB_PATH=~/Documents/Arduino/libraries ARDUINO_IDE_VERSION=100607 VERBOSE := #-verbose -SKETCH_BASENAME = `basename "${SKETCH}"` -smoke: compile size +EXAMPLES=$(shell find ./examples -type f -name \*.ino ) +EXAMPLES_HEX := $(addsuffix .hex,${EXAMPLES}) + astyle: find . -type f -name \*.cpp |xargs -n 1 astyle --style=google find . -type f -name \*.ino |xargs -n 1 astyle --style=google find . -type f -name \*.h |xargs -n 1 astyle --style=google +smoke: ${EXAMPLES_HEX} + +${EXAMPLES_HEX}: %.hex: -compile: $(ARDUINO_PATH)/arduino-builder \ -hardware $(ARDUINO_PATH)/hardware \ -tools $(ARDUINO_TOOLS_PATH) \ @@ -33,7 +36,5 @@ compile: $(VERBOSE) \ -build-path $(BUILD_PATH) \ -ide-version $(ARDUINO_IDE_VERSION) \ - $(SKETCH) - -size: compile - $(ARDUINO_TOOLS_PATH)/avr/bin/avr-size -C --mcu=$(MCU) $(BUILD_PATH)/$(SKETCH_BASENAME).elf + $* + $(ARDUINO_TOOLS_PATH)/avr/bin/avr-size -C --mcu=$(MCU) $(BUILD_PATH)/$(shell basename $*).elf From 22f4858095dcf97f0bc2b274a338311046214c42 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 19 Feb 2016 16:56:24 -0800 Subject: [PATCH 452/602] Include the arduino ~core libraries.\n\nWe don't need it for this repo, but we do need it for other repos and standardization is good --- plugins/KeyboardioHID/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/KeyboardioHID/Makefile b/plugins/KeyboardioHID/Makefile index ca6bb3bd7d..9202634b87 100644 --- a/plugins/KeyboardioHID/Makefile +++ b/plugins/KeyboardioHID/Makefile @@ -32,6 +32,7 @@ ${EXAMPLES_HEX}: %.hex: -tools $(ARDUINO_TOOLS_PATH) \ -tools $(ARDUINO_PATH)/tools-builder \ -fqbn $(FQBN) \ + -libraries $(ARDUINO_PATH)/libraries \ -libraries $(ARDUINO_LOCAL_LIB_PATH) \ $(VERBOSE) \ -build-path $(BUILD_PATH) \ From 36ff080b6a6f1ff40768811b93875de31c9084e0 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Mon, 24 Oct 2016 13:07:15 +0200 Subject: [PATCH 453/602] Make the hiding of Print::write explicit To avoid a compiler warning (with -Woverloaded-virtual), mark Print::write as private in both BootKeyboard.h and MultiReport/Keyboard.h. The original Print::write is not used anywhere, the intent is clearly to hide it. Let the compiler know that, too. Signed-off-by: Gergely Nagy --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h | 3 +++ plugins/KeyboardioHID/src/MultiReport/Keyboard.h | 2 ++ 2 files changed, 5 insertions(+) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index d0e4281bf7..26a8d1cbd0 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -106,6 +106,9 @@ class BootKeyboard_ : public Print, PluggableUSBModule { uint8_t* featureReport; int featureLength; + + private: + using Print::write; }; extern BootKeyboard_ BootKeyboard; diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h index b70cbc8f0b..aca4c515c6 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h @@ -64,6 +64,8 @@ class Keyboard_ : public Print { protected: HID_KeyboardReport_Data_t _keyReport; + private: + using Print::write; }; extern Keyboard_ Keyboard; From b1202b80cb950ed8f77d9801a4bf9a0e8571fd86 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Sat, 29 Oct 2016 10:00:12 +0200 Subject: [PATCH 454/602] Add a method to return if a modifier is active In case one would like to implement behaviour that changes when a modifier is active, one would need to know the state of the modifier. While it is possible to track this on a higher level, this is something already available in the report. As such, the most straightforward way to achieve this goal is to have a function that looks into the report. This patch does just that. Signed-off-by: Gergely Nagy --- plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp | 8 ++++++++ plugins/KeyboardioHID/src/MultiReport/Keyboard.h | 2 ++ 2 files changed, 10 insertions(+) diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index 23face943f..892f6686c4 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -129,6 +129,14 @@ int Keyboard_::sendReport(void) { return HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &_keyReport, sizeof(_keyReport)); } +boolean Keyboard_::isModifierActive(uint8_t k) { + if(k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { + k = k - HID_KEYBOARD_FIRST_MODIFIER; + return !!(_keyReport.modifiers & (1 << k)); + } + return false; +} + size_t Keyboard_::press(uint8_t k) { // If the key is in the range of 'printable' keys if (k <= HID_KEYPAD_HEXADECIMAL ) { diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h index b70cbc8f0b..0eb41d002b 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h @@ -61,6 +61,8 @@ class Keyboard_ : public Print { int sendReport(void); size_t write(uint8_t k); + boolean isModifierActive(uint8_t k); + protected: HID_KeyboardReport_Data_t _keyReport; From 990731450a8faa238df85f8696a258c67a4082d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Hagstr=C3=B6m?= Date: Fri, 6 Jan 2017 15:07:15 +0100 Subject: [PATCH 455/602] Remove all 'flexible arrays', which is not a valid C++ construct --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h | 3 --- plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h | 3 --- plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h | 3 --- plugins/KeyboardioHID/src/MultiReport/Gamepad.h | 3 --- plugins/KeyboardioHID/src/MultiReport/Keyboard.h | 3 --- plugins/KeyboardioHID/src/MultiReport/Mouse.h | 3 --- plugins/KeyboardioHID/src/MultiReport/SystemControl.h | 1 - 7 files changed, 19 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index 26a8d1cbd0..f8238b48c5 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -34,9 +34,6 @@ THE SOFTWARE. typedef union { // Low level key report: up to 6 keys and shift, ctrl etc at once - uint8_t whole8[]; - uint16_t whole16[]; - uint32_t whole32[]; struct { uint8_t modifiers; uint8_t reserved; diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h index 2253dcb3eb..06523c4040 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h @@ -42,9 +42,6 @@ THE SOFTWARE. typedef union { // Absolute mouse report: 8 buttons, 2 absolute axis, wheel - uint8_t whole8[]; - uint16_t whole16[]; - uint32_t whole32[]; struct { uint8_t buttons; uint16_t xAxis; diff --git a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h index 2e330c4a25..c598334104 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h +++ b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h @@ -31,9 +31,6 @@ THE SOFTWARE. typedef union { // Every usable Consumer key possible, up to 4 keys presses possible - uint8_t whole8[]; - uint16_t whole16[]; - uint32_t whole32[]; uint16_t keys[4]; struct { uint16_t key1; diff --git a/plugins/KeyboardioHID/src/MultiReport/Gamepad.h b/plugins/KeyboardioHID/src/MultiReport/Gamepad.h index 556d43f9df..ae3ab2bf8c 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Gamepad.h +++ b/plugins/KeyboardioHID/src/MultiReport/Gamepad.h @@ -43,9 +43,6 @@ THE SOFTWARE. typedef union { // 32 Buttons, 6 Axis, 2 D-Pads - uint8_t whole8[]; - uint16_t whole16[]; - uint32_t whole32[]; uint32_t buttons; struct { diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h index 0e0bf207a0..6c8f261c78 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h @@ -37,9 +37,6 @@ THE SOFTWARE. typedef union { // Modifiers + keymap - uint8_t whole8[]; - uint16_t whole16[]; - uint32_t whole32[]; struct { uint8_t modifiers; uint8_t keys[KEY_BYTES ]; diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.h b/plugins/KeyboardioHID/src/MultiReport/Mouse.h index 82fb29c526..7797fb6ba6 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.h @@ -40,9 +40,6 @@ THE SOFTWARE. typedef union { // Mouse report: 8 buttons, position, wheel - uint8_t whole8[]; - uint16_t whole16[]; - uint32_t whole32[]; struct { uint8_t buttons; int8_t xAxis; diff --git a/plugins/KeyboardioHID/src/MultiReport/SystemControl.h b/plugins/KeyboardioHID/src/MultiReport/SystemControl.h index 57c2a8256a..1bfdb8cd40 100644 --- a/plugins/KeyboardioHID/src/MultiReport/SystemControl.h +++ b/plugins/KeyboardioHID/src/MultiReport/SystemControl.h @@ -32,7 +32,6 @@ THE SOFTWARE. typedef union { // Every usable system control key possible - uint8_t whole8[]; uint8_t key; } HID_SystemControlReport_Data_t; From d34888ea68486c315ab75145107c7e2a4195644c Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Sat, 18 Feb 2017 12:18:00 +0100 Subject: [PATCH 456/602] Don't implement Print for either of the keyboards Kaleidoscope does not use the Print-functions of the Keyboard object, and they could be easily implemented as plugins instead. As such, remove them from KeyboardioHID, and save over 300 bytes of code, and a dozen bytes of RAM. Signed-off-by: Gergely Nagy --- plugins/KeyboardioHID/src/ASCIIMap.h | 138 ------------------ .../src/BootKeyboard/BootKeyboard.cpp | 16 -- .../src/BootKeyboard/BootKeyboard.h | 7 +- .../src/MultiReport/Keyboard.cpp | 20 --- .../KeyboardioHID/src/MultiReport/Keyboard.h | 7 +- 5 files changed, 2 insertions(+), 186 deletions(-) delete mode 100644 plugins/KeyboardioHID/src/ASCIIMap.h diff --git a/plugins/KeyboardioHID/src/ASCIIMap.h b/plugins/KeyboardioHID/src/ASCIIMap.h deleted file mode 100644 index 325e00f09b..0000000000 --- a/plugins/KeyboardioHID/src/ASCIIMap.h +++ /dev/null @@ -1,138 +0,0 @@ -#pragma once - -// Abuse the upper half of the ascii range to indicate -// shifted characters - -#define SHIFT 0x80 -#define NO_KEY 0x00 -static const uint8_t _asciimap[] PROGMEM = { - NO_KEY, // NUL - NO_KEY, // SOH - NO_KEY, // STX - NO_KEY, // ETX - NO_KEY, // EOT - NO_KEY, // ENQ - NO_KEY, // ACK - NO_KEY, // BEL - KEY_BACKSPACE, // BS Backspace - KEY_TAB, // TAB Tab - KEY_ENTER, // LF Enter - NO_KEY, // VT - NO_KEY, // FF - NO_KEY, // CR - NO_KEY, // SO - NO_KEY, // SI - NO_KEY, // DEL - NO_KEY, // DC1 - NO_KEY, // DC2 - NO_KEY, // DC3 - NO_KEY, // DC4 - NO_KEY, // NAK - NO_KEY, // SYN - NO_KEY, // ETB - NO_KEY, // CAN - NO_KEY, // EM - NO_KEY, // SUB - NO_KEY, // ESC - NO_KEY, // FS - NO_KEY, // GS - NO_KEY, // RS - NO_KEY, // US - - KEY_SPACE, // ' ' Space - KEY_1|SHIFT, // ! - KEY_QUOTE|SHIFT, // " - KEY_3|SHIFT, // # - KEY_4|SHIFT, // $ - KEY_5|SHIFT, // % - KEY_7|SHIFT, // & - KEY_QUOTE, // ' - KEY_9|SHIFT, // ( - KEY_0|SHIFT, // ) - KEY_8|SHIFT, // * - KEY_EQUALS|SHIFT, // + - KEY_COMMA, // , - KEY_MINUS, // - - KEY_PERIOD, // . - KEY_SLASH, // / - KEY_0, // 0 - KEY_1, // 1 - KEY_2, // 2 - KEY_3, // 3 - KEY_4, // 4 - KEY_5, // 5 - KEY_6, // 6 - KEY_7, // 7 - KEY_8, // 8 - KEY_9, // 9 - KEY_SEMICOLON|SHIFT, // : - KEY_SEMICOLON, // ; - KEY_COMMA|SHIFT, // < - KEY_EQUALS, // = - KEY_PERIOD|SHIFT, // > - KEY_SLASH|SHIFT, // ? - KEY_2|SHIFT, // @ - KEY_A|SHIFT, // A - KEY_B|SHIFT, // B - KEY_C|SHIFT, // C - KEY_D|SHIFT, // D - KEY_E|SHIFT, // E - KEY_F|SHIFT, // F - KEY_G|SHIFT, // G - KEY_H|SHIFT, // H - KEY_I|SHIFT, // I - KEY_J|SHIFT, // J - KEY_K|SHIFT, // K - KEY_L|SHIFT, // L - KEY_M|SHIFT, // M - KEY_N|SHIFT, // N - KEY_O|SHIFT, // O - KEY_P|SHIFT, // P - KEY_Q|SHIFT, // Q - KEY_R|SHIFT, // R - KEY_S|SHIFT, // S - KEY_T|SHIFT, // T - KEY_U|SHIFT, // U - KEY_V|SHIFT, // V - KEY_W|SHIFT, // W - KEY_X|SHIFT, // X - KEY_Y|SHIFT, // Y - KEY_Z|SHIFT, // Z - KEY_L_BRACKET, // [ - KEY_BACKSLASH, // bslash - KEY_R_BRACKET, // ] - KEY_6|SHIFT, // ^ - KEY_MINUS|SHIFT, // _ - KEY_GRAVE, // ` - KEY_A, // a - KEY_B, // b - KEY_C, // c - KEY_D, // d - KEY_E, // e - KEY_F, // f - KEY_G, // g - KEY_H, // h - KEY_I, // i - KEY_J, // j - KEY_K, // k - KEY_L, // l - KEY_M, // m - KEY_N, // n - KEY_O, // o - KEY_P, // p - KEY_Q, // q - KEY_R, // r - KEY_S, // s - KEY_T, // t - KEY_U, // u - KEY_V, // v - KEY_W, // w - KEY_X, // x - KEY_Y, // y - KEY_Z, // z - KEY_L_BRACKET|SHIFT, // { - KEY_BACKSLASH|SHIFT, // | - KEY_R_BRACKET|SHIFT, // } - KEY_GRAVE|SHIFT, // ~ - NO_KEY // DEL -}; diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index ca78c49c58..4c8df30a76 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -304,20 +304,4 @@ void BootKeyboard_::releaseAll(void) { memset(&_keyReport.keys, 0x00, sizeof(_keyReport.keys)); } -size_t BootKeyboard_::write(uint8_t k) { - if(k >= sizeof(_asciimap)) // Ignore invalid input - return 0; - - // Read key from ascii lookup table - k = pgm_read_byte(_asciimap + k); - - if(k & SHIFT) - press(HID_KEYBOARD_LEFT_SHIFT); - press(k & ~SHIFT); - sendReport(); - releaseAll(); - sendReport(); - return 1; -} - BootKeyboard_ BootKeyboard; diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index f8238b48c5..80f80e69a1 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -30,7 +30,6 @@ THE SOFTWARE. #include "HID-Settings.h" #include "HIDTables.h" #include "HIDAliases.h" -#include "ASCIIMap.h" typedef union { // Low level key report: up to 6 keys and shift, ctrl etc at once @@ -43,13 +42,12 @@ typedef union { } HID_BootKeyboardReport_Data_t; -class BootKeyboard_ : public Print, PluggableUSBModule { +class BootKeyboard_ : public PluggableUSBModule { public: BootKeyboard_(void); size_t press(uint8_t); void begin(void); void end(void); - size_t write(uint8_t); size_t release(uint8_t); void releaseAll(void); @@ -103,9 +101,6 @@ class BootKeyboard_ : public Print, PluggableUSBModule { uint8_t* featureReport; int featureLength; - - private: - using Print::write; }; extern BootKeyboard_ BootKeyboard; diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index 892f6686c4..a3b33a031e 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -182,25 +182,5 @@ void Keyboard_::releaseAll(void) { memset(&_keyReport.allkeys, 0x00, sizeof(_keyReport.allkeys)); } - - -size_t Keyboard_::write(uint8_t k) { - if(k >= sizeof(_asciimap)) // Ignore invalid input - return 0; - - // Read key from ascii lookup table - k = pgm_read_byte(_asciimap + k); - - if(k & SHIFT) - press(HID_KEYBOARD_LEFT_SHIFT); - press(k & ~SHIFT); - sendReport(); - releaseAll(); - sendReport(); - return 1; -} - - - Keyboard_ Keyboard; diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h index 6c8f261c78..66e49336f8 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h @@ -31,7 +31,6 @@ THE SOFTWARE. #include "HIDTables.h" #include "HIDAliases.h" -#include "ASCIIMap.h" #define KEY_BYTES 28 @@ -46,7 +45,7 @@ typedef union { -class Keyboard_ : public Print { +class Keyboard_ { public: Keyboard_(void); void begin(void); @@ -56,15 +55,11 @@ class Keyboard_ : public Print { size_t release(uint8_t k); void releaseAll(void); int sendReport(void); - size_t write(uint8_t k); boolean isModifierActive(uint8_t k); protected: HID_KeyboardReport_Data_t _keyReport; - - private: - using Print::write; }; extern Keyboard_ Keyboard; From 9f853eb6157e421d00c7bdeb45a834a42378b37e Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Sat, 18 Feb 2017 12:31:24 +0100 Subject: [PATCH 457/602] Fix the examples to not use BootKeyboard.write() Signed-off-by: Gergely Nagy --- .../examples/Keyboard/BootKeyboard/BootKeyboard.ino | 5 ++++- .../examples/Keyboard/KeyboardLed/KeyboardLed.ino | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/plugins/KeyboardioHID/examples/Keyboard/BootKeyboard/BootKeyboard.ino b/plugins/KeyboardioHID/examples/Keyboard/BootKeyboard/BootKeyboard.ino index f7cccb64c6..4c07f7df1d 100644 --- a/plugins/KeyboardioHID/examples/Keyboard/BootKeyboard/BootKeyboard.ino +++ b/plugins/KeyboardioHID/examples/Keyboard/BootKeyboard/BootKeyboard.ino @@ -35,7 +35,10 @@ void loop() { // Trigger caps lock manually via button if (!digitalRead(pinButton)) { - BootKeyboard.write(KEY_ENTER); + BootKeyboard.press(KEY_ENTER); + BootKeyboard.sendReport(); + BootKeyboard.releaseAll(); + BootKeyboard.sendReport(); // Simple debounce delay(300); diff --git a/plugins/KeyboardioHID/examples/Keyboard/KeyboardLed/KeyboardLed.ino b/plugins/KeyboardioHID/examples/Keyboard/KeyboardLed/KeyboardLed.ino index 0bc5301de7..9aa7ed4f50 100644 --- a/plugins/KeyboardioHID/examples/Keyboard/KeyboardLed/KeyboardLed.ino +++ b/plugins/KeyboardioHID/examples/Keyboard/KeyboardLed/KeyboardLed.ino @@ -36,7 +36,10 @@ void loop() { // Trigger caps lock manually via button if (!digitalRead(pinButton)) { - BootKeyboard.write(HID_KEYBOARD_CAPS_LOCK); + BootKeyboard.press(HID_KEYBOARD_CAPS_LOCK); + BootKeyboard.sendReport(); + BootKeyboard.releaseAll(); + BootKeyboard.sendReport(); // Simple debounce delay(300); From d5d03880d9b0ff3f194700ce30a2390c32745582 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Sat, 18 Feb 2017 12:40:59 +0100 Subject: [PATCH 458/602] Fix the NKRO example too Signed-off-by: Gergely Nagy --- plugins/KeyboardioHID/examples/Keyboard/NKRO/NKRO.ino | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/examples/Keyboard/NKRO/NKRO.ino b/plugins/KeyboardioHID/examples/Keyboard/NKRO/NKRO.ino index 903d3a7a68..66c08f6f82 100644 --- a/plugins/KeyboardioHID/examples/Keyboard/NKRO/NKRO.ino +++ b/plugins/KeyboardioHID/examples/Keyboard/NKRO/NKRO.ino @@ -48,7 +48,10 @@ void loop() { // Release all keys and hit enter Keyboard.releaseAll(); - Keyboard.println(); + Keyboard.press(KEY_ENTER); + Keyboard.sendReport(); + Keyboard.releaseAll(); + Keyboard.sendReport(); // Simple debounce delay(300); From cbb91de6399ca000edc5eb460e70996dbe92ccfe Mon Sep 17 00:00:00 2001 From: Wez Furlong Date: Fri, 5 May 2017 21:29:01 -0700 Subject: [PATCH 459/602] improve namespacing for DescriptorPrimitives.h Leading underscores are reserved for system/runtime use. In the nRF52 core, we have a conflict with _VOLATILE. This just sticks `D_` on the front, rather than a bare `_`. --- .../KeyboardioHID/src/DescriptorPrimitives.h | 142 +++++++++--------- .../src/MultiReport/AbsoluteMouse.cpp | 55 ++++--- .../src/MultiReport/ConsumerControl.cpp | 27 ++-- .../KeyboardioHID/src/MultiReport/Gamepad.cpp | 81 +++++----- .../src/MultiReport/Keyboard.cpp | 95 ++++++------ .../KeyboardioHID/src/MultiReport/Mouse.cpp | 46 +++--- .../src/MultiReport/SystemControl.cpp | 38 ++--- 7 files changed, 231 insertions(+), 253 deletions(-) diff --git a/plugins/KeyboardioHID/src/DescriptorPrimitives.h b/plugins/KeyboardioHID/src/DescriptorPrimitives.h index 310d7fa89e..54672f9a42 100644 --- a/plugins/KeyboardioHID/src/DescriptorPrimitives.h +++ b/plugins/KeyboardioHID/src/DescriptorPrimitives.h @@ -1,116 +1,116 @@ #pragma once -#define _MULTIBYTE(n) (n + 0x01) +#define D_MULTIBYTE(n) (n + 0x01) -#define _USAGE_PAGE 0x05 -#define _USAGE 0x09 +#define D_USAGE_PAGE 0x05 +#define D_USAGE 0x09 -#define _REPORT_ID 0x85 +#define D_REPORT_ID 0x85 -#define _USAGE_MINIMUM 0x19 -#define _USAGE_MAXIMUM 0x29 +#define D_USAGE_MINIMUM 0x19 +#define D_USAGE_MAXIMUM 0x29 -#define _LOGICAL_MINIMUM 0x15 -#define _LOGICAL_MAXIMUM 0x25 +#define D_LOGICAL_MINIMUM 0x15 +#define D_LOGICAL_MAXIMUM 0x25 -#define _REPORT_SIZE 0x75 -#define _REPORT_COUNT 0x95 +#define D_REPORT_SIZE 0x75 +#define D_REPORT_COUNT 0x95 // USB HID DCD 1.11 section 6.2.2.4 - Main items // // each of these are the type description + 0x01 for a single byte item -#define _INPUT 0x81 -#define _OUTPUT 0x91 -#define _FEATURE 0xb1 -#define _COLLECTION 0xa1 -#define _END_COLLECTION 0xc0 +#define D_INPUT 0x81 +#define D_OUTPUT 0x91 +#define D_FEATURE 0xb1 +#define D_COLLECTION 0xa1 +#define D_END_COLLECTION 0xc0 // The bits that make up inputs, outputs and features // Bit 0 -#define _DATA 0b00000000 -#define _CONSTANT 0b00000001 +#define D_DATA 0b00000000 +#define D_CONSTANT 0b00000001 // Bit 1 -#define _ARRAY 0b00000000 -#define _VARIABLE 0b00000010 +#define D_ARRAY 0b00000000 +#define D_VARIABLE 0b00000010 // Bit 2 -#define _ABSOLUTE 0b00000000 -#define _RELATIVE 0b00000100 +#define D_ABSOLUTE 0b00000000 +#define D_RELATIVE 0b00000100 // Bit 3 -#define _NO_WRAP 0b00000000 -#define _WRAP 0b00001000 +#define D_NO_WRAP 0b00000000 +#define D_WRAP 0b00001000 // Bit 4 -#define _LINEAR 0b00000000 -#define _NON_LINEAR 0b00010000 +#define D_LINEAR 0b00000000 +#define D_NON_LINEAR 0b00010000 // Bit 5 -#define _PREFERRED_STATE 0b00000000 -#define _NO_PREFERRED 0b00100000 +#define D_PREFERRED_STATE 0b00000000 +#define D_NO_PREFERRED 0b00100000 // Bit 6 -#define _NO_NULL_POSITION 0b00000000 -#define _NULL_STATE 0b01000000 +#define D_NO_NULL_POSITION 0b00000000 +#define D_NULL_STATE 0b01000000 // Bit 7 -#define _NON_VOLATILE 0b00000000 -#define _VOLATILE 0b01000000 +#define D_NON_VOLATILE 0b00000000 +#define D_VOLATILE 0b01000000 // Bit 8 -#define _BIT_FIELD 0b00000000 -#define _BUFFERED_BYTES 0b10000000 +#define D_BIT_FIELD 0b00000000 +#define D_BUFFERED_BYTES 0b10000000 // Collection types -#define _PHYSICAL 0x00 // (group of axes) -#define _APPLICATION 0x01 // (mouse, keyboard) -#define _LOGICAL 0x02// (interrelated data) -#define _REPORT 0x03 -#define _NAMED_ARRAY 0x04 -#define _USAGE_SWITCH 0x05 -#define _USAGE_MODIFIER 0x06 -// 0x07-0x7f - Reserved +#define D_PHYSICAL 0x00 // (group of axes) +#define D_APPLICATION 0x01 // (mouse, keyboard) +#define D_LOGICAL 0x02// (interrelated data) +#define D_REPORT 0x03 +#define D_NAMED_ARRAY 0x04 +#define D_USAGE_SWITCH 0x05 +#define D_USAGE_MODIFIER 0x06 +// 0x07-0x7f - Reserved // 0x80-0xff - Vendor define -#define _PAGE_GENERIC_DESKTOP 0x01 -#define _PAGE_SIMULATION 0x02 -#define _PAGE_VR 0x03 -#define _PAGE_SPORT 0x04 -#define _PAGE_GAME 0x05 -#define _PAGE_GENERIC_DEVICE 0x06 -#define _PAGE_KEYBOARD 0x07 -#define _PAGE_LEDS 0x08 -#define _PAGE_BUTTON 0x09 -#define _PAGE_ORDINAL 0x0A -#define _PAGE_TELEPHONY 0x0B -#define _PAGE_CONSUMER 0x0C -#define _PAGE_DIGITIZER 0x0D -#define _PAGE_RESERVED 0x0E -#define _PAGE_PID 0x0F -#define _PAGE_UNICODE 0x10 +#define D_PAGE_GENERIC_DESKTOP 0x01 +#define D_PAGE_SIMULATION 0x02 +#define D_PAGE_VR 0x03 +#define D_PAGE_SPORT 0x04 +#define D_PAGE_GAME 0x05 +#define D_PAGE_GENERIC_DEVICE 0x06 +#define D_PAGE_KEYBOARD 0x07 +#define D_PAGE_LEDS 0x08 +#define D_PAGE_BUTTON 0x09 +#define D_PAGE_ORDINAL 0x0A +#define D_PAGE_TELEPHONY 0x0B +#define D_PAGE_CONSUMER 0x0C +#define D_PAGE_DIGITIZER 0x0D +#define D_PAGE_RESERVED 0x0E +#define D_PAGE_PID 0x0F +#define D_PAGE_UNICODE 0x10 // 0x11-13 RESERVED -#define _PAGE_ALPHANUMERIC_DISPLAY 0x14 -#define _PAGE_MEDICAL_INSTRUMENTS 0x40 +#define D_PAGE_ALPHANUMERIC_DISPLAY 0x14 +#define D_PAGE_MEDICAL_INSTRUMENTS 0x40 // 0x80-83 MONITOR // 0x84-87 POWER -#define _PAGE_BAR_CODE_SCANNER 0x8C -#define _PAGE_SCALE 0x8D -#define _PAGE_MSR 0x8E +#define D_PAGE_BAR_CODE_SCANNER 0x8C +#define D_PAGE_SCALE 0x8D +#define D_PAGE_MSR 0x8E // 0x8F RESERVED POINT OF SALE -#define _PAGE_CAMERA_CONTROL 0x90 -#define _PAGE_ARCADE 0x91 +#define D_PAGE_CAMERA_CONTROL 0x90 +#define D_PAGE_ARCADE 0x91 // Generic Desktop Usages HUT Section 4 p27 -#define _USAGE_POINTER 0x01 -#define _USAGE_MOUSE 0x02 +#define D_USAGE_POINTER 0x01 +#define D_USAGE_MOUSE 0x02 // 0x03 is reserved -#define _USAGE_JOYSTICK 0x04 -#define _USAGE_GAMEPAD 0x05 -#define _USAGE_KEYBOARD 0x06 -#define _USAGE_KEYPAD 0x07 -#define _USAGE_MULITAXIS 0x08 \ No newline at end of file +#define D_USAGE_JOYSTICK 0x04 +#define D_USAGE_GAMEPAD 0x05 +#define D_USAGE_KEYBOARD 0x06 +#define D_USAGE_KEYPAD 0x07 +#define D_USAGE_MULITAXIS 0x08 diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp index e017095eee..e5a31256a8 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp @@ -26,41 +26,41 @@ THE SOFTWARE. static const uint8_t _hidMultiReportDescriptorAbsoluteMouse[] PROGMEM = { /* Mouse absolute */ - _USAGE_PAGE, _PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) 54 */ - _USAGE, _USAGE_MOUSE, /* USAGE (Mouse) */ - _COLLECTION, _APPLICATION, /* COLLECTION (Application) */ - _REPORT_ID, HID_REPORTID_MOUSE_ABSOLUTE, /* REPORT_ID */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) 54 */ + D_USAGE, D_USAGE_MOUSE, /* USAGE (Mouse) */ + D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ + D_REPORT_ID, HID_REPORTID_MOUSE_ABSOLUTE, /* REPORT_ID */ /* 8 Buttons */ - _USAGE_PAGE, _PAGE_BUTTON, /* USAGE_PAGE (Button) */ - _USAGE_MINIMUM, 0x01, /* USAGE_MINIMUM (Button 1) */ - _USAGE_MAXIMUM, 0x08, /* USAGE_MAXIMUM (Button 8) */ - _LOGICAL_MINIMUM, 0x00, /* LOGICAL_MINIMUM (0) */ - _LOGICAL_MAXIMUM, 0x01, /* LOGICAL_MAXIMUM (1) */ - _REPORT_COUNT, 0x08, /* REPORT_COUNT (8) */ - _REPORT_SIZE, 0x01, /* REPORT_SIZE (1) */ - _INPUT, (_DATA|_VARIABLE|_ABSOLUTE), + D_USAGE_PAGE, D_PAGE_BUTTON, /* USAGE_PAGE (Button) */ + D_USAGE_MINIMUM, 0x01, /* USAGE_MINIMUM (Button 1) */ + D_USAGE_MAXIMUM, 0x08, /* USAGE_MAXIMUM (Button 8) */ + D_LOGICAL_MINIMUM, 0x00, /* LOGICAL_MINIMUM (0) */ + D_LOGICAL_MAXIMUM, 0x01, /* LOGICAL_MAXIMUM (1) */ + D_REPORT_COUNT, 0x08, /* REPORT_COUNT (8) */ + D_REPORT_SIZE, 0x01, /* REPORT_SIZE (1) */ + D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), /* X, Y */ - _USAGE_PAGE, _PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ - _USAGE, 0x30, /* USAGE (X) */ - _USAGE, 0x31, /* USAGE (Y) */ - _MULTIBYTE(_LOGICAL_MINIMUM), 0x00, 0x00, /* Logical Minimum (0) */ - _MULTIBYTE(_LOGICAL_MAXIMUM), 0xFF, 0x7f, /* Logical Maximum (32767) */ - _REPORT_SIZE, 0x10, /* Report Size (16), */ - _REPORT_COUNT, 0x02, /* Report Count (2), */ - _INPUT, (_DATA|_VARIABLE|_ABSOLUTE), /* Input (Data, Variable, Absolute) */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ + D_USAGE, 0x30, /* USAGE (X) */ + D_USAGE, 0x31, /* USAGE (Y) */ + D_MULTIBYTE(D_LOGICAL_MINIMUM), 0x00, 0x00, /* Logical Minimum (0) */ + D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xFF, 0x7f, /* Logical Maximum (32767) */ + D_REPORT_SIZE, 0x10, /* Report Size (16), */ + D_REPORT_COUNT, 0x02, /* Report Count (2), */ + D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), /* Input (Data, Variable, Absolute) */ /* Wheel */ - _USAGE, 0x38, /* USAGE (Wheel) */ - _LOGICAL_MINIMUM, 0x81, /* LOGICAL_MINIMUM (-127) */ - _LOGICAL_MAXIMUM, 0x7f, /* LOGICAL_MAXIMUM (127) */ - _REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ - _REPORT_COUNT, 0x01, /* REPORT_COUNT (1) */ - _INPUT, (_DATA|_VARIABLE|_RELATIVE), + D_USAGE, 0x38, /* USAGE (Wheel) */ + D_LOGICAL_MINIMUM, 0x81, /* LOGICAL_MINIMUM (-127) */ + D_LOGICAL_MAXIMUM, 0x7f, /* LOGICAL_MAXIMUM (127) */ + D_REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ + D_REPORT_COUNT, 0x01, /* REPORT_COUNT (1) */ + D_INPUT, (D_DATA|D_VARIABLE|D_RELATIVE), /* End */ - _END_COLLECTION + D_END_COLLECTION }; AbsoluteMouse_::AbsoluteMouse_(void) { @@ -150,4 +150,3 @@ bool AbsoluteMouse_::isPressed(uint8_t b) { AbsoluteMouse_ AbsoluteMouse; - diff --git a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp index f1b478864c..3b75992388 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp @@ -26,19 +26,19 @@ THE SOFTWARE. static const uint8_t _hidMultiReportDescriptorConsumer[] PROGMEM = { /* Consumer Control (Sound/Media keys) */ - _USAGE_PAGE, 0x0C, /* usage page (consumer device) */ - _USAGE, 0x01, /* usage -- consumer control */ - _COLLECTION, _APPLICATION, /* collection (application) */ - _REPORT_ID, HID_REPORTID_CONSUMERCONTROL, /* report id */ + D_USAGE_PAGE, 0x0C, /* usage page (consumer device) */ + D_USAGE, 0x01, /* usage -- consumer control */ + D_COLLECTION, D_APPLICATION, /* collection (application) */ + D_REPORT_ID, HID_REPORTID_CONSUMERCONTROL, /* report id */ /* 4 Media Keys */ - _LOGICAL_MINIMUM, 0x00, /* logical minimum */ - _MULTIBYTE(_LOGICAL_MAXIMUM), 0xFF, 0x03, /* logical maximum (3ff) */ - _USAGE_MINIMUM, 0x00, /* usage minimum (0) */ - _MULTIBYTE(_USAGE_MAXIMUM), 0xFF, 0x03, /* usage maximum (3ff) */ - _REPORT_COUNT, 0x04, /* report count (4) */ - _REPORT_SIZE, 0x10, /* report size (16) */ - _INPUT, 0x00, /* input */ - _END_COLLECTION /* end collection */ + D_LOGICAL_MINIMUM, 0x00, /* logical minimum */ + D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xFF, 0x03, /* logical maximum (3ff) */ + D_USAGE_MINIMUM, 0x00, /* usage minimum (0) */ + D_MULTIBYTE(D_USAGE_MAXIMUM), 0xFF, 0x03, /* usage maximum (3ff) */ + D_REPORT_COUNT, 0x04, /* report count (4) */ + D_REPORT_SIZE, 0x10, /* report size (16) */ + D_INPUT, 0x00, /* input */ + D_END_COLLECTION /* end collection */ }; ConsumerControl_::ConsumerControl_(void) { @@ -92,6 +92,3 @@ void ConsumerControl_::SendReport(void* data, int length) { } ConsumerControl_ ConsumerControl; - - - diff --git a/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp b/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp index 3575459268..2f9d5a2c50 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp @@ -26,51 +26,51 @@ THE SOFTWARE. static const uint8_t _hidMultiReportDescriptorGamepad[] PROGMEM = { /* Gamepad with 32 buttons and 6 axis*/ - _USAGE_PAGE, _PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ - _USAGE, _USAGE_JOYSTICK, /* USAGE (Joystick) */ - _COLLECTION, _APPLICATION, /* COLLECTION (Application) */ - _REPORT_ID, HID_REPORTID_GAMEPAD, /* REPORT_ID */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ + D_USAGE, D_USAGE_JOYSTICK, /* USAGE (Joystick) */ + D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ + D_REPORT_ID, HID_REPORTID_GAMEPAD, /* REPORT_ID */ /* 32 Buttons */ - _USAGE_PAGE, _PAGE_BUTTON, /* USAGE_PAGE (Button) */ - _USAGE_MINIMUM, 0x01, /* USAGE_MINIMUM (Button 1) */ - _USAGE_MAXIMUM, 0x20, /* USAGE_MAXIMUM (Button 32) */ - _LOGICAL_MINIMUM, 0x00, /* _LOGICAL_MINIMUM (0) */ - _LOGICAL_MAXIMUM, 0x01, /* _LOGICAL_MAXIMUM (1) */ - _REPORT_SIZE, 0x01, /* REPORT_SIZE (1) */ - _REPORT_COUNT, 0x20, /* REPORT_COUNT (32) */ - _INPUT, (_DATA|_VARIABLE|_ABSOLUTE), /* INPUT (Data,Var,Abs) */ + D_USAGE_PAGE, D_PAGE_BUTTON, /* USAGE_PAGE (Button) */ + D_USAGE_MINIMUM, 0x01, /* USAGE_MINIMUM (Button 1) */ + D_USAGE_MAXIMUM, 0x20, /* USAGE_MAXIMUM (Button 32) */ + D_LOGICAL_MINIMUM, 0x00, /* _LOGICAL_MINIMUM (0) */ + D_LOGICAL_MAXIMUM, 0x01, /* _LOGICAL_MAXIMUM (1) */ + D_REPORT_SIZE, 0x01, /* REPORT_SIZE (1) */ + D_REPORT_COUNT, 0x20, /* REPORT_COUNT (32) */ + D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ /* 4 16bit Axis */ - _USAGE_PAGE, _PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ - _COLLECTION, _PHYSICAL, /* COLLECTION (Physical) */ - _USAGE, 0x30, /* USAGE (X) */ - _USAGE, 0x31, /* USAGE (Y) */ - _USAGE, 0x33, /* USAGE (Rx) */ - _USAGE, 0x34, /* USAGE (Ry) */ - _MULTIBYTE(_LOGICAL_MINIMUM), 0x00, 0x80, /* _LOGICAL_MINIMUM (-32768) */ - _MULTIBYTE(_LOGICAL_MAXIMUM), 0xFF, 0x7F, /* _LOGICAL_MAXIMUM (32767) */ - _REPORT_SIZE, 0x10, /* REPORT_SIZE (16) */ - _REPORT_COUNT, 0x04, /* REPORT_COUNT (4) */ - _INPUT, (_DATA|_VARIABLE|_ABSOLUTE), /* INPUT (Data,Var,Abs) */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ + D_COLLECTION, D_PHYSICAL, /* COLLECTION (Physical) */ + D_USAGE, 0x30, /* USAGE (X) */ + D_USAGE, 0x31, /* USAGE (Y) */ + D_USAGE, 0x33, /* USAGE (Rx) */ + D_USAGE, 0x34, /* USAGE (Ry) */ + D_MULTIBYTE(D_LOGICAL_MINIMUM), 0x00, 0x80, /* _LOGICAL_MINIMUM (-32768) */ + D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xFF, 0x7F, /* _LOGICAL_MAXIMUM (32767) */ + D_REPORT_SIZE, 0x10, /* REPORT_SIZE (16) */ + D_REPORT_COUNT, 0x04, /* REPORT_COUNT (4) */ + D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ /* 2 8bit Axis */ - _USAGE, 0x32, /* USAGE (Z) */ - _USAGE, 0x35, /* USAGE (Rz) */ - _LOGICAL_MINIMUM, 0x80, /* _LOGICAL_MINIMUM (-128) */ - _LOGICAL_MAXIMUM, 0x7F, /* _LOGICAL_MAXIMUM (127) */ - _REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ - _REPORT_COUNT, 0x02, /* REPORT_COUNT (2) */ - _INPUT, (_DATA|_VARIABLE|_ABSOLUTE), /* INPUT (Data,Var,Abs) */ - _END_COLLECTION, /* END_COLLECTION */ + D_USAGE, 0x32, /* USAGE (Z) */ + D_USAGE, 0x35, /* USAGE (Rz) */ + D_LOGICAL_MINIMUM, 0x80, /* _LOGICAL_MINIMUM (-128) */ + D_LOGICAL_MAXIMUM, 0x7F, /* _LOGICAL_MAXIMUM (127) */ + D_REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ + D_REPORT_COUNT, 0x02, /* REPORT_COUNT (2) */ + D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ + D_END_COLLECTION, /* END_COLLECTION */ /* 2 Hat Switches */ - _USAGE_PAGE, _PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ - _USAGE, 0x39, /* USAGE (Hat switch) */ - _USAGE, 0x39, /* USAGE (Hat switch) */ - _LOGICAL_MINIMUM, 0x01, /* _LOGICAL_MINIMUM (1) */ - _LOGICAL_MAXIMUM, 0x08, /* _LOGICAL_MAXIMUM (8) */ - _REPORT_COUNT, 0x02, /* REPORT_COUNT (2) */ - _REPORT_SIZE, 0x04, /* REPORT_SIZE (4) */ - _INPUT, (_DATA|_VARIABLE|_ABSOLUTE), /* INPUT (Data,Var,Abs) */ - _END_COLLECTION /* END_COLLECTION */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ + D_USAGE, 0x39, /* USAGE (Hat switch) */ + D_USAGE, 0x39, /* USAGE (Hat switch) */ + D_LOGICAL_MINIMUM, 0x01, /* _LOGICAL_MINIMUM (1) */ + D_LOGICAL_MAXIMUM, 0x08, /* _LOGICAL_MAXIMUM (8) */ + D_REPORT_COUNT, 0x02, /* REPORT_COUNT (2) */ + D_REPORT_SIZE, 0x04, /* REPORT_SIZE (4) */ + D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ + D_END_COLLECTION /* END_COLLECTION */ }; Gamepad_::Gamepad_(void) { @@ -158,4 +158,3 @@ void Gamepad_::SendReport(void* data, int length) { } Gamepad_ Gamepad; - diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index a3b33a031e..25d21e1084 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -26,21 +26,21 @@ THE SOFTWARE. static const uint8_t _hidMultiReportDescriptorKeyboard[] PROGMEM = { // NKRO Keyboard - _USAGE_PAGE, _PAGE_GENERIC_DESKTOP, - _USAGE, _USAGE_KEYBOARD, - _COLLECTION, _APPLICATION, - _REPORT_ID, HID_REPORTID_NKRO_KEYBOARD, - _USAGE_PAGE, _PAGE_KEYBOARD, + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, + D_USAGE, D_USAGE_KEYBOARD, + D_COLLECTION, D_APPLICATION, + D_REPORT_ID, HID_REPORTID_NKRO_KEYBOARD, + D_USAGE_PAGE, D_PAGE_KEYBOARD, /* Key modifier byte */ - _USAGE_MINIMUM, HID_KEYBOARD_FIRST_MODIFIER, - _USAGE_MAXIMUM, HID_KEYBOARD_LAST_MODIFIER, - _LOGICAL_MINIMUM, 0x00, - _LOGICAL_MAXIMUM, 0x01, - _REPORT_SIZE, 0x01, - _REPORT_COUNT, 0x08, - _INPUT, (_DATA|_VARIABLE|_ABSOLUTE), + D_USAGE_MINIMUM, HID_KEYBOARD_FIRST_MODIFIER, + D_USAGE_MAXIMUM, HID_KEYBOARD_LAST_MODIFIER, + D_LOGICAL_MINIMUM, 0x00, + D_LOGICAL_MAXIMUM, 0x01, + D_REPORT_SIZE, 0x01, + D_REPORT_COUNT, 0x08, + D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), // USB Code not within 4-49 (0x4-0x31), 51-155 (0x33-0x9B), 157-164 (0x9D-0xA4), // 176-221 (0xB0-0xDD) or 224-231 (0xE0-0xE7) NKRO Mode @@ -49,58 +49,58 @@ static const uint8_t _hidMultiReportDescriptorKeyboard[] PROGMEM = { // Padding 3 bits // To skip HID_KEYBOARD_NON_US_POUND_AND_TILDE, which causes // Linux to choke on our driver. - _REPORT_SIZE, 0x04, - _REPORT_COUNT, 0x01, - _INPUT, (_CONSTANT), + D_REPORT_SIZE, 0x04, + D_REPORT_COUNT, 0x01, + D_INPUT, (D_CONSTANT), - _USAGE_MINIMUM, HID_KEYBOARD_A_AND_A, - _USAGE_MAXIMUM, HID_KEYBOARD_BACKSLASH_AND_PIPE, - _LOGICAL_MINIMUM, 0x00, - _LOGICAL_MAXIMUM, 0x01, - _REPORT_SIZE, 0x01, - _REPORT_COUNT, (HID_KEYBOARD_BACKSLASH_AND_PIPE - HID_KEYBOARD_A_AND_A)+1, - _INPUT, (_DATA|_VARIABLE|_ABSOLUTE), + D_USAGE_MINIMUM, HID_KEYBOARD_A_AND_A, + D_USAGE_MAXIMUM, HID_KEYBOARD_BACKSLASH_AND_PIPE, + D_LOGICAL_MINIMUM, 0x00, + D_LOGICAL_MAXIMUM, 0x01, + D_REPORT_SIZE, 0x01, + D_REPORT_COUNT, (HID_KEYBOARD_BACKSLASH_AND_PIPE - HID_KEYBOARD_A_AND_A)+1, + D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), // Padding 1 bit. // To skip HID_KEYBOARD_NON_US_POUND_AND_TILDE, which causes // Linux to choke on our driver. - _REPORT_SIZE, 0x01, - _REPORT_COUNT, 0x01, - _INPUT, (_CONSTANT), + D_REPORT_SIZE, 0x01, + D_REPORT_COUNT, 0x01, + D_INPUT, (D_CONSTANT), - _USAGE_MINIMUM, HID_KEYBOARD_SEMICOLON_AND_COLON, - _USAGE_MAXIMUM, HID_KEYBOARD_CANCEL, - _LOGICAL_MINIMUM, 0x00, - _LOGICAL_MAXIMUM, 0x01, - _REPORT_SIZE, 0x01, - _REPORT_COUNT, (HID_KEYBOARD_CANCEL-HID_KEYBOARD_SEMICOLON_AND_COLON) +1, - _INPUT, (_DATA|_VARIABLE|_ABSOLUTE), + D_USAGE_MINIMUM, HID_KEYBOARD_SEMICOLON_AND_COLON, + D_USAGE_MAXIMUM, HID_KEYBOARD_CANCEL, + D_LOGICAL_MINIMUM, 0x00, + D_LOGICAL_MAXIMUM, 0x01, + D_REPORT_SIZE, 0x01, + D_REPORT_COUNT, (HID_KEYBOARD_CANCEL-HID_KEYBOARD_SEMICOLON_AND_COLON) +1, + D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), // Padding 1 bit. // To skip HID_KEYBOARD_CLEAR, which causes // Linux to choke on our driver. - _REPORT_SIZE, 0x01, - _REPORT_COUNT, 0x01, - _INPUT, (_CONSTANT), + D_REPORT_SIZE, 0x01, + D_REPORT_COUNT, 0x01, + D_INPUT, (D_CONSTANT), - _USAGE_MINIMUM, HID_KEYBOARD_PRIOR, - _USAGE_MAXIMUM, HID_KEYPAD_HEXADECIMAL, - _LOGICAL_MINIMUM, 0x00, - _LOGICAL_MAXIMUM, 0x01, - _REPORT_SIZE, 0x01, - _REPORT_COUNT, (HID_KEYPAD_HEXADECIMAL - HID_KEYBOARD_PRIOR ) +1 , - _INPUT, (_DATA|_VARIABLE|_ABSOLUTE), + D_USAGE_MINIMUM, HID_KEYBOARD_PRIOR, + D_USAGE_MAXIMUM, HID_KEYPAD_HEXADECIMAL, + D_LOGICAL_MINIMUM, 0x00, + D_LOGICAL_MAXIMUM, 0x01, + D_REPORT_SIZE, 0x01, + D_REPORT_COUNT, (HID_KEYPAD_HEXADECIMAL - HID_KEYBOARD_PRIOR ) +1 , + D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), // Padding (w bits) - _REPORT_SIZE, 0x02, - _REPORT_COUNT, 0x01, - _INPUT, (_CONSTANT), + D_REPORT_SIZE, 0x02, + D_REPORT_COUNT, 0x01, + D_INPUT, (D_CONSTANT), - _END_COLLECTION, + D_END_COLLECTION, }; @@ -138,7 +138,7 @@ boolean Keyboard_::isModifierActive(uint8_t k) { } size_t Keyboard_::press(uint8_t k) { - // If the key is in the range of 'printable' keys + // If the key is in the range of 'printable' keys if (k <= HID_KEYPAD_HEXADECIMAL ) { uint8_t bit = 1 << (uint8_t(k) % 8); _keyReport.keys[k / 8] |= bit; @@ -183,4 +183,3 @@ void Keyboard_::releaseAll(void) { } Keyboard_ Keyboard; - diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp index 396c0bc307..4a345742d3 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp @@ -26,34 +26,34 @@ THE SOFTWARE. static const uint8_t _hidMultiReportDescriptorMouse[] PROGMEM = { /* Mouse relative */ - _USAGE_PAGE, _PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) 54 */ - _USAGE, _USAGE_MOUSE, /* USAGE (Mouse) */ - _COLLECTION, _APPLICATION, /* COLLECTION (Application) */ - _REPORT_ID, HID_REPORTID_MOUSE, /* REPORT_ID */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) 54 */ + D_USAGE, D_USAGE_MOUSE, /* USAGE (Mouse) */ + D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ + D_REPORT_ID, HID_REPORTID_MOUSE, /* REPORT_ID */ /* 8 Buttons */ - _USAGE_PAGE, _PAGE_BUTTON, /* USAGE_PAGE (Button) */ - _USAGE_MINIMUM, 0x01, /* USAGE_MINIMUM (Button 1) */ - _USAGE_MAXIMUM, 0x08, /* USAGE_MAXIMUM (Button 8) */ - _LOGICAL_MINIMUM, 0x00, /* LOGICAL_MINIMUM (0) */ - _LOGICAL_MAXIMUM, 0x01, /* LOGICAL_MAXIMUM (1) */ - _REPORT_COUNT, 0x08, /* REPORT_COUNT (8) */ - _REPORT_SIZE, 0x01, /* REPORT_SIZE (1) */ - _INPUT, (_DATA|_VARIABLE|_ABSOLUTE), /* INPUT (Data,Var,Abs) */ + D_USAGE_PAGE, D_PAGE_BUTTON, /* USAGE_PAGE (Button) */ + D_USAGE_MINIMUM, 0x01, /* USAGE_MINIMUM (Button 1) */ + D_USAGE_MAXIMUM, 0x08, /* USAGE_MAXIMUM (Button 8) */ + D_LOGICAL_MINIMUM, 0x00, /* LOGICAL_MINIMUM (0) */ + D_LOGICAL_MAXIMUM, 0x01, /* LOGICAL_MAXIMUM (1) */ + D_REPORT_COUNT, 0x08, /* REPORT_COUNT (8) */ + D_REPORT_SIZE, 0x01, /* REPORT_SIZE (1) */ + D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ /* X, Y, Wheel */ - _USAGE_PAGE, _PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ - _USAGE, 0x30, /* USAGE (X) */ - _USAGE, 0x31, /* USAGE (Y) */ - _USAGE, 0x38, /* USAGE (Wheel) */ - _LOGICAL_MINIMUM, 0x81, /* LOGICAL_MINIMUM (-127) */ - _LOGICAL_MAXIMUM, 0x7f, /* LOGICAL_MAXIMUM (127) */ - _REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ - _REPORT_COUNT, 0x03, /* REPORT_COUNT (3) */ - _INPUT, (_DATA|_VARIABLE|_RELATIVE), /* INPUT (Data,Var,Rel) */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ + D_USAGE, 0x30, /* USAGE (X) */ + D_USAGE, 0x31, /* USAGE (Y) */ + D_USAGE, 0x38, /* USAGE (Wheel) */ + D_LOGICAL_MINIMUM, 0x81, /* LOGICAL_MINIMUM (-127) */ + D_LOGICAL_MAXIMUM, 0x7f, /* LOGICAL_MAXIMUM (127) */ + D_REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ + D_REPORT_COUNT, 0x03, /* REPORT_COUNT (3) */ + D_INPUT, (D_DATA|D_VARIABLE|D_RELATIVE), /* INPUT (Data,Var,Rel) */ /* End */ - _END_COLLECTION /* END_COLLECTION */ + D_END_COLLECTION /* END_COLLECTION */ }; @@ -114,5 +114,3 @@ void Mouse_::SendReport(void* data, int length) { } Mouse_ Mouse; - - diff --git a/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp b/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp index 7d45e6cc96..5f6cf12357 100644 --- a/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp @@ -27,19 +27,19 @@ THE SOFTWARE. static const uint8_t _hidMultiReportDescriptorSystem[] PROGMEM = { //TODO limit to system keys only? /* System Control (Power Down, Sleep, Wakeup, ...) */ - _USAGE_PAGE, _PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ - _USAGE, 0x80, /* USAGE (System Control) */ - _COLLECTION, _APPLICATION, /* COLLECTION (Application) */ - _REPORT_ID, HID_REPORTID_SYSTEMCONTROL, /* REPORT_ID */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ + D_USAGE, 0x80, /* USAGE (System Control) */ + D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ + D_REPORT_ID, HID_REPORTID_SYSTEMCONTROL, /* REPORT_ID */ /* 1 system key */ - _LOGICAL_MINIMUM, 0x00, /* LOGICAL_MINIMUM (0) */ - _MULTIBYTE(_LOGICAL_MAXIMUM), 0xff, 0x00, /* LOGICAL_MAXIMUM (255) */ - _USAGE_MINIMUM, 0x00, /* USAGE_MINIMUM (Undefined) */ - _USAGE_MAXIMUM, 0xff, /* USAGE_MAXIMUM (System Menu Down) */ - _REPORT_COUNT, 0x01, /* REPORT_COUNT (1) */ - _REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ - _INPUT, (_DATA|_ARRAY|_ABSOLUTE), /* INPUT (Data,Ary,Abs) */ - _END_COLLECTION /* END_COLLECTION */ + D_LOGICAL_MINIMUM, 0x00, /* LOGICAL_MINIMUM (0) */ + D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xff, 0x00, /* LOGICAL_MAXIMUM (255) */ + D_USAGE_MINIMUM, 0x00, /* USAGE_MINIMUM (Undefined) */ + D_USAGE_MAXIMUM, 0xff, /* USAGE_MAXIMUM (System Menu Down) */ + D_REPORT_COUNT, 0x01, /* REPORT_COUNT (1) */ + D_REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ + D_INPUT, (D_DATA|D_ARRAY|D_ABSOLUTE), /* INPUT (Data,Ary,Abs) */ + D_END_COLLECTION /* END_COLLECTION */ }; SystemControl_::SystemControl_(void) { @@ -83,17 +83,3 @@ void SystemControl_::SendReport(void* data, int length) { } SystemControl_ SystemControl; - - - - - - - - - - - - - - From c9619b0214b06f62860593bf5f2337424d25f703 Mon Sep 17 00:00:00 2001 From: Wez Furlong Date: Fri, 5 May 2017 21:35:52 -0700 Subject: [PATCH 460/602] apply astyle --- plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp | 12 ++++++------ plugins/KeyboardioHID/src/MultiReport/Keyboard.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index 25d21e1084..f091d97eb1 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -91,7 +91,7 @@ static const uint8_t _hidMultiReportDescriptorKeyboard[] PROGMEM = { D_LOGICAL_MINIMUM, 0x00, D_LOGICAL_MAXIMUM, 0x01, D_REPORT_SIZE, 0x01, - D_REPORT_COUNT, (HID_KEYPAD_HEXADECIMAL - HID_KEYBOARD_PRIOR ) +1 , + D_REPORT_COUNT, (HID_KEYPAD_HEXADECIMAL - HID_KEYBOARD_PRIOR ) +1, D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), @@ -130,11 +130,11 @@ int Keyboard_::sendReport(void) { } boolean Keyboard_::isModifierActive(uint8_t k) { - if(k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { - k = k - HID_KEYBOARD_FIRST_MODIFIER; - return !!(_keyReport.modifiers & (1 << k)); - } - return false; + if(k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { + k = k - HID_KEYBOARD_FIRST_MODIFIER; + return !!(_keyReport.modifiers & (1 << k)); + } + return false; } size_t Keyboard_::press(uint8_t k) { diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h index 66e49336f8..7d4091344c 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h @@ -35,7 +35,7 @@ THE SOFTWARE. #define KEY_BYTES 28 typedef union { - // Modifiers + keymap + // Modifiers + keymap struct { uint8_t modifiers; uint8_t keys[KEY_BYTES ]; From 5117d805b0c646fa99f92c3830797166884b3599 Mon Sep 17 00:00:00 2001 From: Wez Furlong Date: Fri, 5 May 2017 21:39:38 -0700 Subject: [PATCH 461/602] move mouse button defs to their own header file These defines were duplicated; let's have just one copy. These symbols also collide with the teensy headers, which is why they're on my radar. Will figure out what to do about that later. --- .../KeyboardioHID/src/MultiReport/AbsoluteMouse.h | 13 +------------ plugins/KeyboardioHID/src/MultiReport/Mouse.h | 10 +--------- .../KeyboardioHID/src/MultiReport/MouseButtons.h | 10 ++++++++++ 3 files changed, 12 insertions(+), 21 deletions(-) create mode 100644 plugins/KeyboardioHID/src/MultiReport/MouseButtons.h diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h index 06523c4040..6dbbc97f6d 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h @@ -28,17 +28,7 @@ THE SOFTWARE. #include "PluggableUSB.h" #include "HID.h" #include "HID-Settings.h" - -#define MOUSE_LEFT (1 << 0) -#define MOUSE_RIGHT (1 << 1) -#define MOUSE_MIDDLE (1 << 2) -#define MOUSE_PREV (1 << 3) -#define MOUSE_NEXT (1 << 4) -// actually this mouse report has 8 buttons (for smaller descriptor) -// but the last 3 wont do anything from what I tested -#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE | MOUSE_PREV | MOUSE_NEXT) - - +#include "MouseButtons.h" typedef union { // Absolute mouse report: 8 buttons, 2 absolute axis, wheel @@ -80,4 +70,3 @@ class AbsoluteMouse_ { extern AbsoluteMouse_ AbsoluteMouse; - diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.h b/plugins/KeyboardioHID/src/MultiReport/Mouse.h index 7797fb6ba6..887bd9eb54 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.h @@ -28,15 +28,7 @@ THE SOFTWARE. #include "PluggableUSB.h" #include "HID.h" #include "HID-Settings.h" - -#define MOUSE_LEFT (1 << 0) -#define MOUSE_RIGHT (1 << 1) -#define MOUSE_MIDDLE (1 << 2) -#define MOUSE_PREV (1 << 3) -#define MOUSE_NEXT (1 << 4) -// actually this mouse report has 8 buttons (for smaller descriptor) -// but the last 3 wont do anything from what I tested -#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE | MOUSE_PREV | MOUSE_NEXT) +#include "MouseButtons.h" typedef union { // Mouse report: 8 buttons, position, wheel diff --git a/plugins/KeyboardioHID/src/MultiReport/MouseButtons.h b/plugins/KeyboardioHID/src/MultiReport/MouseButtons.h new file mode 100644 index 0000000000..7cefd19620 --- /dev/null +++ b/plugins/KeyboardioHID/src/MultiReport/MouseButtons.h @@ -0,0 +1,10 @@ +#pragma once + +#define MOUSE_LEFT (1 << 0) +#define MOUSE_RIGHT (1 << 1) +#define MOUSE_MIDDLE (1 << 2) +#define MOUSE_PREV (1 << 3) +#define MOUSE_NEXT (1 << 4) +// actually this mouse report has 8 buttons (for smaller descriptor) +// but the last 3 wont do anything from what I tested +#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE | MOUSE_PREV | MOUSE_NEXT) From b7e91db2a965b883a4773740cc27c36ba9779f02 Mon Sep 17 00:00:00 2001 From: Wez Furlong Date: Sun, 7 May 2017 19:27:20 -0700 Subject: [PATCH 462/602] Remove legacy HIDAliases --- .../Keyboard/BootKeyboard/BootKeyboard.ino | 2 +- .../examples/Keyboard/NKRO/NKRO.ino | 24 +-- plugins/KeyboardioHID/keywords.txt | 2 +- plugins/KeyboardioHID/src/HIDAliases.h | 152 ------------------ 4 files changed, 14 insertions(+), 166 deletions(-) diff --git a/plugins/KeyboardioHID/examples/Keyboard/BootKeyboard/BootKeyboard.ino b/plugins/KeyboardioHID/examples/Keyboard/BootKeyboard/BootKeyboard.ino index 4c07f7df1d..698805aa3d 100644 --- a/plugins/KeyboardioHID/examples/Keyboard/BootKeyboard/BootKeyboard.ino +++ b/plugins/KeyboardioHID/examples/Keyboard/BootKeyboard/BootKeyboard.ino @@ -35,7 +35,7 @@ void loop() { // Trigger caps lock manually via button if (!digitalRead(pinButton)) { - BootKeyboard.press(KEY_ENTER); + BootKeyboard.press(HID_KEYBOARD_ENTER); BootKeyboard.sendReport(); BootKeyboard.releaseAll(); BootKeyboard.sendReport(); diff --git a/plugins/KeyboardioHID/examples/Keyboard/NKRO/NKRO.ino b/plugins/KeyboardioHID/examples/Keyboard/NKRO/NKRO.ino index 66c08f6f82..5179d3fb42 100644 --- a/plugins/KeyboardioHID/examples/Keyboard/NKRO/NKRO.ino +++ b/plugins/KeyboardioHID/examples/Keyboard/NKRO/NKRO.ino @@ -31,24 +31,24 @@ void loop() { if (!digitalRead(pinButton)) { digitalWrite(pinLed, HIGH); - // Do not press to many at once or some OS will have problems. + // Do not press too many at once or some OS will have problems. // Note that the resulting pressed order might differ, // because all keys are pressed at the same time. - Keyboard.press(KEY_0); - Keyboard.press(KEY_1); - Keyboard.press(KEY_2); - Keyboard.press(KEY_3); - Keyboard.press(KEY_4); - Keyboard.press(KEY_5); - Keyboard.press(KEY_6); - Keyboard.press(KEY_7); - Keyboard.press(KEY_8); - Keyboard.press(KEY_9); + Keyboard.press(HID_KEYBOARD_0_AND_RIGHT_PAREN); + Keyboard.press(HID_KEYBOARD_1_AND_EXCLAMATION_POINT); + Keyboard.press(HID_KEYBOARD_2_AND_AT); + Keyboard.press(HID_KEYBOARD_3_AND_POUND); + Keyboard.press(HID_KEYBOARD_4_AND_DOLLAR); + Keyboard.press(HID_KEYBOARD_5_AND_PERCENT); + Keyboard.press(HID_KEYBOARD_6_AND_CARAT); + Keyboard.press(HID_KEYBOARD_7_AND_AMPERSAND); + Keyboard.press(HID_KEYBOARD_8_AND_ASTERISK); + Keyboard.press(HID_KEYBOARD_9_AND_LEFT_PAREN); Keyboard.sendReport(); // Release all keys and hit enter Keyboard.releaseAll(); - Keyboard.press(KEY_ENTER); + Keyboard.press(HID_KEYBOARD_ENTER); Keyboard.sendReport(); Keyboard.releaseAll(); Keyboard.sendReport(); diff --git a/plugins/KeyboardioHID/keywords.txt b/plugins/KeyboardioHID/keywords.txt index fd3d69dd46..ab9196eb98 100644 --- a/plugins/KeyboardioHID/keywords.txt +++ b/plugins/KeyboardioHID/keywords.txt @@ -73,4 +73,4 @@ AbsoluteMouse KEYWORD1 HID_BOOT_PROTOCOL LITERAL1 HID_REPORT_PROTOCOL LITERAL1 -#TODO add key definitions like KEY_ENTER +#TODO add key definitions like HID_KEYBOARD_ENTER diff --git a/plugins/KeyboardioHID/src/HIDAliases.h b/plugins/KeyboardioHID/src/HIDAliases.h index 86394fbe45..bcdf00c797 100644 --- a/plugins/KeyboardioHID/src/HIDAliases.h +++ b/plugins/KeyboardioHID/src/HIDAliases.h @@ -6,155 +6,3 @@ #define HID_LAST_KEY HID_KEYPAD_HEXADECIMAL #define HID_KEYBOARD_FIRST_MODIFIER HID_KEYBOARD_LEFT_CONTROL #define HID_KEYBOARD_LAST_MODIFIER HID_KEYBOARD_RIGHT_GUI - - - -#define KEY_A HID_KEYBOARD_A_AND_A -#define KEY_B HID_KEYBOARD_B_AND_B -#define KEY_C HID_KEYBOARD_C_AND_C -#define KEY_D HID_KEYBOARD_D_AND_D -#define KEY_E HID_KEYBOARD_E_AND_E -#define KEY_F HID_KEYBOARD_F_AND_F -#define KEY_G HID_KEYBOARD_G_AND_G -#define KEY_H HID_KEYBOARD_H_AND_H -#define KEY_I HID_KEYBOARD_I_AND_I -#define KEY_J HID_KEYBOARD_J_AND_J -#define KEY_K HID_KEYBOARD_K_AND_K -#define KEY_L HID_KEYBOARD_L_AND_L -#define KEY_M HID_KEYBOARD_M_AND_M -#define KEY_N HID_KEYBOARD_N_AND_N -#define KEY_O HID_KEYBOARD_O_AND_O -#define KEY_P HID_KEYBOARD_P_AND_P -#define KEY_Q HID_KEYBOARD_Q_AND_Q -#define KEY_R HID_KEYBOARD_R_AND_R -#define KEY_S HID_KEYBOARD_S_AND_S -#define KEY_T HID_KEYBOARD_T_AND_T -#define KEY_U HID_KEYBOARD_U_AND_U -#define KEY_V HID_KEYBOARD_V_AND_V -#define KEY_W HID_KEYBOARD_W_AND_W -#define KEY_X HID_KEYBOARD_X_AND_X -#define KEY_Y HID_KEYBOARD_Y_AND_Y -#define KEY_Z HID_KEYBOARD_Z_AND_Z -#define KEY_1 HID_KEYBOARD_1_AND_EXCLAMATION_POINT -#define KEY_2 HID_KEYBOARD_2_AND_AT -#define KEY_3 HID_KEYBOARD_3_AND_POUND -#define KEY_4 HID_KEYBOARD_4_AND_DOLLAR -#define KEY_5 HID_KEYBOARD_5_AND_PERCENT -#define KEY_6 HID_KEYBOARD_6_AND_CARAT -#define KEY_7 HID_KEYBOARD_7_AND_AMPERSAND -#define KEY_8 HID_KEYBOARD_8_AND_ASTERISK -#define KEY_9 HID_KEYBOARD_9_AND_LEFT_PAREN -#define KEY_0 HID_KEYBOARD_0_AND_RIGHT_PAREN -#define KEY_ENTER HID_KEYBOARD_ENTER // (MARKED AS ENTER_SLASH_RETURN) -#define KEY_ESC HID_KEYBOARD_ESCAPE -#define KEY_BACKSPACE HID_KEYBOARD_DELETE // (BACKSPACE) -#define KEY_TAB HID_KEYBOARD_TAB -#define KEY_SPACE HID_KEYBOARD_SPACEBAR -#define KEY_MINUS HID_KEYBOARD_MINUS_AND_UNDERSCORE // (UNDERSCORE) -#define KEY_EQUALS HID_KEYBOARD_EQUALS_AND_PLUS -#define KEY_L_BRACKET HID_KEYBOARD_LEFT_BRACKET_AND_LEFT_CURLY_BRACE -#define KEY_R_BRACKET HID_KEYBOARD_RIGHT_BRACKET_AND_RIGHT_CURLY_BRACE -#define KEY_BACKSLASH HID_KEYBOARD_BACKSLASH_AND_PIPE -#define KEY_GBP HID_KEYBOARD_NON_US_POUND_AND_TILDE -#define KEY_SEMICOLON HID_KEYBOARD_SEMICOLON_AND_COLON -#define KEY_QUOTE HID_KEYBOARD_QUOTE_AND_DOUBLEQUOTE -#define KEY_GRAVE HID_KEYBOARD_GRAVE_ACCENT_AND_TILDE -#define KEY_COMMA HID_KEYBOARD_COMMA_AND_LESS_THAN -#define KEY_PERIOD HID_KEYBOARD_PERIOD_AND_GREATER_THAN -#define KEY_SLASH HID_KEYBOARD_SLASH_AND_QUESTION_MARK -#define KEY_CAPS HID_KEYBOARD_CAPS_LOCK -#define KEY_F1 HID_KEYBOARD_F1 -#define KEY_F2 HID_KEYBOARD_F2 -#define KEY_F3 HID_KEYBOARD_F3 -#define KEY_F4 HID_KEYBOARD_F4 -#define KEY_F5 HID_KEYBOARD_F5 -#define KEY_F6 HID_KEYBOARD_F6 -#define KEY_F7 HID_KEYBOARD_F7 -#define KEY_F8 HID_KEYBOARD_F8 -#define KEY_F9 HID_KEYBOARD_F9 -#define KEY_F10 HID_KEYBOARD_F10 -#define KEY_F11 HID_KEYBOARD_F11 -#define KEY_F12 HID_KEYBOARD_F12 -#define KEY_PRINTSCR HID_KEYBOARD_PRINTSCREEN -#define KEY_SCROLLLK HID_KEYBOARD_SCROLL_LOCK -#define KEY_PAUSE HID_KEYBOARD_PAUSE -#define KEY_INS HID_KEYBOARD_INSERT -#define KEY_HOME HID_KEYBOARD_HOME -#define KEY_PGUP HID_KEYBOARD_PAGE_UP -#define KEY_DEL_FWD HID_KEYBOARD_DELETE_FORWARD -#define KEY_END HID_KEYBOARD_END -#define KEY_PGDN HID_KEYBOARD_PAGE_DOWN -#define KEY_RARROW HID_KEYBOARD_RIGHT_ARROW -#define KEY_LARROW HID_KEYBOARD_LEFT_ARROW -#define KEY_DARROW HID_KEYBOARD_DOWN_ARROW -#define KEY_UARROW HID_KEYBOARD_UP_ARROW -#define KEY_NONUS_BACKSLASH HID_KEYBOARD_NON_US_BACKSLASH_AND_PIPE -#define KEY_APP HID_KEYBOARD_APPLICATION -#define KEY_PWR HID_KEYBOARD_POWER -#define KEY_F13 HID_KEYBOARD_F13 -#define KEY_F14 HID_KEYBOARD_F14 -#define KEY_F15 HID_KEYBOARD_F15 -#define KEY_F16 HID_KEYBOARD_F16 -#define KEY_F17 HID_KEYBOARD_F17 -#define KEY_F18 HID_KEYBOARD_F18 -#define KEY_F19 HID_KEYBOARD_F19 -#define KEY_F20 HID_KEYBOARD_F20 -#define KEY_F21 HID_KEYBOARD_F21 -#define KEY_F22 HID_KEYBOARD_F22 -#define KEY_F23 HID_KEYBOARD_F23 -#define KEY_F24 HID_KEYBOARD_F24 -#define KEY_EXEC HID_KEYBOARD_EXECUTE -#define KEY_HELP HID_KEYBOARD_HELP -#define KEY_MENU HID_KEYBOARD_MENU -#define KEY_SEL HID_KEYBOARD_SELECT -#define KEY_STOP HID_KEYBOARD_STOP -#define KEY_AGAIN HID_KEYBOARD_AGAIN -#define KEY_UNDO HID_KEYBOARD_UNDO -#define KEY_CUT HID_KEYBOARD_CUT -#define KEY_COPY HID_KEYBOARD_COPY -#define KEY_PASTE HID_KEYBOARD_PASTE -#define KEY_FIND HID_KEYBOARD_FIND -#define KEY_MUTE HID_KEYBOARD_MUTE -#define KEY_VOLUP HID_KEYBOARD_VOLUME_UP -#define KEY_VOLDN HID_KEYBOARD_VOLUME_DOWN -#define KEY_CAPSLOCK HID_KEYBOARD_LOCKING_CAPS_LOCK -#define KEY_NUMLOCK HID_KEYBOARD_LOCKING_NUM_LOCK -#define KEY_SCROLLLOCK HID_KEYBOARD_LOCKING_SCROLL_LOCK -#define KEY_INT1 HID_KEYBOARD_INTERNATIONAL1 -#define KEY_INT2 HID_KEYBOARD_INTERNATIONAL2 -#define KEY_INT3 HID_KEYBOARD_INTERNATIONAL3 -#define KEY_INT4 HID_KEYBOARD_INTERNATIONAL4 -#define KEY_INT5 HID_KEYBOARD_INTERNATIONAL5 -#define KEY_INT6 HID_KEYBOARD_INTERNATIONAL6 -#define KEY_INT7 HID_KEYBOARD_INTERNATIONAL7 -#define KEY_INT8 HID_KEYBOARD_INTERNATIONAL8 -#define KEY_INT9 HID_KEYBOARD_INTERNATIONAL9 -#define KEY_LANG1 HID_KEYBOARD_LANG1 -#define KEY_LANG2 HID_KEYBOARD_LANG2 -#define KEY_LANG3 HID_KEYBOARD_LANG3 -#define KEY_LANG4 HID_KEYBOARD_LANG4 -#define KEY_LANG5 HID_KEYBOARD_LANG5 -#define KEY_LANG6 HID_KEYBOARD_LANG6 -#define KEY_LANG7 HID_KEYBOARD_LANG7 -#define KEY_LANG8 HID_KEYBOARD_LANG8 -#define KEY_LANG9 HID_KEYBOARD_LANG9 -#define KEY_ALTDEL HID_KEYBOARD_ALTERNATE_ERASE -#define KEY_SYSREQ HID_KEYBOARD_SYSREQ_SLASH_ATTENTION -#define KEY_CANCEL HID_KEYBOARD_CANCEL -#define KEY_CLEAR HID_KEYBOARD_CLEAR -#define KEY_PRIOR HID_KEYBOARD_PRIOR -#define KEY_RETURN HID_KEYBOARD_RETURN -#define KEY_SEPARATOR HID_KEYBOARD_SEPARATOR -#define KEY_OUT HID_KEYBOARD_OUT -#define KEY_OPER HID_KEYBOARD_OPER -#define KEY_CLEAR_AGAIN HID_KEYBOARD_CLEAR_SLASH_AGAIN -#define KEY_CRSEL HID_KEYBOARD_CRSEL_SLASH_PROPS -#define KEY_EXSEL HID_KEYBOARD_EXSEL -#define KEY_LCTRL HID_KEYBOARD_LEFT_CONTROL -#define KEY_LSHIFT HID_KEYBOARD_LEFT_SHIFT -#define KEY_LALT HID_KEYBOARD_LEFT_ALT -#define KEY_LGUI HID_KEYBOARD_LEFT_GUI -#define KEY_RCTRL HID_KEYBOARD_RIGHT_CONTROL -#define KEY_RSHIFT HID_KEYBOARD_RIGHT_SHIFT -#define KEY_RALT HID_KEYBOARD_RIGHT_ALT -#define KEY_RGUI HID_KEYBOARD_RIGHT_GUI \ No newline at end of file From ddfbae164c35c82b0fce69f4fae231f7d1d75b05 Mon Sep 17 00:00:00 2001 From: Wez Furlong Date: Sun, 7 May 2017 19:28:25 -0700 Subject: [PATCH 463/602] Add .gitignore --- plugins/KeyboardioHID/.gitignore | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 plugins/KeyboardioHID/.gitignore diff --git a/plugins/KeyboardioHID/.gitignore b/plugins/KeyboardioHID/.gitignore new file mode 100644 index 0000000000..71696a0a6a --- /dev/null +++ b/plugins/KeyboardioHID/.gitignore @@ -0,0 +1,3 @@ +*~ +.#* +.*swp* From db223336d84379a6dde27d527fafa173b56b53d9 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Wed, 17 May 2017 01:44:29 -0700 Subject: [PATCH 464/602] typo in hid table entry --- plugins/KeyboardioHID/src/HIDTables.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/HIDTables.h b/plugins/KeyboardioHID/src/HIDTables.h index e3ff74d312..32cd52e8f6 100644 --- a/plugins/KeyboardioHID/src/HIDTables.h +++ b/plugins/KeyboardioHID/src/HIDTables.h @@ -672,7 +672,7 @@ #define HID_CONSUMER_AC_RENAME 0x298 // HID type SEL #define HID_CONSUMER_AC_MERGE 0x299 // HID type SEL #define HID_CONSUMER_AC_SPLIT 0x29A // HID type SEL -#define HID_CONSUMER_AC_DISRIBUTE_HORIZONTALLY 0x29B // HID type SEL +#define HID_CONSUMER_AC_DISTRIBUTE_HORIZONTALLY 0x29B // HID type SEL #define HID_CONSUMER_AC_DISTRIBUTE_VERTICALLY 0x29C // HID type SEL #endif // __HIDTables__ From 25bd0a0279e430c87749c4d509c6de2ca2a9507b Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 26 May 2017 16:20:24 -0700 Subject: [PATCH 465/602] make astyle --- .../examples/Consumer/Consumer.ino | 24 +++---- .../examples/Gamepad/Gamepad.ino | 69 +++++++++---------- .../Keyboard/BootKeyboard/BootKeyboard.ino | 42 +++++------ .../Keyboard/KeyboardLed/KeyboardLed.ino | 42 +++++------ .../examples/Keyboard/NKRO/NKRO.ino | 66 +++++++++--------- .../Mouse/AbsoluteMouse/AbsoluteMouse.ino | 68 +++++++++--------- .../Mouse/ImprovedMouse/ImprovedMouse.ino | 66 +++++++++--------- .../KeyboardioHID/examples/System/System.ino | 48 ++++++------- 8 files changed, 212 insertions(+), 213 deletions(-) diff --git a/plugins/KeyboardioHID/examples/Consumer/Consumer.ino b/plugins/KeyboardioHID/examples/Consumer/Consumer.ino index b7ae7c9653..e54b4af736 100644 --- a/plugins/KeyboardioHID/examples/Consumer/Consumer.ino +++ b/plugins/KeyboardioHID/examples/Consumer/Consumer.ino @@ -15,22 +15,22 @@ const int pinLed = LED_BUILTIN; const int pinButton = 2; void setup() { - pinMode(pinLed, OUTPUT); - pinMode(pinButton, INPUT_PULLUP); + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); - // Sends a clean report to the host. This is important on any Arduino type. - ConsumerControl.begin(); + // Sends a clean report to the host. This is important on any Arduino type. + ConsumerControl.begin(); } void loop() { - if (!digitalRead(pinButton)) { - digitalWrite(pinLed, HIGH); + if (!digitalRead(pinButton)) { + digitalWrite(pinLed, HIGH); - // See HID Project documentation for more Consumer keys - ConsumerControl.write(HID_CONSUMER_PLAY_SLASH_PAUSE); + // See HID Project documentation for more Consumer keys + ConsumerControl.write(HID_CONSUMER_PLAY_SLASH_PAUSE); - // Simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } + // Simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } } diff --git a/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino b/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino index 541bba9172..6a35a70a31 100644 --- a/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino +++ b/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino @@ -18,49 +18,48 @@ const int pinLed = LED_BUILTIN; const int pinButton = 2; void setup() { - pinMode(pinLed, OUTPUT); - pinMode(pinButton, INPUT_PULLUP); + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); - // Sends a clean report to the host. This is important on any Arduino type. - Gamepad.begin(); + // Sends a clean report to the host. This is important on any Arduino type. + Gamepad.begin(); } void loop() { - if (!digitalRead(pinButton)) { - digitalWrite(pinLed, HIGH); + if (!digitalRead(pinButton)) { + digitalWrite(pinLed, HIGH); - // Press button 1-32 - static uint8_t count = 0; - count++; - if (count == 33) { - Gamepad.releaseAll(); - count = 0; - } - else - Gamepad.press(count); + // Press button 1-32 + static uint8_t count = 0; + count++; + if (count == 33) { + Gamepad.releaseAll(); + count = 0; + } else + Gamepad.press(count); - // Move x/y Axis to a new position (16bit) - Gamepad.xAxis(random(0xFFFF)); - Gamepad.yAxis(random(0xFFFF)); + // Move x/y Axis to a new position (16bit) + Gamepad.xAxis(random(0xFFFF)); + Gamepad.yAxis(random(0xFFFF)); - // Go through all dPad positions - // values: 0-8 (0==centered) - static uint8_t dpad1 = GAMEPAD_DPAD_CENTERED; - Gamepad.dPad1(dpad1++); - if (dpad1 > GAMEPAD_DPAD_UP_LEFT) - dpad1 = GAMEPAD_DPAD_CENTERED; + // Go through all dPad positions + // values: 0-8 (0==centered) + static uint8_t dpad1 = GAMEPAD_DPAD_CENTERED; + Gamepad.dPad1(dpad1++); + if (dpad1 > GAMEPAD_DPAD_UP_LEFT) + dpad1 = GAMEPAD_DPAD_CENTERED; - static int8_t dpad2 = GAMEPAD_DPAD_CENTERED; - Gamepad.dPad2(dpad2--); - if (dpad2 < GAMEPAD_DPAD_CENTERED) - dpad2 = GAMEPAD_DPAD_UP_LEFT; + static int8_t dpad2 = GAMEPAD_DPAD_CENTERED; + Gamepad.dPad2(dpad2--); + if (dpad2 < GAMEPAD_DPAD_CENTERED) + dpad2 = GAMEPAD_DPAD_UP_LEFT; - // Functions above only set the values. - // This writes the report to the host. - Gamepad.write(); + // Functions above only set the values. + // This writes the report to the host. + Gamepad.write(); - // Simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } + // Simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } } diff --git a/plugins/KeyboardioHID/examples/Keyboard/BootKeyboard/BootKeyboard.ino b/plugins/KeyboardioHID/examples/Keyboard/BootKeyboard/BootKeyboard.ino index 698805aa3d..9d21a861ee 100644 --- a/plugins/KeyboardioHID/examples/Keyboard/BootKeyboard/BootKeyboard.ino +++ b/plugins/KeyboardioHID/examples/Keyboard/BootKeyboard/BootKeyboard.ino @@ -17,30 +17,30 @@ const int pinLed = LED_BUILTIN; const int pinButton = 2; void setup() { - pinMode(pinLed, OUTPUT); - pinMode(pinButton, INPUT_PULLUP); + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); - // Sends a clean report to the host. This is important on any Arduino type. - BootKeyboard.begin(); + // Sends a clean report to the host. This is important on any Arduino type. + BootKeyboard.begin(); } void loop() { - // Light led if keyboard uses the boot protocol (normally while in bios) - // Keep in mind that on a 16u2 and Arduino Micro HIGH and LOW for TX/RX Leds are inverted. - if (BootKeyboard.getProtocol() == HID_BOOT_PROTOCOL) - digitalWrite(pinLed, HIGH); - else - digitalWrite(pinLed, LOW); - - // Trigger caps lock manually via button - if (!digitalRead(pinButton)) { - BootKeyboard.press(HID_KEYBOARD_ENTER); - BootKeyboard.sendReport(); - BootKeyboard.releaseAll(); - BootKeyboard.sendReport(); - - // Simple debounce - delay(300); - } + // Light led if keyboard uses the boot protocol (normally while in bios) + // Keep in mind that on a 16u2 and Arduino Micro HIGH and LOW for TX/RX Leds are inverted. + if (BootKeyboard.getProtocol() == HID_BOOT_PROTOCOL) + digitalWrite(pinLed, HIGH); + else + digitalWrite(pinLed, LOW); + + // Trigger caps lock manually via button + if (!digitalRead(pinButton)) { + BootKeyboard.press(HID_KEYBOARD_ENTER); + BootKeyboard.sendReport(); + BootKeyboard.releaseAll(); + BootKeyboard.sendReport(); + + // Simple debounce + delay(300); + } } diff --git a/plugins/KeyboardioHID/examples/Keyboard/KeyboardLed/KeyboardLed.ino b/plugins/KeyboardioHID/examples/Keyboard/KeyboardLed/KeyboardLed.ino index 9aa7ed4f50..e501ff64cf 100644 --- a/plugins/KeyboardioHID/examples/Keyboard/KeyboardLed/KeyboardLed.ino +++ b/plugins/KeyboardioHID/examples/Keyboard/KeyboardLed/KeyboardLed.ino @@ -18,30 +18,30 @@ const int pinLed = LED_BUILTIN; const int pinButton = 2; void setup() { - pinMode(pinLed, OUTPUT); - pinMode(pinButton, INPUT_PULLUP); + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); - // Sends a clean report to the host. This is important on any Arduino type. - BootKeyboard.begin(); + // Sends a clean report to the host. This is important on any Arduino type. + BootKeyboard.begin(); } void loop() { - // Update Led equal to the caps lock state. - // Keep in mind that on a 16u2 and Arduino Micro HIGH and LOW for TX/RX Leds are inverted. - if (BootKeyboard.getLeds() & LED_CAPS_LOCK) - digitalWrite(pinLed, HIGH); - else - digitalWrite(pinLed, LOW); - - // Trigger caps lock manually via button - if (!digitalRead(pinButton)) { - BootKeyboard.press(HID_KEYBOARD_CAPS_LOCK); - BootKeyboard.sendReport(); - BootKeyboard.releaseAll(); - BootKeyboard.sendReport(); - - // Simple debounce - delay(300); - } + // Update Led equal to the caps lock state. + // Keep in mind that on a 16u2 and Arduino Micro HIGH and LOW for TX/RX Leds are inverted. + if (BootKeyboard.getLeds() & LED_CAPS_LOCK) + digitalWrite(pinLed, HIGH); + else + digitalWrite(pinLed, LOW); + + // Trigger caps lock manually via button + if (!digitalRead(pinButton)) { + BootKeyboard.press(HID_KEYBOARD_CAPS_LOCK); + BootKeyboard.sendReport(); + BootKeyboard.releaseAll(); + BootKeyboard.sendReport(); + + // Simple debounce + delay(300); + } } diff --git a/plugins/KeyboardioHID/examples/Keyboard/NKRO/NKRO.ino b/plugins/KeyboardioHID/examples/Keyboard/NKRO/NKRO.ino index 5179d3fb42..0c219729d3 100644 --- a/plugins/KeyboardioHID/examples/Keyboard/NKRO/NKRO.ino +++ b/plugins/KeyboardioHID/examples/Keyboard/NKRO/NKRO.ino @@ -19,42 +19,42 @@ const int pinLed = LED_BUILTIN; const int pinButton = 2; void setup() { - pinMode(pinLed, OUTPUT); - pinMode(pinButton, INPUT_PULLUP); + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); - // Sends a clean report to the host. This is important on any Arduino type. - Keyboard.begin(); + // Sends a clean report to the host. This is important on any Arduino type. + Keyboard.begin(); } void loop() { - // Hold a lot of keys at the same time - if (!digitalRead(pinButton)) { - digitalWrite(pinLed, HIGH); - - // Do not press too many at once or some OS will have problems. - // Note that the resulting pressed order might differ, - // because all keys are pressed at the same time. - Keyboard.press(HID_KEYBOARD_0_AND_RIGHT_PAREN); - Keyboard.press(HID_KEYBOARD_1_AND_EXCLAMATION_POINT); - Keyboard.press(HID_KEYBOARD_2_AND_AT); - Keyboard.press(HID_KEYBOARD_3_AND_POUND); - Keyboard.press(HID_KEYBOARD_4_AND_DOLLAR); - Keyboard.press(HID_KEYBOARD_5_AND_PERCENT); - Keyboard.press(HID_KEYBOARD_6_AND_CARAT); - Keyboard.press(HID_KEYBOARD_7_AND_AMPERSAND); - Keyboard.press(HID_KEYBOARD_8_AND_ASTERISK); - Keyboard.press(HID_KEYBOARD_9_AND_LEFT_PAREN); - Keyboard.sendReport(); - - // Release all keys and hit enter - Keyboard.releaseAll(); - Keyboard.press(HID_KEYBOARD_ENTER); - Keyboard.sendReport(); - Keyboard.releaseAll(); - Keyboard.sendReport(); - - // Simple debounce - delay(300); - } + // Hold a lot of keys at the same time + if (!digitalRead(pinButton)) { + digitalWrite(pinLed, HIGH); + + // Do not press too many at once or some OS will have problems. + // Note that the resulting pressed order might differ, + // because all keys are pressed at the same time. + Keyboard.press(HID_KEYBOARD_0_AND_RIGHT_PAREN); + Keyboard.press(HID_KEYBOARD_1_AND_EXCLAMATION_POINT); + Keyboard.press(HID_KEYBOARD_2_AND_AT); + Keyboard.press(HID_KEYBOARD_3_AND_POUND); + Keyboard.press(HID_KEYBOARD_4_AND_DOLLAR); + Keyboard.press(HID_KEYBOARD_5_AND_PERCENT); + Keyboard.press(HID_KEYBOARD_6_AND_CARAT); + Keyboard.press(HID_KEYBOARD_7_AND_AMPERSAND); + Keyboard.press(HID_KEYBOARD_8_AND_ASTERISK); + Keyboard.press(HID_KEYBOARD_9_AND_LEFT_PAREN); + Keyboard.sendReport(); + + // Release all keys and hit enter + Keyboard.releaseAll(); + Keyboard.press(HID_KEYBOARD_ENTER); + Keyboard.sendReport(); + Keyboard.releaseAll(); + Keyboard.sendReport(); + + // Simple debounce + delay(300); + } } diff --git a/plugins/KeyboardioHID/examples/Mouse/AbsoluteMouse/AbsoluteMouse.ino b/plugins/KeyboardioHID/examples/Mouse/AbsoluteMouse/AbsoluteMouse.ino index 6c67a41f3f..02b2479c5c 100644 --- a/plugins/KeyboardioHID/examples/Mouse/AbsoluteMouse/AbsoluteMouse.ino +++ b/plugins/KeyboardioHID/examples/Mouse/AbsoluteMouse/AbsoluteMouse.ino @@ -18,50 +18,50 @@ const int pinButtonCenter = 3; const int pinButtonMove = 1; void setup() { - // Prepare led + buttons - pinMode(pinLed, OUTPUT); - pinMode(pinButtonClick, INPUT_PULLUP); - pinMode(pinButtonCenter, INPUT_PULLUP); - pinMode(pinButtonMove, INPUT_PULLUP); + // Prepare led + buttons + pinMode(pinLed, OUTPUT); + pinMode(pinButtonClick, INPUT_PULLUP); + pinMode(pinButtonCenter, INPUT_PULLUP); + pinMode(pinButtonMove, INPUT_PULLUP); - // Sends a clean report to the host. This is important on any Arduino type. - AbsoluteMouse.begin(); + // Sends a clean report to the host. This is important on any Arduino type. + AbsoluteMouse.begin(); } void loop() { - if (!digitalRead(pinButtonClick)) { - digitalWrite(pinLed, HIGH); + if (!digitalRead(pinButtonClick)) { + digitalWrite(pinLed, HIGH); - // Same use as the official library, pretty much self explaining - AbsoluteMouse.click(); - //AbsoluteMouse.click(MOUSE_RIGHT); + // Same use as the official library, pretty much self explaining + AbsoluteMouse.click(); + //AbsoluteMouse.click(MOUSE_RIGHT); - // Simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } + // Simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } - if (!digitalRead(pinButtonCenter)) { - digitalWrite(pinLed, HIGH); + if (!digitalRead(pinButtonCenter)) { + digitalWrite(pinLed, HIGH); - // Move to coordinate (16bit signed, -32768 - 32767) - // Moving to the same position twice will not work! - // X and Y start in the upper left corner. - AbsoluteMouse.moveTo(0, 0); + // Move to coordinate (16bit signed, -32768 - 32767) + // Moving to the same position twice will not work! + // X and Y start in the upper left corner. + AbsoluteMouse.moveTo(0, 0); - // Simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } + // Simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } - if (!digitalRead(pinButtonMove)) { - digitalWrite(pinLed, HIGH); + if (!digitalRead(pinButtonMove)) { + digitalWrite(pinLed, HIGH); - // Move relative to last coordinate - AbsoluteMouse.move(1000, 1000); + // Move relative to last coordinate + AbsoluteMouse.move(1000, 1000); - // Simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } + // Simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } } diff --git a/plugins/KeyboardioHID/examples/Mouse/ImprovedMouse/ImprovedMouse.ino b/plugins/KeyboardioHID/examples/Mouse/ImprovedMouse/ImprovedMouse.ino index 378b06ea85..e087ef3947 100644 --- a/plugins/KeyboardioHID/examples/Mouse/ImprovedMouse/ImprovedMouse.ino +++ b/plugins/KeyboardioHID/examples/Mouse/ImprovedMouse/ImprovedMouse.ino @@ -21,49 +21,49 @@ const int pinButtonMove = 3; const int pinButtonScroll = 4; void setup() { - // Prepare led + buttons - pinMode(pinLed, OUTPUT); - pinMode(pinButtonClick, INPUT_PULLUP); - pinMode(pinButtonMove, INPUT_PULLUP); - pinMode(pinButtonScroll, INPUT_PULLUP); - - // Sends a clean report to the host. This is important on any Arduino type. - Mouse.begin(); + // Prepare led + buttons + pinMode(pinLed, OUTPUT); + pinMode(pinButtonClick, INPUT_PULLUP); + pinMode(pinButtonMove, INPUT_PULLUP); + pinMode(pinButtonScroll, INPUT_PULLUP); + + // Sends a clean report to the host. This is important on any Arduino type. + Mouse.begin(); } void loop() { - if (!digitalRead(pinButtonClick)) { - digitalWrite(pinLed, HIGH); + if (!digitalRead(pinButtonClick)) { + digitalWrite(pinLed, HIGH); - // Same use as the official library, pretty much self explaining - Mouse.click(); - //Mouse.click(MOUSE_RIGHT); + // Same use as the official library, pretty much self explaining + Mouse.click(); + //Mouse.click(MOUSE_RIGHT); - // Simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } + // Simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } - if (!digitalRead(pinButtonMove)) { - digitalWrite(pinLed, HIGH); + if (!digitalRead(pinButtonMove)) { + digitalWrite(pinLed, HIGH); - // Same use as the official library, pretty much self explaining - Mouse.move(100, 0); + // Same use as the official library, pretty much self explaining + Mouse.move(100, 0); - // Simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } + // Simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } - if (!digitalRead(pinButtonScroll)) { - digitalWrite(pinLed, HIGH); + if (!digitalRead(pinButtonScroll)) { + digitalWrite(pinLed, HIGH); - // Scroll down a bit, make sure the value is high enough - Mouse.move(0, 0, 160); + // Scroll down a bit, make sure the value is high enough + Mouse.move(0, 0, 160); - // simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } + // simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } } diff --git a/plugins/KeyboardioHID/examples/System/System.ino b/plugins/KeyboardioHID/examples/System/System.ino index 29587a81ea..ecf32bdb99 100644 --- a/plugins/KeyboardioHID/examples/System/System.ino +++ b/plugins/KeyboardioHID/examples/System/System.ino @@ -17,37 +17,37 @@ const int pinButtonS = 2; const int pinButtonW = 3; void setup() { - // prepare led + buttons - pinMode(pinLed, OUTPUT); - pinMode(pinButtonS, INPUT_PULLUP); - pinMode(pinButtonW, INPUT_PULLUP); + // prepare led + buttons + pinMode(pinLed, OUTPUT); + pinMode(pinButtonS, INPUT_PULLUP); + pinMode(pinButtonW, INPUT_PULLUP); - // Sends a clean report to the host. This is important on any Arduino type. - SystemControl.begin(); + // Sends a clean report to the host. This is important on any Arduino type. + SystemControl.begin(); } void loop() { - if (!digitalRead(pinButtonS)) { - digitalWrite(pinLed, HIGH); + if (!digitalRead(pinButtonS)) { + digitalWrite(pinLed, HIGH); - // Puts PC into sleep mode/shuts it down - SystemControl.write(HID_SYSTEM_SLEEP); - //SystemControl.write(HID_SYSTEM_POWER_DOWN); + // Puts PC into sleep mode/shuts it down + SystemControl.write(HID_SYSTEM_SLEEP); + //SystemControl.write(HID_SYSTEM_POWER_DOWN); - // Simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } + // Simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } - if (!digitalRead(pinButtonW)) { - digitalWrite(pinLed, HIGH); + if (!digitalRead(pinButtonW)) { + digitalWrite(pinLed, HIGH); - // Try to wake up the PC - // This might fail on some PCs/Laptops where USB wakeup is not supported - SystemControl.write(HID_SYSTEM_WAKE_UP); + // Try to wake up the PC + // This might fail on some PCs/Laptops where USB wakeup is not supported + SystemControl.write(HID_SYSTEM_WAKE_UP); - // Simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } + // Simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } } From 5f4f21b07a94ac03367fd13234bc7e1814155db6 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Sat, 3 Jun 2017 22:44:18 -0700 Subject: [PATCH 466/602] astyle with current project style guidelines --- .../examples/Consumer/Consumer.ino | 24 +- .../examples/Gamepad/Gamepad.ino | 68 +-- .../Keyboard/BootKeyboard/BootKeyboard.ino | 42 +- .../Keyboard/KeyboardLed/KeyboardLed.ino | 42 +- .../examples/Keyboard/NKRO/NKRO.ino | 66 +-- .../Mouse/AbsoluteMouse/AbsoluteMouse.ino | 68 +-- .../Mouse/ImprovedMouse/ImprovedMouse.ino | 66 +-- .../KeyboardioHID/examples/System/System.ino | 48 +- .../src/BootKeyboard/BootKeyboard.cpp | 414 +++++++++--------- .../src/BootKeyboard/BootKeyboard.h | 96 ++-- plugins/KeyboardioHID/src/LEDs.h | 16 +- .../src/MultiReport/AbsoluteMouse.cpp | 166 +++---- .../src/MultiReport/AbsoluteMouse.h | 58 +-- .../src/MultiReport/ConsumerControl.cpp | 76 ++-- .../src/MultiReport/ConsumerControl.h | 40 +- .../KeyboardioHID/src/MultiReport/Gamepad.cpp | 132 +++--- .../KeyboardioHID/src/MultiReport/Gamepad.h | 150 +++---- .../src/MultiReport/Keyboard.cpp | 248 +++++------ .../KeyboardioHID/src/MultiReport/Keyboard.h | 34 +- .../KeyboardioHID/src/MultiReport/Mouse.cpp | 108 ++--- plugins/KeyboardioHID/src/MultiReport/Mouse.h | 44 +- .../src/MultiReport/SystemControl.cpp | 60 +-- .../src/MultiReport/SystemControl.h | 28 +- 23 files changed, 1047 insertions(+), 1047 deletions(-) diff --git a/plugins/KeyboardioHID/examples/Consumer/Consumer.ino b/plugins/KeyboardioHID/examples/Consumer/Consumer.ino index e54b4af736..b7ae7c9653 100644 --- a/plugins/KeyboardioHID/examples/Consumer/Consumer.ino +++ b/plugins/KeyboardioHID/examples/Consumer/Consumer.ino @@ -15,22 +15,22 @@ const int pinLed = LED_BUILTIN; const int pinButton = 2; void setup() { - pinMode(pinLed, OUTPUT); - pinMode(pinButton, INPUT_PULLUP); + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); - // Sends a clean report to the host. This is important on any Arduino type. - ConsumerControl.begin(); + // Sends a clean report to the host. This is important on any Arduino type. + ConsumerControl.begin(); } void loop() { - if (!digitalRead(pinButton)) { - digitalWrite(pinLed, HIGH); + if (!digitalRead(pinButton)) { + digitalWrite(pinLed, HIGH); - // See HID Project documentation for more Consumer keys - ConsumerControl.write(HID_CONSUMER_PLAY_SLASH_PAUSE); + // See HID Project documentation for more Consumer keys + ConsumerControl.write(HID_CONSUMER_PLAY_SLASH_PAUSE); - // Simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } + // Simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } } diff --git a/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino b/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino index 6a35a70a31..40538f5189 100644 --- a/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino +++ b/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino @@ -18,48 +18,48 @@ const int pinLed = LED_BUILTIN; const int pinButton = 2; void setup() { - pinMode(pinLed, OUTPUT); - pinMode(pinButton, INPUT_PULLUP); + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); - // Sends a clean report to the host. This is important on any Arduino type. - Gamepad.begin(); + // Sends a clean report to the host. This is important on any Arduino type. + Gamepad.begin(); } void loop() { - if (!digitalRead(pinButton)) { - digitalWrite(pinLed, HIGH); + if (!digitalRead(pinButton)) { + digitalWrite(pinLed, HIGH); - // Press button 1-32 - static uint8_t count = 0; - count++; - if (count == 33) { - Gamepad.releaseAll(); - count = 0; - } else - Gamepad.press(count); + // Press button 1-32 + static uint8_t count = 0; + count++; + if (count == 33) { + Gamepad.releaseAll(); + count = 0; + } else + Gamepad.press(count); - // Move x/y Axis to a new position (16bit) - Gamepad.xAxis(random(0xFFFF)); - Gamepad.yAxis(random(0xFFFF)); + // Move x/y Axis to a new position (16bit) + Gamepad.xAxis(random(0xFFFF)); + Gamepad.yAxis(random(0xFFFF)); - // Go through all dPad positions - // values: 0-8 (0==centered) - static uint8_t dpad1 = GAMEPAD_DPAD_CENTERED; - Gamepad.dPad1(dpad1++); - if (dpad1 > GAMEPAD_DPAD_UP_LEFT) - dpad1 = GAMEPAD_DPAD_CENTERED; + // Go through all dPad positions + // values: 0-8 (0==centered) + static uint8_t dpad1 = GAMEPAD_DPAD_CENTERED; + Gamepad.dPad1(dpad1++); + if (dpad1 > GAMEPAD_DPAD_UP_LEFT) + dpad1 = GAMEPAD_DPAD_CENTERED; - static int8_t dpad2 = GAMEPAD_DPAD_CENTERED; - Gamepad.dPad2(dpad2--); - if (dpad2 < GAMEPAD_DPAD_CENTERED) - dpad2 = GAMEPAD_DPAD_UP_LEFT; + static int8_t dpad2 = GAMEPAD_DPAD_CENTERED; + Gamepad.dPad2(dpad2--); + if (dpad2 < GAMEPAD_DPAD_CENTERED) + dpad2 = GAMEPAD_DPAD_UP_LEFT; - // Functions above only set the values. - // This writes the report to the host. - Gamepad.write(); + // Functions above only set the values. + // This writes the report to the host. + Gamepad.write(); - // Simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } + // Simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } } diff --git a/plugins/KeyboardioHID/examples/Keyboard/BootKeyboard/BootKeyboard.ino b/plugins/KeyboardioHID/examples/Keyboard/BootKeyboard/BootKeyboard.ino index 9d21a861ee..698805aa3d 100644 --- a/plugins/KeyboardioHID/examples/Keyboard/BootKeyboard/BootKeyboard.ino +++ b/plugins/KeyboardioHID/examples/Keyboard/BootKeyboard/BootKeyboard.ino @@ -17,30 +17,30 @@ const int pinLed = LED_BUILTIN; const int pinButton = 2; void setup() { - pinMode(pinLed, OUTPUT); - pinMode(pinButton, INPUT_PULLUP); + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); - // Sends a clean report to the host. This is important on any Arduino type. - BootKeyboard.begin(); + // Sends a clean report to the host. This is important on any Arduino type. + BootKeyboard.begin(); } void loop() { - // Light led if keyboard uses the boot protocol (normally while in bios) - // Keep in mind that on a 16u2 and Arduino Micro HIGH and LOW for TX/RX Leds are inverted. - if (BootKeyboard.getProtocol() == HID_BOOT_PROTOCOL) - digitalWrite(pinLed, HIGH); - else - digitalWrite(pinLed, LOW); - - // Trigger caps lock manually via button - if (!digitalRead(pinButton)) { - BootKeyboard.press(HID_KEYBOARD_ENTER); - BootKeyboard.sendReport(); - BootKeyboard.releaseAll(); - BootKeyboard.sendReport(); - - // Simple debounce - delay(300); - } + // Light led if keyboard uses the boot protocol (normally while in bios) + // Keep in mind that on a 16u2 and Arduino Micro HIGH and LOW for TX/RX Leds are inverted. + if (BootKeyboard.getProtocol() == HID_BOOT_PROTOCOL) + digitalWrite(pinLed, HIGH); + else + digitalWrite(pinLed, LOW); + + // Trigger caps lock manually via button + if (!digitalRead(pinButton)) { + BootKeyboard.press(HID_KEYBOARD_ENTER); + BootKeyboard.sendReport(); + BootKeyboard.releaseAll(); + BootKeyboard.sendReport(); + + // Simple debounce + delay(300); + } } diff --git a/plugins/KeyboardioHID/examples/Keyboard/KeyboardLed/KeyboardLed.ino b/plugins/KeyboardioHID/examples/Keyboard/KeyboardLed/KeyboardLed.ino index e501ff64cf..9aa7ed4f50 100644 --- a/plugins/KeyboardioHID/examples/Keyboard/KeyboardLed/KeyboardLed.ino +++ b/plugins/KeyboardioHID/examples/Keyboard/KeyboardLed/KeyboardLed.ino @@ -18,30 +18,30 @@ const int pinLed = LED_BUILTIN; const int pinButton = 2; void setup() { - pinMode(pinLed, OUTPUT); - pinMode(pinButton, INPUT_PULLUP); + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); - // Sends a clean report to the host. This is important on any Arduino type. - BootKeyboard.begin(); + // Sends a clean report to the host. This is important on any Arduino type. + BootKeyboard.begin(); } void loop() { - // Update Led equal to the caps lock state. - // Keep in mind that on a 16u2 and Arduino Micro HIGH and LOW for TX/RX Leds are inverted. - if (BootKeyboard.getLeds() & LED_CAPS_LOCK) - digitalWrite(pinLed, HIGH); - else - digitalWrite(pinLed, LOW); - - // Trigger caps lock manually via button - if (!digitalRead(pinButton)) { - BootKeyboard.press(HID_KEYBOARD_CAPS_LOCK); - BootKeyboard.sendReport(); - BootKeyboard.releaseAll(); - BootKeyboard.sendReport(); - - // Simple debounce - delay(300); - } + // Update Led equal to the caps lock state. + // Keep in mind that on a 16u2 and Arduino Micro HIGH and LOW for TX/RX Leds are inverted. + if (BootKeyboard.getLeds() & LED_CAPS_LOCK) + digitalWrite(pinLed, HIGH); + else + digitalWrite(pinLed, LOW); + + // Trigger caps lock manually via button + if (!digitalRead(pinButton)) { + BootKeyboard.press(HID_KEYBOARD_CAPS_LOCK); + BootKeyboard.sendReport(); + BootKeyboard.releaseAll(); + BootKeyboard.sendReport(); + + // Simple debounce + delay(300); + } } diff --git a/plugins/KeyboardioHID/examples/Keyboard/NKRO/NKRO.ino b/plugins/KeyboardioHID/examples/Keyboard/NKRO/NKRO.ino index 0c219729d3..5179d3fb42 100644 --- a/plugins/KeyboardioHID/examples/Keyboard/NKRO/NKRO.ino +++ b/plugins/KeyboardioHID/examples/Keyboard/NKRO/NKRO.ino @@ -19,42 +19,42 @@ const int pinLed = LED_BUILTIN; const int pinButton = 2; void setup() { - pinMode(pinLed, OUTPUT); - pinMode(pinButton, INPUT_PULLUP); + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); - // Sends a clean report to the host. This is important on any Arduino type. - Keyboard.begin(); + // Sends a clean report to the host. This is important on any Arduino type. + Keyboard.begin(); } void loop() { - // Hold a lot of keys at the same time - if (!digitalRead(pinButton)) { - digitalWrite(pinLed, HIGH); - - // Do not press too many at once or some OS will have problems. - // Note that the resulting pressed order might differ, - // because all keys are pressed at the same time. - Keyboard.press(HID_KEYBOARD_0_AND_RIGHT_PAREN); - Keyboard.press(HID_KEYBOARD_1_AND_EXCLAMATION_POINT); - Keyboard.press(HID_KEYBOARD_2_AND_AT); - Keyboard.press(HID_KEYBOARD_3_AND_POUND); - Keyboard.press(HID_KEYBOARD_4_AND_DOLLAR); - Keyboard.press(HID_KEYBOARD_5_AND_PERCENT); - Keyboard.press(HID_KEYBOARD_6_AND_CARAT); - Keyboard.press(HID_KEYBOARD_7_AND_AMPERSAND); - Keyboard.press(HID_KEYBOARD_8_AND_ASTERISK); - Keyboard.press(HID_KEYBOARD_9_AND_LEFT_PAREN); - Keyboard.sendReport(); - - // Release all keys and hit enter - Keyboard.releaseAll(); - Keyboard.press(HID_KEYBOARD_ENTER); - Keyboard.sendReport(); - Keyboard.releaseAll(); - Keyboard.sendReport(); - - // Simple debounce - delay(300); - } + // Hold a lot of keys at the same time + if (!digitalRead(pinButton)) { + digitalWrite(pinLed, HIGH); + + // Do not press too many at once or some OS will have problems. + // Note that the resulting pressed order might differ, + // because all keys are pressed at the same time. + Keyboard.press(HID_KEYBOARD_0_AND_RIGHT_PAREN); + Keyboard.press(HID_KEYBOARD_1_AND_EXCLAMATION_POINT); + Keyboard.press(HID_KEYBOARD_2_AND_AT); + Keyboard.press(HID_KEYBOARD_3_AND_POUND); + Keyboard.press(HID_KEYBOARD_4_AND_DOLLAR); + Keyboard.press(HID_KEYBOARD_5_AND_PERCENT); + Keyboard.press(HID_KEYBOARD_6_AND_CARAT); + Keyboard.press(HID_KEYBOARD_7_AND_AMPERSAND); + Keyboard.press(HID_KEYBOARD_8_AND_ASTERISK); + Keyboard.press(HID_KEYBOARD_9_AND_LEFT_PAREN); + Keyboard.sendReport(); + + // Release all keys and hit enter + Keyboard.releaseAll(); + Keyboard.press(HID_KEYBOARD_ENTER); + Keyboard.sendReport(); + Keyboard.releaseAll(); + Keyboard.sendReport(); + + // Simple debounce + delay(300); + } } diff --git a/plugins/KeyboardioHID/examples/Mouse/AbsoluteMouse/AbsoluteMouse.ino b/plugins/KeyboardioHID/examples/Mouse/AbsoluteMouse/AbsoluteMouse.ino index 02b2479c5c..6c67a41f3f 100644 --- a/plugins/KeyboardioHID/examples/Mouse/AbsoluteMouse/AbsoluteMouse.ino +++ b/plugins/KeyboardioHID/examples/Mouse/AbsoluteMouse/AbsoluteMouse.ino @@ -18,50 +18,50 @@ const int pinButtonCenter = 3; const int pinButtonMove = 1; void setup() { - // Prepare led + buttons - pinMode(pinLed, OUTPUT); - pinMode(pinButtonClick, INPUT_PULLUP); - pinMode(pinButtonCenter, INPUT_PULLUP); - pinMode(pinButtonMove, INPUT_PULLUP); + // Prepare led + buttons + pinMode(pinLed, OUTPUT); + pinMode(pinButtonClick, INPUT_PULLUP); + pinMode(pinButtonCenter, INPUT_PULLUP); + pinMode(pinButtonMove, INPUT_PULLUP); - // Sends a clean report to the host. This is important on any Arduino type. - AbsoluteMouse.begin(); + // Sends a clean report to the host. This is important on any Arduino type. + AbsoluteMouse.begin(); } void loop() { - if (!digitalRead(pinButtonClick)) { - digitalWrite(pinLed, HIGH); + if (!digitalRead(pinButtonClick)) { + digitalWrite(pinLed, HIGH); - // Same use as the official library, pretty much self explaining - AbsoluteMouse.click(); - //AbsoluteMouse.click(MOUSE_RIGHT); + // Same use as the official library, pretty much self explaining + AbsoluteMouse.click(); + //AbsoluteMouse.click(MOUSE_RIGHT); - // Simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } + // Simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } - if (!digitalRead(pinButtonCenter)) { - digitalWrite(pinLed, HIGH); + if (!digitalRead(pinButtonCenter)) { + digitalWrite(pinLed, HIGH); - // Move to coordinate (16bit signed, -32768 - 32767) - // Moving to the same position twice will not work! - // X and Y start in the upper left corner. - AbsoluteMouse.moveTo(0, 0); + // Move to coordinate (16bit signed, -32768 - 32767) + // Moving to the same position twice will not work! + // X and Y start in the upper left corner. + AbsoluteMouse.moveTo(0, 0); - // Simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } + // Simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } - if (!digitalRead(pinButtonMove)) { - digitalWrite(pinLed, HIGH); + if (!digitalRead(pinButtonMove)) { + digitalWrite(pinLed, HIGH); - // Move relative to last coordinate - AbsoluteMouse.move(1000, 1000); + // Move relative to last coordinate + AbsoluteMouse.move(1000, 1000); - // Simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } + // Simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } } diff --git a/plugins/KeyboardioHID/examples/Mouse/ImprovedMouse/ImprovedMouse.ino b/plugins/KeyboardioHID/examples/Mouse/ImprovedMouse/ImprovedMouse.ino index e087ef3947..378b06ea85 100644 --- a/plugins/KeyboardioHID/examples/Mouse/ImprovedMouse/ImprovedMouse.ino +++ b/plugins/KeyboardioHID/examples/Mouse/ImprovedMouse/ImprovedMouse.ino @@ -21,49 +21,49 @@ const int pinButtonMove = 3; const int pinButtonScroll = 4; void setup() { - // Prepare led + buttons - pinMode(pinLed, OUTPUT); - pinMode(pinButtonClick, INPUT_PULLUP); - pinMode(pinButtonMove, INPUT_PULLUP); - pinMode(pinButtonScroll, INPUT_PULLUP); - - // Sends a clean report to the host. This is important on any Arduino type. - Mouse.begin(); + // Prepare led + buttons + pinMode(pinLed, OUTPUT); + pinMode(pinButtonClick, INPUT_PULLUP); + pinMode(pinButtonMove, INPUT_PULLUP); + pinMode(pinButtonScroll, INPUT_PULLUP); + + // Sends a clean report to the host. This is important on any Arduino type. + Mouse.begin(); } void loop() { - if (!digitalRead(pinButtonClick)) { - digitalWrite(pinLed, HIGH); + if (!digitalRead(pinButtonClick)) { + digitalWrite(pinLed, HIGH); - // Same use as the official library, pretty much self explaining - Mouse.click(); - //Mouse.click(MOUSE_RIGHT); + // Same use as the official library, pretty much self explaining + Mouse.click(); + //Mouse.click(MOUSE_RIGHT); - // Simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } + // Simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } - if (!digitalRead(pinButtonMove)) { - digitalWrite(pinLed, HIGH); + if (!digitalRead(pinButtonMove)) { + digitalWrite(pinLed, HIGH); - // Same use as the official library, pretty much self explaining - Mouse.move(100, 0); + // Same use as the official library, pretty much self explaining + Mouse.move(100, 0); - // Simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } + // Simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } - if (!digitalRead(pinButtonScroll)) { - digitalWrite(pinLed, HIGH); + if (!digitalRead(pinButtonScroll)) { + digitalWrite(pinLed, HIGH); - // Scroll down a bit, make sure the value is high enough - Mouse.move(0, 0, 160); + // Scroll down a bit, make sure the value is high enough + Mouse.move(0, 0, 160); - // simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } + // simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } } diff --git a/plugins/KeyboardioHID/examples/System/System.ino b/plugins/KeyboardioHID/examples/System/System.ino index ecf32bdb99..29587a81ea 100644 --- a/plugins/KeyboardioHID/examples/System/System.ino +++ b/plugins/KeyboardioHID/examples/System/System.ino @@ -17,37 +17,37 @@ const int pinButtonS = 2; const int pinButtonW = 3; void setup() { - // prepare led + buttons - pinMode(pinLed, OUTPUT); - pinMode(pinButtonS, INPUT_PULLUP); - pinMode(pinButtonW, INPUT_PULLUP); + // prepare led + buttons + pinMode(pinLed, OUTPUT); + pinMode(pinButtonS, INPUT_PULLUP); + pinMode(pinButtonW, INPUT_PULLUP); - // Sends a clean report to the host. This is important on any Arduino type. - SystemControl.begin(); + // Sends a clean report to the host. This is important on any Arduino type. + SystemControl.begin(); } void loop() { - if (!digitalRead(pinButtonS)) { - digitalWrite(pinLed, HIGH); + if (!digitalRead(pinButtonS)) { + digitalWrite(pinLed, HIGH); - // Puts PC into sleep mode/shuts it down - SystemControl.write(HID_SYSTEM_SLEEP); - //SystemControl.write(HID_SYSTEM_POWER_DOWN); + // Puts PC into sleep mode/shuts it down + SystemControl.write(HID_SYSTEM_SLEEP); + //SystemControl.write(HID_SYSTEM_POWER_DOWN); - // Simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } + // Simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } - if (!digitalRead(pinButtonW)) { - digitalWrite(pinLed, HIGH); + if (!digitalRead(pinButtonW)) { + digitalWrite(pinLed, HIGH); - // Try to wake up the PC - // This might fail on some PCs/Laptops where USB wakeup is not supported - SystemControl.write(HID_SYSTEM_WAKE_UP); + // Try to wake up the PC + // This might fail on some PCs/Laptops where USB wakeup is not supported + SystemControl.write(HID_SYSTEM_WAKE_UP); - // Simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } + // Simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } } diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 4c8df30a76..0f85f2e94c 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -24,195 +24,195 @@ THE SOFTWARE. #include "BootKeyboard.h" static const uint8_t _hidReportDescriptorKeyboard[] PROGMEM = { - // Keyboard - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 47 */ - 0x09, 0x06, /* USAGE (Keyboard) */ - 0xa1, 0x01, /* COLLECTION (Application) */ - 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ - - /* Keyboard Modifiers (shift, alt, ...) */ - 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) */ - - /* Reserved byte, used for consumer reports, only works with linux */ - /* NOT CURRENTLY USED BY THIS IMPLEMENTATION */ - 0x05, 0x0C, /* Usage Page (Consumer) */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0x75, 0x08, /* REPORT_SIZE (8) */ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ - 0x26, 0xFF, 0x00, /* LOGICAL_MAXIMUM (255) */ - 0x19, 0x00, /* USAGE_MINIMUM (0) */ - 0x29, 0xFF, /* USAGE_MAXIMUM (255) */ - 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ - - /* 5 LEDs for num lock etc, 3 left for advanced, custom usage */ - 0x05, 0x08, /* USAGE_PAGE (LEDs) */ - 0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */ - 0x29, 0x08, /* USAGE_MAXIMUM (Kana + 3 custom)*/ - 0x95, 0x08, /* REPORT_COUNT (8) */ - 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */ - - /* 6 Keyboard keys */ - 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ - 0x95, 0x06, /* REPORT_COUNT (6) */ - 0x75, 0x08, /* REPORT_SIZE (8) */ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ - 0x26, 0xE7, 0x00, /* LOGICAL_MAXIMUM (231) */ - 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ - 0x29, 0xE7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ - 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ - - /* End */ - 0xc0 /* END_COLLECTION */ + // Keyboard + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 47 */ + 0x09, 0x06, /* USAGE (Keyboard) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ + + /* Keyboard Modifiers (shift, alt, ...) */ + 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) */ + + /* Reserved byte, used for consumer reports, only works with linux */ + /* NOT CURRENTLY USED BY THIS IMPLEMENTATION */ + 0x05, 0x0C, /* Usage Page (Consumer) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x26, 0xFF, 0x00, /* LOGICAL_MAXIMUM (255) */ + 0x19, 0x00, /* USAGE_MINIMUM (0) */ + 0x29, 0xFF, /* USAGE_MAXIMUM (255) */ + 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ + + /* 5 LEDs for num lock etc, 3 left for advanced, custom usage */ + 0x05, 0x08, /* USAGE_PAGE (LEDs) */ + 0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */ + 0x29, 0x08, /* USAGE_MAXIMUM (Kana + 3 custom)*/ + 0x95, 0x08, /* REPORT_COUNT (8) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */ + + /* 6 Keyboard keys */ + 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ + 0x95, 0x06, /* REPORT_COUNT (6) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x26, 0xE7, 0x00, /* LOGICAL_MAXIMUM (231) */ + 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ + 0x29, 0xE7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ + 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ + + /* End */ + 0xc0 /* END_COLLECTION */ }; BootKeyboard_::BootKeyboard_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1), leds(0), featureReport(NULL), featureLength(0) { - epType[0] = EP_TYPE_INTERRUPT_IN; - PluggableUSB().plug(this); + epType[0] = EP_TYPE_INTERRUPT_IN; + PluggableUSB().plug(this); } int BootKeyboard_::getInterface(uint8_t* interfaceCount) { - *interfaceCount += 1; // uses 1 - HIDDescriptor hidInterface = { - D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_BOOT_INTERFACE, HID_PROTOCOL_KEYBOARD), - D_HIDREPORT(sizeof(_hidReportDescriptorKeyboard)), - D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) - }; - return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); + *interfaceCount += 1; // uses 1 + HIDDescriptor hidInterface = { + D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_BOOT_INTERFACE, HID_PROTOCOL_KEYBOARD), + D_HIDREPORT(sizeof(_hidReportDescriptorKeyboard)), + D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) + }; + return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); } int BootKeyboard_::getDescriptor(USBSetup& setup) { - // Check if this is a HID Class Descriptor request - if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { - return 0; - } - if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { - return 0; - } - - // In a HID Class Descriptor wIndex cointains the interface number - if (setup.wIndex != pluggedInterface) { - return 0; - } - - // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol - // due to the USB specs, but Windows and Linux just assumes its in report mode. - protocol = HID_REPORT_PROTOCOL; - - return USB_SendControl(TRANSFER_PGM, _hidReportDescriptorKeyboard, sizeof(_hidReportDescriptorKeyboard)); + // Check if this is a HID Class Descriptor request + if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { + return 0; + } + if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { + return 0; + } + + // In a HID Class Descriptor wIndex cointains the interface number + if (setup.wIndex != pluggedInterface) { + return 0; + } + + // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol + // due to the USB specs, but Windows and Linux just assumes its in report mode. + protocol = HID_REPORT_PROTOCOL; + + return USB_SendControl(TRANSFER_PGM, _hidReportDescriptorKeyboard, sizeof(_hidReportDescriptorKeyboard)); } void BootKeyboard_::begin(void) { - // Force API to send a clean report. - // This is important for and HID bridge where the receiver stays on, - // while the sender is resetted. - releaseAll(); - sendReport(); + // Force API to send a clean report. + // This is important for and HID bridge where the receiver stays on, + // while the sender is resetted. + releaseAll(); + sendReport(); } void BootKeyboard_::end(void) { - releaseAll(); - sendReport(); + releaseAll(); + sendReport(); } bool BootKeyboard_::setup(USBSetup& setup) { - if (pluggedInterface != setup.wIndex) { - return false; - } + if (pluggedInterface != setup.wIndex) { + return false; + } - uint8_t request = setup.bRequest; - uint8_t requestType = setup.bmRequestType; + uint8_t request = setup.bRequest; + uint8_t requestType = setup.bmRequestType; - if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) { - if (request == HID_GET_REPORT) { - // TODO: HID_GetReport(); - return true; - } - if (request == HID_GET_PROTOCOL) { - // TODO improve - UEDATX = protocol; - return true; - } - if (request == HID_GET_IDLE) { - // TODO improve - UEDATX = idle; - return true; - } + if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) { + if (request == HID_GET_REPORT) { + // TODO: HID_GetReport(); + return true; } + if (request == HID_GET_PROTOCOL) { + // TODO improve + UEDATX = protocol; + return true; + } + if (request == HID_GET_IDLE) { + // TODO improve + UEDATX = idle; + return true; + } + } - if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) { - if (request == HID_SET_PROTOCOL) { - protocol = setup.wValueL; - return true; + if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) { + if (request == HID_SET_PROTOCOL) { + protocol = setup.wValueL; + return true; + } + if (request == HID_SET_IDLE) { + idle = setup.wValueL; + return true; + } + if (request == HID_SET_REPORT) { + // Check if data has the correct length afterwards + int length = setup.wLength; + + // Feature (set feature report) + if (setup.wValueH == HID_REPORT_TYPE_FEATURE) { + // No need to check for negative featureLength values, + // except the host tries to send more then 32k bytes. + // We dont have that much ram anyways. + if (length == featureLength) { + USB_RecvControl(featureReport, featureLength); + + // Block until data is read (make length negative) + disableFeatureReport(); + return true; } - if (request == HID_SET_IDLE) { - idle = setup.wValueL; - return true; + // TODO fake clear data? + } + + // Output (set led states) + else if (setup.wValueH == HID_REPORT_TYPE_OUTPUT) { + if (length == sizeof(leds)) { + USB_RecvControl(&leds, length); + return true; } - if (request == HID_SET_REPORT) { - // Check if data has the correct length afterwards - int length = setup.wLength; - - // Feature (set feature report) - if(setup.wValueH == HID_REPORT_TYPE_FEATURE) { - // No need to check for negative featureLength values, - // except the host tries to send more then 32k bytes. - // We dont have that much ram anyways. - if (length == featureLength) { - USB_RecvControl(featureReport, featureLength); - - // Block until data is read (make length negative) - disableFeatureReport(); - return true; - } - // TODO fake clear data? - } - - // Output (set led states) - else if(setup.wValueH == HID_REPORT_TYPE_OUTPUT) { - if(length == sizeof(leds)) { - USB_RecvControl(&leds, length); - return true; - } - } - - // Input (set HID report) - else if(setup.wValueH == HID_REPORT_TYPE_INPUT) { - if(length == sizeof(_keyReport)) { - USB_RecvControl(&_keyReport, length); - return true; - } - } + } + + // Input (set HID report) + else if (setup.wValueH == HID_REPORT_TYPE_INPUT) { + if (length == sizeof(_keyReport)) { + USB_RecvControl(&_keyReport, length); + return true; } + } } + } - return false; + return false; } uint8_t BootKeyboard_::getLeds(void) { - return leds; + return leds; } uint8_t BootKeyboard_::getProtocol(void) { - return protocol; + return protocol; } int BootKeyboard_::sendReport(void) { - return USB_Send(pluggedEndpoint | TRANSFER_RELEASE, &_keyReport, sizeof(_keyReport)); + return USB_Send(pluggedEndpoint | TRANSFER_RELEASE, &_keyReport, sizeof(_keyReport)); } void BootKeyboard_::wakeupHost(void) { - USBDevice.wakeupHost(); + USBDevice.wakeupHost(); } @@ -223,35 +223,35 @@ void BootKeyboard_::wakeupHost(void) { size_t BootKeyboard_::press(uint8_t k) { - uint8_t done = 0; - - if ((k >= HID_KEYBOARD_FIRST_MODIFIER) && (k <= HID_KEYBOARD_LAST_MODIFIER)) { - // it's a modifier key - _keyReport.modifiers |= (0x01 << (k - HID_KEYBOARD_FIRST_MODIFIER)); - } else { - // it's some other key: - // Add k to the key report only if it's not already present - // and if there is an empty slot. - for (uint8_t i = 0; i < sizeof(_keyReport.keycodes); i++) { - if (_keyReport.keycodes[i] != k) { // is k already in list? - if (0 == _keyReport.keycodes[i]) { // have we found an empty slot? - _keyReport.keycodes[i] = k; - done = 1; - break; - } - } else { - done = 1; - break; - } - } - // use separate variable to check if slot was found - // for style reasons - we do not know how the compiler - // handles the for() index when it leaves the loop - if (0 == done) { - return 0; + uint8_t done = 0; + + if ((k >= HID_KEYBOARD_FIRST_MODIFIER) && (k <= HID_KEYBOARD_LAST_MODIFIER)) { + // it's a modifier key + _keyReport.modifiers |= (0x01 << (k - HID_KEYBOARD_FIRST_MODIFIER)); + } else { + // it's some other key: + // Add k to the key report only if it's not already present + // and if there is an empty slot. + for (uint8_t i = 0; i < sizeof(_keyReport.keycodes); i++) { + if (_keyReport.keycodes[i] != k) { // is k already in list? + if (0 == _keyReport.keycodes[i]) { // have we found an empty slot? + _keyReport.keycodes[i] = k; + done = 1; + break; } + } else { + done = 1; + break; + } + } + // use separate variable to check if slot was found + // for style reasons - we do not know how the compiler + // handles the for() index when it leaves the loop + if (0 == done) { + return 0; } - return 1; + } + return 1; } @@ -260,48 +260,48 @@ size_t BootKeyboard_::press(uint8_t k) { // it shouldn't be repeated any more. size_t BootKeyboard_::release(uint8_t k) { - uint8_t i; - uint8_t count; - - if ((k >= HID_KEYBOARD_FIRST_MODIFIER) && (k <= HID_KEYBOARD_LAST_MODIFIER)) { - // it's a modifier key - _keyReport.modifiers = _keyReport.modifiers & (~(0x01 << (k - HID_KEYBOARD_LAST_MODIFIER))); - } else { - // it's some other key: - // 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 < sizeof(_keyReport.keycodes); i++) { - if (_keyReport.keycodes[i] == k) { - _keyReport.keycodes[i] = 0; - } - } + uint8_t i; + uint8_t count; + + if ((k >= HID_KEYBOARD_FIRST_MODIFIER) && (k <= HID_KEYBOARD_LAST_MODIFIER)) { + // it's a modifier key + _keyReport.modifiers = _keyReport.modifiers & (~(0x01 << (k - HID_KEYBOARD_LAST_MODIFIER))); + } else { + // it's some other key: + // 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 < sizeof(_keyReport.keycodes); i++) { + if (_keyReport.keycodes[i] == k) { + _keyReport.keycodes[i] = 0; + } + } - // finally rearrange the keys list so that the free (= 0x00) are at the - // end of the keys list - some implementations stop for keys at the - // first occurence of an 0x00 in the keys list - // so (0x00)(0x01)(0x00)(0x03)(0x02)(0x00) becomes - // (0x01)(0x03)(0x02)(0x00)(0x00)(0x00) - count = 0; // holds the number of zeros we've found - i = 0; - while ((i + count) < sizeof(_keyReport.keycodes)) { - if (0 == _keyReport.keycodes[i]) { - count++; // one more zero - for (uint8_t j = i; j < sizeof(_keyReport.keycodes)-count; j++) { - _keyReport.keycodes[j] = _keyReport.keycodes[j+1]; - } - _keyReport.keycodes[sizeof(_keyReport.keycodes)-count] = 0; - } else { - i++; // one more non-zero - } + // finally rearrange the keys list so that the free (= 0x00) are at the + // end of the keys list - some implementations stop for keys at the + // first occurence of an 0x00 in the keys list + // so (0x00)(0x01)(0x00)(0x03)(0x02)(0x00) becomes + // (0x01)(0x03)(0x02)(0x00)(0x00)(0x00) + count = 0; // holds the number of zeros we've found + i = 0; + while ((i + count) < sizeof(_keyReport.keycodes)) { + if (0 == _keyReport.keycodes[i]) { + count++; // one more zero + for (uint8_t j = i; j < sizeof(_keyReport.keycodes)-count; j++) { + _keyReport.keycodes[j] = _keyReport.keycodes[j+1]; } + _keyReport.keycodes[sizeof(_keyReport.keycodes)-count] = 0; + } else { + i++; // one more non-zero + } } + } - return 1; + return 1; } void BootKeyboard_::releaseAll(void) { - memset(&_keyReport.keys, 0x00, sizeof(_keyReport.keys)); + memset(&_keyReport.keys, 0x00, sizeof(_keyReport.keys)); } BootKeyboard_ BootKeyboard; diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index 80f80e69a1..ad3105542e 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -32,75 +32,75 @@ THE SOFTWARE. #include "HIDAliases.h" typedef union { - // Low level key report: up to 6 keys and shift, ctrl etc at once - struct { - uint8_t modifiers; - uint8_t reserved; - uint8_t keycodes[6]; - }; - uint8_t keys[8]; + // Low level key report: up to 6 keys and shift, ctrl etc at once + struct { + uint8_t modifiers; + uint8_t reserved; + uint8_t keycodes[6]; + }; + uint8_t keys[8]; } HID_BootKeyboardReport_Data_t; class BootKeyboard_ : public PluggableUSBModule { - public: - BootKeyboard_(void); - size_t press(uint8_t); - void begin(void); - void end(void); - size_t release(uint8_t); - void releaseAll(void); + public: + BootKeyboard_(void); + size_t press(uint8_t); + void begin(void); + void end(void); + size_t release(uint8_t); + void releaseAll(void); - int sendReport(void); + int sendReport(void); - uint8_t getLeds(void); - uint8_t getProtocol(void); - void wakeupHost(void); + uint8_t getLeds(void); + uint8_t getProtocol(void); + void wakeupHost(void); - void setFeatureReport(void* report, int length) { - if(length > 0) { - featureReport = (uint8_t*)report; - featureLength = length; + void setFeatureReport(void* report, int length) { + if (length > 0) { + featureReport = (uint8_t*)report; + featureLength = length; - // Disable feature report by default - disableFeatureReport(); - } + // Disable feature report by default + disableFeatureReport(); } + } - int availableFeatureReport(void) { - if(featureLength < 0) { - return featureLength & ~0x8000; - } - return 0; + int availableFeatureReport(void) { + if (featureLength < 0) { + return featureLength & ~0x8000; } + return 0; + } - void enableFeatureReport(void) { - featureLength &= ~0x8000; - } + void enableFeatureReport(void) { + featureLength &= ~0x8000; + } - void disableFeatureReport(void) { - featureLength |= 0x8000; - } + void disableFeatureReport(void) { + featureLength |= 0x8000; + } - protected: - HID_BootKeyboardReport_Data_t _keyReport; + protected: + HID_BootKeyboardReport_Data_t _keyReport; - // Implementation of the PUSBListNode - int getInterface(uint8_t* interfaceCount); - int getDescriptor(USBSetup& setup); - bool setup(USBSetup& setup); + // Implementation of the PUSBListNode + int getInterface(uint8_t* interfaceCount); + int getDescriptor(USBSetup& setup); + bool setup(USBSetup& setup); - uint8_t epType[1]; - uint8_t protocol; - uint8_t idle; + uint8_t epType[1]; + uint8_t protocol; + uint8_t idle; - uint8_t leds; + uint8_t leds; - uint8_t* featureReport; - int featureLength; + uint8_t* featureReport; + int featureLength; }; extern BootKeyboard_ BootKeyboard; diff --git a/plugins/KeyboardioHID/src/LEDs.h b/plugins/KeyboardioHID/src/LEDs.h index ccdef1f4af..8381003082 100644 --- a/plugins/KeyboardioHID/src/LEDs.h +++ b/plugins/KeyboardioHID/src/LEDs.h @@ -2,13 +2,13 @@ // Keyboard Leds enum KeyboardLeds : uint8_t { - LED_NUM_LOCK = (1 << 0), - LED_CAPS_LOCK = (1 << 1), - LED_SCROLL_LOCK = (1 << 2), - LED_COMPOSE = (1 << 3), - LED_KANA = (1 << 4), - LED_POWER = (1 << 5), - LED_SHIFT = (1 << 6), - LED_DO_NOT_DISTURB = (1 << 7), + LED_NUM_LOCK = (1 << 0), + LED_CAPS_LOCK = (1 << 1), + LED_SCROLL_LOCK = (1 << 2), + LED_COMPOSE = (1 << 3), + LED_KANA = (1 << 4), + LED_POWER = (1 << 5), + LED_SHIFT = (1 << 6), + LED_DO_NOT_DISTURB = (1 << 7), }; diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp index e5a31256a8..6ce839a4c6 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp @@ -25,127 +25,127 @@ THE SOFTWARE. #include "DescriptorPrimitives.h" static const uint8_t _hidMultiReportDescriptorAbsoluteMouse[] PROGMEM = { - /* Mouse absolute */ - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) 54 */ - D_USAGE, D_USAGE_MOUSE, /* USAGE (Mouse) */ - D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ - D_REPORT_ID, HID_REPORTID_MOUSE_ABSOLUTE, /* REPORT_ID */ - - /* 8 Buttons */ - D_USAGE_PAGE, D_PAGE_BUTTON, /* USAGE_PAGE (Button) */ - D_USAGE_MINIMUM, 0x01, /* USAGE_MINIMUM (Button 1) */ - D_USAGE_MAXIMUM, 0x08, /* USAGE_MAXIMUM (Button 8) */ - D_LOGICAL_MINIMUM, 0x00, /* LOGICAL_MINIMUM (0) */ - D_LOGICAL_MAXIMUM, 0x01, /* LOGICAL_MAXIMUM (1) */ - D_REPORT_COUNT, 0x08, /* REPORT_COUNT (8) */ - D_REPORT_SIZE, 0x01, /* REPORT_SIZE (1) */ - D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), - - /* X, Y */ - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ - D_USAGE, 0x30, /* USAGE (X) */ - D_USAGE, 0x31, /* USAGE (Y) */ - D_MULTIBYTE(D_LOGICAL_MINIMUM), 0x00, 0x00, /* Logical Minimum (0) */ - D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xFF, 0x7f, /* Logical Maximum (32767) */ - D_REPORT_SIZE, 0x10, /* Report Size (16), */ - D_REPORT_COUNT, 0x02, /* Report Count (2), */ - D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), /* Input (Data, Variable, Absolute) */ - - /* Wheel */ - D_USAGE, 0x38, /* USAGE (Wheel) */ - D_LOGICAL_MINIMUM, 0x81, /* LOGICAL_MINIMUM (-127) */ - D_LOGICAL_MAXIMUM, 0x7f, /* LOGICAL_MAXIMUM (127) */ - D_REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ - D_REPORT_COUNT, 0x01, /* REPORT_COUNT (1) */ - D_INPUT, (D_DATA|D_VARIABLE|D_RELATIVE), - - /* End */ - D_END_COLLECTION + /* Mouse absolute */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) 54 */ + D_USAGE, D_USAGE_MOUSE, /* USAGE (Mouse) */ + D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ + D_REPORT_ID, HID_REPORTID_MOUSE_ABSOLUTE, /* REPORT_ID */ + + /* 8 Buttons */ + D_USAGE_PAGE, D_PAGE_BUTTON, /* USAGE_PAGE (Button) */ + D_USAGE_MINIMUM, 0x01, /* USAGE_MINIMUM (Button 1) */ + D_USAGE_MAXIMUM, 0x08, /* USAGE_MAXIMUM (Button 8) */ + D_LOGICAL_MINIMUM, 0x00, /* LOGICAL_MINIMUM (0) */ + D_LOGICAL_MAXIMUM, 0x01, /* LOGICAL_MAXIMUM (1) */ + D_REPORT_COUNT, 0x08, /* REPORT_COUNT (8) */ + D_REPORT_SIZE, 0x01, /* REPORT_SIZE (1) */ + D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), + + /* X, Y */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ + D_USAGE, 0x30, /* USAGE (X) */ + D_USAGE, 0x31, /* USAGE (Y) */ + D_MULTIBYTE(D_LOGICAL_MINIMUM), 0x00, 0x00, /* Logical Minimum (0) */ + D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xFF, 0x7f, /* Logical Maximum (32767) */ + D_REPORT_SIZE, 0x10, /* Report Size (16), */ + D_REPORT_COUNT, 0x02, /* Report Count (2), */ + D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), /* Input (Data, Variable, Absolute) */ + + /* Wheel */ + D_USAGE, 0x38, /* USAGE (Wheel) */ + D_LOGICAL_MINIMUM, 0x81, /* LOGICAL_MINIMUM (-127) */ + D_LOGICAL_MAXIMUM, 0x7f, /* LOGICAL_MAXIMUM (127) */ + D_REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ + D_REPORT_COUNT, 0x01, /* REPORT_COUNT (1) */ + D_INPUT, (D_DATA|D_VARIABLE|D_RELATIVE), + + /* End */ + D_END_COLLECTION }; AbsoluteMouse_::AbsoluteMouse_(void) { - static HIDSubDescriptor node(_hidMultiReportDescriptorAbsoluteMouse, sizeof(_hidMultiReportDescriptorAbsoluteMouse)); - HID().AppendDescriptor(&node); + static HIDSubDescriptor node(_hidMultiReportDescriptorAbsoluteMouse, sizeof(_hidMultiReportDescriptorAbsoluteMouse)); + HID().AppendDescriptor(&node); } void AbsoluteMouse_::SendReport(void* data, int length) { - HID().SendReport(HID_REPORTID_MOUSE_ABSOLUTE, data, length); + HID().SendReport(HID_REPORTID_MOUSE_ABSOLUTE, data, length); } void AbsoluteMouse_::buttons(uint8_t b) { - if (b != _buttons) { - _buttons = b; - moveTo(xAxis, yAxis, 0); - } + if (b != _buttons) { + _buttons = b; + moveTo(xAxis, yAxis, 0); + } } int16_t AbsoluteMouse_::qadd16(int16_t base, int16_t increment) { - // Separate between subtracting and adding - if (increment < 0) { - // Subtracting more would cause an undefined overflow - if ((int16_t)0x8000 - increment > base) - base = 0x8000; - else - base += increment; - } else { - // Adding more would cause an undefined overflow - if ((int16_t)0x7FFF - increment < base) - base = 0x7FFF; - else - base += increment; - } - return base; + // Separate between subtracting and adding + if (increment < 0) { + // Subtracting more would cause an undefined overflow + if ((int16_t)0x8000 - increment > base) + base = 0x8000; + else + base += increment; + } else { + // Adding more would cause an undefined overflow + if ((int16_t)0x7FFF - increment < base) + base = 0x7FFF; + else + base += increment; + } + return base; } void AbsoluteMouse_::begin(void) { - // release all buttons - end(); + // release all buttons + end(); } void AbsoluteMouse_::end(void) { - _buttons = 0; - moveTo(xAxis, yAxis, 0); + _buttons = 0; + moveTo(xAxis, yAxis, 0); } void AbsoluteMouse_::click(uint8_t b) { - _buttons = b; - moveTo(xAxis, yAxis, 0); - _buttons = 0; - moveTo(xAxis, yAxis, 0); + _buttons = b; + moveTo(xAxis, yAxis, 0); + _buttons = 0; + moveTo(xAxis, yAxis, 0); } void AbsoluteMouse_::moveTo(uint16_t x, uint16_t y, signed char wheel) { - xAxis = x; - yAxis = y; - HID_MouseAbsoluteReport_Data_t report; - report.buttons = _buttons; - report.xAxis = x; - report.yAxis = y; - report.wheel = wheel; - SendReport(&report, sizeof(report)); + xAxis = x; + yAxis = y; + HID_MouseAbsoluteReport_Data_t report; + report.buttons = _buttons; + report.xAxis = x; + report.yAxis = y; + report.wheel = wheel; + SendReport(&report, sizeof(report)); } void AbsoluteMouse_::move(int x, int y, signed char wheel) { - moveTo(qadd16(xAxis, x), qadd16(yAxis, y), wheel); + moveTo(qadd16(xAxis, x), qadd16(yAxis, y), wheel); } void AbsoluteMouse_::press(uint8_t b) { - // press LEFT by default - buttons(_buttons | b); + // press LEFT by default + buttons(_buttons | b); } void AbsoluteMouse_::release(uint8_t b) { - // release LEFT by default - buttons(_buttons & ~b); + // release LEFT by default + buttons(_buttons & ~b); } bool AbsoluteMouse_::isPressed(uint8_t b) { - // check LEFT by default - if ((b & _buttons) > 0) - return true; - return false; + // check LEFT by default + if ((b & _buttons) > 0) + return true; + return false; } diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h index 6dbbc97f6d..66b015d43e 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h @@ -31,38 +31,38 @@ THE SOFTWARE. #include "MouseButtons.h" typedef union { - // Absolute mouse report: 8 buttons, 2 absolute axis, wheel - struct { - uint8_t buttons; - uint16_t xAxis; - uint16_t yAxis; - int8_t wheel; - }; -} HID_MouseAbsoluteReport_Data_t; - -class AbsoluteMouse_ { - public: - AbsoluteMouse_(void); - void begin(void); - void end(void); - - void click(uint8_t b = MOUSE_LEFT); - void moveTo(uint16_t x, uint16_t y, signed char wheel = 0); - void move(int x, int y, signed char wheel = 0); - void press(uint8_t b = MOUSE_LEFT); - void release(uint8_t b = MOUSE_LEFT); - bool isPressed(uint8_t b = MOUSE_LEFT); - - // Sending is public in the base class for advanced users. - void SendReport(void* data, int length); - - protected: + // Absolute mouse report: 8 buttons, 2 absolute axis, wheel + struct { + uint8_t buttons; uint16_t xAxis; uint16_t yAxis; - uint8_t _buttons; - void buttons(uint8_t b); + int8_t wheel; + }; +} HID_MouseAbsoluteReport_Data_t; - int16_t qadd16(int16_t base, int16_t increment); +class AbsoluteMouse_ { + public: + AbsoluteMouse_(void); + void begin(void); + void end(void); + + void click(uint8_t b = MOUSE_LEFT); + void moveTo(uint16_t x, uint16_t y, signed char wheel = 0); + void move(int x, int y, signed char wheel = 0); + void press(uint8_t b = MOUSE_LEFT); + void release(uint8_t b = MOUSE_LEFT); + bool isPressed(uint8_t b = MOUSE_LEFT); + + // Sending is public in the base class for advanced users. + void SendReport(void* data, int length); + + protected: + uint16_t xAxis; + uint16_t yAxis; + uint8_t _buttons; + void buttons(uint8_t b); + + int16_t qadd16(int16_t base, int16_t increment); diff --git a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp index 3b75992388..fe0829b502 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp @@ -25,70 +25,70 @@ THE SOFTWARE. #include "DescriptorPrimitives.h" static const uint8_t _hidMultiReportDescriptorConsumer[] PROGMEM = { - /* Consumer Control (Sound/Media keys) */ - D_USAGE_PAGE, 0x0C, /* usage page (consumer device) */ - D_USAGE, 0x01, /* usage -- consumer control */ - D_COLLECTION, D_APPLICATION, /* collection (application) */ - D_REPORT_ID, HID_REPORTID_CONSUMERCONTROL, /* report id */ - /* 4 Media Keys */ - D_LOGICAL_MINIMUM, 0x00, /* logical minimum */ - D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xFF, 0x03, /* logical maximum (3ff) */ - D_USAGE_MINIMUM, 0x00, /* usage minimum (0) */ - D_MULTIBYTE(D_USAGE_MAXIMUM), 0xFF, 0x03, /* usage maximum (3ff) */ - D_REPORT_COUNT, 0x04, /* report count (4) */ - D_REPORT_SIZE, 0x10, /* report size (16) */ - D_INPUT, 0x00, /* input */ - D_END_COLLECTION /* end collection */ + /* Consumer Control (Sound/Media keys) */ + D_USAGE_PAGE, 0x0C, /* usage page (consumer device) */ + D_USAGE, 0x01, /* usage -- consumer control */ + D_COLLECTION, D_APPLICATION, /* collection (application) */ + D_REPORT_ID, HID_REPORTID_CONSUMERCONTROL, /* report id */ + /* 4 Media Keys */ + D_LOGICAL_MINIMUM, 0x00, /* logical minimum */ + D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xFF, 0x03, /* logical maximum (3ff) */ + D_USAGE_MINIMUM, 0x00, /* usage minimum (0) */ + D_MULTIBYTE(D_USAGE_MAXIMUM), 0xFF, 0x03, /* usage maximum (3ff) */ + D_REPORT_COUNT, 0x04, /* report count (4) */ + D_REPORT_SIZE, 0x10, /* report size (16) */ + D_INPUT, 0x00, /* input */ + D_END_COLLECTION /* end collection */ }; ConsumerControl_::ConsumerControl_(void) { - static HIDSubDescriptor node(_hidMultiReportDescriptorConsumer, sizeof(_hidMultiReportDescriptorConsumer)); - HID().AppendDescriptor(&node); + static HIDSubDescriptor node(_hidMultiReportDescriptorConsumer, sizeof(_hidMultiReportDescriptorConsumer)); + HID().AppendDescriptor(&node); } void ConsumerControl_::begin(void) { - // release all buttons - end(); + // release all buttons + end(); } void ConsumerControl_::end(void) { - memset(&_report, 0, sizeof(_report)); - SendReport(&_report, sizeof(_report)); + memset(&_report, 0, sizeof(_report)); + SendReport(&_report, sizeof(_report)); } void ConsumerControl_::write(uint16_t m) { - press(m); - release(m); + press(m); + release(m); } void ConsumerControl_::press(uint16_t m) { - // search for a free spot - for (uint8_t i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { - if (_report.keys[i] == 0x00) { - _report.keys[i] = m; - break; - } + // search for a free spot + for (uint8_t i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { + if (_report.keys[i] == 0x00) { + _report.keys[i] = m; + break; } - SendReport(&_report, sizeof(_report)); + } + SendReport(&_report, sizeof(_report)); } void ConsumerControl_::release(uint16_t m) { - // search and release the keypress - for (uint8_t i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { - if (_report.keys[i] == m) { - _report.keys[i] = 0x00; - // no break to delete multiple keys - } + // search and release the keypress + for (uint8_t i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { + if (_report.keys[i] == m) { + _report.keys[i] = 0x00; + // no break to delete multiple keys } - SendReport(&_report, sizeof(_report)); + } + SendReport(&_report, sizeof(_report)); } void ConsumerControl_::releaseAll(void) { - end(); + end(); } void ConsumerControl_::SendReport(void* data, int length) { - HID().SendReport(HID_REPORTID_CONSUMERCONTROL, data, length); + HID().SendReport(HID_REPORTID_CONSUMERCONTROL, data, length); } ConsumerControl_ ConsumerControl; diff --git a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h index c598334104..b11d036223 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h +++ b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h @@ -30,32 +30,32 @@ THE SOFTWARE. #include "HID-Settings.h" typedef union { - // Every usable Consumer key possible, up to 4 keys presses possible - uint16_t keys[4]; - struct { - uint16_t key1; - uint16_t key2; - uint16_t key3; - uint16_t key4; - }; + // Every usable Consumer key possible, up to 4 keys presses possible + uint16_t keys[4]; + struct { + uint16_t key1; + uint16_t key2; + uint16_t key3; + uint16_t key4; + }; } HID_ConsumerControlReport_Data_t; class ConsumerControl_ { - public: - ConsumerControl_(void); - void begin(void); - void end(void); - void write(uint16_t m); - void press(uint16_t m); - void release(uint16_t m); - void releaseAll(void); + public: + ConsumerControl_(void); + void begin(void); + void end(void); + void write(uint16_t m); + void press(uint16_t m); + void release(uint16_t m); + void releaseAll(void); - // Sending is public in the base class for advanced users. - void SendReport(void* data, int length); + // Sending is public in the base class for advanced users. + void SendReport(void* data, int length); - protected: - HID_ConsumerControlReport_Data_t _report; + protected: + HID_ConsumerControlReport_Data_t _report; }; extern ConsumerControl_ ConsumerControl; diff --git a/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp b/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp index 2f9d5a2c50..3762d87dd9 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp @@ -25,136 +25,136 @@ THE SOFTWARE. #include "DescriptorPrimitives.h" static const uint8_t _hidMultiReportDescriptorGamepad[] PROGMEM = { - /* Gamepad with 32 buttons and 6 axis*/ - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ - D_USAGE, D_USAGE_JOYSTICK, /* USAGE (Joystick) */ - D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ - D_REPORT_ID, HID_REPORTID_GAMEPAD, /* REPORT_ID */ - /* 32 Buttons */ - D_USAGE_PAGE, D_PAGE_BUTTON, /* USAGE_PAGE (Button) */ - D_USAGE_MINIMUM, 0x01, /* USAGE_MINIMUM (Button 1) */ - D_USAGE_MAXIMUM, 0x20, /* USAGE_MAXIMUM (Button 32) */ - D_LOGICAL_MINIMUM, 0x00, /* _LOGICAL_MINIMUM (0) */ - D_LOGICAL_MAXIMUM, 0x01, /* _LOGICAL_MAXIMUM (1) */ - D_REPORT_SIZE, 0x01, /* REPORT_SIZE (1) */ - D_REPORT_COUNT, 0x20, /* REPORT_COUNT (32) */ - D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ - /* 4 16bit Axis */ - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ - D_COLLECTION, D_PHYSICAL, /* COLLECTION (Physical) */ - D_USAGE, 0x30, /* USAGE (X) */ - D_USAGE, 0x31, /* USAGE (Y) */ - D_USAGE, 0x33, /* USAGE (Rx) */ - D_USAGE, 0x34, /* USAGE (Ry) */ - D_MULTIBYTE(D_LOGICAL_MINIMUM), 0x00, 0x80, /* _LOGICAL_MINIMUM (-32768) */ - D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xFF, 0x7F, /* _LOGICAL_MAXIMUM (32767) */ - D_REPORT_SIZE, 0x10, /* REPORT_SIZE (16) */ - D_REPORT_COUNT, 0x04, /* REPORT_COUNT (4) */ - D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ - /* 2 8bit Axis */ - D_USAGE, 0x32, /* USAGE (Z) */ - D_USAGE, 0x35, /* USAGE (Rz) */ - D_LOGICAL_MINIMUM, 0x80, /* _LOGICAL_MINIMUM (-128) */ - D_LOGICAL_MAXIMUM, 0x7F, /* _LOGICAL_MAXIMUM (127) */ - D_REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ - D_REPORT_COUNT, 0x02, /* REPORT_COUNT (2) */ - D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ - D_END_COLLECTION, /* END_COLLECTION */ - - /* 2 Hat Switches */ - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ - D_USAGE, 0x39, /* USAGE (Hat switch) */ - D_USAGE, 0x39, /* USAGE (Hat switch) */ - D_LOGICAL_MINIMUM, 0x01, /* _LOGICAL_MINIMUM (1) */ - D_LOGICAL_MAXIMUM, 0x08, /* _LOGICAL_MAXIMUM (8) */ - D_REPORT_COUNT, 0x02, /* REPORT_COUNT (2) */ - D_REPORT_SIZE, 0x04, /* REPORT_SIZE (4) */ - D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ - D_END_COLLECTION /* END_COLLECTION */ + /* Gamepad with 32 buttons and 6 axis*/ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ + D_USAGE, D_USAGE_JOYSTICK, /* USAGE (Joystick) */ + D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ + D_REPORT_ID, HID_REPORTID_GAMEPAD, /* REPORT_ID */ + /* 32 Buttons */ + D_USAGE_PAGE, D_PAGE_BUTTON, /* USAGE_PAGE (Button) */ + D_USAGE_MINIMUM, 0x01, /* USAGE_MINIMUM (Button 1) */ + D_USAGE_MAXIMUM, 0x20, /* USAGE_MAXIMUM (Button 32) */ + D_LOGICAL_MINIMUM, 0x00, /* _LOGICAL_MINIMUM (0) */ + D_LOGICAL_MAXIMUM, 0x01, /* _LOGICAL_MAXIMUM (1) */ + D_REPORT_SIZE, 0x01, /* REPORT_SIZE (1) */ + D_REPORT_COUNT, 0x20, /* REPORT_COUNT (32) */ + D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ + /* 4 16bit Axis */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ + D_COLLECTION, D_PHYSICAL, /* COLLECTION (Physical) */ + D_USAGE, 0x30, /* USAGE (X) */ + D_USAGE, 0x31, /* USAGE (Y) */ + D_USAGE, 0x33, /* USAGE (Rx) */ + D_USAGE, 0x34, /* USAGE (Ry) */ + D_MULTIBYTE(D_LOGICAL_MINIMUM), 0x00, 0x80, /* _LOGICAL_MINIMUM (-32768) */ + D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xFF, 0x7F, /* _LOGICAL_MAXIMUM (32767) */ + D_REPORT_SIZE, 0x10, /* REPORT_SIZE (16) */ + D_REPORT_COUNT, 0x04, /* REPORT_COUNT (4) */ + D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ + /* 2 8bit Axis */ + D_USAGE, 0x32, /* USAGE (Z) */ + D_USAGE, 0x35, /* USAGE (Rz) */ + D_LOGICAL_MINIMUM, 0x80, /* _LOGICAL_MINIMUM (-128) */ + D_LOGICAL_MAXIMUM, 0x7F, /* _LOGICAL_MAXIMUM (127) */ + D_REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ + D_REPORT_COUNT, 0x02, /* REPORT_COUNT (2) */ + D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ + D_END_COLLECTION, /* END_COLLECTION */ + + /* 2 Hat Switches */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ + D_USAGE, 0x39, /* USAGE (Hat switch) */ + D_USAGE, 0x39, /* USAGE (Hat switch) */ + D_LOGICAL_MINIMUM, 0x01, /* _LOGICAL_MINIMUM (1) */ + D_LOGICAL_MAXIMUM, 0x08, /* _LOGICAL_MAXIMUM (8) */ + D_REPORT_COUNT, 0x02, /* REPORT_COUNT (2) */ + D_REPORT_SIZE, 0x04, /* REPORT_SIZE (4) */ + D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ + D_END_COLLECTION /* END_COLLECTION */ }; Gamepad_::Gamepad_(void) { - static HIDSubDescriptor node(_hidMultiReportDescriptorGamepad, sizeof(_hidMultiReportDescriptorGamepad)); - HID().AppendDescriptor(&node); + static HIDSubDescriptor node(_hidMultiReportDescriptorGamepad, sizeof(_hidMultiReportDescriptorGamepad)); + HID().AppendDescriptor(&node); } void Gamepad_::begin(void) { - // release all buttons - end(); + // release all buttons + end(); } void Gamepad_::end(void) { - memset(&_report, 0x00, sizeof(_report)); - SendReport(&_report, sizeof(_report)); + memset(&_report, 0x00, sizeof(_report)); + SendReport(&_report, sizeof(_report)); } void Gamepad_::write(void) { - SendReport(&_report, sizeof(_report)); + SendReport(&_report, sizeof(_report)); } void Gamepad_::press(uint8_t b) { - _report.buttons |= (uint32_t)1 << (b - 1); + _report.buttons |= (uint32_t)1 << (b - 1); } void Gamepad_::release(uint8_t b) { - _report.buttons &= ~((uint32_t)1 << (b - 1)); + _report.buttons &= ~((uint32_t)1 << (b - 1)); } void Gamepad_::releaseAll(void) { - memset(&_report, 0x00, sizeof(_report)); + memset(&_report, 0x00, sizeof(_report)); } void Gamepad_::buttons(uint32_t b) { - _report.buttons = b; + _report.buttons = b; } void Gamepad_::xAxis(int16_t a) { - _report.xAxis = a; + _report.xAxis = a; } void Gamepad_::yAxis(int16_t a) { - _report.yAxis = a; + _report.yAxis = a; } void Gamepad_::zAxis(int8_t a) { - _report.zAxis = a; + _report.zAxis = a; } void Gamepad_::rxAxis(int16_t a) { - _report.rxAxis = a; + _report.rxAxis = a; } void Gamepad_::ryAxis(int16_t a) { - _report.ryAxis = a; + _report.ryAxis = a; } void Gamepad_::rzAxis(int8_t a) { - _report.rzAxis = a; + _report.rzAxis = a; } void Gamepad_::dPad1(int8_t d) { - _report.dPad1 = d; + _report.dPad1 = d; } void Gamepad_::dPad2(int8_t d) { - _report.dPad2 = d; + _report.dPad2 = d; } void Gamepad_::SendReport(void* data, int length) { - HID().SendReport(HID_REPORTID_GAMEPAD, data, length); + HID().SendReport(HID_REPORTID_GAMEPAD, data, length); } Gamepad_ Gamepad; diff --git a/plugins/KeyboardioHID/src/MultiReport/Gamepad.h b/plugins/KeyboardioHID/src/MultiReport/Gamepad.h index ae3ab2bf8c..7aaa385088 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Gamepad.h +++ b/plugins/KeyboardioHID/src/MultiReport/Gamepad.h @@ -42,84 +42,84 @@ THE SOFTWARE. typedef union { - // 32 Buttons, 6 Axis, 2 D-Pads - uint32_t buttons; - - struct { - uint8_t button1 : 1; - uint8_t button2 : 1; - uint8_t button3 : 1; - uint8_t button4 : 1; - uint8_t button5 : 1; - uint8_t button6 : 1; - uint8_t button7 : 1; - uint8_t button8 : 1; - - uint8_t button9 : 1; - uint8_t button10 : 1; - uint8_t button11 : 1; - uint8_t button12 : 1; - uint8_t button13 : 1; - uint8_t button14 : 1; - uint8_t button15 : 1; - uint8_t button16 : 1; - - uint8_t button17 : 1; - uint8_t button18 : 1; - uint8_t button19 : 1; - uint8_t button20 : 1; - uint8_t button21 : 1; - uint8_t button22 : 1; - uint8_t button23 : 1; - uint8_t button24 : 1; - - uint8_t button25 : 1; - uint8_t button26 : 1; - uint8_t button27 : 1; - uint8_t button28 : 1; - uint8_t button29 : 1; - uint8_t button30 : 1; - uint8_t button31 : 1; - uint8_t button32 : 1; - - int16_t xAxis; - int16_t yAxis; - - int16_t rxAxis; - int16_t ryAxis; - - int8_t zAxis; - int8_t rzAxis; - - uint8_t dPad1 : 4; - uint8_t dPad2 : 4; - }; + // 32 Buttons, 6 Axis, 2 D-Pads + uint32_t buttons; + + struct { + uint8_t button1 : 1; + uint8_t button2 : 1; + uint8_t button3 : 1; + uint8_t button4 : 1; + uint8_t button5 : 1; + uint8_t button6 : 1; + uint8_t button7 : 1; + uint8_t button8 : 1; + + uint8_t button9 : 1; + uint8_t button10 : 1; + uint8_t button11 : 1; + uint8_t button12 : 1; + uint8_t button13 : 1; + uint8_t button14 : 1; + uint8_t button15 : 1; + uint8_t button16 : 1; + + uint8_t button17 : 1; + uint8_t button18 : 1; + uint8_t button19 : 1; + uint8_t button20 : 1; + uint8_t button21 : 1; + uint8_t button22 : 1; + uint8_t button23 : 1; + uint8_t button24 : 1; + + uint8_t button25 : 1; + uint8_t button26 : 1; + uint8_t button27 : 1; + uint8_t button28 : 1; + uint8_t button29 : 1; + uint8_t button30 : 1; + uint8_t button31 : 1; + uint8_t button32 : 1; + + int16_t xAxis; + int16_t yAxis; + + int16_t rxAxis; + int16_t ryAxis; + + int8_t zAxis; + int8_t rzAxis; + + uint8_t dPad1 : 4; + uint8_t dPad2 : 4; + }; } HID_GamepadReport_Data_t; class Gamepad_ { - public: - Gamepad_(void); - - void begin(void); - void end(void); - void write(void); - void press(uint8_t b); - void release(uint8_t b); - void releaseAll(void); - - void buttons(uint32_t b); - void xAxis(int16_t a); - void yAxis(int16_t a); - void zAxis(int8_t a); - void rxAxis(int16_t a); - void ryAxis(int16_t a); - void rzAxis(int8_t a); - void dPad1(int8_t d); - void dPad2(int8_t d); - - void SendReport(void* data, int length); - protected: - HID_GamepadReport_Data_t _report; + public: + Gamepad_(void); + + void begin(void); + void end(void); + void write(void); + void press(uint8_t b); + void release(uint8_t b); + void releaseAll(void); + + void buttons(uint32_t b); + void xAxis(int16_t a); + void yAxis(int16_t a); + void zAxis(int8_t a); + void rxAxis(int16_t a); + void ryAxis(int16_t a); + void rzAxis(int8_t a); + void dPad1(int8_t d); + void dPad2(int8_t d); + + void SendReport(void* data, int length); + protected: + HID_GamepadReport_Data_t _report; }; extern Gamepad_ Gamepad; diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index f091d97eb1..e21a97c6ee 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -25,161 +25,161 @@ THE SOFTWARE. #include "DescriptorPrimitives.h" static const uint8_t _hidMultiReportDescriptorKeyboard[] PROGMEM = { - // NKRO Keyboard - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, - D_USAGE, D_USAGE_KEYBOARD, - D_COLLECTION, D_APPLICATION, - D_REPORT_ID, HID_REPORTID_NKRO_KEYBOARD, - D_USAGE_PAGE, D_PAGE_KEYBOARD, - - - /* Key modifier byte */ - D_USAGE_MINIMUM, HID_KEYBOARD_FIRST_MODIFIER, - D_USAGE_MAXIMUM, HID_KEYBOARD_LAST_MODIFIER, - D_LOGICAL_MINIMUM, 0x00, - D_LOGICAL_MAXIMUM, 0x01, - D_REPORT_SIZE, 0x01, - D_REPORT_COUNT, 0x08, - D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), + // NKRO Keyboard + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, + D_USAGE, D_USAGE_KEYBOARD, + D_COLLECTION, D_APPLICATION, + D_REPORT_ID, HID_REPORTID_NKRO_KEYBOARD, + D_USAGE_PAGE, D_PAGE_KEYBOARD, + + + /* Key modifier byte */ + D_USAGE_MINIMUM, HID_KEYBOARD_FIRST_MODIFIER, + D_USAGE_MAXIMUM, HID_KEYBOARD_LAST_MODIFIER, + D_LOGICAL_MINIMUM, 0x00, + D_LOGICAL_MAXIMUM, 0x01, + D_REPORT_SIZE, 0x01, + D_REPORT_COUNT, 0x08, + D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), // USB Code not within 4-49 (0x4-0x31), 51-155 (0x33-0x9B), 157-164 (0x9D-0xA4), // 176-221 (0xB0-0xDD) or 224-231 (0xE0-0xE7) NKRO Mode - /* NKRO Keyboard */ - - // Padding 3 bits - // To skip HID_KEYBOARD_NON_US_POUND_AND_TILDE, which causes - // Linux to choke on our driver. - D_REPORT_SIZE, 0x04, - D_REPORT_COUNT, 0x01, - D_INPUT, (D_CONSTANT), - - - D_USAGE_MINIMUM, HID_KEYBOARD_A_AND_A, - D_USAGE_MAXIMUM, HID_KEYBOARD_BACKSLASH_AND_PIPE, - D_LOGICAL_MINIMUM, 0x00, - D_LOGICAL_MAXIMUM, 0x01, - D_REPORT_SIZE, 0x01, - D_REPORT_COUNT, (HID_KEYBOARD_BACKSLASH_AND_PIPE - HID_KEYBOARD_A_AND_A)+1, - D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), - - // Padding 1 bit. - // To skip HID_KEYBOARD_NON_US_POUND_AND_TILDE, which causes - // Linux to choke on our driver. - D_REPORT_SIZE, 0x01, - D_REPORT_COUNT, 0x01, - D_INPUT, (D_CONSTANT), - - - D_USAGE_MINIMUM, HID_KEYBOARD_SEMICOLON_AND_COLON, - D_USAGE_MAXIMUM, HID_KEYBOARD_CANCEL, - D_LOGICAL_MINIMUM, 0x00, - D_LOGICAL_MAXIMUM, 0x01, - D_REPORT_SIZE, 0x01, - D_REPORT_COUNT, (HID_KEYBOARD_CANCEL-HID_KEYBOARD_SEMICOLON_AND_COLON) +1, - D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), - - - // Padding 1 bit. - // To skip HID_KEYBOARD_CLEAR, which causes - // Linux to choke on our driver. - D_REPORT_SIZE, 0x01, - D_REPORT_COUNT, 0x01, - D_INPUT, (D_CONSTANT), - - D_USAGE_MINIMUM, HID_KEYBOARD_PRIOR, - D_USAGE_MAXIMUM, HID_KEYPAD_HEXADECIMAL, - D_LOGICAL_MINIMUM, 0x00, - D_LOGICAL_MAXIMUM, 0x01, - D_REPORT_SIZE, 0x01, - D_REPORT_COUNT, (HID_KEYPAD_HEXADECIMAL - HID_KEYBOARD_PRIOR ) +1, - D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), - - - // Padding (w bits) - D_REPORT_SIZE, 0x02, - D_REPORT_COUNT, 0x01, - D_INPUT, (D_CONSTANT), - - D_END_COLLECTION, + /* NKRO Keyboard */ + + // Padding 3 bits + // To skip HID_KEYBOARD_NON_US_POUND_AND_TILDE, which causes + // Linux to choke on our driver. + D_REPORT_SIZE, 0x04, + D_REPORT_COUNT, 0x01, + D_INPUT, (D_CONSTANT), + + + D_USAGE_MINIMUM, HID_KEYBOARD_A_AND_A, + D_USAGE_MAXIMUM, HID_KEYBOARD_BACKSLASH_AND_PIPE, + D_LOGICAL_MINIMUM, 0x00, + D_LOGICAL_MAXIMUM, 0x01, + D_REPORT_SIZE, 0x01, + D_REPORT_COUNT, (HID_KEYBOARD_BACKSLASH_AND_PIPE - HID_KEYBOARD_A_AND_A)+1, + D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), + + // Padding 1 bit. + // To skip HID_KEYBOARD_NON_US_POUND_AND_TILDE, which causes + // Linux to choke on our driver. + D_REPORT_SIZE, 0x01, + D_REPORT_COUNT, 0x01, + D_INPUT, (D_CONSTANT), + + + D_USAGE_MINIMUM, HID_KEYBOARD_SEMICOLON_AND_COLON, + D_USAGE_MAXIMUM, HID_KEYBOARD_CANCEL, + D_LOGICAL_MINIMUM, 0x00, + D_LOGICAL_MAXIMUM, 0x01, + D_REPORT_SIZE, 0x01, + D_REPORT_COUNT, (HID_KEYBOARD_CANCEL-HID_KEYBOARD_SEMICOLON_AND_COLON) +1, + D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), + + + // Padding 1 bit. + // To skip HID_KEYBOARD_CLEAR, which causes + // Linux to choke on our driver. + D_REPORT_SIZE, 0x01, + D_REPORT_COUNT, 0x01, + D_INPUT, (D_CONSTANT), + + D_USAGE_MINIMUM, HID_KEYBOARD_PRIOR, + D_USAGE_MAXIMUM, HID_KEYPAD_HEXADECIMAL, + D_LOGICAL_MINIMUM, 0x00, + D_LOGICAL_MAXIMUM, 0x01, + D_REPORT_SIZE, 0x01, + D_REPORT_COUNT, (HID_KEYPAD_HEXADECIMAL - HID_KEYBOARD_PRIOR) +1, + D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), + + + // Padding (w bits) + D_REPORT_SIZE, 0x02, + D_REPORT_COUNT, 0x01, + D_INPUT, (D_CONSTANT), + + D_END_COLLECTION, }; Keyboard_::Keyboard_(void) { - static HIDSubDescriptor node(_hidMultiReportDescriptorKeyboard, sizeof(_hidMultiReportDescriptorKeyboard)); - HID().AppendDescriptor(&node); + static HIDSubDescriptor node(_hidMultiReportDescriptorKeyboard, sizeof(_hidMultiReportDescriptorKeyboard)); + HID().AppendDescriptor(&node); } void Keyboard_::begin(void) { - // Force API to send a clean report. - // This is important for and HID bridge where the receiver stays on, - // while the sender is resetted. - releaseAll(); - sendReport(); + // Force API to send a clean report. + // This is important for and HID bridge where the receiver stays on, + // while the sender is resetted. + releaseAll(); + sendReport(); } void Keyboard_::end(void) { - releaseAll(); - sendReport(); + releaseAll(); + sendReport(); } int Keyboard_::sendReport(void) { - return HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &_keyReport, sizeof(_keyReport)); + return HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &_keyReport, sizeof(_keyReport)); } boolean Keyboard_::isModifierActive(uint8_t k) { - if(k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { - k = k - HID_KEYBOARD_FIRST_MODIFIER; - return !!(_keyReport.modifiers & (1 << k)); - } - return false; + if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { + k = k - HID_KEYBOARD_FIRST_MODIFIER; + return !!(_keyReport.modifiers & (1 << k)); + } + return false; } size_t Keyboard_::press(uint8_t k) { - // If the key is in the range of 'printable' keys - if (k <= HID_KEYPAD_HEXADECIMAL ) { - uint8_t bit = 1 << (uint8_t(k) % 8); - _keyReport.keys[k / 8] |= bit; - return 1; - } - - // It's a modifier key - else if(k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { - // Convert key into bitfield (0 - 7) - k = k - HID_KEYBOARD_FIRST_MODIFIER; - _keyReport.modifiers |= (1 << k); - return 1; - } - - // No empty/pressed key was found - return 0; + // If the key is in the range of 'printable' keys + if (k <= HID_KEYPAD_HEXADECIMAL) { + uint8_t bit = 1 << (uint8_t(k) % 8); + _keyReport.keys[k / 8] |= bit; + return 1; + } + + // It's a modifier key + else if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { + // Convert key into bitfield (0 - 7) + k = k - HID_KEYBOARD_FIRST_MODIFIER; + _keyReport.modifiers |= (1 << k); + return 1; + } + + // No empty/pressed key was found + return 0; } size_t Keyboard_::release(uint8_t k) { - // If we're releasing a printable key - if (k <= HID_KEYPAD_HEXADECIMAL) { - uint8_t bit = 1 << (k % 8); - _keyReport.keys[k / 8] &= ~bit; - return 1; - } - - // It's a modifier key - else if(k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { - // Convert key into bitfield (0 - 7) - k = k - HID_KEYBOARD_FIRST_MODIFIER; - _keyReport.modifiers &= ~(1 << k); - return 1; - } - - // No empty/pressed key was found - return 0; + // If we're releasing a printable key + if (k <= HID_KEYPAD_HEXADECIMAL) { + uint8_t bit = 1 << (k % 8); + _keyReport.keys[k / 8] &= ~bit; + return 1; + } + + // It's a modifier key + else if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { + // Convert key into bitfield (0 - 7) + k = k - HID_KEYBOARD_FIRST_MODIFIER; + _keyReport.modifiers &= ~(1 << k); + return 1; + } + + // No empty/pressed key was found + return 0; } void Keyboard_::releaseAll(void) { - // Release all keys - memset(&_keyReport.allkeys, 0x00, sizeof(_keyReport.allkeys)); + // Release all keys + memset(&_keyReport.allkeys, 0x00, sizeof(_keyReport.allkeys)); } Keyboard_ Keyboard; diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h index 7d4091344c..37b6f5dee4 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h @@ -35,31 +35,31 @@ THE SOFTWARE. #define KEY_BYTES 28 typedef union { - // Modifiers + keymap - struct { - uint8_t modifiers; - uint8_t keys[KEY_BYTES ]; - }; - uint8_t allkeys[1 + KEY_BYTES]; + // Modifiers + keymap + struct { + uint8_t modifiers; + uint8_t keys[KEY_BYTES ]; + }; + uint8_t allkeys[1 + KEY_BYTES]; } HID_KeyboardReport_Data_t; class Keyboard_ { - public: - Keyboard_(void); - void begin(void); - void end(void); + public: + Keyboard_(void); + void begin(void); + void end(void); - size_t press(uint8_t k); - size_t release(uint8_t k); - void releaseAll(void); - int sendReport(void); + size_t press(uint8_t k); + size_t release(uint8_t k); + void releaseAll(void); + int sendReport(void); - boolean isModifierActive(uint8_t k); + boolean isModifierActive(uint8_t k); - protected: - HID_KeyboardReport_Data_t _keyReport; + protected: + HID_KeyboardReport_Data_t _keyReport; }; extern Keyboard_ Keyboard; diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp index 4a345742d3..065ce1ea70 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp @@ -25,92 +25,92 @@ THE SOFTWARE. #include "DescriptorPrimitives.h" static const uint8_t _hidMultiReportDescriptorMouse[] PROGMEM = { - /* Mouse relative */ - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) 54 */ - D_USAGE, D_USAGE_MOUSE, /* USAGE (Mouse) */ - D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ - D_REPORT_ID, HID_REPORTID_MOUSE, /* REPORT_ID */ - - /* 8 Buttons */ - D_USAGE_PAGE, D_PAGE_BUTTON, /* USAGE_PAGE (Button) */ - D_USAGE_MINIMUM, 0x01, /* USAGE_MINIMUM (Button 1) */ - D_USAGE_MAXIMUM, 0x08, /* USAGE_MAXIMUM (Button 8) */ - D_LOGICAL_MINIMUM, 0x00, /* LOGICAL_MINIMUM (0) */ - D_LOGICAL_MAXIMUM, 0x01, /* LOGICAL_MAXIMUM (1) */ - D_REPORT_COUNT, 0x08, /* REPORT_COUNT (8) */ - D_REPORT_SIZE, 0x01, /* REPORT_SIZE (1) */ - D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ - - /* X, Y, Wheel */ - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ - D_USAGE, 0x30, /* USAGE (X) */ - D_USAGE, 0x31, /* USAGE (Y) */ - D_USAGE, 0x38, /* USAGE (Wheel) */ - D_LOGICAL_MINIMUM, 0x81, /* LOGICAL_MINIMUM (-127) */ - D_LOGICAL_MAXIMUM, 0x7f, /* LOGICAL_MAXIMUM (127) */ - D_REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ - D_REPORT_COUNT, 0x03, /* REPORT_COUNT (3) */ - D_INPUT, (D_DATA|D_VARIABLE|D_RELATIVE), /* INPUT (Data,Var,Rel) */ - - /* End */ - D_END_COLLECTION /* END_COLLECTION */ + /* Mouse relative */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) 54 */ + D_USAGE, D_USAGE_MOUSE, /* USAGE (Mouse) */ + D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ + D_REPORT_ID, HID_REPORTID_MOUSE, /* REPORT_ID */ + + /* 8 Buttons */ + D_USAGE_PAGE, D_PAGE_BUTTON, /* USAGE_PAGE (Button) */ + D_USAGE_MINIMUM, 0x01, /* USAGE_MINIMUM (Button 1) */ + D_USAGE_MAXIMUM, 0x08, /* USAGE_MAXIMUM (Button 8) */ + D_LOGICAL_MINIMUM, 0x00, /* LOGICAL_MINIMUM (0) */ + D_LOGICAL_MAXIMUM, 0x01, /* LOGICAL_MAXIMUM (1) */ + D_REPORT_COUNT, 0x08, /* REPORT_COUNT (8) */ + D_REPORT_SIZE, 0x01, /* REPORT_SIZE (1) */ + D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ + + /* X, Y, Wheel */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ + D_USAGE, 0x30, /* USAGE (X) */ + D_USAGE, 0x31, /* USAGE (Y) */ + D_USAGE, 0x38, /* USAGE (Wheel) */ + D_LOGICAL_MINIMUM, 0x81, /* LOGICAL_MINIMUM (-127) */ + D_LOGICAL_MAXIMUM, 0x7f, /* LOGICAL_MAXIMUM (127) */ + D_REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ + D_REPORT_COUNT, 0x03, /* REPORT_COUNT (3) */ + D_INPUT, (D_DATA|D_VARIABLE|D_RELATIVE), /* INPUT (Data,Var,Rel) */ + + /* End */ + D_END_COLLECTION /* END_COLLECTION */ }; Mouse_::Mouse_(void) { - static HIDSubDescriptor node(_hidMultiReportDescriptorMouse, sizeof(_hidMultiReportDescriptorMouse)); - HID().AppendDescriptor(&node); + static HIDSubDescriptor node(_hidMultiReportDescriptorMouse, sizeof(_hidMultiReportDescriptorMouse)); + HID().AppendDescriptor(&node); } void Mouse_::begin(void) { - end(); + end(); } void Mouse_::end(void) { - _buttons = 0; - move(0, 0, 0); + _buttons = 0; + move(0, 0, 0); } void Mouse_::click(uint8_t b) { - _buttons = b; - move(0,0,0); - _buttons = 0; - move(0,0,0); + _buttons = b; + move(0,0,0); + _buttons = 0; + move(0,0,0); } void Mouse_::move(signed char x, signed char y, signed char wheel) { - HID_MouseReport_Data_t report; - report.buttons = _buttons; - report.xAxis = x; - report.yAxis = y; - report.wheel = wheel; - SendReport(&report, sizeof(report)); + HID_MouseReport_Data_t report; + report.buttons = _buttons; + report.xAxis = x; + report.yAxis = y; + report.wheel = wheel; + SendReport(&report, sizeof(report)); } void Mouse_::buttons(uint8_t b) { - if (b != _buttons) { - _buttons = b; - move(0,0,0); - } + if (b != _buttons) { + _buttons = b; + move(0,0,0); + } } void Mouse_::press(uint8_t b) { - buttons(_buttons | b); + buttons(_buttons | b); } void Mouse_::release(uint8_t b) { - buttons(_buttons & ~b); + buttons(_buttons & ~b); } bool Mouse_::isPressed(uint8_t b) { - if ((b & _buttons) > 0) - return true; - return false; + if ((b & _buttons) > 0) + return true; + return false; } void Mouse_::SendReport(void* data, int length) { - HID().SendReport(HID_REPORTID_MOUSE, data, length); + HID().SendReport(HID_REPORTID_MOUSE, data, length); } Mouse_ Mouse; diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.h b/plugins/KeyboardioHID/src/MultiReport/Mouse.h index 887bd9eb54..fe25c05a98 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.h @@ -31,31 +31,31 @@ THE SOFTWARE. #include "MouseButtons.h" typedef union { - // Mouse report: 8 buttons, position, wheel - struct { - uint8_t buttons; - int8_t xAxis; - int8_t yAxis; - int8_t wheel; - }; + // Mouse report: 8 buttons, position, wheel + struct { + uint8_t buttons; + int8_t xAxis; + int8_t yAxis; + int8_t wheel; + }; } HID_MouseReport_Data_t; class Mouse_ { - 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 - - void SendReport(void* data, int length); - - protected: - 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 + + void SendReport(void* data, int length); + + protected: + uint8_t _buttons; + void buttons(uint8_t b); }; extern Mouse_ Mouse; diff --git a/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp b/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp index 5f6cf12357..b8b87d40dc 100644 --- a/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp @@ -25,61 +25,61 @@ THE SOFTWARE. #include "DescriptorPrimitives.h" static const uint8_t _hidMultiReportDescriptorSystem[] PROGMEM = { - //TODO limit to system keys only? - /* System Control (Power Down, Sleep, Wakeup, ...) */ - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ - D_USAGE, 0x80, /* USAGE (System Control) */ - D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ - D_REPORT_ID, HID_REPORTID_SYSTEMCONTROL, /* REPORT_ID */ - /* 1 system key */ - D_LOGICAL_MINIMUM, 0x00, /* LOGICAL_MINIMUM (0) */ - D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xff, 0x00, /* LOGICAL_MAXIMUM (255) */ - D_USAGE_MINIMUM, 0x00, /* USAGE_MINIMUM (Undefined) */ - D_USAGE_MAXIMUM, 0xff, /* USAGE_MAXIMUM (System Menu Down) */ - D_REPORT_COUNT, 0x01, /* REPORT_COUNT (1) */ - D_REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ - D_INPUT, (D_DATA|D_ARRAY|D_ABSOLUTE), /* INPUT (Data,Ary,Abs) */ - D_END_COLLECTION /* END_COLLECTION */ + //TODO limit to system keys only? + /* System Control (Power Down, Sleep, Wakeup, ...) */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ + D_USAGE, 0x80, /* USAGE (System Control) */ + D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ + D_REPORT_ID, HID_REPORTID_SYSTEMCONTROL, /* REPORT_ID */ + /* 1 system key */ + D_LOGICAL_MINIMUM, 0x00, /* LOGICAL_MINIMUM (0) */ + D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xff, 0x00, /* LOGICAL_MAXIMUM (255) */ + D_USAGE_MINIMUM, 0x00, /* USAGE_MINIMUM (Undefined) */ + D_USAGE_MAXIMUM, 0xff, /* USAGE_MAXIMUM (System Menu Down) */ + D_REPORT_COUNT, 0x01, /* REPORT_COUNT (1) */ + D_REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ + D_INPUT, (D_DATA|D_ARRAY|D_ABSOLUTE), /* INPUT (Data,Ary,Abs) */ + D_END_COLLECTION /* END_COLLECTION */ }; SystemControl_::SystemControl_(void) { - static HIDSubDescriptor node(_hidMultiReportDescriptorSystem, sizeof(_hidMultiReportDescriptorSystem)); - HID().AppendDescriptor(&node); + static HIDSubDescriptor node(_hidMultiReportDescriptorSystem, sizeof(_hidMultiReportDescriptorSystem)); + HID().AppendDescriptor(&node); } void SystemControl_::begin(void) { - // release all buttons - end(); + // release all buttons + end(); } void SystemControl_::end(void) { - uint8_t _report = 0x00; - SendReport(&_report, sizeof(_report)); + uint8_t _report = 0x00; + SendReport(&_report, sizeof(_report)); } void SystemControl_::write(uint8_t s) { - press(s); - release(); + press(s); + release(); } void SystemControl_::release(void) { - begin(); + begin(); } void SystemControl_::releaseAll(void) { - begin(); + begin(); } void SystemControl_::press(uint8_t s) { - if (s == HID_SYSTEM_WAKE_UP) - USBDevice.wakeupHost(); - else - SendReport(&s, sizeof(s)); + if (s == HID_SYSTEM_WAKE_UP) + USBDevice.wakeupHost(); + else + SendReport(&s, sizeof(s)); } void SystemControl_::SendReport(void* data, int length) { - HID().SendReport(HID_REPORTID_SYSTEMCONTROL, data, length); + HID().SendReport(HID_REPORTID_SYSTEMCONTROL, data, length); } SystemControl_ SystemControl; diff --git a/plugins/KeyboardioHID/src/MultiReport/SystemControl.h b/plugins/KeyboardioHID/src/MultiReport/SystemControl.h index 1bfdb8cd40..95f00c2aff 100644 --- a/plugins/KeyboardioHID/src/MultiReport/SystemControl.h +++ b/plugins/KeyboardioHID/src/MultiReport/SystemControl.h @@ -31,24 +31,24 @@ THE SOFTWARE. #include "HIDTables.h" typedef union { - // Every usable system control key possible - uint8_t key; + // Every usable system control key possible + uint8_t key; } HID_SystemControlReport_Data_t; class SystemControl_ { - public: - void begin(void); - void end(void); - void write(uint8_t s); - void press(uint8_t s); - void release(void); - void releaseAll(void); - void SendReport(void* data, int length); - - SystemControl_(void); - - protected: + public: + void begin(void); + void end(void); + void write(uint8_t s); + void press(uint8_t s); + void release(void); + void releaseAll(void); + void SendReport(void* data, int length); + + SystemControl_(void); + + protected: }; From 0f9a2f79988717728da5bb18744f407c3f5d5a84 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Wed, 26 Jul 2017 13:07:26 -0700 Subject: [PATCH 467/602] Add some guard code in sendReport to stop user code from needlessley sending a zillion empty "all keys released" reports. This _should_ help stop the keyboard from forcing a mac to wake up from sleep. It definitely makes the USB bus a LOT less chatty with a keyboard plugged in --- .../src/MultiReport/Keyboard.cpp | 19 ++++++++++++++++--- .../KeyboardioHID/src/MultiReport/Keyboard.h | 3 +++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index e21a97c6ee..8da9e52e08 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -114,19 +114,32 @@ void Keyboard_::begin(void) { // This is important for and HID bridge where the receiver stays on, // while the sender is resetted. releaseAll(); - sendReport(); + sendReportUnchecked(); } void Keyboard_::end(void) { releaseAll(); - sendReport(); + sendReportUnchecked(); } +int Keyboard_::sendReportUnchecked(void) { + return HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &_keyReport, sizeof(_keyReport)); +} int Keyboard_::sendReport(void) { - return HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &_keyReport, sizeof(_keyReport)); + // If the last report is different than the current report, then we need to send a report. + // We guard sendReport like this so that calling code doesn't end up spamming the host with empty reports + // if sendReport is called in a tight loop. + + if (memcmp(_lastKeyReport.allkeys, _keyReport.allkeys, sizeof(_keyReport))) { + // if the two reports are different, send a report + int returnCode = sendReportUnchecked(); + memcpy(_lastKeyReport.allkeys, _keyReport.allkeys, sizeof(_keyReport)); + return returnCode; + } + return -1; } boolean Keyboard_::isModifierActive(uint8_t k) { diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h index 37b6f5dee4..7468967bd7 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h @@ -60,6 +60,9 @@ class Keyboard_ { protected: HID_KeyboardReport_Data_t _keyReport; + HID_KeyboardReport_Data_t _lastKeyReport; + private: + int sendReportUnchecked(void); }; extern Keyboard_ Keyboard; From d1514a724e5bf160bf766998882ea06fe49bb74d Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Thu, 27 Jul 2017 17:38:25 -0700 Subject: [PATCH 468/602] Lift MouseButtons up one directory as part of a refactoring of the code that uses it --- plugins/KeyboardioHID/src/{MultiReport => }/MouseButtons.h | 0 plugins/KeyboardioHID/src/MultiReport/Mouse.h | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename plugins/KeyboardioHID/src/{MultiReport => }/MouseButtons.h (100%) diff --git a/plugins/KeyboardioHID/src/MultiReport/MouseButtons.h b/plugins/KeyboardioHID/src/MouseButtons.h similarity index 100% rename from plugins/KeyboardioHID/src/MultiReport/MouseButtons.h rename to plugins/KeyboardioHID/src/MouseButtons.h diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.h b/plugins/KeyboardioHID/src/MultiReport/Mouse.h index fe25c05a98..631658b4bc 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.h @@ -28,7 +28,7 @@ THE SOFTWARE. #include "PluggableUSB.h" #include "HID.h" #include "HID-Settings.h" -#include "MouseButtons.h" +#include "../MouseButtons.h" typedef union { // Mouse report: 8 buttons, position, wheel From 398e5c050d1de41701f6c287fb04005cd0b00e25 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Thu, 27 Jul 2017 17:39:00 -0700 Subject: [PATCH 469/602] Extract the brains of AbsoluteMouse to a bit of shared code This mostly undoes a refactoring of Nico's code --- .../src/DeviceAPIs/AbsoluteMouseAPI.h | 102 ++++++++++++++++++ .../src/DeviceAPIs/AbsoluteMouseAPI.hpp | 101 +++++++++++++++++ 2 files changed, 203 insertions(+) create mode 100644 plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h create mode 100644 plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.hpp diff --git a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h new file mode 100644 index 0000000000..e9087e31af --- /dev/null +++ b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h @@ -0,0 +1,102 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 guard +#pragma once + +#include +#include "PluggableUSB.h" +#include "HID.h" +#include "HID-Settings.h" +#include "MouseButtons.h" +#include "DescriptorPrimitives.h" + + +#define DESCRIPTOR_ABS_MOUSE_BUTTONS \ + /* 8 Buttons */ \ + D_USAGE_PAGE, D_PAGE_BUTTON, /* USAGE_PAGE (Button) */ \ + D_USAGE_MINIMUM, 0x01, /* USAGE_MINIMUM (Button 1) */ \ + D_USAGE_MAXIMUM, 0x08, /* USAGE_MAXIMUM (Button 8) */ \ + D_LOGICAL_MINIMUM, 0x00, /* LOGICAL_MINIMUM (0) */ \ + D_LOGICAL_MAXIMUM, 0x01, /* LOGICAL_MAXIMUM (1) */ \ + D_REPORT_COUNT, 0x08, /* REPORT_COUNT (8) */ \ + D_REPORT_SIZE, 0x01, /* REPORT_SIZE (1) */ \ + D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), + +# define DESCRIPTOR_ABS_MOUSE_XY \ + /* X, Y */ \ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ \ + D_USAGE, 0x30, /* USAGE (X) */ \ + D_USAGE, 0x31, /* USAGE (Y) */ \ + D_MULTIBYTE(D_LOGICAL_MINIMUM), 0x00, 0x00, /* Logical Minimum (0) */ \ + D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xFF, 0x7f, /* Logical Maximum (32767) */ \ + D_REPORT_SIZE, 0x10, /* Report Size (16), */ \ + D_REPORT_COUNT, 0x02, /* Report Count (2), */ \ + D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), /* Input (Data, Variable, Absolute) */ + +#define DESCRIPTOR_ABS_MOUSE_WHEEL \ + /* Wheel */ \ + D_USAGE, 0x38, /* USAGE (Wheel) */ \ + D_LOGICAL_MINIMUM, 0x81, /* LOGICAL_MINIMUM (-127) */ \ + D_LOGICAL_MAXIMUM, 0x7f, /* LOGICAL_MAXIMUM (127) */ \ + D_REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ \ + D_REPORT_COUNT, 0x01, /* REPORT_COUNT (1) */ \ + D_INPUT, (D_DATA|D_VARIABLE|D_RELATIVE), + +typedef union { + // Absolute mouse report: 8 buttons, 2 absolute axis, wheel + struct { + uint8_t buttons; + uint16_t xAxis; + uint16_t yAxis; + int8_t wheel; + }; +} HID_MouseAbsoluteReport_Data_t; + +class AbsoluteMouseAPI { + public: + inline AbsoluteMouseAPI(void); + inline void begin(void); + inline void end(void); + + inline void click(uint8_t b = MOUSE_LEFT); + inline void moveTo(uint16_t x, uint16_t y, signed char wheel = 0); + inline void move(int x, int y, signed char wheel = 0); + inline void press(uint8_t b = MOUSE_LEFT); + inline void release(uint8_t b = MOUSE_LEFT); + inline bool isPressed(uint8_t b = MOUSE_LEFT); + + // Sending is public in the base class for advanced users. + virtual void SendReport(void* data, int length); + + protected: + uint16_t xAxis; + uint16_t yAxis; + uint8_t _buttons; + + inline void buttons(uint8_t b); + inline int16_t qadd16(int16_t base, int16_t increment); +}; + +#include "AbsoluteMouseAPI.hpp" + diff --git a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.hpp b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.hpp new file mode 100644 index 0000000000..912fff688e --- /dev/null +++ b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.hpp @@ -0,0 +1,101 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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. +*/ + +#pragma once + +AbsoluteMouseAPI::AbsoluteMouseAPI(void): xAxis(0), yAxis(0), _buttons(0) { // Empty +} + +void AbsoluteMouseAPI::buttons(uint8_t b) { + if (b != _buttons) { + _buttons = b; + moveTo(xAxis, yAxis, 0); + } +} + +int16_t AbsoluteMouseAPI::qadd16(int16_t base, int16_t increment) { + // Separate between subtracting and adding + if (increment < 0) { + // Subtracting more would cause an undefined overflow + if ((int16_t)0x8000 - increment > base) + base = 0x8000; + else + base += increment; + } else { + // Adding more would cause an undefined overflow + if ((int16_t)0x7FFF - increment < base) + base = 0x7FFF; + else + base += increment; + } + return base; +} + +void AbsoluteMouseAPI::begin(void) { + // release all buttons + end(); +} + +void AbsoluteMouseAPI::end(void) { + _buttons = 0; + moveTo(xAxis, yAxis, 0); +} + +void AbsoluteMouseAPI::click(uint8_t b) { + _buttons = b; + moveTo(xAxis, yAxis, 0); + _buttons = 0; + moveTo(xAxis, yAxis, 0); +} + +void AbsoluteMouseAPI::moveTo(uint16_t x, uint16_t y, signed char wheel) { + xAxis = x; + yAxis = y; + HID_MouseAbsoluteReport_Data_t report; + report.buttons = _buttons; + report.xAxis = x; + report.yAxis = y; + report.wheel = wheel; + SendReport(&report, sizeof(report)); +} + +void AbsoluteMouseAPI::move(int x, int y, signed char wheel) { + moveTo(qadd16(xAxis, x), qadd16(yAxis, y), wheel); +} + +void AbsoluteMouseAPI::press(uint8_t b) { + // press LEFT by default + buttons(_buttons | b); +} + +void AbsoluteMouseAPI::release(uint8_t b) { + // release LEFT by default + buttons(_buttons & ~b); +} + +bool AbsoluteMouseAPI::isPressed(uint8_t b) { + // check LEFT by default + if ((b & _buttons) > 0) + return true; + return false; +} From dc2468fd4fd614ef8d4e0d4f5999f0a6d3ee9af4 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Thu, 27 Jul 2017 17:39:49 -0700 Subject: [PATCH 470/602] Use newly-reextracted AbsoluteMouseAPI --- .../src/MultiReport/AbsoluteMouse.cpp | 125 ++---------------- .../src/MultiReport/AbsoluteMouse.h | 44 +----- 2 files changed, 19 insertions(+), 150 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp index 6ce839a4c6..52c64fa0f5 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp @@ -25,128 +25,27 @@ THE SOFTWARE. #include "DescriptorPrimitives.h" static const uint8_t _hidMultiReportDescriptorAbsoluteMouse[] PROGMEM = { - /* Mouse absolute */ - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) 54 */ - D_USAGE, D_USAGE_MOUSE, /* USAGE (Mouse) */ - D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ - D_REPORT_ID, HID_REPORTID_MOUSE_ABSOLUTE, /* REPORT_ID */ + /* Mouse absolute */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) 54 */ + D_USAGE, D_USAGE_MOUSE, /* USAGE (Mouse) */ + D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ + D_REPORT_ID, HID_REPORTID_MOUSE_ABSOLUTE, /* REPORT_ID */ - /* 8 Buttons */ - D_USAGE_PAGE, D_PAGE_BUTTON, /* USAGE_PAGE (Button) */ - D_USAGE_MINIMUM, 0x01, /* USAGE_MINIMUM (Button 1) */ - D_USAGE_MAXIMUM, 0x08, /* USAGE_MAXIMUM (Button 8) */ - D_LOGICAL_MINIMUM, 0x00, /* LOGICAL_MINIMUM (0) */ - D_LOGICAL_MAXIMUM, 0x01, /* LOGICAL_MAXIMUM (1) */ - D_REPORT_COUNT, 0x08, /* REPORT_COUNT (8) */ - D_REPORT_SIZE, 0x01, /* REPORT_SIZE (1) */ - D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), + DESCRIPTOR_ABS_MOUSE_BUTTONS + DESCRIPTOR_ABS_MOUSE_XY + DESCRIPTOR_ABS_MOUSE_WHEEL - /* X, Y */ - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ - D_USAGE, 0x30, /* USAGE (X) */ - D_USAGE, 0x31, /* USAGE (Y) */ - D_MULTIBYTE(D_LOGICAL_MINIMUM), 0x00, 0x00, /* Logical Minimum (0) */ - D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xFF, 0x7f, /* Logical Maximum (32767) */ - D_REPORT_SIZE, 0x10, /* Report Size (16), */ - D_REPORT_COUNT, 0x02, /* Report Count (2), */ - D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), /* Input (Data, Variable, Absolute) */ - - /* Wheel */ - D_USAGE, 0x38, /* USAGE (Wheel) */ - D_LOGICAL_MINIMUM, 0x81, /* LOGICAL_MINIMUM (-127) */ - D_LOGICAL_MAXIMUM, 0x7f, /* LOGICAL_MAXIMUM (127) */ - D_REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ - D_REPORT_COUNT, 0x01, /* REPORT_COUNT (1) */ - D_INPUT, (D_DATA|D_VARIABLE|D_RELATIVE), - - /* End */ - D_END_COLLECTION + D_END_COLLECTION /* End */ }; AbsoluteMouse_::AbsoluteMouse_(void) { - static HIDSubDescriptor node(_hidMultiReportDescriptorAbsoluteMouse, sizeof(_hidMultiReportDescriptorAbsoluteMouse)); - HID().AppendDescriptor(&node); + static HIDSubDescriptor node(_hidMultiReportDescriptorAbsoluteMouse, sizeof(_hidMultiReportDescriptorAbsoluteMouse)); + HID().AppendDescriptor(&node); } void AbsoluteMouse_::SendReport(void* data, int length) { - HID().SendReport(HID_REPORTID_MOUSE_ABSOLUTE, data, length); -} - - -void AbsoluteMouse_::buttons(uint8_t b) { - if (b != _buttons) { - _buttons = b; - moveTo(xAxis, yAxis, 0); - } -} - -int16_t AbsoluteMouse_::qadd16(int16_t base, int16_t increment) { - // Separate between subtracting and adding - if (increment < 0) { - // Subtracting more would cause an undefined overflow - if ((int16_t)0x8000 - increment > base) - base = 0x8000; - else - base += increment; - } else { - // Adding more would cause an undefined overflow - if ((int16_t)0x7FFF - increment < base) - base = 0x7FFF; - else - base += increment; - } - return base; -} - -void AbsoluteMouse_::begin(void) { - // release all buttons - end(); -} - -void AbsoluteMouse_::end(void) { - _buttons = 0; - moveTo(xAxis, yAxis, 0); -} - -void AbsoluteMouse_::click(uint8_t b) { - _buttons = b; - moveTo(xAxis, yAxis, 0); - _buttons = 0; - moveTo(xAxis, yAxis, 0); -} - -void AbsoluteMouse_::moveTo(uint16_t x, uint16_t y, signed char wheel) { - xAxis = x; - yAxis = y; - HID_MouseAbsoluteReport_Data_t report; - report.buttons = _buttons; - report.xAxis = x; - report.yAxis = y; - report.wheel = wheel; - SendReport(&report, sizeof(report)); -} - -void AbsoluteMouse_::move(int x, int y, signed char wheel) { - moveTo(qadd16(xAxis, x), qadd16(yAxis, y), wheel); -} - -void AbsoluteMouse_::press(uint8_t b) { - // press LEFT by default - buttons(_buttons | b); -} - -void AbsoluteMouse_::release(uint8_t b) { - // release LEFT by default - buttons(_buttons & ~b); + HID().SendReport(HID_REPORTID_MOUSE_ABSOLUTE, data, length); } -bool AbsoluteMouse_::isPressed(uint8_t b) { - // check LEFT by default - if ((b & _buttons) > 0) - return true; - return false; -} - - AbsoluteMouse_ AbsoluteMouse; diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h index 66b015d43e..12faef21b4 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h @@ -28,45 +28,15 @@ THE SOFTWARE. #include "PluggableUSB.h" #include "HID.h" #include "HID-Settings.h" -#include "MouseButtons.h" - -typedef union { - // Absolute mouse report: 8 buttons, 2 absolute axis, wheel - struct { - uint8_t buttons; - uint16_t xAxis; - uint16_t yAxis; - int8_t wheel; - }; -} HID_MouseAbsoluteReport_Data_t; - -class AbsoluteMouse_ { - public: - AbsoluteMouse_(void); - void begin(void); - void end(void); - - void click(uint8_t b = MOUSE_LEFT); - void moveTo(uint16_t x, uint16_t y, signed char wheel = 0); - void move(int x, int y, signed char wheel = 0); - void press(uint8_t b = MOUSE_LEFT); - void release(uint8_t b = MOUSE_LEFT); - bool isPressed(uint8_t b = MOUSE_LEFT); - - // Sending is public in the base class for advanced users. - void SendReport(void* data, int length); - - protected: - uint16_t xAxis; - uint16_t yAxis; - uint8_t _buttons; - void buttons(uint8_t b); - - int16_t qadd16(int16_t base, int16_t increment); - +#include "../DeviceAPIs/AbsoluteMouseAPI.h" +class AbsoluteMouse_ : public AbsoluteMouseAPI { + public: + AbsoluteMouse_(void); + protected: + // Sending is public in the base class for advanced users. + virtual void SendReport(void* data, int length); }; - extern AbsoluteMouse_ AbsoluteMouse; From a8984396aecebee6af74a39ac2774b96f74ee02c Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Thu, 27 Jul 2017 18:00:09 -0700 Subject: [PATCH 471/602] Reimport Nico's standalone absolute mouse class --- .../src/SingleReport/SingleAbsoluteMouse.cpp | 144 ++++++++++++++++++ .../src/SingleReport/SingleAbsoluteMouse.h | 55 +++++++ 2 files changed, 199 insertions(+) create mode 100644 plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp create mode 100644 plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp new file mode 100644 index 0000000000..bad902c487 --- /dev/null +++ b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp @@ -0,0 +1,144 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 "SingleAbsoluteMouse.h" + +static const uint8_t _hidSingleReportDescriptorAbsoluteMouse[] PROGMEM = { + /* Mouse absolute */ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 54 */ + 0x09, 0x02, /* USAGE (Mouse) */ + 0xA1, 0x01, /* COLLECTION (Application) */ + + /* 8 Buttons */ + 0x05, 0x09, /* USAGE_PAGE (Button) */ + 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ + 0x29, 0x08, /* USAGE_MAXIMUM (Button 8) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x95, 0x08, /* REPORT_COUNT (8) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + + /* X, Y */ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x30, /* USAGE (X) */ + 0x09, 0x31, /* USAGE (Y) */ + 0x16, 0x00, 0x80, /* Logical Minimum (-32768) */ + 0x26, 0xFF, 0x7F, /* Logical Maximum (32767) */ + 0x75, 0x10, /* Report Size (16), */ + 0x95, 0x02, /* Report Count (2), */ + 0x81, 0x02, /* Input (Data, Variable, Absolute) */ + + /* Wheel */ + 0x09, 0x38, /* USAGE (Wheel) */ + 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) */ + + /* End */ + 0xc0 /* END_COLLECTION */ +}; + + +SingleAbsoluteMouse_::SingleAbsoluteMouse_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1) +{ + epType[0] = EP_TYPE_INTERRUPT_IN; + PluggableUSB().plug(this); +} + +int SingleAbsoluteMouse_::getInterface(uint8_t* interfaceCount) +{ + *interfaceCount += 1; // uses 1 + HIDDescriptor hidInterface = { + D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE), + D_HIDREPORT(sizeof(_hidSingleReportDescriptorAbsoluteMouse)), + D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) + }; + return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); +} + +int SingleAbsoluteMouse_::getDescriptor(USBSetup& setup) +{ + // Check if this is a HID Class Descriptor request + if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { return 0; } + if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { return 0; } + + // In a HID Class Descriptor wIndex cointains the interface number + if (setup.wIndex != pluggedInterface) { return 0; } + + // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol + // due to the USB specs, but Windows and Linux just assumes its in report mode. + protocol = HID_REPORT_PROTOCOL; + + return USB_SendControl(TRANSFER_PGM, _hidSingleReportDescriptorAbsoluteMouse, sizeof(_hidSingleReportDescriptorAbsoluteMouse)); +} + +bool SingleAbsoluteMouse_::setup(USBSetup& setup) +{ + if (pluggedInterface != setup.wIndex) { + return false; + } + + uint8_t request = setup.bRequest; + uint8_t requestType = setup.bmRequestType; + + if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) + { + if (request == HID_GET_REPORT) { + // TODO: HID_GetReport(); + return true; + } + if (request == HID_GET_PROTOCOL) { + // TODO: Send8(protocol); + return true; + } + } + + if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) + { + if (request == HID_SET_PROTOCOL) { + protocol = setup.wValueL; + return true; + } + if (request == HID_SET_IDLE) { + idle = setup.wValueL; + return true; + } + if (request == HID_SET_REPORT) + { + } + } + + return false; +} + +void SingleAbsoluteMouse_::SendReport(void* data, int length) +{ + USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, length); +} + +SingleAbsoluteMouse_ SingleAbsoluteMouse; + + diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h new file mode 100644 index 0000000000..4244fad4bb --- /dev/null +++ b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h @@ -0,0 +1,55 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +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 guard +#pragma once + +#include +#include "PluggableUSB.h" +#include "HID.h" +#include "HID-Settings.h" +#include "../DeviceAPIs/AbsoluteMouseAPI.h" + + +class SingleAbsoluteMouse_ : public PluggableUSBModule, public AbsoluteMouseAPI +{ +public: + SingleAbsoluteMouse_(void); + uint8_t getLeds(void); + uint8_t getProtocol(void); + +protected: + // Implementation of the PUSBListNode + int getInterface(uint8_t* interfaceCount); + int getDescriptor(USBSetup& setup); + bool setup(USBSetup& setup); + + uint8_t epType[1]; + uint8_t protocol; + uint8_t idle; + + virtual inline void SendReport(void* data, int length) override; +}; +extern SingleAbsoluteMouse_ SingleAbsoluteMouse; + + From 5decbb957dfa93440caa24ffa40ba79ed598d73d Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Thu, 27 Jul 2017 19:08:14 -0700 Subject: [PATCH 472/602] Include singleabsolutemouse --- plugins/KeyboardioHID/src/KeyboardioHID.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/KeyboardioHID/src/KeyboardioHID.h b/plugins/KeyboardioHID/src/KeyboardioHID.h index f88565ef31..6d9a6930e7 100644 --- a/plugins/KeyboardioHID/src/KeyboardioHID.h +++ b/plugins/KeyboardioHID/src/KeyboardioHID.h @@ -47,4 +47,6 @@ THE SOFTWARE. #include "MultiReport/SystemControl.h" #include "MultiReport/Keyboard.h" +#include "SingleReport/SingleAbsoluteMouse.h" + #include "BootKeyboard/BootKeyboard.h" From 25f53d063933ebad742a7827e6b479065c339371 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Thu, 27 Jul 2017 19:08:44 -0700 Subject: [PATCH 473/602] Refactor SingleAbsoluteMouse' HID descriptor to use our definition macros and to share content with the composite device --- plugins/KeyboardioHID/Makefile | 2 +- .../src/SingleReport/SingleAbsoluteMouse.cpp | 43 ++++--------------- 2 files changed, 9 insertions(+), 36 deletions(-) diff --git a/plugins/KeyboardioHID/Makefile b/plugins/KeyboardioHID/Makefile index 9202634b87..d63420ee7a 100644 --- a/plugins/KeyboardioHID/Makefile +++ b/plugins/KeyboardioHID/Makefile @@ -6,7 +6,7 @@ MCU = atmega32u4 ARDUINO_LIBS = -ARDUINO_PATH=/Applications/Arduino.app/Contents/Java/ +ARDUINO_PATH ?= /Applications/Arduino.app/Contents/Java/ ARDUINO_TOOLS_PATH=$(ARDUINO_PATH)/hardware/tools FQBN=arduino:avr:leonardo BUILD_PATH := $(shell mktemp -d 2>/dev/null || mktemp -d -t 'build') diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp index bad902c487..0a0009b001 100644 --- a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp @@ -24,41 +24,14 @@ THE SOFTWARE. #include "SingleAbsoluteMouse.h" static const uint8_t _hidSingleReportDescriptorAbsoluteMouse[] PROGMEM = { - /* Mouse absolute */ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 54 */ - 0x09, 0x02, /* USAGE (Mouse) */ - 0xA1, 0x01, /* COLLECTION (Application) */ - - /* 8 Buttons */ - 0x05, 0x09, /* USAGE_PAGE (Button) */ - 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ - 0x29, 0x08, /* USAGE_MAXIMUM (Button 8) */ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ - 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ - 0x95, 0x08, /* REPORT_COUNT (8) */ - 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - - /* X, Y */ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ - 0x09, 0x30, /* USAGE (X) */ - 0x09, 0x31, /* USAGE (Y) */ - 0x16, 0x00, 0x80, /* Logical Minimum (-32768) */ - 0x26, 0xFF, 0x7F, /* Logical Maximum (32767) */ - 0x75, 0x10, /* Report Size (16), */ - 0x95, 0x02, /* Report Count (2), */ - 0x81, 0x02, /* Input (Data, Variable, Absolute) */ - - /* Wheel */ - 0x09, 0x38, /* USAGE (Wheel) */ - 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) */ - - /* End */ - 0xc0 /* END_COLLECTION */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) 54 */ + D_USAGE, D_USAGE_MOUSE, /* USAGE (Mouse) */ + D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ + + DESCRIPTOR_ABS_MOUSE_BUTTONS + DESCRIPTOR_ABS_MOUSE_XY + DESCRIPTOR_ABS_MOUSE_WHEEL + D_END_COLLECTION /* End */ }; From 1145bb5b71f31b04603d0b39ff400af68cdf484c Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 28 Jul 2017 00:01:04 -0700 Subject: [PATCH 474/602] downCase SendReport --- plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h | 2 +- plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.hpp | 2 +- plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h | 2 +- plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp | 6 +++--- plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h | 2 +- plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp | 4 ++-- plugins/KeyboardioHID/src/MultiReport/Gamepad.h | 2 +- plugins/KeyboardioHID/src/MultiReport/Mouse.cpp | 2 +- plugins/KeyboardioHID/src/MultiReport/Mouse.h | 2 +- plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp | 4 ++-- plugins/KeyboardioHID/src/MultiReport/SystemControl.h | 2 +- .../KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h | 2 +- 12 files changed, 16 insertions(+), 16 deletions(-) diff --git a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h index e9087e31af..e027af690f 100644 --- a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h +++ b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h @@ -87,7 +87,7 @@ class AbsoluteMouseAPI { inline bool isPressed(uint8_t b = MOUSE_LEFT); // Sending is public in the base class for advanced users. - virtual void SendReport(void* data, int length); + virtual void sendReport(void* data, int length); protected: uint16_t xAxis; diff --git a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.hpp b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.hpp index 912fff688e..edcb2c21a7 100644 --- a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.hpp +++ b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.hpp @@ -76,7 +76,7 @@ void AbsoluteMouseAPI::moveTo(uint16_t x, uint16_t y, signed char wheel) { report.xAxis = x; report.yAxis = y; report.wheel = wheel; - SendReport(&report, sizeof(report)); + sendReport(&report, sizeof(report)); } void AbsoluteMouseAPI::move(int x, int y, signed char wheel) { diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h index 12faef21b4..d395ed1c95 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h @@ -36,7 +36,7 @@ class AbsoluteMouse_ : public AbsoluteMouseAPI { protected: // Sending is public in the base class for advanced users. - virtual void SendReport(void* data, int length); + virtual void sendReport(void* data, int length); }; extern AbsoluteMouse_ AbsoluteMouse; diff --git a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp index fe0829b502..c27ff33d55 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp @@ -53,7 +53,7 @@ void ConsumerControl_::begin(void) { void ConsumerControl_::end(void) { memset(&_report, 0, sizeof(_report)); - SendReport(&_report, sizeof(_report)); + sendReport(&_report, sizeof(_report)); } void ConsumerControl_::write(uint16_t m) { @@ -69,7 +69,7 @@ void ConsumerControl_::press(uint16_t m) { break; } } - SendReport(&_report, sizeof(_report)); + sendReport(&_report, sizeof(_report)); } void ConsumerControl_::release(uint16_t m) { @@ -80,7 +80,7 @@ void ConsumerControl_::release(uint16_t m) { // no break to delete multiple keys } } - SendReport(&_report, sizeof(_report)); + sendReport(&_report, sizeof(_report)); } void ConsumerControl_::releaseAll(void) { diff --git a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h index b11d036223..6039d1eee4 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h +++ b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h @@ -52,7 +52,7 @@ class ConsumerControl_ { void releaseAll(void); // Sending is public in the base class for advanced users. - void SendReport(void* data, int length); + void sendReport(void* data, int length); protected: diff --git a/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp b/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp index 3762d87dd9..f7c38d8c58 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp @@ -86,11 +86,11 @@ void Gamepad_::begin(void) { void Gamepad_::end(void) { memset(&_report, 0x00, sizeof(_report)); - SendReport(&_report, sizeof(_report)); + sendReport(&_report, sizeof(_report)); } void Gamepad_::write(void) { - SendReport(&_report, sizeof(_report)); + sendReport(&_report, sizeof(_report)); } diff --git a/plugins/KeyboardioHID/src/MultiReport/Gamepad.h b/plugins/KeyboardioHID/src/MultiReport/Gamepad.h index 7aaa385088..d315c47944 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Gamepad.h +++ b/plugins/KeyboardioHID/src/MultiReport/Gamepad.h @@ -117,7 +117,7 @@ class Gamepad_ { void dPad1(int8_t d); void dPad2(int8_t d); - void SendReport(void* data, int length); + void sendReport(void* data, int length); protected: HID_GamepadReport_Data_t _report; }; diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp index 065ce1ea70..c8d3392d6a 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp @@ -84,7 +84,7 @@ void Mouse_::move(signed char x, signed char y, signed char wheel) { report.xAxis = x; report.yAxis = y; report.wheel = wheel; - SendReport(&report, sizeof(report)); + sendReport(&report, sizeof(report)); } void Mouse_::buttons(uint8_t b) { diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.h b/plugins/KeyboardioHID/src/MultiReport/Mouse.h index 631658b4bc..860cfef95e 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.h @@ -52,7 +52,7 @@ class Mouse_ { void release(uint8_t b = MOUSE_LEFT); // release LEFT by default bool isPressed(uint8_t b = MOUSE_LEFT); // check LEFT by default - void SendReport(void* data, int length); + void sendReport(void* data, int length); protected: uint8_t _buttons; diff --git a/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp b/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp index b8b87d40dc..2afa216f26 100644 --- a/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp @@ -54,7 +54,7 @@ void SystemControl_::begin(void) { void SystemControl_::end(void) { uint8_t _report = 0x00; - SendReport(&_report, sizeof(_report)); + sendReport(&_report, sizeof(_report)); } void SystemControl_::write(uint8_t s) { @@ -74,7 +74,7 @@ void SystemControl_::press(uint8_t s) { if (s == HID_SYSTEM_WAKE_UP) USBDevice.wakeupHost(); else - SendReport(&s, sizeof(s)); + sendReport(&s, sizeof(s)); } diff --git a/plugins/KeyboardioHID/src/MultiReport/SystemControl.h b/plugins/KeyboardioHID/src/MultiReport/SystemControl.h index 95f00c2aff..bbf68f0144 100644 --- a/plugins/KeyboardioHID/src/MultiReport/SystemControl.h +++ b/plugins/KeyboardioHID/src/MultiReport/SystemControl.h @@ -44,7 +44,7 @@ class SystemControl_ { void press(uint8_t s); void release(void); void releaseAll(void); - void SendReport(void* data, int length); + void sendReport(void* data, int length); SystemControl_(void); diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h index 4244fad4bb..c90d658da3 100644 --- a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h +++ b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h @@ -48,7 +48,7 @@ class SingleAbsoluteMouse_ : public PluggableUSBModule, public AbsoluteMouseAPI uint8_t protocol; uint8_t idle; - virtual inline void SendReport(void* data, int length) override; + virtual inline void sendReport(void* data, int length) override; }; extern SingleAbsoluteMouse_ SingleAbsoluteMouse; From 412a0e3bf6e935bee2ebe840e5de694cbd772054 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 28 Jul 2017 00:03:03 -0700 Subject: [PATCH 475/602] Finish downcasing sendReport --- plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp | 2 +- plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp | 2 +- plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp | 2 +- plugins/KeyboardioHID/src/MultiReport/Mouse.cpp | 2 +- plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp | 2 +- plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp index 52c64fa0f5..5fa251cb5b 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp @@ -44,7 +44,7 @@ AbsoluteMouse_::AbsoluteMouse_(void) { } -void AbsoluteMouse_::SendReport(void* data, int length) { +void AbsoluteMouse_::sendReport(void* data, int length) { HID().SendReport(HID_REPORTID_MOUSE_ABSOLUTE, data, length); } diff --git a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp index c27ff33d55..2df9efd89e 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp @@ -87,7 +87,7 @@ void ConsumerControl_::releaseAll(void) { end(); } -void ConsumerControl_::SendReport(void* data, int length) { +void ConsumerControl_::sendReport(void* data, int length) { HID().SendReport(HID_REPORTID_CONSUMERCONTROL, data, length); } diff --git a/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp b/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp index f7c38d8c58..525d2508df 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp @@ -153,7 +153,7 @@ void Gamepad_::dPad2(int8_t d) { } -void Gamepad_::SendReport(void* data, int length) { +void Gamepad_::sendReport(void* data, int length) { HID().SendReport(HID_REPORTID_GAMEPAD, data, length); } diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp index c8d3392d6a..23f0bac69b 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp @@ -109,7 +109,7 @@ bool Mouse_::isPressed(uint8_t b) { } -void Mouse_::SendReport(void* data, int length) { +void Mouse_::sendReport(void* data, int length) { HID().SendReport(HID_REPORTID_MOUSE, data, length); } diff --git a/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp b/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp index 2afa216f26..417047d9ec 100644 --- a/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp @@ -78,7 +78,7 @@ void SystemControl_::press(uint8_t s) { } -void SystemControl_::SendReport(void* data, int length) { +void SystemControl_::sendReport(void* data, int length) { HID().SendReport(HID_REPORTID_SYSTEMCONTROL, data, length); } diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp index 0a0009b001..ff4da906d1 100644 --- a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp @@ -107,7 +107,7 @@ bool SingleAbsoluteMouse_::setup(USBSetup& setup) return false; } -void SingleAbsoluteMouse_::SendReport(void* data, int length) +void SingleAbsoluteMouse_::sendReport(void* data, int length) { USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, length); } From 03ac0650cef8f4f79c760f3c6d09241411ca061e Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Sun, 13 Aug 2017 11:08:07 -0700 Subject: [PATCH 476/602] Use the alias we've already defined for the "top" of the keymap This just improves clarity, but doesn't change behavior --- plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index 8da9e52e08..c3f0fe11ab 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -152,7 +152,7 @@ boolean Keyboard_::isModifierActive(uint8_t k) { size_t Keyboard_::press(uint8_t k) { // If the key is in the range of 'printable' keys - if (k <= HID_KEYPAD_HEXADECIMAL) { + if (k <= HID_LAST_KEY) { uint8_t bit = 1 << (uint8_t(k) % 8); _keyReport.keys[k / 8] |= bit; return 1; @@ -172,7 +172,7 @@ size_t Keyboard_::press(uint8_t k) { size_t Keyboard_::release(uint8_t k) { // If we're releasing a printable key - if (k <= HID_KEYPAD_HEXADECIMAL) { + if (k <= HID_LAST_KEY) { uint8_t bit = 1 << (k % 8); _keyReport.keys[k / 8] &= ~bit; return 1; From d0b9abc139ea61ce18b12a11777d46bf00850e81 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Sun, 13 Aug 2017 11:21:08 -0700 Subject: [PATCH 477/602] Add a new 'wasModifierActive' method to help introspect the last key report sent We need this upstream in Kaleidoscope to work around a chromeos bug --- plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp | 14 ++++++++++++++ plugins/KeyboardioHID/src/MultiReport/Keyboard.h | 1 + 2 files changed, 15 insertions(+) diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index c3f0fe11ab..10a04b3003 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -142,6 +142,9 @@ int Keyboard_::sendReport(void) { return -1; } +/* Returns true if the modifer key passed in will be sent during this key report + * Returns false in all other cases + * */ boolean Keyboard_::isModifierActive(uint8_t k) { if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { k = k - HID_KEYBOARD_FIRST_MODIFIER; @@ -150,6 +153,17 @@ boolean Keyboard_::isModifierActive(uint8_t k) { return false; } +/* Returns true if the modifer key passed in was being sent during the previous key report + * Returns false in all other cases + * */ +boolean Keyboard_::wasModifierActive(uint8_t k) { + if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { + k = k - HID_KEYBOARD_FIRST_MODIFIER; + return !!(_lastKeyReport.modifiers & (1 << k)); + } + return false; +} + size_t Keyboard_::press(uint8_t k) { // If the key is in the range of 'printable' keys if (k <= HID_LAST_KEY) { diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h index 7468967bd7..c989d540ee 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h @@ -57,6 +57,7 @@ class Keyboard_ { int sendReport(void); boolean isModifierActive(uint8_t k); + boolean wasModifierActive(uint8_t k); protected: HID_KeyboardReport_Data_t _keyReport; From d660e60ec8eed3e0045d83f5a2b4beda1d87ef98 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Sun, 29 Oct 2017 20:01:55 +0100 Subject: [PATCH 478/602] Implement Keyboard.getLEDs() Add a LEDS usage page to the HID descriptors, and a `.getLEDs` method pass-through. Signed-off-by: Gergely Nagy --- plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp | 10 ++++++++++ plugins/KeyboardioHID/src/MultiReport/Keyboard.h | 2 ++ 2 files changed, 12 insertions(+) diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index 10a04b3003..b23d4a906e 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -42,9 +42,19 @@ static const uint8_t _hidMultiReportDescriptorKeyboard[] PROGMEM = { D_REPORT_COUNT, 0x08, D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), + + /* 5 LEDs for num lock etc, 3 left for advanced, custom usage */ + D_USAGE_PAGE, D_PAGE_LEDS, + D_USAGE_MINIMUM, 0x01, + D_USAGE_MAXIMUM, 0x08, + D_REPORT_COUNT, 0x08, + D_REPORT_SIZE, 0x01, + D_OUTPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), + // USB Code not within 4-49 (0x4-0x31), 51-155 (0x33-0x9B), 157-164 (0x9D-0xA4), // 176-221 (0xB0-0xDD) or 224-231 (0xE0-0xE7) NKRO Mode /* NKRO Keyboard */ + D_USAGE_PAGE, D_PAGE_KEYBOARD, // Padding 3 bits // To skip HID_KEYBOARD_NON_US_POUND_AND_TILDE, which causes diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h index c989d540ee..070c1845c3 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h @@ -59,6 +59,8 @@ class Keyboard_ { boolean isModifierActive(uint8_t k); boolean wasModifierActive(uint8_t k); + uint8_t getLEDs() { return HID().getLEDs(); }; + protected: HID_KeyboardReport_Data_t _keyReport; HID_KeyboardReport_Data_t _lastKeyReport; From 5b57a0c183806d86f50f9fdc0463262affb71f7b Mon Sep 17 00:00:00 2001 From: SjB Date: Tue, 7 Nov 2017 00:05:59 -0500 Subject: [PATCH 479/602] Support for Vertical mouse wheel movement. Extended the HID Descriptor to send a Consumer Device page that support a vertical mouse will message --- .../src/DeviceAPIs/AbsoluteMouseAPI.h | 17 ++++++++++++++--- .../src/DeviceAPIs/AbsoluteMouseAPI.hpp | 9 +++++---- .../src/MultiReport/AbsoluteMouse.cpp | 1 + plugins/KeyboardioHID/src/MultiReport/Mouse.cpp | 13 +++++++++++-- plugins/KeyboardioHID/src/MultiReport/Mouse.h | 5 +++-- 5 files changed, 34 insertions(+), 11 deletions(-) diff --git a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h index e027af690f..b8ac6f34b1 100644 --- a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h +++ b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h @@ -63,13 +63,24 @@ THE SOFTWARE. D_REPORT_COUNT, 0x01, /* REPORT_COUNT (1) */ \ D_INPUT, (D_DATA|D_VARIABLE|D_RELATIVE), +#define DESCRIPTOR_ABS_MOUSE_HWHEEL \ + D_USAGE_PAGE, D_PAGE_CONSUMER, /* USAGE_PAGE (Consumer Device) */ \ + D_PAGE_ORDINAL, 0x38, 0x02, \ + D_USAGE_MINIMUM, 0x81, \ + D_USAGE_MAXIMUM, 0x7f, \ + D_REPORT_SIZE, 0x08, \ + D_REPORT_COUNT, 0x01, \ + D_INPUT, (D_DATA|D_VARIABLE|D_RELATIVE), + + typedef union { // Absolute mouse report: 8 buttons, 2 absolute axis, wheel struct { uint8_t buttons; uint16_t xAxis; uint16_t yAxis; - int8_t wheel; + int8_t vWheel; + int8_t hWheel; }; } HID_MouseAbsoluteReport_Data_t; @@ -80,8 +91,8 @@ class AbsoluteMouseAPI { inline void end(void); inline void click(uint8_t b = MOUSE_LEFT); - inline void moveTo(uint16_t x, uint16_t y, signed char wheel = 0); - inline void move(int x, int y, signed char wheel = 0); + inline void moveTo(uint16_t x, uint16_t y, signed char vWheel = 0, signed char hWheel = 0); + inline void move(int x, int y, signed char vWheel = 0, signed char hWheel = 0); inline void press(uint8_t b = MOUSE_LEFT); inline void release(uint8_t b = MOUSE_LEFT); inline bool isPressed(uint8_t b = MOUSE_LEFT); diff --git a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.hpp b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.hpp index edcb2c21a7..82a8bb220d 100644 --- a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.hpp +++ b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.hpp @@ -68,19 +68,20 @@ void AbsoluteMouseAPI::click(uint8_t b) { moveTo(xAxis, yAxis, 0); } -void AbsoluteMouseAPI::moveTo(uint16_t x, uint16_t y, signed char wheel) { +void AbsoluteMouseAPI::moveTo(uint16_t x, uint16_t y, signed char vWheel, signed char hWheel) { xAxis = x; yAxis = y; HID_MouseAbsoluteReport_Data_t report; report.buttons = _buttons; report.xAxis = x; report.yAxis = y; - report.wheel = wheel; + report.vWheel = vWheel; + report.hWheel = hWheel; sendReport(&report, sizeof(report)); } -void AbsoluteMouseAPI::move(int x, int y, signed char wheel) { - moveTo(qadd16(xAxis, x), qadd16(yAxis, y), wheel); +void AbsoluteMouseAPI::move(int x, int y, signed char vWheel, signed char hWheel) { + moveTo(qadd16(xAxis, x), qadd16(yAxis, y), vWheel, hWheel); } void AbsoluteMouseAPI::press(uint8_t b) { diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp index 5fa251cb5b..ba2d2292c4 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp @@ -34,6 +34,7 @@ static const uint8_t _hidMultiReportDescriptorAbsoluteMouse[] PROGMEM = { DESCRIPTOR_ABS_MOUSE_BUTTONS DESCRIPTOR_ABS_MOUSE_XY DESCRIPTOR_ABS_MOUSE_WHEEL + DESCRIPTOR_ABS_MOUSE_HWHEEL D_END_COLLECTION /* End */ }; diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp index 23f0bac69b..1fb32b489c 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp @@ -52,6 +52,14 @@ static const uint8_t _hidMultiReportDescriptorMouse[] PROGMEM = { D_REPORT_COUNT, 0x03, /* REPORT_COUNT (3) */ D_INPUT, (D_DATA|D_VARIABLE|D_RELATIVE), /* INPUT (Data,Var,Rel) */ + /* Horizontal wheel */ + D_USAGE_PAGE, D_PAGE_CONSUMER, /* USAGE_PAGE (Consumer Device) */ + D_PAGE_ORDINAL, 0x38, 0x02, + D_USAGE_MINIMUM, 0x81, + D_USAGE_MAXIMUM, 0x7f, + D_REPORT_SIZE, 0x08, + D_REPORT_COUNT, 0x01, + D_INPUT, (D_DATA|D_VARIABLE|D_RELATIVE), /* End */ D_END_COLLECTION /* END_COLLECTION */ }; @@ -78,12 +86,13 @@ void Mouse_::click(uint8_t b) { move(0,0,0); } -void Mouse_::move(signed char x, signed char y, signed char wheel) { +void Mouse_::move(signed char x, signed char y, signed char vWheel, signed char hWheel) { HID_MouseReport_Data_t report; report.buttons = _buttons; report.xAxis = x; report.yAxis = y; - report.wheel = wheel; + report.vWheel = vWheel; + report.hWheel = hWheel; sendReport(&report, sizeof(report)); } diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.h b/plugins/KeyboardioHID/src/MultiReport/Mouse.h index 860cfef95e..2b60c43c63 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.h @@ -36,7 +36,8 @@ typedef union { uint8_t buttons; int8_t xAxis; int8_t yAxis; - int8_t wheel; + int8_t vWheel; + int8_t hWheel; }; } HID_MouseReport_Data_t; @@ -47,7 +48,7 @@ class Mouse_ { 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 move(signed char x, signed char y, signed char vWheel = 0, signed char hWheel = 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 From d0def777d2bc3a598fbaebf58a14abae678d52b8 Mon Sep 17 00:00:00 2001 From: SjB Date: Thu, 16 Nov 2017 14:36:46 -0500 Subject: [PATCH 480/602] added documentation to Readme.md --- plugins/KeyboardioHID/Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/Readme.md b/plugins/KeyboardioHID/Readme.md index 54760a64bc..582aadcfbb 100644 --- a/plugins/KeyboardioHID/Readme.md +++ b/plugins/KeyboardioHID/Readme.md @@ -8,7 +8,7 @@ Based on Nico Hood's HID-Project. Please don't contact Nico with issues in this **Supported HID devices:** * Boot Keyboard * NKRO Keyboard (press up to 113 keys at the same time) -* Mouse (5 buttons, move, wheel) +* Mouse (5 buttons, move, vertical wheel, horizontal wheel) * Absolute Mouse * Consumer/Media Keys (4 keys for music player, web browser and more) * System Key (for PC standby/shutdown) From 0d192de17183fa226768d508486cfecc10235343 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Fri, 24 Nov 2017 17:57:31 +0100 Subject: [PATCH 481/602] ConsumerControl: Report separately from press / release Instead of always sending a report on every `press`, `release`, and `releaseAll`, let the user of this code decide when to send the report. This will allow us to treat `ConsumerControl` the same way we do with `Keyboard`, and clear the report each cycle. That in turn will help us not send many presses for the same key in a single report. Signed-off-by: Gergely Nagy --- plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp | 8 +++++--- plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp index 2df9efd89e..8e0c49905d 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp @@ -69,7 +69,6 @@ void ConsumerControl_::press(uint16_t m) { break; } } - sendReport(&_report, sizeof(_report)); } void ConsumerControl_::release(uint16_t m) { @@ -80,15 +79,18 @@ void ConsumerControl_::release(uint16_t m) { // no break to delete multiple keys } } - sendReport(&_report, sizeof(_report)); } void ConsumerControl_::releaseAll(void) { - end(); + memset(&_report, 0, sizeof(_report)); } void ConsumerControl_::sendReport(void* data, int length) { HID().SendReport(HID_REPORTID_CONSUMERCONTROL, data, length); } +void ConsumerControl_::sendReport(void) { + sendReport(&_report, sizeof(_report)); +} + ConsumerControl_ ConsumerControl; diff --git a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h index 6039d1eee4..ce4fb2d70e 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h +++ b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h @@ -53,7 +53,7 @@ class ConsumerControl_ { // Sending is public in the base class for advanced users. void sendReport(void* data, int length); - + void sendReport(void); protected: HID_ConsumerControlReport_Data_t _report; From a01df80478642ce3517451160e6a5ef8cfa4a5ca Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Tue, 28 Nov 2017 15:32:04 +0100 Subject: [PATCH 482/602] ConsumerControl: Guard the report Guard `sendReport` like it is done for `Keyboard.sendReport`, so it only sends a report when it is different than the previous. Signed-off-by: Gergely Nagy --- .../src/MultiReport/ConsumerControl.cpp | 17 +++++++++++++---- .../src/MultiReport/ConsumerControl.h | 5 ++++- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp index 8e0c49905d..a94898c9d1 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp @@ -53,7 +53,7 @@ void ConsumerControl_::begin(void) { void ConsumerControl_::end(void) { memset(&_report, 0, sizeof(_report)); - sendReport(&_report, sizeof(_report)); + sendReport(); } void ConsumerControl_::write(uint16_t m) { @@ -85,12 +85,21 @@ void ConsumerControl_::releaseAll(void) { memset(&_report, 0, sizeof(_report)); } -void ConsumerControl_::sendReport(void* data, int length) { - HID().SendReport(HID_REPORTID_CONSUMERCONTROL, data, length); +void ConsumerControl_::sendReportUnchecked(void) { + HID().SendReport(HID_REPORTID_CONSUMERCONTROL, &_report, sizeof(_report)); } void ConsumerControl_::sendReport(void) { - sendReport(&_report, sizeof(_report)); + // If the last report is different than the current report, then we need to send a report. + // We guard sendReport like this so that calling code doesn't end up spamming the host with empty reports + // if sendReport is called in a tight loop. + + // if the previous report is the same, return early without a new report. + if (memcmp(&_lastReport, &_report, sizeof(_report)) == 0) + return; + + sendReportUnchecked(); + memcpy(&_lastReport, &_report, sizeof(_report)); } ConsumerControl_ ConsumerControl; diff --git a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h index ce4fb2d70e..96e3150693 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h +++ b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h @@ -52,10 +52,13 @@ class ConsumerControl_ { void releaseAll(void); // Sending is public in the base class for advanced users. - void sendReport(void* data, int length); void sendReport(void); protected: HID_ConsumerControlReport_Data_t _report; + HID_ConsumerControlReport_Data_t _lastReport; + + private: + void sendReportUnchecked(void); }; extern ConsumerControl_ ConsumerControl; From dc692dd1e8a30fbe8fa85789052298c785fbd4e2 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Tue, 28 Nov 2017 22:17:52 -0800 Subject: [PATCH 483/602] Make the smoke tests use our version of the Arduino HID library, which we currently need for the LEDs support. Ideally, this would get upstreamed --- plugins/KeyboardioHID/.travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/.travis.yml b/plugins/KeyboardioHID/.travis.yml index c2ad5fca9c..c09f846c7e 100644 --- a/plugins/KeyboardioHID/.travis.yml +++ b/plugins/KeyboardioHID/.travis.yml @@ -5,7 +5,8 @@ before_install: - tar xf arduino-1.6.7-linux64.tar.xz - popd script: -- make smoke ARDUINO_PATH=../arduino-1.6.7 ARDUINO_LOCAL_LIB_PATH=.. +- git clone https://github.com/keyboardio/Arduino-HID ../Arduino-HID +- make smoke -libraries lib ARDUINO_PATH=../arduino-1.6.7 ARDUINO_LOCAL_LIB_PATH=.. notifications: irc: From b512dbcda3df70d8bc4b92408a9dddefcfd0cb4a Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Tue, 28 Nov 2017 22:23:26 -0800 Subject: [PATCH 484/602] Second attempt at a travis recipe --- plugins/KeyboardioHID/.travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/KeyboardioHID/.travis.yml b/plugins/KeyboardioHID/.travis.yml index c09f846c7e..cb7c9ad048 100644 --- a/plugins/KeyboardioHID/.travis.yml +++ b/plugins/KeyboardioHID/.travis.yml @@ -5,8 +5,8 @@ before_install: - tar xf arduino-1.6.7-linux64.tar.xz - popd script: -- git clone https://github.com/keyboardio/Arduino-HID ../Arduino-HID -- make smoke -libraries lib ARDUINO_PATH=../arduino-1.6.7 ARDUINO_LOCAL_LIB_PATH=.. +- git clone https://github.com/keyboardio/Arduino-HID ../HID +- make smoke ARDUINO_PATH=../arduino-1.6.7 ARDUINO_LOCAL_LIB_PATH=.. notifications: irc: From b74c6e8766dabeef33c83f5610c436d8359a9a8c Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Wed, 29 Nov 2017 10:31:29 +0100 Subject: [PATCH 485/602] AbsMouse: Remove support for the horizontal scroll wheel We do not use the wheels on `AbsoluteMouse`, and having the horizontal wheel added to the descriptor causes issues at least on Linux, rendering the whole of `AbsoluteMouse` unusable. With the horizontal wheel support gone, it works again. Fixes #15. Signed-off-by: Gergely Nagy --- .../src/DeviceAPIs/AbsoluteMouseAPI.h | 18 +++--------------- .../src/DeviceAPIs/AbsoluteMouseAPI.hpp | 11 +++++------ .../src/MultiReport/AbsoluteMouse.cpp | 1 - 3 files changed, 8 insertions(+), 22 deletions(-) diff --git a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h index b8ac6f34b1..725d83c5bb 100644 --- a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h +++ b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h @@ -63,24 +63,13 @@ THE SOFTWARE. D_REPORT_COUNT, 0x01, /* REPORT_COUNT (1) */ \ D_INPUT, (D_DATA|D_VARIABLE|D_RELATIVE), -#define DESCRIPTOR_ABS_MOUSE_HWHEEL \ - D_USAGE_PAGE, D_PAGE_CONSUMER, /* USAGE_PAGE (Consumer Device) */ \ - D_PAGE_ORDINAL, 0x38, 0x02, \ - D_USAGE_MINIMUM, 0x81, \ - D_USAGE_MAXIMUM, 0x7f, \ - D_REPORT_SIZE, 0x08, \ - D_REPORT_COUNT, 0x01, \ - D_INPUT, (D_DATA|D_VARIABLE|D_RELATIVE), - - typedef union { // Absolute mouse report: 8 buttons, 2 absolute axis, wheel struct { uint8_t buttons; uint16_t xAxis; uint16_t yAxis; - int8_t vWheel; - int8_t hWheel; + int8_t wheel; }; } HID_MouseAbsoluteReport_Data_t; @@ -91,8 +80,8 @@ class AbsoluteMouseAPI { inline void end(void); inline void click(uint8_t b = MOUSE_LEFT); - inline void moveTo(uint16_t x, uint16_t y, signed char vWheel = 0, signed char hWheel = 0); - inline void move(int x, int y, signed char vWheel = 0, signed char hWheel = 0); + inline void moveTo(uint16_t x, uint16_t y, signed char wheel = 0); + inline void move(int x, int y, signed char wheel = 0); inline void press(uint8_t b = MOUSE_LEFT); inline void release(uint8_t b = MOUSE_LEFT); inline bool isPressed(uint8_t b = MOUSE_LEFT); @@ -110,4 +99,3 @@ class AbsoluteMouseAPI { }; #include "AbsoluteMouseAPI.hpp" - diff --git a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.hpp b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.hpp index 82a8bb220d..744f1193f3 100644 --- a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.hpp +++ b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.hpp @@ -23,7 +23,7 @@ THE SOFTWARE. #pragma once -AbsoluteMouseAPI::AbsoluteMouseAPI(void): xAxis(0), yAxis(0), _buttons(0) { // Empty +AbsoluteMouseAPI::AbsoluteMouseAPI(void): xAxis(0), yAxis(0), _buttons(0) { // Empty } void AbsoluteMouseAPI::buttons(uint8_t b) { @@ -68,20 +68,19 @@ void AbsoluteMouseAPI::click(uint8_t b) { moveTo(xAxis, yAxis, 0); } -void AbsoluteMouseAPI::moveTo(uint16_t x, uint16_t y, signed char vWheel, signed char hWheel) { +void AbsoluteMouseAPI::moveTo(uint16_t x, uint16_t y, signed char wheel) { xAxis = x; yAxis = y; HID_MouseAbsoluteReport_Data_t report; report.buttons = _buttons; report.xAxis = x; report.yAxis = y; - report.vWheel = vWheel; - report.hWheel = hWheel; + report.wheel = wheel; sendReport(&report, sizeof(report)); } -void AbsoluteMouseAPI::move(int x, int y, signed char vWheel, signed char hWheel) { - moveTo(qadd16(xAxis, x), qadd16(yAxis, y), vWheel, hWheel); +void AbsoluteMouseAPI::move(int x, int y, signed char wheel) { + moveTo(qadd16(xAxis, x), qadd16(yAxis, y), wheel); } void AbsoluteMouseAPI::press(uint8_t b) { diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp index ba2d2292c4..5fa251cb5b 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp @@ -34,7 +34,6 @@ static const uint8_t _hidMultiReportDescriptorAbsoluteMouse[] PROGMEM = { DESCRIPTOR_ABS_MOUSE_BUTTONS DESCRIPTOR_ABS_MOUSE_XY DESCRIPTOR_ABS_MOUSE_WHEEL - DESCRIPTOR_ABS_MOUSE_HWHEEL D_END_COLLECTION /* End */ }; From e0db7f680553df2fa4db21959ea59fea1da2d7df Mon Sep 17 00:00:00 2001 From: Michael Richters Date: Sun, 26 Nov 2017 11:30:15 -0600 Subject: [PATCH 486/602] Made keyboard HID reports public With _keyReport & _lastKeyReport public, plugins get more flexibility without adding that code. You really need to know what you're doing if you're going to access these, however. --- plugins/KeyboardioHID/src/MultiReport/Keyboard.h | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h index 070c1845c3..3ae4effd78 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h @@ -61,7 +61,6 @@ class Keyboard_ { uint8_t getLEDs() { return HID().getLEDs(); }; - protected: HID_KeyboardReport_Data_t _keyReport; HID_KeyboardReport_Data_t _lastKeyReport; private: From ced3133c2c5630c995675a649d76a7bbd98bec34 Mon Sep 17 00:00:00 2001 From: Michael Richters Date: Wed, 29 Nov 2017 14:50:51 -0600 Subject: [PATCH 487/602] Changed names of public key report variables Removed leading underscores from `keyReport` and `lastKeyReport`. --- .../src/MultiReport/Keyboard.cpp | 20 +++++++++---------- .../KeyboardioHID/src/MultiReport/Keyboard.h | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index b23d4a906e..eb67da8889 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -134,7 +134,7 @@ void Keyboard_::end(void) { } int Keyboard_::sendReportUnchecked(void) { - return HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &_keyReport, sizeof(_keyReport)); + return HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &keyReport, sizeof(keyReport)); } @@ -143,10 +143,10 @@ int Keyboard_::sendReport(void) { // We guard sendReport like this so that calling code doesn't end up spamming the host with empty reports // if sendReport is called in a tight loop. - if (memcmp(_lastKeyReport.allkeys, _keyReport.allkeys, sizeof(_keyReport))) { + if (memcmp(lastKeyReport.allkeys, keyReport.allkeys, sizeof(keyReport))) { // if the two reports are different, send a report int returnCode = sendReportUnchecked(); - memcpy(_lastKeyReport.allkeys, _keyReport.allkeys, sizeof(_keyReport)); + memcpy(lastKeyReport.allkeys, keyReport.allkeys, sizeof(keyReport)); return returnCode; } return -1; @@ -158,7 +158,7 @@ int Keyboard_::sendReport(void) { boolean Keyboard_::isModifierActive(uint8_t k) { if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { k = k - HID_KEYBOARD_FIRST_MODIFIER; - return !!(_keyReport.modifiers & (1 << k)); + return !!(keyReport.modifiers & (1 << k)); } return false; } @@ -169,7 +169,7 @@ boolean Keyboard_::isModifierActive(uint8_t k) { boolean Keyboard_::wasModifierActive(uint8_t k) { if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { k = k - HID_KEYBOARD_FIRST_MODIFIER; - return !!(_lastKeyReport.modifiers & (1 << k)); + return !!(lastKeyReport.modifiers & (1 << k)); } return false; } @@ -178,7 +178,7 @@ size_t Keyboard_::press(uint8_t k) { // If the key is in the range of 'printable' keys if (k <= HID_LAST_KEY) { uint8_t bit = 1 << (uint8_t(k) % 8); - _keyReport.keys[k / 8] |= bit; + keyReport.keys[k / 8] |= bit; return 1; } @@ -186,7 +186,7 @@ size_t Keyboard_::press(uint8_t k) { else if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { // Convert key into bitfield (0 - 7) k = k - HID_KEYBOARD_FIRST_MODIFIER; - _keyReport.modifiers |= (1 << k); + keyReport.modifiers |= (1 << k); return 1; } @@ -198,7 +198,7 @@ size_t Keyboard_::release(uint8_t k) { // If we're releasing a printable key if (k <= HID_LAST_KEY) { uint8_t bit = 1 << (k % 8); - _keyReport.keys[k / 8] &= ~bit; + keyReport.keys[k / 8] &= ~bit; return 1; } @@ -206,7 +206,7 @@ size_t Keyboard_::release(uint8_t k) { else if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { // Convert key into bitfield (0 - 7) k = k - HID_KEYBOARD_FIRST_MODIFIER; - _keyReport.modifiers &= ~(1 << k); + keyReport.modifiers &= ~(1 << k); return 1; } @@ -216,7 +216,7 @@ size_t Keyboard_::release(uint8_t k) { void Keyboard_::releaseAll(void) { // Release all keys - memset(&_keyReport.allkeys, 0x00, sizeof(_keyReport.allkeys)); + memset(&keyReport.allkeys, 0x00, sizeof(keyReport.allkeys)); } Keyboard_ Keyboard; diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h index 3ae4effd78..c5567ab0a4 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h @@ -61,8 +61,8 @@ class Keyboard_ { uint8_t getLEDs() { return HID().getLEDs(); }; - HID_KeyboardReport_Data_t _keyReport; - HID_KeyboardReport_Data_t _lastKeyReport; + HID_KeyboardReport_Data_t keyReport; + HID_KeyboardReport_Data_t lastKeyReport; private: int sendReportUnchecked(void); }; From 22621ce2f1b16bb08fc66ac936b26c177b157772 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Fri, 24 Nov 2017 23:16:35 +0100 Subject: [PATCH 488/602] Mouse: Pull sendReport out of move & buttons Instead of sending a report immediately after a move or a button press, let the user of the library decide when to send it. While there, also expose a `releaseAll` method, so we follow the same pattern as `Keyboard`, allowing the user to send & clear the report each cycle. This separation is required to address keyboardio/Kaleidoscope-MouseKeys#10. Signed-off-by: Gergely Nagy --- .../KeyboardioHID/src/MultiReport/Mouse.cpp | 32 ++++++++----------- plugins/KeyboardioHID/src/MultiReport/Mouse.h | 6 ++-- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp index 1fb32b489c..f0b8288d73 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp @@ -75,51 +75,47 @@ void Mouse_::begin(void) { } void Mouse_::end(void) { - _buttons = 0; - move(0, 0, 0); + releaseAll(); + sendReport(); } void Mouse_::click(uint8_t b) { - _buttons = b; - move(0,0,0); - _buttons = 0; - move(0,0,0); + press(b); + sendReport(); + release(b); } void Mouse_::move(signed char x, signed char y, signed char vWheel, signed char hWheel) { - HID_MouseReport_Data_t report; - report.buttons = _buttons; report.xAxis = x; report.yAxis = y; report.vWheel = vWheel; report.hWheel = hWheel; - sendReport(&report, sizeof(report)); } -void Mouse_::buttons(uint8_t b) { - if (b != _buttons) { - _buttons = b; - move(0,0,0); - } +void Mouse_::releaseAll(void) { + memset(&report, 0, sizeof(report)); } void Mouse_::press(uint8_t b) { - buttons(_buttons | b); + report.buttons |= b; } void Mouse_::release(uint8_t b) { - buttons(_buttons & ~b); + report.buttons &= ~b; } bool Mouse_::isPressed(uint8_t b) { - if ((b & _buttons) > 0) + if ((b & report.buttons) > 0) return true; return false; } - void Mouse_::sendReport(void* data, int length) { HID().SendReport(HID_REPORTID_MOUSE, data, length); } +void Mouse_::sendReport(void) { + sendReport(&report, sizeof(report)); +} + Mouse_ Mouse; diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.h b/plugins/KeyboardioHID/src/MultiReport/Mouse.h index 2b60c43c63..ec99e7666c 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.h @@ -54,9 +54,11 @@ class Mouse_ { bool isPressed(uint8_t b = MOUSE_LEFT); // check LEFT by default void sendReport(void* data, int length); + void sendReport(void); + + void releaseAll(void); protected: - uint8_t _buttons; - void buttons(uint8_t b); + HID_MouseReport_Data_t report; }; extern Mouse_ Mouse; From 8a8feee84ff08af96bbee9d91b803d7cf30a258d Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Tue, 28 Nov 2017 15:20:44 +0100 Subject: [PATCH 489/602] Mouse: Guard sendReport() to only send reports on change If the report has not changed, do not send a report. This reduces USB chattiness. We store the previous report for this. The previous `sendReport` function was rolled into one, renamed `sendReportUnchecked`, and made private. The new `sendReport()` has the guard, similar how `Keyboard.sendReport()` works. Signed-off-by: Gergely Nagy --- plugins/KeyboardioHID/src/MultiReport/Mouse.cpp | 15 ++++++++++++--- plugins/KeyboardioHID/src/MultiReport/Mouse.h | 5 ++++- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp index f0b8288d73..d216e2afc1 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp @@ -110,12 +110,21 @@ bool Mouse_::isPressed(uint8_t b) { return false; } -void Mouse_::sendReport(void* data, int length) { - HID().SendReport(HID_REPORTID_MOUSE, data, length); +void Mouse_::sendReportUnchecked(void) { + HID().SendReport(HID_REPORTID_MOUSE, &report, sizeof(report)); } void Mouse_::sendReport(void) { - sendReport(&report, sizeof(report)); + // If the last report is different than the current report, then we need to send a report. + // We guard sendReport like this so that calling code doesn't end up spamming the host with empty reports + // if sendReport is called in a tight loop. + + // if the two reports are the same, return early without a report + if (memcmp(&lastReport, &report, sizeof(report)) == 0) + return; + + sendReportUnchecked(); + memcpy(&lastReport, &report, sizeof(report)); } Mouse_ Mouse; diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.h b/plugins/KeyboardioHID/src/MultiReport/Mouse.h index ec99e7666c..f84eb3c9ea 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.h @@ -53,12 +53,15 @@ class Mouse_ { void release(uint8_t b = MOUSE_LEFT); // release LEFT by default bool isPressed(uint8_t b = MOUSE_LEFT); // check LEFT by default - void sendReport(void* data, int length); void sendReport(void); void releaseAll(void); protected: HID_MouseReport_Data_t report; + HID_MouseReport_Data_t lastReport; + + private: + void sendReportUnchecked(void); }; extern Mouse_ Mouse; From f5a8f554745f472abfa714c62ebf1a80390de571 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Wed, 29 Nov 2017 08:41:46 +0100 Subject: [PATCH 490/602] Mouse: Only skip the report if it is both unchanged and empty Signed-off-by: Gergely Nagy --- plugins/KeyboardioHID/src/MultiReport/Mouse.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp index d216e2afc1..542f138876 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp @@ -119,9 +119,16 @@ void Mouse_::sendReport(void) { // We guard sendReport like this so that calling code doesn't end up spamming the host with empty reports // if sendReport is called in a tight loop. - // if the two reports are the same, return early without a report - if (memcmp(&lastReport, &report, sizeof(report)) == 0) - return; + // if the two reports are the same, check if they're empty, and return early + // without a report if they are. + if (memcmp(&lastReport, &report, sizeof(report)) == 0) { + if (0 == report.buttons && + 0 == report.xAxis && + 0 == report.yAxis && + 0 == report.vWheel && + 0 == report.hWheel) + return; + } sendReportUnchecked(); memcpy(&lastReport, &report, sizeof(report)); From 3447cbea0724c61bd7e0b7d40be4837dfdee43a1 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Thu, 30 Nov 2017 09:28:37 +0100 Subject: [PATCH 491/602] Mouse: Simplified empty report comparison Instead of comparing each member of the report against zero, compare against an empty report with one sweeping `memcmp`. This makes the code smaller, easier to understand, and safer too: if the report gains or loses elements, compilation will fail until the empty report is updated too. This costs about 6 bytes of RAM, an acceptable price. Signed-off-by: Gergely Nagy --- plugins/KeyboardioHID/src/MultiReport/Mouse.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp index 542f138876..5b25183b9c 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp @@ -121,14 +121,10 @@ void Mouse_::sendReport(void) { // if the two reports are the same, check if they're empty, and return early // without a report if they are. - if (memcmp(&lastReport, &report, sizeof(report)) == 0) { - if (0 == report.buttons && - 0 == report.xAxis && - 0 == report.yAxis && - 0 == report.vWheel && - 0 == report.hWheel) - return; - } + static HID_MouseReport_Data_t emptyReport; + if (memcmp(&lastReport, &report, sizeof(report)) == 0 && + memcmp(&report, &emptyReport, sizeof(report)) == 0) + return; sendReportUnchecked(); memcpy(&lastReport, &report, sizeof(report)); From 80bbe3a3986c1a12771f2952c8d66a85b6166795 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Thu, 30 Nov 2017 14:31:34 +0100 Subject: [PATCH 492/602] Mouse: Rework the USB descriptors Instead of bundling X, Y, and Wheel together, pull out the latter, split it into resolution modifier + wheel, and base the horizontal wheel on top of that. Functionally, this should be the same, just structured in a different way. This seems to upset at least Linux a lot less, and will hopefully fix #18. Signed-off-by: Gergely Nagy --- .../KeyboardioHID/src/DescriptorPrimitives.h | 5 + .../KeyboardioHID/src/MultiReport/Mouse.cpp | 93 ++++++++++++------- 2 files changed, 66 insertions(+), 32 deletions(-) diff --git a/plugins/KeyboardioHID/src/DescriptorPrimitives.h b/plugins/KeyboardioHID/src/DescriptorPrimitives.h index 54672f9a42..4ef0a8726a 100644 --- a/plugins/KeyboardioHID/src/DescriptorPrimitives.h +++ b/plugins/KeyboardioHID/src/DescriptorPrimitives.h @@ -14,9 +14,14 @@ #define D_LOGICAL_MINIMUM 0x15 #define D_LOGICAL_MAXIMUM 0x25 +#define D_PHYSICAL_MINIMUM 0x35 +#define D_PHYSICAL_MAXIMUM 0x45 + #define D_REPORT_SIZE 0x75 #define D_REPORT_COUNT 0x95 +#define D_PUSH 0xa4 +#define D_POP 0xb4 // USB HID DCD 1.11 section 6.2.2.4 - Main items // diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp index 1fb32b489c..a3328f8a52 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp @@ -26,45 +26,74 @@ THE SOFTWARE. static const uint8_t _hidMultiReportDescriptorMouse[] PROGMEM = { /* Mouse relative */ - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) 54 */ - D_USAGE, D_USAGE_MOUSE, /* USAGE (Mouse) */ - D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ - D_REPORT_ID, HID_REPORTID_MOUSE, /* REPORT_ID */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, // USAGE_PAGE (Generic Desktop) + D_USAGE, D_USAGE_MOUSE, // USAGE (Mouse) + D_COLLECTION, D_APPLICATION, // COLLECTION (Application) + D_REPORT_ID, HID_REPORTID_MOUSE, // REPORT_ID (Mouse) /* 8 Buttons */ - D_USAGE_PAGE, D_PAGE_BUTTON, /* USAGE_PAGE (Button) */ - D_USAGE_MINIMUM, 0x01, /* USAGE_MINIMUM (Button 1) */ - D_USAGE_MAXIMUM, 0x08, /* USAGE_MAXIMUM (Button 8) */ - D_LOGICAL_MINIMUM, 0x00, /* LOGICAL_MINIMUM (0) */ - D_LOGICAL_MAXIMUM, 0x01, /* LOGICAL_MAXIMUM (1) */ - D_REPORT_COUNT, 0x08, /* REPORT_COUNT (8) */ - D_REPORT_SIZE, 0x01, /* REPORT_SIZE (1) */ - D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ - - /* X, Y, Wheel */ - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ - D_USAGE, 0x30, /* USAGE (X) */ - D_USAGE, 0x31, /* USAGE (Y) */ - D_USAGE, 0x38, /* USAGE (Wheel) */ - D_LOGICAL_MINIMUM, 0x81, /* LOGICAL_MINIMUM (-127) */ - D_LOGICAL_MAXIMUM, 0x7f, /* LOGICAL_MAXIMUM (127) */ - D_REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ - D_REPORT_COUNT, 0x03, /* REPORT_COUNT (3) */ - D_INPUT, (D_DATA|D_VARIABLE|D_RELATIVE), /* INPUT (Data,Var,Rel) */ + D_USAGE_PAGE, D_PAGE_BUTTON, // USAGE_PAGE (Button) + D_USAGE_MINIMUM, 0x01, // USAGE_MINIMUM (Button 1) + D_USAGE_MAXIMUM, 0x08, // USAGE_MAXIMUM (Button 8) + D_LOGICAL_MINIMUM, 0x00, // LOGICAL_MINIMUM (0) + D_LOGICAL_MAXIMUM, 0x01, // LOGICAL_MAXIMUM (1) + D_REPORT_COUNT, 0x08, // REPORT_COUNT (8) + D_REPORT_SIZE, 0x01, // REPORT_SIZE (1) + D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), // INPUT (Data,Var,Abs) + + /* X, Y */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, // USAGE_PAGE (Generic Desktop) + D_USAGE, 0x30, // USAGE (X) + D_USAGE, 0x31, // USAGE (Y) + D_LOGICAL_MINIMUM, 0x81, // LOGICAL_MINIMUM (-127) + D_LOGICAL_MAXIMUM, 0x7f, // LOGICAL_MAXIMUM (127) + D_REPORT_SIZE, 0x08, // REPORT_SIZE (8) + D_REPORT_COUNT, 0x02, // REPORT_COUNT (3) + D_INPUT, (D_DATA|D_VARIABLE|D_RELATIVE), // INPUT (Data,Var,Rel) + + /* Wheels */ + + /* Vertical wheel */ + D_COLLECTION, D_LOGICAL, // COLLECTION (Logical) + D_USAGE, 0x48, // USAGE (Resolution Multiplier) + D_LOGICAL_MINIMUM, 0x00, // LOGICAL_MINIMUM (0) + D_LOGICAL_MAXIMUM, 0x01, // LOGICAL_MAXIMUM (1) + D_PHYSICAL_MINIMUM, 0x01, // PHYSICAL_MINIMUM (1) + D_PHYSICAL_MAXIMUM, 0x04, // PHYSICAL_MAXIMUM (4) + D_REPORT_SIZE, 0x02, // REPORT_SIZE (2) + D_REPORT_COUNT, 0x01, // REPORT_COUNT (1) + D_PUSH, // PUSH + D_FEATURE, (D_DATA|D_VARIABLE|D_ABSOLUTE), // FEATURE (Data,Var,Abs) + D_USAGE, 0x38, // USAGE (Wheel) + D_LOGICAL_MINIMUM, 0x81, // LOGICAL_MINIMUM (-127) + D_LOGICAL_MAXIMUM, 0x7f, // LOGICAL_MAXIMUM (127) + D_PHYSICAL_MINIMUM, 0x00, // PHYSICAL_MINIMUM (0) + D_PHYSICAL_MAXIMUM, 0x00, // PHYSICAL_MAXIMUM (0) + D_REPORT_SIZE, 0x08, // REPORT_SIZE (8) + D_INPUT, (D_DATA|D_VARIABLE|D_RELATIVE), // INPUT (Data,Var,Rel) + D_END_COLLECTION, // END_COLLECTION /* Horizontal wheel */ - D_USAGE_PAGE, D_PAGE_CONSUMER, /* USAGE_PAGE (Consumer Device) */ - D_PAGE_ORDINAL, 0x38, 0x02, - D_USAGE_MINIMUM, 0x81, - D_USAGE_MAXIMUM, 0x7f, - D_REPORT_SIZE, 0x08, - D_REPORT_COUNT, 0x01, - D_INPUT, (D_DATA|D_VARIABLE|D_RELATIVE), + D_COLLECTION, D_LOGICAL, // COLLECTION (Logical) + D_USAGE, 0x48, // USAGE (Resolution Multiplier) + D_POP, // POP + D_FEATURE, (D_DATA|D_VARIABLE|D_ABSOLUTE), // FEATURE (Data,Var,Abs) + D_PHYSICAL_MINIMUM, 0x00, // PHYSICAL_MINIMUM (0) -- padding start + D_PHYSICAL_MAXIMUM, 0x00, // PHYSICAL_MAXIMUM (0) + D_REPORT_SIZE, 0x04, // REPORT_SIZE (4) + D_FEATURE, (D_CONSTANT|D_VARIABLE|D_ABSOLUTE), // FEATURE (Const,Var,Abs) -- padding end + D_USAGE_PAGE, D_PAGE_CONSUMER, // USAGE_PAGE (Consumer) + D_PAGE_ORDINAL, 0x38, 0x02, // PAGE (AC Pan) + D_LOGICAL_MINIMUM, 0x81, // LOGICAL_MINIMUM (-127) + D_LOGICAL_MAXIMUM, 0x7f, // LOGICAL_MAXIMUM (127) + D_REPORT_SIZE, 0x08, // REPORT_SIZE (8) + D_INPUT, (D_DATA|D_VARIABLE|D_RELATIVE), // INPUT (Data,Var,Rel) + D_END_COLLECTION, // END_COLLECTION + /* End */ - D_END_COLLECTION /* END_COLLECTION */ + D_END_COLLECTION // END_COLLECTION }; - Mouse_::Mouse_(void) { static HIDSubDescriptor node(_hidMultiReportDescriptorMouse, sizeof(_hidMultiReportDescriptorMouse)); HID().AppendDescriptor(&node); From 95fa7466b408decd61608155f3ba90e4e12b85c5 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Fri, 1 Dec 2017 18:40:11 +0100 Subject: [PATCH 493/602] Mouse: Append the descriptor late, in Mouse.begin Because `Mouse` is *always* instantiated, the constructor always runs, and thus, the node is always registered whenever the `Mouse` object is referenced, even if done so in code that gets optimized out. To combat this, and allow the compiler to optimize out `Mouse` fully, do the append in `Mouse.begin`. This way, if the `Mouse` global is referenced by code that gets optimized out, the constructor will be optimized out, allowing the full object to get dropped. As we call `Mouse.begin` during `setup`, there is no risk doing a late append, either. This addresses the most important part of keyboardio/Kaleidoscope#257. Signed-off-by: Gergely Nagy --- plugins/KeyboardioHID/src/MultiReport/Mouse.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp index a5073bb2d4..8dd7a3f89f 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp @@ -95,11 +95,12 @@ static const uint8_t _hidMultiReportDescriptorMouse[] PROGMEM = { }; Mouse_::Mouse_(void) { - static HIDSubDescriptor node(_hidMultiReportDescriptorMouse, sizeof(_hidMultiReportDescriptorMouse)); - HID().AppendDescriptor(&node); } void Mouse_::begin(void) { + static HIDSubDescriptor node(_hidMultiReportDescriptorMouse, sizeof(_hidMultiReportDescriptorMouse)); + HID().AppendDescriptor(&node); + end(); } From 67cb9d83eb505faec3bc14ae9ae225a15225cdb4 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Fri, 8 Dec 2017 01:11:38 +0100 Subject: [PATCH 494/602] Revert the Mouse USB HID descriptor change, and fix hWheel better As it turns out, the *real* problem was two typos, `D_USAGE_MINIMUM` and `D_USAGE_MAXIMUM` were used in the horizontal wheel descriptor instead of `D_LOGICAL_MINIMUM` and `D_LOGICAL_MAXIMUM`. This patch reverts the previous USB HID descriptor rework, and fixes the horizontal wheel descriptor only, saving us some 46 bytes of program space. Signed-off-by: Gergely Nagy --- .../KeyboardioHID/src/MultiReport/Mouse.cpp | 93 +++++++------------ 1 file changed, 32 insertions(+), 61 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp index a5073bb2d4..6bb8763edf 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp @@ -26,74 +26,45 @@ THE SOFTWARE. static const uint8_t _hidMultiReportDescriptorMouse[] PROGMEM = { /* Mouse relative */ - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, // USAGE_PAGE (Generic Desktop) - D_USAGE, D_USAGE_MOUSE, // USAGE (Mouse) - D_COLLECTION, D_APPLICATION, // COLLECTION (Application) - D_REPORT_ID, HID_REPORTID_MOUSE, // REPORT_ID (Mouse) + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) 54 */ + D_USAGE, D_USAGE_MOUSE, /* USAGE (Mouse) */ + D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ + D_REPORT_ID, HID_REPORTID_MOUSE, /* REPORT_ID */ /* 8 Buttons */ - D_USAGE_PAGE, D_PAGE_BUTTON, // USAGE_PAGE (Button) - D_USAGE_MINIMUM, 0x01, // USAGE_MINIMUM (Button 1) - D_USAGE_MAXIMUM, 0x08, // USAGE_MAXIMUM (Button 8) - D_LOGICAL_MINIMUM, 0x00, // LOGICAL_MINIMUM (0) - D_LOGICAL_MAXIMUM, 0x01, // LOGICAL_MAXIMUM (1) - D_REPORT_COUNT, 0x08, // REPORT_COUNT (8) - D_REPORT_SIZE, 0x01, // REPORT_SIZE (1) - D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), // INPUT (Data,Var,Abs) - - /* X, Y */ - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, // USAGE_PAGE (Generic Desktop) - D_USAGE, 0x30, // USAGE (X) - D_USAGE, 0x31, // USAGE (Y) - D_LOGICAL_MINIMUM, 0x81, // LOGICAL_MINIMUM (-127) - D_LOGICAL_MAXIMUM, 0x7f, // LOGICAL_MAXIMUM (127) - D_REPORT_SIZE, 0x08, // REPORT_SIZE (8) - D_REPORT_COUNT, 0x02, // REPORT_COUNT (3) - D_INPUT, (D_DATA|D_VARIABLE|D_RELATIVE), // INPUT (Data,Var,Rel) - - /* Wheels */ - - /* Vertical wheel */ - D_COLLECTION, D_LOGICAL, // COLLECTION (Logical) - D_USAGE, 0x48, // USAGE (Resolution Multiplier) - D_LOGICAL_MINIMUM, 0x00, // LOGICAL_MINIMUM (0) - D_LOGICAL_MAXIMUM, 0x01, // LOGICAL_MAXIMUM (1) - D_PHYSICAL_MINIMUM, 0x01, // PHYSICAL_MINIMUM (1) - D_PHYSICAL_MAXIMUM, 0x04, // PHYSICAL_MAXIMUM (4) - D_REPORT_SIZE, 0x02, // REPORT_SIZE (2) - D_REPORT_COUNT, 0x01, // REPORT_COUNT (1) - D_PUSH, // PUSH - D_FEATURE, (D_DATA|D_VARIABLE|D_ABSOLUTE), // FEATURE (Data,Var,Abs) - D_USAGE, 0x38, // USAGE (Wheel) - D_LOGICAL_MINIMUM, 0x81, // LOGICAL_MINIMUM (-127) - D_LOGICAL_MAXIMUM, 0x7f, // LOGICAL_MAXIMUM (127) - D_PHYSICAL_MINIMUM, 0x00, // PHYSICAL_MINIMUM (0) - D_PHYSICAL_MAXIMUM, 0x00, // PHYSICAL_MAXIMUM (0) - D_REPORT_SIZE, 0x08, // REPORT_SIZE (8) - D_INPUT, (D_DATA|D_VARIABLE|D_RELATIVE), // INPUT (Data,Var,Rel) - D_END_COLLECTION, // END_COLLECTION + D_USAGE_PAGE, D_PAGE_BUTTON, /* USAGE_PAGE (Button) */ + D_USAGE_MINIMUM, 0x01, /* USAGE_MINIMUM (Button 1) */ + D_USAGE_MAXIMUM, 0x08, /* USAGE_MAXIMUM (Button 8) */ + D_LOGICAL_MINIMUM, 0x00, /* LOGICAL_MINIMUM (0) */ + D_LOGICAL_MAXIMUM, 0x01, /* LOGICAL_MAXIMUM (1) */ + D_REPORT_COUNT, 0x08, /* REPORT_COUNT (8) */ + D_REPORT_SIZE, 0x01, /* REPORT_SIZE (1) */ + D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ + + /* X, Y, Wheel */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ + D_USAGE, 0x30, /* USAGE (X) */ + D_USAGE, 0x31, /* USAGE (Y) */ + D_USAGE, 0x38, /* USAGE (Wheel) */ + D_LOGICAL_MINIMUM, 0x81, /* LOGICAL_MINIMUM (-127) */ + D_LOGICAL_MAXIMUM, 0x7f, /* LOGICAL_MAXIMUM (127) */ + D_REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ + D_REPORT_COUNT, 0x03, /* REPORT_COUNT (3) */ + D_INPUT, (D_DATA|D_VARIABLE|D_RELATIVE), /* INPUT (Data,Var,Rel) */ /* Horizontal wheel */ - D_COLLECTION, D_LOGICAL, // COLLECTION (Logical) - D_USAGE, 0x48, // USAGE (Resolution Multiplier) - D_POP, // POP - D_FEATURE, (D_DATA|D_VARIABLE|D_ABSOLUTE), // FEATURE (Data,Var,Abs) - D_PHYSICAL_MINIMUM, 0x00, // PHYSICAL_MINIMUM (0) -- padding start - D_PHYSICAL_MAXIMUM, 0x00, // PHYSICAL_MAXIMUM (0) - D_REPORT_SIZE, 0x04, // REPORT_SIZE (4) - D_FEATURE, (D_CONSTANT|D_VARIABLE|D_ABSOLUTE), // FEATURE (Const,Var,Abs) -- padding end - D_USAGE_PAGE, D_PAGE_CONSUMER, // USAGE_PAGE (Consumer) - D_PAGE_ORDINAL, 0x38, 0x02, // PAGE (AC Pan) - D_LOGICAL_MINIMUM, 0x81, // LOGICAL_MINIMUM (-127) - D_LOGICAL_MAXIMUM, 0x7f, // LOGICAL_MAXIMUM (127) - D_REPORT_SIZE, 0x08, // REPORT_SIZE (8) - D_INPUT, (D_DATA|D_VARIABLE|D_RELATIVE), // INPUT (Data,Var,Rel) - D_END_COLLECTION, // END_COLLECTION - + D_USAGE_PAGE, D_PAGE_CONSUMER, /* USAGE_PAGE (Consumer Device) */ + D_PAGE_ORDINAL, 0x38, 0x02, + D_LOGICAL_MINIMUM, 0x81, + D_LOGICAL_MAXIMUM, 0x7f, + D_REPORT_SIZE, 0x08, + D_REPORT_COUNT, 0x01, + D_INPUT, (D_DATA|D_VARIABLE|D_RELATIVE), /* End */ - D_END_COLLECTION // END_COLLECTION + D_END_COLLECTION /* END_COLLECTION */ }; + Mouse_::Mouse_(void) { static HIDSubDescriptor node(_hidMultiReportDescriptorMouse, sizeof(_hidMultiReportDescriptorMouse)); HID().AppendDescriptor(&node); From 6e798eebf36b18076ffc855f3b9874167e24b73e Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Thu, 7 Dec 2017 17:36:40 -0800 Subject: [PATCH 495/602] Mouse: Cleaned up the comments on the descriptor This makes catching potential issues easier. --- .../KeyboardioHID/src/MultiReport/Mouse.cpp | 59 +++++++++---------- 1 file changed, 29 insertions(+), 30 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp index 6bb8763edf..9600fcca91 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp @@ -26,45 +26,44 @@ THE SOFTWARE. static const uint8_t _hidMultiReportDescriptorMouse[] PROGMEM = { /* Mouse relative */ - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) 54 */ - D_USAGE, D_USAGE_MOUSE, /* USAGE (Mouse) */ - D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ - D_REPORT_ID, HID_REPORTID_MOUSE, /* REPORT_ID */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, // USAGE_PAGE (Generic Desktop) + D_USAGE, D_USAGE_MOUSE, // USAGE (Mouse) + D_COLLECTION, D_APPLICATION, // COLLECTION (Application) + D_REPORT_ID, HID_REPORTID_MOUSE, // REPORT_ID (Mouse) /* 8 Buttons */ - D_USAGE_PAGE, D_PAGE_BUTTON, /* USAGE_PAGE (Button) */ - D_USAGE_MINIMUM, 0x01, /* USAGE_MINIMUM (Button 1) */ - D_USAGE_MAXIMUM, 0x08, /* USAGE_MAXIMUM (Button 8) */ - D_LOGICAL_MINIMUM, 0x00, /* LOGICAL_MINIMUM (0) */ - D_LOGICAL_MAXIMUM, 0x01, /* LOGICAL_MAXIMUM (1) */ - D_REPORT_COUNT, 0x08, /* REPORT_COUNT (8) */ - D_REPORT_SIZE, 0x01, /* REPORT_SIZE (1) */ - D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ + D_USAGE_PAGE, D_PAGE_BUTTON, // USAGE_PAGE (Button) + D_USAGE_MINIMUM, 0x01, // USAGE_MINIMUM (Button 1) + D_USAGE_MAXIMUM, 0x08, // USAGE_MAXIMUM (Button 8) + D_LOGICAL_MINIMUM, 0x00, // LOGICAL_MINIMUM (0) + D_LOGICAL_MAXIMUM, 0x01, // LOGICAL_MAXIMUM (1) + D_REPORT_COUNT, 0x08, // REPORT_COUNT (8) + D_REPORT_SIZE, 0x01, // REPORT_SIZE (1) + D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), // INPUT (Data,Var,Abs) /* X, Y, Wheel */ - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ - D_USAGE, 0x30, /* USAGE (X) */ - D_USAGE, 0x31, /* USAGE (Y) */ - D_USAGE, 0x38, /* USAGE (Wheel) */ - D_LOGICAL_MINIMUM, 0x81, /* LOGICAL_MINIMUM (-127) */ - D_LOGICAL_MAXIMUM, 0x7f, /* LOGICAL_MAXIMUM (127) */ - D_REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ - D_REPORT_COUNT, 0x03, /* REPORT_COUNT (3) */ - D_INPUT, (D_DATA|D_VARIABLE|D_RELATIVE), /* INPUT (Data,Var,Rel) */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, // USAGE_PAGE (Generic Desktop) + D_USAGE, 0x30, // USAGE (X) + D_USAGE, 0x31, // USAGE (Y) + D_USAGE, 0x38, // USAGE (Wheel) + D_LOGICAL_MINIMUM, 0x81, // LOGICAL_MINIMUM (-127) + D_LOGICAL_MAXIMUM, 0x7f, // LOGICAL_MAXIMUM (127) + D_REPORT_SIZE, 0x08, // REPORT_SIZE (8) + D_REPORT_COUNT, 0x03, // REPORT_COUNT (3) + D_INPUT, (D_DATA|D_VARIABLE|D_RELATIVE), // INPUT (Data,Var,Rel) /* Horizontal wheel */ - D_USAGE_PAGE, D_PAGE_CONSUMER, /* USAGE_PAGE (Consumer Device) */ - D_PAGE_ORDINAL, 0x38, 0x02, - D_LOGICAL_MINIMUM, 0x81, - D_LOGICAL_MAXIMUM, 0x7f, - D_REPORT_SIZE, 0x08, - D_REPORT_COUNT, 0x01, - D_INPUT, (D_DATA|D_VARIABLE|D_RELATIVE), + D_USAGE_PAGE, D_PAGE_CONSUMER, // USAGE_PAGE (Consumer) + D_PAGE_ORDINAL, 0x38, 0x02, // PAGE (AC Pan) + D_LOGICAL_MINIMUM, 0x81, // LOGICAL_MINIMUM (-127) + D_LOGICAL_MAXIMUM, 0x7f, // LOGICAL_MAXIMUM (127) + D_REPORT_SIZE, 0x08, // REPORT_SIZE (8) + D_INPUT, (D_DATA|D_VARIABLE|D_RELATIVE), // INPUT (Data,Var,Rel) + /* End */ - D_END_COLLECTION /* END_COLLECTION */ + D_END_COLLECTION // END_COLLECTION }; - Mouse_::Mouse_(void) { static HIDSubDescriptor node(_hidMultiReportDescriptorMouse, sizeof(_hidMultiReportDescriptorMouse)); HID().AppendDescriptor(&node); From e1388f569b7b583e4b78b30cc9a7148c2b429d5f Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Wed, 20 Dec 2017 23:37:38 +0100 Subject: [PATCH 496/602] Keyboard: Don't skip NONUS_POUND and CLEAR To be able to send NONUS_POUND and CLEAR keycodes, we need our report bitmap to support them, and not mask them over with constants. These were originally masked due to bugs in the Linux kernel: it treats NONUS_POUND the same as BACKSLASH, and CLEAR the same as DELETE. There is no way for userland to distinguish the two under Linux. But this is a linux-specific issue, one that is not relevant when neither NONUS_POUND or CLEAR appear on the keymap. Linux will happily accept a descriptor that does not mask this out (even ancient versions, going back 13 years). It will not double-press if these appear in the report. At worst, repeat will kick in faster if both BACKSLASH and NONUS_POUND are held at the same time. However, other OSes may - and do - work differently, and some of them handle NONUS_POUND separately from BACKSLASH. Because not masking out these keys in the report causes no issues under Linux (the only reason for the mask) unless the keys are in the report, and even then, the issue is not critical, we should not punish other operating systems. Linux has had this issue for at least 13 years (7 for CLEAR/DELETE). Changing it would require changes to the kernel and a whole lot of userland too. I do not see that happening in my lifetime, and that's even more reason for not waiting for Linux to get rid of the bug before changing the descriptors. Therefore, this patch removes the mask, and only the first four bits remain masked. Therefore, operating systems that can treat NONUS_POUND and CLEAR separately from BACKSLASH and DELETE will be able to do that, and Linux will not be severely impacted either. And we also save a few bytes. Fixes keyboardio/Kaleidoscope#273. Signed-off-by: Gergely Nagy --- .../src/MultiReport/Keyboard.cpp | 48 ++----------------- 1 file changed, 5 insertions(+), 43 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index eb67da8889..95c0d15e37 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -51,62 +51,24 @@ static const uint8_t _hidMultiReportDescriptorKeyboard[] PROGMEM = { D_REPORT_SIZE, 0x01, D_OUTPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), -// USB Code not within 4-49 (0x4-0x31), 51-155 (0x33-0x9B), 157-164 (0x9D-0xA4), -// 176-221 (0xB0-0xDD) or 224-231 (0xE0-0xE7) NKRO Mode /* NKRO Keyboard */ D_USAGE_PAGE, D_PAGE_KEYBOARD, - // Padding 3 bits - // To skip HID_KEYBOARD_NON_US_POUND_AND_TILDE, which causes - // Linux to choke on our driver. + // Padding 4 bits, to skip NO_EVENT & 3 error states. D_REPORT_SIZE, 0x04, D_REPORT_COUNT, 0x01, D_INPUT, (D_CONSTANT), - D_USAGE_MINIMUM, HID_KEYBOARD_A_AND_A, - D_USAGE_MAXIMUM, HID_KEYBOARD_BACKSLASH_AND_PIPE, - D_LOGICAL_MINIMUM, 0x00, - D_LOGICAL_MAXIMUM, 0x01, - D_REPORT_SIZE, 0x01, - D_REPORT_COUNT, (HID_KEYBOARD_BACKSLASH_AND_PIPE - HID_KEYBOARD_A_AND_A)+1, - D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), - - // Padding 1 bit. - // To skip HID_KEYBOARD_NON_US_POUND_AND_TILDE, which causes - // Linux to choke on our driver. - D_REPORT_SIZE, 0x01, - D_REPORT_COUNT, 0x01, - D_INPUT, (D_CONSTANT), - - - D_USAGE_MINIMUM, HID_KEYBOARD_SEMICOLON_AND_COLON, - D_USAGE_MAXIMUM, HID_KEYBOARD_CANCEL, + D_USAGE_MAXIMUM, HID_LAST_KEY, D_LOGICAL_MINIMUM, 0x00, D_LOGICAL_MAXIMUM, 0x01, D_REPORT_SIZE, 0x01, - D_REPORT_COUNT, (HID_KEYBOARD_CANCEL-HID_KEYBOARD_SEMICOLON_AND_COLON) +1, + D_REPORT_COUNT, (HID_LAST_KEY - HID_KEYBOARD_A_AND_A), D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), - - // Padding 1 bit. - // To skip HID_KEYBOARD_CLEAR, which causes - // Linux to choke on our driver. - D_REPORT_SIZE, 0x01, - D_REPORT_COUNT, 0x01, - D_INPUT, (D_CONSTANT), - - D_USAGE_MINIMUM, HID_KEYBOARD_PRIOR, - D_USAGE_MAXIMUM, HID_KEYPAD_HEXADECIMAL, - D_LOGICAL_MINIMUM, 0x00, - D_LOGICAL_MAXIMUM, 0x01, - D_REPORT_SIZE, 0x01, - D_REPORT_COUNT, (HID_KEYPAD_HEXADECIMAL - HID_KEYBOARD_PRIOR) +1, - D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), - - - // Padding (w bits) - D_REPORT_SIZE, 0x02, + // Padding (3 bits) to round up the report to byte boundary. + D_REPORT_SIZE, 0x03, D_REPORT_COUNT, 0x01, D_INPUT, (D_CONSTANT), From 9327c1ca8656b2c8f30223136a6967c657f9a751 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Fri, 1 Dec 2017 13:32:44 +0100 Subject: [PATCH 497/602] BootKeyboard: Add a sendReport guard, and implement is/wasModifierActive Signed-off-by: Gergely Nagy --- .../src/BootKeyboard/BootKeyboard.cpp | 30 ++++++++++++++++++- .../src/BootKeyboard/BootKeyboard.h | 5 ++-- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 0f85f2e94c..db4247a556 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -208,7 +208,13 @@ uint8_t BootKeyboard_::getProtocol(void) { } int BootKeyboard_::sendReport(void) { - return USB_Send(pluggedEndpoint | TRANSFER_RELEASE, &_keyReport, sizeof(_keyReport)); + if (memcmp(&_lastKeyReport, &_keyReport, sizeof(_keyReport))) { + // if the two reports are different, send a report + int returnCode = USB_Send(pluggedEndpoint | TRANSFER_RELEASE, &_keyReport, sizeof(_keyReport)); + memcpy(&_lastKeyReport, &_keyReport, sizeof(_keyReport)); + return returnCode; + } + return -1; } void BootKeyboard_::wakeupHost(void) { @@ -304,4 +310,26 @@ void BootKeyboard_::releaseAll(void) { memset(&_keyReport.keys, 0x00, sizeof(_keyReport.keys)); } +/* Returns true if the modifer key passed in will be sent during this key report + * Returns false in all other cases + * */ +boolean BootKeyboard_::isModifierActive(uint8_t k) { + if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { + k = k - HID_KEYBOARD_FIRST_MODIFIER; + return !!(_keyReport.modifiers & (1 << k)); + } + return false; +} + +/* Returns true if the modifer key passed in was being sent during the previous key report + * Returns false in all other cases + * */ +boolean BootKeyboard_::wasModifierActive(uint8_t k) { + if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { + k = k - HID_KEYBOARD_FIRST_MODIFIER; + return !!(_lastKeyReport.modifiers & (1 << k)); + } + return false; +} + BootKeyboard_ BootKeyboard; diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index ad3105542e..9f6e78983e 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -53,7 +53,8 @@ class BootKeyboard_ : public PluggableUSBModule { int sendReport(void); - + boolean isModifierActive(uint8_t k); + boolean wasModifierActive(uint8_t k); uint8_t getLeds(void); uint8_t getProtocol(void); @@ -86,7 +87,7 @@ class BootKeyboard_ : public PluggableUSBModule { protected: - HID_BootKeyboardReport_Data_t _keyReport; + HID_BootKeyboardReport_Data_t _keyReport, _lastKeyReport; // Implementation of the PUSBListNode int getInterface(uint8_t* interfaceCount); From d9e5b72d1ecf637825bc38f9a76d9f4e34c56d30 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Fri, 1 Dec 2017 13:39:17 +0100 Subject: [PATCH 498/602] BootKeyboard: Remove the (unused) consumer reports BootKeyboard does not implement consumer reports, drop that from the descriptor, saving us a few bytes of code space. Signed-off-by: Gergely Nagy --- .../KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp | 11 ----------- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h | 3 +-- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index db4247a556..505bc8d635 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -39,17 +39,6 @@ static const uint8_t _hidReportDescriptorKeyboard[] PROGMEM = { 0x95, 0x08, /* REPORT_COUNT (8) */ 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - /* Reserved byte, used for consumer reports, only works with linux */ - /* NOT CURRENTLY USED BY THIS IMPLEMENTATION */ - 0x05, 0x0C, /* Usage Page (Consumer) */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0x75, 0x08, /* REPORT_SIZE (8) */ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ - 0x26, 0xFF, 0x00, /* LOGICAL_MAXIMUM (255) */ - 0x19, 0x00, /* USAGE_MINIMUM (0) */ - 0x29, 0xFF, /* USAGE_MAXIMUM (255) */ - 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ - /* 5 LEDs for num lock etc, 3 left for advanced, custom usage */ 0x05, 0x08, /* USAGE_PAGE (LEDs) */ 0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */ diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index 9f6e78983e..e02bc083bb 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -35,10 +35,9 @@ typedef union { // Low level key report: up to 6 keys and shift, ctrl etc at once struct { uint8_t modifiers; - uint8_t reserved; uint8_t keycodes[6]; }; - uint8_t keys[8]; + uint8_t keys[7]; } HID_BootKeyboardReport_Data_t; From 1c720603469143823762647931efedd2f13e9910 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Fri, 1 Dec 2017 15:01:29 +0100 Subject: [PATCH 499/602] BootKeyboard: Allow setting a default protocol To support OSes, BIOSes and other things that may not send a `SET_PROTOCOL` request, allow setting the default protocol. Signed-off-by: Gergely Nagy --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp | 2 +- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 505bc8d635..62a2351e2f 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -92,7 +92,7 @@ int BootKeyboard_::getDescriptor(USBSetup& setup) { // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol // due to the USB specs, but Windows and Linux just assumes its in report mode. - protocol = HID_REPORT_PROTOCOL; + protocol = default_protocol; return USB_SendControl(TRANSFER_PGM, _hidReportDescriptorKeyboard, sizeof(_hidReportDescriptorKeyboard)); } diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index e02bc083bb..b6cbc5c0b1 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -84,6 +84,7 @@ class BootKeyboard_ : public PluggableUSBModule { featureLength |= 0x8000; } + uint8_t default_protocol = HID_REPORT_PROTOCOL; protected: HID_BootKeyboardReport_Data_t _keyReport, _lastKeyReport; From 3a62a8da8f9c840cae7671c1a858bcb9d8305fd9 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Fri, 1 Dec 2017 15:30:17 +0100 Subject: [PATCH 500/602] BootKeyboard: Implement a way to set the protocol forcibly In rare cases it may be desirable to be able to set the report protocol, to force it, and override whatever the host is doing or not doing. The `setProtocol` method does just this. Signed-off-by: Gergely Nagy --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp | 4 ++++ plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h | 1 + 2 files changed, 5 insertions(+) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 62a2351e2f..a730373a46 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -196,6 +196,10 @@ uint8_t BootKeyboard_::getProtocol(void) { return protocol; } +void BootKeyboard_::setProtocol(uint8_t protocol) { + this->protocol = protocol; +} + int BootKeyboard_::sendReport(void) { if (memcmp(&_lastKeyReport, &_keyReport, sizeof(_keyReport))) { // if the two reports are different, send a report diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index b6cbc5c0b1..daa93b0848 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -57,6 +57,7 @@ class BootKeyboard_ : public PluggableUSBModule { uint8_t getLeds(void); uint8_t getProtocol(void); + void setProtocol(uint8_t protocol); void wakeupHost(void); void setFeatureReport(void* report, int length) { From 8454d2c4a3068197eb1fed20466167553d132c47 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Fri, 29 Dec 2017 14:21:47 +0100 Subject: [PATCH 501/602] BootKeyboard: Optimize the report sorting on release Use a smaller algorithm to push the holes in the report to the end. This saves us about 32 bytes of PROGMEM. Signed-off-by: Gergely Nagy --- .../src/BootKeyboard/BootKeyboard.cpp | 29 ++++++++----------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index a730373a46..67a22511c5 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -259,9 +259,6 @@ size_t BootKeyboard_::press(uint8_t k) { // it shouldn't be repeated any more. size_t BootKeyboard_::release(uint8_t k) { - uint8_t i; - uint8_t count; - if ((k >= HID_KEYBOARD_FIRST_MODIFIER) && (k <= HID_KEYBOARD_LAST_MODIFIER)) { // it's a modifier key _keyReport.modifiers = _keyReport.modifiers & (~(0x01 << (k - HID_KEYBOARD_LAST_MODIFIER))); @@ -269,29 +266,27 @@ size_t BootKeyboard_::release(uint8_t k) { // it's some other key: // 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 < sizeof(_keyReport.keycodes); i++) { + for (uint8_t i = 0; i < sizeof(_keyReport.keycodes); i++) { if (_keyReport.keycodes[i] == k) { _keyReport.keycodes[i] = 0; } } - // finally rearrange the keys list so that the free (= 0x00) are at the + // rearrange the keys list so that the free (= 0x00) are at the // end of the keys list - some implementations stop for keys at the // first occurence of an 0x00 in the keys list // so (0x00)(0x01)(0x00)(0x03)(0x02)(0x00) becomes - // (0x01)(0x03)(0x02)(0x00)(0x00)(0x00) - count = 0; // holds the number of zeros we've found - i = 0; - while ((i + count) < sizeof(_keyReport.keycodes)) { - if (0 == _keyReport.keycodes[i]) { - count++; // one more zero - for (uint8_t j = i; j < sizeof(_keyReport.keycodes)-count; j++) { - _keyReport.keycodes[j] = _keyReport.keycodes[j+1]; - } - _keyReport.keycodes[sizeof(_keyReport.keycodes)-count] = 0; - } else { - i++; // one more non-zero + // (0x03)(0x02)(0x01)(0x00)(0x00)(0x00) + uint8_t current = 0, nextpos = 0; + + while (current < sizeof(_keyReport.keycodes)) { + if (_keyReport.keycodes[current]) { + uint8_t tmp = _keyReport.keycodes[nextpos]; + _keyReport.keycodes[nextpos] = _keyReport.keycodes[current]; + _keyReport.keycodes[current] = tmp; + ++nextpos; } + ++current; } } From e3e35e3280258176c2178093cd730ede4e2253ad Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Fri, 29 Dec 2017 16:33:27 +0100 Subject: [PATCH 502/602] BootKeyboard: Drop support for FeatureReport and WakeupHost Neither of them is used by Kaleidoscope, neither of them is implemented by Keyboard, either, so no need to have them here. This saves us another 30 bytes or so. Signed-off-by: Gergely Nagy --- .../src/BootKeyboard/BootKeyboard.cpp | 25 ++------------- .../src/BootKeyboard/BootKeyboard.h | 31 ------------------- 2 files changed, 2 insertions(+), 54 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 67a22511c5..05f1b29a03 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -61,7 +61,7 @@ static const uint8_t _hidReportDescriptorKeyboard[] PROGMEM = { 0xc0 /* END_COLLECTION */ }; -BootKeyboard_::BootKeyboard_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1), leds(0), featureReport(NULL), featureLength(0) { +BootKeyboard_::BootKeyboard_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1), leds(0) { epType[0] = EP_TYPE_INTERRUPT_IN; PluggableUSB().plug(this); } @@ -152,23 +152,7 @@ bool BootKeyboard_::setup(USBSetup& setup) { // Check if data has the correct length afterwards int length = setup.wLength; - // Feature (set feature report) - if (setup.wValueH == HID_REPORT_TYPE_FEATURE) { - // No need to check for negative featureLength values, - // except the host tries to send more then 32k bytes. - // We dont have that much ram anyways. - if (length == featureLength) { - USB_RecvControl(featureReport, featureLength); - - // Block until data is read (make length negative) - disableFeatureReport(); - return true; - } - // TODO fake clear data? - } - - // Output (set led states) - else if (setup.wValueH == HID_REPORT_TYPE_OUTPUT) { + if (setup.wValueH == HID_REPORT_TYPE_OUTPUT) { if (length == sizeof(leds)) { USB_RecvControl(&leds, length); return true; @@ -210,11 +194,6 @@ int BootKeyboard_::sendReport(void) { return -1; } -void BootKeyboard_::wakeupHost(void) { - USBDevice.wakeupHost(); -} - - // 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 diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index daa93b0848..ea54bcb443 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -58,32 +58,6 @@ class BootKeyboard_ : public PluggableUSBModule { uint8_t getLeds(void); uint8_t getProtocol(void); void setProtocol(uint8_t protocol); - void wakeupHost(void); - - void setFeatureReport(void* report, int length) { - if (length > 0) { - featureReport = (uint8_t*)report; - featureLength = length; - - // Disable feature report by default - disableFeatureReport(); - } - } - - int availableFeatureReport(void) { - if (featureLength < 0) { - return featureLength & ~0x8000; - } - return 0; - } - - void enableFeatureReport(void) { - featureLength &= ~0x8000; - } - - void disableFeatureReport(void) { - featureLength |= 0x8000; - } uint8_t default_protocol = HID_REPORT_PROTOCOL; @@ -100,10 +74,5 @@ class BootKeyboard_ : public PluggableUSBModule { uint8_t idle; uint8_t leds; - - uint8_t* featureReport; - int featureLength; }; extern BootKeyboard_ BootKeyboard; - - From 53f678af0e3f69f32e21c2bcac3cb62c9082a53e Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Mon, 15 Jan 2018 13:15:48 +0100 Subject: [PATCH 503/602] Mouse: Add a missing REPORT_COUNT to the horizontal wheel Usage Without a report count, the HID descriptor is invalid, and while Linux and Windows appear to handle that gracefully, OSX does not, and disables the entire device. Fixes #25. Signed-off-by: Gergely Nagy --- plugins/KeyboardioHID/src/MultiReport/Mouse.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp index 36cbc59035..438e6afa87 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp @@ -58,6 +58,7 @@ static const uint8_t _hidMultiReportDescriptorMouse[] PROGMEM = { D_LOGICAL_MINIMUM, 0x81, // LOGICAL_MINIMUM (-127) D_LOGICAL_MAXIMUM, 0x7f, // LOGICAL_MAXIMUM (127) D_REPORT_SIZE, 0x08, // REPORT_SIZE (8) + D_REPORT_COUNT, 0x01, // REPORT_COUNT (1) D_INPUT, (D_DATA|D_VARIABLE|D_RELATIVE), // INPUT (Data,Var,Rel) /* End */ From 979400912d9648e25ad85d9bbc2122665f1156bb Mon Sep 17 00:00:00 2001 From: Michael Richters Date: Mon, 22 Jan 2018 23:06:10 -0600 Subject: [PATCH 504/602] Improved workaround for ChromeOS modifier bug In Kaleidoscope/src/kaleidoscope/hid.cpp, there is a description of a ChromeOS bug that causes certain modifier keys to be missed if they are added in the same Keyboard HID report as a printable keycode (e.g. `shift`+`[`). The workaround there sends an extra report any time `hid::pressKey()` is called with a `Key` that has a modifier flag bit set. That solves the problem in one case, but there are other ways for a report to get sent with both a new modifier and a new normal keycode. There is also the possibility that a plugin might want to stop that report from being sent, and there's also the problem that calling `pressKey()` for a modified key when the report is only partially complete could cause unintentional key release events. This change is a general fix for the problem, regardless of how the bits in the key report got set. I added a check to `Keyboard.sendReport()` to test if any modifier bits changed, and if so, if any were pressed (though we should probably skip that extra check). If so, it copies the modifier byte from the new keyboard report to the old one, and re-sends the (modified) old report before proceeding to compare the old report with the new one, and sending the new report. Waiting to address the problem until `sendReport()` is called should correctly deal with all of the aforementioned issues, though this solution is more complex than the previous one. --- .../KeyboardioHID/src/MultiReport/Keyboard.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index eb67da8889..8cbd362d37 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -139,6 +139,21 @@ int Keyboard_::sendReportUnchecked(void) { int Keyboard_::sendReport(void) { + // ChromeOS 51-60 (at least) bug: if a modifier and a normal keycode are added in the + // same report, in some cases the shift is not applied (e.g. `shift`+`[` doesn't yield + // `{`). To compensate for this, check to see if the modifier byte has changed. If so, + // check to see if any modifier keys have been pressed (probably not necessary to do + // this step, actually). If so, copy the modifier byte to the previous key report, and + // resend it before proceeding. + uint8_t mods_changed = lastKeyReport.modifiers ^ keyReport.modifiers; + if (mods_changed) { + uint8_t mods_pressed = keyReport.modifiers & mods_changed; + if (mods_pressed) { + lastKeyReport.modifiers = keyReport.modifiers; + HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &lastKeyReport, sizeof(lastKeyReport)); + } + } + // If the last report is different than the current report, then we need to send a report. // We guard sendReport like this so that calling code doesn't end up spamming the host with empty reports // if sendReport is called in a tight loop. From 35c8aa077c0c9101065d8aeab3aa6098e4f97a02 Mon Sep 17 00:00:00 2001 From: Michael Richters Date: Mon, 22 Jan 2018 23:27:57 -0600 Subject: [PATCH 505/602] Simplified ChromeOS modifier bug workaround Since it's simpler to just check for any changes to modifier bits than it is to only act on modifier presses, take out the extra check and simplify the code. --- plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index 8cbd362d37..da4a0a6870 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -142,16 +142,10 @@ int Keyboard_::sendReport(void) { // ChromeOS 51-60 (at least) bug: if a modifier and a normal keycode are added in the // same report, in some cases the shift is not applied (e.g. `shift`+`[` doesn't yield // `{`). To compensate for this, check to see if the modifier byte has changed. If so, - // check to see if any modifier keys have been pressed (probably not necessary to do - // this step, actually). If so, copy the modifier byte to the previous key report, and - // resend it before proceeding. - uint8_t mods_changed = lastKeyReport.modifiers ^ keyReport.modifiers; - if (mods_changed) { - uint8_t mods_pressed = keyReport.modifiers & mods_changed; - if (mods_pressed) { - lastKeyReport.modifiers = keyReport.modifiers; - HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &lastKeyReport, sizeof(lastKeyReport)); - } + // copy the modifier byte to the previous key report, and resend it before proceeding. + if (lastKeyReport.modifiers != keyReport.modifiers) { + lastKeyReport.modifiers = keyReport.modifiers; + HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &lastKeyReport, sizeof(lastKeyReport)); } // If the last report is different than the current report, then we need to send a report. From 087fc67c6209ec894a3e3bec423ca939c05a49f7 Mon Sep 17 00:00:00 2001 From: Michael Richters Date: Tue, 23 Jan 2018 22:43:58 -0600 Subject: [PATCH 506/602] Check return value of HID().SendReport() This keeps `lastKeyReport` accurate, but if `SendReport()` fails (and returns -1), I'm not sure what we should really do. Try again after a delay? It seems like merely restoring or not clobbering `lastKeyReport` is only half correct in this case. --- plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index da4a0a6870..ed37a3b9ed 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -144,8 +144,11 @@ int Keyboard_::sendReport(void) { // `{`). To compensate for this, check to see if the modifier byte has changed. If so, // copy the modifier byte to the previous key report, and resend it before proceeding. if (lastKeyReport.modifiers != keyReport.modifiers) { + uint8_t last_mods = lastKeyReport.modifiers; lastKeyReport.modifiers = keyReport.modifiers; - HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &lastKeyReport, sizeof(lastKeyReport)); + int returnCode = HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &lastKeyReport, sizeof(lastKeyReport)); + if (returnCode < 0) + lastKeyReport.modifiers = last_mods; } // If the last report is different than the current report, then we need to send a report. @@ -155,7 +158,8 @@ int Keyboard_::sendReport(void) { if (memcmp(lastKeyReport.allkeys, keyReport.allkeys, sizeof(keyReport))) { // if the two reports are different, send a report int returnCode = sendReportUnchecked(); - memcpy(lastKeyReport.allkeys, keyReport.allkeys, sizeof(keyReport)); + if (returnCode > 0) + memcpy(lastKeyReport.allkeys, keyReport.allkeys, sizeof(keyReport)); return returnCode; } return -1; From 3b6126969e83bf6afb36edc09f8a254da53b4e47 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Mon, 28 May 2018 18:00:41 +0200 Subject: [PATCH 507/602] Fix up BootKeyboard to work under OSX MacOS needs the HID descriptors and the report to have a particular layout. Namely, the descriptors need to have LEDs first, one padding byte, 6KRO keys, and modifiers last. The report must have modifiers first, padding, then the keys. Signed-off-by: Gergely Nagy --- .../src/BootKeyboard/BootKeyboard.cpp | 24 ++++++++++++------- .../src/BootKeyboard/BootKeyboard.h | 1 + 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 05f1b29a03..5f322c557a 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -30,15 +30,6 @@ static const uint8_t _hidReportDescriptorKeyboard[] PROGMEM = { 0xa1, 0x01, /* COLLECTION (Application) */ 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ - /* Keyboard Modifiers (shift, alt, ...) */ - 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) */ - /* 5 LEDs for num lock etc, 3 left for advanced, custom usage */ 0x05, 0x08, /* USAGE_PAGE (LEDs) */ 0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */ @@ -47,6 +38,11 @@ static const uint8_t _hidReportDescriptorKeyboard[] PROGMEM = { 0x75, 0x01, /* REPORT_SIZE (1) */ 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */ + // 1 byte padding, needed for OSX + 0x75, 0x08, /* REPORT_COUNT (8) */ + 0x95, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x01, /* INPUT (Data, Const) */ + /* 6 Keyboard keys */ 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ 0x95, 0x06, /* REPORT_COUNT (6) */ @@ -57,6 +53,16 @@ static const uint8_t _hidReportDescriptorKeyboard[] PROGMEM = { 0x29, 0xE7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ + /* Keyboard Modifiers (shift, alt, ...) */ + 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) */ + + /* End */ 0xc0 /* END_COLLECTION */ }; diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index ea54bcb443..5729a265d1 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -35,6 +35,7 @@ typedef union { // Low level key report: up to 6 keys and shift, ctrl etc at once struct { uint8_t modifiers; + uint8_t __padding; uint8_t keycodes[6]; }; uint8_t keys[7]; From b5688a5b358d208ca963e30d8ea7f10be1fe082d Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Mon, 28 May 2018 21:21:13 +0200 Subject: [PATCH 508/602] BootKeyboard: Use the HID descriptor macros Fixes #33. Signed-off-by: Gergely Nagy --- .../src/BootKeyboard/BootKeyboard.cpp | 69 ++++++++++--------- 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 5f322c557a..21481a9332 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -22,49 +22,50 @@ THE SOFTWARE. */ #include "BootKeyboard.h" +#include "DescriptorPrimitives.h" static const uint8_t _hidReportDescriptorKeyboard[] PROGMEM = { // Keyboard - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 47 */ - 0x09, 0x06, /* USAGE (Keyboard) */ - 0xa1, 0x01, /* COLLECTION (Application) */ - 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, + D_USAGE, D_USAGE_KEYBOARD, + D_COLLECTION, D_APPLICATION, + D_USAGE_PAGE, D_PAGE_KEYBOARD, /* 5 LEDs for num lock etc, 3 left for advanced, custom usage */ - 0x05, 0x08, /* USAGE_PAGE (LEDs) */ - 0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */ - 0x29, 0x08, /* USAGE_MAXIMUM (Kana + 3 custom)*/ - 0x95, 0x08, /* REPORT_COUNT (8) */ - 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */ - - // 1 byte padding, needed for OSX - 0x75, 0x08, /* REPORT_COUNT (8) */ - 0x95, 0x01, /* REPORT_SIZE (1) */ - 0x81, 0x01, /* INPUT (Data, Const) */ + D_USAGE_PAGE, D_PAGE_LEDS, + D_USAGE_MINIMUM, 0x01, + D_USAGE_MAXIMUM, 0x08, + D_REPORT_COUNT, 0x08, + D_REPORT_SIZE, 0x01, + D_OUTPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), + + /* 1 byte padding, needed for OSX. + * Tested on High Sierra, with FileVault & boot menu. + */ + D_REPORT_COUNT, 0x08, + D_REPORT_SIZE, 0x01, + D_INPUT, (D_CONSTANT), /* 6 Keyboard keys */ - 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ - 0x95, 0x06, /* REPORT_COUNT (6) */ - 0x75, 0x08, /* REPORT_SIZE (8) */ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ - 0x26, 0xE7, 0x00, /* LOGICAL_MAXIMUM (231) */ - 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ - 0x29, 0xE7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ - 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ + D_USAGE_PAGE, D_PAGE_KEYBOARD, + D_REPORT_COUNT, 0x06, + D_REPORT_SIZE, 0x08, + D_LOGICAL_MINIMUM, 0x00, + D_MULTIBYTE(D_LOGICAL_MAXIMUM), HID_KEYBOARD_LAST_MODIFIER, 0x00, + D_USAGE_MINIMUM, HID_KEYBOARD_NO_EVENT, + D_USAGE_MAXIMUM, HID_KEYBOARD_LAST_MODIFIER, + D_INPUT, (D_DATA|D_ARRAY|D_ABSOLUTE), /* Keyboard Modifiers (shift, alt, ...) */ - 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) */ - - - /* End */ - 0xc0 /* END_COLLECTION */ + D_USAGE_MINIMUM, HID_KEYBOARD_FIRST_MODIFIER, + D_USAGE_MAXIMUM, HID_KEYBOARD_LAST_MODIFIER, + D_LOGICAL_MINIMUM, 0x00, + D_LOGICAL_MAXIMUM, 0x01, + D_REPORT_SIZE, 0x01, + D_REPORT_COUNT, 0x08, + D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), + + D_END_COLLECTION }; BootKeyboard_::BootKeyboard_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1), leds(0) { From 63d60149db4abf27f692bff68d8306774072ceb3 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Sat, 2 Jun 2018 08:25:27 +0200 Subject: [PATCH 509/602] BootKeyboard: default to BOOT protocol The primary reason for this change is to allow us to get rid of WakeupKeyboard in HostPowerManagement, because having two boot-keyboard enabled endpoints has the chance of confusing the hell out of certain operating systems, bootloaders, or BIOSes. As in, whichever gets found first, wins, which becomes a problem when WakeupKeyboard wins: that one does not implement a real keyboard. If it wins, one will be able to wake up a sleeping systems, but will be unable to type. That is not behaviour we desire. If we drop WakeupKeyboard, we need another way to have a boot-proto-enabled keyboard that defaults to boot proto, which is what this patch does with BootKeyboard. The reason we need to default to BOOT, contrary to what the USB spec says, is because Linux, Windows and OSX will only enable wakeup-support for a keyboard if it defaults to boot. Even if we say we support wakeup, even if we can switch to boot mode, if that is not the default, they will disable wakeup by default. That is not something we desire, either. So, we default to boot. This should work everywhere, and does so on all three major OSes. It also makes the firmware work out of the box on FreeBSD, which doesn't support the report protocol at all. Signed-off-by: Gergely Nagy --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp | 2 +- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 21481a9332..6735b09cb2 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -68,7 +68,7 @@ static const uint8_t _hidReportDescriptorKeyboard[] PROGMEM = { D_END_COLLECTION }; -BootKeyboard_::BootKeyboard_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1), leds(0) { +BootKeyboard_::BootKeyboard_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_BOOT_PROTOCOL), idle(1), leds(0) { epType[0] = EP_TYPE_INTERRUPT_IN; PluggableUSB().plug(this); } diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index 5729a265d1..ffcff3deae 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -60,7 +60,7 @@ class BootKeyboard_ : public PluggableUSBModule { uint8_t getProtocol(void); void setProtocol(uint8_t protocol); - uint8_t default_protocol = HID_REPORT_PROTOCOL; + uint8_t default_protocol = HID_BOOT_PROTOCOL; protected: HID_BootKeyboardReport_Data_t _keyReport, _lastKeyReport; From 5290b4f4089e15481cd86258b3d1016732d4eb7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fjo=CC=88lnir=20A=CC=81sgeirsson?= Date: Wed, 30 May 2018 21:53:51 +0900 Subject: [PATCH 510/602] Made Boot descriptor conform to spec. Changed Boot descriptor to conform to format outlined in USB HID specification. The descriptor before this changed did not specify the order of the report bytes correctly. (keys,reserved,leds,modifiers as opposed to modifiers,reserved,leds,keys). --- .../src/BootKeyboard/BootKeyboard.cpp | 64 ++++++++++--------- .../src/BootKeyboard/BootKeyboard.h | 4 +- 2 files changed, 35 insertions(+), 33 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 21481a9332..665ac76666 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -24,47 +24,49 @@ THE SOFTWARE. #include "BootKeyboard.h" #include "DescriptorPrimitives.h" +// See Appendix B of USB HID spec static const uint8_t _hidReportDescriptorKeyboard[] PROGMEM = { // Keyboard D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, D_USAGE, D_USAGE_KEYBOARD, + D_COLLECTION, D_APPLICATION, + // Modifiers D_USAGE_PAGE, D_PAGE_KEYBOARD, + D_USAGE_MINIMUM, 0xe0, + D_USAGE_MAXIMUM, 0xe7, + D_LOGICAL_MINIMUM, 0x0, + D_LOGICAL_MAXIMUM, 0x1, + D_REPORT_SIZE, 0x1, + D_REPORT_COUNT, 0x8, + D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), - /* 5 LEDs for num lock etc, 3 left for advanced, custom usage */ - D_USAGE_PAGE, D_PAGE_LEDS, - D_USAGE_MINIMUM, 0x01, - D_USAGE_MAXIMUM, 0x08, - D_REPORT_COUNT, 0x08, - D_REPORT_SIZE, 0x01, - D_OUTPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), - - /* 1 byte padding, needed for OSX. - * Tested on High Sierra, with FileVault & boot menu. - */ - D_REPORT_COUNT, 0x08, - D_REPORT_SIZE, 0x01, + // Reserved byte + D_REPORT_COUNT, 0x1, + D_REPORT_SIZE, 0x8, D_INPUT, (D_CONSTANT), - /* 6 Keyboard keys */ + // LEDs + D_REPORT_COUNT, 0x5, + D_REPORT_SIZE, 0x1, + D_USAGE_PAGE, D_PAGE_LEDS, + D_USAGE_MINIMUM, 0x1, + D_USAGE_MAXIMUM, 0x5, + D_OUTPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), + // Pad LEDs up to a byte + D_REPORT_COUNT, 0x1, + D_REPORT_SIZE, 0x3, + D_OUTPUT, (D_CONSTANT), + + // Non-modifiers + D_REPORT_COUNT, 0x6, + D_REPORT_SIZE, 0x8, + D_LOGICAL_MINIMUM, 0x0, + D_LOGICAL_MAXIMUM, 0xff, D_USAGE_PAGE, D_PAGE_KEYBOARD, - D_REPORT_COUNT, 0x06, - D_REPORT_SIZE, 0x08, - D_LOGICAL_MINIMUM, 0x00, - D_MULTIBYTE(D_LOGICAL_MAXIMUM), HID_KEYBOARD_LAST_MODIFIER, 0x00, - D_USAGE_MINIMUM, HID_KEYBOARD_NO_EVENT, - D_USAGE_MAXIMUM, HID_KEYBOARD_LAST_MODIFIER, + D_USAGE_MINIMUM, 0x0, + D_USAGE_MAXIMUM, 0xff, D_INPUT, (D_DATA|D_ARRAY|D_ABSOLUTE), - - /* Keyboard Modifiers (shift, alt, ...) */ - D_USAGE_MINIMUM, HID_KEYBOARD_FIRST_MODIFIER, - D_USAGE_MAXIMUM, HID_KEYBOARD_LAST_MODIFIER, - D_LOGICAL_MINIMUM, 0x00, - D_LOGICAL_MAXIMUM, 0x01, - D_REPORT_SIZE, 0x01, - D_REPORT_COUNT, 0x08, - D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), - D_END_COLLECTION }; @@ -281,7 +283,7 @@ size_t BootKeyboard_::release(uint8_t k) { void BootKeyboard_::releaseAll(void) { - memset(&_keyReport.keys, 0x00, sizeof(_keyReport.keys)); + memset(&_keyReport.bytes, 0x00, sizeof(_keyReport.bytes)); } /* Returns true if the modifer key passed in will be sent during this key report diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index 5729a265d1..4afebfc582 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -35,10 +35,10 @@ typedef union { // Low level key report: up to 6 keys and shift, ctrl etc at once struct { uint8_t modifiers; - uint8_t __padding; + uint8_t reserved; uint8_t keycodes[6]; }; - uint8_t keys[7]; + uint8_t bytes[8]; } HID_BootKeyboardReport_Data_t; From dddb46f2306c6527d73d83c6f83d1280d896300b Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Mon, 4 Jun 2018 07:32:21 +0200 Subject: [PATCH 511/602] BootKeyboard: Added explanatory comments about why we default to BOOT Signed-off-by: Gergely Nagy --- .../src/BootKeyboard/BootKeyboard.h | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index ffcff3deae..984f860070 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -60,6 +60,35 @@ class BootKeyboard_ : public PluggableUSBModule { uint8_t getProtocol(void); void setProtocol(uint8_t protocol); + /* The USB specification says that keyboards should start with + * HID_REPORT_PROTOCOL as a default, and yet, we default to HID_BOOT_PROTOCOL + * instead. We do this to support operating systems that require the keyboard + * to default to boot protocol during negotiation in order to enable them to + * wake the host up. This includes Linux, MacOS, and Windows. If the keyboard + * conforms to the spec, and starts in report mode, it will work under these + * operating systems, but if they are suspended, the keyboard will not be + * allowed to wake them up. + * + * Furthermore, there are BIOSes out there that do not implement a HID + * descriptor parser, nor do they explicitly send a SET_PROTOCOL request to + * put the keyboard into boot protocol. For these to work, we need to default + * to boot protocol. + * + * We could - and for some time, did - work the first issue around by having + * another end-point that implements a boot-keyboard, with boot-protocol as + * default. Sadly, that has side-effects too: some BIOSes, Grub, and OSX's + * FileVault gets easily confused, and will use the first node of a device. If + * that happens to be the dummy wakeup-only keyboard, then the keyboard will + * be unusable. + * + * There is no reliable way to support all these scenarios while still + * conforming to the specification. + * + * Luckily for us, all three major OSes are fine with boot being the default, + * they will all explicitly set the protocol to report. Any spec-conforming + * host will also work fine with boot being the default, because they are + * required - by spec - to set the protocol themselves. + */ uint8_t default_protocol = HID_BOOT_PROTOCOL; protected: From 5ea40e845c083f27a187f74da48c97905bd0f6db Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Tue, 5 Jun 2018 22:47:59 +0200 Subject: [PATCH 512/602] BootKeyboard: Fix modifier release When releasing a modifier, we were computing the bit index wrong: we substracted `HID_KEYBOARD_LAST_MODIFIER` from the keycode (going into negatives and wrapping around) instead of `HID_KEYBOARD_FIRST_MODIFIER`. Computing the index wrong meant that `BootKeyboard.release(Key_LeftShift.keyCode)` never cleared the shift bit from `_keyReport.modifiers`. This had undesired effects when BootKeyboard was active, and we explicitly wanted to release a single key, but keep the rest of the report intact. Signed-off-by: Gergely Nagy --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 27b7f365dd..9ff8c9a670 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -249,7 +249,7 @@ size_t BootKeyboard_::press(uint8_t k) { size_t BootKeyboard_::release(uint8_t k) { if ((k >= HID_KEYBOARD_FIRST_MODIFIER) && (k <= HID_KEYBOARD_LAST_MODIFIER)) { // it's a modifier key - _keyReport.modifiers = _keyReport.modifiers & (~(0x01 << (k - HID_KEYBOARD_LAST_MODIFIER))); + _keyReport.modifiers = _keyReport.modifiers & (~(0x01 << (k - HID_KEYBOARD_FIRST_MODIFIER))); } else { // it's some other key: // Test the key report to see if k is present. Clear it if it exists. From 6db62320f47df5d460d6991a97017ea03bb48822 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Wed, 6 Jun 2018 00:39:59 +0200 Subject: [PATCH 513/602] BootKeyboard: Disable HID_SET_IDLE Because OSX behaves strangely when HID_SET_IDLE is implemented (symptoms include key chatter), we disable it for now. Other operating systems to not suffer if we force the idle setting to zero, either. Signed-off-by: Gergely Nagy --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 9ff8c9a670..2fed812ad0 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -154,7 +154,14 @@ bool BootKeyboard_::setup(USBSetup& setup) { return true; } if (request == HID_SET_IDLE) { + // We currently ignore SET_IDLE, because we don't really do anything with it, and implementing + // it causes issues on OSX, such as key chatter. Other operating systems do not suffer if we + // force this to zero, either. +#if 0 idle = setup.wValueL; +#else + idle = 0; +#endif return true; } if (request == HID_SET_REPORT) { From 14f99d8c696978e62a9cf965529f26da40fd9a31 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Thu, 7 Jun 2018 21:07:01 +0200 Subject: [PATCH 514/602] BootKeyboard: Move the plugging to .begin() Instead of plugging the BootKeyboard at constructor-time, do so at begin()-time, so we can control when it happens. We want to control when it happens so that we can set the default protocol based on various boot-time considerations, without having to recompile the firmware. Signed-off-by: Gergely Nagy --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 2fed812ad0..4a1eba69d0 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -72,7 +72,6 @@ static const uint8_t _hidReportDescriptorKeyboard[] PROGMEM = { BootKeyboard_::BootKeyboard_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_BOOT_PROTOCOL), idle(1), leds(0) { epType[0] = EP_TYPE_INTERRUPT_IN; - PluggableUSB().plug(this); } int BootKeyboard_::getInterface(uint8_t* interfaceCount) { @@ -108,6 +107,8 @@ int BootKeyboard_::getDescriptor(USBSetup& setup) { void BootKeyboard_::begin(void) { + PluggableUSB().plug(this); + // Force API to send a clean report. // This is important for and HID bridge where the receiver stays on, // while the sender is resetted. From f188d945300fbae43fb06a3375a54978bab56578 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Fri, 8 Jun 2018 07:59:09 +0200 Subject: [PATCH 515/602] Revert BootKeyboard defaulting to BOOT protocol This reverts commit 63d60149db4abf27f692bff68d8306774072ceb3 and dddb46f2306c6527d73d83c6f83d1280d896300b. Signed-off-by: Gergely Nagy --- .../src/BootKeyboard/BootKeyboard.cpp | 2 +- .../src/BootKeyboard/BootKeyboard.h | 31 +------------------ 2 files changed, 2 insertions(+), 31 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 4a1eba69d0..228078759e 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -70,7 +70,7 @@ static const uint8_t _hidReportDescriptorKeyboard[] PROGMEM = { D_END_COLLECTION }; -BootKeyboard_::BootKeyboard_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_BOOT_PROTOCOL), idle(1), leds(0) { +BootKeyboard_::BootKeyboard_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1), leds(0) { epType[0] = EP_TYPE_INTERRUPT_IN; } diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index 390a9c14de..4afebfc582 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -60,36 +60,7 @@ class BootKeyboard_ : public PluggableUSBModule { uint8_t getProtocol(void); void setProtocol(uint8_t protocol); - /* The USB specification says that keyboards should start with - * HID_REPORT_PROTOCOL as a default, and yet, we default to HID_BOOT_PROTOCOL - * instead. We do this to support operating systems that require the keyboard - * to default to boot protocol during negotiation in order to enable them to - * wake the host up. This includes Linux, MacOS, and Windows. If the keyboard - * conforms to the spec, and starts in report mode, it will work under these - * operating systems, but if they are suspended, the keyboard will not be - * allowed to wake them up. - * - * Furthermore, there are BIOSes out there that do not implement a HID - * descriptor parser, nor do they explicitly send a SET_PROTOCOL request to - * put the keyboard into boot protocol. For these to work, we need to default - * to boot protocol. - * - * We could - and for some time, did - work the first issue around by having - * another end-point that implements a boot-keyboard, with boot-protocol as - * default. Sadly, that has side-effects too: some BIOSes, Grub, and OSX's - * FileVault gets easily confused, and will use the first node of a device. If - * that happens to be the dummy wakeup-only keyboard, then the keyboard will - * be unusable. - * - * There is no reliable way to support all these scenarios while still - * conforming to the specification. - * - * Luckily for us, all three major OSes are fine with boot being the default, - * they will all explicitly set the protocol to report. Any spec-conforming - * host will also work fine with boot being the default, because they are - * required - by spec - to set the protocol themselves. - */ - uint8_t default_protocol = HID_BOOT_PROTOCOL; + uint8_t default_protocol = HID_REPORT_PROTOCOL; protected: HID_BootKeyboardReport_Data_t _keyReport, _lastKeyReport; From 88fc920203b2a8ff796c402dce55bceba505dbfe Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Thu, 26 Jul 2018 18:40:16 -0700 Subject: [PATCH 516/602] We -always- want to restore the last key report, even if our USB send failed. Since we're abusing that data structure to save memory, we really want to leave it in its original state. --- plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index 5b452449a3..415e61461e 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -109,8 +109,7 @@ int Keyboard_::sendReport(void) { uint8_t last_mods = lastKeyReport.modifiers; lastKeyReport.modifiers = keyReport.modifiers; int returnCode = HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &lastKeyReport, sizeof(lastKeyReport)); - if (returnCode < 0) - lastKeyReport.modifiers = last_mods; + lastKeyReport.modifiers = last_mods; } // If the last report is different than the current report, then we need to send a report. From fc78480cf5bb300701d0811d5224fa3ea347a6b0 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Thu, 26 Jul 2018 19:27:37 -0700 Subject: [PATCH 517/602] Add new 'isKeyPressed/wasKeyPressed API to help calling code be more efficient --- .../src/BootKeyboard/BootKeyboard.cpp | 27 +++++++++++++++++++ .../src/BootKeyboard/BootKeyboard.h | 2 ++ .../src/MultiReport/Keyboard.cpp | 25 +++++++++++++++++ .../KeyboardioHID/src/MultiReport/Keyboard.h | 2 ++ 4 files changed, 56 insertions(+) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 228078759e..4e2fdc08bb 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -294,6 +294,33 @@ void BootKeyboard_::releaseAll(void) { memset(&_keyReport.bytes, 0x00, sizeof(_keyReport.bytes)); } + +/* Returns true if the non-modifer key passed in will be sent during this key report + * Returns false in all other cases + * */ +boolean BootKeyboard_::isKeyPressed(uint8_t k) { + for (uint8_t i = 0; i < sizeof(_keyReport.keycodes); i++) { + if (_keyReport.keycodes[i] == k) { + return true; + } + } + return false; +} + +/* Returns true if the non-modifer key passed in was sent during the previous key report + * Returns false in all other cases + * */ +boolean BootKeyboard_::wasKeyPressed(uint8_t k) { + for (uint8_t i = 0; i < sizeof(_keyReport.keycodes); i++) { + if (_lastKeyReport.keycodes[i] == k) { + return true; + } + } + return false; +} + + + /* Returns true if the modifer key passed in will be sent during this key report * Returns false in all other cases * */ diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index 4afebfc582..68296c9160 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -55,6 +55,8 @@ class BootKeyboard_ : public PluggableUSBModule { boolean isModifierActive(uint8_t k); boolean wasModifierActive(uint8_t k); + boolean isKeyPressed(uint8_t k); + boolean wasKeyPressed(uint8_t k); uint8_t getLeds(void); uint8_t getProtocol(void); diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index 415e61461e..b0696b107e 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -148,6 +148,31 @@ boolean Keyboard_::wasModifierActive(uint8_t k) { return false; } + +/* Returns true if the non-modifier key passed in will be sent during this key report + * Returns false in all other cases + * */ +boolean Keyboard_::isKeyPressed(uint8_t k) { + if (k <= HID_LAST_KEY) { + uint8_t bit = 1 << (uint8_t(k) % 8); + return !! (keyReport.keys[k / 8] & bit); + } + return false; +} + +/* Returns true if the non-modifer key passed in was sent during the previous key report + * Returns false in all other cases + * */ +boolean Keyboard_::wasKeyPressed(uint8_t k) { + + if (k <= HID_LAST_KEY) { + uint8_t bit = 1 << (uint8_t(k) % 8); + return !! (lastKeyReport.keys[k / 8] & bit); + } + return false; +} + + size_t Keyboard_::press(uint8_t k) { // If the key is in the range of 'printable' keys if (k <= HID_LAST_KEY) { diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h index c5567ab0a4..acdb41affb 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h @@ -56,6 +56,8 @@ class Keyboard_ { void releaseAll(void); int sendReport(void); + boolean isKeyPressed(uint8_t k); + boolean wasKeyPressed(uint8_t k); boolean isModifierActive(uint8_t k); boolean wasModifierActive(uint8_t k); From 816a997ff831f91e9ab42d4873d90a1aff359ba8 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Thu, 26 Jul 2018 23:11:59 -0700 Subject: [PATCH 518/602] The old behavior of always sending the old report with the new modifiers made sense only for toggle-on, not for toggle off. --- .../KeyboardioHID/src/MultiReport/Keyboard.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index b0696b107e..fab829022c 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -103,15 +103,27 @@ int Keyboard_::sendReportUnchecked(void) { int Keyboard_::sendReport(void) { // ChromeOS 51-60 (at least) bug: if a modifier and a normal keycode are added in the // same report, in some cases the shift is not applied (e.g. `shift`+`[` doesn't yield - // `{`). To compensate for this, check to see if the modifier byte has changed. If so, - // copy the modifier byte to the previous key report, and resend it before proceeding. - if (lastKeyReport.modifiers != keyReport.modifiers) { + // `{`). To compensate for this, check to see if the modifier byte has changed. + + + // If modifiers are being turned on, then we send the previous report with the new modifiers + if ( (lastKeyReport.modifiers ^ keyReport.modifiers) & keyReport.modifiers) { uint8_t last_mods = lastKeyReport.modifiers; lastKeyReport.modifiers = keyReport.modifiers; int returnCode = HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &lastKeyReport, sizeof(lastKeyReport)); lastKeyReport.modifiers = last_mods; } + // If modifiers are being turned off, then we send the new report with the previous modifiers. + else if ( (lastKeyReport.modifiers ^ keyReport.modifiers) & lastKeyReport.modifiers) { + uint8_t mods = keyReport.modifiers; + keyReport.modifiers = lastKeyReport.modifiers; + int returnCode = HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &keyReport, sizeof(lastKeyReport)); + keyReport.modifiers = mods; + } + + + // If the last report is different than the current report, then we need to send a report. // We guard sendReport like this so that calling code doesn't end up spamming the host with empty reports // if sendReport is called in a tight loop. From 9906ed0b1854098bbe1c9deff1932c458e35f0fc Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Sun, 29 Jul 2018 20:53:13 +0200 Subject: [PATCH 519/602] Mouse: Implement Mouse_::stop() This mirrors `move()`, and the intent is to use it when releasing a mouse key outside of the main event loop (such as during a macro). Signed-off-by: Gergely Nagy --- plugins/KeyboardioHID/src/MultiReport/Mouse.cpp | 11 +++++++++++ plugins/KeyboardioHID/src/MultiReport/Mouse.h | 11 +++++++++++ 2 files changed, 22 insertions(+) diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp index 438e6afa87..e0289a8f2a 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp @@ -93,6 +93,17 @@ void Mouse_::move(signed char x, signed char y, signed char vWheel, signed char report.hWheel = hWheel; } +void Mouse_::stop(bool x, bool y, bool vWheel, bool hWheel) { + if (x) + report.xAxis = 0; + if (y) + report.yAxis = 0; + if (vWheel) + report.vWheel = 0; + if (hWheel) + report.hWheel = 0; +} + void Mouse_::releaseAll(void) { memset(&report, 0, sizeof(report)); } diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.h b/plugins/KeyboardioHID/src/MultiReport/Mouse.h index f84eb3c9ea..9bf0ea9f75 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.h @@ -49,6 +49,17 @@ class Mouse_ { void end(void); void click(uint8_t b = MOUSE_LEFT); void move(signed char x, signed char y, signed char vWheel = 0, signed char hWheel = 0); + /** stop() stops mouse and/or mouse wheel movement in given directions. + * + * Counterpart of move(), this function allows us to undo whatever movement we + * were supposed to make. The intended use-case is one where we send multiple + * reports per cycle, and want greater control over them, when we don't want + * to clear the whole report, just parts of it. + * + * Any of the arguments that is set to true, will be cleared from the report + * to be sent by the next call to sendReport(). + */ + void stop(bool x, bool y, bool vWheel = false, bool hWheel = false); 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 From ec75c9603b4038cd768275bb642063cc71bc77f3 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Tue, 31 Jul 2018 07:07:52 +0200 Subject: [PATCH 520/602] Replace ::stop() with ::getReport() Instead of providing a ::stop() method, provide ::getReport() instead, allowing stop()-like functionality to be implemented on top of that and ::move(). Signed-off-by: Gergely Nagy --- .../KeyboardioHID/src/MultiReport/Mouse.cpp | 11 ---------- plugins/KeyboardioHID/src/MultiReport/Mouse.h | 20 +++++++++---------- 2 files changed, 9 insertions(+), 22 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp index e0289a8f2a..438e6afa87 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp @@ -93,17 +93,6 @@ void Mouse_::move(signed char x, signed char y, signed char vWheel, signed char report.hWheel = hWheel; } -void Mouse_::stop(bool x, bool y, bool vWheel, bool hWheel) { - if (x) - report.xAxis = 0; - if (y) - report.yAxis = 0; - if (vWheel) - report.vWheel = 0; - if (hWheel) - report.hWheel = 0; -} - void Mouse_::releaseAll(void) { memset(&report, 0, sizeof(report)); } diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.h b/plugins/KeyboardioHID/src/MultiReport/Mouse.h index 9bf0ea9f75..b5ab19b516 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.h @@ -49,21 +49,19 @@ class Mouse_ { void end(void); void click(uint8_t b = MOUSE_LEFT); void move(signed char x, signed char y, signed char vWheel = 0, signed char hWheel = 0); - /** stop() stops mouse and/or mouse wheel movement in given directions. - * - * Counterpart of move(), this function allows us to undo whatever movement we - * were supposed to make. The intended use-case is one where we send multiple - * reports per cycle, and want greater control over them, when we don't want - * to clear the whole report, just parts of it. - * - * Any of the arguments that is set to true, will be cleared from the report - * to be sent by the next call to sendReport(). - */ - void stop(bool x, bool y, bool vWheel = false, bool hWheel = false); 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 + /** getReport returns the current report. + * + * The current report is the one to be send next time sendReport() is called. + * + * @returns A copy of the report. + */ + const HID_MouseReport_Data_t getReport() { + return report; + } void sendReport(void); void releaseAll(void); From aaf051222703041ccab7bb86b625157084da6587 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Wed, 15 Aug 2018 14:05:01 -0700 Subject: [PATCH 521/602] Sending an extra report when toggling off a Modifier leads to numerous likely unnecessary reports. Since I didn't document why I believe it's necessary and the problem may have been caused by another nearby code path, I'm yanking it for now. --- plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index fab829022c..cd030afd0e 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -114,15 +114,6 @@ int Keyboard_::sendReport(void) { lastKeyReport.modifiers = last_mods; } - // If modifiers are being turned off, then we send the new report with the previous modifiers. - else if ( (lastKeyReport.modifiers ^ keyReport.modifiers) & lastKeyReport.modifiers) { - uint8_t mods = keyReport.modifiers; - keyReport.modifiers = lastKeyReport.modifiers; - int returnCode = HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &keyReport, sizeof(lastKeyReport)); - keyReport.modifiers = mods; - } - - // If the last report is different than the current report, then we need to send a report. // We guard sendReport like this so that calling code doesn't end up spamming the host with empty reports From 0e799fae66ded409490cf7346477edec41634d96 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Wed, 15 Aug 2018 14:56:23 -0700 Subject: [PATCH 522/602] Revert "Sending an extra report when toggling off a Modifier leads to numerous" Replicated the issue that caused this change. With a keymap containing LSHIFT(Key_3) At least on Linux + Wayland, holding down the key in question willl sometimes correctly result in but sometimes it will result in This reverts commit aaf051222703041ccab7bb86b625157084da6587. --- plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index cd030afd0e..fab829022c 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -114,6 +114,15 @@ int Keyboard_::sendReport(void) { lastKeyReport.modifiers = last_mods; } + // If modifiers are being turned off, then we send the new report with the previous modifiers. + else if ( (lastKeyReport.modifiers ^ keyReport.modifiers) & lastKeyReport.modifiers) { + uint8_t mods = keyReport.modifiers; + keyReport.modifiers = lastKeyReport.modifiers; + int returnCode = HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &keyReport, sizeof(lastKeyReport)); + keyReport.modifiers = mods; + } + + // If the last report is different than the current report, then we need to send a report. // We guard sendReport like this so that calling code doesn't end up spamming the host with empty reports From 91e353a37b57fe36151be0decf279ddbb993bd8f Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Wed, 15 Aug 2018 15:03:58 -0700 Subject: [PATCH 523/602] Do our report deduplication -before- we send the special OS-workaround modifier reports --- plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index fab829022c..cf29bc91de 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -101,6 +101,13 @@ int Keyboard_::sendReportUnchecked(void) { int Keyboard_::sendReport(void) { + // If the last report is different than the current report, then we need to send a report. + // We guard sendReport like this so that calling code doesn't end up spamming the host with empty reports + // if sendReport is called in a tight loop. + + if (memcmp(lastKeyReport.allkeys, keyReport.allkeys, sizeof(keyReport))) { + // if the two reports are different, send a report + // ChromeOS 51-60 (at least) bug: if a modifier and a normal keycode are added in the // same report, in some cases the shift is not applied (e.g. `shift`+`[` doesn't yield // `{`). To compensate for this, check to see if the modifier byte has changed. @@ -124,12 +131,8 @@ int Keyboard_::sendReport(void) { - // If the last report is different than the current report, then we need to send a report. - // We guard sendReport like this so that calling code doesn't end up spamming the host with empty reports - // if sendReport is called in a tight loop. - if (memcmp(lastKeyReport.allkeys, keyReport.allkeys, sizeof(keyReport))) { - // if the two reports are different, send a report + int returnCode = sendReportUnchecked(); if (returnCode > 0) memcpy(lastKeyReport.allkeys, keyReport.allkeys, sizeof(keyReport)); From d630089000007848ca6d6e9b077d53772a2cbd74 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Wed, 15 Aug 2018 15:04:37 -0700 Subject: [PATCH 524/602] Only send our modifier deduplication reports if a modifier is changing in the same report as non-modifier keys --- plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index cf29bc91de..60e547ed6e 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -113,8 +113,11 @@ int Keyboard_::sendReport(void) { // `{`). To compensate for this, check to see if the modifier byte has changed. - // If modifiers are being turned on, then we send the previous report with the new modifiers - if ( (lastKeyReport.modifiers ^ keyReport.modifiers) & keyReport.modifiers) { + // If modifiers are being turned on at the same time as any change + // to the non-modifier keys in the report, then we send the previous + // report with the new modifiers + if ( ( (lastKeyReport.modifiers ^ keyReport.modifiers) & keyReport.modifiers) + && (memcmp(lastKeyReport.keys,keyReport.keys, sizeof(keyReport.keys)))) { uint8_t last_mods = lastKeyReport.modifiers; lastKeyReport.modifiers = keyReport.modifiers; int returnCode = HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &lastKeyReport, sizeof(lastKeyReport)); @@ -122,7 +125,8 @@ int Keyboard_::sendReport(void) { } // If modifiers are being turned off, then we send the new report with the previous modifiers. - else if ( (lastKeyReport.modifiers ^ keyReport.modifiers) & lastKeyReport.modifiers) { + else if (( (lastKeyReport.modifiers ^ keyReport.modifiers) & lastKeyReport.modifiers) + && (memcmp(lastKeyReport.keys,keyReport.keys, sizeof(keyReport.keys)))) { uint8_t mods = keyReport.modifiers; keyReport.modifiers = lastKeyReport.modifiers; int returnCode = HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &keyReport, sizeof(lastKeyReport)); From 6664a5a58be3850962ee620971a7f7b33c7e4b4b Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Wed, 15 Aug 2018 15:07:59 -0700 Subject: [PATCH 525/602] Add a comment explaining weird behavior --- plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index 60e547ed6e..24883fd5de 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -125,6 +125,10 @@ int Keyboard_::sendReport(void) { } // If modifiers are being turned off, then we send the new report with the previous modifiers. + // We need to do this, at least on Linux 4.17 + Wayland. + // Jesse has observed that sending Shift + 3 key up events in the same report + // will sometimes result in a spurious '3' rather than '#', especially when the keys + // had been held for a while else if (( (lastKeyReport.modifiers ^ keyReport.modifiers) & lastKeyReport.modifiers) && (memcmp(lastKeyReport.keys,keyReport.keys, sizeof(keyReport.keys)))) { uint8_t mods = keyReport.modifiers; From 66be7d5d5f9f1b19d7b3a005e1ab3b7f1380f1fe Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Thu, 23 Aug 2018 23:10:05 +0200 Subject: [PATCH 526/602] Add a LICENSE file, and proper headers to all files Update the copyright lines in all files, to reflect Keyboard.io's work too. Also add a LICENSE file with the MIT license, that the files were licensed under. Signed-off-by: Gergely Nagy --- plugins/KeyboardioHID/LICENSE | 22 ++++++++++++++++ .../src/BootKeyboard/BootKeyboard.cpp | 2 ++ .../src/BootKeyboard/BootKeyboard.h | 2 ++ .../KeyboardioHID/src/DescriptorPrimitives.h | 25 ++++++++++++++++++ .../src/DeviceAPIs/AbsoluteMouseAPI.h | 2 ++ .../src/DeviceAPIs/AbsoluteMouseAPI.hpp | 2 ++ plugins/KeyboardioHID/src/HID-Settings.h | 2 ++ plugins/KeyboardioHID/src/HIDAliases.h | 25 ++++++++++++++++++ plugins/KeyboardioHID/src/HIDTables.h | 24 +++++++++++++++++ plugins/KeyboardioHID/src/KeyboardioHID.h | 2 ++ plugins/KeyboardioHID/src/LEDs.h | 26 ++++++++++++++++++- plugins/KeyboardioHID/src/MouseButtons.h | 25 ++++++++++++++++++ .../src/MultiReport/AbsoluteMouse.cpp | 2 ++ .../src/MultiReport/AbsoluteMouse.h | 2 ++ .../src/MultiReport/ConsumerControl.cpp | 2 ++ .../src/MultiReport/ConsumerControl.h | 2 ++ .../KeyboardioHID/src/MultiReport/Gamepad.cpp | 2 ++ .../KeyboardioHID/src/MultiReport/Gamepad.h | 3 ++- .../src/MultiReport/Keyboard.cpp | 14 +++++----- .../KeyboardioHID/src/MultiReport/Keyboard.h | 3 ++- .../KeyboardioHID/src/MultiReport/Mouse.cpp | 2 ++ plugins/KeyboardioHID/src/MultiReport/Mouse.h | 2 ++ .../src/MultiReport/SystemControl.cpp | 2 ++ .../src/MultiReport/SystemControl.h | 3 ++- .../src/SingleReport/SingleAbsoluteMouse.cpp | 4 +-- .../src/SingleReport/SingleAbsoluteMouse.h | 8 +++--- 26 files changed, 194 insertions(+), 16 deletions(-) create mode 100644 plugins/KeyboardioHID/LICENSE diff --git a/plugins/KeyboardioHID/LICENSE b/plugins/KeyboardioHID/LICENSE new file mode 100644 index 0000000000..71074013ca --- /dev/null +++ b/plugins/KeyboardioHID/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + +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. diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 4e2fdc08bb..30f00c1fcc 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -1,5 +1,7 @@ /* Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + See the readme for credit to other people. Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index 68296c9160..a53ddc77e3 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -1,5 +1,7 @@ /* Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + See the readme for credit to other people. Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/plugins/KeyboardioHID/src/DescriptorPrimitives.h b/plugins/KeyboardioHID/src/DescriptorPrimitives.h index 4ef0a8726a..2edc0ccb9c 100644 --- a/plugins/KeyboardioHID/src/DescriptorPrimitives.h +++ b/plugins/KeyboardioHID/src/DescriptorPrimitives.h @@ -1,3 +1,28 @@ +/* +Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + +See the readme for credit to other people. + +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. +*/ + #pragma once #define D_MULTIBYTE(n) (n + 0x01) diff --git a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h index 725d83c5bb..7c91a27194 100644 --- a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h +++ b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h @@ -1,5 +1,7 @@ /* Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + See the readme for credit to other people. Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.hpp b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.hpp index 744f1193f3..afbc41ab7a 100644 --- a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.hpp +++ b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.hpp @@ -1,5 +1,7 @@ /* Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + See the readme for credit to other people. Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/plugins/KeyboardioHID/src/HID-Settings.h b/plugins/KeyboardioHID/src/HID-Settings.h index dcb16ae053..a55b1ff173 100644 --- a/plugins/KeyboardioHID/src/HID-Settings.h +++ b/plugins/KeyboardioHID/src/HID-Settings.h @@ -1,5 +1,7 @@ /* Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + See the readme for credit to other people. Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/plugins/KeyboardioHID/src/HIDAliases.h b/plugins/KeyboardioHID/src/HIDAliases.h index bcdf00c797..5cf2eef725 100644 --- a/plugins/KeyboardioHID/src/HIDAliases.h +++ b/plugins/KeyboardioHID/src/HIDAliases.h @@ -1,3 +1,28 @@ +/* +Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + +See the readme for credit to other people. + +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. +*/ + #pragma once #include "HIDTables.h" diff --git a/plugins/KeyboardioHID/src/HIDTables.h b/plugins/KeyboardioHID/src/HIDTables.h index 32cd52e8f6..60d2a6ca18 100644 --- a/plugins/KeyboardioHID/src/HIDTables.h +++ b/plugins/KeyboardioHID/src/HIDTables.h @@ -1,3 +1,27 @@ +/* +Copyright (c) 2015-2018 Keyboard.io, Inc + +See the readme for credit to other people. + +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 __HIDTables__ #define __HIDTables__ diff --git a/plugins/KeyboardioHID/src/KeyboardioHID.h b/plugins/KeyboardioHID/src/KeyboardioHID.h index 6d9a6930e7..7f68e208b5 100644 --- a/plugins/KeyboardioHID/src/KeyboardioHID.h +++ b/plugins/KeyboardioHID/src/KeyboardioHID.h @@ -1,5 +1,7 @@ /* Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + See the readme for credit to other people. Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/plugins/KeyboardioHID/src/LEDs.h b/plugins/KeyboardioHID/src/LEDs.h index 8381003082..2df7e6b00b 100644 --- a/plugins/KeyboardioHID/src/LEDs.h +++ b/plugins/KeyboardioHID/src/LEDs.h @@ -1,3 +1,28 @@ +/* +Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + +See the readme for credit to other people. + +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. +*/ + #pragma once // Keyboard Leds @@ -11,4 +36,3 @@ enum KeyboardLeds : uint8_t { LED_SHIFT = (1 << 6), LED_DO_NOT_DISTURB = (1 << 7), }; - diff --git a/plugins/KeyboardioHID/src/MouseButtons.h b/plugins/KeyboardioHID/src/MouseButtons.h index 7cefd19620..ae328ca107 100644 --- a/plugins/KeyboardioHID/src/MouseButtons.h +++ b/plugins/KeyboardioHID/src/MouseButtons.h @@ -1,3 +1,28 @@ +/* +Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + +See the readme for credit to other people. + +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. +*/ + #pragma once #define MOUSE_LEFT (1 << 0) diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp index 5fa251cb5b..e7f74411e9 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp @@ -1,5 +1,7 @@ /* Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + See the readme for credit to other people. Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h index d395ed1c95..84530b95f9 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h @@ -1,5 +1,7 @@ /* Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + See the readme for credit to other people. Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp index a94898c9d1..ddac89a12e 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp @@ -1,5 +1,7 @@ /* Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + See the readme for credit to other people. Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h index 96e3150693..e913b30060 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h +++ b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h @@ -1,5 +1,7 @@ /* Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + See the readme for credit to other people. Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp b/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp index 525d2508df..c02c8f4bf7 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp @@ -1,5 +1,7 @@ /* Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + See the readme for credit to other people. Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/plugins/KeyboardioHID/src/MultiReport/Gamepad.h b/plugins/KeyboardioHID/src/MultiReport/Gamepad.h index d315c47944..a2ec7aacef 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Gamepad.h +++ b/plugins/KeyboardioHID/src/MultiReport/Gamepad.h @@ -1,5 +1,7 @@ /* Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + See the readme for credit to other people. Permission is hereby granted, free of charge, to any person obtaining a copy @@ -122,4 +124,3 @@ class Gamepad_ { HID_GamepadReport_Data_t _report; }; extern Gamepad_ Gamepad; - diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index 24883fd5de..187289f087 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -1,5 +1,7 @@ /* Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + See the readme for credit to other people. Permission is hereby granted, free of charge, to any person obtaining a copy @@ -110,11 +112,11 @@ int Keyboard_::sendReport(void) { // ChromeOS 51-60 (at least) bug: if a modifier and a normal keycode are added in the // same report, in some cases the shift is not applied (e.g. `shift`+`[` doesn't yield - // `{`). To compensate for this, check to see if the modifier byte has changed. + // `{`). To compensate for this, check to see if the modifier byte has changed. - // If modifiers are being turned on at the same time as any change - // to the non-modifier keys in the report, then we send the previous + // If modifiers are being turned on at the same time as any change + // to the non-modifier keys in the report, then we send the previous // report with the new modifiers if ( ( (lastKeyReport.modifiers ^ keyReport.modifiers) & keyReport.modifiers) && (memcmp(lastKeyReport.keys,keyReport.keys, sizeof(keyReport.keys)))) { @@ -124,8 +126,8 @@ int Keyboard_::sendReport(void) { lastKeyReport.modifiers = last_mods; } - // If modifiers are being turned off, then we send the new report with the previous modifiers. - // We need to do this, at least on Linux 4.17 + Wayland. + // If modifiers are being turned off, then we send the new report with the previous modifiers. + // We need to do this, at least on Linux 4.17 + Wayland. // Jesse has observed that sending Shift + 3 key up events in the same report // will sometimes result in a spurious '3' rather than '#', especially when the keys // had been held for a while @@ -135,7 +137,7 @@ int Keyboard_::sendReport(void) { keyReport.modifiers = lastKeyReport.modifiers; int returnCode = HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &keyReport, sizeof(lastKeyReport)); keyReport.modifiers = mods; - } + } diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h index acdb41affb..7d2bb4450d 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h @@ -1,5 +1,7 @@ /* Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + See the readme for credit to other people. Permission is hereby granted, free of charge, to any person obtaining a copy @@ -69,4 +71,3 @@ class Keyboard_ { int sendReportUnchecked(void); }; extern Keyboard_ Keyboard; - diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp index 438e6afa87..96362d79e2 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp @@ -1,5 +1,7 @@ /* Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + See the readme for credit to other people. Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.h b/plugins/KeyboardioHID/src/MultiReport/Mouse.h index b5ab19b516..d03dd17fd7 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.h @@ -1,5 +1,7 @@ /* Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + See the readme for credit to other people. Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp b/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp index 417047d9ec..78a15c32a1 100644 --- a/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp @@ -1,5 +1,7 @@ /* Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + See the readme for credit to other people. Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/plugins/KeyboardioHID/src/MultiReport/SystemControl.h b/plugins/KeyboardioHID/src/MultiReport/SystemControl.h index bbf68f0144..d56a7d8475 100644 --- a/plugins/KeyboardioHID/src/MultiReport/SystemControl.h +++ b/plugins/KeyboardioHID/src/MultiReport/SystemControl.h @@ -1,5 +1,7 @@ /* Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + See the readme for credit to other people. Permission is hereby granted, free of charge, to any person obtaining a copy @@ -54,4 +56,3 @@ class SystemControl_ { extern SystemControl_ SystemControl; - diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp index ff4da906d1..bf19068e08 100644 --- a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp @@ -1,5 +1,7 @@ /* Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + See the readme for credit to other people. Permission is hereby granted, free of charge, to any person obtaining a copy @@ -113,5 +115,3 @@ void SingleAbsoluteMouse_::sendReport(void* data, int length) } SingleAbsoluteMouse_ SingleAbsoluteMouse; - - diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h index c90d658da3..0a8c43f2d2 100644 --- a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h +++ b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h @@ -1,5 +1,7 @@ /* Copyright (c) 2014-2015 NicoHood +Copyright (c) 2015-2018 Keyboard.io, Inc + See the readme for credit to other people. Permission is hereby granted, free of charge, to any person obtaining a copy @@ -43,13 +45,11 @@ class SingleAbsoluteMouse_ : public PluggableUSBModule, public AbsoluteMouseAPI int getInterface(uint8_t* interfaceCount); int getDescriptor(USBSetup& setup); bool setup(USBSetup& setup); - + uint8_t epType[1]; uint8_t protocol; uint8_t idle; - + virtual inline void sendReport(void* data, int length) override; }; extern SingleAbsoluteMouse_ SingleAbsoluteMouse; - - From 6e971329affaa7207f78256453d893e9ddddd3c7 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Thu, 23 Aug 2018 23:11:27 +0200 Subject: [PATCH 527/602] Add CONTRIBUTING.md Copied from Kaleidoscope, because it is applicable here too. Signed-off-by: Gergely Nagy --- plugins/KeyboardioHID/CONTRIBUTING.md | 50 +++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 plugins/KeyboardioHID/CONTRIBUTING.md diff --git a/plugins/KeyboardioHID/CONTRIBUTING.md b/plugins/KeyboardioHID/CONTRIBUTING.md new file mode 100644 index 0000000000..c490e3ce3b --- /dev/null +++ b/plugins/KeyboardioHID/CONTRIBUTING.md @@ -0,0 +1,50 @@ +# Developer Certificate of Origin + +All contributions must include acceptance of the DCO: + +``` +Developer Certificate of Origin +Version 1.1 + +Copyright (C) 2004, 2006 The Linux Foundation and its contributors. +1 Letterman Drive +Suite D4700 +San Francisco, CA, 94129 + +Everyone is permitted to copy and distribute verbatim copies of this +license document, but changing it is not allowed. + + +Developer's Certificate of Origin 1.1 + +By making a contribution to this project, I certify that: + +(a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + +(b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or + +(c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +(d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. +``` + +## Sign your work + +To accept the DCO, please add this line to each commit message with your name +and email address (`git commit -s` will do this for you): + + Signed-off-by: Jane Example From 97e7a467068370be956cd9c65971ee655303cfa6 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Wed, 10 Oct 2018 06:59:58 +0200 Subject: [PATCH 528/602] Travis cleanup Remove the IRC notifications from Travis (we're not using IRC anymore). Signed-off-by: Gergely Nagy --- plugins/KeyboardioHID/.travis.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/plugins/KeyboardioHID/.travis.yml b/plugins/KeyboardioHID/.travis.yml index cb7c9ad048..b54659742c 100644 --- a/plugins/KeyboardioHID/.travis.yml +++ b/plugins/KeyboardioHID/.travis.yml @@ -9,13 +9,6 @@ script: - make smoke ARDUINO_PATH=../arduino-1.6.7 ARDUINO_LOCAL_LIB_PATH=.. notifications: - irc: - channels: - - "chat.freenode.net#keyboardio" - use_notice: true - skip_join: true - template: - - "%{repository_name}/%{branch} %{commit} by %{author}: %{commit_subject} %{build_url} %{message}" email: on_success: change on_failure: change From a09a96240de45d5eb61a6b675bcc9cd8c9ee95c3 Mon Sep 17 00:00:00 2001 From: tiltowait Date: Sat, 19 Jan 2019 17:57:19 -0800 Subject: [PATCH 529/602] Add functions for determining whether any modifiers are/were active Signed-off-by: tiltowait --- .../src/BootKeyboard/BootKeyboard.cpp | 14 ++++++++++++++ .../KeyboardioHID/src/BootKeyboard/BootKeyboard.h | 2 ++ plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp | 14 ++++++++++++++ plugins/KeyboardioHID/src/MultiReport/Keyboard.h | 2 ++ 4 files changed, 32 insertions(+) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 30f00c1fcc..105b4a9fc9 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -345,4 +345,18 @@ boolean BootKeyboard_::wasModifierActive(uint8_t k) { return false; } +/* Returns true if any modifier key will be sent during this key report + * Returns false in all other cases + * */ +boolean BootKeyboard_::isAnyModifierActive() { + return _keyReport.modifiers > 0; +} + +/* Returns true if any modifier key was being sent during the previous key report + * Returns false in all other cases + * */ +boolean BootKeyboard_::wasAnyModifierActive() { + return _lastKeyReport.modifiers > 0; +} + BootKeyboard_ BootKeyboard; diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index a53ddc77e3..7f2ef54e58 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -57,6 +57,8 @@ class BootKeyboard_ : public PluggableUSBModule { boolean isModifierActive(uint8_t k); boolean wasModifierActive(uint8_t k); + boolean isAnyModifierActive(); + boolean wasAnyModifierActive(); boolean isKeyPressed(uint8_t k); boolean wasKeyPressed(uint8_t k); diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index 187289f087..7d49624270 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -173,6 +173,20 @@ boolean Keyboard_::wasModifierActive(uint8_t k) { return false; } +/* Returns true if *any* modifier will be sent during this key report + * Returns false in all other cases + * */ +boolean Keyboard_::isAnyModifierActive() { + return keyReport.modifiers > 0; +} + +/* Returns true if *any* modifier was being sent during the previous key report + * Returns false in all other cases + * */ +boolean Keyboard_::wasAnyModifierActive() { + return lastKeyReport.modifiers > 0; +} + /* Returns true if the non-modifier key passed in will be sent during this key report * Returns false in all other cases diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h index 7d2bb4450d..4f93ef6d14 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h @@ -62,6 +62,8 @@ class Keyboard_ { boolean wasKeyPressed(uint8_t k); boolean isModifierActive(uint8_t k); boolean wasModifierActive(uint8_t k); + boolean isAnyModifierActive(); + boolean wasAnyModifierActive(); uint8_t getLEDs() { return HID().getLEDs(); }; From dd524c36df512a3614856f8a04aa6303edebf547 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Fri, 19 Apr 2019 23:03:23 +0200 Subject: [PATCH 530/602] Copy HID.h and HID.cpp over We depend on our version of these, tightly. To make it easier to add new features to the HID class itself, lets move it here. Arduino seems to prefer the local copy over the built-in library, if both are present, so this should be safe. Signed-off-by: Gergely Nagy --- plugins/KeyboardioHID/src/HID.cpp | 160 ++++++++++++++++++++++++++++++ plugins/KeyboardioHID/src/HID.h | 127 ++++++++++++++++++++++++ 2 files changed, 287 insertions(+) create mode 100644 plugins/KeyboardioHID/src/HID.cpp create mode 100644 plugins/KeyboardioHID/src/HID.h diff --git a/plugins/KeyboardioHID/src/HID.cpp b/plugins/KeyboardioHID/src/HID.cpp new file mode 100644 index 0000000000..526ed892e4 --- /dev/null +++ b/plugins/KeyboardioHID/src/HID.cpp @@ -0,0 +1,160 @@ +/* + Copyright (c) 2015, Arduino LLC + Original code (pre-library): 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 "HID.h" + +#if defined(USBCON) + +HID_& HID() { + static HID_ obj; + return obj; +} + +int HID_::getInterface(uint8_t* interfaceCount) { + *interfaceCount += 1; // uses 1 + HIDDescriptor hidInterface = { + D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE), + D_HIDREPORT(descriptorSize), + D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) + }; + return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); +} + +int HID_::getDescriptor(USBSetup& setup) { + // Check if this is a HID Class Descriptor request + if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { + return 0; + } + if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { + return 0; + } + + // In a HID Class Descriptor wIndex cointains the interface number + if (setup.wIndex != pluggedInterface) { + return 0; + } + + int total = 0; + HIDSubDescriptor* node; + for (node = rootNode; node; node = node->next) { + int res = USB_SendControl(TRANSFER_PGM, node->data, node->length); + if (res == -1) + return -1; + total += res; + } + + // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol + // due to the USB specs, but Windows and Linux just assumes its in report mode. + protocol = HID_REPORT_PROTOCOL; + + return total; +} + +uint8_t HID_::getShortName(char *name) { + name[0] = 'k'; + name[1] = 'b'; + name[2] = 'i'; + name[3] = 'o'; + name[4] = '0'; + name[5] = '1'; + return 6; +} + +void HID_::AppendDescriptor(HIDSubDescriptor *node) { + if (!rootNode) { + rootNode = node; + } else { + HIDSubDescriptor *current = rootNode; + while (current->next) { + current = current->next; + } + current->next = node; + } + descriptorSize += node->length; +} + +int HID_::SendReport(uint8_t id, const void* data, int len) { + auto ret = USB_Send(pluggedEndpoint, &id, 1); + if (ret < 0) return ret; + auto ret2 = USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, len); + if (ret2 < 0) return ret2; + return ret + ret2; +} + +bool HID_::setup(USBSetup& setup) { + if (pluggedInterface != setup.wIndex) { + return false; + } + + uint8_t request = setup.bRequest; + uint8_t requestType = setup.bmRequestType; + + if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) { + if (request == HID_GET_REPORT) { + // TODO: HID_GetReport(); + return true; + } + if (request == HID_GET_PROTOCOL) { + // TODO: Send8(protocol); + return true; + } + if (request == HID_GET_IDLE) { + // TODO: Send8(idle); + } + } + + if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) { + if (request == HID_SET_PROTOCOL) { + // The USB Host tells us if we are in boot or report mode. + // This only works with a real boot compatible device. + protocol = setup.wValueL; + return true; + } + if (request == HID_SET_IDLE) { + idle = setup.wValueL; + return true; + } + if (request == HID_SET_REPORT) { + uint16_t length = setup.wLength; + + if (length == sizeof(setReportData)) { + USB_RecvControl(&setReportData, length); + } else if (length == sizeof(setReportData.leds)) { + USB_RecvControl(&setReportData.leds, length); + setReportData.reportId = 0; + } + } + } + + return false; +} + +HID_::HID_(void) : PluggableUSBModule(1, 1, epType), + rootNode(NULL), descriptorSize(0), + protocol(HID_REPORT_PROTOCOL), idle(1) { + setReportData.reportId = 0; + setReportData.leds = 0; + epType[0] = EP_TYPE_INTERRUPT_IN; + PluggableUSB().plug(this); +} + +int HID_::begin(void) { + return 0; +} + +#endif /* if defined(USBCON) */ diff --git a/plugins/KeyboardioHID/src/HID.h b/plugins/KeyboardioHID/src/HID.h new file mode 100644 index 0000000000..15a7ccd0a6 --- /dev/null +++ b/plugins/KeyboardioHID/src/HID.h @@ -0,0 +1,127 @@ +/* + Copyright (c) 2015, Arduino LLC + Original code (pre-library): 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. + */ + +#ifndef HID_h +#define HID_h + +#include +#include +#include "HID-Settings.h" + +#if defined(USBCON) + +#define _USING_HID + +// HID 'Driver' +// ------------ +#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 + +#define HID_HID_DESCRIPTOR_TYPE 0x21 +#define HID_REPORT_DESCRIPTOR_TYPE 0x22 +#define HID_PHYSICAL_DESCRIPTOR_TYPE 0x23 + +// HID subclass HID1.11 Page 8 4.2 Subclass +#define HID_SUBCLASS_NONE 0 +#define HID_SUBCLASS_BOOT_INTERFACE 1 + +// HID Keyboard/Mouse bios compatible protocols HID1.11 Page 9 4.3 Protocols +#define HID_PROTOCOL_NONE 0 +#define HID_PROTOCOL_KEYBOARD 1 +#define HID_PROTOCOL_MOUSE 2 + +// Normal or bios protocol (Keyboard/Mouse) HID1.11 Page 54 7.2.5 Get_Protocol Request +// "protocol" variable is used for this purpose. +#define HID_BOOT_PROTOCOL 0 +#define HID_REPORT_PROTOCOL 1 + +// HID Request Type HID1.11 Page 51 7.2.1 Get_Report Request +#define HID_REPORT_TYPE_INPUT 1 +#define HID_REPORT_TYPE_OUTPUT 2 +#define HID_REPORT_TYPE_FEATURE 3 + +typedef struct { + uint8_t len; // 9 + uint8_t dtype; // 0x21 + uint8_t addr; + uint8_t versionL; // 0x101 + uint8_t versionH; // 0x101 + uint8_t country; + uint8_t desctype; // 0x22 report + uint8_t descLenL; + uint8_t descLenH; +} HIDDescDescriptor; + +typedef struct { + InterfaceDescriptor hid; + HIDDescDescriptor desc; + EndpointDescriptor in; +} HIDDescriptor; + +class HIDSubDescriptor { + public: + HIDSubDescriptor *next = NULL; + HIDSubDescriptor(const void *d, const uint16_t l) : data(d), length(l) { } + + const void* data; + const uint16_t length; +}; + +class HID_ : public PluggableUSBModule { + public: + HID_(void); + int begin(void); + int SendReport(uint8_t id, const void* data, int len); + void AppendDescriptor(HIDSubDescriptor* node); + uint8_t getLEDs(void) { return setReportData.leds; }; + + protected: + // Implementation of the PluggableUSBModule + int getInterface(uint8_t* interfaceCount); + int getDescriptor(USBSetup& setup); + bool setup(USBSetup& setup); + uint8_t getShortName(char* name); + + private: + EPTYPE_DESCRIPTOR_SIZE epType[1]; + + HIDSubDescriptor* rootNode; + uint16_t descriptorSize; + + uint8_t protocol; + uint8_t idle; + struct { + uint8_t reportId; + uint8_t leds; + } setReportData; +}; + +// Replacement for global singleton. +// This function prevents static-initialization-order-fiasco +// https://isocpp.org/wiki/faq/ctors#static-init-order-on-first-use +HID_& HID(); + +#define D_HIDREPORT(length) { 9, 0x21, 0x01, 0x01, 0, 1, 0x22, lowByte(length), highByte(length) } + +#endif // USBCON + +#endif // HID_h From 0adc4350959c12fecc4adde1b32fd8ef7c5a8a6d Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Fri, 19 Apr 2019 23:06:25 +0200 Subject: [PATCH 531/602] library.properties: Switch the architecture to any In preparation for a SAMD port, switch the architecture to any. While there, also correct the URL. Signed-off-by: Gergely Nagy --- plugins/KeyboardioHID/library.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/KeyboardioHID/library.properties b/plugins/KeyboardioHID/library.properties index 9f2345c611..df240b4c3b 100644 --- a/plugins/KeyboardioHID/library.properties +++ b/plugins/KeyboardioHID/library.properties @@ -5,6 +5,6 @@ maintainer=Jesse Vincent sentence=HID Driver for keyboardio keyboards. paragraph=Includes Boot Keyboard, NKRO Keyboard, Mouse, ConsumerControl, SystemControl, Gamepad. Based on Nico Hood's HID-Project category=Communication -url=https://github.com/keyboardio/HID -architectures=avr +url=https://github.com/keyboardio/KeyboardioHID +architectures=* dot_a_linkage=true From 4e7c3bb5cb7c2310dedec5a788bc094b4dce6d3b Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Fri, 19 Apr 2019 23:09:41 +0200 Subject: [PATCH 532/602] Don't include PluggableUSB.h directly Some Arduino Cores place PluggableUSB.h elsewhere. To make our lives easier when porting to those, lets have one place that includes PluggableUSB.h (HID-Settings.h). Signed-off-by: Gergely Nagy --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h | 1 - plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h | 1 - plugins/KeyboardioHID/src/HID-Settings.h | 2 ++ plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h | 1 - plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h | 1 - plugins/KeyboardioHID/src/MultiReport/Gamepad.h | 1 - plugins/KeyboardioHID/src/MultiReport/Keyboard.h | 1 - plugins/KeyboardioHID/src/MultiReport/Mouse.h | 1 - plugins/KeyboardioHID/src/MultiReport/SystemControl.h | 1 - plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h | 1 - 10 files changed, 2 insertions(+), 9 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index 7f2ef54e58..b2322591ee 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -27,7 +27,6 @@ THE SOFTWARE. #pragma once #include -#include "PluggableUSB.h" #include "HID.h" #include "HID-Settings.h" #include "HIDTables.h" diff --git a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h index 7c91a27194..e1e1243da3 100644 --- a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h +++ b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h @@ -27,7 +27,6 @@ THE SOFTWARE. #pragma once #include -#include "PluggableUSB.h" #include "HID.h" #include "HID-Settings.h" #include "MouseButtons.h" diff --git a/plugins/KeyboardioHID/src/HID-Settings.h b/plugins/KeyboardioHID/src/HID-Settings.h index a55b1ff173..26aa313b9d 100644 --- a/plugins/KeyboardioHID/src/HID-Settings.h +++ b/plugins/KeyboardioHID/src/HID-Settings.h @@ -68,3 +68,5 @@ THE SOFTWARE. #define HID_REPORT_TYPE_INPUT 1 #define HID_REPORT_TYPE_OUTPUT 2 #define HID_REPORT_TYPE_FEATURE 3 + +#include "PluggableUSB.h" diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h index 84530b95f9..0de95a29a0 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h @@ -27,7 +27,6 @@ THE SOFTWARE. #pragma once #include -#include "PluggableUSB.h" #include "HID.h" #include "HID-Settings.h" #include "../DeviceAPIs/AbsoluteMouseAPI.h" diff --git a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h index e913b30060..ecd122ec6b 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h +++ b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h @@ -27,7 +27,6 @@ THE SOFTWARE. #pragma once #include -#include "PluggableUSB.h" #include "HID.h" #include "HID-Settings.h" diff --git a/plugins/KeyboardioHID/src/MultiReport/Gamepad.h b/plugins/KeyboardioHID/src/MultiReport/Gamepad.h index a2ec7aacef..3dd6b4188a 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Gamepad.h +++ b/plugins/KeyboardioHID/src/MultiReport/Gamepad.h @@ -27,7 +27,6 @@ THE SOFTWARE. #pragma once #include -#include "PluggableUSB.h" #include "HID.h" #include "HID-Settings.h" diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h index 4f93ef6d14..14a38130b5 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h @@ -27,7 +27,6 @@ THE SOFTWARE. #pragma once #include -#include "PluggableUSB.h" #include "HID.h" #include "HID-Settings.h" diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.h b/plugins/KeyboardioHID/src/MultiReport/Mouse.h index d03dd17fd7..5723b70459 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.h @@ -27,7 +27,6 @@ THE SOFTWARE. #pragma once #include -#include "PluggableUSB.h" #include "HID.h" #include "HID-Settings.h" #include "../MouseButtons.h" diff --git a/plugins/KeyboardioHID/src/MultiReport/SystemControl.h b/plugins/KeyboardioHID/src/MultiReport/SystemControl.h index d56a7d8475..7f4bb98d4a 100644 --- a/plugins/KeyboardioHID/src/MultiReport/SystemControl.h +++ b/plugins/KeyboardioHID/src/MultiReport/SystemControl.h @@ -27,7 +27,6 @@ THE SOFTWARE. #pragma once #include -#include "PluggableUSB.h" #include "HID.h" #include "HID-Settings.h" #include "HIDTables.h" diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h index 0a8c43f2d2..2aa4196631 100644 --- a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h +++ b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h @@ -27,7 +27,6 @@ THE SOFTWARE. #pragma once #include -#include "PluggableUSB.h" #include "HID.h" #include "HID-Settings.h" #include "../DeviceAPIs/AbsoluteMouseAPI.h" From 192186d3581fc101cb8bb5ba9892774db48968d5 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Fri, 19 Apr 2019 23:12:34 +0200 Subject: [PATCH 533/602] Port the library to the Atmel SAMD core This is heavily based on the implementation of the same port in Nico Hood's HID project, but slightly adapted to KeyboardioHID. The SAMD port does not support `HID_GET_PROTOCOL` and `HID_GET_IDLE` yet, but everything else should be functional. Signed-off-by: Gergely Nagy --- .../src/BootKeyboard/BootKeyboard.cpp | 10 ++++ .../src/BootKeyboard/BootKeyboard.h | 2 +- plugins/KeyboardioHID/src/HID-Settings.h | 58 +++++++++++++++++++ .../src/MultiReport/SystemControl.cpp | 15 ++++- .../src/SingleReport/SingleAbsoluteMouse.h | 2 +- plugins/KeyboardioHID/src/arch/samd.cpp | 13 +++++ 6 files changed, 96 insertions(+), 4 deletions(-) create mode 100644 plugins/KeyboardioHID/src/arch/samd.cpp diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 105b4a9fc9..d25db7fab1 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -141,12 +141,22 @@ bool BootKeyboard_::setup(USBSetup& setup) { } if (request == HID_GET_PROTOCOL) { // TODO improve +#ifdef __AVR__ UEDATX = protocol; +#endif +#ifdef ARDUINO_ARCH_SAM + USBDevice.armSend(0, &protocol, 1); +#endif return true; } if (request == HID_GET_IDLE) { // TODO improve +#ifdef __AVR__ UEDATX = idle; +#endif +#ifdef ARDUINO_ARCH_SAM + USBDevice.armSend(0, &idle, 1); +#endif return true; } } diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index b2322591ee..50760af26a 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -75,7 +75,7 @@ class BootKeyboard_ : public PluggableUSBModule { int getDescriptor(USBSetup& setup); bool setup(USBSetup& setup); - uint8_t epType[1]; + EPTYPE_DESCRIPTOR_SIZE epType[1]; uint8_t protocol; uint8_t idle; diff --git a/plugins/KeyboardioHID/src/HID-Settings.h b/plugins/KeyboardioHID/src/HID-Settings.h index 26aa313b9d..5bf09eb92d 100644 --- a/plugins/KeyboardioHID/src/HID-Settings.h +++ b/plugins/KeyboardioHID/src/HID-Settings.h @@ -69,4 +69,62 @@ THE SOFTWARE. #define HID_REPORT_TYPE_OUTPUT 2 #define HID_REPORT_TYPE_FEATURE 3 +#if defined(ARDUINO_ARCH_AVR) + #include "PluggableUSB.h" + +#define EPTYPE_DESCRIPTOR_SIZE uint8_t + +#elif defined(ARDUINO_ARCH_SAM) + +#include "USB/PluggableUSB.h" + +#define EPTYPE_DESCRIPTOR_SIZE uint32_t +#define EP_TYPE_INTERRUPT_IN (UOTGHS_DEVEPTCFG_EPSIZE_512_BYTE | \ + UOTGHS_DEVEPTCFG_EPDIR_IN | \ + UOTGHS_DEVEPTCFG_EPTYPE_BLK | \ + UOTGHS_DEVEPTCFG_EPBK_1_BANK | \ + UOTGHS_DEVEPTCFG_NBTRANS_1_TRANS | \ + UOTGHS_DEVEPTCFG_ALLOC) +#define EP_TYPE_INTERRUPT_OUT (UOTGHS_DEVEPTCFG_EPSIZE_512_BYTE | \ + UOTGHS_DEVEPTCFG_EPTYPE_BLK | \ + UOTGHS_DEVEPTCFG_EPBK_1_BANK | \ + UOTGHS_DEVEPTCFG_NBTRANS_1_TRANS | \ + UOTGHS_DEVEPTCFG_ALLOC) +#define USB_EP_SIZE EPX_SIZE +#define USB_SendControl USBD_SendControl +#define USB_Available USBD_Available +#define USB_Recv USBD_Recv +#define USB_Send USBD_Send +#define USB_Flush USBD_Flush + +#elif defined(ARDUINO_ARCH_SAMD) + +#include "USB/PluggableUSB.h" + +#define EPTYPE_DESCRIPTOR_SIZE uint32_t +#define EP_TYPE_INTERRUPT_IN USB_ENDPOINT_TYPE_INTERRUPT | USB_ENDPOINT_IN(0); +#define EP_TYPE_INTERRUPT_OUT USB_ENDPOINT_TYPE_INTERRUPT | USB_ENDPOINT_OUT(0); +#define USB_EP_SIZE EPX_SIZE +//#define USB_SendControl USBDevice.sendControl -> real C++ functions to take care of PGM overloading +#define USB_Available USBDevice.available +#define USB_Recv USBDevice.recv +#define USB_RecvControl USBDevice.recvControl +#define USB_Send USBDevice.send +#define USB_Flush USBDevice.flush + +int USB_SendControl(void* y, uint8_t z); +int USB_SendControl(uint8_t x, const void* y, uint8_t z); + +#define TRANSFER_PGM 0 +#define TRANSFER_RELEASE 0 + +#define HID_REPORT_TYPE_INPUT 1 +#define HID_REPORT_TYPE_OUTPUT 2 +#define HID_REPORT_TYPE_FEATURE 3 + +#else + +#error "Unsupported architecture" + +#endif diff --git a/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp b/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp index 78a15c32a1..9f67a5957b 100644 --- a/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp @@ -26,6 +26,10 @@ THE SOFTWARE. #include "SystemControl.h" #include "DescriptorPrimitives.h" +#ifdef ARDUINO_ARCH_SAMD +#include "USB/SAMD21_USBDevice.h" +#endif + static const uint8_t _hidMultiReportDescriptorSystem[] PROGMEM = { //TODO limit to system keys only? /* System Control (Power Down, Sleep, Wakeup, ...) */ @@ -73,10 +77,17 @@ void SystemControl_::releaseAll(void) { } void SystemControl_::press(uint8_t s) { - if (s == HID_SYSTEM_WAKE_UP) + if (s == HID_SYSTEM_WAKE_UP) { +#ifdef __AVR__ USBDevice.wakeupHost(); - else +#endif +#ifdef ARDUINO_ARCH_SAMD + extern USBDevice_SAMD21G18x usbd; + usbd.wakeupHost(); +#endif + } else { sendReport(&s, sizeof(s)); + } } diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h index 2aa4196631..4d0a832f6c 100644 --- a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h +++ b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h @@ -45,7 +45,7 @@ class SingleAbsoluteMouse_ : public PluggableUSBModule, public AbsoluteMouseAPI int getDescriptor(USBSetup& setup); bool setup(USBSetup& setup); - uint8_t epType[1]; + EPTYPE_DESCRIPTOR_SIZE epType[1]; uint8_t protocol; uint8_t idle; diff --git a/plugins/KeyboardioHID/src/arch/samd.cpp b/plugins/KeyboardioHID/src/arch/samd.cpp new file mode 100644 index 0000000000..a50e79fdcc --- /dev/null +++ b/plugins/KeyboardioHID/src/arch/samd.cpp @@ -0,0 +1,13 @@ +#include "Arduino.h" + +#ifdef ARDUINO_ARCH_SAMD + +int USB_SendControl(void* b, unsigned char c) { + USBDevice.sendControl(b, c); +} + +int USB_SendControl(uint8_t a, const void* b, uint8_t c) { + USBDevice.sendControl(b, c); +} + +#endif From b20237c37d189427b185cf4f33f6142de327cc6d Mon Sep 17 00:00:00 2001 From: Florian Fleissner Date: Wed, 12 Jun 2019 19:01:40 +0200 Subject: [PATCH 534/602] Ran make astyle Signed-off-by: Florian Fleissner --- .../examples/Consumer/Consumer.ino | 24 +- .../examples/Gamepad/Gamepad.ino | 68 +-- .../Keyboard/BootKeyboard/BootKeyboard.ino | 42 +- .../Keyboard/KeyboardLed/KeyboardLed.ino | 42 +- .../examples/Keyboard/NKRO/NKRO.ino | 66 +-- .../Mouse/AbsoluteMouse/AbsoluteMouse.ino | 68 +-- .../Mouse/ImprovedMouse/ImprovedMouse.ino | 66 +-- .../KeyboardioHID/examples/System/System.ino | 48 +- .../src/BootKeyboard/BootKeyboard.cpp | 416 +++++++++--------- .../src/BootKeyboard/BootKeyboard.h | 86 ++-- plugins/KeyboardioHID/src/HID.cpp | 208 ++++----- plugins/KeyboardioHID/src/HID.h | 89 ++-- plugins/KeyboardioHID/src/LEDs.h | 16 +- .../src/MultiReport/ConsumerControl.cpp | 88 ++-- .../src/MultiReport/ConsumerControl.h | 46 +- .../KeyboardioHID/src/MultiReport/Gamepad.cpp | 132 +++--- .../KeyboardioHID/src/MultiReport/Gamepad.h | 150 +++---- .../src/MultiReport/Keyboard.cpp | 302 ++++++------- .../KeyboardioHID/src/MultiReport/Keyboard.h | 60 +-- .../KeyboardioHID/src/MultiReport/Mouse.cpp | 140 +++--- plugins/KeyboardioHID/src/MultiReport/Mouse.h | 66 +-- .../src/MultiReport/SystemControl.cpp | 66 +-- .../src/MultiReport/SystemControl.h | 28 +- .../src/SingleReport/SingleAbsoluteMouse.cpp | 132 +++--- .../src/SingleReport/SingleAbsoluteMouse.h | 7 +- 25 files changed, 1229 insertions(+), 1227 deletions(-) diff --git a/plugins/KeyboardioHID/examples/Consumer/Consumer.ino b/plugins/KeyboardioHID/examples/Consumer/Consumer.ino index b7ae7c9653..e54b4af736 100644 --- a/plugins/KeyboardioHID/examples/Consumer/Consumer.ino +++ b/plugins/KeyboardioHID/examples/Consumer/Consumer.ino @@ -15,22 +15,22 @@ const int pinLed = LED_BUILTIN; const int pinButton = 2; void setup() { - pinMode(pinLed, OUTPUT); - pinMode(pinButton, INPUT_PULLUP); + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); - // Sends a clean report to the host. This is important on any Arduino type. - ConsumerControl.begin(); + // Sends a clean report to the host. This is important on any Arduino type. + ConsumerControl.begin(); } void loop() { - if (!digitalRead(pinButton)) { - digitalWrite(pinLed, HIGH); + if (!digitalRead(pinButton)) { + digitalWrite(pinLed, HIGH); - // See HID Project documentation for more Consumer keys - ConsumerControl.write(HID_CONSUMER_PLAY_SLASH_PAUSE); + // See HID Project documentation for more Consumer keys + ConsumerControl.write(HID_CONSUMER_PLAY_SLASH_PAUSE); - // Simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } + // Simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } } diff --git a/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino b/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino index 40538f5189..6a35a70a31 100644 --- a/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino +++ b/plugins/KeyboardioHID/examples/Gamepad/Gamepad.ino @@ -18,48 +18,48 @@ const int pinLed = LED_BUILTIN; const int pinButton = 2; void setup() { - pinMode(pinLed, OUTPUT); - pinMode(pinButton, INPUT_PULLUP); + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); - // Sends a clean report to the host. This is important on any Arduino type. - Gamepad.begin(); + // Sends a clean report to the host. This is important on any Arduino type. + Gamepad.begin(); } void loop() { - if (!digitalRead(pinButton)) { - digitalWrite(pinLed, HIGH); + if (!digitalRead(pinButton)) { + digitalWrite(pinLed, HIGH); - // Press button 1-32 - static uint8_t count = 0; - count++; - if (count == 33) { - Gamepad.releaseAll(); - count = 0; - } else - Gamepad.press(count); + // Press button 1-32 + static uint8_t count = 0; + count++; + if (count == 33) { + Gamepad.releaseAll(); + count = 0; + } else + Gamepad.press(count); - // Move x/y Axis to a new position (16bit) - Gamepad.xAxis(random(0xFFFF)); - Gamepad.yAxis(random(0xFFFF)); + // Move x/y Axis to a new position (16bit) + Gamepad.xAxis(random(0xFFFF)); + Gamepad.yAxis(random(0xFFFF)); - // Go through all dPad positions - // values: 0-8 (0==centered) - static uint8_t dpad1 = GAMEPAD_DPAD_CENTERED; - Gamepad.dPad1(dpad1++); - if (dpad1 > GAMEPAD_DPAD_UP_LEFT) - dpad1 = GAMEPAD_DPAD_CENTERED; + // Go through all dPad positions + // values: 0-8 (0==centered) + static uint8_t dpad1 = GAMEPAD_DPAD_CENTERED; + Gamepad.dPad1(dpad1++); + if (dpad1 > GAMEPAD_DPAD_UP_LEFT) + dpad1 = GAMEPAD_DPAD_CENTERED; - static int8_t dpad2 = GAMEPAD_DPAD_CENTERED; - Gamepad.dPad2(dpad2--); - if (dpad2 < GAMEPAD_DPAD_CENTERED) - dpad2 = GAMEPAD_DPAD_UP_LEFT; + static int8_t dpad2 = GAMEPAD_DPAD_CENTERED; + Gamepad.dPad2(dpad2--); + if (dpad2 < GAMEPAD_DPAD_CENTERED) + dpad2 = GAMEPAD_DPAD_UP_LEFT; - // Functions above only set the values. - // This writes the report to the host. - Gamepad.write(); + // Functions above only set the values. + // This writes the report to the host. + Gamepad.write(); - // Simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } + // Simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } } diff --git a/plugins/KeyboardioHID/examples/Keyboard/BootKeyboard/BootKeyboard.ino b/plugins/KeyboardioHID/examples/Keyboard/BootKeyboard/BootKeyboard.ino index 698805aa3d..9d21a861ee 100644 --- a/plugins/KeyboardioHID/examples/Keyboard/BootKeyboard/BootKeyboard.ino +++ b/plugins/KeyboardioHID/examples/Keyboard/BootKeyboard/BootKeyboard.ino @@ -17,30 +17,30 @@ const int pinLed = LED_BUILTIN; const int pinButton = 2; void setup() { - pinMode(pinLed, OUTPUT); - pinMode(pinButton, INPUT_PULLUP); + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); - // Sends a clean report to the host. This is important on any Arduino type. - BootKeyboard.begin(); + // Sends a clean report to the host. This is important on any Arduino type. + BootKeyboard.begin(); } void loop() { - // Light led if keyboard uses the boot protocol (normally while in bios) - // Keep in mind that on a 16u2 and Arduino Micro HIGH and LOW for TX/RX Leds are inverted. - if (BootKeyboard.getProtocol() == HID_BOOT_PROTOCOL) - digitalWrite(pinLed, HIGH); - else - digitalWrite(pinLed, LOW); - - // Trigger caps lock manually via button - if (!digitalRead(pinButton)) { - BootKeyboard.press(HID_KEYBOARD_ENTER); - BootKeyboard.sendReport(); - BootKeyboard.releaseAll(); - BootKeyboard.sendReport(); - - // Simple debounce - delay(300); - } + // Light led if keyboard uses the boot protocol (normally while in bios) + // Keep in mind that on a 16u2 and Arduino Micro HIGH and LOW for TX/RX Leds are inverted. + if (BootKeyboard.getProtocol() == HID_BOOT_PROTOCOL) + digitalWrite(pinLed, HIGH); + else + digitalWrite(pinLed, LOW); + + // Trigger caps lock manually via button + if (!digitalRead(pinButton)) { + BootKeyboard.press(HID_KEYBOARD_ENTER); + BootKeyboard.sendReport(); + BootKeyboard.releaseAll(); + BootKeyboard.sendReport(); + + // Simple debounce + delay(300); + } } diff --git a/plugins/KeyboardioHID/examples/Keyboard/KeyboardLed/KeyboardLed.ino b/plugins/KeyboardioHID/examples/Keyboard/KeyboardLed/KeyboardLed.ino index 9aa7ed4f50..e501ff64cf 100644 --- a/plugins/KeyboardioHID/examples/Keyboard/KeyboardLed/KeyboardLed.ino +++ b/plugins/KeyboardioHID/examples/Keyboard/KeyboardLed/KeyboardLed.ino @@ -18,30 +18,30 @@ const int pinLed = LED_BUILTIN; const int pinButton = 2; void setup() { - pinMode(pinLed, OUTPUT); - pinMode(pinButton, INPUT_PULLUP); + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); - // Sends a clean report to the host. This is important on any Arduino type. - BootKeyboard.begin(); + // Sends a clean report to the host. This is important on any Arduino type. + BootKeyboard.begin(); } void loop() { - // Update Led equal to the caps lock state. - // Keep in mind that on a 16u2 and Arduino Micro HIGH and LOW for TX/RX Leds are inverted. - if (BootKeyboard.getLeds() & LED_CAPS_LOCK) - digitalWrite(pinLed, HIGH); - else - digitalWrite(pinLed, LOW); - - // Trigger caps lock manually via button - if (!digitalRead(pinButton)) { - BootKeyboard.press(HID_KEYBOARD_CAPS_LOCK); - BootKeyboard.sendReport(); - BootKeyboard.releaseAll(); - BootKeyboard.sendReport(); - - // Simple debounce - delay(300); - } + // Update Led equal to the caps lock state. + // Keep in mind that on a 16u2 and Arduino Micro HIGH and LOW for TX/RX Leds are inverted. + if (BootKeyboard.getLeds() & LED_CAPS_LOCK) + digitalWrite(pinLed, HIGH); + else + digitalWrite(pinLed, LOW); + + // Trigger caps lock manually via button + if (!digitalRead(pinButton)) { + BootKeyboard.press(HID_KEYBOARD_CAPS_LOCK); + BootKeyboard.sendReport(); + BootKeyboard.releaseAll(); + BootKeyboard.sendReport(); + + // Simple debounce + delay(300); + } } diff --git a/plugins/KeyboardioHID/examples/Keyboard/NKRO/NKRO.ino b/plugins/KeyboardioHID/examples/Keyboard/NKRO/NKRO.ino index 5179d3fb42..0c219729d3 100644 --- a/plugins/KeyboardioHID/examples/Keyboard/NKRO/NKRO.ino +++ b/plugins/KeyboardioHID/examples/Keyboard/NKRO/NKRO.ino @@ -19,42 +19,42 @@ const int pinLed = LED_BUILTIN; const int pinButton = 2; void setup() { - pinMode(pinLed, OUTPUT); - pinMode(pinButton, INPUT_PULLUP); + pinMode(pinLed, OUTPUT); + pinMode(pinButton, INPUT_PULLUP); - // Sends a clean report to the host. This is important on any Arduino type. - Keyboard.begin(); + // Sends a clean report to the host. This is important on any Arduino type. + Keyboard.begin(); } void loop() { - // Hold a lot of keys at the same time - if (!digitalRead(pinButton)) { - digitalWrite(pinLed, HIGH); - - // Do not press too many at once or some OS will have problems. - // Note that the resulting pressed order might differ, - // because all keys are pressed at the same time. - Keyboard.press(HID_KEYBOARD_0_AND_RIGHT_PAREN); - Keyboard.press(HID_KEYBOARD_1_AND_EXCLAMATION_POINT); - Keyboard.press(HID_KEYBOARD_2_AND_AT); - Keyboard.press(HID_KEYBOARD_3_AND_POUND); - Keyboard.press(HID_KEYBOARD_4_AND_DOLLAR); - Keyboard.press(HID_KEYBOARD_5_AND_PERCENT); - Keyboard.press(HID_KEYBOARD_6_AND_CARAT); - Keyboard.press(HID_KEYBOARD_7_AND_AMPERSAND); - Keyboard.press(HID_KEYBOARD_8_AND_ASTERISK); - Keyboard.press(HID_KEYBOARD_9_AND_LEFT_PAREN); - Keyboard.sendReport(); - - // Release all keys and hit enter - Keyboard.releaseAll(); - Keyboard.press(HID_KEYBOARD_ENTER); - Keyboard.sendReport(); - Keyboard.releaseAll(); - Keyboard.sendReport(); - - // Simple debounce - delay(300); - } + // Hold a lot of keys at the same time + if (!digitalRead(pinButton)) { + digitalWrite(pinLed, HIGH); + + // Do not press too many at once or some OS will have problems. + // Note that the resulting pressed order might differ, + // because all keys are pressed at the same time. + Keyboard.press(HID_KEYBOARD_0_AND_RIGHT_PAREN); + Keyboard.press(HID_KEYBOARD_1_AND_EXCLAMATION_POINT); + Keyboard.press(HID_KEYBOARD_2_AND_AT); + Keyboard.press(HID_KEYBOARD_3_AND_POUND); + Keyboard.press(HID_KEYBOARD_4_AND_DOLLAR); + Keyboard.press(HID_KEYBOARD_5_AND_PERCENT); + Keyboard.press(HID_KEYBOARD_6_AND_CARAT); + Keyboard.press(HID_KEYBOARD_7_AND_AMPERSAND); + Keyboard.press(HID_KEYBOARD_8_AND_ASTERISK); + Keyboard.press(HID_KEYBOARD_9_AND_LEFT_PAREN); + Keyboard.sendReport(); + + // Release all keys and hit enter + Keyboard.releaseAll(); + Keyboard.press(HID_KEYBOARD_ENTER); + Keyboard.sendReport(); + Keyboard.releaseAll(); + Keyboard.sendReport(); + + // Simple debounce + delay(300); + } } diff --git a/plugins/KeyboardioHID/examples/Mouse/AbsoluteMouse/AbsoluteMouse.ino b/plugins/KeyboardioHID/examples/Mouse/AbsoluteMouse/AbsoluteMouse.ino index 6c67a41f3f..02b2479c5c 100644 --- a/plugins/KeyboardioHID/examples/Mouse/AbsoluteMouse/AbsoluteMouse.ino +++ b/plugins/KeyboardioHID/examples/Mouse/AbsoluteMouse/AbsoluteMouse.ino @@ -18,50 +18,50 @@ const int pinButtonCenter = 3; const int pinButtonMove = 1; void setup() { - // Prepare led + buttons - pinMode(pinLed, OUTPUT); - pinMode(pinButtonClick, INPUT_PULLUP); - pinMode(pinButtonCenter, INPUT_PULLUP); - pinMode(pinButtonMove, INPUT_PULLUP); + // Prepare led + buttons + pinMode(pinLed, OUTPUT); + pinMode(pinButtonClick, INPUT_PULLUP); + pinMode(pinButtonCenter, INPUT_PULLUP); + pinMode(pinButtonMove, INPUT_PULLUP); - // Sends a clean report to the host. This is important on any Arduino type. - AbsoluteMouse.begin(); + // Sends a clean report to the host. This is important on any Arduino type. + AbsoluteMouse.begin(); } void loop() { - if (!digitalRead(pinButtonClick)) { - digitalWrite(pinLed, HIGH); + if (!digitalRead(pinButtonClick)) { + digitalWrite(pinLed, HIGH); - // Same use as the official library, pretty much self explaining - AbsoluteMouse.click(); - //AbsoluteMouse.click(MOUSE_RIGHT); + // Same use as the official library, pretty much self explaining + AbsoluteMouse.click(); + //AbsoluteMouse.click(MOUSE_RIGHT); - // Simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } + // Simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } - if (!digitalRead(pinButtonCenter)) { - digitalWrite(pinLed, HIGH); + if (!digitalRead(pinButtonCenter)) { + digitalWrite(pinLed, HIGH); - // Move to coordinate (16bit signed, -32768 - 32767) - // Moving to the same position twice will not work! - // X and Y start in the upper left corner. - AbsoluteMouse.moveTo(0, 0); + // Move to coordinate (16bit signed, -32768 - 32767) + // Moving to the same position twice will not work! + // X and Y start in the upper left corner. + AbsoluteMouse.moveTo(0, 0); - // Simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } + // Simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } - if (!digitalRead(pinButtonMove)) { - digitalWrite(pinLed, HIGH); + if (!digitalRead(pinButtonMove)) { + digitalWrite(pinLed, HIGH); - // Move relative to last coordinate - AbsoluteMouse.move(1000, 1000); + // Move relative to last coordinate + AbsoluteMouse.move(1000, 1000); - // Simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } + // Simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } } diff --git a/plugins/KeyboardioHID/examples/Mouse/ImprovedMouse/ImprovedMouse.ino b/plugins/KeyboardioHID/examples/Mouse/ImprovedMouse/ImprovedMouse.ino index 378b06ea85..e087ef3947 100644 --- a/plugins/KeyboardioHID/examples/Mouse/ImprovedMouse/ImprovedMouse.ino +++ b/plugins/KeyboardioHID/examples/Mouse/ImprovedMouse/ImprovedMouse.ino @@ -21,49 +21,49 @@ const int pinButtonMove = 3; const int pinButtonScroll = 4; void setup() { - // Prepare led + buttons - pinMode(pinLed, OUTPUT); - pinMode(pinButtonClick, INPUT_PULLUP); - pinMode(pinButtonMove, INPUT_PULLUP); - pinMode(pinButtonScroll, INPUT_PULLUP); - - // Sends a clean report to the host. This is important on any Arduino type. - Mouse.begin(); + // Prepare led + buttons + pinMode(pinLed, OUTPUT); + pinMode(pinButtonClick, INPUT_PULLUP); + pinMode(pinButtonMove, INPUT_PULLUP); + pinMode(pinButtonScroll, INPUT_PULLUP); + + // Sends a clean report to the host. This is important on any Arduino type. + Mouse.begin(); } void loop() { - if (!digitalRead(pinButtonClick)) { - digitalWrite(pinLed, HIGH); + if (!digitalRead(pinButtonClick)) { + digitalWrite(pinLed, HIGH); - // Same use as the official library, pretty much self explaining - Mouse.click(); - //Mouse.click(MOUSE_RIGHT); + // Same use as the official library, pretty much self explaining + Mouse.click(); + //Mouse.click(MOUSE_RIGHT); - // Simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } + // Simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } - if (!digitalRead(pinButtonMove)) { - digitalWrite(pinLed, HIGH); + if (!digitalRead(pinButtonMove)) { + digitalWrite(pinLed, HIGH); - // Same use as the official library, pretty much self explaining - Mouse.move(100, 0); + // Same use as the official library, pretty much self explaining + Mouse.move(100, 0); - // Simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } + // Simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } - if (!digitalRead(pinButtonScroll)) { - digitalWrite(pinLed, HIGH); + if (!digitalRead(pinButtonScroll)) { + digitalWrite(pinLed, HIGH); - // Scroll down a bit, make sure the value is high enough - Mouse.move(0, 0, 160); + // Scroll down a bit, make sure the value is high enough + Mouse.move(0, 0, 160); - // simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } + // simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } } diff --git a/plugins/KeyboardioHID/examples/System/System.ino b/plugins/KeyboardioHID/examples/System/System.ino index 29587a81ea..ecf32bdb99 100644 --- a/plugins/KeyboardioHID/examples/System/System.ino +++ b/plugins/KeyboardioHID/examples/System/System.ino @@ -17,37 +17,37 @@ const int pinButtonS = 2; const int pinButtonW = 3; void setup() { - // prepare led + buttons - pinMode(pinLed, OUTPUT); - pinMode(pinButtonS, INPUT_PULLUP); - pinMode(pinButtonW, INPUT_PULLUP); + // prepare led + buttons + pinMode(pinLed, OUTPUT); + pinMode(pinButtonS, INPUT_PULLUP); + pinMode(pinButtonW, INPUT_PULLUP); - // Sends a clean report to the host. This is important on any Arduino type. - SystemControl.begin(); + // Sends a clean report to the host. This is important on any Arduino type. + SystemControl.begin(); } void loop() { - if (!digitalRead(pinButtonS)) { - digitalWrite(pinLed, HIGH); + if (!digitalRead(pinButtonS)) { + digitalWrite(pinLed, HIGH); - // Puts PC into sleep mode/shuts it down - SystemControl.write(HID_SYSTEM_SLEEP); - //SystemControl.write(HID_SYSTEM_POWER_DOWN); + // Puts PC into sleep mode/shuts it down + SystemControl.write(HID_SYSTEM_SLEEP); + //SystemControl.write(HID_SYSTEM_POWER_DOWN); - // Simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } + // Simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } - if (!digitalRead(pinButtonW)) { - digitalWrite(pinLed, HIGH); + if (!digitalRead(pinButtonW)) { + digitalWrite(pinLed, HIGH); - // Try to wake up the PC - // This might fail on some PCs/Laptops where USB wakeup is not supported - SystemControl.write(HID_SYSTEM_WAKE_UP); + // Try to wake up the PC + // This might fail on some PCs/Laptops where USB wakeup is not supported + SystemControl.write(HID_SYSTEM_WAKE_UP); - // Simple debounce - delay(300); - digitalWrite(pinLed, LOW); - } + // Simple debounce + delay(300); + digitalWrite(pinLed, LOW); + } } diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index d25db7fab1..610a01f141 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -28,199 +28,199 @@ THE SOFTWARE. // See Appendix B of USB HID spec static const uint8_t _hidReportDescriptorKeyboard[] PROGMEM = { - // Keyboard - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, - D_USAGE, D_USAGE_KEYBOARD, - - D_COLLECTION, D_APPLICATION, - // Modifiers - D_USAGE_PAGE, D_PAGE_KEYBOARD, - D_USAGE_MINIMUM, 0xe0, - D_USAGE_MAXIMUM, 0xe7, - D_LOGICAL_MINIMUM, 0x0, - D_LOGICAL_MAXIMUM, 0x1, - D_REPORT_SIZE, 0x1, - D_REPORT_COUNT, 0x8, - D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), - - // Reserved byte - D_REPORT_COUNT, 0x1, - D_REPORT_SIZE, 0x8, - D_INPUT, (D_CONSTANT), - - // LEDs - D_REPORT_COUNT, 0x5, - D_REPORT_SIZE, 0x1, - D_USAGE_PAGE, D_PAGE_LEDS, - D_USAGE_MINIMUM, 0x1, - D_USAGE_MAXIMUM, 0x5, - D_OUTPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), - // Pad LEDs up to a byte - D_REPORT_COUNT, 0x1, - D_REPORT_SIZE, 0x3, - D_OUTPUT, (D_CONSTANT), - - // Non-modifiers - D_REPORT_COUNT, 0x6, - D_REPORT_SIZE, 0x8, - D_LOGICAL_MINIMUM, 0x0, - D_LOGICAL_MAXIMUM, 0xff, - D_USAGE_PAGE, D_PAGE_KEYBOARD, - D_USAGE_MINIMUM, 0x0, - D_USAGE_MAXIMUM, 0xff, - D_INPUT, (D_DATA|D_ARRAY|D_ABSOLUTE), - D_END_COLLECTION + // Keyboard + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, + D_USAGE, D_USAGE_KEYBOARD, + + D_COLLECTION, D_APPLICATION, + // Modifiers + D_USAGE_PAGE, D_PAGE_KEYBOARD, + D_USAGE_MINIMUM, 0xe0, + D_USAGE_MAXIMUM, 0xe7, + D_LOGICAL_MINIMUM, 0x0, + D_LOGICAL_MAXIMUM, 0x1, + D_REPORT_SIZE, 0x1, + D_REPORT_COUNT, 0x8, + D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), + + // Reserved byte + D_REPORT_COUNT, 0x1, + D_REPORT_SIZE, 0x8, + D_INPUT, (D_CONSTANT), + + // LEDs + D_REPORT_COUNT, 0x5, + D_REPORT_SIZE, 0x1, + D_USAGE_PAGE, D_PAGE_LEDS, + D_USAGE_MINIMUM, 0x1, + D_USAGE_MAXIMUM, 0x5, + D_OUTPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), + // Pad LEDs up to a byte + D_REPORT_COUNT, 0x1, + D_REPORT_SIZE, 0x3, + D_OUTPUT, (D_CONSTANT), + + // Non-modifiers + D_REPORT_COUNT, 0x6, + D_REPORT_SIZE, 0x8, + D_LOGICAL_MINIMUM, 0x0, + D_LOGICAL_MAXIMUM, 0xff, + D_USAGE_PAGE, D_PAGE_KEYBOARD, + D_USAGE_MINIMUM, 0x0, + D_USAGE_MAXIMUM, 0xff, + D_INPUT, (D_DATA|D_ARRAY|D_ABSOLUTE), + D_END_COLLECTION }; BootKeyboard_::BootKeyboard_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1), leds(0) { - epType[0] = EP_TYPE_INTERRUPT_IN; + epType[0] = EP_TYPE_INTERRUPT_IN; } int BootKeyboard_::getInterface(uint8_t* interfaceCount) { - *interfaceCount += 1; // uses 1 - HIDDescriptor hidInterface = { - D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_BOOT_INTERFACE, HID_PROTOCOL_KEYBOARD), - D_HIDREPORT(sizeof(_hidReportDescriptorKeyboard)), - D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) - }; - return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); + *interfaceCount += 1; // uses 1 + HIDDescriptor hidInterface = { + D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_BOOT_INTERFACE, HID_PROTOCOL_KEYBOARD), + D_HIDREPORT(sizeof(_hidReportDescriptorKeyboard)), + D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) + }; + return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); } int BootKeyboard_::getDescriptor(USBSetup& setup) { - // Check if this is a HID Class Descriptor request - if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { - return 0; - } - if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { - return 0; - } - - // In a HID Class Descriptor wIndex cointains the interface number - if (setup.wIndex != pluggedInterface) { - return 0; - } - - // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol - // due to the USB specs, but Windows and Linux just assumes its in report mode. - protocol = default_protocol; - - return USB_SendControl(TRANSFER_PGM, _hidReportDescriptorKeyboard, sizeof(_hidReportDescriptorKeyboard)); + // Check if this is a HID Class Descriptor request + if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { + return 0; + } + if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { + return 0; + } + + // In a HID Class Descriptor wIndex cointains the interface number + if (setup.wIndex != pluggedInterface) { + return 0; + } + + // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol + // due to the USB specs, but Windows and Linux just assumes its in report mode. + protocol = default_protocol; + + return USB_SendControl(TRANSFER_PGM, _hidReportDescriptorKeyboard, sizeof(_hidReportDescriptorKeyboard)); } void BootKeyboard_::begin(void) { - PluggableUSB().plug(this); + PluggableUSB().plug(this); - // Force API to send a clean report. - // This is important for and HID bridge where the receiver stays on, - // while the sender is resetted. - releaseAll(); - sendReport(); + // Force API to send a clean report. + // This is important for and HID bridge where the receiver stays on, + // while the sender is resetted. + releaseAll(); + sendReport(); } void BootKeyboard_::end(void) { - releaseAll(); - sendReport(); + releaseAll(); + sendReport(); } bool BootKeyboard_::setup(USBSetup& setup) { - if (pluggedInterface != setup.wIndex) { - return false; - } + if (pluggedInterface != setup.wIndex) { + return false; + } - uint8_t request = setup.bRequest; - uint8_t requestType = setup.bmRequestType; + uint8_t request = setup.bRequest; + uint8_t requestType = setup.bmRequestType; - if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) { - if (request == HID_GET_REPORT) { - // TODO: HID_GetReport(); - return true; - } - if (request == HID_GET_PROTOCOL) { - // TODO improve + if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) { + if (request == HID_GET_REPORT) { + // TODO: HID_GetReport(); + return true; + } + if (request == HID_GET_PROTOCOL) { + // TODO improve #ifdef __AVR__ - UEDATX = protocol; + UEDATX = protocol; #endif #ifdef ARDUINO_ARCH_SAM - USBDevice.armSend(0, &protocol, 1); + USBDevice.armSend(0, &protocol, 1); #endif - return true; - } - if (request == HID_GET_IDLE) { - // TODO improve + return true; + } + if (request == HID_GET_IDLE) { + // TODO improve #ifdef __AVR__ - UEDATX = idle; + UEDATX = idle; #endif #ifdef ARDUINO_ARCH_SAM - USBDevice.armSend(0, &idle, 1); + USBDevice.armSend(0, &idle, 1); #endif - return true; + return true; + } } - } - if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) { - if (request == HID_SET_PROTOCOL) { - protocol = setup.wValueL; - return true; - } - if (request == HID_SET_IDLE) { - // We currently ignore SET_IDLE, because we don't really do anything with it, and implementing - // it causes issues on OSX, such as key chatter. Other operating systems do not suffer if we - // force this to zero, either. + if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) { + if (request == HID_SET_PROTOCOL) { + protocol = setup.wValueL; + return true; + } + if (request == HID_SET_IDLE) { + // We currently ignore SET_IDLE, because we don't really do anything with it, and implementing + // it causes issues on OSX, such as key chatter. Other operating systems do not suffer if we + // force this to zero, either. #if 0 - idle = setup.wValueL; + idle = setup.wValueL; #else - idle = 0; + idle = 0; #endif - return true; - } - if (request == HID_SET_REPORT) { - // Check if data has the correct length afterwards - int length = setup.wLength; - - if (setup.wValueH == HID_REPORT_TYPE_OUTPUT) { - if (length == sizeof(leds)) { - USB_RecvControl(&leds, length); - return true; + return true; } - } - - // Input (set HID report) - else if (setup.wValueH == HID_REPORT_TYPE_INPUT) { - if (length == sizeof(_keyReport)) { - USB_RecvControl(&_keyReport, length); - return true; + if (request == HID_SET_REPORT) { + // Check if data has the correct length afterwards + int length = setup.wLength; + + if (setup.wValueH == HID_REPORT_TYPE_OUTPUT) { + if (length == sizeof(leds)) { + USB_RecvControl(&leds, length); + return true; + } + } + + // Input (set HID report) + else if (setup.wValueH == HID_REPORT_TYPE_INPUT) { + if (length == sizeof(_keyReport)) { + USB_RecvControl(&_keyReport, length); + return true; + } + } } - } } - } - return false; + return false; } uint8_t BootKeyboard_::getLeds(void) { - return leds; + return leds; } uint8_t BootKeyboard_::getProtocol(void) { - return protocol; + return protocol; } void BootKeyboard_::setProtocol(uint8_t protocol) { - this->protocol = protocol; + this->protocol = protocol; } int BootKeyboard_::sendReport(void) { - if (memcmp(&_lastKeyReport, &_keyReport, sizeof(_keyReport))) { - // if the two reports are different, send a report - int returnCode = USB_Send(pluggedEndpoint | TRANSFER_RELEASE, &_keyReport, sizeof(_keyReport)); - memcpy(&_lastKeyReport, &_keyReport, sizeof(_keyReport)); - return returnCode; - } - return -1; + if (memcmp(&_lastKeyReport, &_keyReport, sizeof(_keyReport))) { + // if the two reports are different, send a report + int returnCode = USB_Send(pluggedEndpoint | TRANSFER_RELEASE, &_keyReport, sizeof(_keyReport)); + memcpy(&_lastKeyReport, &_keyReport, sizeof(_keyReport)); + return returnCode; + } + return -1; } // press() adds the specified key (printing, non-printing, or modifier) @@ -230,35 +230,35 @@ int BootKeyboard_::sendReport(void) { size_t BootKeyboard_::press(uint8_t k) { - uint8_t done = 0; - - if ((k >= HID_KEYBOARD_FIRST_MODIFIER) && (k <= HID_KEYBOARD_LAST_MODIFIER)) { - // it's a modifier key - _keyReport.modifiers |= (0x01 << (k - HID_KEYBOARD_FIRST_MODIFIER)); - } else { - // it's some other key: - // Add k to the key report only if it's not already present - // and if there is an empty slot. - for (uint8_t i = 0; i < sizeof(_keyReport.keycodes); i++) { - if (_keyReport.keycodes[i] != k) { // is k already in list? - if (0 == _keyReport.keycodes[i]) { // have we found an empty slot? - _keyReport.keycodes[i] = k; - done = 1; - break; + uint8_t done = 0; + + if ((k >= HID_KEYBOARD_FIRST_MODIFIER) && (k <= HID_KEYBOARD_LAST_MODIFIER)) { + // it's a modifier key + _keyReport.modifiers |= (0x01 << (k - HID_KEYBOARD_FIRST_MODIFIER)); + } else { + // it's some other key: + // Add k to the key report only if it's not already present + // and if there is an empty slot. + for (uint8_t i = 0; i < sizeof(_keyReport.keycodes); i++) { + if (_keyReport.keycodes[i] != k) { // is k already in list? + if (0 == _keyReport.keycodes[i]) { // have we found an empty slot? + _keyReport.keycodes[i] = k; + done = 1; + break; + } + } else { + done = 1; + break; + } + } + // use separate variable to check if slot was found + // for style reasons - we do not know how the compiler + // handles the for() index when it leaves the loop + if (0 == done) { + return 0; } - } else { - done = 1; - break; - } - } - // use separate variable to check if slot was found - // for style reasons - we do not know how the compiler - // handles the for() index when it leaves the loop - if (0 == done) { - return 0; } - } - return 1; + return 1; } @@ -267,43 +267,43 @@ size_t BootKeyboard_::press(uint8_t k) { // it shouldn't be repeated any more. size_t BootKeyboard_::release(uint8_t k) { - if ((k >= HID_KEYBOARD_FIRST_MODIFIER) && (k <= HID_KEYBOARD_LAST_MODIFIER)) { - // it's a modifier key - _keyReport.modifiers = _keyReport.modifiers & (~(0x01 << (k - HID_KEYBOARD_FIRST_MODIFIER))); - } else { - // it's some other key: - // 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 (uint8_t i = 0; i < sizeof(_keyReport.keycodes); i++) { - if (_keyReport.keycodes[i] == k) { - _keyReport.keycodes[i] = 0; - } - } + if ((k >= HID_KEYBOARD_FIRST_MODIFIER) && (k <= HID_KEYBOARD_LAST_MODIFIER)) { + // it's a modifier key + _keyReport.modifiers = _keyReport.modifiers & (~(0x01 << (k - HID_KEYBOARD_FIRST_MODIFIER))); + } else { + // it's some other key: + // 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 (uint8_t i = 0; i < sizeof(_keyReport.keycodes); i++) { + if (_keyReport.keycodes[i] == k) { + _keyReport.keycodes[i] = 0; + } + } - // rearrange the keys list so that the free (= 0x00) are at the - // end of the keys list - some implementations stop for keys at the - // first occurence of an 0x00 in the keys list - // so (0x00)(0x01)(0x00)(0x03)(0x02)(0x00) becomes - // (0x03)(0x02)(0x01)(0x00)(0x00)(0x00) - uint8_t current = 0, nextpos = 0; - - while (current < sizeof(_keyReport.keycodes)) { - if (_keyReport.keycodes[current]) { - uint8_t tmp = _keyReport.keycodes[nextpos]; - _keyReport.keycodes[nextpos] = _keyReport.keycodes[current]; - _keyReport.keycodes[current] = tmp; - ++nextpos; - } - ++current; + // rearrange the keys list so that the free (= 0x00) are at the + // end of the keys list - some implementations stop for keys at the + // first occurence of an 0x00 in the keys list + // so (0x00)(0x01)(0x00)(0x03)(0x02)(0x00) becomes + // (0x03)(0x02)(0x01)(0x00)(0x00)(0x00) + uint8_t current = 0, nextpos = 0; + + while (current < sizeof(_keyReport.keycodes)) { + if (_keyReport.keycodes[current]) { + uint8_t tmp = _keyReport.keycodes[nextpos]; + _keyReport.keycodes[nextpos] = _keyReport.keycodes[current]; + _keyReport.keycodes[current] = tmp; + ++nextpos; + } + ++current; + } } - } - return 1; + return 1; } void BootKeyboard_::releaseAll(void) { - memset(&_keyReport.bytes, 0x00, sizeof(_keyReport.bytes)); + memset(&_keyReport.bytes, 0x00, sizeof(_keyReport.bytes)); } @@ -337,36 +337,36 @@ boolean BootKeyboard_::wasKeyPressed(uint8_t k) { * Returns false in all other cases * */ boolean BootKeyboard_::isModifierActive(uint8_t k) { - if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { - k = k - HID_KEYBOARD_FIRST_MODIFIER; - return !!(_keyReport.modifiers & (1 << k)); - } - return false; + if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { + k = k - HID_KEYBOARD_FIRST_MODIFIER; + return !!(_keyReport.modifiers & (1 << k)); + } + return false; } /* Returns true if the modifer key passed in was being sent during the previous key report * Returns false in all other cases * */ boolean BootKeyboard_::wasModifierActive(uint8_t k) { - if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { - k = k - HID_KEYBOARD_FIRST_MODIFIER; - return !!(_lastKeyReport.modifiers & (1 << k)); - } - return false; + if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { + k = k - HID_KEYBOARD_FIRST_MODIFIER; + return !!(_lastKeyReport.modifiers & (1 << k)); + } + return false; } /* Returns true if any modifier key will be sent during this key report * Returns false in all other cases * */ boolean BootKeyboard_::isAnyModifierActive() { - return _keyReport.modifiers > 0; + return _keyReport.modifiers > 0; } /* Returns true if any modifier key was being sent during the previous key report * Returns false in all other cases * */ boolean BootKeyboard_::wasAnyModifierActive() { - return _lastKeyReport.modifiers > 0; + return _lastKeyReport.modifiers > 0; } BootKeyboard_ BootKeyboard; diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index 50760af26a..3cfe7b12a5 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -33,52 +33,52 @@ THE SOFTWARE. #include "HIDAliases.h" typedef union { - // Low level key report: up to 6 keys and shift, ctrl etc at once - struct { - uint8_t modifiers; - uint8_t reserved; - uint8_t keycodes[6]; - }; - uint8_t bytes[8]; + // Low level key report: up to 6 keys and shift, ctrl etc at once + struct { + uint8_t modifiers; + uint8_t reserved; + uint8_t keycodes[6]; + }; + uint8_t bytes[8]; } HID_BootKeyboardReport_Data_t; class BootKeyboard_ : public PluggableUSBModule { - public: - BootKeyboard_(void); - size_t press(uint8_t); - void begin(void); - void end(void); - size_t release(uint8_t); - void releaseAll(void); - - int sendReport(void); - - boolean isModifierActive(uint8_t k); - boolean wasModifierActive(uint8_t k); - boolean isAnyModifierActive(); - boolean wasAnyModifierActive(); - boolean isKeyPressed(uint8_t k); - boolean wasKeyPressed(uint8_t k); - - uint8_t getLeds(void); - uint8_t getProtocol(void); - void setProtocol(uint8_t protocol); - - uint8_t default_protocol = HID_REPORT_PROTOCOL; - - protected: - HID_BootKeyboardReport_Data_t _keyReport, _lastKeyReport; - - // Implementation of the PUSBListNode - int getInterface(uint8_t* interfaceCount); - int getDescriptor(USBSetup& setup); - bool setup(USBSetup& setup); - - EPTYPE_DESCRIPTOR_SIZE epType[1]; - uint8_t protocol; - uint8_t idle; - - uint8_t leds; + public: + BootKeyboard_(void); + size_t press(uint8_t); + void begin(void); + void end(void); + size_t release(uint8_t); + void releaseAll(void); + + int sendReport(void); + + boolean isModifierActive(uint8_t k); + boolean wasModifierActive(uint8_t k); + boolean isAnyModifierActive(); + boolean wasAnyModifierActive(); + boolean isKeyPressed(uint8_t k); + boolean wasKeyPressed(uint8_t k); + + uint8_t getLeds(void); + uint8_t getProtocol(void); + void setProtocol(uint8_t protocol); + + uint8_t default_protocol = HID_REPORT_PROTOCOL; + + protected: + HID_BootKeyboardReport_Data_t _keyReport, _lastKeyReport; + + // Implementation of the PUSBListNode + int getInterface(uint8_t* interfaceCount); + int getDescriptor(USBSetup& setup); + bool setup(USBSetup& setup); + + EPTYPE_DESCRIPTOR_SIZE epType[1]; + uint8_t protocol; + uint8_t idle; + + uint8_t leds; }; extern BootKeyboard_ BootKeyboard; diff --git a/plugins/KeyboardioHID/src/HID.cpp b/plugins/KeyboardioHID/src/HID.cpp index 526ed892e4..8d64ad4e4c 100644 --- a/plugins/KeyboardioHID/src/HID.cpp +++ b/plugins/KeyboardioHID/src/HID.cpp @@ -21,140 +21,140 @@ #if defined(USBCON) HID_& HID() { - static HID_ obj; - return obj; + static HID_ obj; + return obj; } int HID_::getInterface(uint8_t* interfaceCount) { - *interfaceCount += 1; // uses 1 - HIDDescriptor hidInterface = { - D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE), - D_HIDREPORT(descriptorSize), - D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) - }; - return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); + *interfaceCount += 1; // uses 1 + HIDDescriptor hidInterface = { + D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE), + D_HIDREPORT(descriptorSize), + D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) + }; + return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); } int HID_::getDescriptor(USBSetup& setup) { - // Check if this is a HID Class Descriptor request - if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { - return 0; - } - if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { - return 0; - } + // Check if this is a HID Class Descriptor request + if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { + return 0; + } + if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { + return 0; + } - // In a HID Class Descriptor wIndex cointains the interface number - if (setup.wIndex != pluggedInterface) { - return 0; - } - - int total = 0; - HIDSubDescriptor* node; - for (node = rootNode; node; node = node->next) { - int res = USB_SendControl(TRANSFER_PGM, node->data, node->length); - if (res == -1) - return -1; - total += res; - } - - // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol - // due to the USB specs, but Windows and Linux just assumes its in report mode. - protocol = HID_REPORT_PROTOCOL; - - return total; + // In a HID Class Descriptor wIndex cointains the interface number + if (setup.wIndex != pluggedInterface) { + return 0; + } + + int total = 0; + HIDSubDescriptor* node; + for (node = rootNode; node; node = node->next) { + int res = USB_SendControl(TRANSFER_PGM, node->data, node->length); + if (res == -1) + return -1; + total += res; + } + + // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol + // due to the USB specs, but Windows and Linux just assumes its in report mode. + protocol = HID_REPORT_PROTOCOL; + + return total; } uint8_t HID_::getShortName(char *name) { - name[0] = 'k'; - name[1] = 'b'; - name[2] = 'i'; - name[3] = 'o'; - name[4] = '0'; - name[5] = '1'; - return 6; + name[0] = 'k'; + name[1] = 'b'; + name[2] = 'i'; + name[3] = 'o'; + name[4] = '0'; + name[5] = '1'; + return 6; } void HID_::AppendDescriptor(HIDSubDescriptor *node) { - if (!rootNode) { - rootNode = node; - } else { - HIDSubDescriptor *current = rootNode; - while (current->next) { - current = current->next; + if (!rootNode) { + rootNode = node; + } else { + HIDSubDescriptor *current = rootNode; + while (current->next) { + current = current->next; + } + current->next = node; } - current->next = node; - } - descriptorSize += node->length; + descriptorSize += node->length; } int HID_::SendReport(uint8_t id, const void* data, int len) { - auto ret = USB_Send(pluggedEndpoint, &id, 1); - if (ret < 0) return ret; - auto ret2 = USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, len); - if (ret2 < 0) return ret2; - return ret + ret2; + auto ret = USB_Send(pluggedEndpoint, &id, 1); + if (ret < 0) return ret; + auto ret2 = USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, len); + if (ret2 < 0) return ret2; + return ret + ret2; } bool HID_::setup(USBSetup& setup) { - if (pluggedInterface != setup.wIndex) { - return false; - } - - uint8_t request = setup.bRequest; - uint8_t requestType = setup.bmRequestType; - - if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) { - if (request == HID_GET_REPORT) { - // TODO: HID_GetReport(); - return true; - } - if (request == HID_GET_PROTOCOL) { - // TODO: Send8(protocol); - return true; - } - if (request == HID_GET_IDLE) { - // TODO: Send8(idle); + if (pluggedInterface != setup.wIndex) { + return false; } - } - - if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) { - if (request == HID_SET_PROTOCOL) { - // The USB Host tells us if we are in boot or report mode. - // This only works with a real boot compatible device. - protocol = setup.wValueL; - return true; - } - if (request == HID_SET_IDLE) { - idle = setup.wValueL; - return true; + + uint8_t request = setup.bRequest; + uint8_t requestType = setup.bmRequestType; + + if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) { + if (request == HID_GET_REPORT) { + // TODO: HID_GetReport(); + return true; + } + if (request == HID_GET_PROTOCOL) { + // TODO: Send8(protocol); + return true; + } + if (request == HID_GET_IDLE) { + // TODO: Send8(idle); + } } - if (request == HID_SET_REPORT) { - uint16_t length = setup.wLength; - - if (length == sizeof(setReportData)) { - USB_RecvControl(&setReportData, length); - } else if (length == sizeof(setReportData.leds)) { - USB_RecvControl(&setReportData.leds, length); - setReportData.reportId = 0; - } + + if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) { + if (request == HID_SET_PROTOCOL) { + // The USB Host tells us if we are in boot or report mode. + // This only works with a real boot compatible device. + protocol = setup.wValueL; + return true; + } + if (request == HID_SET_IDLE) { + idle = setup.wValueL; + return true; + } + if (request == HID_SET_REPORT) { + uint16_t length = setup.wLength; + + if (length == sizeof(setReportData)) { + USB_RecvControl(&setReportData, length); + } else if (length == sizeof(setReportData.leds)) { + USB_RecvControl(&setReportData.leds, length); + setReportData.reportId = 0; + } + } } - } - return false; + return false; } HID_::HID_(void) : PluggableUSBModule(1, 1, epType), - rootNode(NULL), descriptorSize(0), - protocol(HID_REPORT_PROTOCOL), idle(1) { - setReportData.reportId = 0; - setReportData.leds = 0; - epType[0] = EP_TYPE_INTERRUPT_IN; - PluggableUSB().plug(this); + rootNode(NULL), descriptorSize(0), + protocol(HID_REPORT_PROTOCOL), idle(1) { + setReportData.reportId = 0; + setReportData.leds = 0; + epType[0] = EP_TYPE_INTERRUPT_IN; + PluggableUSB().plug(this); } int HID_::begin(void) { - return 0; + return 0; } #endif /* if defined(USBCON) */ diff --git a/plugins/KeyboardioHID/src/HID.h b/plugins/KeyboardioHID/src/HID.h index 15a7ccd0a6..b2fd38b2e7 100644 --- a/plugins/KeyboardioHID/src/HID.h +++ b/plugins/KeyboardioHID/src/HID.h @@ -60,59 +60,62 @@ #define HID_REPORT_TYPE_FEATURE 3 typedef struct { - uint8_t len; // 9 - uint8_t dtype; // 0x21 - uint8_t addr; - uint8_t versionL; // 0x101 - uint8_t versionH; // 0x101 - uint8_t country; - uint8_t desctype; // 0x22 report - uint8_t descLenL; - uint8_t descLenH; + uint8_t len; // 9 + uint8_t dtype; // 0x21 + uint8_t addr; + uint8_t versionL; // 0x101 + uint8_t versionH; // 0x101 + uint8_t country; + uint8_t desctype; // 0x22 report + uint8_t descLenL; + uint8_t descLenH; } HIDDescDescriptor; typedef struct { - InterfaceDescriptor hid; - HIDDescDescriptor desc; - EndpointDescriptor in; + InterfaceDescriptor hid; + HIDDescDescriptor desc; + EndpointDescriptor in; } HIDDescriptor; class HIDSubDescriptor { - public: - HIDSubDescriptor *next = NULL; - HIDSubDescriptor(const void *d, const uint16_t l) : data(d), length(l) { } + public: + HIDSubDescriptor *next = NULL; + HIDSubDescriptor(const void *d, const uint16_t l) : data(d), length(l) { } - const void* data; - const uint16_t length; + const void* data; + const uint16_t length; }; class HID_ : public PluggableUSBModule { - public: - HID_(void); - int begin(void); - int SendReport(uint8_t id, const void* data, int len); - void AppendDescriptor(HIDSubDescriptor* node); - uint8_t getLEDs(void) { return setReportData.leds; }; - - protected: - // Implementation of the PluggableUSBModule - int getInterface(uint8_t* interfaceCount); - int getDescriptor(USBSetup& setup); - bool setup(USBSetup& setup); - uint8_t getShortName(char* name); - - private: - EPTYPE_DESCRIPTOR_SIZE epType[1]; - - HIDSubDescriptor* rootNode; - uint16_t descriptorSize; - - uint8_t protocol; - uint8_t idle; - struct { - uint8_t reportId; - uint8_t leds; - } setReportData; + public: + + HID_(void); + int begin(void); + int SendReport(uint8_t id, const void* data, int len); + void AppendDescriptor(HIDSubDescriptor* node); + uint8_t getLEDs(void) { + return setReportData.leds; + }; + + protected: + // Implementation of the PluggableUSBModule + int getInterface(uint8_t* interfaceCount); + int getDescriptor(USBSetup& setup); + bool setup(USBSetup& setup); + uint8_t getShortName(char* name); + + private: + EPTYPE_DESCRIPTOR_SIZE epType[1]; + + HIDSubDescriptor* rootNode; + uint16_t descriptorSize; + + uint8_t protocol; + uint8_t idle; + struct { + uint8_t reportId; + uint8_t leds; + } setReportData; }; // Replacement for global singleton. diff --git a/plugins/KeyboardioHID/src/LEDs.h b/plugins/KeyboardioHID/src/LEDs.h index 2df7e6b00b..e1df22ac5a 100644 --- a/plugins/KeyboardioHID/src/LEDs.h +++ b/plugins/KeyboardioHID/src/LEDs.h @@ -27,12 +27,12 @@ THE SOFTWARE. // Keyboard Leds enum KeyboardLeds : uint8_t { - LED_NUM_LOCK = (1 << 0), - LED_CAPS_LOCK = (1 << 1), - LED_SCROLL_LOCK = (1 << 2), - LED_COMPOSE = (1 << 3), - LED_KANA = (1 << 4), - LED_POWER = (1 << 5), - LED_SHIFT = (1 << 6), - LED_DO_NOT_DISTURB = (1 << 7), + LED_NUM_LOCK = (1 << 0), + LED_CAPS_LOCK = (1 << 1), + LED_SCROLL_LOCK = (1 << 2), + LED_COMPOSE = (1 << 3), + LED_KANA = (1 << 4), + LED_POWER = (1 << 5), + LED_SHIFT = (1 << 6), + LED_DO_NOT_DISTURB = (1 << 7), }; diff --git a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp index ddac89a12e..dc6876cb55 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp @@ -27,81 +27,81 @@ THE SOFTWARE. #include "DescriptorPrimitives.h" static const uint8_t _hidMultiReportDescriptorConsumer[] PROGMEM = { - /* Consumer Control (Sound/Media keys) */ - D_USAGE_PAGE, 0x0C, /* usage page (consumer device) */ - D_USAGE, 0x01, /* usage -- consumer control */ - D_COLLECTION, D_APPLICATION, /* collection (application) */ - D_REPORT_ID, HID_REPORTID_CONSUMERCONTROL, /* report id */ - /* 4 Media Keys */ - D_LOGICAL_MINIMUM, 0x00, /* logical minimum */ - D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xFF, 0x03, /* logical maximum (3ff) */ - D_USAGE_MINIMUM, 0x00, /* usage minimum (0) */ - D_MULTIBYTE(D_USAGE_MAXIMUM), 0xFF, 0x03, /* usage maximum (3ff) */ - D_REPORT_COUNT, 0x04, /* report count (4) */ - D_REPORT_SIZE, 0x10, /* report size (16) */ - D_INPUT, 0x00, /* input */ - D_END_COLLECTION /* end collection */ + /* Consumer Control (Sound/Media keys) */ + D_USAGE_PAGE, 0x0C, /* usage page (consumer device) */ + D_USAGE, 0x01, /* usage -- consumer control */ + D_COLLECTION, D_APPLICATION, /* collection (application) */ + D_REPORT_ID, HID_REPORTID_CONSUMERCONTROL, /* report id */ + /* 4 Media Keys */ + D_LOGICAL_MINIMUM, 0x00, /* logical minimum */ + D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xFF, 0x03, /* logical maximum (3ff) */ + D_USAGE_MINIMUM, 0x00, /* usage minimum (0) */ + D_MULTIBYTE(D_USAGE_MAXIMUM), 0xFF, 0x03, /* usage maximum (3ff) */ + D_REPORT_COUNT, 0x04, /* report count (4) */ + D_REPORT_SIZE, 0x10, /* report size (16) */ + D_INPUT, 0x00, /* input */ + D_END_COLLECTION /* end collection */ }; ConsumerControl_::ConsumerControl_(void) { - static HIDSubDescriptor node(_hidMultiReportDescriptorConsumer, sizeof(_hidMultiReportDescriptorConsumer)); - HID().AppendDescriptor(&node); + static HIDSubDescriptor node(_hidMultiReportDescriptorConsumer, sizeof(_hidMultiReportDescriptorConsumer)); + HID().AppendDescriptor(&node); } void ConsumerControl_::begin(void) { - // release all buttons - end(); + // release all buttons + end(); } void ConsumerControl_::end(void) { - memset(&_report, 0, sizeof(_report)); - sendReport(); + memset(&_report, 0, sizeof(_report)); + sendReport(); } void ConsumerControl_::write(uint16_t m) { - press(m); - release(m); + press(m); + release(m); } void ConsumerControl_::press(uint16_t m) { - // search for a free spot - for (uint8_t i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { - if (_report.keys[i] == 0x00) { - _report.keys[i] = m; - break; + // search for a free spot + for (uint8_t i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { + if (_report.keys[i] == 0x00) { + _report.keys[i] = m; + break; + } } - } } void ConsumerControl_::release(uint16_t m) { - // search and release the keypress - for (uint8_t i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { - if (_report.keys[i] == m) { - _report.keys[i] = 0x00; - // no break to delete multiple keys + // search and release the keypress + for (uint8_t i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { + if (_report.keys[i] == m) { + _report.keys[i] = 0x00; + // no break to delete multiple keys + } } - } } void ConsumerControl_::releaseAll(void) { - memset(&_report, 0, sizeof(_report)); + memset(&_report, 0, sizeof(_report)); } void ConsumerControl_::sendReportUnchecked(void) { - HID().SendReport(HID_REPORTID_CONSUMERCONTROL, &_report, sizeof(_report)); + HID().SendReport(HID_REPORTID_CONSUMERCONTROL, &_report, sizeof(_report)); } void ConsumerControl_::sendReport(void) { - // If the last report is different than the current report, then we need to send a report. - // We guard sendReport like this so that calling code doesn't end up spamming the host with empty reports - // if sendReport is called in a tight loop. + // If the last report is different than the current report, then we need to send a report. + // We guard sendReport like this so that calling code doesn't end up spamming the host with empty reports + // if sendReport is called in a tight loop. - // if the previous report is the same, return early without a new report. - if (memcmp(&_lastReport, &_report, sizeof(_report)) == 0) - return; + // if the previous report is the same, return early without a new report. + if (memcmp(&_lastReport, &_report, sizeof(_report)) == 0) + return; - sendReportUnchecked(); - memcpy(&_lastReport, &_report, sizeof(_report)); + sendReportUnchecked(); + memcpy(&_lastReport, &_report, sizeof(_report)); } ConsumerControl_ ConsumerControl; diff --git a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h index ecd122ec6b..b918bd760e 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h +++ b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h @@ -31,35 +31,35 @@ THE SOFTWARE. #include "HID-Settings.h" typedef union { - // Every usable Consumer key possible, up to 4 keys presses possible - uint16_t keys[4]; - struct { - uint16_t key1; - uint16_t key2; - uint16_t key3; - uint16_t key4; - }; + // Every usable Consumer key possible, up to 4 keys presses possible + uint16_t keys[4]; + struct { + uint16_t key1; + uint16_t key2; + uint16_t key3; + uint16_t key4; + }; } HID_ConsumerControlReport_Data_t; class ConsumerControl_ { - public: - ConsumerControl_(void); - void begin(void); - void end(void); - void write(uint16_t m); - void press(uint16_t m); - void release(uint16_t m); - void releaseAll(void); + public: + ConsumerControl_(void); + void begin(void); + void end(void); + void write(uint16_t m); + void press(uint16_t m); + void release(uint16_t m); + void releaseAll(void); - // Sending is public in the base class for advanced users. - void sendReport(void); + // Sending is public in the base class for advanced users. + void sendReport(void); - protected: - HID_ConsumerControlReport_Data_t _report; - HID_ConsumerControlReport_Data_t _lastReport; + protected: + HID_ConsumerControlReport_Data_t _report; + HID_ConsumerControlReport_Data_t _lastReport; - private: - void sendReportUnchecked(void); + private: + void sendReportUnchecked(void); }; extern ConsumerControl_ ConsumerControl; diff --git a/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp b/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp index c02c8f4bf7..4bd4187679 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp @@ -27,136 +27,136 @@ THE SOFTWARE. #include "DescriptorPrimitives.h" static const uint8_t _hidMultiReportDescriptorGamepad[] PROGMEM = { - /* Gamepad with 32 buttons and 6 axis*/ - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ - D_USAGE, D_USAGE_JOYSTICK, /* USAGE (Joystick) */ - D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ - D_REPORT_ID, HID_REPORTID_GAMEPAD, /* REPORT_ID */ - /* 32 Buttons */ - D_USAGE_PAGE, D_PAGE_BUTTON, /* USAGE_PAGE (Button) */ - D_USAGE_MINIMUM, 0x01, /* USAGE_MINIMUM (Button 1) */ - D_USAGE_MAXIMUM, 0x20, /* USAGE_MAXIMUM (Button 32) */ - D_LOGICAL_MINIMUM, 0x00, /* _LOGICAL_MINIMUM (0) */ - D_LOGICAL_MAXIMUM, 0x01, /* _LOGICAL_MAXIMUM (1) */ - D_REPORT_SIZE, 0x01, /* REPORT_SIZE (1) */ - D_REPORT_COUNT, 0x20, /* REPORT_COUNT (32) */ - D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ - /* 4 16bit Axis */ - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ - D_COLLECTION, D_PHYSICAL, /* COLLECTION (Physical) */ - D_USAGE, 0x30, /* USAGE (X) */ - D_USAGE, 0x31, /* USAGE (Y) */ - D_USAGE, 0x33, /* USAGE (Rx) */ - D_USAGE, 0x34, /* USAGE (Ry) */ - D_MULTIBYTE(D_LOGICAL_MINIMUM), 0x00, 0x80, /* _LOGICAL_MINIMUM (-32768) */ - D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xFF, 0x7F, /* _LOGICAL_MAXIMUM (32767) */ - D_REPORT_SIZE, 0x10, /* REPORT_SIZE (16) */ - D_REPORT_COUNT, 0x04, /* REPORT_COUNT (4) */ - D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ - /* 2 8bit Axis */ - D_USAGE, 0x32, /* USAGE (Z) */ - D_USAGE, 0x35, /* USAGE (Rz) */ - D_LOGICAL_MINIMUM, 0x80, /* _LOGICAL_MINIMUM (-128) */ - D_LOGICAL_MAXIMUM, 0x7F, /* _LOGICAL_MAXIMUM (127) */ - D_REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ - D_REPORT_COUNT, 0x02, /* REPORT_COUNT (2) */ - D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ - D_END_COLLECTION, /* END_COLLECTION */ - - /* 2 Hat Switches */ - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ - D_USAGE, 0x39, /* USAGE (Hat switch) */ - D_USAGE, 0x39, /* USAGE (Hat switch) */ - D_LOGICAL_MINIMUM, 0x01, /* _LOGICAL_MINIMUM (1) */ - D_LOGICAL_MAXIMUM, 0x08, /* _LOGICAL_MAXIMUM (8) */ - D_REPORT_COUNT, 0x02, /* REPORT_COUNT (2) */ - D_REPORT_SIZE, 0x04, /* REPORT_SIZE (4) */ - D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ - D_END_COLLECTION /* END_COLLECTION */ + /* Gamepad with 32 buttons and 6 axis*/ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ + D_USAGE, D_USAGE_JOYSTICK, /* USAGE (Joystick) */ + D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ + D_REPORT_ID, HID_REPORTID_GAMEPAD, /* REPORT_ID */ + /* 32 Buttons */ + D_USAGE_PAGE, D_PAGE_BUTTON, /* USAGE_PAGE (Button) */ + D_USAGE_MINIMUM, 0x01, /* USAGE_MINIMUM (Button 1) */ + D_USAGE_MAXIMUM, 0x20, /* USAGE_MAXIMUM (Button 32) */ + D_LOGICAL_MINIMUM, 0x00, /* _LOGICAL_MINIMUM (0) */ + D_LOGICAL_MAXIMUM, 0x01, /* _LOGICAL_MAXIMUM (1) */ + D_REPORT_SIZE, 0x01, /* REPORT_SIZE (1) */ + D_REPORT_COUNT, 0x20, /* REPORT_COUNT (32) */ + D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ + /* 4 16bit Axis */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ + D_COLLECTION, D_PHYSICAL, /* COLLECTION (Physical) */ + D_USAGE, 0x30, /* USAGE (X) */ + D_USAGE, 0x31, /* USAGE (Y) */ + D_USAGE, 0x33, /* USAGE (Rx) */ + D_USAGE, 0x34, /* USAGE (Ry) */ + D_MULTIBYTE(D_LOGICAL_MINIMUM), 0x00, 0x80, /* _LOGICAL_MINIMUM (-32768) */ + D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xFF, 0x7F, /* _LOGICAL_MAXIMUM (32767) */ + D_REPORT_SIZE, 0x10, /* REPORT_SIZE (16) */ + D_REPORT_COUNT, 0x04, /* REPORT_COUNT (4) */ + D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ + /* 2 8bit Axis */ + D_USAGE, 0x32, /* USAGE (Z) */ + D_USAGE, 0x35, /* USAGE (Rz) */ + D_LOGICAL_MINIMUM, 0x80, /* _LOGICAL_MINIMUM (-128) */ + D_LOGICAL_MAXIMUM, 0x7F, /* _LOGICAL_MAXIMUM (127) */ + D_REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ + D_REPORT_COUNT, 0x02, /* REPORT_COUNT (2) */ + D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ + D_END_COLLECTION, /* END_COLLECTION */ + + /* 2 Hat Switches */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ + D_USAGE, 0x39, /* USAGE (Hat switch) */ + D_USAGE, 0x39, /* USAGE (Hat switch) */ + D_LOGICAL_MINIMUM, 0x01, /* _LOGICAL_MINIMUM (1) */ + D_LOGICAL_MAXIMUM, 0x08, /* _LOGICAL_MAXIMUM (8) */ + D_REPORT_COUNT, 0x02, /* REPORT_COUNT (2) */ + D_REPORT_SIZE, 0x04, /* REPORT_SIZE (4) */ + D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ + D_END_COLLECTION /* END_COLLECTION */ }; Gamepad_::Gamepad_(void) { - static HIDSubDescriptor node(_hidMultiReportDescriptorGamepad, sizeof(_hidMultiReportDescriptorGamepad)); - HID().AppendDescriptor(&node); + static HIDSubDescriptor node(_hidMultiReportDescriptorGamepad, sizeof(_hidMultiReportDescriptorGamepad)); + HID().AppendDescriptor(&node); } void Gamepad_::begin(void) { - // release all buttons - end(); + // release all buttons + end(); } void Gamepad_::end(void) { - memset(&_report, 0x00, sizeof(_report)); - sendReport(&_report, sizeof(_report)); + memset(&_report, 0x00, sizeof(_report)); + sendReport(&_report, sizeof(_report)); } void Gamepad_::write(void) { - sendReport(&_report, sizeof(_report)); + sendReport(&_report, sizeof(_report)); } void Gamepad_::press(uint8_t b) { - _report.buttons |= (uint32_t)1 << (b - 1); + _report.buttons |= (uint32_t)1 << (b - 1); } void Gamepad_::release(uint8_t b) { - _report.buttons &= ~((uint32_t)1 << (b - 1)); + _report.buttons &= ~((uint32_t)1 << (b - 1)); } void Gamepad_::releaseAll(void) { - memset(&_report, 0x00, sizeof(_report)); + memset(&_report, 0x00, sizeof(_report)); } void Gamepad_::buttons(uint32_t b) { - _report.buttons = b; + _report.buttons = b; } void Gamepad_::xAxis(int16_t a) { - _report.xAxis = a; + _report.xAxis = a; } void Gamepad_::yAxis(int16_t a) { - _report.yAxis = a; + _report.yAxis = a; } void Gamepad_::zAxis(int8_t a) { - _report.zAxis = a; + _report.zAxis = a; } void Gamepad_::rxAxis(int16_t a) { - _report.rxAxis = a; + _report.rxAxis = a; } void Gamepad_::ryAxis(int16_t a) { - _report.ryAxis = a; + _report.ryAxis = a; } void Gamepad_::rzAxis(int8_t a) { - _report.rzAxis = a; + _report.rzAxis = a; } void Gamepad_::dPad1(int8_t d) { - _report.dPad1 = d; + _report.dPad1 = d; } void Gamepad_::dPad2(int8_t d) { - _report.dPad2 = d; + _report.dPad2 = d; } void Gamepad_::sendReport(void* data, int length) { - HID().SendReport(HID_REPORTID_GAMEPAD, data, length); + HID().SendReport(HID_REPORTID_GAMEPAD, data, length); } Gamepad_ Gamepad; diff --git a/plugins/KeyboardioHID/src/MultiReport/Gamepad.h b/plugins/KeyboardioHID/src/MultiReport/Gamepad.h index 3dd6b4188a..7d299eb032 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Gamepad.h +++ b/plugins/KeyboardioHID/src/MultiReport/Gamepad.h @@ -43,83 +43,83 @@ THE SOFTWARE. typedef union { - // 32 Buttons, 6 Axis, 2 D-Pads - uint32_t buttons; - - struct { - uint8_t button1 : 1; - uint8_t button2 : 1; - uint8_t button3 : 1; - uint8_t button4 : 1; - uint8_t button5 : 1; - uint8_t button6 : 1; - uint8_t button7 : 1; - uint8_t button8 : 1; - - uint8_t button9 : 1; - uint8_t button10 : 1; - uint8_t button11 : 1; - uint8_t button12 : 1; - uint8_t button13 : 1; - uint8_t button14 : 1; - uint8_t button15 : 1; - uint8_t button16 : 1; - - uint8_t button17 : 1; - uint8_t button18 : 1; - uint8_t button19 : 1; - uint8_t button20 : 1; - uint8_t button21 : 1; - uint8_t button22 : 1; - uint8_t button23 : 1; - uint8_t button24 : 1; - - uint8_t button25 : 1; - uint8_t button26 : 1; - uint8_t button27 : 1; - uint8_t button28 : 1; - uint8_t button29 : 1; - uint8_t button30 : 1; - uint8_t button31 : 1; - uint8_t button32 : 1; - - int16_t xAxis; - int16_t yAxis; - - int16_t rxAxis; - int16_t ryAxis; - - int8_t zAxis; - int8_t rzAxis; - - uint8_t dPad1 : 4; - uint8_t dPad2 : 4; - }; + // 32 Buttons, 6 Axis, 2 D-Pads + uint32_t buttons; + + struct { + uint8_t button1 : 1; + uint8_t button2 : 1; + uint8_t button3 : 1; + uint8_t button4 : 1; + uint8_t button5 : 1; + uint8_t button6 : 1; + uint8_t button7 : 1; + uint8_t button8 : 1; + + uint8_t button9 : 1; + uint8_t button10 : 1; + uint8_t button11 : 1; + uint8_t button12 : 1; + uint8_t button13 : 1; + uint8_t button14 : 1; + uint8_t button15 : 1; + uint8_t button16 : 1; + + uint8_t button17 : 1; + uint8_t button18 : 1; + uint8_t button19 : 1; + uint8_t button20 : 1; + uint8_t button21 : 1; + uint8_t button22 : 1; + uint8_t button23 : 1; + uint8_t button24 : 1; + + uint8_t button25 : 1; + uint8_t button26 : 1; + uint8_t button27 : 1; + uint8_t button28 : 1; + uint8_t button29 : 1; + uint8_t button30 : 1; + uint8_t button31 : 1; + uint8_t button32 : 1; + + int16_t xAxis; + int16_t yAxis; + + int16_t rxAxis; + int16_t ryAxis; + + int8_t zAxis; + int8_t rzAxis; + + uint8_t dPad1 : 4; + uint8_t dPad2 : 4; + }; } HID_GamepadReport_Data_t; class Gamepad_ { - public: - Gamepad_(void); - - void begin(void); - void end(void); - void write(void); - void press(uint8_t b); - void release(uint8_t b); - void releaseAll(void); - - void buttons(uint32_t b); - void xAxis(int16_t a); - void yAxis(int16_t a); - void zAxis(int8_t a); - void rxAxis(int16_t a); - void ryAxis(int16_t a); - void rzAxis(int8_t a); - void dPad1(int8_t d); - void dPad2(int8_t d); - - void sendReport(void* data, int length); - protected: - HID_GamepadReport_Data_t _report; + public: + Gamepad_(void); + + void begin(void); + void end(void); + void write(void); + void press(uint8_t b); + void release(uint8_t b); + void releaseAll(void); + + void buttons(uint32_t b); + void xAxis(int16_t a); + void yAxis(int16_t a); + void zAxis(int8_t a); + void rxAxis(int16_t a); + void ryAxis(int16_t a); + void rzAxis(int8_t a); + void dPad1(int8_t d); + void dPad2(int8_t d); + + void sendReport(void* data, int length); + protected: + HID_GamepadReport_Data_t _report; }; extern Gamepad_ Gamepad; diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index 7d49624270..453af3cba8 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -27,74 +27,74 @@ THE SOFTWARE. #include "DescriptorPrimitives.h" static const uint8_t _hidMultiReportDescriptorKeyboard[] PROGMEM = { - // NKRO Keyboard - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, - D_USAGE, D_USAGE_KEYBOARD, - D_COLLECTION, D_APPLICATION, - D_REPORT_ID, HID_REPORTID_NKRO_KEYBOARD, - D_USAGE_PAGE, D_PAGE_KEYBOARD, - - - /* Key modifier byte */ - D_USAGE_MINIMUM, HID_KEYBOARD_FIRST_MODIFIER, - D_USAGE_MAXIMUM, HID_KEYBOARD_LAST_MODIFIER, - D_LOGICAL_MINIMUM, 0x00, - D_LOGICAL_MAXIMUM, 0x01, - D_REPORT_SIZE, 0x01, - D_REPORT_COUNT, 0x08, - D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), - - - /* 5 LEDs for num lock etc, 3 left for advanced, custom usage */ - D_USAGE_PAGE, D_PAGE_LEDS, - D_USAGE_MINIMUM, 0x01, - D_USAGE_MAXIMUM, 0x08, - D_REPORT_COUNT, 0x08, - D_REPORT_SIZE, 0x01, - D_OUTPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), - - /* NKRO Keyboard */ - D_USAGE_PAGE, D_PAGE_KEYBOARD, - - // Padding 4 bits, to skip NO_EVENT & 3 error states. - D_REPORT_SIZE, 0x04, - D_REPORT_COUNT, 0x01, - D_INPUT, (D_CONSTANT), - - D_USAGE_MINIMUM, HID_KEYBOARD_A_AND_A, - D_USAGE_MAXIMUM, HID_LAST_KEY, - D_LOGICAL_MINIMUM, 0x00, - D_LOGICAL_MAXIMUM, 0x01, - D_REPORT_SIZE, 0x01, - D_REPORT_COUNT, (HID_LAST_KEY - HID_KEYBOARD_A_AND_A), - D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), - - // Padding (3 bits) to round up the report to byte boundary. - D_REPORT_SIZE, 0x03, - D_REPORT_COUNT, 0x01, - D_INPUT, (D_CONSTANT), - - D_END_COLLECTION, + // NKRO Keyboard + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, + D_USAGE, D_USAGE_KEYBOARD, + D_COLLECTION, D_APPLICATION, + D_REPORT_ID, HID_REPORTID_NKRO_KEYBOARD, + D_USAGE_PAGE, D_PAGE_KEYBOARD, + + + /* Key modifier byte */ + D_USAGE_MINIMUM, HID_KEYBOARD_FIRST_MODIFIER, + D_USAGE_MAXIMUM, HID_KEYBOARD_LAST_MODIFIER, + D_LOGICAL_MINIMUM, 0x00, + D_LOGICAL_MAXIMUM, 0x01, + D_REPORT_SIZE, 0x01, + D_REPORT_COUNT, 0x08, + D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), + + + /* 5 LEDs for num lock etc, 3 left for advanced, custom usage */ + D_USAGE_PAGE, D_PAGE_LEDS, + D_USAGE_MINIMUM, 0x01, + D_USAGE_MAXIMUM, 0x08, + D_REPORT_COUNT, 0x08, + D_REPORT_SIZE, 0x01, + D_OUTPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), + + /* NKRO Keyboard */ + D_USAGE_PAGE, D_PAGE_KEYBOARD, + + // Padding 4 bits, to skip NO_EVENT & 3 error states. + D_REPORT_SIZE, 0x04, + D_REPORT_COUNT, 0x01, + D_INPUT, (D_CONSTANT), + + D_USAGE_MINIMUM, HID_KEYBOARD_A_AND_A, + D_USAGE_MAXIMUM, HID_LAST_KEY, + D_LOGICAL_MINIMUM, 0x00, + D_LOGICAL_MAXIMUM, 0x01, + D_REPORT_SIZE, 0x01, + D_REPORT_COUNT, (HID_LAST_KEY - HID_KEYBOARD_A_AND_A), + D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), + + // Padding (3 bits) to round up the report to byte boundary. + D_REPORT_SIZE, 0x03, + D_REPORT_COUNT, 0x01, + D_INPUT, (D_CONSTANT), + + D_END_COLLECTION, }; Keyboard_::Keyboard_(void) { - static HIDSubDescriptor node(_hidMultiReportDescriptorKeyboard, sizeof(_hidMultiReportDescriptorKeyboard)); - HID().AppendDescriptor(&node); + static HIDSubDescriptor node(_hidMultiReportDescriptorKeyboard, sizeof(_hidMultiReportDescriptorKeyboard)); + HID().AppendDescriptor(&node); } void Keyboard_::begin(void) { - // Force API to send a clean report. - // This is important for and HID bridge where the receiver stays on, - // while the sender is resetted. - releaseAll(); - sendReportUnchecked(); + // Force API to send a clean report. + // This is important for and HID bridge where the receiver stays on, + // while the sender is resetted. + releaseAll(); + sendReportUnchecked(); } void Keyboard_::end(void) { - releaseAll(); - sendReportUnchecked(); + releaseAll(); + sendReportUnchecked(); } int Keyboard_::sendReportUnchecked(void) { @@ -103,88 +103,88 @@ int Keyboard_::sendReportUnchecked(void) { int Keyboard_::sendReport(void) { - // If the last report is different than the current report, then we need to send a report. - // We guard sendReport like this so that calling code doesn't end up spamming the host with empty reports - // if sendReport is called in a tight loop. - - if (memcmp(lastKeyReport.allkeys, keyReport.allkeys, sizeof(keyReport))) { - // if the two reports are different, send a report - - // ChromeOS 51-60 (at least) bug: if a modifier and a normal keycode are added in the - // same report, in some cases the shift is not applied (e.g. `shift`+`[` doesn't yield - // `{`). To compensate for this, check to see if the modifier byte has changed. - - - // If modifiers are being turned on at the same time as any change - // to the non-modifier keys in the report, then we send the previous - // report with the new modifiers - if ( ( (lastKeyReport.modifiers ^ keyReport.modifiers) & keyReport.modifiers) - && (memcmp(lastKeyReport.keys,keyReport.keys, sizeof(keyReport.keys)))) { - uint8_t last_mods = lastKeyReport.modifiers; - lastKeyReport.modifiers = keyReport.modifiers; - int returnCode = HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &lastKeyReport, sizeof(lastKeyReport)); - lastKeyReport.modifiers = last_mods; - } - - // If modifiers are being turned off, then we send the new report with the previous modifiers. - // We need to do this, at least on Linux 4.17 + Wayland. - // Jesse has observed that sending Shift + 3 key up events in the same report - // will sometimes result in a spurious '3' rather than '#', especially when the keys - // had been held for a while - else if (( (lastKeyReport.modifiers ^ keyReport.modifiers) & lastKeyReport.modifiers) - && (memcmp(lastKeyReport.keys,keyReport.keys, sizeof(keyReport.keys)))) { - uint8_t mods = keyReport.modifiers; - keyReport.modifiers = lastKeyReport.modifiers; - int returnCode = HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &keyReport, sizeof(lastKeyReport)); - keyReport.modifiers = mods; - } - - - - - - int returnCode = sendReportUnchecked(); - if (returnCode > 0) - memcpy(lastKeyReport.allkeys, keyReport.allkeys, sizeof(keyReport)); - return returnCode; - } - return -1; + // If the last report is different than the current report, then we need to send a report. + // We guard sendReport like this so that calling code doesn't end up spamming the host with empty reports + // if sendReport is called in a tight loop. + + if (memcmp(lastKeyReport.allkeys, keyReport.allkeys, sizeof(keyReport))) { + // if the two reports are different, send a report + + // ChromeOS 51-60 (at least) bug: if a modifier and a normal keycode are added in the + // same report, in some cases the shift is not applied (e.g. `shift`+`[` doesn't yield + // `{`). To compensate for this, check to see if the modifier byte has changed. + + + // If modifiers are being turned on at the same time as any change + // to the non-modifier keys in the report, then we send the previous + // report with the new modifiers + if ( ( (lastKeyReport.modifiers ^ keyReport.modifiers) & keyReport.modifiers) + && (memcmp(lastKeyReport.keys,keyReport.keys, sizeof(keyReport.keys)))) { + uint8_t last_mods = lastKeyReport.modifiers; + lastKeyReport.modifiers = keyReport.modifiers; + int returnCode = HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &lastKeyReport, sizeof(lastKeyReport)); + lastKeyReport.modifiers = last_mods; + } + + // If modifiers are being turned off, then we send the new report with the previous modifiers. + // We need to do this, at least on Linux 4.17 + Wayland. + // Jesse has observed that sending Shift + 3 key up events in the same report + // will sometimes result in a spurious '3' rather than '#', especially when the keys + // had been held for a while + else if (( (lastKeyReport.modifiers ^ keyReport.modifiers) & lastKeyReport.modifiers) + && (memcmp(lastKeyReport.keys,keyReport.keys, sizeof(keyReport.keys)))) { + uint8_t mods = keyReport.modifiers; + keyReport.modifiers = lastKeyReport.modifiers; + int returnCode = HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &keyReport, sizeof(lastKeyReport)); + keyReport.modifiers = mods; + } + + + + + + int returnCode = sendReportUnchecked(); + if (returnCode > 0) + memcpy(lastKeyReport.allkeys, keyReport.allkeys, sizeof(keyReport)); + return returnCode; + } + return -1; } /* Returns true if the modifer key passed in will be sent during this key report * Returns false in all other cases * */ boolean Keyboard_::isModifierActive(uint8_t k) { - if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { - k = k - HID_KEYBOARD_FIRST_MODIFIER; - return !!(keyReport.modifiers & (1 << k)); - } - return false; + if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { + k = k - HID_KEYBOARD_FIRST_MODIFIER; + return !!(keyReport.modifiers & (1 << k)); + } + return false; } /* Returns true if the modifer key passed in was being sent during the previous key report * Returns false in all other cases * */ boolean Keyboard_::wasModifierActive(uint8_t k) { - if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { - k = k - HID_KEYBOARD_FIRST_MODIFIER; - return !!(lastKeyReport.modifiers & (1 << k)); - } - return false; + if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { + k = k - HID_KEYBOARD_FIRST_MODIFIER; + return !!(lastKeyReport.modifiers & (1 << k)); + } + return false; } /* Returns true if *any* modifier will be sent during this key report * Returns false in all other cases * */ boolean Keyboard_::isAnyModifierActive() { - return keyReport.modifiers > 0; + return keyReport.modifiers > 0; } /* Returns true if *any* modifier was being sent during the previous key report * Returns false in all other cases * */ boolean Keyboard_::wasAnyModifierActive() { - return lastKeyReport.modifiers > 0; + return lastKeyReport.modifiers > 0; } @@ -213,48 +213,48 @@ boolean Keyboard_::wasKeyPressed(uint8_t k) { size_t Keyboard_::press(uint8_t k) { - // If the key is in the range of 'printable' keys - if (k <= HID_LAST_KEY) { - uint8_t bit = 1 << (uint8_t(k) % 8); - keyReport.keys[k / 8] |= bit; - return 1; - } - - // It's a modifier key - else if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { - // Convert key into bitfield (0 - 7) - k = k - HID_KEYBOARD_FIRST_MODIFIER; - keyReport.modifiers |= (1 << k); - return 1; - } - - // No empty/pressed key was found - return 0; + // If the key is in the range of 'printable' keys + if (k <= HID_LAST_KEY) { + uint8_t bit = 1 << (uint8_t(k) % 8); + keyReport.keys[k / 8] |= bit; + return 1; + } + + // It's a modifier key + else if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { + // Convert key into bitfield (0 - 7) + k = k - HID_KEYBOARD_FIRST_MODIFIER; + keyReport.modifiers |= (1 << k); + return 1; + } + + // No empty/pressed key was found + return 0; } size_t Keyboard_::release(uint8_t k) { - // If we're releasing a printable key - if (k <= HID_LAST_KEY) { - uint8_t bit = 1 << (k % 8); - keyReport.keys[k / 8] &= ~bit; - return 1; - } - - // It's a modifier key - else if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { - // Convert key into bitfield (0 - 7) - k = k - HID_KEYBOARD_FIRST_MODIFIER; - keyReport.modifiers &= ~(1 << k); - return 1; - } - - // No empty/pressed key was found - return 0; + // If we're releasing a printable key + if (k <= HID_LAST_KEY) { + uint8_t bit = 1 << (k % 8); + keyReport.keys[k / 8] &= ~bit; + return 1; + } + + // It's a modifier key + else if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { + // Convert key into bitfield (0 - 7) + k = k - HID_KEYBOARD_FIRST_MODIFIER; + keyReport.modifiers &= ~(1 << k); + return 1; + } + + // No empty/pressed key was found + return 0; } void Keyboard_::releaseAll(void) { - // Release all keys - memset(&keyReport.allkeys, 0x00, sizeof(keyReport.allkeys)); + // Release all keys + memset(&keyReport.allkeys, 0x00, sizeof(keyReport.allkeys)); } Keyboard_ Keyboard; diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h index 14a38130b5..898c859ffd 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h @@ -36,39 +36,41 @@ THE SOFTWARE. #define KEY_BYTES 28 typedef union { - // Modifiers + keymap - struct { - uint8_t modifiers; - uint8_t keys[KEY_BYTES ]; - }; - uint8_t allkeys[1 + KEY_BYTES]; + // Modifiers + keymap + struct { + uint8_t modifiers; + uint8_t keys[KEY_BYTES ]; + }; + uint8_t allkeys[1 + KEY_BYTES]; } HID_KeyboardReport_Data_t; class Keyboard_ { - public: - Keyboard_(void); - void begin(void); - void end(void); - - size_t press(uint8_t k); - size_t release(uint8_t k); - void releaseAll(void); - int sendReport(void); - - boolean isKeyPressed(uint8_t k); - boolean wasKeyPressed(uint8_t k); - boolean isModifierActive(uint8_t k); - boolean wasModifierActive(uint8_t k); - boolean isAnyModifierActive(); - boolean wasAnyModifierActive(); - - uint8_t getLEDs() { return HID().getLEDs(); }; - - HID_KeyboardReport_Data_t keyReport; - HID_KeyboardReport_Data_t lastKeyReport; - private: - int sendReportUnchecked(void); + public: + Keyboard_(void); + void begin(void); + void end(void); + + size_t press(uint8_t k); + size_t release(uint8_t k); + void releaseAll(void); + int sendReport(void); + + boolean isKeyPressed(uint8_t k); + boolean wasKeyPressed(uint8_t k); + boolean isModifierActive(uint8_t k); + boolean wasModifierActive(uint8_t k); + boolean isAnyModifierActive(); + boolean wasAnyModifierActive(); + + uint8_t getLEDs() { + return HID().getLEDs(); + }; + + HID_KeyboardReport_Data_t keyReport; + HID_KeyboardReport_Data_t lastKeyReport; + private: + int sendReportUnchecked(void); }; extern Keyboard_ Keyboard; diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp index 96362d79e2..af73545e76 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp @@ -27,110 +27,110 @@ THE SOFTWARE. #include "DescriptorPrimitives.h" static const uint8_t _hidMultiReportDescriptorMouse[] PROGMEM = { - /* Mouse relative */ - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, // USAGE_PAGE (Generic Desktop) - D_USAGE, D_USAGE_MOUSE, // USAGE (Mouse) - D_COLLECTION, D_APPLICATION, // COLLECTION (Application) - D_REPORT_ID, HID_REPORTID_MOUSE, // REPORT_ID (Mouse) - - /* 8 Buttons */ - D_USAGE_PAGE, D_PAGE_BUTTON, // USAGE_PAGE (Button) - D_USAGE_MINIMUM, 0x01, // USAGE_MINIMUM (Button 1) - D_USAGE_MAXIMUM, 0x08, // USAGE_MAXIMUM (Button 8) - D_LOGICAL_MINIMUM, 0x00, // LOGICAL_MINIMUM (0) - D_LOGICAL_MAXIMUM, 0x01, // LOGICAL_MAXIMUM (1) - D_REPORT_COUNT, 0x08, // REPORT_COUNT (8) - D_REPORT_SIZE, 0x01, // REPORT_SIZE (1) - D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), // INPUT (Data,Var,Abs) - - /* X, Y, Wheel */ - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, // USAGE_PAGE (Generic Desktop) - D_USAGE, 0x30, // USAGE (X) - D_USAGE, 0x31, // USAGE (Y) - D_USAGE, 0x38, // USAGE (Wheel) - D_LOGICAL_MINIMUM, 0x81, // LOGICAL_MINIMUM (-127) - D_LOGICAL_MAXIMUM, 0x7f, // LOGICAL_MAXIMUM (127) - D_REPORT_SIZE, 0x08, // REPORT_SIZE (8) - D_REPORT_COUNT, 0x03, // REPORT_COUNT (3) - D_INPUT, (D_DATA|D_VARIABLE|D_RELATIVE), // INPUT (Data,Var,Rel) - - /* Horizontal wheel */ - D_USAGE_PAGE, D_PAGE_CONSUMER, // USAGE_PAGE (Consumer) - D_PAGE_ORDINAL, 0x38, 0x02, // PAGE (AC Pan) - D_LOGICAL_MINIMUM, 0x81, // LOGICAL_MINIMUM (-127) - D_LOGICAL_MAXIMUM, 0x7f, // LOGICAL_MAXIMUM (127) - D_REPORT_SIZE, 0x08, // REPORT_SIZE (8) - D_REPORT_COUNT, 0x01, // REPORT_COUNT (1) - D_INPUT, (D_DATA|D_VARIABLE|D_RELATIVE), // INPUT (Data,Var,Rel) - - /* End */ - D_END_COLLECTION // END_COLLECTION + /* Mouse relative */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, // USAGE_PAGE (Generic Desktop) + D_USAGE, D_USAGE_MOUSE, // USAGE (Mouse) + D_COLLECTION, D_APPLICATION, // COLLECTION (Application) + D_REPORT_ID, HID_REPORTID_MOUSE, // REPORT_ID (Mouse) + + /* 8 Buttons */ + D_USAGE_PAGE, D_PAGE_BUTTON, // USAGE_PAGE (Button) + D_USAGE_MINIMUM, 0x01, // USAGE_MINIMUM (Button 1) + D_USAGE_MAXIMUM, 0x08, // USAGE_MAXIMUM (Button 8) + D_LOGICAL_MINIMUM, 0x00, // LOGICAL_MINIMUM (0) + D_LOGICAL_MAXIMUM, 0x01, // LOGICAL_MAXIMUM (1) + D_REPORT_COUNT, 0x08, // REPORT_COUNT (8) + D_REPORT_SIZE, 0x01, // REPORT_SIZE (1) + D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), // INPUT (Data,Var,Abs) + + /* X, Y, Wheel */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, // USAGE_PAGE (Generic Desktop) + D_USAGE, 0x30, // USAGE (X) + D_USAGE, 0x31, // USAGE (Y) + D_USAGE, 0x38, // USAGE (Wheel) + D_LOGICAL_MINIMUM, 0x81, // LOGICAL_MINIMUM (-127) + D_LOGICAL_MAXIMUM, 0x7f, // LOGICAL_MAXIMUM (127) + D_REPORT_SIZE, 0x08, // REPORT_SIZE (8) + D_REPORT_COUNT, 0x03, // REPORT_COUNT (3) + D_INPUT, (D_DATA|D_VARIABLE|D_RELATIVE), // INPUT (Data,Var,Rel) + + /* Horizontal wheel */ + D_USAGE_PAGE, D_PAGE_CONSUMER, // USAGE_PAGE (Consumer) + D_PAGE_ORDINAL, 0x38, 0x02, // PAGE (AC Pan) + D_LOGICAL_MINIMUM, 0x81, // LOGICAL_MINIMUM (-127) + D_LOGICAL_MAXIMUM, 0x7f, // LOGICAL_MAXIMUM (127) + D_REPORT_SIZE, 0x08, // REPORT_SIZE (8) + D_REPORT_COUNT, 0x01, // REPORT_COUNT (1) + D_INPUT, (D_DATA|D_VARIABLE|D_RELATIVE), // INPUT (Data,Var,Rel) + + /* End */ + D_END_COLLECTION // END_COLLECTION }; Mouse_::Mouse_(void) { } void Mouse_::begin(void) { - static HIDSubDescriptor node(_hidMultiReportDescriptorMouse, sizeof(_hidMultiReportDescriptorMouse)); - HID().AppendDescriptor(&node); + static HIDSubDescriptor node(_hidMultiReportDescriptorMouse, sizeof(_hidMultiReportDescriptorMouse)); + HID().AppendDescriptor(&node); - end(); + end(); } void Mouse_::end(void) { - releaseAll(); - sendReport(); + releaseAll(); + sendReport(); } void Mouse_::click(uint8_t b) { - press(b); - sendReport(); - release(b); + press(b); + sendReport(); + release(b); } void Mouse_::move(signed char x, signed char y, signed char vWheel, signed char hWheel) { - report.xAxis = x; - report.yAxis = y; - report.vWheel = vWheel; - report.hWheel = hWheel; + report.xAxis = x; + report.yAxis = y; + report.vWheel = vWheel; + report.hWheel = hWheel; } void Mouse_::releaseAll(void) { - memset(&report, 0, sizeof(report)); + memset(&report, 0, sizeof(report)); } void Mouse_::press(uint8_t b) { - report.buttons |= b; + report.buttons |= b; } void Mouse_::release(uint8_t b) { - report.buttons &= ~b; + report.buttons &= ~b; } bool Mouse_::isPressed(uint8_t b) { - if ((b & report.buttons) > 0) - return true; - return false; + if ((b & report.buttons) > 0) + return true; + return false; } void Mouse_::sendReportUnchecked(void) { - HID().SendReport(HID_REPORTID_MOUSE, &report, sizeof(report)); + HID().SendReport(HID_REPORTID_MOUSE, &report, sizeof(report)); } void Mouse_::sendReport(void) { - // If the last report is different than the current report, then we need to send a report. - // We guard sendReport like this so that calling code doesn't end up spamming the host with empty reports - // if sendReport is called in a tight loop. - - // if the two reports are the same, check if they're empty, and return early - // without a report if they are. - static HID_MouseReport_Data_t emptyReport; - if (memcmp(&lastReport, &report, sizeof(report)) == 0 && - memcmp(&report, &emptyReport, sizeof(report)) == 0) - return; - - sendReportUnchecked(); - memcpy(&lastReport, &report, sizeof(report)); + // If the last report is different than the current report, then we need to send a report. + // We guard sendReport like this so that calling code doesn't end up spamming the host with empty reports + // if sendReport is called in a tight loop. + + // if the two reports are the same, check if they're empty, and return early + // without a report if they are. + static HID_MouseReport_Data_t emptyReport; + if (memcmp(&lastReport, &report, sizeof(report)) == 0 && + memcmp(&report, &emptyReport, sizeof(report)) == 0) + return; + + sendReportUnchecked(); + memcpy(&lastReport, &report, sizeof(report)); } Mouse_ Mouse; diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.h b/plugins/KeyboardioHID/src/MultiReport/Mouse.h index 5723b70459..447c48e6b5 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.h @@ -32,46 +32,46 @@ THE SOFTWARE. #include "../MouseButtons.h" typedef union { - // Mouse report: 8 buttons, position, wheel - struct { - uint8_t buttons; - int8_t xAxis; - int8_t yAxis; - int8_t vWheel; - int8_t hWheel; - }; + // Mouse report: 8 buttons, position, wheel + struct { + uint8_t buttons; + int8_t xAxis; + int8_t yAxis; + int8_t vWheel; + int8_t hWheel; + }; } HID_MouseReport_Data_t; class Mouse_ { - 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 vWheel = 0, signed char hWheel = 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 + 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 vWheel = 0, signed char hWheel = 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 - /** getReport returns the current report. - * - * The current report is the one to be send next time sendReport() is called. - * - * @returns A copy of the report. - */ - const HID_MouseReport_Data_t getReport() { - return report; - } - void sendReport(void); + /** getReport returns the current report. + * + * The current report is the one to be send next time sendReport() is called. + * + * @returns A copy of the report. + */ + const HID_MouseReport_Data_t getReport() { + return report; + } + void sendReport(void); - void releaseAll(void); + void releaseAll(void); - protected: - HID_MouseReport_Data_t report; - HID_MouseReport_Data_t lastReport; + protected: + HID_MouseReport_Data_t report; + HID_MouseReport_Data_t lastReport; - private: - void sendReportUnchecked(void); + private: + void sendReportUnchecked(void); }; extern Mouse_ Mouse; diff --git a/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp b/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp index 9f67a5957b..0a341f15e2 100644 --- a/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp @@ -31,68 +31,68 @@ THE SOFTWARE. #endif static const uint8_t _hidMultiReportDescriptorSystem[] PROGMEM = { - //TODO limit to system keys only? - /* System Control (Power Down, Sleep, Wakeup, ...) */ - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ - D_USAGE, 0x80, /* USAGE (System Control) */ - D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ - D_REPORT_ID, HID_REPORTID_SYSTEMCONTROL, /* REPORT_ID */ - /* 1 system key */ - D_LOGICAL_MINIMUM, 0x00, /* LOGICAL_MINIMUM (0) */ - D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xff, 0x00, /* LOGICAL_MAXIMUM (255) */ - D_USAGE_MINIMUM, 0x00, /* USAGE_MINIMUM (Undefined) */ - D_USAGE_MAXIMUM, 0xff, /* USAGE_MAXIMUM (System Menu Down) */ - D_REPORT_COUNT, 0x01, /* REPORT_COUNT (1) */ - D_REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ - D_INPUT, (D_DATA|D_ARRAY|D_ABSOLUTE), /* INPUT (Data,Ary,Abs) */ - D_END_COLLECTION /* END_COLLECTION */ + //TODO limit to system keys only? + /* System Control (Power Down, Sleep, Wakeup, ...) */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ + D_USAGE, 0x80, /* USAGE (System Control) */ + D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ + D_REPORT_ID, HID_REPORTID_SYSTEMCONTROL, /* REPORT_ID */ + /* 1 system key */ + D_LOGICAL_MINIMUM, 0x00, /* LOGICAL_MINIMUM (0) */ + D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xff, 0x00, /* LOGICAL_MAXIMUM (255) */ + D_USAGE_MINIMUM, 0x00, /* USAGE_MINIMUM (Undefined) */ + D_USAGE_MAXIMUM, 0xff, /* USAGE_MAXIMUM (System Menu Down) */ + D_REPORT_COUNT, 0x01, /* REPORT_COUNT (1) */ + D_REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ + D_INPUT, (D_DATA|D_ARRAY|D_ABSOLUTE), /* INPUT (Data,Ary,Abs) */ + D_END_COLLECTION /* END_COLLECTION */ }; SystemControl_::SystemControl_(void) { - static HIDSubDescriptor node(_hidMultiReportDescriptorSystem, sizeof(_hidMultiReportDescriptorSystem)); - HID().AppendDescriptor(&node); + static HIDSubDescriptor node(_hidMultiReportDescriptorSystem, sizeof(_hidMultiReportDescriptorSystem)); + HID().AppendDescriptor(&node); } void SystemControl_::begin(void) { - // release all buttons - end(); + // release all buttons + end(); } void SystemControl_::end(void) { - uint8_t _report = 0x00; - sendReport(&_report, sizeof(_report)); + uint8_t _report = 0x00; + sendReport(&_report, sizeof(_report)); } void SystemControl_::write(uint8_t s) { - press(s); - release(); + press(s); + release(); } void SystemControl_::release(void) { - begin(); + begin(); } void SystemControl_::releaseAll(void) { - begin(); + begin(); } void SystemControl_::press(uint8_t s) { - if (s == HID_SYSTEM_WAKE_UP) { + if (s == HID_SYSTEM_WAKE_UP) { #ifdef __AVR__ - USBDevice.wakeupHost(); + USBDevice.wakeupHost(); #endif #ifdef ARDUINO_ARCH_SAMD - extern USBDevice_SAMD21G18x usbd; - usbd.wakeupHost(); + extern USBDevice_SAMD21G18x usbd; + usbd.wakeupHost(); #endif - } else { - sendReport(&s, sizeof(s)); - } + } else { + sendReport(&s, sizeof(s)); + } } void SystemControl_::sendReport(void* data, int length) { - HID().SendReport(HID_REPORTID_SYSTEMCONTROL, data, length); + HID().SendReport(HID_REPORTID_SYSTEMCONTROL, data, length); } SystemControl_ SystemControl; diff --git a/plugins/KeyboardioHID/src/MultiReport/SystemControl.h b/plugins/KeyboardioHID/src/MultiReport/SystemControl.h index 7f4bb98d4a..67da98060f 100644 --- a/plugins/KeyboardioHID/src/MultiReport/SystemControl.h +++ b/plugins/KeyboardioHID/src/MultiReport/SystemControl.h @@ -32,24 +32,24 @@ THE SOFTWARE. #include "HIDTables.h" typedef union { - // Every usable system control key possible - uint8_t key; + // Every usable system control key possible + uint8_t key; } HID_SystemControlReport_Data_t; class SystemControl_ { - public: - void begin(void); - void end(void); - void write(uint8_t s); - void press(uint8_t s); - void release(void); - void releaseAll(void); - void sendReport(void* data, int length); - - SystemControl_(void); - - protected: + public: + void begin(void); + void end(void); + void write(uint8_t s); + void press(uint8_t s); + void release(void); + void releaseAll(void); + void sendReport(void* data, int length); + + SystemControl_(void); + + protected: }; diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp index bf19068e08..e0202e5704 100644 --- a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp @@ -37,81 +37,79 @@ static const uint8_t _hidSingleReportDescriptorAbsoluteMouse[] PROGMEM = { }; -SingleAbsoluteMouse_::SingleAbsoluteMouse_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1) -{ - epType[0] = EP_TYPE_INTERRUPT_IN; - PluggableUSB().plug(this); +SingleAbsoluteMouse_::SingleAbsoluteMouse_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1) { + epType[0] = EP_TYPE_INTERRUPT_IN; + PluggableUSB().plug(this); } -int SingleAbsoluteMouse_::getInterface(uint8_t* interfaceCount) -{ - *interfaceCount += 1; // uses 1 - HIDDescriptor hidInterface = { - D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE), - D_HIDREPORT(sizeof(_hidSingleReportDescriptorAbsoluteMouse)), - D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) - }; - return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); +int SingleAbsoluteMouse_::getInterface(uint8_t* interfaceCount) { + *interfaceCount += 1; // uses 1 + HIDDescriptor hidInterface = { + D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE), + D_HIDREPORT(sizeof(_hidSingleReportDescriptorAbsoluteMouse)), + D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) + }; + return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); } -int SingleAbsoluteMouse_::getDescriptor(USBSetup& setup) -{ - // Check if this is a HID Class Descriptor request - if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { return 0; } - if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { return 0; } - - // In a HID Class Descriptor wIndex cointains the interface number - if (setup.wIndex != pluggedInterface) { return 0; } - - // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol - // due to the USB specs, but Windows and Linux just assumes its in report mode. - protocol = HID_REPORT_PROTOCOL; - - return USB_SendControl(TRANSFER_PGM, _hidSingleReportDescriptorAbsoluteMouse, sizeof(_hidSingleReportDescriptorAbsoluteMouse)); +int SingleAbsoluteMouse_::getDescriptor(USBSetup& setup) { + // Check if this is a HID Class Descriptor request + if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { + return 0; + } + if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { + return 0; + } + + // In a HID Class Descriptor wIndex cointains the interface number + if (setup.wIndex != pluggedInterface) { + return 0; + } + + // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol + // due to the USB specs, but Windows and Linux just assumes its in report mode. + protocol = HID_REPORT_PROTOCOL; + + return USB_SendControl(TRANSFER_PGM, _hidSingleReportDescriptorAbsoluteMouse, sizeof(_hidSingleReportDescriptorAbsoluteMouse)); } -bool SingleAbsoluteMouse_::setup(USBSetup& setup) -{ - if (pluggedInterface != setup.wIndex) { - return false; - } - - uint8_t request = setup.bRequest; - uint8_t requestType = setup.bmRequestType; - - if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) - { - if (request == HID_GET_REPORT) { - // TODO: HID_GetReport(); - return true; - } - if (request == HID_GET_PROTOCOL) { - // TODO: Send8(protocol); - return true; - } - } - - if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) - { - if (request == HID_SET_PROTOCOL) { - protocol = setup.wValueL; - return true; - } - if (request == HID_SET_IDLE) { - idle = setup.wValueL; - return true; - } - if (request == HID_SET_REPORT) - { - } - } - - return false; +bool SingleAbsoluteMouse_::setup(USBSetup& setup) { + if (pluggedInterface != setup.wIndex) { + return false; + } + + uint8_t request = setup.bRequest; + uint8_t requestType = setup.bmRequestType; + + if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) { + if (request == HID_GET_REPORT) { + // TODO: HID_GetReport(); + return true; + } + if (request == HID_GET_PROTOCOL) { + // TODO: Send8(protocol); + return true; + } + } + + if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) { + if (request == HID_SET_PROTOCOL) { + protocol = setup.wValueL; + return true; + } + if (request == HID_SET_IDLE) { + idle = setup.wValueL; + return true; + } + if (request == HID_SET_REPORT) { + } + } + + return false; } -void SingleAbsoluteMouse_::sendReport(void* data, int length) -{ - USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, length); +void SingleAbsoluteMouse_::sendReport(void* data, int length) { + USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, length); } SingleAbsoluteMouse_ SingleAbsoluteMouse; diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h index 4d0a832f6c..b96ec82d6a 100644 --- a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h +++ b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h @@ -32,14 +32,13 @@ THE SOFTWARE. #include "../DeviceAPIs/AbsoluteMouseAPI.h" -class SingleAbsoluteMouse_ : public PluggableUSBModule, public AbsoluteMouseAPI -{ -public: +class SingleAbsoluteMouse_ : public PluggableUSBModule, public AbsoluteMouseAPI { + public: SingleAbsoluteMouse_(void); uint8_t getLeds(void); uint8_t getProtocol(void); -protected: + protected: // Implementation of the PUSBListNode int getInterface(uint8_t* interfaceCount); int getDescriptor(USBSetup& setup); From 0cb7459d294f19da1951c2e7fa9fde21cef861e8 Mon Sep 17 00:00:00 2001 From: Florian Fleissner Date: Wed, 12 Jun 2019 19:02:31 +0200 Subject: [PATCH 535/602] Added a hook for HID report notification This commit adds a hook that enables other modules to be informed about what is actually reported. Signed-off-by: Florian Fleissner --- plugins/KeyboardioHID/src/HID.cpp | 8 ++++++++ plugins/KeyboardioHID/src/HID.h | 12 ++++++++++++ 2 files changed, 20 insertions(+) diff --git a/plugins/KeyboardioHID/src/HID.cpp b/plugins/KeyboardioHID/src/HID.cpp index 8d64ad4e4c..6835fdaeb5 100644 --- a/plugins/KeyboardioHID/src/HID.cpp +++ b/plugins/KeyboardioHID/src/HID.cpp @@ -89,6 +89,14 @@ void HID_::AppendDescriptor(HIDSubDescriptor *node) { } int HID_::SendReport(uint8_t id, const void* data, int len) { + auto result = SendReport_(id, data, len); + if(send_report_hook) { + (*send_report_hook)(id, data, len, result); + } + return result; +} + +int HID_::SendReport_(uint8_t id, const void* data, int len) { auto ret = USB_Send(pluggedEndpoint, &id, 1); if (ret < 0) return ret; auto ret2 = USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, len); diff --git a/plugins/KeyboardioHID/src/HID.h b/plugins/KeyboardioHID/src/HID.h index b2fd38b2e7..d5688a593e 100644 --- a/plugins/KeyboardioHID/src/HID.h +++ b/plugins/KeyboardioHID/src/HID.h @@ -89,6 +89,8 @@ class HIDSubDescriptor { class HID_ : public PluggableUSBModule { public: + typedef void(*SendReportHook)(uint8_t id, const void* data, int len, int result); + HID_(void); int begin(void); int SendReport(uint8_t id, const void* data, int len); @@ -97,6 +99,13 @@ class HID_ : public PluggableUSBModule { return setReportData.leds; }; + void setSendReportHook(SendReportHook hook) { + send_report_hook = hook; + } + SendReportHook getCurrentSendReportHook() const { + return send_report_hook; + } + protected: // Implementation of the PluggableUSBModule int getInterface(uint8_t* interfaceCount); @@ -104,9 +113,12 @@ class HID_ : public PluggableUSBModule { bool setup(USBSetup& setup); uint8_t getShortName(char* name); + int SendReport_(uint8_t id, const void* data, int len); private: EPTYPE_DESCRIPTOR_SIZE epType[1]; + SendReportHook send_report_hook = nullptr; + HIDSubDescriptor* rootNode; uint16_t descriptorSize; From 6fbf35c08ee40f4f2a27cf6108df4ba1a9ad4eae Mon Sep 17 00:00:00 2001 From: Florian Fleissner Date: Thu, 13 Jun 2019 14:35:32 +0200 Subject: [PATCH 536/602] Fixed a missing default implementation This only causes an error when build with the virtual hardware. The physical core threw away the respective symbol as unreferenced during garbage collection. That's why the error only showed up when starting to share the HID-implementation with the virtual hardware. Signed-off-by: Florian Fleissner --- plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h index e1e1243da3..e3ffa18cf2 100644 --- a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h +++ b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h @@ -88,7 +88,7 @@ class AbsoluteMouseAPI { inline bool isPressed(uint8_t b = MOUSE_LEFT); // Sending is public in the base class for advanced users. - virtual void sendReport(void* data, int length); + virtual void sendReport(void* data, int length) {} protected: uint16_t xAxis; From 31a2abcdbda49a1ccb2f2b051d4a293d975ae517 Mon Sep 17 00:00:00 2001 From: Florian Fleissner Date: Thu, 13 Jun 2019 14:37:39 +0200 Subject: [PATCH 537/602] Conditionally build the HID core This is necessary as the virtual hardware now supports its own implementation of HID.cpp. Signed-off-by: Florian Fleissner --- plugins/KeyboardioHID/src/HID.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/KeyboardioHID/src/HID.cpp b/plugins/KeyboardioHID/src/HID.cpp index 526ed892e4..bf5fce4181 100644 --- a/plugins/KeyboardioHID/src/HID.cpp +++ b/plugins/KeyboardioHID/src/HID.cpp @@ -16,6 +16,8 @@ SOFTWARE. */ +#ifndef KEYBOARDIOHID_BUILD_WITHOUT_HID + #include "HID.h" #if defined(USBCON) @@ -158,3 +160,5 @@ int HID_::begin(void) { } #endif /* if defined(USBCON) */ + +#endif /* ifndef KEYBOARDIOHID_BUILD_WITHOUT_HID */ From 98389c7dad32a298b23bd0d5b4d9303ce65f6207 Mon Sep 17 00:00:00 2001 From: Florian Fleissner Date: Thu, 20 Jun 2019 14:15:40 +0200 Subject: [PATCH 538/602] Added a HIDReportObserver class The new observer class is used in all places where reports are send. It replaces the old observer that was solely used by HID.*. Signed-off-by: Florian Fleissner --- .../src/BootKeyboard/BootKeyboard.cpp | 2 + plugins/KeyboardioHID/src/HID.cpp | 5 +- plugins/KeyboardioHID/src/HID.h | 11 ---- .../KeyboardioHID/src/HIDReportObserver.cpp | 27 ++++++++++ plugins/KeyboardioHID/src/HIDReportObserver.h | 54 +++++++++++++++++++ .../src/SingleReport/SingleAbsoluteMouse.cpp | 4 +- 6 files changed, 88 insertions(+), 15 deletions(-) create mode 100644 plugins/KeyboardioHID/src/HIDReportObserver.cpp create mode 100644 plugins/KeyboardioHID/src/HIDReportObserver.h diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 610a01f141..4cdcc3a44f 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -25,6 +25,7 @@ THE SOFTWARE. #include "BootKeyboard.h" #include "DescriptorPrimitives.h" +#include "HIDReportObserver.h" // See Appendix B of USB HID spec static const uint8_t _hidReportDescriptorKeyboard[] PROGMEM = { @@ -217,6 +218,7 @@ int BootKeyboard_::sendReport(void) { if (memcmp(&_lastKeyReport, &_keyReport, sizeof(_keyReport))) { // if the two reports are different, send a report int returnCode = USB_Send(pluggedEndpoint | TRANSFER_RELEASE, &_keyReport, sizeof(_keyReport)); + HIDReportObserver::observeReport(HID_REPORTID_KEYBOARD, &_keyReport, sizeof(_keyReport), returnCode); memcpy(&_lastKeyReport, &_keyReport, sizeof(_keyReport)); return returnCode; } diff --git a/plugins/KeyboardioHID/src/HID.cpp b/plugins/KeyboardioHID/src/HID.cpp index 4a177cb2ff..ac7ef8ed37 100644 --- a/plugins/KeyboardioHID/src/HID.cpp +++ b/plugins/KeyboardioHID/src/HID.cpp @@ -19,6 +19,7 @@ #ifndef KEYBOARDIOHID_BUILD_WITHOUT_HID #include "HID.h" +#include "HIDReportObserver.h" #if defined(USBCON) @@ -92,9 +93,7 @@ void HID_::AppendDescriptor(HIDSubDescriptor *node) { int HID_::SendReport(uint8_t id, const void* data, int len) { auto result = SendReport_(id, data, len); - if(send_report_hook) { - (*send_report_hook)(id, data, len, result); - } + HIDReportObserver::observeReport(id, data, len, result); return result; } diff --git a/plugins/KeyboardioHID/src/HID.h b/plugins/KeyboardioHID/src/HID.h index d5688a593e..44995e9cb3 100644 --- a/plugins/KeyboardioHID/src/HID.h +++ b/plugins/KeyboardioHID/src/HID.h @@ -89,8 +89,6 @@ class HIDSubDescriptor { class HID_ : public PluggableUSBModule { public: - typedef void(*SendReportHook)(uint8_t id, const void* data, int len, int result); - HID_(void); int begin(void); int SendReport(uint8_t id, const void* data, int len); @@ -99,13 +97,6 @@ class HID_ : public PluggableUSBModule { return setReportData.leds; }; - void setSendReportHook(SendReportHook hook) { - send_report_hook = hook; - } - SendReportHook getCurrentSendReportHook() const { - return send_report_hook; - } - protected: // Implementation of the PluggableUSBModule int getInterface(uint8_t* interfaceCount); @@ -117,8 +108,6 @@ class HID_ : public PluggableUSBModule { private: EPTYPE_DESCRIPTOR_SIZE epType[1]; - SendReportHook send_report_hook = nullptr; - HIDSubDescriptor* rootNode; uint16_t descriptorSize; diff --git a/plugins/KeyboardioHID/src/HIDReportObserver.cpp b/plugins/KeyboardioHID/src/HIDReportObserver.cpp new file mode 100644 index 0000000000..8f0ec1d945 --- /dev/null +++ b/plugins/KeyboardioHID/src/HIDReportObserver.cpp @@ -0,0 +1,27 @@ +/* +Copyright (c) 2015-2019 Keyboard.io, Inc + +See the readme for credit to other people. + +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 "HIDReportObserver.h" + +HIDReportObserver::SendReportHook HIDReportObserver::send_report_hook_ = nullptr; diff --git a/plugins/KeyboardioHID/src/HIDReportObserver.h b/plugins/KeyboardioHID/src/HIDReportObserver.h new file mode 100644 index 0000000000..2a94ca7a0c --- /dev/null +++ b/plugins/KeyboardioHID/src/HIDReportObserver.h @@ -0,0 +1,54 @@ +/* +Copyright (c) 2015-2019 Keyboard.io, Inc + +See the readme for credit to other people. + +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. +*/ + +#pragma once + +#include + +class HIDReportObserver +{ + public: + + typedef void(*SendReportHook)(uint8_t id, const void* data, + int len, int result); + + static void observeReport(uint8_t id, const void* data, + int len, int result) { + if(send_report_hook_) { + (*send_report_hook_)(id, data, len, result); + } + } + + static SendReportHook currentHook() { return send_report_hook_; } + + static SendReportHook resetHook(SendReportHook new_hook) { + auto previous_hook = send_report_hook_; + send_report_hook_ = new_hook; + return previous_hook; + } + + private: + + static SendReportHook send_report_hook_; +}; diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp index e0202e5704..b4795d8b5b 100644 --- a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp @@ -24,6 +24,7 @@ THE SOFTWARE. */ #include "SingleAbsoluteMouse.h" +#include "HIDReportObserver.h" static const uint8_t _hidSingleReportDescriptorAbsoluteMouse[] PROGMEM = { D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) 54 */ @@ -109,7 +110,8 @@ bool SingleAbsoluteMouse_::setup(USBSetup& setup) { } void SingleAbsoluteMouse_::sendReport(void* data, int length) { - USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, length); + auto result = USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, length); + HIDReportObserver::observeReport(HID_REPORTID_MOUSE_ABSOLUTE, data, length, result); } SingleAbsoluteMouse_ SingleAbsoluteMouse; From 8bf97d412c4020d659771f24b1af6be0f92c1bed Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Fri, 8 Nov 2019 12:38:09 +0100 Subject: [PATCH 539/602] SAMD: Fix the host wakeup code We can't include `SAMD21_USBDevice.h`, because it unconditionally redefines symbols, leading to linking errors. We work this around by implementing pretty much the same thing its `.wakeupHost()` method does. This is a workaround, until the SAMD core is fixed to expose the `wakeupHost()` method in a sane way. Mind you, this doesn't quite work yet, but at least it compiles, and is a step in the right direction. Signed-off-by: Gergely Nagy --- .../KeyboardioHID/src/MultiReport/SystemControl.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp b/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp index 0a341f15e2..7c98acff58 100644 --- a/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp @@ -26,10 +26,6 @@ THE SOFTWARE. #include "SystemControl.h" #include "DescriptorPrimitives.h" -#ifdef ARDUINO_ARCH_SAMD -#include "USB/SAMD21_USBDevice.h" -#endif - static const uint8_t _hidMultiReportDescriptorSystem[] PROGMEM = { //TODO limit to system keys only? /* System Control (Power Down, Sleep, Wakeup, ...) */ @@ -82,8 +78,10 @@ void SystemControl_::press(uint8_t s) { USBDevice.wakeupHost(); #endif #ifdef ARDUINO_ARCH_SAMD - extern USBDevice_SAMD21G18x usbd; - usbd.wakeupHost(); + // This is USBDevice_SAMD21G18x.wakeupHost(). But we can't include that + // header, because it redefines a few symbols, and causes linking + // errors. So we simply reimplement the same thing here. + USB->DEVICE.CTRLB.bit.UPRSM = 1; #endif } else { sendReport(&s, sizeof(s)); From 25ff8564c0b01822132a0a2fd3afa7f32884c104 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Wed, 13 Nov 2019 13:13:20 +0100 Subject: [PATCH 540/602] SAMD: Fix the descriptor sending When sending the HID descriptor in `HID_::getDescriptor()`, we need to send it as one package on SAMD. For this reason, we tell the USB library to pack messages before sending anything, and then flush it at the end. To be able to avoid ifdefs in that function, we introduce `USB_PackMessages()`, which is a wrapper around `USBDevice.packMessages()` on SAMD, and a no-op on AVR (where we do not need this packing). Signed-off-by: Gergely Nagy --- plugins/KeyboardioHID/src/HID-Settings.h | 6 ++++++ plugins/KeyboardioHID/src/HID.cpp | 2 ++ plugins/KeyboardioHID/src/arch/avr.cpp | 8 ++++++++ plugins/KeyboardioHID/src/arch/samd.cpp | 4 ++++ 4 files changed, 20 insertions(+) create mode 100644 plugins/KeyboardioHID/src/arch/avr.cpp diff --git a/plugins/KeyboardioHID/src/HID-Settings.h b/plugins/KeyboardioHID/src/HID-Settings.h index 5bf09eb92d..c9fdec64b2 100644 --- a/plugins/KeyboardioHID/src/HID-Settings.h +++ b/plugins/KeyboardioHID/src/HID-Settings.h @@ -69,6 +69,12 @@ THE SOFTWARE. #define HID_REPORT_TYPE_OUTPUT 2 #define HID_REPORT_TYPE_FEATURE 3 +// Controls whether to pack messages or not. When set, any sends will be delayed +// until packing is toggled off, and sent then. This is a no-op on AVR, but is +// required for SAMD. We place a forward-declaration here to be able to avoid +// architecture-specific ifdefs elsewhere in the code. +void USB_PackMessages(bool pack); + #if defined(ARDUINO_ARCH_AVR) #include "PluggableUSB.h" diff --git a/plugins/KeyboardioHID/src/HID.cpp b/plugins/KeyboardioHID/src/HID.cpp index ac7ef8ed37..6e1062283b 100644 --- a/plugins/KeyboardioHID/src/HID.cpp +++ b/plugins/KeyboardioHID/src/HID.cpp @@ -54,6 +54,7 @@ int HID_::getDescriptor(USBSetup& setup) { int total = 0; HIDSubDescriptor* node; + USB_PackMessages(true); for (node = rootNode; node; node = node->next) { int res = USB_SendControl(TRANSFER_PGM, node->data, node->length); if (res == -1) @@ -65,6 +66,7 @@ int HID_::getDescriptor(USBSetup& setup) { // due to the USB specs, but Windows and Linux just assumes its in report mode. protocol = HID_REPORT_PROTOCOL; + USB_PackMessages(false); return total; } diff --git a/plugins/KeyboardioHID/src/arch/avr.cpp b/plugins/KeyboardioHID/src/arch/avr.cpp new file mode 100644 index 0000000000..9c0fcf2a7d --- /dev/null +++ b/plugins/KeyboardioHID/src/arch/avr.cpp @@ -0,0 +1,8 @@ +#include "Arduino.h" + +#ifdef ARDUINO_ARCH_AVR + +void USB_PackMessages(bool pack) { +} + +#endif diff --git a/plugins/KeyboardioHID/src/arch/samd.cpp b/plugins/KeyboardioHID/src/arch/samd.cpp index a50e79fdcc..c76e3bb73a 100644 --- a/plugins/KeyboardioHID/src/arch/samd.cpp +++ b/plugins/KeyboardioHID/src/arch/samd.cpp @@ -10,4 +10,8 @@ int USB_SendControl(uint8_t a, const void* b, uint8_t c) { USBDevice.sendControl(b, c); } +void USB_PackMessages(bool pack) { + USBDevice.packMessages(pack); +} + #endif From d3bfab9fa837f35efa2a759663ea646ab4e3de0c Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Fri, 6 Dec 2019 12:03:12 +0100 Subject: [PATCH 541/602] HID_::SendReport_: Use a single send on SAMD On SAMD, we need to send the whole report in one go, otherwise the report does not arrive to the host. To do this, we merge the report id and the report itself into a single buffer, and send that instead of sending the report id and the data separately. Signed-off-by: Gergely Nagy --- plugins/KeyboardioHID/src/HID.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/plugins/KeyboardioHID/src/HID.cpp b/plugins/KeyboardioHID/src/HID.cpp index 6e1062283b..c1a31c82cd 100644 --- a/plugins/KeyboardioHID/src/HID.cpp +++ b/plugins/KeyboardioHID/src/HID.cpp @@ -100,11 +100,25 @@ int HID_::SendReport(uint8_t id, const void* data, int len) { } int HID_::SendReport_(uint8_t id, const void* data, int len) { + /* On SAMD, we need to send the whole report in one batch; sending the id, and + * the report itself separately does not work, the report never arrives. Due + * to this, we merge the two into a single buffer, and send that. + * + * While the same would work for other architectures, AVR included, doing so + * costs RAM, which is something scarce on AVR. So on that platform, we opt to + * send the id and the report separately instead. */ +#ifdef ARDUINO_ARCH_SAMD + uint8_t p[64]; + p[0] = id; + memcpy(&p[1], data, len); + return USB_Send(pluggedEndpoint, p, len+1); +#else auto ret = USB_Send(pluggedEndpoint, &id, 1); if (ret < 0) return ret; auto ret2 = USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, len); if (ret2 < 0) return ret2; return ret + ret2; +#endif } bool HID_::setup(USBSetup& setup) { From 552116d86067eac8a1d79d596f0adebe06ec7b42 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Sat, 7 Dec 2019 09:35:18 +0100 Subject: [PATCH 542/602] HID: Mark HID_::getShortName weak Marking the method weak allows us to override it elsewhere, which in turn makes it possible to have a different shortname than 'kbio01'. This is the first half of the fix for #54. Signed-off-by: Gergely Nagy --- plugins/KeyboardioHID/src/HID.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/KeyboardioHID/src/HID.cpp b/plugins/KeyboardioHID/src/HID.cpp index c1a31c82cd..54ed9df7bc 100644 --- a/plugins/KeyboardioHID/src/HID.cpp +++ b/plugins/KeyboardioHID/src/HID.cpp @@ -70,6 +70,7 @@ int HID_::getDescriptor(USBSetup& setup) { return total; } +__attribute__((weak)) uint8_t HID_::getShortName(char *name) { name[0] = 'k'; name[1] = 'b'; From 72fad9ef5d826bda5873852b07182c41065aec76 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Fri, 13 Dec 2019 10:42:46 +0100 Subject: [PATCH 543/602] Delay appending the HID descriptors until .begin() To be able to better control when and in which order HID descriptors are appended, delay doing so until calling `.begin()`, at least for NKRO-keyboard and Consumer- and SystemControl. The Mouse class was already doing the same. Signed-off-by: Gergely Nagy --- plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp | 5 +++-- plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp | 5 +++-- plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp | 5 +++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp index dc6876cb55..38616e9591 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp @@ -44,11 +44,12 @@ static const uint8_t _hidMultiReportDescriptorConsumer[] PROGMEM = { }; ConsumerControl_::ConsumerControl_(void) { - static HIDSubDescriptor node(_hidMultiReportDescriptorConsumer, sizeof(_hidMultiReportDescriptorConsumer)); - HID().AppendDescriptor(&node); } void ConsumerControl_::begin(void) { + static HIDSubDescriptor node(_hidMultiReportDescriptorConsumer, sizeof(_hidMultiReportDescriptorConsumer)); + HID().AppendDescriptor(&node); + // release all buttons end(); } diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index 453af3cba8..caeb1a182f 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -79,11 +79,12 @@ static const uint8_t _hidMultiReportDescriptorKeyboard[] PROGMEM = { }; Keyboard_::Keyboard_(void) { - static HIDSubDescriptor node(_hidMultiReportDescriptorKeyboard, sizeof(_hidMultiReportDescriptorKeyboard)); - HID().AppendDescriptor(&node); } void Keyboard_::begin(void) { + static HIDSubDescriptor node(_hidMultiReportDescriptorKeyboard, sizeof(_hidMultiReportDescriptorKeyboard)); + HID().AppendDescriptor(&node); + // Force API to send a clean report. // This is important for and HID bridge where the receiver stays on, // while the sender is resetted. diff --git a/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp b/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp index 7c98acff58..d4a5724642 100644 --- a/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp @@ -45,11 +45,12 @@ static const uint8_t _hidMultiReportDescriptorSystem[] PROGMEM = { }; SystemControl_::SystemControl_(void) { - static HIDSubDescriptor node(_hidMultiReportDescriptorSystem, sizeof(_hidMultiReportDescriptorSystem)); - HID().AppendDescriptor(&node); } void SystemControl_::begin(void) { + static HIDSubDescriptor node(_hidMultiReportDescriptorSystem, sizeof(_hidMultiReportDescriptorSystem)); + HID().AppendDescriptor(&node); + // release all buttons end(); } From 49adba4e5256479b375b6b14da8c1acdb879b93e Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Tue, 17 Dec 2019 13:06:49 +0100 Subject: [PATCH 544/602] Revert "Delay appending the HID descriptors until .begin()" --- plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp | 5 ++--- plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp | 5 ++--- plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp | 5 ++--- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp index 38616e9591..dc6876cb55 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp @@ -44,12 +44,11 @@ static const uint8_t _hidMultiReportDescriptorConsumer[] PROGMEM = { }; ConsumerControl_::ConsumerControl_(void) { -} - -void ConsumerControl_::begin(void) { static HIDSubDescriptor node(_hidMultiReportDescriptorConsumer, sizeof(_hidMultiReportDescriptorConsumer)); HID().AppendDescriptor(&node); +} +void ConsumerControl_::begin(void) { // release all buttons end(); } diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index caeb1a182f..453af3cba8 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -79,12 +79,11 @@ static const uint8_t _hidMultiReportDescriptorKeyboard[] PROGMEM = { }; Keyboard_::Keyboard_(void) { -} - -void Keyboard_::begin(void) { static HIDSubDescriptor node(_hidMultiReportDescriptorKeyboard, sizeof(_hidMultiReportDescriptorKeyboard)); HID().AppendDescriptor(&node); +} +void Keyboard_::begin(void) { // Force API to send a clean report. // This is important for and HID bridge where the receiver stays on, // while the sender is resetted. diff --git a/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp b/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp index d4a5724642..7c98acff58 100644 --- a/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp @@ -45,12 +45,11 @@ static const uint8_t _hidMultiReportDescriptorSystem[] PROGMEM = { }; SystemControl_::SystemControl_(void) { -} - -void SystemControl_::begin(void) { static HIDSubDescriptor node(_hidMultiReportDescriptorSystem, sizeof(_hidMultiReportDescriptorSystem)); HID().AppendDescriptor(&node); +} +void SystemControl_::begin(void) { // release all buttons end(); } From 2c224b817a3e3b2825b6fa605905400ea1b674a7 Mon Sep 17 00:00:00 2001 From: Michael Richters Date: Mon, 14 Sep 2020 11:31:04 -0700 Subject: [PATCH 545/602] Update HIDTables.h to match USB-IF HID Usage tables 1.2 --- plugins/KeyboardioHID/src/HIDTables.h | 1394 +++++++++++++------------ 1 file changed, 745 insertions(+), 649 deletions(-) diff --git a/plugins/KeyboardioHID/src/HIDTables.h b/plugins/KeyboardioHID/src/HIDTables.h index 60d2a6ca18..85072b0f9b 100644 --- a/plugins/KeyboardioHID/src/HIDTables.h +++ b/plugins/KeyboardioHID/src/HIDTables.h @@ -22,12 +22,11 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef __HIDTables__ -#define __HIDTables__ +#pragma once // These mappings were extracted and transcribed from -// http://www.usb.org_SLASH_developers_SLASH_devclass_docs_SLASH_Hut1_12v2.pdf +// https://www.usb.org/sites/default/files/hut1_2.pdf // // In most cases, I've preserved the "official" USB Implementers forum // "Usage Name", though I've standardized some abbreviations and spacing @@ -38,665 +37,762 @@ THE SOFTWARE. // // Not every HID usage listed in this file is currently supported by Arduino // In particular, any System Control or Consumer Control entry that doesn't -// have a comment indicating that it's "HID type OSC" will require additional -// code in the Arduino core to work. +// have a comment indicating that it's "HID type OSC" may require additional +// code in the Arduino core to work, although // some keycodes with usage +// type RTC (Re-Trigger Control) and OOC (On/Off Control) are also functional. // // Non-working usages are listed here in the interest of not having to manually // convert more usage names each and every time our HID stack gets a little bit // better. // // -// -- Jesse Vincent , January 2014 +// -- Jesse Vincent , September 2020 -// System control mappings +// ============================================================================== +// System Control USB HID keycodes +// [Section 4: Generic Desktop Page (0x01)] -#define HID_SYSTEM_POWER_DOWN 0x81 // HID type OSC -#define HID_SYSTEM_SLEEP 0x82 // HID type OSC -#define HID_SYSTEM_WAKE_UP 0x83 // HID type OSC -#define HID_SYSTEM_CONTEXT_MENU 0x84 // HID type OSC -#define HID_SYSTEM_MAIN_MENU 0x85 // HID type OSC -#define HID_SYSTEM_APP_MENU 0x86 // HID type OSC -#define HID_SYSTEM_MENU_HELP 0x87 // HID type OSC -#define HID_SYSTEM_MENU_EXIT 0x88 // HID type OSC -#define HID_SYSTEM_MENU_SELECT 0x89 // HID type OSC -#define HID_SYSTEM_MENU_RIGHT 0x8A // HID type RTC -#define HID_SYSTEM_MENU_LEFT 0x8B // HID type RTC -#define HID_SYSTEM_MENU_UP 0x8C // HID type RTC -#define HID_SYSTEM_MENU_DOWN 0x8D // HID type RTC -#define HID_SYSTEM_COLD_RESTART 0x8E // HID type OSC -#define HID_SYSTEM_WARM_RESTART 0x8F // HID type OSC -#define HID_D_PAD_UP 0x90 // HID type OOC -#define HID_D_PAD_DOWN 0x91 // HID type OOC -#define HID_D_PAD_RIGHT 0x92 // HID type OOC -#define HID_D_PAD_LEFT 0x93 // HID type OOC -// 0x94-0x9F are reserved -#define HID_SYSTEM_DOCK 0xA0 // HID type OSC -#define HID_SYSTEM_UNDOCK 0xA1 // HID type OSC -#define HID_SYSTEM_SETUP 0xA2 // HID type OSC -#define HID_SYSTEM_BREAK 0xA3 // HID type OSC -#define HID_SYSTEM_DEBUGGER_BREAK 0xA4 // HID type OSC -#define HID_APPLICATION_BREAK 0xA5 // HID type OSC -#define HID_APPLICATION_DEBUGGER_BREAK 0xA6 // HID type OSC -#define HID_SYSTEM_SPEAKER_MUTE 0xA7 // HID type OSC -#define HID_SYSTEM_HIBERNATE 0xA8 // HID type OSC -// 0xA9-0xAF are reserved -#define HID_SYSTEM_DISPLAY_INVERT 0xB0 // HID type OSC -#define HID_SYSTEM_DISPLAY_INTERNAL 0xB1 // HID type OSC -#define HID_SYSTEM_DISPLAY_EXTERNAL 0xB2 // HID type OSC -#define HID_SYSTEM_DISPLAY_BOTH 0xB3 // HID type OSC -#define HID_SYSTEM_DISPLAY_DUAL 0xB4 // HID type OSC -#define HID_SYSTEM_DISPLAY_TOGGLE_INT_SLASH_EXT 0xB5 // HID type OSC -#define HID_SYSTEM_DISPLAY_SWAP_PRIMARY_SLASH_SECONDARY 0xB6 // HID type OSC -#define HID_SYSTEM_DISPLAY_LCD_AUTOSCALE 0xB7 // HID type OSC +// ----|-------------------------------------------------------|-------|--------- +// Name Value Usage Type +// ----|-------------------------------------------------------|-------|--------- +#define HID_SYSTEM_POWER_DOWN 0x81 // OSC +#define HID_SYSTEM_SLEEP 0x82 // OSC +#define HID_SYSTEM_WAKE_UP 0x83 // OSC +#define HID_SYSTEM_CONTEXT_MENU 0x84 // OSC +#define HID_SYSTEM_MAIN_MENU 0x85 // OSC +#define HID_SYSTEM_APP_MENU 0x86 // OSC +#define HID_SYSTEM_MENU_HELP 0x87 // OSC +#define HID_SYSTEM_MENU_EXIT 0x88 // OSC +#define HID_SYSTEM_MENU_SELECT 0x89 // OSC +#define HID_SYSTEM_MENU_RIGHT 0x8A // RTC +#define HID_SYSTEM_MENU_LEFT 0x8B // RTC +#define HID_SYSTEM_MENU_UP 0x8C // RTC +#define HID_SYSTEM_MENU_DOWN 0x8D // RTC +#define HID_SYSTEM_COLD_RESTART 0x8E // OSC +#define HID_SYSTEM_WARM_RESTART 0x8F // OSC +#define HID_D_PAD_UP 0x90 // OOC +#define HID_D_PAD_DOWN 0x91 // OOC +#define HID_D_PAD_RIGHT 0x92 // OOC +#define HID_D_PAD_LEFT 0x93 // OOC +#define HID_INDEX_TRIGGER 0x94 // MC/DV +#define HID_PALM_TRIGGER 0x95 // MC/DV +#define HID_THUMBSTICK 0x96 // CP +#define HID_SYSTEM_FUNCTION_SHIFT 0x97 // MC +#define HID_SYSTEM_FUNCTION_SHIFT_LOCK 0x98 // OOC +#define HID_SYSTEM_FUNCTION_SHIFT_LOCK_INDICATOR 0x99 // DV +#define HID_DISMISS_NOTIFICATION 0x9A // OSC +#define HID_DO_NOT_DISTURB 0x9B // OOC +// Reserved 0x9C-9F +#define HID_SYSTEM_DOCK 0xA0 // OSC +#define HID_SYSTEM_UNDOCK 0xA1 // OSC +#define HID_SYSTEM_SETUP 0xA2 // OSC +#define HID_SYSTEM_BREAK 0xA3 // OSC +#define HID_SYSTEM_DEBUGGER_BREAK 0xA4 // OSC +#define HID_APPLICATION_BREAK 0xA5 // OSC +#define HID_APPLICATION_DEBUGGER_BREAK 0xA6 // OSC +#define HID_SYSTEM_SPEAKER_MUTE 0xA7 // OSC +#define HID_SYSTEM_HIBERNATE 0xA8 // OSC +// Reserved 0xA9-AF +#define HID_SYSTEM_DISPLAY_INVERT 0xB0 // OSC +#define HID_SYSTEM_DISPLAY_INTERNAL 0xB1 // OSC +#define HID_SYSTEM_DISPLAY_EXTERNAL 0xB2 // OSC +#define HID_SYSTEM_DISPLAY_BOTH 0xB3 // OSC +#define HID_SYSTEM_DISPLAY_DUAL 0xB4 // OSC +#define HID_SYSTEM_DISPLAY_TOGGLE_INT_SLASH_EXT 0xB5 // OSC +#define HID_SYSTEM_DISPLAY_SWAP_PRIMARY_SLASH_SECONDARY 0xB6 // OSC +#define HID_SYSTEM_DISPLAY_LCD_AUTOSCALE 0xB7 // OSC +// Reserved 0xB8-BF -// Keyboard HID mappings -// Reserved (no_event_indicated) 0x00 -#define HID_KEYBOARD_NO_EVENT 0x00 -#define HID_KEYBOARD_ERROR_ROLLOVER 0x01 -#define HID_KEYBOARD_POST_FAIL 0x02 -#define HID_KEYBOARD_ERROR_UNDEFINED 0x03 -#define HID_KEYBOARD_A_AND_A 0x04 -#define HID_KEYBOARD_B_AND_B 0x05 -#define HID_KEYBOARD_C_AND_C 0x06 -#define HID_KEYBOARD_D_AND_D 0x07 -#define HID_KEYBOARD_E_AND_E 0x08 -#define HID_KEYBOARD_F_AND_F 0x09 -#define HID_KEYBOARD_G_AND_G 0x0A -#define HID_KEYBOARD_H_AND_H 0x0B -#define HID_KEYBOARD_I_AND_I 0x0C -#define HID_KEYBOARD_J_AND_J 0x0D -#define HID_KEYBOARD_K_AND_K 0x0E -#define HID_KEYBOARD_L_AND_L 0x0F -#define HID_KEYBOARD_M_AND_M 0x10 -#define HID_KEYBOARD_N_AND_N 0x11 -#define HID_KEYBOARD_O_AND_O 0x12 -#define HID_KEYBOARD_P_AND_P 0x13 -#define HID_KEYBOARD_Q_AND_Q 0x14 -#define HID_KEYBOARD_R_AND_R 0x15 -#define HID_KEYBOARD_S_AND_S 0x16 -#define HID_KEYBOARD_T_AND_T 0x17 -#define HID_KEYBOARD_U_AND_U 0x18 -#define HID_KEYBOARD_V_AND_V 0x19 -#define HID_KEYBOARD_W_AND_W 0x1A -#define HID_KEYBOARD_X_AND_X 0x1B -#define HID_KEYBOARD_Y_AND_Y 0x1C -#define HID_KEYBOARD_Z_AND_Z 0x1D -#define HID_KEYBOARD_1_AND_EXCLAMATION_POINT 0x1E -#define HID_KEYBOARD_2_AND_AT 0x1F -#define HID_KEYBOARD_3_AND_POUND 0x20 -#define HID_KEYBOARD_4_AND_DOLLAR 0x21 -#define HID_KEYBOARD_5_AND_PERCENT 0x22 -#define HID_KEYBOARD_6_AND_CARAT 0x23 -#define HID_KEYBOARD_7_AND_AMPERSAND 0x24 -#define HID_KEYBOARD_8_AND_ASTERISK 0x25 -#define HID_KEYBOARD_9_AND_LEFT_PAREN 0x26 -#define HID_KEYBOARD_0_AND_RIGHT_PAREN 0x27 -#define HID_KEYBOARD_ENTER 0x28 // (MARKED AS ENTER_SLASH_RETURN) -#define HID_KEYBOARD_ESCAPE 0x29 -#define HID_KEYBOARD_DELETE 0x2A // (BACKSPACE) -#define HID_KEYBOARD_TAB 0x2B -#define HID_KEYBOARD_SPACEBAR 0x2C -#define HID_KEYBOARD_MINUS_AND_UNDERSCORE 0x2D // (UNDERSCORE) -#define HID_KEYBOARD_EQUALS_AND_PLUS 0x2E -#define HID_KEYBOARD_LEFT_BRACKET_AND_LEFT_CURLY_BRACE 0x2F -#define HID_KEYBOARD_RIGHT_BRACKET_AND_RIGHT_CURLY_BRACE 0x30 -#define HID_KEYBOARD_BACKSLASH_AND_PIPE 0x31 -#define HID_KEYBOARD_NON_US_POUND_AND_TILDE 0x32 -#define HID_KEYBOARD_SEMICOLON_AND_COLON 0x33 -#define HID_KEYBOARD_QUOTE_AND_DOUBLEQUOTE 0x34 -#define HID_KEYBOARD_GRAVE_ACCENT_AND_TILDE 0x35 -#define HID_KEYBOARD_COMMA_AND_LESS_THAN 0x36 -#define HID_KEYBOARD_PERIOD_AND_GREATER_THAN 0x37 -#define HID_KEYBOARD_SLASH_AND_QUESTION_MARK 0x38 -#define HID_KEYBOARD_CAPS_LOCK 0x39 -#define HID_KEYBOARD_F1 0x3A -#define HID_KEYBOARD_F2 0x3B -#define HID_KEYBOARD_F3 0x3C -#define HID_KEYBOARD_F4 0x3D -#define HID_KEYBOARD_F5 0x3E -#define HID_KEYBOARD_F6 0x3F -#define HID_KEYBOARD_F7 0x40 -#define HID_KEYBOARD_F8 0x41 -#define HID_KEYBOARD_F9 0x42 -#define HID_KEYBOARD_F10 0x43 -#define HID_KEYBOARD_F11 0x44 -#define HID_KEYBOARD_F12 0x45 -#define HID_KEYBOARD_PRINTSCREEN 0x46 -#define HID_KEYBOARD_SCROLL_LOCK 0x47 -#define HID_KEYBOARD_PAUSE 0x48 -#define HID_KEYBOARD_INSERT 0x49 -#define HID_KEYBOARD_HOME 0x4A -#define HID_KEYBOARD_PAGE_UP 0x4B -#define HID_KEYBOARD_DELETE_FORWARD 0x4C -#define HID_KEYBOARD_END 0x4D -#define HID_KEYBOARD_PAGE_DOWN 0x4E -#define HID_KEYBOARD_RIGHT_ARROW 0x4F -#define HID_KEYBOARD_LEFT_ARROW 0x50 -#define HID_KEYBOARD_DOWN_ARROW 0x51 -#define HID_KEYBOARD_UP_ARROW 0x52 -#define HID_KEYPAD_NUM_LOCK_AND_CLEAR 0x53 -#define HID_KEYPAD_DIVIDE 0x54 -#define HID_KEYPAD_MULTIPLY 0x55 -#define HID_KEYPAD_SUBTRACT 0x56 -#define HID_KEYPAD_ADD 0x57 -#define HID_KEYPAD_ENTER 0x58 -#define HID_KEYPAD_1_AND_END 0x59 -#define HID_KEYPAD_2_AND_DOWN_ARROW 0x5A -#define HID_KEYPAD_3_AND_PAGE_DOWN 0x5B -#define HID_KEYPAD_4_AND_LEFT_ARROW 0x5C -#define HID_KEYPAD_5 0x5D -#define HID_KEYPAD_6_AND_RIGHT_ARROW 0x5E -#define HID_KEYPAD_7_AND_HOME 0x5F -#define HID_KEYPAD_8_AND_UP_ARROW 0x60 -#define HID_KEYPAD_9_AND_PAGE_UP 0x61 -#define HID_KEYPAD_0_AND_INSERT 0x62 -#define HID_KEYPAD_PERIOD_AND_DELETE 0x63 -#define HID_KEYBOARD_NON_US_BACKSLASH_AND_PIPE 0x64 -#define HID_KEYBOARD_APPLICATION 0x65 -#define HID_KEYBOARD_POWER 0x66 -#define HID_KEYPAD_EQUALS 0x67 -#define HID_KEYBOARD_F13 0x68 -#define HID_KEYBOARD_F14 0x69 -#define HID_KEYBOARD_F15 0x6A -#define HID_KEYBOARD_F16 0x6B -#define HID_KEYBOARD_F17 0x6C -#define HID_KEYBOARD_F18 0x6D -#define HID_KEYBOARD_F19 0x6E -#define HID_KEYBOARD_F20 0x6F -#define HID_KEYBOARD_F21 0x70 -#define HID_KEYBOARD_F22 0x71 -#define HID_KEYBOARD_F23 0x72 -#define HID_KEYBOARD_F24 0x73 -#define HID_KEYBOARD_EXECUTE 0x74 -#define HID_KEYBOARD_HELP 0x75 -#define HID_KEYBOARD_MENU 0x76 -#define HID_KEYBOARD_SELECT 0x77 -#define HID_KEYBOARD_STOP 0x78 -#define HID_KEYBOARD_AGAIN 0x79 -#define HID_KEYBOARD_UNDO 0x7A -#define HID_KEYBOARD_CUT 0x7B -#define HID_KEYBOARD_COPY 0x7C -#define HID_KEYBOARD_PASTE 0x7D -#define HID_KEYBOARD_FIND 0x7E -#define HID_KEYBOARD_MUTE 0x7F -#define HID_KEYBOARD_VOLUME_UP 0x80 -#define HID_KEYBOARD_VOLUME_DOWN 0x81 -#define HID_KEYBOARD_LOCKING_CAPS_LOCK 0x82 -#define HID_KEYBOARD_LOCKING_NUM_LOCK 0x83 -#define HID_KEYBOARD_LOCKING_SCROLL_LOCK 0x84 -#define HID_KEYPAD_COMMA 0x85 -#define HID_KEYPAD_EQUAL_SIGN 0x86 -#define HID_KEYBOARD_INTERNATIONAL1 0x87 -#define HID_KEYBOARD_INTERNATIONAL2 0x88 -#define HID_KEYBOARD_INTERNATIONAL3 0x89 -#define HID_KEYBOARD_INTERNATIONAL4 0x8A -#define HID_KEYBOARD_INTERNATIONAL5 0x8B -#define HID_KEYBOARD_INTERNATIONAL6 0x8C -#define HID_KEYBOARD_INTERNATIONAL7 0x8D -#define HID_KEYBOARD_INTERNATIONAL8 0x8E -#define HID_KEYBOARD_INTERNATIONAL9 0x8F -#define HID_KEYBOARD_LANG1 0x90 -#define HID_KEYBOARD_LANG2 0x91 -#define HID_KEYBOARD_LANG3 0x92 -#define HID_KEYBOARD_LANG4 0x93 -#define HID_KEYBOARD_LANG5 0x94 -#define HID_KEYBOARD_LANG6 0x95 -#define HID_KEYBOARD_LANG7 0x96 -#define HID_KEYBOARD_LANG8 0x97 -#define HID_KEYBOARD_LANG9 0x98 -#define HID_KEYBOARD_ALTERNATE_ERASE 0x99 -#define HID_KEYBOARD_SYSREQ_SLASH_ATTENTION 0x9A -#define HID_KEYBOARD_CANCEL 0x9B -#define HID_KEYBOARD_CLEAR 0x9C -#define HID_KEYBOARD_PRIOR 0x9D -#define HID_KEYBOARD_RETURN 0x9E -#define HID_KEYBOARD_SEPARATOR 0x9F -#define HID_KEYBOARD_OUT 0xA0 -#define HID_KEYBOARD_OPER 0xA1 -#define HID_KEYBOARD_CLEAR_SLASH_AGAIN 0xA2 -#define HID_KEYBOARD_CRSEL_SLASH_PROPS 0xA3 -#define HID_KEYBOARD_EXSEL 0xA4 -// Reserved 0xA5-AF -#define HID_KEYPAD_00 0xB0 -#define HID_KEYPAD_000 0xB1 -#define HID_THOUSANDS_SEPARATOR 0xB2 -#define HID_DECIMAL_SEPARATOR 0xB3 -#define HID_CURRENCY_UNIT 0xB4 -#define HID_CURRENCY_SUBUNIT 0xB5 -#define HID_KEYPAD_LEFT_PAREN 0xB6 -#define HID_KEYPAD_RIGHT_PAREN 0xB7 -#define HID_KEYPAD_LEFT_CURLY_BRACE 0xB8 -#define HID_KEYPAD_RIGHT_CURLY_BRACE 0xB9 -#define HID_KEYPAD_TAB 0xBA -#define HID_KEYPAD_BACKSPACE 0xBB -#define HID_KEYPAD_A 0xBC -#define HID_KEYPAD_B 0xBD -#define HID_KEYPAD_C 0xBE -#define HID_KEYPAD_D 0xBF -#define HID_KEYPAD_E 0xC0 -#define HID_KEYPAD_F 0xC1 -#define HID_KEYPAD_XOR 0xC2 -#define HID_KEYPAD_CARAT 0xC3 -#define HID_KEYPAD_PERCENT 0xC4 -#define HID_KEYPAD_LESS_THAN 0xC5 -#define HID_KEYPAD_GREATER_THAN 0xC6 -#define HID_KEYPAD_AMPERSAND 0xC7 -#define HID_KEYPAD_DOUBLEAMPERSAND 0xC8 -#define HID_KEYPAD_PIPE 0xC9 -#define HID_KEYPAD_DOUBLEPIPE 0xCA -#define HID_KEYPAD_COLON 0xCB -#define HID_KEYPAD_POUND_SIGN 0xCC -#define HID_KEYPAD_SPACE 0xCD -#define HID_KEYPAD_AT_SIGN 0xCE -#define HID_KEYPAD_EXCLAMATION_POINT 0xCF -#define HID_KEYPAD_MEMORY_STORE 0xD0 -#define HID_KEYPAD_MEMORY_RECALL 0xD1 -#define HID_KEYPAD_MEMORY_CLEAR 0xD2 -#define HID_KEYPAD_MEMORY_ADD 0xD3 -#define HID_KEYPAD_MEMORY_SUBTRACT 0xD4 -#define HID_KEYPAD_MEMORY_MULTIPLY 0xD5 -#define HID_KEYPAD_MEMORY_DIVIDE 0xD6 -#define HID_KEYPAD_PLUS_SLASH_MINUS 0xD7 -#define HID_KEYPAD_CLEAR 0xD8 -#define HID_KEYPAD_CLEAR_ENTRY 0xD9 -#define HID_KEYPAD_BINARY 0xDA -#define HID_KEYPAD_OCTAL 0xDB -#define HID_KEYPAD_DECIMAL 0xDC -#define HID_KEYPAD_HEXADECIMAL 0xDD +// ============================================================================== +// Keyboard USB HID keycodes +// [Section 10: Keyboard/Keypad Page (0x07)] -// 0xDE-0xDF - RESERVED -#define HID_KEYBOARD_LEFT_CONTROL 0xE0 -#define HID_KEYBOARD_LEFT_SHIFT 0xE1 -#define HID_KEYBOARD_LEFT_ALT 0xE2 -#define HID_KEYBOARD_LEFT_GUI 0xE3 -#define HID_KEYBOARD_RIGHT_CONTROL 0xE4 -#define HID_KEYBOARD_RIGHT_SHIFT 0xE5 -#define HID_KEYBOARD_RIGHT_ALT 0xE6 -#define HID_KEYBOARD_RIGHT_GUI 0xE7 +// ----|-------------------------------------------------------|-------|--------- +// Name Value Usage Type +// ----|-------------------------------------------------------|-------|--------- +#define HID_KEYBOARD_NO_EVENT 0x00 // Sel +#define HID_KEYBOARD_ERROR_ROLLOVER 0x01 // Sel +#define HID_KEYBOARD_POST_FAIL 0x02 // Sel +#define HID_KEYBOARD_ERROR_UNDEFINED 0x03 // Sel +#define HID_KEYBOARD_A_AND_A 0x04 // Sel +#define HID_KEYBOARD_B_AND_B 0x05 // Sel +#define HID_KEYBOARD_C_AND_C 0x06 // Sel +#define HID_KEYBOARD_D_AND_D 0x07 // Sel +#define HID_KEYBOARD_E_AND_E 0x08 // Sel +#define HID_KEYBOARD_F_AND_F 0x09 // Sel +#define HID_KEYBOARD_G_AND_G 0x0A // Sel +#define HID_KEYBOARD_H_AND_H 0x0B // Sel +#define HID_KEYBOARD_I_AND_I 0x0C // Sel +#define HID_KEYBOARD_J_AND_J 0x0D // Sel +#define HID_KEYBOARD_K_AND_K 0x0E // Sel +#define HID_KEYBOARD_L_AND_L 0x0F // Sel +#define HID_KEYBOARD_M_AND_M 0x10 // Sel +#define HID_KEYBOARD_N_AND_N 0x11 // Sel +#define HID_KEYBOARD_O_AND_O 0x12 // Sel +#define HID_KEYBOARD_P_AND_P 0x13 // Sel +#define HID_KEYBOARD_Q_AND_Q 0x14 // Sel +#define HID_KEYBOARD_R_AND_R 0x15 // Sel +#define HID_KEYBOARD_S_AND_S 0x16 // Sel +#define HID_KEYBOARD_T_AND_T 0x17 // Sel +#define HID_KEYBOARD_U_AND_U 0x18 // Sel +#define HID_KEYBOARD_V_AND_V 0x19 // Sel +#define HID_KEYBOARD_W_AND_W 0x1A // Sel +#define HID_KEYBOARD_X_AND_X 0x1B // Sel +#define HID_KEYBOARD_Y_AND_Y 0x1C // Sel +#define HID_KEYBOARD_Z_AND_Z 0x1D // Sel +#define HID_KEYBOARD_1_AND_EXCLAMATION_POINT 0x1E // Sel +#define HID_KEYBOARD_2_AND_AT 0x1F // Sel +#define HID_KEYBOARD_3_AND_POUND 0x20 // Sel +#define HID_KEYBOARD_4_AND_DOLLAR 0x21 // Sel +#define HID_KEYBOARD_5_AND_PERCENT 0x22 // Sel +#define HID_KEYBOARD_6_AND_CARAT 0x23 // Sel +#define HID_KEYBOARD_7_AND_AMPERSAND 0x24 // Sel +#define HID_KEYBOARD_8_AND_ASTERISK 0x25 // Sel +#define HID_KEYBOARD_9_AND_LEFT_PAREN 0x26 // Sel +#define HID_KEYBOARD_0_AND_RIGHT_PAREN 0x27 // Sel +#define HID_KEYBOARD_ENTER 0x28 // Sel +//#define HID_KEYBOARD_ENTER HID_KEYBOARD_ENTER_SLASH_RETURN +#define HID_KEYBOARD_ESCAPE 0x29 // Sel +#define HID_KEYBOARD_DELETE 0x2A // Sel +//#define HID_KEYBOARD_BACKSPACE HID_KEYBOARD_DELETE +#define HID_KEYBOARD_TAB 0x2B // Sel +#define HID_KEYBOARD_SPACEBAR 0x2C // Sel +#define HID_KEYBOARD_MINUS_AND_UNDERSCORE 0x2D // Sel +#define HID_KEYBOARD_EQUALS_AND_PLUS 0x2E // Sel +#define HID_KEYBOARD_LEFT_BRACKET_AND_LEFT_CURLY_BRACE 0x2F // Sel +#define HID_KEYBOARD_RIGHT_BRACKET_AND_RIGHT_CURLY_BRACE 0x30 // Sel +#define HID_KEYBOARD_BACKSLASH_AND_PIPE 0x31 // Sel +#define HID_KEYBOARD_NON_US_POUND_AND_TILDE 0x32 // Sel +#define HID_KEYBOARD_SEMICOLON_AND_COLON 0x33 // Sel +#define HID_KEYBOARD_QUOTE_AND_DOUBLEQUOTE 0x34 // Sel +#define HID_KEYBOARD_GRAVE_ACCENT_AND_TILDE 0x35 // Sel +#define HID_KEYBOARD_COMMA_AND_LESS_THAN 0x36 // Sel +#define HID_KEYBOARD_PERIOD_AND_GREATER_THAN 0x37 // Sel +#define HID_KEYBOARD_SLASH_AND_QUESTION_MARK 0x38 // Sel +#define HID_KEYBOARD_CAPS_LOCK 0x39 // Sel +#define HID_KEYBOARD_F1 0x3A // Sel +#define HID_KEYBOARD_F2 0x3B // Sel +#define HID_KEYBOARD_F3 0x3C // Sel +#define HID_KEYBOARD_F4 0x3D // Sel +#define HID_KEYBOARD_F5 0x3E // Sel +#define HID_KEYBOARD_F6 0x3F // Sel +#define HID_KEYBOARD_F7 0x40 // Sel +#define HID_KEYBOARD_F8 0x41 // Sel +#define HID_KEYBOARD_F9 0x42 // Sel +#define HID_KEYBOARD_F10 0x43 // Sel +#define HID_KEYBOARD_F11 0x44 // Sel +#define HID_KEYBOARD_F12 0x45 // Sel +#define HID_KEYBOARD_PRINTSCREEN 0x46 // Sel +#define HID_KEYBOARD_SCROLL_LOCK 0x47 // Sel +#define HID_KEYBOARD_PAUSE 0x48 // Sel +#define HID_KEYBOARD_INSERT 0x49 // Sel +#define HID_KEYBOARD_HOME 0x4A // Sel +#define HID_KEYBOARD_PAGE_UP 0x4B // Sel +#define HID_KEYBOARD_DELETE_FORWARD 0x4C // Sel +#define HID_KEYBOARD_END 0x4D // Sel +#define HID_KEYBOARD_PAGE_DOWN 0x4E // Sel +#define HID_KEYBOARD_RIGHT_ARROW 0x4F // Sel +#define HID_KEYBOARD_LEFT_ARROW 0x50 // Sel +#define HID_KEYBOARD_DOWN_ARROW 0x51 // Sel +#define HID_KEYBOARD_UP_ARROW 0x52 // Sel +#define HID_KEYPAD_NUM_LOCK_AND_CLEAR 0x53 // Sel +#define HID_KEYPAD_DIVIDE 0x54 // Sel +#define HID_KEYPAD_MULTIPLY 0x55 // Sel +#define HID_KEYPAD_SUBTRACT 0x56 // Sel +#define HID_KEYPAD_ADD 0x57 // Sel +#define HID_KEYPAD_ENTER 0x58 // Sel +#define HID_KEYPAD_1_AND_END 0x59 // Sel +#define HID_KEYPAD_2_AND_DOWN_ARROW 0x5A // Sel +#define HID_KEYPAD_3_AND_PAGE_DOWN 0x5B // Sel +#define HID_KEYPAD_4_AND_LEFT_ARROW 0x5C // Sel +#define HID_KEYPAD_5 0x5D // Sel +#define HID_KEYPAD_6_AND_RIGHT_ARROW 0x5E // Sel +#define HID_KEYPAD_7_AND_HOME 0x5F // Sel +#define HID_KEYPAD_8_AND_UP_ARROW 0x60 // Sel +#define HID_KEYPAD_9_AND_PAGE_UP 0x61 // Sel +#define HID_KEYPAD_0_AND_INSERT 0x62 // Sel +#define HID_KEYPAD_PERIOD_AND_DELETE 0x63 // Sel +#define HID_KEYBOARD_NON_US_BACKSLASH_AND_PIPE 0x64 // Sel +#define HID_KEYBOARD_APPLICATION 0x65 // Sel +#define HID_KEYBOARD_POWER 0x66 // Sel +#define HID_KEYPAD_EQUALS 0x67 // Sel +#define HID_KEYBOARD_F13 0x68 // Sel +#define HID_KEYBOARD_F14 0x69 // Sel +#define HID_KEYBOARD_F15 0x6A // Sel +#define HID_KEYBOARD_F16 0x6B // Sel +#define HID_KEYBOARD_F17 0x6C // Sel +#define HID_KEYBOARD_F18 0x6D // Sel +#define HID_KEYBOARD_F19 0x6E // Sel +#define HID_KEYBOARD_F20 0x6F // Sel +#define HID_KEYBOARD_F21 0x70 // Sel +#define HID_KEYBOARD_F22 0x71 // Sel +#define HID_KEYBOARD_F23 0x72 // Sel +#define HID_KEYBOARD_F24 0x73 // Sel +#define HID_KEYBOARD_EXECUTE 0x74 // Sel +#define HID_KEYBOARD_HELP 0x75 // Sel +#define HID_KEYBOARD_MENU 0x76 // Sel +#define HID_KEYBOARD_SELECT 0x77 // Sel +#define HID_KEYBOARD_STOP 0x78 // Sel +#define HID_KEYBOARD_AGAIN 0x79 // Sel +#define HID_KEYBOARD_UNDO 0x7A // Sel +#define HID_KEYBOARD_CUT 0x7B // Sel +#define HID_KEYBOARD_COPY 0x7C // Sel +#define HID_KEYBOARD_PASTE 0x7D // Sel +#define HID_KEYBOARD_FIND 0x7E // Sel +#define HID_KEYBOARD_MUTE 0x7F // Sel +#define HID_KEYBOARD_VOLUME_UP 0x80 // Sel +#define HID_KEYBOARD_VOLUME_DOWN 0x81 // Sel +#define HID_KEYBOARD_LOCKING_CAPS_LOCK 0x82 // Sel +#define HID_KEYBOARD_LOCKING_NUM_LOCK 0x83 // Sel +#define HID_KEYBOARD_LOCKING_SCROLL_LOCK 0x84 // Sel +#define HID_KEYPAD_COMMA 0x85 // Sel +#define HID_KEYPAD_EQUAL_SIGN 0x86 // Sel +#define HID_KEYBOARD_INTERNATIONAL1 0x87 // Sel +#define HID_KEYBOARD_INTERNATIONAL2 0x88 // Sel +#define HID_KEYBOARD_INTERNATIONAL3 0x89 // Sel +#define HID_KEYBOARD_INTERNATIONAL4 0x8A // Sel +#define HID_KEYBOARD_INTERNATIONAL5 0x8B // Sel +#define HID_KEYBOARD_INTERNATIONAL6 0x8C // Sel +#define HID_KEYBOARD_INTERNATIONAL7 0x8D // Sel +#define HID_KEYBOARD_INTERNATIONAL8 0x8E // Sel +#define HID_KEYBOARD_INTERNATIONAL9 0x8F // Sel +#define HID_KEYBOARD_LANG1 0x90 // Sel +#define HID_KEYBOARD_LANG2 0x91 // Sel +#define HID_KEYBOARD_LANG3 0x92 // Sel +#define HID_KEYBOARD_LANG4 0x93 // Sel +#define HID_KEYBOARD_LANG5 0x94 // Sel +#define HID_KEYBOARD_LANG6 0x95 // Sel +#define HID_KEYBOARD_LANG7 0x96 // Sel +#define HID_KEYBOARD_LANG8 0x97 // Sel +#define HID_KEYBOARD_LANG9 0x98 // Sel +#define HID_KEYBOARD_ALTERNATE_ERASE 0x99 // Sel +#define HID_KEYBOARD_SYSREQ_SLASH_ATTENTION 0x9A // Sel +#define HID_KEYBOARD_CANCEL 0x9B // Sel +#define HID_KEYBOARD_CLEAR 0x9C // Sel +#define HID_KEYBOARD_PRIOR 0x9D // Sel +#define HID_KEYBOARD_RETURN 0x9E // Sel +#define HID_KEYBOARD_SEPARATOR 0x9F // Sel +#define HID_KEYBOARD_OUT 0xA0 // Sel +#define HID_KEYBOARD_OPER 0xA1 // Sel +#define HID_KEYBOARD_CLEAR_SLASH_AGAIN 0xA2 // Sel +#define HID_KEYBOARD_CRSEL_SLASH_PROPS 0xA3 // Sel +#define HID_KEYBOARD_EXSEL 0xA4 // Sel +// Reserved 0xA5-AF +#define HID_KEYPAD_00 0xB0 // Sel +#define HID_KEYPAD_000 0xB1 // Sel +#define HID_THOUSANDS_SEPARATOR 0xB2 // Sel +#define HID_DECIMAL_SEPARATOR 0xB3 // Sel +#define HID_CURRENCY_UNIT 0xB4 // Sel +#define HID_CURRENCY_SUBUNIT 0xB5 // Sel +#define HID_KEYPAD_LEFT_PAREN 0xB6 // Sel +#define HID_KEYPAD_RIGHT_PAREN 0xB7 // Sel +#define HID_KEYPAD_LEFT_CURLY_BRACE 0xB8 // Sel +#define HID_KEYPAD_RIGHT_CURLY_BRACE 0xB9 // Sel +#define HID_KEYPAD_TAB 0xBA // Sel +#define HID_KEYPAD_BACKSPACE 0xBB // Sel +#define HID_KEYPAD_A 0xBC // Sel +#define HID_KEYPAD_B 0xBD // Sel +#define HID_KEYPAD_C 0xBE // Sel +#define HID_KEYPAD_D 0xBF // Sel +#define HID_KEYPAD_E 0xC0 // Sel +#define HID_KEYPAD_F 0xC1 // Sel +#define HID_KEYPAD_XOR 0xC2 // Sel +#define HID_KEYPAD_CARAT 0xC3 // Sel +#define HID_KEYPAD_PERCENT 0xC4 // Sel +#define HID_KEYPAD_LESS_THAN 0xC5 // Sel +#define HID_KEYPAD_GREATER_THAN 0xC6 // Sel +#define HID_KEYPAD_AMPERSAND 0xC7 // Sel +#define HID_KEYPAD_DOUBLEAMPERSAND 0xC8 // Sel +#define HID_KEYPAD_PIPE 0xC9 // Sel +#define HID_KEYPAD_DOUBLEPIPE 0xCA // Sel +#define HID_KEYPAD_COLON 0xCB // Sel +#define HID_KEYPAD_POUND_SIGN 0xCC // Sel +#define HID_KEYPAD_SPACE 0xCD // Sel +#define HID_KEYPAD_AT_SIGN 0xCE // Sel +#define HID_KEYPAD_EXCLAMATION_POINT 0xCF // Sel +#define HID_KEYPAD_MEMORY_STORE 0xD0 // Sel +#define HID_KEYPAD_MEMORY_RECALL 0xD1 // Sel +#define HID_KEYPAD_MEMORY_CLEAR 0xD2 // Sel +#define HID_KEYPAD_MEMORY_ADD 0xD3 // Sel +#define HID_KEYPAD_MEMORY_SUBTRACT 0xD4 // Sel +#define HID_KEYPAD_MEMORY_MULTIPLY 0xD5 // Sel +#define HID_KEYPAD_MEMORY_DIVIDE 0xD6 // Sel +#define HID_KEYPAD_PLUS_SLASH_MINUS 0xD7 // Sel +#define HID_KEYPAD_CLEAR 0xD8 // Sel +#define HID_KEYPAD_CLEAR_ENTRY 0xD9 // Sel +#define HID_KEYPAD_BINARY 0xDA // Sel +#define HID_KEYPAD_OCTAL 0xDB // Sel +#define HID_KEYPAD_DECIMAL 0xDC // Sel +#define HID_KEYPAD_HEXADECIMAL 0xDD // Sel +// Reserved 0xDE-DF +#define HID_KEYBOARD_LEFT_CONTROL 0xE0 // DV +#define HID_KEYBOARD_LEFT_SHIFT 0xE1 // DV +#define HID_KEYBOARD_LEFT_ALT 0xE2 // DV +#define HID_KEYBOARD_LEFT_GUI 0xE3 // DV +#define HID_KEYBOARD_RIGHT_CONTROL 0xE4 // DV +#define HID_KEYBOARD_RIGHT_SHIFT 0xE5 // DV +#define HID_KEYBOARD_RIGHT_ALT 0xE6 // DV +#define HID_KEYBOARD_RIGHT_GUI 0xE7 // DV +// Reserved 0xE8-FFFF -// Consumer_Page_(0x0C) 0x15 -#define HID_CONSUMER_NUMERIC_KEY_PAD 0x02 // HID type NARY -#define HID_CONSUMER_PROGRAMMABLE_BUTTONS 0x03 // HID type NARY -#define HID_CONSUMER_MICROPHONE_CA 0x04 -#define HID_CONSUMER_HEADPHONE_CA 0x05 -#define HID_CONSUMER_GRAPHIC_EQUALIZER_CA 0x06 -// Reserved 0x07-1F -#define HID_CONSUMER_PLUS_10 0x20 // HID type OSC -#define HID_CONSUMER_PLUS_100 0x21 // HID type OSC -#define HID_CONSUMER_AM_SLASH_PM 0x22 // HID type OSC -// Reserved 0x23-3F -#define HID_CONSUMER_POWER 0x30 // HID type OOC -#define HID_CONSUMER_RESET 0x31 // HID type OSC -#define HID_CONSUMER_SLEEP 0x32 // HID type OSC -#define HID_CONSUMER_SLEEP_AFTER 0x33 // HID type OSC -#define HID_CONSUMER_SLEEP_MODE 0x34 // HID type RTC -#define HID_CONSUMER_ILLUMINATION 0x35 // HID type OOC -#define HID_CONSUMER_FUNCTION_BUTTONS 0x36 // HID type NARY -// Reserved 0x37-3F -#define HID_CONSUMER_MENU 0x40 // HID type OOC -#define HID_CONSUMER_MENU_PICK 0x41 // HID type OSC -#define HID_CONSUMER_MENU_UP 0x42 // HID type OSC -#define HID_CONSUMER_MENU_DOWN 0x43 // HID type OSC -#define HID_CONSUMER_MENU_LEFT 0x44 // HID type OSC -#define HID_CONSUMER_MENU_RIGHT 0x45 // HID type OSC -#define HID_CONSUMER_MENU_ESCAPE 0x46 // HID type OSC -#define HID_CONSUMER_MENU_VALUE_INCREASE 0x47 // HID type OSC -#define HID_CONSUMER_MENU_VALUE_DECREASE 0x48 // HID type OSC -// Reserved 0x49-5F -#define HID_CONSUMER_DATA_ON_SCREEN 0x60 // HID type OOC -#define HID_CONSUMER_CLOSED_CAPTION 0x61 // HID type OOC -#define HID_CONSUMER_CLOSED_CAPTION_SELECT 0x62 // HID type OSC -#define HID_CONSUMER_VCR_SLASH_TV 0x63 // HID type OOC -#define HID_CONSUMER_BROADCAST_MODE 0x64 // HID type OSC -#define HID_CONSUMER_SNAPSHOT 0x65 // HID type OSC -#define HID_CONSUMER_STILL 0x66 // HID type OSC -// Reserved 0x67-7F -#define HID_CONSUMER_SELECTION 0x80 // HID type NARY -#define HID_CONSUMER_ASSIGN_SELECTION 0x81 // HID type OSC -#define HID_CONSUMER_MODE_STEP 0x82 // HID type OSC -#define HID_CONSUMER_RECALL_LAST 0x83 // HID type OSC -#define HID_CONSUMER_ENTER_CHANNEL 0x84 // HID type OSC -#define HID_CONSUMER_ORDER_MOVIE 0x85 // HID type OSC -#define HID_CONSUMER_CHANNEL 0x86 // HID type LC -#define HID_CONSUMER_MEDIA_SELECTION 0x87 // HID type NARY -#define HID_CONSUMER_MEDIA_SELECT_COMPUTER 0x88 // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_TV 0x89 // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_WWW 0x8A // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_DVD 0x8B // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_TELEPHONE 0x8C // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_PROGRAM_GUIDE 0x8D // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_VIDEO_PHONE 0x8E // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_GAMES 0x8F // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_MESSAGES 0x90 // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_CD 0x91 // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_VCR 0x92 // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_TUNER 0x93 // HID type SEL -#define HID_CONSUMER_QUIT 0x94 // HID type OSC -#define HID_CONSUMER_HELP 0x95 // HID type OOC -#define HID_CONSUMER_MEDIA_SELECT_TAPE 0x96 // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_CABLE 0x97 // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_SATELLITE 0x98 // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_SECURITY 0x99 // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_HOME 0x9A // HID type SEL -#define HID_CONSUMER_MEDIA_SELECT_CALL 0x9B // HID type SEL -#define HID_CONSUMER_CHANNEL_INCREMENT 0x9C // HID type OSC -#define HID_CONSUMER_CHANNEL_DECREMENT 0x9D // HID type OSC -#define HID_CONSUMER_MEDIA_SELECT_SAP 0x9E // HID type SEL -// Reserved 0x9F -#define HID_CONSUMER_VCR_PLUS 0xA0 // HID type OSC -#define HID_CONSUMER_ONCE 0xA1 // HID type OSC -#define HID_CONSUMER_DAILY 0xA2 // HID type OSC -#define HID_CONSUMER_WEEKLY 0xA3 // HID type OSC -#define HID_CONSUMER_MONTHLY 0xA4 // HID type OSC -// Reserved 0xA5-AF -#define HID_CONSUMER_PLAY 0xB0 // HID type OOC -#define HID_CONSUMER_PAUSE 0xB1 // HID type OOC -#define HID_CONSUMER_RECORD 0xB2 // HID type OOC -#define HID_CONSUMER_FAST_FORWARD 0xB3 // HID type OOC -#define HID_CONSUMER_REWIND 0xB4 // HID type OOC -#define HID_CONSUMER_SCAN_NEXT_TRACK 0xB5 // HID type OSC -#define HID_CONSUMER_SCAN_PREVIOUS_TRACK 0xB6 // HID type OSC -#define HID_CONSUMER_STOP 0xB7 // HID type OSC -#define HID_CONSUMER_EJECT 0xB8 // HID type OSC -#define HID_CONSUMER_RANDOM_PLAY 0xB9 // HID type OOC -#define HID_CONSUMER_SELECT_DISC 0xBA // HID type NARY -#define HID_CONSUMER_ENTER_DISC_MC 0xBB -#define HID_CONSUMER_REPEAT 0xBC // HID type OSC -#define HID_CONSUMER_TRACKING 0xBD // HID type LC -#define HID_CONSUMER_TRACK_NORMAL 0xBE // HID type OSC -#define HID_CONSUMER_SLOW_TRACKING 0xBF // HID type LC -#define HID_CONSUMER_FRAME_FORWARD 0xC0 // HID type RTC -#define HID_CONSUMER_FRAME_BACK 0xC1 // HID type RTC -#define HID_CONSUMER_MARK 0xC2 // HID type OSC -#define HID_CONSUMER_CLEAR_MARK 0xC3 // HID type OSC -#define HID_CONSUMER_REPEAT_FROM_MARK 0xC4 // HID type OOC -#define HID_CONSUMER_RETURN_TO_MARK 0xC5 // HID type OSC -#define HID_CONSUMER_SEARCH_MARK_FORWARD 0xC6 // HID type OSC -#define HID_CONSUMER_SEARCH_MARK_BACKWARDS 0xC7 // HID type OSC -#define HID_CONSUMER_COUNTER_RESET 0xC8 // HID type OSC -#define HID_CONSUMER_SHOW_COUNTER 0xC9 // HID type OSC -#define HID_CONSUMER_TRACKING_INCREMENT 0xCA // HID type RTC -#define HID_CONSUMER_TRACKING_DECREMENT 0xCB // HID type RTC -#define HID_CONSUMER_STOP_SLASH_EJECT 0xCC // HID type OSC -#define HID_CONSUMER_PLAY_SLASH_PAUSE 0xCD // HID type OSC -#define HID_CONSUMER_PLAY_SLASH_SKIP 0xCE // HID type OSC -// Reserved 0xCF-DF -#define HID_CONSUMER_VOLUME 0xE0 // HID type LC -#define HID_CONSUMER_BALANCE 0xE1 // HID type LC -#define HID_CONSUMER_MUTE 0xE2 // HID type OOC -#define HID_CONSUMER_BASS 0xE3 // HID type LC -#define HID_CONSUMER_TREBLE 0xE4 // HID type LC -#define HID_CONSUMER_BASS_BOOST 0xE5 // HID type OOC -#define HID_CONSUMER_SURROUND_MODE 0xE6 // HID type OSC -#define HID_CONSUMER_LOUDNESS 0xE7 // HID type OOC -#define HID_CONSUMER_MPX 0xE8 // HID type OOC -#define HID_CONSUMER_VOLUME_INCREMENT 0xE9 // HID type RTC -#define HID_CONSUMER_VOLUME_DECREMENT 0xEA // HID type RTC -// Reserved 0xEB-EF -#define HID_CONSUMER_SPEED_SELECT 0xF0 // HID type OSC -#define HID_CONSUMER_PLAYBACK_SPEED 0xF1 // HID type NARY -#define HID_CONSUMER_STANDARD_PLAY 0xF2 // HID type SEL -#define HID_CONSUMER_LONG_PLAY 0xF3 // HID type SEL -#define HID_CONSUMER_EXTENDED_PLAY 0xF4 // HID type SEL -#define HID_CONSUMER_SLOW 0xF5 // HID type OSC -// Reserved 0xF6-FF -#define HID_CONSUMER_FAN_ENABLE 0x100 // HID type OOC -#define HID_CONSUMER_FAN_SPEED 0x101 // HID type LC -#define HID_CONSUMER_LIGHT_ENABLE 0x102 // HID type OOC -#define HID_CONSUMER_LIGHT_ILLUMINATION_LEVEL 0x103 // HID type LC -#define HID_CONSUMER_CLIMATE_CONTROL_ENABLE 0x104 // HID type OOC -#define HID_CONSUMER_ROOM_TEMPERATURE 0x105 // HID type LC -#define HID_CONSUMER_SECURITY_ENABLE 0x106 // HID type OOC -#define HID_CONSUMER_FIRE_ALARM 0x107 // HID type OSC -#define HID_CONSUMER_POLICE_ALARM 0x108 // HID type OSC -#define HID_CONSUMER_PROXIMITY 0x109 // HID type LC -#define HID_CONSUMER_MOTION 0x10A // HID type OSC -#define HID_CONSUMER_DURESS_ALARM 0x10B // HID type OSC -#define HID_CONSUMER_HOLDUP_ALARM 0x10C // HID type OSC -#define HID_CONSUMER_MEDICAL_ALARM 0x10D // HID type OSC -// Reserved 0x10E-14F -#define HID_CONSUMER_BALANCE_RIGHT 0x150 // HID type RTC -#define HID_CONSUMER_BALANCE_LEFT 0x151 // HID type RTC -#define HID_CONSUMER_BASS_INCREMENT 0x152 // HID type RTC -#define HID_CONSUMER_BASS_DECREMENT 0x153 // HID type RTC -#define HID_CONSUMER_TREBLE_INCREMENT 0x154 // HID type RTC -#define HID_CONSUMER_TREBLE_DECREMENT 0x155 // HID type RTC -// Reserved 0x156-15F -#define HID_CONSUMER_SPEAKER_SYSTEM 0x160 // HID type CL -#define HID_CONSUMER_CHANNEL_LEFT 0x161 // HID type CL -#define HID_CONSUMER_CHANNEL_RIGHT 0x162 // HID type CL -#define HID_CONSUMER_CHANNEL_CENTER 0x163 // HID type CL -#define HID_CONSUMER_CHANNEL_FRONT 0x164 // HID type CL -#define HID_CONSUMER_CHANNEL_CENTER_FRONT 0x165 // HID type CL -#define HID_CONSUMER_CHANNEL_SIDE 0x166 // HID type CL -#define HID_CONSUMER_CHANNEL_SURROUND 0x167 // HID type CL -#define HID_CONSUMER_CHANNEL_LOW_FREQUENCY_ENHANCEMENT 0x168 // HID type CL -#define HID_CONSUMER_CHANNEL_TOP 0x169 // HID type CL -#define HID_CONSUMER_CHANNEL_UNKNOWN 0x16A // HID type CL -// Reserved 0x16B-16F -#define HID_CONSUMER_SUB_CHANNEL 0x170 // HID type LC -#define HID_CONSUMER_SUB_CHANNEL_INCREMENT 0x171 // HID type OSC -#define HID_CONSUMER_SUB_CHANNEL_DECREMENT 0x172 // HID type OSC -#define HID_CONSUMER_ALTERNATE_AUDIO_INCREMENT 0x173 // HID type OSC -#define HID_CONSUMER_ALTERNATE_AUDIO_DECREMENT 0x174 // HID type OSC -// Reserved 0x175-17F -#define HID_CONSUMER_APPLICATION_LAUNCH_BUTTONS 0x180 // HID type NARY -#define HID_CONSUMER_AL_LAUNCH_BUTTON_CONFIGURATION_TOOL 0x181 // HID type SEL -#define HID_CONSUMER_AL_PROGRAMMABLE_BUTTON_CONFIGURATION 0x182 // HID type SEL -#define HID_CONSUMER_AL_CONSUMER_CONTROL_CONFIGURATION 0x183 // HID type SEL -#define HID_CONSUMER_AL_WORD_PROCESSOR 0x184 // HID type SEL -#define HID_CONSUMER_AL_TEXT_EDITOR 0x185 // HID type SEL -#define HID_CONSUMER_AL_SPREADSHEET 0x186 // HID type SEL -#define HID_CONSUMER_AL_GRAPHICS_EDITOR 0x187 // HID type SEL -#define HID_CONSUMER_AL_PRESENTATION_APP 0x188 // HID type SEL -#define HID_CONSUMER_AL_DATABASE_APP 0x189 // HID type SEL -#define HID_CONSUMER_AL_EMAIL_READER 0x18A // HID type SEL -#define HID_CONSUMER_AL_NEWSREADER 0x18B // HID type SEL -#define HID_CONSUMER_AL_VOICEMAIL 0x18C // HID type SEL -#define HID_CONSUMER_AL_CONTACTS_SLASH_ADDRESS_BOOK 0x18D // HID type SEL -#define HID_CONSUMER_AL_CALENDAR_SLASH_SCHEDULE 0x18E // HID type SEL -#define HID_CONSUMER_AL_TASK_SLASH_PROJECT_MANAGER 0x18F // HID type SEL -#define HID_CONSUMER_AL_LOG_SLASH_JOURNAL_SLASH_TIMECARD 0x190 // HID type SEL -#define HID_CONSUMER_AL_CHECKBOOK_SLASH_FINANCE 0x191 // HID type SEL -#define HID_CONSUMER_AL_CALCULATOR 0x192 // HID type SEL -#define HID_CONSUMER_AL_A_SLASH_V_CAPTURE_SLASH_PLAYBACK 0x193 // HID type SEL -#define HID_CONSUMER_AL_LOCAL_MACHINE_BROWSER 0x194 // HID type SEL -#define HID_CONSUMER_AL_LAN_SLASH_WAN_BROWSER 0x195 // HID type SEL -#define HID_CONSUMER_AL_INTERNET_BROWSER 0x196 // HID type SEL -#define HID_CONSUMER_AL_REMOTE_NETWORKING_SLASH_ISP_CONNECT 0x197 // HID type SEL -#define HID_CONSUMER_AL_NETWORK_CONFERENCE 0x198 // HID type SEL -#define HID_CONSUMER_AL_NETWORK_CHAT 0x199 // HID type SEL -#define HID_CONSUMER_AL_TELEPHONY_SLASH_DIALER 0x19A // HID type SEL -#define HID_CONSUMER_AL_LOGON 0x19B // HID type SEL -#define HID_CONSUMER_AL_LOGOFF 0x19C // HID type SEL -#define HID_CONSUMER_AL_LOGON_SLASH_LOGOFF 0x19D // HID type SEL -#define HID_CONSUMER_AL_TERMINAL_LOCK_SLASH_SCREENSAVER 0x19E // HID type SEL -#define HID_CONSUMER_AL_CONTROL_PANEL 0x19F // HID type SEL -#define HID_CONSUMER_AL_COMMAND_LINE_PROCESSOR_SLASH_RUN 0x1A0 // HID type SEL -#define HID_CONSUMER_AL_PROCESS_SLASH_TASK_MANAGER 0x1A1 // HID type SEL -#define HID_CONSUMER_AL_SELECT_TASK_SLASH_APPLICATION 0x1A2 // HID type SEL -#define HID_CONSUMER_AL_NEXT_TASK_SLASH_APPLICATION 0x1A3 // HID type SEL -#define HID_CONSUMER_AL_PREVIOUS_TASK_SLASH_APPLICATION 0x1A4 // HID type SEL -#define HID_CONSUMER_AL_PREEMPTIVE_HALT_TASK_SLASH_APPLICATION 0x1A5 // HID type SEL -#define HID_CONSUMER_AL_INTEGRATED_HELP_CENTER 0x1A6 // HID type SEL -#define HID_CONSUMER_AL_DOCUMENTS 0x1A7 // HID type SEL -#define HID_CONSUMER_AL_THESAURUS 0x1A8 // HID type SEL -#define HID_CONSUMER_AL_DICTIONARY 0x1A9 // HID type SEL -#define HID_CONSUMER_AL_DESKTOP 0x1AA // HID type SEL -#define HID_CONSUMER_AL_SPELL_CHECK 0x1AB // HID type SEL -#define HID_CONSUMER_AL_GRAMMAR_CHECK 0x1AC // HID type SEL -#define HID_CONSUMER_AL_WIRELESS_STATUS 0x1AD // HID type SEL -#define HID_CONSUMER_AL_KEYBOARD_LAYOUT 0x1AE // HID type SEL -#define HID_CONSUMER_AL_VIRUS_PROTECTION 0x1AF // HID type SEL -#define HID_CONSUMER_AL_ENCRYPTION 0x1B0 // HID type SEL -#define HID_CONSUMER_AL_SCREEN_SAVER 0x1B1 // HID type SEL -#define HID_CONSUMER_AL_ALARMS 0x1B2 // HID type SEL -#define HID_CONSUMER_AL_CLOCK 0x1B3 // HID type SEL -#define HID_CONSUMER_AL_FILE_BROWSER 0x1B4 // HID type SEL -#define HID_CONSUMER_AL_POWER_STATUS 0x1B5 // HID type SEL -#define HID_CONSUMER_AL_IMAGE_BROWSER 0x1B6 // HID type SEL -#define HID_CONSUMER_AL_AUDIO_BROWSER 0x1B7 // HID type SEL -#define HID_CONSUMER_AL_MOVIE_BROWSER 0x1B8 // HID type SEL -#define HID_CONSUMER_AL_DIGITAL_RIGHTS_MANAGER 0x1B9 // HID type SEL -#define HID_CONSUMER_AL_DIGITAL_WALLET 0x1BA // HID type SEL -// _Reserved 0x1BB -#define HID_CONSUMER_AL_INSTANT_MESSAGING 0x1BC // HID type SEL -#define HID_CONSUMER_AL_OEM_FEATURES_SLASH__TIPS_SLASH_TUTORIAL_BROWSER 0x1BD // HID type SEL -#define HID_CONSUMER_AL_OEM_HELP 0x1BE // HID type SEL -#define HID_CONSUMER_AL_ONLINE_COMMUNITY 0x1BF // HID type SEL -#define HID_CONSUMER_AL_ENTERTAINMENT_CONTENT_BROWSER 0x1C0 // HID type SEL -#define HID_CONSUMER_AL_ONLINE_SHOPPING_BROWSER 0x1C1 // HID type SEL -#define HID_CONSUMER_AL_SMARTCARD_INFORMATION_SLASH_HELP 0x1C2 // HID type SEL -#define HID_CONSUMER_AL_MARKET_MONITOR_SLASH_FINANCE_BROWSER 0x1C3 // HID type SEL -#define HID_CONSUMER_AL_CUSTOMIZED_CORPORATE_NEWS_BROWSER 0x1C4 // HID type SEL -#define HID_CONSUMER_AL_ONLINE_ACTIVITY_BROWSER 0x1C5 // HID type SEL -#define HID_CONSUMER_AL_RESEARCH_SLASH_SEARCH_BROWSER 0x1C6 // HID type SEL -#define HID_CONSUMER_AL_AUDIO_PLAYER 0x1C7 // HID type SEL -// Reserved 0x1C8-1FF -#define HID_CONSUMER_GENERIC_GUI_APPLICATION_CONTROLS 0x200 // HID type NARY -#define HID_CONSUMER_AC_NEW 0x201 // HID type SEL -#define HID_CONSUMER_AC_OPEN 0x202 // HID type SEL -#define HID_CONSUMER_AC_CLOSE 0x203 // HID type SEL -#define HID_CONSUMER_AC_EXIT 0x204 // HID type SEL -#define HID_CONSUMER_AC_MAXIMIZE 0x205 // HID type SEL -#define HID_CONSUMER_AC_MINIMIZE 0x206 // HID type SEL -#define HID_CONSUMER_AC_SAVE 0x207 // HID type SEL -#define HID_CONSUMER_AC_PRINT 0x208 // HID type SEL -#define HID_CONSUMER_AC_PROPERTIES 0x209 // HID type SEL -#define HID_CONSUMER_AC_UNDO 0x21A // HID type SEL -#define HID_CONSUMER_AC_COPY 0x21B // HID type SEL -#define HID_CONSUMER_AC_CUT 0x21C // HID type SEL -#define HID_CONSUMER_AC_PASTE 0x21D // HID type SEL -#define HID_CONSUMER_AC_SELECT_ALL 0x21E // HID type SEL -#define HID_CONSUMER_AC_FIND 0x21F // HID type SEL -#define HID_CONSUMER_AC_FIND_AND_REPLACE 0x220 // HID type SEL -#define HID_CONSUMER_AC_SEARCH 0x221 // HID type SEL -#define HID_CONSUMER_AC_GO_TO 0x222 // HID type SEL -#define HID_CONSUMER_AC_HOME 0x223 // HID type SEL -#define HID_CONSUMER_AC_BACK 0x224 // HID type SEL -#define HID_CONSUMER_AC_FORWARD 0x225 // HID type SEL -#define HID_CONSUMER_AC_STOP 0x226 // HID type SEL -#define HID_CONSUMER_AC_REFRESH 0x227 // HID type SEL -#define HID_CONSUMER_AC_PREVIOUS_LINK 0x228 // HID type SEL -#define HID_CONSUMER_AC_NEXT_LINK 0x229 // HID type SEL -#define HID_CONSUMER_AC_BOOKMARKS 0x22A // HID type SEL -#define HID_CONSUMER_AC_HISTORY 0x22B // HID type SEL -#define HID_CONSUMER_AC_SUBSCRIPTIONS 0x22C // HID type SEL -#define HID_CONSUMER_AC_ZOOM_IN 0x22D // HID type SEL -#define HID_CONSUMER_AC_ZOOM_OUT 0x22E // HID type SEL -#define HID_CONSUMER_AC_ZOOM 0x22F // HID type LC -#define HID_CONSUMER_AC_FULL_SCREEN_VIEW 0x230 // HID type SEL -#define HID_CONSUMER_AC_NORMAL_VIEW 0x231 // HID type SEL -#define HID_CONSUMER_AC_VIEW_TOGGLE 0x232 // HID type SEL -#define HID_CONSUMER_AC_SCROLL_UP 0x233 // HID type SEL -#define HID_CONSUMER_AC_SCROLL_DOWN 0x234 // HID type SEL -#define HID_CONSUMER_AC_SCROLL 0x235 // HID type LC -#define HID_CONSUMER_AC_PAN_LEFT 0x236 // HID type SEL -#define HID_CONSUMER_AC_PAN_RIGHT 0x237 // HID type SEL -#define HID_CONSUMER_AC_PAN 0x238 // HID type LC -#define HID_CONSUMER_AC_NEW_WINDOW 0x239 // HID type SEL -#define HID_CONSUMER_AC_TILE_HORIZONTALLY 0x23A // HID type SEL -#define HID_CONSUMER_AC_TILE_VERTICALLY 0x23B // HID type SEL -#define HID_CONSUMER_AC_FORMAT 0x23C // HID type SEL -#define HID_CONSUMER_AC_EDIT 0x23D // HID type SEL -#define HID_CONSUMER_AC_BOLD 0x23E // HID type SEL -#define HID_CONSUMER_AC_ITALICS 0x23F // HID type SEL -#define HID_CONSUMER_AC_UNDERLINE 0x240 // HID type SEL -#define HID_CONSUMER_AC_STRIKETHROUGH 0x241 // HID type SEL -#define HID_CONSUMER_AC_SUBSCRIPT 0x242 // HID type SEL -#define HID_CONSUMER_AC_SUPERSCRIPT 0x243 // HID type SEL -#define HID_CONSUMER_AC_ALL_CAPS 0x244 // HID type SEL -#define HID_CONSUMER_AC_ROTATE 0x245 // HID type SEL -#define HID_CONSUMER_AC_RESIZE 0x246 // HID type SEL -#define HID_CONSUMER_AC_FLIP_HORIZONTAL 0x247 // HID type SEL -#define HID_CONSUMER_AC_FLIP_VERTICAL 0x248 // HID type SEL -#define HID_CONSUMER_AC_MIRROR_HORIZONTAL 0x249 // HID type SEL -#define HID_CONSUMER_AC_MIRROR_VERTICAL 0x24A // HID type SEL -#define HID_CONSUMER_AC_FONT_SELECT 0x24B // HID type SEL -#define HID_CONSUMER_AC_FONT_COLOR 0x24C // HID type SEL -#define HID_CONSUMER_AC_FONT_SIZE 0x24D // HID type SEL -#define HID_CONSUMER_AC_JUSTIFY_LEFT 0x24E // HID type SEL -#define HID_CONSUMER_AC_JUSTIFY_CENTER_H 0x24F // HID type SEL -#define HID_CONSUMER_AC_JUSTIFY_RIGHT 0x250 // HID type SEL -#define HID_CONSUMER_AC_JUSTIFY_BLOCK_H 0x251 // HID type SEL -#define HID_CONSUMER_AC_JUSTIFY_TOP 0x252 // HID type SEL -#define HID_CONSUMER_AC_JUSTIFY_CENTER_V 0x253 // HID type SEL -#define HID_CONSUMER_AC_JUSTIFY_BOTTOM 0x254 // HID type SEL -#define HID_CONSUMER_AC_JUSTIFY_BLOCK_V 0x255 // HID type SEL -#define HID_CONSUMER_AC_INDENT_DECREASE 0x256 // HID type SEL -#define HID_CONSUMER_AC_INDENT_INCREASE 0x257 // HID type SEL -#define HID_CONSUMER_AC_NUMBERED_LIST 0x258 // HID type SEL -#define HID_CONSUMER_AC_RESTART_NUMBERING 0x259 // HID type SEL -#define HID_CONSUMER_AC_BULLETED_LIST 0x25A // HID type SEL -#define HID_CONSUMER_AC_PROMOTE 0x25B // HID type SEL -#define HID_CONSUMER_AC_DEMOTE 0x25C // HID type SEL -#define HID_CONSUMER_AC_YES 0x25D // HID type SEL -#define HID_CONSUMER_AC_NO 0x25E // HID type SEL -#define HID_CONSUMER_AC_CANCEL 0x25F // HID type SEL -#define HID_CONSUMER_AC_CATALOG 0x260 // HID type SEL -#define HID_CONSUMER_AC_BUY_SLASH_CHECKOUT 0x261 // HID type SEL -#define HID_CONSUMER_AC_ADD_TO_CART 0x262 // HID type SEL -#define HID_CONSUMER_AC_EXPAND 0x263 // HID type SEL -#define HID_CONSUMER_AC_EXPAND_ALL 0x264 // HID type SEL -#define HID_CONSUMER_AC_COLLAPSE 0x265 // HID type SEL -#define HID_CONSUMER_AC_COLLAPSE_ALL 0x266 // HID type SEL -#define HID_CONSUMER_AC_PRINT_PREVIEW 0x267 // HID type SEL -#define HID_CONSUMER_AC_PASTE_SPECIAL 0x268 // HID type SEL -#define HID_CONSUMER_AC_INSERT_MODE 0x269 // HID type SEL -#define HID_CONSUMER_AC_DELETE 0x26A // HID type SEL -#define HID_CONSUMER_AC_LOCK 0x26B // HID type SEL -#define HID_CONSUMER_AC_UNLOCK 0x26C // HID type SEL -#define HID_CONSUMER_AC_PROTECT 0x26D // HID type SEL -#define HID_CONSUMER_AC_UNPROTECT 0x26E // HID type SEL -#define HID_CONSUMER_AC_ATTACH_COMMENT 0x26F // HID type SEL -#define HID_CONSUMER_AC_DELETE_COMMENT 0x270 // HID type SEL -#define HID_CONSUMER_AC_VIEW_COMMENT 0x271 // HID type SEL -#define HID_CONSUMER_AC_SELECT_WORD 0x272 // HID type SEL -#define HID_CONSUMER_AC_SELECT_SENTENCE 0x273 // HID type SEL -#define HID_CONSUMER_AC_SELECT_PARAGRAPH 0x274 // HID type SEL -#define HID_CONSUMER_AC_SELECT_COLUMN 0x275 // HID type SEL -#define HID_CONSUMER_AC_SELECT_ROW 0x276 // HID type SEL -#define HID_CONSUMER_AC_SELECT_TABLE 0x277 // HID type SEL -#define HID_CONSUMER_AC_SELECT_OBJECT 0x278 // HID type SEL -#define HID_CONSUMER_AC_REDO_SLASH_REPEAT 0x279 // HID type SEL -#define HID_CONSUMER_AC_SORT 0x27A // HID type SEL -#define HID_CONSUMER_AC_SORT_ASCENDING 0x27B // HID type SEL -#define HID_CONSUMER_AC_SORT_DESCENDING 0x27C // HID type SEL -#define HID_CONSUMER_AC_FILTER 0x27D // HID type SEL -#define HID_CONSUMER_AC_SET_CLOCK 0x27E // HID type SEL -#define HID_CONSUMER_AC_VIEW_CLOCK 0x27F // HID type SEL -#define HID_CONSUMER_AC_SELECT_TIME_ZONE 0x280 // HID type SEL -#define HID_CONSUMER_AC_EDIT_TIME_ZONES 0x281 // HID type SEL -#define HID_CONSUMER_AC_SET_ALARM 0x282 // HID type SEL -#define HID_CONSUMER_AC_CLEAR_ALARM 0x283 // HID type SEL -#define HID_CONSUMER_AC_SNOOZE_ALARM 0x284 // HID type SEL -#define HID_CONSUMER_AC_RESET_ALARM 0x285 // HID type SEL -#define HID_CONSUMER_AC_SYNCHRONIZE 0x286 // HID type SEL -#define HID_CONSUMER_AC_SEND_SLASH_RECEIVE 0x287 // HID type SEL -#define HID_CONSUMER_AC_SEND_TO 0x288 // HID type SEL -#define HID_CONSUMER_AC_REPLY 0x289 // HID type SEL -#define HID_CONSUMER_AC_REPLY_ALL 0x28A // HID type SEL -#define HID_CONSUMER_AC_FORWARD_MSG 0x28B // HID type SEL -#define HID_CONSUMER_AC_SEND 0x28C // HID type SEL -#define HID_CONSUMER_AC_ATTACH_FILE 0x28D // HID type SEL -#define HID_CONSUMER_AC_UPLOAD 0x28E // HID type SEL -#define HID_CONSUMER_AC_DOWNLOAD_(SAVE_TARGET_AS) 0x28F // HID type SEL -#define HID_CONSUMER_AC_SET_BORDERS 0x290 // HID type SEL -#define HID_CONSUMER_AC_INSERT_ROW 0x291 // HID type SEL -#define HID_CONSUMER_AC_INSERT_COLUMN 0x292 // HID type SEL -#define HID_CONSUMER_AC_INSERT_FILE 0x293 // HID type SEL -#define HID_CONSUMER_AC_INSERT_PICTURE 0x294 // HID type SEL -#define HID_CONSUMER_AC_INSERT_OBJECT 0x295 // HID type SEL -#define HID_CONSUMER_AC_INSERT_SYMBOL 0x296 // HID type SEL -#define HID_CONSUMER_AC_SAVE_AND_CLOSE 0x297 // HID type SEL -#define HID_CONSUMER_AC_RENAME 0x298 // HID type SEL -#define HID_CONSUMER_AC_MERGE 0x299 // HID type SEL -#define HID_CONSUMER_AC_SPLIT 0x29A // HID type SEL -#define HID_CONSUMER_AC_DISTRIBUTE_HORIZONTALLY 0x29B // HID type SEL -#define HID_CONSUMER_AC_DISTRIBUTE_VERTICALLY 0x29C // HID type SEL +// ============================================================================== +// Consumer Control USB HID keycodes +// [Section 15: Consumer Page (0x0C)] -#endif // __HIDTables__ +// ----|-------------------------------------------------------|-------|--------- +// Name Value Usage Type +// ----|-------------------------------------------------------|-------|--------- +#define HID_CONSUMER_CONSUMER_CONTROL_CA 0x01 // CA +#define HID_CONSUMER_NUMERIC_KEY_PAD 0x02 // NAry +#define HID_CONSUMER_PROGRAMMABLE_BUTTONS 0x03 // NAry +#define HID_CONSUMER_MICROPHONE_CA 0x04 +#define HID_CONSUMER_HEADPHONE_CA 0x05 +#define HID_CONSUMER_GRAPHIC_EQUALIZER_CA 0x06 +// Reserved 0x07-1F +#define HID_CONSUMER_PLUS_10 0x20 // OSC +#define HID_CONSUMER_PLUS_100 0x21 // OSC +#define HID_CONSUMER_AM_SLASH_PM 0x22 // OSC +// Reserved 0x23-3F +#define HID_CONSUMER_POWER 0x30 // OOC +#define HID_CONSUMER_RESET 0x31 // OSC +#define HID_CONSUMER_SLEEP 0x32 // OSC +#define HID_CONSUMER_SLEEP_AFTER 0x33 // OSC +#define HID_CONSUMER_SLEEP_MODE 0x34 // RTC +#define HID_CONSUMER_ILLUMINATION 0x35 // OOC +#define HID_CONSUMER_FUNCTION_BUTTONS 0x36 // NAry +// Reserved 0x37-3F +#define HID_CONSUMER_MENU 0x40 // OOC +#define HID_CONSUMER_MENU_PICK 0x41 // OSC +#define HID_CONSUMER_MENU_UP 0x42 // OSC +#define HID_CONSUMER_MENU_DOWN 0x43 // OSC +#define HID_CONSUMER_MENU_LEFT 0x44 // OSC +#define HID_CONSUMER_MENU_RIGHT 0x45 // OSC +#define HID_CONSUMER_MENU_ESCAPE 0x46 // OSC +#define HID_CONSUMER_MENU_VALUE_INCREASE 0x47 // OSC +#define HID_CONSUMER_MENU_VALUE_DECREASE 0x48 // OSC +// Reserved 0x49-5F +#define HID_CONSUMER_DATA_ON_SCREEN 0x60 // OOC +#define HID_CONSUMER_CLOSED_CAPTION 0x61 // OOC +#define HID_CONSUMER_CLOSED_CAPTION_SELECT 0x62 // OSC +#define HID_CONSUMER_VCR_SLASH_TV 0x63 // OOC +#define HID_CONSUMER_BROADCAST_MODE 0x64 // OSC +#define HID_CONSUMER_SNAPSHOT 0x65 // OSC +#define HID_CONSUMER_STILL 0x66 // OSC +#define HID_CONSUMER_PICTURE_IN_PICTURE_TOGGLE 0x67 // OSC +#define HID_CONSUMER_PICTURE_IN_PICTURE_SWAP 0x68 // OSC +#define HID_CONSUMER_RED_MENU_BUTTON 0x69 // MC +#define HID_CONSUMER_GREEN_MENU_BUTTON 0x6A // MC +#define HID_CONSUMER_BLUE_MENU_BUTTON 0x6B // MC +#define HID_CONSUMER_YELLOW_MENU_BUTTON 0x6C // MC +#define HID_CONSUMER_ASPECT 0x6D // OSC +#define HID_CONSUMER_3D_MODE_SELECT 0x6E // OSC +#define HID_CONSUMER_DISPLAY_BRIGHTNESS_INCREMENT 0x6F // RTC +#define HID_CONSUMER_DISPLAY_BRIGHTNESS_DECREMENT 0x70 // RTC +#define HID_CONSUMER_DISPLAY_BRIGHTNESS 0x71 // LC +#define HID_CONSUMER_DISPLAY_BACKLIGHT_TOGGLE 0x72 // OOC +#define HID_CONSUMER_DISPLAY_SET_BRIGHTNESS_TO_MINIMUM 0x73 // OSC +#define HID_CONSUMER_DISPLAY_SET_BRIGHTNESS_TO_MAXIMUM 0x74 // OSC +#define HID_CONSUMER_DISPLAY_SET_AUTO_BRIGHTNESS 0x75 // OOC +#define HID_CONSUMER_CAMERA_ACCESS_ENABLED 0x76 // OOC +#define HID_CONSUMER_CAMERA_ACCESS_DISABLED 0x77 // OOC +#define HID_CONSUMER_CAMERA_ACCESS_TOGGLE 0x78 // OOC +#define HID_CONSUMER_KEYBOARD_BRIGHTNESS_INCREMENT 0x79 // OSC +#define HID_CONSUMER_KEYBOARD_BRIGHTNESS_DECREMENT 0x7A // OSC +#define HID_CONSUMER_KEYBOARD_BACKLIGHT_SET_LEVEL 0x7B // OC +#define HID_CONSUMER_KEYBOARD_BACKLIGHT_OOC 0x7C // OOC +#define HID_CONSUMER_KEYBOARD_BACKLIGHT_SET_MINIMUM 0x7D // OSC +#define HID_CONSUMER_KEYBOARD_BACKLIGHT_SET_MAXIMUM 0x7E // OSC +#define HID_CONSUMER_KEYBOARD_BACKLIGHT_AUTO 0x7F // OOC +#define HID_CONSUMER_SELECTION 0x80 // NAry +#define HID_CONSUMER_ASSIGN_SELECTION 0x81 // OSC +#define HID_CONSUMER_MODE_STEP 0x82 // OSC +#define HID_CONSUMER_RECALL_LAST 0x83 // OSC +#define HID_CONSUMER_ENTER_CHANNEL 0x84 // OSC +#define HID_CONSUMER_ORDER_MOVIE 0x85 // OSC +#define HID_CONSUMER_CHANNEL 0x86 // LC +#define HID_CONSUMER_MEDIA_SELECTION 0x87 // NAry +#define HID_CONSUMER_MEDIA_SELECT_COMPUTER 0x88 // Sel +#define HID_CONSUMER_MEDIA_SELECT_TV 0x89 // Sel +#define HID_CONSUMER_MEDIA_SELECT_WWW 0x8A // Sel +#define HID_CONSUMER_MEDIA_SELECT_DVD 0x8B // Sel +#define HID_CONSUMER_MEDIA_SELECT_TELEPHONE 0x8C // Sel +#define HID_CONSUMER_MEDIA_SELECT_PROGRAM_GUIDE 0x8D // Sel +#define HID_CONSUMER_MEDIA_SELECT_VIDEO_PHONE 0x8E // Sel +#define HID_CONSUMER_MEDIA_SELECT_GAMES 0x8F // Sel +#define HID_CONSUMER_MEDIA_SELECT_MESSAGES 0x90 // Sel +#define HID_CONSUMER_MEDIA_SELECT_CD 0x91 // Sel +#define HID_CONSUMER_MEDIA_SELECT_VCR 0x92 // Sel +#define HID_CONSUMER_MEDIA_SELECT_TUNER 0x93 // Sel +#define HID_CONSUMER_QUIT 0x94 // OSC +#define HID_CONSUMER_HELP 0x95 // OOC +#define HID_CONSUMER_MEDIA_SELECT_TAPE 0x96 // Sel +#define HID_CONSUMER_MEDIA_SELECT_CABLE 0x97 // Sel +#define HID_CONSUMER_MEDIA_SELECT_SATELLITE 0x98 // Sel +#define HID_CONSUMER_MEDIA_SELECT_SECURITY 0x99 // Sel +#define HID_CONSUMER_MEDIA_SELECT_HOME 0x9A // Sel +#define HID_CONSUMER_MEDIA_SELECT_CALL 0x9B // Sel +#define HID_CONSUMER_CHANNEL_INCREMENT 0x9C // OSC +#define HID_CONSUMER_CHANNEL_DECREMENT 0x9D // OSC +#define HID_CONSUMER_MEDIA_SELECT_SAP 0x9E // Sel +// Reserved 0x9F +#define HID_CONSUMER_VCR_PLUS 0xA0 // OSC +#define HID_CONSUMER_ONCE 0xA1 // OSC +#define HID_CONSUMER_DAILY 0xA2 // OSC +#define HID_CONSUMER_WEEKLY 0xA3 // OSC +#define HID_CONSUMER_MONTHLY 0xA4 // OSC +// Reserved 0xA5-AF +#define HID_CONSUMER_PLAY 0xB0 // OOC +#define HID_CONSUMER_PAUSE 0xB1 // OOC +#define HID_CONSUMER_RECORD 0xB2 // OOC +#define HID_CONSUMER_FAST_FORWARD 0xB3 // OOC +#define HID_CONSUMER_REWIND 0xB4 // OOC +#define HID_CONSUMER_SCAN_NEXT_TRACK 0xB5 // OSC +#define HID_CONSUMER_SCAN_PREVIOUS_TRACK 0xB6 // OSC +#define HID_CONSUMER_STOP 0xB7 // OSC +#define HID_CONSUMER_EJECT 0xB8 // OSC +#define HID_CONSUMER_RANDOM_PLAY 0xB9 // OOC +#define HID_CONSUMER_SELECT_DISC 0xBA // NAry +#define HID_CONSUMER_ENTER_DISC_MC 0xBB +#define HID_CONSUMER_REPEAT 0xBC // OSC +#define HID_CONSUMER_TRACKING 0xBD // LC +#define HID_CONSUMER_TRACK_NORMAL 0xBE // OSC +#define HID_CONSUMER_SLOW_TRACKING 0xBF // LC +#define HID_CONSUMER_FRAME_FORWARD 0xC0 // RTC +#define HID_CONSUMER_FRAME_BACK 0xC1 // RTC +#define HID_CONSUMER_MARK 0xC2 // OSC +#define HID_CONSUMER_CLEAR_MARK 0xC3 // OSC +#define HID_CONSUMER_REPEAT_FROM_MARK 0xC4 // OOC +#define HID_CONSUMER_RETURN_TO_MARK 0xC5 // OSC +#define HID_CONSUMER_SEARCH_MARK_FORWARD 0xC6 // OSC +#define HID_CONSUMER_SEARCH_MARK_BACKWARDS 0xC7 // OSC +#define HID_CONSUMER_COUNTER_RESET 0xC8 // OSC +#define HID_CONSUMER_SHOW_COUNTER 0xC9 // OSC +#define HID_CONSUMER_TRACKING_INCREMENT 0xCA // RTC +#define HID_CONSUMER_TRACKING_DECREMENT 0xCB // RTC +#define HID_CONSUMER_STOP_SLASH_EJECT 0xCC // OSC +#define HID_CONSUMER_PLAY_SLASH_PAUSE 0xCD // OSC +#define HID_CONSUMER_PLAY_SLASH_SKIP 0xCE // OSC +#define HID_CONSUMER_VOICE_COMMAND 0xCF // Sel +#define HID_CONSUMER_INVOKE_CAPTURE_INTERFACE 0xD0 // Sel +#define HID_CONSUMER_START_OR_STOP_GAME_RECORDING 0xD1 // Sel +#define HID_CONSUMER_HISTORICAL_GAME_CAPTURE 0xD2 // Sel +#define HID_CONSUMER_CAPTURE_GAME_SCREENSHOT 0xD3 // Sel +#define HID_CONSUMER_SHOW_OR_HIDE_RECORDING_INDICATOR 0xD4 // Sel +#define HID_CONSUMER_START_OR_STOP_MICROPHONE_CAPTURE 0xD5 // Sel +#define HID_CONSUMER_START_OR_STOP_CAMERA_CAPTURE 0xD6 // Sel +#define HID_CONSUMER_START_OR_STOP_GAME_BROADCAST 0xD7 // Sel +// Reserved 0xD8-DF +#define HID_CONSUMER_VOLUME 0xE0 // LC +#define HID_CONSUMER_BALANCE 0xE1 // LC +#define HID_CONSUMER_MUTE 0xE2 // OOC +#define HID_CONSUMER_BASS 0xE3 // LC +#define HID_CONSUMER_TREBLE 0xE4 // LC +#define HID_CONSUMER_BASS_BOOST 0xE5 // OOC +#define HID_CONSUMER_SURROUND_MODE 0xE6 // OSC +#define HID_CONSUMER_LOUDNESS 0xE7 // OOC +#define HID_CONSUMER_MPX 0xE8 // OOC +#define HID_CONSUMER_VOLUME_INCREMENT 0xE9 // RTC +#define HID_CONSUMER_VOLUME_DECREMENT 0xEA // RTC +// Reserved 0xEB-EF +#define HID_CONSUMER_SPEED_SELECT 0xF0 // OSC +#define HID_CONSUMER_PLAYBACK_SPEED 0xF1 // NAry +#define HID_CONSUMER_STANDARD_PLAY 0xF2 // Sel +#define HID_CONSUMER_LONG_PLAY 0xF3 // Sel +#define HID_CONSUMER_EXTENDED_PLAY 0xF4 // Sel +#define HID_CONSUMER_SLOW 0xF5 // OSC +// Reserved 0xF6-FF +#define HID_CONSUMER_FAN_ENABLE 0x100 // OOC +#define HID_CONSUMER_FAN_SPEED 0x101 // LC +#define HID_CONSUMER_LIGHT_ENABLE 0x102 // OOC +#define HID_CONSUMER_LIGHT_ILLUMINATION_LEVEL 0x103 // LC +#define HID_CONSUMER_CLIMATE_CONTROL_ENABLE 0x104 // OOC +#define HID_CONSUMER_ROOM_TEMPERATURE 0x105 // LC +#define HID_CONSUMER_SECURITY_ENABLE 0x106 // OOC +#define HID_CONSUMER_FIRE_ALARM 0x107 // OSC +#define HID_CONSUMER_POLICE_ALARM 0x108 // OSC +#define HID_CONSUMER_PROXIMITY 0x109 // LC +#define HID_CONSUMER_MOTION 0x10A // OSC +#define HID_CONSUMER_DURESS_ALARM 0x10B // OSC +#define HID_CONSUMER_HOLDUP_ALARM 0x10C // OSC +#define HID_CONSUMER_MEDICAL_ALARM 0x10D // OSC +// Reserved 0x10E-14F +#define HID_CONSUMER_BALANCE_RIGHT 0x150 // RTC +#define HID_CONSUMER_BALANCE_LEFT 0x151 // RTC +#define HID_CONSUMER_BASS_INCREMENT 0x152 // RTC +#define HID_CONSUMER_BASS_DECREMENT 0x153 // RTC +#define HID_CONSUMER_TREBLE_INCREMENT 0x154 // RTC +#define HID_CONSUMER_TREBLE_DECREMENT 0x155 // RTC +// Reserved 0x156-15F +#define HID_CONSUMER_SPEAKER_SYSTEM 0x160 // CL +#define HID_CONSUMER_CHANNEL_LEFT 0x161 // CL +#define HID_CONSUMER_CHANNEL_RIGHT 0x162 // CL +#define HID_CONSUMER_CHANNEL_CENTER 0x163 // CL +#define HID_CONSUMER_CHANNEL_FRONT 0x164 // CL +#define HID_CONSUMER_CHANNEL_CENTER_FRONT 0x165 // CL +#define HID_CONSUMER_CHANNEL_SIDE 0x166 // CL +#define HID_CONSUMER_CHANNEL_SURROUND 0x167 // CL +#define HID_CONSUMER_CHANNEL_LOW_FREQUENCY_ENHANCEMENT 0x168 // CL +#define HID_CONSUMER_CHANNEL_TOP 0x169 // CL +#define HID_CONSUMER_CHANNEL_UNKNOWN 0x16A // CL +// Reserved 0x16B-16F +#define HID_CONSUMER_SUB_CHANNEL 0x170 // LC +#define HID_CONSUMER_SUB_CHANNEL_INCREMENT 0x171 // OSC +#define HID_CONSUMER_SUB_CHANNEL_DECREMENT 0x172 // OSC +#define HID_CONSUMER_ALTERNATE_AUDIO_INCREMENT 0x173 // OSC +#define HID_CONSUMER_ALTERNATE_AUDIO_DECREMENT 0x174 // OSC +// Reserved 0x175-17F +#define HID_CONSUMER_APPLICATION_LAUNCH_BUTTONS 0x180 // NAry +#define HID_CONSUMER_AL_LAUNCH_BUTTON_CONFIGURATION_TOOL 0x181 // Sel +#define HID_CONSUMER_AL_PROGRAMMABLE_BUTTON_CONFIGURATION 0x182 // Sel +#define HID_CONSUMER_AL_CONSUMER_CONTROL_CONFIGURATION 0x183 // Sel +#define HID_CONSUMER_AL_WORD_PROCESSOR 0x184 // Sel +#define HID_CONSUMER_AL_TEXT_EDITOR 0x185 // Sel +#define HID_CONSUMER_AL_SPREADSHEET 0x186 // Sel +#define HID_CONSUMER_AL_GRAPHICS_EDITOR 0x187 // Sel +#define HID_CONSUMER_AL_PRESENTATION_APP 0x188 // Sel +#define HID_CONSUMER_AL_DATABASE_APP 0x189 // Sel +#define HID_CONSUMER_AL_EMAIL_READER 0x18A // Sel +#define HID_CONSUMER_AL_NEWSREADER 0x18B // Sel +#define HID_CONSUMER_AL_VOICEMAIL 0x18C // Sel +#define HID_CONSUMER_AL_CONTACTS_SLASH_ADDRESS_BOOK 0x18D // Sel +#define HID_CONSUMER_AL_CALENDAR_SLASH_SCHEDULE 0x18E // Sel +#define HID_CONSUMER_AL_TASK_SLASH_PROJECT_MANAGER 0x18F // Sel +#define HID_CONSUMER_AL_LOG_SLASH_JOURNAL_SLASH_TIMECARD 0x190 // Sel +#define HID_CONSUMER_AL_CHECKBOOK_SLASH_FINANCE 0x191 // Sel +#define HID_CONSUMER_AL_CALCULATOR 0x192 // Sel +#define HID_CONSUMER_AL_A_SLASH_V_CAPTURE_SLASH_PLAYBACK 0x193 // Sel +#define HID_CONSUMER_AL_LOCAL_MACHINE_BROWSER 0x194 // Sel +#define HID_CONSUMER_AL_LAN_SLASH_WAN_BROWSER 0x195 // Sel +#define HID_CONSUMER_AL_INTERNET_BROWSER 0x196 // Sel +#define HID_CONSUMER_AL_REMOTE_NETWORKING_SLASH_ISP_CONNECT 0x197 // Sel +#define HID_CONSUMER_AL_NETWORK_CONFERENCE 0x198 // Sel +#define HID_CONSUMER_AL_NETWORK_CHAT 0x199 // Sel +#define HID_CONSUMER_AL_TELEPHONY_SLASH_DIALER 0x19A // Sel +#define HID_CONSUMER_AL_LOGON 0x19B // Sel +#define HID_CONSUMER_AL_LOGOFF 0x19C // Sel +#define HID_CONSUMER_AL_LOGON_SLASH_LOGOFF 0x19D // Sel +#define HID_CONSUMER_AL_TERMINAL_LOCK_SLASH_SCREENSAVER 0x19E // Sel +#define HID_CONSUMER_AL_CONTROL_PANEL 0x19F // Sel +#define HID_CONSUMER_AL_COMMAND_LINE_PROCESSOR_SLASH_RUN 0x1A0 // Sel +#define HID_CONSUMER_AL_PROCESS_SLASH_TASK_MANAGER 0x1A1 // Sel +#define HID_CONSUMER_AL_SELECT_TASK_SLASH_APPLICATION 0x1A2 // Sel +#define HID_CONSUMER_AL_NEXT_TASK_SLASH_APPLICATION 0x1A3 // Sel +#define HID_CONSUMER_AL_PREVIOUS_TASK_SLASH_APPLICATION 0x1A4 // Sel +#define HID_CONSUMER_AL_PREEMPTIVE_HALT_TASK_SLASH_APPLICATION 0x1A5 // Sel +#define HID_CONSUMER_AL_INTEGRATED_HELP_CENTER 0x1A6 // Sel +#define HID_CONSUMER_AL_DOCUMENTS 0x1A7 // Sel +#define HID_CONSUMER_AL_THESAURUS 0x1A8 // Sel +#define HID_CONSUMER_AL_DICTIONARY 0x1A9 // Sel +#define HID_CONSUMER_AL_DESKTOP 0x1AA // Sel +#define HID_CONSUMER_AL_SPELL_CHECK 0x1AB // Sel +#define HID_CONSUMER_AL_GRAMMAR_CHECK 0x1AC // Sel +#define HID_CONSUMER_AL_WIRELESS_STATUS 0x1AD // Sel +#define HID_CONSUMER_AL_KEYBOARD_LAYOUT 0x1AE // Sel +#define HID_CONSUMER_AL_VIRUS_PROTECTION 0x1AF // Sel +#define HID_CONSUMER_AL_ENCRYPTION 0x1B0 // Sel +#define HID_CONSUMER_AL_SCREEN_SAVER 0x1B1 // Sel +#define HID_CONSUMER_AL_ALARMS 0x1B2 // Sel +#define HID_CONSUMER_AL_CLOCK 0x1B3 // Sel +#define HID_CONSUMER_AL_FILE_BROWSER 0x1B4 // Sel +#define HID_CONSUMER_AL_POWER_STATUS 0x1B5 // Sel +#define HID_CONSUMER_AL_IMAGE_BROWSER 0x1B6 // Sel +#define HID_CONSUMER_AL_AUDIO_BROWSER 0x1B7 // Sel +#define HID_CONSUMER_AL_MOVIE_BROWSER 0x1B8 // Sel +#define HID_CONSUMER_AL_DIGITAL_RIGHTS_MANAGER 0x1B9 // Sel +#define HID_CONSUMER_AL_DIGITAL_WALLET 0x1BA // Sel +// _Reserved 0x1BB +#define HID_CONSUMER_AL_INSTANT_MESSAGING 0x1BC // Sel +#define HID_CONSUMER_AL_OEM_FEATURES_SLASH__TIPS_SLASH_TUTORIAL_BROWSER \ + 0x1BD // Sel +#define HID_CONSUMER_AL_OEM_HELP 0x1BE // Sel +#define HID_CONSUMER_AL_ONLINE_COMMUNITY 0x1BF // Sel +#define HID_CONSUMER_AL_ENTERTAINMENT_CONTENT_BROWSER 0x1C0 // Sel +#define HID_CONSUMER_AL_ONLINE_SHOPPING_BROWSER 0x1C1 // Sel +#define HID_CONSUMER_AL_SMARTCARD_INFORMATION_SLASH_HELP 0x1C2 // Sel +#define HID_CONSUMER_AL_MARKET_MONITOR_SLASH_FINANCE_BROWSER 0x1C3 // Sel +#define HID_CONSUMER_AL_CUSTOMIZED_CORPORATE_NEWS_BROWSER 0x1C4 // Sel +#define HID_CONSUMER_AL_ONLINE_ACTIVITY_BROWSER 0x1C5 // Sel +#define HID_CONSUMER_AL_RESEARCH_SLASH_SEARCH_BROWSER 0x1C6 // Sel +#define HID_CONSUMER_AL_AUDIO_PLAYER 0x1C7 // Sel +#define HID_CONSUMER_AL_MESSAGE_STATUS 0x1C8 // Sel +#define HID_CONSUMER_AL_CONTACT_SYNC 0x1C9 // Sel +#define HID_CONSUMER_AL_NAVIGATION 0x1CA // Sel +#define HID_CONSUMER_AL_CONTEXT_AWARE_DESKTOP_ASSISTANT 0x1CB // Sel +// Reserved 0x1CC-1FF +#define HID_CONSUMER_GENERIC_GUI_APPLICATION_CONTROLS 0x200 // NAry +#define HID_CONSUMER_AC_NEW 0x201 // Sel +#define HID_CONSUMER_AC_OPEN 0x202 // Sel +#define HID_CONSUMER_AC_CLOSE 0x203 // Sel +#define HID_CONSUMER_AC_EXIT 0x204 // Sel +#define HID_CONSUMER_AC_MAXIMIZE 0x205 // Sel +#define HID_CONSUMER_AC_MINIMIZE 0x206 // Sel +#define HID_CONSUMER_AC_SAVE 0x207 // Sel +#define HID_CONSUMER_AC_PRINT 0x208 // Sel +#define HID_CONSUMER_AC_PROPERTIES 0x209 // Sel +// Reserved 0x20A-219 +#define HID_CONSUMER_AC_UNDO 0x21A // Sel +#define HID_CONSUMER_AC_COPY 0x21B // Sel +#define HID_CONSUMER_AC_CUT 0x21C // Sel +#define HID_CONSUMER_AC_PASTE 0x21D // Sel +#define HID_CONSUMER_AC_SELECT_ALL 0x21E // Sel +#define HID_CONSUMER_AC_FIND 0x21F // Sel +#define HID_CONSUMER_AC_FIND_AND_REPLACE 0x220 // Sel +#define HID_CONSUMER_AC_SEARCH 0x221 // Sel +#define HID_CONSUMER_AC_GO_TO 0x222 // Sel +#define HID_CONSUMER_AC_HOME 0x223 // Sel +#define HID_CONSUMER_AC_BACK 0x224 // Sel +#define HID_CONSUMER_AC_FORWARD 0x225 // Sel +#define HID_CONSUMER_AC_STOP 0x226 // Sel +#define HID_CONSUMER_AC_REFRESH 0x227 // Sel +#define HID_CONSUMER_AC_PREVIOUS_LINK 0x228 // Sel +#define HID_CONSUMER_AC_NEXT_LINK 0x229 // Sel +#define HID_CONSUMER_AC_BOOKMARKS 0x22A // Sel +#define HID_CONSUMER_AC_HISTORY 0x22B // Sel +#define HID_CONSUMER_AC_SUBSCRIPTIONS 0x22C // Sel +#define HID_CONSUMER_AC_ZOOM_IN 0x22D // Sel +#define HID_CONSUMER_AC_ZOOM_OUT 0x22E // Sel +#define HID_CONSUMER_AC_ZOOM 0x22F // LC +#define HID_CONSUMER_AC_FULL_SCREEN_VIEW 0x230 // Sel +#define HID_CONSUMER_AC_NORMAL_VIEW 0x231 // Sel +#define HID_CONSUMER_AC_VIEW_TOGGLE 0x232 // Sel +#define HID_CONSUMER_AC_SCROLL_UP 0x233 // Sel +#define HID_CONSUMER_AC_SCROLL_DOWN 0x234 // Sel +#define HID_CONSUMER_AC_SCROLL 0x235 // LC +#define HID_CONSUMER_AC_PAN_LEFT 0x236 // Sel +#define HID_CONSUMER_AC_PAN_RIGHT 0x237 // Sel +#define HID_CONSUMER_AC_PAN 0x238 // LC +#define HID_CONSUMER_AC_NEW_WINDOW 0x239 // Sel +#define HID_CONSUMER_AC_TILE_HORIZONTALLY 0x23A // Sel +#define HID_CONSUMER_AC_TILE_VERTICALLY 0x23B // Sel +#define HID_CONSUMER_AC_FORMAT 0x23C // Sel +#define HID_CONSUMER_AC_EDIT 0x23D // Sel +#define HID_CONSUMER_AC_BOLD 0x23E // Sel +#define HID_CONSUMER_AC_ITALICS 0x23F // Sel +#define HID_CONSUMER_AC_UNDERLINE 0x240 // Sel +#define HID_CONSUMER_AC_STRIKETHROUGH 0x241 // Sel +#define HID_CONSUMER_AC_SUBSCRIPT 0x242 // Sel +#define HID_CONSUMER_AC_SUPERSCRIPT 0x243 // Sel +#define HID_CONSUMER_AC_ALL_CAPS 0x244 // Sel +#define HID_CONSUMER_AC_ROTATE 0x245 // Sel +#define HID_CONSUMER_AC_RESIZE 0x246 // Sel +#define HID_CONSUMER_AC_FLIP_HORIZONTAL 0x247 // Sel +#define HID_CONSUMER_AC_FLIP_VERTICAL 0x248 // Sel +#define HID_CONSUMER_AC_MIRROR_HORIZONTAL 0x249 // Sel +#define HID_CONSUMER_AC_MIRROR_VERTICAL 0x24A // Sel +#define HID_CONSUMER_AC_FONT_SELECT 0x24B // Sel +#define HID_CONSUMER_AC_FONT_COLOR 0x24C // Sel +#define HID_CONSUMER_AC_FONT_SIZE 0x24D // Sel +#define HID_CONSUMER_AC_JUSTIFY_LEFT 0x24E // Sel +#define HID_CONSUMER_AC_JUSTIFY_CENTER_H 0x24F // Sel +#define HID_CONSUMER_AC_JUSTIFY_RIGHT 0x250 // Sel +#define HID_CONSUMER_AC_JUSTIFY_BLOCK_H 0x251 // Sel +#define HID_CONSUMER_AC_JUSTIFY_TOP 0x252 // Sel +#define HID_CONSUMER_AC_JUSTIFY_CENTER_V 0x253 // Sel +#define HID_CONSUMER_AC_JUSTIFY_BOTTOM 0x254 // Sel +#define HID_CONSUMER_AC_JUSTIFY_BLOCK_V 0x255 // Sel +#define HID_CONSUMER_AC_INDENT_DECREASE 0x256 // Sel +#define HID_CONSUMER_AC_INDENT_INCREASE 0x257 // Sel +#define HID_CONSUMER_AC_NUMBERED_LIST 0x258 // Sel +#define HID_CONSUMER_AC_RESTART_NUMBERING 0x259 // Sel +#define HID_CONSUMER_AC_BULLETED_LIST 0x25A // Sel +#define HID_CONSUMER_AC_PROMOTE 0x25B // Sel +#define HID_CONSUMER_AC_DEMOTE 0x25C // Sel +#define HID_CONSUMER_AC_YES 0x25D // Sel +#define HID_CONSUMER_AC_NO 0x25E // Sel +#define HID_CONSUMER_AC_CANCEL 0x25F // Sel +#define HID_CONSUMER_AC_CATALOG 0x260 // Sel +#define HID_CONSUMER_AC_BUY_SLASH_CHECKOUT 0x261 // Sel +#define HID_CONSUMER_AC_ADD_TO_CART 0x262 // Sel +#define HID_CONSUMER_AC_EXPAND 0x263 // Sel +#define HID_CONSUMER_AC_EXPAND_ALL 0x264 // Sel +#define HID_CONSUMER_AC_COLLAPSE 0x265 // Sel +#define HID_CONSUMER_AC_COLLAPSE_ALL 0x266 // Sel +#define HID_CONSUMER_AC_PRINT_PREVIEW 0x267 // Sel +#define HID_CONSUMER_AC_PASTE_SPECIAL 0x268 // Sel +#define HID_CONSUMER_AC_INSERT_MODE 0x269 // Sel +#define HID_CONSUMER_AC_DELETE 0x26A // Sel +#define HID_CONSUMER_AC_LOCK 0x26B // Sel +#define HID_CONSUMER_AC_UNLOCK 0x26C // Sel +#define HID_CONSUMER_AC_PROTECT 0x26D // Sel +#define HID_CONSUMER_AC_UNPROTECT 0x26E // Sel +#define HID_CONSUMER_AC_ATTACH_COMMENT 0x26F // Sel +#define HID_CONSUMER_AC_DELETE_COMMENT 0x270 // Sel +#define HID_CONSUMER_AC_VIEW_COMMENT 0x271 // Sel +#define HID_CONSUMER_AC_SELECT_WORD 0x272 // Sel +#define HID_CONSUMER_AC_SELECT_SENTENCE 0x273 // Sel +#define HID_CONSUMER_AC_SELECT_PARAGRAPH 0x274 // Sel +#define HID_CONSUMER_AC_SELECT_COLUMN 0x275 // Sel +#define HID_CONSUMER_AC_SELECT_ROW 0x276 // Sel +#define HID_CONSUMER_AC_SELECT_TABLE 0x277 // Sel +#define HID_CONSUMER_AC_SELECT_OBJECT 0x278 // Sel +#define HID_CONSUMER_AC_REDO_SLASH_REPEAT 0x279 // Sel +#define HID_CONSUMER_AC_SORT 0x27A // Sel +#define HID_CONSUMER_AC_SORT_ASCENDING 0x27B // Sel +#define HID_CONSUMER_AC_SORT_DESCENDING 0x27C // Sel +#define HID_CONSUMER_AC_FILTER 0x27D // Sel +#define HID_CONSUMER_AC_SET_CLOCK 0x27E // Sel +#define HID_CONSUMER_AC_VIEW_CLOCK 0x27F // Sel +#define HID_CONSUMER_AC_SELECT_TIME_ZONE 0x280 // Sel +#define HID_CONSUMER_AC_EDIT_TIME_ZONES 0x281 // Sel +#define HID_CONSUMER_AC_SET_ALARM 0x282 // Sel +#define HID_CONSUMER_AC_CLEAR_ALARM 0x283 // Sel +#define HID_CONSUMER_AC_SNOOZE_ALARM 0x284 // Sel +#define HID_CONSUMER_AC_RESET_ALARM 0x285 // Sel +#define HID_CONSUMER_AC_SYNCHRONIZE 0x286 // Sel +#define HID_CONSUMER_AC_SEND_SLASH_RECEIVE 0x287 // Sel +#define HID_CONSUMER_AC_SEND_TO 0x288 // Sel +#define HID_CONSUMER_AC_REPLY 0x289 // Sel +#define HID_CONSUMER_AC_REPLY_ALL 0x28A // Sel +#define HID_CONSUMER_AC_FORWARD_MSG 0x28B // Sel +#define HID_CONSUMER_AC_SEND 0x28C // Sel +#define HID_CONSUMER_AC_ATTACH_FILE 0x28D // Sel +#define HID_CONSUMER_AC_UPLOAD 0x28E // Sel +#define HID_CONSUMER_AC_DOWNLOAD 0x28F // Sel +#define HID_CONSUMER_AC_SET_BORDERS 0x290 // Sel +#define HID_CONSUMER_AC_INSERT_ROW 0x291 // Sel +#define HID_CONSUMER_AC_INSERT_COLUMN 0x292 // Sel +#define HID_CONSUMER_AC_INSERT_FILE 0x293 // Sel +#define HID_CONSUMER_AC_INSERT_PICTURE 0x294 // Sel +#define HID_CONSUMER_AC_INSERT_OBJECT 0x295 // Sel +#define HID_CONSUMER_AC_INSERT_SYMBOL 0x296 // Sel +#define HID_CONSUMER_AC_SAVE_AND_CLOSE 0x297 // Sel +#define HID_CONSUMER_AC_RENAME 0x298 // Sel +#define HID_CONSUMER_AC_MERGE 0x299 // Sel +#define HID_CONSUMER_AC_SPLIT 0x29A // Sel +#define HID_CONSUMER_AC_DISTRIBUTE_HORIZONTALLY 0x29B // Sel +#define HID_CONSUMER_AC_DISTRIBUTE_VERTICALLY 0x29C // Sel +#define HID_CONSUMER_AC_NEXT_KEYBOARD_LAYOUT_SELECT 0x29D // Sel +#define HID_CONSUMER_AC_NAVIGATION_GUIDANCE 0x29E // Sel +#define HID_CONSUMER_AC_DESKTOP_SHOW_ALL_WINDOWS 0x29F // Sel +#define HID_CONSUMER_AC_SOFT_KEY_LEFT 0x2A0 // Sel +#define HID_CONSUMER_AC_SOFT_KEY_RIGHT 0x2A1 // Sel +#define HID_CONSUMER_AC_DESKTOP_SHOW_ALL_APPLICATIONS 0x2A2 // Sel +// Reserved 0x2A3-2AF +#define HID_CONSUMER_AC_IDLE_KEEP_ALIVE 0x2B0 // Sel +// Reserved 0x2B1-2BF +#define HID_CONSUMER_EXTENDED_KEYBOARD_ATTRIBUTES_COLLECTION 0x2C0 // CL +#define HID_CONSUMER_KEYBOARD_FORM_FACTOR 0x2C1 // SV +#define HID_CONSUMER_KEYBOARD_KEY_TYPE 0x2C2 // SV +#define HID_CONSUMER_KEYBOARD_PHYSICAL_LAYOUT 0x2C3 // SV +#define HID_CONSUMER_VENDOR_SPECIFIC_KEYBOARD_PHYSICAL_LAYOUT 0x2C4 // SV +#define HID_CONSUMER_KEYBOARD_IETF_LANGUAGE_TAG_INDEX 0x2C5 // SV +#define HID_CONSUMER_IMPLEMENTED_KEYBOARD_INPUT_ASSIST_CONTROLS 0x2C6 // SV +#define HID_CONSUMER_KEYBOARD_INPUT_ASSIST_PREVIOUS 0x2C7 // Sel +#define HID_CONSUMER_KEYBOARD_INPUT_ASSIST_NEXT 0x2C8 // Sel +#define HID_CONSUMER_KEYBOARD_INPUT_ASSIST_PREVIOUS_GROUP 0x2C9 // Sel +#define HID_CONSUMER_KEYBOARD_INPUT_ASSIST_NEXT_GROUP 0x2CA // Sel +#define HID_CONSUMER_KEYBOARD_INPUT_ASSIST_ACCEPT 0x2CB // Sel +#define HID_CONSUMER_KEYBOARD_INPUT_ASSIST_CANCEL 0x2CC // Sel +// Reserved 0x2CD-2CF +#define HID_CONSUMER_PRIVACY_SCREEN_TOGGLE 0x2D0 // OOC +#define HID_CONSUMER_PRIVACY_SCREEN_LEVEL_DECREMENT 0x2D1 +#define HID_CONSUMER_PRIVACY_SCREEN_LEVEL_INCREMENT 0x2D2 +#define HID_CONSUMER_PRIVACY_SCREEN_LEVEL_MINIMUM 0x2D3 // OSC +#define HID_CONSUMER_PRIVACY_SCREEN_LEVEL_MAXIMUM 0x2D4 // OSC +// Reserved 0x2D5-4FF +// HID_CONTACT_* (not included here) 0x500-514 +// Reserved 0x515-FFFF From bb661e5d3614769b4fcacfc67663420a12035cf0 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Sat, 3 Oct 2020 20:21:43 -0700 Subject: [PATCH 546/602] remove an accidental extra space --- plugins/KeyboardioHID/src/HIDTables.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/HIDTables.h b/plugins/KeyboardioHID/src/HIDTables.h index 85072b0f9b..02325b3ade 100644 --- a/plugins/KeyboardioHID/src/HIDTables.h +++ b/plugins/KeyboardioHID/src/HIDTables.h @@ -606,7 +606,7 @@ THE SOFTWARE. #define HID_CONSUMER_AL_DIGITAL_WALLET 0x1BA // Sel // _Reserved 0x1BB #define HID_CONSUMER_AL_INSTANT_MESSAGING 0x1BC // Sel -#define HID_CONSUMER_AL_OEM_FEATURES_SLASH__TIPS_SLASH_TUTORIAL_BROWSER \ +#define HID_CONSUMER_AL_OEM_FEATURES_SLASH_TIPS_SLASH_TUTORIAL_BROWSER \ 0x1BD // Sel #define HID_CONSUMER_AL_OEM_HELP 0x1BE // Sel #define HID_CONSUMER_AL_ONLINE_COMMUNITY 0x1BF // Sel From 0629d0ff069589e40db9cea839b5aec0b11c4e38 Mon Sep 17 00:00:00 2001 From: Michael Richters Date: Fri, 4 Dec 2020 13:08:06 -0600 Subject: [PATCH 547/602] Change `make astyle` to use the same options as Kaleidoscope Signed-off-by: Michael Richters --- plugins/KeyboardioHID/.astylerc | 7 +++++++ plugins/KeyboardioHID/Makefile | 4 +--- 2 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 plugins/KeyboardioHID/.astylerc diff --git a/plugins/KeyboardioHID/.astylerc b/plugins/KeyboardioHID/.astylerc new file mode 100644 index 0000000000..cb82ff6b94 --- /dev/null +++ b/plugins/KeyboardioHID/.astylerc @@ -0,0 +1,7 @@ +style=google +unpad-paren +pad-header +pad-oper +indent-classes +indent=spaces=2 +max-continuation-indent=80 diff --git a/plugins/KeyboardioHID/Makefile b/plugins/KeyboardioHID/Makefile index d63420ee7a..bf3298c69c 100644 --- a/plugins/KeyboardioHID/Makefile +++ b/plugins/KeyboardioHID/Makefile @@ -19,9 +19,7 @@ EXAMPLES_HEX := $(addsuffix .hex,${EXAMPLES}) astyle: - find . -type f -name \*.cpp |xargs -n 1 astyle --style=google - find . -type f -name \*.ino |xargs -n 1 astyle --style=google - find . -type f -name \*.h |xargs -n 1 astyle --style=google + astyle --project --recursive "src/*.cpp,*.h,*.ino" smoke: ${EXAMPLES_HEX} From dbd52b3e4f32c3d5f07ef668d8333f9b5cb7197c Mon Sep 17 00:00:00 2001 From: Michael Richters Date: Fri, 4 Dec 2020 13:09:07 -0600 Subject: [PATCH 548/602] Format code using new `make astyle` options Signed-off-by: Michael Richters --- .../src/BootKeyboard/BootKeyboard.cpp | 438 +++++++++--------- .../src/BootKeyboard/BootKeyboard.h | 86 ++-- .../src/DeviceAPIs/AbsoluteMouseAPI.h | 58 +-- plugins/KeyboardioHID/src/HID.cpp | 226 ++++----- plugins/KeyboardioHID/src/HID.h | 94 ++-- plugins/KeyboardioHID/src/HIDReportObserver.h | 49 +- plugins/KeyboardioHID/src/HIDTables.h | 2 +- plugins/KeyboardioHID/src/LEDs.h | 16 +- .../src/MultiReport/AbsoluteMouse.cpp | 24 +- .../src/MultiReport/AbsoluteMouse.h | 10 +- .../src/MultiReport/ConsumerControl.cpp | 88 ++-- .../src/MultiReport/ConsumerControl.h | 46 +- .../KeyboardioHID/src/MultiReport/Gamepad.cpp | 132 +++--- .../KeyboardioHID/src/MultiReport/Gamepad.h | 150 +++--- .../src/MultiReport/Keyboard.cpp | 322 ++++++------- .../KeyboardioHID/src/MultiReport/Keyboard.h | 62 +-- .../KeyboardioHID/src/MultiReport/Mouse.cpp | 140 +++--- plugins/KeyboardioHID/src/MultiReport/Mouse.h | 66 +-- .../src/MultiReport/SystemControl.cpp | 70 +-- .../src/MultiReport/SystemControl.h | 28 +- .../src/SingleReport/SingleAbsoluteMouse.cpp | 128 ++--- .../src/SingleReport/SingleAbsoluteMouse.h | 32 +- plugins/KeyboardioHID/src/arch/samd.cpp | 4 +- 23 files changed, 1136 insertions(+), 1135 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 4cdcc3a44f..bdd83a562e 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -29,200 +29,200 @@ THE SOFTWARE. // See Appendix B of USB HID spec static const uint8_t _hidReportDescriptorKeyboard[] PROGMEM = { - // Keyboard - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, - D_USAGE, D_USAGE_KEYBOARD, - - D_COLLECTION, D_APPLICATION, - // Modifiers - D_USAGE_PAGE, D_PAGE_KEYBOARD, - D_USAGE_MINIMUM, 0xe0, - D_USAGE_MAXIMUM, 0xe7, - D_LOGICAL_MINIMUM, 0x0, - D_LOGICAL_MAXIMUM, 0x1, - D_REPORT_SIZE, 0x1, - D_REPORT_COUNT, 0x8, - D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), - - // Reserved byte - D_REPORT_COUNT, 0x1, - D_REPORT_SIZE, 0x8, - D_INPUT, (D_CONSTANT), - - // LEDs - D_REPORT_COUNT, 0x5, - D_REPORT_SIZE, 0x1, - D_USAGE_PAGE, D_PAGE_LEDS, - D_USAGE_MINIMUM, 0x1, - D_USAGE_MAXIMUM, 0x5, - D_OUTPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), - // Pad LEDs up to a byte - D_REPORT_COUNT, 0x1, - D_REPORT_SIZE, 0x3, - D_OUTPUT, (D_CONSTANT), - - // Non-modifiers - D_REPORT_COUNT, 0x6, - D_REPORT_SIZE, 0x8, - D_LOGICAL_MINIMUM, 0x0, - D_LOGICAL_MAXIMUM, 0xff, - D_USAGE_PAGE, D_PAGE_KEYBOARD, - D_USAGE_MINIMUM, 0x0, - D_USAGE_MAXIMUM, 0xff, - D_INPUT, (D_DATA|D_ARRAY|D_ABSOLUTE), - D_END_COLLECTION + // Keyboard + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, + D_USAGE, D_USAGE_KEYBOARD, + + D_COLLECTION, D_APPLICATION, + // Modifiers + D_USAGE_PAGE, D_PAGE_KEYBOARD, + D_USAGE_MINIMUM, 0xe0, + D_USAGE_MAXIMUM, 0xe7, + D_LOGICAL_MINIMUM, 0x0, + D_LOGICAL_MAXIMUM, 0x1, + D_REPORT_SIZE, 0x1, + D_REPORT_COUNT, 0x8, + D_INPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), + + // Reserved byte + D_REPORT_COUNT, 0x1, + D_REPORT_SIZE, 0x8, + D_INPUT, (D_CONSTANT), + + // LEDs + D_REPORT_COUNT, 0x5, + D_REPORT_SIZE, 0x1, + D_USAGE_PAGE, D_PAGE_LEDS, + D_USAGE_MINIMUM, 0x1, + D_USAGE_MAXIMUM, 0x5, + D_OUTPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), + // Pad LEDs up to a byte + D_REPORT_COUNT, 0x1, + D_REPORT_SIZE, 0x3, + D_OUTPUT, (D_CONSTANT), + + // Non-modifiers + D_REPORT_COUNT, 0x6, + D_REPORT_SIZE, 0x8, + D_LOGICAL_MINIMUM, 0x0, + D_LOGICAL_MAXIMUM, 0xff, + D_USAGE_PAGE, D_PAGE_KEYBOARD, + D_USAGE_MINIMUM, 0x0, + D_USAGE_MAXIMUM, 0xff, + D_INPUT, (D_DATA | D_ARRAY | D_ABSOLUTE), + D_END_COLLECTION }; BootKeyboard_::BootKeyboard_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1), leds(0) { - epType[0] = EP_TYPE_INTERRUPT_IN; + epType[0] = EP_TYPE_INTERRUPT_IN; } int BootKeyboard_::getInterface(uint8_t* interfaceCount) { - *interfaceCount += 1; // uses 1 - HIDDescriptor hidInterface = { - D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_BOOT_INTERFACE, HID_PROTOCOL_KEYBOARD), - D_HIDREPORT(sizeof(_hidReportDescriptorKeyboard)), - D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) - }; - return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); + *interfaceCount += 1; // uses 1 + HIDDescriptor hidInterface = { + D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_BOOT_INTERFACE, HID_PROTOCOL_KEYBOARD), + D_HIDREPORT(sizeof(_hidReportDescriptorKeyboard)), + D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) + }; + return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); } int BootKeyboard_::getDescriptor(USBSetup& setup) { - // Check if this is a HID Class Descriptor request - if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { - return 0; - } - if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { - return 0; - } - - // In a HID Class Descriptor wIndex cointains the interface number - if (setup.wIndex != pluggedInterface) { - return 0; - } - - // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol - // due to the USB specs, but Windows and Linux just assumes its in report mode. - protocol = default_protocol; - - return USB_SendControl(TRANSFER_PGM, _hidReportDescriptorKeyboard, sizeof(_hidReportDescriptorKeyboard)); + // Check if this is a HID Class Descriptor request + if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { + return 0; + } + if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { + return 0; + } + + // In a HID Class Descriptor wIndex cointains the interface number + if (setup.wIndex != pluggedInterface) { + return 0; + } + + // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol + // due to the USB specs, but Windows and Linux just assumes its in report mode. + protocol = default_protocol; + + return USB_SendControl(TRANSFER_PGM, _hidReportDescriptorKeyboard, sizeof(_hidReportDescriptorKeyboard)); } void BootKeyboard_::begin(void) { - PluggableUSB().plug(this); + PluggableUSB().plug(this); - // Force API to send a clean report. - // This is important for and HID bridge where the receiver stays on, - // while the sender is resetted. - releaseAll(); - sendReport(); + // Force API to send a clean report. + // This is important for and HID bridge where the receiver stays on, + // while the sender is resetted. + releaseAll(); + sendReport(); } void BootKeyboard_::end(void) { - releaseAll(); - sendReport(); + releaseAll(); + sendReport(); } bool BootKeyboard_::setup(USBSetup& setup) { - if (pluggedInterface != setup.wIndex) { - return false; - } + if (pluggedInterface != setup.wIndex) { + return false; + } - uint8_t request = setup.bRequest; - uint8_t requestType = setup.bmRequestType; + uint8_t request = setup.bRequest; + uint8_t requestType = setup.bmRequestType; - if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) { - if (request == HID_GET_REPORT) { - // TODO: HID_GetReport(); - return true; - } - if (request == HID_GET_PROTOCOL) { - // TODO improve + if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) { + if (request == HID_GET_REPORT) { + // TODO: HID_GetReport(); + return true; + } + if (request == HID_GET_PROTOCOL) { + // TODO improve #ifdef __AVR__ - UEDATX = protocol; + UEDATX = protocol; #endif #ifdef ARDUINO_ARCH_SAM - USBDevice.armSend(0, &protocol, 1); + USBDevice.armSend(0, &protocol, 1); #endif - return true; - } - if (request == HID_GET_IDLE) { - // TODO improve + return true; + } + if (request == HID_GET_IDLE) { + // TODO improve #ifdef __AVR__ - UEDATX = idle; + UEDATX = idle; #endif #ifdef ARDUINO_ARCH_SAM - USBDevice.armSend(0, &idle, 1); + USBDevice.armSend(0, &idle, 1); #endif - return true; - } + return true; } + } - if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) { - if (request == HID_SET_PROTOCOL) { - protocol = setup.wValueL; - return true; - } - if (request == HID_SET_IDLE) { - // We currently ignore SET_IDLE, because we don't really do anything with it, and implementing - // it causes issues on OSX, such as key chatter. Other operating systems do not suffer if we - // force this to zero, either. + if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) { + if (request == HID_SET_PROTOCOL) { + protocol = setup.wValueL; + return true; + } + if (request == HID_SET_IDLE) { + // We currently ignore SET_IDLE, because we don't really do anything with it, and implementing + // it causes issues on OSX, such as key chatter. Other operating systems do not suffer if we + // force this to zero, either. #if 0 - idle = setup.wValueL; + idle = setup.wValueL; #else - idle = 0; + idle = 0; #endif - return true; + return true; + } + if (request == HID_SET_REPORT) { + // Check if data has the correct length afterwards + int length = setup.wLength; + + if (setup.wValueH == HID_REPORT_TYPE_OUTPUT) { + if (length == sizeof(leds)) { + USB_RecvControl(&leds, length); + return true; } - if (request == HID_SET_REPORT) { - // Check if data has the correct length afterwards - int length = setup.wLength; - - if (setup.wValueH == HID_REPORT_TYPE_OUTPUT) { - if (length == sizeof(leds)) { - USB_RecvControl(&leds, length); - return true; - } - } - - // Input (set HID report) - else if (setup.wValueH == HID_REPORT_TYPE_INPUT) { - if (length == sizeof(_keyReport)) { - USB_RecvControl(&_keyReport, length); - return true; - } - } + } + + // Input (set HID report) + else if (setup.wValueH == HID_REPORT_TYPE_INPUT) { + if (length == sizeof(_keyReport)) { + USB_RecvControl(&_keyReport, length); + return true; } + } } + } - return false; + return false; } uint8_t BootKeyboard_::getLeds(void) { - return leds; + return leds; } uint8_t BootKeyboard_::getProtocol(void) { - return protocol; + return protocol; } void BootKeyboard_::setProtocol(uint8_t protocol) { - this->protocol = protocol; + this->protocol = protocol; } int BootKeyboard_::sendReport(void) { - if (memcmp(&_lastKeyReport, &_keyReport, sizeof(_keyReport))) { - // if the two reports are different, send a report - int returnCode = USB_Send(pluggedEndpoint | TRANSFER_RELEASE, &_keyReport, sizeof(_keyReport)); - HIDReportObserver::observeReport(HID_REPORTID_KEYBOARD, &_keyReport, sizeof(_keyReport), returnCode); - memcpy(&_lastKeyReport, &_keyReport, sizeof(_keyReport)); - return returnCode; - } - return -1; + if (memcmp(&_lastKeyReport, &_keyReport, sizeof(_keyReport))) { + // if the two reports are different, send a report + int returnCode = USB_Send(pluggedEndpoint | TRANSFER_RELEASE, &_keyReport, sizeof(_keyReport)); + HIDReportObserver::observeReport(HID_REPORTID_KEYBOARD, &_keyReport, sizeof(_keyReport), returnCode); + memcpy(&_lastKeyReport, &_keyReport, sizeof(_keyReport)); + return returnCode; + } + return -1; } // press() adds the specified key (printing, non-printing, or modifier) @@ -232,35 +232,35 @@ int BootKeyboard_::sendReport(void) { size_t BootKeyboard_::press(uint8_t k) { - uint8_t done = 0; - - if ((k >= HID_KEYBOARD_FIRST_MODIFIER) && (k <= HID_KEYBOARD_LAST_MODIFIER)) { - // it's a modifier key - _keyReport.modifiers |= (0x01 << (k - HID_KEYBOARD_FIRST_MODIFIER)); - } else { - // it's some other key: - // Add k to the key report only if it's not already present - // and if there is an empty slot. - for (uint8_t i = 0; i < sizeof(_keyReport.keycodes); i++) { - if (_keyReport.keycodes[i] != k) { // is k already in list? - if (0 == _keyReport.keycodes[i]) { // have we found an empty slot? - _keyReport.keycodes[i] = k; - done = 1; - break; - } - } else { - done = 1; - break; - } - } - // use separate variable to check if slot was found - // for style reasons - we do not know how the compiler - // handles the for() index when it leaves the loop - if (0 == done) { - return 0; + uint8_t done = 0; + + if ((k >= HID_KEYBOARD_FIRST_MODIFIER) && (k <= HID_KEYBOARD_LAST_MODIFIER)) { + // it's a modifier key + _keyReport.modifiers |= (0x01 << (k - HID_KEYBOARD_FIRST_MODIFIER)); + } else { + // it's some other key: + // Add k to the key report only if it's not already present + // and if there is an empty slot. + for (uint8_t i = 0; i < sizeof(_keyReport.keycodes); i++) { + if (_keyReport.keycodes[i] != k) { // is k already in list? + if (0 == _keyReport.keycodes[i]) { // have we found an empty slot? + _keyReport.keycodes[i] = k; + done = 1; + break; } + } else { + done = 1; + break; + } } - return 1; + // use separate variable to check if slot was found + // for style reasons - we do not know how the compiler + // handles the for() index when it leaves the loop + if (0 == done) { + return 0; + } + } + return 1; } @@ -269,43 +269,43 @@ size_t BootKeyboard_::press(uint8_t k) { // it shouldn't be repeated any more. size_t BootKeyboard_::release(uint8_t k) { - if ((k >= HID_KEYBOARD_FIRST_MODIFIER) && (k <= HID_KEYBOARD_LAST_MODIFIER)) { - // it's a modifier key - _keyReport.modifiers = _keyReport.modifiers & (~(0x01 << (k - HID_KEYBOARD_FIRST_MODIFIER))); - } else { - // it's some other key: - // 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 (uint8_t i = 0; i < sizeof(_keyReport.keycodes); i++) { - if (_keyReport.keycodes[i] == k) { - _keyReport.keycodes[i] = 0; - } - } + if ((k >= HID_KEYBOARD_FIRST_MODIFIER) && (k <= HID_KEYBOARD_LAST_MODIFIER)) { + // it's a modifier key + _keyReport.modifiers = _keyReport.modifiers & (~(0x01 << (k - HID_KEYBOARD_FIRST_MODIFIER))); + } else { + // it's some other key: + // 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 (uint8_t i = 0; i < sizeof(_keyReport.keycodes); i++) { + if (_keyReport.keycodes[i] == k) { + _keyReport.keycodes[i] = 0; + } + } - // rearrange the keys list so that the free (= 0x00) are at the - // end of the keys list - some implementations stop for keys at the - // first occurence of an 0x00 in the keys list - // so (0x00)(0x01)(0x00)(0x03)(0x02)(0x00) becomes - // (0x03)(0x02)(0x01)(0x00)(0x00)(0x00) - uint8_t current = 0, nextpos = 0; - - while (current < sizeof(_keyReport.keycodes)) { - if (_keyReport.keycodes[current]) { - uint8_t tmp = _keyReport.keycodes[nextpos]; - _keyReport.keycodes[nextpos] = _keyReport.keycodes[current]; - _keyReport.keycodes[current] = tmp; - ++nextpos; - } - ++current; - } + // rearrange the keys list so that the free (= 0x00) are at the + // end of the keys list - some implementations stop for keys at the + // first occurence of an 0x00 in the keys list + // so (0x00)(0x01)(0x00)(0x03)(0x02)(0x00) becomes + // (0x03)(0x02)(0x01)(0x00)(0x00)(0x00) + uint8_t current = 0, nextpos = 0; + + while (current < sizeof(_keyReport.keycodes)) { + if (_keyReport.keycodes[current]) { + uint8_t tmp = _keyReport.keycodes[nextpos]; + _keyReport.keycodes[nextpos] = _keyReport.keycodes[current]; + _keyReport.keycodes[current] = tmp; + ++nextpos; + } + ++current; } + } - return 1; + return 1; } void BootKeyboard_::releaseAll(void) { - memset(&_keyReport.bytes, 0x00, sizeof(_keyReport.bytes)); + memset(&_keyReport.bytes, 0x00, sizeof(_keyReport.bytes)); } @@ -313,24 +313,24 @@ void BootKeyboard_::releaseAll(void) { * Returns false in all other cases * */ boolean BootKeyboard_::isKeyPressed(uint8_t k) { - for (uint8_t i = 0; i < sizeof(_keyReport.keycodes); i++) { - if (_keyReport.keycodes[i] == k) { - return true; - } + for (uint8_t i = 0; i < sizeof(_keyReport.keycodes); i++) { + if (_keyReport.keycodes[i] == k) { + return true; } - return false; + } + return false; } /* Returns true if the non-modifer key passed in was sent during the previous key report * Returns false in all other cases * */ boolean BootKeyboard_::wasKeyPressed(uint8_t k) { - for (uint8_t i = 0; i < sizeof(_keyReport.keycodes); i++) { - if (_lastKeyReport.keycodes[i] == k) { - return true; - } + for (uint8_t i = 0; i < sizeof(_keyReport.keycodes); i++) { + if (_lastKeyReport.keycodes[i] == k) { + return true; } - return false; + } + return false; } @@ -339,36 +339,36 @@ boolean BootKeyboard_::wasKeyPressed(uint8_t k) { * Returns false in all other cases * */ boolean BootKeyboard_::isModifierActive(uint8_t k) { - if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { - k = k - HID_KEYBOARD_FIRST_MODIFIER; - return !!(_keyReport.modifiers & (1 << k)); - } - return false; + if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { + k = k - HID_KEYBOARD_FIRST_MODIFIER; + return !!(_keyReport.modifiers & (1 << k)); + } + return false; } /* Returns true if the modifer key passed in was being sent during the previous key report * Returns false in all other cases * */ boolean BootKeyboard_::wasModifierActive(uint8_t k) { - if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { - k = k - HID_KEYBOARD_FIRST_MODIFIER; - return !!(_lastKeyReport.modifiers & (1 << k)); - } - return false; + if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { + k = k - HID_KEYBOARD_FIRST_MODIFIER; + return !!(_lastKeyReport.modifiers & (1 << k)); + } + return false; } /* Returns true if any modifier key will be sent during this key report * Returns false in all other cases * */ boolean BootKeyboard_::isAnyModifierActive() { - return _keyReport.modifiers > 0; + return _keyReport.modifiers > 0; } /* Returns true if any modifier key was being sent during the previous key report * Returns false in all other cases * */ boolean BootKeyboard_::wasAnyModifierActive() { - return _lastKeyReport.modifiers > 0; + return _lastKeyReport.modifiers > 0; } BootKeyboard_ BootKeyboard; diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index 3cfe7b12a5..50760af26a 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -33,52 +33,52 @@ THE SOFTWARE. #include "HIDAliases.h" typedef union { - // Low level key report: up to 6 keys and shift, ctrl etc at once - struct { - uint8_t modifiers; - uint8_t reserved; - uint8_t keycodes[6]; - }; - uint8_t bytes[8]; + // Low level key report: up to 6 keys and shift, ctrl etc at once + struct { + uint8_t modifiers; + uint8_t reserved; + uint8_t keycodes[6]; + }; + uint8_t bytes[8]; } HID_BootKeyboardReport_Data_t; class BootKeyboard_ : public PluggableUSBModule { - public: - BootKeyboard_(void); - size_t press(uint8_t); - void begin(void); - void end(void); - size_t release(uint8_t); - void releaseAll(void); - - int sendReport(void); - - boolean isModifierActive(uint8_t k); - boolean wasModifierActive(uint8_t k); - boolean isAnyModifierActive(); - boolean wasAnyModifierActive(); - boolean isKeyPressed(uint8_t k); - boolean wasKeyPressed(uint8_t k); - - uint8_t getLeds(void); - uint8_t getProtocol(void); - void setProtocol(uint8_t protocol); - - uint8_t default_protocol = HID_REPORT_PROTOCOL; - - protected: - HID_BootKeyboardReport_Data_t _keyReport, _lastKeyReport; - - // Implementation of the PUSBListNode - int getInterface(uint8_t* interfaceCount); - int getDescriptor(USBSetup& setup); - bool setup(USBSetup& setup); - - EPTYPE_DESCRIPTOR_SIZE epType[1]; - uint8_t protocol; - uint8_t idle; - - uint8_t leds; + public: + BootKeyboard_(void); + size_t press(uint8_t); + void begin(void); + void end(void); + size_t release(uint8_t); + void releaseAll(void); + + int sendReport(void); + + boolean isModifierActive(uint8_t k); + boolean wasModifierActive(uint8_t k); + boolean isAnyModifierActive(); + boolean wasAnyModifierActive(); + boolean isKeyPressed(uint8_t k); + boolean wasKeyPressed(uint8_t k); + + uint8_t getLeds(void); + uint8_t getProtocol(void); + void setProtocol(uint8_t protocol); + + uint8_t default_protocol = HID_REPORT_PROTOCOL; + + protected: + HID_BootKeyboardReport_Data_t _keyReport, _lastKeyReport; + + // Implementation of the PUSBListNode + int getInterface(uint8_t* interfaceCount); + int getDescriptor(USBSetup& setup); + bool setup(USBSetup& setup); + + EPTYPE_DESCRIPTOR_SIZE epType[1]; + uint8_t protocol; + uint8_t idle; + + uint8_t leds; }; extern BootKeyboard_ BootKeyboard; diff --git a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h index e3ffa18cf2..36cfef147d 100644 --- a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h +++ b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h @@ -65,38 +65,38 @@ THE SOFTWARE. D_INPUT, (D_DATA|D_VARIABLE|D_RELATIVE), typedef union { - // Absolute mouse report: 8 buttons, 2 absolute axis, wheel - struct { - uint8_t buttons; - uint16_t xAxis; - uint16_t yAxis; - int8_t wheel; - }; -} HID_MouseAbsoluteReport_Data_t; - -class AbsoluteMouseAPI { - public: - inline AbsoluteMouseAPI(void); - inline void begin(void); - inline void end(void); - - inline void click(uint8_t b = MOUSE_LEFT); - inline void moveTo(uint16_t x, uint16_t y, signed char wheel = 0); - inline void move(int x, int y, signed char wheel = 0); - inline void press(uint8_t b = MOUSE_LEFT); - inline void release(uint8_t b = MOUSE_LEFT); - inline bool isPressed(uint8_t b = MOUSE_LEFT); - - // Sending is public in the base class for advanced users. - virtual void sendReport(void* data, int length) {} - - protected: + // Absolute mouse report: 8 buttons, 2 absolute axis, wheel + struct { + uint8_t buttons; uint16_t xAxis; uint16_t yAxis; - uint8_t _buttons; + int8_t wheel; + }; +} HID_MouseAbsoluteReport_Data_t; - inline void buttons(uint8_t b); - inline int16_t qadd16(int16_t base, int16_t increment); +class AbsoluteMouseAPI { + public: + inline AbsoluteMouseAPI(void); + inline void begin(void); + inline void end(void); + + inline void click(uint8_t b = MOUSE_LEFT); + inline void moveTo(uint16_t x, uint16_t y, signed char wheel = 0); + inline void move(int x, int y, signed char wheel = 0); + inline void press(uint8_t b = MOUSE_LEFT); + inline void release(uint8_t b = MOUSE_LEFT); + inline bool isPressed(uint8_t b = MOUSE_LEFT); + + // Sending is public in the base class for advanced users. + virtual void sendReport(void* data, int length) {} + + protected: + uint16_t xAxis; + uint16_t yAxis; + uint8_t _buttons; + + inline void buttons(uint8_t b); + inline int16_t qadd16(int16_t base, int16_t increment); }; #include "AbsoluteMouseAPI.hpp" diff --git a/plugins/KeyboardioHID/src/HID.cpp b/plugins/KeyboardioHID/src/HID.cpp index 54ed9df7bc..34a223cc5d 100644 --- a/plugins/KeyboardioHID/src/HID.cpp +++ b/plugins/KeyboardioHID/src/HID.cpp @@ -24,80 +24,80 @@ #if defined(USBCON) HID_& HID() { - static HID_ obj; - return obj; + static HID_ obj; + return obj; } int HID_::getInterface(uint8_t* interfaceCount) { - *interfaceCount += 1; // uses 1 - HIDDescriptor hidInterface = { - D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE), - D_HIDREPORT(descriptorSize), - D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) - }; - return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); + *interfaceCount += 1; // uses 1 + HIDDescriptor hidInterface = { + D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE), + D_HIDREPORT(descriptorSize), + D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) + }; + return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); } int HID_::getDescriptor(USBSetup& setup) { - // Check if this is a HID Class Descriptor request - if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { - return 0; - } - if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { - return 0; - } - - // In a HID Class Descriptor wIndex cointains the interface number - if (setup.wIndex != pluggedInterface) { - return 0; - } - - int total = 0; - HIDSubDescriptor* node; - USB_PackMessages(true); - for (node = rootNode; node; node = node->next) { - int res = USB_SendControl(TRANSFER_PGM, node->data, node->length); - if (res == -1) - return -1; - total += res; - } - - // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol - // due to the USB specs, but Windows and Linux just assumes its in report mode. - protocol = HID_REPORT_PROTOCOL; + // Check if this is a HID Class Descriptor request + if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { + return 0; + } + if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { + return 0; + } - USB_PackMessages(false); - return total; + // In a HID Class Descriptor wIndex cointains the interface number + if (setup.wIndex != pluggedInterface) { + return 0; + } + + int total = 0; + HIDSubDescriptor* node; + USB_PackMessages(true); + for (node = rootNode; node; node = node->next) { + int res = USB_SendControl(TRANSFER_PGM, node->data, node->length); + if (res == -1) + return -1; + total += res; + } + + // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol + // due to the USB specs, but Windows and Linux just assumes its in report mode. + protocol = HID_REPORT_PROTOCOL; + + USB_PackMessages(false); + return total; } __attribute__((weak)) uint8_t HID_::getShortName(char *name) { - name[0] = 'k'; - name[1] = 'b'; - name[2] = 'i'; - name[3] = 'o'; - name[4] = '0'; - name[5] = '1'; - return 6; + name[0] = 'k'; + name[1] = 'b'; + name[2] = 'i'; + name[3] = 'o'; + name[4] = '0'; + name[5] = '1'; + return 6; } void HID_::AppendDescriptor(HIDSubDescriptor *node) { - if (!rootNode) { - rootNode = node; - } else { - HIDSubDescriptor *current = rootNode; - while (current->next) { - current = current->next; - } - current->next = node; + if (!rootNode) { + rootNode = node; + } else { + HIDSubDescriptor *current = rootNode; + while (current->next) { + current = current->next; } - descriptorSize += node->length; + current->next = node; + } + descriptorSize += node->length; } int HID_::SendReport(uint8_t id, const void* data, int len) { - auto result = SendReport_(id, data, len); - HIDReportObserver::observeReport(id, data, len, result); - return result; + auto result = SendReport_(id, data, len); + HIDReportObserver::observeReport(id, data, len, result); + return result; } int HID_::SendReport_(uint8_t id, const void* data, int len) { @@ -109,78 +109,78 @@ int HID_::SendReport_(uint8_t id, const void* data, int len) { * costs RAM, which is something scarce on AVR. So on that platform, we opt to * send the id and the report separately instead. */ #ifdef ARDUINO_ARCH_SAMD - uint8_t p[64]; - p[0] = id; - memcpy(&p[1], data, len); - return USB_Send(pluggedEndpoint, p, len+1); + uint8_t p[64]; + p[0] = id; + memcpy(&p[1], data, len); + return USB_Send(pluggedEndpoint, p, len + 1); #else - auto ret = USB_Send(pluggedEndpoint, &id, 1); - if (ret < 0) return ret; - auto ret2 = USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, len); - if (ret2 < 0) return ret2; - return ret + ret2; + auto ret = USB_Send(pluggedEndpoint, &id, 1); + if (ret < 0) return ret; + auto ret2 = USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, len); + if (ret2 < 0) return ret2; + return ret + ret2; #endif } bool HID_::setup(USBSetup& setup) { - if (pluggedInterface != setup.wIndex) { - return false; - } + if (pluggedInterface != setup.wIndex) { + return false; + } - uint8_t request = setup.bRequest; - uint8_t requestType = setup.bmRequestType; - - if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) { - if (request == HID_GET_REPORT) { - // TODO: HID_GetReport(); - return true; - } - if (request == HID_GET_PROTOCOL) { - // TODO: Send8(protocol); - return true; - } - if (request == HID_GET_IDLE) { - // TODO: Send8(idle); - } - } + uint8_t request = setup.bRequest; + uint8_t requestType = setup.bmRequestType; - if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) { - if (request == HID_SET_PROTOCOL) { - // The USB Host tells us if we are in boot or report mode. - // This only works with a real boot compatible device. - protocol = setup.wValueL; - return true; - } - if (request == HID_SET_IDLE) { - idle = setup.wValueL; - return true; - } - if (request == HID_SET_REPORT) { - uint16_t length = setup.wLength; - - if (length == sizeof(setReportData)) { - USB_RecvControl(&setReportData, length); - } else if (length == sizeof(setReportData.leds)) { - USB_RecvControl(&setReportData.leds, length); - setReportData.reportId = 0; - } - } + if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) { + if (request == HID_GET_REPORT) { + // TODO: HID_GetReport(); + return true; + } + if (request == HID_GET_PROTOCOL) { + // TODO: Send8(protocol); + return true; + } + if (request == HID_GET_IDLE) { + // TODO: Send8(idle); } + } + + if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) { + if (request == HID_SET_PROTOCOL) { + // The USB Host tells us if we are in boot or report mode. + // This only works with a real boot compatible device. + protocol = setup.wValueL; + return true; + } + if (request == HID_SET_IDLE) { + idle = setup.wValueL; + return true; + } + if (request == HID_SET_REPORT) { + uint16_t length = setup.wLength; + + if (length == sizeof(setReportData)) { + USB_RecvControl(&setReportData, length); + } else if (length == sizeof(setReportData.leds)) { + USB_RecvControl(&setReportData.leds, length); + setReportData.reportId = 0; + } + } + } - return false; + return false; } HID_::HID_(void) : PluggableUSBModule(1, 1, epType), - rootNode(NULL), descriptorSize(0), - protocol(HID_REPORT_PROTOCOL), idle(1) { - setReportData.reportId = 0; - setReportData.leds = 0; - epType[0] = EP_TYPE_INTERRUPT_IN; - PluggableUSB().plug(this); + rootNode(NULL), descriptorSize(0), + protocol(HID_REPORT_PROTOCOL), idle(1) { + setReportData.reportId = 0; + setReportData.leds = 0; + epType[0] = EP_TYPE_INTERRUPT_IN; + PluggableUSB().plug(this); } int HID_::begin(void) { - return 0; + return 0; } #endif /* if defined(USBCON) */ diff --git a/plugins/KeyboardioHID/src/HID.h b/plugins/KeyboardioHID/src/HID.h index 44995e9cb3..f890b337b4 100644 --- a/plugins/KeyboardioHID/src/HID.h +++ b/plugins/KeyboardioHID/src/HID.h @@ -60,63 +60,63 @@ #define HID_REPORT_TYPE_FEATURE 3 typedef struct { - uint8_t len; // 9 - uint8_t dtype; // 0x21 - uint8_t addr; - uint8_t versionL; // 0x101 - uint8_t versionH; // 0x101 - uint8_t country; - uint8_t desctype; // 0x22 report - uint8_t descLenL; - uint8_t descLenH; + uint8_t len; // 9 + uint8_t dtype; // 0x21 + uint8_t addr; + uint8_t versionL; // 0x101 + uint8_t versionH; // 0x101 + uint8_t country; + uint8_t desctype; // 0x22 report + uint8_t descLenL; + uint8_t descLenH; } HIDDescDescriptor; typedef struct { - InterfaceDescriptor hid; - HIDDescDescriptor desc; - EndpointDescriptor in; + InterfaceDescriptor hid; + HIDDescDescriptor desc; + EndpointDescriptor in; } HIDDescriptor; class HIDSubDescriptor { - public: - HIDSubDescriptor *next = NULL; - HIDSubDescriptor(const void *d, const uint16_t l) : data(d), length(l) { } + public: + HIDSubDescriptor *next = NULL; + HIDSubDescriptor(const void *d, const uint16_t l) : data(d), length(l) { } - const void* data; - const uint16_t length; + const void* data; + const uint16_t length; }; class HID_ : public PluggableUSBModule { - public: - - HID_(void); - int begin(void); - int SendReport(uint8_t id, const void* data, int len); - void AppendDescriptor(HIDSubDescriptor* node); - uint8_t getLEDs(void) { - return setReportData.leds; - }; - - protected: - // Implementation of the PluggableUSBModule - int getInterface(uint8_t* interfaceCount); - int getDescriptor(USBSetup& setup); - bool setup(USBSetup& setup); - uint8_t getShortName(char* name); - - int SendReport_(uint8_t id, const void* data, int len); - private: - EPTYPE_DESCRIPTOR_SIZE epType[1]; - - HIDSubDescriptor* rootNode; - uint16_t descriptorSize; - - uint8_t protocol; - uint8_t idle; - struct { - uint8_t reportId; - uint8_t leds; - } setReportData; + public: + + HID_(void); + int begin(void); + int SendReport(uint8_t id, const void* data, int len); + void AppendDescriptor(HIDSubDescriptor* node); + uint8_t getLEDs(void) { + return setReportData.leds; + }; + + protected: + // Implementation of the PluggableUSBModule + int getInterface(uint8_t* interfaceCount); + int getDescriptor(USBSetup& setup); + bool setup(USBSetup& setup); + uint8_t getShortName(char* name); + + int SendReport_(uint8_t id, const void* data, int len); + private: + EPTYPE_DESCRIPTOR_SIZE epType[1]; + + HIDSubDescriptor* rootNode; + uint16_t descriptorSize; + + uint8_t protocol; + uint8_t idle; + struct { + uint8_t reportId; + uint8_t leds; + } setReportData; }; // Replacement for global singleton. diff --git a/plugins/KeyboardioHID/src/HIDReportObserver.h b/plugins/KeyboardioHID/src/HIDReportObserver.h index 2a94ca7a0c..23de69914e 100644 --- a/plugins/KeyboardioHID/src/HIDReportObserver.h +++ b/plugins/KeyboardioHID/src/HIDReportObserver.h @@ -26,29 +26,30 @@ THE SOFTWARE. #include -class HIDReportObserver -{ - public: - - typedef void(*SendReportHook)(uint8_t id, const void* data, - int len, int result); - - static void observeReport(uint8_t id, const void* data, - int len, int result) { - if(send_report_hook_) { - (*send_report_hook_)(id, data, len, result); - } +class HIDReportObserver { + public: + + typedef void(*SendReportHook)(uint8_t id, const void* data, + int len, int result); + + static void observeReport(uint8_t id, const void* data, + int len, int result) { + if (send_report_hook_) { + (*send_report_hook_)(id, data, len, result); } - - static SendReportHook currentHook() { return send_report_hook_; } - - static SendReportHook resetHook(SendReportHook new_hook) { - auto previous_hook = send_report_hook_; - send_report_hook_ = new_hook; - return previous_hook; - } - - private: - - static SendReportHook send_report_hook_; + } + + static SendReportHook currentHook() { + return send_report_hook_; + } + + static SendReportHook resetHook(SendReportHook new_hook) { + auto previous_hook = send_report_hook_; + send_report_hook_ = new_hook; + return previous_hook; + } + + private: + + static SendReportHook send_report_hook_; }; diff --git a/plugins/KeyboardioHID/src/HIDTables.h b/plugins/KeyboardioHID/src/HIDTables.h index 02325b3ade..168c687e83 100644 --- a/plugins/KeyboardioHID/src/HIDTables.h +++ b/plugins/KeyboardioHID/src/HIDTables.h @@ -38,7 +38,7 @@ THE SOFTWARE. // Not every HID usage listed in this file is currently supported by Arduino // In particular, any System Control or Consumer Control entry that doesn't // have a comment indicating that it's "HID type OSC" may require additional -// code in the Arduino core to work, although // some keycodes with usage +// code in the Arduino core to work, although // some keycodes with usage // type RTC (Re-Trigger Control) and OOC (On/Off Control) are also functional. // // Non-working usages are listed here in the interest of not having to manually diff --git a/plugins/KeyboardioHID/src/LEDs.h b/plugins/KeyboardioHID/src/LEDs.h index e1df22ac5a..2df7e6b00b 100644 --- a/plugins/KeyboardioHID/src/LEDs.h +++ b/plugins/KeyboardioHID/src/LEDs.h @@ -27,12 +27,12 @@ THE SOFTWARE. // Keyboard Leds enum KeyboardLeds : uint8_t { - LED_NUM_LOCK = (1 << 0), - LED_CAPS_LOCK = (1 << 1), - LED_SCROLL_LOCK = (1 << 2), - LED_COMPOSE = (1 << 3), - LED_KANA = (1 << 4), - LED_POWER = (1 << 5), - LED_SHIFT = (1 << 6), - LED_DO_NOT_DISTURB = (1 << 7), + LED_NUM_LOCK = (1 << 0), + LED_CAPS_LOCK = (1 << 1), + LED_SCROLL_LOCK = (1 << 2), + LED_COMPOSE = (1 << 3), + LED_KANA = (1 << 4), + LED_POWER = (1 << 5), + LED_SHIFT = (1 << 6), + LED_DO_NOT_DISTURB = (1 << 7), }; diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp index e7f74411e9..a6b10618f2 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp @@ -27,27 +27,27 @@ THE SOFTWARE. #include "DescriptorPrimitives.h" static const uint8_t _hidMultiReportDescriptorAbsoluteMouse[] PROGMEM = { - /* Mouse absolute */ - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) 54 */ - D_USAGE, D_USAGE_MOUSE, /* USAGE (Mouse) */ - D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ - D_REPORT_ID, HID_REPORTID_MOUSE_ABSOLUTE, /* REPORT_ID */ + /* Mouse absolute */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) 54 */ + D_USAGE, D_USAGE_MOUSE, /* USAGE (Mouse) */ + D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ + D_REPORT_ID, HID_REPORTID_MOUSE_ABSOLUTE, /* REPORT_ID */ - DESCRIPTOR_ABS_MOUSE_BUTTONS - DESCRIPTOR_ABS_MOUSE_XY - DESCRIPTOR_ABS_MOUSE_WHEEL + DESCRIPTOR_ABS_MOUSE_BUTTONS + DESCRIPTOR_ABS_MOUSE_XY + DESCRIPTOR_ABS_MOUSE_WHEEL - D_END_COLLECTION /* End */ + D_END_COLLECTION /* End */ }; AbsoluteMouse_::AbsoluteMouse_(void) { - static HIDSubDescriptor node(_hidMultiReportDescriptorAbsoluteMouse, sizeof(_hidMultiReportDescriptorAbsoluteMouse)); - HID().AppendDescriptor(&node); + static HIDSubDescriptor node(_hidMultiReportDescriptorAbsoluteMouse, sizeof(_hidMultiReportDescriptorAbsoluteMouse)); + HID().AppendDescriptor(&node); } void AbsoluteMouse_::sendReport(void* data, int length) { - HID().SendReport(HID_REPORTID_MOUSE_ABSOLUTE, data, length); + HID().SendReport(HID_REPORTID_MOUSE_ABSOLUTE, data, length); } AbsoluteMouse_ AbsoluteMouse; diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h index 0de95a29a0..4b536a029c 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h @@ -32,12 +32,12 @@ THE SOFTWARE. #include "../DeviceAPIs/AbsoluteMouseAPI.h" class AbsoluteMouse_ : public AbsoluteMouseAPI { - public: - AbsoluteMouse_(void); + public: + AbsoluteMouse_(void); - protected: - // Sending is public in the base class for advanced users. - virtual void sendReport(void* data, int length); + protected: + // Sending is public in the base class for advanced users. + virtual void sendReport(void* data, int length); }; extern AbsoluteMouse_ AbsoluteMouse; diff --git a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp index dc6876cb55..ddac89a12e 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp @@ -27,81 +27,81 @@ THE SOFTWARE. #include "DescriptorPrimitives.h" static const uint8_t _hidMultiReportDescriptorConsumer[] PROGMEM = { - /* Consumer Control (Sound/Media keys) */ - D_USAGE_PAGE, 0x0C, /* usage page (consumer device) */ - D_USAGE, 0x01, /* usage -- consumer control */ - D_COLLECTION, D_APPLICATION, /* collection (application) */ - D_REPORT_ID, HID_REPORTID_CONSUMERCONTROL, /* report id */ - /* 4 Media Keys */ - D_LOGICAL_MINIMUM, 0x00, /* logical minimum */ - D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xFF, 0x03, /* logical maximum (3ff) */ - D_USAGE_MINIMUM, 0x00, /* usage minimum (0) */ - D_MULTIBYTE(D_USAGE_MAXIMUM), 0xFF, 0x03, /* usage maximum (3ff) */ - D_REPORT_COUNT, 0x04, /* report count (4) */ - D_REPORT_SIZE, 0x10, /* report size (16) */ - D_INPUT, 0x00, /* input */ - D_END_COLLECTION /* end collection */ + /* Consumer Control (Sound/Media keys) */ + D_USAGE_PAGE, 0x0C, /* usage page (consumer device) */ + D_USAGE, 0x01, /* usage -- consumer control */ + D_COLLECTION, D_APPLICATION, /* collection (application) */ + D_REPORT_ID, HID_REPORTID_CONSUMERCONTROL, /* report id */ + /* 4 Media Keys */ + D_LOGICAL_MINIMUM, 0x00, /* logical minimum */ + D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xFF, 0x03, /* logical maximum (3ff) */ + D_USAGE_MINIMUM, 0x00, /* usage minimum (0) */ + D_MULTIBYTE(D_USAGE_MAXIMUM), 0xFF, 0x03, /* usage maximum (3ff) */ + D_REPORT_COUNT, 0x04, /* report count (4) */ + D_REPORT_SIZE, 0x10, /* report size (16) */ + D_INPUT, 0x00, /* input */ + D_END_COLLECTION /* end collection */ }; ConsumerControl_::ConsumerControl_(void) { - static HIDSubDescriptor node(_hidMultiReportDescriptorConsumer, sizeof(_hidMultiReportDescriptorConsumer)); - HID().AppendDescriptor(&node); + static HIDSubDescriptor node(_hidMultiReportDescriptorConsumer, sizeof(_hidMultiReportDescriptorConsumer)); + HID().AppendDescriptor(&node); } void ConsumerControl_::begin(void) { - // release all buttons - end(); + // release all buttons + end(); } void ConsumerControl_::end(void) { - memset(&_report, 0, sizeof(_report)); - sendReport(); + memset(&_report, 0, sizeof(_report)); + sendReport(); } void ConsumerControl_::write(uint16_t m) { - press(m); - release(m); + press(m); + release(m); } void ConsumerControl_::press(uint16_t m) { - // search for a free spot - for (uint8_t i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { - if (_report.keys[i] == 0x00) { - _report.keys[i] = m; - break; - } + // search for a free spot + for (uint8_t i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { + if (_report.keys[i] == 0x00) { + _report.keys[i] = m; + break; } + } } void ConsumerControl_::release(uint16_t m) { - // search and release the keypress - for (uint8_t i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { - if (_report.keys[i] == m) { - _report.keys[i] = 0x00; - // no break to delete multiple keys - } + // search and release the keypress + for (uint8_t i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { + if (_report.keys[i] == m) { + _report.keys[i] = 0x00; + // no break to delete multiple keys } + } } void ConsumerControl_::releaseAll(void) { - memset(&_report, 0, sizeof(_report)); + memset(&_report, 0, sizeof(_report)); } void ConsumerControl_::sendReportUnchecked(void) { - HID().SendReport(HID_REPORTID_CONSUMERCONTROL, &_report, sizeof(_report)); + HID().SendReport(HID_REPORTID_CONSUMERCONTROL, &_report, sizeof(_report)); } void ConsumerControl_::sendReport(void) { - // If the last report is different than the current report, then we need to send a report. - // We guard sendReport like this so that calling code doesn't end up spamming the host with empty reports - // if sendReport is called in a tight loop. + // If the last report is different than the current report, then we need to send a report. + // We guard sendReport like this so that calling code doesn't end up spamming the host with empty reports + // if sendReport is called in a tight loop. - // if the previous report is the same, return early without a new report. - if (memcmp(&_lastReport, &_report, sizeof(_report)) == 0) - return; + // if the previous report is the same, return early without a new report. + if (memcmp(&_lastReport, &_report, sizeof(_report)) == 0) + return; - sendReportUnchecked(); - memcpy(&_lastReport, &_report, sizeof(_report)); + sendReportUnchecked(); + memcpy(&_lastReport, &_report, sizeof(_report)); } ConsumerControl_ ConsumerControl; diff --git a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h index b918bd760e..ecd122ec6b 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h +++ b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h @@ -31,35 +31,35 @@ THE SOFTWARE. #include "HID-Settings.h" typedef union { - // Every usable Consumer key possible, up to 4 keys presses possible - uint16_t keys[4]; - struct { - uint16_t key1; - uint16_t key2; - uint16_t key3; - uint16_t key4; - }; + // Every usable Consumer key possible, up to 4 keys presses possible + uint16_t keys[4]; + struct { + uint16_t key1; + uint16_t key2; + uint16_t key3; + uint16_t key4; + }; } HID_ConsumerControlReport_Data_t; class ConsumerControl_ { - public: - ConsumerControl_(void); - void begin(void); - void end(void); - void write(uint16_t m); - void press(uint16_t m); - void release(uint16_t m); - void releaseAll(void); + public: + ConsumerControl_(void); + void begin(void); + void end(void); + void write(uint16_t m); + void press(uint16_t m); + void release(uint16_t m); + void releaseAll(void); - // Sending is public in the base class for advanced users. - void sendReport(void); + // Sending is public in the base class for advanced users. + void sendReport(void); - protected: - HID_ConsumerControlReport_Data_t _report; - HID_ConsumerControlReport_Data_t _lastReport; + protected: + HID_ConsumerControlReport_Data_t _report; + HID_ConsumerControlReport_Data_t _lastReport; - private: - void sendReportUnchecked(void); + private: + void sendReportUnchecked(void); }; extern ConsumerControl_ ConsumerControl; diff --git a/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp b/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp index 4bd4187679..1c0895e130 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp @@ -27,136 +27,136 @@ THE SOFTWARE. #include "DescriptorPrimitives.h" static const uint8_t _hidMultiReportDescriptorGamepad[] PROGMEM = { - /* Gamepad with 32 buttons and 6 axis*/ - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ - D_USAGE, D_USAGE_JOYSTICK, /* USAGE (Joystick) */ - D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ - D_REPORT_ID, HID_REPORTID_GAMEPAD, /* REPORT_ID */ - /* 32 Buttons */ - D_USAGE_PAGE, D_PAGE_BUTTON, /* USAGE_PAGE (Button) */ - D_USAGE_MINIMUM, 0x01, /* USAGE_MINIMUM (Button 1) */ - D_USAGE_MAXIMUM, 0x20, /* USAGE_MAXIMUM (Button 32) */ - D_LOGICAL_MINIMUM, 0x00, /* _LOGICAL_MINIMUM (0) */ - D_LOGICAL_MAXIMUM, 0x01, /* _LOGICAL_MAXIMUM (1) */ - D_REPORT_SIZE, 0x01, /* REPORT_SIZE (1) */ - D_REPORT_COUNT, 0x20, /* REPORT_COUNT (32) */ - D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ - /* 4 16bit Axis */ - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ - D_COLLECTION, D_PHYSICAL, /* COLLECTION (Physical) */ - D_USAGE, 0x30, /* USAGE (X) */ - D_USAGE, 0x31, /* USAGE (Y) */ - D_USAGE, 0x33, /* USAGE (Rx) */ - D_USAGE, 0x34, /* USAGE (Ry) */ - D_MULTIBYTE(D_LOGICAL_MINIMUM), 0x00, 0x80, /* _LOGICAL_MINIMUM (-32768) */ - D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xFF, 0x7F, /* _LOGICAL_MAXIMUM (32767) */ - D_REPORT_SIZE, 0x10, /* REPORT_SIZE (16) */ - D_REPORT_COUNT, 0x04, /* REPORT_COUNT (4) */ - D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ - /* 2 8bit Axis */ - D_USAGE, 0x32, /* USAGE (Z) */ - D_USAGE, 0x35, /* USAGE (Rz) */ - D_LOGICAL_MINIMUM, 0x80, /* _LOGICAL_MINIMUM (-128) */ - D_LOGICAL_MAXIMUM, 0x7F, /* _LOGICAL_MAXIMUM (127) */ - D_REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ - D_REPORT_COUNT, 0x02, /* REPORT_COUNT (2) */ - D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ - D_END_COLLECTION, /* END_COLLECTION */ - - /* 2 Hat Switches */ - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ - D_USAGE, 0x39, /* USAGE (Hat switch) */ - D_USAGE, 0x39, /* USAGE (Hat switch) */ - D_LOGICAL_MINIMUM, 0x01, /* _LOGICAL_MINIMUM (1) */ - D_LOGICAL_MAXIMUM, 0x08, /* _LOGICAL_MAXIMUM (8) */ - D_REPORT_COUNT, 0x02, /* REPORT_COUNT (2) */ - D_REPORT_SIZE, 0x04, /* REPORT_SIZE (4) */ - D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ - D_END_COLLECTION /* END_COLLECTION */ + /* Gamepad with 32 buttons and 6 axis*/ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ + D_USAGE, D_USAGE_JOYSTICK, /* USAGE (Joystick) */ + D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ + D_REPORT_ID, HID_REPORTID_GAMEPAD, /* REPORT_ID */ + /* 32 Buttons */ + D_USAGE_PAGE, D_PAGE_BUTTON, /* USAGE_PAGE (Button) */ + D_USAGE_MINIMUM, 0x01, /* USAGE_MINIMUM (Button 1) */ + D_USAGE_MAXIMUM, 0x20, /* USAGE_MAXIMUM (Button 32) */ + D_LOGICAL_MINIMUM, 0x00, /* _LOGICAL_MINIMUM (0) */ + D_LOGICAL_MAXIMUM, 0x01, /* _LOGICAL_MAXIMUM (1) */ + D_REPORT_SIZE, 0x01, /* REPORT_SIZE (1) */ + D_REPORT_COUNT, 0x20, /* REPORT_COUNT (32) */ + D_INPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ + /* 4 16bit Axis */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ + D_COLLECTION, D_PHYSICAL, /* COLLECTION (Physical) */ + D_USAGE, 0x30, /* USAGE (X) */ + D_USAGE, 0x31, /* USAGE (Y) */ + D_USAGE, 0x33, /* USAGE (Rx) */ + D_USAGE, 0x34, /* USAGE (Ry) */ + D_MULTIBYTE(D_LOGICAL_MINIMUM), 0x00, 0x80, /* _LOGICAL_MINIMUM (-32768) */ + D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xFF, 0x7F, /* _LOGICAL_MAXIMUM (32767) */ + D_REPORT_SIZE, 0x10, /* REPORT_SIZE (16) */ + D_REPORT_COUNT, 0x04, /* REPORT_COUNT (4) */ + D_INPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ + /* 2 8bit Axis */ + D_USAGE, 0x32, /* USAGE (Z) */ + D_USAGE, 0x35, /* USAGE (Rz) */ + D_LOGICAL_MINIMUM, 0x80, /* _LOGICAL_MINIMUM (-128) */ + D_LOGICAL_MAXIMUM, 0x7F, /* _LOGICAL_MAXIMUM (127) */ + D_REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ + D_REPORT_COUNT, 0x02, /* REPORT_COUNT (2) */ + D_INPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ + D_END_COLLECTION, /* END_COLLECTION */ + + /* 2 Hat Switches */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ + D_USAGE, 0x39, /* USAGE (Hat switch) */ + D_USAGE, 0x39, /* USAGE (Hat switch) */ + D_LOGICAL_MINIMUM, 0x01, /* _LOGICAL_MINIMUM (1) */ + D_LOGICAL_MAXIMUM, 0x08, /* _LOGICAL_MAXIMUM (8) */ + D_REPORT_COUNT, 0x02, /* REPORT_COUNT (2) */ + D_REPORT_SIZE, 0x04, /* REPORT_SIZE (4) */ + D_INPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ + D_END_COLLECTION /* END_COLLECTION */ }; Gamepad_::Gamepad_(void) { - static HIDSubDescriptor node(_hidMultiReportDescriptorGamepad, sizeof(_hidMultiReportDescriptorGamepad)); - HID().AppendDescriptor(&node); + static HIDSubDescriptor node(_hidMultiReportDescriptorGamepad, sizeof(_hidMultiReportDescriptorGamepad)); + HID().AppendDescriptor(&node); } void Gamepad_::begin(void) { - // release all buttons - end(); + // release all buttons + end(); } void Gamepad_::end(void) { - memset(&_report, 0x00, sizeof(_report)); - sendReport(&_report, sizeof(_report)); + memset(&_report, 0x00, sizeof(_report)); + sendReport(&_report, sizeof(_report)); } void Gamepad_::write(void) { - sendReport(&_report, sizeof(_report)); + sendReport(&_report, sizeof(_report)); } void Gamepad_::press(uint8_t b) { - _report.buttons |= (uint32_t)1 << (b - 1); + _report.buttons |= (uint32_t)1 << (b - 1); } void Gamepad_::release(uint8_t b) { - _report.buttons &= ~((uint32_t)1 << (b - 1)); + _report.buttons &= ~((uint32_t)1 << (b - 1)); } void Gamepad_::releaseAll(void) { - memset(&_report, 0x00, sizeof(_report)); + memset(&_report, 0x00, sizeof(_report)); } void Gamepad_::buttons(uint32_t b) { - _report.buttons = b; + _report.buttons = b; } void Gamepad_::xAxis(int16_t a) { - _report.xAxis = a; + _report.xAxis = a; } void Gamepad_::yAxis(int16_t a) { - _report.yAxis = a; + _report.yAxis = a; } void Gamepad_::zAxis(int8_t a) { - _report.zAxis = a; + _report.zAxis = a; } void Gamepad_::rxAxis(int16_t a) { - _report.rxAxis = a; + _report.rxAxis = a; } void Gamepad_::ryAxis(int16_t a) { - _report.ryAxis = a; + _report.ryAxis = a; } void Gamepad_::rzAxis(int8_t a) { - _report.rzAxis = a; + _report.rzAxis = a; } void Gamepad_::dPad1(int8_t d) { - _report.dPad1 = d; + _report.dPad1 = d; } void Gamepad_::dPad2(int8_t d) { - _report.dPad2 = d; + _report.dPad2 = d; } void Gamepad_::sendReport(void* data, int length) { - HID().SendReport(HID_REPORTID_GAMEPAD, data, length); + HID().SendReport(HID_REPORTID_GAMEPAD, data, length); } Gamepad_ Gamepad; diff --git a/plugins/KeyboardioHID/src/MultiReport/Gamepad.h b/plugins/KeyboardioHID/src/MultiReport/Gamepad.h index 7d299eb032..3dd6b4188a 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Gamepad.h +++ b/plugins/KeyboardioHID/src/MultiReport/Gamepad.h @@ -43,83 +43,83 @@ THE SOFTWARE. typedef union { - // 32 Buttons, 6 Axis, 2 D-Pads - uint32_t buttons; - - struct { - uint8_t button1 : 1; - uint8_t button2 : 1; - uint8_t button3 : 1; - uint8_t button4 : 1; - uint8_t button5 : 1; - uint8_t button6 : 1; - uint8_t button7 : 1; - uint8_t button8 : 1; - - uint8_t button9 : 1; - uint8_t button10 : 1; - uint8_t button11 : 1; - uint8_t button12 : 1; - uint8_t button13 : 1; - uint8_t button14 : 1; - uint8_t button15 : 1; - uint8_t button16 : 1; - - uint8_t button17 : 1; - uint8_t button18 : 1; - uint8_t button19 : 1; - uint8_t button20 : 1; - uint8_t button21 : 1; - uint8_t button22 : 1; - uint8_t button23 : 1; - uint8_t button24 : 1; - - uint8_t button25 : 1; - uint8_t button26 : 1; - uint8_t button27 : 1; - uint8_t button28 : 1; - uint8_t button29 : 1; - uint8_t button30 : 1; - uint8_t button31 : 1; - uint8_t button32 : 1; - - int16_t xAxis; - int16_t yAxis; - - int16_t rxAxis; - int16_t ryAxis; - - int8_t zAxis; - int8_t rzAxis; - - uint8_t dPad1 : 4; - uint8_t dPad2 : 4; - }; + // 32 Buttons, 6 Axis, 2 D-Pads + uint32_t buttons; + + struct { + uint8_t button1 : 1; + uint8_t button2 : 1; + uint8_t button3 : 1; + uint8_t button4 : 1; + uint8_t button5 : 1; + uint8_t button6 : 1; + uint8_t button7 : 1; + uint8_t button8 : 1; + + uint8_t button9 : 1; + uint8_t button10 : 1; + uint8_t button11 : 1; + uint8_t button12 : 1; + uint8_t button13 : 1; + uint8_t button14 : 1; + uint8_t button15 : 1; + uint8_t button16 : 1; + + uint8_t button17 : 1; + uint8_t button18 : 1; + uint8_t button19 : 1; + uint8_t button20 : 1; + uint8_t button21 : 1; + uint8_t button22 : 1; + uint8_t button23 : 1; + uint8_t button24 : 1; + + uint8_t button25 : 1; + uint8_t button26 : 1; + uint8_t button27 : 1; + uint8_t button28 : 1; + uint8_t button29 : 1; + uint8_t button30 : 1; + uint8_t button31 : 1; + uint8_t button32 : 1; + + int16_t xAxis; + int16_t yAxis; + + int16_t rxAxis; + int16_t ryAxis; + + int8_t zAxis; + int8_t rzAxis; + + uint8_t dPad1 : 4; + uint8_t dPad2 : 4; + }; } HID_GamepadReport_Data_t; class Gamepad_ { - public: - Gamepad_(void); - - void begin(void); - void end(void); - void write(void); - void press(uint8_t b); - void release(uint8_t b); - void releaseAll(void); - - void buttons(uint32_t b); - void xAxis(int16_t a); - void yAxis(int16_t a); - void zAxis(int8_t a); - void rxAxis(int16_t a); - void ryAxis(int16_t a); - void rzAxis(int8_t a); - void dPad1(int8_t d); - void dPad2(int8_t d); - - void sendReport(void* data, int length); - protected: - HID_GamepadReport_Data_t _report; + public: + Gamepad_(void); + + void begin(void); + void end(void); + void write(void); + void press(uint8_t b); + void release(uint8_t b); + void releaseAll(void); + + void buttons(uint32_t b); + void xAxis(int16_t a); + void yAxis(int16_t a); + void zAxis(int8_t a); + void rxAxis(int16_t a); + void ryAxis(int16_t a); + void rzAxis(int8_t a); + void dPad1(int8_t d); + void dPad2(int8_t d); + + void sendReport(void* data, int length); + protected: + HID_GamepadReport_Data_t _report; }; extern Gamepad_ Gamepad; diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index 453af3cba8..663cba1405 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -27,164 +27,164 @@ THE SOFTWARE. #include "DescriptorPrimitives.h" static const uint8_t _hidMultiReportDescriptorKeyboard[] PROGMEM = { - // NKRO Keyboard - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, - D_USAGE, D_USAGE_KEYBOARD, - D_COLLECTION, D_APPLICATION, - D_REPORT_ID, HID_REPORTID_NKRO_KEYBOARD, - D_USAGE_PAGE, D_PAGE_KEYBOARD, - - - /* Key modifier byte */ - D_USAGE_MINIMUM, HID_KEYBOARD_FIRST_MODIFIER, - D_USAGE_MAXIMUM, HID_KEYBOARD_LAST_MODIFIER, - D_LOGICAL_MINIMUM, 0x00, - D_LOGICAL_MAXIMUM, 0x01, - D_REPORT_SIZE, 0x01, - D_REPORT_COUNT, 0x08, - D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), - - - /* 5 LEDs for num lock etc, 3 left for advanced, custom usage */ - D_USAGE_PAGE, D_PAGE_LEDS, - D_USAGE_MINIMUM, 0x01, - D_USAGE_MAXIMUM, 0x08, - D_REPORT_COUNT, 0x08, - D_REPORT_SIZE, 0x01, - D_OUTPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), - - /* NKRO Keyboard */ - D_USAGE_PAGE, D_PAGE_KEYBOARD, - - // Padding 4 bits, to skip NO_EVENT & 3 error states. - D_REPORT_SIZE, 0x04, - D_REPORT_COUNT, 0x01, - D_INPUT, (D_CONSTANT), - - D_USAGE_MINIMUM, HID_KEYBOARD_A_AND_A, - D_USAGE_MAXIMUM, HID_LAST_KEY, - D_LOGICAL_MINIMUM, 0x00, - D_LOGICAL_MAXIMUM, 0x01, - D_REPORT_SIZE, 0x01, - D_REPORT_COUNT, (HID_LAST_KEY - HID_KEYBOARD_A_AND_A), - D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), - - // Padding (3 bits) to round up the report to byte boundary. - D_REPORT_SIZE, 0x03, - D_REPORT_COUNT, 0x01, - D_INPUT, (D_CONSTANT), - - D_END_COLLECTION, + // NKRO Keyboard + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, + D_USAGE, D_USAGE_KEYBOARD, + D_COLLECTION, D_APPLICATION, + D_REPORT_ID, HID_REPORTID_NKRO_KEYBOARD, + D_USAGE_PAGE, D_PAGE_KEYBOARD, + + + /* Key modifier byte */ + D_USAGE_MINIMUM, HID_KEYBOARD_FIRST_MODIFIER, + D_USAGE_MAXIMUM, HID_KEYBOARD_LAST_MODIFIER, + D_LOGICAL_MINIMUM, 0x00, + D_LOGICAL_MAXIMUM, 0x01, + D_REPORT_SIZE, 0x01, + D_REPORT_COUNT, 0x08, + D_INPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), + + + /* 5 LEDs for num lock etc, 3 left for advanced, custom usage */ + D_USAGE_PAGE, D_PAGE_LEDS, + D_USAGE_MINIMUM, 0x01, + D_USAGE_MAXIMUM, 0x08, + D_REPORT_COUNT, 0x08, + D_REPORT_SIZE, 0x01, + D_OUTPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), + + /* NKRO Keyboard */ + D_USAGE_PAGE, D_PAGE_KEYBOARD, + + // Padding 4 bits, to skip NO_EVENT & 3 error states. + D_REPORT_SIZE, 0x04, + D_REPORT_COUNT, 0x01, + D_INPUT, (D_CONSTANT), + + D_USAGE_MINIMUM, HID_KEYBOARD_A_AND_A, + D_USAGE_MAXIMUM, HID_LAST_KEY, + D_LOGICAL_MINIMUM, 0x00, + D_LOGICAL_MAXIMUM, 0x01, + D_REPORT_SIZE, 0x01, + D_REPORT_COUNT, (HID_LAST_KEY - HID_KEYBOARD_A_AND_A), + D_INPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), + + // Padding (3 bits) to round up the report to byte boundary. + D_REPORT_SIZE, 0x03, + D_REPORT_COUNT, 0x01, + D_INPUT, (D_CONSTANT), + + D_END_COLLECTION, }; Keyboard_::Keyboard_(void) { - static HIDSubDescriptor node(_hidMultiReportDescriptorKeyboard, sizeof(_hidMultiReportDescriptorKeyboard)); - HID().AppendDescriptor(&node); + static HIDSubDescriptor node(_hidMultiReportDescriptorKeyboard, sizeof(_hidMultiReportDescriptorKeyboard)); + HID().AppendDescriptor(&node); } void Keyboard_::begin(void) { - // Force API to send a clean report. - // This is important for and HID bridge where the receiver stays on, - // while the sender is resetted. - releaseAll(); - sendReportUnchecked(); + // Force API to send a clean report. + // This is important for and HID bridge where the receiver stays on, + // while the sender is resetted. + releaseAll(); + sendReportUnchecked(); } void Keyboard_::end(void) { - releaseAll(); - sendReportUnchecked(); + releaseAll(); + sendReportUnchecked(); } int Keyboard_::sendReportUnchecked(void) { - return HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &keyReport, sizeof(keyReport)); + return HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &keyReport, sizeof(keyReport)); } int Keyboard_::sendReport(void) { - // If the last report is different than the current report, then we need to send a report. - // We guard sendReport like this so that calling code doesn't end up spamming the host with empty reports - // if sendReport is called in a tight loop. - - if (memcmp(lastKeyReport.allkeys, keyReport.allkeys, sizeof(keyReport))) { - // if the two reports are different, send a report - - // ChromeOS 51-60 (at least) bug: if a modifier and a normal keycode are added in the - // same report, in some cases the shift is not applied (e.g. `shift`+`[` doesn't yield - // `{`). To compensate for this, check to see if the modifier byte has changed. - - - // If modifiers are being turned on at the same time as any change - // to the non-modifier keys in the report, then we send the previous - // report with the new modifiers - if ( ( (lastKeyReport.modifiers ^ keyReport.modifiers) & keyReport.modifiers) - && (memcmp(lastKeyReport.keys,keyReport.keys, sizeof(keyReport.keys)))) { - uint8_t last_mods = lastKeyReport.modifiers; - lastKeyReport.modifiers = keyReport.modifiers; - int returnCode = HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &lastKeyReport, sizeof(lastKeyReport)); - lastKeyReport.modifiers = last_mods; - } - - // If modifiers are being turned off, then we send the new report with the previous modifiers. - // We need to do this, at least on Linux 4.17 + Wayland. - // Jesse has observed that sending Shift + 3 key up events in the same report - // will sometimes result in a spurious '3' rather than '#', especially when the keys - // had been held for a while - else if (( (lastKeyReport.modifiers ^ keyReport.modifiers) & lastKeyReport.modifiers) - && (memcmp(lastKeyReport.keys,keyReport.keys, sizeof(keyReport.keys)))) { - uint8_t mods = keyReport.modifiers; - keyReport.modifiers = lastKeyReport.modifiers; - int returnCode = HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &keyReport, sizeof(lastKeyReport)); - keyReport.modifiers = mods; - } - - - - - - int returnCode = sendReportUnchecked(); - if (returnCode > 0) - memcpy(lastKeyReport.allkeys, keyReport.allkeys, sizeof(keyReport)); - return returnCode; + // If the last report is different than the current report, then we need to send a report. + // We guard sendReport like this so that calling code doesn't end up spamming the host with empty reports + // if sendReport is called in a tight loop. + + if (memcmp(lastKeyReport.allkeys, keyReport.allkeys, sizeof(keyReport))) { + // if the two reports are different, send a report + + // ChromeOS 51-60 (at least) bug: if a modifier and a normal keycode are added in the + // same report, in some cases the shift is not applied (e.g. `shift`+`[` doesn't yield + // `{`). To compensate for this, check to see if the modifier byte has changed. + + + // If modifiers are being turned on at the same time as any change + // to the non-modifier keys in the report, then we send the previous + // report with the new modifiers + if (((lastKeyReport.modifiers ^ keyReport.modifiers) & keyReport.modifiers) + && (memcmp(lastKeyReport.keys, keyReport.keys, sizeof(keyReport.keys)))) { + uint8_t last_mods = lastKeyReport.modifiers; + lastKeyReport.modifiers = keyReport.modifiers; + int returnCode = HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &lastKeyReport, sizeof(lastKeyReport)); + lastKeyReport.modifiers = last_mods; } - return -1; + + // If modifiers are being turned off, then we send the new report with the previous modifiers. + // We need to do this, at least on Linux 4.17 + Wayland. + // Jesse has observed that sending Shift + 3 key up events in the same report + // will sometimes result in a spurious '3' rather than '#', especially when the keys + // had been held for a while + else if (((lastKeyReport.modifiers ^ keyReport.modifiers) & lastKeyReport.modifiers) + && (memcmp(lastKeyReport.keys, keyReport.keys, sizeof(keyReport.keys)))) { + uint8_t mods = keyReport.modifiers; + keyReport.modifiers = lastKeyReport.modifiers; + int returnCode = HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &keyReport, sizeof(lastKeyReport)); + keyReport.modifiers = mods; + } + + + + + + int returnCode = sendReportUnchecked(); + if (returnCode > 0) + memcpy(lastKeyReport.allkeys, keyReport.allkeys, sizeof(keyReport)); + return returnCode; + } + return -1; } /* Returns true if the modifer key passed in will be sent during this key report * Returns false in all other cases * */ boolean Keyboard_::isModifierActive(uint8_t k) { - if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { - k = k - HID_KEYBOARD_FIRST_MODIFIER; - return !!(keyReport.modifiers & (1 << k)); - } - return false; + if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { + k = k - HID_KEYBOARD_FIRST_MODIFIER; + return !!(keyReport.modifiers & (1 << k)); + } + return false; } /* Returns true if the modifer key passed in was being sent during the previous key report * Returns false in all other cases * */ boolean Keyboard_::wasModifierActive(uint8_t k) { - if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { - k = k - HID_KEYBOARD_FIRST_MODIFIER; - return !!(lastKeyReport.modifiers & (1 << k)); - } - return false; + if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { + k = k - HID_KEYBOARD_FIRST_MODIFIER; + return !!(lastKeyReport.modifiers & (1 << k)); + } + return false; } /* Returns true if *any* modifier will be sent during this key report * Returns false in all other cases * */ boolean Keyboard_::isAnyModifierActive() { - return keyReport.modifiers > 0; + return keyReport.modifiers > 0; } /* Returns true if *any* modifier was being sent during the previous key report * Returns false in all other cases * */ boolean Keyboard_::wasAnyModifierActive() { - return lastKeyReport.modifiers > 0; + return lastKeyReport.modifiers > 0; } @@ -192,11 +192,11 @@ boolean Keyboard_::wasAnyModifierActive() { * Returns false in all other cases * */ boolean Keyboard_::isKeyPressed(uint8_t k) { - if (k <= HID_LAST_KEY) { - uint8_t bit = 1 << (uint8_t(k) % 8); - return !! (keyReport.keys[k / 8] & bit); - } - return false; + if (k <= HID_LAST_KEY) { + uint8_t bit = 1 << (uint8_t(k) % 8); + return !!(keyReport.keys[k / 8] & bit); + } + return false; } /* Returns true if the non-modifer key passed in was sent during the previous key report @@ -204,57 +204,57 @@ boolean Keyboard_::isKeyPressed(uint8_t k) { * */ boolean Keyboard_::wasKeyPressed(uint8_t k) { - if (k <= HID_LAST_KEY) { - uint8_t bit = 1 << (uint8_t(k) % 8); - return !! (lastKeyReport.keys[k / 8] & bit); - } - return false; + if (k <= HID_LAST_KEY) { + uint8_t bit = 1 << (uint8_t(k) % 8); + return !!(lastKeyReport.keys[k / 8] & bit); + } + return false; } size_t Keyboard_::press(uint8_t k) { - // If the key is in the range of 'printable' keys - if (k <= HID_LAST_KEY) { - uint8_t bit = 1 << (uint8_t(k) % 8); - keyReport.keys[k / 8] |= bit; - return 1; - } - - // It's a modifier key - else if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { - // Convert key into bitfield (0 - 7) - k = k - HID_KEYBOARD_FIRST_MODIFIER; - keyReport.modifiers |= (1 << k); - return 1; - } - - // No empty/pressed key was found - return 0; + // If the key is in the range of 'printable' keys + if (k <= HID_LAST_KEY) { + uint8_t bit = 1 << (uint8_t(k) % 8); + keyReport.keys[k / 8] |= bit; + return 1; + } + + // It's a modifier key + else if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { + // Convert key into bitfield (0 - 7) + k = k - HID_KEYBOARD_FIRST_MODIFIER; + keyReport.modifiers |= (1 << k); + return 1; + } + + // No empty/pressed key was found + return 0; } size_t Keyboard_::release(uint8_t k) { - // If we're releasing a printable key - if (k <= HID_LAST_KEY) { - uint8_t bit = 1 << (k % 8); - keyReport.keys[k / 8] &= ~bit; - return 1; - } - - // It's a modifier key - else if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { - // Convert key into bitfield (0 - 7) - k = k - HID_KEYBOARD_FIRST_MODIFIER; - keyReport.modifiers &= ~(1 << k); - return 1; - } - - // No empty/pressed key was found - return 0; + // If we're releasing a printable key + if (k <= HID_LAST_KEY) { + uint8_t bit = 1 << (k % 8); + keyReport.keys[k / 8] &= ~bit; + return 1; + } + + // It's a modifier key + else if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { + // Convert key into bitfield (0 - 7) + k = k - HID_KEYBOARD_FIRST_MODIFIER; + keyReport.modifiers &= ~(1 << k); + return 1; + } + + // No empty/pressed key was found + return 0; } void Keyboard_::releaseAll(void) { - // Release all keys - memset(&keyReport.allkeys, 0x00, sizeof(keyReport.allkeys)); + // Release all keys + memset(&keyReport.allkeys, 0x00, sizeof(keyReport.allkeys)); } Keyboard_ Keyboard; diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h index 898c859ffd..ee39f95e90 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h @@ -36,41 +36,41 @@ THE SOFTWARE. #define KEY_BYTES 28 typedef union { - // Modifiers + keymap - struct { - uint8_t modifiers; - uint8_t keys[KEY_BYTES ]; - }; - uint8_t allkeys[1 + KEY_BYTES]; + // Modifiers + keymap + struct { + uint8_t modifiers; + uint8_t keys[KEY_BYTES ]; + }; + uint8_t allkeys[1 + KEY_BYTES]; } HID_KeyboardReport_Data_t; class Keyboard_ { - public: - Keyboard_(void); - void begin(void); - void end(void); - - size_t press(uint8_t k); - size_t release(uint8_t k); - void releaseAll(void); - int sendReport(void); - - boolean isKeyPressed(uint8_t k); - boolean wasKeyPressed(uint8_t k); - boolean isModifierActive(uint8_t k); - boolean wasModifierActive(uint8_t k); - boolean isAnyModifierActive(); - boolean wasAnyModifierActive(); - - uint8_t getLEDs() { - return HID().getLEDs(); - }; - - HID_KeyboardReport_Data_t keyReport; - HID_KeyboardReport_Data_t lastKeyReport; - private: - int sendReportUnchecked(void); + public: + Keyboard_(void); + void begin(void); + void end(void); + + size_t press(uint8_t k); + size_t release(uint8_t k); + void releaseAll(void); + int sendReport(void); + + boolean isKeyPressed(uint8_t k); + boolean wasKeyPressed(uint8_t k); + boolean isModifierActive(uint8_t k); + boolean wasModifierActive(uint8_t k); + boolean isAnyModifierActive(); + boolean wasAnyModifierActive(); + + uint8_t getLEDs() { + return HID().getLEDs(); + }; + + HID_KeyboardReport_Data_t keyReport; + HID_KeyboardReport_Data_t lastKeyReport; + private: + int sendReportUnchecked(void); }; extern Keyboard_ Keyboard; diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp index af73545e76..de4f4b26da 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp @@ -27,110 +27,110 @@ THE SOFTWARE. #include "DescriptorPrimitives.h" static const uint8_t _hidMultiReportDescriptorMouse[] PROGMEM = { - /* Mouse relative */ - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, // USAGE_PAGE (Generic Desktop) - D_USAGE, D_USAGE_MOUSE, // USAGE (Mouse) - D_COLLECTION, D_APPLICATION, // COLLECTION (Application) - D_REPORT_ID, HID_REPORTID_MOUSE, // REPORT_ID (Mouse) - - /* 8 Buttons */ - D_USAGE_PAGE, D_PAGE_BUTTON, // USAGE_PAGE (Button) - D_USAGE_MINIMUM, 0x01, // USAGE_MINIMUM (Button 1) - D_USAGE_MAXIMUM, 0x08, // USAGE_MAXIMUM (Button 8) - D_LOGICAL_MINIMUM, 0x00, // LOGICAL_MINIMUM (0) - D_LOGICAL_MAXIMUM, 0x01, // LOGICAL_MAXIMUM (1) - D_REPORT_COUNT, 0x08, // REPORT_COUNT (8) - D_REPORT_SIZE, 0x01, // REPORT_SIZE (1) - D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), // INPUT (Data,Var,Abs) - - /* X, Y, Wheel */ - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, // USAGE_PAGE (Generic Desktop) - D_USAGE, 0x30, // USAGE (X) - D_USAGE, 0x31, // USAGE (Y) - D_USAGE, 0x38, // USAGE (Wheel) - D_LOGICAL_MINIMUM, 0x81, // LOGICAL_MINIMUM (-127) - D_LOGICAL_MAXIMUM, 0x7f, // LOGICAL_MAXIMUM (127) - D_REPORT_SIZE, 0x08, // REPORT_SIZE (8) - D_REPORT_COUNT, 0x03, // REPORT_COUNT (3) - D_INPUT, (D_DATA|D_VARIABLE|D_RELATIVE), // INPUT (Data,Var,Rel) - - /* Horizontal wheel */ - D_USAGE_PAGE, D_PAGE_CONSUMER, // USAGE_PAGE (Consumer) - D_PAGE_ORDINAL, 0x38, 0x02, // PAGE (AC Pan) - D_LOGICAL_MINIMUM, 0x81, // LOGICAL_MINIMUM (-127) - D_LOGICAL_MAXIMUM, 0x7f, // LOGICAL_MAXIMUM (127) - D_REPORT_SIZE, 0x08, // REPORT_SIZE (8) - D_REPORT_COUNT, 0x01, // REPORT_COUNT (1) - D_INPUT, (D_DATA|D_VARIABLE|D_RELATIVE), // INPUT (Data,Var,Rel) - - /* End */ - D_END_COLLECTION // END_COLLECTION + /* Mouse relative */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, // USAGE_PAGE (Generic Desktop) + D_USAGE, D_USAGE_MOUSE, // USAGE (Mouse) + D_COLLECTION, D_APPLICATION, // COLLECTION (Application) + D_REPORT_ID, HID_REPORTID_MOUSE, // REPORT_ID (Mouse) + + /* 8 Buttons */ + D_USAGE_PAGE, D_PAGE_BUTTON, // USAGE_PAGE (Button) + D_USAGE_MINIMUM, 0x01, // USAGE_MINIMUM (Button 1) + D_USAGE_MAXIMUM, 0x08, // USAGE_MAXIMUM (Button 8) + D_LOGICAL_MINIMUM, 0x00, // LOGICAL_MINIMUM (0) + D_LOGICAL_MAXIMUM, 0x01, // LOGICAL_MAXIMUM (1) + D_REPORT_COUNT, 0x08, // REPORT_COUNT (8) + D_REPORT_SIZE, 0x01, // REPORT_SIZE (1) + D_INPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), // INPUT (Data,Var,Abs) + + /* X, Y, Wheel */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, // USAGE_PAGE (Generic Desktop) + D_USAGE, 0x30, // USAGE (X) + D_USAGE, 0x31, // USAGE (Y) + D_USAGE, 0x38, // USAGE (Wheel) + D_LOGICAL_MINIMUM, 0x81, // LOGICAL_MINIMUM (-127) + D_LOGICAL_MAXIMUM, 0x7f, // LOGICAL_MAXIMUM (127) + D_REPORT_SIZE, 0x08, // REPORT_SIZE (8) + D_REPORT_COUNT, 0x03, // REPORT_COUNT (3) + D_INPUT, (D_DATA | D_VARIABLE | D_RELATIVE), // INPUT (Data,Var,Rel) + + /* Horizontal wheel */ + D_USAGE_PAGE, D_PAGE_CONSUMER, // USAGE_PAGE (Consumer) + D_PAGE_ORDINAL, 0x38, 0x02, // PAGE (AC Pan) + D_LOGICAL_MINIMUM, 0x81, // LOGICAL_MINIMUM (-127) + D_LOGICAL_MAXIMUM, 0x7f, // LOGICAL_MAXIMUM (127) + D_REPORT_SIZE, 0x08, // REPORT_SIZE (8) + D_REPORT_COUNT, 0x01, // REPORT_COUNT (1) + D_INPUT, (D_DATA | D_VARIABLE | D_RELATIVE), // INPUT (Data,Var,Rel) + + /* End */ + D_END_COLLECTION // END_COLLECTION }; Mouse_::Mouse_(void) { } void Mouse_::begin(void) { - static HIDSubDescriptor node(_hidMultiReportDescriptorMouse, sizeof(_hidMultiReportDescriptorMouse)); - HID().AppendDescriptor(&node); + static HIDSubDescriptor node(_hidMultiReportDescriptorMouse, sizeof(_hidMultiReportDescriptorMouse)); + HID().AppendDescriptor(&node); - end(); + end(); } void Mouse_::end(void) { - releaseAll(); - sendReport(); + releaseAll(); + sendReport(); } void Mouse_::click(uint8_t b) { - press(b); - sendReport(); - release(b); + press(b); + sendReport(); + release(b); } void Mouse_::move(signed char x, signed char y, signed char vWheel, signed char hWheel) { - report.xAxis = x; - report.yAxis = y; - report.vWheel = vWheel; - report.hWheel = hWheel; + report.xAxis = x; + report.yAxis = y; + report.vWheel = vWheel; + report.hWheel = hWheel; } void Mouse_::releaseAll(void) { - memset(&report, 0, sizeof(report)); + memset(&report, 0, sizeof(report)); } void Mouse_::press(uint8_t b) { - report.buttons |= b; + report.buttons |= b; } void Mouse_::release(uint8_t b) { - report.buttons &= ~b; + report.buttons &= ~b; } bool Mouse_::isPressed(uint8_t b) { - if ((b & report.buttons) > 0) - return true; - return false; + if ((b & report.buttons) > 0) + return true; + return false; } void Mouse_::sendReportUnchecked(void) { - HID().SendReport(HID_REPORTID_MOUSE, &report, sizeof(report)); + HID().SendReport(HID_REPORTID_MOUSE, &report, sizeof(report)); } void Mouse_::sendReport(void) { - // If the last report is different than the current report, then we need to send a report. - // We guard sendReport like this so that calling code doesn't end up spamming the host with empty reports - // if sendReport is called in a tight loop. - - // if the two reports are the same, check if they're empty, and return early - // without a report if they are. - static HID_MouseReport_Data_t emptyReport; - if (memcmp(&lastReport, &report, sizeof(report)) == 0 && - memcmp(&report, &emptyReport, sizeof(report)) == 0) - return; - - sendReportUnchecked(); - memcpy(&lastReport, &report, sizeof(report)); + // If the last report is different than the current report, then we need to send a report. + // We guard sendReport like this so that calling code doesn't end up spamming the host with empty reports + // if sendReport is called in a tight loop. + + // if the two reports are the same, check if they're empty, and return early + // without a report if they are. + static HID_MouseReport_Data_t emptyReport; + if (memcmp(&lastReport, &report, sizeof(report)) == 0 && + memcmp(&report, &emptyReport, sizeof(report)) == 0) + return; + + sendReportUnchecked(); + memcpy(&lastReport, &report, sizeof(report)); } Mouse_ Mouse; diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.h b/plugins/KeyboardioHID/src/MultiReport/Mouse.h index 447c48e6b5..5723b70459 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.h @@ -32,46 +32,46 @@ THE SOFTWARE. #include "../MouseButtons.h" typedef union { - // Mouse report: 8 buttons, position, wheel - struct { - uint8_t buttons; - int8_t xAxis; - int8_t yAxis; - int8_t vWheel; - int8_t hWheel; - }; + // Mouse report: 8 buttons, position, wheel + struct { + uint8_t buttons; + int8_t xAxis; + int8_t yAxis; + int8_t vWheel; + int8_t hWheel; + }; } HID_MouseReport_Data_t; class Mouse_ { - 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 vWheel = 0, signed char hWheel = 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 + 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 vWheel = 0, signed char hWheel = 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 - /** getReport returns the current report. - * - * The current report is the one to be send next time sendReport() is called. - * - * @returns A copy of the report. - */ - const HID_MouseReport_Data_t getReport() { - return report; - } - void sendReport(void); + /** getReport returns the current report. + * + * The current report is the one to be send next time sendReport() is called. + * + * @returns A copy of the report. + */ + const HID_MouseReport_Data_t getReport() { + return report; + } + void sendReport(void); - void releaseAll(void); + void releaseAll(void); - protected: - HID_MouseReport_Data_t report; - HID_MouseReport_Data_t lastReport; + protected: + HID_MouseReport_Data_t report; + HID_MouseReport_Data_t lastReport; - private: - void sendReportUnchecked(void); + private: + void sendReportUnchecked(void); }; extern Mouse_ Mouse; diff --git a/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp b/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp index 7c98acff58..168bc51a8a 100644 --- a/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp @@ -27,70 +27,70 @@ THE SOFTWARE. #include "DescriptorPrimitives.h" static const uint8_t _hidMultiReportDescriptorSystem[] PROGMEM = { - //TODO limit to system keys only? - /* System Control (Power Down, Sleep, Wakeup, ...) */ - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ - D_USAGE, 0x80, /* USAGE (System Control) */ - D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ - D_REPORT_ID, HID_REPORTID_SYSTEMCONTROL, /* REPORT_ID */ - /* 1 system key */ - D_LOGICAL_MINIMUM, 0x00, /* LOGICAL_MINIMUM (0) */ - D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xff, 0x00, /* LOGICAL_MAXIMUM (255) */ - D_USAGE_MINIMUM, 0x00, /* USAGE_MINIMUM (Undefined) */ - D_USAGE_MAXIMUM, 0xff, /* USAGE_MAXIMUM (System Menu Down) */ - D_REPORT_COUNT, 0x01, /* REPORT_COUNT (1) */ - D_REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ - D_INPUT, (D_DATA|D_ARRAY|D_ABSOLUTE), /* INPUT (Data,Ary,Abs) */ - D_END_COLLECTION /* END_COLLECTION */ + //TODO limit to system keys only? + /* System Control (Power Down, Sleep, Wakeup, ...) */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ + D_USAGE, 0x80, /* USAGE (System Control) */ + D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ + D_REPORT_ID, HID_REPORTID_SYSTEMCONTROL, /* REPORT_ID */ + /* 1 system key */ + D_LOGICAL_MINIMUM, 0x00, /* LOGICAL_MINIMUM (0) */ + D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xff, 0x00, /* LOGICAL_MAXIMUM (255) */ + D_USAGE_MINIMUM, 0x00, /* USAGE_MINIMUM (Undefined) */ + D_USAGE_MAXIMUM, 0xff, /* USAGE_MAXIMUM (System Menu Down) */ + D_REPORT_COUNT, 0x01, /* REPORT_COUNT (1) */ + D_REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ + D_INPUT, (D_DATA | D_ARRAY | D_ABSOLUTE), /* INPUT (Data,Ary,Abs) */ + D_END_COLLECTION /* END_COLLECTION */ }; SystemControl_::SystemControl_(void) { - static HIDSubDescriptor node(_hidMultiReportDescriptorSystem, sizeof(_hidMultiReportDescriptorSystem)); - HID().AppendDescriptor(&node); + static HIDSubDescriptor node(_hidMultiReportDescriptorSystem, sizeof(_hidMultiReportDescriptorSystem)); + HID().AppendDescriptor(&node); } void SystemControl_::begin(void) { - // release all buttons - end(); + // release all buttons + end(); } void SystemControl_::end(void) { - uint8_t _report = 0x00; - sendReport(&_report, sizeof(_report)); + uint8_t _report = 0x00; + sendReport(&_report, sizeof(_report)); } void SystemControl_::write(uint8_t s) { - press(s); - release(); + press(s); + release(); } void SystemControl_::release(void) { - begin(); + begin(); } void SystemControl_::releaseAll(void) { - begin(); + begin(); } void SystemControl_::press(uint8_t s) { - if (s == HID_SYSTEM_WAKE_UP) { + if (s == HID_SYSTEM_WAKE_UP) { #ifdef __AVR__ - USBDevice.wakeupHost(); + USBDevice.wakeupHost(); #endif #ifdef ARDUINO_ARCH_SAMD - // This is USBDevice_SAMD21G18x.wakeupHost(). But we can't include that - // header, because it redefines a few symbols, and causes linking - // errors. So we simply reimplement the same thing here. - USB->DEVICE.CTRLB.bit.UPRSM = 1; + // This is USBDevice_SAMD21G18x.wakeupHost(). But we can't include that + // header, because it redefines a few symbols, and causes linking + // errors. So we simply reimplement the same thing here. + USB->DEVICE.CTRLB.bit.UPRSM = 1; #endif - } else { - sendReport(&s, sizeof(s)); - } + } else { + sendReport(&s, sizeof(s)); + } } void SystemControl_::sendReport(void* data, int length) { - HID().SendReport(HID_REPORTID_SYSTEMCONTROL, data, length); + HID().SendReport(HID_REPORTID_SYSTEMCONTROL, data, length); } SystemControl_ SystemControl; diff --git a/plugins/KeyboardioHID/src/MultiReport/SystemControl.h b/plugins/KeyboardioHID/src/MultiReport/SystemControl.h index 67da98060f..7f4bb98d4a 100644 --- a/plugins/KeyboardioHID/src/MultiReport/SystemControl.h +++ b/plugins/KeyboardioHID/src/MultiReport/SystemControl.h @@ -32,24 +32,24 @@ THE SOFTWARE. #include "HIDTables.h" typedef union { - // Every usable system control key possible - uint8_t key; + // Every usable system control key possible + uint8_t key; } HID_SystemControlReport_Data_t; class SystemControl_ { - public: - void begin(void); - void end(void); - void write(uint8_t s); - void press(uint8_t s); - void release(void); - void releaseAll(void); - void sendReport(void* data, int length); - - SystemControl_(void); - - protected: + public: + void begin(void); + void end(void); + void write(uint8_t s); + void press(uint8_t s); + void release(void); + void releaseAll(void); + void sendReport(void* data, int length); + + SystemControl_(void); + + protected: }; diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp index b4795d8b5b..c11c038687 100644 --- a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp @@ -27,91 +27,91 @@ THE SOFTWARE. #include "HIDReportObserver.h" static const uint8_t _hidSingleReportDescriptorAbsoluteMouse[] PROGMEM = { - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) 54 */ - D_USAGE, D_USAGE_MOUSE, /* USAGE (Mouse) */ - D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ - - DESCRIPTOR_ABS_MOUSE_BUTTONS - DESCRIPTOR_ABS_MOUSE_XY - DESCRIPTOR_ABS_MOUSE_WHEEL - D_END_COLLECTION /* End */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) 54 */ + D_USAGE, D_USAGE_MOUSE, /* USAGE (Mouse) */ + D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ + + DESCRIPTOR_ABS_MOUSE_BUTTONS + DESCRIPTOR_ABS_MOUSE_XY + DESCRIPTOR_ABS_MOUSE_WHEEL + D_END_COLLECTION /* End */ }; SingleAbsoluteMouse_::SingleAbsoluteMouse_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1) { - epType[0] = EP_TYPE_INTERRUPT_IN; - PluggableUSB().plug(this); + epType[0] = EP_TYPE_INTERRUPT_IN; + PluggableUSB().plug(this); } int SingleAbsoluteMouse_::getInterface(uint8_t* interfaceCount) { - *interfaceCount += 1; // uses 1 - HIDDescriptor hidInterface = { - D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE), - D_HIDREPORT(sizeof(_hidSingleReportDescriptorAbsoluteMouse)), - D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) - }; - return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); + *interfaceCount += 1; // uses 1 + HIDDescriptor hidInterface = { + D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE), + D_HIDREPORT(sizeof(_hidSingleReportDescriptorAbsoluteMouse)), + D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) + }; + return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); } int SingleAbsoluteMouse_::getDescriptor(USBSetup& setup) { - // Check if this is a HID Class Descriptor request - if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { - return 0; - } - if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { - return 0; - } - - // In a HID Class Descriptor wIndex cointains the interface number - if (setup.wIndex != pluggedInterface) { - return 0; - } - - // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol - // due to the USB specs, but Windows and Linux just assumes its in report mode. - protocol = HID_REPORT_PROTOCOL; - - return USB_SendControl(TRANSFER_PGM, _hidSingleReportDescriptorAbsoluteMouse, sizeof(_hidSingleReportDescriptorAbsoluteMouse)); + // Check if this is a HID Class Descriptor request + if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { + return 0; + } + if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { + return 0; + } + + // In a HID Class Descriptor wIndex cointains the interface number + if (setup.wIndex != pluggedInterface) { + return 0; + } + + // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol + // due to the USB specs, but Windows and Linux just assumes its in report mode. + protocol = HID_REPORT_PROTOCOL; + + return USB_SendControl(TRANSFER_PGM, _hidSingleReportDescriptorAbsoluteMouse, sizeof(_hidSingleReportDescriptorAbsoluteMouse)); } bool SingleAbsoluteMouse_::setup(USBSetup& setup) { - if (pluggedInterface != setup.wIndex) { - return false; - } + if (pluggedInterface != setup.wIndex) { + return false; + } + + uint8_t request = setup.bRequest; + uint8_t requestType = setup.bmRequestType; - uint8_t request = setup.bRequest; - uint8_t requestType = setup.bmRequestType; - - if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) { - if (request == HID_GET_REPORT) { - // TODO: HID_GetReport(); - return true; - } - if (request == HID_GET_PROTOCOL) { - // TODO: Send8(protocol); - return true; - } + if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) { + if (request == HID_GET_REPORT) { + // TODO: HID_GetReport(); + return true; + } + if (request == HID_GET_PROTOCOL) { + // TODO: Send8(protocol); + return true; } + } - if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) { - if (request == HID_SET_PROTOCOL) { - protocol = setup.wValueL; - return true; - } - if (request == HID_SET_IDLE) { - idle = setup.wValueL; - return true; - } - if (request == HID_SET_REPORT) { - } + if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) { + if (request == HID_SET_PROTOCOL) { + protocol = setup.wValueL; + return true; } + if (request == HID_SET_IDLE) { + idle = setup.wValueL; + return true; + } + if (request == HID_SET_REPORT) { + } + } - return false; + return false; } void SingleAbsoluteMouse_::sendReport(void* data, int length) { - auto result = USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, length); - HIDReportObserver::observeReport(HID_REPORTID_MOUSE_ABSOLUTE, data, length, result); + auto result = USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, length); + HIDReportObserver::observeReport(HID_REPORTID_MOUSE_ABSOLUTE, data, length, result); } SingleAbsoluteMouse_ SingleAbsoluteMouse; diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h index b96ec82d6a..8c021fca7b 100644 --- a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h +++ b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h @@ -33,21 +33,21 @@ THE SOFTWARE. class SingleAbsoluteMouse_ : public PluggableUSBModule, public AbsoluteMouseAPI { - public: - SingleAbsoluteMouse_(void); - uint8_t getLeds(void); - uint8_t getProtocol(void); - - protected: - // Implementation of the PUSBListNode - int getInterface(uint8_t* interfaceCount); - int getDescriptor(USBSetup& setup); - bool setup(USBSetup& setup); - - EPTYPE_DESCRIPTOR_SIZE epType[1]; - uint8_t protocol; - uint8_t idle; - - virtual inline void sendReport(void* data, int length) override; + public: + SingleAbsoluteMouse_(void); + uint8_t getLeds(void); + uint8_t getProtocol(void); + + protected: + // Implementation of the PUSBListNode + int getInterface(uint8_t* interfaceCount); + int getDescriptor(USBSetup& setup); + bool setup(USBSetup& setup); + + EPTYPE_DESCRIPTOR_SIZE epType[1]; + uint8_t protocol; + uint8_t idle; + + virtual inline void sendReport(void* data, int length) override; }; extern SingleAbsoluteMouse_ SingleAbsoluteMouse; diff --git a/plugins/KeyboardioHID/src/arch/samd.cpp b/plugins/KeyboardioHID/src/arch/samd.cpp index c76e3bb73a..6d79ad1b15 100644 --- a/plugins/KeyboardioHID/src/arch/samd.cpp +++ b/plugins/KeyboardioHID/src/arch/samd.cpp @@ -3,11 +3,11 @@ #ifdef ARDUINO_ARCH_SAMD int USB_SendControl(void* b, unsigned char c) { - USBDevice.sendControl(b, c); + USBDevice.sendControl(b, c); } int USB_SendControl(uint8_t a, const void* b, uint8_t c) { - USBDevice.sendControl(b, c); + USBDevice.sendControl(b, c); } void USB_PackMessages(bool pack) { From b173fc6a73cf0f320a9905ac2138a4ed17364ee6 Mon Sep 17 00:00:00 2001 From: Michael Richters Date: Fri, 4 Dec 2020 13:22:12 -0600 Subject: [PATCH 549/602] Remove unnecessary `void` in functions with no parameters Signed-off-by: Michael Richters --- .../src/BootKeyboard/BootKeyboard.cpp | 14 +++++++------- .../KeyboardioHID/src/BootKeyboard/BootKeyboard.h | 14 +++++++------- .../src/DeviceAPIs/AbsoluteMouseAPI.h | 6 +++--- .../src/DeviceAPIs/AbsoluteMouseAPI.hpp | 6 +++--- plugins/KeyboardioHID/src/HID.cpp | 4 ++-- plugins/KeyboardioHID/src/HID.h | 6 +++--- .../src/MultiReport/AbsoluteMouse.cpp | 2 +- .../KeyboardioHID/src/MultiReport/AbsoluteMouse.h | 2 +- .../src/MultiReport/ConsumerControl.cpp | 12 ++++++------ .../src/MultiReport/ConsumerControl.h | 12 ++++++------ plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp | 10 +++++----- plugins/KeyboardioHID/src/MultiReport/Gamepad.h | 10 +++++----- plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp | 12 ++++++------ plugins/KeyboardioHID/src/MultiReport/Keyboard.h | 12 ++++++------ plugins/KeyboardioHID/src/MultiReport/Mouse.cpp | 12 ++++++------ plugins/KeyboardioHID/src/MultiReport/Mouse.h | 12 ++++++------ .../src/MultiReport/SystemControl.cpp | 10 +++++----- .../KeyboardioHID/src/MultiReport/SystemControl.h | 10 +++++----- .../src/SingleReport/SingleAbsoluteMouse.cpp | 2 +- .../src/SingleReport/SingleAbsoluteMouse.h | 6 +++--- 20 files changed, 87 insertions(+), 87 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index bdd83a562e..073a9e4e1e 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -73,7 +73,7 @@ static const uint8_t _hidReportDescriptorKeyboard[] PROGMEM = { D_END_COLLECTION }; -BootKeyboard_::BootKeyboard_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1), leds(0) { +BootKeyboard_::BootKeyboard_() : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1), leds(0) { epType[0] = EP_TYPE_INTERRUPT_IN; } @@ -109,7 +109,7 @@ int BootKeyboard_::getDescriptor(USBSetup& setup) { } -void BootKeyboard_::begin(void) { +void BootKeyboard_::begin() { PluggableUSB().plug(this); // Force API to send a clean report. @@ -120,7 +120,7 @@ void BootKeyboard_::begin(void) { } -void BootKeyboard_::end(void) { +void BootKeyboard_::end() { releaseAll(); sendReport(); } @@ -202,11 +202,11 @@ bool BootKeyboard_::setup(USBSetup& setup) { return false; } -uint8_t BootKeyboard_::getLeds(void) { +uint8_t BootKeyboard_::getLeds() { return leds; } -uint8_t BootKeyboard_::getProtocol(void) { +uint8_t BootKeyboard_::getProtocol() { return protocol; } @@ -214,7 +214,7 @@ void BootKeyboard_::setProtocol(uint8_t protocol) { this->protocol = protocol; } -int BootKeyboard_::sendReport(void) { +int BootKeyboard_::sendReport() { if (memcmp(&_lastKeyReport, &_keyReport, sizeof(_keyReport))) { // if the two reports are different, send a report int returnCode = USB_Send(pluggedEndpoint | TRANSFER_RELEASE, &_keyReport, sizeof(_keyReport)); @@ -304,7 +304,7 @@ size_t BootKeyboard_::release(uint8_t k) { } -void BootKeyboard_::releaseAll(void) { +void BootKeyboard_::releaseAll() { memset(&_keyReport.bytes, 0x00, sizeof(_keyReport.bytes)); } diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index 50760af26a..7fe9fa4fe0 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -45,14 +45,14 @@ typedef union { class BootKeyboard_ : public PluggableUSBModule { public: - BootKeyboard_(void); + BootKeyboard_(); size_t press(uint8_t); - void begin(void); - void end(void); + void begin(); + void end(); size_t release(uint8_t); - void releaseAll(void); + void releaseAll(); - int sendReport(void); + int sendReport(); boolean isModifierActive(uint8_t k); boolean wasModifierActive(uint8_t k); @@ -61,8 +61,8 @@ class BootKeyboard_ : public PluggableUSBModule { boolean isKeyPressed(uint8_t k); boolean wasKeyPressed(uint8_t k); - uint8_t getLeds(void); - uint8_t getProtocol(void); + uint8_t getLeds(); + uint8_t getProtocol(); void setProtocol(uint8_t protocol); uint8_t default_protocol = HID_REPORT_PROTOCOL; diff --git a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h index 36cfef147d..ee77e92da6 100644 --- a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h +++ b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h @@ -76,9 +76,9 @@ typedef union { class AbsoluteMouseAPI { public: - inline AbsoluteMouseAPI(void); - inline void begin(void); - inline void end(void); + inline AbsoluteMouseAPI(); + inline void begin(); + inline void end(); inline void click(uint8_t b = MOUSE_LEFT); inline void moveTo(uint16_t x, uint16_t y, signed char wheel = 0); diff --git a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.hpp b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.hpp index afbc41ab7a..bfa899231f 100644 --- a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.hpp +++ b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.hpp @@ -25,7 +25,7 @@ THE SOFTWARE. #pragma once -AbsoluteMouseAPI::AbsoluteMouseAPI(void): xAxis(0), yAxis(0), _buttons(0) { // Empty +AbsoluteMouseAPI::AbsoluteMouseAPI(): xAxis(0), yAxis(0), _buttons(0) { // Empty } void AbsoluteMouseAPI::buttons(uint8_t b) { @@ -53,12 +53,12 @@ int16_t AbsoluteMouseAPI::qadd16(int16_t base, int16_t increment) { return base; } -void AbsoluteMouseAPI::begin(void) { +void AbsoluteMouseAPI::begin() { // release all buttons end(); } -void AbsoluteMouseAPI::end(void) { +void AbsoluteMouseAPI::end() { _buttons = 0; moveTo(xAxis, yAxis, 0); } diff --git a/plugins/KeyboardioHID/src/HID.cpp b/plugins/KeyboardioHID/src/HID.cpp index 34a223cc5d..1c6e98ac60 100644 --- a/plugins/KeyboardioHID/src/HID.cpp +++ b/plugins/KeyboardioHID/src/HID.cpp @@ -170,7 +170,7 @@ bool HID_::setup(USBSetup& setup) { return false; } -HID_::HID_(void) : PluggableUSBModule(1, 1, epType), +HID_::HID_() : PluggableUSBModule(1, 1, epType), rootNode(NULL), descriptorSize(0), protocol(HID_REPORT_PROTOCOL), idle(1) { setReportData.reportId = 0; @@ -179,7 +179,7 @@ HID_::HID_(void) : PluggableUSBModule(1, 1, epType), PluggableUSB().plug(this); } -int HID_::begin(void) { +int HID_::begin() { return 0; } diff --git a/plugins/KeyboardioHID/src/HID.h b/plugins/KeyboardioHID/src/HID.h index f890b337b4..716ea209c5 100644 --- a/plugins/KeyboardioHID/src/HID.h +++ b/plugins/KeyboardioHID/src/HID.h @@ -89,11 +89,11 @@ class HIDSubDescriptor { class HID_ : public PluggableUSBModule { public: - HID_(void); - int begin(void); + HID_(); + int begin(); int SendReport(uint8_t id, const void* data, int len); void AppendDescriptor(HIDSubDescriptor* node); - uint8_t getLEDs(void) { + uint8_t getLEDs() { return setReportData.leds; }; diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp index a6b10618f2..5c86e461fa 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp @@ -40,7 +40,7 @@ static const uint8_t _hidMultiReportDescriptorAbsoluteMouse[] PROGMEM = { D_END_COLLECTION /* End */ }; -AbsoluteMouse_::AbsoluteMouse_(void) { +AbsoluteMouse_::AbsoluteMouse_() { static HIDSubDescriptor node(_hidMultiReportDescriptorAbsoluteMouse, sizeof(_hidMultiReportDescriptorAbsoluteMouse)); HID().AppendDescriptor(&node); } diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h index 4b536a029c..8dabd08575 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.h @@ -33,7 +33,7 @@ THE SOFTWARE. class AbsoluteMouse_ : public AbsoluteMouseAPI { public: - AbsoluteMouse_(void); + AbsoluteMouse_(); protected: // Sending is public in the base class for advanced users. diff --git a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp index ddac89a12e..9758d72261 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp @@ -43,17 +43,17 @@ static const uint8_t _hidMultiReportDescriptorConsumer[] PROGMEM = { D_END_COLLECTION /* end collection */ }; -ConsumerControl_::ConsumerControl_(void) { +ConsumerControl_::ConsumerControl_() { static HIDSubDescriptor node(_hidMultiReportDescriptorConsumer, sizeof(_hidMultiReportDescriptorConsumer)); HID().AppendDescriptor(&node); } -void ConsumerControl_::begin(void) { +void ConsumerControl_::begin() { // release all buttons end(); } -void ConsumerControl_::end(void) { +void ConsumerControl_::end() { memset(&_report, 0, sizeof(_report)); sendReport(); } @@ -83,15 +83,15 @@ void ConsumerControl_::release(uint16_t m) { } } -void ConsumerControl_::releaseAll(void) { +void ConsumerControl_::releaseAll() { memset(&_report, 0, sizeof(_report)); } -void ConsumerControl_::sendReportUnchecked(void) { +void ConsumerControl_::sendReportUnchecked() { HID().SendReport(HID_REPORTID_CONSUMERCONTROL, &_report, sizeof(_report)); } -void ConsumerControl_::sendReport(void) { +void ConsumerControl_::sendReport() { // If the last report is different than the current report, then we need to send a report. // We guard sendReport like this so that calling code doesn't end up spamming the host with empty reports // if sendReport is called in a tight loop. diff --git a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h index ecd122ec6b..051ef9332e 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h +++ b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h @@ -44,22 +44,22 @@ typedef union { class ConsumerControl_ { public: - ConsumerControl_(void); - void begin(void); - void end(void); + ConsumerControl_(); + void begin(); + void end(); void write(uint16_t m); void press(uint16_t m); void release(uint16_t m); - void releaseAll(void); + void releaseAll(); // Sending is public in the base class for advanced users. - void sendReport(void); + void sendReport(); protected: HID_ConsumerControlReport_Data_t _report; HID_ConsumerControlReport_Data_t _lastReport; private: - void sendReportUnchecked(void); + void sendReportUnchecked(); }; extern ConsumerControl_ ConsumerControl; diff --git a/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp b/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp index 1c0895e130..b92c222ab0 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp @@ -75,23 +75,23 @@ static const uint8_t _hidMultiReportDescriptorGamepad[] PROGMEM = { D_END_COLLECTION /* END_COLLECTION */ }; -Gamepad_::Gamepad_(void) { +Gamepad_::Gamepad_() { static HIDSubDescriptor node(_hidMultiReportDescriptorGamepad, sizeof(_hidMultiReportDescriptorGamepad)); HID().AppendDescriptor(&node); } -void Gamepad_::begin(void) { +void Gamepad_::begin() { // release all buttons end(); } -void Gamepad_::end(void) { +void Gamepad_::end() { memset(&_report, 0x00, sizeof(_report)); sendReport(&_report, sizeof(_report)); } -void Gamepad_::write(void) { +void Gamepad_::write() { sendReport(&_report, sizeof(_report)); } @@ -106,7 +106,7 @@ void Gamepad_::release(uint8_t b) { } -void Gamepad_::releaseAll(void) { +void Gamepad_::releaseAll() { memset(&_report, 0x00, sizeof(_report)); } diff --git a/plugins/KeyboardioHID/src/MultiReport/Gamepad.h b/plugins/KeyboardioHID/src/MultiReport/Gamepad.h index 3dd6b4188a..f61dc7fc00 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Gamepad.h +++ b/plugins/KeyboardioHID/src/MultiReport/Gamepad.h @@ -99,14 +99,14 @@ typedef union { class Gamepad_ { public: - Gamepad_(void); + Gamepad_(); - void begin(void); - void end(void); - void write(void); + void begin(); + void end(); + void write(); void press(uint8_t b); void release(uint8_t b); - void releaseAll(void); + void releaseAll(); void buttons(uint32_t b); void xAxis(int16_t a); diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index 663cba1405..2ad63141f2 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -78,12 +78,12 @@ static const uint8_t _hidMultiReportDescriptorKeyboard[] PROGMEM = { }; -Keyboard_::Keyboard_(void) { +Keyboard_::Keyboard_() { static HIDSubDescriptor node(_hidMultiReportDescriptorKeyboard, sizeof(_hidMultiReportDescriptorKeyboard)); HID().AppendDescriptor(&node); } -void Keyboard_::begin(void) { +void Keyboard_::begin() { // Force API to send a clean report. // This is important for and HID bridge where the receiver stays on, // while the sender is resetted. @@ -92,17 +92,17 @@ void Keyboard_::begin(void) { } -void Keyboard_::end(void) { +void Keyboard_::end() { releaseAll(); sendReportUnchecked(); } -int Keyboard_::sendReportUnchecked(void) { +int Keyboard_::sendReportUnchecked() { return HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &keyReport, sizeof(keyReport)); } -int Keyboard_::sendReport(void) { +int Keyboard_::sendReport() { // If the last report is different than the current report, then we need to send a report. // We guard sendReport like this so that calling code doesn't end up spamming the host with empty reports // if sendReport is called in a tight loop. @@ -252,7 +252,7 @@ size_t Keyboard_::release(uint8_t k) { return 0; } -void Keyboard_::releaseAll(void) { +void Keyboard_::releaseAll() { // Release all keys memset(&keyReport.allkeys, 0x00, sizeof(keyReport.allkeys)); } diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h index ee39f95e90..5e695e0ba9 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h @@ -48,14 +48,14 @@ typedef union { class Keyboard_ { public: - Keyboard_(void); - void begin(void); - void end(void); + Keyboard_(); + void begin(); + void end(); size_t press(uint8_t k); size_t release(uint8_t k); - void releaseAll(void); - int sendReport(void); + void releaseAll(); + int sendReport(); boolean isKeyPressed(uint8_t k); boolean wasKeyPressed(uint8_t k); @@ -71,6 +71,6 @@ class Keyboard_ { HID_KeyboardReport_Data_t keyReport; HID_KeyboardReport_Data_t lastKeyReport; private: - int sendReportUnchecked(void); + int sendReportUnchecked(); }; extern Keyboard_ Keyboard; diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp index de4f4b26da..8a696819d6 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp @@ -67,17 +67,17 @@ static const uint8_t _hidMultiReportDescriptorMouse[] PROGMEM = { D_END_COLLECTION // END_COLLECTION }; -Mouse_::Mouse_(void) { +Mouse_::Mouse_() { } -void Mouse_::begin(void) { +void Mouse_::begin() { static HIDSubDescriptor node(_hidMultiReportDescriptorMouse, sizeof(_hidMultiReportDescriptorMouse)); HID().AppendDescriptor(&node); end(); } -void Mouse_::end(void) { +void Mouse_::end() { releaseAll(); sendReport(); } @@ -95,7 +95,7 @@ void Mouse_::move(signed char x, signed char y, signed char vWheel, signed char report.hWheel = hWheel; } -void Mouse_::releaseAll(void) { +void Mouse_::releaseAll() { memset(&report, 0, sizeof(report)); } @@ -113,11 +113,11 @@ bool Mouse_::isPressed(uint8_t b) { return false; } -void Mouse_::sendReportUnchecked(void) { +void Mouse_::sendReportUnchecked() { HID().SendReport(HID_REPORTID_MOUSE, &report, sizeof(report)); } -void Mouse_::sendReport(void) { +void Mouse_::sendReport() { // If the last report is different than the current report, then we need to send a report. // We guard sendReport like this so that calling code doesn't end up spamming the host with empty reports // if sendReport is called in a tight loop. diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.h b/plugins/KeyboardioHID/src/MultiReport/Mouse.h index 5723b70459..e903183ae0 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.h @@ -45,9 +45,9 @@ typedef union { class Mouse_ { public: - Mouse_(void); - void begin(void); - void end(void); + Mouse_(); + void begin(); + void end(); void click(uint8_t b = MOUSE_LEFT); void move(signed char x, signed char y, signed char vWheel = 0, signed char hWheel = 0); void press(uint8_t b = MOUSE_LEFT); // press LEFT by default @@ -63,15 +63,15 @@ class Mouse_ { const HID_MouseReport_Data_t getReport() { return report; } - void sendReport(void); + void sendReport(); - void releaseAll(void); + void releaseAll(); protected: HID_MouseReport_Data_t report; HID_MouseReport_Data_t lastReport; private: - void sendReportUnchecked(void); + void sendReportUnchecked(); }; extern Mouse_ Mouse; diff --git a/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp b/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp index 168bc51a8a..86403dc24d 100644 --- a/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp @@ -44,17 +44,17 @@ static const uint8_t _hidMultiReportDescriptorSystem[] PROGMEM = { D_END_COLLECTION /* END_COLLECTION */ }; -SystemControl_::SystemControl_(void) { +SystemControl_::SystemControl_() { static HIDSubDescriptor node(_hidMultiReportDescriptorSystem, sizeof(_hidMultiReportDescriptorSystem)); HID().AppendDescriptor(&node); } -void SystemControl_::begin(void) { +void SystemControl_::begin() { // release all buttons end(); } -void SystemControl_::end(void) { +void SystemControl_::end() { uint8_t _report = 0x00; sendReport(&_report, sizeof(_report)); } @@ -64,11 +64,11 @@ void SystemControl_::write(uint8_t s) { release(); } -void SystemControl_::release(void) { +void SystemControl_::release() { begin(); } -void SystemControl_::releaseAll(void) { +void SystemControl_::releaseAll() { begin(); } diff --git a/plugins/KeyboardioHID/src/MultiReport/SystemControl.h b/plugins/KeyboardioHID/src/MultiReport/SystemControl.h index 7f4bb98d4a..1b6fd1b1a9 100644 --- a/plugins/KeyboardioHID/src/MultiReport/SystemControl.h +++ b/plugins/KeyboardioHID/src/MultiReport/SystemControl.h @@ -39,15 +39,15 @@ typedef union { class SystemControl_ { public: - void begin(void); - void end(void); + void begin(); + void end(); void write(uint8_t s); void press(uint8_t s); - void release(void); - void releaseAll(void); + void release(); + void releaseAll(); void sendReport(void* data, int length); - SystemControl_(void); + SystemControl_(); protected: }; diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp index c11c038687..31ac2edcac 100644 --- a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp @@ -38,7 +38,7 @@ static const uint8_t _hidSingleReportDescriptorAbsoluteMouse[] PROGMEM = { }; -SingleAbsoluteMouse_::SingleAbsoluteMouse_(void) : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1) { +SingleAbsoluteMouse_::SingleAbsoluteMouse_() : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1) { epType[0] = EP_TYPE_INTERRUPT_IN; PluggableUSB().plug(this); } diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h index 8c021fca7b..7a59403e8d 100644 --- a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h +++ b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.h @@ -34,9 +34,9 @@ THE SOFTWARE. class SingleAbsoluteMouse_ : public PluggableUSBModule, public AbsoluteMouseAPI { public: - SingleAbsoluteMouse_(void); - uint8_t getLeds(void); - uint8_t getProtocol(void); + SingleAbsoluteMouse_(); + uint8_t getLeds(); + uint8_t getProtocol(); protected: // Implementation of the PUSBListNode From dd127bdff13eaf2046635eb46146be81ef4c8912 Mon Sep 17 00:00:00 2001 From: Michael Richters Date: Fri, 4 Dec 2020 13:30:24 -0600 Subject: [PATCH 550/602] Replace non-standard `boolean` with `bool` Signed-off-by: Michael Richters --- .../KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp | 12 ++++++------ .../KeyboardioHID/src/BootKeyboard/BootKeyboard.h | 12 ++++++------ plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp | 12 ++++++------ plugins/KeyboardioHID/src/MultiReport/Keyboard.h | 12 ++++++------ 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 073a9e4e1e..027c3a7631 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -312,7 +312,7 @@ void BootKeyboard_::releaseAll() { /* Returns true if the non-modifer key passed in will be sent during this key report * Returns false in all other cases * */ -boolean BootKeyboard_::isKeyPressed(uint8_t k) { +bool BootKeyboard_::isKeyPressed(uint8_t k) { for (uint8_t i = 0; i < sizeof(_keyReport.keycodes); i++) { if (_keyReport.keycodes[i] == k) { return true; @@ -324,7 +324,7 @@ boolean BootKeyboard_::isKeyPressed(uint8_t k) { /* Returns true if the non-modifer key passed in was sent during the previous key report * Returns false in all other cases * */ -boolean BootKeyboard_::wasKeyPressed(uint8_t k) { +bool BootKeyboard_::wasKeyPressed(uint8_t k) { for (uint8_t i = 0; i < sizeof(_keyReport.keycodes); i++) { if (_lastKeyReport.keycodes[i] == k) { return true; @@ -338,7 +338,7 @@ boolean BootKeyboard_::wasKeyPressed(uint8_t k) { /* Returns true if the modifer key passed in will be sent during this key report * Returns false in all other cases * */ -boolean BootKeyboard_::isModifierActive(uint8_t k) { +bool BootKeyboard_::isModifierActive(uint8_t k) { if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { k = k - HID_KEYBOARD_FIRST_MODIFIER; return !!(_keyReport.modifiers & (1 << k)); @@ -349,7 +349,7 @@ boolean BootKeyboard_::isModifierActive(uint8_t k) { /* Returns true if the modifer key passed in was being sent during the previous key report * Returns false in all other cases * */ -boolean BootKeyboard_::wasModifierActive(uint8_t k) { +bool BootKeyboard_::wasModifierActive(uint8_t k) { if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { k = k - HID_KEYBOARD_FIRST_MODIFIER; return !!(_lastKeyReport.modifiers & (1 << k)); @@ -360,14 +360,14 @@ boolean BootKeyboard_::wasModifierActive(uint8_t k) { /* Returns true if any modifier key will be sent during this key report * Returns false in all other cases * */ -boolean BootKeyboard_::isAnyModifierActive() { +bool BootKeyboard_::isAnyModifierActive() { return _keyReport.modifiers > 0; } /* Returns true if any modifier key was being sent during the previous key report * Returns false in all other cases * */ -boolean BootKeyboard_::wasAnyModifierActive() { +bool BootKeyboard_::wasAnyModifierActive() { return _lastKeyReport.modifiers > 0; } diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index 7fe9fa4fe0..eb213e0938 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -54,12 +54,12 @@ class BootKeyboard_ : public PluggableUSBModule { int sendReport(); - boolean isModifierActive(uint8_t k); - boolean wasModifierActive(uint8_t k); - boolean isAnyModifierActive(); - boolean wasAnyModifierActive(); - boolean isKeyPressed(uint8_t k); - boolean wasKeyPressed(uint8_t k); + bool isModifierActive(uint8_t k); + bool wasModifierActive(uint8_t k); + bool isAnyModifierActive(); + bool wasAnyModifierActive(); + bool isKeyPressed(uint8_t k); + bool wasKeyPressed(uint8_t k); uint8_t getLeds(); uint8_t getProtocol(); diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index 2ad63141f2..0ebafd97c6 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -154,7 +154,7 @@ int Keyboard_::sendReport() { /* Returns true if the modifer key passed in will be sent during this key report * Returns false in all other cases * */ -boolean Keyboard_::isModifierActive(uint8_t k) { +bool Keyboard_::isModifierActive(uint8_t k) { if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { k = k - HID_KEYBOARD_FIRST_MODIFIER; return !!(keyReport.modifiers & (1 << k)); @@ -165,7 +165,7 @@ boolean Keyboard_::isModifierActive(uint8_t k) { /* Returns true if the modifer key passed in was being sent during the previous key report * Returns false in all other cases * */ -boolean Keyboard_::wasModifierActive(uint8_t k) { +bool Keyboard_::wasModifierActive(uint8_t k) { if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { k = k - HID_KEYBOARD_FIRST_MODIFIER; return !!(lastKeyReport.modifiers & (1 << k)); @@ -176,14 +176,14 @@ boolean Keyboard_::wasModifierActive(uint8_t k) { /* Returns true if *any* modifier will be sent during this key report * Returns false in all other cases * */ -boolean Keyboard_::isAnyModifierActive() { +bool Keyboard_::isAnyModifierActive() { return keyReport.modifiers > 0; } /* Returns true if *any* modifier was being sent during the previous key report * Returns false in all other cases * */ -boolean Keyboard_::wasAnyModifierActive() { +bool Keyboard_::wasAnyModifierActive() { return lastKeyReport.modifiers > 0; } @@ -191,7 +191,7 @@ boolean Keyboard_::wasAnyModifierActive() { /* Returns true if the non-modifier key passed in will be sent during this key report * Returns false in all other cases * */ -boolean Keyboard_::isKeyPressed(uint8_t k) { +bool Keyboard_::isKeyPressed(uint8_t k) { if (k <= HID_LAST_KEY) { uint8_t bit = 1 << (uint8_t(k) % 8); return !!(keyReport.keys[k / 8] & bit); @@ -202,7 +202,7 @@ boolean Keyboard_::isKeyPressed(uint8_t k) { /* Returns true if the non-modifer key passed in was sent during the previous key report * Returns false in all other cases * */ -boolean Keyboard_::wasKeyPressed(uint8_t k) { +bool Keyboard_::wasKeyPressed(uint8_t k) { if (k <= HID_LAST_KEY) { uint8_t bit = 1 << (uint8_t(k) % 8); diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h index 5e695e0ba9..fee565cfac 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h @@ -57,12 +57,12 @@ class Keyboard_ { void releaseAll(); int sendReport(); - boolean isKeyPressed(uint8_t k); - boolean wasKeyPressed(uint8_t k); - boolean isModifierActive(uint8_t k); - boolean wasModifierActive(uint8_t k); - boolean isAnyModifierActive(); - boolean wasAnyModifierActive(); + bool isKeyPressed(uint8_t k); + bool wasKeyPressed(uint8_t k); + bool isModifierActive(uint8_t k); + bool wasModifierActive(uint8_t k); + bool isAnyModifierActive(); + bool wasAnyModifierActive(); uint8_t getLEDs() { return HID().getLEDs(); From 490ba3ba6ffbaa909d2a54713f4387823c682a50 Mon Sep 17 00:00:00 2001 From: Michael Richters Date: Fri, 4 Dec 2020 14:15:11 -0600 Subject: [PATCH 551/602] Change variable names to conform to coding style guide Signed-off-by: Michael Richters --- .../src/BootKeyboard/BootKeyboard.cpp | 64 +++++++++---------- .../src/BootKeyboard/BootKeyboard.h | 2 +- .../src/DeviceAPIs/AbsoluteMouseAPI.h | 6 +- .../src/DeviceAPIs/AbsoluteMouseAPI.hpp | 34 +++++----- .../src/MultiReport/AbsoluteMouse.cpp | 4 +- .../src/MultiReport/ConsumerControl.cpp | 22 +++---- .../src/MultiReport/ConsumerControl.h | 4 +- .../KeyboardioHID/src/MultiReport/Gamepad.cpp | 34 +++++----- .../KeyboardioHID/src/MultiReport/Gamepad.h | 2 +- .../src/MultiReport/Keyboard.cpp | 56 ++++++++-------- .../KeyboardioHID/src/MultiReport/Keyboard.h | 4 +- .../KeyboardioHID/src/MultiReport/Mouse.cpp | 32 +++++----- plugins/KeyboardioHID/src/MultiReport/Mouse.h | 8 +-- .../src/MultiReport/SystemControl.cpp | 8 +-- 14 files changed, 140 insertions(+), 140 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 027c3a7631..0ddc2f6216 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -28,7 +28,7 @@ THE SOFTWARE. #include "HIDReportObserver.h" // See Appendix B of USB HID spec -static const uint8_t _hidReportDescriptorKeyboard[] PROGMEM = { +static const uint8_t boot_keyboard_hid_descriptor_[] PROGMEM = { // Keyboard D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, D_USAGE, D_USAGE_KEYBOARD, @@ -81,7 +81,7 @@ int BootKeyboard_::getInterface(uint8_t* interfaceCount) { *interfaceCount += 1; // uses 1 HIDDescriptor hidInterface = { D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_BOOT_INTERFACE, HID_PROTOCOL_KEYBOARD), - D_HIDREPORT(sizeof(_hidReportDescriptorKeyboard)), + D_HIDREPORT(sizeof(boot_keyboard_hid_descriptor_)), D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) }; return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); @@ -105,7 +105,7 @@ int BootKeyboard_::getDescriptor(USBSetup& setup) { // due to the USB specs, but Windows and Linux just assumes its in report mode. protocol = default_protocol; - return USB_SendControl(TRANSFER_PGM, _hidReportDescriptorKeyboard, sizeof(_hidReportDescriptorKeyboard)); + return USB_SendControl(TRANSFER_PGM, boot_keyboard_hid_descriptor_, sizeof(boot_keyboard_hid_descriptor_)); } @@ -191,8 +191,8 @@ bool BootKeyboard_::setup(USBSetup& setup) { // Input (set HID report) else if (setup.wValueH == HID_REPORT_TYPE_INPUT) { - if (length == sizeof(_keyReport)) { - USB_RecvControl(&_keyReport, length); + if (length == sizeof(key_report_)) { + USB_RecvControl(&key_report_, length); return true; } } @@ -215,11 +215,11 @@ void BootKeyboard_::setProtocol(uint8_t protocol) { } int BootKeyboard_::sendReport() { - if (memcmp(&_lastKeyReport, &_keyReport, sizeof(_keyReport))) { + if (memcmp(&last_key_report_, &key_report_, sizeof(key_report_))) { // if the two reports are different, send a report - int returnCode = USB_Send(pluggedEndpoint | TRANSFER_RELEASE, &_keyReport, sizeof(_keyReport)); - HIDReportObserver::observeReport(HID_REPORTID_KEYBOARD, &_keyReport, sizeof(_keyReport), returnCode); - memcpy(&_lastKeyReport, &_keyReport, sizeof(_keyReport)); + int returnCode = USB_Send(pluggedEndpoint | TRANSFER_RELEASE, &key_report_, sizeof(key_report_)); + HIDReportObserver::observeReport(HID_REPORTID_KEYBOARD, &key_report_, sizeof(key_report_), returnCode); + memcpy(&last_key_report_, &key_report_, sizeof(key_report_)); return returnCode; } return -1; @@ -236,15 +236,15 @@ size_t BootKeyboard_::press(uint8_t k) { if ((k >= HID_KEYBOARD_FIRST_MODIFIER) && (k <= HID_KEYBOARD_LAST_MODIFIER)) { // it's a modifier key - _keyReport.modifiers |= (0x01 << (k - HID_KEYBOARD_FIRST_MODIFIER)); + key_report_.modifiers |= (0x01 << (k - HID_KEYBOARD_FIRST_MODIFIER)); } else { // it's some other key: // Add k to the key report only if it's not already present // and if there is an empty slot. - for (uint8_t i = 0; i < sizeof(_keyReport.keycodes); i++) { - if (_keyReport.keycodes[i] != k) { // is k already in list? - if (0 == _keyReport.keycodes[i]) { // have we found an empty slot? - _keyReport.keycodes[i] = k; + for (uint8_t i = 0; i < sizeof(key_report_.keycodes); i++) { + if (key_report_.keycodes[i] != k) { // is k already in list? + if (0 == key_report_.keycodes[i]) { // have we found an empty slot? + key_report_.keycodes[i] = k; done = 1; break; } @@ -271,14 +271,14 @@ size_t BootKeyboard_::press(uint8_t k) { size_t BootKeyboard_::release(uint8_t k) { if ((k >= HID_KEYBOARD_FIRST_MODIFIER) && (k <= HID_KEYBOARD_LAST_MODIFIER)) { // it's a modifier key - _keyReport.modifiers = _keyReport.modifiers & (~(0x01 << (k - HID_KEYBOARD_FIRST_MODIFIER))); + key_report_.modifiers = key_report_.modifiers & (~(0x01 << (k - HID_KEYBOARD_FIRST_MODIFIER))); } else { // it's some other key: // 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 (uint8_t i = 0; i < sizeof(_keyReport.keycodes); i++) { - if (_keyReport.keycodes[i] == k) { - _keyReport.keycodes[i] = 0; + for (uint8_t i = 0; i < sizeof(key_report_.keycodes); i++) { + if (key_report_.keycodes[i] == k) { + key_report_.keycodes[i] = 0; } } @@ -289,11 +289,11 @@ size_t BootKeyboard_::release(uint8_t k) { // (0x03)(0x02)(0x01)(0x00)(0x00)(0x00) uint8_t current = 0, nextpos = 0; - while (current < sizeof(_keyReport.keycodes)) { - if (_keyReport.keycodes[current]) { - uint8_t tmp = _keyReport.keycodes[nextpos]; - _keyReport.keycodes[nextpos] = _keyReport.keycodes[current]; - _keyReport.keycodes[current] = tmp; + while (current < sizeof(key_report_.keycodes)) { + if (key_report_.keycodes[current]) { + uint8_t tmp = key_report_.keycodes[nextpos]; + key_report_.keycodes[nextpos] = key_report_.keycodes[current]; + key_report_.keycodes[current] = tmp; ++nextpos; } ++current; @@ -305,7 +305,7 @@ size_t BootKeyboard_::release(uint8_t k) { void BootKeyboard_::releaseAll() { - memset(&_keyReport.bytes, 0x00, sizeof(_keyReport.bytes)); + memset(&key_report_.bytes, 0x00, sizeof(key_report_.bytes)); } @@ -313,8 +313,8 @@ void BootKeyboard_::releaseAll() { * Returns false in all other cases * */ bool BootKeyboard_::isKeyPressed(uint8_t k) { - for (uint8_t i = 0; i < sizeof(_keyReport.keycodes); i++) { - if (_keyReport.keycodes[i] == k) { + for (uint8_t i = 0; i < sizeof(key_report_.keycodes); i++) { + if (key_report_.keycodes[i] == k) { return true; } } @@ -325,8 +325,8 @@ bool BootKeyboard_::isKeyPressed(uint8_t k) { * Returns false in all other cases * */ bool BootKeyboard_::wasKeyPressed(uint8_t k) { - for (uint8_t i = 0; i < sizeof(_keyReport.keycodes); i++) { - if (_lastKeyReport.keycodes[i] == k) { + for (uint8_t i = 0; i < sizeof(key_report_.keycodes); i++) { + if (last_key_report_.keycodes[i] == k) { return true; } } @@ -341,7 +341,7 @@ bool BootKeyboard_::wasKeyPressed(uint8_t k) { bool BootKeyboard_::isModifierActive(uint8_t k) { if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { k = k - HID_KEYBOARD_FIRST_MODIFIER; - return !!(_keyReport.modifiers & (1 << k)); + return !!(key_report_.modifiers & (1 << k)); } return false; } @@ -352,7 +352,7 @@ bool BootKeyboard_::isModifierActive(uint8_t k) { bool BootKeyboard_::wasModifierActive(uint8_t k) { if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { k = k - HID_KEYBOARD_FIRST_MODIFIER; - return !!(_lastKeyReport.modifiers & (1 << k)); + return !!(last_key_report_.modifiers & (1 << k)); } return false; } @@ -361,14 +361,14 @@ bool BootKeyboard_::wasModifierActive(uint8_t k) { * Returns false in all other cases * */ bool BootKeyboard_::isAnyModifierActive() { - return _keyReport.modifiers > 0; + return key_report_.modifiers > 0; } /* Returns true if any modifier key was being sent during the previous key report * Returns false in all other cases * */ bool BootKeyboard_::wasAnyModifierActive() { - return _lastKeyReport.modifiers > 0; + return last_key_report_.modifiers > 0; } BootKeyboard_ BootKeyboard; diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index eb213e0938..dc075ed906 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -68,7 +68,7 @@ class BootKeyboard_ : public PluggableUSBModule { uint8_t default_protocol = HID_REPORT_PROTOCOL; protected: - HID_BootKeyboardReport_Data_t _keyReport, _lastKeyReport; + HID_BootKeyboardReport_Data_t key_report_, last_key_report_; // Implementation of the PUSBListNode int getInterface(uint8_t* interfaceCount); diff --git a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h index ee77e92da6..0acf6b9698 100644 --- a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h +++ b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h @@ -91,9 +91,9 @@ class AbsoluteMouseAPI { virtual void sendReport(void* data, int length) {} protected: - uint16_t xAxis; - uint16_t yAxis; - uint8_t _buttons; + uint16_t x_axis_; + uint16_t y_axis_; + uint8_t buttons_; inline void buttons(uint8_t b); inline int16_t qadd16(int16_t base, int16_t increment); diff --git a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.hpp b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.hpp index bfa899231f..8c602099ab 100644 --- a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.hpp +++ b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.hpp @@ -25,13 +25,13 @@ THE SOFTWARE. #pragma once -AbsoluteMouseAPI::AbsoluteMouseAPI(): xAxis(0), yAxis(0), _buttons(0) { // Empty +AbsoluteMouseAPI::AbsoluteMouseAPI(): x_axis_(0), y_axis_(0), buttons_(0) { // Empty } void AbsoluteMouseAPI::buttons(uint8_t b) { - if (b != _buttons) { - _buttons = b; - moveTo(xAxis, yAxis, 0); + if (b != buttons_) { + buttons_ = b; + moveTo(x_axis_, y_axis_, 0); } } @@ -59,22 +59,22 @@ void AbsoluteMouseAPI::begin() { } void AbsoluteMouseAPI::end() { - _buttons = 0; - moveTo(xAxis, yAxis, 0); + buttons_ = 0; + moveTo(x_axis_, y_axis_, 0); } void AbsoluteMouseAPI::click(uint8_t b) { - _buttons = b; - moveTo(xAxis, yAxis, 0); - _buttons = 0; - moveTo(xAxis, yAxis, 0); + buttons_ = b; + moveTo(x_axis_, y_axis_, 0); + buttons_ = 0; + moveTo(x_axis_, y_axis_, 0); } void AbsoluteMouseAPI::moveTo(uint16_t x, uint16_t y, signed char wheel) { - xAxis = x; - yAxis = y; + x_axis_ = x; + y_axis_ = y; HID_MouseAbsoluteReport_Data_t report; - report.buttons = _buttons; + report.buttons = buttons_; report.xAxis = x; report.yAxis = y; report.wheel = wheel; @@ -82,22 +82,22 @@ void AbsoluteMouseAPI::moveTo(uint16_t x, uint16_t y, signed char wheel) { } void AbsoluteMouseAPI::move(int x, int y, signed char wheel) { - moveTo(qadd16(xAxis, x), qadd16(yAxis, y), wheel); + moveTo(qadd16(x_axis_, x), qadd16(y_axis_, y), wheel); } void AbsoluteMouseAPI::press(uint8_t b) { // press LEFT by default - buttons(_buttons | b); + buttons(buttons_ | b); } void AbsoluteMouseAPI::release(uint8_t b) { // release LEFT by default - buttons(_buttons & ~b); + buttons(buttons_ & ~b); } bool AbsoluteMouseAPI::isPressed(uint8_t b) { // check LEFT by default - if ((b & _buttons) > 0) + if ((b & buttons_) > 0) return true; return false; } diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp index 5c86e461fa..119b899363 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp @@ -26,7 +26,7 @@ THE SOFTWARE. #include "AbsoluteMouse.h" #include "DescriptorPrimitives.h" -static const uint8_t _hidMultiReportDescriptorAbsoluteMouse[] PROGMEM = { +static const uint8_t absolute_mouse_hid_descriptor_[] PROGMEM = { /* Mouse absolute */ D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) 54 */ D_USAGE, D_USAGE_MOUSE, /* USAGE (Mouse) */ @@ -41,7 +41,7 @@ static const uint8_t _hidMultiReportDescriptorAbsoluteMouse[] PROGMEM = { }; AbsoluteMouse_::AbsoluteMouse_() { - static HIDSubDescriptor node(_hidMultiReportDescriptorAbsoluteMouse, sizeof(_hidMultiReportDescriptorAbsoluteMouse)); + static HIDSubDescriptor node(absolute_mouse_hid_descriptor_, sizeof(absolute_mouse_hid_descriptor_)); HID().AppendDescriptor(&node); } diff --git a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp index 9758d72261..5253988505 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp @@ -26,7 +26,7 @@ THE SOFTWARE. #include "ConsumerControl.h" #include "DescriptorPrimitives.h" -static const uint8_t _hidMultiReportDescriptorConsumer[] PROGMEM = { +static const uint8_t consumer_control_hid_descriptor_[] PROGMEM = { /* Consumer Control (Sound/Media keys) */ D_USAGE_PAGE, 0x0C, /* usage page (consumer device) */ D_USAGE, 0x01, /* usage -- consumer control */ @@ -44,7 +44,7 @@ static const uint8_t _hidMultiReportDescriptorConsumer[] PROGMEM = { }; ConsumerControl_::ConsumerControl_() { - static HIDSubDescriptor node(_hidMultiReportDescriptorConsumer, sizeof(_hidMultiReportDescriptorConsumer)); + static HIDSubDescriptor node(consumer_control_hid_descriptor_, sizeof(consumer_control_hid_descriptor_)); HID().AppendDescriptor(&node); } @@ -54,7 +54,7 @@ void ConsumerControl_::begin() { } void ConsumerControl_::end() { - memset(&_report, 0, sizeof(_report)); + memset(&report_, 0, sizeof(report_)); sendReport(); } @@ -66,8 +66,8 @@ void ConsumerControl_::write(uint16_t m) { void ConsumerControl_::press(uint16_t m) { // search for a free spot for (uint8_t i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { - if (_report.keys[i] == 0x00) { - _report.keys[i] = m; + if (report_.keys[i] == 0x00) { + report_.keys[i] = m; break; } } @@ -76,19 +76,19 @@ void ConsumerControl_::press(uint16_t m) { void ConsumerControl_::release(uint16_t m) { // search and release the keypress for (uint8_t i = 0; i < sizeof(HID_ConsumerControlReport_Data_t) / 2; i++) { - if (_report.keys[i] == m) { - _report.keys[i] = 0x00; + if (report_.keys[i] == m) { + report_.keys[i] = 0x00; // no break to delete multiple keys } } } void ConsumerControl_::releaseAll() { - memset(&_report, 0, sizeof(_report)); + memset(&report_, 0, sizeof(report_)); } void ConsumerControl_::sendReportUnchecked() { - HID().SendReport(HID_REPORTID_CONSUMERCONTROL, &_report, sizeof(_report)); + HID().SendReport(HID_REPORTID_CONSUMERCONTROL, &report_, sizeof(report_)); } void ConsumerControl_::sendReport() { @@ -97,11 +97,11 @@ void ConsumerControl_::sendReport() { // if sendReport is called in a tight loop. // if the previous report is the same, return early without a new report. - if (memcmp(&_lastReport, &_report, sizeof(_report)) == 0) + if (memcmp(&last_report_, &report_, sizeof(report_)) == 0) return; sendReportUnchecked(); - memcpy(&_lastReport, &_report, sizeof(_report)); + memcpy(&last_report_, &report_, sizeof(report_)); } ConsumerControl_ ConsumerControl; diff --git a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h index 051ef9332e..ed3ac03f8d 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h +++ b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.h @@ -56,8 +56,8 @@ class ConsumerControl_ { void sendReport(); protected: - HID_ConsumerControlReport_Data_t _report; - HID_ConsumerControlReport_Data_t _lastReport; + HID_ConsumerControlReport_Data_t report_; + HID_ConsumerControlReport_Data_t last_report_; private: void sendReportUnchecked(); diff --git a/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp b/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp index b92c222ab0..09d5eb4af6 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp @@ -26,7 +26,7 @@ THE SOFTWARE. #include "Gamepad.h" #include "DescriptorPrimitives.h" -static const uint8_t _hidMultiReportDescriptorGamepad[] PROGMEM = { +static const uint8_t gamepad_hid_descriptor_[] PROGMEM = { /* Gamepad with 32 buttons and 6 axis*/ D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ D_USAGE, D_USAGE_JOYSTICK, /* USAGE (Joystick) */ @@ -76,7 +76,7 @@ static const uint8_t _hidMultiReportDescriptorGamepad[] PROGMEM = { }; Gamepad_::Gamepad_() { - static HIDSubDescriptor node(_hidMultiReportDescriptorGamepad, sizeof(_hidMultiReportDescriptorGamepad)); + static HIDSubDescriptor node(gamepad_hid_descriptor_, sizeof(gamepad_hid_descriptor_)); HID().AppendDescriptor(&node); } @@ -87,71 +87,71 @@ void Gamepad_::begin() { } void Gamepad_::end() { - memset(&_report, 0x00, sizeof(_report)); - sendReport(&_report, sizeof(_report)); + memset(&report_, 0x00, sizeof(report_)); + sendReport(&report_, sizeof(report_)); } void Gamepad_::write() { - sendReport(&_report, sizeof(_report)); + sendReport(&report_, sizeof(report_)); } void Gamepad_::press(uint8_t b) { - _report.buttons |= (uint32_t)1 << (b - 1); + report_.buttons |= (uint32_t)1 << (b - 1); } void Gamepad_::release(uint8_t b) { - _report.buttons &= ~((uint32_t)1 << (b - 1)); + report_.buttons &= ~((uint32_t)1 << (b - 1)); } void Gamepad_::releaseAll() { - memset(&_report, 0x00, sizeof(_report)); + memset(&report_, 0x00, sizeof(report_)); } void Gamepad_::buttons(uint32_t b) { - _report.buttons = b; + report_.buttons = b; } void Gamepad_::xAxis(int16_t a) { - _report.xAxis = a; + report_.xAxis = a; } void Gamepad_::yAxis(int16_t a) { - _report.yAxis = a; + report_.yAxis = a; } void Gamepad_::zAxis(int8_t a) { - _report.zAxis = a; + report_.zAxis = a; } void Gamepad_::rxAxis(int16_t a) { - _report.rxAxis = a; + report_.rxAxis = a; } void Gamepad_::ryAxis(int16_t a) { - _report.ryAxis = a; + report_.ryAxis = a; } void Gamepad_::rzAxis(int8_t a) { - _report.rzAxis = a; + report_.rzAxis = a; } void Gamepad_::dPad1(int8_t d) { - _report.dPad1 = d; + report_.dPad1 = d; } void Gamepad_::dPad2(int8_t d) { - _report.dPad2 = d; + report_.dPad2 = d; } diff --git a/plugins/KeyboardioHID/src/MultiReport/Gamepad.h b/plugins/KeyboardioHID/src/MultiReport/Gamepad.h index f61dc7fc00..c2892d1dc8 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Gamepad.h +++ b/plugins/KeyboardioHID/src/MultiReport/Gamepad.h @@ -120,6 +120,6 @@ class Gamepad_ { void sendReport(void* data, int length); protected: - HID_GamepadReport_Data_t _report; + HID_GamepadReport_Data_t report_; }; extern Gamepad_ Gamepad; diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index 0ebafd97c6..b9cdacaebf 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -26,7 +26,7 @@ THE SOFTWARE. #include "Keyboard.h" #include "DescriptorPrimitives.h" -static const uint8_t _hidMultiReportDescriptorKeyboard[] PROGMEM = { +static const uint8_t nkro_keyboard_hid_descriptor_[] PROGMEM = { // NKRO Keyboard D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, D_USAGE, D_USAGE_KEYBOARD, @@ -79,7 +79,7 @@ static const uint8_t _hidMultiReportDescriptorKeyboard[] PROGMEM = { }; Keyboard_::Keyboard_() { - static HIDSubDescriptor node(_hidMultiReportDescriptorKeyboard, sizeof(_hidMultiReportDescriptorKeyboard)); + static HIDSubDescriptor node(nkro_keyboard_hid_descriptor_, sizeof(nkro_keyboard_hid_descriptor_)); HID().AppendDescriptor(&node); } @@ -98,7 +98,7 @@ void Keyboard_::end() { } int Keyboard_::sendReportUnchecked() { - return HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &keyReport, sizeof(keyReport)); + return HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &key_report_, sizeof(key_report_)); } @@ -107,7 +107,7 @@ int Keyboard_::sendReport() { // We guard sendReport like this so that calling code doesn't end up spamming the host with empty reports // if sendReport is called in a tight loop. - if (memcmp(lastKeyReport.allkeys, keyReport.allkeys, sizeof(keyReport))) { + if (memcmp(last_key_report_.allkeys, key_report_.allkeys, sizeof(key_report_))) { // if the two reports are different, send a report // ChromeOS 51-60 (at least) bug: if a modifier and a normal keycode are added in the @@ -118,12 +118,12 @@ int Keyboard_::sendReport() { // If modifiers are being turned on at the same time as any change // to the non-modifier keys in the report, then we send the previous // report with the new modifiers - if (((lastKeyReport.modifiers ^ keyReport.modifiers) & keyReport.modifiers) - && (memcmp(lastKeyReport.keys, keyReport.keys, sizeof(keyReport.keys)))) { - uint8_t last_mods = lastKeyReport.modifiers; - lastKeyReport.modifiers = keyReport.modifiers; - int returnCode = HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &lastKeyReport, sizeof(lastKeyReport)); - lastKeyReport.modifiers = last_mods; + if (((last_key_report_.modifiers ^ key_report_.modifiers) & key_report_.modifiers) + && (memcmp(last_key_report_.keys, key_report_.keys, sizeof(key_report_.keys)))) { + uint8_t last_mods = last_key_report_.modifiers; + last_key_report_.modifiers = key_report_.modifiers; + int returnCode = HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &last_key_report_, sizeof(last_key_report_)); + last_key_report_.modifiers = last_mods; } // If modifiers are being turned off, then we send the new report with the previous modifiers. @@ -131,12 +131,12 @@ int Keyboard_::sendReport() { // Jesse has observed that sending Shift + 3 key up events in the same report // will sometimes result in a spurious '3' rather than '#', especially when the keys // had been held for a while - else if (((lastKeyReport.modifiers ^ keyReport.modifiers) & lastKeyReport.modifiers) - && (memcmp(lastKeyReport.keys, keyReport.keys, sizeof(keyReport.keys)))) { - uint8_t mods = keyReport.modifiers; - keyReport.modifiers = lastKeyReport.modifiers; - int returnCode = HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &keyReport, sizeof(lastKeyReport)); - keyReport.modifiers = mods; + else if (((last_key_report_.modifiers ^ key_report_.modifiers) & last_key_report_.modifiers) + && (memcmp(last_key_report_.keys, key_report_.keys, sizeof(key_report_.keys)))) { + uint8_t mods = key_report_.modifiers; + key_report_.modifiers = last_key_report_.modifiers; + int returnCode = HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &key_report_, sizeof(last_key_report_)); + key_report_.modifiers = mods; } @@ -145,7 +145,7 @@ int Keyboard_::sendReport() { int returnCode = sendReportUnchecked(); if (returnCode > 0) - memcpy(lastKeyReport.allkeys, keyReport.allkeys, sizeof(keyReport)); + memcpy(last_key_report_.allkeys, key_report_.allkeys, sizeof(key_report_)); return returnCode; } return -1; @@ -157,7 +157,7 @@ int Keyboard_::sendReport() { bool Keyboard_::isModifierActive(uint8_t k) { if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { k = k - HID_KEYBOARD_FIRST_MODIFIER; - return !!(keyReport.modifiers & (1 << k)); + return !!(key_report_.modifiers & (1 << k)); } return false; } @@ -168,7 +168,7 @@ bool Keyboard_::isModifierActive(uint8_t k) { bool Keyboard_::wasModifierActive(uint8_t k) { if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { k = k - HID_KEYBOARD_FIRST_MODIFIER; - return !!(lastKeyReport.modifiers & (1 << k)); + return !!(last_key_report_.modifiers & (1 << k)); } return false; } @@ -177,14 +177,14 @@ bool Keyboard_::wasModifierActive(uint8_t k) { * Returns false in all other cases * */ bool Keyboard_::isAnyModifierActive() { - return keyReport.modifiers > 0; + return key_report_.modifiers > 0; } /* Returns true if *any* modifier was being sent during the previous key report * Returns false in all other cases * */ bool Keyboard_::wasAnyModifierActive() { - return lastKeyReport.modifiers > 0; + return last_key_report_.modifiers > 0; } @@ -194,7 +194,7 @@ bool Keyboard_::wasAnyModifierActive() { bool Keyboard_::isKeyPressed(uint8_t k) { if (k <= HID_LAST_KEY) { uint8_t bit = 1 << (uint8_t(k) % 8); - return !!(keyReport.keys[k / 8] & bit); + return !!(key_report_.keys[k / 8] & bit); } return false; } @@ -206,7 +206,7 @@ bool Keyboard_::wasKeyPressed(uint8_t k) { if (k <= HID_LAST_KEY) { uint8_t bit = 1 << (uint8_t(k) % 8); - return !!(lastKeyReport.keys[k / 8] & bit); + return !!(last_key_report_.keys[k / 8] & bit); } return false; } @@ -216,7 +216,7 @@ size_t Keyboard_::press(uint8_t k) { // If the key is in the range of 'printable' keys if (k <= HID_LAST_KEY) { uint8_t bit = 1 << (uint8_t(k) % 8); - keyReport.keys[k / 8] |= bit; + key_report_.keys[k / 8] |= bit; return 1; } @@ -224,7 +224,7 @@ size_t Keyboard_::press(uint8_t k) { else if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { // Convert key into bitfield (0 - 7) k = k - HID_KEYBOARD_FIRST_MODIFIER; - keyReport.modifiers |= (1 << k); + key_report_.modifiers |= (1 << k); return 1; } @@ -236,7 +236,7 @@ size_t Keyboard_::release(uint8_t k) { // If we're releasing a printable key if (k <= HID_LAST_KEY) { uint8_t bit = 1 << (k % 8); - keyReport.keys[k / 8] &= ~bit; + key_report_.keys[k / 8] &= ~bit; return 1; } @@ -244,7 +244,7 @@ size_t Keyboard_::release(uint8_t k) { else if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { // Convert key into bitfield (0 - 7) k = k - HID_KEYBOARD_FIRST_MODIFIER; - keyReport.modifiers &= ~(1 << k); + key_report_.modifiers &= ~(1 << k); return 1; } @@ -254,7 +254,7 @@ size_t Keyboard_::release(uint8_t k) { void Keyboard_::releaseAll() { // Release all keys - memset(&keyReport.allkeys, 0x00, sizeof(keyReport.allkeys)); + memset(&key_report_.allkeys, 0x00, sizeof(key_report_.allkeys)); } Keyboard_ Keyboard; diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h index fee565cfac..422032bad6 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h @@ -68,8 +68,8 @@ class Keyboard_ { return HID().getLEDs(); }; - HID_KeyboardReport_Data_t keyReport; - HID_KeyboardReport_Data_t lastKeyReport; + HID_KeyboardReport_Data_t key_report_; + HID_KeyboardReport_Data_t last_key_report_; private: int sendReportUnchecked(); }; diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp index 8a696819d6..14d69e764b 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp @@ -26,7 +26,7 @@ THE SOFTWARE. #include "Mouse.h" #include "DescriptorPrimitives.h" -static const uint8_t _hidMultiReportDescriptorMouse[] PROGMEM = { +static const uint8_t mouse_hid_descriptor_[] PROGMEM = { /* Mouse relative */ D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, // USAGE_PAGE (Generic Desktop) D_USAGE, D_USAGE_MOUSE, // USAGE (Mouse) @@ -71,7 +71,7 @@ Mouse_::Mouse_() { } void Mouse_::begin() { - static HIDSubDescriptor node(_hidMultiReportDescriptorMouse, sizeof(_hidMultiReportDescriptorMouse)); + static HIDSubDescriptor node(mouse_hid_descriptor_, sizeof(mouse_hid_descriptor_)); HID().AppendDescriptor(&node); end(); @@ -88,33 +88,33 @@ void Mouse_::click(uint8_t b) { release(b); } -void Mouse_::move(signed char x, signed char y, signed char vWheel, signed char hWheel) { - report.xAxis = x; - report.yAxis = y; - report.vWheel = vWheel; - report.hWheel = hWheel; +void Mouse_::move(signed char x, signed char y, signed char v_wheel, signed char h_wheel) { + report_.xAxis = x; + report_.yAxis = y; + report_.vWheel = v_wheel; + report_.hWheel = h_wheel; } void Mouse_::releaseAll() { - memset(&report, 0, sizeof(report)); + memset(&report_, 0, sizeof(report_)); } void Mouse_::press(uint8_t b) { - report.buttons |= b; + report_.buttons |= b; } void Mouse_::release(uint8_t b) { - report.buttons &= ~b; + report_.buttons &= ~b; } bool Mouse_::isPressed(uint8_t b) { - if ((b & report.buttons) > 0) + if ((b & report_.buttons) > 0) return true; return false; } void Mouse_::sendReportUnchecked() { - HID().SendReport(HID_REPORTID_MOUSE, &report, sizeof(report)); + HID().SendReport(HID_REPORTID_MOUSE, &report_, sizeof(report_)); } void Mouse_::sendReport() { @@ -124,13 +124,13 @@ void Mouse_::sendReport() { // if the two reports are the same, check if they're empty, and return early // without a report if they are. - static HID_MouseReport_Data_t emptyReport; - if (memcmp(&lastReport, &report, sizeof(report)) == 0 && - memcmp(&report, &emptyReport, sizeof(report)) == 0) + static HID_MouseReport_Data_t empty_report; + if (memcmp(&last_report_, &report_, sizeof(report_)) == 0 && + memcmp(&report_, &empty_report, sizeof(report_)) == 0) return; sendReportUnchecked(); - memcpy(&lastReport, &report, sizeof(report)); + memcpy(&last_report_, &report_, sizeof(report_)); } Mouse_ Mouse; diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.h b/plugins/KeyboardioHID/src/MultiReport/Mouse.h index e903183ae0..9cf04bd494 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.h @@ -49,7 +49,7 @@ class Mouse_ { void begin(); void end(); void click(uint8_t b = MOUSE_LEFT); - void move(signed char x, signed char y, signed char vWheel = 0, signed char hWheel = 0); + void move(signed char x, signed char y, signed char v_wheel = 0, signed char h_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 @@ -61,15 +61,15 @@ class Mouse_ { * @returns A copy of the report. */ const HID_MouseReport_Data_t getReport() { - return report; + return report_; } void sendReport(); void releaseAll(); protected: - HID_MouseReport_Data_t report; - HID_MouseReport_Data_t lastReport; + HID_MouseReport_Data_t report_; + HID_MouseReport_Data_t last_report_; private: void sendReportUnchecked(); diff --git a/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp b/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp index 86403dc24d..56df83185c 100644 --- a/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp @@ -26,7 +26,7 @@ THE SOFTWARE. #include "SystemControl.h" #include "DescriptorPrimitives.h" -static const uint8_t _hidMultiReportDescriptorSystem[] PROGMEM = { +static const uint8_t system_control_hid_descriptor_[] PROGMEM = { //TODO limit to system keys only? /* System Control (Power Down, Sleep, Wakeup, ...) */ D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ @@ -45,7 +45,7 @@ static const uint8_t _hidMultiReportDescriptorSystem[] PROGMEM = { }; SystemControl_::SystemControl_() { - static HIDSubDescriptor node(_hidMultiReportDescriptorSystem, sizeof(_hidMultiReportDescriptorSystem)); + static HIDSubDescriptor node(system_control_hid_descriptor_, sizeof(system_control_hid_descriptor_)); HID().AppendDescriptor(&node); } @@ -55,8 +55,8 @@ void SystemControl_::begin() { } void SystemControl_::end() { - uint8_t _report = 0x00; - sendReport(&_report, sizeof(_report)); + uint8_t report = 0x00; + sendReport(&report, sizeof(report)); } void SystemControl_::write(uint8_t s) { From 5175b8df3191957d3a1206b0161368f802994079 Mon Sep 17 00:00:00 2001 From: Michael Richters Date: Fri, 4 Dec 2020 14:17:30 -0600 Subject: [PATCH 552/602] Match variable names in header to those used in cpp file Signed-off-by: Michael Richters --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index dc075ed906..fd37d96f5c 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -46,10 +46,10 @@ typedef union { class BootKeyboard_ : public PluggableUSBModule { public: BootKeyboard_(); - size_t press(uint8_t); + size_t press(uint8_t k); void begin(); void end(); - size_t release(uint8_t); + size_t release(uint8_t k); void releaseAll(); int sendReport(); From c4b098d34f6ae5832d96b705b9dce57c014dfac6 Mon Sep 17 00:00:00 2001 From: Michael Richters Date: Fri, 4 Dec 2020 14:21:29 -0600 Subject: [PATCH 553/602] Standardize names of HID report variables across classes Signed-off-by: Michael Richters --- .../src/BootKeyboard/BootKeyboard.cpp | 58 +++++++++---------- .../src/BootKeyboard/BootKeyboard.h | 2 +- .../src/MultiReport/Keyboard.cpp | 52 ++++++++--------- .../KeyboardioHID/src/MultiReport/Keyboard.h | 4 +- 4 files changed, 58 insertions(+), 58 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 0ddc2f6216..3546d50b7a 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -191,8 +191,8 @@ bool BootKeyboard_::setup(USBSetup& setup) { // Input (set HID report) else if (setup.wValueH == HID_REPORT_TYPE_INPUT) { - if (length == sizeof(key_report_)) { - USB_RecvControl(&key_report_, length); + if (length == sizeof(report_)) { + USB_RecvControl(&report_, length); return true; } } @@ -215,11 +215,11 @@ void BootKeyboard_::setProtocol(uint8_t protocol) { } int BootKeyboard_::sendReport() { - if (memcmp(&last_key_report_, &key_report_, sizeof(key_report_))) { + if (memcmp(&last_report_, &report_, sizeof(report_))) { // if the two reports are different, send a report - int returnCode = USB_Send(pluggedEndpoint | TRANSFER_RELEASE, &key_report_, sizeof(key_report_)); - HIDReportObserver::observeReport(HID_REPORTID_KEYBOARD, &key_report_, sizeof(key_report_), returnCode); - memcpy(&last_key_report_, &key_report_, sizeof(key_report_)); + int returnCode = USB_Send(pluggedEndpoint | TRANSFER_RELEASE, &report_, sizeof(report_)); + HIDReportObserver::observeReport(HID_REPORTID_KEYBOARD, &report_, sizeof(report_), returnCode); + memcpy(&last_report_, &report_, sizeof(report_)); return returnCode; } return -1; @@ -236,15 +236,15 @@ size_t BootKeyboard_::press(uint8_t k) { if ((k >= HID_KEYBOARD_FIRST_MODIFIER) && (k <= HID_KEYBOARD_LAST_MODIFIER)) { // it's a modifier key - key_report_.modifiers |= (0x01 << (k - HID_KEYBOARD_FIRST_MODIFIER)); + report_.modifiers |= (0x01 << (k - HID_KEYBOARD_FIRST_MODIFIER)); } else { // it's some other key: // Add k to the key report only if it's not already present // and if there is an empty slot. - for (uint8_t i = 0; i < sizeof(key_report_.keycodes); i++) { - if (key_report_.keycodes[i] != k) { // is k already in list? - if (0 == key_report_.keycodes[i]) { // have we found an empty slot? - key_report_.keycodes[i] = k; + for (uint8_t i = 0; i < sizeof(report_.keycodes); i++) { + if (report_.keycodes[i] != k) { // is k already in list? + if (0 == report_.keycodes[i]) { // have we found an empty slot? + report_.keycodes[i] = k; done = 1; break; } @@ -271,14 +271,14 @@ size_t BootKeyboard_::press(uint8_t k) { size_t BootKeyboard_::release(uint8_t k) { if ((k >= HID_KEYBOARD_FIRST_MODIFIER) && (k <= HID_KEYBOARD_LAST_MODIFIER)) { // it's a modifier key - key_report_.modifiers = key_report_.modifiers & (~(0x01 << (k - HID_KEYBOARD_FIRST_MODIFIER))); + report_.modifiers = report_.modifiers & (~(0x01 << (k - HID_KEYBOARD_FIRST_MODIFIER))); } else { // it's some other key: // 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 (uint8_t i = 0; i < sizeof(key_report_.keycodes); i++) { - if (key_report_.keycodes[i] == k) { - key_report_.keycodes[i] = 0; + for (uint8_t i = 0; i < sizeof(report_.keycodes); i++) { + if (report_.keycodes[i] == k) { + report_.keycodes[i] = 0; } } @@ -289,11 +289,11 @@ size_t BootKeyboard_::release(uint8_t k) { // (0x03)(0x02)(0x01)(0x00)(0x00)(0x00) uint8_t current = 0, nextpos = 0; - while (current < sizeof(key_report_.keycodes)) { - if (key_report_.keycodes[current]) { - uint8_t tmp = key_report_.keycodes[nextpos]; - key_report_.keycodes[nextpos] = key_report_.keycodes[current]; - key_report_.keycodes[current] = tmp; + while (current < sizeof(report_.keycodes)) { + if (report_.keycodes[current]) { + uint8_t tmp = report_.keycodes[nextpos]; + report_.keycodes[nextpos] = report_.keycodes[current]; + report_.keycodes[current] = tmp; ++nextpos; } ++current; @@ -305,7 +305,7 @@ size_t BootKeyboard_::release(uint8_t k) { void BootKeyboard_::releaseAll() { - memset(&key_report_.bytes, 0x00, sizeof(key_report_.bytes)); + memset(&report_.bytes, 0x00, sizeof(report_.bytes)); } @@ -313,8 +313,8 @@ void BootKeyboard_::releaseAll() { * Returns false in all other cases * */ bool BootKeyboard_::isKeyPressed(uint8_t k) { - for (uint8_t i = 0; i < sizeof(key_report_.keycodes); i++) { - if (key_report_.keycodes[i] == k) { + for (uint8_t i = 0; i < sizeof(report_.keycodes); i++) { + if (report_.keycodes[i] == k) { return true; } } @@ -325,8 +325,8 @@ bool BootKeyboard_::isKeyPressed(uint8_t k) { * Returns false in all other cases * */ bool BootKeyboard_::wasKeyPressed(uint8_t k) { - for (uint8_t i = 0; i < sizeof(key_report_.keycodes); i++) { - if (last_key_report_.keycodes[i] == k) { + for (uint8_t i = 0; i < sizeof(report_.keycodes); i++) { + if (last_report_.keycodes[i] == k) { return true; } } @@ -341,7 +341,7 @@ bool BootKeyboard_::wasKeyPressed(uint8_t k) { bool BootKeyboard_::isModifierActive(uint8_t k) { if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { k = k - HID_KEYBOARD_FIRST_MODIFIER; - return !!(key_report_.modifiers & (1 << k)); + return !!(report_.modifiers & (1 << k)); } return false; } @@ -352,7 +352,7 @@ bool BootKeyboard_::isModifierActive(uint8_t k) { bool BootKeyboard_::wasModifierActive(uint8_t k) { if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { k = k - HID_KEYBOARD_FIRST_MODIFIER; - return !!(last_key_report_.modifiers & (1 << k)); + return !!(last_report_.modifiers & (1 << k)); } return false; } @@ -361,14 +361,14 @@ bool BootKeyboard_::wasModifierActive(uint8_t k) { * Returns false in all other cases * */ bool BootKeyboard_::isAnyModifierActive() { - return key_report_.modifiers > 0; + return report_.modifiers > 0; } /* Returns true if any modifier key was being sent during the previous key report * Returns false in all other cases * */ bool BootKeyboard_::wasAnyModifierActive() { - return last_key_report_.modifiers > 0; + return last_report_.modifiers > 0; } BootKeyboard_ BootKeyboard; diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index fd37d96f5c..38da09db90 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -68,7 +68,7 @@ class BootKeyboard_ : public PluggableUSBModule { uint8_t default_protocol = HID_REPORT_PROTOCOL; protected: - HID_BootKeyboardReport_Data_t key_report_, last_key_report_; + HID_BootKeyboardReport_Data_t report_, last_report_; // Implementation of the PUSBListNode int getInterface(uint8_t* interfaceCount); diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index b9cdacaebf..68ff9e0d96 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -98,7 +98,7 @@ void Keyboard_::end() { } int Keyboard_::sendReportUnchecked() { - return HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &key_report_, sizeof(key_report_)); + return HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &report_, sizeof(report_)); } @@ -107,7 +107,7 @@ int Keyboard_::sendReport() { // We guard sendReport like this so that calling code doesn't end up spamming the host with empty reports // if sendReport is called in a tight loop. - if (memcmp(last_key_report_.allkeys, key_report_.allkeys, sizeof(key_report_))) { + if (memcmp(last_report_.allkeys, report_.allkeys, sizeof(report_))) { // if the two reports are different, send a report // ChromeOS 51-60 (at least) bug: if a modifier and a normal keycode are added in the @@ -118,12 +118,12 @@ int Keyboard_::sendReport() { // If modifiers are being turned on at the same time as any change // to the non-modifier keys in the report, then we send the previous // report with the new modifiers - if (((last_key_report_.modifiers ^ key_report_.modifiers) & key_report_.modifiers) - && (memcmp(last_key_report_.keys, key_report_.keys, sizeof(key_report_.keys)))) { - uint8_t last_mods = last_key_report_.modifiers; - last_key_report_.modifiers = key_report_.modifiers; - int returnCode = HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &last_key_report_, sizeof(last_key_report_)); - last_key_report_.modifiers = last_mods; + if (((last_report_.modifiers ^ report_.modifiers) & report_.modifiers) + && (memcmp(last_report_.keys, report_.keys, sizeof(report_.keys)))) { + uint8_t last_mods = last_report_.modifiers; + last_report_.modifiers = report_.modifiers; + int returnCode = HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &last_report_, sizeof(last_report_)); + last_report_.modifiers = last_mods; } // If modifiers are being turned off, then we send the new report with the previous modifiers. @@ -131,12 +131,12 @@ int Keyboard_::sendReport() { // Jesse has observed that sending Shift + 3 key up events in the same report // will sometimes result in a spurious '3' rather than '#', especially when the keys // had been held for a while - else if (((last_key_report_.modifiers ^ key_report_.modifiers) & last_key_report_.modifiers) - && (memcmp(last_key_report_.keys, key_report_.keys, sizeof(key_report_.keys)))) { - uint8_t mods = key_report_.modifiers; - key_report_.modifiers = last_key_report_.modifiers; - int returnCode = HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &key_report_, sizeof(last_key_report_)); - key_report_.modifiers = mods; + else if (((last_report_.modifiers ^ report_.modifiers) & last_report_.modifiers) + && (memcmp(last_report_.keys, report_.keys, sizeof(report_.keys)))) { + uint8_t mods = report_.modifiers; + report_.modifiers = last_report_.modifiers; + int returnCode = HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &report_, sizeof(last_report_)); + report_.modifiers = mods; } @@ -145,7 +145,7 @@ int Keyboard_::sendReport() { int returnCode = sendReportUnchecked(); if (returnCode > 0) - memcpy(last_key_report_.allkeys, key_report_.allkeys, sizeof(key_report_)); + memcpy(last_report_.allkeys, report_.allkeys, sizeof(report_)); return returnCode; } return -1; @@ -157,7 +157,7 @@ int Keyboard_::sendReport() { bool Keyboard_::isModifierActive(uint8_t k) { if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { k = k - HID_KEYBOARD_FIRST_MODIFIER; - return !!(key_report_.modifiers & (1 << k)); + return !!(report_.modifiers & (1 << k)); } return false; } @@ -168,7 +168,7 @@ bool Keyboard_::isModifierActive(uint8_t k) { bool Keyboard_::wasModifierActive(uint8_t k) { if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { k = k - HID_KEYBOARD_FIRST_MODIFIER; - return !!(last_key_report_.modifiers & (1 << k)); + return !!(last_report_.modifiers & (1 << k)); } return false; } @@ -177,14 +177,14 @@ bool Keyboard_::wasModifierActive(uint8_t k) { * Returns false in all other cases * */ bool Keyboard_::isAnyModifierActive() { - return key_report_.modifiers > 0; + return report_.modifiers > 0; } /* Returns true if *any* modifier was being sent during the previous key report * Returns false in all other cases * */ bool Keyboard_::wasAnyModifierActive() { - return last_key_report_.modifiers > 0; + return last_report_.modifiers > 0; } @@ -194,7 +194,7 @@ bool Keyboard_::wasAnyModifierActive() { bool Keyboard_::isKeyPressed(uint8_t k) { if (k <= HID_LAST_KEY) { uint8_t bit = 1 << (uint8_t(k) % 8); - return !!(key_report_.keys[k / 8] & bit); + return !!(report_.keys[k / 8] & bit); } return false; } @@ -206,7 +206,7 @@ bool Keyboard_::wasKeyPressed(uint8_t k) { if (k <= HID_LAST_KEY) { uint8_t bit = 1 << (uint8_t(k) % 8); - return !!(last_key_report_.keys[k / 8] & bit); + return !!(last_report_.keys[k / 8] & bit); } return false; } @@ -216,7 +216,7 @@ size_t Keyboard_::press(uint8_t k) { // If the key is in the range of 'printable' keys if (k <= HID_LAST_KEY) { uint8_t bit = 1 << (uint8_t(k) % 8); - key_report_.keys[k / 8] |= bit; + report_.keys[k / 8] |= bit; return 1; } @@ -224,7 +224,7 @@ size_t Keyboard_::press(uint8_t k) { else if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { // Convert key into bitfield (0 - 7) k = k - HID_KEYBOARD_FIRST_MODIFIER; - key_report_.modifiers |= (1 << k); + report_.modifiers |= (1 << k); return 1; } @@ -236,7 +236,7 @@ size_t Keyboard_::release(uint8_t k) { // If we're releasing a printable key if (k <= HID_LAST_KEY) { uint8_t bit = 1 << (k % 8); - key_report_.keys[k / 8] &= ~bit; + report_.keys[k / 8] &= ~bit; return 1; } @@ -244,7 +244,7 @@ size_t Keyboard_::release(uint8_t k) { else if (k >= HID_KEYBOARD_FIRST_MODIFIER && k <= HID_KEYBOARD_LAST_MODIFIER) { // Convert key into bitfield (0 - 7) k = k - HID_KEYBOARD_FIRST_MODIFIER; - key_report_.modifiers &= ~(1 << k); + report_.modifiers &= ~(1 << k); return 1; } @@ -254,7 +254,7 @@ size_t Keyboard_::release(uint8_t k) { void Keyboard_::releaseAll() { // Release all keys - memset(&key_report_.allkeys, 0x00, sizeof(key_report_.allkeys)); + memset(&report_.allkeys, 0x00, sizeof(report_.allkeys)); } Keyboard_ Keyboard; diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h index 422032bad6..309529ea15 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h @@ -68,8 +68,8 @@ class Keyboard_ { return HID().getLEDs(); }; - HID_KeyboardReport_Data_t key_report_; - HID_KeyboardReport_Data_t last_key_report_; + HID_KeyboardReport_Data_t report_; + HID_KeyboardReport_Data_t last_report_; private: int sendReportUnchecked(); }; From 82dfac1a1fd3ebb64b285484f5bbe344e6b08b4b Mon Sep 17 00:00:00 2001 From: Michael Richters Date: Fri, 4 Dec 2020 14:58:20 -0600 Subject: [PATCH 554/602] Format whitespace and comments for readability Signed-off-by: Michael Richters --- .../KeyboardioHID/src/DescriptorPrimitives.h | 49 +++++----- .../src/DeviceAPIs/AbsoluteMouseAPI.h | 18 ++-- .../src/DeviceAPIs/AbsoluteMouseAPI.hpp | 4 +- plugins/KeyboardioHID/src/LEDs.h | 16 +-- plugins/KeyboardioHID/src/MouseButtons.h | 8 +- .../src/MultiReport/AbsoluteMouse.cpp | 3 +- .../src/MultiReport/ConsumerControl.cpp | 32 +++--- .../KeyboardioHID/src/MultiReport/Gamepad.cpp | 97 ++++++++----------- .../src/MultiReport/Keyboard.cpp | 48 ++++----- .../KeyboardioHID/src/MultiReport/Keyboard.h | 1 - .../KeyboardioHID/src/MultiReport/Mouse.cpp | 64 ++++++------ .../src/MultiReport/SystemControl.cpp | 27 +++--- 12 files changed, 179 insertions(+), 188 deletions(-) diff --git a/plugins/KeyboardioHID/src/DescriptorPrimitives.h b/plugins/KeyboardioHID/src/DescriptorPrimitives.h index 2edc0ccb9c..857dd84b80 100644 --- a/plugins/KeyboardioHID/src/DescriptorPrimitives.h +++ b/plugins/KeyboardioHID/src/DescriptorPrimitives.h @@ -60,45 +60,44 @@ THE SOFTWARE. // The bits that make up inputs, outputs and features // Bit 0 -#define D_DATA 0b00000000 -#define D_CONSTANT 0b00000001 +#define D_DATA 0b00000000 +#define D_CONSTANT 0b00000001 // Bit 1 -#define D_ARRAY 0b00000000 -#define D_VARIABLE 0b00000010 +#define D_ARRAY 0b00000000 +#define D_VARIABLE 0b00000010 // Bit 2 -#define D_ABSOLUTE 0b00000000 -#define D_RELATIVE 0b00000100 +#define D_ABSOLUTE 0b00000000 +#define D_RELATIVE 0b00000100 // Bit 3 -#define D_NO_WRAP 0b00000000 -#define D_WRAP 0b00001000 +#define D_NO_WRAP 0b00000000 +#define D_WRAP 0b00001000 // Bit 4 -#define D_LINEAR 0b00000000 -#define D_NON_LINEAR 0b00010000 +#define D_LINEAR 0b00000000 +#define D_NON_LINEAR 0b00010000 // Bit 5 -#define D_PREFERRED_STATE 0b00000000 -#define D_NO_PREFERRED 0b00100000 +#define D_PREFERRED_STATE 0b00000000 +#define D_NO_PREFERRED 0b00100000 // Bit 6 -#define D_NO_NULL_POSITION 0b00000000 -#define D_NULL_STATE 0b01000000 +#define D_NO_NULL_POSITION 0b00000000 +#define D_NULL_STATE 0b01000000 // Bit 7 -#define D_NON_VOLATILE 0b00000000 -#define D_VOLATILE 0b01000000 - +#define D_NON_VOLATILE 0b00000000 +#define D_VOLATILE 0b01000000 // Bit 8 -#define D_BIT_FIELD 0b00000000 -#define D_BUFFERED_BYTES 0b10000000 +#define D_BIT_FIELD 0b00000000 +#define D_BUFFERED_BYTES 0b10000000 // Collection types -#define D_PHYSICAL 0x00 // (group of axes) -#define D_APPLICATION 0x01 // (mouse, keyboard) -#define D_LOGICAL 0x02// (interrelated data) -#define D_REPORT 0x03 -#define D_NAMED_ARRAY 0x04 -#define D_USAGE_SWITCH 0x05 +#define D_PHYSICAL 0x00 // (group of axes) +#define D_APPLICATION 0x01 // (mouse, keyboard) +#define D_LOGICAL 0x02 // (interrelated data) +#define D_REPORT 0x03 +#define D_NAMED_ARRAY 0x04 +#define D_USAGE_SWITCH 0x05 #define D_USAGE_MODIFIER 0x06 // 0x07-0x7f - Reserved // 0x80-0xff - Vendor define diff --git a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h index 0acf6b9698..1d69f87631 100644 --- a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h +++ b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h @@ -33,15 +33,15 @@ THE SOFTWARE. #include "DescriptorPrimitives.h" -#define DESCRIPTOR_ABS_MOUSE_BUTTONS \ - /* 8 Buttons */ \ - D_USAGE_PAGE, D_PAGE_BUTTON, /* USAGE_PAGE (Button) */ \ - D_USAGE_MINIMUM, 0x01, /* USAGE_MINIMUM (Button 1) */ \ - D_USAGE_MAXIMUM, 0x08, /* USAGE_MAXIMUM (Button 8) */ \ - D_LOGICAL_MINIMUM, 0x00, /* LOGICAL_MINIMUM (0) */ \ - D_LOGICAL_MAXIMUM, 0x01, /* LOGICAL_MAXIMUM (1) */ \ - D_REPORT_COUNT, 0x08, /* REPORT_COUNT (8) */ \ - D_REPORT_SIZE, 0x01, /* REPORT_SIZE (1) */ \ +#define DESCRIPTOR_ABS_MOUSE_BUTTONS \ + /* 8 Buttons */ \ + D_USAGE_PAGE, D_PAGE_BUTTON, /* USAGE_PAGE (Button) */ \ + D_USAGE_MINIMUM, 0x01, /* USAGE_MINIMUM (Button 1) */ \ + D_USAGE_MAXIMUM, 0x08, /* USAGE_MAXIMUM (Button 8) */ \ + D_LOGICAL_MINIMUM, 0x00, /* LOGICAL_MINIMUM (0) */ \ + D_LOGICAL_MAXIMUM, 0x01, /* LOGICAL_MAXIMUM (1) */ \ + D_REPORT_COUNT, 0x08, /* REPORT_COUNT (8) */ \ + D_REPORT_SIZE, 0x01, /* REPORT_SIZE (1) */ \ D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), # define DESCRIPTOR_ABS_MOUSE_XY \ diff --git a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.hpp b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.hpp index 8c602099ab..21bb1f5845 100644 --- a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.hpp +++ b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.hpp @@ -25,8 +25,8 @@ THE SOFTWARE. #pragma once -AbsoluteMouseAPI::AbsoluteMouseAPI(): x_axis_(0), y_axis_(0), buttons_(0) { // Empty -} +AbsoluteMouseAPI::AbsoluteMouseAPI() + : x_axis_(0), y_axis_(0), buttons_(0) {} void AbsoluteMouseAPI::buttons(uint8_t b) { if (b != buttons_) { diff --git a/plugins/KeyboardioHID/src/LEDs.h b/plugins/KeyboardioHID/src/LEDs.h index 2df7e6b00b..8469664dd8 100644 --- a/plugins/KeyboardioHID/src/LEDs.h +++ b/plugins/KeyboardioHID/src/LEDs.h @@ -27,12 +27,12 @@ THE SOFTWARE. // Keyboard Leds enum KeyboardLeds : uint8_t { - LED_NUM_LOCK = (1 << 0), - LED_CAPS_LOCK = (1 << 1), - LED_SCROLL_LOCK = (1 << 2), - LED_COMPOSE = (1 << 3), - LED_KANA = (1 << 4), - LED_POWER = (1 << 5), - LED_SHIFT = (1 << 6), - LED_DO_NOT_DISTURB = (1 << 7), + LED_NUM_LOCK = (1 << 0), + LED_CAPS_LOCK = (1 << 1), + LED_SCROLL_LOCK = (1 << 2), + LED_COMPOSE = (1 << 3), + LED_KANA = (1 << 4), + LED_POWER = (1 << 5), + LED_SHIFT = (1 << 6), + LED_DO_NOT_DISTURB = (1 << 7), }; diff --git a/plugins/KeyboardioHID/src/MouseButtons.h b/plugins/KeyboardioHID/src/MouseButtons.h index ae328ca107..ac94137a7c 100644 --- a/plugins/KeyboardioHID/src/MouseButtons.h +++ b/plugins/KeyboardioHID/src/MouseButtons.h @@ -25,11 +25,11 @@ THE SOFTWARE. #pragma once -#define MOUSE_LEFT (1 << 0) -#define MOUSE_RIGHT (1 << 1) +#define MOUSE_LEFT (1 << 0) +#define MOUSE_RIGHT (1 << 1) #define MOUSE_MIDDLE (1 << 2) -#define MOUSE_PREV (1 << 3) -#define MOUSE_NEXT (1 << 4) +#define MOUSE_PREV (1 << 3) +#define MOUSE_NEXT (1 << 4) // actually this mouse report has 8 buttons (for smaller descriptor) // but the last 3 wont do anything from what I tested #define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE | MOUSE_PREV | MOUSE_NEXT) diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp index 119b899363..63698d3d2b 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp @@ -41,7 +41,8 @@ static const uint8_t absolute_mouse_hid_descriptor_[] PROGMEM = { }; AbsoluteMouse_::AbsoluteMouse_() { - static HIDSubDescriptor node(absolute_mouse_hid_descriptor_, sizeof(absolute_mouse_hid_descriptor_)); + static HIDSubDescriptor node(absolute_mouse_hid_descriptor_, + sizeof(absolute_mouse_hid_descriptor_)); HID().AppendDescriptor(&node); } diff --git a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp index 5253988505..961ffdac7b 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp @@ -28,23 +28,24 @@ THE SOFTWARE. static const uint8_t consumer_control_hid_descriptor_[] PROGMEM = { /* Consumer Control (Sound/Media keys) */ - D_USAGE_PAGE, 0x0C, /* usage page (consumer device) */ - D_USAGE, 0x01, /* usage -- consumer control */ - D_COLLECTION, D_APPLICATION, /* collection (application) */ - D_REPORT_ID, HID_REPORTID_CONSUMERCONTROL, /* report id */ + D_USAGE_PAGE, 0x0C, /* usage page (consumer device) */ + D_USAGE, 0x01, /* usage -- consumer control */ + D_COLLECTION, D_APPLICATION, /* collection (application) */ + D_REPORT_ID, HID_REPORTID_CONSUMERCONTROL, /* report id */ /* 4 Media Keys */ - D_LOGICAL_MINIMUM, 0x00, /* logical minimum */ - D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xFF, 0x03, /* logical maximum (3ff) */ - D_USAGE_MINIMUM, 0x00, /* usage minimum (0) */ - D_MULTIBYTE(D_USAGE_MAXIMUM), 0xFF, 0x03, /* usage maximum (3ff) */ - D_REPORT_COUNT, 0x04, /* report count (4) */ - D_REPORT_SIZE, 0x10, /* report size (16) */ - D_INPUT, 0x00, /* input */ + D_LOGICAL_MINIMUM, 0x00, /* logical minimum */ + D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xFF, 0x03, /* logical maximum (3ff) */ + D_USAGE_MINIMUM, 0x00, /* usage minimum (0) */ + D_MULTIBYTE(D_USAGE_MAXIMUM), 0xFF, 0x03, /* usage maximum (3ff) */ + D_REPORT_COUNT, 0x04, /* report count (4) */ + D_REPORT_SIZE, 0x10, /* report size (16) */ + D_INPUT, 0x00, /* input */ D_END_COLLECTION /* end collection */ }; ConsumerControl_::ConsumerControl_() { - static HIDSubDescriptor node(consumer_control_hid_descriptor_, sizeof(consumer_control_hid_descriptor_)); + static HIDSubDescriptor node(consumer_control_hid_descriptor_, + sizeof(consumer_control_hid_descriptor_)); HID().AppendDescriptor(&node); } @@ -92,9 +93,10 @@ void ConsumerControl_::sendReportUnchecked() { } void ConsumerControl_::sendReport() { - // If the last report is different than the current report, then we need to send a report. - // We guard sendReport like this so that calling code doesn't end up spamming the host with empty reports - // if sendReport is called in a tight loop. + // If the last report is different than the current report, then we need to + // send a report. We guard sendReport like this so that calling code doesn't + // end up spamming the host with empty reports if sendReport is called in a + // tight loop. // if the previous report is the same, return early without a new report. if (memcmp(&last_report_, &report_, sizeof(report_)) == 0) diff --git a/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp b/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp index 09d5eb4af6..b82b71415c 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp @@ -28,59 +28,58 @@ THE SOFTWARE. static const uint8_t gamepad_hid_descriptor_[] PROGMEM = { /* Gamepad with 32 buttons and 6 axis*/ - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ - D_USAGE, D_USAGE_JOYSTICK, /* USAGE (Joystick) */ - D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ - D_REPORT_ID, HID_REPORTID_GAMEPAD, /* REPORT_ID */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ + D_USAGE, D_USAGE_JOYSTICK, /* USAGE (Joystick) */ + D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ + D_REPORT_ID, HID_REPORTID_GAMEPAD, /* REPORT_ID */ /* 32 Buttons */ - D_USAGE_PAGE, D_PAGE_BUTTON, /* USAGE_PAGE (Button) */ - D_USAGE_MINIMUM, 0x01, /* USAGE_MINIMUM (Button 1) */ - D_USAGE_MAXIMUM, 0x20, /* USAGE_MAXIMUM (Button 32) */ - D_LOGICAL_MINIMUM, 0x00, /* _LOGICAL_MINIMUM (0) */ - D_LOGICAL_MAXIMUM, 0x01, /* _LOGICAL_MAXIMUM (1) */ - D_REPORT_SIZE, 0x01, /* REPORT_SIZE (1) */ - D_REPORT_COUNT, 0x20, /* REPORT_COUNT (32) */ - D_INPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ + D_USAGE_PAGE, D_PAGE_BUTTON, /* USAGE_PAGE (Button) */ + D_USAGE_MINIMUM, 0x01, /* USAGE_MINIMUM (Button 1) */ + D_USAGE_MAXIMUM, 0x20, /* USAGE_MAXIMUM (Button 32) */ + D_LOGICAL_MINIMUM, 0x00, /* LOGICAL_MINIMUM (0) */ + D_LOGICAL_MAXIMUM, 0x01, /* LOGICAL_MAXIMUM (1) */ + D_REPORT_SIZE, 0x01, /* REPORT_SIZE (1) */ + D_REPORT_COUNT, 0x20, /* REPORT_COUNT (32) */ + D_INPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ /* 4 16bit Axis */ - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ - D_COLLECTION, D_PHYSICAL, /* COLLECTION (Physical) */ - D_USAGE, 0x30, /* USAGE (X) */ - D_USAGE, 0x31, /* USAGE (Y) */ - D_USAGE, 0x33, /* USAGE (Rx) */ - D_USAGE, 0x34, /* USAGE (Ry) */ - D_MULTIBYTE(D_LOGICAL_MINIMUM), 0x00, 0x80, /* _LOGICAL_MINIMUM (-32768) */ - D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xFF, 0x7F, /* _LOGICAL_MAXIMUM (32767) */ - D_REPORT_SIZE, 0x10, /* REPORT_SIZE (16) */ - D_REPORT_COUNT, 0x04, /* REPORT_COUNT (4) */ - D_INPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ + D_COLLECTION, D_PHYSICAL, /* COLLECTION (Physical) */ + D_USAGE, 0x30, /* USAGE (X) */ + D_USAGE, 0x31, /* USAGE (Y) */ + D_USAGE, 0x33, /* USAGE (Rx) */ + D_USAGE, 0x34, /* USAGE (Ry) */ + D_MULTIBYTE(D_LOGICAL_MINIMUM), 0x00, 0x80, /* LOGICAL_MINIMUM (-32768) */ + D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xFF, 0x7F, /* LOGICAL_MAXIMUM (32767) */ + D_REPORT_SIZE, 0x10, /* REPORT_SIZE (16) */ + D_REPORT_COUNT, 0x04, /* REPORT_COUNT (4) */ + D_INPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ /* 2 8bit Axis */ - D_USAGE, 0x32, /* USAGE (Z) */ - D_USAGE, 0x35, /* USAGE (Rz) */ - D_LOGICAL_MINIMUM, 0x80, /* _LOGICAL_MINIMUM (-128) */ - D_LOGICAL_MAXIMUM, 0x7F, /* _LOGICAL_MAXIMUM (127) */ - D_REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ - D_REPORT_COUNT, 0x02, /* REPORT_COUNT (2) */ - D_INPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ - D_END_COLLECTION, /* END_COLLECTION */ - + D_USAGE, 0x32, /* USAGE (Z) */ + D_USAGE, 0x35, /* USAGE (Rz) */ + D_LOGICAL_MINIMUM, 0x80, /* LOGICAL_MINIMUM (-128) */ + D_LOGICAL_MAXIMUM, 0x7F, /* LOGICAL_MAXIMUM (127) */ + D_REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ + D_REPORT_COUNT, 0x02, /* REPORT_COUNT (2) */ + D_INPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ + D_END_COLLECTION, /* END_COLLECTION */ /* 2 Hat Switches */ - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ - D_USAGE, 0x39, /* USAGE (Hat switch) */ - D_USAGE, 0x39, /* USAGE (Hat switch) */ - D_LOGICAL_MINIMUM, 0x01, /* _LOGICAL_MINIMUM (1) */ - D_LOGICAL_MAXIMUM, 0x08, /* _LOGICAL_MAXIMUM (8) */ - D_REPORT_COUNT, 0x02, /* REPORT_COUNT (2) */ - D_REPORT_SIZE, 0x04, /* REPORT_SIZE (4) */ - D_INPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ - D_END_COLLECTION /* END_COLLECTION */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ + D_USAGE, 0x39, /* USAGE (Hat switch) */ + D_USAGE, 0x39, /* USAGE (Hat switch) */ + D_LOGICAL_MINIMUM, 0x01, /* LOGICAL_MINIMUM (1) */ + D_LOGICAL_MAXIMUM, 0x08, /* LOGICAL_MAXIMUM (8) */ + D_REPORT_COUNT, 0x02, /* REPORT_COUNT (2) */ + D_REPORT_SIZE, 0x04, /* REPORT_SIZE (4) */ + D_INPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ + D_END_COLLECTION /* END_COLLECTION */ }; Gamepad_::Gamepad_() { - static HIDSubDescriptor node(gamepad_hid_descriptor_, sizeof(gamepad_hid_descriptor_)); + static HIDSubDescriptor node(gamepad_hid_descriptor_, + sizeof(gamepad_hid_descriptor_)); HID().AppendDescriptor(&node); } - void Gamepad_::begin() { // release all buttons end(); @@ -95,17 +94,14 @@ void Gamepad_::write() { sendReport(&report_, sizeof(report_)); } - void Gamepad_::press(uint8_t b) { report_.buttons |= (uint32_t)1 << (b - 1); } - void Gamepad_::release(uint8_t b) { report_.buttons &= ~((uint32_t)1 << (b - 1)); } - void Gamepad_::releaseAll() { memset(&report_, 0x00, sizeof(report_)); } @@ -114,47 +110,38 @@ void Gamepad_::buttons(uint32_t b) { report_.buttons = b; } - void Gamepad_::xAxis(int16_t a) { report_.xAxis = a; } - void Gamepad_::yAxis(int16_t a) { report_.yAxis = a; } - void Gamepad_::zAxis(int8_t a) { report_.zAxis = a; } - void Gamepad_::rxAxis(int16_t a) { report_.rxAxis = a; } - void Gamepad_::ryAxis(int16_t a) { report_.ryAxis = a; } - void Gamepad_::rzAxis(int8_t a) { report_.rzAxis = a; } - void Gamepad_::dPad1(int8_t d) { report_.dPad1 = d; } - void Gamepad_::dPad2(int8_t d) { report_.dPad2 = d; } - void Gamepad_::sendReport(void* data, int length) { HID().SendReport(HID_REPORTID_GAMEPAD, data, length); } diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index 68ff9e0d96..587d08426d 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -34,7 +34,6 @@ static const uint8_t nkro_keyboard_hid_descriptor_[] PROGMEM = { D_REPORT_ID, HID_REPORTID_NKRO_KEYBOARD, D_USAGE_PAGE, D_PAGE_KEYBOARD, - /* Key modifier byte */ D_USAGE_MINIMUM, HID_KEYBOARD_FIRST_MODIFIER, D_USAGE_MAXIMUM, HID_KEYBOARD_LAST_MODIFIER, @@ -44,7 +43,6 @@ static const uint8_t nkro_keyboard_hid_descriptor_[] PROGMEM = { D_REPORT_COUNT, 0x08, D_INPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), - /* 5 LEDs for num lock etc, 3 left for advanced, custom usage */ D_USAGE_PAGE, D_PAGE_LEDS, D_USAGE_MINIMUM, 0x01, @@ -75,18 +73,17 @@ static const uint8_t nkro_keyboard_hid_descriptor_[] PROGMEM = { D_INPUT, (D_CONSTANT), D_END_COLLECTION, - }; Keyboard_::Keyboard_() { - static HIDSubDescriptor node(nkro_keyboard_hid_descriptor_, sizeof(nkro_keyboard_hid_descriptor_)); + static HIDSubDescriptor node(nkro_keyboard_hid_descriptor_, + sizeof(nkro_keyboard_hid_descriptor_)); HID().AppendDescriptor(&node); } void Keyboard_::begin() { - // Force API to send a clean report. - // This is important for and HID bridge where the receiver stays on, - // while the sender is resetted. + // Force API to send a clean report. This is important for and HID bridge + // where the receiver stays on, while the sender is resetted. releaseAll(); sendReportUnchecked(); } @@ -103,39 +100,42 @@ int Keyboard_::sendReportUnchecked() { int Keyboard_::sendReport() { - // If the last report is different than the current report, then we need to send a report. - // We guard sendReport like this so that calling code doesn't end up spamming the host with empty reports - // if sendReport is called in a tight loop. + // If the last report is different than the current report, then we need to + // send a report. We guard sendReport like this so that calling code doesn't + // end up spamming the host with empty reports if sendReport is called in a + // tight loop. if (memcmp(last_report_.allkeys, report_.allkeys, sizeof(report_))) { // if the two reports are different, send a report - // ChromeOS 51-60 (at least) bug: if a modifier and a normal keycode are added in the - // same report, in some cases the shift is not applied (e.g. `shift`+`[` doesn't yield - // `{`). To compensate for this, check to see if the modifier byte has changed. - + // ChromeOS 51-60 (at least) bug: if a modifier and a normal keycode are + // added in the same report, in some cases the shift is not applied + // (e.g. `shift`+`[` doesn't yield `{`). To compensate for this, check to + // see if the modifier byte has changed. - // If modifiers are being turned on at the same time as any change - // to the non-modifier keys in the report, then we send the previous - // report with the new modifiers + // If modifiers are being turned on at the same time as any change to the + // non-modifier keys in the report, then we send the previous report with + // the new modifiers if (((last_report_.modifiers ^ report_.modifiers) & report_.modifiers) && (memcmp(last_report_.keys, report_.keys, sizeof(report_.keys)))) { uint8_t last_mods = last_report_.modifiers; last_report_.modifiers = report_.modifiers; - int returnCode = HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &last_report_, sizeof(last_report_)); + int returnCode = HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, + &last_report_, sizeof(last_report_)); last_report_.modifiers = last_mods; } - // If modifiers are being turned off, then we send the new report with the previous modifiers. - // We need to do this, at least on Linux 4.17 + Wayland. - // Jesse has observed that sending Shift + 3 key up events in the same report - // will sometimes result in a spurious '3' rather than '#', especially when the keys - // had been held for a while + // If modifiers are being turned off, then we send the new report with the + // previous modifiers. We need to do this, at least on Linux 4.17 + + // Wayland. Jesse has observed that sending Shift + 3 key up events in the + // same report will sometimes result in a spurious '3' rather than '#', + // especially when the keys had been held for a while else if (((last_report_.modifiers ^ report_.modifiers) & last_report_.modifiers) && (memcmp(last_report_.keys, report_.keys, sizeof(report_.keys)))) { uint8_t mods = report_.modifiers; report_.modifiers = last_report_.modifiers; - int returnCode = HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &report_, sizeof(last_report_)); + int returnCode = HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, + &report_, sizeof(last_report_)); report_.modifiers = mods; } diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h index 309529ea15..fc7637fb34 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h @@ -45,7 +45,6 @@ typedef union { } HID_KeyboardReport_Data_t; - class Keyboard_ { public: Keyboard_(); diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp index 14d69e764b..d4ef883399 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp @@ -29,39 +29,39 @@ THE SOFTWARE. static const uint8_t mouse_hid_descriptor_[] PROGMEM = { /* Mouse relative */ D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, // USAGE_PAGE (Generic Desktop) - D_USAGE, D_USAGE_MOUSE, // USAGE (Mouse) - D_COLLECTION, D_APPLICATION, // COLLECTION (Application) - D_REPORT_ID, HID_REPORTID_MOUSE, // REPORT_ID (Mouse) + D_USAGE, D_USAGE_MOUSE, // USAGE (Mouse) + D_COLLECTION, D_APPLICATION, // COLLECTION (Application) + D_REPORT_ID, HID_REPORTID_MOUSE, // REPORT_ID (Mouse) /* 8 Buttons */ - D_USAGE_PAGE, D_PAGE_BUTTON, // USAGE_PAGE (Button) - D_USAGE_MINIMUM, 0x01, // USAGE_MINIMUM (Button 1) - D_USAGE_MAXIMUM, 0x08, // USAGE_MAXIMUM (Button 8) - D_LOGICAL_MINIMUM, 0x00, // LOGICAL_MINIMUM (0) - D_LOGICAL_MAXIMUM, 0x01, // LOGICAL_MAXIMUM (1) - D_REPORT_COUNT, 0x08, // REPORT_COUNT (8) - D_REPORT_SIZE, 0x01, // REPORT_SIZE (1) - D_INPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), // INPUT (Data,Var,Abs) + D_USAGE_PAGE, D_PAGE_BUTTON, // USAGE_PAGE (Button) + D_USAGE_MINIMUM, 0x01, // USAGE_MINIMUM (Button 1) + D_USAGE_MAXIMUM, 0x08, // USAGE_MAXIMUM (Button 8) + D_LOGICAL_MINIMUM, 0x00, // LOGICAL_MINIMUM (0) + D_LOGICAL_MAXIMUM, 0x01, // LOGICAL_MAXIMUM (1) + D_REPORT_COUNT, 0x08, // REPORT_COUNT (8) + D_REPORT_SIZE, 0x01, // REPORT_SIZE (1) + D_INPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), // INPUT (Data,Var,Abs) /* X, Y, Wheel */ - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, // USAGE_PAGE (Generic Desktop) - D_USAGE, 0x30, // USAGE (X) - D_USAGE, 0x31, // USAGE (Y) - D_USAGE, 0x38, // USAGE (Wheel) - D_LOGICAL_MINIMUM, 0x81, // LOGICAL_MINIMUM (-127) - D_LOGICAL_MAXIMUM, 0x7f, // LOGICAL_MAXIMUM (127) - D_REPORT_SIZE, 0x08, // REPORT_SIZE (8) - D_REPORT_COUNT, 0x03, // REPORT_COUNT (3) - D_INPUT, (D_DATA | D_VARIABLE | D_RELATIVE), // INPUT (Data,Var,Rel) + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, // USAGE_PAGE (Generic Desktop) + D_USAGE, 0x30, // USAGE (X) + D_USAGE, 0x31, // USAGE (Y) + D_USAGE, 0x38, // USAGE (Wheel) + D_LOGICAL_MINIMUM, 0x81, // LOGICAL_MINIMUM (-127) + D_LOGICAL_MAXIMUM, 0x7f, // LOGICAL_MAXIMUM (127) + D_REPORT_SIZE, 0x08, // REPORT_SIZE (8) + D_REPORT_COUNT, 0x03, // REPORT_COUNT (3) + D_INPUT, (D_DATA | D_VARIABLE | D_RELATIVE), // INPUT (Data,Var,Rel) /* Horizontal wheel */ - D_USAGE_PAGE, D_PAGE_CONSUMER, // USAGE_PAGE (Consumer) - D_PAGE_ORDINAL, 0x38, 0x02, // PAGE (AC Pan) - D_LOGICAL_MINIMUM, 0x81, // LOGICAL_MINIMUM (-127) - D_LOGICAL_MAXIMUM, 0x7f, // LOGICAL_MAXIMUM (127) - D_REPORT_SIZE, 0x08, // REPORT_SIZE (8) - D_REPORT_COUNT, 0x01, // REPORT_COUNT (1) - D_INPUT, (D_DATA | D_VARIABLE | D_RELATIVE), // INPUT (Data,Var,Rel) + D_USAGE_PAGE, D_PAGE_CONSUMER, // USAGE_PAGE (Consumer) + D_PAGE_ORDINAL, 0x38, 0x02, // PAGE (AC Pan) + D_LOGICAL_MINIMUM, 0x81, // LOGICAL_MINIMUM (-127) + D_LOGICAL_MAXIMUM, 0x7f, // LOGICAL_MAXIMUM (127) + D_REPORT_SIZE, 0x08, // REPORT_SIZE (8) + D_REPORT_COUNT, 0x01, // REPORT_COUNT (1) + D_INPUT, (D_DATA | D_VARIABLE | D_RELATIVE), // INPUT (Data,Var,Rel) /* End */ D_END_COLLECTION // END_COLLECTION @@ -71,7 +71,8 @@ Mouse_::Mouse_() { } void Mouse_::begin() { - static HIDSubDescriptor node(mouse_hid_descriptor_, sizeof(mouse_hid_descriptor_)); + static HIDSubDescriptor node(mouse_hid_descriptor_, + sizeof(mouse_hid_descriptor_)); HID().AppendDescriptor(&node); end(); @@ -118,9 +119,10 @@ void Mouse_::sendReportUnchecked() { } void Mouse_::sendReport() { - // If the last report is different than the current report, then we need to send a report. - // We guard sendReport like this so that calling code doesn't end up spamming the host with empty reports - // if sendReport is called in a tight loop. + // If the last report is different than the current report, then we need to + // send a report. We guard sendReport like this so that calling code doesn't + // end up spamming the host with empty reports if sendReport is called in a + // tight loop. // if the two reports are the same, check if they're empty, and return early // without a report if they are. diff --git a/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp b/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp index 56df83185c..b448cd7201 100644 --- a/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp @@ -29,23 +29,24 @@ THE SOFTWARE. static const uint8_t system_control_hid_descriptor_[] PROGMEM = { //TODO limit to system keys only? /* System Control (Power Down, Sleep, Wakeup, ...) */ - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ - D_USAGE, 0x80, /* USAGE (System Control) */ - D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ - D_REPORT_ID, HID_REPORTID_SYSTEMCONTROL, /* REPORT_ID */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ + D_USAGE, 0x80, /* USAGE (System Control) */ + D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ + D_REPORT_ID, HID_REPORTID_SYSTEMCONTROL, /* REPORT_ID */ /* 1 system key */ - D_LOGICAL_MINIMUM, 0x00, /* LOGICAL_MINIMUM (0) */ - D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xff, 0x00, /* LOGICAL_MAXIMUM (255) */ - D_USAGE_MINIMUM, 0x00, /* USAGE_MINIMUM (Undefined) */ - D_USAGE_MAXIMUM, 0xff, /* USAGE_MAXIMUM (System Menu Down) */ - D_REPORT_COUNT, 0x01, /* REPORT_COUNT (1) */ - D_REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ - D_INPUT, (D_DATA | D_ARRAY | D_ABSOLUTE), /* INPUT (Data,Ary,Abs) */ - D_END_COLLECTION /* END_COLLECTION */ + D_LOGICAL_MINIMUM, 0x00, /* LOGICAL_MINIMUM (0) */ + D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xff, 0x00, /* LOGICAL_MAXIMUM (255) */ + D_USAGE_MINIMUM, 0x00, /* USAGE_MINIMUM (Undefined) */ + D_USAGE_MAXIMUM, 0xff, /* USAGE_MAXIMUM (System Menu Down) */ + D_REPORT_COUNT, 0x01, /* REPORT_COUNT (1) */ + D_REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ + D_INPUT, (D_DATA | D_ARRAY | D_ABSOLUTE), /* INPUT (Data,Ary,Abs) */ + D_END_COLLECTION /* END_COLLECTION */ }; SystemControl_::SystemControl_() { - static HIDSubDescriptor node(system_control_hid_descriptor_, sizeof(system_control_hid_descriptor_)); + static HIDSubDescriptor node(system_control_hid_descriptor_, + sizeof(system_control_hid_descriptor_)); HID().AppendDescriptor(&node); } From 62226fa5e01b33ccf860014b3ef1f2764b3307f3 Mon Sep 17 00:00:00 2001 From: Michael Richters Date: Fri, 4 Dec 2020 15:12:34 -0600 Subject: [PATCH 555/602] Replace `signed char` with `int8_t` Signed-off-by: Michael Richters --- plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h | 4 ++-- plugins/KeyboardioHID/src/MultiReport/Mouse.cpp | 2 +- plugins/KeyboardioHID/src/MultiReport/Mouse.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h index 1d69f87631..61bfdf7cbd 100644 --- a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h +++ b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h @@ -81,8 +81,8 @@ class AbsoluteMouseAPI { inline void end(); inline void click(uint8_t b = MOUSE_LEFT); - inline void moveTo(uint16_t x, uint16_t y, signed char wheel = 0); - inline void move(int x, int y, signed char wheel = 0); + inline void moveTo(uint16_t x, uint16_t y, int8_t wheel = 0); + inline void move(int x, int y, int8_t wheel = 0); inline void press(uint8_t b = MOUSE_LEFT); inline void release(uint8_t b = MOUSE_LEFT); inline bool isPressed(uint8_t b = MOUSE_LEFT); diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp index d4ef883399..001bb54168 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp @@ -89,7 +89,7 @@ void Mouse_::click(uint8_t b) { release(b); } -void Mouse_::move(signed char x, signed char y, signed char v_wheel, signed char h_wheel) { +void Mouse_::move(int8_t x, int8_t y, int8_t v_wheel, int8_t h_wheel) { report_.xAxis = x; report_.yAxis = y; report_.vWheel = v_wheel; diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.h b/plugins/KeyboardioHID/src/MultiReport/Mouse.h index 9cf04bd494..99235f204b 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.h @@ -49,7 +49,7 @@ class Mouse_ { void begin(); void end(); void click(uint8_t b = MOUSE_LEFT); - void move(signed char x, signed char y, signed char v_wheel = 0, signed char h_wheel = 0); + void move(int8_t x, int8_t y, int8_t v_wheel = 0, int8_t h_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 From 8fe2358bce78e5b7564ccc772213da57983f0ae8 Mon Sep 17 00:00:00 2001 From: Michael Richters Date: Fri, 4 Dec 2020 15:37:55 -0600 Subject: [PATCH 556/602] Untabify comments in HID descriptor definitions Signed-off-by: Michael Richters --- .../src/DeviceAPIs/AbsoluteMouseAPI.h | 40 +++++----- .../src/MultiReport/AbsoluteMouse.cpp | 10 +-- .../src/MultiReport/ConsumerControl.cpp | 22 ++--- .../KeyboardioHID/src/MultiReport/Gamepad.cpp | 80 +++++++++---------- .../src/MultiReport/SystemControl.cpp | 24 +++--- 5 files changed, 88 insertions(+), 88 deletions(-) diff --git a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h index 61bfdf7cbd..9f77750a8a 100644 --- a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h +++ b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h @@ -33,35 +33,35 @@ THE SOFTWARE. #include "DescriptorPrimitives.h" -#define DESCRIPTOR_ABS_MOUSE_BUTTONS \ - /* 8 Buttons */ \ - D_USAGE_PAGE, D_PAGE_BUTTON, /* USAGE_PAGE (Button) */ \ +#define DESCRIPTOR_ABS_MOUSE_BUTTONS \ + /* 8 Buttons */ \ + D_USAGE_PAGE, D_PAGE_BUTTON, /* USAGE_PAGE (Button) */ \ D_USAGE_MINIMUM, 0x01, /* USAGE_MINIMUM (Button 1) */ \ D_USAGE_MAXIMUM, 0x08, /* USAGE_MAXIMUM (Button 8) */ \ - D_LOGICAL_MINIMUM, 0x00, /* LOGICAL_MINIMUM (0) */ \ - D_LOGICAL_MAXIMUM, 0x01, /* LOGICAL_MAXIMUM (1) */ \ - D_REPORT_COUNT, 0x08, /* REPORT_COUNT (8) */ \ - D_REPORT_SIZE, 0x01, /* REPORT_SIZE (1) */ \ + D_LOGICAL_MINIMUM, 0x00, /* LOGICAL_MINIMUM (0) */ \ + D_LOGICAL_MAXIMUM, 0x01, /* LOGICAL_MAXIMUM (1) */ \ + D_REPORT_COUNT, 0x08, /* REPORT_COUNT (8) */ \ + D_REPORT_SIZE, 0x01, /* REPORT_SIZE (1) */ \ D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), # define DESCRIPTOR_ABS_MOUSE_XY \ - /* X, Y */ \ + /* X, Y */ \ D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ \ - D_USAGE, 0x30, /* USAGE (X) */ \ - D_USAGE, 0x31, /* USAGE (Y) */ \ - D_MULTIBYTE(D_LOGICAL_MINIMUM), 0x00, 0x00, /* Logical Minimum (0) */ \ - D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xFF, 0x7f, /* Logical Maximum (32767) */ \ - D_REPORT_SIZE, 0x10, /* Report Size (16), */ \ - D_REPORT_COUNT, 0x02, /* Report Count (2), */ \ + D_USAGE, 0x30, /* USAGE (X) */ \ + D_USAGE, 0x31, /* USAGE (Y) */ \ + D_MULTIBYTE(D_LOGICAL_MINIMUM), 0x00, 0x00, /* Logical Minimum (0) */ \ + D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xFF, 0x7f, /* Logical Maximum (32767) */ \ + D_REPORT_SIZE, 0x10, /* Report Size (16), */ \ + D_REPORT_COUNT, 0x02, /* Report Count (2), */ \ D_INPUT, (D_DATA|D_VARIABLE|D_ABSOLUTE), /* Input (Data, Variable, Absolute) */ #define DESCRIPTOR_ABS_MOUSE_WHEEL \ - /* Wheel */ \ - D_USAGE, 0x38, /* USAGE (Wheel) */ \ - D_LOGICAL_MINIMUM, 0x81, /* LOGICAL_MINIMUM (-127) */ \ - D_LOGICAL_MAXIMUM, 0x7f, /* LOGICAL_MAXIMUM (127) */ \ - D_REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ \ - D_REPORT_COUNT, 0x01, /* REPORT_COUNT (1) */ \ + /* Wheel */ \ + D_USAGE, 0x38, /* USAGE (Wheel) */ \ + D_LOGICAL_MINIMUM, 0x81, /* LOGICAL_MINIMUM (-127) */ \ + D_LOGICAL_MAXIMUM, 0x7f, /* LOGICAL_MAXIMUM (127) */ \ + D_REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ \ + D_REPORT_COUNT, 0x01, /* REPORT_COUNT (1) */ \ D_INPUT, (D_DATA|D_VARIABLE|D_RELATIVE), typedef union { diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp index 63698d3d2b..437ef915de 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp @@ -28,16 +28,16 @@ THE SOFTWARE. static const uint8_t absolute_mouse_hid_descriptor_[] PROGMEM = { /* Mouse absolute */ - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) 54 */ - D_USAGE, D_USAGE_MOUSE, /* USAGE (Mouse) */ - D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ - D_REPORT_ID, HID_REPORTID_MOUSE_ABSOLUTE, /* REPORT_ID */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) 54 */ + D_USAGE, D_USAGE_MOUSE, /* USAGE (Mouse) */ + D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ + D_REPORT_ID, HID_REPORTID_MOUSE_ABSOLUTE, /* REPORT_ID */ DESCRIPTOR_ABS_MOUSE_BUTTONS DESCRIPTOR_ABS_MOUSE_XY DESCRIPTOR_ABS_MOUSE_WHEEL - D_END_COLLECTION /* End */ + D_END_COLLECTION /* End */ }; AbsoluteMouse_::AbsoluteMouse_() { diff --git a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp index 961ffdac7b..0cb4c2f549 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp @@ -28,18 +28,18 @@ THE SOFTWARE. static const uint8_t consumer_control_hid_descriptor_[] PROGMEM = { /* Consumer Control (Sound/Media keys) */ - D_USAGE_PAGE, 0x0C, /* usage page (consumer device) */ - D_USAGE, 0x01, /* usage -- consumer control */ - D_COLLECTION, D_APPLICATION, /* collection (application) */ - D_REPORT_ID, HID_REPORTID_CONSUMERCONTROL, /* report id */ + D_USAGE_PAGE, 0x0C, /* usage page (consumer device) */ + D_USAGE, 0x01, /* usage -- consumer control */ + D_COLLECTION, D_APPLICATION, /* collection (application) */ + D_REPORT_ID, HID_REPORTID_CONSUMERCONTROL, /* report id */ /* 4 Media Keys */ - D_LOGICAL_MINIMUM, 0x00, /* logical minimum */ - D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xFF, 0x03, /* logical maximum (3ff) */ - D_USAGE_MINIMUM, 0x00, /* usage minimum (0) */ - D_MULTIBYTE(D_USAGE_MAXIMUM), 0xFF, 0x03, /* usage maximum (3ff) */ - D_REPORT_COUNT, 0x04, /* report count (4) */ - D_REPORT_SIZE, 0x10, /* report size (16) */ - D_INPUT, 0x00, /* input */ + D_LOGICAL_MINIMUM, 0x00, /* logical minimum */ + D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xFF, 0x03, /* logical maximum (3ff) */ + D_USAGE_MINIMUM, 0x00, /* usage minimum (0) */ + D_MULTIBYTE(D_USAGE_MAXIMUM), 0xFF, 0x03, /* usage maximum (3ff) */ + D_REPORT_COUNT, 0x04, /* report count (4) */ + D_REPORT_SIZE, 0x10, /* report size (16) */ + D_INPUT, 0x00, /* input */ D_END_COLLECTION /* end collection */ }; diff --git a/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp b/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp index b82b71415c..7b0774c050 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp @@ -28,50 +28,50 @@ THE SOFTWARE. static const uint8_t gamepad_hid_descriptor_[] PROGMEM = { /* Gamepad with 32 buttons and 6 axis*/ - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ - D_USAGE, D_USAGE_JOYSTICK, /* USAGE (Joystick) */ - D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ - D_REPORT_ID, HID_REPORTID_GAMEPAD, /* REPORT_ID */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ + D_USAGE, D_USAGE_JOYSTICK, /* USAGE (Joystick) */ + D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ + D_REPORT_ID, HID_REPORTID_GAMEPAD, /* REPORT_ID */ /* 32 Buttons */ - D_USAGE_PAGE, D_PAGE_BUTTON, /* USAGE_PAGE (Button) */ - D_USAGE_MINIMUM, 0x01, /* USAGE_MINIMUM (Button 1) */ - D_USAGE_MAXIMUM, 0x20, /* USAGE_MAXIMUM (Button 32) */ - D_LOGICAL_MINIMUM, 0x00, /* LOGICAL_MINIMUM (0) */ - D_LOGICAL_MAXIMUM, 0x01, /* LOGICAL_MAXIMUM (1) */ - D_REPORT_SIZE, 0x01, /* REPORT_SIZE (1) */ - D_REPORT_COUNT, 0x20, /* REPORT_COUNT (32) */ - D_INPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ + D_USAGE_PAGE, D_PAGE_BUTTON, /* USAGE_PAGE (Button) */ + D_USAGE_MINIMUM, 0x01, /* USAGE_MINIMUM (Button 1) */ + D_USAGE_MAXIMUM, 0x20, /* USAGE_MAXIMUM (Button 32) */ + D_LOGICAL_MINIMUM, 0x00, /* LOGICAL_MINIMUM (0) */ + D_LOGICAL_MAXIMUM, 0x01, /* LOGICAL_MAXIMUM (1) */ + D_REPORT_SIZE, 0x01, /* REPORT_SIZE (1) */ + D_REPORT_COUNT, 0x20, /* REPORT_COUNT (32) */ + D_INPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ /* 4 16bit Axis */ - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ - D_COLLECTION, D_PHYSICAL, /* COLLECTION (Physical) */ - D_USAGE, 0x30, /* USAGE (X) */ - D_USAGE, 0x31, /* USAGE (Y) */ - D_USAGE, 0x33, /* USAGE (Rx) */ - D_USAGE, 0x34, /* USAGE (Ry) */ - D_MULTIBYTE(D_LOGICAL_MINIMUM), 0x00, 0x80, /* LOGICAL_MINIMUM (-32768) */ - D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xFF, 0x7F, /* LOGICAL_MAXIMUM (32767) */ - D_REPORT_SIZE, 0x10, /* REPORT_SIZE (16) */ - D_REPORT_COUNT, 0x04, /* REPORT_COUNT (4) */ - D_INPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ + D_COLLECTION, D_PHYSICAL, /* COLLECTION (Physical) */ + D_USAGE, 0x30, /* USAGE (X) */ + D_USAGE, 0x31, /* USAGE (Y) */ + D_USAGE, 0x33, /* USAGE (Rx) */ + D_USAGE, 0x34, /* USAGE (Ry) */ + D_MULTIBYTE(D_LOGICAL_MINIMUM), 0x00, 0x80, /* LOGICAL_MINIMUM (-32768) */ + D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xFF, 0x7F, /* LOGICAL_MAXIMUM (32767) */ + D_REPORT_SIZE, 0x10, /* REPORT_SIZE (16) */ + D_REPORT_COUNT, 0x04, /* REPORT_COUNT (4) */ + D_INPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ /* 2 8bit Axis */ - D_USAGE, 0x32, /* USAGE (Z) */ - D_USAGE, 0x35, /* USAGE (Rz) */ - D_LOGICAL_MINIMUM, 0x80, /* LOGICAL_MINIMUM (-128) */ - D_LOGICAL_MAXIMUM, 0x7F, /* LOGICAL_MAXIMUM (127) */ - D_REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ - D_REPORT_COUNT, 0x02, /* REPORT_COUNT (2) */ - D_INPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ - D_END_COLLECTION, /* END_COLLECTION */ + D_USAGE, 0x32, /* USAGE (Z) */ + D_USAGE, 0x35, /* USAGE (Rz) */ + D_LOGICAL_MINIMUM, 0x80, /* LOGICAL_MINIMUM (-128) */ + D_LOGICAL_MAXIMUM, 0x7F, /* LOGICAL_MAXIMUM (127) */ + D_REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ + D_REPORT_COUNT, 0x02, /* REPORT_COUNT (2) */ + D_INPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ + D_END_COLLECTION, /* END_COLLECTION */ /* 2 Hat Switches */ - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ - D_USAGE, 0x39, /* USAGE (Hat switch) */ - D_USAGE, 0x39, /* USAGE (Hat switch) */ - D_LOGICAL_MINIMUM, 0x01, /* LOGICAL_MINIMUM (1) */ - D_LOGICAL_MAXIMUM, 0x08, /* LOGICAL_MAXIMUM (8) */ - D_REPORT_COUNT, 0x02, /* REPORT_COUNT (2) */ - D_REPORT_SIZE, 0x04, /* REPORT_SIZE (4) */ - D_INPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ - D_END_COLLECTION /* END_COLLECTION */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ + D_USAGE, 0x39, /* USAGE (Hat switch) */ + D_USAGE, 0x39, /* USAGE (Hat switch) */ + D_LOGICAL_MINIMUM, 0x01, /* LOGICAL_MINIMUM (1) */ + D_LOGICAL_MAXIMUM, 0x08, /* LOGICAL_MAXIMUM (8) */ + D_REPORT_COUNT, 0x02, /* REPORT_COUNT (2) */ + D_REPORT_SIZE, 0x04, /* REPORT_SIZE (4) */ + D_INPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), /* INPUT (Data,Var,Abs) */ + D_END_COLLECTION /* END_COLLECTION */ }; Gamepad_::Gamepad_() { diff --git a/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp b/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp index b448cd7201..c8cb7cf818 100644 --- a/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp @@ -29,19 +29,19 @@ THE SOFTWARE. static const uint8_t system_control_hid_descriptor_[] PROGMEM = { //TODO limit to system keys only? /* System Control (Power Down, Sleep, Wakeup, ...) */ - D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ - D_USAGE, 0x80, /* USAGE (System Control) */ - D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ - D_REPORT_ID, HID_REPORTID_SYSTEMCONTROL, /* REPORT_ID */ + D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) */ + D_USAGE, 0x80, /* USAGE (System Control) */ + D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ + D_REPORT_ID, HID_REPORTID_SYSTEMCONTROL, /* REPORT_ID */ /* 1 system key */ - D_LOGICAL_MINIMUM, 0x00, /* LOGICAL_MINIMUM (0) */ - D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xff, 0x00, /* LOGICAL_MAXIMUM (255) */ - D_USAGE_MINIMUM, 0x00, /* USAGE_MINIMUM (Undefined) */ - D_USAGE_MAXIMUM, 0xff, /* USAGE_MAXIMUM (System Menu Down) */ - D_REPORT_COUNT, 0x01, /* REPORT_COUNT (1) */ - D_REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ - D_INPUT, (D_DATA | D_ARRAY | D_ABSOLUTE), /* INPUT (Data,Ary,Abs) */ - D_END_COLLECTION /* END_COLLECTION */ + D_LOGICAL_MINIMUM, 0x00, /* LOGICAL_MINIMUM (0) */ + D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xff, 0x00, /* LOGICAL_MAXIMUM (255) */ + D_USAGE_MINIMUM, 0x00, /* USAGE_MINIMUM (Undefined) */ + D_USAGE_MAXIMUM, 0xff, /* USAGE_MAXIMUM (System Menu Down) */ + D_REPORT_COUNT, 0x01, /* REPORT_COUNT (1) */ + D_REPORT_SIZE, 0x08, /* REPORT_SIZE (8) */ + D_INPUT, (D_DATA | D_ARRAY | D_ABSOLUTE), /* INPUT (Data,Ary,Abs) */ + D_END_COLLECTION /* END_COLLECTION */ }; SystemControl_::SystemControl_() { From eaacffd918411842b987276db3b5eb4169c640d2 Mon Sep 17 00:00:00 2001 From: Michael Richters Date: Fri, 4 Dec 2020 23:42:08 -0600 Subject: [PATCH 557/602] Improve handling of simultaneous changes in a single NKRO report When `sendReport()` is called, it now first checks for changes in the modifiers byte, and breaks down the process of transitioning to the new report into three stages: 1. First, any non-modifier keycodes that toggled off are removed from the old report, if any, and a report is (conditionally) sent. This ensures that a key with a modifier flag attached that toggles off won't have the host process the modifier first, potentially causing a erroneous repeat character. For example, if `LSHIFT(Key_4)` is held and released, we need to first send a report without the `4`, or some hosts will process the release of `shift` first, and give us `$$$4` in the output instead of `$$$$`. 2. Second, the modifiers that toggled on and/or off are updated, and a report is sent. This handles the situation where a key with a modifier flag toggles on, and we need to ensure that the host will process the modifier first to prevent erroneous output on the first character (`4$$$` vs `$$$$`). 3. Last, if there are any non-modifier keycodes that toggled on, they are added to the old report, and the final report is sent. To accomplish this, the old report is modified in each step, and `sendReportUnchecked()` sends the contents of that (modified) old report rather than the new one. We could avoid that by making a temporary copy of the old report, and updating and sending that instead, but there isn't much point to doing so because there isn't any reasonable way for us to recover from errors. Kaleidoscope doesn't even check the return value when calling `sendReport()`, and it's not clear what we should do if an error occurs, anyway. Signed-off-by: Michael Richters --- .../src/MultiReport/Keyboard.cpp | 108 ++++++++++-------- 1 file changed, 63 insertions(+), 45 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index 587d08426d..b776bc8afa 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -95,59 +95,77 @@ void Keyboard_::end() { } int Keyboard_::sendReportUnchecked() { - return HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, &report_, sizeof(report_)); + return HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, + &last_report_, sizeof(last_report_)); } +// Sending the current HID report to the host: +// +// Depending on the differences between the current and previous HID reports, we +// might need to send one or two extra reports to guarantee that the host will +// process the changes in the correct order. There are two important scenarios +// to consider: +// +// 1. If a non-modifier keycode toggles off in the same report as a modifier +// changes, the host might process the modifier change first. For example, if +// both `shift` and `4` toggle off in the same report (most likely from a +// `LSHIFT(Key_4)` key being released), and that key has been held long enough +// to trigger character repeat, we could end up with a plain `4` in the output +// at the end of the repeat: `$$$$4` instead of `$$$$$`. +// +// 2. If a non-modifier keycode toggles on in the same report as a modifier +// changes, the host might process the non-modifer first. For example, pressing +// and holding an `LSHIFT(Key_4)` key might result in `4$$$` rather than `$$$$`. +// +// Therefore, each call to `sendReport()` must send (up to) three reports to the +// host to guarantee the correct order of processing: +// +// 1. A report with toggled-off non-modifiers removed. +// 2. A report with changes to modifiers. +// 3. A report with toggled-on non-modifiers added. int Keyboard_::sendReport() { - // If the last report is different than the current report, then we need to - // send a report. We guard sendReport like this so that calling code doesn't - // end up spamming the host with empty reports if sendReport is called in a - // tight loop. - - if (memcmp(last_report_.allkeys, report_.allkeys, sizeof(report_))) { - // if the two reports are different, send a report - - // ChromeOS 51-60 (at least) bug: if a modifier and a normal keycode are - // added in the same report, in some cases the shift is not applied - // (e.g. `shift`+`[` doesn't yield `{`). To compensate for this, check to - // see if the modifier byte has changed. - - // If modifiers are being turned on at the same time as any change to the - // non-modifier keys in the report, then we send the previous report with - // the new modifiers - if (((last_report_.modifiers ^ report_.modifiers) & report_.modifiers) - && (memcmp(last_report_.keys, report_.keys, sizeof(report_.keys)))) { - uint8_t last_mods = last_report_.modifiers; - last_report_.modifiers = report_.modifiers; - int returnCode = HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, - &last_report_, sizeof(last_report_)); - last_report_.modifiers = last_mods; + // If the new HID report differs from the previous one both in active modifier + // keycodes and non-modifier keycodes, we will need to send at least one extra + // report. First, we compare the modifiers bytes of the two reports. + const uint8_t old_modifiers = last_report_.modifiers; + const uint8_t new_modifiers = report_.modifiers; + + const uint8_t changed_modifiers = old_modifiers ^ new_modifiers; + + if (changed_modifiers != 0) { + // There was at least one modifier change (toggled on or off), remove any + // non-modifiers from the stored previous report that toggled off in the new + // report, and send it to the host. + bool non_modifiers_toggled_off = false; + for (uint8_t i = 0; i < KEY_BYTES; ++i) { + byte released_keycodes = last_report_.keys[i] & ~(report_.keys[i]); + if (released_keycodes != 0) { + last_report_.keys[i] &= ~released_keycodes; + non_modifiers_toggled_off = true; + } } - - // If modifiers are being turned off, then we send the new report with the - // previous modifiers. We need to do this, at least on Linux 4.17 + - // Wayland. Jesse has observed that sending Shift + 3 key up events in the - // same report will sometimes result in a spurious '3' rather than '#', - // especially when the keys had been held for a while - else if (((last_report_.modifiers ^ report_.modifiers) & last_report_.modifiers) - && (memcmp(last_report_.keys, report_.keys, sizeof(report_.keys)))) { - uint8_t mods = report_.modifiers; - report_.modifiers = last_report_.modifiers; - int returnCode = HID().SendReport(HID_REPORTID_NKRO_KEYBOARD, - &report_, sizeof(last_report_)); - report_.modifiers = mods; + if (non_modifiers_toggled_off) { + sendReportUnchecked(); } + // Next, update the modifiers byte of the stored previous report, and send + // it. + last_report_.modifiers = new_modifiers; + sendReportUnchecked(); + } - - - - - int returnCode = sendReportUnchecked(); - if (returnCode > 0) - memcpy(last_report_.allkeys, report_.allkeys, sizeof(report_)); - return returnCode; + // Finally, copy the new report to the previous one, and send it. + if (memcmp(last_report_.keys, report_.keys, sizeof(report_.keys)) != 0) { + memcpy(last_report_.keys, report_.keys, sizeof(report_.keys)); + return sendReportUnchecked(); } + // A note on return values: Kaleidoscope doesn't actually check the return + // value of `sendReport()`, so this function could be changed to return + // void. It would be nice if we could do something to recover from an error + // here, but it's not at all clear what that should be. Also note that if the + // extra reports above return an error, there's not much we can do to try to + // recover. We could try to send the report again, but that would be likely to + // fail as well. return -1; } From c6f1c25fb5c5e704593ec15d6d89bc16406d00f3 Mon Sep 17 00:00:00 2001 From: Michael Richters Date: Tue, 13 Apr 2021 14:30:34 -0500 Subject: [PATCH 558/602] Make Keyboard HID report data variables private These were originally made public at my request in order to (imperfectly) work around a mid-cycle report problem in Qukeys. That problem was that, if a plugin wanted to send one or more extra reports in response to a keyswitch toggling on or off, it was not possible to safely send such a report from an `onKeyswitchEvent()` handler, because the new report was likely incomplete. The workaround was to give plugins direct access to the old report's data structure, which could then be modified and sent. This wasn't a good solution, however, because of potentially complex plugin interactions. That workaround has since been replaced with a system that only sends reports in another handler function (`beforeReportingState()` or `afterEachCycle()`). This works, and while it creates more complexity, it solves the problem without requiring direct access to the report data, and better avoids potential bugs. Signed-off-by: Michael Richters --- plugins/KeyboardioHID/src/MultiReport/Keyboard.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h index fc7637fb34..799b1fd816 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h @@ -67,9 +67,10 @@ class Keyboard_ { return HID().getLEDs(); }; + private: HID_KeyboardReport_Data_t report_; HID_KeyboardReport_Data_t last_report_; - private: + int sendReportUnchecked(); }; extern Keyboard_ Keyboard; From ee8790a98f60d84d162ead113d4bdfc109c43f3d Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Tue, 28 Sep 2021 02:23:31 +0200 Subject: [PATCH 559/602] Fix HID_SET_IDLE Based on arduino/ArduinoCore-avr#422, we need to use `wValueH` rather than `wValueL` when handling the `HID_SET_IDLE` request, according to the USB spec. Fixes #71. Signed-off-by: Gergely Nagy --- plugins/KeyboardioHID/src/HID.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/HID.cpp b/plugins/KeyboardioHID/src/HID.cpp index 1c6e98ac60..37a9c4b415 100644 --- a/plugins/KeyboardioHID/src/HID.cpp +++ b/plugins/KeyboardioHID/src/HID.cpp @@ -152,7 +152,7 @@ bool HID_::setup(USBSetup& setup) { return true; } if (request == HID_SET_IDLE) { - idle = setup.wValueL; + idle = setup.wValueH; return true; } if (request == HID_SET_REPORT) { From 9cc0e82834f2147857be281b07cc665441748f8d Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Sat, 30 Oct 2021 13:29:01 +0200 Subject: [PATCH 560/602] Add very basic gdb32 support Signed-off-by: Gergely Nagy --- plugins/KeyboardioHID/src/HID-Settings.h | 75 ++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/plugins/KeyboardioHID/src/HID-Settings.h b/plugins/KeyboardioHID/src/HID-Settings.h index c9fdec64b2..b18c33b1e1 100644 --- a/plugins/KeyboardioHID/src/HID-Settings.h +++ b/plugins/KeyboardioHID/src/HID-Settings.h @@ -129,6 +129,81 @@ int USB_SendControl(uint8_t x, const void* y, uint8_t z); #define HID_REPORT_TYPE_OUTPUT 2 #define HID_REPORT_TYPE_FEATURE 3 +#elif defined(ARDUINO_ARCH_GD32) + +#include "api/PluggableUSB.h" +#include "USBCore.h" + +#define EPTYPE_DESCRIPTOR_SIZE unsigned int +#define USB_DEVICE_CLASS_HUMAN_INTERFACE 0x03 + +#define EP_TYPE_INTERRUPT_IN EPTYPE(USB_TRX_IN, USB_EP_ATTR_INT); +#define EP_TYPE_INTERRUPT_OUT EPTYPE(USB_TRX_OUT, USB_EP_ATTR_INT); + +// TODO(@algernon): Most of these would belong to the core, into USBCore.h and +// USBAPI.h. Move them there, eventually. + +#define USB_ENDPOINT_TYPE_INTERRUPT USB_EP_ATTR_INT + +#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 USB_ENDPOINT_IN(addr) (lowByte((addr) | 0x80)) + +#define USB_EP_SIZE 64 + +#define TRANSFER_PGM 0x80 +#define TRANSFER_RELEASE 0x40 +#define TRANSFER_ZERO 0x20 + +// 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) +#define REQUEST_DEVICETOHOST_STANDARD_INTERFACE (REQUEST_DEVICETOHOST | REQUEST_STANDARD | REQUEST_INTERFACE) + +// Interface +typedef struct +{ + uint8_t len; // 9 + uint8_t dtype; // 4 + uint8_t number; + uint8_t alternate; + uint8_t numEndpoints; + uint8_t interfaceClass; + uint8_t interfaceSubClass; + uint8_t protocol; + uint8_t iInterface; +} InterfaceDescriptor; + +// Endpoint +typedef struct +{ + uint8_t len; // 7 + uint8_t dtype; // 5 + uint8_t addr; + uint8_t attr; + uint16_t packetSize; + uint8_t interval; +} EndpointDescriptor; + #else #error "Unsupported architecture" From 30fc7b9e0fa15f47bcaab1a0109d2923333fc012 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Tue, 2 Nov 2021 12:05:45 +0100 Subject: [PATCH 561/602] BootKeyboard: Reorganize how the default protocol can be set Instead of doing the plugging late, in `.begin()`, allow setting the protocol in the constructor, and mark the global object weak, so it can be overridden in a user sketch, with one that has the desired protocol set. Signed-off-by: Gergely Nagy --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp | 6 +++--- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 3546d50b7a..7c6b949934 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -73,8 +73,9 @@ static const uint8_t boot_keyboard_hid_descriptor_[] PROGMEM = { D_END_COLLECTION }; -BootKeyboard_::BootKeyboard_() : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1), leds(0) { +BootKeyboard_::BootKeyboard_(uint8_t protocol_) : PluggableUSBModule(1, 1, epType), protocol(protocol_), default_protocol(protocol_), idle(1), leds(0) { epType[0] = EP_TYPE_INTERRUPT_IN; + PluggableUSB().plug(this); } int BootKeyboard_::getInterface(uint8_t* interfaceCount) { @@ -110,8 +111,6 @@ int BootKeyboard_::getDescriptor(USBSetup& setup) { void BootKeyboard_::begin() { - PluggableUSB().plug(this); - // Force API to send a clean report. // This is important for and HID bridge where the receiver stays on, // while the sender is resetted. @@ -371,4 +370,5 @@ bool BootKeyboard_::wasAnyModifierActive() { return last_report_.modifiers > 0; } +__attribute__((weak)) BootKeyboard_ BootKeyboard; diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index 38da09db90..0414debf94 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -45,7 +45,7 @@ typedef union { class BootKeyboard_ : public PluggableUSBModule { public: - BootKeyboard_(); + BootKeyboard_(uint8_t protocol_ = HID_REPORT_PROTOCOL); size_t press(uint8_t k); void begin(); void end(); @@ -65,7 +65,7 @@ class BootKeyboard_ : public PluggableUSBModule { uint8_t getProtocol(); void setProtocol(uint8_t protocol); - uint8_t default_protocol = HID_REPORT_PROTOCOL; + uint8_t default_protocol; protected: HID_BootKeyboardReport_Data_t report_, last_report_; From 99d20d4478d25661d16d5c790e21e30e63e85590 Mon Sep 17 00:00:00 2001 From: Brian Cully Date: Fri, 12 Nov 2021 13:39:10 -0500 Subject: [PATCH 562/602] Fixes for GD32 architecture. * Explicitly pack interface and endpoint descriptors so they are the correct size. * Move module plugs and HID sub-descriptors to constructors as gd32 needs them very early. --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp | 3 ++- plugins/KeyboardioHID/src/HID-Settings.h | 2 ++ plugins/KeyboardioHID/src/MultiReport/Mouse.cpp | 5 ++--- plugins/KeyboardioHID/src/arch/gd32.cpp | 8 ++++++++ 4 files changed, 14 insertions(+), 4 deletions(-) create mode 100644 plugins/KeyboardioHID/src/arch/gd32.cpp diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 3546d50b7a..7d106ec04f 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -75,6 +75,7 @@ static const uint8_t boot_keyboard_hid_descriptor_[] PROGMEM = { BootKeyboard_::BootKeyboard_() : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1), leds(0) { epType[0] = EP_TYPE_INTERRUPT_IN; + PluggableUSB().plug(this); } int BootKeyboard_::getInterface(uint8_t* interfaceCount) { @@ -110,7 +111,7 @@ int BootKeyboard_::getDescriptor(USBSetup& setup) { void BootKeyboard_::begin() { - PluggableUSB().plug(this); + // PluggableUSB().plug(this); // Force API to send a clean report. // This is important for and HID bridge where the receiver stays on, diff --git a/plugins/KeyboardioHID/src/HID-Settings.h b/plugins/KeyboardioHID/src/HID-Settings.h index b18c33b1e1..0b229b5f9e 100644 --- a/plugins/KeyboardioHID/src/HID-Settings.h +++ b/plugins/KeyboardioHID/src/HID-Settings.h @@ -179,6 +179,7 @@ int USB_SendControl(uint8_t x, const void* y, uint8_t z); #define REQUEST_HOSTTODEVICE_CLASS_INTERFACE (REQUEST_HOSTTODEVICE | REQUEST_CLASS | REQUEST_INTERFACE) #define REQUEST_DEVICETOHOST_STANDARD_INTERFACE (REQUEST_DEVICETOHOST | REQUEST_STANDARD | REQUEST_INTERFACE) +#pragma pack(push, 1) // Interface typedef struct { @@ -203,6 +204,7 @@ typedef struct uint16_t packetSize; uint8_t interval; } EndpointDescriptor; +#pragma pack(pop) #else diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp index 001bb54168..71005aa19b 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp @@ -68,13 +68,12 @@ static const uint8_t mouse_hid_descriptor_[] PROGMEM = { }; Mouse_::Mouse_() { -} - -void Mouse_::begin() { static HIDSubDescriptor node(mouse_hid_descriptor_, sizeof(mouse_hid_descriptor_)); HID().AppendDescriptor(&node); +} +void Mouse_::begin() { end(); } diff --git a/plugins/KeyboardioHID/src/arch/gd32.cpp b/plugins/KeyboardioHID/src/arch/gd32.cpp new file mode 100644 index 0000000000..24599172a6 --- /dev/null +++ b/plugins/KeyboardioHID/src/arch/gd32.cpp @@ -0,0 +1,8 @@ +#include "Arduino.h" + +#ifdef ARDUINO_ARCH_GD32 + +void USB_PackMessages(bool pack) { +} + +#endif From 20b3ad4d063f1dd1301dff4563e34120104255c9 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Tue, 2 Nov 2021 11:52:49 +0100 Subject: [PATCH 563/602] BootKeyboard: Move plugging to the constructor Signed-off-by: Gergely Nagy --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 7d106ec04f..53e6ec4f0c 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -111,8 +111,6 @@ int BootKeyboard_::getDescriptor(USBSetup& setup) { void BootKeyboard_::begin() { - // PluggableUSB().plug(this); - // Force API to send a clean report. // This is important for and HID bridge where the receiver stays on, // while the sender is resetted. From a32d07924be5a8a20f10f3692806d261bfb01760 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Tue, 9 Nov 2021 18:40:18 -0800 Subject: [PATCH 564/602] TRANSFER_ macros are now in the USB core --- plugins/KeyboardioHID/src/HID-Settings.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/plugins/KeyboardioHID/src/HID-Settings.h b/plugins/KeyboardioHID/src/HID-Settings.h index 0b229b5f9e..f9a59321a4 100644 --- a/plugins/KeyboardioHID/src/HID-Settings.h +++ b/plugins/KeyboardioHID/src/HID-Settings.h @@ -155,10 +155,6 @@ int USB_SendControl(uint8_t x, const void* y, uint8_t z); #define USB_EP_SIZE 64 -#define TRANSFER_PGM 0x80 -#define TRANSFER_RELEASE 0x40 -#define TRANSFER_ZERO 0x20 - // bmRequestType #define REQUEST_HOSTTODEVICE 0x00 #define REQUEST_DEVICETOHOST 0x80 From 0c2a04ce868baaafd2665a671473fc6b5e321c1a Mon Sep 17 00:00:00 2001 From: Brian Cully Date: Fri, 12 Nov 2021 14:59:16 -0500 Subject: [PATCH 565/602] =?UTF-8?q?Explicitly=20pack=20=E2=80=98HIDDescrip?= =?UTF-8?q?tor=E2=80=99=20and=20=E2=80=98HIDDescDescriptor=E2=80=99.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I missed these on the last commit. It's not causing problems with gd32, but it's probably better to be explicit that we don't want any padding. --- plugins/KeyboardioHID/src/HID.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/KeyboardioHID/src/HID.h b/plugins/KeyboardioHID/src/HID.h index 716ea209c5..8788e2010f 100644 --- a/plugins/KeyboardioHID/src/HID.h +++ b/plugins/KeyboardioHID/src/HID.h @@ -59,6 +59,7 @@ #define HID_REPORT_TYPE_OUTPUT 2 #define HID_REPORT_TYPE_FEATURE 3 +#pragma pack(push, 1) typedef struct { uint8_t len; // 9 uint8_t dtype; // 0x21 @@ -76,6 +77,7 @@ typedef struct { HIDDescDescriptor desc; EndpointDescriptor in; } HIDDescriptor; +#pragma pack(pop) class HIDSubDescriptor { public: From 98f32eb8613b15da485ae571ab4adaa8d8f977ef Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Thu, 9 Dec 2021 13:33:35 -0800 Subject: [PATCH 566/602] Remove USB definitions for GD32 that are now in the arduino core --- plugins/KeyboardioHID/src/HID-Settings.h | 62 ------------------------ 1 file changed, 62 deletions(-) diff --git a/plugins/KeyboardioHID/src/HID-Settings.h b/plugins/KeyboardioHID/src/HID-Settings.h index f9a59321a4..b05bba804f 100644 --- a/plugins/KeyboardioHID/src/HID-Settings.h +++ b/plugins/KeyboardioHID/src/HID-Settings.h @@ -140,68 +140,6 @@ int USB_SendControl(uint8_t x, const void* y, uint8_t z); #define EP_TYPE_INTERRUPT_IN EPTYPE(USB_TRX_IN, USB_EP_ATTR_INT); #define EP_TYPE_INTERRUPT_OUT EPTYPE(USB_TRX_OUT, USB_EP_ATTR_INT); -// TODO(@algernon): Most of these would belong to the core, into USBCore.h and -// USBAPI.h. Move them there, eventually. - -#define USB_ENDPOINT_TYPE_INTERRUPT USB_EP_ATTR_INT - -#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 USB_ENDPOINT_IN(addr) (lowByte((addr) | 0x80)) - -#define USB_EP_SIZE 64 - -// 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) -#define REQUEST_DEVICETOHOST_STANDARD_INTERFACE (REQUEST_DEVICETOHOST | REQUEST_STANDARD | REQUEST_INTERFACE) - -#pragma pack(push, 1) -// Interface -typedef struct -{ - uint8_t len; // 9 - uint8_t dtype; // 4 - uint8_t number; - uint8_t alternate; - uint8_t numEndpoints; - uint8_t interfaceClass; - uint8_t interfaceSubClass; - uint8_t protocol; - uint8_t iInterface; -} InterfaceDescriptor; - -// Endpoint -typedef struct -{ - uint8_t len; // 7 - uint8_t dtype; // 5 - uint8_t addr; - uint8_t attr; - uint16_t packetSize; - uint8_t interval; -} EndpointDescriptor; -#pragma pack(pop) - #else #error "Unsupported architecture" From 9f868411c0e5cd3728c79741cea83a78a26fafab Mon Sep 17 00:00:00 2001 From: Michael Richters Date: Tue, 14 Dec 2021 09:09:15 -0600 Subject: [PATCH 567/602] Fix init order warning for BootKeyboard constructor The constructor for `BootKeyboard` had its arguments in the wrong order; they're required to be in the same order the member variables are listed in the class definition in the header file. Signed-off-by: Michael Richters --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 7c6b949934..0e7af7ce2d 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -73,7 +73,7 @@ static const uint8_t boot_keyboard_hid_descriptor_[] PROGMEM = { D_END_COLLECTION }; -BootKeyboard_::BootKeyboard_(uint8_t protocol_) : PluggableUSBModule(1, 1, epType), protocol(protocol_), default_protocol(protocol_), idle(1), leds(0) { +BootKeyboard_::BootKeyboard_(uint8_t protocol_) : PluggableUSBModule(1, 1, epType), default_protocol(protocol_), protocol(protocol_), idle(1), leds(0) { epType[0] = EP_TYPE_INTERRUPT_IN; PluggableUSB().plug(this); } From b5ab484456941d3be69ee14d54057a944c42ced9 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Tue, 11 Jan 2022 17:34:32 -0800 Subject: [PATCH 568/602] Until Kaleidoscope supports CDC-ACM, we need to rRevert "Remove USB definitions for GD32 that are now in the arduino core" This reverts commit 98f32eb8613b15da485ae571ab4adaa8d8f977ef. --- plugins/KeyboardioHID/src/HID-Settings.h | 62 ++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/plugins/KeyboardioHID/src/HID-Settings.h b/plugins/KeyboardioHID/src/HID-Settings.h index b05bba804f..f9a59321a4 100644 --- a/plugins/KeyboardioHID/src/HID-Settings.h +++ b/plugins/KeyboardioHID/src/HID-Settings.h @@ -140,6 +140,68 @@ int USB_SendControl(uint8_t x, const void* y, uint8_t z); #define EP_TYPE_INTERRUPT_IN EPTYPE(USB_TRX_IN, USB_EP_ATTR_INT); #define EP_TYPE_INTERRUPT_OUT EPTYPE(USB_TRX_OUT, USB_EP_ATTR_INT); +// TODO(@algernon): Most of these would belong to the core, into USBCore.h and +// USBAPI.h. Move them there, eventually. + +#define USB_ENDPOINT_TYPE_INTERRUPT USB_EP_ATTR_INT + +#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 USB_ENDPOINT_IN(addr) (lowByte((addr) | 0x80)) + +#define USB_EP_SIZE 64 + +// 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) +#define REQUEST_DEVICETOHOST_STANDARD_INTERFACE (REQUEST_DEVICETOHOST | REQUEST_STANDARD | REQUEST_INTERFACE) + +#pragma pack(push, 1) +// Interface +typedef struct +{ + uint8_t len; // 9 + uint8_t dtype; // 4 + uint8_t number; + uint8_t alternate; + uint8_t numEndpoints; + uint8_t interfaceClass; + uint8_t interfaceSubClass; + uint8_t protocol; + uint8_t iInterface; +} InterfaceDescriptor; + +// Endpoint +typedef struct +{ + uint8_t len; // 7 + uint8_t dtype; // 5 + uint8_t addr; + uint8_t attr; + uint16_t packetSize; + uint8_t interval; +} EndpointDescriptor; +#pragma pack(pop) + #else #error "Unsupported architecture" From 5375381ddca9c73bc882fec4b75437579b07b9f4 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Tue, 8 Feb 2022 12:30:53 -0800 Subject: [PATCH 569/602] Revert "Until Kaleidoscope supports CDC-ACM, we need to rRevert "Remove USB definitions for GD32 that are now in the arduino core"" This reverts commit b5ab484456941d3be69ee14d54057a944c42ced9. --- plugins/KeyboardioHID/src/HID-Settings.h | 62 ------------------------ 1 file changed, 62 deletions(-) diff --git a/plugins/KeyboardioHID/src/HID-Settings.h b/plugins/KeyboardioHID/src/HID-Settings.h index f9a59321a4..b05bba804f 100644 --- a/plugins/KeyboardioHID/src/HID-Settings.h +++ b/plugins/KeyboardioHID/src/HID-Settings.h @@ -140,68 +140,6 @@ int USB_SendControl(uint8_t x, const void* y, uint8_t z); #define EP_TYPE_INTERRUPT_IN EPTYPE(USB_TRX_IN, USB_EP_ATTR_INT); #define EP_TYPE_INTERRUPT_OUT EPTYPE(USB_TRX_OUT, USB_EP_ATTR_INT); -// TODO(@algernon): Most of these would belong to the core, into USBCore.h and -// USBAPI.h. Move them there, eventually. - -#define USB_ENDPOINT_TYPE_INTERRUPT USB_EP_ATTR_INT - -#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 USB_ENDPOINT_IN(addr) (lowByte((addr) | 0x80)) - -#define USB_EP_SIZE 64 - -// 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) -#define REQUEST_DEVICETOHOST_STANDARD_INTERFACE (REQUEST_DEVICETOHOST | REQUEST_STANDARD | REQUEST_INTERFACE) - -#pragma pack(push, 1) -// Interface -typedef struct -{ - uint8_t len; // 9 - uint8_t dtype; // 4 - uint8_t number; - uint8_t alternate; - uint8_t numEndpoints; - uint8_t interfaceClass; - uint8_t interfaceSubClass; - uint8_t protocol; - uint8_t iInterface; -} InterfaceDescriptor; - -// Endpoint -typedef struct -{ - uint8_t len; // 7 - uint8_t dtype; // 5 - uint8_t addr; - uint8_t attr; - uint16_t packetSize; - uint8_t interval; -} EndpointDescriptor; -#pragma pack(pop) - #else #error "Unsupported architecture" From e4f12fc661763fab3e3773f7eb8fb7074ec5758a Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Wed, 16 Feb 2022 12:01:30 -0800 Subject: [PATCH 570/602] We always require PluggableUSB --- plugins/KeyboardioHID/src/HID-Settings.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/plugins/KeyboardioHID/src/HID-Settings.h b/plugins/KeyboardioHID/src/HID-Settings.h index b05bba804f..12e4712a10 100644 --- a/plugins/KeyboardioHID/src/HID-Settings.h +++ b/plugins/KeyboardioHID/src/HID-Settings.h @@ -77,14 +77,10 @@ void USB_PackMessages(bool pack); #if defined(ARDUINO_ARCH_AVR) -#include "PluggableUSB.h" - #define EPTYPE_DESCRIPTOR_SIZE uint8_t #elif defined(ARDUINO_ARCH_SAM) -#include "USB/PluggableUSB.h" - #define EPTYPE_DESCRIPTOR_SIZE uint32_t #define EP_TYPE_INTERRUPT_IN (UOTGHS_DEVEPTCFG_EPSIZE_512_BYTE | \ UOTGHS_DEVEPTCFG_EPDIR_IN | \ @@ -106,8 +102,6 @@ void USB_PackMessages(bool pack); #elif defined(ARDUINO_ARCH_SAMD) -#include "USB/PluggableUSB.h" - #define EPTYPE_DESCRIPTOR_SIZE uint32_t #define EP_TYPE_INTERRUPT_IN USB_ENDPOINT_TYPE_INTERRUPT | USB_ENDPOINT_IN(0); #define EP_TYPE_INTERRUPT_OUT USB_ENDPOINT_TYPE_INTERRUPT | USB_ENDPOINT_OUT(0); @@ -131,7 +125,6 @@ int USB_SendControl(uint8_t x, const void* y, uint8_t z); #elif defined(ARDUINO_ARCH_GD32) -#include "api/PluggableUSB.h" #include "USBCore.h" #define EPTYPE_DESCRIPTOR_SIZE unsigned int From 98d0a4320a00102ff67878d048abbe860a1eed9d Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Wed, 16 Feb 2022 12:01:55 -0800 Subject: [PATCH 571/602] remove redundant definition --- plugins/KeyboardioHID/src/HID-Settings.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/plugins/KeyboardioHID/src/HID-Settings.h b/plugins/KeyboardioHID/src/HID-Settings.h index 12e4712a10..9f369cdfb9 100644 --- a/plugins/KeyboardioHID/src/HID-Settings.h +++ b/plugins/KeyboardioHID/src/HID-Settings.h @@ -119,10 +119,6 @@ int USB_SendControl(uint8_t x, const void* y, uint8_t z); #define TRANSFER_PGM 0 #define TRANSFER_RELEASE 0 -#define HID_REPORT_TYPE_INPUT 1 -#define HID_REPORT_TYPE_OUTPUT 2 -#define HID_REPORT_TYPE_FEATURE 3 - #elif defined(ARDUINO_ARCH_GD32) #include "USBCore.h" From 30307bf77a00c8d9e1cf900df01e42135d40c07e Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Wed, 16 Feb 2022 12:26:38 -0800 Subject: [PATCH 572/602] Remove redundant include --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index 0414debf94..d7cfeadb83 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -28,7 +28,6 @@ THE SOFTWARE. #include #include "HID.h" -#include "HID-Settings.h" #include "HIDTables.h" #include "HIDAliases.h" From 16023709de9a73918bb4b23bf2f7c3ec7559a267 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Wed, 16 Feb 2022 12:08:35 -0800 Subject: [PATCH 573/602] Add some bulletproofing against future improvement to the GD32 USB core --- plugins/KeyboardioHID/src/HID-Settings.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plugins/KeyboardioHID/src/HID-Settings.h b/plugins/KeyboardioHID/src/HID-Settings.h index 9f369cdfb9..e7074145f4 100644 --- a/plugins/KeyboardioHID/src/HID-Settings.h +++ b/plugins/KeyboardioHID/src/HID-Settings.h @@ -124,7 +124,12 @@ int USB_SendControl(uint8_t x, const void* y, uint8_t z); #include "USBCore.h" #define EPTYPE_DESCRIPTOR_SIZE unsigned int + + +// Should eventually get defined upstream +#ifndef USB_DEVICE_CLASS_HUMAN_INTERFACE #define USB_DEVICE_CLASS_HUMAN_INTERFACE 0x03 +#endif #define EP_TYPE_INTERRUPT_IN EPTYPE(USB_TRX_IN, USB_EP_ATTR_INT); #define EP_TYPE_INTERRUPT_OUT EPTYPE(USB_TRX_OUT, USB_EP_ATTR_INT); From 5159e67093e25a4ef95193d188bc29a790800612 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Wed, 16 Feb 2022 17:54:23 -0800 Subject: [PATCH 574/602] Pack the struct for AbsoluteMouse, otherwise we end up with 8 bit reports rather than 6 bit reports on GD32 --- plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h index 9f77750a8a..a2150728e0 100644 --- a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h +++ b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.h @@ -64,6 +64,7 @@ THE SOFTWARE. D_REPORT_COUNT, 0x01, /* REPORT_COUNT (1) */ \ D_INPUT, (D_DATA|D_VARIABLE|D_RELATIVE), +#pragma pack(push, 1) typedef union { // Absolute mouse report: 8 buttons, 2 absolute axis, wheel struct { @@ -73,6 +74,7 @@ typedef union { int8_t wheel; }; } HID_MouseAbsoluteReport_Data_t; +#pragma pack(pop) class AbsoluteMouseAPI { public: From aba80ff606431e94f5e6313343cc0fc18632b790 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Wed, 16 Feb 2022 18:22:16 -0800 Subject: [PATCH 575/602] Specify a default HID EP buffer size when we don't have one manually set. --- plugins/KeyboardioHID/src/HID.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/HID.cpp b/plugins/KeyboardioHID/src/HID.cpp index 37a9c4b415..3944216ee7 100644 --- a/plugins/KeyboardioHID/src/HID.cpp +++ b/plugins/KeyboardioHID/src/HID.cpp @@ -175,7 +175,7 @@ HID_::HID_() : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1) { setReportData.reportId = 0; setReportData.leds = 0; - epType[0] = EP_TYPE_INTERRUPT_IN; + epType[0] = EP_TYPE_INTERRUPT_IN(USB_EP_SIZE); PluggableUSB().plug(this); } From b46791a7427a617a760a1d4776927fb7ebcee53b Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Wed, 16 Feb 2022 18:19:19 -0800 Subject: [PATCH 576/602] Give BootKeyboard a custom EP buffer size on platforms that support it --- .../KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 0e7af7ce2d..855c781987 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -73,8 +73,15 @@ static const uint8_t boot_keyboard_hid_descriptor_[] PROGMEM = { D_END_COLLECTION }; +#ifdef ARCH_HAS_CONFIGURABLE_EP_SIZES +static const uint8_t BOOT_KEYBOARD_EP_SIZE = 8; +#else +static const uint8_t BOOT_KEYBOARD_EP_SIZE = USB_EP_SIZE; +#endif + + BootKeyboard_::BootKeyboard_(uint8_t protocol_) : PluggableUSBModule(1, 1, epType), default_protocol(protocol_), protocol(protocol_), idle(1), leds(0) { - epType[0] = EP_TYPE_INTERRUPT_IN; + epType[0] = EP_TYPE_INTERRUPT_IN(BOOT_KEYBOARD_EP_SIZE); // This is an 8 byte report, so ask for an 8 byte buffer, so reports aren't split PluggableUSB().plug(this); } @@ -83,7 +90,7 @@ int BootKeyboard_::getInterface(uint8_t* interfaceCount) { HIDDescriptor hidInterface = { D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_BOOT_INTERFACE, HID_PROTOCOL_KEYBOARD), D_HIDREPORT(sizeof(boot_keyboard_hid_descriptor_)), - D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) + D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, BOOT_KEYBOARD_EP_SIZE, 0x01) }; return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); } From af4018020a819e59cacc6bba31ef23547df19fe2 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Wed, 16 Feb 2022 18:21:20 -0800 Subject: [PATCH 577/602] Give AbsMouse a 6 byte buffer when we can --- .../src/SingleReport/SingleAbsoluteMouse.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp index 31ac2edcac..02e36581b2 100644 --- a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp @@ -25,6 +25,7 @@ THE SOFTWARE. #include "SingleAbsoluteMouse.h" #include "HIDReportObserver.h" +#include "HID-Settings.h" static const uint8_t _hidSingleReportDescriptorAbsoluteMouse[] PROGMEM = { D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) 54 */ @@ -37,9 +38,16 @@ static const uint8_t _hidSingleReportDescriptorAbsoluteMouse[] PROGMEM = { D_END_COLLECTION /* End */ }; +#ifdef ARCH_HAS_CONFIGURABLE_EP_SIZES +static const uint8_t SINGLE_ABSOLUTEMOUSE_EP_SIZE = 6; +#else +static const uint8_t SINGLE_ABSOLUTEMOUSE_EP_SIZE = USB_EP_SIZE; +#endif + + SingleAbsoluteMouse_::SingleAbsoluteMouse_() : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1) { - epType[0] = EP_TYPE_INTERRUPT_IN; + epType[0] = EP_TYPE_INTERRUPT_IN(SINGLE_ABSOLUTEMOUSE_EP_SIZE); PluggableUSB().plug(this); } @@ -48,7 +56,7 @@ int SingleAbsoluteMouse_::getInterface(uint8_t* interfaceCount) { HIDDescriptor hidInterface = { D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE), D_HIDREPORT(sizeof(_hidSingleReportDescriptorAbsoluteMouse)), - D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) + D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, SINGLE_ABSOLUTEMOUSE_EP_SIZE, 0x01) }; return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); } From 3515356648d1ff21f469ac9e1229bec8da4b7d1d Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Wed, 16 Feb 2022 18:22:34 -0800 Subject: [PATCH 578/602] Use the fancy new EP definitions on GD32 --- plugins/KeyboardioHID/src/HID-Settings.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/plugins/KeyboardioHID/src/HID-Settings.h b/plugins/KeyboardioHID/src/HID-Settings.h index e7074145f4..f9d1691d30 100644 --- a/plugins/KeyboardioHID/src/HID-Settings.h +++ b/plugins/KeyboardioHID/src/HID-Settings.h @@ -131,8 +131,11 @@ int USB_SendControl(uint8_t x, const void* y, uint8_t z); #define USB_DEVICE_CLASS_HUMAN_INTERFACE 0x03 #endif -#define EP_TYPE_INTERRUPT_IN EPTYPE(USB_TRX_IN, USB_EP_ATTR_INT); -#define EP_TYPE_INTERRUPT_OUT EPTYPE(USB_TRX_OUT, USB_EP_ATTR_INT); + +constexpr uint16_t EP_TYPE_INTERRUPT_IN(uint8_t buffer_size) { return EPDesc(USB_TRX_IN, USB_EP_ATTR_INT, buffer_size).val; } +constexpr uint16_t EP_TYPE_INTERRUPT_OUT(uint8_t buffer_size) { return EPDesc(USB_TRX_OUT, USB_EP_ATTR_INT, buffer_size).val; } + + #else From 7d62cb43cb4a28a2c71bbe718d6b57a378594207 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Wed, 16 Feb 2022 18:53:26 -0800 Subject: [PATCH 579/602] GD32 has customizable buffer sizes --- plugins/KeyboardioHID/src/HID-Settings.h | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/KeyboardioHID/src/HID-Settings.h b/plugins/KeyboardioHID/src/HID-Settings.h index f9d1691d30..d5cf5c159f 100644 --- a/plugins/KeyboardioHID/src/HID-Settings.h +++ b/plugins/KeyboardioHID/src/HID-Settings.h @@ -131,6 +131,7 @@ int USB_SendControl(uint8_t x, const void* y, uint8_t z); #define USB_DEVICE_CLASS_HUMAN_INTERFACE 0x03 #endif +#define ARCH_HAS_CONFIGURABLE_EP_SIZES constexpr uint16_t EP_TYPE_INTERRUPT_IN(uint8_t buffer_size) { return EPDesc(USB_TRX_IN, USB_EP_ATTR_INT, buffer_size).val; } constexpr uint16_t EP_TYPE_INTERRUPT_OUT(uint8_t buffer_size) { return EPDesc(USB_TRX_OUT, USB_EP_ATTR_INT, buffer_size).val; } From 0491bc97d163470348fc4856c5243261876f7d3c Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Tue, 1 Mar 2022 13:48:14 -0800 Subject: [PATCH 580/602] Fixes for broken refactoring that added GD32 customizable endpoint size support. --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp | 4 ++++ plugins/KeyboardioHID/src/HID-Settings.h | 2 ++ plugins/KeyboardioHID/src/HID.cpp | 6 ++++++ .../KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp | 6 ++++++ 4 files changed, 18 insertions(+) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 855c781987..3772054644 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -81,7 +81,11 @@ static const uint8_t BOOT_KEYBOARD_EP_SIZE = USB_EP_SIZE; BootKeyboard_::BootKeyboard_(uint8_t protocol_) : PluggableUSBModule(1, 1, epType), default_protocol(protocol_), protocol(protocol_), idle(1), leds(0) { +#ifdef ARCH_HAS_CONFIGURABLE_EP_SIZES epType[0] = EP_TYPE_INTERRUPT_IN(BOOT_KEYBOARD_EP_SIZE); // This is an 8 byte report, so ask for an 8 byte buffer, so reports aren't split +#else + epType[0] = EP_TYPE_INTERRUPT_IN; +#endif PluggableUSB().plug(this); } diff --git a/plugins/KeyboardioHID/src/HID-Settings.h b/plugins/KeyboardioHID/src/HID-Settings.h index d5cf5c159f..b45fb5bd05 100644 --- a/plugins/KeyboardioHID/src/HID-Settings.h +++ b/plugins/KeyboardioHID/src/HID-Settings.h @@ -26,6 +26,8 @@ THE SOFTWARE. // Include guard #pragma once +#include + #define HID_REPORTID_NONE 0 #ifndef HID_REPORTID_MOUSE diff --git a/plugins/KeyboardioHID/src/HID.cpp b/plugins/KeyboardioHID/src/HID.cpp index 3944216ee7..f3e2c730be 100644 --- a/plugins/KeyboardioHID/src/HID.cpp +++ b/plugins/KeyboardioHID/src/HID.cpp @@ -175,7 +175,13 @@ HID_::HID_() : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1) { setReportData.reportId = 0; setReportData.leds = 0; + +#ifdef ARCH_HAS_CONFIGURABLE_EP_SIZES epType[0] = EP_TYPE_INTERRUPT_IN(USB_EP_SIZE); +#else + epType[0] = EP_TYPE_INTERRUPT_IN; +#endif + PluggableUSB().plug(this); } diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp index 02e36581b2..05f5176ceb 100644 --- a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp @@ -47,7 +47,13 @@ static const uint8_t SINGLE_ABSOLUTEMOUSE_EP_SIZE = USB_EP_SIZE; SingleAbsoluteMouse_::SingleAbsoluteMouse_() : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1) { + +#ifdef ARCH_HAS_CONFIGURABLE_EP_SIZES epType[0] = EP_TYPE_INTERRUPT_IN(SINGLE_ABSOLUTEMOUSE_EP_SIZE); +#else + epType[0] = EP_TYPE_INTERRUPT_IN; +#endif + PluggableUSB().plug(this); } From 1700ca077e0c56d612800190f01e32b70faaf738 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Tue, 1 Mar 2022 21:50:29 -0800 Subject: [PATCH 581/602] On GD32, PluggableUSB.h is inside api/, but it's also already included, so we don't want to include it again --- plugins/KeyboardioHID/src/HID-Settings.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/HID-Settings.h b/plugins/KeyboardioHID/src/HID-Settings.h index b45fb5bd05..7eff1e0931 100644 --- a/plugins/KeyboardioHID/src/HID-Settings.h +++ b/plugins/KeyboardioHID/src/HID-Settings.h @@ -26,7 +26,6 @@ THE SOFTWARE. // Include guard #pragma once -#include #define HID_REPORTID_NONE 0 @@ -79,10 +78,14 @@ void USB_PackMessages(bool pack); #if defined(ARDUINO_ARCH_AVR) +#include + #define EPTYPE_DESCRIPTOR_SIZE uint8_t #elif defined(ARDUINO_ARCH_SAM) +#include + #define EPTYPE_DESCRIPTOR_SIZE uint32_t #define EP_TYPE_INTERRUPT_IN (UOTGHS_DEVEPTCFG_EPSIZE_512_BYTE | \ UOTGHS_DEVEPTCFG_EPDIR_IN | \ @@ -104,6 +107,8 @@ void USB_PackMessages(bool pack); #elif defined(ARDUINO_ARCH_SAMD) +#include + #define EPTYPE_DESCRIPTOR_SIZE uint32_t #define EP_TYPE_INTERRUPT_IN USB_ENDPOINT_TYPE_INTERRUPT | USB_ENDPOINT_IN(0); #define EP_TYPE_INTERRUPT_OUT USB_ENDPOINT_TYPE_INTERRUPT | USB_ENDPOINT_OUT(0); From d1c14874d3cbee9c04f5c7498bc9d23773f0397b Mon Sep 17 00:00:00 2001 From: Michael Richters Date: Wed, 9 Mar 2022 13:28:38 -0600 Subject: [PATCH 582/602] Simplify and correct check for no-op Mouse HID reports Signed-off-by: Michael Richters --- .../KeyboardioHID/src/MultiReport/Mouse.cpp | 24 ++++++++----------- plugins/KeyboardioHID/src/MultiReport/Mouse.h | 2 +- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp index 71005aa19b..53e626aa6d 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp @@ -118,20 +118,16 @@ void Mouse_::sendReportUnchecked() { } void Mouse_::sendReport() { - // If the last report is different than the current report, then we need to - // send a report. We guard sendReport like this so that calling code doesn't - // end up spamming the host with empty reports if sendReport is called in a - // tight loop. - - // if the two reports are the same, check if they're empty, and return early - // without a report if they are. - static HID_MouseReport_Data_t empty_report; - if (memcmp(&last_report_, &report_, sizeof(report_)) == 0 && - memcmp(&report_, &empty_report, sizeof(report_)) == 0) - return; - - sendReportUnchecked(); - memcpy(&last_report_, &report_, sizeof(report_)); + // If the button state has not changed, and neither the cursor nor the wheel + // is being told to move, there is no need to send a report. This check + // prevents us from sending lots of no-op reports if the caller is in a loop + // and not checking or buggy. + if (report_.buttons != prev_report_buttons_ || + report_.xAxis != 0 || report_.yAxis != 0 || + report_.vWheel != 0 || report_.hWheel != 0) { + sendReportUnchecked(); + prev_report_buttons_ = report_.buttons; + } } Mouse_ Mouse; diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.h b/plugins/KeyboardioHID/src/MultiReport/Mouse.h index 99235f204b..1a00797cbe 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.h @@ -69,7 +69,7 @@ class Mouse_ { protected: HID_MouseReport_Data_t report_; - HID_MouseReport_Data_t last_report_; + uint8_t prev_report_buttons_ = 0; private: void sendReportUnchecked(); From cb34edd6bf0eb5aca68f13527636b03a829365ee Mon Sep 17 00:00:00 2001 From: Michael Richters Date: Wed, 9 Mar 2022 13:29:20 -0600 Subject: [PATCH 583/602] Correct Mouse HID `click()` method This method was only sending one report, but two are necessary for a "click". There was an assumption, based on the old Kaleidoscope, that a report would be sent every cycle, so the release report would be "free". This is not true of Kaleidoscope any longer, and any other client might also not behave that way. Also, if the mouse button was already active ("held"), the "press" report would be a no-op, so instead of a click, we'd just get a release. Signed-off-by: Michael Richters --- plugins/KeyboardioHID/src/MultiReport/Mouse.cpp | 10 ++++++++++ plugins/KeyboardioHID/src/MultiReport/Mouse.h | 3 +++ 2 files changed, 13 insertions(+) diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp index 53e626aa6d..dd3cec6e32 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp @@ -83,9 +83,19 @@ void Mouse_::end() { } void Mouse_::click(uint8_t b) { + // If one or more of the buttons to be clicked was already pressed, we need to + // send a report to release it first, to guarantee that this will be a "click" + // and not merely a release. + if (report_.buttons & b) { + release(b); + sendReport(); + } + // Next, send a report with the button(s) pressed: press(b); sendReport(); + // Finally, send the report with the button(s) released: release(b); + sendReport(); } void Mouse_::move(int8_t x, int8_t y, int8_t v_wheel, int8_t h_wheel) { diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.h b/plugins/KeyboardioHID/src/MultiReport/Mouse.h index 1a00797cbe..469be1fd19 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.h +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.h @@ -48,6 +48,9 @@ class Mouse_ { Mouse_(); void begin(); void end(); + // Note: the following `click()` method is unlike the `move()`, `press()`, and + // `release()` methods, in that it doesn't merely modify the pending report, + // but also calls `sendReport()` at least twice. void click(uint8_t b = MOUSE_LEFT); void move(int8_t x, int8_t y, int8_t v_wheel = 0, int8_t h_wheel = 0); void press(uint8_t b = MOUSE_LEFT); // press LEFT by default From c69cdff339035e03ac77b5a99a6365c7b9567c8f Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Sun, 3 Apr 2022 16:45:57 -0700 Subject: [PATCH 584/602] Create unions for fields we receive from the host with bbacking buffers that are modulo 16 bits in size. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is currently necessary because these fields are read directly from the USB peripheral with ‘usbd_ep_data_read’, which can only read in 16-bit chunks (as of version 2.1.2 of the firmware library). --- .../src/BootKeyboard/BootKeyboard.cpp | 4 ++-- .../KeyboardioHID/src/BootKeyboard/BootKeyboard.h | 14 +++++++++++++- plugins/KeyboardioHID/src/HID.cpp | 6 +++--- plugins/KeyboardioHID/src/HID.h | 10 ++++++++-- 4 files changed, 26 insertions(+), 8 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 3772054644..284bddcad8 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -193,8 +193,8 @@ bool BootKeyboard_::setup(USBSetup& setup) { int length = setup.wLength; if (setup.wValueH == HID_REPORT_TYPE_OUTPUT) { - if (length == sizeof(leds)) { - USB_RecvControl(&leds, length); + if (length == sizeof(leds_wrapper.leds)) { + USB_RecvControl(&leds_wrapper.leds, length); return true; } } diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index d7cfeadb83..63b46e8b4b 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -77,7 +77,19 @@ class BootKeyboard_ : public PluggableUSBModule { EPTYPE_DESCRIPTOR_SIZE epType[1]; uint8_t protocol; uint8_t idle; + union { + uint8_t leds; + uint8_t padding_[2]; + } leds_wrapper; + /* + * Create union for the ‘leds’ field that has a backing + * buffers that is modulo 16 bits in size. + * + * This is currently necessary because on GD 32 this field is read + * directly from the USB peripheral with ‘usbd_ep_data_read’, + * which can only read in 16-bit chunks (as of version 2.1.2 + * of the firmware library). + */ - uint8_t leds; }; extern BootKeyboard_ BootKeyboard; diff --git a/plugins/KeyboardioHID/src/HID.cpp b/plugins/KeyboardioHID/src/HID.cpp index f3e2c730be..4da46ec547 100644 --- a/plugins/KeyboardioHID/src/HID.cpp +++ b/plugins/KeyboardioHID/src/HID.cpp @@ -160,8 +160,8 @@ bool HID_::setup(USBSetup& setup) { if (length == sizeof(setReportData)) { USB_RecvControl(&setReportData, length); - } else if (length == sizeof(setReportData.leds)) { - USB_RecvControl(&setReportData.leds, length); + } else if (length == sizeof(setReportData.leds_wrapper.leds)) { + USB_RecvControl(&setReportData.leds_wrapper.leds, length); setReportData.reportId = 0; } } @@ -174,7 +174,7 @@ HID_::HID_() : PluggableUSBModule(1, 1, epType), rootNode(NULL), descriptorSize(0), protocol(HID_REPORT_PROTOCOL), idle(1) { setReportData.reportId = 0; - setReportData.leds = 0; + setReportData.leds_wrapper.leds = 0; #ifdef ARCH_HAS_CONFIGURABLE_EP_SIZES epType[0] = EP_TYPE_INTERRUPT_IN(USB_EP_SIZE); diff --git a/plugins/KeyboardioHID/src/HID.h b/plugins/KeyboardioHID/src/HID.h index 8788e2010f..5a89439ec0 100644 --- a/plugins/KeyboardioHID/src/HID.h +++ b/plugins/KeyboardioHID/src/HID.h @@ -96,7 +96,7 @@ class HID_ : public PluggableUSBModule { int SendReport(uint8_t id, const void* data, int len); void AppendDescriptor(HIDSubDescriptor* node); uint8_t getLEDs() { - return setReportData.leds; + return setReportData.leds_wrapper.leds; }; protected: @@ -117,7 +117,13 @@ class HID_ : public PluggableUSBModule { uint8_t idle; struct { uint8_t reportId; - uint8_t leds; + /* this wrapper union is here because on GD32, the USB endpoint reading code *only* works with + * chunks of data that are multiples of 16 bits + */ + union { + uint8_t leds; + uint8_t padding_[2]; + } leds_wrapper; } setReportData; }; From cea28ac6d66c08df5dba64e8a595f3c466eb328a Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Sun, 3 Apr 2022 16:55:01 -0700 Subject: [PATCH 585/602] Fixups to the last commit --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 284bddcad8..8ab92e667d 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -80,7 +80,7 @@ static const uint8_t BOOT_KEYBOARD_EP_SIZE = USB_EP_SIZE; #endif -BootKeyboard_::BootKeyboard_(uint8_t protocol_) : PluggableUSBModule(1, 1, epType), default_protocol(protocol_), protocol(protocol_), idle(1), leds(0) { +BootKeyboard_::BootKeyboard_(uint8_t protocol_) : PluggableUSBModule(1, 1, epType), default_protocol(protocol_), protocol(protocol_), idle(1), leds_wrapper.leds(0) { #ifdef ARCH_HAS_CONFIGURABLE_EP_SIZES epType[0] = EP_TYPE_INTERRUPT_IN(BOOT_KEYBOARD_EP_SIZE); // This is an 8 byte report, so ask for an 8 byte buffer, so reports aren't split #else @@ -213,7 +213,7 @@ bool BootKeyboard_::setup(USBSetup& setup) { } uint8_t BootKeyboard_::getLeds() { - return leds; + return leds_wrapper.leds; } uint8_t BootKeyboard_::getProtocol() { From acbb10c6ba145a5f0d00552d62b727cd4159f685 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Sun, 3 Apr 2022 18:12:07 -0700 Subject: [PATCH 586/602] Fixup the previous commit --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 8ab92e667d..5bc2495714 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -80,7 +80,7 @@ static const uint8_t BOOT_KEYBOARD_EP_SIZE = USB_EP_SIZE; #endif -BootKeyboard_::BootKeyboard_(uint8_t protocol_) : PluggableUSBModule(1, 1, epType), default_protocol(protocol_), protocol(protocol_), idle(1), leds_wrapper.leds(0) { +BootKeyboard_::BootKeyboard_(uint8_t protocol_) : PluggableUSBModule(1, 1, epType), default_protocol(protocol_), protocol(protocol_), idle(1), leds_wrapper({0}) { #ifdef ARCH_HAS_CONFIGURABLE_EP_SIZES epType[0] = EP_TYPE_INTERRUPT_IN(BOOT_KEYBOARD_EP_SIZE); // This is an 8 byte report, so ask for an 8 byte buffer, so reports aren't split #else From 1668154e78094de23271cb5abd8b69b86a8b28cb Mon Sep 17 00:00:00 2001 From: Michael Richters Date: Mon, 4 Apr 2022 19:02:32 -0500 Subject: [PATCH 587/602] Revert "Fixup the previous commit" This reverts commit acbb10c6ba145a5f0d00552d62b727cd4159f685. Signed-off-by: Michael Richters --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 5bc2495714..8ab92e667d 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -80,7 +80,7 @@ static const uint8_t BOOT_KEYBOARD_EP_SIZE = USB_EP_SIZE; #endif -BootKeyboard_::BootKeyboard_(uint8_t protocol_) : PluggableUSBModule(1, 1, epType), default_protocol(protocol_), protocol(protocol_), idle(1), leds_wrapper({0}) { +BootKeyboard_::BootKeyboard_(uint8_t protocol_) : PluggableUSBModule(1, 1, epType), default_protocol(protocol_), protocol(protocol_), idle(1), leds_wrapper.leds(0) { #ifdef ARCH_HAS_CONFIGURABLE_EP_SIZES epType[0] = EP_TYPE_INTERRUPT_IN(BOOT_KEYBOARD_EP_SIZE); // This is an 8 byte report, so ask for an 8 byte buffer, so reports aren't split #else From a6fec9d11a0c980bb68255b8a9105a33d4319d0f Mon Sep 17 00:00:00 2001 From: Michael Richters Date: Mon, 4 Apr 2022 19:02:37 -0500 Subject: [PATCH 588/602] Revert "Fixups to the last commit" This reverts commit cea28ac6d66c08df5dba64e8a595f3c466eb328a. Signed-off-by: Michael Richters --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 8ab92e667d..284bddcad8 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -80,7 +80,7 @@ static const uint8_t BOOT_KEYBOARD_EP_SIZE = USB_EP_SIZE; #endif -BootKeyboard_::BootKeyboard_(uint8_t protocol_) : PluggableUSBModule(1, 1, epType), default_protocol(protocol_), protocol(protocol_), idle(1), leds_wrapper.leds(0) { +BootKeyboard_::BootKeyboard_(uint8_t protocol_) : PluggableUSBModule(1, 1, epType), default_protocol(protocol_), protocol(protocol_), idle(1), leds(0) { #ifdef ARCH_HAS_CONFIGURABLE_EP_SIZES epType[0] = EP_TYPE_INTERRUPT_IN(BOOT_KEYBOARD_EP_SIZE); // This is an 8 byte report, so ask for an 8 byte buffer, so reports aren't split #else @@ -213,7 +213,7 @@ bool BootKeyboard_::setup(USBSetup& setup) { } uint8_t BootKeyboard_::getLeds() { - return leds_wrapper.leds; + return leds; } uint8_t BootKeyboard_::getProtocol() { From ca0f8c1bc3fdeb881af3aa541067f7c793264229 Mon Sep 17 00:00:00 2001 From: Michael Richters Date: Mon, 4 Apr 2022 19:03:22 -0500 Subject: [PATCH 589/602] Revert "Merge pull request #83 from keyboardio/f/gd32-16-bit-workaround" This reverts commit c964f84fd53ad0f5084e34e92a9339ef31678abc, reversing changes made to 75c1e0b1ffaf17ad0c561288ef3e566ff058c145. Signed-off-by: Michael Richters --- .../src/BootKeyboard/BootKeyboard.cpp | 4 ++-- .../KeyboardioHID/src/BootKeyboard/BootKeyboard.h | 14 +------------- plugins/KeyboardioHID/src/HID.cpp | 6 +++--- plugins/KeyboardioHID/src/HID.h | 10 ++-------- 4 files changed, 8 insertions(+), 26 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 284bddcad8..3772054644 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -193,8 +193,8 @@ bool BootKeyboard_::setup(USBSetup& setup) { int length = setup.wLength; if (setup.wValueH == HID_REPORT_TYPE_OUTPUT) { - if (length == sizeof(leds_wrapper.leds)) { - USB_RecvControl(&leds_wrapper.leds, length); + if (length == sizeof(leds)) { + USB_RecvControl(&leds, length); return true; } } diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index 63b46e8b4b..d7cfeadb83 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -77,19 +77,7 @@ class BootKeyboard_ : public PluggableUSBModule { EPTYPE_DESCRIPTOR_SIZE epType[1]; uint8_t protocol; uint8_t idle; - union { - uint8_t leds; - uint8_t padding_[2]; - } leds_wrapper; - /* - * Create union for the ‘leds’ field that has a backing - * buffers that is modulo 16 bits in size. - * - * This is currently necessary because on GD 32 this field is read - * directly from the USB peripheral with ‘usbd_ep_data_read’, - * which can only read in 16-bit chunks (as of version 2.1.2 - * of the firmware library). - */ + uint8_t leds; }; extern BootKeyboard_ BootKeyboard; diff --git a/plugins/KeyboardioHID/src/HID.cpp b/plugins/KeyboardioHID/src/HID.cpp index 4da46ec547..f3e2c730be 100644 --- a/plugins/KeyboardioHID/src/HID.cpp +++ b/plugins/KeyboardioHID/src/HID.cpp @@ -160,8 +160,8 @@ bool HID_::setup(USBSetup& setup) { if (length == sizeof(setReportData)) { USB_RecvControl(&setReportData, length); - } else if (length == sizeof(setReportData.leds_wrapper.leds)) { - USB_RecvControl(&setReportData.leds_wrapper.leds, length); + } else if (length == sizeof(setReportData.leds)) { + USB_RecvControl(&setReportData.leds, length); setReportData.reportId = 0; } } @@ -174,7 +174,7 @@ HID_::HID_() : PluggableUSBModule(1, 1, epType), rootNode(NULL), descriptorSize(0), protocol(HID_REPORT_PROTOCOL), idle(1) { setReportData.reportId = 0; - setReportData.leds_wrapper.leds = 0; + setReportData.leds = 0; #ifdef ARCH_HAS_CONFIGURABLE_EP_SIZES epType[0] = EP_TYPE_INTERRUPT_IN(USB_EP_SIZE); diff --git a/plugins/KeyboardioHID/src/HID.h b/plugins/KeyboardioHID/src/HID.h index 5a89439ec0..8788e2010f 100644 --- a/plugins/KeyboardioHID/src/HID.h +++ b/plugins/KeyboardioHID/src/HID.h @@ -96,7 +96,7 @@ class HID_ : public PluggableUSBModule { int SendReport(uint8_t id, const void* data, int len); void AppendDescriptor(HIDSubDescriptor* node); uint8_t getLEDs() { - return setReportData.leds_wrapper.leds; + return setReportData.leds; }; protected: @@ -117,13 +117,7 @@ class HID_ : public PluggableUSBModule { uint8_t idle; struct { uint8_t reportId; - /* this wrapper union is here because on GD32, the USB endpoint reading code *only* works with - * chunks of data that are multiples of 16 bits - */ - union { - uint8_t leds; - uint8_t padding_[2]; - } leds_wrapper; + uint8_t leds; } setReportData; }; From fe2d78704e1481435e9cc3dd458099c1923a812b Mon Sep 17 00:00:00 2001 From: Michael Richters Date: Mon, 4 Apr 2022 19:26:31 -0500 Subject: [PATCH 590/602] Alternate workaround for the GD32 `uint_16t*` cast bug This version confines the changes to the method definitions affected, and should make it simpler to revert those changes later. Signed-off-by: Michael Richters --- .../src/BootKeyboard/BootKeyboard.cpp | 22 +++++++++++++- plugins/KeyboardioHID/src/HID.cpp | 29 +++++++++++++++++-- 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 3772054644..3a2cd59bde 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -192,12 +192,32 @@ bool BootKeyboard_::setup(USBSetup& setup) { // Check if data has the correct length afterwards int length = setup.wLength; + // ------------------------------------------------------------ + // Workaround for a bug in the GD32 core: + // + // On GD32, when we call `USV_RecvControl`, it casts the (void*) pointer + // we give it to `uint16_t*`, which means that it will alway write an even + // number of bytes to that pointer. Because we don't want to overwrite + // the next byte in memory past `leds`, we use a temporary array that is + // guaranteed to be big enough, and copy the data from that: if (setup.wValueH == HID_REPORT_TYPE_OUTPUT) { if (length == sizeof(leds)) { - USB_RecvControl(&leds, length); + uint8_t raw_report_data[2]; + USB_RecvControl(&raw_report_data, length); + leds = raw_report_data[0]; return true; } } + // Once the GD32 core bug is fixed, we can replace the above code with the + // original code below: + // ------------------------------------------------------------ + // if (setup.wValueH == HID_REPORT_TYPE_OUTPUT) { + // if (length == sizeof(leds)) { + // USB_RecvControl(&leds, length); + // return true; + // } + // } + // ------------------------------------------------------------ // Input (set HID report) else if (setup.wValueH == HID_REPORT_TYPE_INPUT) { diff --git a/plugins/KeyboardioHID/src/HID.cpp b/plugins/KeyboardioHID/src/HID.cpp index f3e2c730be..d8abdbd03c 100644 --- a/plugins/KeyboardioHID/src/HID.cpp +++ b/plugins/KeyboardioHID/src/HID.cpp @@ -158,12 +158,37 @@ bool HID_::setup(USBSetup& setup) { if (request == HID_SET_REPORT) { uint16_t length = setup.wLength; + // ------------------------------------------------------------ + // Workaround for a bug in the GD32 core: + // + // On GD32, when we call `USV_RecvControl`, it casts the (void*) pointer + // we give it to `uint16_t*`, which means that it will alway write an even + // number of bytes to that pointer. Because we might be trying to just + // read the `leds` byte, and we don't want to overwrite the next byte in + // memory, instead of giving it the pointer to the `setReportData` member + // variable directly, we have it write into to temporary `raw_report_data` + // array that's guaranteed to be big enough, then copy the data from that + // array into `setReportData`: + uint8_t raw_report_data[sizeof(setReportData) + 1]; if (length == sizeof(setReportData)) { - USB_RecvControl(&setReportData, length); + USB_RecvControl(&raw_report_data, length); + setReportData.reportId = raw_report_data[0]; + setReportData.leds = raw_report_data[1]; } else if (length == sizeof(setReportData.leds)) { - USB_RecvControl(&setReportData.leds, length); + USB_RecvControl(&raw_report_data, length); setReportData.reportId = 0; + setReportData.leds = raw_report_data[0]; } + // Once the GD32 core bug is fixed, we can replace the above code with the + // original code below: + // ------------------------------------------------------------ + // if (length == sizeof(setReportData)) { + // USB_RecvControl(&setReportData, length); + // } else if (length == sizeof(setReportData.leds)) { + // USB_RecvControl(&setReportData.leds, length); + // setReportData.reportId = 0; + // } + // ------------------------------------------------------------ } } From c53e3fcb3622872e73b3eca6e52ba725aa8a6218 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Tue, 31 May 2022 20:36:59 -0700 Subject: [PATCH 591/602] Fixes for USB REPORT handling on GD32 --- .../src/BootKeyboard/BootKeyboard.cpp | 21 ++++++++++++------- plugins/KeyboardioHID/src/HID.cpp | 1 + 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 3a2cd59bde..f92c755564 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -152,21 +152,23 @@ bool BootKeyboard_::setup(USBSetup& setup) { } if (request == HID_GET_PROTOCOL) { // TODO improve -#ifdef __AVR__ +#if defined(__AVR__) UEDATX = protocol; -#endif -#ifdef ARDUINO_ARCH_SAM +#elif defined(ARDUINO_ARCH_SAM) USBDevice.armSend(0, &protocol, 1); +#else + USB_SendControl(TRANSFER_RELEASE, &protocol, sizeof(protocol)); #endif return true; } if (request == HID_GET_IDLE) { // TODO improve -#ifdef __AVR__ +#if defined(__AVR__) UEDATX = idle; -#endif -#ifdef ARDUINO_ARCH_SAM +#elif defined(ARDUINO_ARCH_SAM) USBDevice.armSend(0, &idle, 1); +#else + USB_SendControl(TRANSFER_RELEASE, &idle, sizeof(idle)); #endif return true; } @@ -191,6 +193,7 @@ bool BootKeyboard_::setup(USBSetup& setup) { if (request == HID_SET_REPORT) { // Check if data has the correct length afterwards int length = setup.wLength; + // ------------------------------------------------------------ // Workaround for a bug in the GD32 core: @@ -206,7 +209,11 @@ bool BootKeyboard_::setup(USBSetup& setup) { USB_RecvControl(&raw_report_data, length); leds = raw_report_data[0]; return true; - } +// } else { +// char tmp[8]; +// USB_RecvControl(&tmp, length); +// return true; + } } // Once the GD32 core bug is fixed, we can replace the above code with the // original code below: diff --git a/plugins/KeyboardioHID/src/HID.cpp b/plugins/KeyboardioHID/src/HID.cpp index d8abdbd03c..733c54735b 100644 --- a/plugins/KeyboardioHID/src/HID.cpp +++ b/plugins/KeyboardioHID/src/HID.cpp @@ -189,6 +189,7 @@ bool HID_::setup(USBSetup& setup) { // setReportData.reportId = 0; // } // ------------------------------------------------------------ + return true; } } From 781eb41c26e5f25915df546956dda88a419382b6 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Mon, 6 Jun 2022 14:14:24 -0700 Subject: [PATCH 592/602] We inherited code from Nico Hood's HID project that would always send a "release" report at init time. This is...not actually correct on a normal device. This commit reverts that behavior, which, among other things, caused the Keyboardio Model 100 to freeze on boot on Intel macs. That code came with this comment: // Force API to send a clean report. // This is important for and HID bridge where the receiver stays on, // while the sender is resetted. Added in this commit: commit 91e2a62e8698d71a6a9a6f887dc4cd89ae287d12 Author: NicoHood Date: Sun Oct 25 14:26:55 2015 +0100 Made Keyboard API a lot more flexible --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp | 5 ----- plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.hpp | 2 -- plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp | 2 -- plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp | 2 -- plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp | 4 ---- plugins/KeyboardioHID/src/MultiReport/Mouse.cpp | 1 - plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp | 2 -- 7 files changed, 18 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index f92c755564..12d8d61a84 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -122,11 +122,6 @@ int BootKeyboard_::getDescriptor(USBSetup& setup) { void BootKeyboard_::begin() { - // Force API to send a clean report. - // This is important for and HID bridge where the receiver stays on, - // while the sender is resetted. - releaseAll(); - sendReport(); } diff --git a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.hpp b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.hpp index 21bb1f5845..48e615a74f 100644 --- a/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.hpp +++ b/plugins/KeyboardioHID/src/DeviceAPIs/AbsoluteMouseAPI.hpp @@ -54,8 +54,6 @@ int16_t AbsoluteMouseAPI::qadd16(int16_t base, int16_t increment) { } void AbsoluteMouseAPI::begin() { - // release all buttons - end(); } void AbsoluteMouseAPI::end() { diff --git a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp index 0cb4c2f549..ffada2b7fe 100644 --- a/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/ConsumerControl.cpp @@ -50,8 +50,6 @@ ConsumerControl_::ConsumerControl_() { } void ConsumerControl_::begin() { - // release all buttons - end(); } void ConsumerControl_::end() { diff --git a/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp b/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp index 7b0774c050..d533ff7259 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Gamepad.cpp @@ -81,8 +81,6 @@ Gamepad_::Gamepad_() { } void Gamepad_::begin() { - // release all buttons - end(); } void Gamepad_::end() { diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index b776bc8afa..c9e6e9176a 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -82,10 +82,6 @@ Keyboard_::Keyboard_() { } void Keyboard_::begin() { - // Force API to send a clean report. This is important for and HID bridge - // where the receiver stays on, while the sender is resetted. - releaseAll(); - sendReportUnchecked(); } diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp index dd3cec6e32..ca4bdf71cf 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp @@ -74,7 +74,6 @@ Mouse_::Mouse_() { } void Mouse_::begin() { - end(); } void Mouse_::end() { diff --git a/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp b/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp index c8cb7cf818..c01f19bff7 100644 --- a/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp @@ -51,8 +51,6 @@ SystemControl_::SystemControl_() { } void SystemControl_::begin() { - // release all buttons - end(); } void SystemControl_::end() { From b5867eab777e9fc26968c108647a09cc2d9db831 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Sun, 2 Oct 2022 18:43:17 +0200 Subject: [PATCH 593/602] SystemControl: Restore release() and releaseAll() Since 781eb41c26e5f25915df546956dda88a419382b6, `SystemControl_::begin()` is a no-op, calling it in `release()` and `releaseAll()` is not doing what it did prior to that commit: call `end()`, which is what the release functions really wanted to do in the first place. However, calling `end()` is also backwards: `end()` should be calling one of the release functions instead. So lets do that: `releaseAll()` will now send an empty report, and `release()` and `end()` will call it. Signed-off-by: Gergely Nagy --- plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp b/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp index c01f19bff7..7385b32051 100644 --- a/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/SystemControl.cpp @@ -54,8 +54,7 @@ void SystemControl_::begin() { } void SystemControl_::end() { - uint8_t report = 0x00; - sendReport(&report, sizeof(report)); + releaseAll(); } void SystemControl_::write(uint8_t s) { @@ -64,11 +63,12 @@ void SystemControl_::write(uint8_t s) { } void SystemControl_::release() { - begin(); + releaseAll(); } void SystemControl_::releaseAll() { - begin(); + uint8_t report = 0x00; + sendReport(&report, sizeof(report)); } void SystemControl_::press(uint8_t s) { From ffac84d0e8abcd5013f3e9507a066807c3baa0bd Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Wed, 2 Nov 2022 22:57:16 -0500 Subject: [PATCH 594/602] fix NKRO report fencepost There was a fencepost error in counting the number of bits in the key bitmap. This resulted in the report descriptor declaring one more Usage than items in the report, which might cause validation problems on some HID implementations. The only affected Usage was Keypad Hexadecimal, which is probably not used often. Signed-off-by: Taylor Yu --- plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp | 8 +++++--- plugins/KeyboardioHID/src/MultiReport/Keyboard.h | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp index c9e6e9176a..8cd8de4ffe 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.cpp @@ -64,13 +64,15 @@ static const uint8_t nkro_keyboard_hid_descriptor_[] PROGMEM = { D_LOGICAL_MINIMUM, 0x00, D_LOGICAL_MAXIMUM, 0x01, D_REPORT_SIZE, 0x01, - D_REPORT_COUNT, (HID_LAST_KEY - HID_KEYBOARD_A_AND_A), + D_REPORT_COUNT, (KEY_BITS - 4), D_INPUT, (D_DATA | D_VARIABLE | D_ABSOLUTE), - // Padding (3 bits) to round up the report to byte boundary. - D_REPORT_SIZE, 0x03, +#if (KEY_BITS % 8) + // Padding to round up the report to byte boundary. + D_REPORT_SIZE, (8 - (KEY_BITS % 8)), D_REPORT_COUNT, 0x01, D_INPUT, (D_CONSTANT), +#endif D_END_COLLECTION, }; diff --git a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h index 799b1fd816..ef0881b8a0 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Keyboard.h +++ b/plugins/KeyboardioHID/src/MultiReport/Keyboard.h @@ -33,7 +33,8 @@ THE SOFTWARE. #include "HIDTables.h" #include "HIDAliases.h" -#define KEY_BYTES 28 +#define KEY_BITS (4 + HID_LAST_KEY - HID_KEYBOARD_A_AND_A + 1) +#define KEY_BYTES ((KEY_BITS + 7) / 8) typedef union { // Modifiers + keymap From 22668d5f366c6e1e581ba9b5249b422604466f37 Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Thu, 3 Nov 2022 21:13:03 -0500 Subject: [PATCH 595/602] reject Get/Set Protocol for non-boot On non-boot devices, reject Get/Set Protocol requests, because we don't implement the boot protocol for non-BootKeyboard devices. Signed-off-by: Taylor Yu --- plugins/KeyboardioHID/src/HID.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/plugins/KeyboardioHID/src/HID.cpp b/plugins/KeyboardioHID/src/HID.cpp index 733c54735b..3be661d20a 100644 --- a/plugins/KeyboardioHID/src/HID.cpp +++ b/plugins/KeyboardioHID/src/HID.cpp @@ -136,8 +136,7 @@ bool HID_::setup(USBSetup& setup) { return true; } if (request == HID_GET_PROTOCOL) { - // TODO: Send8(protocol); - return true; + return false; } if (request == HID_GET_IDLE) { // TODO: Send8(idle); @@ -146,10 +145,7 @@ bool HID_::setup(USBSetup& setup) { if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) { if (request == HID_SET_PROTOCOL) { - // The USB Host tells us if we are in boot or report mode. - // This only works with a real boot compatible device. - protocol = setup.wValueL; - return true; + return false; } if (request == HID_SET_IDLE) { idle = setup.wValueH; From cae7666b677e36e79dbe67b176952cbfbfae89ab Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Mon, 7 Nov 2022 23:03:54 -0600 Subject: [PATCH 596/602] fix get/set idle Always respond with the current Idle period, possibly set by the host. Also, set the initial idle period to 0 (indefinite), because that's how we actually behave. Signed-off-by: Taylor Yu --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp | 9 +-------- plugins/KeyboardioHID/src/HID.cpp | 5 +++-- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 12d8d61a84..db9d42768c 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -80,7 +80,7 @@ static const uint8_t BOOT_KEYBOARD_EP_SIZE = USB_EP_SIZE; #endif -BootKeyboard_::BootKeyboard_(uint8_t protocol_) : PluggableUSBModule(1, 1, epType), default_protocol(protocol_), protocol(protocol_), idle(1), leds(0) { +BootKeyboard_::BootKeyboard_(uint8_t protocol_) : PluggableUSBModule(1, 1, epType), default_protocol(protocol_), protocol(protocol_), idle(0), leds(0) { #ifdef ARCH_HAS_CONFIGURABLE_EP_SIZES epType[0] = EP_TYPE_INTERRUPT_IN(BOOT_KEYBOARD_EP_SIZE); // This is an 8 byte report, so ask for an 8 byte buffer, so reports aren't split #else @@ -175,14 +175,7 @@ bool BootKeyboard_::setup(USBSetup& setup) { return true; } if (request == HID_SET_IDLE) { - // We currently ignore SET_IDLE, because we don't really do anything with it, and implementing - // it causes issues on OSX, such as key chatter. Other operating systems do not suffer if we - // force this to zero, either. -#if 0 idle = setup.wValueL; -#else - idle = 0; -#endif return true; } if (request == HID_SET_REPORT) { diff --git a/plugins/KeyboardioHID/src/HID.cpp b/plugins/KeyboardioHID/src/HID.cpp index 733c54735b..d6f843ea0c 100644 --- a/plugins/KeyboardioHID/src/HID.cpp +++ b/plugins/KeyboardioHID/src/HID.cpp @@ -140,7 +140,8 @@ bool HID_::setup(USBSetup& setup) { return true; } if (request == HID_GET_IDLE) { - // TODO: Send8(idle); + USB_SendControl(TRANSFER_RELEASE, &idle, sizeof(idle)); + return true; } } @@ -198,7 +199,7 @@ bool HID_::setup(USBSetup& setup) { HID_::HID_() : PluggableUSBModule(1, 1, epType), rootNode(NULL), descriptorSize(0), - protocol(HID_REPORT_PROTOCOL), idle(1) { + protocol(HID_REPORT_PROTOCOL), idle(0) { setReportData.reportId = 0; setReportData.leds = 0; From 0c972328efe085418a5eb70bd0f7b409ae7062f9 Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Thu, 3 Nov 2022 19:37:43 -0500 Subject: [PATCH 597/602] reset protocol on bus reset Only reset boot/report protocol on USB bus reset. Windows 10 will sometimes try to cache report descriptors if it has high confidence that it's a device it's seen before. This means it won't retrieve either the configuration descriptor set or the report descriptors when resetting after receving control from the BIOS/UEFI. The BIOS or UEFI probably set the boot keyboard to boot protocol, which meant that when Windows regained control, the boot keyboard was still in boot protocol, contrary to the USB HID specification. This requires the higher-level driver to call a polling function, because detection of USB reset events isn't as portable as checking the USB device configuration. Signed-off-by: Taylor Yu --- .../src/BootKeyboard/BootKeyboard.cpp | 26 ++++++++++++++++--- .../src/BootKeyboard/BootKeyboard.h | 1 + plugins/KeyboardioHID/src/HID-Settings.h | 5 +++- plugins/KeyboardioHID/src/HID.cpp | 4 --- .../src/SingleReport/SingleAbsoluteMouse.cpp | 10 ++----- 5 files changed, 29 insertions(+), 17 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index db9d42768c..08740b8492 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -26,6 +26,7 @@ THE SOFTWARE. #include "BootKeyboard.h" #include "DescriptorPrimitives.h" #include "HIDReportObserver.h" +#include "HID-Settings.h" // See Appendix B of USB HID spec static const uint8_t boot_keyboard_hid_descriptor_[] PROGMEM = { @@ -113,10 +114,6 @@ int BootKeyboard_::getDescriptor(USBSetup& setup) { return 0; } - // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol - // due to the USB specs, but Windows and Linux just assumes its in report mode. - protocol = default_protocol; - return USB_SendControl(TRANSFER_PGM, boot_keyboard_hid_descriptor_, sizeof(boot_keyboard_hid_descriptor_)); } @@ -396,5 +393,26 @@ bool BootKeyboard_::wasAnyModifierActive() { return last_report_.modifiers > 0; } +/* + * Check whether the device has seen a bus reset. Unfortunately, the most + * portable way is to poll for changes in the host-selected configuration. This + * needs to be periodically called from the keyboard driver to poll for a reset + * condition. + */ +void BootKeyboard_::checkReset() { + static bool was_configed; + + if (was_configed) { + if (!USB_Configured()) { + was_configed = false; + protocol = default_protocol; + } + } else { + if (USB_Configured()) { + was_configed = true; + } + } +} + __attribute__((weak)) BootKeyboard_ BootKeyboard; diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index d7cfeadb83..15ddb38a59 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -65,6 +65,7 @@ class BootKeyboard_ : public PluggableUSBModule { void setProtocol(uint8_t protocol); uint8_t default_protocol; + void checkReset(); protected: HID_BootKeyboardReport_Data_t report_, last_report_; diff --git a/plugins/KeyboardioHID/src/HID-Settings.h b/plugins/KeyboardioHID/src/HID-Settings.h index 7eff1e0931..24577fe482 100644 --- a/plugins/KeyboardioHID/src/HID-Settings.h +++ b/plugins/KeyboardioHID/src/HID-Settings.h @@ -81,6 +81,7 @@ void USB_PackMessages(bool pack); #include #define EPTYPE_DESCRIPTOR_SIZE uint8_t +#define USB_Configured USBDevice.configured #elif defined(ARDUINO_ARCH_SAM) @@ -104,6 +105,7 @@ void USB_PackMessages(bool pack); #define USB_Recv USBD_Recv #define USB_Send USBD_Send #define USB_Flush USBD_Flush +#define USB_Configured USBDevice.configured #elif defined(ARDUINO_ARCH_SAMD) @@ -119,6 +121,7 @@ void USB_PackMessages(bool pack); #define USB_RecvControl USBDevice.recvControl #define USB_Send USBDevice.send #define USB_Flush USBDevice.flush +#define USB_Configured USBDevice.configured int USB_SendControl(void* y, uint8_t z); int USB_SendControl(uint8_t x, const void* y, uint8_t z); @@ -143,7 +146,7 @@ int USB_SendControl(uint8_t x, const void* y, uint8_t z); constexpr uint16_t EP_TYPE_INTERRUPT_IN(uint8_t buffer_size) { return EPDesc(USB_TRX_IN, USB_EP_ATTR_INT, buffer_size).val; } constexpr uint16_t EP_TYPE_INTERRUPT_OUT(uint8_t buffer_size) { return EPDesc(USB_TRX_OUT, USB_EP_ATTR_INT, buffer_size).val; } - +#define USB_Configured USBCore().configured #else diff --git a/plugins/KeyboardioHID/src/HID.cpp b/plugins/KeyboardioHID/src/HID.cpp index 9ffc369bb4..9be216b5fd 100644 --- a/plugins/KeyboardioHID/src/HID.cpp +++ b/plugins/KeyboardioHID/src/HID.cpp @@ -62,10 +62,6 @@ int HID_::getDescriptor(USBSetup& setup) { total += res; } - // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol - // due to the USB specs, but Windows and Linux just assumes its in report mode. - protocol = HID_REPORT_PROTOCOL; - USB_PackMessages(false); return total; } diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp index 05f5176ceb..69998fe69a 100644 --- a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp @@ -81,10 +81,6 @@ int SingleAbsoluteMouse_::getDescriptor(USBSetup& setup) { return 0; } - // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol - // due to the USB specs, but Windows and Linux just assumes its in report mode. - protocol = HID_REPORT_PROTOCOL; - return USB_SendControl(TRANSFER_PGM, _hidSingleReportDescriptorAbsoluteMouse, sizeof(_hidSingleReportDescriptorAbsoluteMouse)); } @@ -102,15 +98,13 @@ bool SingleAbsoluteMouse_::setup(USBSetup& setup) { return true; } if (request == HID_GET_PROTOCOL) { - // TODO: Send8(protocol); - return true; + return false; } } if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) { if (request == HID_SET_PROTOCOL) { - protocol = setup.wValueL; - return true; + return false; } if (request == HID_SET_IDLE) { idle = setup.wValueL; From d2ead6d295e9aab91164ec08e193ef3417a94b76 Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Wed, 11 Jan 2023 22:27:20 -0600 Subject: [PATCH 598/602] make BootKeyboard first HID Use a singleton for BootKeyboard to make sure that it is the first HID interface. Some UEFIs or BIOSes appear to only recognize a boot keyboard if it's the first HID interface. Signed-off-by: Taylor Yu --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp | 5 ++++- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h | 2 +- plugins/KeyboardioHID/src/HID.cpp | 4 ++++ .../KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp | 3 +++ 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 08740b8492..b0c0dc2947 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -415,4 +415,7 @@ void BootKeyboard_::checkReset() { } __attribute__((weak)) -BootKeyboard_ BootKeyboard; +BootKeyboard_& BootKeyboard() { + static BootKeyboard_ obj; + return obj; +}; diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index 15ddb38a59..177871b1d4 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -81,4 +81,4 @@ class BootKeyboard_ : public PluggableUSBModule { uint8_t leds; }; -extern BootKeyboard_ BootKeyboard; +extern BootKeyboard_& BootKeyboard(); diff --git a/plugins/KeyboardioHID/src/HID.cpp b/plugins/KeyboardioHID/src/HID.cpp index 9be216b5fd..cbbe889415 100644 --- a/plugins/KeyboardioHID/src/HID.cpp +++ b/plugins/KeyboardioHID/src/HID.cpp @@ -20,6 +20,7 @@ #include "HID.h" #include "HIDReportObserver.h" +#include "BootKeyboard/BootKeyboard.h" #if defined(USBCON) @@ -192,6 +193,9 @@ bool HID_::setup(USBSetup& setup) { HID_::HID_() : PluggableUSBModule(1, 1, epType), rootNode(NULL), descriptorSize(0), protocol(HID_REPORT_PROTOCOL), idle(0) { + // Invoke BootKeyboard constructor so it will be the first HID interface + (void)BootKeyboard(); + setReportData.reportId = 0; setReportData.leds = 0; diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp index 69998fe69a..7b1a742690 100644 --- a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp @@ -24,6 +24,7 @@ THE SOFTWARE. */ #include "SingleAbsoluteMouse.h" +#include "BootKeyboard/BootKeyboard.h" #include "HIDReportObserver.h" #include "HID-Settings.h" @@ -48,6 +49,8 @@ static const uint8_t SINGLE_ABSOLUTEMOUSE_EP_SIZE = USB_EP_SIZE; SingleAbsoluteMouse_::SingleAbsoluteMouse_() : PluggableUSBModule(1, 1, epType), protocol(HID_REPORT_PROTOCOL), idle(1) { + // Invoke BootKeyboard constructor so it will be the first HID interface + (void)BootKeyboard(); #ifdef ARCH_HAS_CONFIGURABLE_EP_SIZES epType[0] = EP_TYPE_INTERRUPT_IN(SINGLE_ABSOLUTEMOUSE_EP_SIZE); #else From 88defa347f8956bc7b7985b81cf41fade341ac40 Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Sun, 15 Jan 2023 16:29:08 -0600 Subject: [PATCH 599/602] use an action hook onReset for BootKeyboard Instead of having a poll function to check for USB reset in BootKeyboard, use an onReset hook instead. Signed-off-by: Taylor Yu --- .../src/BootKeyboard/BootKeyboard.cpp | 23 +++++-------------- .../src/BootKeyboard/BootKeyboard.h | 2 +- 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index b0c0dc2947..48dba2ea8a 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -394,24 +394,13 @@ bool BootKeyboard_::wasAnyModifierActive() { } /* - * Check whether the device has seen a bus reset. Unfortunately, the most - * portable way is to poll for changes in the host-selected configuration. This - * needs to be periodically called from the keyboard driver to poll for a reset - * condition. + * Hook function to reset any needed state after a USB reset. + * + * Right now, it sets the protocol back to the default (report protocol), as + * required by the HID specification. */ -void BootKeyboard_::checkReset() { - static bool was_configed; - - if (was_configed) { - if (!USB_Configured()) { - was_configed = false; - protocol = default_protocol; - } - } else { - if (USB_Configured()) { - was_configed = true; - } - } +void BootKeyboard_::onUSBReset() { + protocol = default_protocol; } __attribute__((weak)) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h index 177871b1d4..38f263e7d8 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.h @@ -65,7 +65,7 @@ class BootKeyboard_ : public PluggableUSBModule { void setProtocol(uint8_t protocol); uint8_t default_protocol; - void checkReset(); + void onUSBReset(); protected: HID_BootKeyboardReport_Data_t report_, last_report_; From a8fc7bad070c4536fd4fe044ab05620ddfdb5236 Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Fri, 10 Feb 2023 21:10:44 -0600 Subject: [PATCH 600/602] remove GD32 `recvControl` workaround Remove the GD32 `recvControl` workaround, because changes to the USB core mean that it's no longer required. Signed-off-by: Taylor Yu --- .../src/BootKeyboard/BootKeyboard.cpp | 29 ++----------------- plugins/KeyboardioHID/src/HID.cpp | 29 ++----------------- 2 files changed, 4 insertions(+), 54 deletions(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index 48dba2ea8a..dd4b6156fc 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -179,37 +179,12 @@ bool BootKeyboard_::setup(USBSetup& setup) { // Check if data has the correct length afterwards int length = setup.wLength; - - // ------------------------------------------------------------ - // Workaround for a bug in the GD32 core: - // - // On GD32, when we call `USV_RecvControl`, it casts the (void*) pointer - // we give it to `uint16_t*`, which means that it will alway write an even - // number of bytes to that pointer. Because we don't want to overwrite - // the next byte in memory past `leds`, we use a temporary array that is - // guaranteed to be big enough, and copy the data from that: if (setup.wValueH == HID_REPORT_TYPE_OUTPUT) { if (length == sizeof(leds)) { - uint8_t raw_report_data[2]; - USB_RecvControl(&raw_report_data, length); - leds = raw_report_data[0]; + USB_RecvControl(&leds, length); return true; -// } else { -// char tmp[8]; -// USB_RecvControl(&tmp, length); -// return true; - } + } } - // Once the GD32 core bug is fixed, we can replace the above code with the - // original code below: - // ------------------------------------------------------------ - // if (setup.wValueH == HID_REPORT_TYPE_OUTPUT) { - // if (length == sizeof(leds)) { - // USB_RecvControl(&leds, length); - // return true; - // } - // } - // ------------------------------------------------------------ // Input (set HID report) else if (setup.wValueH == HID_REPORT_TYPE_INPUT) { diff --git a/plugins/KeyboardioHID/src/HID.cpp b/plugins/KeyboardioHID/src/HID.cpp index cbbe889415..94d502d66b 100644 --- a/plugins/KeyboardioHID/src/HID.cpp +++ b/plugins/KeyboardioHID/src/HID.cpp @@ -152,37 +152,12 @@ bool HID_::setup(USBSetup& setup) { if (request == HID_SET_REPORT) { uint16_t length = setup.wLength; - // ------------------------------------------------------------ - // Workaround for a bug in the GD32 core: - // - // On GD32, when we call `USV_RecvControl`, it casts the (void*) pointer - // we give it to `uint16_t*`, which means that it will alway write an even - // number of bytes to that pointer. Because we might be trying to just - // read the `leds` byte, and we don't want to overwrite the next byte in - // memory, instead of giving it the pointer to the `setReportData` member - // variable directly, we have it write into to temporary `raw_report_data` - // array that's guaranteed to be big enough, then copy the data from that - // array into `setReportData`: - uint8_t raw_report_data[sizeof(setReportData) + 1]; if (length == sizeof(setReportData)) { - USB_RecvControl(&raw_report_data, length); - setReportData.reportId = raw_report_data[0]; - setReportData.leds = raw_report_data[1]; + USB_RecvControl(&setReportData, length); } else if (length == sizeof(setReportData.leds)) { - USB_RecvControl(&raw_report_data, length); + USB_RecvControl(&setReportData.leds, length); setReportData.reportId = 0; - setReportData.leds = raw_report_data[0]; } - // Once the GD32 core bug is fixed, we can replace the above code with the - // original code below: - // ------------------------------------------------------------ - // if (length == sizeof(setReportData)) { - // USB_RecvControl(&setReportData, length); - // } else if (length == sizeof(setReportData.leds)) { - // USB_RecvControl(&setReportData.leds, length); - // setReportData.reportId = 0; - // } - // ------------------------------------------------------------ return true; } } From 78f24d663cb376ed22831a2e3edd12f1ef361d5d Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Wed, 6 Dec 2023 12:45:43 -0600 Subject: [PATCH 601/602] use pointer collection in mouse descriptors It's possible that some KVM switches or OSes didn't like the mouse devices, because the axes aren't wrapped in a Pointer Physical Collection. Also use the correct macro for the item tag for the multibyte AC Pan on the relative mouse. No change in encoding; it's just a more meaningful macro. Signed-off-by: Taylor Yu --- plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp | 3 +++ plugins/KeyboardioHID/src/MultiReport/Mouse.cpp | 5 ++++- .../KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp | 3 +++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp index 437ef915de..0fc17e7ac8 100644 --- a/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/AbsoluteMouse.cpp @@ -31,12 +31,15 @@ static const uint8_t absolute_mouse_hid_descriptor_[] PROGMEM = { D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) 54 */ D_USAGE, D_USAGE_MOUSE, /* USAGE (Mouse) */ D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ + D_USAGE, D_USAGE_POINTER, /* USAGE (Pointer) */ + D_COLLECTION, D_PHYSICAL, /* COLLECTION (Physical)*/ D_REPORT_ID, HID_REPORTID_MOUSE_ABSOLUTE, /* REPORT_ID */ DESCRIPTOR_ABS_MOUSE_BUTTONS DESCRIPTOR_ABS_MOUSE_XY DESCRIPTOR_ABS_MOUSE_WHEEL + D_END_COLLECTION, D_END_COLLECTION /* End */ }; diff --git a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp index ca4bdf71cf..924d30915f 100644 --- a/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp +++ b/plugins/KeyboardioHID/src/MultiReport/Mouse.cpp @@ -31,6 +31,8 @@ static const uint8_t mouse_hid_descriptor_[] PROGMEM = { D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, // USAGE_PAGE (Generic Desktop) D_USAGE, D_USAGE_MOUSE, // USAGE (Mouse) D_COLLECTION, D_APPLICATION, // COLLECTION (Application) + D_USAGE, D_USAGE_POINTER, // USAGE (Pointer) + D_COLLECTION, D_PHYSICAL, // COLLECTION (Physical) D_REPORT_ID, HID_REPORTID_MOUSE, // REPORT_ID (Mouse) /* 8 Buttons */ @@ -56,7 +58,7 @@ static const uint8_t mouse_hid_descriptor_[] PROGMEM = { /* Horizontal wheel */ D_USAGE_PAGE, D_PAGE_CONSUMER, // USAGE_PAGE (Consumer) - D_PAGE_ORDINAL, 0x38, 0x02, // PAGE (AC Pan) + D_MULTIBYTE(D_USAGE), 0x38, 0x02, // USAGE (AC Pan) D_LOGICAL_MINIMUM, 0x81, // LOGICAL_MINIMUM (-127) D_LOGICAL_MAXIMUM, 0x7f, // LOGICAL_MAXIMUM (127) D_REPORT_SIZE, 0x08, // REPORT_SIZE (8) @@ -64,6 +66,7 @@ static const uint8_t mouse_hid_descriptor_[] PROGMEM = { D_INPUT, (D_DATA | D_VARIABLE | D_RELATIVE), // INPUT (Data,Var,Rel) /* End */ + D_END_COLLECTION, // END_COLLECTION D_END_COLLECTION // END_COLLECTION }; diff --git a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp index 7b1a742690..98f8db3c70 100644 --- a/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp +++ b/plugins/KeyboardioHID/src/SingleReport/SingleAbsoluteMouse.cpp @@ -32,10 +32,13 @@ static const uint8_t _hidSingleReportDescriptorAbsoluteMouse[] PROGMEM = { D_USAGE_PAGE, D_PAGE_GENERIC_DESKTOP, /* USAGE_PAGE (Generic Desktop) 54 */ D_USAGE, D_USAGE_MOUSE, /* USAGE (Mouse) */ D_COLLECTION, D_APPLICATION, /* COLLECTION (Application) */ + D_USAGE, D_USAGE_POINTER, /* USAGE (Pointer) */ + D_COLLECTION, D_PHYSICAL, /* COLLECTION (Physical)*/ DESCRIPTOR_ABS_MOUSE_BUTTONS DESCRIPTOR_ABS_MOUSE_XY DESCRIPTOR_ABS_MOUSE_WHEEL + D_END_COLLECTION, D_END_COLLECTION /* End */ }; From f9f3ae7070ec58271108c7afa638c2923e8aac70 Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Thu, 14 Dec 2023 08:16:36 -0600 Subject: [PATCH 602/602] BootKeyboard: use positive Logical Maximum In a HID Report Descriptor, the correct encoding for Logical Maximum (255) is `26 FF 00`, not `25 FF`. The latter encodes Logical Maximum (-1). This is a common error, and some hosts rightfully reject it. (The correct Logical Maximum is probably 221, because otherwise, the modifier keys could also be encoded in the key codes array, which is invalid for their usage type. A lot of production keyboards use 255 anyway, and hosts seem to accept that.) Signed-off-by: Taylor Yu --- plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp index dd4b6156fc..a97731bae1 100644 --- a/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp +++ b/plugins/KeyboardioHID/src/BootKeyboard/BootKeyboard.cpp @@ -66,7 +66,7 @@ static const uint8_t boot_keyboard_hid_descriptor_[] PROGMEM = { D_REPORT_COUNT, 0x6, D_REPORT_SIZE, 0x8, D_LOGICAL_MINIMUM, 0x0, - D_LOGICAL_MAXIMUM, 0xff, + D_MULTIBYTE(D_LOGICAL_MAXIMUM), 0xff, 0x0, // make sure it's not negative D_USAGE_PAGE, D_PAGE_KEYBOARD, D_USAGE_MINIMUM, 0x0, D_USAGE_MAXIMUM, 0xff,
  • =!Im=ymD169iP`vb+hF_v1fa#4de6_>3K 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

    =!Im=ymD169iP`vb+hF_v1fa#4de6_>3K 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