Compare commits

...
328 Commits
Author SHA1 Message Date
Cameron Gutman b48494cb96 Version 12.2 2026-09-12 14:22:35 -05:00
Cameron Gutman 98c12bebff Update to OkHttp 5.5
Disable fast fallback due to it being intolerate of thread interruptions.
2026-09-02 22:00:09 -05:00
Cameron Gutman 801dba1ba8 Update to AGP 9.4.0 2026-09-02 21:44:35 -05:00
Cameron Gutman 4eb24a8d7b Enable core library desugaring to fix jmDNS on older Android versions 2026-09-02 21:40:37 -05:00
Cameron Gutman 5c0c2390b2 Add (currently unused) justification for LNP 2026-09-02 21:27:02 -05:00
Cameron Gutman b55b4b6d68 Add entries for new languages 2026-09-02 21:25:32 -05:00
Cameron Gutman 4dc95b563c Merge remote-tracking branch 'origin/weblate' 2026-09-02 21:22:00 -05:00
Cameron Gutman 31b700304a Update to libopus 1.6.1 and openssl 4.0.2
Built via GH Actions from https://github.com/cgutman/moonlight-mobile-deps/commit/419349aa689e8749a9fb91a22dc45531ddd3df45
2026-09-02 01:38:14 -05:00
Cameron Gutman ddb674a9b9 Add support for Android 16.1 keyboard capture
Fixes #975
Fixes #1281
Fixes #1505
2026-09-01 21:20:38 -05:00
Cameron Gutman abde6021e8 Fix crashes and ANRs in controller LED handling 2026-09-01 21:15:51 -05:00
Cameron Gutman ad8614907c Suppress Lint warnings for using newer constants 2026-09-01 21:15:38 -05:00
Cameron Gutman 8974dcda6e Add support for newer keycodes from Android 15 and 16 2026-09-01 21:08:42 -05:00
Cameron Gutman 6d4c64a575 Disable producer throttling on the video surface 2026-09-01 21:02:04 -05:00
Cameron Gutman 68adf9ecc9 Disable H.264 constraint and level_idc modifications on Oreo and later 2026-09-01 21:01:41 -05:00
Cameron Gutman 3df0103a8c Remove unused code paths for < API 21 2026-09-01 20:58:38 -05:00
Cameron Gutman 8d720748c1 Fix Lint error 2026-09-01 20:56:50 -05:00
Cameron Gutman 578f38f6a5 Fix AppVeyor CI 2026-09-01 01:43:28 -05:00
Etienne Haarsma 280454fdb0 Added Xbox Series S/X controller to Xbox One controller driver (#1478) 2026-09-01 01:22:57 -05:00
Ivan Vojtko 0711e236c0 Update UI helper to not fail on Meta Quest devices (#1516) 2026-09-01 01:22:42 -05:00
Dave Lane b9c5edddef Fix missing shift modifier for plus key (#1582) 2026-09-01 01:21:36 -05:00
T2Fat2Fly 3c6a0d12f5 Fix rumble not working due to deprecated API call (#1454) 2026-09-01 01:20:34 -05:00
vhenzor 583f662a87 Add Vendor 8BitDo to XboxOneController (#1461)
Some new 8BitDo controller or adapter are now detected as XboxOne controller instead of Xbox360 controller in XInput mode like the 8BitDo Ultimate-3-mode (https://www.8bitdo.com/ultimate-3-mode-controller-xbox/).

Like commit #1333 (https://github.com/moonlight-stream/moonlight-android/pull/1333/commits), adding 8BitDo's Vendor ID to SUPPORTED_VENDORS improve compatibility and enable rumble for supported controller.
2026-09-01 01:19:35 -05:00
Cameron Gutman 3f114ac76c Update AppVeyor config 2026-09-01 01:14:50 -05:00
Cameron Gutman 4b2221d374 Target API level 36 2026-09-01 01:12:33 -05:00
Cameron Gutman c2e224ebf8 Sync SDL joystick code with upstream 2026-09-01 00:38:40 -05:00
Cameron Gutman 0dc4c4fe67 Update moonlight-common-c 2026-09-01 00:38:37 -05:00
Cameron Gutman 9221a0ca3a Update Java compatibility to JDK 17 2026-08-31 23:30:13 -05:00
Cameron Gutman b3a7e32a08 Update jMDNS and BouncyCastle dependencies 2026-08-31 23:28:13 -05:00
Cameron Gutman 1fa0e2a0f9 Update NDK to r29 2026-08-31 23:03:13 -05:00
Cameron Gutman 9d8b073ca5 Update SDK and AGP 2026-08-31 23:02:07 -05:00
Jorys Paulin 03bdf30d0a Translated using Weblate (French)
Currently translated at 100.0% (251 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/fr/
2026-08-11 17:51:24 +02:00
Damglador 6e15cc5fa3 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (251 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/uk/
2026-06-30 17:01:19 +02:00
Margin 9d26550264 Translated using Weblate (Indonesian)
Currently translated at 82.4% (207 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/id/
2026-04-11 21:10:41 +02:00
தமிழ்நேரம் 7ffde1e8fc Translated using Weblate (Tamil)
Currently translated at 100.0% (251 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/ta/
2026-03-02 11:09:49 +01:00
Tomás Mendes 30d234d71e Translated using Weblate (Portuguese)
Currently translated at 88.0% (221 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/pt/
2026-01-03 11:01:47 +00:00
MrSnowflake a75104f13d Translated using Weblate (Dutch)
Currently translated at 100.0% (251 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/nl/
2025-12-17 17:00:20 +01:00
sanhoe 73d3180d20 Translated using Weblate (Korean)
Currently translated at 100.0% (251 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/ko/
2025-10-12 04:11:39 +00:00
veldenb f51be309a0 Translated using Weblate (Dutch)
Currently translated at 100.0% (251 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/nl/
2025-07-29 23:11:07 +02:00
therealmate a7a424cf27 Translated using Weblate (Hungarian)
Currently translated at 100.0% (251 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/hu/
2025-06-24 09:01:47 +00:00
தமிழ்நேரம் 19dc67eb47 Translated using Weblate (Tamil)
Currently translated at 100.0% (251 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/ta/
2025-06-23 03:01:46 +00:00
aga_90 9869f3125f Translated using Weblate (Hungarian)
Currently translated at 96.0% (241 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/hu/
2025-05-01 01:09:50 +02:00
ℂ𝕠𝕠𝕠𝕝 (𝕘𝕚𝕥𝕙𝕦𝕓.𝕔𝕠𝕞/ℂ𝕠𝕠𝕠𝕝) 8a8efc0dcf Translated using Weblate (Latvian)
Currently translated at 16.3% (41 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/lv/
2025-04-20 04:19:16 +02:00
ℂ𝕠𝕠𝕠𝕝 (𝕘𝕚𝕥𝕙𝕦𝕓.𝕔𝕠𝕞/ℂ𝕠𝕠𝕠𝕝) 54e1f2a124 Translated using Weblate (Latvian)
Currently translated at 5.1% (13 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/lv/
2025-04-19 17:33:27 +02:00
ℂ𝕠𝕠𝕠𝕝 (𝕘𝕚𝕥𝕙𝕦𝕓.𝕔𝕠𝕞/ℂ𝕠𝕠𝕠𝕝) f827e96e1a Added translation using Weblate (Latvian) 2025-04-19 16:40:19 +02:00
Danilo Issida Goncalves 5835fb832c Translated using Weblate (Portuguese (Brazil))
Currently translated at 91.2% (229 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/pt_BR/
2025-03-26 15:08:53 +01:00
Philip Goto 9484275ab6 Translated using Weblate (Dutch)
Currently translated at 85.6% (215 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/nl/
2025-02-15 23:14:55 +01:00
Philip Goto 2a0ccb88bb Translated using Weblate (Dutch)
Currently translated at 80.4% (202 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/nl/
2025-02-05 15:02:05 +01:00
Linx d3eb327f63 Translated using Weblate (Spanish)
Currently translated at 100.0% (251 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/es/
2025-01-20 06:29:39 +01:00
தமிழ்நேரம் c122bcd45b Translated using Weblate (Tamil)
Currently translated at 100.0% (251 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/ta/
2025-01-19 10:34:46 +01:00
தமிழ்நேரம் 16b6cf6edb Added translation using Weblate (Tamil) 2025-01-18 09:40:36 +01:00
Любомир Василев 325bc3349e Translated using Weblate (Bulgarian)
Currently translated at 100.0% (251 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/bg/
2024-12-20 08:25:54 +01:00
Любомир Василев 7416477763 Translated using Weblate (Bulgarian)
Currently translated at 100.0% (251 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/bg/
2024-12-19 10:00:22 +01:00
Любомир Василев bcd8c8f77d Translated using Weblate (Bulgarian)
Currently translated at 79.2% (199 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/bg/
2024-12-18 08:38:19 +01:00
Любомир Василев d44432ed81 Translated using Weblate (Bulgarian)
Currently translated at 64.5% (162 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/bg/
2024-12-17 10:00:46 +01:00
Любомир Василев d46f5d4353 Translated using Weblate (Bulgarian)
Currently translated at 52.9% (133 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/bg/
2024-12-15 13:01:19 +00:00
yungleballz 27ded2add8 Translated using Weblate (Spanish)
Currently translated at 100.0% (251 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/es/
2024-11-15 15:00:24 +00:00
Jorys Paulin 9b0bfaf079 Translated using Weblate (French)
Currently translated at 100.0% (251 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/fr/
2024-11-08 17:01:01 +00:00
Leandro Cândido 522d61d7e2 Translated using Weblate (Portuguese (Brazil))
Currently translated at 90.8% (228 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/pt_BR/
2024-10-04 18:15:40 +02:00
phlostically 8550e99463 Translated using Weblate (Esperanto)
Currently translated at 14.3% (36 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/eo/
2024-10-02 23:16:22 +02:00
phlostically 2f6deb72b3 Added translation using Weblate (Esperanto) 2024-10-01 22:36:08 +02:00
Tomonobu Terakubo 10941746e4 Translated using Weblate (Japanese)
Currently translated at 58.5% (147 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/ja/
2024-09-20 01:40:51 +02:00
Allan Nordhøy 4827b0e6de Translated using Weblate (Norwegian Bokmål)
Currently translated at 62.5% (157 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/nb_NO/
2024-09-02 22:09:13 +02:00
Cameron Gutman f10085f552 Update to libopus v1.5.2
ARMv7 now compiled with floating point enabled
2024-07-27 17:09:42 -05:00
Cameron Gutman eb7f0887bf Enable support for 16KB pages 2024-07-27 16:55:21 -05:00
Cameron Gutman 34a9132d60 Update to NDK r27 2024-07-27 16:44:01 -05:00
Cameron Gutman 24d3fb000a Update AGP and Gradle 2024-07-27 16:43:44 -05:00
ReenigneArcher b7b6adaff7 feat(activity): allow PC Name and AppName for ShortcutTrampoline (#1387) 2024-07-27 16:23:23 -05:00
Matheus VargemandReenigneArcher 85ed72802f feat: Add Guide menu to on-screen virtual controller (#1265)
* Add `Guide Button` to OSC controller

In order to allow the `Guide Button` to be pressed without a physical gamepad, add the button to the On-screen virtual controller

Co-authored-by: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com>
2024-07-27 16:21:17 -05:00
Артём Журин e1fcb19b23 Translated using Weblate (Russian)
Currently translated at 100.0% (251 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/ru/
2024-07-04 16:09:13 +02:00
Артём Журин 2df69bcdea Translated using Weblate (Russian)
Currently translated at 100.0% (251 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/ru/
2024-07-01 11:09:08 +02:00
sanhoe 454b443b81 Translated using Weblate (Korean)
Currently translated at 100.0% (251 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/ko/
2024-06-26 16:09:17 +02:00
Артём Журин f97704764a Translated using Weblate (Russian)
Currently translated at 100.0% (251 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/ru/
2024-06-20 20:09:21 +00:00
Gunawan Wibisono 9ef23038ab Translated using Weblate (Indonesian)
Currently translated at 74.5% (187 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/id/
2024-05-25 06:09:15 +02:00
Marocco2 e48c38f47a Translated using Weblate (Italian)
Currently translated at 100.0% (251 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/it/
2024-05-25 06:09:15 +02:00
NephilimDM cf64d102de Translated using Weblate (Italian)
Currently translated at 96.4% (242 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/it/
2024-04-25 12:07:21 +02:00
Yutaro Urata 2716c68c7a Translated using Weblate (Japanese)
Currently translated at 49.0% (123 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/ja/
2024-04-09 19:01:54 +02:00
Cameron Gutman f54f8c83e7 Update to libopus v1.5.1 2024-03-17 22:53:24 -05:00
Cameron Gutman 124bfdf418 Bump all dependencies to latest versions
Most of these were blocked on min API level 21
2024-03-17 17:57:56 -05:00
Cameron Gutman 01507d9995 Enable BTI on ARMv8 2024-03-17 17:56:33 -05:00
Cameron Gutman 070c82bc44 Update to NDK 26c 2024-03-17 17:53:43 -05:00
Cameron Gutman 17df15293f Drop support for Jelly Bean and KitKat
NDK support for these is already gone
2024-03-17 17:43:42 -05:00
komurlu 6551076613 Add Vendor 8BitDo to Xbox360Controller (#1333)
8BitDo Ultimate Bluetooth Controller was not being recognized in XInput mode when using the dongle.
Adding 8BitDo's Vendor ID to SUPPORTED_VENDORS seems to fix it.
2024-02-27 22:49:33 -06:00
Cameron Gutman 1b1b100e63 Version 12.1 2024-02-27 22:45:27 -06:00
Serdar Sağlam d73b9e16da Translated using Weblate (Turkish)
Currently translated at 100.0% (251 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/tr/
2024-02-27 10:02:02 +01:00
yungleballz cc788e4410 Translated using Weblate (German)
Currently translated at 100.0% (251 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/de/
2024-02-24 10:33:34 +01:00
Cameron Gutman e70014bb28 Merge remote-tracking branch 'origin/weblate' 2024-02-21 23:54:35 -06:00
Cameron Gutman 082cc84a71 Remove sustained performance mode
Our CPU usage is so low that it's doubtful we'd ever trigger thermal throttling.
2024-02-17 19:16:35 -06:00
Cameron Gutman 2ba7f0d989 Update to AGP 8.2.2 2024-02-17 18:54:59 -06:00
Cameron Gutman 9a7381b35f Update moonlight-common-c with RTSP encryption 2024-02-17 18:46:55 -06:00
Cameron Gutman 613ecfff44 Add Game Mode configuration 2024-02-17 18:46:28 -06:00
Vag Ko f638548a02 Translated using Weblate (Greek)
Currently translated at 71.3% (179 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/el/
2024-02-12 22:02:05 +01:00
Jorys Paulin 224bab68bf Translated using Weblate (French)
Currently translated at 100.0% (251 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/fr/
2024-02-10 21:02:03 +01:00
Jorys Paulin 6aca18bd76 Translated using Weblate (French)
Currently translated at 100.0% (251 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/fr/
2024-02-05 13:01:49 +01:00
Mike 3c58e2fbba Translated using Weblate (Polish)
Currently translated at 100.0% (251 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/pl/
2024-01-30 21:01:56 +01:00
bittin1ddc447d824349b2 aaaebde05e Translated using Weblate (Swedish)
Currently translated at 100.0% (251 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/sv/
2024-01-24 07:01:52 +01:00
137615 8ff9f70bd7 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (251 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/zh_Hans/
2024-01-23 05:01:53 +01:00
Vadym Nekhai 523ca862b9 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (251 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/uk/
2024-01-21 16:01:49 +01:00
gallegonovato 78b8d1e9f3 Translated using Weblate (Spanish)
Currently translated at 100.0% (251 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/es/
2024-01-21 16:01:48 +01:00
Anonymous 83c698b36d Translated using Weblate (Chinese (Simplified))
Currently translated at 96.0% (241 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/zh_Hans/
2024-01-20 04:03:09 +01:00
Anonymous 27fe37f221 Translated using Weblate (Romanian)
Currently translated at 60.9% (153 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/ro/
2024-01-20 04:03:09 +01:00
Anonymous 3722106daf Translated using Weblate (Dutch)
Currently translated at 70.1% (176 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/nl/
2024-01-20 04:03:08 +01:00
Cameron Gutman 3ea9ef1ef2 Merge remote-tracking branch 'origin/weblate' 2024-01-19 21:01:22 -06:00
Cameron Gutman fcd27b48b2 Eat all exceptions from attempting to start ACTION_REQUEST_CHANNEL_BROWSABLE
Fixes #1302
2024-01-19 20:59:56 -06:00
Cameron Gutman 6ff37a17ec Tweak strings for rumble strength options 2024-01-19 20:51:13 -06:00
Cameron Gutman f2c6e9e32e Update moonlight-common-c with finalized encryption changes 2024-01-19 19:19:00 -06:00
Alek Lefebvre dbf1b88a3d Adjust emulated rumble strength (#1288) 2024-01-19 19:12:21 -06:00
joaomacp 3aab9eb13b Analog stick for scrolling in mouse emulation mode 2024-01-15 15:45:00 -06:00
Cameron Gutman 3f9f8f7b3b Opt in for video encryption on platforms with fast AES implementations 2024-01-15 15:05:38 -06:00
Cameron Gutman f7520ba40c Move encryption enablement logic into JNI code 2024-01-15 14:59:01 -06:00
Cameron Gutman 7b13f12817 Update moonlight-common-c with new encryption support 2024-01-15 14:54:59 -06:00
Jorys Paulin 57e19d75e2 Translated using Weblate (French)
Currently translated at 100.0% (242 of 242 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/fr/
2024-01-09 15:06:17 +00:00
Guillaume Zin 4330a223c6 Handle start+select as home button on Thrustmaster Score A gamepad (#1299) 2023-12-31 14:13:22 -06:00
Cameron Gutman 69387c32ad Display error codes when the connection is terminated 2023-12-30 21:14:22 -06:00
Cameron Gutman a102ec4ee8 Fix inverted logic 2023-12-30 20:35:00 -06:00
Cameron Gutman 2a094437dd Don't override HDR color format for AV1 2023-12-30 20:33:31 -06:00
Cameron Gutman 4142907376 Don't consume special key combos that we don't handle 2023-12-30 19:50:36 -06:00
Cameron Gutman e63dc9a93b Suppress bogus UnspecifiedRegisterReceiverFlag warning 2023-12-29 23:55:30 -06:00
Cameron Gutman 1fe19e912e Update moonlight-common-c for X-SS-Connect-Data support 2023-12-29 22:30:56 -06:00
Cameron Gutman 56ad48446e Bump AGP to 8.2.0 2023-12-29 22:29:18 -06:00
Cameron Gutman a18aa26985 Update moonlight-common-c to remove per-codec bitrate adjustments 2023-12-03 22:20:30 -06:00
Cameron Gutman 5443cc014a Add support for ECDSA server keys 2023-11-29 22:37:12 -06:00
Cameron Gutman 7d77e1c1f2 Don't hardcode signature length 2023-11-29 22:32:00 -06:00
Cameron Gutman ca82cd9752 Use generic PrivateKey type rather than RSAPrivateKey 2023-11-29 22:20:50 -06:00
bittin1ddc447d824349b2 dbd86bb861 Translated using Weblate (Swedish)
Currently translated at 100.0% (242 of 242 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/sv/
2023-11-25 05:08:16 +00:00
Cameron Gutman 0af56b4981 Remove roundIcon attribute
This should only be used if the round icon is actually different.
2023-11-24 21:02:50 -06:00
Cameron Gutman f1be5365bb Version 12.0.2 2023-11-01 20:35:57 -05:00
Cameron Gutman c356862ac1 Avoid unnecessary reinitialization of PS4/PS5 gamepads during stream exit
onInputDeviceChanged() is triggered by starting/stopping pointer capture, so we should
unregister our callbacks before that happens to avoid triggering several gamepad context
reinitializations right as the stream is exiting
2023-10-29 16:45:07 -05:00
Cameron Gutman fc77322f59 Merge remote-tracking branch 'origin/weblate' 2023-10-29 15:51:59 -05:00
Cameron Gutman 032e944d49 Update moonlight-common-c with multi-homed host fix 2023-10-29 15:34:09 -05:00
Cameron Gutman 0da47da8d8 Move shortcut creation/updates off the main thread for the common cases
These caused quite a few ANRs due to long Binder calls in ShortcutManager.getDynamicShortcuts()
2023-10-26 00:24:44 -05:00
Cameron Gutman ebfe843299 Don't process incoming input device requests from the host after we've stopped 2023-10-26 00:05:24 -05:00
Cameron Gutman 827d2362b7 Don't create LightsSessions for devices without an RGB LED 2023-10-25 23:53:35 -05:00
Cameron Gutman 4fa1eb4088 Fix max FPS detection on Lollipop and earlier 2023-10-25 23:47:40 -05:00
Cameron Gutman 885b59fd52 Fix NPE when receiving non-view-associated mouse events with absolute mouse mode enabled 2023-10-25 23:13:54 -05:00
Cameron Gutman ff5d9f72aa Fix ANRs trying to get battery state during controller arrival 2023-10-25 23:13:11 -05:00
Marocco2 030bb91789 Translated using Weblate (Italian)
Currently translated at 100.0% (242 of 242 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/it/
2023-10-22 09:01:23 +00:00
Jorys Paulin 34788b2808 Translated using Weblate (French)
Currently translated at 100.0% (242 of 242 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/fr/
2023-10-19 06:09:40 +02:00
Cameron Gutman abc4123c52 Version 12.0.1 2023-10-17 22:39:49 -05:00
Cameron Gutman 26f8c0842e Merge remote-tracking branch 'origin/weblate' 2023-10-16 23:57:21 -05:00
Cameron Gutman d430d83ba8 Add clickpad button emulation combo (Select+L1) 2023-10-16 23:56:56 -05:00
Cameron Gutman a52f189fb1 Update ShieldControllerExtensions to fix crash in getBatteryPercentage() 2023-10-16 23:55:39 -05:00
Cameron Gutman dc1045b69e Don't lie to our own clickpad heuristics when overriding the controller type 2023-10-16 23:38:12 -05:00
Cameron Gutman 3a89dbf4ab Update moonlight-common-c 2023-10-16 23:17:08 -05:00
Cameron Gutman d69b4eca1e Disable gamepad motion sensors by default on Android 12 due to an OS bug 2023-10-16 23:16:55 -05:00
Marocco2 568bba82f0 Translated using Weblate (Italian)
Currently translated at 100.0% (242 of 242 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/it/
2023-10-16 04:19:16 +00:00
Smoukus b52e6c88ec Translated using Weblate (German)
Currently translated at 92.5% (224 of 242 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/de/
2023-10-16 04:19:14 +00:00
Cameron Gutman 720595091e Change AV1 bitrate multiplier to match HEVC 2023-10-15 12:49:42 -05:00
Cameron Gutman fe929c8e58 Fix debug build assert 2023-10-13 23:23:42 -05:00
Cameron Gutman 9ecec1eb3c Add support for H.264/HEVC bitstreams with multiple sets of parameter set NALUs 2023-10-13 23:21:50 -05:00
Cameron Gutman 79532f6f14 Version 12.0 2023-10-13 23:02:46 -05:00
Cameron Gutman b400ba385e Update moonlight-common-c 2023-10-12 00:33:55 -05:00
Cameron Gutman 9915007f30 Check for a null UsbManager object
Apparently this can happen on some (broken?) devices
2023-10-12 00:22:28 -05:00
Cameron Gutman 0168a55596 Propagate the controller number to the standalone DS4 touchpad device 2023-10-07 23:26:26 -05:00
Cameron Gutman 229eff49fb Consume unhandled gamepad mouse events to prevent duplicate mouse actions 2023-10-07 23:04:36 -05:00
Cameron Gutman 0e3b472f78 Fix DS4 clickpad button on devices that expose the touchpad as a mouse 2023-10-07 22:58:07 -05:00
Cameron Gutman 5f29b30d34 Fix DS4 clickpad button on Nvidia Shield (again) 2023-10-07 22:53:19 -05:00
Cameron Gutman 9480363362 Update fastlane metadata with new features 2023-10-07 21:07:53 -05:00
Cameron Gutman 5dd80edde4 Wait 1 second after input device reconfiguration to enable motion sensors 2023-10-07 21:07:02 -05:00
Cameron Gutman 2243cf2017 Rewrite NsdManagerDiscoveryAgent lifecycle to avoid listener reuse 2023-10-07 20:42:13 -05:00
Cameron Gutman d7791c8543 Adjust default bitrate logic to match new Qt logic 2023-10-07 19:54:02 -05:00
Cameron Gutman 30822c1ba5 Only check for motion sensors on Sony or Nintendo gamepads on Android 12
This works around a bug in Android 12 that leads to random crashes when input devices change.
2023-10-07 19:07:15 -05:00
Cameron Gutman d250f4dc60 Move battery updates to a background HandlerThread
They can cause long Binder transactions that lead to ANRs.
2023-10-07 00:49:03 -05:00
Cameron Gutman bc27492206 Split ControllerHandler teardown into stop() and destroy() functions 2023-10-07 00:35:36 -05:00
Cameron Gutman 2b63203a5b Update moonlight-common-c 2023-10-06 23:12:21 -05:00
Cameron Gutman dc9a26f57b Update to AGP 8.1.2 2023-10-06 23:11:41 -05:00
Jorys Paulin 6f2d7464ba Translated using Weblate (French)
Currently translated at 100.0% (242 of 242 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/fr/
2023-09-30 19:01:03 +02:00
Jen Kung-chih 6996c101b4 Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (242 of 242 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/zh_Hant/
2023-09-24 23:00:42 +02:00
Cameron Gutman 99dc773c7a Merge remote-tracking branch 'origin/weblate' 2023-09-23 12:59:56 -04:00
Cameron Gutman 6ec3f9455a Update moonlight-common-c with frame corruption fixes 2023-09-23 12:58:57 -04:00
Cameron Gutman 6589a568e2 Add freeform window metadata for ChromeOS 2023-09-23 02:48:53 -04:00
Cameron Gutman 55da48e28c Remove USB options from settings page if USB host mode is not supported 2023-09-23 02:21:53 -04:00
Cameron Gutman 081cca48fb Implement cursor visibility and quit key shortcuts
Fixes #1255
2023-09-23 02:20:26 -04:00
137615 6b6a93725c Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (242 of 242 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/zh_Hant/
2023-09-20 12:01:18 +00:00
137615 c280a52d33 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (242 of 242 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/zh_Hans/
2023-09-20 12:01:17 +00:00
sanhoe b659439f0b Translated using Weblate (Korean)
Currently translated at 100.0% (242 of 242 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/ko/
2023-09-20 12:01:16 +00:00
gallegonovato 6453b3c45c Translated using Weblate (Spanish)
Currently translated at 100.0% (242 of 242 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/es/
2023-09-20 12:01:15 +00:00
Cameron Gutman 978a879c43 Batch async control stream callbacks 2023-09-18 23:25:59 -05:00
Cameron Gutman 833ef3630b Invoke control stream callbacks on a separate thread 2023-09-17 15:00:21 -05:00
Cameron Gutman 024b8c93bc Merge remote-tracking branch 'origin/weblate' 2023-09-16 23:12:05 -05:00
Cameron Gutman d32c4f86a7 Fix unguarded use of Lollipop API 2023-09-16 22:53:13 -05:00
Cameron Gutman cafc4450b2 Override controller type when motion sensor emulation is enabled
Without this, the host will still select an Xbox controller even if it can't support motion sensors.
2023-09-16 22:48:38 -05:00
Cameron Gutman 7d69b53958 Tweak preference strings 2023-09-16 22:27:01 -05:00
Cameron Gutman 4d3e883e49 Correct sensors for device orientation 2023-09-16 22:26:11 -05:00
Cameron Gutman 8f9a687872 Add device sensor fallback option
Correction for device orientation is not implemented yet
2023-09-16 20:25:54 -05:00
Cameron Gutman 08d509d831 Use the device vibrator for devices with built-in gamepads 2023-09-16 19:14:22 -05:00
Cameron Gutman b06dec8449 Fix detection of G Cloud gamepad as an internal controller 2023-09-16 19:09:40 -05:00
Cameron Gutman 28c93b934b Update moonlight-common-c 2023-09-16 16:03:52 -05:00
Cameron Gutman 394a57a26d Disable native touch passthrough for now 2023-09-16 15:59:07 -05:00
bittin1ddc447d824349b2 3856b57a6f Translated using Weblate (Swedish)
Currently translated at 100.0% (239 of 239 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/sv/
2023-09-08 11:59:27 +02:00
Zan 1456 9a3a076890 Translated using Weblate (Hungarian)
Currently translated at 100.0% (239 of 239 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/hu/
2023-09-08 11:59:26 +02:00
Cameron Gutman 314dfcddcf Link to Sunshine 2023-09-03 18:05:00 -05:00
Cameron Gutman 1a85bda997 Update to AGP 8.1.1 2023-09-02 23:32:30 -05:00
Cameron Gutman e8b30d5a88 Set KEY_PRIORITY during low latency option probing 2023-09-02 23:32:16 -05:00
Cameron Gutman 96bd1a7799 Update moonlight-common-c 2023-09-02 22:46:59 -05:00
sanhoe cb0a1f13bc Translated using Weblate (Korean)
Currently translated at 100.0% (239 of 239 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/ko/
2023-08-08 04:53:26 +02:00
Cameron Gutman e92fdeef47 Fix RGB LED capability flag on Android 12 and 13 2023-08-03 23:02:11 -05:00
Cameron Gutman 62bae62386 Fix end of stream toast for AV1 2023-08-03 21:10:06 -05:00
Cameron Gutman 2636d79b86 Fix handling of ACTION_CANCEL for multi-pointer gestures 2023-08-03 02:29:55 -05:00
Cameron Gutman c9c1ef91fd Fix mishandling ACTION_MOVE events for native pen/touch events 2023-07-27 23:15:26 -05:00
weng weng ce7bba3e09 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (239 of 239 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/zh_Hans/
2023-07-26 13:04:56 +02:00
S. MohammadMahdi Zamanian bfd53f39bd Added translation using Weblate (Persian) 2023-07-26 09:23:11 +02:00
Cameron Gutman 554fee037c Fix race condition when stopDiscovery() is called during onServiceFound()/onServiceLost() 2023-07-25 18:46:31 -05:00
Cameron Gutman 67b2853ef0 Add contact area and orientation for pen/touch events 2023-07-22 17:18:57 -05:00
Cameron Gutman 0e29e13d03 Use private API to detect clickpads on Android O and earlier 2023-07-22 14:34:27 -05:00
Jen Kung-chih 35f2a238e9 Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (239 of 239 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/zh_Hant/
2023-07-19 18:05:46 +02:00
Jorys Paulin fcb34ab6ee Translated using Weblate (French)
Currently translated at 100.0% (239 of 239 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/fr/
2023-07-13 11:51:59 +02:00
Cameron Gutman 3fbf682785 Pass gamepad touch input natively by default
Most devices will have a touchscreen which already provides mouse input
and Steam Input is can provide gamepad touchpad mouse control if desired.
2023-07-12 01:21:35 -05:00
Cameron Gutman 16086a6d3f Send the touchpad button on the gamepad even when using the touchpad for mouse control 2023-07-12 01:16:33 -05:00
Cameron Gutman 18b6aae381 Disable gamepad sensors while in PiP mode 2023-07-12 01:07:14 -05:00
Cameron Gutman 642c353164 Fix handling of onInputDeviceChanged when using sensors and lights
DS4 triggers this path when we release our pointer capture on activity pause
2023-07-12 00:32:28 -05:00
Cameron Gutman 42f64e5e88 Rename videoformat_hevcauto translations to videoformat_auto 2023-07-11 20:18:31 -05:00
Cameron Gutman 6af748b2cc Remove videoformat_hevcauto translations that still reference HEVC 2023-07-11 20:12:10 -05:00
Cameron Gutman 4fe97b69c7 Fix invalid format string 2023-07-11 20:10:52 -05:00
Cameron Gutman 04d46272dd Remove now unused videoformat_hevcnever string 2023-07-11 20:10:38 -05:00
Cameron Gutman 1c0290dc7a Merge remote-tracking branch 'origin/weblate' 2023-07-11 20:05:21 -05:00
Cameron Gutman 38588402e3 Use NsdManager for mDNS discovery on Android 14 2023-07-11 19:58:50 -05:00
Luna Jernberg dfe3b8888d Translated using Weblate (Swedish)
Currently translated at 99.5% (238 of 239 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/sv/
2023-07-11 17:49:16 +02:00
ThomasTech e8f4022f1e Translated using Weblate (French)
Currently translated at 95.3% (228 of 239 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/fr/
2023-07-11 17:49:15 +02:00
gallegonovato e37bb32c82 Translated using Weblate (Spanish)
Currently translated at 100.0% (239 of 239 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/es/
2023-07-11 17:49:15 +02:00
Cameron Gutman 1f72c82acb Consolidate AV1 and HEVC options into a single preference 2023-07-09 15:04:26 -05:00
Cameron Gutman e6876926a4 Add options to control gamepad touchpad and motion and reorganize input settings 2023-07-09 14:46:46 -05:00
Cameron Gutman 2b8a43ab13 Update locale selections to add Hebrew, Swedish, and Indonesian languages 2023-07-09 14:00:14 -05:00
Cameron Gutman 8737466368 Merge branch 'weblate' of github.com:moonlight-stream/moonlight-android 2023-07-09 13:47:07 -05:00
Cameron Gutman 83916fa43e Map the Menu key for keyboards 2023-07-08 23:21:19 -05:00
Cameron Gutman 1fe5a12a45 Update moonlight-common-c 2023-07-08 23:19:33 -05:00
Cameron Gutman fa7f3115ed Add AV1 autoselection by performance point criteria 2023-07-07 23:09:05 -05:00
Cameron Gutman 4dc6143440 Override the stock DS4 touchpad button mapping for Shield devices
Nvidia's stock mapping treats the clickpad as a second select button.
2023-07-05 23:00:54 -05:00
Cameron Gutman f1503aa56c Implement battery reporting for Shield controllers 2023-07-05 18:57:01 -05:00
Cameron Gutman 67f344b755 Move serverCodecModeSupport into SERVER_INFORMATION struct 2023-07-02 23:56:34 -05:00
Cameron Gutman f1bcc217a9 Update to new HDR support option in moonlight-common-c 2023-07-02 23:48:19 -05:00
Cameron Gutman 458460515d Plumb AV1 preference and rework HEVC preference to match 2023-07-02 23:48:13 -05:00
Cameron Gutman 3a78095574 Initial implementation of AV1 2023-07-02 22:49:42 -05:00
Cameron Gutman d6bbfa1af1 Fix unmapped paddle and share button presses 2023-07-02 20:32:57 -05:00
Cameron Gutman 4e1b778f31 Import some SDL code and use it for controller classification
Imported as of 4aee17b039981f2bb79892f3d3e3e17bd6b66530
2023-07-02 20:20:55 -05:00
Cameron Gutman 5f4496036c Don't use GameManager loading flag
This is meant to affect CPU throttling, which we don't need.
2023-07-02 19:08:58 -05:00
Cameron Gutman d4079940b4 Implement controller LED and battery state extensions 2023-07-02 19:03:31 -05:00
Cameron Gutman 803ad116fb Pull in latest moonlight-common-c change 2023-06-28 17:28:41 -05:00
Cameron Gutman 27701eda49 Handle paddle buttons on Xbox Elite controllers 2023-06-28 17:28:25 -05:00
Cameron Gutman 71c831b02d Handle 2-direction d-pad key events 2023-06-28 17:22:05 -05:00
Cameron Gutman 0d72a0e009 Implement latest pen/touch protocol updates 2023-06-27 22:21:39 -05:00
Cameron Gutman 69a4502f90 Fix pen/touch coordinates when reported from the background touch view 2023-06-25 00:50:17 -05:00
Cameron Gutman daaa7f4e63 Fix pen rotation values 2023-06-25 00:26:32 -05:00
Cameron Gutman d1579e9b0d Support PS4/PS5 touchpad click on older kernels 2023-06-24 23:45:31 -05:00
Cameron Gutman 5890fff240 Add pen and touch events 2023-06-24 23:13:59 -05:00
Cameron Gutman d6f6307050 Fix units of gyro motion and deduplicate sensor events 2023-06-24 23:12:28 -05:00
Cameron Gutman 6bf9c31860 Pull in updated moonlight-common-c pen/touch APIs 2023-06-24 21:29:44 -05:00
Cameron Gutman a2e628f3f8 Add controller arrival metadata support 2023-06-24 20:23:43 -05:00
Cameron Gutman 8f5416ff31 Target Android 14 2023-06-24 19:38:34 -05:00
Cameron Gutman db86f18133 Use new per-activity predictive back support on Android 14
We can't enable it on the Game activity, but we an use it for all other activities.
2023-06-24 19:38:07 -05:00
Cameron Gutman 419e4e656e Use an explicit intent for requesting USB permission 2023-06-24 19:37:12 -05:00
Cameron Gutman eed4327d26 Add controller touchpad support 2023-06-24 19:09:10 -05:00
Cameron Gutman 5c6eaf2602 Add controller gyro and accelerometer support 2023-06-24 19:06:58 -05:00
Cameron Gutman 71169ed740 Add trigger rumble support 2023-06-24 17:59:10 -05:00
Cameron Gutman dca8d93aa8 Add Share button mapping for Xbox Series X controller 2023-06-24 16:16:02 -05:00
Cameron Gutman 6cb152f602 Increase gamepad limit to 16 for Sunshine hosts 2023-06-24 16:15:00 -05:00
Cameron Gutman ddefda3afa Plumb new Sunshine protocol extensions 2023-06-24 15:19:50 -05:00
Cameron Gutman 7f15f45beb Only display the host processing latency if it was present 2023-06-24 15:00:54 -05:00
Timothy Lusk 46f887efec Add host processing latency to performance stats overlay 2023-06-24 14:19:05 -05:00
semjon00 90afecd766 Add option to stream at device native FPS
Useful for phones with overclocked refresh rate
2023-06-24 14:16:49 -05:00
Cameron Gutman 388343c3ee Update to AGP 8.0.2 2023-06-24 14:15:38 -05:00
ns6089 c8df37e89e Compensate for choreographer vsync offset 2023-06-24 13:52:20 -05:00
Clxff H3r4ld0 cc85d5c343 Translated using Weblate (Indonesian)
Currently translated at 79.5% (183 of 230 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/id/
2023-05-27 17:50:51 +02:00
Jorys Paulin f8437cdb8f Translated using Weblate (French)
Currently translated at 100.0% (230 of 230 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/fr/
2023-05-21 16:51:09 +02:00
shakedex c99a210905 Translated using Weblate (Hebrew)
Currently translated at 57.3% (132 of 230 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/he/
2023-04-30 10:50:54 +02:00
Yutaro Urata e33673c9e9 Translated using Weblate (Japanese)
Currently translated at 51.7% (119 of 230 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/ja/
2023-04-30 10:50:53 +02:00
shakedex 79283e93cb Translated using Weblate (Hebrew)
Currently translated at 50.4% (116 of 230 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/he/
2023-04-27 01:51:19 +02:00
shakedex a60e85a3a4 Added translation using Weblate (Hebrew) 2023-04-25 23:56:54 +02:00
Simon Nilsson 80910ed38d Translated using Weblate (Swedish)
Currently translated at 100.0% (230 of 230 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/sv/
2023-03-31 22:09:41 +02:00
Simon Nilsson 825a338474 Added translation using Weblate (Swedish) 2023-03-29 16:56:54 +02:00
Cameron Gutman 19b6e94824 Add horizontal scrolling in mouse emulation mode 2023-03-04 12:31:31 -06:00
Cameron Gutman 0b581011c5 Version 11.0 2023-02-28 21:31:32 -06:00
Cliff Heraldo 6b7669bb75 Translated using Weblate (Indonesian)
Currently translated at 32.1% (74 of 230 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/id/
2023-02-27 10:37:51 +01:00
Cameron Gutman 67bcc56c6d Remove strict codec recovery timeout
Codec recovery depends on incoming frames, so it cannot be reliably time-constrained
2023-02-26 13:26:01 -06:00
Cameron Gutman 7d8cfa3c6a Remove URL filtering to fix wiki links to outside pages 2023-02-25 20:37:49 -06:00
Cameron Gutman f659af29da Fix mDNS detection of hosts with the same IP address
This is the case for PCs running GFE and Sunshine side-by-side.
2023-02-25 20:29:51 -06:00
Cameron Gutman 94b202f7b6 Update moonlight-common-c 2023-02-25 13:13:05 -06:00
Cameron Gutman ca86fdafab Merge remote-tracking branch 'origin/weblate' 2023-02-25 13:01:55 -06:00
Cameron Gutman 370dbb1a10 Send non-ASCII soft keys as UTF-8 2023-02-25 12:49:55 -06:00
luten145 f77543cd9b Added clipboard support
You can paste Android's clipboard contents.
2023-02-25 12:30:58 -06:00
Steffen_LT 7104e0d725 Relative mouse fix on Chromebooks with touchscreens 2023-02-25 12:28:49 -06:00
weng weng 230a67cac0 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (230 of 230 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/zh_Hans/
2023-02-24 08:36:54 +01:00
Jen Kung-chih a695f38974 Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (230 of 230 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/zh_Hant/
2023-02-23 07:38:22 +01:00
Cameron Gutman 151c09f098 Merge remote-tracking branch 'origin/weblate' 2023-02-21 22:44:00 -06:00
gallegonovato 8200f5690d Translated using Weblate (Spanish)
Currently translated at 100.0% (230 of 230 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/es/
2023-02-22 05:43:42 +01:00
Cameron Gutman 77a8cf2704 Remove the touchscreen trackpad option hiding entirely
Fixes #1184
2023-02-21 22:42:35 -06:00
Cameron Gutman fe424961e1 Update Fastlane metadata 2023-02-21 22:37:24 -06:00
Cameron Gutman b668cb78ff Update to AGP 7.4.1 2023-02-21 22:36:04 -06:00
bladeoner 48278419b0 Update Gradle to version 7.6 2023-02-21 22:29:32 -06:00
Cameron Gutman 632da03667 Merge remote-tracking branch 'origin/weblate' 2023-02-21 02:15:03 -06:00
Cameron Gutman d36b73fc1b Fix crash with IPv4-mapped IPv6 addresses 2023-02-20 23:31:53 -06:00
Cameron Gutman 292ed35555 Update moonlight-common-c 2023-02-20 23:24:32 -06:00
Cameron Gutman 02d0ad496f Fix error message being displayed even after successful WoL 2023-02-20 23:01:46 -06:00
Cameron Gutman eb2fc7af40 Add GameStream EOL notice for GFE PCs 2023-02-20 23:01:08 -06:00
Cameron Gutman 6550deedbb Fix handling of missing addresses 2023-02-20 22:35:27 -06:00
Cameron Gutman 80acd9b9eb Modernize HTTPS launch/resume for Sunshine 2023-02-20 22:04:41 -06:00
Cameron Gutman b961636f02 Plumb HDR metadata into MediaCodec 2023-02-20 21:42:45 -06:00
Cameron Gutman f4df0714b5 Implement horizontal scrolling with Sunshine 2023-02-20 19:56:01 -06:00
Cameron Gutman 91dd7b7049 Plumb non-normalized key flag extension for Sunshine 2023-02-20 19:52:52 -06:00
Karim Mreisi 121bef7d2d fix: use address and port for details hash 2023-02-20 13:32:55 -06:00
Karim Mreisi 3a9eabf50b fix: support host names with _
Use a JSON to properly encapsule different computer addresses and their
port, instead of using "_" as separator.

Fix usage of '_' in computer host names / domain names.
2023-02-20 13:32:55 -06:00
bladeoner c8198b4091 Update bug and feature_request forms 2023-02-20 13:25:03 -06:00
Cameron Gutman e4538e4a51 Only remove touchscreen-trackpad option on TV devices
Some VR headset devices can make use of this without a proper touchscreen
2023-02-20 13:22:01 -06:00
Cameron Gutman b47f3ef397 Remove input batching to replace with common-c implementation 2023-02-20 13:19:59 -06:00
Jen Kung-chih 6e096c0ac3 Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (229 of 229 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/zh_Hant/
2023-02-14 07:37:50 +01:00
weng weng ee3b4686bf Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (229 of 229 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/zh_Hans/
2023-02-14 07:37:49 +01:00
gallegonovato 759b77eafe Translated using Weblate (Spanish)
Currently translated at 100.0% (229 of 229 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/es/
2023-02-12 22:38:54 +01:00
Cameron Gutman de15ec666f Merge remote-tracking branch 'origin/weblate' 2023-02-11 14:27:49 -06:00
Cameron Gutman 3de86f15af Disable HEVC RFI on platforms with older Tegra BSPs
Fixes #1177
2023-02-11 14:26:54 -06:00
Cameron Gutman 1b9dff719c Remove most NVIDIA-specific references in code 2023-02-11 14:25:54 -06:00
Jorys Paulin abcf4e3d4a Translated using Weblate (French)
Currently translated at 100.0% (228 of 228 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/fr/
2023-02-09 11:38:54 +01:00
Jen Kung-chih 9823abe686 Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (228 of 228 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/zh_Hant/
2023-01-24 09:51:09 +01:00
LUTEN 723e08f69b Translated using Weblate (Korean)
Currently translated at 100.0% (228 of 228 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/ko/
2023-01-12 08:49:04 +01:00
ssantos daf0a0891e Translated using Weblate (Portuguese)
Currently translated at 100.0% (228 of 228 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/pt/
2023-01-10 19:51:36 +01:00
Jen Kung-chih 49dc68f77f Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (228 of 228 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/zh_Hant/
2022-12-30 06:51:13 +01:00
gallegonovato f81a1c36cc Translated using Weblate (Spanish)
Currently translated at 100.0% (228 of 228 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/es/
2022-12-24 15:51:06 +01:00
Dan 9a11a771dd Translated using Weblate (Ukrainian)
Currently translated at 100.0% (228 of 228 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/uk/
2022-12-21 01:50:21 +01:00
Translator-3000 b56a4b8b49 Translated using Weblate (Italian)
Currently translated at 100.0% (228 of 228 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/it/
2022-12-19 18:49:33 +01:00
Cameron Gutman 1aa963992b Improve Xbox 360W controller numbering 2022-12-16 00:35:19 -06:00
Cameron Gutman 1b601324d0 Remove automatic detection logic for CONFIG_JOYSTICK_XPAD_LEDS=y
It doesn't work due to Android app sandboxing
2022-12-16 00:20:06 -06:00
Cameron Gutman 1aea723ef0 Rework Xbox360W support to handle multiple controllers 2022-12-15 23:33:48 -06:00
Cameron Gutman 1e828a10b9 Request our desired refresh rate rather than the actual frame rate
This ensures we'll get the highest compatible refresh rate rather than the lowest.
2022-12-15 22:53:25 -06:00
Cameron Gutman 970423f873 Use setFrameRate() instead of preferredDisplayModeId if the modes differ only by refresh rate
This seems to avoid a bug on the Chromecast 4K where it can decide to switch to 4K24 instead of 4K60

Fixes #1151
2022-12-14 23:05:22 -06:00
Cameron Gutman 2d7493fd1e Improve check for kernel support for Xbox360W LED configuration 2022-12-14 21:49:42 -06:00
sivan-koren fa7eb1c4b1 Set Lights on XBOX360 Wireless Controllers for New Android/Google TVs Through 2023 - Fixes: #1061 (#1157) 2022-12-14 21:29:41 -06:00
SpeedPartner 4916af3697 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (228 of 228 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/zh_Hans/
2022-12-08 14:47:25 +01:00
Eric 8484bf1cb9 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (228 of 228 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/zh_Hans/
2022-12-08 14:47:25 +01:00
SpeedPartner 005afb3c73 Translated using Weblate (Chinese (Simplified))
Currently translated at 98.6% (225 of 228 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/zh_Hans/
2022-12-07 14:04:03 +01:00
Jen Kung-chih 84b0d004b9 Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (228 of 228 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/zh_Hant/
2022-12-07 11:47:26 +01:00
299 changed files with 38994 additions and 19267 deletions
-48
View File
@@ -1,48 +0,0 @@
---
name: Bug report
about: Follow the troubleshooting guide before reporting a bug
---
**READ ME FIRST!**
If you're here because something basic is not working (like gamepad input, video, or similar), it's probably something specific to your setup, so make sure you've gone through the Troubleshooting Guide first: https://github.com/moonlight-stream/moonlight-docs/wiki/Troubleshooting
If you still have trouble with basic functionality after following the guide, join our Discord server where there are many other volunteers who can help (or direct you back here if it looks like a Moonlight bug after all). https://moonlight-stream.org/discord
**Describe the bug**
A clear and concise description of what the bug is.
**Steps to reproduce**
Any special steps that are required for the bug to appear.
**Screenshots**
If applicable, add screenshots to help explain your problem. If the issue is related to video glitching or poor quality, please include screenshots.
**Affected games**
List the games you've tried that exhibit the issue. To see if the issue is game-specific, try streaming Steam Big Picture with Moonlight and see if the issue persists there.
**Other Moonlight clients**
- Does the issue occur when using Moonlight on PC or iOS?
**Moonlight settings (please complete the following information)**
- Have any settings been adjusted from defaults?
- If so, which settings have been changed?
- Does the problem still occur after reverting settings back to default?
**Gamepad-related issues (please complete if problem is gamepad-related)**
- Do you have any gamepads connected to your host PC directly?
- If gamepad input is not working, does it work if you use Moonlight's on-screen controls?
- Does the problem still remain if you stream the desktop and use https://html5gamepad.com to test your gamepad?
- Instructions for streaming the desktop can be found here: https://github.com/moonlight-stream/moonlight-docs/wiki/Setup-Guide
**Device details (please complete the following information)**
- Android version: [e.g. Android 10]
- Device model: [e.g. Samsung Galaxy S21]
**Server PC details (please complete the following information)**
- OS: [e.g. Windows 10 1809]
- GeForce Experience version: [e.g. 3.16.0.140]
- Nvidia GPU driver: [e.g. 417.35]
- Antivirus and firewall software: [e.g. Windows Defender and Windows Firewall]
**Additional context**
Anything else you think may be relevant to the issue or special about your specific setup.
+176
View File
@@ -0,0 +1,176 @@
name: Bug report
description: Follow the troubleshooting guide before reporting a bug
title: "[Issue]: "
labels: bug
body:
- type: markdown
attributes:
value: |
Thank you for taking the time to fill out this bug form!
**READ ME FIRST!**
If you're here because something basic is not working (like gamepad input, video, or similar), it's probably something specific to your setup, so make sure you've gone through the Troubleshooting Guide first: https://github.com/moonlight-stream/moonlight-docs/wiki/Troubleshooting
If you still have trouble with basic functionality after following the guide, join our Discord server where there are many other volunteers who can help (or direct you back here if it looks like a Moonlight bug after all). https://moonlight-stream.org/discord
- type: textarea
id: describe-bug
attributes:
label: Describe the bug
description: A clear and concise description of what the bug is.
validations:
required: true
- type: textarea
id: steps-reproduce
attributes:
label: Steps to reproduce
description: Any special steps that are required for the bug to appear.
validations:
required: true
- type: textarea
id: affected-games
attributes:
label: Affected games
description: List the games you've tried that exhibit the issue. To see if the issue is game-specific, try streaming Steam Big Picture with Moonlight and see if the issue persists there.
validations:
required: true
- type: dropdown
id: other-clients
attributes:
label: Other Moonlight clients
description: Does the issue occur when using Moonlight on PC or iOS?
options:
- "PC"
- "iOS"
validations:
required: true
- type: dropdown
id: settings-adjusted
attributes:
label: Moonlight adjusted settings
description: Have any settings been adjusted from defaults?
options:
- "Yes"
- "No"
validations:
required: true
- type: textarea
id: settings-adjusted-settings
attributes:
label: Moonlight adjusted settings (please complete the following information)
description: If the settings have been adjusted, which settings have been changed?
validations:
required: true
- type: dropdown
id: settings-default
attributes:
label: Moonlight default settings
description: Does the problem still occur after reverting settings back to default?
options:
- "Yes"
- "No"
validations:
required: true
- type: dropdown
id: gamepad-connected
attributes:
label: Gamepad-related connection issue
description: Do you have any gamepads connected to your host PC directly?
options:
- "Yes"
- "No"
validations:
required: true
- type: dropdown
id: gamepad-on-screen
attributes:
label: Gamepad-related input issue
description: If gamepad input is not working, does it work if you use Moonlight's on-screen controls?
options:
- "Yes"
- "No"
validations:
required: true
- type: dropdown
id: gamepad-test
attributes:
label: Gamepad-related streaming issue
description: |
Does the problem still remain if you stream the desktop and use https://html5gamepad.com to test your gamepad?
Instructions for streaming the desktop can be found here: https://github.com/moonlight-stream/moonlight-docs/wiki/Setup-Guide
options:
- "Yes"
- "No"
validations:
required: true
- type: input
id: android
attributes:
label: Android version
description: What is the Android version?
placeholder: e.g. Android 10
validations:
required: true
- type: input
id: device
attributes:
label: Device model
description: What is the device model?
placeholder: e.g. Samsung Galaxy S21
validations:
required: true
- type: input
id: server-os
attributes:
label: Server PC OS version
description: What is the PC OS version?
placeholder: e.g. Windows 10 1809
validations:
required: true
- type: input
id: server-geforce
attributes:
label: Server PC GeForce Experience version
description: What is the GeForce Experience version?
placeholder: e.g. 3.16.0.140
validations:
required: true
- type: input
id: server-driver
attributes:
label: Server PC Nvidia GPU driver version
description: What is the Nvidia GPU driver version?
placeholder: e.g. 417.35
validations:
required: true
- type: input
id: server-antivirus
attributes:
label: Server PC antivirus and firewall software
description: Which antivirus and firewall software are installed on the Server PC?
placeholder: e.g. Windows Defender and Windows Firewall
validations:
required: true
- type: textarea
id: screenshots
attributes:
label: Screenshots
description: If applicable, add screenshots to help explain your problem. If the issue is related to video glitching or poor quality, please include screenshots.
validations:
required: false
- type: textarea
id: logs
attributes:
label: Relevant log output
description: |
Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
render: Shell
validations:
required: false
- type: textarea
id: additional
attributes:
label: Additional context
description: Anything else you think may be relevant to the issue or special about your specific setup.
validations:
required: false
-17
View File
@@ -1,17 +0,0 @@
---
name: Feature request
about: Suggest an idea for this project
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
@@ -0,0 +1,37 @@
name: Feature request
description: Suggest an idea for this project
title: "[Feature request]: "
labels: enhancement
body:
- type: markdown
attributes:
value: |
Thank you for taking the time to fill out this feature form!
- type: textarea
id: feature
attributes:
label: Is your feature request related to a problem? Please describe.
description: A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
validations:
required: true
- type: textarea
id: solution
attributes:
label: Describe the solution you'd like
description: A clear and concise description of what you want to happen.
validations:
required: true
- type: textarea
id: alternatives
attributes:
label: Describe alternatives you've considered
description: A clear and concise description of any alternative solutions or features you've considered.
validations:
required: true
- type: textarea
id: screenshots
attributes:
label: Screenshots
description: Add any other context or screenshots about the feature request here.
validations:
required: false
+1 -1
View File
@@ -3,7 +3,7 @@
[![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/232a8tadrrn8jv0k/branch/master?svg=true)](https://ci.appveyor.com/project/cgutman/moonlight-android/branch/master)
[![Translation Status](https://hosted.weblate.org/widgets/moonlight/-/moonlight-android/svg-badge.svg)](https://hosted.weblate.org/projects/moonlight/moonlight-android/)
[Moonlight for Android](https://moonlight-stream.org) is an open source client for NVIDIA GameStream, as used by the NVIDIA Shield.
[Moonlight for Android](https://moonlight-stream.org) is an open source client for NVIDIA GameStream and [Sunshine](https://github.com/LizardByte/Sunshine).
Moonlight for Android will allow you to stream your full collection of games from your Windows PC to your Android device,
whether in your own home or over the internet.
+32 -20
View File
@@ -1,16 +1,18 @@
apply plugin: 'com.android.application'
android {
ndkVersion "23.2.8568313"
ndkVersion "29.0.14206865"
compileSdk 33
compileSdk 37
namespace 'com.limelight'
defaultConfig {
minSdk 16
targetSdk 33
minSdk 21
targetSdk 36
versionName "10.11"
versionCode = 301
versionName "12.2"
versionCode = 315
// Generate native debug symbols to allow Google Play to symbolicate our native crashes
ndk.debugSymbolLevel = 'FULL'
@@ -18,6 +20,11 @@ android {
flavorDimensions.add("root")
buildFeatures {
buildConfig = true
resValues = true
}
productFlavors {
root {
// Android O has native mouse capture, so don't show the rooted
@@ -50,8 +57,9 @@ android {
compileOptions {
encoding "UTF-8"
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
coreLibraryDesugaringEnabled true
}
lint {
@@ -78,9 +86,6 @@ android {
applicationIdSuffix ".debug"
resValue "string", "app_label", "Moonlight (Debug)"
resValue "string", "app_label_root", "Moonlight (Root Debug)"
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
release {
// To whomever is releasing/using an APK in release mode with
@@ -118,7 +123,7 @@ android {
resValue "string", "app_label_root", "Moonlight (Root)"
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
@@ -127,15 +132,22 @@ android {
path "src/main/jni/Android.mk"
}
}
packaging {
resources {
// BouncyCastle includes duplicate LICENSE.md files
excludes += '/META-INF/*.md'
}
}
}
dependencies {
implementation 'org.bouncycastle:bcprov-jdk15on:1.70'
implementation 'org.bouncycastle:bcpkix-jdk15on:1.70'
implementation 'org.jcodec:jcodec:0.2.3'
implementation 'com.squareup.okhttp3:okhttp:3.12.13'
implementation 'com.squareup.okio:okio:1.17.5'
// 3.5.8 requires minSdk 19, uses StandardCharsets.UTF_8 internally
implementation 'org.jmdns:jmdns:3.5.7'
implementation 'com.github.cgutman:ShieldControllerExtensions:1.0'
implementation 'org.bouncycastle:bcprov-jdk18on:1.85.2'
implementation 'org.bouncycastle:bcpkix-jdk18on:1.85'
implementation 'org.jcodec:jcodec:0.2.5'
implementation 'com.squareup.okhttp3:okhttp:5.5.0'
implementation 'org.jmdns:jmdns:3.6.3'
implementation 'com.github.cgutman:ShieldControllerExtensions:1.0.1'
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.5'
}
+42 -22
View File
@@ -1,16 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.limelight">
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CAPTURE_KEYBOARD" />
<uses-permission android:name="com.android.providers.tv.permission.READ_EPG_DATA"/>
<uses-permission android:name="com.android.providers.tv.permission.WRITE_EPG_DATA"/>
<!-- We don't need a MulticastLock on API level 34+ because we use NsdManager for mDNS -->
<uses-permission
android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"
android:maxSdkVersion="33" />
<uses-feature
android:name="android.hardware.touchscreen"
android:required="false" />
@@ -26,6 +30,12 @@
<uses-feature
android:name="android.software.leanback"
android:required="false" />
<uses-feature
android:name="android.hardware.sensor.accelerometer"
android:required="false" />
<uses-feature
android:name="android.hardware.sensor.gyroscope"
android:required="false" />
<!-- Disable legacy input emulation on ChromeOS -->
<uses-feature
@@ -41,7 +51,6 @@
android:banner="@drawable/atv_banner"
android:appCategory="game"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher"
android:installLocation="auto"
android:gwpAsanMode="always"
android:localeConfig="@xml/locales_config"
@@ -68,6 +77,11 @@
<meta-data
android:name="com.android.graphics.intervention.wm.allowDownscale"
android:value="false"/>
<!-- Game Mode configuration -->
<meta-data
android:name="android.game_mode_config"
android:resource="@xml/game_mode_config" />
<!-- Samsung DeX support requires explicit placement of android:resizeableActivity="true"
in each activity even though it is implied by targeting API 24+ -->
@@ -76,7 +90,12 @@
android:name=".PcView"
android:exported="true"
android:resizeableActivity="true"
android:enableOnBackInvokedCallback="true"
android:configChanges="mcc|mnc|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize|layoutDirection">
<meta-data android:name="WindowManagerPreference:FreeformWindowSize" android:value="system-default" />
<meta-data android:name="WindowManagerPreference:FreeformWindowOrientation" android:value="landscape" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -92,37 +111,37 @@
android:noHistory="true"
android:exported="true"
android:resizeableActivity="true"
android:enableOnBackInvokedCallback="true"
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize|layoutDirection">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.limelight.PcView" />
<meta-data android:name="WindowManagerPreference:FreeformWindowSize" android:value="system-default" />
<meta-data android:name="WindowManagerPreference:FreeformWindowOrientation" android:value="landscape" />
</activity>
<activity
android:name=".AppView"
android:resizeableActivity="true"
android:enableOnBackInvokedCallback="true"
android:configChanges="mcc|mnc|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize|layoutDirection">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.limelight.PcView" />
<meta-data android:name="WindowManagerPreference:FreeformWindowSize" android:value="system-default" />
<meta-data android:name="WindowManagerPreference:FreeformWindowOrientation" android:value="landscape" />
</activity>
<activity
android:name=".preferences.StreamSettings"
android:resizeableActivity="true"
android:enableOnBackInvokedCallback="true"
android:configChanges="mcc|mnc|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize|layoutDirection"
android:label="Streaming Settings">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.limelight.PcView" />
<meta-data android:name="WindowManagerPreference:FreeformWindowSize" android:value="system-default" />
<meta-data android:name="WindowManagerPreference:FreeformWindowOrientation" android:value="landscape" />
</activity>
<activity
android:name=".preferences.AddComputerManually"
android:resizeableActivity="true"
android:windowSoftInputMode="stateVisible"
android:enableOnBackInvokedCallback="true"
android:configChanges="mcc|mnc|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize|layoutDirection"
android:label="Add Computer Manually">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.limelight.PcView" />
<meta-data android:name="WindowManagerPreference:FreeformWindowSize" android:value="system-default" />
<meta-data android:name="WindowManagerPreference:FreeformWindowOrientation" android:value="landscape" />
</activity>
<activity
android:name=".Game"
@@ -130,13 +149,14 @@
android:noHistory="true"
android:supportsPictureInPicture="true"
android:resizeableActivity="true"
android:enableOnBackInvokedCallback="false"
android:launchMode="singleTask"
android:excludeFromRecents="true"
android:theme="@style/StreamTheme"
android:preferMinimalPostProcessing="true">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.limelight.AppView" />
<meta-data android:name="WindowManagerPreference:FreeformWindowSize" android:value="system-default" />
<meta-data android:name="WindowManagerPreference:FreeformWindowOrientation" android:value="landscape" />
<!-- Special metadata for NVIDIA Shield devices to prevent input buffering
and most importantly, opt out of mouse acceleration while streaming -->
@@ -161,10 +181,10 @@
<activity
android:name=".HelpActivity"
android:resizeableActivity="true"
android:enableOnBackInvokedCallback="true"
android:configChanges="mcc|mnc|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize|layoutDirection">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.limelight.PcView" />
<meta-data android:name="WindowManagerPreference:FreeformWindowSize" android:value="system-default" />
<meta-data android:name="WindowManagerPreference:FreeformWindowOrientation" android:value="landscape" />
</activity>
</application>
File diff suppressed because it is too large Load Diff
@@ -71,12 +71,6 @@ public class HelpActivity extends Activity {
refreshBackDispatchState();
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return !(url.toUpperCase().startsWith("https://github.com/moonlight-stream/moonlight-docs/wiki/".toUpperCase()) ||
url.toUpperCase().startsWith("http://github.com/moonlight-stream/moonlight-docs/wiki/".toUpperCase()));
}
});
webView.loadUrl(getIntent().getData().toString());
+20 -6
View File
@@ -118,6 +118,7 @@ public class PcView extends Activity implements AdapterFragmentCallbacks {
private final static int VIEW_DETAILS_ID = 8;
private final static int FULL_APP_LIST_ID = 9;
private final static int TEST_NETWORK_ID = 10;
private final static int GAMESTREAM_EOL_ID = 11;
private void initializeViews() {
setContentView(R.layout.activity_pc_view);
@@ -259,6 +260,11 @@ public class PcView extends Activity implements AdapterFragmentCallbacks {
updateComputer(details);
}
});
// Add a launcher shortcut for this PC (off the main thread to prevent ANRs)
if (details.pairState == PairState.PAIRED) {
shortcutHelper.createAppViewShortcutForOnlineHost(details);
}
}
}
});
@@ -352,9 +358,13 @@ public class PcView extends Activity implements AdapterFragmentCallbacks {
if (computer.details.state == ComputerDetails.State.OFFLINE ||
computer.details.state == ComputerDetails.State.UNKNOWN) {
menu.add(Menu.NONE, WOL_ID, 1, getResources().getString(R.string.pcview_menu_send_wol));
menu.add(Menu.NONE, GAMESTREAM_EOL_ID, 2, getResources().getString(R.string.pcview_menu_eol));
}
else if (computer.details.pairState != PairState.PAIRED) {
menu.add(Menu.NONE, PAIR_ID, 1, getResources().getString(R.string.pcview_menu_pair_pc));
if (computer.details.nvidiaServer) {
menu.add(Menu.NONE, GAMESTREAM_EOL_ID, 2, getResources().getString(R.string.pcview_menu_eol));
}
}
else {
if (computer.details.runningGameId != 0) {
@@ -362,6 +372,10 @@ public class PcView extends Activity implements AdapterFragmentCallbacks {
menu.add(Menu.NONE, QUIT_ID, 2, getResources().getString(R.string.applist_menu_quit));
}
if (computer.details.nvidiaServer) {
menu.add(Menu.NONE, GAMESTREAM_EOL_ID, 3, getResources().getString(R.string.pcview_menu_eol));
}
menu.add(Menu.NONE, FULL_APP_LIST_ID, 4, getResources().getString(R.string.pcview_menu_app_list));
}
@@ -412,7 +426,8 @@ public class PcView extends Activity implements AdapterFragmentCallbacks {
// Spin the dialog off in a thread because it blocks
Dialog.displayDialog(PcView.this, getResources().getString(R.string.pair_pairing_title),
getResources().getString(R.string.pair_pairing_msg)+" "+pinStr, false);
getResources().getString(R.string.pair_pairing_msg)+" "+pinStr+"\n\n"+
getResources().getString(R.string.pair_pairing_help), false);
PairingManager pm = httpConn.getPairingManager();
@@ -656,6 +671,10 @@ public class PcView extends Activity implements AdapterFragmentCallbacks {
ServerHelper.doNetworkTest(PcView.this);
return true;
case GAMESTREAM_EOL_ID:
HelpLauncher.launchGameStreamEolFaq(PcView.this);
return true;
default:
return super.onContextItemSelected(item);
}
@@ -706,11 +725,6 @@ public class PcView extends Activity implements AdapterFragmentCallbacks {
}
}
// Add a launcher shortcut for this PC
if (details.pairState == PairState.PAIRED) {
shortcutHelper.createAppViewShortcutForOnlineHost(details);
}
if (existingEntry != null) {
// Replace the information in the existing entry
existingEntry.details = details;
@@ -8,19 +8,26 @@ import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import com.limelight.computers.ComputerDatabaseManager;
import com.limelight.computers.ComputerManagerListener;
import com.limelight.computers.ComputerManagerService;
import com.limelight.nvstream.http.ComputerDetails;
import com.limelight.nvstream.http.NvApp;
import com.limelight.nvstream.http.NvHTTP;
import com.limelight.nvstream.http.PairingManager;
import com.limelight.nvstream.wol.WakeOnLanSender;
import com.limelight.utils.CacheHelper;
import com.limelight.utils.Dialog;
import com.limelight.utils.ServerHelper;
import com.limelight.utils.SpinnerDialog;
import com.limelight.utils.UiHelper;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class ShortcutTrampoline extends Activity {
@@ -33,6 +40,7 @@ public class ShortcutTrampoline extends Activity {
private SpinnerDialog blockingLoadSpinner;
private ComputerManagerService.ComputerManagerBinder managerBinder;
private final ServiceConnection serviceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder binder) {
final ComputerManagerService.ComputerManagerBinder localBinder =
@@ -214,9 +222,9 @@ public class ShortcutTrampoline extends Activity {
}
};
protected boolean validateInput(String uuidString, String appIdString) {
// Validate UUID
if (uuidString == null) {
protected boolean validateInput(String uuidString, String appIdString, String nameString) {
// Validate PC UUID/Name
if (uuidString == null && nameString == null) {
Dialog.displayDialog(ShortcutTrampoline.this,
getResources().getString(R.string.conn_error_title),
getResources().getString(R.string.scut_invalid_uuid),
@@ -224,14 +232,25 @@ public class ShortcutTrampoline extends Activity {
return false;
}
try {
UUID.fromString(uuidString);
} catch (IllegalArgumentException ex) {
Dialog.displayDialog(ShortcutTrampoline.this,
getResources().getString(R.string.conn_error_title),
getResources().getString(R.string.scut_invalid_uuid),
true);
return false;
if (uuidString != null && !uuidString.isEmpty()) {
try {
UUID.fromString(uuidString);
} catch (IllegalArgumentException ex) {
Dialog.displayDialog(ShortcutTrampoline.this,
getResources().getString(R.string.conn_error_title),
getResources().getString(R.string.scut_invalid_uuid),
true);
return false;
}
} else {
// UUID is null, so fallback to Name
if (nameString == null || nameString.isEmpty()) {
Dialog.displayDialog(ShortcutTrampoline.this,
getResources().getString(R.string.conn_error_title),
getResources().getString(R.string.scut_invalid_uuid),
true);
return false;
}
}
// Validate App ID (if provided)
@@ -255,24 +274,93 @@ public class ShortcutTrampoline extends Activity {
super.onCreate(savedInstanceState);
UiHelper.notifyNewRootView(this);
ComputerDatabaseManager dbManager = new ComputerDatabaseManager(this);
ComputerDetails _computer = null;
String appIdString = getIntent().getStringExtra(Game.EXTRA_APP_ID);
// PC arguments, both are optional, but at least one must be provided
uuidString = getIntent().getStringExtra(AppView.UUID_EXTRA);
String nameString = getIntent().getStringExtra(AppView.NAME_EXTRA);
if (validateInput(uuidString, appIdString)) {
if (appIdString != null && !appIdString.isEmpty()) {
app = new NvApp(getIntent().getStringExtra(Game.EXTRA_APP_NAME),
Integer.parseInt(appIdString),
getIntent().getBooleanExtra(Game.EXTRA_APP_HDR, false));
// App arguments, both are optional, but one must be provided in order to start an app
String appIdString = getIntent().getStringExtra(Game.EXTRA_APP_ID);
String appNameString = getIntent().getStringExtra(Game.EXTRA_APP_NAME);
if (!validateInput(uuidString, appIdString, nameString)) {
// Invalid input, so just return
return;
}
if (uuidString == null || uuidString.isEmpty()) {
// Use nameString to find the corresponding UUID
_computer = dbManager.getComputerByName(nameString);
if (_computer == null) {
Dialog.displayDialog(ShortcutTrampoline.this,
getResources().getString(R.string.conn_error_title),
getResources().getString(R.string.scut_pc_not_found),
true);
return;
}
// Bind to the computer manager service
bindService(new Intent(this, ComputerManagerService.class), serviceConnection,
Service.BIND_AUTO_CREATE);
uuidString = _computer.uuid;
blockingLoadSpinner = SpinnerDialog.displayDialog(this, getResources().getString(R.string.conn_establishing_title),
getResources().getString(R.string.applist_connect_msg), true);
// Set the AppView UUID intent, since it wasn't provided
setIntent(new Intent(getIntent()).putExtra(AppView.UUID_EXTRA, uuidString));
}
if (appIdString != null && !appIdString.isEmpty()) {
app = new NvApp(getIntent().getStringExtra(Game.EXTRA_APP_NAME),
Integer.parseInt(appIdString),
getIntent().getBooleanExtra(Game.EXTRA_APP_HDR, false));
}
else if (appNameString != null && !appNameString.isEmpty()) {
// Use appNameString to find the corresponding AppId
try {
int appId = -1;
String rawAppList = CacheHelper.readInputStreamToString(CacheHelper.openCacheFileForInput(getCacheDir(), "applist", uuidString));
if (rawAppList.isEmpty()) {
Dialog.displayDialog(ShortcutTrampoline.this,
getResources().getString(R.string.conn_error_title),
getResources().getString(R.string.scut_invalid_app_id),
true);
return;
}
List<NvApp> applist = NvHTTP.getAppListByReader(new StringReader(rawAppList));
for (NvApp _app : applist) {
if (_app.getAppName().equals(appNameString)) {
appId = _app.getAppId();
break;
}
}
if (appId < 0) {
Dialog.displayDialog(ShortcutTrampoline.this,
getResources().getString(R.string.conn_error_title),
getResources().getString(R.string.scut_invalid_app_id),
true);
return;
}
setIntent(new Intent(getIntent()).putExtra(Game.EXTRA_APP_ID, appId));
app = new NvApp(
appNameString,
appId,
getIntent().getBooleanExtra(Game.EXTRA_APP_HDR, false));
} catch (IOException | XmlPullParserException e) {
Dialog.displayDialog(ShortcutTrampoline.this,
getResources().getString(R.string.conn_error_title),
getResources().getString(R.string.scut_invalid_app_id),
true);
return;
}
}
// Bind to the computer manager service
bindService(new Intent(this, ComputerManagerService.class), serviceConnection,
Service.BIND_AUTO_CREATE);
blockingLoadSpinner = SpinnerDialog.displayDialog(this, getResources().getString(R.string.conn_establishing_title),
getResources().getString(R.string.applist_connect_msg), true);
}
@Override
@@ -26,51 +26,41 @@ public class AndroidAudioRenderer implements AudioRenderer {
}
private AudioTrack createAudioTrack(int channelConfig, int sampleRate, int bufferSize, boolean lowLatency) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
return new AudioTrack(AudioManager.STREAM_MUSIC,
sampleRate,
channelConfig,
AudioFormat.ENCODING_PCM_16BIT,
bufferSize,
AudioTrack.MODE_STREAM);
AudioAttributes.Builder attributesBuilder = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_GAME);
AudioFormat format = new AudioFormat.Builder()
.setEncoding(AudioFormat.ENCODING_PCM_16BIT)
.setSampleRate(sampleRate)
.setChannelMask(channelConfig)
.build();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
// Use FLAG_LOW_LATENCY on L through N
if (lowLatency) {
attributesBuilder.setFlags(AudioAttributes.FLAG_LOW_LATENCY);
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
AudioTrack.Builder trackBuilder = new AudioTrack.Builder()
.setAudioFormat(format)
.setAudioAttributes(attributesBuilder.build())
.setTransferMode(AudioTrack.MODE_STREAM)
.setBufferSizeInBytes(bufferSize);
// Use PERFORMANCE_MODE_LOW_LATENCY on O and later
if (lowLatency) {
trackBuilder.setPerformanceMode(AudioTrack.PERFORMANCE_MODE_LOW_LATENCY);
}
return trackBuilder.build();
}
else {
AudioAttributes.Builder attributesBuilder = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_GAME);
AudioFormat format = new AudioFormat.Builder()
.setEncoding(AudioFormat.ENCODING_PCM_16BIT)
.setSampleRate(sampleRate)
.setChannelMask(channelConfig)
.build();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
// Use FLAG_LOW_LATENCY on L through N
if (lowLatency) {
attributesBuilder.setFlags(AudioAttributes.FLAG_LOW_LATENCY);
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
AudioTrack.Builder trackBuilder = new AudioTrack.Builder()
.setAudioFormat(format)
.setAudioAttributes(attributesBuilder.build())
.setTransferMode(AudioTrack.MODE_STREAM)
.setBufferSizeInBytes(bufferSize);
// Use PERFORMANCE_MODE_LOW_LATENCY on O and later
if (lowLatency) {
trackBuilder.setPerformanceMode(AudioTrack.PERFORMANCE_MODE_LOW_LATENCY);
}
return trackBuilder.build();
}
else {
return new AudioTrack(attributesBuilder.build(),
format,
bufferSize,
AudioTrack.MODE_STREAM,
AudioManager.AUDIO_SESSION_ID_GENERATE);
}
return new AudioTrack(attributesBuilder.build(),
format,
bufferSize,
AudioTrack.MODE_STREAM,
AudioManager.AUDIO_SESSION_ID_GENERATE);
}
}
@@ -91,20 +81,10 @@ public class AndroidAudioRenderer implements AudioRenderer {
channelConfig = AudioFormat.CHANNEL_OUT_5POINT1;
break;
case 8:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// AudioFormat.CHANNEL_OUT_7POINT1_SURROUND isn't available until Android 6.0,
// yet the CHANNEL_OUT_SIDE_LEFT and CHANNEL_OUT_SIDE_RIGHT constants were added
// in 5.0, so just hardcode the constant so we can work on Lollipop.
channelConfig = 0x000018fc; // AudioFormat.CHANNEL_OUT_7POINT1_SURROUND
}
else {
// On KitKat and lower, creation of the AudioTrack will fail if we specify
// CHANNEL_OUT_SIDE_LEFT or CHANNEL_OUT_SIDE_RIGHT. That leaves us with
// the old CHANNEL_OUT_7POINT1 which uses left-of-center and right-of-center
// speakers instead of side-left and side-right. This non-standard layout
// is probably not what the user wants, but we don't really have a choice.
channelConfig = AudioFormat.CHANNEL_OUT_7POINT1;
}
// AudioFormat.CHANNEL_OUT_7POINT1_SURROUND isn't available until Android 6.0,
// yet the CHANNEL_OUT_SIDE_LEFT and CHANNEL_OUT_SIDE_RIGHT constants were added
// in 5.0, so just hardcode the constant so we can work on Lollipop.
channelConfig = 0x000018fc; // AudioFormat.CHANNEL_OUT_7POINT1_SURROUND
break;
default:
LimeLog.severe("Decoder returned unhandled channel count");
@@ -12,12 +12,12 @@ import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Calendar;
@@ -48,7 +48,7 @@ public class AndroidCryptoProvider implements LimelightCryptoProvider {
private final File keyFile;
private X509Certificate cert;
private RSAPrivateKey key;
private PrivateKey key;
private byte[] pemCertBytes;
private static final Object globalCryptoLock = new Object();
@@ -94,7 +94,7 @@ public class AndroidCryptoProvider implements LimelightCryptoProvider {
cert = (X509Certificate) certFactory.generateCertificate(new ByteArrayInputStream(certBytes));
pemCertBytes = certBytes;
KeyFactory keyFactory = KeyFactory.getInstance("RSA", bcProvider);
key = (RSAPrivateKey) keyFactory.generatePrivate(new PKCS8EncodedKeySpec(keyBytes));
key = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(keyBytes));
} catch (CertificateException e) {
// May happen if the cert is corrupt
LimeLog.warning("Corrupted certificate");
@@ -144,7 +144,7 @@ public class AndroidCryptoProvider implements LimelightCryptoProvider {
try {
ContentSigner sigGen = new JcaContentSignerBuilder("SHA256withRSA").setProvider(bcProvider).build(keyPair.getPrivate());
cert = new JcaX509CertificateConverter().setProvider(bcProvider).getCertificate(certBuilder.build(sigGen));
key = (RSAPrivateKey) keyPair.getPrivate();
key = keyPair.getPrivate();
} catch (Exception e) {
throw new RuntimeException(e);
}
@@ -215,7 +215,7 @@ public class AndroidCryptoProvider implements LimelightCryptoProvider {
}
}
public RSAPrivateKey getClientPrivateKey() {
public PrivateKey getClientPrivateKey() {
// Use a lock here to ensure only one guy will be generating or loading
// the certificate and key at a time
synchronized (globalCryptoLock) {
File diff suppressed because it is too large Load Diff
@@ -1,5 +1,6 @@
package com.limelight.binding.input;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.hardware.input.InputManager;
import android.os.Build;
@@ -34,6 +35,7 @@ public class KeyboardTranslator implements InputManager.InputDeviceListener {
public static final int VK_EQUALS = 61;
public static final int VK_ESCAPE = 27;
public static final int VK_F1 = 112;
public static final int VK_F13 = 0x7C;
public static final int VK_END = 35;
public static final int VK_HOME = 36;
public static final int VK_NUM_LOCK = 144;
@@ -104,18 +106,20 @@ public class KeyboardTranslator implements InputManager.InputDeviceListener {
}
}
public static boolean needsShift(int keycode) {
switch (keycode)
{
case KeyEvent.KEYCODE_AT:
case KeyEvent.KEYCODE_POUND:
case KeyEvent.KEYCODE_PLUS:
case KeyEvent.KEYCODE_STAR:
return true;
default:
return false;
public boolean hasNormalizedMapping(int keycode, int deviceId) {
if (deviceId >= 0) {
KeyboardMapping mapping = keyboardMappings.get(deviceId);
if (mapping != null) {
// Try to map this device-specific keycode onto a QWERTY layout.
// GFE assumes incoming keycodes are from a QWERTY keyboard.
int qwertyKeyCode = mapping.getQwertyKeyCodeForDeviceKeyCode(keycode);
if (qwertyKeyCode != KeyEvent.KEYCODE_UNKNOWN) {
return true;
}
}
}
return false;
}
/**
@@ -124,6 +128,7 @@ public class KeyboardTranslator implements InputManager.InputDeviceListener {
* @param deviceId InputDevice.getId() or -1 if unknown
* @return a GFE keycode for the given keycode
*/
@SuppressLint("InlinedApi")
public short translate(int keycode, int deviceId) {
int translated;
@@ -159,6 +164,10 @@ public class KeyboardTranslator implements InputManager.InputDeviceListener {
keycode <= KeyEvent.KEYCODE_F12) {
translated = (keycode - KeyEvent.KEYCODE_F1) + VK_F1;
}
else if (keycode >= KeyEvent.KEYCODE_F13 &&
keycode <= KeyEvent.KEYCODE_F24) {
translated = (keycode - KeyEvent.KEYCODE_F13) + VK_F13;
}
else {
switch (keycode) {
case KeyEvent.KEYCODE_ALT_LEFT:
@@ -230,6 +239,10 @@ public class KeyboardTranslator implements InputManager.InputDeviceListener {
translated = 0x5c;
break;
case KeyEvent.KEYCODE_MENU:
translated = 0x5d;
break;
case KeyEvent.KEYCODE_MINUS:
translated = 0xbd;
break;
@@ -343,20 +356,15 @@ public class KeyboardTranslator implements InputManager.InputDeviceListener {
translated = 0x6E;
break;
case KeyEvent.KEYCODE_AT:
translated = 2 + VK_0;
case KeyEvent.KEYCODE_PRINT:
translated = 0x2A;
break;
case KeyEvent.KEYCODE_POUND:
translated = 3 + VK_0;
break;
case KeyEvent.KEYCODE_STAR:
translated = 8 + VK_0;
case KeyEvent.KEYCODE_SCREENSHOT:
translated = 0x2C;
break;
default:
System.out.println("No key for "+keycode);
return 0;
}
}
@@ -15,8 +15,8 @@ import android.view.View;
// is unavailable on this system (ex: DeX, ChromeOS)
@TargetApi(Build.VERSION_CODES.O)
public class AndroidNativePointerCaptureProvider extends AndroidPointerIconCaptureProvider implements InputManager.InputDeviceListener {
private InputManager inputManager;
private View targetView;
private final InputManager inputManager;
private final View targetView;
public AndroidNativePointerCaptureProvider(Activity activity, View targetView) {
super(activity, targetView);
@@ -44,7 +44,10 @@ public class AndroidNativePointerCaptureProvider extends AndroidPointerIconCaptu
// with SOURCE_TOUCHSCREEN, SOURCE_KEYBOARD, and SOURCE_MOUSE.
// Upon enabling pointer capture, that device will switch to
// SOURCE_KEYBOARD and SOURCE_TOUCHPAD.
if (device.supportsSource(InputDevice.SOURCE_TOUCHSCREEN)) {
// Only skip on non ChromeOS devices cause the ChromeOS pointer else
// gets disabled removing relative mouse capabilities
// on Chromebooks with touchscreens
if (device.supportsSource(InputDevice.SOURCE_TOUCHSCREEN) && !targetView.getContext().getPackageManager().hasSystemFeature("org.chromium.arc.device_management")) {
continue;
}
@@ -59,8 +62,19 @@ public class AndroidNativePointerCaptureProvider extends AndroidPointerIconCaptu
}
@Override
public void enableCapture() {
super.enableCapture();
public void showCursor() {
super.showCursor();
// It is important to unregister the listener *before* releasing pointer capture,
// because releasing pointer capture can cause an onInputDeviceChanged() callback
// for devices with a touchpad (like a DS4 controller).
inputManager.unregisterInputDeviceListener(this);
targetView.releasePointerCapture();
}
@Override
public void hideCursor() {
super.hideCursor();
// Listen for device events to enable/disable capture
inputManager.registerInputDeviceListener(this, null);
@@ -71,16 +85,12 @@ public class AndroidNativePointerCaptureProvider extends AndroidPointerIconCaptu
}
}
@Override
public void disableCapture() {
super.disableCapture();
inputManager.unregisterInputDeviceListener(this);
targetView.releasePointerCapture();
}
@Override
public void onWindowFocusChanged(boolean focusActive) {
if (!focusActive || !isCapturing) {
// NB: We have to check cursor visibility here because Android pointer capture
// doesn't support capturing the cursor while it's visible. Enabling pointer
// capture implicitly hides the cursor.
if (!focusActive || !isCapturing || isCursorVisible) {
return;
}
@@ -4,14 +4,13 @@ import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.os.Build;
import android.view.MotionEvent;
import android.view.PointerIcon;
import android.view.View;
@TargetApi(Build.VERSION_CODES.N)
public class AndroidPointerIconCaptureProvider extends InputCaptureProvider {
private View targetView;
private Context context;
private final View targetView;
private final Context context;
public AndroidPointerIconCaptureProvider(Activity activity, View targetView) {
this.context = activity;
@@ -23,14 +22,14 @@ public class AndroidPointerIconCaptureProvider extends InputCaptureProvider {
}
@Override
public void enableCapture() {
super.enableCapture();
public void hideCursor() {
super.hideCursor();
targetView.setPointerIcon(PointerIcon.getSystemIcon(context, PointerIcon.TYPE_NULL));
}
@Override
public void disableCapture() {
super.disableCapture();
public void showCursor() {
super.showCursor();
targetView.setPointerIcon(null);
}
}
@@ -4,12 +4,15 @@ import android.view.MotionEvent;
public abstract class InputCaptureProvider {
protected boolean isCapturing;
protected boolean isCursorVisible;
public void enableCapture() {
isCapturing = true;
hideCursor();
}
public void disableCapture() {
isCapturing = false;
showCursor();
}
public void destroy() {}
@@ -22,6 +25,14 @@ public abstract class InputCaptureProvider {
return isCapturing;
}
public void showCursor() {
isCursorVisible = true;
}
public void hideCursor() {
isCursorVisible = false;
}
public boolean eventHasRelativeMouseAxes(MotionEvent event) {
return false;
}
@@ -22,7 +22,7 @@ public class ShieldCaptureProvider extends InputCaptureProvider {
private static int AXIS_RELATIVE_X;
private static int AXIS_RELATIVE_Y;
private Context context;
private final Context context;
static {
try {
@@ -62,14 +62,14 @@ public class ShieldCaptureProvider extends InputCaptureProvider {
}
@Override
public void enableCapture() {
super.enableCapture();
public void hideCursor() {
super.hideCursor();
setCursorVisibility(false);
}
@Override
public void disableCapture() {
super.disableCapture();
public void showCursor() {
super.showCursor();
setCursorVisibility(true);
}
@@ -8,10 +8,12 @@ public abstract class AbstractController {
private UsbDriverListener listener;
protected short buttonFlags;
protected int buttonFlags, supportedButtonFlags;
protected float leftTrigger, rightTrigger;
protected float rightStickX, rightStickY;
protected float leftStickX, leftStickY;
protected short capabilities;
protected byte type;
public int getControllerId() {
return deviceId;
@@ -25,6 +27,18 @@ public abstract class AbstractController {
return productId;
}
public int getSupportedButtonFlags() {
return supportedButtonFlags;
}
public short getCapabilities() {
return capabilities;
}
public byte getType() {
return type;
}
protected void setButtonFlag(int buttonFlag, int data) {
if (data != 0) {
buttonFlags |= buttonFlag;
@@ -51,6 +65,8 @@ public abstract class AbstractController {
public abstract void rumble(short lowFreqMotor, short highFreqMotor);
public abstract void rumbleTriggers(short leftTrigger, short rightTrigger);
protected void notifyDeviceRemoved() {
listener.deviceRemoved(this);
}
@@ -8,6 +8,8 @@ import android.hardware.usb.UsbInterface;
import android.os.SystemClock;
import com.limelight.LimeLog;
import com.limelight.nvstream.input.ControllerPacket;
import com.limelight.nvstream.jni.MoonBridge;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
@@ -25,6 +27,14 @@ public abstract class AbstractXboxController extends AbstractController {
super(deviceId, listener, device.getVendorId(), device.getProductId());
this.device = device;
this.connection = connection;
this.type = MoonBridge.LI_CTYPE_XBOX;
this.capabilities = MoonBridge.LI_CCAP_ANALOG_TRIGGERS | MoonBridge.LI_CCAP_RUMBLE;
this.buttonFlags =
ControllerPacket.A_FLAG | ControllerPacket.B_FLAG | ControllerPacket.X_FLAG | ControllerPacket.Y_FLAG |
ControllerPacket.UP_FLAG | ControllerPacket.DOWN_FLAG | ControllerPacket.LEFT_FLAG | ControllerPacket.RIGHT_FLAG |
ControllerPacket.LB_FLAG | ControllerPacket.RB_FLAG |
ControllerPacket.LS_CLK_FLAG | ControllerPacket.RS_CLK_FLAG |
ControllerPacket.BACK_FLAG | ControllerPacket.PLAY_FLAG | ControllerPacket.SPECIAL_BUTTON_FLAG;
}
private Thread createInputThread() {
@@ -1,7 +1,7 @@
package com.limelight.binding.input.driver;
public interface UsbDriverListener {
void reportControllerState(int controllerId, short buttonFlags,
void reportControllerState(int controllerId, int buttonFlags,
float leftStickX, float leftStickY,
float rightStickX, float rightStickY,
float leftTrigger, float rightTrigger);
@@ -1,5 +1,6 @@
package com.limelight.binding.input.driver;
import android.annotation.SuppressLint;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
@@ -20,6 +21,7 @@ import com.limelight.LimeLog;
import com.limelight.R;
import com.limelight.preferences.PreferenceConfiguration;
import java.io.File;
import java.util.ArrayList;
public class UsbDriverService extends Service implements UsbDriverListener {
@@ -41,7 +43,8 @@ public class UsbDriverService extends Service implements UsbDriverListener {
private int nextDeviceId;
@Override
public void reportControllerState(int controllerId, short buttonFlags, float leftStickX, float leftStickY, float rightStickX, float rightStickY, float leftTrigger, float rightTrigger) {
public void reportControllerState(int controllerId, int buttonFlags, float leftStickX, float leftStickY,
float rightStickX, float rightStickY, float leftTrigger, float rightTrigger) {
// Call through to the client's listener
if (listener != null) {
listener.reportControllerState(controllerId, buttonFlags, leftStickX, leftStickY, rightStickX, rightStickY, leftTrigger, rightTrigger);
@@ -157,7 +160,12 @@ public class UsbDriverService extends Service implements UsbDriverListener {
// just returning a false result or returning 0 enumerated devices,
// they throw an undocumented SecurityException from this call, crashing
// the whole app. :(
usbManager.requestPermission(device, PendingIntent.getBroadcast(UsbDriverService.this, 0, new Intent(ACTION_USB_PERMISSION), intentFlags));
// Use an explicit intent to activate our unexported broadcast receiver, as required on Android 14+
Intent i = new Intent(ACTION_USB_PERMISSION);
i.setPackage(getPackageName());
usbManager.requestPermission(device, PendingIntent.getBroadcast(UsbDriverService.this, 0, i, intentFlags));
} catch (SecurityException e) {
Toast.makeText(this, this.getText(R.string.error_usb_prohibited), Toast.LENGTH_LONG).show();
if (stateListener != null) {
@@ -183,6 +191,9 @@ public class UsbDriverService extends Service implements UsbDriverListener {
else if (Xbox360Controller.canClaimDevice(device)) {
controller = new Xbox360Controller(device, connection, nextDeviceId++, this);
}
else if (Xbox360WirelessDongle.canClaimDevice(device)) {
controller = new Xbox360WirelessDongle(device, connection, nextDeviceId++, this);
}
else {
// Unreachable
return;
@@ -200,28 +211,22 @@ public class UsbDriverService extends Service implements UsbDriverListener {
}
public static boolean isRecognizedInputDevice(UsbDevice device) {
// On KitKat and later, we can determine if this VID and PID combo
// matches an existing input device and defer to the built-in controller
// support in that case. Prior to KitKat, we'll always return true to be safe.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
for (int id : InputDevice.getDeviceIds()) {
InputDevice inputDev = InputDevice.getDevice(id);
if (inputDev == null) {
// Device was removed while looping
continue;
}
if (inputDev.getVendorId() == device.getVendorId() &&
inputDev.getProductId() == device.getProductId()) {
return true;
}
// Determine if this VID and PID combo matches an existing input device
// and defer to the built-in controller support in that case.
for (int id : InputDevice.getDeviceIds()) {
InputDevice inputDev = InputDevice.getDevice(id);
if (inputDev == null) {
// Device was removed while looping
continue;
}
return false;
}
else {
return true;
if (inputDev.getVendorId() == device.getVendorId() &&
inputDev.getProductId() == device.getProductId()) {
return true;
}
}
return false;
}
public static boolean kernelSupportsXboxOne() {
@@ -248,13 +253,37 @@ public class UsbDriverService extends Service implements UsbDriverListener {
}
}
public static boolean shouldClaimDevice(UsbDevice device, boolean claimAllAvailable) {
return ((!kernelSupportsXboxOne() || !isRecognizedInputDevice(device) || claimAllAvailable) && XboxOneController.canClaimDevice(device)) ||
((!isRecognizedInputDevice(device) || claimAllAvailable) && Xbox360Controller.canClaimDevice(device));
public static boolean kernelSupportsXbox360W() {
// Check if this kernel is 4.2+ to see if the xpad driver sets Xbox 360 wireless LEDs
// https://github.com/torvalds/linux/commit/75b7f05d2798ee3a1cc5bbdd54acd0e318a80396
String kernelVersion = System.getProperty("os.version");
if (kernelVersion != null) {
if (kernelVersion.startsWith("2.") || kernelVersion.startsWith("3.") ||
kernelVersion.startsWith("4.0.") || kernelVersion.startsWith("4.1.")) {
// Even if LED devices are present, the driver won't set the initial LED state.
return false;
}
}
// We know we have a kernel that should set Xbox 360 wireless LEDs, but we still don't
// know if CONFIG_JOYSTICK_XPAD_LEDS was enabled during the kernel build. Unfortunately
// it's not possible to detect this reliably due to Android's app sandboxing. Reading
// /proc/config.gz and enumerating /sys/class/leds are both blocked by SELinux on any
// relatively modern device. We will assume that CONFIG_JOYSTICK_XPAD_LEDS=y on these
// kernels and users can override by using the settings option to claim all devices.
return true;
}
public static boolean shouldClaimDevice(UsbDevice device, boolean claimAllAvailable) {
return ((!kernelSupportsXboxOne() || !isRecognizedInputDevice(device) || claimAllAvailable) && XboxOneController.canClaimDevice(device)) ||
((!isRecognizedInputDevice(device) || claimAllAvailable) && Xbox360Controller.canClaimDevice(device)) ||
// We must not call isRecognizedInputDevice() because wireless controllers don't share the same product ID as the dongle
((!kernelSupportsXbox360W() || claimAllAvailable) && Xbox360WirelessDongle.canClaimDevice(device));
}
@SuppressLint("UnspecifiedRegisterReceiverFlag")
private void start() {
if (started) {
if (started || usbManager == null) {
return;
}
@@ -39,6 +39,7 @@ public class Xbox360Controller extends AbstractXboxController {
0x20d6, // PowerA
0x24c6, // PowerA
0x2f24, // GameSir
0x2dc8, // 8BitDo
};
public static boolean canClaimDevice(UsbDevice device) {
@@ -156,4 +157,9 @@ public class Xbox360Controller extends AbstractXboxController {
LimeLog.warning("Rumble transfer failed: "+res);
}
}
@Override
public void rumbleTriggers(short leftTrigger, short rightTrigger) {
// Trigger motors not present on Xbox 360 controllers
}
}
@@ -0,0 +1,148 @@
package com.limelight.binding.input.driver;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.os.Build;
import android.view.InputDevice;
import com.limelight.LimeLog;
import java.nio.ByteBuffer;
public class Xbox360WirelessDongle extends AbstractController {
private UsbDevice device;
private UsbDeviceConnection connection;
private static final int XB360W_IFACE_SUBCLASS = 93;
private static final int XB360W_IFACE_PROTOCOL = 129; // Wireless only
private static final int[] SUPPORTED_VENDORS = {
0x045e, // Microsoft
};
public static boolean canClaimDevice(UsbDevice device) {
for (int supportedVid : SUPPORTED_VENDORS) {
if (device.getVendorId() == supportedVid &&
device.getInterfaceCount() >= 1 &&
device.getInterface(0).getInterfaceClass() == UsbConstants.USB_CLASS_VENDOR_SPEC &&
device.getInterface(0).getInterfaceSubclass() == XB360W_IFACE_SUBCLASS &&
device.getInterface(0).getInterfaceProtocol() == XB360W_IFACE_PROTOCOL) {
return true;
}
}
return false;
}
public Xbox360WirelessDongle(UsbDevice device, UsbDeviceConnection connection, int deviceId, UsbDriverListener listener) {
super(deviceId, listener, device.getVendorId(), device.getProductId());
this.device = device;
this.connection = connection;
}
private void sendLedCommandToEndpoint(UsbEndpoint endpoint, int controllerIndex) {
byte[] commandBuffer = {
0x00,
0x00,
0x08,
(byte) (0x40 + (2 + (controllerIndex % 4))),
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00};
int res = connection.bulkTransfer(endpoint, commandBuffer, commandBuffer.length, 3000);
if (res != commandBuffer.length) {
LimeLog.warning("LED set transfer failed: "+res);
}
}
private void sendLedCommandToInterface(UsbInterface iface, int controllerIndex) {
// Claim this interface to kick xpad off it (temporarily)
if (!connection.claimInterface(iface, true)) {
LimeLog.warning("Failed to claim interface: "+iface.getId());
return;
}
// Find the out endpoint for this interface
for (int i = 0; i < iface.getEndpointCount(); i++) {
UsbEndpoint endpt = iface.getEndpoint(i);
if (endpt.getDirection() == UsbConstants.USB_DIR_OUT) {
// Send the LED command
sendLedCommandToEndpoint(endpt, controllerIndex);
break;
}
}
// Release the interface to allow xpad to take over again
connection.releaseInterface(iface);
}
@Override
public boolean start() {
int controllerIndex = 0;
// On Android, there is a controller number associated with input devices.
// We can use this to approximate the likely controller number. This won't
// be completely accurate because there's no guarantee the order of interfaces
// matches the order that devices were enumerated by xpad, but it's probably
// better than nothing.
for (int id : InputDevice.getDeviceIds()) {
InputDevice inputDev = InputDevice.getDevice(id);
if (inputDev == null) {
// Device was removed while looping
continue;
}
// Newer xpad versions use a special product ID (0x02a1) for controllers
// rather than copying the product ID of the dongle itself.
if (inputDev.getVendorId() == device.getVendorId() &&
(inputDev.getProductId() == device.getProductId() ||
inputDev.getProductId() == 0x02a1) &&
inputDev.getControllerNumber() > 0) {
controllerIndex = inputDev.getControllerNumber() - 1;
break;
}
}
// Send LED commands on the out endpoint of each interface. There is one interface
// corresponding to each possible attached controller.
for (int i = 0; i < device.getInterfaceCount(); i++) {
UsbInterface iface = device.getInterface(i);
// Skip the non-input interfaces
if (iface.getInterfaceClass() != UsbConstants.USB_CLASS_VENDOR_SPEC ||
iface.getInterfaceSubclass() != XB360W_IFACE_SUBCLASS ||
iface.getInterfaceProtocol() != XB360W_IFACE_PROTOCOL) {
continue;
}
sendLedCommandToInterface(iface, controllerIndex++);
}
// "Fail" to give control back to the kernel driver
return false;
}
@Override
public void stop() {
// Nothing to do
}
@Override
public void rumble(short lowFreqMotor, short highFreqMotor) {
// Unreachable.
}
@Override
public void rumbleTriggers(short leftTrigger, short rightTrigger) {
// Unreachable.
}
}
@@ -6,6 +6,7 @@ import android.hardware.usb.UsbDeviceConnection;
import com.limelight.LimeLog;
import com.limelight.nvstream.input.ControllerPacket;
import com.limelight.nvstream.jni.MoonBridge;
import java.nio.ByteBuffer;
import java.util.Arrays;
@@ -24,10 +25,12 @@ public class XboxOneController extends AbstractXboxController {
0x20d6, // PowerA
0x24c6, // PowerA
0x2e24, // Hyperkin
0x2dc8, // 8BitDo
};
private static final byte[] FW2015_INIT = {0x05, 0x20, 0x00, 0x01, 0x00};
private static final byte[] ONE_S_INIT = {0x05, 0x20, 0x00, 0x0f, 0x06};
private static final byte[] SERIES_S_INIT = {0x05, 0x20, 0x00, 0x0f, 0x06};
private static final byte[] HORI_INIT = {0x01, 0x20, 0x00, 0x09, 0x00, 0x04, 0x20, 0x3a,
0x00, 0x00, 0x00, (byte)0x80, 0x00};
private static final byte[] PDP_INIT1 = {0x0a, 0x20, 0x00, 0x03, 0x00, 0x01, 0x14};
@@ -42,7 +45,11 @@ public class XboxOneController extends AbstractXboxController {
new InitPacket(0x0f0d, 0x0067, HORI_INIT),
new InitPacket(0x0000, 0x0000, FW2015_INIT),
new InitPacket(0x045e, 0x02ea, ONE_S_INIT),
new InitPacket(0x045e, 0x02fe, ONE_S_INIT),
new InitPacket(0x045e, 0x0b00, ONE_S_INIT),
new InitPacket(0x045e, 0x0b05, SERIES_S_INIT),
new InitPacket(0x045e, 0x0b12, SERIES_S_INIT),
new InitPacket(0x045e, 0x0b13, SERIES_S_INIT),
new InitPacket(0x0e6f, 0x0000, PDP_INIT1),
new InitPacket(0x0e6f, 0x0000, PDP_INIT2),
new InitPacket(0x24c6, 0x541a, RUMBLE_INIT1),
@@ -54,9 +61,14 @@ public class XboxOneController extends AbstractXboxController {
};
private byte seqNum = 0;
private short lowFreqMotor = 0;
private short highFreqMotor = 0;
private short leftTriggerMotor = 0;
private short rightTriggerMotor = 0;
public XboxOneController(UsbDevice device, UsbDeviceConnection connection, int deviceId, UsbDriverListener listener) {
super(device, connection, deviceId, listener);
capabilities |= MoonBridge.LI_CCAP_TRIGGER_RUMBLE;
}
private void processButtons(ByteBuffer buffer) {
@@ -176,12 +188,14 @@ public class XboxOneController extends AbstractXboxController {
return true;
}
@Override
public void rumble(short lowFreqMotor, short highFreqMotor) {
private void sendRumblePacket() {
byte[] data = {
0x09, 0x00, seqNum++, 0x09, 0x00,
0x0F, 0x00, 0x00,
(byte)(lowFreqMotor >> 9), (byte)(highFreqMotor >> 9),
0x0F,
(byte)(leftTriggerMotor >> 9),
(byte)(rightTriggerMotor >> 9),
(byte)(lowFreqMotor >> 9),
(byte)(highFreqMotor >> 9),
(byte)0xFF, 0x00, (byte)0xFF
};
int res = connection.bulkTransfer(outEndpt, data, data.length, 100);
@@ -190,6 +204,20 @@ public class XboxOneController extends AbstractXboxController {
}
}
@Override
public void rumble(short lowFreqMotor, short highFreqMotor) {
this.lowFreqMotor = lowFreqMotor;
this.highFreqMotor = highFreqMotor;
sendRumblePacket();
}
@Override
public void rumbleTriggers(short leftTrigger, short rightTrigger) {
this.leftTriggerMotor = leftTrigger;
this.rightTriggerMotor = rightTrigger;
sendRumblePacket();
}
private static class InitPacket {
final int vendorId;
final int productId;
@@ -9,6 +9,7 @@ public interface EvdevListener {
void mouseMove(int deltaX, int deltaY);
void mouseButtonEvent(int buttonId, boolean down);
void mouseScroll(byte amount);
void mouseVScroll(byte amount);
void mouseHScroll(byte amount);
void keyboardEvent(boolean buttonDown, short keyCode);
}
@@ -185,6 +185,10 @@ public class VirtualControllerConfigurationLoader {
private static final int START_BACK_WIDTH = 12;
private static final int START_BACK_HEIGHT = 7;
// Make the Guide Menu be in the center of START and BACK menu
private static final int GUIDE_X = START_X-BACK_X;
private static final int GUIDE_Y = START_BACK_Y;
public static void createDefaultLayout(final VirtualController controller, final Context context) {
DisplayMetrics screen = context.getResources().getDisplayMetrics();
@@ -333,6 +337,16 @@ public class VirtualControllerConfigurationLoader {
);
}
if(config.showGuideButton){
controller.addElement(createDigitalButton(VirtualControllerElement.EID_GDB,
ControllerPacket.SPECIAL_BUTTON_FLAG, 0, 1, "GUIDE", -1, controller, context),
screenScale(GUIDE_X, height)+ rightDisplacement,
screenScale(GUIDE_Y, height),
screenScale(START_BACK_WIDTH, height),
screenScale(START_BACK_HEIGHT, height)
);
}
controller.setOpacity(config.oscOpacity);
}
@@ -35,6 +35,7 @@ public abstract class VirtualControllerElement extends View {
public static final int EID_RS = 13;
public static final int EID_LSB = 14;
public static final int EID_RSB = 15;
public static final int EID_GDB = 16;
protected VirtualController virtualController;
protected final int elementId;
File diff suppressed because it is too large Load Diff
@@ -356,7 +356,14 @@ public class MediaCodecHelper {
if (configInfo.reqGlEsVersion >= 0x30000) {
LimeLog.info("Added omx.nvidia/c2.nvidia to reference frame invalidation support list");
refFrameInvalidationAvcPrefixes.add("omx.nvidia");
refFrameInvalidationHevcPrefixes.add("omx.nvidia");
// Exclude HEVC RFI on Pixel C and Tegra devices prior to Android 11. Misbehaving RFI
// on these devices can cause hundreds of milliseconds of latency, so it's not worth
// using it unless we're absolutely sure that it will not cause increased latency.
if (!Build.DEVICE.equalsIgnoreCase("dragon") && Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
refFrameInvalidationHevcPrefixes.add("omx.nvidia");
}
refFrameInvalidationAvcPrefixes.add("c2.nvidia"); // Unconfirmed
refFrameInvalidationHevcPrefixes.add("c2.nvidia"); // Unconfirmed
@@ -522,6 +529,17 @@ public class MediaCodecHelper {
setNewOption = true;
}
if (tryNumber < 3) {
if (MediaCodecHelper.decoderSupportsMaxOperatingRate(decoderInfo.getName())) {
videoFormat.setInteger(MediaFormat.KEY_OPERATING_RATE, Short.MAX_VALUE);
setNewOption = true;
}
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
videoFormat.setInteger(MediaFormat.KEY_PRIORITY, 0);
setNewOption = true;
}
}
// MediaCodec supports vendor-defined format keys using the "vendor.<extension name>.<parameter name>" syntax.
// These allow access to functionality that is not exposed through documented MediaFormat.KEY_* values.
// https://cs.android.com/android/platform/superproject/+/master:hardware/qcom/sdm845/media/mm-video-v4l2/vidc/common/inc/vidc_vendor_extensions.h;l=67
@@ -538,17 +556,17 @@ public class MediaCodecHelper {
// https://cs.android.com/android/_/android/platform/hardware/qcom/sm8150/media/+/0621ceb1c1b19564999db8293574a0e12952ff6c
//
// We will first try both, then try vendor.qti-ext-dec-low-latency.enable alone if that fails
if (tryNumber < 3) {
if (tryNumber < 4) {
videoFormat.setInteger("vendor.qti-ext-dec-picture-order.enable", 1);
setNewOption = true;
}
if (tryNumber < 4) {
if (tryNumber < 5) {
videoFormat.setInteger("vendor.qti-ext-dec-low-latency.enable", 1);
setNewOption = true;
}
}
else if (isDecoderInList(kirinDecoderPrefixes, decoderInfo.getName())) {
if (tryNumber < 3) {
if (tryNumber < 4) {
// Kirin low latency options
// https://developer.huawei.com/consumer/cn/forum/topic/0202325564295980115
videoFormat.setInteger("vendor.hisi-ext-low-latency-video-dec.video-scene-for-low-latency-req", 1);
@@ -557,14 +575,14 @@ public class MediaCodecHelper {
}
}
else if (isDecoderInList(exynosDecoderPrefixes, decoderInfo.getName())) {
if (tryNumber < 3) {
if (tryNumber < 4) {
// Exynos low latency option for H.264 decoder
videoFormat.setInteger("vendor.rtc-ext-dec-low-latency.enable", 1);
setNewOption = true;
}
}
else if (isDecoderInList(amlogicDecoderPrefixes, decoderInfo.getName())) {
if (tryNumber < 3) {
if (tryNumber < 4) {
// Amlogic low latency vendor extension
// https://github.com/codewalkerster/android_vendor_amlogic_common_prebuilt_libstagefrighthw/commit/41fefc4e035c476d58491324a5fe7666bfc2989e
videoFormat.setInteger("vendor.low-latency.enable", 1);
@@ -573,55 +591,44 @@ public class MediaCodecHelper {
}
}
// FIXME: We should probably integrate this into the try system
if (MediaCodecHelper.decoderSupportsMaxOperatingRate(decoderInfo.getName())) {
videoFormat.setInteger(MediaFormat.KEY_OPERATING_RATE, Short.MAX_VALUE);
}
return setNewOption;
}
public static boolean decoderSupportsFusedIdrFrame(MediaCodecInfo decoderInfo, String mimeType) {
// If adaptive playback is supported, we can submit new CSD together with a keyframe
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
try {
if (decoderInfo.getCapabilitiesForType(mimeType).
isFeatureSupported(CodecCapabilities.FEATURE_AdaptivePlayback))
{
LimeLog.info("Decoder supports fused IDR frames (FEATURE_AdaptivePlayback)");
return true;
}
} catch (Exception e) {
// Tolerate buggy codecs
e.printStackTrace();
try {
if (decoderInfo.getCapabilitiesForType(mimeType).
isFeatureSupported(CodecCapabilities.FEATURE_AdaptivePlayback)) {
LimeLog.info("Decoder supports fused IDR frames (FEATURE_AdaptivePlayback)");
return true;
}
} catch (Exception e) {
// Tolerate buggy codecs
e.printStackTrace();
}
return false;
}
public static boolean decoderSupportsAdaptivePlayback(MediaCodecInfo decoderInfo, String mimeType) {
// Possibly enable adaptive playback on KitKat and above
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (isDecoderInList(blacklistedAdaptivePlaybackPrefixes, decoderInfo.getName())) {
LimeLog.info("Decoder blacklisted for adaptive playback");
return false;
}
try {
if (decoderInfo.getCapabilitiesForType(mimeType).
isFeatureSupported(CodecCapabilities.FEATURE_AdaptivePlayback))
{
// This will make getCapabilities() return that adaptive playback is supported
LimeLog.info("Adaptive playback supported (FEATURE_AdaptivePlayback)");
return true;
}
} catch (Exception e) {
// Tolerate buggy codecs
e.printStackTrace();
}
if (isDecoderInList(blacklistedAdaptivePlaybackPrefixes, decoderInfo.getName())) {
LimeLog.info("Decoder blacklisted for adaptive playback");
return false;
}
try {
if (decoderInfo.getCapabilitiesForType(mimeType).
isFeatureSupported(CodecCapabilities.FEATURE_AdaptivePlayback))
{
// This will make getCapabilities() return that adaptive playback is supported
LimeLog.info("Adaptive playback supported (FEATURE_AdaptivePlayback)");
return true;
}
} catch (Exception e) {
// Tolerate buggy codecs
e.printStackTrace();
}
return false;
}
@@ -684,14 +691,18 @@ public class MediaCodecHelper {
return isDecoderInList(refFrameInvalidationHevcPrefixes, decoderInfo.getName());
}
public static boolean decoderIsWhitelistedForHevc(MediaCodecInfo decoderInfo) {
// Google didn't have official support for HEVC (or more importantly, a CTS test) until
// Lollipop. I've seen some MediaTek devices on 4.4 crash when attempting to use HEVC,
// so I'm restricting HEVC usage to Lollipop and higher.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
return false;
public static boolean decoderSupportsRefFrameInvalidationAv1(MediaCodecInfo decoderInfo) {
// We'll use the same heuristics as HEVC for now
if (decoderSupportsAndroidRLowLatency(decoderInfo, "video/av01") ||
decoderSupportsKnownVendorLowLatencyOption(decoderInfo.getName())) {
LimeLog.info("Enabling AV1 RFI based on low latency option support");
return true;
}
return false;
}
public static boolean decoderIsWhitelistedForHevc(MediaCodecInfo decoderInfo) {
//
// Software decoders are terrible and we never want to use them.
// We want to catch decoders like:
@@ -729,22 +740,41 @@ public class MediaCodecHelper {
// Otherwise, we use our list of known working HEVC decoders
return isDecoderInList(whitelistedHevcDecoders, decoderInfo.getName());
}
public static boolean isDecoderWhitelistedForAv1(MediaCodecInfo decoderInfo) {
// Google didn't have official support for AV1 (or more importantly, a CTS test) until
// Android 10, so don't use any decoder before then.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
return false;
}
//
// Software decoders are terrible and we never want to use them.
// We want to catch decoders like:
// OMX.qcom.video.decoder.hevcswvdec
// OMX.SEC.hevc.sw.dec
//
if (decoderInfo.getName().contains("sw")) {
LimeLog.info("Disallowing AV1 on software decoder: " + decoderInfo.getName());
return false;
}
else if (!decoderInfo.isHardwareAccelerated() || decoderInfo.isSoftwareOnly()) {
LimeLog.info("Disallowing AV1 on software decoder: " + decoderInfo.getName());
return false;
}
// TODO: Test some AV1 decoders
return false;
}
@SuppressWarnings("deprecation")
@SuppressLint("NewApi")
private static LinkedList<MediaCodecInfo> getMediaCodecList() {
LinkedList<MediaCodecInfo> infoList = new LinkedList<>();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
Collections.addAll(infoList, mcl.getCodecInfos());
}
else {
for (int i = 0; i < MediaCodecList.getCodecCount(); i++) {
infoList.add(MediaCodecList.getCodecInfoAt(i));
}
}
MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
Collections.addAll(infoList, mcl.getCodecInfos());
return infoList;
}
@@ -11,6 +11,10 @@ class VideoStats {
int totalFramesRendered;
int frameLossEvents;
int framesLost;
char minHostProcessingLatency;
char maxHostProcessingLatency;
int totalHostProcessingLatency;
int framesWithHostProcessingLatency;
long measurementStartTimestamp;
void add(VideoStats other) {
@@ -22,6 +26,15 @@ class VideoStats {
this.frameLossEvents += other.frameLossEvents;
this.framesLost += other.framesLost;
if (this.minHostProcessingLatency == 0) {
this.minHostProcessingLatency = other.minHostProcessingLatency;
} else {
this.minHostProcessingLatency = (char) Math.min(this.minHostProcessingLatency, other.minHostProcessingLatency);
}
this.maxHostProcessingLatency = (char) Math.max(this.maxHostProcessingLatency, other.maxHostProcessingLatency);
this.totalHostProcessingLatency += other.totalHostProcessingLatency;
this.framesWithHostProcessingLatency += other.framesWithHostProcessingLatency;
if (this.measurementStartTimestamp == 0) {
this.measurementStartTimestamp = other.measurementStartTimestamp;
}
@@ -37,6 +50,10 @@ class VideoStats {
this.totalFramesRendered = other.totalFramesRendered;
this.frameLossEvents = other.frameLossEvents;
this.framesLost = other.framesLost;
this.minHostProcessingLatency = other.minHostProcessingLatency;
this.maxHostProcessingLatency = other.maxHostProcessingLatency;
this.totalHostProcessingLatency = other.totalHostProcessingLatency;
this.framesWithHostProcessingLatency = other.framesWithHostProcessingLatency;
this.measurementStartTimestamp = other.measurementStartTimestamp;
}
@@ -48,6 +65,10 @@ class VideoStats {
this.totalFramesRendered = 0;
this.frameLossEvents = 0;
this.framesLost = 0;
this.minHostProcessingLatency = 0;
this.maxHostProcessingLatency = 0;
this.totalHostProcessingLatency = 0;
this.framesWithHostProcessingLatency = 0;
this.measurementStartTimestamp = 0;
}
@@ -9,6 +9,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import com.limelight.LimeLog;
import com.limelight.nvstream.http.ComputerDetails;
import com.limelight.nvstream.http.NvHTTP;
@@ -18,18 +19,28 @@ import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import org.json.JSONException;
import org.json.JSONObject;
public class ComputerDatabaseManager {
private static final String COMPUTER_DB_NAME = "computers3.db";
private static final String COMPUTER_DB_NAME = "computers4.db";
private static final String COMPUTER_TABLE_NAME = "Computers";
private static final String COMPUTER_UUID_COLUMN_NAME = "UUID";
private static final String COMPUTER_NAME_COLUMN_NAME = "ComputerName";
private static final String ADDRESSES_COLUMN_NAME = "Addresses";
private interface AddressFields {
String LOCAL = "local";
String REMOTE = "remote";
String MANUAL = "manual";
String IPv6 = "ipv6";
String ADDRESS = "address";
String PORT = "port";
}
private static final String MAC_ADDRESS_COLUMN_NAME = "MacAddress";
private static final String SERVER_CERT_COLUMN_NAME = "ServerCert";
private static final char ADDRESS_DELIMITER = ';';
private static final char PORT_DELIMITER = '_';
private SQLiteDatabase computerDb;
public ComputerDatabaseManager(Context c) {
@@ -64,24 +75,54 @@ public class ComputerDatabaseManager {
for (ComputerDetails computer : oldComputers) {
updateComputer(computer);
}
oldComputers = LegacyDatabaseReader3.migrateAllComputers(c);
for (ComputerDetails computer : oldComputers) {
updateComputer(computer);
}
}
public void deleteComputer(ComputerDetails details) {
computerDb.delete(COMPUTER_TABLE_NAME, COMPUTER_UUID_COLUMN_NAME+"=?", new String[]{details.uuid});
}
public static JSONObject tupleToJson(ComputerDetails.AddressTuple tuple) throws JSONException {
if (tuple == null) {
return null;
}
JSONObject json = new JSONObject();
json.put(AddressFields.ADDRESS, tuple.address);
json.put(AddressFields.PORT, tuple.port);
return json;
}
public static ComputerDetails.AddressTuple tupleFromJson(JSONObject json, String name) throws JSONException {
if (!json.has(name)) {
return null;
}
JSONObject address = json.getJSONObject(name);
return new ComputerDetails.AddressTuple(
address.getString(AddressFields.ADDRESS), address.getInt(AddressFields.PORT));
}
public boolean updateComputer(ComputerDetails details) {
ContentValues values = new ContentValues();
values.put(COMPUTER_UUID_COLUMN_NAME, details.uuid);
values.put(COMPUTER_NAME_COLUMN_NAME, details.name);
StringBuilder addresses = new StringBuilder();
addresses.append(details.localAddress != null ? splitTupleToAddress(details.localAddress) : "");
addresses.append(ADDRESS_DELIMITER).append(details.remoteAddress != null ? splitTupleToAddress(details.remoteAddress) : "");
addresses.append(ADDRESS_DELIMITER).append(details.manualAddress != null ? splitTupleToAddress(details.manualAddress) : "");
addresses.append(ADDRESS_DELIMITER).append(details.ipv6Address != null ? splitTupleToAddress(details.ipv6Address) : "");
try {
JSONObject addresses = new JSONObject();
addresses.put(AddressFields.LOCAL, tupleToJson(details.localAddress));
addresses.put(AddressFields.REMOTE, tupleToJson(details.remoteAddress));
addresses.put(AddressFields.MANUAL, tupleToJson(details.manualAddress));
addresses.put(AddressFields.IPv6, tupleToJson(details.ipv6Address));
values.put(ADDRESSES_COLUMN_NAME, addresses.toString());
} catch (JSONException e) {
throw new RuntimeException(e);
}
values.put(ADDRESSES_COLUMN_NAME, addresses.toString());
values.put(MAC_ADDRESS_COLUMN_NAME, details.macAddress);
try {
if (details.serverCert != null) {
@@ -97,44 +138,20 @@ public class ComputerDatabaseManager {
return -1 != computerDb.insertWithOnConflict(COMPUTER_TABLE_NAME, null, values, SQLiteDatabase.CONFLICT_REPLACE);
}
private static String readNonEmptyString(String input) {
if (input.isEmpty()) {
return null;
}
return input;
}
private static ComputerDetails.AddressTuple splitAddressToTuple(String input) {
if (input == null) {
return null;
}
String[] parts = input.split(""+PORT_DELIMITER, -1);
if (parts.length == 1) {
return new ComputerDetails.AddressTuple(parts[0], NvHTTP.DEFAULT_HTTP_PORT);
}
else {
return new ComputerDetails.AddressTuple(parts[0], Integer.parseInt(parts[1]));
}
}
private static String splitTupleToAddress(ComputerDetails.AddressTuple tuple) {
return tuple.address+PORT_DELIMITER+tuple.port;
}
private ComputerDetails getComputerFromCursor(Cursor c) {
ComputerDetails details = new ComputerDetails();
details.uuid = c.getString(0);
details.name = c.getString(1);
String[] addresses = c.getString(2).split(""+ADDRESS_DELIMITER, -1);
details.localAddress = splitAddressToTuple(readNonEmptyString(addresses[0]));
details.remoteAddress = splitAddressToTuple(readNonEmptyString(addresses[1]));
details.manualAddress = splitAddressToTuple(readNonEmptyString(addresses[2]));
details.ipv6Address = splitAddressToTuple(readNonEmptyString(addresses[3]));
try {
JSONObject addresses = new JSONObject(c.getString(2));
details.localAddress = tupleFromJson(addresses, AddressFields.LOCAL);
details.remoteAddress = tupleFromJson(addresses, AddressFields.REMOTE);
details.manualAddress = tupleFromJson(addresses, AddressFields.MANUAL);
details.ipv6Address = tupleFromJson(addresses, AddressFields.IPv6);
} catch (JSONException e) {
throw new RuntimeException(e);
}
// External port is persisted in the remote address field
if (details.remoteAddress != null) {
@@ -173,6 +190,35 @@ public class ComputerDatabaseManager {
}
}
/**
* Get a computer by name
* NOTE: It is perfectly valid for multiple computers to have the same name,
* this function will only return the first one it finds.
* Consider using getComputerByUUID instead.
* @param name The name of the computer
* @see ComputerDatabaseManager#getComputerByUUID(String) for alternative.
* @return The computer details, or null if no computer with that name exists
*/
public ComputerDetails getComputerByName(String name) {
try (final Cursor c = computerDb.query(
COMPUTER_TABLE_NAME, null, COMPUTER_NAME_COLUMN_NAME+"=?",
new String[]{ name }, null, null, null)
) {
if (!c.moveToFirst()) {
// No matching computer
return null;
}
return getComputerFromCursor(c);
}
}
/**
* Get a computer by UUID
* @param uuid The UUID of the computer
* @see ComputerDatabaseManager#getComputerByName(String) for alternative.
* @return The computer details, or null if no computer with that UUID exists
*/
public ComputerDetails getComputerByUUID(String uuid) {
try (final Cursor c = computerDb.query(
COMPUTER_TABLE_NAME, null, COMPUTER_UUID_COLUMN_NAME+"=?",
@@ -341,57 +341,53 @@ public class ComputerManagerService extends Service {
// Acquire the default network lock since we could be changing global process state
defaultNetworkLock.lock();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// On Lollipop or later, we can bind our process to the underlying interface
// to ensure our STUN request goes out on that interface or not at all (which is
// preferable to getting a VPN endpoint address back).
Network[] networks = connMgr.getAllNetworks();
for (Network net : networks) {
NetworkCapabilities netCaps = connMgr.getNetworkCapabilities(net);
if (netCaps != null) {
if (!netCaps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) &&
!netCaps.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) {
// This network looks like an underlying multicast-capable transport,
// so let's guess that it's probably where our mDNS response came from.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (connMgr.bindProcessToNetwork(net)) {
boundToNetwork = true;
break;
}
}
else if (ConnectivityManager.setProcessDefaultNetwork(net)) {
// On Lollipop or later, we can bind our process to the underlying interface
// to ensure our STUN request goes out on that interface or not at all (which is
// preferable to getting a VPN endpoint address back).
Network[] networks = connMgr.getAllNetworks();
for (Network net : networks) {
NetworkCapabilities netCaps = connMgr.getNetworkCapabilities(net);
if (netCaps != null) {
if (!netCaps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) &&
!netCaps.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) {
// This network looks like an underlying multicast-capable transport,
// so let's guess that it's probably where our mDNS response came from.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (connMgr.bindProcessToNetwork(net)) {
boundToNetwork = true;
break;
}
} else if (ConnectivityManager.setProcessDefaultNetwork(net)) {
boundToNetwork = true;
break;
}
}
}
}
}
// Perform the STUN request if we're not on a VPN or if we bound to a network
if (!activeNetworkIsVpn || boundToNetwork) {
String stunResolvedAddress = NvConnection.findExternalAddressForMdns("stun.moonlight-stream.org", 3478);
if (stunResolvedAddress != null) {
// We don't know for sure what the external port is, so we will have to guess.
// When we contact the PC (if we haven't already), it will update the port.
details.remoteAddress = new ComputerDetails.AddressTuple(stunResolvedAddress, details.guessExternalPort());
// Perform the STUN request if we're not on a VPN or if we bound to a network
if (!activeNetworkIsVpn || boundToNetwork) {
String stunResolvedAddress = NvConnection.findExternalAddressForMdns("stun.moonlight-stream.org", 3478);
if (stunResolvedAddress != null) {
// We don't know for sure what the external port is, so we will have to guess.
// When we contact the PC (if we haven't already), it will update the port.
details.remoteAddress = new ComputerDetails.AddressTuple(stunResolvedAddress, details.guessExternalPort());
}
}
}
// Unbind from the network
if (boundToNetwork) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
connMgr.bindProcessToNetwork(null);
// Unbind from the network
if (boundToNetwork) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
connMgr.bindProcessToNetwork(null);
} else {
ConnectivityManager.setProcessDefaultNetwork(null);
}
}
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
ConnectivityManager.setProcessDefaultNetwork(null);
}
}
// Unlock the network state
if (activeNetworkIsVpn) {
defaultNetworkLock.unlock();
// Unlock the network state
if (activeNetworkIsVpn) {
defaultNetworkLock.unlock();
}
}
}
@@ -431,11 +427,6 @@ public class ComputerManagerService extends Service {
}
}
@Override
public void notifyComputerRemoved(MdnsComputer computer) {
// Nothing to do here
}
@Override
public void notifyDiscoveryFailure(Exception e) {
LimeLog.severe("mDNS discovery failed");
@@ -0,0 +1,123 @@
package com.limelight.computers;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import com.limelight.nvstream.http.ComputerDetails;
import com.limelight.nvstream.http.NvHTTP;
import java.io.ByteArrayInputStream;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.LinkedList;
import java.util.List;
public class LegacyDatabaseReader3 {
private static final String COMPUTER_DB_NAME = "computers3.db";
private static final String COMPUTER_TABLE_NAME = "Computers";
private static final char ADDRESS_DELIMITER = ';';
private static final char PORT_DELIMITER = '_';
private static String readNonEmptyString(String input) {
if (input.isEmpty()) {
return null;
}
return input;
}
private static ComputerDetails.AddressTuple splitAddressToTuple(String input) {
if (input == null) {
return null;
}
String[] parts = input.split(""+PORT_DELIMITER, -1);
if (parts.length == 1) {
return new ComputerDetails.AddressTuple(parts[0], NvHTTP.DEFAULT_HTTP_PORT);
}
else {
return new ComputerDetails.AddressTuple(parts[0], Integer.parseInt(parts[1]));
}
}
private static String splitTupleToAddress(ComputerDetails.AddressTuple tuple) {
return tuple.address+PORT_DELIMITER+tuple.port;
}
private static ComputerDetails getComputerFromCursor(Cursor c) {
ComputerDetails details = new ComputerDetails();
details.uuid = c.getString(0);
details.name = c.getString(1);
String[] addresses = c.getString(2).split(""+ADDRESS_DELIMITER, -1);
details.localAddress = splitAddressToTuple(readNonEmptyString(addresses[0]));
details.remoteAddress = splitAddressToTuple(readNonEmptyString(addresses[1]));
details.manualAddress = splitAddressToTuple(readNonEmptyString(addresses[2]));
details.ipv6Address = splitAddressToTuple(readNonEmptyString(addresses[3]));
// External port is persisted in the remote address field
if (details.remoteAddress != null) {
details.externalPort = details.remoteAddress.port;
}
else {
details.externalPort = NvHTTP.DEFAULT_HTTP_PORT;
}
details.macAddress = c.getString(3);
try {
byte[] derCertData = c.getBlob(4);
if (derCertData != null) {
details.serverCert = (X509Certificate) CertificateFactory.getInstance("X.509")
.generateCertificate(new ByteArrayInputStream(derCertData));
}
} catch (CertificateException e) {
e.printStackTrace();
}
// This signifies we don't have dynamic state (like pair state)
details.state = ComputerDetails.State.UNKNOWN;
return details;
}
public static List<ComputerDetails> getAllComputers(SQLiteDatabase computerDb) {
try (final Cursor c = computerDb.rawQuery("SELECT * FROM "+COMPUTER_TABLE_NAME, null)) {
LinkedList<ComputerDetails> computerList = new LinkedList<>();
while (c.moveToNext()) {
ComputerDetails details = getComputerFromCursor(c);
// If a critical field is corrupt or missing, skip the database entry
if (details.uuid == null) {
continue;
}
computerList.add(details);
}
return computerList;
}
}
public static List<ComputerDetails> migrateAllComputers(Context c) {
try (final SQLiteDatabase computerDb = SQLiteDatabase.openDatabase(
c.getDatabasePath(COMPUTER_DB_NAME).getPath(),
null, SQLiteDatabase.OPEN_READONLY)
) {
// Open the existing database
return getAllComputers(computerDb);
} catch (SQLiteException e) {
return new LinkedList<ComputerDetails>();
} finally {
// Close and delete the old DB
c.deleteDatabase(COMPUTER_DB_NAME);
}
}
}
@@ -3,22 +3,21 @@ package com.limelight.discovery;
import java.util.List;
import com.limelight.nvstream.mdns.MdnsComputer;
import com.limelight.nvstream.mdns.JmDNSDiscoveryAgent;
import com.limelight.nvstream.mdns.MdnsDiscoveryAgent;
import com.limelight.nvstream.mdns.MdnsDiscoveryListener;
import com.limelight.nvstream.mdns.NsdManagerDiscoveryAgent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.MulticastLock;
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
public class DiscoveryService extends Service {
private MdnsDiscoveryAgent discoveryAgent;
private MdnsDiscoveryListener boundListener;
private MulticastLock multicastLock;
public class DiscoveryBinder extends Binder {
public void setListener(MdnsDiscoveryListener listener) {
@@ -26,13 +25,11 @@ public class DiscoveryService extends Service {
}
public void startDiscovery(int queryIntervalMs) {
multicastLock.acquire();
discoveryAgent.startDiscovery(queryIntervalMs);
}
public void stopDiscovery() {
discoveryAgent.stopDiscovery();
multicastLock.release();
}
public List<MdnsComputer> getComputerSet() {
@@ -42,11 +39,7 @@ public class DiscoveryService extends Service {
@Override
public void onCreate() {
WifiManager wifiMgr = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
multicastLock = wifiMgr.createMulticastLock("Limelight mDNS");
multicastLock.setReferenceCounted(false);
discoveryAgent = new MdnsDiscoveryAgent(new MdnsDiscoveryListener() {
MdnsDiscoveryListener listener = new MdnsDiscoveryListener() {
@Override
public void notifyComputerAdded(MdnsComputer computer) {
if (boundListener != null) {
@@ -54,20 +47,28 @@ public class DiscoveryService extends Service {
}
}
@Override
public void notifyComputerRemoved(MdnsComputer computer) {
if (boundListener != null) {
boundListener.notifyComputerRemoved(computer);
}
}
@Override
public void notifyDiscoveryFailure(Exception e) {
if (boundListener != null) {
boundListener.notifyDiscoveryFailure(e);
}
}
});
};
// Prior to Android 14, NsdManager doesn't provide all the capabilities needed for parity
// with jmDNS (specifically handling multiple addresses for a single service). There are
// also documented reliability bugs early in the Android 4.x series shortly after it was
// introduced. The benefit of using NsdManager over jmDNS is that it works correctly in
// environments where mDNS proxying is required, like ChromeOS, WSA, and the emulator.
//
// As such, we use the jmDNS-based MdnsDiscoveryAgent prior to Android 14 and NsdManager
// on Android 14 and above.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
discoveryAgent = new JmDNSDiscoveryAgent(getApplicationContext(), listener);
}
else {
discoveryAgent = new NsdManagerDiscoveryAgent(getApplicationContext(), listener);
}
}
private final DiscoveryBinder binder = new DiscoveryBinder();
@@ -81,7 +82,6 @@ public class DiscoveryService extends Service {
public boolean onUnbind(Intent intent) {
// Stop any discovery session
discoveryAgent.stopDiscovery();
multicastLock.release();
// Unbind the listener
boundListener = null;
@@ -28,14 +28,8 @@ public class DiskAssetLoader {
public DiskAssetLoader(Context context) {
this.cacheDir = context.getCacheDir();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
this.isLowRamDevice =
((ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE)).isLowRamDevice();
}
else {
// Use conservative low RAM behavior on very old devices
this.isLowRamDevice = true;
}
this.isLowRamDevice =
((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE)).isLowRamDevice();
}
public boolean checkCacheExists(CachedAppAssetLoader.LoaderTuple tuple) {
@@ -9,6 +9,7 @@ import javax.crypto.SecretKey;
public class ConnectionContext {
public ComputerDetails.AddressTuple serverAddress;
public int httpsPort;
public boolean isNvidiaServerSoftware;
public X509Certificate serverCert;
public StreamConfiguration streamConfig;
public NvConnectionListener connListener;
@@ -18,6 +19,7 @@ public class ConnectionContext {
// This is the version quad from the appversion tag of /serverinfo
public String serverAppVersion;
public String serverGfeVersion;
public int serverCodecModeSupport;
// This is the sessionUrl0 tag from /resume and /launch
public String rtspSessionUrl;
@@ -15,7 +15,6 @@ import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
@@ -33,7 +32,7 @@ import com.limelight.LimeLog;
import com.limelight.nvstream.av.audio.AudioRenderer;
import com.limelight.nvstream.av.video.VideoDecoderRenderer;
import com.limelight.nvstream.http.ComputerDetails;
import com.limelight.nvstream.http.GfeHttpResponseException;
import com.limelight.nvstream.http.HostHttpResponseException;
import com.limelight.nvstream.http.LimelightCryptoProvider;
import com.limelight.nvstream.http.NvApp;
import com.limelight.nvstream.http.NvHTTP;
@@ -48,21 +47,13 @@ public class NvConnection {
private ConnectionContext context;
private static Semaphore connectionAllowed = new Semaphore(1);
private final boolean isMonkey;
private final boolean batchMouseInput;
private final Context appContext;
private static final int MOUSE_BATCH_PERIOD_MS = 5;
private Timer mouseInputTimer;
private final Object mouseInputLock = new Object();
private short relMouseX, relMouseY, relMouseWidth, relMouseHeight;
private short absMouseX, absMouseY, absMouseWidth, absMouseHeight;
public NvConnection(Context appContext, ComputerDetails.AddressTuple host, int httpsPort, String uniqueId, StreamConfiguration config, LimelightCryptoProvider cryptoProvider, X509Certificate serverCert, boolean batchMouseInput)
public NvConnection(Context appContext, ComputerDetails.AddressTuple host, int httpsPort, String uniqueId, StreamConfiguration config, LimelightCryptoProvider cryptoProvider, X509Certificate serverCert)
{
this.appContext = appContext;
this.cryptoProvider = cryptoProvider;
this.uniqueId = uniqueId;
this.batchMouseInput = batchMouseInput;
this.context = new ConnectionContext();
this.context.serverAddress = host;
@@ -96,11 +87,6 @@ public class NvConnection {
}
public void stop() {
// Stop sending additional input
if (mouseInputTimer != null) {
mouseInputTimer.cancel();
}
// Interrupt any pending connection. This is thread-safe.
MoonBridge.interruptConnection();
@@ -115,24 +101,6 @@ public class NvConnection {
connectionAllowed.release();
}
private void flushMousePosition() {
synchronized (mouseInputLock) {
if (relMouseX != 0 || relMouseY != 0) {
if (relMouseWidth != 0 || relMouseHeight != 0) {
MoonBridge.sendMouseMoveAsMousePosition(relMouseX, relMouseY, relMouseWidth, relMouseHeight);
}
else {
MoonBridge.sendMouseMove(relMouseX, relMouseY);
}
relMouseX = relMouseY = relMouseWidth = relMouseHeight = 0;
}
if (absMouseX != 0 || absMouseY != 0 || absMouseWidth != 0 || absMouseHeight != 0) {
MoonBridge.sendMousePosition(absMouseX, absMouseY, absMouseWidth, absMouseHeight);
absMouseX = absMouseY = absMouseWidth = absMouseHeight = 0;
}
}
}
private InetAddress resolveServerAddress() throws IOException {
// Try to find an address that works for this host
InetAddress[] addrs = InetAddress.getAllByName(context.serverAddress.address);
@@ -230,7 +198,7 @@ public class NvConnection {
}
}
}
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
else {
NetworkInfo activeNetworkInfo = connMgr.getActiveNetworkInfo();
if (activeNetworkInfo != null) {
switch (activeNetworkInfo.getType()) {
@@ -263,6 +231,9 @@ public class NvConnection {
return false;
}
ComputerDetails details = h.getComputerDetails(serverInfo);
context.isNvidiaServerSoftware = details.nvidiaServer;
// May be missing for older servers
context.serverGfeVersion = h.getGfeVersion(serverInfo);
@@ -271,9 +242,11 @@ public class NvConnection {
return false;
}
context.negotiatedHdr = context.streamConfig.getEnableHdr();
if ((h.getServerCodecModeSupport(serverInfo) & 0x200) == 0 && context.negotiatedHdr) {
context.connListener.displayTransientMessage("Your GPU does not support streaming HDR. The stream will be SDR.");
context.serverCodecModeSupport = (int)h.getServerCodecModeSupport(serverInfo);
context.negotiatedHdr = (context.streamConfig.getSupportedVideoFormats() & MoonBridge.VIDEO_FORMAT_MASK_10BIT) != 0;
if ((context.serverCodecModeSupport & 0x20200) == 0 && context.negotiatedHdr) {
context.connListener.displayTransientMessage("Your PC GPU does not support streaming HDR. The stream will be SDR.");
context.negotiatedHdr = false;
}
@@ -283,13 +256,13 @@ public class NvConnection {
// Check for a supported stream resolution
if ((context.streamConfig.getWidth() > 4096 || context.streamConfig.getHeight() > 4096) &&
(h.getServerCodecModeSupport(serverInfo) & 0x200) == 0) {
(h.getServerCodecModeSupport(serverInfo) & 0x200) == 0 && context.isNvidiaServerSoftware) {
context.connListener.displayMessage("Your host PC does not support streaming at resolutions above 4K.");
return false;
}
else if ((context.streamConfig.getWidth() > 4096 || context.streamConfig.getHeight() > 4096) &&
!context.streamConfig.getHevcSupported()) {
context.connListener.displayMessage("Your streaming device must support HEVC to stream at resolutions above 4K.");
(context.streamConfig.getSupportedVideoFormats() & ~MoonBridge.VIDEO_FORMAT_MASK_H264) == 0) {
context.connListener.displayMessage("Your streaming device must support HEVC or AV1 to stream at resolutions above 4K.");
return false;
}
else if (context.streamConfig.getHeight() >= 2160 && !h.supports4K(serverInfo)) {
@@ -338,14 +311,14 @@ public class NvConnection {
if (h.getCurrentGame(serverInfo) != 0) {
try {
if (h.getCurrentGame(serverInfo) == app.getAppId()) {
if (!h.resumeApp(context)) {
if (!h.launchApp(context, "resume", app.getAppId(), context.negotiatedHdr)) {
context.connListener.displayMessage("Failed to resume existing session");
return false;
}
} else {
return quitAndLaunch(h, context);
}
} catch (GfeHttpResponseException e) {
} catch (HostHttpResponseException e) {
if (e.getErrorCode() == 470) {
// This is the error you get when you try to resume a session that's not yours.
// Because this is fairly common, we'll display a more detailed message.
@@ -378,7 +351,7 @@ public class NvConnection {
context.connListener.displayMessage("Failed to quit previous session! You must quit it manually");
return false;
}
} catch (GfeHttpResponseException e) {
} catch (HostHttpResponseException e) {
if (e.getErrorCode() == 599) {
context.connListener.displayMessage("This session wasn't started by this device," +
" so it cannot be quit. End streaming on the original " +
@@ -396,7 +369,7 @@ public class NvConnection {
private boolean launchNotRunningApp(NvHTTP h, ConnectionContext context)
throws IOException, XmlPullParserException {
// Launch the app since it's not running
if (!h.launchApp(context, context.streamConfig.getApp().getAppId(), context.negotiatedHdr)) {
if (!h.launchApp(context, "launch", context.streamConfig.getApp().getAppId(), context.negotiatedHdr)) {
context.connListener.displayMessage("Failed to launch application");
return false;
}
@@ -423,7 +396,7 @@ public class NvConnection {
return;
}
context.connListener.stageComplete(appName);
} catch (GfeHttpResponseException e) {
} catch (HostHttpResponseException e) {
e.printStackTrace();
context.connListener.displayMessage(e.getMessage());
context.connListener.stageFailed(appName, 0, e.getErrorCode());
@@ -454,15 +427,13 @@ public class NvConnection {
MoonBridge.setupBridge(videoDecoderRenderer, audioRenderer, connectionListener);
int ret = MoonBridge.startConnection(context.serverAddress.address,
context.serverAppVersion, context.serverGfeVersion, context.rtspSessionUrl,
context.serverCodecModeSupport,
context.negotiatedWidth, context.negotiatedHeight,
context.streamConfig.getRefreshRate(), context.streamConfig.getBitrate(),
context.negotiatedPacketSize, context.negotiatedRemoteStreaming,
context.streamConfig.getAudioConfiguration().toInt(),
context.streamConfig.getHevcSupported(),
context.negotiatedHdr,
context.streamConfig.getHevcBitratePercentageMultiplier(),
context.streamConfig.getSupportedVideoFormats(),
context.streamConfig.getClientRefreshRateX100(),
context.streamConfig.getEncryptionFlags(),
context.riKey.getEncoded(), ib.array(),
context.videoCapabilities,
context.streamConfig.getColorSpace(),
@@ -474,20 +445,6 @@ public class NvConnection {
connectionAllowed.release();
return;
}
if (batchMouseInput) {
// High polling rate mice can cause GeForce Experience's input queue to get backed up,
// causing massive input latency. We counter this by limiting our mouse events to 200 Hz
// which appears to avoid triggering the issue on all known configurations.
mouseInputTimer = new Timer("MouseInput", true);
mouseInputTimer.schedule(new TimerTask() {
@Override
public void run() {
// Flush the mouse position every 5 ms
flushMousePosition();
}
}, MOUSE_BATCH_PERIOD_MS, MOUSE_BATCH_PERIOD_MS);
}
}
}
}).start();
@@ -496,65 +453,27 @@ public class NvConnection {
public void sendMouseMove(final short deltaX, final short deltaY)
{
if (!isMonkey) {
synchronized (mouseInputLock) {
relMouseX += deltaX;
relMouseY += deltaY;
// Reset these to ensure we don't send this as a position update
relMouseWidth = 0;
relMouseHeight = 0;
}
if (!batchMouseInput) {
flushMousePosition();
}
MoonBridge.sendMouseMove(deltaX, deltaY);
}
}
public void sendMousePosition(short x, short y, short referenceWidth, short referenceHeight)
{
if (!isMonkey) {
synchronized (mouseInputLock) {
absMouseX = x;
absMouseY = y;
absMouseWidth = referenceWidth;
absMouseHeight = referenceHeight;
}
if (!batchMouseInput) {
flushMousePosition();
}
MoonBridge.sendMousePosition(x, y, referenceWidth, referenceHeight);
}
}
public void sendMouseMoveAsMousePosition(short deltaX, short deltaY, short referenceWidth, short referenceHeight)
{
if (!isMonkey) {
synchronized (mouseInputLock) {
// Only accumulate the delta if the reference size is the same
if (relMouseWidth == referenceWidth && relMouseHeight == referenceHeight) {
relMouseX += deltaX;
relMouseY += deltaY;
}
else {
relMouseX = deltaX;
relMouseY = deltaY;
}
relMouseWidth = referenceWidth;
relMouseHeight = referenceHeight;
}
if (!batchMouseInput) {
flushMousePosition();
}
MoonBridge.sendMouseMoveAsMousePosition(deltaX, deltaY, referenceWidth, referenceHeight);
}
}
public void sendMouseButtonDown(final byte mouseButton)
{
if (!isMonkey) {
flushMousePosition();
MoonBridge.sendMouseButton(MouseButtonPacket.PRESS_EVENT, mouseButton);
}
}
@@ -562,13 +481,12 @@ public class NvConnection {
public void sendMouseButtonUp(final byte mouseButton)
{
if (!isMonkey) {
flushMousePosition();
MoonBridge.sendMouseButton(MouseButtonPacket.RELEASE_EVENT, mouseButton);
}
}
public void sendControllerInput(final short controllerNumber,
final short activeGamepadMask, final short buttonFlags,
final short activeGamepadMask, final int buttonFlags,
final byte leftTrigger, final byte rightTrigger,
final short leftStickX, final short leftStickY,
final short rightStickX, final short rightStickY)
@@ -578,38 +496,89 @@ public class NvConnection {
leftTrigger, rightTrigger, leftStickX, leftStickY, rightStickX, rightStickY);
}
}
public void sendControllerInput(final short buttonFlags,
final byte leftTrigger, final byte rightTrigger,
final short leftStickX, final short leftStickY,
final short rightStickX, final short rightStickY)
{
public void sendKeyboardInput(final short keyMap, final byte keyDirection, final byte modifier, final byte flags) {
if (!isMonkey) {
MoonBridge.sendControllerInput(buttonFlags, leftTrigger, rightTrigger, leftStickX,
leftStickY, rightStickX, rightStickY);
}
}
public void sendKeyboardInput(final short keyMap, final byte keyDirection, final byte modifier) {
if (!isMonkey) {
MoonBridge.sendKeyboardInput(keyMap, keyDirection, modifier);
MoonBridge.sendKeyboardInput(keyMap, keyDirection, modifier, flags);
}
}
public void sendMouseScroll(final byte scrollClicks) {
if (!isMonkey) {
flushMousePosition();
MoonBridge.sendMouseScroll(scrollClicks);
MoonBridge.sendMouseHighResScroll((short)(scrollClicks * 120)); // WHEEL_DELTA
}
}
public void sendMouseHScroll(final byte scrollClicks) {
if (!isMonkey) {
MoonBridge.sendMouseHighResHScroll((short)(scrollClicks * 120)); // WHEEL_DELTA
}
}
public void sendMouseHighResScroll(final short scrollAmount) {
if (!isMonkey) {
flushMousePosition();
MoonBridge.sendMouseHighResScroll(scrollAmount);
}
}
public void sendMouseHighResHScroll(final short scrollAmount) {
if (!isMonkey) {
MoonBridge.sendMouseHighResHScroll(scrollAmount);
}
}
public int sendTouchEvent(byte eventType, int pointerId, float x, float y, float pressureOrDistance,
float contactAreaMajor, float contactAreaMinor, short rotation) {
if (!isMonkey) {
return MoonBridge.sendTouchEvent(eventType, pointerId, x, y, pressureOrDistance,
contactAreaMajor, contactAreaMinor, rotation);
}
else {
return MoonBridge.LI_ERR_UNSUPPORTED;
}
}
public int sendPenEvent(byte eventType, byte toolType, byte penButtons, float x, float y,
float pressureOrDistance, float contactAreaMajor, float contactAreaMinor,
short rotation, byte tilt) {
if (!isMonkey) {
return MoonBridge.sendPenEvent(eventType, toolType, penButtons, x, y, pressureOrDistance,
contactAreaMajor, contactAreaMinor, rotation, tilt);
}
else {
return MoonBridge.LI_ERR_UNSUPPORTED;
}
}
public int sendControllerArrivalEvent(byte controllerNumber, short activeGamepadMask, byte type,
int supportedButtonFlags, short capabilities) {
return MoonBridge.sendControllerArrivalEvent(controllerNumber, activeGamepadMask, type, supportedButtonFlags, capabilities);
}
public int sendControllerTouchEvent(byte controllerNumber, byte eventType, int pointerId,
float x, float y, float pressure) {
if (!isMonkey) {
return MoonBridge.sendControllerTouchEvent(controllerNumber, eventType, pointerId, x, y, pressure);
}
else {
return MoonBridge.LI_ERR_UNSUPPORTED;
}
}
public int sendControllerMotionEvent(byte controllerNumber, byte motionType,
float x, float y, float z) {
if (!isMonkey) {
return MoonBridge.sendControllerMotionEvent(controllerNumber, motionType, x, y, z);
}
else {
return MoonBridge.LI_ERR_UNSUPPORTED;
}
}
public void sendControllerBatteryEvent(byte controllerNumber, byte batteryState, byte batteryPercentage) {
MoonBridge.sendControllerBatteryEvent(controllerNumber, batteryState, batteryPercentage);
}
public void sendUtf8Text(final String text) {
if (!isMonkey) {
MoonBridge.sendUtf8Text(text);
@@ -13,6 +13,11 @@ public interface NvConnectionListener {
void displayTransientMessage(String message);
void rumble(short controllerNumber, short lowFreqMotor, short highFreqMotor);
void rumbleTriggers(short controllerNumber, short leftTrigger, short rightTrigger);
void setHdrMode(boolean enabled);
void setHdrMode(boolean enabled, byte[] hdrMetadata);
void setMotionEventState(short controllerNumber, byte motionType, short reportRateHz);
void setControllerLED(short controllerNumber, byte r, byte g, byte b);
}
@@ -22,13 +22,12 @@ public class StreamConfiguration {
private int maxPacketSize;
private int remote;
private MoonBridge.AudioConfiguration audioConfiguration;
private boolean supportsHevc;
private int hevcBitratePercentageMultiplier;
private boolean enableHdr;
private int supportedVideoFormats;
private int attachedGamepadMask;
private int encryptionFlags;
private int colorRange;
private int colorSpace;
private boolean persistGamepadsAfterDisconnect;
public static class Builder {
private StreamConfiguration config = new StreamConfiguration();
@@ -84,16 +83,6 @@ public class StreamConfiguration {
return this;
}
public StreamConfiguration.Builder setHevcBitratePercentageMultiplier(int multiplier) {
config.hevcBitratePercentageMultiplier = multiplier;
return this;
}
public StreamConfiguration.Builder setEnableHdr(boolean enableHdr) {
config.enableHdr = enableHdr;
return this;
}
public StreamConfiguration.Builder setAttachedGamepadMask(int attachedGamepadMask) {
config.attachedGamepadMask = attachedGamepadMask;
return this;
@@ -109,18 +98,13 @@ public class StreamConfiguration {
return this;
}
public StreamConfiguration.Builder setClientRefreshRateX100(int refreshRateX100) {
config.clientRefreshRateX100 = refreshRateX100;
public StreamConfiguration.Builder setPersistGamepadsAfterDisconnect(boolean value) {
config.persistGamepadsAfterDisconnect = value;
return this;
}
public StreamConfiguration.Builder setAudioEncryption(boolean enable) {
if (enable) {
config.encryptionFlags |= MoonBridge.ENCFLG_AUDIO;
}
else {
config.encryptionFlags &= ~MoonBridge.ENCFLG_AUDIO;
}
public StreamConfiguration.Builder setClientRefreshRateX100(int refreshRateX100) {
config.clientRefreshRateX100 = refreshRateX100;
return this;
}
@@ -129,8 +113,8 @@ public class StreamConfiguration {
return this;
}
public StreamConfiguration.Builder setHevcSupported(boolean supportsHevc) {
config.supportsHevc = supportsHevc;
public StreamConfiguration.Builder setSupportedVideoFormats(int supportedVideoFormats) {
config.supportedVideoFormats = supportedVideoFormats;
return this;
}
@@ -162,8 +146,7 @@ public class StreamConfiguration {
this.sops = true;
this.enableAdaptiveResolution = false;
this.audioConfiguration = MoonBridge.AUDIO_CONFIGURATION_STEREO;
this.supportsHevc = false;
this.enableHdr = false;
this.supportedVideoFormats = MoonBridge.VIDEO_FORMAT_H264;
this.attachedGamepadMask = 0;
}
@@ -215,28 +198,20 @@ public class StreamConfiguration {
return audioConfiguration;
}
public boolean getHevcSupported() {
return supportsHevc;
}
public int getHevcBitratePercentageMultiplier() {
return hevcBitratePercentageMultiplier;
}
public boolean getEnableHdr() {
return enableHdr;
public int getSupportedVideoFormats() {
return supportedVideoFormats;
}
public int getAttachedGamepadMask() {
return attachedGamepadMask;
}
public int getClientRefreshRateX100() {
return clientRefreshRateX100;
public boolean getPersistGamepadsAfterDisconnect() {
return persistGamepadsAfterDisconnect;
}
public int getEncryptionFlags() {
return encryptionFlags;
public int getClientRefreshRateX100() {
return clientRefreshRateX100;
}
public int getColorRange() {
@@ -10,11 +10,12 @@ public abstract class VideoDecoderRenderer {
// This is called once for each frame-start NALU. This means it will be called several times
// for an IDR frame which contains several parameter sets and the I-frame data.
public abstract int submitDecodeUnit(byte[] decodeUnitData, int decodeUnitLength, int decodeUnitType,
int frameNumber, int frameType, long receiveTimeMs, long enqueueTimeMs);
int frameNumber, int frameType, char frameHostProcessingLatency,
long receiveTimeUs, long enqueueTimeUs);
public abstract void cleanup();
public abstract int getCapabilities();
public abstract void setHdrMode(boolean enabled);
public abstract void setHdrMode(boolean enabled, byte[] hdrMetadata);
}
@@ -1,6 +1,7 @@
package com.limelight.nvstream.http;
import java.security.cert.X509Certificate;
import java.util.Objects;
public class ComputerDetails {
@@ -31,7 +32,7 @@ public class ComputerDetails {
@Override
public int hashCode() {
return address.hashCode();
return Objects.hash(address, port);
}
@Override
@@ -74,6 +75,7 @@ public class ComputerDetails {
public PairingManager.PairState pairState;
public int runningGameId;
public String rawAppList;
public boolean nvidiaServer;
public ComputerDetails() {
// Use defaults
@@ -142,6 +144,7 @@ public class ComputerDetails {
this.httpsPort = details.httpsPort;
this.pairState = details.pairState;
this.runningGameId = details.runningGameId;
this.nvidiaServer = details.nvidiaServer;
this.rawAppList = details.rawAppList;
}
@@ -2,13 +2,13 @@ package com.limelight.nvstream.http;
import java.io.IOException;
public class GfeHttpResponseException extends IOException {
public class HostHttpResponseException extends IOException {
private static final long serialVersionUID = 1543508830807804222L;
private int errorCode;
private String errorMsg;
public GfeHttpResponseException(int errorCode, String errorMsg) {
public HostHttpResponseException(int errorCode, String errorMsg) {
this.errorCode = errorCode;
this.errorMsg = errorMsg;
}
@@ -23,6 +23,6 @@ public class GfeHttpResponseException extends IOException {
@Override
public String getMessage() {
return "GeForce Experience returned error: "+errorMsg+" (Error code: "+errorCode+")";
return "Host PC returned error: "+errorMsg+" (Error code: "+errorCode+")";
}
}
@@ -1,11 +1,11 @@
package com.limelight.nvstream.http;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
public interface LimelightCryptoProvider {
X509Certificate getClientCertificate();
RSAPrivateKey getClientPrivateKey();
PrivateKey getClientPrivateKey();
byte[] getPemEncodedClientCertificate();
String encodeBase64String(byte[] data);
}
@@ -8,6 +8,7 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.Proxy;
import java.net.Socket;
@@ -49,6 +50,7 @@ import com.limelight.BuildConfig;
import com.limelight.LimeLog;
import com.limelight.nvstream.ConnectionContext;
import com.limelight.nvstream.http.PairingManager.PairState;
import com.limelight.nvstream.jni.MoonBridge;
import okhttp3.ConnectionPool;
import okhttp3.HttpUrl;
@@ -176,6 +178,7 @@ public class NvHTTP {
.readTimeout(READ_TIMEOUT, TimeUnit.MILLISECONDS)
.connectTimeout(LONG_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS)
.proxy(Proxy.NO_PROXY)
.fastFallback(false)
.build();
httpClientShortConnectTimeout = httpClientLongConnectTimeout.newBuilder()
@@ -209,9 +212,21 @@ public class NvHTTP {
this.httpsPort = httpsPort;
try {
// If this is an IPv4-mapped IPv6 address, OkHTTP will choke on it if it's
// in IPv6 form, because InetAddress.getByName() will return an Inet4Address
// for what OkHTTP thinks is an IPv6 address. Normalize it into IPv4 form
// to avoid triggering this bug.
String addressString = address.address;
if (addressString.contains(":") && addressString.contains(".")) {
InetAddress addr = InetAddress.getByName(addressString);
if (addr instanceof Inet4Address) {
addressString = ((Inet4Address)addr).getHostAddress();
}
}
this.baseUrlHttp = new HttpUrl.Builder()
.scheme("http")
.host(address.address)
.host(addressString)
.port(address.port)
.build();
} catch (IllegalArgumentException e) {
@@ -266,7 +281,7 @@ public class NvHTTP {
return getXmlString(new StringReader(str), tagname, throwIfMissing);
}
private static void verifyResponseStatus(XmlPullParser xpp) throws GfeHttpResponseException {
private static void verifyResponseStatus(XmlPullParser xpp) throws HostHttpResponseException {
// We use Long.parseLong() because in rare cases GFE can send back a status code of
// 0xFFFFFFFF, which will cause Integer.parseInt() to throw a NumberFormatException due
// to exceeding Integer.MAX_VALUE. We'll get the desired error code of -1 by just casting
@@ -280,7 +295,7 @@ public class NvHTTP {
statusCode = 418;
statusMsg = "Missing audio capture device. Reinstall GeForce Experience.";
}
throw new GfeHttpResponseException(statusCode, statusMsg);
throw new HostHttpResponseException(statusCode, statusMsg);
}
}
@@ -306,7 +321,7 @@ public class NvHTTP {
if (e.getCause() instanceof CertificateException) {
// Jump to the GfeHttpResponseException exception handler to retry
// over HTTP which will allow us to pair again to update the cert
throw new GfeHttpResponseException(401, "Server certificate mismatch");
throw new HostHttpResponseException(401, "Server certificate mismatch");
}
else {
throw e;
@@ -317,7 +332,7 @@ public class NvHTTP {
// We want this because it will throw us into the HTTP case if the client is unpaired.
getServerVersion(resp);
}
catch (GfeHttpResponseException e) {
catch (HostHttpResponseException e) {
if (e.getErrorCode() == 401) {
// Cert validation error - fall back to HTTP
return openHttpConnectionToString(client, baseUrlHttp, "serverinfo");
@@ -342,11 +357,10 @@ public class NvHTTP {
return new ComputerDetails.AddressTuple(address, port);
}
public ComputerDetails getComputerDetails(boolean likelyOnline) throws IOException, XmlPullParserException {
public ComputerDetails getComputerDetails(String serverInfo) throws IOException, XmlPullParserException {
ComputerDetails details = new ComputerDetails();
String serverInfo = getServerInfo(likelyOnline);
details.name = getXmlString(serverInfo, "hostname", false);
if (details.name == null || details.name.isEmpty()) {
details.name = "UNKNOWN";
@@ -368,12 +382,19 @@ public class NvHTTP {
details.pairState = getPairState(serverInfo);
details.runningGameId = getCurrentGame(serverInfo);
// The MJOLNIR codename was used by GFE but never by any third-party server
details.nvidiaServer = getXmlString(serverInfo, "state", true).contains("MJOLNIR");
// We could reach it so it's online
details.state = ComputerDetails.State.ONLINE;
return details;
}
public ComputerDetails getComputerDetails(boolean likelyOnline) throws IOException, XmlPullParserException {
return getComputerDetails(getServerInfo(likelyOnline));
}
// This hack is Android-specific but we do it on all platforms
// because it doesn't really matter
@@ -383,16 +404,7 @@ public class NvHTTP {
try {
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(new KeyManager[] { keyManager }, new TrustManager[] { trustManager }, new SecureRandom());
// TLS 1.2 is not enabled by default prior to Android 5.0, so we'll need a custom
// SSLSocketFactory in order to connect to GFE 3.20.4 which requires TLSv1.2 or later.
// We don't just always use TLSv12SocketFactory because explicitly specifying TLS versions
// prevents later TLS versions from being negotiated even if client and server otherwise
// support them.
return client.newBuilder().sslSocketFactory(
Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ?
sc.getSocketFactory() : new TLSv12SocketFactory(sc),
trustManager).build();
return client.newBuilder().sslSocketFactory(sc.getSocketFactory(), trustManager).build();
} catch (NoSuchAlgorithmException | KeyManagementException e) {
throw new RuntimeException(e);
}
@@ -435,7 +447,7 @@ public class NvHTTP {
throw new FileNotFoundException(completeUrl.toString());
}
else {
throw new GfeHttpResponseException(response.code(), response.message());
throw new HostHttpResponseException(response.code(), response.message());
}
}
@@ -575,6 +587,12 @@ public class NvHTTP {
}
}
/**
* Get an app by ID
* @param appId The ID of the app
* @see #getAppByName(String) for alternative.
* @return app details, or null if no app with that ID exists
*/
public NvApp getAppById(int appId) throws IOException, XmlPullParserException {
LinkedList<NvApp> appList = getAppList();
for (NvApp appFromList : appList) {
@@ -584,11 +602,16 @@ public class NvHTTP {
}
return null;
}
/* NOTE: Only use this function if you know what you're doing.
* It's totally valid to have two apps named the same thing,
* or even nothing at all! Look apps up by ID if at all possible
* using the above function */
/**
* Get an app by name
* NOTE: It is perfectly valid for multiple apps to have the same name,
* this function will only return the first one it finds.
* Consider using getAppById instead.
* @param appName The name of the app
* @see #getAppById(int) for alternative.
* @return app details, or null if no app with that name exists
*/
public NvApp getAppByName(String appName) throws IOException, XmlPullParserException {
LinkedList<NvApp> appList = getAppList();
for (NvApp appFromList : appList) {
@@ -669,7 +692,7 @@ public class NvHTTP {
return openHttpConnectionToString(httpClientLongConnectTimeout, getHttpsUrl(true), "applist");
}
public LinkedList<NvApp> getAppList() throws GfeHttpResponseException, IOException, XmlPullParserException {
public LinkedList<NvApp> getAppList() throws HostHttpResponseException, IOException, XmlPullParserException {
if (verbose) {
// Use the raw function so the app list is printed
return getAppListByReader(new StringReader(getAppListRaw()));
@@ -681,12 +704,12 @@ public class NvHTTP {
}
}
String executePairingCommand(String additionalArguments, boolean enableReadTimeout) throws GfeHttpResponseException, IOException {
String executePairingCommand(String additionalArguments, boolean enableReadTimeout) throws HostHttpResponseException, IOException {
return openHttpConnectionToString(enableReadTimeout ? httpClientLongConnectTimeout : httpClientLongConnectNoReadTimeout,
baseUrlHttp, "pair", "devicename=roth&updateState=1&" + additionalArguments);
}
String executePairingChallenge() throws GfeHttpResponseException, IOException {
String executePairingChallenge() throws HostHttpResponseException, IOException {
return openHttpConnectionToString(httpClientLongConnectTimeout, getHttpsUrl(true),
"pair", "devicename=roth&updateState=1&phrase=pairchallenge");
}
@@ -731,27 +754,30 @@ public class NvHTTP {
return new String(hexChars);
}
public boolean launchApp(ConnectionContext context, int appId, boolean enableHdr) throws IOException, XmlPullParserException {
public boolean launchApp(ConnectionContext context, String verb, int appId, boolean enableHdr) throws IOException, XmlPullParserException {
// Using an FPS value over 60 causes SOPS to default to 720p60,
// so force it to 0 to ensure the correct resolution is set. We
// used to use 60 here but that locked the frame rate to 60 FPS
// on GFE 3.20.3.
int fps = context.streamConfig.getLaunchRefreshRate() > 60 ? 0 : context.streamConfig.getLaunchRefreshRate();
int fps = context.isNvidiaServerSoftware && context.streamConfig.getLaunchRefreshRate() > 60 ?
0 : context.streamConfig.getLaunchRefreshRate();
// Using an unsupported resolution (not 720p, 1080p, or 4K) causes
// GFE to force SOPS to 720p60. This is fine for < 720p resolutions like
// 360p or 480p, but it is not ideal for 1440p and other resolutions.
// When we detect an unsupported resolution, disable SOPS unless it's under 720p.
// FIXME: Detect support resolutions using the serverinfo response, not a hardcoded list
boolean enableSops = context.streamConfig.getSops();
if (context.negotiatedWidth * context.negotiatedHeight > 1280 * 720 &&
context.negotiatedWidth * context.negotiatedHeight != 1920 * 1080 &&
context.negotiatedWidth * context.negotiatedHeight != 3840 * 2160) {
LimeLog.info("Disabling SOPS due to non-standard resolution: "+context.negotiatedWidth+"x"+context.negotiatedHeight);
enableSops = false;
if (context.isNvidiaServerSoftware) {
// Using an unsupported resolution (not 720p, 1080p, or 4K) causes
// GFE to force SOPS to 720p60. This is fine for < 720p resolutions like
// 360p or 480p, but it is not ideal for 1440p and other resolutions.
// When we detect an unsupported resolution, disable SOPS unless it's under 720p.
// FIXME: Detect support resolutions using the serverinfo response, not a hardcoded list
if (context.negotiatedWidth * context.negotiatedHeight > 1280 * 720 &&
context.negotiatedWidth * context.negotiatedHeight != 1920 * 1080 &&
context.negotiatedWidth * context.negotiatedHeight != 3840 * 2160) {
LimeLog.info("Disabling SOPS due to non-standard resolution: "+context.negotiatedWidth+"x"+context.negotiatedHeight);
enableSops = false;
}
}
String xmlStr = openHttpConnectionToString(httpClientLongConnectNoReadTimeout, getHttpsUrl(true), "launch",
String xmlStr = openHttpConnectionToString(httpClientLongConnectNoReadTimeout, getHttpsUrl(true), verb,
"appid=" + appId +
"&mode=" + context.negotiatedWidth + "x" + context.negotiatedHeight + "x" + fps +
"&additionalStates=1&sops=" + (enableSops ? 1 : 0) +
@@ -760,24 +786,12 @@ public class NvHTTP {
(!enableHdr ? "" : "&hdrMode=1&clientHdrCapVersion=0&clientHdrCapSupportedFlagsInUint32=0&clientHdrCapMetaDataId=NV_STATIC_METADATA_TYPE_1&clientHdrCapDisplayData=0x0x0x0x0x0x0x0x0x0x0") +
"&localAudioPlayMode=" + (context.streamConfig.getPlayLocalAudio() ? 1 : 0) +
"&surroundAudioInfo=" + context.streamConfig.getAudioConfiguration().getSurroundAudioInfo() +
(context.streamConfig.getAttachedGamepadMask() != 0 ? "&remoteControllersBitmap=" + context.streamConfig.getAttachedGamepadMask() : "") +
(context.streamConfig.getAttachedGamepadMask() != 0 ? "&gcmap=" + context.streamConfig.getAttachedGamepadMask() : ""));
if (!getXmlString(xmlStr, "gamesession", true).equals("0")) {
// sessionUrl0 will be missing for older GFE versions
context.rtspSessionUrl = getXmlString(xmlStr, "sessionUrl0", false);
return true;
}
else {
return false;
}
}
public boolean resumeApp(ConnectionContext context) throws IOException, XmlPullParserException {
String xmlStr = openHttpConnectionToString(httpClientLongConnectNoReadTimeout, getHttpsUrl(true), "resume",
"rikey="+bytesToHex(context.riKey.getEncoded()) +
"&rikeyid="+context.riKeyId +
"&surroundAudioInfo=" + context.streamConfig.getAudioConfiguration().getSurroundAudioInfo());
if (!getXmlString(xmlStr, "resume", true).equals("0")) {
"&remoteControllersBitmap=" + context.streamConfig.getAttachedGamepadMask() +
"&gcmap=" + context.streamConfig.getAttachedGamepadMask() +
"&gcpersist="+(context.streamConfig.getPersistGamepadsAfterDisconnect() ? 1 : 0) +
MoonBridge.getLaunchUrlQueryParameters());
if ((verb.equals("launch") && !getXmlString(xmlStr, "gamesession", true).equals("0") ||
(verb.equals("resume") && !getXmlString(xmlStr, "resume", true).equals("0")))) {
// sessionUrl0 will be missing for older GFE versions
context.rtspSessionUrl = getXmlString(xmlStr, "sessionUrl0", false);
return true;
@@ -798,67 +812,9 @@ public class NvHTTP {
if (getCurrentGame(getServerInfo(true)) != 0) {
// Generate a synthetic GfeResponseException letting the caller know
// that they can't kill someone else's stream.
throw new GfeHttpResponseException(599, "");
throw new HostHttpResponseException(599, "");
}
return true;
}
// Based on example code from https://blog.dev-area.net/2015/08/13/android-4-1-enable-tls-1-1-and-tls-1-2/
private static class TLSv12SocketFactory extends SSLSocketFactory {
private SSLSocketFactory internalSSLSocketFactory;
public TLSv12SocketFactory(SSLContext context) {
internalSSLSocketFactory = context.getSocketFactory();
}
@Override
public String[] getDefaultCipherSuites() {
return internalSSLSocketFactory.getDefaultCipherSuites();
}
@Override
public String[] getSupportedCipherSuites() {
return internalSSLSocketFactory.getSupportedCipherSuites();
}
@Override
public Socket createSocket() throws IOException {
return enableTLSv12OnSocket(internalSSLSocketFactory.createSocket());
}
@Override
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
return enableTLSv12OnSocket(internalSSLSocketFactory.createSocket(s, host, port, autoClose));
}
@Override
public Socket createSocket(String host, int port) throws IOException {
return enableTLSv12OnSocket(internalSSLSocketFactory.createSocket(host, port));
}
@Override
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException {
return enableTLSv12OnSocket(internalSSLSocketFactory.createSocket(host, port, localHost, localPort));
}
@Override
public Socket createSocket(InetAddress host, int port) throws IOException {
return enableTLSv12OnSocket(internalSSLSocketFactory.createSocket(host, port));
}
@Override
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
return enableTLSv12OnSocket(internalSSLSocketFactory.createSocket(address, port, localAddress, localPort));
}
private Socket enableTLSv12OnSocket(Socket socket) {
if (socket instanceof SSLSocket) {
// TLS 1.2 is not enabled by default prior to Android 5.0. We must enable it
// explicitly to ensure we can communicate with GFE 3.20.4 which blocks TLS 1.0.
((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1.2"});
}
return socket;
}
}
}
@@ -98,10 +98,21 @@ public class PairingManager {
System.arraycopy(pin.getBytes("UTF-8"), 0, saltedPin, salt.length, pin.length());
return saltedPin;
}
private static Signature getSha256SignatureInstanceForKey(Key key) throws NoSuchAlgorithmException {
switch (key.getAlgorithm()) {
case "RSA":
return Signature.getInstance("SHA256withRSA");
case "EC":
return Signature.getInstance("SHA256withECDSA");
default:
throw new NoSuchAlgorithmException("Unhandled key algorithm: " + key.getAlgorithm());
}
}
private static boolean verifySignature(byte[] data, byte[] signature, Certificate cert) {
try {
Signature sig = Signature.getInstance("SHA256withRSA");
Signature sig = PairingManager.getSha256SignatureInstanceForKey(cert.getPublicKey());
sig.initVerify(cert.getPublicKey());
sig.update(data);
return sig.verify(signature);
@@ -113,12 +124,10 @@ public class PairingManager {
private static byte[] signData(byte[] data, PrivateKey key) {
try {
Signature sig = Signature.getInstance("SHA256withRSA");
Signature sig = PairingManager.getSha256SignatureInstanceForKey(key);
sig.initSign(key);
sig.update(data);
byte[] signature = new byte[256];
sig.sign(signature, 0, signature.length);
return signature;
return sig.sign();
} catch (NoSuchAlgorithmException | SignatureException | InvalidKeyException e) {
e.printStackTrace();
throw new RuntimeException(e);
@@ -245,7 +254,7 @@ public class PairingManager {
// Get the server's signed secret
byte[] serverSecretResp = hexToBytes(NvHTTP.getXmlString(secretResp, "pairingsecret", true));
byte[] serverSecret = Arrays.copyOfRange(serverSecretResp, 0, 16);
byte[] serverSignature = Arrays.copyOfRange(serverSecretResp, 16, 272);
byte[] serverSignature = Arrays.copyOfRange(serverSecretResp, 16, serverSecretResp.length);
// Ensure the authenticity of the data
if (!verifySignature(serverSecret, serverSignature, serverCert)) {
@@ -1,19 +1,27 @@
package com.limelight.nvstream.input;
public class ControllerPacket {
public static final short A_FLAG = 0x1000;
public static final short B_FLAG = 0x2000;
public static final short X_FLAG = 0x4000;
public static final short Y_FLAG = (short)0x8000;
public static final short UP_FLAG = 0x0001;
public static final short DOWN_FLAG = 0x0002;
public static final short LEFT_FLAG = 0x0004;
public static final short RIGHT_FLAG = 0x0008;
public static final short LB_FLAG = 0x0100;
public static final short RB_FLAG = 0x0200;
public static final short PLAY_FLAG = 0x0010;
public static final short BACK_FLAG = 0x0020;
public static final short LS_CLK_FLAG = 0x0040;
public static final short RS_CLK_FLAG = 0x0080;
public static final short SPECIAL_BUTTON_FLAG = 0x0400;
public static final int A_FLAG = 0x1000;
public static final int B_FLAG = 0x2000;
public static final int X_FLAG = 0x4000;
public static final int Y_FLAG = 0x8000;
public static final int UP_FLAG = 0x0001;
public static final int DOWN_FLAG = 0x0002;
public static final int LEFT_FLAG = 0x0004;
public static final int RIGHT_FLAG = 0x0008;
public static final int LB_FLAG = 0x0100;
public static final int RB_FLAG = 0x0200;
public static final int PLAY_FLAG = 0x0010;
public static final int BACK_FLAG = 0x0020;
public static final int LS_CLK_FLAG = 0x0040;
public static final int RS_CLK_FLAG = 0x0080;
public static final int SPECIAL_BUTTON_FLAG = 0x0400;
// Extended buttons (Sunshine only)
public static final int PADDLE1_FLAG = 0x010000;
public static final int PADDLE2_FLAG = 0x020000;
public static final int PADDLE3_FLAG = 0x040000;
public static final int PADDLE4_FLAG = 0x080000;
public static final int TOUCHPAD_FLAG = 0x100000; // Touchpad buttons on Sony controllers
public static final int MISC_FLAG = 0x200000; // Share/Mic/Capture/Mute buttons on various controllers
}
@@ -14,13 +14,13 @@ public class MoonBridge {
public static final int VIDEO_FORMAT_H264 = 0x0001;
public static final int VIDEO_FORMAT_H265 = 0x0100;
public static final int VIDEO_FORMAT_H265_MAIN10 = 0x0200;
public static final int VIDEO_FORMAT_AV1_MAIN8 = 0x1000;
public static final int VIDEO_FORMAT_AV1_MAIN10 = 0x2000;
public static final int VIDEO_FORMAT_MASK_H264 = 0x00FF;
public static final int VIDEO_FORMAT_MASK_H265 = 0xFF00;
public static final int ENCFLG_NONE = 0;
public static final int ENCFLG_AUDIO = 1;
public static final int ENCFLG_ALL = 0xFFFFFFFF;
public static final int VIDEO_FORMAT_MASK_H264 = 0x000F;
public static final int VIDEO_FORMAT_MASK_H265 = 0x0F00;
public static final int VIDEO_FORMAT_MASK_AV1 = 0xF000;
public static final int VIDEO_FORMAT_MASK_10BIT = 0x2200;
public static final int BUFFER_TYPE_PICDATA = 0;
public static final int BUFFER_TYPE_SPS = 1;
@@ -40,6 +40,7 @@ public class MoonBridge {
public static final int CAPABILITY_DIRECT_SUBMIT = 1;
public static final int CAPABILITY_REFERENCE_FRAME_INVALIDATION_AVC = 2;
public static final int CAPABILITY_REFERENCE_FRAME_INVALIDATION_HEVC = 4;
public static final int CAPABILITY_REFERENCE_FRAME_INVALIDATION_AV1 = 0x40;
public static final int DR_OK = 0;
public static final int DR_NEED_IDR = -1;
@@ -73,6 +74,58 @@ public class MoonBridge {
public static final int ML_TEST_RESULT_INCONCLUSIVE = 0xFFFFFFFF;
public static final byte SS_KBE_FLAG_NON_NORMALIZED = 0x01;
public static final int LI_ERR_UNSUPPORTED = -5501;
public static final byte LI_TOUCH_EVENT_HOVER = 0x00;
public static final byte LI_TOUCH_EVENT_DOWN = 0x01;
public static final byte LI_TOUCH_EVENT_UP = 0x02;
public static final byte LI_TOUCH_EVENT_MOVE = 0x03;
public static final byte LI_TOUCH_EVENT_CANCEL = 0x04;
public static final byte LI_TOUCH_EVENT_BUTTON_ONLY = 0x05;
public static final byte LI_TOUCH_EVENT_HOVER_LEAVE = 0x06;
public static final byte LI_TOUCH_EVENT_CANCEL_ALL = 0x07;
public static final byte LI_TOOL_TYPE_UNKNOWN = 0x00;
public static final byte LI_TOOL_TYPE_PEN = 0x01;
public static final byte LI_TOOL_TYPE_ERASER = 0x02;
public static final byte LI_PEN_BUTTON_PRIMARY = 0x01;
public static final byte LI_PEN_BUTTON_SECONDARY = 0x02;
public static final byte LI_PEN_BUTTON_TERTIARY = 0x04;
public static final byte LI_TILT_UNKNOWN = (byte)0xFF;
public static final short LI_ROT_UNKNOWN = (short)0xFFFF;
public static final byte LI_CTYPE_UNKNOWN = 0x00;
public static final byte LI_CTYPE_XBOX = 0x01;
public static final byte LI_CTYPE_PS = 0x02;
public static final byte LI_CTYPE_NINTENDO = 0x03;
public static final byte LI_CTYPE_STEAM = 0x04;
public static final short LI_CCAP_ANALOG_TRIGGERS = 0x01;
public static final short LI_CCAP_RUMBLE = 0x02;
public static final short LI_CCAP_TRIGGER_RUMBLE = 0x04;
public static final short LI_CCAP_TOUCHPAD = 0x08;
public static final short LI_CCAP_ACCEL = 0x10;
public static final short LI_CCAP_GYRO = 0x20;
public static final short LI_CCAP_BATTERY_STATE = 0x40;
public static final short LI_CCAP_RGB_LED = 0x80;
public static final short LI_CCAP_DUAL_TOUCHPAD = 0x100;
public static final byte LI_MOTION_TYPE_ACCEL = 0x01;
public static final byte LI_MOTION_TYPE_GYRO = 0x02;
public static final byte LI_BATTERY_STATE_UNKNOWN = 0x00;
public static final byte LI_BATTERY_STATE_NOT_PRESENT = 0x01;
public static final byte LI_BATTERY_STATE_DISCHARGING = 0x02;
public static final byte LI_BATTERY_STATE_CHARGING = 0x03;
public static final byte LI_BATTERY_STATE_NOT_CHARGING = 0x04; // Connected to power but not charging
public static final byte LI_BATTERY_STATE_FULL = 0x05;
public static final byte LI_BATTERY_PERCENTAGE_UNKNOWN = (byte)0xFF;
private static AudioRenderer audioRenderer;
private static VideoDecoderRenderer videoRenderer;
private static NvConnectionListener connectionListener;
@@ -165,11 +218,11 @@ public class MoonBridge {
}
public static int bridgeDrSubmitDecodeUnit(byte[] decodeUnitData, int decodeUnitLength, int decodeUnitType,
int frameNumber, int frameType,
long receiveTimeMs, long enqueueTimeMs) {
int frameNumber, int frameType, char frameHostProcessingLatency,
long receiveTimeUs, long enqueueTimeUs) {
if (videoRenderer != null) {
return videoRenderer.submitDecodeUnit(decodeUnitData, decodeUnitLength,
decodeUnitType, frameNumber, frameType, receiveTimeMs, enqueueTimeMs);
decodeUnitType, frameNumber, frameType, frameHostProcessingLatency, receiveTimeUs, enqueueTimeUs);
}
else {
return DR_OK;
@@ -251,9 +304,27 @@ public class MoonBridge {
}
}
public static void bridgeClSetHdrMode(boolean enabled) {
public static void bridgeClSetHdrMode(boolean enabled, byte[] hdrMetadata) {
if (connectionListener != null) {
connectionListener.setHdrMode(enabled);
connectionListener.setHdrMode(enabled, hdrMetadata);
}
}
public static void bridgeClRumbleTriggers(short controllerNumber, short leftTrigger, short rightTrigger) {
if (connectionListener != null) {
connectionListener.rumbleTriggers(controllerNumber, leftTrigger, rightTrigger);
}
}
public static void bridgeClSetMotionEventState(short controllerNumber, byte eventType, short sampleRateHz) {
if (connectionListener != null) {
connectionListener.setMotionEventState(controllerNumber, eventType, sampleRateHz);
}
}
public static void bridgeClSetControllerLED(short controllerNumber, byte r, byte g, byte b) {
if (connectionListener != null) {
connectionListener.setControllerLED(controllerNumber, r, g, b);
}
}
@@ -270,14 +341,11 @@ public class MoonBridge {
}
public static native int startConnection(String address, String appVersion, String gfeVersion,
String rtspSessionUrl,
String rtspSessionUrl, int serverCodecModeSupport,
int width, int height, int fps,
int bitrate, int packetSize, int streamingRemotely,
int audioConfiguration, boolean supportsHevc,
boolean enableHdr,
int hevcBitratePercentageMultiplier,
int audioConfiguration, int supportedVideoFormats,
int clientRefreshRateX100,
int encryptionFlags,
byte[] riAesKey, byte[] riAesIv,
int videoCapabilities,
int colorSpace, int colorRange);
@@ -295,22 +363,32 @@ public class MoonBridge {
public static native void sendMouseButton(byte buttonEvent, byte mouseButton);
public static native void sendMultiControllerInput(short controllerNumber,
short activeGamepadMask, short buttonFlags,
short activeGamepadMask, int buttonFlags,
byte leftTrigger, byte rightTrigger,
short leftStickX, short leftStickY,
short rightStickX, short rightStickY);
public static native void sendControllerInput(short buttonFlags,
byte leftTrigger, byte rightTrigger,
short leftStickX, short leftStickY,
short rightStickX, short rightStickY);
public static native int sendTouchEvent(byte eventType, int pointerId, float x, float y, float pressure,
float contactAreaMajor, float contactAreaMinor, short rotation);
public static native void sendKeyboardInput(short keyMap, byte keyDirection, byte modifier);
public static native int sendPenEvent(byte eventType, byte toolType, byte penButtons, float x, float y,
float pressure, float contactAreaMajor, float contactAreaMinor,
short rotation, byte tilt);
public static native void sendMouseScroll(byte scrollClicks);
public static native int sendControllerArrivalEvent(byte controllerNumber, short activeGamepadMask, byte type, int supportedButtonFlags, short capabilities);
public static native int sendControllerTouchEvent(byte controllerNumber, byte eventType, int pointerId, float x, float y, float pressure);
public static native int sendControllerMotionEvent(byte controllerNumber, byte motionType, float x, float y, float z);
public static native int sendControllerBatteryEvent(byte controllerNumber, byte batteryState, byte batteryPercentage);
public static native void sendKeyboardInput(short keyMap, byte keyDirection, byte modifier, byte flags);
public static native void sendMouseHighResScroll(short scrollAmount);
public static native void sendMouseHighResHScroll(short scrollAmount);
public static native void sendUtf8Text(String text);
public static native String getStageName(int stage);
@@ -332,5 +410,13 @@ public class MoonBridge {
// The RTT is in the top 32 bits, and the RTT variance is in the bottom 32 bits
public static native long getEstimatedRttInfo();
public static native String getLaunchUrlQueryParameters();
public static native byte guessControllerType(int vendorId, int productId);
public static native boolean guessControllerHasPaddles(int vendorId, int productId);
public static native boolean guessControllerHasShareButton(int vendorId, int productId);
public static native void init();
}
@@ -0,0 +1,269 @@
package com.limelight.nvstream.mdns;
import android.content.Context;
import android.net.wifi.WifiManager;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.ArrayList;
import java.util.HashSet;
import javax.jmdns.JmmDNS;
import javax.jmdns.NetworkTopologyDiscovery;
import javax.jmdns.ServiceEvent;
import javax.jmdns.ServiceInfo;
import javax.jmdns.ServiceListener;
import javax.jmdns.impl.NetworkTopologyDiscoveryImpl;
import com.limelight.LimeLog;
public class JmDNSDiscoveryAgent extends MdnsDiscoveryAgent implements ServiceListener {
private static final String SERVICE_TYPE = "_nvstream._tcp.local.";
private WifiManager.MulticastLock multicastLock;
private Thread discoveryThread;
private HashSet<String> pendingResolution = new HashSet<>();
// The resolver factory's instance member has a static lifetime which
// means our ref count and listener must be static also.
private static int resolverRefCount = 0;
private static HashSet<ServiceListener> listeners = new HashSet<>();
private static ServiceListener nvstreamListener = new ServiceListener() {
@Override
public void serviceAdded(ServiceEvent event) {
HashSet<ServiceListener> localListeners;
// Copy the listener set into a new set so we can invoke
// the callbacks without holding the listeners monitor the
// whole time.
synchronized (listeners) {
localListeners = new HashSet<ServiceListener>(listeners);
}
for (ServiceListener listener : localListeners) {
listener.serviceAdded(event);
}
}
@Override
public void serviceRemoved(ServiceEvent event) {
HashSet<ServiceListener> localListeners;
// Copy the listener set into a new set so we can invoke
// the callbacks without holding the listeners monitor the
// whole time.
synchronized (listeners) {
localListeners = new HashSet<ServiceListener>(listeners);
}
for (ServiceListener listener : localListeners) {
listener.serviceRemoved(event);
}
}
@Override
public void serviceResolved(ServiceEvent event) {
HashSet<ServiceListener> localListeners;
// Copy the listener set into a new set so we can invoke
// the callbacks without holding the listeners monitor the
// whole time.
synchronized (listeners) {
localListeners = new HashSet<ServiceListener>(listeners);
}
for (ServiceListener listener : localListeners) {
listener.serviceResolved(event);
}
}
};
public static class MyNetworkTopologyDiscovery extends NetworkTopologyDiscoveryImpl {
@Override
public boolean useInetAddress(NetworkInterface networkInterface, InetAddress interfaceAddress) {
// This is an copy of jmDNS's implementation, except we omit the multicast check, since
// it seems at least some devices lie about interfaces not supporting multicast when they really do.
try {
if (!networkInterface.isUp()) {
return false;
}
/*
if (!networkInterface.supportsMulticast()) {
return false;
}
*/
if (networkInterface.isLoopback()) {
return false;
}
return true;
} catch (Exception exception) {
return false;
}
}
}
static {
// Override jmDNS's default topology discovery class with ours
NetworkTopologyDiscovery.Factory.setClassDelegate(new NetworkTopologyDiscovery.Factory.ClassDelegate() {
@Override
public NetworkTopologyDiscovery newNetworkTopologyDiscovery() {
return new MyNetworkTopologyDiscovery();
}
});
}
private static JmmDNS referenceResolver() {
synchronized (JmDNSDiscoveryAgent.class) {
JmmDNS instance = JmmDNS.Factory.getInstance();
if (++resolverRefCount == 1) {
// This will cause the listener to be invoked for known hosts immediately.
// JmDNS only supports one listener per service, so we have to do this here
// with a static listener.
instance.addServiceListener(SERVICE_TYPE, nvstreamListener);
}
return instance;
}
}
private static void dereferenceResolver() {
synchronized (JmDNSDiscoveryAgent.class) {
if (--resolverRefCount == 0) {
try {
JmmDNS.Factory.close();
} catch (IOException e) {}
}
}
}
public JmDNSDiscoveryAgent(Context context, MdnsDiscoveryListener listener) {
super(listener);
// Create the multicast lock required to receive mDNS traffic
WifiManager wifiMgr = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
multicastLock = wifiMgr.createMulticastLock("Limelight mDNS");
multicastLock.setReferenceCounted(false);
}
private void handleResolvedServiceInfo(ServiceInfo info) {
synchronized (pendingResolution) {
pendingResolution.remove(info.getName());
}
try {
handleServiceInfo(info);
} catch (UnsupportedEncodingException e) {
// Invalid DNS response
LimeLog.info("mDNS: Invalid response for machine: "+info.getName());
return;
}
}
private void handleServiceInfo(ServiceInfo info) throws UnsupportedEncodingException {
reportNewComputer(info.getName(), info.getPort(), info.getInet4Addresses(), info.getInet6Addresses());
}
public void startDiscovery(final int discoveryIntervalMs) {
// Kill any existing discovery before starting a new one
stopDiscovery();
// Acquire the multicast lock to start receiving mDNS traffic
multicastLock.acquire();
// Add our listener to the set
synchronized (listeners) {
listeners.add(JmDNSDiscoveryAgent.this);
}
discoveryThread = new Thread() {
@Override
public void run() {
// This may result in listener callbacks so we must register
// our listener first.
JmmDNS resolver = referenceResolver();
try {
while (!Thread.interrupted()) {
// Start an mDNS request
resolver.requestServiceInfo(SERVICE_TYPE, null, discoveryIntervalMs);
// Run service resolution again for pending machines
ArrayList<String> pendingNames;
synchronized (pendingResolution) {
pendingNames = new ArrayList<String>(pendingResolution);
}
for (String name : pendingNames) {
LimeLog.info("mDNS: Retrying service resolution for machine: "+name);
ServiceInfo[] infos = resolver.getServiceInfos(SERVICE_TYPE, name, 500);
if (infos != null && infos.length != 0) {
LimeLog.info("mDNS: Resolved (retry) with "+infos.length+" service entries");
for (ServiceInfo svcinfo : infos) {
handleResolvedServiceInfo(svcinfo);
}
}
}
// Wait for the next polling interval
try {
Thread.sleep(discoveryIntervalMs);
} catch (InterruptedException e) {
break;
}
}
}
finally {
// Dereference the resolver
dereferenceResolver();
}
}
};
discoveryThread.setName("mDNS Discovery Thread");
discoveryThread.start();
}
public void stopDiscovery() {
// Release the multicast lock to stop receiving mDNS traffic
multicastLock.release();
// Remove our listener from the set
synchronized (listeners) {
listeners.remove(JmDNSDiscoveryAgent.this);
}
// If there's already a running thread, interrupt it
if (discoveryThread != null) {
discoveryThread.interrupt();
discoveryThread = null;
}
}
@Override
public void serviceAdded(ServiceEvent event) {
LimeLog.info("mDNS: Machine appeared: "+event.getInfo().getName());
ServiceInfo info = event.getDNS().getServiceInfo(SERVICE_TYPE, event.getInfo().getName(), 500);
if (info == null) {
// This machine is pending resolution
synchronized (pendingResolution) {
pendingResolution.add(event.getInfo().getName());
}
return;
}
LimeLog.info("mDNS: Resolved (blocking)");
handleResolvedServiceInfo(info);
}
@Override
public void serviceRemoved(ServiceEvent event) {
LimeLog.info("mDNS: Machine disappeared: "+event.getInfo().getName());
}
@Override
public void serviceResolved(ServiceEvent event) {
// We handle this synchronously
}
}
@@ -1,166 +1,64 @@
package com.limelight.nvstream.mdns;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import javax.jmdns.JmmDNS;
import javax.jmdns.NetworkTopologyDiscovery;
import javax.jmdns.ServiceEvent;
import javax.jmdns.ServiceInfo;
import javax.jmdns.ServiceListener;
import javax.jmdns.impl.NetworkTopologyDiscoveryImpl;
import com.limelight.LimeLog;
public class MdnsDiscoveryAgent implements ServiceListener {
public static final String SERVICE_TYPE = "_nvstream._tcp.local.";
private MdnsDiscoveryListener listener;
private Thread discoveryThread;
private HashMap<InetAddress, MdnsComputer> computers = new HashMap<InetAddress, MdnsComputer>();
private HashSet<String> pendingResolution = new HashSet<String>();
// The resolver factory's instance member has a static lifetime which
// means our ref count and listener must be static also.
private static int resolverRefCount = 0;
private static HashSet<ServiceListener> listeners = new HashSet<ServiceListener>();
private static ServiceListener nvstreamListener = new ServiceListener() {
@Override
public void serviceAdded(ServiceEvent event) {
HashSet<ServiceListener> localListeners;
// Copy the listener set into a new set so we can invoke
// the callbacks without holding the listeners monitor the
// whole time.
synchronized (listeners) {
localListeners = new HashSet<ServiceListener>(listeners);
}
for (ServiceListener listener : localListeners) {
listener.serviceAdded(event);
}
}
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
@Override
public void serviceRemoved(ServiceEvent event) {
HashSet<ServiceListener> localListeners;
// Copy the listener set into a new set so we can invoke
// the callbacks without holding the listeners monitor the
// whole time.
synchronized (listeners) {
localListeners = new HashSet<ServiceListener>(listeners);
}
for (ServiceListener listener : localListeners) {
listener.serviceRemoved(event);
}
}
public abstract class MdnsDiscoveryAgent {
protected MdnsDiscoveryListener listener;
@Override
public void serviceResolved(ServiceEvent event) {
HashSet<ServiceListener> localListeners;
// Copy the listener set into a new set so we can invoke
// the callbacks without holding the listeners monitor the
// whole time.
synchronized (listeners) {
localListeners = new HashSet<ServiceListener>(listeners);
}
for (ServiceListener listener : localListeners) {
listener.serviceResolved(event);
}
}
};
public static class MyNetworkTopologyDiscovery extends NetworkTopologyDiscoveryImpl {
@Override
public boolean useInetAddress(NetworkInterface networkInterface, InetAddress interfaceAddress) {
// This is an copy of jmDNS's implementation, except we omit the multicast check, since
// it seems at least some devices lie about interfaces not supporting multicast when they really do.
try {
if (!networkInterface.isUp()) {
return false;
}
/*
if (!networkInterface.supportsMulticast()) {
return false;
}
*/
if (networkInterface.isLoopback()) {
return false;
}
return true;
} catch (Exception exception) {
return false;
}
}
};
static {
// Override jmDNS's default topology discovery class with ours
NetworkTopologyDiscovery.Factory.setClassDelegate(new NetworkTopologyDiscovery.Factory.ClassDelegate() {
@Override
public NetworkTopologyDiscovery newNetworkTopologyDiscovery() {
return new MyNetworkTopologyDiscovery();
}
});
}
private static JmmDNS referenceResolver() {
synchronized (MdnsDiscoveryAgent.class) {
JmmDNS instance = JmmDNS.Factory.getInstance();
if (++resolverRefCount == 1) {
// This will cause the listener to be invoked for known hosts immediately.
// JmDNS only supports one listener per service, so we have to do this here
// with a static listener.
instance.addServiceListener(SERVICE_TYPE, nvstreamListener);
}
return instance;
}
}
private static void dereferenceResolver() {
synchronized (MdnsDiscoveryAgent.class) {
if (--resolverRefCount == 0) {
try {
JmmDNS.Factory.close();
} catch (IOException e) {}
}
}
}
protected HashSet<MdnsComputer> computers = new HashSet<>();
public MdnsDiscoveryAgent(MdnsDiscoveryListener listener) {
this.listener = listener;
}
private void handleResolvedServiceInfo(ServiceInfo info) {
synchronized (pendingResolution) {
pendingResolution.remove(info.getName());
public abstract void startDiscovery(final int discoveryIntervalMs);
public abstract void stopDiscovery();
protected void reportNewComputer(String name, int port, Inet4Address[] v4Addrs, Inet6Address[] v6Addrs) {
LimeLog.info("mDNS: "+name+" has "+v4Addrs.length+" IPv4 addresses");
LimeLog.info("mDNS: "+name+" has "+v6Addrs.length+" IPv6 addresses");
Inet6Address v6GlobalAddr = getBestIpv6Address(v6Addrs);
// Add a computer object for each IPv4 address reported by the PC
for (Inet4Address v4Addr : v4Addrs) {
synchronized (computers) {
MdnsComputer computer = new MdnsComputer(name, v4Addr, v6GlobalAddr, port);
if (computers.add(computer)) {
// This was a new entry
listener.notifyComputerAdded(computer);
}
}
}
try {
handleServiceInfo(info);
} catch (UnsupportedEncodingException e) {
// Invalid DNS response
LimeLog.info("mDNS: Invalid response for machine: "+info.getName());
return;
// If there were no IPv4 addresses, use IPv6 for registration
if (v4Addrs.length == 0) {
Inet6Address v6LocalAddr = getLocalAddress(v6Addrs);
if (v6LocalAddr != null || v6GlobalAddr != null) {
MdnsComputer computer = new MdnsComputer(name, v6LocalAddr, v6GlobalAddr, port);
if (computers.add(computer)) {
// This was a new entry
listener.notifyComputerAdded(computer);
}
}
}
}
private Inet6Address getLocalAddress(Inet6Address[] addresses) {
public List<MdnsComputer> getComputerSet() {
synchronized (computers) {
return new ArrayList<>(computers);
}
}
protected static Inet6Address getLocalAddress(Inet6Address[] addresses) {
for (Inet6Address addr : addresses) {
if (addr.isLinkLocalAddress() || addr.isSiteLocalAddress()) {
return addr;
@@ -174,7 +72,7 @@ public class MdnsDiscoveryAgent implements ServiceListener {
return null;
}
private Inet6Address getLinkLocalAddress(Inet6Address[] addresses) {
protected static Inet6Address getLinkLocalAddress(Inet6Address[] addresses) {
for (Inet6Address addr : addresses) {
if (addr.isLinkLocalAddress()) {
LimeLog.info("Found link-local address: "+addr.getHostAddress());
@@ -185,7 +83,7 @@ public class MdnsDiscoveryAgent implements ServiceListener {
return null;
}
private Inet6Address getBestIpv6Address(Inet6Address[] addresses) {
protected static Inet6Address getBestIpv6Address(Inet6Address[] addresses) {
// First try to find a link local address, so we can match the interface identifier
// with a global address (this will work for SLAAC but not DHCPv6).
Inet6Address linkLocalAddr = getLinkLocalAddress(addresses);
@@ -247,162 +145,4 @@ public class MdnsDiscoveryAgent implements ServiceListener {
return null;
}
private void handleServiceInfo(ServiceInfo info) throws UnsupportedEncodingException {
Inet4Address v4Addrs[] = info.getInet4Addresses();
Inet6Address v6Addrs[] = info.getInet6Addresses();
LimeLog.info("mDNS: "+info.getName()+" has "+v4Addrs.length+" IPv4 addresses");
LimeLog.info("mDNS: "+info.getName()+" has "+v6Addrs.length+" IPv6 addresses");
Inet6Address v6GlobalAddr = getBestIpv6Address(v6Addrs);
// Add a computer object for each IPv4 address reported by the PC
for (Inet4Address v4Addr : v4Addrs) {
synchronized (computers) {
MdnsComputer computer = new MdnsComputer(info.getName(), v4Addr, v6GlobalAddr, info.getPort());
if (computers.put(computer.getLocalAddress(), computer) == null) {
// This was a new entry
listener.notifyComputerAdded(computer);
}
}
}
// If there were no IPv4 addresses, use IPv6 for registration
if (v4Addrs.length == 0) {
Inet6Address v6LocalAddr = getLocalAddress(v6Addrs);
if (v6LocalAddr != null || v6GlobalAddr != null) {
MdnsComputer computer = new MdnsComputer(info.getName(), v6LocalAddr, v6GlobalAddr, info.getPort());
if (computers.put(v6LocalAddr != null ?
computer.getLocalAddress() : computer.getIpv6Address(), computer) == null) {
// This was a new entry
listener.notifyComputerAdded(computer);
}
}
}
}
public void startDiscovery(final int discoveryIntervalMs) {
// Kill any existing discovery before starting a new one
stopDiscovery();
// Add our listener to the set
synchronized (listeners) {
listeners.add(MdnsDiscoveryAgent.this);
}
discoveryThread = new Thread() {
@Override
public void run() {
// This may result in listener callbacks so we must register
// our listener first.
JmmDNS resolver = referenceResolver();
try {
while (!Thread.interrupted()) {
// Start an mDNS request
resolver.requestServiceInfo(SERVICE_TYPE, null, discoveryIntervalMs);
// Run service resolution again for pending machines
ArrayList<String> pendingNames;
synchronized (pendingResolution) {
pendingNames = new ArrayList<String>(pendingResolution);
}
for (String name : pendingNames) {
LimeLog.info("mDNS: Retrying service resolution for machine: "+name);
ServiceInfo[] infos = resolver.getServiceInfos(SERVICE_TYPE, name, 500);
if (infos != null && infos.length != 0) {
LimeLog.info("mDNS: Resolved (retry) with "+infos.length+" service entries");
for (ServiceInfo svcinfo : infos) {
handleResolvedServiceInfo(svcinfo);
}
}
}
// Wait for the next polling interval
try {
Thread.sleep(discoveryIntervalMs);
} catch (InterruptedException e) {
break;
}
}
}
finally {
// Dereference the resolver
dereferenceResolver();
}
}
};
discoveryThread.setName("mDNS Discovery Thread");
discoveryThread.start();
}
public void stopDiscovery() {
// Remove our listener from the set
synchronized (listeners) {
listeners.remove(MdnsDiscoveryAgent.this);
}
// If there's already a running thread, interrupt it
if (discoveryThread != null) {
discoveryThread.interrupt();
discoveryThread = null;
}
}
public List<MdnsComputer> getComputerSet() {
synchronized (computers) {
return new ArrayList<MdnsComputer>(computers.values());
}
}
@Override
public void serviceAdded(ServiceEvent event) {
LimeLog.info("mDNS: Machine appeared: "+event.getInfo().getName());
ServiceInfo info = event.getDNS().getServiceInfo(SERVICE_TYPE, event.getInfo().getName(), 500);
if (info == null) {
// This machine is pending resolution
synchronized (pendingResolution) {
pendingResolution.add(event.getInfo().getName());
}
return;
}
LimeLog.info("mDNS: Resolved (blocking)");
handleResolvedServiceInfo(info);
}
@Override
public void serviceRemoved(ServiceEvent event) {
LimeLog.info("mDNS: Machine disappeared: "+event.getInfo().getName());
Inet4Address v4Addrs[] = event.getInfo().getInet4Addresses();
for (Inet4Address addr : v4Addrs) {
synchronized (computers) {
MdnsComputer computer = computers.remove(addr);
if (computer != null) {
listener.notifyComputerRemoved(computer);
break;
}
}
}
Inet6Address v6Addrs[] = event.getInfo().getInet6Addresses();
for (Inet6Address addr : v6Addrs) {
synchronized (computers) {
MdnsComputer computer = computers.remove(addr);
if (computer != null) {
listener.notifyComputerRemoved(computer);
break;
}
}
}
}
@Override
public void serviceResolved(ServiceEvent event) {
// We handle this synchronously
}
}
@@ -2,6 +2,5 @@ package com.limelight.nvstream.mdns;
public interface MdnsDiscoveryListener {
void notifyComputerAdded(MdnsComputer computer);
void notifyComputerRemoved(MdnsComputer computer);
void notifyDiscoveryFailure(Exception e);
}
@@ -0,0 +1,234 @@
package com.limelight.nvstream.mdns;
import android.annotation.TargetApi;
import android.content.Context;
import android.net.nsd.NsdManager;
import android.net.nsd.NsdServiceInfo;
import android.os.Build;
import com.limelight.LimeLog;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@TargetApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public class NsdManagerDiscoveryAgent extends MdnsDiscoveryAgent {
private static final String SERVICE_TYPE = "_nvstream._tcp";
private final NsdManager nsdManager;
private final Object listenerLock = new Object();
private NsdManager.DiscoveryListener pendingListener;
private NsdManager.DiscoveryListener activeListener;
private final HashMap<String, NsdManager.ServiceInfoCallback> serviceCallbacks = new HashMap<>();
private final ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 0, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
private NsdManager.DiscoveryListener createDiscoveryListener() {
return new NsdManager.DiscoveryListener() {
@Override
public void onStartDiscoveryFailed(String serviceType, int errorCode) {
LimeLog.severe("NSD: Service discovery start failed: " + errorCode);
// This listener is no longer pending after this failure
synchronized (listenerLock) {
if (pendingListener != this) {
return;
}
pendingListener = null;
}
listener.notifyDiscoveryFailure(new RuntimeException("onStartDiscoveryFailed(): " + errorCode));
}
@Override
public void onStopDiscoveryFailed(String serviceType, int errorCode) {
LimeLog.severe("NSD: Service discovery stop failed: " + errorCode);
// This listener is no longer active after this failure
synchronized (listenerLock) {
if (activeListener != this) {
return;
}
activeListener = null;
}
}
@Override
public void onDiscoveryStarted(String serviceType) {
LimeLog.info("NSD: Service discovery started");
synchronized (listenerLock) {
if (pendingListener != this) {
// If we registered another discovery listener in the meantime, stop this one
nsdManager.stopServiceDiscovery(this);
return;
}
pendingListener = null;
activeListener = this;
}
}
@Override
public void onDiscoveryStopped(String serviceType) {
LimeLog.info("NSD: Service discovery stopped");
synchronized (listenerLock) {
if (activeListener != this) {
return;
}
activeListener = null;
}
}
@Override
public void onServiceFound(NsdServiceInfo nsdServiceInfo) {
// Protect against racing stopDiscovery() call
synchronized (listenerLock) {
// Ignore callbacks if we're not the active listener
if (activeListener != this) {
return;
}
LimeLog.info("NSD: Machine appeared: " + nsdServiceInfo.getServiceName());
NsdManager.ServiceInfoCallback serviceInfoCallback = new NsdManager.ServiceInfoCallback() {
@Override
public void onServiceInfoCallbackRegistrationFailed(int errorCode) {
LimeLog.severe("NSD: Service info callback registration failed: " + errorCode);
listener.notifyDiscoveryFailure(new RuntimeException("onServiceInfoCallbackRegistrationFailed(): " + errorCode));
}
@Override
public void onServiceUpdated(NsdServiceInfo nsdServiceInfo) {
LimeLog.info("NSD: Machine resolved: " + nsdServiceInfo.getServiceName());
reportNewComputer(nsdServiceInfo.getServiceName(), nsdServiceInfo.getPort(),
getV4Addrs(nsdServiceInfo.getHostAddresses()),
getV6Addrs(nsdServiceInfo.getHostAddresses()));
}
@Override
public void onServiceLost() {
}
@Override
public void onServiceInfoCallbackUnregistered() {
}
};
nsdManager.registerServiceInfoCallback(nsdServiceInfo, executor, serviceInfoCallback);
serviceCallbacks.put(nsdServiceInfo.getServiceName(), serviceInfoCallback);
}
}
@Override
public void onServiceLost(NsdServiceInfo nsdServiceInfo) {
// Protect against racing stopDiscovery() call
synchronized (listenerLock) {
// Ignore callbacks if we're not the active listener
if (activeListener != this) {
return;
}
LimeLog.info("NSD: Machine lost: " + nsdServiceInfo.getServiceName());
NsdManager.ServiceInfoCallback serviceInfoCallback = serviceCallbacks.remove(nsdServiceInfo.getServiceName());
if (serviceInfoCallback != null) {
nsdManager.unregisterServiceInfoCallback(serviceInfoCallback);
}
}
}
};
}
public NsdManagerDiscoveryAgent(Context context, MdnsDiscoveryListener listener) {
super(listener);
this.nsdManager = context.getSystemService(NsdManager.class);
}
@Override
public void startDiscovery(int discoveryIntervalMs) {
synchronized (listenerLock) {
// Register a new service discovery listener if there's not already one starting or running
if (pendingListener == null && activeListener == null) {
pendingListener = createDiscoveryListener();
nsdManager.discoverServices(SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, pendingListener);
}
}
}
@Override
public void stopDiscovery() {
// Protect against racing ServiceInfoCallback and DiscoveryListener callbacks
synchronized (listenerLock) {
// Clear any pending listener to ensure the discoverStarted() callback
// will realize it's gone and stop itself.
pendingListener = null;
// Unregister the service discovery listener
if (activeListener != null) {
nsdManager.stopServiceDiscovery(activeListener);
// Even though listener stoppage is asynchronous, the listener is gone as far as
// we're concerned. We null this right now to ensure pending callbacks know it's
// stopped and startDiscovery() can immediately create a new listener. If we left
// it until onDiscoveryStopped() was called, startDiscovery() would get confused
// and assume a listener was already running, even though it's stopping.
activeListener = null;
}
// Unregister all service info callbacks
for (NsdManager.ServiceInfoCallback callback : serviceCallbacks.values()) {
nsdManager.unregisterServiceInfoCallback(callback);
}
serviceCallbacks.clear();
}
}
private static Inet4Address[] getV4Addrs(List<InetAddress> addrs) {
int matchCount = 0;
for (InetAddress addr : addrs) {
if (addr instanceof Inet4Address) {
matchCount++;
}
}
Inet4Address[] matching = new Inet4Address[matchCount];
int i = 0;
for (InetAddress addr : addrs) {
if (addr instanceof Inet4Address) {
matching[i++] = (Inet4Address) addr;
}
}
return matching;
}
private static Inet6Address[] getV6Addrs(List<InetAddress> addrs) {
int matchCount = 0;
for (InetAddress addr : addrs) {
if (addr instanceof Inet6Address) {
matchCount++;
}
}
Inet6Address[] matching = new Inet6Address[matchCount];
int i = 0;
for (InetAddress addr : addrs) {
if (addr instanceof Inet6Address) {
matching[i++] = (Inet6Address) addr;
}
}
return matching;
}
}
@@ -77,8 +77,21 @@ public class WakeOnLanSender {
try {
sendPacketsForAddress(InetAddress.getByName("255.255.255.255"), address.port, sock, payload);
sentWolPacket = true;
} catch (IOException e) {
e.printStackTrace();
lastException = e;
}
try {
for (InetAddress resolvedAddress : InetAddress.getAllByName(address.address)) {
sendPacketsForAddress(resolvedAddress, address.port, sock, payload);
try {
sendPacketsForAddress(resolvedAddress, address.port, sock, payload);
sentWolPacket = true;
} catch (IOException e) {
e.printStackTrace();
lastException = e;
}
}
} catch (IOException e) {
// We may have addresses that don't resolve on this subnet,
@@ -13,7 +13,6 @@ import com.limelight.R;
import static com.limelight.binding.input.virtual_controller.VirtualControllerConfigurationLoader.OSC_PREFERENCE;
public class ConfirmDeleteOscPreference extends DialogPreference {
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public ConfirmDeleteOscPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@@ -26,7 +25,6 @@ public class ConfirmDeleteOscPreference extends DialogPreference {
super(context, attrs);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public ConfirmDeleteOscPreference(Context context) {
super(context);
}
@@ -11,12 +11,10 @@ import android.provider.Settings;
import android.util.AttributeSet;
public class LanguagePreference extends ListPreference {
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public LanguagePreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public LanguagePreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@@ -10,6 +10,19 @@ import android.view.Display;
import com.limelight.nvstream.jni.MoonBridge;
public class PreferenceConfiguration {
public enum FormatOption {
AUTO,
FORCE_AV1,
FORCE_HEVC,
FORCE_H264,
};
public enum AnalogStickForScrolling {
NONE,
RIGHT,
LEFT
}
private static final String LEGACY_RES_FPS_PREF_STRING = "list_resolution_fps";
private static final String LEGACY_ENABLE_51_SURROUND_PREF_STRING = "checkbox_51_surround";
@@ -31,16 +44,19 @@ public class PreferenceConfiguration {
private static final String VIDEO_FORMAT_PREF_STRING = "video_format";
private static final String ONSCREEN_CONTROLLER_PREF_STRING = "checkbox_show_onscreen_controls";
private static final String ONLY_L3_R3_PREF_STRING = "checkbox_only_show_L3R3";
private static final String SHOW_GUIDE_BUTTON_PREF_STRING = "checkbox_show_guide_button";
private static final String LEGACY_DISABLE_FRAME_DROP_PREF_STRING = "checkbox_disable_frame_drop";
private static final String ENABLE_HDR_PREF_STRING = "checkbox_enable_hdr";
private static final String ENABLE_PIP_PREF_STRING = "checkbox_enable_pip";
private static final String ENABLE_PERF_OVERLAY_STRING = "checkbox_enable_perf_overlay";
private static final String BIND_ALL_USB_STRING = "checkbox_usb_bind_all";
private static final String MOUSE_EMULATION_STRING = "checkbox_mouse_emulation";
private static final String ANALOG_SCROLLING_PREF_STRING = "analog_scrolling";
private static final String MOUSE_NAV_BUTTONS_STRING = "checkbox_mouse_nav_buttons";
static final String UNLOCK_FPS_STRING = "checkbox_unlock_fps";
private static final String VIBRATE_OSC_PREF_STRING = "checkbox_vibrate_osc";
private static final String VIBRATE_FALLBACK_PREF_STRING = "checkbox_vibrate_fallback";
private static final String VIBRATE_FALLBACK_STRENGTH_PREF_STRING = "seekbar_vibrate_fallback_strength";
private static final String FLIP_FACE_BUTTONS_PREF_STRING = "checkbox_flip_face_buttons";
private static final String TOUCHSCREEN_TRACKPAD_PREF_STRING = "checkbox_touchscreen_trackpad";
private static final String LATENCY_TOAST_PREF_STRING = "checkbox_enable_post_stream_toast";
@@ -49,6 +65,9 @@ public class PreferenceConfiguration {
private static final String ENABLE_AUDIO_FX_PREF_STRING = "checkbox_enable_audiofx";
private static final String REDUCE_REFRESH_RATE_PREF_STRING = "checkbox_reduce_refresh_rate";
private static final String FULL_RANGE_PREF_STRING = "checkbox_full_range";
private static final String GAMEPAD_TOUCHPAD_AS_MOUSE_PREF_STRING = "checkbox_gamepad_touchpad_as_mouse";
private static final String GAMEPAD_MOTION_SENSORS_PREF_STRING = "checkbox_gamepad_motion_sensors";
private static final String GAMEPAD_MOTION_FALLBACK_PREF_STRING = "checkbox_gamepad_motion_fallback";
static final String DEFAULT_RESOLUTION = "1280x720";
static final String DEFAULT_FPS = "60";
@@ -62,17 +81,21 @@ public class PreferenceConfiguration {
private static final boolean DEFAULT_MULTI_CONTROLLER = true;
private static final boolean DEFAULT_USB_DRIVER = true;
private static final String DEFAULT_VIDEO_FORMAT = "auto";
private static final boolean ONSCREEN_CONTROLLER_DEFAULT = false;
private static final boolean ONLY_L3_R3_DEFAULT = false;
private static final boolean SHOW_GUIDE_BUTTON_DEFAULT = true;
private static final boolean DEFAULT_ENABLE_HDR = false;
private static final boolean DEFAULT_ENABLE_PIP = false;
private static final boolean DEFAULT_ENABLE_PERF_OVERLAY = false;
private static final boolean DEFAULT_BIND_ALL_USB = false;
private static final boolean DEFAULT_MOUSE_EMULATION = true;
private static final String DEFAULT_ANALOG_STICK_FOR_SCROLLING = "right";
private static final boolean DEFAULT_MOUSE_NAV_BUTTONS = false;
private static final boolean DEFAULT_UNLOCK_FPS = false;
private static final boolean DEFAULT_VIBRATE_OSC = true;
private static final boolean DEFAULT_VIBRATE_FALLBACK = false;
private static final int DEFAULT_VIBRATE_FALLBACK_STRENGTH = 100;
private static final boolean DEFAULT_FLIP_FACE_BUTTONS = false;
private static final boolean DEFAULT_TOUCHSCREEN_TRACKPAD = true;
private static final String DEFAULT_AUDIO_CONFIG = "2"; // Stereo
@@ -82,10 +105,9 @@ public class PreferenceConfiguration {
private static final boolean DEFAULT_ENABLE_AUDIO_FX = false;
private static final boolean DEFAULT_REDUCE_REFRESH_RATE = false;
private static final boolean DEFAULT_FULL_RANGE = false;
public static final int FORCE_H265_ON = -1;
public static final int AUTOSELECT_H265 = 0;
public static final int FORCE_H265_OFF = 1;
private static final boolean DEFAULT_GAMEPAD_TOUCHPAD_AS_MOUSE = false;
private static final boolean DEFAULT_GAMEPAD_MOTION_SENSORS = true;
private static final boolean DEFAULT_GAMEPAD_MOTION_FALLBACK = false;
public static final int FRAME_PACING_MIN_LATENCY = 0;
public static final int FRAME_PACING_BALANCED = 1;
@@ -102,7 +124,7 @@ public class PreferenceConfiguration {
public int width, height, fps;
public int bitrate;
public int videoFormat;
public FormatOption videoFormat;
public int deadzonePercentage;
public int oscOpacity;
public boolean stretchVideo, enableSops, playHostAudio, disableWarnings;
@@ -110,16 +132,19 @@ public class PreferenceConfiguration {
public boolean smallIconMode, multiController, usbDriver, flipFaceButtons;
public boolean onscreenController;
public boolean onlyL3R3;
public boolean showGuideButton;
public boolean enableHdr;
public boolean enablePip;
public boolean enablePerfOverlay;
public boolean enableLatencyToast;
public boolean bindAllUsb;
public boolean mouseEmulation;
public AnalogStickForScrolling analogStickForScrolling;
public boolean mouseNavButtons;
public boolean unlockFps;
public boolean vibrateOsc;
public boolean vibrateFallbackToDevice;
public int vibrateFallbackToDeviceStrength;
public boolean touchscreenTrackpad;
public MoonBridge.AudioConfiguration audioConfiguration;
public int framePacing;
@@ -127,6 +152,9 @@ public class PreferenceConfiguration {
public boolean enableAudioFx;
public boolean reduceRefreshRate;
public boolean fullRange;
public boolean gamepadMotionSensors;
public boolean gamepadTouchpadAsMouse;
public boolean gamepadMotionSensorsFallbackToDevice;
public static boolean isNativeResolution(int width, int height) {
// It's not a native resolution if it matches an existing resolution option
@@ -233,33 +261,62 @@ public class PreferenceConfiguration {
int height = getHeightFromResolutionString(resString);
int fps = Integer.parseInt(fpsString);
// This table prefers 16:10 resolutions because they are
// only slightly more pixels than the 16:9 equivalents, so
// we don't want to bump those 16:10 resolutions up to the
// next 16:9 slot.
//
// This logic is shamelessly stolen from Moonlight Qt:
// https://github.com/moonlight-stream/moonlight-qt/blob/master/app/settings/streamingpreferences.cpp
if (width * height <= 640 * 360) {
return (int)(1000 * (fps / 30.0));
}
else if (width * height <= 854 * 480) {
return (int)(1500 * (fps / 30.0));
}
// This covers 1280x720 and 1280x800 too
else if (width * height <= 1366 * 768) {
return (int)(5000 * (fps / 30.0));
}
else if (width * height <= 1920 * 1200) {
return (int)(10000 * (fps / 30.0));
}
else if (width * height <= 2560 * 1600) {
return (int)(20000 * (fps / 30.0));
}
else /* if (width * height <= 3840 * 2160) */ {
return (int)(40000 * (fps / 30.0));
// Don't scale bitrate linearly beyond 60 FPS. It's definitely not a linear
// bitrate increase for frame rate once we get to values that high.
double frameRateFactor = (fps <= 60 ? fps : (Math.sqrt(fps / 60.f) * 60.f)) / 30.f;
// TODO: Collect some empirical data to see if these defaults make sense.
// We're just using the values that the Shield used, as we have for years.
int[] pixelVals = {
640 * 360,
854 * 480,
1280 * 720,
1920 * 1080,
2560 * 1440,
3840 * 2160,
-1,
};
int[] factorVals = {
1,
2,
5,
10,
20,
40,
-1
};
// Calculate the resolution factor by linear interpolation of the resolution table
float resolutionFactor;
int pixels = width * height;
for (int i = 0; ; i++) {
if (pixels == pixelVals[i]) {
// We can bail immediately for exact matches
resolutionFactor = factorVals[i];
break;
}
else if (pixels < pixelVals[i]) {
if (i == 0) {
// Never go below the lowest resolution entry
resolutionFactor = factorVals[i];
}
else {
// Interpolate between the entry greater than the chosen resolution (i) and the entry less than the chosen resolution (i-1)
resolutionFactor = ((float)(pixels - pixelVals[i-1]) / (pixelVals[i] - pixelVals[i-1])) * (factorVals[i] - factorVals[i-1]) + factorVals[i-1];
}
break;
}
else if (pixelVals[i] == -1) {
// Never go above the highest resolution entry
resolutionFactor = factorVals[i-1];
break;
}
}
return (int)Math.round(resolutionFactor * frameRateFactor) * 1000;
}
public static boolean getDefaultSmallMode(Context context) {
@@ -289,22 +346,25 @@ public class PreferenceConfiguration {
prefs.getString(FPS_PREF_STRING, DEFAULT_FPS));
}
private static int getVideoFormatValue(Context context) {
private static FormatOption getVideoFormatValue(Context context) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
String str = prefs.getString(VIDEO_FORMAT_PREF_STRING, DEFAULT_VIDEO_FORMAT);
if (str.equals("auto")) {
return AUTOSELECT_H265;
return FormatOption.AUTO;
}
else if (str.equals("forceav1")) {
return FormatOption.FORCE_AV1;
}
else if (str.equals("forceh265")) {
return FORCE_H265_ON;
return FormatOption.FORCE_HEVC;
}
else if (str.equals("neverh265")) {
return FORCE_H265_OFF;
return FormatOption.FORCE_H264;
}
else {
// Should never get here
return AUTOSELECT_H265;
return FormatOption.AUTO;
}
}
@@ -339,6 +399,21 @@ public class PreferenceConfiguration {
}
}
private static AnalogStickForScrolling getAnalogStickForScrollingValue(Context context) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
String str = prefs.getString(ANALOG_SCROLLING_PREF_STRING, DEFAULT_ANALOG_STICK_FOR_SCROLLING);
if (str.equals("right")) {
return AnalogStickForScrolling.RIGHT;
}
else if (str.equals("left")) {
return AnalogStickForScrolling.LEFT;
}
else {
return AnalogStickForScrolling.NONE;
}
}
public static void resetStreamingSettings(Context context) {
// We consider resolution, FPS, bitrate, HDR, and video format as "streaming settings" here
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
@@ -458,6 +533,15 @@ public class PreferenceConfiguration {
prefs.edit().putBoolean(SMALL_ICONS_PREF_STRING, getDefaultSmallMode(context)).apply();
}
if (!prefs.contains(GAMEPAD_MOTION_SENSORS_PREF_STRING) && Build.VERSION.SDK_INT == Build.VERSION_CODES.S) {
// Android 12 has a nasty bug that causes crashes when the app touches the InputDevice's
// associated InputDeviceSensorManager (just calling getSensorManager() is enough).
// As a workaround, we will override the default value for the gamepad motion sensor
// option to disabled on Android 12 to reduce the impact of this bug.
// https://cs.android.com/android/_/android/platform/frameworks/base/+/8970010a5e9f3dc5c069f56b4147552accfcbbeb
prefs.edit().putBoolean(GAMEPAD_MOTION_SENSORS_PREF_STRING, false).apply();
}
// This must happen after the preferences migration to ensure the preferences are populated
config.bitrate = prefs.getInt(BITRATE_PREF_STRING, prefs.getInt(BITRATE_PREF_OLD_STRING, 0) * 1000);
if (config.bitrate == 0) {
@@ -478,6 +562,8 @@ public class PreferenceConfiguration {
config.videoFormat = getVideoFormatValue(context);
config.framePacing = getFramePacingValue(context);
config.analogStickForScrolling = getAnalogStickForScrollingValue(context);
config.deadzonePercentage = prefs.getInt(DEADZONE_PREF_STRING, DEFAULT_DEADZONE);
config.oscOpacity = prefs.getInt(OSC_OPACITY_PREF_STRING, DEFAULT_OPACITY);
@@ -494,6 +580,7 @@ public class PreferenceConfiguration {
config.usbDriver = prefs.getBoolean(USB_DRIVER_PREF_SRING, DEFAULT_USB_DRIVER);
config.onscreenController = prefs.getBoolean(ONSCREEN_CONTROLLER_PREF_STRING, ONSCREEN_CONTROLLER_DEFAULT);
config.onlyL3R3 = prefs.getBoolean(ONLY_L3_R3_PREF_STRING, ONLY_L3_R3_DEFAULT);
config.showGuideButton = prefs.getBoolean(SHOW_GUIDE_BUTTON_PREF_STRING, SHOW_GUIDE_BUTTON_DEFAULT);
config.enableHdr = prefs.getBoolean(ENABLE_HDR_PREF_STRING, DEFAULT_ENABLE_HDR) && !isShieldAtvFirmwareWithBrokenHdr();
config.enablePip = prefs.getBoolean(ENABLE_PIP_PREF_STRING, DEFAULT_ENABLE_PIP);
config.enablePerfOverlay = prefs.getBoolean(ENABLE_PERF_OVERLAY_STRING, DEFAULT_ENABLE_PERF_OVERLAY);
@@ -503,6 +590,7 @@ public class PreferenceConfiguration {
config.unlockFps = prefs.getBoolean(UNLOCK_FPS_STRING, DEFAULT_UNLOCK_FPS);
config.vibrateOsc = prefs.getBoolean(VIBRATE_OSC_PREF_STRING, DEFAULT_VIBRATE_OSC);
config.vibrateFallbackToDevice = prefs.getBoolean(VIBRATE_FALLBACK_PREF_STRING, DEFAULT_VIBRATE_FALLBACK);
config.vibrateFallbackToDeviceStrength = prefs.getInt(VIBRATE_FALLBACK_STRENGTH_PREF_STRING, DEFAULT_VIBRATE_FALLBACK_STRENGTH);
config.flipFaceButtons = prefs.getBoolean(FLIP_FACE_BUTTONS_PREF_STRING, DEFAULT_FLIP_FACE_BUTTONS);
config.touchscreenTrackpad = prefs.getBoolean(TOUCHSCREEN_TRACKPAD_PREF_STRING, DEFAULT_TOUCHSCREEN_TRACKPAD);
config.enableLatencyToast = prefs.getBoolean(LATENCY_TOAST_PREF_STRING, DEFAULT_LATENCY_TOAST);
@@ -510,6 +598,9 @@ public class PreferenceConfiguration {
config.enableAudioFx = prefs.getBoolean(ENABLE_AUDIO_FX_PREF_STRING, DEFAULT_ENABLE_AUDIO_FX);
config.reduceRefreshRate = prefs.getBoolean(REDUCE_REFRESH_RATE_PREF_STRING, DEFAULT_REDUCE_REFRESH_RATE);
config.fullRange = prefs.getBoolean(FULL_RANGE_PREF_STRING, DEFAULT_FULL_RANGE);
config.gamepadTouchpadAsMouse = prefs.getBoolean(GAMEPAD_TOUCHPAD_AS_MOUSE_PREF_STRING, DEFAULT_GAMEPAD_TOUCHPAD_AS_MOUSE);
config.gamepadMotionSensors = prefs.getBoolean(GAMEPAD_MOTION_SENSORS_PREF_STRING, DEFAULT_GAMEPAD_MOTION_SENSORS);
config.gamepadMotionSensorsFallbackToDevice = prefs.getBoolean(GAMEPAD_MOTION_FALLBACK_PREF_STRING, DEFAULT_GAMEPAD_MOTION_FALLBACK);
return config;
}
@@ -123,6 +123,7 @@ public class StreamSettings extends Activity {
public static class SettingsFragment extends PreferenceFragment {
private int nativeResolutionStartIndex = Integer.MAX_VALUE;
private boolean nativeFramerateShown = false;
private void setValue(String preferenceKey, String value) {
ListPreference pref = (ListPreference) findPreference(preferenceKey);
@@ -130,6 +131,18 @@ public class StreamSettings extends Activity {
pref.setValue(value);
}
private void appendPreferenceEntry(ListPreference pref, String newEntryName, String newEntryValue) {
CharSequence[] newEntries = Arrays.copyOf(pref.getEntries(), pref.getEntries().length + 1);
CharSequence[] newValues = Arrays.copyOf(pref.getEntryValues(), pref.getEntryValues().length + 1);
// Add the new option
newEntries[newEntries.length - 1] = newEntryName;
newValues[newValues.length - 1] = newEntryValue;
pref.setEntries(newEntries);
pref.setEntryValues(newValues);
}
private void addNativeResolutionEntry(int nativeWidth, int nativeHeight, boolean insetsRemoved, boolean portrait) {
ListPreference pref = (ListPreference) findPreference(PreferenceConfiguration.RESOLUTION_PREF_STRING);
@@ -155,29 +168,18 @@ public class StreamSettings extends Activity {
String newValue = nativeWidth+"x"+nativeHeight;
CharSequence[] values = pref.getEntryValues();
// Check if the native resolution is already present
for (CharSequence value : values) {
for (CharSequence value : pref.getEntryValues()) {
if (newValue.equals(value.toString())) {
// It is present in the default list, so don't add it again
return;
}
}
CharSequence[] newEntries = Arrays.copyOf(pref.getEntries(), pref.getEntries().length + 1);
CharSequence[] newValues = Arrays.copyOf(values, values.length + 1);
// Add the new native option
newEntries[newEntries.length - 1] = newName;
newValues[newValues.length - 1] = newValue;
pref.setEntries(newEntries);
pref.setEntryValues(newValues);
if (newValues.length - 1 < nativeResolutionStartIndex) {
nativeResolutionStartIndex = newValues.length - 1;
if (pref.getEntryValues().length < nativeResolutionStartIndex) {
nativeResolutionStartIndex = pref.getEntryValues().length;
}
appendPreferenceEntry(pref, newName, newValue);
}
private void addNativeResolutionEntries(int nativeWidth, int nativeHeight, boolean insetsRemoved) {
@@ -187,6 +189,30 @@ public class StreamSettings extends Activity {
addNativeResolutionEntry(nativeWidth, nativeHeight, insetsRemoved, false);
}
private void addNativeFrameRateEntry(float framerate) {
int frameRateRounded = Math.round(framerate);
if (frameRateRounded == 0) {
return;
}
ListPreference pref = (ListPreference) findPreference(PreferenceConfiguration.FPS_PREF_STRING);
String fpsValue = Integer.toString(frameRateRounded);
String fpsName = getResources().getString(R.string.resolution_prefix_native) +
" (" + fpsValue + " " + getResources().getString(R.string.fps_suffix_fps) + ")";
// Check if the native frame rate is already present
for (CharSequence value : pref.getEntryValues()) {
if (fpsValue.equals(value.toString())) {
// It is present in the default list, so don't add it again
nativeFramerateShown = false;
return;
}
}
appendPreferenceEntry(pref, fpsName, fpsValue);
nativeFramerateShown = true;
}
private void removeValue(String preferenceKey, String value, Runnable onMatched) {
int matchingCount = 0;
@@ -252,19 +278,10 @@ public class StreamSettings extends Activity {
PreferenceScreen screen = getPreferenceScreen();
// hide on-screen controls category on non touch screen devices
if (!getActivity().getPackageManager().
hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN)) {
{
PreferenceCategory category =
(PreferenceCategory) findPreference("category_onscreen_controls");
screen.removePreference(category);
}
{
PreferenceCategory category =
(PreferenceCategory) findPreference("category_input_settings");
category.removePreference(findPreference("checkbox_touchscreen_trackpad"));
}
if (!getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN)) {
PreferenceCategory category =
(PreferenceCategory) findPreference("category_onscreen_controls");
screen.removePreference(category);
}
// Hide remote desktop mouse mode on pre-Oreo (which doesn't have pointer capture)
@@ -276,6 +293,30 @@ public class StreamSettings extends Activity {
category.removePreference(findPreference("checkbox_absolute_mouse_mode"));
}
// Hide gamepad motion sensor option when running on OSes before Android 12.
// Support for motion, LED, battery, and other extensions were introduced in S.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
PreferenceCategory category =
(PreferenceCategory) findPreference("category_gamepad_settings");
category.removePreference(findPreference("checkbox_gamepad_motion_sensors"));
}
// Hide gamepad motion sensor fallback option if the device has no gyro or accelerometer
if (!getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_SENSOR_ACCELEROMETER) &&
!getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_SENSOR_GYROSCOPE)) {
PreferenceCategory category =
(PreferenceCategory) findPreference("category_gamepad_settings");
category.removePreference(findPreference("checkbox_gamepad_motion_fallback"));
}
// Hide USB driver options on devices without USB host support
if (!getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_USB_HOST)) {
PreferenceCategory category =
(PreferenceCategory) findPreference("category_gamepad_settings");
category.removePreference(findPreference("checkbox_usb_bind_all"));
category.removePreference(findPreference("checkbox_usb_driver"));
}
// Remove PiP mode on devices pre-Oreo, where the feature is not available (some low RAM devices),
// and on Fire OS where it violates the Amazon App Store guidelines for some reason.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O ||
@@ -292,26 +333,29 @@ public class StreamSettings extends Activity {
(PreferenceCategory) findPreference("category_help");
screen.removePreference(category);
}*/
PreferenceCategory category_gamepad_settings =
(PreferenceCategory) findPreference("category_gamepad_settings");
// Remove the vibration options if the device can't vibrate
if (!((Vibrator)getActivity().getSystemService(Context.VIBRATOR_SERVICE)).hasVibrator()) {
PreferenceCategory category =
(PreferenceCategory) findPreference("category_input_settings");
category.removePreference(findPreference("checkbox_vibrate_fallback"));
category_gamepad_settings.removePreference(findPreference("checkbox_vibrate_fallback"));
category_gamepad_settings.removePreference(findPreference("seekbar_vibrate_fallback_strength"));
// The entire OSC category may have already been removed by the touchscreen check above
category = (PreferenceCategory) findPreference("category_onscreen_controls");
PreferenceCategory category = (PreferenceCategory) findPreference("category_onscreen_controls");
if (category != null) {
category.removePreference(findPreference("checkbox_vibrate_osc"));
}
}
else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O ||
!((Vibrator)getActivity().getSystemService(Context.VIBRATOR_SERVICE)).hasAmplitudeControl() ) {
// Remove the vibration strength selector of the device doesn't have amplitude control
category_gamepad_settings.removePreference(findPreference("seekbar_vibrate_fallback_strength"));
}
int maxSupportedFps = 0;
Display display = getActivity().getWindowManager().getDefaultDisplay();
float maxSupportedFps = display.getRefreshRate();
// Hide non-supported resolution/FPS combinations
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Display display = getActivity().getWindowManager().getDefaultDisplay();
int maxSupportedResW = 0;
// Add a native resolution with any insets included for users that don't want content
@@ -379,7 +423,7 @@ public class StreamSettings extends Activity {
}
if (candidate.getRefreshRate() > maxSupportedFps) {
maxSupportedFps = (int)candidate.getRefreshRate();
maxSupportedFps = candidate.getRefreshRate();
}
}
@@ -467,30 +511,15 @@ public class StreamSettings extends Activity {
// Never remove 720p
}
}
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
// On Android 4.2 and later, we can get the true metrics via the
// getRealMetrics() function (unlike the lies that getWidth() and getHeight()
// tell to us).
else {
// We can get the true metrics via the getRealMetrics() function (unlike the lies
// that getWidth() and getHeight() tell to us).
DisplayMetrics metrics = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getRealMetrics(metrics);
display.getRealMetrics(metrics);
int width = Math.max(metrics.widthPixels, metrics.heightPixels);
int height = Math.min(metrics.widthPixels, metrics.heightPixels);
addNativeResolutionEntries(width, height, false);
}
else {
// On Android 4.1, we have to resort to reflection to invoke hidden APIs
// to get the real screen dimensions.
Display display = getActivity().getWindowManager().getDefaultDisplay();
try {
Method getRawHeightFunc = Display.class.getMethod("getRawHeight");
Method getRawWidthFunc = Display.class.getMethod("getRawWidth");
int width = (Integer) getRawWidthFunc.invoke(display);
int height = (Integer) getRawHeightFunc.invoke(display);
addNativeResolutionEntries(Math.max(width, height), Math.min(width, height), false);
} catch (Exception e) {
e.printStackTrace();
}
}
if (!PreferenceConfiguration.readPreferences(this.getActivity()).unlockFps) {
// We give some extra room in case the FPS is rounded down
@@ -517,50 +546,31 @@ public class StreamSettings extends Activity {
}
// Never remove 30 FPS or 60 FPS
}
// Android L introduces proper 7.1 surround sound support. Remove the 7.1 option
// for earlier versions of Android to prevent AudioTrack initialization issues.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
LimeLog.info("Excluding 7.1 surround sound option based on OS");
removeValue(PreferenceConfiguration.AUDIO_CONFIG_PREF_STRING, "71", new Runnable() {
@Override
public void run() {
setValue(PreferenceConfiguration.AUDIO_CONFIG_PREF_STRING, "51");
}
});
}
addNativeFrameRateEntry(maxSupportedFps);
// Android L introduces the drop duplicate behavior of releaseOutputBuffer()
// that the unlock FPS option relies on to not massively increase latency.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
LimeLog.info("Excluding unlock FPS toggle based on OS");
PreferenceCategory category =
(PreferenceCategory) findPreference("category_advanced_settings");
category.removePreference(findPreference("checkbox_unlock_fps"));
}
else {
findPreference(PreferenceConfiguration.UNLOCK_FPS_STRING).setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
// HACK: We need to let the preference change succeed before reinitializing to ensure
// it's reflected in the new layout.
final Handler h = new Handler();
h.postDelayed(new Runnable() {
@Override
public void run() {
// Ensure the activity is still open when this timeout expires
StreamSettings settingsActivity = (StreamSettings)SettingsFragment.this.getActivity();
if (settingsActivity != null) {
settingsActivity.reloadSettings();
}
findPreference(PreferenceConfiguration.UNLOCK_FPS_STRING).setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
// HACK: We need to let the preference change succeed before reinitializing to ensure
// it's reflected in the new layout.
final Handler h = new Handler();
h.postDelayed(new Runnable() {
@Override
public void run() {
// Ensure the activity is still open when this timeout expires
StreamSettings settingsActivity = (StreamSettings) SettingsFragment.this.getActivity();
if (settingsActivity != null) {
settingsActivity.reloadSettings();
}
}, 500);
}
}, 500);
// Allow the original preference change to take place
return true;
}
});
}
// Allow the original preference change to take place
return true;
}
});
// Remove HDR preference for devices below Nougat
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
@@ -570,7 +580,6 @@ public class StreamSettings extends Activity {
category.removePreference(findPreference("checkbox_enable_hdr"));
}
else {
Display display = getActivity().getWindowManager().getDefaultDisplay();
Display.HdrCapabilities hdrCaps = display.getHdrCapabilities();
// We must now ensure our display is compatible with HDR10
@@ -580,6 +589,7 @@ public class StreamSettings extends Activity {
for (int hdrType : hdrCaps.getSupportedHdrTypes()) {
if (hdrType == Display.HdrCapabilities.HDR_TYPE_HDR10) {
foundHdr10 = true;
break;
}
}
}
@@ -641,6 +651,15 @@ public class StreamSettings extends Activity {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(SettingsFragment.this.getActivity());
String valueStr = (String) newValue;
// If this is native frame rate, show the warning dialog
CharSequence[] values = ((ListPreference)preference).getEntryValues();
if (nativeFramerateShown && values[values.length - 1].toString().equals(newValue.toString())) {
Dialog.displayDialog(getActivity(),
getResources().getString(R.string.title_native_fps_dialog),
getResources().getString(R.string.text_native_res_dialog),
false);
}
// Write the new bitrate value
resetBitrateToDefault(prefs, null, valueStr);
@@ -21,7 +21,6 @@ public class WebLauncherPreference extends Preference {
initialize(attrs);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public WebLauncherPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
initialize(attrs);
@@ -30,6 +30,6 @@ public class AdapterFragment extends Fragment {
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
callbacks.receiveAbsListView((AbsListView) getView().findViewById(R.id.fragmentView));
callbacks.receiveAbsListView(getView().findViewById(R.id.fragmentView));
}
}
@@ -30,7 +30,6 @@ public class StreamView extends SurfaceView {
super(context, attrs, defStyleAttr);
}
@TargetApi(21)
public StreamView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@@ -44,4 +44,8 @@ public class HelpLauncher {
public static void launchTroubleshooting(Context context) {
launchUrl(context, "https://github.com/moonlight-stream/moonlight-docs/wiki/Troubleshooting");
}
public static void launchGameStreamEolFaq(Context context) {
launchUrl(context, "https://github.com/moonlight-stream/moonlight-docs/wiki/NVIDIA-GameStream-End-Of-Service-Announcement-FAQ");
}
}
@@ -20,7 +20,7 @@ public class NetHelper {
}
}
}
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
else {
NetworkInfo activeNetworkInfo = connMgr.getActiveNetworkInfo();
if (activeNetworkInfo != null) {
return activeNetworkInfo.getType() == ConnectivityManager.TYPE_VPN;
@@ -6,13 +6,12 @@ import android.widget.Toast;
import com.limelight.AppView;
import com.limelight.Game;
import com.limelight.PcView;
import com.limelight.R;
import com.limelight.ShortcutTrampoline;
import com.limelight.binding.PlatformBinding;
import com.limelight.computers.ComputerManagerService;
import com.limelight.nvstream.http.ComputerDetails;
import com.limelight.nvstream.http.GfeHttpResponseException;
import com.limelight.nvstream.http.HostHttpResponseException;
import com.limelight.nvstream.http.NvApp;
import com.limelight.nvstream.http.NvHTTP;
import com.limelight.nvstream.jni.MoonBridge;
@@ -135,7 +134,7 @@ public class ServerHelper {
} else {
message = parent.getResources().getString(R.string.applist_quit_fail) + " " + app.getAppName();
}
} catch (GfeHttpResponseException e) {
} catch (HostHttpResponseException e) {
if (e.getErrorCode() == 599) {
message = "This session wasn't started by this device," +
" so it cannot be quit. End streaming on the original " +
@@ -2,15 +2,12 @@ package com.limelight.utils;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager;
import android.graphics.Bitmap;
import android.graphics.drawable.Icon;
import android.os.Build;
import com.limelight.AppView;
import com.limelight.ShortcutTrampoline;
import com.limelight.R;
import com.limelight.nvstream.http.ComputerDetails;
import com.limelight.nvstream.http.NvApp;
@@ -53,7 +53,11 @@ public class TvChannelHelper {
intent.putExtra(TvContract.EXTRA_CHANNEL_ID, getChannelId(computer.uuid));
try {
context.startActivityForResult(intent, 0);
} catch (ActivityNotFoundException e) {
} catch (Exception ignored) {
// ActivityNotFoundException is the only officially documented
// exception that can result from this call. However some buggy
// devices throw others.
// See https://github.com/moonlight-stream/moonlight-android/issues/1302
}
}
}
@@ -29,37 +29,43 @@ public class UiHelper {
private static final int TV_VERTICAL_PADDING_DP = 15;
private static final int TV_HORIZONTAL_PADDING_DP = 15;
private static void setGameModeStatus(Context context, boolean streaming, boolean loading, boolean interruptible) {
private static void setGameModeStatus(Context context, boolean streaming, boolean interruptible) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
GameManager gameManager = context.getSystemService(GameManager.class);
try {
GameManager gameManager = context.getSystemService(GameManager.class);
if (gameManager == null) {
return; // Not supported on this device (e.g., Meta Quest)
}
if (streaming) {
gameManager.setGameState(new GameState(loading, interruptible ? GameState.MODE_GAMEPLAY_INTERRUPTIBLE : GameState.MODE_GAMEPLAY_UNINTERRUPTIBLE));
}
else {
gameManager.setGameState(new GameState(loading, GameState.MODE_NONE));
if (streaming) {
gameManager.setGameState(new GameState(false, interruptible ? GameState.MODE_GAMEPLAY_INTERRUPTIBLE : GameState.MODE_GAMEPLAY_UNINTERRUPTIBLE));
} else {
gameManager.setGameState(new GameState(false, GameState.MODE_NONE));
}
} catch (Throwable t) {
// Swallow any failure. Some OEM builds ship partial/incompatible GameManager impls.
}
}
}
public static void notifyStreamConnecting(Context context) {
setGameModeStatus(context, true, true, true);
setGameModeStatus(context, true, true);
}
public static void notifyStreamConnected(Context context) {
setGameModeStatus(context, true, false, false);
setGameModeStatus(context, true, false);
}
public static void notifyStreamEnteringPiP(Context context) {
setGameModeStatus(context, true, false, true);
setGameModeStatus(context, true, true);
}
public static void notifyStreamExitingPiP(Context context) {
setGameModeStatus(context, true, false, false);
setGameModeStatus(context, true, false);
}
public static void notifyStreamEnded(Context context) {
setGameModeStatus(context, false, false, false);
setGameModeStatus(context, false, false);
}
public static void setLocale(Activity activity)
@@ -115,7 +121,7 @@ public class UiHelper {
UiModeManager modeMgr = (UiModeManager) activity.getSystemService(Context.UI_MODE_SERVICE);
// Set GameState.MODE_NONE initially for all activities
setGameModeStatus(activity, false, false, false);
setGameModeStatus(activity, false, false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
// Allow this non-streaming activity to layout under notches.
+5 -2
View File
@@ -1,4 +1,7 @@
# Application.mk for Moonlight
# Our minimum version is Android 4.1
APP_PLATFORM := android-16
# Our minimum version is Android 5.0
APP_PLATFORM := android-21
# We support 16KB pages
APP_SUPPORT_FLEXIBLE_PAGE_SIZES := true
+11 -3
View File
@@ -28,7 +28,9 @@ LOCAL_SRC_FILES := moonlight-common-c/src/AudioStream.c \
moonlight-common-c/src/SimpleStun.c \
moonlight-common-c/src/VideoDepacketizer.c \
moonlight-common-c/src/VideoStream.c \
moonlight-common-c/reedsolomon/rs.c \
moonlight-common-c/nanors/deps/obl/oblas_common.c \
moonlight-common-c/nanors/deps/obl/oblas_lite.c \
moonlight-common-c/nanors/rs.c \
moonlight-common-c/enet/callbacks.c \
moonlight-common-c/enet/compress.c \
moonlight-common-c/enet/host.c \
@@ -40,10 +42,12 @@ LOCAL_SRC_FILES := moonlight-common-c/src/AudioStream.c \
moonlight-common-c/enet/win32.c \
simplejni.c \
callbacks.c \
minisdl.c \
LOCAL_C_INCLUDES := $(LOCAL_PATH)/moonlight-common-c/enet/include \
$(LOCAL_PATH)/moonlight-common-c/reedsolomon \
$(LOCAL_PATH)/moonlight-common-c/nanors/deps/obl \
$(LOCAL_PATH)/moonlight-common-c/nanors \
$(LOCAL_PATH)/moonlight-common-c/src \
LOCAL_CFLAGS := -DHAS_SOCKLEN_T=1 -DLC_ANDROID -DHAVE_CLOCK_GETTIME=1
@@ -54,7 +58,11 @@ endif
LOCAL_LDLIBS := -llog
LOCAL_STATIC_LIBRARIES := libopus libssl libcrypto
LOCAL_STATIC_LIBRARIES := libopus libcrypto cpufeatures
LOCAL_LDFLAGS += -Wl,--exclude-libs,ALL
LOCAL_BRANCH_PROTECTION := standard
include $(BUILD_SHARED_LIBRARY)
$(call import-module,android/cpufeatures)
@@ -0,0 +1 @@
Static libraries were built from https://github.com/cgutman/moonlight-mobile-deps using AppVeyor CI
+94 -16
View File
@@ -8,6 +8,8 @@
#include <opus_multistream.h>
#include <android/log.h>
#include <cpu-features.h>
static OpusMSDecoder* Decoder;
static OPUS_MULTISTREAM_CONFIGURATION OpusConfig;
@@ -33,6 +35,9 @@ static jmethodID BridgeClConnectionTerminatedMethod;
static jmethodID BridgeClRumbleMethod;
static jmethodID BridgeClConnectionStatusUpdateMethod;
static jmethodID BridgeClSetHdrModeMethod;
static jmethodID BridgeClRumbleTriggersMethod;
static jmethodID BridgeClSetMotionEventStateMethod;
static jmethodID BridgeClSetControllerLEDMethod;
static jbyteArray DecodedFrameBuffer;
static jshortArray DecodedAudioBuffer;
@@ -80,7 +85,7 @@ Java_com_limelight_nvstream_jni_MoonBridge_init(JNIEnv *env, jclass clazz) {
BridgeDrStartMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeDrStart", "()V");
BridgeDrStopMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeDrStop", "()V");
BridgeDrCleanupMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeDrCleanup", "()V");
BridgeDrSubmitDecodeUnitMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeDrSubmitDecodeUnit", "([BIIIIJJ)I");
BridgeDrSubmitDecodeUnitMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeDrSubmitDecodeUnit", "([BIIIICJJ)I");
BridgeArInitMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeArInit", "(III)I");
BridgeArStartMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeArStart", "()V");
BridgeArStopMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeArStop", "()V");
@@ -93,7 +98,10 @@ Java_com_limelight_nvstream_jni_MoonBridge_init(JNIEnv *env, jclass clazz) {
BridgeClConnectionTerminatedMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeClConnectionTerminated", "(I)V");
BridgeClRumbleMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeClRumble", "(SSS)V");
BridgeClConnectionStatusUpdateMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeClConnectionStatusUpdate", "(I)V");
BridgeClSetHdrModeMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeClSetHdrMode", "(Z)V");
BridgeClSetHdrModeMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeClSetHdrMode", "(Z[B)V");
BridgeClRumbleTriggersMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeClRumbleTriggers", "(SSS)V");
BridgeClSetMotionEventStateMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeClSetMotionEventState", "(SBS)V");
BridgeClSetControllerLEDMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeClSetControllerLED", "(SBBB)V");
}
int BridgeDrSetup(int videoFormat, int width, int height, int redrawRate, void* context, int drFlags) {
@@ -159,8 +167,8 @@ int BridgeDrSubmitDecodeUnit(PDECODE_UNIT decodeUnit) {
ret = (*env)->CallStaticIntMethod(env, GlobalBridgeClass, BridgeDrSubmitDecodeUnitMethod,
DecodedFrameBuffer, currentEntry->length, currentEntry->bufferType,
decodeUnit->frameNumber, decodeUnit->frameType,
(jlong)decodeUnit->receiveTimeMs, (jlong)decodeUnit->enqueueTimeMs);
decodeUnit->frameNumber, decodeUnit->frameType, (jchar)decodeUnit->frameHostProcessingLatency,
(jlong)decodeUnit->receiveTimeUs, (jlong)decodeUnit->enqueueTimeUs);
if ((*env)->ExceptionCheck(env)) {
// We will crash here
(*JVM)->DetachCurrentThread(JVM);
@@ -180,8 +188,8 @@ int BridgeDrSubmitDecodeUnit(PDECODE_UNIT decodeUnit) {
ret = (*env)->CallStaticIntMethod(env, GlobalBridgeClass, BridgeDrSubmitDecodeUnitMethod,
DecodedFrameBuffer, offset, BUFFER_TYPE_PICDATA,
decodeUnit->frameNumber, decodeUnit->frameType,
(jlong)decodeUnit->receiveTimeMs, (jlong)decodeUnit->enqueueTimeMs);
decodeUnit->frameNumber, decodeUnit->frameType, (jchar)decodeUnit->frameHostProcessingLatency,
(jlong)decodeUnit->receiveTimeUs, (jlong)decodeUnit->enqueueTimeUs);
if ((*env)->ExceptionCheck(env)) {
// We will crash here
(*JVM)->DetachCurrentThread(JVM);
@@ -331,7 +339,50 @@ void BridgeClConnectionStatusUpdate(int connectionStatus) {
void BridgeClSetHdrMode(bool enabled) {
JNIEnv* env = GetThreadEnv();
(*env)->CallStaticVoidMethod(env, GlobalBridgeClass, BridgeClSetHdrModeMethod, enabled);
jbyteArray hdrMetadataByteArray = NULL;
SS_HDR_METADATA hdrMetadata;
// Check if HDR metadata was provided
if (enabled && LiGetHdrMetadata(&hdrMetadata)) {
hdrMetadataByteArray = (*env)->NewByteArray(env, sizeof(SS_HDR_METADATA));
(*env)->SetByteArrayRegion(env, hdrMetadataByteArray, 0, sizeof(SS_HDR_METADATA), (jbyte*)&hdrMetadata);
}
(*env)->CallStaticVoidMethod(env, GlobalBridgeClass, BridgeClSetHdrModeMethod, enabled, hdrMetadataByteArray);
if ((*env)->ExceptionCheck(env)) {
// We will crash here
(*JVM)->DetachCurrentThread(JVM);
}
}
void BridgeClRumbleTriggers(unsigned short controllerNumber, unsigned short leftTrigger, unsigned short rightTrigger) {
JNIEnv* env = GetThreadEnv();
// The seemingly redundant short casts are required in order to convert the unsigned short to a signed short.
// If we leave it as an unsigned short, CheckJNI will fail when the value exceeds 32767. The cast itself is
// fine because the Java code treats the value as unsigned even though it's stored in a signed type.
(*env)->CallStaticVoidMethod(env, GlobalBridgeClass, BridgeClRumbleTriggersMethod, controllerNumber, (short)leftTrigger, (short)rightTrigger);
if ((*env)->ExceptionCheck(env)) {
// We will crash here
(*JVM)->DetachCurrentThread(JVM);
}
}
void BridgeClSetMotionEventState(uint16_t controllerNumber, uint8_t motionType, uint16_t reportRateHz) {
JNIEnv* env = GetThreadEnv();
(*env)->CallStaticVoidMethod(env, GlobalBridgeClass, BridgeClSetMotionEventStateMethod, controllerNumber, motionType, reportRateHz);
if ((*env)->ExceptionCheck(env)) {
// We will crash here
(*JVM)->DetachCurrentThread(JVM);
}
}
void BridgeClSetControllerLED(uint16_t controllerNumber, uint8_t r, uint8_t g, uint8_t b) {
JNIEnv* env = GetThreadEnv();
// These jbyte casts are necessary to satisfy CheckJNI
(*env)->CallStaticVoidMethod(env, GlobalBridgeClass, BridgeClSetControllerLEDMethod, controllerNumber, (jbyte)r, (jbyte)g, (jbyte)b);
if ((*env)->ExceptionCheck(env)) {
// We will crash here
(*JVM)->DetachCurrentThread(JVM);
@@ -372,19 +423,42 @@ static CONNECTION_LISTENER_CALLBACKS BridgeConnListenerCallbacks = {
.rumble = BridgeClRumble,
.connectionStatusUpdate = BridgeClConnectionStatusUpdate,
.setHdrMode = BridgeClSetHdrMode,
.rumbleTriggers = BridgeClRumbleTriggers,
.setMotionEventState = BridgeClSetMotionEventState,
.setControllerLED = BridgeClSetControllerLED,
};
static bool
hasFastAes() {
if (android_getCpuCount() <= 2) {
return false;
}
switch (android_getCpuFamily()) {
case ANDROID_CPU_FAMILY_ARM:
return !!(android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_AES);
case ANDROID_CPU_FAMILY_ARM64:
return !!(android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_AES);
case ANDROID_CPU_FAMILY_X86:
case ANDROID_CPU_FAMILY_X86_64:
return !!(android_getCpuFeatures() & ANDROID_CPU_X86_FEATURE_AES_NI);
case ANDROID_CPU_FAMILY_MIPS:
case ANDROID_CPU_FAMILY_MIPS64:
return false;
default:
// Assume new architectures will all have crypto acceleration (RISC-V will)
return true;
}
}
JNIEXPORT jint JNICALL
Java_com_limelight_nvstream_jni_MoonBridge_startConnection(JNIEnv *env, jclass clazz,
jstring address, jstring appVersion, jstring gfeVersion,
jstring rtspSessionUrl,
jstring rtspSessionUrl, jint serverCodecModeSupport,
jint width, jint height, jint fps,
jint bitrate, jint packetSize, jint streamingRemotely,
jint audioConfiguration, jboolean supportsHevc,
jboolean enableHdr,
jint hevcBitratePercentageMultiplier,
jint audioConfiguration, jint supportedVideoFormats,
jint clientRefreshRateX100,
jint encryptionFlags,
jbyteArray riAesKey, jbyteArray riAesIv,
jint videoCapabilities,
jint colorSpace, jint colorRange) {
@@ -393,6 +467,7 @@ Java_com_limelight_nvstream_jni_MoonBridge_startConnection(JNIEnv *env, jclass c
.serverInfoAppVersion = (*env)->GetStringUTFChars(env, appVersion, 0),
.serverInfoGfeVersion = gfeVersion ? (*env)->GetStringUTFChars(env, gfeVersion, 0) : NULL,
.rtspSessionUrl = rtspSessionUrl ? (*env)->GetStringUTFChars(env, rtspSessionUrl, 0) : NULL,
.serverCodecModeSupport = serverCodecModeSupport,
};
STREAM_CONFIGURATION streamConfig = {
.width = width,
@@ -402,11 +477,9 @@ Java_com_limelight_nvstream_jni_MoonBridge_startConnection(JNIEnv *env, jclass c
.packetSize = packetSize,
.streamingRemotely = streamingRemotely,
.audioConfiguration = audioConfiguration,
.supportsHevc = supportsHevc,
.enableHdr = enableHdr,
.hevcBitratePercentageMultiplier = hevcBitratePercentageMultiplier,
.supportedVideoFormats = supportedVideoFormats,
.clientRefreshRateX100 = clientRefreshRateX100,
.encryptionFlags = encryptionFlags,
.encryptionFlags = ENCFLG_AUDIO,
.colorSpace = colorSpace,
.colorRange = colorRange
};
@@ -421,6 +494,11 @@ Java_com_limelight_nvstream_jni_MoonBridge_startConnection(JNIEnv *env, jclass c
BridgeVideoRendererCallbacks.capabilities = videoCapabilities;
// Enable all encryption features if the platform has fast AES support
if (hasFastAes()) {
streamConfig.encryptionFlags = ENCFLG_ALL;
}
int ret = LiStartConnection(&serverInfo,
&streamConfig,
&BridgeConnListenerCallbacks,
@@ -0,0 +1,677 @@
/*
Copyright (C) Valve Corporation
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#define MAKE_CONTROLLER_ID( nVID, nPID ) (unsigned int)( (unsigned int)nVID << 16 | (unsigned int)nPID )
static const ControllerDescription_t arrControllers[] = {
{ MAKE_CONTROLLER_ID( 0x0079, 0x181a ), k_eControllerType_PS3Controller, NULL }, // Venom Arcade Stick
{ MAKE_CONTROLLER_ID( 0x044f, 0xb315 ), k_eControllerType_PS3Controller, NULL }, // Firestorm Dual Analog 3
{ MAKE_CONTROLLER_ID( 0x044f, 0xd007 ), k_eControllerType_PS3Controller, NULL }, // Thrustmaster wireless 3-1
{ MAKE_CONTROLLER_ID( 0x046d, 0xcad1 ), k_eControllerType_PS3Controller, NULL }, // Logitech Chillstream
//{ MAKE_CONTROLLER_ID( 0x046d, 0xc24f ), k_eControllerType_PS3Controller, NULL }, // Logitech G29 (PS3)
{ MAKE_CONTROLLER_ID( 0x054c, 0x0268 ), k_eControllerType_PS3Controller, NULL }, // Sony PS3 Controller
{ MAKE_CONTROLLER_ID( 0x056e, 0x200f ), k_eControllerType_PS3Controller, NULL }, // From SDL
{ MAKE_CONTROLLER_ID( 0x056e, 0x2013 ), k_eControllerType_PS3Controller, NULL }, // JC-U4113SBK
{ MAKE_CONTROLLER_ID( 0x05b8, 0x1004 ), k_eControllerType_PS3Controller, NULL }, // From SDL
{ MAKE_CONTROLLER_ID( 0x05b8, 0x1006 ), k_eControllerType_PS3Controller, NULL }, // JC-U3412SBK
{ MAKE_CONTROLLER_ID( 0x06a3, 0xf622 ), k_eControllerType_PS3Controller, NULL }, // Cyborg V3
{ MAKE_CONTROLLER_ID( 0x0738, 0x3180 ), k_eControllerType_PS3Controller, NULL }, // Mad Catz Alpha PS3 mode
{ MAKE_CONTROLLER_ID( 0x0738, 0x3250 ), k_eControllerType_PS3Controller, NULL }, // madcats fightpad pro ps3
{ MAKE_CONTROLLER_ID( 0x0738, 0x3481 ), k_eControllerType_PS3Controller, NULL }, // Mad Catz FightStick TE 2+ PS3
{ MAKE_CONTROLLER_ID( 0x0738, 0x8180 ), k_eControllerType_PS3Controller, NULL }, // Mad Catz Alpha PS4 mode (no touchpad on device)
{ MAKE_CONTROLLER_ID( 0x0738, 0x8838 ), k_eControllerType_PS3Controller, NULL }, // Madcatz Fightstick Pro
{ MAKE_CONTROLLER_ID( 0x0810, 0x0001 ), k_eControllerType_PS3Controller, NULL }, // actually ps2 - maybe break out later
{ MAKE_CONTROLLER_ID( 0x0810, 0x0003 ), k_eControllerType_PS3Controller, NULL }, // actually ps2 - maybe break out later
{ MAKE_CONTROLLER_ID( 0x0925, 0x0005 ), k_eControllerType_PS3Controller, NULL }, // Sony PS3 Controller
{ MAKE_CONTROLLER_ID( 0x0925, 0x8866 ), k_eControllerType_PS3Controller, NULL }, // PS2 maybe break out later
{ MAKE_CONTROLLER_ID( 0x0925, 0x8888 ), k_eControllerType_PS3Controller, NULL }, // Actually ps2 -maybe break out later Lakeview Research WiseGroup Ltd, MP-8866 Dual Joypad
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0109 ), k_eControllerType_PS3Controller, NULL }, // PDP Versus Fighting Pad
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x011e ), k_eControllerType_PS3Controller, NULL }, // Rock Candy PS4
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0128 ), k_eControllerType_PS3Controller, NULL }, // Rock Candy PS3
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0214 ), k_eControllerType_PS3Controller, NULL }, // afterglow ps3
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x1314 ), k_eControllerType_PS3Controller, NULL }, // PDP Afterglow Wireless PS3 controller
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x6302 ), k_eControllerType_PS3Controller, NULL }, // From SDL
{ MAKE_CONTROLLER_ID( 0x0e8f, 0x0008 ), k_eControllerType_PS3Controller, NULL }, // Green Asia
{ MAKE_CONTROLLER_ID( 0x0e8f, 0x3075 ), k_eControllerType_PS3Controller, NULL }, // SpeedLink Strike FX
{ MAKE_CONTROLLER_ID( 0x0e8f, 0x310d ), k_eControllerType_PS3Controller, NULL }, // From SDL
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x0009 ), k_eControllerType_PS3Controller, NULL }, // HORI BDA GP1
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x004d ), k_eControllerType_PS3Controller, NULL }, // Horipad 3
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x005f ), k_eControllerType_PS3Controller, NULL }, // HORI Fighting Commander 4 PS3
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x006a ), k_eControllerType_PS3Controller, NULL }, // Real Arcade Pro 4
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x006e ), k_eControllerType_PS3Controller, NULL }, // HORI horipad4 ps3
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x0085 ), k_eControllerType_PS3Controller, NULL }, // HORI Fighting Commander PS3
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x0086 ), k_eControllerType_PS3Controller, NULL }, // HORI Fighting Commander PC (Uses the Xbox 360 protocol, but has PS3 buttons)
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x0088 ), k_eControllerType_PS3Controller, NULL }, // HORI Fighting Stick mini 4
{ MAKE_CONTROLLER_ID( 0x0f30, 0x1100 ), k_eControllerType_PS3Controller, NULL }, // Qanba Q1 fight stick
{ MAKE_CONTROLLER_ID( 0x11ff, 0x3331 ), k_eControllerType_PS3Controller, NULL }, // SRXJ-PH2400
{ MAKE_CONTROLLER_ID( 0x12ba, 0x0100 ), k_eControllerType_PS3Controller, NULL }, // PS3 Guitar Hero Guitar
{ MAKE_CONTROLLER_ID( 0x12ba, 0x0120 ), k_eControllerType_PS3Controller, NULL }, // PS3 Guitar Hero Drums
{ MAKE_CONTROLLER_ID( 0x12ba, 0x0140 ), k_eControllerType_PS3Controller, NULL }, // PS3 DJ Hero Turntable
{ MAKE_CONTROLLER_ID( 0x12ba, 0x0200 ), k_eControllerType_PS3Controller, NULL }, // PS3 Rock Band Guitar
{ MAKE_CONTROLLER_ID( 0x12ba, 0x0210 ), k_eControllerType_PS3Controller, NULL }, // PS3 Rock Band Drums
{ MAKE_CONTROLLER_ID( 0x12ba, 0x0218 ), k_eControllerType_PS3Controller, NULL }, // PS3 Midi Pro Adapter - Drums Mode
{ MAKE_CONTROLLER_ID( 0x12ba, 0x074b ), k_eControllerType_PS3Controller, NULL }, // PS3 / Wii U Guitar Hero Live Guitar
{ MAKE_CONTROLLER_ID( 0x12ba, 0x2330 ), k_eControllerType_PS3Controller, NULL }, // PS3 Rock Band Keyboard
{ MAKE_CONTROLLER_ID( 0x12ba, 0x2338 ), k_eControllerType_PS3Controller, NULL }, // PS3 Midi Pro Adapter - Keyboard Mode
{ MAKE_CONTROLLER_ID( 0x12ba, 0x2430 ), k_eControllerType_PS3Controller, NULL }, // PS3 Mustang Guitar
{ MAKE_CONTROLLER_ID( 0x12ba, 0x2438 ), k_eControllerType_PS3Controller, NULL }, // PS3 Midi Pro Adapter - Mustang Guitar Mode
{ MAKE_CONTROLLER_ID( 0x12ba, 0x2530 ), k_eControllerType_PS3Controller, NULL }, // PS3 Squire Guitar
{ MAKE_CONTROLLER_ID( 0x12ba, 0x2538 ), k_eControllerType_PS3Controller, NULL }, // PS3 Midi Pro Adapter - Squire Guitar Mode
{ MAKE_CONTROLLER_ID( 0x1345, 0x1000 ), k_eControllerType_PS3Controller, NULL }, // PS2 ACME GA-D5
{ MAKE_CONTROLLER_ID( 0x1345, 0x6005 ), k_eControllerType_PS3Controller, NULL }, // ps2 maybe break out later
{ MAKE_CONTROLLER_ID( 0x146b, 0x5500 ), k_eControllerType_PS3Controller, NULL }, // From SDL
{ MAKE_CONTROLLER_ID( 0x1a34, 0x0836 ), k_eControllerType_PS3Controller, NULL }, // Afterglow PS3
{ MAKE_CONTROLLER_ID( 0x1BAD, 0x0004 ), k_eControllerType_PS3Controller, NULL }, // Wii RB1 Guitar (Uses PS3 protocol)
{ MAKE_CONTROLLER_ID( 0x1BAD, 0x0005 ), k_eControllerType_PS3Controller, NULL }, // Wii RB1 Drums (Uses PS3 protocol)
{ MAKE_CONTROLLER_ID( 0x1BAD, 0x3010 ), k_eControllerType_PS3Controller, NULL }, // Wii RB2 Guitar (Uses PS3 protocol)
{ MAKE_CONTROLLER_ID( 0x1BAD, 0x3110 ), k_eControllerType_PS3Controller, NULL }, // Wii RB2 Drums (Uses PS3 protocol)
{ MAKE_CONTROLLER_ID( 0x1BAD, 0x3138 ), k_eControllerType_PS3Controller, NULL }, // Wii RB3 Midi Pro Adapter - Drums Mode (Uses PS3 protocol)
{ MAKE_CONTROLLER_ID( 0x1BAD, 0x3330 ), k_eControllerType_PS3Controller, NULL }, // Wii RB3 Keyboard (Uses PS3 protocol)
{ MAKE_CONTROLLER_ID( 0x1BAD, 0x3338 ), k_eControllerType_PS3Controller, NULL }, // Wii RB3 Midi Pro Adapter - Keyboard Mode (Uses PS3 protocol)
{ MAKE_CONTROLLER_ID( 0x1BAD, 0x3430 ), k_eControllerType_PS3Controller, NULL }, // Wii RB3 Mustang Guitar (Uses PS3 protocol)
{ MAKE_CONTROLLER_ID( 0x1BAD, 0x3438 ), k_eControllerType_PS3Controller, NULL }, // Wii RB3 Midi Pro Adapter - Mustang Guitar Mode (Uses PS3 protocol)
{ MAKE_CONTROLLER_ID( 0x1BAD, 0x3530 ), k_eControllerType_PS3Controller, NULL }, // Wii RB3 Squire Guitar (Uses PS3 protocol)
{ MAKE_CONTROLLER_ID( 0x1BAD, 0x3538 ), k_eControllerType_PS3Controller, NULL }, // Wii RB3 Midi Pro Adapter - Squire Guitar Mode (Uses PS3 protocol)
{ MAKE_CONTROLLER_ID( 0x20bc, 0x5500 ), k_eControllerType_PS3Controller, NULL }, // ShanWan PS3
{ MAKE_CONTROLLER_ID( 0x20d6, 0x576d ), k_eControllerType_PS3Controller, NULL }, // Power A PS3
{ MAKE_CONTROLLER_ID( 0x20d6, 0xca6d ), k_eControllerType_PS3Controller, NULL }, // BDA Pro Ex
{ MAKE_CONTROLLER_ID( 0x2563, 0x0523 ), k_eControllerType_PS3Controller, NULL }, // Digiflip GP006
{ MAKE_CONTROLLER_ID( 0x2563, 0x0575 ), k_eControllerType_PS3Controller, "Retro Controller" }, // SWITCH CO., LTD. Retro-bit, Retro Fighters Controllers
{ MAKE_CONTROLLER_ID( 0x25f0, 0x83c3 ), k_eControllerType_PS3Controller, NULL }, // gioteck vx2
{ MAKE_CONTROLLER_ID( 0x25f0, 0xc121 ), k_eControllerType_PS3Controller, NULL }, //
{ MAKE_CONTROLLER_ID( 0x2c22, 0x2003 ), k_eControllerType_PS3Controller, NULL }, // Qanba Drone
{ MAKE_CONTROLLER_ID( 0x2c22, 0x2302 ), k_eControllerType_PS3Controller, NULL }, // Qanba Obsidian
{ MAKE_CONTROLLER_ID( 0x2c22, 0x2502 ), k_eControllerType_PS3Controller, NULL }, // Qanba Dragon
{ MAKE_CONTROLLER_ID( 0x8380, 0x0003 ), k_eControllerType_PS3Controller, NULL }, // BTP 2163
{ MAKE_CONTROLLER_ID( 0x8888, 0x0308 ), k_eControllerType_PS3Controller, NULL }, // Sony PS3 Controller
{ MAKE_CONTROLLER_ID( 0x0079, 0x181b ), k_eControllerType_PS4Controller, NULL }, // Venom Arcade Stick - XXX:this may not work and may need to be called a ps3 controller
//{ MAKE_CONTROLLER_ID( 0x046d, 0xc260 ), k_eControllerType_PS4Controller, NULL }, // Logitech G29 (PS4)
{ MAKE_CONTROLLER_ID( 0x044f, 0xd00e ), k_eControllerType_PS4Controller, NULL }, // Thrustmaster Eswap Pro - No gyro and lightbar doesn't change color. Works otherwise
{ MAKE_CONTROLLER_ID( 0x054c, 0x05c4 ), k_eControllerType_PS4Controller, NULL }, // Sony PS4 Controller
{ MAKE_CONTROLLER_ID( 0x054c, 0x05c5 ), k_eControllerType_PS4Controller, NULL }, // STRIKEPAD PS4 Grip Add-on
{ MAKE_CONTROLLER_ID( 0x054c, 0x09cc ), k_eControllerType_PS4Controller, NULL }, // Sony PS4 Slim Controller
{ MAKE_CONTROLLER_ID( 0x054c, 0x0ba0 ), k_eControllerType_PS4Controller, NULL }, // Sony PS4 Controller (Wireless dongle)
{ MAKE_CONTROLLER_ID( 0x0738, 0x8250 ), k_eControllerType_PS4Controller, NULL }, // Mad Catz FightPad Pro PS4
{ MAKE_CONTROLLER_ID( 0x0738, 0x8384 ), k_eControllerType_PS4Controller, NULL }, // Mad Catz FightStick TE S+ PS4
{ MAKE_CONTROLLER_ID( 0x0738, 0x8480 ), k_eControllerType_PS4Controller, NULL }, // Mad Catz FightStick TE 2 PS4
{ MAKE_CONTROLLER_ID( 0x0738, 0x8481 ), k_eControllerType_PS4Controller, NULL }, // Mad Catz FightStick TE 2+ PS4
{ MAKE_CONTROLLER_ID( 0x0c12, 0x0e10 ), k_eControllerType_PS4Controller, NULL }, // Armor Armor 3 Pad PS4
{ MAKE_CONTROLLER_ID( 0x0c12, 0x0e13 ), k_eControllerType_PS4Controller, NULL }, // ZEROPLUS P4 Wired Gamepad
{ MAKE_CONTROLLER_ID( 0x0c12, 0x0e15 ), k_eControllerType_PS4Controller, NULL }, // Game:Pad 4
{ MAKE_CONTROLLER_ID( 0x0c12, 0x0e20 ), k_eControllerType_PS4Controller, NULL }, // Brook Mars Controller - needs FW update to show up as Ps4 controller on PC. Has Gyro but touchpad is a single button.
{ MAKE_CONTROLLER_ID( 0x0c12, 0x0ef6 ), k_eControllerType_PS4Controller, NULL }, // Hitbox Arcade Stick
{ MAKE_CONTROLLER_ID( 0x0c12, 0x1cf6 ), k_eControllerType_PS4Controller, NULL }, // EMIO PS4 Elite Controller
{ MAKE_CONTROLLER_ID( 0x0c12, 0x1e10 ), k_eControllerType_PS4Controller, NULL }, // P4 Wired Gamepad generic knock off - lightbar but not trackpad or gyro
{ MAKE_CONTROLLER_ID( 0x0c12, 0x2e18 ), k_eControllerType_PS4Controller, NULL }, // ZEROPLUS P4 Wired Gamepad
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0203 ), k_eControllerType_PS4Controller, NULL }, // Victrix Pro FS (PS4 peripheral but no trackpad/lightbar)
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0207 ), k_eControllerType_PS4Controller, NULL }, // Victrix Pro FS V2 w/ Touchpad for PS4
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x020a ), k_eControllerType_PS4Controller, NULL }, // Victrix Pro FS PS4/PS5 (PS4 mode)
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x0055 ), k_eControllerType_PS4Controller, NULL }, // HORIPAD 4 FPS
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x005e ), k_eControllerType_PS4Controller, NULL }, // HORI Fighting Commander 4 PS4
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x0066 ), k_eControllerType_PS4Controller, NULL }, // HORIPAD 4 FPS Plus
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x0084 ), k_eControllerType_PS4Controller, NULL }, // HORI Fighting Commander PS4
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x0087 ), k_eControllerType_PS4Controller, NULL }, // HORI Fighting Stick mini 4
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x008a ), k_eControllerType_PS4Controller, NULL }, // HORI Real Arcade Pro 4
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x009c ), k_eControllerType_PS4Controller, NULL }, // HORI TAC PRO mousething
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x00a0 ), k_eControllerType_PS4Controller, NULL }, // HORI TAC4 mousething
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x00ed ), k_eControllerType_XInputPS4Controller, NULL }, // Hori Fighting Stick mini 4 kai - becomes an Xbox 360 controller on PC
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x00ee ), k_eControllerType_PS4Controller, NULL }, // Hori mini wired https://www.playstation.com/en-us/explore/accessories/gaming-controllers/mini-wired-gamepad/
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x011c ), k_eControllerType_PS4Controller, NULL }, // Hori Fighting Stick α
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x0123 ), k_eControllerType_PS4Controller, NULL }, // HORI Wireless Controller Light (Japan only) - only over bt- over usb is xbox and pid 0x0124
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x0162 ), k_eControllerType_PS4Controller, NULL }, // HORI Fighting Commander OCTA
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x0164 ), k_eControllerType_XInputPS4Controller, NULL }, // HORI Fighting Commander OCTA
{ MAKE_CONTROLLER_ID( 0x11c0, 0x4001 ), k_eControllerType_PS4Controller, NULL }, // "PS4 Fun Controller" added from user log
{ MAKE_CONTROLLER_ID( 0x146b, 0x0603 ), k_eControllerType_XInputPS4Controller, NULL }, // Nacon PS4 Compact Controller
{ MAKE_CONTROLLER_ID( 0x146b, 0x0604 ), k_eControllerType_XInputPS4Controller, NULL }, // NACON Daija Arcade Stick
{ MAKE_CONTROLLER_ID( 0x146b, 0x0605 ), k_eControllerType_XInputPS4Controller, NULL }, // NACON PS4 controller in Xbox mode - might also be other bigben brand xbox controllers
{ MAKE_CONTROLLER_ID( 0x146b, 0x0606 ), k_eControllerType_XInputPS4Controller, NULL }, // NACON Unknown Controller
{ MAKE_CONTROLLER_ID( 0x146b, 0x0609 ), k_eControllerType_XInputPS4Controller, NULL }, // NACON Wireless Controller for PS4
{ MAKE_CONTROLLER_ID( 0x146b, 0x0d01 ), k_eControllerType_PS4Controller, NULL }, // Nacon Revolution Pro Controller - has gyro
{ MAKE_CONTROLLER_ID( 0x146b, 0x0d02 ), k_eControllerType_PS4Controller, NULL }, // Nacon Revolution Pro Controller v2 - has gyro
{ MAKE_CONTROLLER_ID( 0x146b, 0x0d06 ), k_eControllerType_PS4Controller, NULL }, // NACON Asymmetric Controller Wireless Dongle -- show up as ps4 until you connect controller to it then it reboots into Xbox controller with different vvid/pid
{ MAKE_CONTROLLER_ID( 0x146b, 0x0d08 ), k_eControllerType_PS4Controller, NULL }, // NACON Revolution Unlimited Wireless Dongle
{ MAKE_CONTROLLER_ID( 0x146b, 0x0d09 ), k_eControllerType_PS4Controller, NULL }, // NACON Daija Fight Stick - touchpad but no gyro/rumble
{ MAKE_CONTROLLER_ID( 0x146b, 0x0d10 ), k_eControllerType_PS4Controller, NULL }, // NACON Revolution Infinite - has gyro
{ MAKE_CONTROLLER_ID( 0x146b, 0x0d10 ), k_eControllerType_PS4Controller, NULL }, // NACON Revolution Unlimited
{ MAKE_CONTROLLER_ID( 0x146b, 0x0d13 ), k_eControllerType_PS4Controller, NULL }, // NACON Revolution Pro Controller 3
{ MAKE_CONTROLLER_ID( 0x146b, 0x1103 ), k_eControllerType_PS4Controller, NULL }, // NACON Asymmetric Controller -- on windows this doesn't enumerate
{ MAKE_CONTROLLER_ID( 0x1532, 0X0401 ), k_eControllerType_PS4Controller, NULL }, // Razer Panthera PS4 Controller
{ MAKE_CONTROLLER_ID( 0x1532, 0x1000 ), k_eControllerType_PS4Controller, NULL }, // Razer Raiju PS4 Controller
{ MAKE_CONTROLLER_ID( 0x1532, 0x1004 ), k_eControllerType_PS4Controller, NULL }, // Razer Raiju 2 Ultimate USB
{ MAKE_CONTROLLER_ID( 0x1532, 0x1007 ), k_eControllerType_PS4Controller, NULL }, // Razer Raiju 2 Tournament edition USB
{ MAKE_CONTROLLER_ID( 0x1532, 0x1008 ), k_eControllerType_PS4Controller, NULL }, // Razer Panthera Evo Fightstick
{ MAKE_CONTROLLER_ID( 0x1532, 0x1009 ), k_eControllerType_PS4Controller, NULL }, // Razer Raiju 2 Ultimate BT
{ MAKE_CONTROLLER_ID( 0x1532, 0x100A ), k_eControllerType_PS4Controller, NULL }, // Razer Raiju 2 Tournament edition BT
{ MAKE_CONTROLLER_ID( 0x1532, 0x1100 ), k_eControllerType_PS4Controller, NULL }, // Razer RAION Fightpad - Trackpad, no gyro, lightbar hardcoded to green
{ MAKE_CONTROLLER_ID( 0x20d6, 0x792a ), k_eControllerType_PS4Controller, NULL }, // PowerA Fusion Fight Pad
{ MAKE_CONTROLLER_ID( 0x2c22, 0x2000 ), k_eControllerType_PS4Controller, NULL }, // Qanba Drone
{ MAKE_CONTROLLER_ID( 0x2c22, 0x2300 ), k_eControllerType_PS4Controller, NULL }, // Qanba Obsidian
{ MAKE_CONTROLLER_ID( 0x2c22, 0x2303 ), k_eControllerType_XInputPS4Controller, NULL }, // Qanba Obsidian Arcade Joystick
{ MAKE_CONTROLLER_ID( 0x2c22, 0x2500 ), k_eControllerType_PS4Controller, NULL }, // Qanba Dragon
{ MAKE_CONTROLLER_ID( 0x2c22, 0x2503 ), k_eControllerType_XInputPS4Controller, NULL }, // Qanba Dragon Arcade Joystick
{ MAKE_CONTROLLER_ID( 0x3285, 0x0d16 ), k_eControllerType_PS4Controller, NULL }, // NACON Revolution 5 Pro (PS4 mode with dongle)
{ MAKE_CONTROLLER_ID( 0x3285, 0x0d17 ), k_eControllerType_PS4Controller, NULL }, // NACON Revolution 5 Pro (PS4 mode wired)
{ MAKE_CONTROLLER_ID( 0x7545, 0x0104 ), k_eControllerType_PS4Controller, NULL }, // Armor 3 or Level Up Cobra - At least one variant has gyro
{ MAKE_CONTROLLER_ID (0x9886, 0x0024 ), k_eControllerType_XInputPS4Controller, NULL }, // Astro C40 in Xbox 360 mode
{ MAKE_CONTROLLER_ID( 0x9886, 0x0025 ), k_eControllerType_PS4Controller, NULL }, // Astro C40
// Removing the Giotek because there were a bunch of help tickets from users w/ issues including from non-PS4 controller users. This VID/PID is probably used in different FW's
// { MAKE_CONTROLLER_ID( 0x7545, 0x1122 ), k_eControllerType_PS4Controller, NULL }, // Giotek VX4 - trackpad/gyro don't work. Had to not filter on interface info. Light bar is flaky, but works.
{ MAKE_CONTROLLER_ID( 0x054c, 0x0ce6 ), k_eControllerType_PS5Controller, NULL }, // Sony DualSense Controller
{ MAKE_CONTROLLER_ID( 0x054c, 0x0e5f ), k_eControllerType_PS5Controller, NULL }, // Access Controller for PS5
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0209 ), k_eControllerType_PS5Controller, NULL }, // Victrix Pro FS PS4/PS5 (PS5 mode)
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x0163 ), k_eControllerType_PS5Controller, NULL }, // HORI Fighting Commander OCTA
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x0184 ), k_eControllerType_PS5Controller, NULL }, // Hori Fighting Stick α
{ MAKE_CONTROLLER_ID( 0x1532, 0x100b ), k_eControllerType_PS5Controller, NULL }, // Razer Wolverine V2 Pro (Wired)
{ MAKE_CONTROLLER_ID( 0x1532, 0x100c ), k_eControllerType_PS5Controller, NULL }, // Razer Wolverine V2 Pro (Wireless)
{ MAKE_CONTROLLER_ID( 0x1532, 0x1012 ), k_eControllerType_PS5Controller, NULL }, // Razer Kitsune
{ MAKE_CONTROLLER_ID( 0x1532, 0x1024 ), k_eControllerType_PS5Controller, NULL }, // Razer Raiju V3 Pro (PS5 mode wired)
{ MAKE_CONTROLLER_ID( 0x1532, 0x1026 ), k_eControllerType_PS5Controller, NULL }, // Razer Raiju V3 Pro (PS5 mode with dongle)
{ MAKE_CONTROLLER_ID( 0x3285, 0x0d18 ), k_eControllerType_PS5Controller, NULL }, // NACON Revolution 5 Pro (PS5 mode with dongle)
{ MAKE_CONTROLLER_ID( 0x3285, 0x0d19 ), k_eControllerType_PS5Controller, NULL }, // NACON Revolution 5 Pro (PS5 mode wired)
{ MAKE_CONTROLLER_ID( 0x358a, 0x0104 ), k_eControllerType_PS5Controller, NULL }, // Backbone One PlayStation Edition for iOS
{ MAKE_CONTROLLER_ID( 0x358a, 0x0304 ), k_eControllerType_PS5Controller, NULL }, // Backbone One PlayStation Edition Gen 2
{ MAKE_CONTROLLER_ID( 0x0079, 0x0006 ), k_eControllerType_UnknownNonSteamController, NULL }, // DragonRise Generic USB PCB, sometimes configured as a PC Twin Shock Controller - looks like a DS3 but the face buttons are 1-4 instead of symbols
{ MAKE_CONTROLLER_ID( 0x0079, 0x18d4 ), k_eControllerType_XBox360Controller, NULL }, // GPD Win 2 X-Box Controller
{ MAKE_CONTROLLER_ID( 0x0351, 0x1000 ), k_eControllerType_XBox360Controller, NULL }, // CRKD Guitar
{ MAKE_CONTROLLER_ID( 0x0351, 0x2000 ), k_eControllerType_XBox360Controller, NULL }, // CRKD Guitar
{ MAKE_CONTROLLER_ID( 0x03eb, 0xff02 ), k_eControllerType_XBox360Controller, NULL }, // Wooting Two
{ MAKE_CONTROLLER_ID( 0x044f, 0xb326 ), k_eControllerType_XBox360Controller, NULL }, // Thrustmaster Gamepad GP XID
{ MAKE_CONTROLLER_ID( 0x045e, 0x028e ), k_eControllerType_XBox360Controller, "Xbox 360 Controller" }, // Microsoft Xbox 360 Wired Controller
{ MAKE_CONTROLLER_ID( 0x045e, 0x028f ), k_eControllerType_XBox360Controller, "Xbox 360 Controller" }, // Microsoft Xbox 360 Play and Charge Cable
{ MAKE_CONTROLLER_ID( 0x045e, 0x0291 ), k_eControllerType_XBox360Controller, "Xbox 360 Wireless Controller" }, // X-box 360 Wireless Receiver (third party knockoff)
{ MAKE_CONTROLLER_ID( 0x045e, 0x02a0 ), k_eControllerType_XBox360Controller, NULL }, // Microsoft Xbox 360 Big Button IR
{ MAKE_CONTROLLER_ID( 0x045e, 0x02a1 ), k_eControllerType_XBox360Controller, "Xbox 360 Wireless Controller" }, // Microsoft Xbox 360 Wireless Controller with XUSB driver on Windows
{ MAKE_CONTROLLER_ID( 0x045e, 0x02a2 ), k_eControllerType_XBox360Controller, "Xbox 360 Wireless Racing Wheel" }, // Xbox 360 Wireless Racing Wheel with XUSB driver on Windows
{ MAKE_CONTROLLER_ID( 0x045e, 0x02a9 ), k_eControllerType_XBox360Controller, "Xbox 360 Wireless Controller" }, // X-box 360 Wireless Receiver (third party knockoff)
{ MAKE_CONTROLLER_ID( 0x045e, 0x0719 ), k_eControllerType_XBox360Controller, "Xbox 360 Wireless Controller" }, // Microsoft Xbox 360 Wireless Receiver
{ MAKE_CONTROLLER_ID( 0x046d, 0xc21d ), k_eControllerType_XBox360Controller, NULL }, // Logitech Gamepad F310
{ MAKE_CONTROLLER_ID( 0x046d, 0xc21e ), k_eControllerType_XBox360Controller, NULL }, // Logitech Gamepad F510
{ MAKE_CONTROLLER_ID( 0x046d, 0xc21f ), k_eControllerType_XBox360Controller, NULL }, // Logitech Gamepad F710
{ MAKE_CONTROLLER_ID( 0x046d, 0xc242 ), k_eControllerType_XBox360Controller, NULL }, // Logitech Chillstream Controller
{ MAKE_CONTROLLER_ID( 0x056e, 0x2004 ), k_eControllerType_XBox360Controller, NULL }, // Elecom JC-U3613M
// This isn't actually an Xbox 360 controller, it just looks like one
// { MAKE_CONTROLLER_ID( 0x06a3, 0xf51a ), k_eControllerType_XBox360Controller, NULL }, // Saitek P3600
{ MAKE_CONTROLLER_ID( 0x0738, 0x02A6 ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz Wireless Rock Band Guitar
{ MAKE_CONTROLLER_ID( 0x0738, 0x02AB ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz Wireless Precision Bass Guitar
{ MAKE_CONTROLLER_ID( 0x0738, 0x4716 ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz Wired Xbox 360 Controller
{ MAKE_CONTROLLER_ID( 0x0738, 0x4718 ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz Street Fighter IV FightStick SE
{ MAKE_CONTROLLER_ID( 0x0738, 0x4726 ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz Xbox 360 Controller
{ MAKE_CONTROLLER_ID( 0x0738, 0x4728 ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz Street Fighter IV FightPad
{ MAKE_CONTROLLER_ID( 0x0738, 0x4736 ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz MicroCon Gamepad
{ MAKE_CONTROLLER_ID( 0x0738, 0x4738 ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz Wired Xbox 360 Controller (SFIV)
{ MAKE_CONTROLLER_ID( 0x0738, 0x4740 ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz Beat Pad
{ MAKE_CONTROLLER_ID( 0x0738, 0x9806 ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz Precision Bass Guitar
{ MAKE_CONTROLLER_ID( 0x0738, 0xb726 ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz Xbox controller - MW2
{ MAKE_CONTROLLER_ID( 0x0738, 0xbeef ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz JOYTECH NEO SE Advanced GamePad
{ MAKE_CONTROLLER_ID( 0x0738, 0xcb02 ), k_eControllerType_XBox360Controller, NULL }, // Saitek Cyborg Rumble Pad - PC/Xbox 360
{ MAKE_CONTROLLER_ID( 0x0738, 0xcb03 ), k_eControllerType_XBox360Controller, NULL }, // Saitek P3200 Rumble Pad - PC/Xbox 360
{ MAKE_CONTROLLER_ID( 0x0738, 0xf738 ), k_eControllerType_XBox360Controller, NULL }, // Super SFIV FightStick TE S
{ MAKE_CONTROLLER_ID( 0x0955, 0x7210 ), k_eControllerType_XBox360Controller, NULL }, // Nvidia Shield local controller
{ MAKE_CONTROLLER_ID( 0x0955, 0xb400 ), k_eControllerType_XBox360Controller, NULL }, // NVIDIA Shield streaming controller
{ MAKE_CONTROLLER_ID( 0x0b05, 0x1b4c ), k_eControllerType_XBox360Controller, NULL }, // ASUS ROG Ally X built-in controller
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0105 ), k_eControllerType_XBox360Controller, NULL }, // HSM3 Xbox360 dancepad
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0113 ), k_eControllerType_XBox360Controller, "PDP Xbox 360 Afterglow" }, // PDP Afterglow Gamepad for Xbox 360
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x011f ), k_eControllerType_XBox360Controller, "PDP Xbox 360 Rock Candy" }, // PDP Rock Candy Gamepad for Xbox 360
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0125 ), k_eControllerType_XBox360Controller, "PDP INJUSTICE FightStick" }, // PDP INJUSTICE FightStick for Xbox 360
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0127 ), k_eControllerType_XBox360Controller, "PDP INJUSTICE FightPad" }, // PDP INJUSTICE FightPad for Xbox 360
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0131 ), k_eControllerType_XBox360Controller, "PDP EA Soccer Controller" }, // PDP EA Soccer Gamepad
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0133 ), k_eControllerType_XBox360Controller, "PDP Battlefield 4 Controller" }, // PDP Battlefield 4 Gamepad
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0143 ), k_eControllerType_XBox360Controller, "PDP MK X Fight Stick" }, // PDP MK X Fight Stick for Xbox 360
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0147 ), k_eControllerType_XBox360Controller, "PDP Xbox 360 Marvel Controller" }, // PDP Marvel Controller for Xbox 360
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0201 ), k_eControllerType_XBox360Controller, "PDP Xbox 360 Controller" }, // PDP Gamepad for Xbox 360
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0213 ), k_eControllerType_XBox360Controller, "PDP Xbox 360 Afterglow" }, // PDP Afterglow Gamepad for Xbox 360
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x021f ), k_eControllerType_XBox360Controller, "PDP Xbox 360 Rock Candy" }, // PDP Rock Candy Gamepad for Xbox 360
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0301 ), k_eControllerType_XBox360Controller, "PDP Xbox 360 Controller" }, // PDP Gamepad for Xbox 360
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0313 ), k_eControllerType_XBox360Controller, "PDP Xbox 360 Afterglow" }, // PDP Afterglow Gamepad for Xbox 360
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0314 ), k_eControllerType_XBox360Controller, "PDP Xbox 360 Afterglow" }, // PDP Afterglow Gamepad for Xbox 360
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0401 ), k_eControllerType_XBox360Controller, "PDP Xbox 360 Controller" }, // PDP Gamepad for Xbox 360
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0413 ), k_eControllerType_XBox360Controller, NULL }, // PDP Afterglow AX.1 (unlisted)
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0501 ), k_eControllerType_XBox360Controller, NULL }, // PDP Xbox 360 Controller (unlisted)
{ MAKE_CONTROLLER_ID( 0x0e6f, 0xf900 ), k_eControllerType_XBox360Controller, NULL }, // PDP Afterglow AX.1 (unlisted)
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x000a ), k_eControllerType_XBox360Controller, NULL }, // Hori Co. DOA4 FightStick
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x000c ), k_eControllerType_XBox360Controller, NULL }, // Hori PadEX Turbo
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x000d ), k_eControllerType_XBox360Controller, NULL }, // Hori Fighting Stick EX2
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x0016 ), k_eControllerType_XBox360Controller, NULL }, // Hori Real Arcade Pro.EX
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x001b ), k_eControllerType_XBox360Controller, NULL }, // Hori Real Arcade Pro VX
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x008c ), k_eControllerType_XBox360Controller, NULL }, // Hori Real Arcade Pro 4
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x00db ), k_eControllerType_XBox360Controller, "HORI Slime Controller" }, // Hori Dragon Quest Slime Controller
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x011e ), k_eControllerType_XBox360Controller, NULL }, // Hori Fighting Stick α
{ MAKE_CONTROLLER_ID( 0x1038, 0x1430 ), k_eControllerType_XBox360Controller, "SteelSeries Stratus Duo" }, // SteelSeries Stratus Duo
{ MAKE_CONTROLLER_ID( 0x1038, 0x1431 ), k_eControllerType_XBox360Controller, "SteelSeries Stratus Duo" }, // SteelSeries Stratus Duo
{ MAKE_CONTROLLER_ID( 0x1038, 0xb360 ), k_eControllerType_XBox360Controller, NULL }, // SteelSeries Nimbus/Stratus XL
{ MAKE_CONTROLLER_ID( 0x11c9, 0x55f0 ), k_eControllerType_XBox360Controller, NULL }, // Nacon GC-100XF
{ MAKE_CONTROLLER_ID( 0x12ab, 0x0004 ), k_eControllerType_XBox360Controller, NULL }, // Honey Bee Xbox360 dancepad
{ MAKE_CONTROLLER_ID( 0x12ab, 0x0301 ), k_eControllerType_XBox360Controller, NULL }, // PDP AFTERGLOW AX.1
{ MAKE_CONTROLLER_ID( 0x12ab, 0x0303 ), k_eControllerType_XBox360Controller, NULL }, // Mortal Kombat Klassic FightStick
{ MAKE_CONTROLLER_ID( 0x1430, 0x02a0 ), k_eControllerType_XBox360Controller, NULL }, // RedOctane Controller Adapter
{ MAKE_CONTROLLER_ID( 0x1430, 0x02a7 ), k_eControllerType_XBox360Controller, NULL }, // Guitar Hero Wireless Guitar (Linux)
{ MAKE_CONTROLLER_ID( 0x1430, 0x02a8 ), k_eControllerType_XBox360Controller, NULL }, // Guitar Hero Wireless Drum Kit (Linux)
{ MAKE_CONTROLLER_ID( 0x1430, 0x0705 ), k_eControllerType_XBox360Controller, NULL }, // Guitar Hero 5 Guitar
{ MAKE_CONTROLLER_ID( 0x1430, 0x070B ), k_eControllerType_XBox360Controller, NULL }, // Guitar Hero Live Guitar
{ MAKE_CONTROLLER_ID( 0x1430, 0x0805 ), k_eControllerType_XBox360Controller, NULL }, // Band Hero Wireless Drum Kit
{ MAKE_CONTROLLER_ID( 0x1430, 0x1715 ), k_eControllerType_XBox360Controller, NULL }, // DJ Hero Turntable (Wired)
{ MAKE_CONTROLLER_ID( 0x1430, 0x1705 ), k_eControllerType_XBox360Controller, NULL }, // DJ Hero Turntable (Wireless)
{ MAKE_CONTROLLER_ID( 0x1430, 0x4734 ), k_eControllerType_XBox360Controller, NULL }, // Guitar Hero World Tour Kiosk
{ MAKE_CONTROLLER_ID( 0x1430, 0x4748 ), k_eControllerType_XBox360Controller, NULL }, // RedOctane Guitar Hero X-plorer
{ MAKE_CONTROLLER_ID( 0x1430, 0xf801 ), k_eControllerType_XBox360Controller, NULL }, // RedOctane Controller
{ MAKE_CONTROLLER_ID( 0x146b, 0x0601 ), k_eControllerType_XBox360Controller, NULL }, // BigBen Interactive XBOX 360 Controller
// { MAKE_CONTROLLER_ID( 0x1532, 0x0037 ), k_eControllerType_XBox360Controller, NULL }, // Razer Sabertooth
{ MAKE_CONTROLLER_ID( 0x15e4, 0x3f00 ), k_eControllerType_XBox360Controller, NULL }, // Power A Mini Pro Elite
{ MAKE_CONTROLLER_ID( 0x15e4, 0x3f0a ), k_eControllerType_XBox360Controller, NULL }, // Xbox Airflo wired controller
{ MAKE_CONTROLLER_ID( 0x15e4, 0x3f10 ), k_eControllerType_XBox360Controller, NULL }, // Batarang Xbox 360 controller
{ MAKE_CONTROLLER_ID( 0x162e, 0xbeef ), k_eControllerType_XBox360Controller, NULL }, // Joytech Neo-Se Take2
{ MAKE_CONTROLLER_ID( 0x1689, 0xfd00 ), k_eControllerType_XBox360Controller, NULL }, // Razer Onza Tournament Edition
{ MAKE_CONTROLLER_ID( 0x1689, 0xfd01 ), k_eControllerType_XBox360Controller, NULL }, // Razer Onza Classic Edition
{ MAKE_CONTROLLER_ID( 0x1689, 0xfe00 ), k_eControllerType_XBox360Controller, NULL }, // Razer Sabertooth
{ MAKE_CONTROLLER_ID( 0x1949, 0x041a ), k_eControllerType_XBox360Controller, "Amazon Luna Controller" }, // Amazon Luna Controller
{ MAKE_CONTROLLER_ID( 0x1bad, 0x0002 ), k_eControllerType_XBox360Controller, NULL }, // Harmonix Rock Band 1 Guitar
{ MAKE_CONTROLLER_ID( 0x1bad, 0x0003 ), k_eControllerType_XBox360Controller, NULL }, // Harmonix Rock Band Drumkit
{ MAKE_CONTROLLER_ID( 0x1bad, 0x0130 ), k_eControllerType_XBox360Controller, NULL }, // ION Drum Rocker
{ MAKE_CONTROLLER_ID( 0x1bad, 0x02a6 ), k_eControllerType_XBox360Controller, NULL }, // Rock Band 2 Wireless Guitar (Linux)
{ MAKE_CONTROLLER_ID( 0x1bad, 0x02ab ), k_eControllerType_XBox360Controller, NULL }, // Rock Band Wireless Bass Guitar (Linux)
{ MAKE_CONTROLLER_ID( 0x1bad, 0x1330 ), k_eControllerType_XBox360Controller, NULL }, // Rock Band Keyboard (Mustang)
{ MAKE_CONTROLLER_ID( 0x1bad, 0x1338 ), k_eControllerType_XBox360Controller, NULL }, // Rock Band MIDI Pro Adapter (Keyboard)
{ MAKE_CONTROLLER_ID( 0x1bad, 0x1430 ), k_eControllerType_XBox360Controller, NULL }, // Rock Band Pro Guitar (Mustang)
{ MAKE_CONTROLLER_ID( 0x1bad, 0x1530 ), k_eControllerType_XBox360Controller, NULL }, // Rock Band Pro Guitar (Squire)
{ MAKE_CONTROLLER_ID( 0x1bad, 0x1438 ), k_eControllerType_XBox360Controller, NULL }, // Rock Band MIDI Pro Adapter (Mustang Guitar)
{ MAKE_CONTROLLER_ID( 0x1bad, 0x1538 ), k_eControllerType_XBox360Controller, NULL }, // Rock Band MIDI Pro Adapter (Squire Guitar)
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf016 ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz Xbox 360 Controller
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf018 ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz Street Fighter IV SE Fighting Stick
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf019 ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz Brawlstick for Xbox 360
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf021 ), k_eControllerType_XBox360Controller, NULL }, // Mad Cats Ghost Recon FS GamePad
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf023 ), k_eControllerType_XBox360Controller, NULL }, // MLG Pro Circuit Controller (Xbox)
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf025 ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz Call Of Duty
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf027 ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz FPS Pro
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf028 ), k_eControllerType_XBox360Controller, NULL }, // Street Fighter IV FightPad
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf02e ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz Fightpad
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf036 ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz MicroCon GamePad Pro
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf038 ), k_eControllerType_XBox360Controller, NULL }, // Street Fighter IV FightStick TE
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf039 ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz MvC2 TE
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf03a ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz SFxT Fightstick Pro
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf03d ), k_eControllerType_XBox360Controller, NULL }, // Street Fighter IV Arcade Stick TE - Chun Li
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf03e ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz MLG FightStick TE
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf03f ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz FightStick SoulCaliber
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf042 ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz FightStick TES+
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf080 ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz FightStick TE2
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf501 ), k_eControllerType_XBox360Controller, NULL }, // HoriPad EX2 Turbo
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf502 ), k_eControllerType_XBox360Controller, NULL }, // Hori Real Arcade Pro.VX SA
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf503 ), k_eControllerType_XBox360Controller, NULL }, // Hori Fighting Stick VX
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf504 ), k_eControllerType_XBox360Controller, NULL }, // Hori Real Arcade Pro. EX
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf505 ), k_eControllerType_XBox360Controller, NULL }, // Hori Fighting Stick EX2B
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf506 ), k_eControllerType_XBox360Controller, NULL }, // Hori Real Arcade Pro.EX Premium VLX
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf900 ), k_eControllerType_XBox360Controller, NULL }, // Harmonix Xbox 360 Controller
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf901 ), k_eControllerType_XBox360Controller, NULL }, // Gamestop Xbox 360 Controller
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf902 ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz Gamepad2
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf903 ), k_eControllerType_XBox360Controller, NULL }, // Tron Xbox 360 controller
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf904 ), k_eControllerType_XBox360Controller, NULL }, // PDP Versus Fighting Pad
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf906 ), k_eControllerType_XBox360Controller, NULL }, // MortalKombat FightStick
{ MAKE_CONTROLLER_ID( 0x1bad, 0xfa01 ), k_eControllerType_XBox360Controller, NULL }, // MadCatz GamePad
{ MAKE_CONTROLLER_ID( 0x1bad, 0xfd00 ), k_eControllerType_XBox360Controller, NULL }, // Razer Onza TE
{ MAKE_CONTROLLER_ID( 0x1bad, 0xfd01 ), k_eControllerType_XBox360Controller, NULL }, // Razer Onza
{ MAKE_CONTROLLER_ID( 0x2068, 0x0001 ), k_eControllerType_XBox360Controller, NULL }, // Power Gig Guitar
{ MAKE_CONTROLLER_ID( 0x2068, 0x0002 ), k_eControllerType_XBox360Controller, NULL }, // Power Gig Drums
{ MAKE_CONTROLLER_ID( 0x24c6, 0x5000 ), k_eControllerType_XBox360Controller, NULL }, // Razer Atrox Arcade Stick
{ MAKE_CONTROLLER_ID( 0x24c6, 0x5300 ), k_eControllerType_XBox360Controller, NULL }, // PowerA MINI PROEX Controller
{ MAKE_CONTROLLER_ID( 0x24c6, 0x5303 ), k_eControllerType_XBox360Controller, NULL }, // Xbox Airflo wired controller
{ MAKE_CONTROLLER_ID( 0x24c6, 0x530a ), k_eControllerType_XBox360Controller, NULL }, // Xbox 360 Pro EX Controller
{ MAKE_CONTROLLER_ID( 0x24c6, 0x531a ), k_eControllerType_XBox360Controller, NULL }, // PowerA Pro Ex
{ MAKE_CONTROLLER_ID( 0x24c6, 0x5397 ), k_eControllerType_XBox360Controller, NULL }, // FUS1ON Tournament Controller
{ MAKE_CONTROLLER_ID( 0x24c6, 0x5500 ), k_eControllerType_XBox360Controller, NULL }, // Hori XBOX 360 EX 2 with Turbo
{ MAKE_CONTROLLER_ID( 0x24c6, 0x5501 ), k_eControllerType_XBox360Controller, NULL }, // Hori Real Arcade Pro VX-SA
{ MAKE_CONTROLLER_ID( 0x24c6, 0x5502 ), k_eControllerType_XBox360Controller, NULL }, // Hori Fighting Stick VX Alt
{ MAKE_CONTROLLER_ID( 0x24c6, 0x5503 ), k_eControllerType_XBox360Controller, NULL }, // Hori Fighting Edge
{ MAKE_CONTROLLER_ID( 0x24c6, 0x5506 ), k_eControllerType_XBox360Controller, NULL }, // Hori SOULCALIBUR V Stick
{ MAKE_CONTROLLER_ID( 0x24c6, 0x550d ), k_eControllerType_XBox360Controller, NULL }, // Hori GEM Xbox controller
{ MAKE_CONTROLLER_ID( 0x24c6, 0x550e ), k_eControllerType_XBox360Controller, NULL }, // Hori Real Arcade Pro V Kai 360
{ MAKE_CONTROLLER_ID( 0x24c6, 0x5508 ), k_eControllerType_XBox360Controller, NULL }, // Hori PAD A
{ MAKE_CONTROLLER_ID( 0x24c6, 0x5510 ), k_eControllerType_XBox360Controller, NULL }, // Hori Fighting Commander ONE
{ MAKE_CONTROLLER_ID( 0x24c6, 0x5b00 ), k_eControllerType_XBox360Controller, NULL }, // ThrustMaster Ferrari Italia 458 Racing Wheel
{ MAKE_CONTROLLER_ID( 0x24c6, 0x5b02 ), k_eControllerType_XBox360Controller, NULL }, // Thrustmaster, Inc. GPX Controller
{ MAKE_CONTROLLER_ID( 0x24c6, 0x5b03 ), k_eControllerType_XBox360Controller, NULL }, // Thrustmaster Ferrari 458 Racing Wheel
{ MAKE_CONTROLLER_ID( 0x24c6, 0x5d04 ), k_eControllerType_XBox360Controller, NULL }, // Razer Sabertooth
{ MAKE_CONTROLLER_ID( 0x24c6, 0xfafa ), k_eControllerType_XBox360Controller, NULL }, // Aplay Controller
{ MAKE_CONTROLLER_ID( 0x24c6, 0xfafb ), k_eControllerType_XBox360Controller, NULL }, // Aplay Controller
{ MAKE_CONTROLLER_ID( 0x24c6, 0xfafc ), k_eControllerType_XBox360Controller, NULL }, // Afterglow Gamepad 1
{ MAKE_CONTROLLER_ID( 0x24c6, 0xfafd ), k_eControllerType_XBox360Controller, NULL }, // Afterglow Gamepad 3
{ MAKE_CONTROLLER_ID( 0x3537, 0x103e ), k_eControllerType_XBox360Controller, "Gamesir Xbox Controller" }, // Gamesir dongle for Supernova (and maybe others) in Xinput mode
{ MAKE_CONTROLLER_ID( 0x24c6, 0xfafe ), k_eControllerType_XBox360Controller, NULL }, // Rock Candy Gamepad for Xbox 360
{ MAKE_CONTROLLER_ID( 0x3651, 0x1000 ), k_eControllerType_XBox360Controller, NULL }, // CRKD Guitar
{ MAKE_CONTROLLER_ID( 0x3651, 0x6000 ), k_eControllerType_XBox360Controller, NULL }, // CRKD Guitar
{ MAKE_CONTROLLER_ID( 0x03f0, 0x0495 ), k_eControllerType_XBoxOneController, NULL }, // HP HyperX Clutch Gladiate
{ MAKE_CONTROLLER_ID( 0x044f, 0xd012 ), k_eControllerType_XBoxOneController, NULL }, // ThrustMaster eSwap PRO Controller Xbox
{ MAKE_CONTROLLER_ID( 0x045e, 0x02d1 ), k_eControllerType_XBoxOneController, "Xbox One Controller" }, // Microsoft Xbox One Controller
{ MAKE_CONTROLLER_ID( 0x045e, 0x02dd ), k_eControllerType_XBoxOneController, "Xbox One Controller" }, // Microsoft Xbox One Controller (Firmware 2015)
{ MAKE_CONTROLLER_ID( 0x045e, 0x02e0 ), k_eControllerType_XBoxOneController, "Xbox One S Controller" }, // Microsoft Xbox One S Controller (Bluetooth)
{ MAKE_CONTROLLER_ID( 0x045e, 0x02ea ), k_eControllerType_XBoxOneController, "Xbox One S Controller" }, // Microsoft Xbox One S Controller
{ MAKE_CONTROLLER_ID( 0x045e, 0x02fd ), k_eControllerType_XBoxOneController, "Xbox One S Controller" }, // Microsoft Xbox One S Controller (Bluetooth)
{ MAKE_CONTROLLER_ID( 0x045e, 0x02ff ), k_eControllerType_XBoxOneController, "Xbox One Controller" }, // Microsoft Xbox One Controller with XBOXGIP driver on Windows
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b0a ), k_eControllerType_XBoxOneController, "Xbox Adaptive Controller" }, // Microsoft Xbox Adaptive Controller
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b0c ), k_eControllerType_XBoxOneController, "Xbox Adaptive Controller" }, // Microsoft Xbox Adaptive Controller (Bluetooth)
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b12 ), k_eControllerType_XBoxOneController, "Xbox Series X Controller" }, // Microsoft Xbox Series X Controller
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b13 ), k_eControllerType_XBoxOneController, "Xbox Series X Controller" }, // Microsoft Xbox Series X Controller (BLE)
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b20 ), k_eControllerType_XBoxOneController, "Xbox One S Controller" }, // Microsoft Xbox One S Controller (BLE)
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b21 ), k_eControllerType_XBoxOneController, "Xbox Adaptive Controller" }, // Microsoft Xbox Adaptive Controller (BLE)
{ MAKE_CONTROLLER_ID( 0x0738, 0x4a01 ), k_eControllerType_XBoxOneController, NULL }, // Mad Catz FightStick TE 2
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0139 ), k_eControllerType_XBoxOneController, "PDP Xbox One Afterglow" }, // PDP Afterglow Wired Controller for Xbox One
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x013B ), k_eControllerType_XBoxOneController, "PDP Xbox One Face-Off Controller" }, // PDP Face-Off Gamepad for Xbox One
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x013a ), k_eControllerType_XBoxOneController, NULL }, // PDP Xbox One Controller (unlisted)
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0145 ), k_eControllerType_XBoxOneController, "PDP MK X Fight Pad" }, // PDP MK X Fight Pad for Xbox One
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0146 ), k_eControllerType_XBoxOneController, "PDP Xbox One Rock Candy" }, // PDP Rock Candy Wired Controller for Xbox One
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x015b ), k_eControllerType_XBoxOneController, "PDP Fallout 4 Vault Boy Controller" }, // PDP Fallout 4 Vault Boy Wired Controller for Xbox One
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x015c ), k_eControllerType_XBoxOneController, "PDP Xbox One @Play Controller" }, // PDP @Play Wired Controller for Xbox One
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x015d ), k_eControllerType_XBoxOneController, "PDP Mirror's Edge Controller" }, // PDP Mirror's Edge Wired Controller for Xbox One
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x015f ), k_eControllerType_XBoxOneController, "PDP Metallic Controller" }, // PDP Metallic Wired Controller for Xbox One
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0160 ), k_eControllerType_XBoxOneController, "PDP NFL Face-Off Controller" }, // PDP NFL Official Face-Off Wired Controller for Xbox One
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0161 ), k_eControllerType_XBoxOneController, "PDP Xbox One Camo" }, // PDP Camo Wired Controller for Xbox One
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0162 ), k_eControllerType_XBoxOneController, "PDP Xbox One Controller" }, // PDP Wired Controller for Xbox One
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0163 ), k_eControllerType_XBoxOneController, "PDP Deliverer of Truth" }, // PDP Legendary Collection: Deliverer of Truth
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0164 ), k_eControllerType_XBoxOneController, "PDP Battlefield 1 Controller" }, // PDP Battlefield 1 Official Wired Controller for Xbox One
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0165 ), k_eControllerType_XBoxOneController, "PDP Titanfall 2 Controller" }, // PDP Titanfall 2 Official Wired Controller for Xbox One
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0166 ), k_eControllerType_XBoxOneController, "PDP Mass Effect: Andromeda Controller" }, // PDP Mass Effect: Andromeda Official Wired Controller for Xbox One
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0167 ), k_eControllerType_XBoxOneController, "PDP Halo Wars 2 Face-Off Controller" }, // PDP Halo Wars 2 Official Face-Off Wired Controller for Xbox One
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0205 ), k_eControllerType_XBoxOneController, "PDP Victrix Pro Fight Stick" }, // PDP Victrix Pro Fight Stick
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0206 ), k_eControllerType_XBoxOneController, "PDP Mortal Kombat Controller" }, // PDP Mortal Kombat 25 Anniversary Edition Stick (Xbox One)
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0246 ), k_eControllerType_XBoxOneController, "PDP Xbox One Rock Candy" }, // PDP Rock Candy Wired Controller for Xbox One
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0261 ), k_eControllerType_XBoxOneController, "PDP Xbox One Camo" }, // PDP Camo Wired Controller
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0262 ), k_eControllerType_XBoxOneController, "PDP Xbox One Controller" }, // PDP Wired Controller
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02a0 ), k_eControllerType_XBoxOneController, "PDP Xbox One Midnight Blue" }, // PDP Wired Controller for Xbox One - Midnight Blue
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02a1 ), k_eControllerType_XBoxOneController, "PDP Xbox One Verdant Green" }, // PDP Wired Controller for Xbox One - Verdant Green
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02a2 ), k_eControllerType_XBoxOneController, "PDP Xbox One Crimson Red" }, // PDP Wired Controller for Xbox One - Crimson Red
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02a3 ), k_eControllerType_XBoxOneController, "PDP Xbox One Arctic White" }, // PDP Wired Controller for Xbox One - Arctic White
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02a4 ), k_eControllerType_XBoxOneController, "PDP Xbox One Phantom Black" }, // PDP Wired Controller for Xbox One - Stealth Series | Phantom Black
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02a5 ), k_eControllerType_XBoxOneController, "PDP Xbox One Ghost White" }, // PDP Wired Controller for Xbox One - Stealth Series | Ghost White
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02a6 ), k_eControllerType_XBoxOneController, "PDP Xbox One Revenant Blue" }, // PDP Wired Controller for Xbox One - Stealth Series | Revenant Blue
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02a7 ), k_eControllerType_XBoxOneController, "PDP Xbox One Raven Black" }, // PDP Wired Controller for Xbox One - Raven Black
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02a8 ), k_eControllerType_XBoxOneController, "PDP Xbox One Arctic White" }, // PDP Wired Controller for Xbox One - Arctic White
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02a9 ), k_eControllerType_XBoxOneController, "PDP Xbox One Midnight Blue" }, // PDP Wired Controller for Xbox One - Midnight Blue
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02aa ), k_eControllerType_XBoxOneController, "PDP Xbox One Verdant Green" }, // PDP Wired Controller for Xbox One - Verdant Green
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02ab ), k_eControllerType_XBoxOneController, "PDP Xbox One Crimson Red" }, // PDP Wired Controller for Xbox One - Crimson Red
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02ac ), k_eControllerType_XBoxOneController, "PDP Xbox One Ember Orange" }, // PDP Wired Controller for Xbox One - Ember Orange
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02ad ), k_eControllerType_XBoxOneController, "PDP Xbox One Phantom Black" }, // PDP Wired Controller for Xbox One - Stealth Series | Phantom Black
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02ae ), k_eControllerType_XBoxOneController, "PDP Xbox One Ghost White" }, // PDP Wired Controller for Xbox One - Stealth Series | Ghost White
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02af ), k_eControllerType_XBoxOneController, "PDP Xbox One Revenant Blue" }, // PDP Wired Controller for Xbox One - Stealth Series | Revenant Blue
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02b0 ), k_eControllerType_XBoxOneController, "PDP Xbox One Raven Black" }, // PDP Wired Controller for Xbox One - Raven Black
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02b1 ), k_eControllerType_XBoxOneController, "PDP Xbox One Arctic White" }, // PDP Wired Controller for Xbox One - Arctic White
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02b3 ), k_eControllerType_XBoxOneController, "PDP Xbox One Afterglow" }, // PDP Afterglow Prismatic Wired Controller
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02b5 ), k_eControllerType_XBoxOneController, "PDP Xbox One GAMEware Controller" }, // PDP GAMEware Wired Controller Xbox One
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02b6 ), k_eControllerType_XBoxOneController, NULL }, // PDP One-Handed Joystick Adaptive Controller
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02bd ), k_eControllerType_XBoxOneController, "PDP Xbox One Royal Purple" }, // PDP Wired Controller for Xbox One - Royal Purple
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02be ), k_eControllerType_XBoxOneController, "PDP Xbox One Raven Black" }, // PDP Deluxe Wired Controller for Xbox One - Raven Black
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02bf ), k_eControllerType_XBoxOneController, "PDP Xbox One Midnight Blue" }, // PDP Deluxe Wired Controller for Xbox One - Midnight Blue
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02c0 ), k_eControllerType_XBoxOneController, "PDP Xbox One Phantom Black" }, // PDP Deluxe Wired Controller for Xbox One - Stealth Series | Phantom Black
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02c1 ), k_eControllerType_XBoxOneController, "PDP Xbox One Ghost White" }, // PDP Deluxe Wired Controller for Xbox One - Stealth Series | Ghost White
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02c2 ), k_eControllerType_XBoxOneController, "PDP Xbox One Revenant Blue" }, // PDP Deluxe Wired Controller for Xbox One - Stealth Series | Revenant Blue
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02c3 ), k_eControllerType_XBoxOneController, "PDP Xbox One Verdant Green" }, // PDP Deluxe Wired Controller for Xbox One - Verdant Green
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02c4 ), k_eControllerType_XBoxOneController, "PDP Xbox One Ember Orange" }, // PDP Deluxe Wired Controller for Xbox One - Ember Orange
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02c5 ), k_eControllerType_XBoxOneController, "PDP Xbox One Royal Purple" }, // PDP Deluxe Wired Controller for Xbox One - Royal Purple
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02c6 ), k_eControllerType_XBoxOneController, "PDP Xbox One Crimson Red" }, // PDP Deluxe Wired Controller for Xbox One - Crimson Red
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02c7 ), k_eControllerType_XBoxOneController, "PDP Xbox One Arctic White" }, // PDP Deluxe Wired Controller for Xbox One - Arctic White
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02c8 ), k_eControllerType_XBoxOneController, "PDP Kingdom Hearts Controller" }, // PDP Kingdom Hearts Wired Controller
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02c9 ), k_eControllerType_XBoxOneController, "PDP Xbox One Phantasm Red" }, // PDP Deluxe Wired Controller for Xbox One - Stealth Series | Phantasm Red
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02ca ), k_eControllerType_XBoxOneController, "PDP Xbox One Specter Violet" }, // PDP Deluxe Wired Controller for Xbox One - Stealth Series | Specter Violet
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02cb ), k_eControllerType_XBoxOneController, "PDP Xbox One Specter Violet" }, // PDP Wired Controller for Xbox One - Stealth Series | Specter Violet
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02cd ), k_eControllerType_XBoxOneController, "PDP Xbox One Blu-merang" }, // PDP Rock Candy Wired Controller for Xbox One - Blu-merang
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02ce ), k_eControllerType_XBoxOneController, "PDP Xbox One Cranblast" }, // PDP Rock Candy Wired Controller for Xbox One - Cranblast
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02cf ), k_eControllerType_XBoxOneController, "PDP Xbox One Aqualime" }, // PDP Rock Candy Wired Controller for Xbox One - Aqualime
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02d5 ), k_eControllerType_XBoxOneController, "PDP Xbox One Red Camo" }, // PDP Wired Controller for Xbox One - Red Camo
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0346 ), k_eControllerType_XBoxOneController, "PDP Xbox One RC Gamepad" }, // PDP RC Gamepad for Xbox One
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0446 ), k_eControllerType_XBoxOneController, "PDP Xbox One RC Gamepad" }, // PDP RC Gamepad for Xbox One
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02da ), k_eControllerType_XBoxOneController, "PDP Xbox Series X Afterglow" }, // PDP Xbox Series X Afterglow
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02d6 ), k_eControllerType_XBoxOneController, "Victrix Gambit Tournament Controller" }, // Victrix Gambit Tournament Controller
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02d9 ), k_eControllerType_XBoxOneController, "PDP Xbox Series X Midnight Blue" }, // PDP Xbox Series X Midnight Blue
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x0063 ), k_eControllerType_XBoxOneController, NULL }, // Hori Real Arcade Pro Hayabusa (USA) Xbox One
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x0067 ), k_eControllerType_XBoxOneController, NULL }, // HORIPAD ONE
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x0078 ), k_eControllerType_XBoxOneController, NULL }, // Hori Real Arcade Pro V Kai Xbox One
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x00c5 ), k_eControllerType_XBoxOneController, NULL }, // HORI Fighting Commander
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x0150 ), k_eControllerType_XBoxOneController, NULL }, // HORI Fighting Commander OCTA for Xbox Series X
{ MAKE_CONTROLLER_ID( 0x10f5, 0x7009 ), k_eControllerType_XBoxOneController, NULL }, // Turtle Beach Recon Controller
{ MAKE_CONTROLLER_ID( 0x10f5, 0x7013 ), k_eControllerType_XBoxOneController, NULL }, // Turtle Beach REACT-R
{ MAKE_CONTROLLER_ID( 0x1532, 0x0a00 ), k_eControllerType_XBoxOneController, NULL }, // Razer Atrox Arcade Stick
{ MAKE_CONTROLLER_ID( 0x1532, 0x0a03 ), k_eControllerType_XBoxOneController, NULL }, // Razer Wildcat
{ MAKE_CONTROLLER_ID( 0x1532, 0x0a14 ), k_eControllerType_XBoxOneController, NULL }, // Razer Wolverine Ultimate
{ MAKE_CONTROLLER_ID( 0x1532, 0x0a15 ), k_eControllerType_XBoxOneController, NULL }, // Razer Wolverine Tournament Edition
{ MAKE_CONTROLLER_ID( 0x20d6, 0x2001 ), k_eControllerType_XBoxOneController, "PowerA Xbox Series X Controller" }, // PowerA Xbox Series X EnWired Controller - Black Inline
{ MAKE_CONTROLLER_ID( 0x20d6, 0x2002 ), k_eControllerType_XBoxOneController, "PowerA Xbox Series X Controller" }, // PowerA Xbox Series X EnWired Controller Gray/White Inline
{ MAKE_CONTROLLER_ID( 0x20d6, 0x2003 ), k_eControllerType_XBoxOneController, "PowerA Xbox Series X Controller" }, // PowerA Xbox Series X EnWired Controller Green Inline
{ MAKE_CONTROLLER_ID( 0x20d6, 0x2004 ), k_eControllerType_XBoxOneController, "PowerA Xbox Series X Controller" }, // PowerA Xbox Series X EnWired Controller Pink inline
{ MAKE_CONTROLLER_ID( 0x20d6, 0x2005 ), k_eControllerType_XBoxOneController, "PowerA Xbox Series X Controller" }, // PowerA Xbox Series X Wired Controller Core - Black
{ MAKE_CONTROLLER_ID( 0x20d6, 0x2006 ), k_eControllerType_XBoxOneController, "PowerA Xbox Series X Controller" }, // PowerA Xbox Series X Wired Controller Core - White
{ MAKE_CONTROLLER_ID( 0x20d6, 0x2009 ), k_eControllerType_XBoxOneController, "PowerA Xbox Series X Controller" }, // PowerA Xbox Series X EnWired Controller Red inline
{ MAKE_CONTROLLER_ID( 0x20d6, 0x200a ), k_eControllerType_XBoxOneController, "PowerA Xbox Series X Controller" }, // PowerA Xbox Series X EnWired Controller Blue inline
{ MAKE_CONTROLLER_ID( 0x20d6, 0x200b ), k_eControllerType_XBoxOneController, "PowerA Xbox Series X Controller" }, // PowerA Xbox Series X EnWired Controller Camo Metallic Red
{ MAKE_CONTROLLER_ID( 0x20d6, 0x200c ), k_eControllerType_XBoxOneController, "PowerA Xbox Series X Controller" }, // PowerA Xbox Series X EnWired Controller Camo Metallic Blue
{ MAKE_CONTROLLER_ID( 0x20d6, 0x200d ), k_eControllerType_XBoxOneController, "PowerA Xbox Series X Controller" }, // PowerA Xbox Series X EnWired Controller Seafoam Fade
{ MAKE_CONTROLLER_ID( 0x20d6, 0x200e ), k_eControllerType_XBoxOneController, "PowerA Xbox Series X Controller" }, // PowerA Xbox Series X EnWired Controller Midnight Blue
{ MAKE_CONTROLLER_ID( 0x20d6, 0x200f ), k_eControllerType_XBoxOneController, "PowerA Xbox Series X Controller" }, // PowerA Xbox Series X EnWired Soldier Green
{ MAKE_CONTROLLER_ID( 0x20d6, 0x2011 ), k_eControllerType_XBoxOneController, "PowerA Xbox Series X Controller" }, // PowerA Xbox Series X EnWired - Metallic Ice
{ MAKE_CONTROLLER_ID( 0x20d6, 0x2012 ), k_eControllerType_XBoxOneController, "PowerA Xbox Series X Controller" }, // PowerA Xbox Series X Cuphead EnWired Controller - Mugman
{ MAKE_CONTROLLER_ID( 0x20d6, 0x2015 ), k_eControllerType_XBoxOneController, "PowerA Xbox Series X Controller" }, // PowerA Xbox Series X EnWired Controller - Blue Hint
{ MAKE_CONTROLLER_ID( 0x20d6, 0x2016 ), k_eControllerType_XBoxOneController, "PowerA Xbox Series X Controller" }, // PowerA Xbox Series X EnWired Controller - Green Hint
{ MAKE_CONTROLLER_ID( 0x20d6, 0x2017 ), k_eControllerType_XBoxOneController, "PowerA Xbox Series X Controller" }, // PowerA Xbox Series X EnWired Controller - Arctic Camo
{ MAKE_CONTROLLER_ID( 0x20d6, 0x2018 ), k_eControllerType_XBoxOneController, "PowerA Xbox Series X Controller" }, // PowerA Xbox Series X EnWired Controller Arc Lightning
{ MAKE_CONTROLLER_ID( 0x20d6, 0x2019 ), k_eControllerType_XBoxOneController, "PowerA Xbox Series X Controller" }, // PowerA Xbox Series X EnWired Controller Royal Purple
{ MAKE_CONTROLLER_ID( 0x20d6, 0x201a ), k_eControllerType_XBoxOneController, "PowerA Xbox Series X Controller" }, // PowerA Xbox Series X EnWired Controller Nebula
{ MAKE_CONTROLLER_ID( 0x20d6, 0x4001 ), k_eControllerType_XBoxOneController, "PowerA Fusion Pro 2 Controller" }, // PowerA Fusion Pro 2 Wired Controller (Xbox Series X style)
{ MAKE_CONTROLLER_ID( 0x20d6, 0x4002 ), k_eControllerType_XBoxOneController, "PowerA Spectra Infinity Controller" }, // PowerA Spectra Infinity Wired Controller (Xbox Series X style)
{ MAKE_CONTROLLER_ID( 0x20d6, 0x890b ), k_eControllerType_XBoxOneController, NULL }, // PowerA MOGA XP-Ultra Controller (Xbox Series X style)
{ MAKE_CONTROLLER_ID( 0x24c6, 0x541a ), k_eControllerType_XBoxOneController, NULL }, // PowerA Xbox One Mini Wired Controller
{ MAKE_CONTROLLER_ID( 0x24c6, 0x542a ), k_eControllerType_XBoxOneController, NULL }, // Xbox ONE spectra
{ MAKE_CONTROLLER_ID( 0x24c6, 0x543a ), k_eControllerType_XBoxOneController, "PowerA Xbox One Controller" }, // PowerA Xbox ONE liquid metal controller
{ MAKE_CONTROLLER_ID( 0x24c6, 0x551a ), k_eControllerType_XBoxOneController, NULL }, // PowerA FUSION Pro Controller
{ MAKE_CONTROLLER_ID( 0x24c6, 0x561a ), k_eControllerType_XBoxOneController, NULL }, // PowerA FUSION Controller
{ MAKE_CONTROLLER_ID( 0x24c6, 0x581a ), k_eControllerType_XBoxOneController, NULL }, // BDA XB1 Classic Controller
{ MAKE_CONTROLLER_ID( 0x24c6, 0x591a ), k_eControllerType_XBoxOneController, NULL }, // PowerA FUSION Pro Controller
{ MAKE_CONTROLLER_ID( 0x24c6, 0x592a ), k_eControllerType_XBoxOneController, NULL }, // BDA XB1 Spectra Pro
{ MAKE_CONTROLLER_ID( 0x24c6, 0x791a ), k_eControllerType_XBoxOneController, NULL }, // PowerA Fusion Fight Pad
{ MAKE_CONTROLLER_ID( 0x2dc8, 0x2002 ), k_eControllerType_XBoxOneController, NULL }, // 8BitDo Ultimate Wired Controller for Xbox
{ MAKE_CONTROLLER_ID( 0x2dc8, 0x3106 ), k_eControllerType_XBoxOneController, NULL }, // 8BitDo Ultimate Wired Controller. Windows, Android, Switch.
{ MAKE_CONTROLLER_ID( 0x2dc8, 0x310a ), k_eControllerType_XBoxOneController, NULL }, // 8BitDo Ultimate 2C Wireless Controller
{ MAKE_CONTROLLER_ID( 0x2e24, 0x0652 ), k_eControllerType_XBoxOneController, NULL }, // Hyperkin Duke
{ MAKE_CONTROLLER_ID( 0x2e24, 0x1618 ), k_eControllerType_XBoxOneController, NULL }, // Hyperkin Duke
{ MAKE_CONTROLLER_ID( 0x2e24, 0x1688 ), k_eControllerType_XBoxOneController, NULL }, // Hyperkin X91
{ MAKE_CONTROLLER_ID( 0x146b, 0x0611 ), k_eControllerType_XBoxOneController, NULL }, // Xbox Controller Mode for NACON Revolution 3
// These have been added via Minidump for unrecognized Xinput controller assert
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x1414 ), k_eControllerType_XBox360Controller, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0159 ), k_eControllerType_XBox360Controller, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x24c6, 0xfaff ), k_eControllerType_XBox360Controller, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x006d ), k_eControllerType_XBox360Controller, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x00a4 ), k_eControllerType_XBox360Controller, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x0079, 0x1832 ), k_eControllerType_XBox360Controller, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x0079, 0x187f ), k_eControllerType_XBox360Controller, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x0079, 0x1883 ), k_eControllerType_XBox360Controller, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x03eb, 0xff01 ), k_eControllerType_XBox360Controller, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x0c12, 0x0ef8 ), k_eControllerType_XBox360Controller, NULL }, // Homemade fightstick based on brook pcb (with XInput driver??)
{ MAKE_CONTROLLER_ID( 0x046d, 0x1000 ), k_eControllerType_XBox360Controller, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x11ff, 0x0511 ), k_eControllerType_XBox360Controller, NULL }, // PXN V900
{ MAKE_CONTROLLER_ID( 0x1345, 0x6006 ), k_eControllerType_XBox360Controller, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x056e, 0x2012 ), k_eControllerType_XBox360Controller, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x146b, 0x0602 ), k_eControllerType_XBox360Controller, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x00ae ), k_eControllerType_XBox360Controller, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x046d, 0x0401 ), k_eControllerType_XBox360Controller, NULL }, // logitech xinput
{ MAKE_CONTROLLER_ID( 0x046d, 0x0301 ), k_eControllerType_XBox360Controller, NULL }, // logitech xinput
{ MAKE_CONTROLLER_ID( 0x046d, 0xcaa3 ), k_eControllerType_XBox360Controller, NULL }, // logitech xinput
{ MAKE_CONTROLLER_ID( 0x046d, 0xc261 ), k_eControllerType_XBox360Controller, NULL }, // logitech xinput
{ MAKE_CONTROLLER_ID( 0x046d, 0x0291 ), k_eControllerType_XBox360Controller, NULL }, // logitech xinput
{ MAKE_CONTROLLER_ID( 0x0079, 0x18d3 ), k_eControllerType_XBox360Controller, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x00b1 ), k_eControllerType_XBox360Controller, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x0079, 0x188e ), k_eControllerType_XBox360Controller, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x0079, 0x187c ), k_eControllerType_XBox360Controller, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x0079, 0x189c ), k_eControllerType_XBox360Controller, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x0079, 0x1874 ), k_eControllerType_XBox360Controller, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x2f24, 0x0050 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x2f24, 0x2e ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x2f24, 0x91 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x1430, 0x719 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0xf0d, 0xed ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0xf0d, 0xc0 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0xe6f, 0x152 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x46d, 0x1007 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0xe6f, 0x2b8 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x79, 0x18a1 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
// Added from Minidumps 10-9-19
{ MAKE_CONTROLLER_ID( 0x0, 0x6686 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x12ab, 0x304 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x1430, 0x291 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x1430, 0x2a9 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x1430, 0x70b ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x1bad, 0x28e ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x1bad, 0x2a0 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x1bad, 0x5500 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x20ab, 0x55ef ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x24c6, 0x5509 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x2516, 0x69 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x25b1, 0x360 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x2c22, 0x2203 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x2f24, 0x11 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x2f24, 0x53 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x2f24, 0xb7 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x46d, 0x0 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x46d, 0x1004 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x46d, 0x1008 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x46d, 0xf301 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x738, 0x2a0 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x738, 0x7263 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x738, 0xb738 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x738, 0xcb29 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x738, 0xf401 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x79, 0x18c2 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x79, 0x18c8 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x79, 0x18cf ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0xc12, 0xe17 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0xc12, 0xe1c ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0xc12, 0xe22 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0xc12, 0xe30 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0xd2d2, 0xd2d2 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0xd62, 0x9a1a ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0xd62, 0x9a1b ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0xe00, 0xe00 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0xe6f, 0x12a ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0xe6f, 0x2b2 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0xf0d, 0x97 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0xf0d, 0xba ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0xf0d, 0xd8 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0xfff, 0x2a1 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x45e, 0x867 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
// Added 12-17-2020
{ MAKE_CONTROLLER_ID( 0x16d0, 0xf3f ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x2f24, 0x8f ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0xe6f, 0xf501 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
{ MAKE_CONTROLLER_ID( 0x057e, 0x2006 ), k_eControllerType_SwitchJoyConLeft, NULL }, // Nintendo Switch Joy-Con (Left)
{ MAKE_CONTROLLER_ID( 0x057e, 0x2067 ), k_eControllerType_SwitchJoyConLeft, NULL }, // Nintendo Switch 2 Joy-Con (Left)
{ MAKE_CONTROLLER_ID( 0x057e, 0x2007 ), k_eControllerType_SwitchJoyConRight, NULL }, // Nintendo Switch Joy-Con (Right)
{ MAKE_CONTROLLER_ID( 0x057e, 0x2066 ), k_eControllerType_SwitchJoyConRight, NULL }, // Nintendo Switch 2 Joy-Con (Right)
{ MAKE_CONTROLLER_ID( 0x057e, 0x2008 ), k_eControllerType_SwitchJoyConPair, NULL }, // Nintendo Switch Joy-Con (Left+Right Combined)
{ MAKE_CONTROLLER_ID( 0x057e, 0x2068 ), k_eControllerType_SwitchJoyConPair, NULL }, // Nintendo Switch 2 Joy-Con (Left+Right Combined)
// This same controller ID is spoofed by many 3rd-party Switch controllers.
// The ones we currently know of are:
// * Any 8bitdo controller with Switch support
// * ORTZ Gaming Wireless Pro Controller
// * ZhiXu Gamepad Wireless
// * Sunwaytek Wireless Motion Controller for Nintendo Switch
{ MAKE_CONTROLLER_ID( 0x057e, 0x2009 ), k_eControllerType_SwitchProController, NULL }, // Nintendo Switch Pro Controller
{ MAKE_CONTROLLER_ID( 0x057e, 0x2069 ), k_eControllerType_Switch2ProController, NULL }, // Nintendo Switch 2 Pro Controller
//{ MAKE_CONTROLLER_ID( 0x057e, 0x2017 ), k_eControllerType_SwitchProController, NULL }, // Nintendo Online SNES Controller
//{ MAKE_CONTROLLER_ID( 0x057e, 0x2019 ), k_eControllerType_SwitchProController, NULL }, // Nintendo Online N64 Controller
//{ MAKE_CONTROLLER_ID( 0x057e, 0x201e ), k_eControllerType_SwitchProController, NULL }, // Nintendo Online SEGA Genesis Controller
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x00c1 ), k_eControllerType_SwitchInputOnlyController, NULL }, // HORIPAD for Nintendo Switch
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x0092 ), k_eControllerType_SwitchInputOnlyController, NULL }, // HORI Pokken Tournament DX Pro Pad
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x00f6 ), k_eControllerType_SwitchProController, NULL }, // HORI Wireless Switch Pad
// The HORIPAD S, which comes in multiple styles:
// - NSW-108, classic GameCube controller
// - NSW-244, Fighting Commander arcade pad
// - NSW-278, Hori Pad Mini gamepad
// - NSW-326, HORIPAD FPS for Nintendo Switch
//
// The first two, at least, shouldn't have their buttons remapped, and since we
// can't tell which model we're actually using, we won't do any button remapping
// for any of them.
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x00dc ), k_eControllerType_XInputSwitchController, NULL }, // HORIPAD S - Looks like a Switch controller but uses the Xbox 360 controller protocol, there is also a version of this that looks like a GameCube controller
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0180 ), k_eControllerType_SwitchInputOnlyController, NULL }, // PDP Faceoff Wired Pro Controller for Nintendo Switch
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0181 ), k_eControllerType_SwitchInputOnlyController, NULL }, // PDP Faceoff Deluxe Wired Pro Controller for Nintendo Switch
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0184 ), k_eControllerType_SwitchInputOnlyController, NULL }, // PDP Faceoff Wired Deluxe+ Audio Controller
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0185 ), k_eControllerType_SwitchInputOnlyController, NULL }, // PDP Wired Fight Pad Pro for Nintendo Switch
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0186 ), k_eControllerType_SwitchProController, NULL }, // PDP Afterglow Wireless Switch Controller - working gyro. USB is for charging only. Many later "Wireless" line devices w/ gyro also use this vid/pid
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0187 ), k_eControllerType_SwitchInputOnlyController, NULL }, // PDP Rockcandy Wired Controller
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0188 ), k_eControllerType_SwitchInputOnlyController, NULL }, // PDP Afterglow Wired Deluxe+ Audio Controller
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x018b ), k_eControllerType_SwitchInputOnlyController, NULL }, // PDP Afterglow Wave Wired/Wireless Controller for Switch
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x018c ), k_eControllerType_SwitchProController, "PDP REALMz Wireless Controller" }, // PDP REALMz Wireless Controller for Switch
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0193 ), k_eControllerType_Switch2ProController, NULL }, // Turtle Beach Afterglow Wireless RGB Gaming Controller for Nintendo Switch 2 and the Turtle Beach Rematch Wireless RGB Gaming Controller for Nintendo Switch 2
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0196 ), k_eControllerType_Switch2InputOnlyController, NULL }, // Turtle Beach Rematch Wired Controller for Nintendo Switch 2
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0197 ), k_eControllerType_Switch2InputOnlyController, NULL }, // Turtle Beach Afterglow Wave Wired Controller for Nintendo Switch 2
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0198 ), k_eControllerType_Switch2InputOnlyController, NULL }, // Turtle Beach Afterglow Wired Controller for Switch 2
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x00aa ), k_eControllerType_SwitchInputOnlyController, NULL }, // HORI Real Arcade Pro V Hayabusa in Switch Mode
{ MAKE_CONTROLLER_ID( 0x20d6, 0xa711 ), k_eControllerType_SwitchInputOnlyController, NULL }, // PowerA Wired Controller Plus/PowerA Wired Controller Nintendo GameCube Style
{ MAKE_CONTROLLER_ID( 0x20d6, 0xa712 ), k_eControllerType_SwitchInputOnlyController, NULL }, // PowerA Nintendo Switch Fusion Fight Pad
{ MAKE_CONTROLLER_ID( 0x20d6, 0xa713 ), k_eControllerType_SwitchInputOnlyController, NULL }, // PowerA Super Mario Controller
{ MAKE_CONTROLLER_ID( 0x20d6, 0xa714 ), k_eControllerType_SwitchInputOnlyController, NULL }, // PowerA Nintendo Switch Spectra Controller
{ MAKE_CONTROLLER_ID( 0x20d6, 0xa715 ), k_eControllerType_SwitchInputOnlyController, NULL }, // Power A Fusion Wireless Arcade Stick (USB Mode) Over BT is shows up as 057e 2009
{ MAKE_CONTROLLER_ID( 0x20d6, 0xa716 ), k_eControllerType_SwitchInputOnlyController, NULL }, // PowerA Nintendo Switch Fusion Pro Controller - USB requires toggling switch on back of device
{ MAKE_CONTROLLER_ID( 0x20d6, 0xa718 ), k_eControllerType_SwitchInputOnlyController, NULL }, // PowerA Nintendo Switch Nano Wired Controller
{ MAKE_CONTROLLER_ID( 0x33dd, 0x0001 ), k_eControllerType_SwitchInputOnlyController, NULL }, // ZUIKI MasCon for Nintendo Switch Black
{ MAKE_CONTROLLER_ID( 0x33dd, 0x0002 ), k_eControllerType_SwitchInputOnlyController, NULL }, // ZUIKI MasCon for Nintendo Switch ??
{ MAKE_CONTROLLER_ID( 0x33dd, 0x0003 ), k_eControllerType_SwitchInputOnlyController, NULL }, // ZUIKI MasCon for Nintendo Switch Red
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x00f0 ), k_eControllerType_SwitchInputOnlyController, NULL }, // HORI Taiko Controller For Switch
{ MAKE_CONTROLLER_ID( 0x054c, 0x0df2 ), k_eControllerType_PS5EdgeController, NULL }, // Sony DualSense Edge Controller
{ MAKE_CONTROLLER_ID( 0x045e, 0x02e3 ), k_eControllerType_XBoxEliteController, "Xbox One Elite Controller" }, // Microsoft Xbox One Elite Controller
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b00 ), k_eControllerType_XBoxEliteController, "Xbox One Elite 2 Controller" }, // Microsoft Xbox One Elite Series 2 Controller
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b05 ), k_eControllerType_XBoxEliteController, "Xbox One Elite 2 Controller" }, // Microsoft Xbox One Elite Series 2 Controller (Bluetooth)
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b22 ), k_eControllerType_XBoxEliteController, "Xbox One Elite 2 Controller" }, // Microsoft Xbox One Elite Series 2 Controller (BLE)
{ MAKE_CONTROLLER_ID( 0x2dc8, 0x6000 ), k_eControllerType_8BitDoController, "8Bitdo SF30 Controller" }, // 8BitDo SF30 Pro Controller in Steam Mode
{ MAKE_CONTROLLER_ID( 0x2dc8, 0x6100 ), k_eControllerType_8BitDoController, "8Bitdo SF30 Controller" }, // 8BitDo SF30 Pro Controller in Steam Mode (Bluetooth)
{ MAKE_CONTROLLER_ID( 0x2dc8, 0x6001 ), k_eControllerType_8BitDoController, "8Bitdo SN30 Controller" }, // 8BitDo SN30 Pro Controller in Steam Mode
{ MAKE_CONTROLLER_ID( 0x2dc8, 0x6101 ), k_eControllerType_8BitDoController, "8Bitdo SN30 Controller" }, // 8BitDo SN30 Pro Controller in Steam Mode (Bluetooth)
{ MAKE_CONTROLLER_ID( 0x2dc8, 0x6003 ), k_eControllerType_8BitDoController, "8Bitdo Pro 2 Controller" }, // 8BitDo Pro 2 Controller in Steam Mode
{ MAKE_CONTROLLER_ID( 0x2dc8, 0x6006 ), k_eControllerType_8BitDoController, "8Bitdo Pro 2 Controller" }, // 8BitDo Pro 2 Controller in Steam Mode
{ MAKE_CONTROLLER_ID( 0x2dc8, 0x6009 ), k_eControllerType_8BitDoController, "8Bitdo Pro 3 Controller" }, // 8BitDo Pro 3 Controller in Steam Mode (Bluetooth)
{ MAKE_CONTROLLER_ID( 0x2dc8, 0x6012 ), k_eControllerType_8BitDoController, "8Bitdo Ultimate 2 Wireless Controller" }, // 8BitDo Ultimate 2 Wireless Controller in Steam Mode (Bluetooth)
// Valve products
{ MAKE_CONTROLLER_ID( 0x0000, 0x11fb ), k_eControllerType_MobileTouch, NULL }, // Streaming mobile touch virtual controls
{ MAKE_CONTROLLER_ID( 0x28de, 0x1101 ), k_eControllerType_SteamController, NULL }, // Valve Legacy Steam Controller (CHELL)
{ MAKE_CONTROLLER_ID( 0x28de, 0x1102 ), k_eControllerType_SteamController, NULL }, // Valve wired Steam Controller (D0G)
{ MAKE_CONTROLLER_ID( 0x28de, 0x1105 ), k_eControllerType_SteamController, NULL }, // Valve Bluetooth Steam Controller (D0G)
{ MAKE_CONTROLLER_ID( 0x28de, 0x1106 ), k_eControllerType_SteamController, NULL }, // Valve Bluetooth Steam Controller (D0G)
{ MAKE_CONTROLLER_ID( 0x28de, 0x11ff ), k_eControllerType_UnknownNonSteamController, NULL }, // Steam Virtual Gamepad
{ MAKE_CONTROLLER_ID( 0x28de, 0x1142 ), k_eControllerType_SteamController, NULL }, // Valve wireless Steam Controller
{ MAKE_CONTROLLER_ID( 0x28de, 0x1201 ), k_eControllerType_SteamControllerV2, NULL }, // Valve wired Steam Controller (HEADCRAB)
{ MAKE_CONTROLLER_ID( 0x28de, 0x1202 ), k_eControllerType_SteamControllerV2, NULL }, // Valve Bluetooth Steam Controller (HEADCRAB)
{ MAKE_CONTROLLER_ID( 0x28de, 0x1205 ), k_eControllerType_SteamControllerNeptune, NULL }, // Valve Steam Deck Builtin Controller
{ MAKE_CONTROLLER_ID( 0x28de, 0x1302 ), k_eControllerType_SteamControllerTriton, NULL }, // Valve Steam Triton Controller
{ MAKE_CONTROLLER_ID( 0x28de, 0x1303 ), k_eControllerType_SteamControllerTriton, NULL }, // Valve Steam Triton Controller (BLE)
{ MAKE_CONTROLLER_ID( 0x28de, 0x1304 ), k_eControllerType_SteamControllerTriton, NULL }, // Valve Steam Proteus Dongle (Proprietary)
{ MAKE_CONTROLLER_ID( 0x28de, 0x1305 ), k_eControllerType_SteamControllerTriton, NULL }, // Valve Steam Nereid Dongle (Proprietary)
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x01AB ), k_eControllerType_HoriSteamController, NULL }, // HORI Wireless HORIPAD for Steam
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x0196 ), k_eControllerType_HoriSteamController, NULL }, // HORI Wireless HORIPAD for Steam ( BT )
};
@@ -0,0 +1,86 @@
/*
Copyright (C) Valve Corporation
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef CONTROLLER_TYPE_H
#define CONTROLLER_TYPE_H
#ifdef _WIN32
#pragma once
#endif
//-----------------------------------------------------------------------------
// Purpose: Steam Controller models
// WARNING: DO NOT RENUMBER EXISTING VALUES - STORED IN A DATABASE
//-----------------------------------------------------------------------------
typedef enum
{
k_eControllerType_None = -1,
k_eControllerType_Unknown = 0,
// Steam Controllers
k_eControllerType_UnknownSteamController = 1,
k_eControllerType_SteamController = 2,
k_eControllerType_SteamControllerV2 = 3,
k_eControllerType_SteamControllerNeptune = 4,
k_eControllerType_SteamControllerTriton = 10,
// Other Controllers
k_eControllerType_UnknownNonSteamController = 30,
k_eControllerType_XBox360Controller = 31,
k_eControllerType_XBoxOneController = 32,
k_eControllerType_PS3Controller = 33,
k_eControllerType_PS4Controller = 34,
k_eControllerType_WiiController = 35,
k_eControllerType_AppleController = 36,
k_eControllerType_AndroidController = 37,
k_eControllerType_SwitchProController = 38,
k_eControllerType_SwitchJoyConLeft = 39,
k_eControllerType_SwitchJoyConRight = 40,
k_eControllerType_SwitchJoyConPair = 41,
k_eControllerType_SwitchInputOnlyController = 42,
k_eControllerType_MobileTouch = 43,
k_eControllerType_XInputSwitchController = 44, // Client-side only, used to mark Nintendo Switch style controllers as using XInput instead of the Nintendo Switch protocol
k_eControllerType_PS5Controller = 45,
k_eControllerType_XBoxEliteController = 46,
k_eControllerType_XInputPS4Controller = 47, // Client-side only, used to mark DualShock 4 style controllers using XInput instead of the DualShock 4 controller protocol
k_eControllerType_PS5EdgeController = 48,
k_eControllerType_HoriSteamController = 49,
k_eControllerType_8BitDoController = 50,
k_eControllerType_Switch2ProController = 51,
k_eControllerType_Switch2InputOnlyController = 52,
k_eControllerType_LastController, // Don't add game controllers below this enumeration - this enumeration can change value
// Keyboards and Mice
k_eControllertype_GenericKeyboard = 400,
k_eControllertype_GenericMouse = 800,
} EControllerType;
typedef struct
{
unsigned int m_unDeviceID;
EControllerType m_eControllerType;
const char *m_pszName;
} ControllerDescription_t;
extern EControllerType GuessControllerType( int nVID, int nPID );
extern const char *GuessControllerName( int nVID, int nPID );
#endif // CONTROLLER_TYPE_H
@@ -1,100 +0,0 @@
ANDROID_API_TARGET=21
PARALLEL_JOBS=$(nproc)
rm -r ./android
mkdir android
function build_one
{
PREFIX=$(pwd)/android/$CPU
SYSROOT=$NDK/platforms/android-$ANDROID_API_TARGET/arch-$SYSROOT_CPU
TOOLCHAIN_PATH=$NDK/toolchains/$TOOLCHAIN_DIR/prebuilt/linux-x86_64
export PATH=$PATH:$TOOLCHAIN_PATH/bin
./configure \
--build=x86_64-unknown-linux-gnu \
--host=$TOOLCHAIN_BIN_PREFIX \
--target=$TOOLCHAIN_BIN_PREFIX \
CFLAGS="--sysroot=$SYSROOT -O2 $ADDI_CFLAGS" \
$ADDI_CONFIGURE_FLAGS
make clean
make -j$PARALLEL_JOBS
mkdir android/$CPU
cp .libs/libopus.a android/$CPU
}
function build_mips
{
CPU=mips
SYSROOT_CPU=mips
TOOLCHAIN_BIN_PREFIX=mipsel-linux-android
TOOLCHAIN_DIR=mipsel-linux-android-4.9
ADDI_CFLAGS="-mips32 -mhard-float -EL -mno-dsp"
ADDI_CONFIGURE_FLAGS="--enable-fixed-point" # fixed point
build_one
}
function build_mips64
{
CPU=mips64
SYSROOT_CPU=mips64
TOOLCHAIN_BIN_PREFIX=mips64el-linux-android
TOOLCHAIN_DIR=mips64el-linux-android-4.9
ADDI_CFLAGS="-mips64r6"
ADDI_CONFIGURE_FLAGS="--enable-fixed-point" # fixed point
build_one
}
function build_x86
{
CPU=x86
SYSROOT_CPU=x86
TOOLCHAIN_BIN_PREFIX=i686-linux-android
TOOLCHAIN_DIR=x86-4.9
ADDI_CFLAGS="-march=i686 -mtune=atom -mstackrealign -msse -msse2 -msse3 -mssse3 -mfpmath=sse -m32"
ADDI_CONFIGURE_FLAGS="" # floating point for SSE optimizations
build_one
}
function build_x86_64
{
CPU=x86_64
SYSROOT_CPU=x86_64
TOOLCHAIN_BIN_PREFIX=x86_64-linux-android
TOOLCHAIN_DIR=x86_64-4.9
ADDI_CFLAGS="-msse -msse2 -msse3 -mssse3 -msse4 -msse4.1 -msse4.2 -mpopcnt -m64"
ADDI_CONFIGURE_FLAGS="" # floating point for SSE optimizations
build_one
}
function build_armv7
{
CPU=arm
SYSROOT_CPU=arm
TOOLCHAIN_BIN_PREFIX=arm-linux-androideabi
TOOLCHAIN_DIR=arm-linux-androideabi-4.9
ADDI_CFLAGS="-marm -mfpu=vfpv3-d16"
ADDI_LDFLAGS=""
ADDI_CONFIGURE_FLAGS="--enable-fixed-point" # fixed point for NEON, EDSP, Media
build_one
}
# ARMv8 doesn't currently have assembly in the opus project. We still use fixed point
# anyway in the hopes that it will be more performant even without assembly.
function build_armv8
{
CPU=aarch64
SYSROOT_CPU=arm64
TOOLCHAIN_BIN_PREFIX=aarch64-linux-android
TOOLCHAIN_DIR=aarch64-linux-android-4.9
ADDI_CFLAGS=""
ADDI_LDFLAGS=""
ADDI_CONFIGURE_FLAGS="--enable-fixed-point"
build_one
}
build_mips
build_mips64
build_x86
build_x86_64
build_armv7
build_armv8
@@ -1,342 +0,0 @@
/* Copyright (c) 2007-2008 CSIRO
Copyright (c) 2007-2009 Xiph.Org Foundation
Copyright (c) 2008-2012 Gregory Maxwell
Written by Jean-Marc Valin and Gregory Maxwell */
/*
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
@file opus_custom.h
@brief Opus-Custom reference implementation API
*/
#ifndef OPUS_CUSTOM_H
#define OPUS_CUSTOM_H
#include "opus_defines.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef CUSTOM_MODES
# define OPUS_CUSTOM_EXPORT OPUS_EXPORT
# define OPUS_CUSTOM_EXPORT_STATIC OPUS_EXPORT
#else
# define OPUS_CUSTOM_EXPORT
# ifdef OPUS_BUILD
# define OPUS_CUSTOM_EXPORT_STATIC static OPUS_INLINE
# else
# define OPUS_CUSTOM_EXPORT_STATIC
# endif
#endif
/** @defgroup opus_custom Opus Custom
* @{
* Opus Custom is an optional part of the Opus specification and
* reference implementation which uses a distinct API from the regular
* API and supports frame sizes that are not normally supported.\ Use
* of Opus Custom is discouraged for all but very special applications
* for which a frame size different from 2.5, 5, 10, or 20 ms is needed
* (for either complexity or latency reasons) and where interoperability
* is less important.
*
* In addition to the interoperability limitations the use of Opus custom
* disables a substantial chunk of the codec and generally lowers the
* quality available at a given bitrate. Normally when an application needs
* a different frame size from the codec it should buffer to match the
* sizes but this adds a small amount of delay which may be important
* in some very low latency applications. Some transports (especially
* constant rate RF transports) may also work best with frames of
* particular durations.
*
* Libopus only supports custom modes if they are enabled at compile time.
*
* The Opus Custom API is similar to the regular API but the
* @ref opus_encoder_create and @ref opus_decoder_create calls take
* an additional mode parameter which is a structure produced by
* a call to @ref opus_custom_mode_create. Both the encoder and decoder
* must create a mode using the same sample rate (fs) and frame size
* (frame size) so these parameters must either be signaled out of band
* or fixed in a particular implementation.
*
* Similar to regular Opus the custom modes support on the fly frame size
* switching, but the sizes available depend on the particular frame size in
* use. For some initial frame sizes on a single on the fly size is available.
*/
/** Contains the state of an encoder. One encoder state is needed
for each stream. It is initialized once at the beginning of the
stream. Do *not* re-initialize the state for every frame.
@brief Encoder state
*/
typedef struct OpusCustomEncoder OpusCustomEncoder;
/** State of the decoder. One decoder state is needed for each stream.
It is initialized once at the beginning of the stream. Do *not*
re-initialize the state for every frame.
@brief Decoder state
*/
typedef struct OpusCustomDecoder OpusCustomDecoder;
/** The mode contains all the information necessary to create an
encoder. Both the encoder and decoder need to be initialized
with exactly the same mode, otherwise the output will be
corrupted.
@brief Mode configuration
*/
typedef struct OpusCustomMode OpusCustomMode;
/** Creates a new mode struct. This will be passed to an encoder or
* decoder. The mode MUST NOT BE DESTROYED until the encoders and
* decoders that use it are destroyed as well.
* @param [in] Fs <tt>int</tt>: Sampling rate (8000 to 96000 Hz)
* @param [in] frame_size <tt>int</tt>: Number of samples (per channel) to encode in each
* packet (64 - 1024, prime factorization must contain zero or more 2s, 3s, or 5s and no other primes)
* @param [out] error <tt>int*</tt>: Returned error code (if NULL, no error will be returned)
* @return A newly created mode
*/
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT OpusCustomMode *opus_custom_mode_create(opus_int32 Fs, int frame_size, int *error);
/** Destroys a mode struct. Only call this after all encoders and
* decoders using this mode are destroyed as well.
* @param [in] mode <tt>OpusCustomMode*</tt>: Mode to be freed.
*/
OPUS_CUSTOM_EXPORT void opus_custom_mode_destroy(OpusCustomMode *mode);
#if !defined(OPUS_BUILD) || defined(CELT_ENCODER_C)
/* Encoder */
/** Gets the size of an OpusCustomEncoder structure.
* @param [in] mode <tt>OpusCustomMode *</tt>: Mode configuration
* @param [in] channels <tt>int</tt>: Number of channels
* @returns size
*/
OPUS_CUSTOM_EXPORT_STATIC OPUS_WARN_UNUSED_RESULT int opus_custom_encoder_get_size(
const OpusCustomMode *mode,
int channels
) OPUS_ARG_NONNULL(1);
# ifdef CUSTOM_MODES
/** Initializes a previously allocated encoder state
* The memory pointed to by st must be the size returned by opus_custom_encoder_get_size.
* This is intended for applications which use their own allocator instead of malloc.
* @see opus_custom_encoder_create(),opus_custom_encoder_get_size()
* To reset a previously initialized state use the OPUS_RESET_STATE CTL.
* @param [in] st <tt>OpusCustomEncoder*</tt>: Encoder state
* @param [in] mode <tt>OpusCustomMode *</tt>: Contains all the information about the characteristics of
* the stream (must be the same characteristics as used for the
* decoder)
* @param [in] channels <tt>int</tt>: Number of channels
* @return OPUS_OK Success or @ref opus_errorcodes
*/
OPUS_CUSTOM_EXPORT int opus_custom_encoder_init(
OpusCustomEncoder *st,
const OpusCustomMode *mode,
int channels
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2);
# endif
#endif
/** Creates a new encoder state. Each stream needs its own encoder
* state (can't be shared across simultaneous streams).
* @param [in] mode <tt>OpusCustomMode*</tt>: Contains all the information about the characteristics of
* the stream (must be the same characteristics as used for the
* decoder)
* @param [in] channels <tt>int</tt>: Number of channels
* @param [out] error <tt>int*</tt>: Returns an error code
* @return Newly created encoder state.
*/
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT OpusCustomEncoder *opus_custom_encoder_create(
const OpusCustomMode *mode,
int channels,
int *error
) OPUS_ARG_NONNULL(1);
/** Destroys a an encoder state.
* @param[in] st <tt>OpusCustomEncoder*</tt>: State to be freed.
*/
OPUS_CUSTOM_EXPORT void opus_custom_encoder_destroy(OpusCustomEncoder *st);
/** Encodes a frame of audio.
* @param [in] st <tt>OpusCustomEncoder*</tt>: Encoder state
* @param [in] pcm <tt>float*</tt>: PCM audio in float format, with a normal range of +/-1.0.
* Samples with a range beyond +/-1.0 are supported but will
* be clipped by decoders using the integer API and should
* only be used if it is known that the far end supports
* extended dynamic range. There must be exactly
* frame_size samples per channel.
* @param [in] frame_size <tt>int</tt>: Number of samples per frame of input signal
* @param [out] compressed <tt>char *</tt>: The compressed data is written here. This may not alias pcm and must be at least maxCompressedBytes long.
* @param [in] maxCompressedBytes <tt>int</tt>: Maximum number of bytes to use for compressing the frame
* (can change from one frame to another)
* @return Number of bytes written to "compressed".
* If negative, an error has occurred (see error codes). It is IMPORTANT that
* the length returned be somehow transmitted to the decoder. Otherwise, no
* decoding is possible.
*/
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_encode_float(
OpusCustomEncoder *st,
const float *pcm,
int frame_size,
unsigned char *compressed,
int maxCompressedBytes
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
/** Encodes a frame of audio.
* @param [in] st <tt>OpusCustomEncoder*</tt>: Encoder state
* @param [in] pcm <tt>opus_int16*</tt>: PCM audio in signed 16-bit format (native endian).
* There must be exactly frame_size samples per channel.
* @param [in] frame_size <tt>int</tt>: Number of samples per frame of input signal
* @param [out] compressed <tt>char *</tt>: The compressed data is written here. This may not alias pcm and must be at least maxCompressedBytes long.
* @param [in] maxCompressedBytes <tt>int</tt>: Maximum number of bytes to use for compressing the frame
* (can change from one frame to another)
* @return Number of bytes written to "compressed".
* If negative, an error has occurred (see error codes). It is IMPORTANT that
* the length returned be somehow transmitted to the decoder. Otherwise, no
* decoding is possible.
*/
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_encode(
OpusCustomEncoder *st,
const opus_int16 *pcm,
int frame_size,
unsigned char *compressed,
int maxCompressedBytes
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
/** Perform a CTL function on an Opus custom encoder.
*
* Generally the request and subsequent arguments are generated
* by a convenience macro.
* @see opus_encoderctls
*/
OPUS_CUSTOM_EXPORT int opus_custom_encoder_ctl(OpusCustomEncoder * OPUS_RESTRICT st, int request, ...) OPUS_ARG_NONNULL(1);
#if !defined(OPUS_BUILD) || defined(CELT_DECODER_C)
/* Decoder */
/** Gets the size of an OpusCustomDecoder structure.
* @param [in] mode <tt>OpusCustomMode *</tt>: Mode configuration
* @param [in] channels <tt>int</tt>: Number of channels
* @returns size
*/
OPUS_CUSTOM_EXPORT_STATIC OPUS_WARN_UNUSED_RESULT int opus_custom_decoder_get_size(
const OpusCustomMode *mode,
int channels
) OPUS_ARG_NONNULL(1);
/** Initializes a previously allocated decoder state
* The memory pointed to by st must be the size returned by opus_custom_decoder_get_size.
* This is intended for applications which use their own allocator instead of malloc.
* @see opus_custom_decoder_create(),opus_custom_decoder_get_size()
* To reset a previously initialized state use the OPUS_RESET_STATE CTL.
* @param [in] st <tt>OpusCustomDecoder*</tt>: Decoder state
* @param [in] mode <tt>OpusCustomMode *</tt>: Contains all the information about the characteristics of
* the stream (must be the same characteristics as used for the
* encoder)
* @param [in] channels <tt>int</tt>: Number of channels
* @return OPUS_OK Success or @ref opus_errorcodes
*/
OPUS_CUSTOM_EXPORT_STATIC int opus_custom_decoder_init(
OpusCustomDecoder *st,
const OpusCustomMode *mode,
int channels
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2);
#endif
/** Creates a new decoder state. Each stream needs its own decoder state (can't
* be shared across simultaneous streams).
* @param [in] mode <tt>OpusCustomMode</tt>: Contains all the information about the characteristics of the
* stream (must be the same characteristics as used for the encoder)
* @param [in] channels <tt>int</tt>: Number of channels
* @param [out] error <tt>int*</tt>: Returns an error code
* @return Newly created decoder state.
*/
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT OpusCustomDecoder *opus_custom_decoder_create(
const OpusCustomMode *mode,
int channels,
int *error
) OPUS_ARG_NONNULL(1);
/** Destroys a an decoder state.
* @param[in] st <tt>OpusCustomDecoder*</tt>: State to be freed.
*/
OPUS_CUSTOM_EXPORT void opus_custom_decoder_destroy(OpusCustomDecoder *st);
/** Decode an opus custom frame with floating point output
* @param [in] st <tt>OpusCustomDecoder*</tt>: Decoder state
* @param [in] data <tt>char*</tt>: Input payload. Use a NULL pointer to indicate packet loss
* @param [in] len <tt>int</tt>: Number of bytes in payload
* @param [out] pcm <tt>float*</tt>: Output signal (interleaved if 2 channels). length
* is frame_size*channels*sizeof(float)
* @param [in] frame_size Number of samples per channel of available space in *pcm.
* @returns Number of decoded samples or @ref opus_errorcodes
*/
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_decode_float(
OpusCustomDecoder *st,
const unsigned char *data,
int len,
float *pcm,
int frame_size
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
/** Decode an opus custom frame
* @param [in] st <tt>OpusCustomDecoder*</tt>: Decoder state
* @param [in] data <tt>char*</tt>: Input payload. Use a NULL pointer to indicate packet loss
* @param [in] len <tt>int</tt>: Number of bytes in payload
* @param [out] pcm <tt>opus_int16*</tt>: Output signal (interleaved if 2 channels). length
* is frame_size*channels*sizeof(opus_int16)
* @param [in] frame_size Number of samples per channel of available space in *pcm.
* @returns Number of decoded samples or @ref opus_errorcodes
*/
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_decode(
OpusCustomDecoder *st,
const unsigned char *data,
int len,
opus_int16 *pcm,
int frame_size
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
/** Perform a CTL function on an Opus custom decoder.
*
* Generally the request and subsequent arguments are generated
* by a convenience macro.
* @see opus_genericctls
*/
OPUS_CUSTOM_EXPORT int opus_custom_decoder_ctl(OpusCustomDecoder * OPUS_RESTRICT st, int request, ...) OPUS_ARG_NONNULL(1);
/**@}*/
#ifdef __cplusplus
}
#endif
#endif /* OPUS_CUSTOM_H */
+243
View File
@@ -0,0 +1,243 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2026 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
// This file includes a few functions standalone from SDL_joystick.c useful for joystick typing
#include "minisdl.h"
#include "controller_type.h"
#include "controller_list.h"
#include "usb_ids.h"
// Macro to combine a USB vendor ID and product ID into a single Uint32 value
#define MAKE_VIDPID(VID, PID) (((Uint32)(VID)) << 16 | (PID))
static Uint32 initial_old_xboxone_controllers[] = {
MAKE_VIDPID(0x0000, 0x6686),
MAKE_VIDPID(0x0079, 0x18a1),
MAKE_VIDPID(0x0079, 0x18c2),
MAKE_VIDPID(0x0079, 0x18c8),
MAKE_VIDPID(0x0079, 0x18cf),
MAKE_VIDPID(0x03f0, 0x0495),
MAKE_VIDPID(0x045e, 0x02d1),
MAKE_VIDPID(0x045e, 0x02dd),
MAKE_VIDPID(0x045e, 0x02e0),
MAKE_VIDPID(0x045e, 0x02e3),
MAKE_VIDPID(0x045e, 0x02ea),
MAKE_VIDPID(0x045e, 0x02fd),
MAKE_VIDPID(0x045e, 0x02ff),
MAKE_VIDPID(0x045e, 0x0867),
MAKE_VIDPID(0x045e, 0x0b00),
MAKE_VIDPID(0x045e, 0x0b05),
MAKE_VIDPID(0x045e, 0x0b0a),
MAKE_VIDPID(0x045e, 0x0b0c),
MAKE_VIDPID(0x045e, 0x0b20),
MAKE_VIDPID(0x045e, 0x0b21),
MAKE_VIDPID(0x045e, 0x0b22),
MAKE_VIDPID(0x046d, 0x0000),
MAKE_VIDPID(0x046d, 0x1004),
MAKE_VIDPID(0x046d, 0x1007),
MAKE_VIDPID(0x046d, 0x1008),
MAKE_VIDPID(0x046d, 0xf301),
MAKE_VIDPID(0x0738, 0x02a0),
MAKE_VIDPID(0x0738, 0x4a01),
MAKE_VIDPID(0x0738, 0x7263),
MAKE_VIDPID(0x0738, 0xb738),
MAKE_VIDPID(0x0738, 0xcb29),
MAKE_VIDPID(0x0738, 0xf401),
MAKE_VIDPID(0x0c12, 0x0e17),
MAKE_VIDPID(0x0c12, 0x0e1c),
MAKE_VIDPID(0x0c12, 0x0e22),
MAKE_VIDPID(0x0c12, 0x0e30),
MAKE_VIDPID(0x0d62, 0x9a1a),
MAKE_VIDPID(0x0d62, 0x9a1b),
MAKE_VIDPID(0x0e00, 0x0e00),
MAKE_VIDPID(0x0e6f, 0x012a),
MAKE_VIDPID(0x0e6f, 0x0139),
MAKE_VIDPID(0x0e6f, 0x013B),
MAKE_VIDPID(0x0e6f, 0x013a),
MAKE_VIDPID(0x0e6f, 0x0145),
MAKE_VIDPID(0x0e6f, 0x0146),
MAKE_VIDPID(0x0e6f, 0x0152),
MAKE_VIDPID(0x0e6f, 0x015b),
MAKE_VIDPID(0x0e6f, 0x015c),
MAKE_VIDPID(0x0e6f, 0x015d),
MAKE_VIDPID(0x0e6f, 0x015f),
MAKE_VIDPID(0x0e6f, 0x0160),
MAKE_VIDPID(0x0e6f, 0x0161),
MAKE_VIDPID(0x0e6f, 0x0162),
MAKE_VIDPID(0x0e6f, 0x0163),
MAKE_VIDPID(0x0e6f, 0x0164),
MAKE_VIDPID(0x0e6f, 0x0165),
MAKE_VIDPID(0x0e6f, 0x0166),
MAKE_VIDPID(0x0e6f, 0x0167),
MAKE_VIDPID(0x0e6f, 0x0205),
MAKE_VIDPID(0x0e6f, 0x0206),
MAKE_VIDPID(0x0e6f, 0x0246),
MAKE_VIDPID(0x0e6f, 0x0261),
MAKE_VIDPID(0x0e6f, 0x0262),
MAKE_VIDPID(0x0e6f, 0x02a0),
MAKE_VIDPID(0x0e6f, 0x02a1),
MAKE_VIDPID(0x0e6f, 0x02a2),
MAKE_VIDPID(0x0e6f, 0x02a3),
MAKE_VIDPID(0x0e6f, 0x02a4),
MAKE_VIDPID(0x0e6f, 0x02a5),
MAKE_VIDPID(0x0e6f, 0x02a6),
MAKE_VIDPID(0x0e6f, 0x02a7),
MAKE_VIDPID(0x0e6f, 0x02a8),
MAKE_VIDPID(0x0e6f, 0x02a9),
MAKE_VIDPID(0x0e6f, 0x02aa),
MAKE_VIDPID(0x0e6f, 0x02ab),
MAKE_VIDPID(0x0e6f, 0x02ac),
MAKE_VIDPID(0x0e6f, 0x02ad),
MAKE_VIDPID(0x0e6f, 0x02ae),
MAKE_VIDPID(0x0e6f, 0x02af),
MAKE_VIDPID(0x0e6f, 0x02b0),
MAKE_VIDPID(0x0e6f, 0x02b1),
MAKE_VIDPID(0x0e6f, 0x02b2),
MAKE_VIDPID(0x0e6f, 0x02b3),
MAKE_VIDPID(0x0e6f, 0x02b5),
MAKE_VIDPID(0x0e6f, 0x02b6),
MAKE_VIDPID(0x0e6f, 0x02b8),
MAKE_VIDPID(0x0e6f, 0x02bd),
MAKE_VIDPID(0x0e6f, 0x02be),
MAKE_VIDPID(0x0e6f, 0x02bf),
MAKE_VIDPID(0x0e6f, 0x02c0),
MAKE_VIDPID(0x0e6f, 0x02c1),
MAKE_VIDPID(0x0e6f, 0x02c2),
MAKE_VIDPID(0x0e6f, 0x02c3),
MAKE_VIDPID(0x0e6f, 0x02c4),
MAKE_VIDPID(0x0e6f, 0x02c5),
MAKE_VIDPID(0x0e6f, 0x02c6),
MAKE_VIDPID(0x0e6f, 0x02c7),
MAKE_VIDPID(0x0e6f, 0x02c8),
MAKE_VIDPID(0x0e6f, 0x02c9),
MAKE_VIDPID(0x0e6f, 0x02ca),
MAKE_VIDPID(0x0e6f, 0x02cb),
MAKE_VIDPID(0x0e6f, 0x02cd),
MAKE_VIDPID(0x0e6f, 0x02ce),
MAKE_VIDPID(0x0e6f, 0x02cf),
MAKE_VIDPID(0x0e6f, 0x02d5),
MAKE_VIDPID(0x0e6f, 0x0346),
MAKE_VIDPID(0x0e6f, 0x0446),
MAKE_VIDPID(0x0e6f, 0xf501),
MAKE_VIDPID(0x0f0d, 0x0063),
MAKE_VIDPID(0x0f0d, 0x0067),
MAKE_VIDPID(0x0f0d, 0x0078),
MAKE_VIDPID(0x0f0d, 0x0097),
MAKE_VIDPID(0x0f0d, 0x00ba),
MAKE_VIDPID(0x0f0d, 0x00c0),
MAKE_VIDPID(0x0f0d, 0x00c5),
MAKE_VIDPID(0x0f0d, 0x00d8),
MAKE_VIDPID(0x0f0d, 0x00ed),
MAKE_VIDPID(0x0fff, 0x02a1),
MAKE_VIDPID(0x12ab, 0x0304),
MAKE_VIDPID(0x1430, 0x0291),
MAKE_VIDPID(0x1430, 0x02a9),
MAKE_VIDPID(0x1430, 0x070b),
MAKE_VIDPID(0x1430, 0x0719),
MAKE_VIDPID(0x146b, 0x0611),
MAKE_VIDPID(0x1532, 0x0a00),
MAKE_VIDPID(0x1532, 0x0a03),
MAKE_VIDPID(0x1532, 0x0a14),
MAKE_VIDPID(0x1532, 0x0a15),
MAKE_VIDPID(0x16d0, 0x0f3f),
MAKE_VIDPID(0x1bad, 0x028e),
MAKE_VIDPID(0x1bad, 0x02a0),
MAKE_VIDPID(0x1bad, 0x5500),
MAKE_VIDPID(0x20ab, 0x55ef),
MAKE_VIDPID(0x24c6, 0x541a),
MAKE_VIDPID(0x24c6, 0x542a),
MAKE_VIDPID(0x24c6, 0x543a),
MAKE_VIDPID(0x24c6, 0x5509),
MAKE_VIDPID(0x24c6, 0x551a),
MAKE_VIDPID(0x24c6, 0x561a),
MAKE_VIDPID(0x24c6, 0x581a),
MAKE_VIDPID(0x24c6, 0x591a),
MAKE_VIDPID(0x24c6, 0x592a),
MAKE_VIDPID(0x24c6, 0x791a),
MAKE_VIDPID(0x2516, 0x0069),
MAKE_VIDPID(0x25b1, 0x0360),
MAKE_VIDPID(0x2c22, 0x2203),
MAKE_VIDPID(0x2e24, 0x0652),
MAKE_VIDPID(0x2e24, 0x1618),
MAKE_VIDPID(0x2e24, 0x1688),
MAKE_VIDPID(0x2f24, 0x0011),
MAKE_VIDPID(0x2f24, 0x002e),
MAKE_VIDPID(0x2f24, 0x0050),
MAKE_VIDPID(0x2f24, 0x0053),
MAKE_VIDPID(0x2f24, 0x008f),
MAKE_VIDPID(0x2f24, 0x0091),
MAKE_VIDPID(0x2f24, 0x00b7),
MAKE_VIDPID(0xd2d2, 0xd2d2),
};
EControllerType GuessControllerType( int nVID, int nPID )
{
unsigned int unDeviceID = MAKE_CONTROLLER_ID( nVID, nPID );
int iIndex;
for ( iIndex = 0; iIndex < sizeof( arrControllers ) / sizeof( arrControllers[0] ); ++iIndex )
{
if ( unDeviceID == arrControllers[ iIndex ].m_unDeviceID )
{
return arrControllers[ iIndex ].m_eControllerType;
}
}
return k_eControllerType_UnknownNonSteamController;
}
bool SDL_IsJoystickXboxOne(Uint16 vendor_id, Uint16 product_id)
{
EControllerType eType = GuessControllerType(vendor_id, product_id);
return eType == k_eControllerType_XBoxOneController ||
eType == k_eControllerType_XBoxEliteController;
}
bool SDL_IsJoystickXboxOneElite(Uint16 vendor_id, Uint16 product_id)
{
EControllerType eType = GuessControllerType(vendor_id, product_id);
return eType == k_eControllerType_XBoxEliteController;
}
bool SDL_IsJoystickXboxSeriesX(Uint16 vendor_id, Uint16 product_id)
{
if (!SDL_IsJoystickXboxOne(vendor_id, product_id)) {
return false;
}
// Most new controllers have the share button, so we'll default to true and
// have a list of older XBox One controllers that are known not to have it.
Uint32 vidpid = MAKE_VIDPID(vendor_id, product_id);
for (int i = 0; i < (sizeof(initial_old_xboxone_controllers) / sizeof(*initial_old_xboxone_controllers)); i++) {
if (vidpid == initial_old_xboxone_controllers[i]) {
return false;
}
}
return true;
}
bool SDL_IsJoystickDualSenseEdge(Uint16 vendor_id, Uint16 product_id)
{
EControllerType eType = GuessControllerType(vendor_id, product_id);
return eType == k_eControllerType_PS5EdgeController;
}
+11
View File
@@ -0,0 +1,11 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
typedef uint16_t Uint16;
typedef uint32_t Uint32;
bool SDL_IsJoystickXboxOneElite(Uint16 vendor_id, Uint16 product_id);
bool SDL_IsJoystickXboxSeriesX(Uint16 vendor_id, Uint16 product_id);
bool SDL_IsJoystickDualSenseEdge(Uint16 vendor_id, Uint16 product_id);
@@ -1,11 +1,5 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE:= libssl
LOCAL_SRC_FILES:= $(TARGET_ARCH_ABI)/libssl.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= libcrypto
LOCAL_SRC_FILES:= $(TARGET_ARCH_ABI)/libcrypto.a
@@ -1,7 +1,7 @@
/*
* Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -1,7 +1,7 @@
/*
* Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -1,92 +1,109 @@
/*
* Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2002-2026 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef HEADER_AES_H
# define HEADER_AES_H
#ifndef OPENSSL_AES_H
#define OPENSSL_AES_H
#pragma once
# include <openssl/opensslconf.h>
#include <openssl/macros.h>
#ifndef OPENSSL_NO_DEPRECATED_3_0
#define HEADER_AES_H
#endif
# include <stddef.h>
# ifdef __cplusplus
#include <openssl/opensslconf.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
# endif
#endif
# define AES_ENCRYPT 1
# define AES_DECRYPT 0
#define AES_BLOCK_SIZE 16
/*
* Because array size can't be a const in C, the following two are macros.
* Both sizes are in bytes.
*/
# define AES_MAXNR 14
# define AES_BLOCK_SIZE 16
#ifndef OPENSSL_NO_DEPRECATED_3_0
#define AES_ENCRYPT 1
#define AES_DECRYPT 0
#define AES_MAXNR 14
/* This should be a hidden type, but EVP requires that the size be known */
struct aes_key_st {
# ifdef AES_LONG
#ifdef AES_LONG
unsigned long rd_key[4 * (AES_MAXNR + 1)];
# else
#else
unsigned int rd_key[4 * (AES_MAXNR + 1)];
# endif
#endif
int rounds;
};
typedef struct aes_key_st AES_KEY;
const char *AES_options(void);
int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
AES_KEY *key);
int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
AES_KEY *key);
#endif
#ifndef OPENSSL_NO_DEPRECATED_3_0
OSSL_DEPRECATEDIN_3_0 const char *AES_options(void);
OSSL_DEPRECATEDIN_3_0
int AES_set_encrypt_key(const unsigned char *userKey, int bits,
AES_KEY *key);
OSSL_DEPRECATEDIN_3_0
int AES_set_decrypt_key(const unsigned char *userKey, int bits,
AES_KEY *key);
OSSL_DEPRECATEDIN_3_0
void AES_encrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key);
const AES_KEY *key);
OSSL_DEPRECATEDIN_3_0
void AES_decrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key);
const AES_KEY *key);
OSSL_DEPRECATEDIN_3_0
void AES_ecb_encrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key, const int enc);
const AES_KEY *key, int enc);
OSSL_DEPRECATEDIN_3_0
void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, const int enc);
size_t length, const AES_KEY *key,
unsigned char *ivec, int enc);
OSSL_DEPRECATEDIN_3_0
void AES_cfb128_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, int *num, const int enc);
size_t length, const AES_KEY *key,
unsigned char *ivec, int *num, int enc);
OSSL_DEPRECATEDIN_3_0
void AES_cfb1_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, int *num, const int enc);
size_t length, const AES_KEY *key,
unsigned char *ivec, int *num, int enc);
OSSL_DEPRECATEDIN_3_0
void AES_cfb8_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, int *num, const int enc);
size_t length, const AES_KEY *key,
unsigned char *ivec, int *num, int enc);
OSSL_DEPRECATEDIN_3_0
void AES_ofb128_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, int *num);
size_t length, const AES_KEY *key,
unsigned char *ivec, int *num);
/* NB: the IV is _two_ blocks long */
OSSL_DEPRECATEDIN_3_0
void AES_ige_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, const int enc);
size_t length, const AES_KEY *key,
unsigned char *ivec, int enc);
/* NB: the IV is _four_ blocks long */
OSSL_DEPRECATEDIN_3_0
void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
const AES_KEY *key2, const unsigned char *ivec,
const int enc);
size_t length, const AES_KEY *key, const AES_KEY *key2,
const unsigned char *ivec, int enc);
OSSL_DEPRECATEDIN_3_0
int AES_wrap_key(AES_KEY *key, const unsigned char *iv,
unsigned char *out,
const unsigned char *in, unsigned int inlen);
unsigned char *out, const unsigned char *in,
unsigned int inlen);
OSSL_DEPRECATEDIN_3_0
int AES_unwrap_key(AES_KEY *key, const unsigned char *iv,
unsigned char *out,
const unsigned char *in, unsigned int inlen);
unsigned char *out, const unsigned char *in,
unsigned int inlen);
#endif
# ifdef __cplusplus
#ifdef __cplusplus
}
# endif
#endif
#endif
File diff suppressed because it is too large Load Diff
@@ -1,10 +0,0 @@
/*
* Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#error "This file is obsolete; please update your software."
@@ -1,256 +1,140 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef HEADER_ASN1ERR_H
# define HEADER_ASN1ERR_H
#ifndef OPENSSL_ASN1ERR_H
#define OPENSSL_ASN1ERR_H
#pragma once
# include <openssl/symhacks.h>
# ifdef __cplusplus
extern "C"
# endif
int ERR_load_ASN1_strings(void);
/*
* ASN1 function codes.
*/
# define ASN1_F_A2D_ASN1_OBJECT 100
# define ASN1_F_A2I_ASN1_INTEGER 102
# define ASN1_F_A2I_ASN1_STRING 103
# define ASN1_F_APPEND_EXP 176
# define ASN1_F_ASN1_BIO_INIT 113
# define ASN1_F_ASN1_BIT_STRING_SET_BIT 183
# define ASN1_F_ASN1_CB 177
# define ASN1_F_ASN1_CHECK_TLEN 104
# define ASN1_F_ASN1_COLLECT 106
# define ASN1_F_ASN1_D2I_EX_PRIMITIVE 108
# define ASN1_F_ASN1_D2I_FP 109
# define ASN1_F_ASN1_D2I_READ_BIO 107
# define ASN1_F_ASN1_DIGEST 184
# define ASN1_F_ASN1_DO_ADB 110
# define ASN1_F_ASN1_DO_LOCK 233
# define ASN1_F_ASN1_DUP 111
# define ASN1_F_ASN1_ENC_SAVE 115
# define ASN1_F_ASN1_EX_C2I 204
# define ASN1_F_ASN1_FIND_END 190
# define ASN1_F_ASN1_GENERALIZEDTIME_ADJ 216
# define ASN1_F_ASN1_GENERATE_V3 178
# define ASN1_F_ASN1_GET_INT64 224
# define ASN1_F_ASN1_GET_OBJECT 114
# define ASN1_F_ASN1_GET_UINT64 225
# define ASN1_F_ASN1_I2D_BIO 116
# define ASN1_F_ASN1_I2D_FP 117
# define ASN1_F_ASN1_ITEM_D2I_FP 206
# define ASN1_F_ASN1_ITEM_DUP 191
# define ASN1_F_ASN1_ITEM_EMBED_D2I 120
# define ASN1_F_ASN1_ITEM_EMBED_NEW 121
# define ASN1_F_ASN1_ITEM_EX_I2D 144
# define ASN1_F_ASN1_ITEM_FLAGS_I2D 118
# define ASN1_F_ASN1_ITEM_I2D_BIO 192
# define ASN1_F_ASN1_ITEM_I2D_FP 193
# define ASN1_F_ASN1_ITEM_PACK 198
# define ASN1_F_ASN1_ITEM_SIGN 195
# define ASN1_F_ASN1_ITEM_SIGN_CTX 220
# define ASN1_F_ASN1_ITEM_UNPACK 199
# define ASN1_F_ASN1_ITEM_VERIFY 197
# define ASN1_F_ASN1_MBSTRING_NCOPY 122
# define ASN1_F_ASN1_OBJECT_NEW 123
# define ASN1_F_ASN1_OUTPUT_DATA 214
# define ASN1_F_ASN1_PCTX_NEW 205
# define ASN1_F_ASN1_PRIMITIVE_NEW 119
# define ASN1_F_ASN1_SCTX_NEW 221
# define ASN1_F_ASN1_SIGN 128
# define ASN1_F_ASN1_STR2TYPE 179
# define ASN1_F_ASN1_STRING_GET_INT64 227
# define ASN1_F_ASN1_STRING_GET_UINT64 230
# define ASN1_F_ASN1_STRING_SET 186
# define ASN1_F_ASN1_STRING_TABLE_ADD 129
# define ASN1_F_ASN1_STRING_TO_BN 228
# define ASN1_F_ASN1_STRING_TYPE_NEW 130
# define ASN1_F_ASN1_TEMPLATE_EX_D2I 132
# define ASN1_F_ASN1_TEMPLATE_NEW 133
# define ASN1_F_ASN1_TEMPLATE_NOEXP_D2I 131
# define ASN1_F_ASN1_TIME_ADJ 217
# define ASN1_F_ASN1_TYPE_GET_INT_OCTETSTRING 134
# define ASN1_F_ASN1_TYPE_GET_OCTETSTRING 135
# define ASN1_F_ASN1_UTCTIME_ADJ 218
# define ASN1_F_ASN1_VERIFY 137
# define ASN1_F_B64_READ_ASN1 209
# define ASN1_F_B64_WRITE_ASN1 210
# define ASN1_F_BIO_NEW_NDEF 208
# define ASN1_F_BITSTR_CB 180
# define ASN1_F_BN_TO_ASN1_STRING 229
# define ASN1_F_C2I_ASN1_BIT_STRING 189
# define ASN1_F_C2I_ASN1_INTEGER 194
# define ASN1_F_C2I_ASN1_OBJECT 196
# define ASN1_F_C2I_IBUF 226
# define ASN1_F_C2I_UINT64_INT 101
# define ASN1_F_COLLECT_DATA 140
# define ASN1_F_D2I_ASN1_OBJECT 147
# define ASN1_F_D2I_ASN1_UINTEGER 150
# define ASN1_F_D2I_AUTOPRIVATEKEY 207
# define ASN1_F_D2I_PRIVATEKEY 154
# define ASN1_F_D2I_PUBLICKEY 155
# define ASN1_F_DO_BUF 142
# define ASN1_F_DO_CREATE 124
# define ASN1_F_DO_DUMP 125
# define ASN1_F_DO_TCREATE 222
# define ASN1_F_I2A_ASN1_OBJECT 126
# define ASN1_F_I2D_ASN1_BIO_STREAM 211
# define ASN1_F_I2D_ASN1_OBJECT 143
# define ASN1_F_I2D_DSA_PUBKEY 161
# define ASN1_F_I2D_EC_PUBKEY 181
# define ASN1_F_I2D_PRIVATEKEY 163
# define ASN1_F_I2D_PUBLICKEY 164
# define ASN1_F_I2D_RSA_PUBKEY 165
# define ASN1_F_LONG_C2I 166
# define ASN1_F_NDEF_PREFIX 127
# define ASN1_F_NDEF_SUFFIX 136
# define ASN1_F_OID_MODULE_INIT 174
# define ASN1_F_PARSE_TAGGING 182
# define ASN1_F_PKCS5_PBE2_SET_IV 167
# define ASN1_F_PKCS5_PBE2_SET_SCRYPT 231
# define ASN1_F_PKCS5_PBE_SET 202
# define ASN1_F_PKCS5_PBE_SET0_ALGOR 215
# define ASN1_F_PKCS5_PBKDF2_SET 219
# define ASN1_F_PKCS5_SCRYPT_SET 232
# define ASN1_F_SMIME_READ_ASN1 212
# define ASN1_F_SMIME_TEXT 213
# define ASN1_F_STABLE_GET 138
# define ASN1_F_STBL_MODULE_INIT 223
# define ASN1_F_UINT32_C2I 105
# define ASN1_F_UINT32_NEW 139
# define ASN1_F_UINT64_C2I 112
# define ASN1_F_UINT64_NEW 141
# define ASN1_F_X509_CRL_ADD0_REVOKED 169
# define ASN1_F_X509_INFO_NEW 170
# define ASN1_F_X509_NAME_ENCODE 203
# define ASN1_F_X509_NAME_EX_D2I 158
# define ASN1_F_X509_NAME_EX_NEW 171
# define ASN1_F_X509_PKEY_NEW 173
#include <openssl/opensslconf.h>
#include <openssl/symhacks.h>
#include <openssl/cryptoerr_legacy.h>
/*
* ASN1 reason codes.
*/
# define ASN1_R_ADDING_OBJECT 171
# define ASN1_R_ASN1_PARSE_ERROR 203
# define ASN1_R_ASN1_SIG_PARSE_ERROR 204
# define ASN1_R_AUX_ERROR 100
# define ASN1_R_BAD_OBJECT_HEADER 102
# define ASN1_R_BAD_TEMPLATE 230
# define ASN1_R_BMPSTRING_IS_WRONG_LENGTH 214
# define ASN1_R_BN_LIB 105
# define ASN1_R_BOOLEAN_IS_WRONG_LENGTH 106
# define ASN1_R_BUFFER_TOO_SMALL 107
# define ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER 108
# define ASN1_R_CONTEXT_NOT_INITIALISED 217
# define ASN1_R_DATA_IS_WRONG 109
# define ASN1_R_DECODE_ERROR 110
# define ASN1_R_DEPTH_EXCEEDED 174
# define ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED 198
# define ASN1_R_ENCODE_ERROR 112
# define ASN1_R_ERROR_GETTING_TIME 173
# define ASN1_R_ERROR_LOADING_SECTION 172
# define ASN1_R_ERROR_SETTING_CIPHER_PARAMS 114
# define ASN1_R_EXPECTING_AN_INTEGER 115
# define ASN1_R_EXPECTING_AN_OBJECT 116
# define ASN1_R_EXPLICIT_LENGTH_MISMATCH 119
# define ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED 120
# define ASN1_R_FIELD_MISSING 121
# define ASN1_R_FIRST_NUM_TOO_LARGE 122
# define ASN1_R_HEADER_TOO_LONG 123
# define ASN1_R_ILLEGAL_BITSTRING_FORMAT 175
# define ASN1_R_ILLEGAL_BOOLEAN 176
# define ASN1_R_ILLEGAL_CHARACTERS 124
# define ASN1_R_ILLEGAL_FORMAT 177
# define ASN1_R_ILLEGAL_HEX 178
# define ASN1_R_ILLEGAL_IMPLICIT_TAG 179
# define ASN1_R_ILLEGAL_INTEGER 180
# define ASN1_R_ILLEGAL_NEGATIVE_VALUE 226
# define ASN1_R_ILLEGAL_NESTED_TAGGING 181
# define ASN1_R_ILLEGAL_NULL 125
# define ASN1_R_ILLEGAL_NULL_VALUE 182
# define ASN1_R_ILLEGAL_OBJECT 183
# define ASN1_R_ILLEGAL_OPTIONAL_ANY 126
# define ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE 170
# define ASN1_R_ILLEGAL_PADDING 221
# define ASN1_R_ILLEGAL_TAGGED_ANY 127
# define ASN1_R_ILLEGAL_TIME_VALUE 184
# define ASN1_R_ILLEGAL_ZERO_CONTENT 222
# define ASN1_R_INTEGER_NOT_ASCII_FORMAT 185
# define ASN1_R_INTEGER_TOO_LARGE_FOR_LONG 128
# define ASN1_R_INVALID_BIT_STRING_BITS_LEFT 220
# define ASN1_R_INVALID_BMPSTRING_LENGTH 129
# define ASN1_R_INVALID_DIGIT 130
# define ASN1_R_INVALID_MIME_TYPE 205
# define ASN1_R_INVALID_MODIFIER 186
# define ASN1_R_INVALID_NUMBER 187
# define ASN1_R_INVALID_OBJECT_ENCODING 216
# define ASN1_R_INVALID_SCRYPT_PARAMETERS 227
# define ASN1_R_INVALID_SEPARATOR 131
# define ASN1_R_INVALID_STRING_TABLE_VALUE 218
# define ASN1_R_INVALID_UNIVERSALSTRING_LENGTH 133
# define ASN1_R_INVALID_UTF8STRING 134
# define ASN1_R_INVALID_VALUE 219
# define ASN1_R_LIST_ERROR 188
# define ASN1_R_MIME_NO_CONTENT_TYPE 206
# define ASN1_R_MIME_PARSE_ERROR 207
# define ASN1_R_MIME_SIG_PARSE_ERROR 208
# define ASN1_R_MISSING_EOC 137
# define ASN1_R_MISSING_SECOND_NUMBER 138
# define ASN1_R_MISSING_VALUE 189
# define ASN1_R_MSTRING_NOT_UNIVERSAL 139
# define ASN1_R_MSTRING_WRONG_TAG 140
# define ASN1_R_NESTED_ASN1_STRING 197
# define ASN1_R_NESTED_TOO_DEEP 201
# define ASN1_R_NON_HEX_CHARACTERS 141
# define ASN1_R_NOT_ASCII_FORMAT 190
# define ASN1_R_NOT_ENOUGH_DATA 142
# define ASN1_R_NO_CONTENT_TYPE 209
# define ASN1_R_NO_MATCHING_CHOICE_TYPE 143
# define ASN1_R_NO_MULTIPART_BODY_FAILURE 210
# define ASN1_R_NO_MULTIPART_BOUNDARY 211
# define ASN1_R_NO_SIG_CONTENT_TYPE 212
# define ASN1_R_NULL_IS_WRONG_LENGTH 144
# define ASN1_R_OBJECT_NOT_ASCII_FORMAT 191
# define ASN1_R_ODD_NUMBER_OF_CHARS 145
# define ASN1_R_SECOND_NUMBER_TOO_LARGE 147
# define ASN1_R_SEQUENCE_LENGTH_MISMATCH 148
# define ASN1_R_SEQUENCE_NOT_CONSTRUCTED 149
# define ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG 192
# define ASN1_R_SHORT_LINE 150
# define ASN1_R_SIG_INVALID_MIME_TYPE 213
# define ASN1_R_STREAMING_NOT_SUPPORTED 202
# define ASN1_R_STRING_TOO_LONG 151
# define ASN1_R_STRING_TOO_SHORT 152
# define ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD 154
# define ASN1_R_TIME_NOT_ASCII_FORMAT 193
# define ASN1_R_TOO_LARGE 223
# define ASN1_R_TOO_LONG 155
# define ASN1_R_TOO_SMALL 224
# define ASN1_R_TYPE_NOT_CONSTRUCTED 156
# define ASN1_R_TYPE_NOT_PRIMITIVE 195
# define ASN1_R_UNEXPECTED_EOC 159
# define ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH 215
# define ASN1_R_UNKNOWN_FORMAT 160
# define ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM 161
# define ASN1_R_UNKNOWN_OBJECT_TYPE 162
# define ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE 163
# define ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM 199
# define ASN1_R_UNKNOWN_TAG 194
# define ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE 164
# define ASN1_R_UNSUPPORTED_CIPHER 228
# define ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE 167
# define ASN1_R_UNSUPPORTED_TYPE 196
# define ASN1_R_WRONG_INTEGER_TYPE 225
# define ASN1_R_WRONG_PUBLIC_KEY_TYPE 200
# define ASN1_R_WRONG_TAG 168
#define ASN1_R_ADDING_OBJECT 171
#define ASN1_R_ASN1_PARSE_ERROR 203
#define ASN1_R_ASN1_SIG_PARSE_ERROR 204
#define ASN1_R_AUX_ERROR 100
#define ASN1_R_BAD_OBJECT_HEADER 102
#define ASN1_R_BAD_TEMPLATE 230
#define ASN1_R_BMPSTRING_IS_WRONG_LENGTH 214
#define ASN1_R_BN_LIB 105
#define ASN1_R_BOOLEAN_IS_WRONG_LENGTH 106
#define ASN1_R_BUFFER_TOO_SMALL 107
#define ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER 108
#define ASN1_R_CONTEXT_NOT_INITIALISED 217
#define ASN1_R_DATA_IS_WRONG 109
#define ASN1_R_DECODE_ERROR 110
#define ASN1_R_DEPTH_EXCEEDED 174
#define ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED 198
#define ASN1_R_ENCODE_ERROR 112
#define ASN1_R_ERROR_GETTING_TIME 173
#define ASN1_R_ERROR_LOADING_SECTION 172
#define ASN1_R_ERROR_SETTING_CIPHER_PARAMS 114
#define ASN1_R_EXPECTING_AN_INTEGER 115
#define ASN1_R_EXPECTING_AN_OBJECT 116
#define ASN1_R_EXPLICIT_LENGTH_MISMATCH 119
#define ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED 120
#define ASN1_R_FIELD_MISSING 121
#define ASN1_R_FIRST_NUM_TOO_LARGE 122
#define ASN1_R_GENERALIZEDTIME_IS_TOO_SHORT 232
#define ASN1_R_HEADER_TOO_LONG 123
#define ASN1_R_ILLEGAL_BITSTRING_FORMAT 175
#define ASN1_R_ILLEGAL_BOOLEAN 176
#define ASN1_R_ILLEGAL_CHARACTERS 124
#define ASN1_R_ILLEGAL_FORMAT 177
#define ASN1_R_ILLEGAL_HEX 178
#define ASN1_R_ILLEGAL_IMPLICIT_TAG 179
#define ASN1_R_ILLEGAL_INTEGER 180
#define ASN1_R_ILLEGAL_NEGATIVE_VALUE 226
#define ASN1_R_ILLEGAL_NESTED_TAGGING 181
#define ASN1_R_ILLEGAL_NULL 125
#define ASN1_R_ILLEGAL_NULL_VALUE 182
#define ASN1_R_ILLEGAL_OBJECT 183
#define ASN1_R_ILLEGAL_OPTIONAL_ANY 126
#define ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE 170
#define ASN1_R_ILLEGAL_PADDING 221
#define ASN1_R_ILLEGAL_TAGGED_ANY 127
#define ASN1_R_ILLEGAL_TIME_VALUE 184
#define ASN1_R_ILLEGAL_ZERO_CONTENT 222
#define ASN1_R_INTEGER_NOT_ASCII_FORMAT 185
#define ASN1_R_INTEGER_TOO_LARGE_FOR_LONG 128
#define ASN1_R_INVALID_BIT_STRING_BITS_LEFT 220
#define ASN1_R_INVALID_BMPSTRING_LENGTH 129
#define ASN1_R_INVALID_DIGIT 130
#define ASN1_R_INVALID_MIME_TYPE 205
#define ASN1_R_INVALID_MODIFIER 186
#define ASN1_R_INVALID_NUMBER 187
#define ASN1_R_INVALID_OBJECT_ENCODING 216
#define ASN1_R_INVALID_SCRYPT_PARAMETERS 227
#define ASN1_R_INVALID_SEPARATOR 131
#define ASN1_R_INVALID_STRING_TABLE_VALUE 218
#define ASN1_R_INVALID_UNIVERSALSTRING_LENGTH 133
#define ASN1_R_INVALID_UTF8STRING 134
#define ASN1_R_INVALID_VALUE 219
#define ASN1_R_LENGTH_TOO_LONG 231
#define ASN1_R_LIST_ERROR 188
#define ASN1_R_MIME_NO_CONTENT_TYPE 206
#define ASN1_R_MIME_PARSE_ERROR 207
#define ASN1_R_MIME_SIG_PARSE_ERROR 208
#define ASN1_R_MISSING_EOC 137
#define ASN1_R_MISSING_SECOND_NUMBER 138
#define ASN1_R_MISSING_VALUE 189
#define ASN1_R_MSTRING_NOT_UNIVERSAL 139
#define ASN1_R_MSTRING_WRONG_TAG 140
#define ASN1_R_NESTED_ASN1_STRING 197
#define ASN1_R_NESTED_TOO_DEEP 201
#define ASN1_R_NON_HEX_CHARACTERS 141
#define ASN1_R_NOT_ASCII_FORMAT 190
#define ASN1_R_NOT_ENOUGH_DATA 142
#define ASN1_R_NO_CONTENT_TYPE 209
#define ASN1_R_NO_MATCHING_CHOICE_TYPE 143
#define ASN1_R_NO_MULTIPART_BODY_FAILURE 210
#define ASN1_R_NO_MULTIPART_BOUNDARY 211
#define ASN1_R_NO_SIG_CONTENT_TYPE 212
#define ASN1_R_NULL_IS_WRONG_LENGTH 144
#define ASN1_R_OBJECT_NOT_ASCII_FORMAT 191
#define ASN1_R_ODD_NUMBER_OF_CHARS 145
#define ASN1_R_SECOND_NUMBER_TOO_LARGE 147
#define ASN1_R_SEQUENCE_LENGTH_MISMATCH 148
#define ASN1_R_SEQUENCE_NOT_CONSTRUCTED 149
#define ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG 192
#define ASN1_R_SHORT_LINE 150
#define ASN1_R_SIG_INVALID_MIME_TYPE 213
#define ASN1_R_STREAMING_NOT_SUPPORTED 202
#define ASN1_R_STRING_TOO_LONG 151
#define ASN1_R_STRING_TOO_SHORT 152
#define ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD 154
#define ASN1_R_TIME_NOT_ASCII_FORMAT 193
#define ASN1_R_TOO_LARGE 223
#define ASN1_R_TOO_LONG 155
#define ASN1_R_TOO_SMALL 224
#define ASN1_R_TYPE_NOT_CONSTRUCTED 156
#define ASN1_R_TYPE_NOT_PRIMITIVE 195
#define ASN1_R_UNEXPECTED_EOC 159
#define ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH 215
#define ASN1_R_UNKNOWN_DIGEST 229
#define ASN1_R_UNKNOWN_FORMAT 160
#define ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM 161
#define ASN1_R_UNKNOWN_OBJECT_TYPE 162
#define ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE 163
#define ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM 199
#define ASN1_R_UNKNOWN_TAG 194
#define ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE 164
#define ASN1_R_UNSUPPORTED_CIPHER 228
#define ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE 167
#define ASN1_R_UNSUPPORTED_TYPE 196
#define ASN1_R_UTCTIME_IS_TOO_SHORT 233
#define ASN1_R_WRONG_INTEGER_TYPE 225
#define ASN1_R_WRONG_PUBLIC_KEY_TYPE 200
#define ASN1_R_WRONG_TAG 168
#endif
File diff suppressed because it is too large Load Diff
@@ -1,7 +1,7 @@
/*
* Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
@@ -9,33 +9,44 @@
#include <stdlib.h>
#ifndef HEADER_ASYNC_H
# define HEADER_ASYNC_H
#ifndef OPENSSL_ASYNC_H
#define OPENSSL_ASYNC_H
#pragma once
#include <openssl/macros.h>
#ifndef OPENSSL_NO_DEPRECATED_3_0
#define HEADER_ASYNC_H
#endif
#if defined(_WIN32)
# if defined(BASETYPES) || defined(_WINDEF_H)
#if defined(BASETYPES) || defined(_WINDEF_H)
/* application has to include <windows.h> to use this */
#define OSSL_ASYNC_FD HANDLE
#define OSSL_BAD_ASYNC_FD INVALID_HANDLE_VALUE
# endif
#else
#define OSSL_ASYNC_FD int
#define OSSL_BAD_ASYNC_FD -1
#define OSSL_ASYNC_FD HANDLE
#define OSSL_BAD_ASYNC_FD INVALID_HANDLE_VALUE
#endif
# include <openssl/asyncerr.h>
#else
#define OSSL_ASYNC_FD int
#define OSSL_BAD_ASYNC_FD -1
#endif
#include <openssl/asyncerr.h>
# ifdef __cplusplus
#ifdef __cplusplus
extern "C" {
# endif
#endif
typedef struct async_job_st ASYNC_JOB;
typedef struct async_wait_ctx_st ASYNC_WAIT_CTX;
typedef int (*ASYNC_callback_fn)(void *arg);
#define ASYNC_ERR 0
#define ASYNC_NO_JOBS 1
#define ASYNC_PAUSE 2
#define ASYNC_FINISH 3
#define ASYNC_ERR 0
#define ASYNC_NO_JOBS 1
#define ASYNC_PAUSE 2
#define ASYNC_FINISH 3
#define ASYNC_STATUS_UNSUPPORTED 0
#define ASYNC_STATUS_ERR 1
#define ASYNC_STATUS_OK 2
#define ASYNC_STATUS_EAGAIN 3
int ASYNC_init_thread(size_t max_size, size_t init_size);
void ASYNC_cleanup_thread(void);
@@ -44,24 +55,40 @@ void ASYNC_cleanup_thread(void);
ASYNC_WAIT_CTX *ASYNC_WAIT_CTX_new(void);
void ASYNC_WAIT_CTX_free(ASYNC_WAIT_CTX *ctx);
int ASYNC_WAIT_CTX_set_wait_fd(ASYNC_WAIT_CTX *ctx, const void *key,
OSSL_ASYNC_FD fd,
void *custom_data,
void (*cleanup)(ASYNC_WAIT_CTX *, const void *,
OSSL_ASYNC_FD, void *));
OSSL_ASYNC_FD fd,
void *custom_data,
void (*cleanup)(ASYNC_WAIT_CTX *, const void *,
OSSL_ASYNC_FD, void *));
int ASYNC_WAIT_CTX_get_fd(ASYNC_WAIT_CTX *ctx, const void *key,
OSSL_ASYNC_FD *fd, void **custom_data);
OSSL_ASYNC_FD *fd, void **custom_data);
int ASYNC_WAIT_CTX_get_all_fds(ASYNC_WAIT_CTX *ctx, OSSL_ASYNC_FD *fd,
size_t *numfds);
size_t *numfds);
int ASYNC_WAIT_CTX_get_callback(ASYNC_WAIT_CTX *ctx,
ASYNC_callback_fn *callback,
void **callback_arg);
int ASYNC_WAIT_CTX_set_callback(ASYNC_WAIT_CTX *ctx,
ASYNC_callback_fn callback,
void *callback_arg);
int ASYNC_WAIT_CTX_set_status(ASYNC_WAIT_CTX *ctx, int status);
int ASYNC_WAIT_CTX_get_status(ASYNC_WAIT_CTX *ctx);
int ASYNC_WAIT_CTX_get_changed_fds(ASYNC_WAIT_CTX *ctx, OSSL_ASYNC_FD *addfd,
size_t *numaddfds, OSSL_ASYNC_FD *delfd,
size_t *numdelfds);
size_t *numaddfds, OSSL_ASYNC_FD *delfd,
size_t *numdelfds);
int ASYNC_WAIT_CTX_clear_fd(ASYNC_WAIT_CTX *ctx, const void *key);
#endif
int ASYNC_is_capable(void);
typedef void *(*ASYNC_stack_alloc_fn)(size_t *num);
typedef void (*ASYNC_stack_free_fn)(void *addr);
int ASYNC_set_mem_functions(ASYNC_stack_alloc_fn alloc_fn,
ASYNC_stack_free_fn free_fn);
void ASYNC_get_mem_functions(ASYNC_stack_alloc_fn *alloc_fn,
ASYNC_stack_free_fn *free_fn);
int ASYNC_start_job(ASYNC_JOB **job, ASYNC_WAIT_CTX *ctx, int *ret,
int (*func)(void *), void *args, size_t size);
int (*func)(void *), void *args, size_t size);
int ASYNC_pause_job(void);
ASYNC_JOB *ASYNC_get_current_job(void);
@@ -69,8 +96,7 @@ ASYNC_WAIT_CTX *ASYNC_get_wait_ctx(ASYNC_JOB *job);
void ASYNC_block_pause(void);
void ASYNC_unblock_pause(void);
# ifdef __cplusplus
#ifdef __cplusplus
}
# endif
#endif
#endif
@@ -1,42 +1,27 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef HEADER_ASYNCERR_H
# define HEADER_ASYNCERR_H
#ifndef OPENSSL_ASYNCERR_H
#define OPENSSL_ASYNCERR_H
#pragma once
# ifndef HEADER_SYMHACKS_H
# include <openssl/symhacks.h>
# endif
# ifdef __cplusplus
extern "C"
# endif
int ERR_load_ASYNC_strings(void);
/*
* ASYNC function codes.
*/
# define ASYNC_F_ASYNC_CTX_NEW 100
# define ASYNC_F_ASYNC_INIT_THREAD 101
# define ASYNC_F_ASYNC_JOB_NEW 102
# define ASYNC_F_ASYNC_PAUSE_JOB 103
# define ASYNC_F_ASYNC_START_FUNC 104
# define ASYNC_F_ASYNC_START_JOB 105
# define ASYNC_F_ASYNC_WAIT_CTX_SET_WAIT_FD 106
#include <openssl/opensslconf.h>
#include <openssl/symhacks.h>
#include <openssl/cryptoerr_legacy.h>
/*
* ASYNC reason codes.
*/
# define ASYNC_R_FAILED_TO_SET_POOL 101
# define ASYNC_R_FAILED_TO_SWAP_CONTEXT 102
# define ASYNC_R_INIT_FAILED 105
# define ASYNC_R_INVALID_POOL_SIZE 103
#define ASYNC_R_FAILED_TO_SET_POOL 101
#define ASYNC_R_FAILED_TO_SWAP_CONTEXT 102
#define ASYNC_R_INIT_FAILED 105
#define ASYNC_R_INVALID_POOL_SIZE 103
#endif
File diff suppressed because it is too large Load Diff
@@ -1,124 +1,70 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef HEADER_BIOERR_H
# define HEADER_BIOERR_H
#ifndef OPENSSL_BIOERR_H
#define OPENSSL_BIOERR_H
#pragma once
# ifndef HEADER_SYMHACKS_H
# include <openssl/symhacks.h>
# endif
# ifdef __cplusplus
extern "C"
# endif
int ERR_load_BIO_strings(void);
/*
* BIO function codes.
*/
# define BIO_F_ACPT_STATE 100
# define BIO_F_ADDRINFO_WRAP 148
# define BIO_F_ADDR_STRINGS 134
# define BIO_F_BIO_ACCEPT 101
# define BIO_F_BIO_ACCEPT_EX 137
# define BIO_F_BIO_ACCEPT_NEW 152
# define BIO_F_BIO_ADDR_NEW 144
# define BIO_F_BIO_BIND 147
# define BIO_F_BIO_CALLBACK_CTRL 131
# define BIO_F_BIO_CONNECT 138
# define BIO_F_BIO_CONNECT_NEW 153
# define BIO_F_BIO_CTRL 103
# define BIO_F_BIO_GETS 104
# define BIO_F_BIO_GET_HOST_IP 106
# define BIO_F_BIO_GET_NEW_INDEX 102
# define BIO_F_BIO_GET_PORT 107
# define BIO_F_BIO_LISTEN 139
# define BIO_F_BIO_LOOKUP 135
# define BIO_F_BIO_LOOKUP_EX 143
# define BIO_F_BIO_MAKE_PAIR 121
# define BIO_F_BIO_METH_NEW 146
# define BIO_F_BIO_NEW 108
# define BIO_F_BIO_NEW_DGRAM_SCTP 145
# define BIO_F_BIO_NEW_FILE 109
# define BIO_F_BIO_NEW_MEM_BUF 126
# define BIO_F_BIO_NREAD 123
# define BIO_F_BIO_NREAD0 124
# define BIO_F_BIO_NWRITE 125
# define BIO_F_BIO_NWRITE0 122
# define BIO_F_BIO_PARSE_HOSTSERV 136
# define BIO_F_BIO_PUTS 110
# define BIO_F_BIO_READ 111
# define BIO_F_BIO_READ_EX 105
# define BIO_F_BIO_READ_INTERN 120
# define BIO_F_BIO_SOCKET 140
# define BIO_F_BIO_SOCKET_NBIO 142
# define BIO_F_BIO_SOCK_INFO 141
# define BIO_F_BIO_SOCK_INIT 112
# define BIO_F_BIO_WRITE 113
# define BIO_F_BIO_WRITE_EX 119
# define BIO_F_BIO_WRITE_INTERN 128
# define BIO_F_BUFFER_CTRL 114
# define BIO_F_CONN_CTRL 127
# define BIO_F_CONN_STATE 115
# define BIO_F_DGRAM_SCTP_NEW 149
# define BIO_F_DGRAM_SCTP_READ 132
# define BIO_F_DGRAM_SCTP_WRITE 133
# define BIO_F_DOAPR_OUTCH 150
# define BIO_F_FILE_CTRL 116
# define BIO_F_FILE_READ 130
# define BIO_F_LINEBUFFER_CTRL 129
# define BIO_F_LINEBUFFER_NEW 151
# define BIO_F_MEM_WRITE 117
# define BIO_F_NBIOF_NEW 154
# define BIO_F_SLG_WRITE 155
# define BIO_F_SSL_NEW 118
#include <openssl/opensslconf.h>
#include <openssl/symhacks.h>
#include <openssl/cryptoerr_legacy.h>
/*
* BIO reason codes.
*/
# define BIO_R_ACCEPT_ERROR 100
# define BIO_R_ADDRINFO_ADDR_IS_NOT_AF_INET 141
# define BIO_R_AMBIGUOUS_HOST_OR_SERVICE 129
# define BIO_R_BAD_FOPEN_MODE 101
# define BIO_R_BROKEN_PIPE 124
# define BIO_R_CONNECT_ERROR 103
# define BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET 107
# define BIO_R_GETSOCKNAME_ERROR 132
# define BIO_R_GETSOCKNAME_TRUNCATED_ADDRESS 133
# define BIO_R_GETTING_SOCKTYPE 134
# define BIO_R_INVALID_ARGUMENT 125
# define BIO_R_INVALID_SOCKET 135
# define BIO_R_IN_USE 123
# define BIO_R_LENGTH_TOO_LONG 102
# define BIO_R_LISTEN_V6_ONLY 136
# define BIO_R_LOOKUP_RETURNED_NOTHING 142
# define BIO_R_MALFORMED_HOST_OR_SERVICE 130
# define BIO_R_NBIO_CONNECT_ERROR 110
# define BIO_R_NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED 143
# define BIO_R_NO_HOSTNAME_OR_SERVICE_SPECIFIED 144
# define BIO_R_NO_PORT_DEFINED 113
# define BIO_R_NO_SUCH_FILE 128
# define BIO_R_NULL_PARAMETER 115
# define BIO_R_UNABLE_TO_BIND_SOCKET 117
# define BIO_R_UNABLE_TO_CREATE_SOCKET 118
# define BIO_R_UNABLE_TO_KEEPALIVE 137
# define BIO_R_UNABLE_TO_LISTEN_SOCKET 119
# define BIO_R_UNABLE_TO_NODELAY 138
# define BIO_R_UNABLE_TO_REUSEADDR 139
# define BIO_R_UNAVAILABLE_IP_FAMILY 145
# define BIO_R_UNINITIALIZED 120
# define BIO_R_UNKNOWN_INFO_TYPE 140
# define BIO_R_UNSUPPORTED_IP_FAMILY 146
# define BIO_R_UNSUPPORTED_METHOD 121
# define BIO_R_UNSUPPORTED_PROTOCOL_FAMILY 131
# define BIO_R_WRITE_TO_READ_ONLY_BIO 126
# define BIO_R_WSASTARTUP 122
#define BIO_R_ACCEPT_ERROR 100
#define BIO_R_ADDRINFO_ADDR_IS_NOT_AF_INET 141
#define BIO_R_AMBIGUOUS_HOST_OR_SERVICE 129
#define BIO_R_BAD_FOPEN_MODE 101
#define BIO_R_BROKEN_PIPE 124
#define BIO_R_CONNECT_ERROR 103
#define BIO_R_CONNECT_TIMEOUT 147
#define BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET 107
#define BIO_R_GETSOCKNAME_ERROR 132
#define BIO_R_GETSOCKNAME_TRUNCATED_ADDRESS 133
#define BIO_R_GETTING_SOCKTYPE 134
#define BIO_R_INVALID_ARGUMENT 125
#define BIO_R_INVALID_SOCKET 135
#define BIO_R_IN_USE 123
#define BIO_R_LENGTH_TOO_LONG 102
#define BIO_R_LISTEN_V6_ONLY 136
#define BIO_R_LOCAL_ADDR_NOT_AVAILABLE 111
#define BIO_R_LOOKUP_RETURNED_NOTHING 142
#define BIO_R_MALFORMED_HOST_OR_SERVICE 130
#define BIO_R_NBIO_CONNECT_ERROR 110
#define BIO_R_NON_FATAL 112
#define BIO_R_NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED 143
#define BIO_R_NO_HOSTNAME_OR_SERVICE_SPECIFIED 144
#define BIO_R_NO_PORT_DEFINED 113
#define BIO_R_NO_SUCH_FILE 128
#define BIO_R_NULL_PARAMETER 115 /* unused */
#define BIO_R_TFO_DISABLED 106
#define BIO_R_TFO_NO_KERNEL_SUPPORT 108
#define BIO_R_TRANSFER_ERROR 104
#define BIO_R_TRANSFER_TIMEOUT 105
#define BIO_R_UNABLE_TO_BIND_SOCKET 117
#define BIO_R_UNABLE_TO_CREATE_SOCKET 118
#define BIO_R_UNABLE_TO_KEEPALIVE 137
#define BIO_R_UNABLE_TO_LISTEN_SOCKET 119
#define BIO_R_UNABLE_TO_NODELAY 138
#define BIO_R_UNABLE_TO_REUSEADDR 139
#define BIO_R_UNABLE_TO_TFO 109
#define BIO_R_UNAVAILABLE_IP_FAMILY 145
#define BIO_R_UNINITIALIZED 120
#define BIO_R_UNKNOWN_INFO_TYPE 140
#define BIO_R_UNSUPPORTED_IP_FAMILY 146
#define BIO_R_UNSUPPORTED_METHOD 121
#define BIO_R_UNSUPPORTED_PROTOCOL_FAMILY 131
#define BIO_R_WRITE_TO_READ_ONLY_BIO 126
#define BIO_R_WSASTARTUP 122
#define BIO_R_PORT_MISMATCH 150
#define BIO_R_PEER_ADDR_NOT_AVAILABLE 151
#endif
@@ -1,61 +1,78 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef HEADER_BLOWFISH_H
# define HEADER_BLOWFISH_H
#ifndef OPENSSL_BLOWFISH_H
#define OPENSSL_BLOWFISH_H
#pragma once
# include <openssl/opensslconf.h>
#include <openssl/macros.h>
#ifndef OPENSSL_NO_DEPRECATED_3_0
#define HEADER_BLOWFISH_H
#endif
# ifndef OPENSSL_NO_BF
# include <openssl/e_os2.h>
# ifdef __cplusplus
#include <openssl/opensslconf.h>
#ifndef OPENSSL_NO_BF
#include <openssl/e_os2.h>
#ifdef __cplusplus
extern "C" {
# endif
#endif
# define BF_ENCRYPT 1
# define BF_DECRYPT 0
#define BF_BLOCK 8
#ifndef OPENSSL_NO_DEPRECATED_3_0
#define BF_ENCRYPT 1
#define BF_DECRYPT 0
/*-
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* ! BF_LONG has to be at least 32 bits wide. !
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*/
# define BF_LONG unsigned int
typedef unsigned int BF_LONG;
# define BF_ROUNDS 16
# define BF_BLOCK 8
#define BF_ROUNDS 16
typedef struct bf_key_st {
BF_LONG P[BF_ROUNDS + 2];
BF_LONG S[4 * 256];
} BF_KEY;
void BF_set_key(BF_KEY *key, int len, const unsigned char *data);
#endif /* OPENSSL_NO_DEPRECATED_3_0 */
#ifndef OPENSSL_NO_DEPRECATED_3_0
OSSL_DEPRECATEDIN_3_0 void BF_set_key(BF_KEY *key, int len,
const unsigned char *data);
OSSL_DEPRECATEDIN_3_0 void BF_encrypt(BF_LONG *data, const BF_KEY *key);
OSSL_DEPRECATEDIN_3_0 void BF_decrypt(BF_LONG *data, const BF_KEY *key);
OSSL_DEPRECATEDIN_3_0 void BF_ecb_encrypt(const unsigned char *in,
unsigned char *out, const BF_KEY *key,
int enc);
OSSL_DEPRECATEDIN_3_0 void BF_cbc_encrypt(const unsigned char *in,
unsigned char *out, long length,
const BF_KEY *schedule,
unsigned char *ivec, int enc);
OSSL_DEPRECATEDIN_3_0 void BF_cfb64_encrypt(const unsigned char *in,
unsigned char *out,
long length, const BF_KEY *schedule,
unsigned char *ivec, int *num,
int enc);
OSSL_DEPRECATEDIN_3_0 void BF_ofb64_encrypt(const unsigned char *in,
unsigned char *out,
long length, const BF_KEY *schedule,
unsigned char *ivec, int *num);
OSSL_DEPRECATEDIN_3_0 const char *BF_options(void);
#endif
void BF_encrypt(BF_LONG *data, const BF_KEY *key);
void BF_decrypt(BF_LONG *data, const BF_KEY *key);
void BF_ecb_encrypt(const unsigned char *in, unsigned char *out,
const BF_KEY *key, int enc);
void BF_cbc_encrypt(const unsigned char *in, unsigned char *out, long length,
const BF_KEY *schedule, unsigned char *ivec, int enc);
void BF_cfb64_encrypt(const unsigned char *in, unsigned char *out,
long length, const BF_KEY *schedule,
unsigned char *ivec, int *num, int enc);
void BF_ofb64_encrypt(const unsigned char *in, unsigned char *out,
long length, const BF_KEY *schedule,
unsigned char *ivec, int *num);
const char *BF_options(void);
# ifdef __cplusplus
#ifdef __cplusplus
}
# endif
# endif
#endif
#endif
#endif
@@ -1,56 +1,62 @@
/*
* Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 1995-2026 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
* Licensed under the OpenSSL license (the "License"). You may not use
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef HEADER_BN_H
# define HEADER_BN_H
#ifndef OPENSSL_BN_H
#define OPENSSL_BN_H
#pragma once
# include <openssl/e_os2.h>
# ifndef OPENSSL_NO_STDIO
# include <stdio.h>
# endif
# include <openssl/opensslconf.h>
# include <openssl/ossl_typ.h>
# include <openssl/crypto.h>
# include <openssl/bnerr.h>
#include <openssl/macros.h>
#ifndef OPENSSL_NO_DEPRECATED_3_0
#define HEADER_BN_H
#endif
#ifdef __cplusplus
#include <openssl/e_os2.h>
#ifndef OPENSSL_NO_STDIO
#include <stdio.h>
#endif
#include <openssl/opensslconf.h>
#include <openssl/types.h>
#include <openssl/crypto.h>
#include <openssl/bnerr.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* 64-bit processor with LP64 ABI
*/
# ifdef SIXTY_FOUR_BIT_LONG
# define BN_ULONG unsigned long
# define BN_BYTES 8
# endif
#ifdef SIXTY_FOUR_BIT_LONG
typedef unsigned long BN_ULONG;
#define BN_BYTES 8
#endif
/*
* 64-bit processor other than LP64 ABI
*/
# ifdef SIXTY_FOUR_BIT
# define BN_ULONG unsigned long long
# define BN_BYTES 8
# endif
#ifdef SIXTY_FOUR_BIT
typedef unsigned long long BN_ULONG;
#define BN_BYTES 8
#endif
# ifdef THIRTY_TWO_BIT
# define BN_ULONG unsigned int
# define BN_BYTES 4
# endif
#ifdef THIRTY_TWO_BIT
typedef unsigned int BN_ULONG;
#define BN_BYTES 4
#endif
# define BN_BITS2 (BN_BYTES * 8)
# define BN_BITS (BN_BITS2 * 2)
# define BN_TBIT ((BN_ULONG)1 << (BN_BITS2 - 1))
#define BN_BITS2 (BN_BYTES * 8)
#define BN_BITS (BN_BITS2 * 2)
#define BN_TBIT ((BN_ULONG)1 << (BN_BITS2 - 1))
# define BN_FLG_MALLOCED 0x01
# define BN_FLG_STATIC_DATA 0x02
#define BN_FLG_MALLOCED 0x01
#define BN_FLG_STATIC_DATA 0x02
/*
* avoid leaking exponent information through timing,
@@ -58,26 +64,26 @@ extern "C" {
* BN_div() will call BN_div_no_branch,
* BN_mod_inverse() will call bn_mod_inverse_no_branch.
*/
# define BN_FLG_CONSTTIME 0x04
# define BN_FLG_SECURE 0x08
#define BN_FLG_CONSTTIME 0x04
#define BN_FLG_SECURE 0x08
# if OPENSSL_API_COMPAT < 0x00908000L
#ifndef OPENSSL_NO_DEPRECATED_0_9_8
/* deprecated name for the flag */
# define BN_FLG_EXP_CONSTTIME BN_FLG_CONSTTIME
# define BN_FLG_FREE 0x8000 /* used for debugging */
# endif
#define BN_FLG_EXP_CONSTTIME BN_FLG_CONSTTIME
#define BN_FLG_FREE 0x8000 /* used for debugging */
#endif
void BN_set_flags(BIGNUM *b, int n);
int BN_get_flags(const BIGNUM *b, int n);
/* Values for |top| in BN_rand() */
#define BN_RAND_TOP_ANY -1
#define BN_RAND_TOP_ONE 0
#define BN_RAND_TOP_TWO 1
#define BN_RAND_TOP_ANY -1
#define BN_RAND_TOP_ONE 0
#define BN_RAND_TOP_TWO 1
/* Values for |bottom| in BN_rand() */
#define BN_RAND_BOTTOM_ANY 0
#define BN_RAND_BOTTOM_ODD 1
#define BN_RAND_BOTTOM_ANY 0
#define BN_RAND_BOTTOM_ODD 1
/*
* get a clone of a BIGNUM with changed flags, for *temporary* use only (the
@@ -94,17 +100,18 @@ BN_GENCB *BN_GENCB_new(void);
void BN_GENCB_free(BN_GENCB *cb);
/* Populate a BN_GENCB structure with an "old"-style callback */
void BN_GENCB_set_old(BN_GENCB *gencb, void (*callback) (int, int, void *),
void *cb_arg);
void BN_GENCB_set_old(BN_GENCB *gencb, void (*callback)(int, int, void *),
void *cb_arg);
/* Populate a BN_GENCB structure with a "new"-style callback */
void BN_GENCB_set(BN_GENCB *gencb, int (*callback) (int, int, BN_GENCB *),
void *cb_arg);
void BN_GENCB_set(BN_GENCB *gencb, int (*callback)(int, int, BN_GENCB *),
void *cb_arg);
void *BN_GENCB_get_arg(BN_GENCB *cb);
# define BN_prime_checks 0 /* default: select number of iterations based
* on the size of the number */
#ifndef OPENSSL_NO_DEPRECATED_3_0
#define BN_prime_checks 0 /* default: select number of iterations based \
* on the size of the number */
/*
* BN_prime_checks_for_size() returns the number of Miller-Rabin iterations
@@ -169,16 +176,16 @@ void *BN_GENCB_get_arg(BN_GENCB *cb);
* (b) >= 6 | >= 12 | 34 | 64 bit
*/
# define BN_prime_checks_for_size(b) ((b) >= 3747 ? 3 : \
(b) >= 1345 ? 4 : \
(b) >= 476 ? 5 : \
(b) >= 400 ? 6 : \
(b) >= 347 ? 7 : \
(b) >= 308 ? 8 : \
(b) >= 55 ? 27 : \
/* b >= 6 */ 34)
#define BN_prime_checks_for_size(b) ((b) >= 3747 ? 3 : (b) >= 1345 ? 4 \
: (b) >= 476 ? 5 \
: (b) >= 400 ? 6 \
: (b) >= 347 ? 7 \
: (b) >= 308 ? 8 \
: (b) >= 55 ? 27 \
: /* b >= 6 */ 34)
#endif
# define BN_num_bytes(a) ((BN_num_bits(a)+7)/8)
#define BN_num_bytes(a) ((BN_num_bits(a) + 7) / 8)
int BN_abs_is_word(const BIGNUM *a, const BN_ULONG w);
int BN_is_zero(const BIGNUM *a);
@@ -186,30 +193,44 @@ int BN_is_one(const BIGNUM *a);
int BN_is_word(const BIGNUM *a, const BN_ULONG w);
int BN_is_odd(const BIGNUM *a);
# define BN_one(a) (BN_set_word((a),1))
#define BN_one(a) (BN_set_word((a), 1))
void BN_zero_ex(BIGNUM *a);
# if OPENSSL_API_COMPAT >= 0x00908000L
# define BN_zero(a) BN_zero_ex(a)
# else
# define BN_zero(a) (BN_set_word((a),0))
# endif
#if OPENSSL_API_LEVEL > 908
#define BN_zero(a) BN_zero_ex(a)
#else
#define BN_zero(a) (BN_set_word((a), 0))
#endif
const BIGNUM *BN_value_one(void);
char *BN_options(void);
BN_CTX *BN_CTX_new_ex(OSSL_LIB_CTX *ctx);
BN_CTX *BN_CTX_new(void);
BN_CTX *BN_CTX_secure_new_ex(OSSL_LIB_CTX *ctx);
BN_CTX *BN_CTX_secure_new(void);
void BN_CTX_free(BN_CTX *c);
void BN_CTX_start(BN_CTX *ctx);
BIGNUM *BN_CTX_get(BN_CTX *ctx);
void BN_CTX_end(BN_CTX *ctx);
int BN_rand_ex(BIGNUM *rnd, int bits, int top, int bottom,
unsigned int strength, BN_CTX *ctx);
int BN_rand(BIGNUM *rnd, int bits, int top, int bottom);
int BN_priv_rand_ex(BIGNUM *rnd, int bits, int top, int bottom,
unsigned int strength, BN_CTX *ctx);
int BN_priv_rand(BIGNUM *rnd, int bits, int top, int bottom);
int BN_rand_range_ex(BIGNUM *r, const BIGNUM *range, unsigned int strength,
BN_CTX *ctx);
int BN_rand_range(BIGNUM *rnd, const BIGNUM *range);
int BN_priv_rand_range_ex(BIGNUM *r, const BIGNUM *range,
unsigned int strength, BN_CTX *ctx);
int BN_priv_rand_range(BIGNUM *rnd, const BIGNUM *range);
#ifndef OPENSSL_NO_DEPRECATED_3_0
OSSL_DEPRECATEDIN_3_0
int BN_pseudo_rand(BIGNUM *rnd, int bits, int top, int bottom);
OSSL_DEPRECATEDIN_3_0
int BN_pseudo_rand_range(BIGNUM *rnd, const BIGNUM *range);
#endif
int BN_num_bits(const BIGNUM *a);
int BN_num_bits_word(BN_ULONG l);
int BN_security_bits(int L, int N);
@@ -219,10 +240,18 @@ void BN_clear_free(BIGNUM *a);
BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b);
void BN_swap(BIGNUM *a, BIGNUM *b);
BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret);
BIGNUM *BN_signed_bin2bn(const unsigned char *s, int len, BIGNUM *ret);
int BN_bn2bin(const BIGNUM *a, unsigned char *to);
int BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen);
int BN_signed_bn2bin(const BIGNUM *a, unsigned char *to, int tolen);
BIGNUM *BN_lebin2bn(const unsigned char *s, int len, BIGNUM *ret);
BIGNUM *BN_signed_lebin2bn(const unsigned char *s, int len, BIGNUM *ret);
int BN_bn2lebinpad(const BIGNUM *a, unsigned char *to, int tolen);
int BN_signed_bn2lebin(const BIGNUM *a, unsigned char *to, int tolen);
BIGNUM *BN_native2bn(const unsigned char *s, int len, BIGNUM *ret);
BIGNUM *BN_signed_native2bn(const unsigned char *s, int len, BIGNUM *ret);
int BN_bn2nativepad(const BIGNUM *a, unsigned char *to, int tolen);
int BN_signed_bn2native(const BIGNUM *a, unsigned char *to, int tolen);
BIGNUM *BN_mpi2bn(const unsigned char *s, int len, BIGNUM *ret);
int BN_bn2mpi(const BIGNUM *a, unsigned char *to);
int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
@@ -243,24 +272,24 @@ void BN_set_negative(BIGNUM *b, int n);
int BN_is_negative(const BIGNUM *b);
int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, const BIGNUM *d,
BN_CTX *ctx);
# define BN_mod(rem,m,d,ctx) BN_div(NULL,(rem),(m),(d),(ctx))
int BN_nnmod(BIGNUM *r, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx);
BN_CTX *ctx);
#define BN_mod(rem, a, m, ctx) BN_div(NULL, (rem), (a), (m), (ctx))
int BN_nnmod(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx);
int BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
BN_CTX *ctx);
BN_CTX *ctx);
int BN_mod_add_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
const BIGNUM *m);
const BIGNUM *m);
int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
BN_CTX *ctx);
BN_CTX *ctx);
int BN_mod_sub_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
const BIGNUM *m);
const BIGNUM *m);
int BN_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
BN_CTX *ctx);
BN_CTX *ctx);
int BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx);
int BN_mod_lshift1(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx);
int BN_mod_lshift1_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *m);
int BN_mod_lshift(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m,
BN_CTX *ctx);
BN_CTX *ctx);
int BN_mod_lshift_quick(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m);
BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w);
@@ -279,24 +308,29 @@ int BN_lshift1(BIGNUM *r, const BIGNUM *a);
int BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx);
int BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx);
const BIGNUM *m, BN_CTX *ctx);
int BN_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx,
BN_MONT_CTX *in_mont);
const BIGNUM *m, BN_CTX *ctx,
BN_MONT_CTX *in_mont);
int BN_mod_exp_mont_word(BIGNUM *r, BN_ULONG a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
int BN_mod_exp2_mont(BIGNUM *r, const BIGNUM *a1, const BIGNUM *p1,
const BIGNUM *a2, const BIGNUM *p2, const BIGNUM *m,
BN_CTX *ctx, BN_MONT_CTX *m_ctx);
const BIGNUM *a2, const BIGNUM *p2, const BIGNUM *m,
BN_CTX *ctx, BN_MONT_CTX *m_ctx);
int BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx);
const BIGNUM *m, BN_CTX *ctx);
int BN_mod_exp_mont_consttime_x2(BIGNUM *rr1, const BIGNUM *a1, const BIGNUM *p1,
const BIGNUM *m1, BN_MONT_CTX *in_mont1,
BIGNUM *rr2, const BIGNUM *a2, const BIGNUM *p2,
const BIGNUM *m2, BN_MONT_CTX *in_mont2,
BN_CTX *ctx);
int BN_mask_bits(BIGNUM *a, int n);
# ifndef OPENSSL_NO_STDIO
#ifndef OPENSSL_NO_STDIO
int BN_print_fp(FILE *fp, const BIGNUM *a);
# endif
#endif
int BN_print(BIO *bio, const BIGNUM *a);
int BN_reciprocal(BIGNUM *r, const BIGNUM *m, int len, BN_CTX *ctx);
int BN_rshift(BIGNUM *r, const BIGNUM *a, int n);
@@ -315,63 +349,77 @@ int BN_gcd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
int BN_kronecker(const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); /* returns
* -2 for
* error */
int BN_are_coprime(BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
BIGNUM *BN_mod_inverse(BIGNUM *ret,
const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx);
const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx);
BIGNUM *BN_mod_sqrt(BIGNUM *ret,
const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx);
const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx);
void BN_consttime_swap(BN_ULONG swap, BIGNUM *a, BIGNUM *b, int nwords);
/* Deprecated versions */
DEPRECATEDIN_0_9_8(BIGNUM *BN_generate_prime(BIGNUM *ret, int bits, int safe,
const BIGNUM *add,
const BIGNUM *rem,
void (*callback) (int, int,
void *),
void *cb_arg))
DEPRECATEDIN_0_9_8(int
BN_is_prime(const BIGNUM *p, int nchecks,
void (*callback) (int, int, void *),
BN_CTX *ctx, void *cb_arg))
DEPRECATEDIN_0_9_8(int
BN_is_prime_fasttest(const BIGNUM *p, int nchecks,
void (*callback) (int, int, void *),
BN_CTX *ctx, void *cb_arg,
int do_trial_division))
/* Newer versions */
int BN_generate_prime_ex(BIGNUM *ret, int bits, int safe, const BIGNUM *add,
const BIGNUM *rem, BN_GENCB *cb);
#ifndef OPENSSL_NO_DEPRECATED_0_9_8
OSSL_DEPRECATEDIN_0_9_8
BIGNUM *BN_generate_prime(BIGNUM *ret, int bits, int safe,
const BIGNUM *add, const BIGNUM *rem,
void (*callback)(int, int, void *),
void *cb_arg);
OSSL_DEPRECATEDIN_0_9_8
int BN_is_prime(const BIGNUM *p, int nchecks,
void (*callback)(int, int, void *),
BN_CTX *ctx, void *cb_arg);
OSSL_DEPRECATEDIN_0_9_8
int BN_is_prime_fasttest(const BIGNUM *p, int nchecks,
void (*callback)(int, int, void *),
BN_CTX *ctx, void *cb_arg,
int do_trial_division);
#endif
#ifndef OPENSSL_NO_DEPRECATED_3_0
OSSL_DEPRECATEDIN_3_0
int BN_is_prime_ex(const BIGNUM *p, int nchecks, BN_CTX *ctx, BN_GENCB *cb);
OSSL_DEPRECATEDIN_3_0
int BN_is_prime_fasttest_ex(const BIGNUM *p, int nchecks, BN_CTX *ctx,
int do_trial_division, BN_GENCB *cb);
int do_trial_division, BN_GENCB *cb);
#endif
/* Newer versions */
int BN_generate_prime_ex2(BIGNUM *ret, int bits, int safe,
const BIGNUM *add, const BIGNUM *rem, BN_GENCB *cb,
BN_CTX *ctx);
int BN_generate_prime_ex(BIGNUM *ret, int bits, int safe, const BIGNUM *add,
const BIGNUM *rem, BN_GENCB *cb);
int BN_check_prime(const BIGNUM *p, BN_CTX *ctx, BN_GENCB *cb);
#ifndef OPENSSL_NO_DEPRECATED_3_0
OSSL_DEPRECATEDIN_3_0
int BN_X931_generate_Xpq(BIGNUM *Xp, BIGNUM *Xq, int nbits, BN_CTX *ctx);
OSSL_DEPRECATEDIN_3_0
int BN_X931_derive_prime_ex(BIGNUM *p, BIGNUM *p1, BIGNUM *p2,
const BIGNUM *Xp, const BIGNUM *Xp1,
const BIGNUM *Xp2, const BIGNUM *e, BN_CTX *ctx,
BN_GENCB *cb);
const BIGNUM *Xp, const BIGNUM *Xp1,
const BIGNUM *Xp2, const BIGNUM *e, BN_CTX *ctx,
BN_GENCB *cb);
OSSL_DEPRECATEDIN_3_0
int BN_X931_generate_prime_ex(BIGNUM *p, BIGNUM *p1, BIGNUM *p2, BIGNUM *Xp1,
BIGNUM *Xp2, const BIGNUM *Xp, const BIGNUM *e,
BN_CTX *ctx, BN_GENCB *cb);
BIGNUM *Xp2, const BIGNUM *Xp, const BIGNUM *e,
BN_CTX *ctx, BN_GENCB *cb);
#endif
BN_MONT_CTX *BN_MONT_CTX_new(void);
int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
BN_MONT_CTX *mont, BN_CTX *ctx);
BN_MONT_CTX *mont, BN_CTX *ctx);
int BN_to_montgomery(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont,
BN_CTX *ctx);
BN_CTX *ctx);
int BN_from_montgomery(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont,
BN_CTX *ctx);
BN_CTX *ctx);
void BN_MONT_CTX_free(BN_MONT_CTX *mont);
int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx);
BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to, BN_MONT_CTX *from);
BN_MONT_CTX *BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, CRYPTO_RWLOCK *lock,
const BIGNUM *mod, BN_CTX *ctx);
const BIGNUM *mod, BN_CTX *ctx);
/* BN_BLINDING flags */
# define BN_BLINDING_NO_UPDATE 0x00000001
# define BN_BLINDING_NO_RECREATE 0x00000002
#define BN_BLINDING_NO_UPDATE 0x00000001
#define BN_BLINDING_NO_RECREATE 0x00000002
BN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, BIGNUM *mod);
void BN_BLINDING_free(BN_BLINDING *b);
@@ -380,7 +428,7 @@ int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx);
int BN_BLINDING_invert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx);
int BN_BLINDING_convert_ex(BIGNUM *n, BIGNUM *r, BN_BLINDING *b, BN_CTX *);
int BN_BLINDING_invert_ex(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b,
BN_CTX *);
BN_CTX *);
int BN_BLINDING_is_current_thread(BN_BLINDING *b);
void BN_BLINDING_set_current_thread(BN_BLINDING *b);
@@ -390,30 +438,32 @@ int BN_BLINDING_unlock(BN_BLINDING *b);
unsigned long BN_BLINDING_get_flags(const BN_BLINDING *);
void BN_BLINDING_set_flags(BN_BLINDING *, unsigned long);
BN_BLINDING *BN_BLINDING_create_param(BN_BLINDING *b,
const BIGNUM *e, BIGNUM *m, BN_CTX *ctx,
int (*bn_mod_exp) (BIGNUM *r,
const BIGNUM *a,
const BIGNUM *p,
const BIGNUM *m,
BN_CTX *ctx,
BN_MONT_CTX *m_ctx),
BN_MONT_CTX *m_ctx);
DEPRECATEDIN_0_9_8(void BN_set_params(int mul, int high, int low, int mont))
DEPRECATEDIN_0_9_8(int BN_get_params(int which)) /* 0, mul, 1 high, 2 low, 3
* mont */
const BIGNUM *e, BIGNUM *m, BN_CTX *ctx,
int (*bn_mod_exp)(BIGNUM *r,
const BIGNUM *a,
const BIGNUM *p,
const BIGNUM *m,
BN_CTX *ctx,
BN_MONT_CTX *m_ctx),
BN_MONT_CTX *m_ctx);
#ifndef OPENSSL_NO_DEPRECATED_0_9_8
OSSL_DEPRECATEDIN_0_9_8
void BN_set_params(int mul, int high, int low, int mont);
OSSL_DEPRECATEDIN_0_9_8
int BN_get_params(int which); /* 0, mul, 1 high, 2 low, 3 mont */
#endif
BN_RECP_CTX *BN_RECP_CTX_new(void);
void BN_RECP_CTX_free(BN_RECP_CTX *recp);
int BN_RECP_CTX_set(BN_RECP_CTX *recp, const BIGNUM *rdiv, BN_CTX *ctx);
int BN_mod_mul_reciprocal(BIGNUM *r, const BIGNUM *x, const BIGNUM *y,
BN_RECP_CTX *recp, BN_CTX *ctx);
BN_RECP_CTX *recp, BN_CTX *ctx);
int BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx);
const BIGNUM *m, BN_CTX *ctx);
int BN_div_recp(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m,
BN_RECP_CTX *recp, BN_CTX *ctx);
BN_RECP_CTX *recp, BN_CTX *ctx);
# ifndef OPENSSL_NO_EC2M
#ifndef OPENSSL_NO_EC2M
/*
* Functions for arithmetic over binary polynomials represented by BIGNUMs.
@@ -426,31 +476,31 @@ int BN_div_recp(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m,
* r = a + b
*/
int BN_GF2m_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
# define BN_GF2m_sub(r, a, b) BN_GF2m_add(r, a, b)
#define BN_GF2m_sub(r, a, b) BN_GF2m_add(r, a, b)
/*
* r=a mod p
*/
int BN_GF2m_mod(BIGNUM *r, const BIGNUM *a, const BIGNUM *p);
/* r = (a * b) mod p */
int BN_GF2m_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
const BIGNUM *p, BN_CTX *ctx);
const BIGNUM *p, BN_CTX *ctx);
/* r = (a * a) mod p */
int BN_GF2m_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx);
/* r = (1 / b) mod p */
int BN_GF2m_mod_inv(BIGNUM *r, const BIGNUM *b, const BIGNUM *p, BN_CTX *ctx);
/* r = (a / b) mod p */
int BN_GF2m_mod_div(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
const BIGNUM *p, BN_CTX *ctx);
const BIGNUM *p, BN_CTX *ctx);
/* r = (a ^ b) mod p */
int BN_GF2m_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
const BIGNUM *p, BN_CTX *ctx);
const BIGNUM *p, BN_CTX *ctx);
/* r = sqrt(a) mod p */
int BN_GF2m_mod_sqrt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
BN_CTX *ctx);
BN_CTX *ctx);
/* r^2 + r = a mod p */
int BN_GF2m_mod_solve_quad(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
BN_CTX *ctx);
# define BN_GF2m_cmp(a, b) BN_ucmp((a), (b))
BN_CTX *ctx);
#define BN_GF2m_cmp(a, b) BN_ucmp((a), (b))
/*-
* Some functions allow for representation of the irreducible polynomials
* as an unsigned int[], say p. The irreducible f(t) is then of the form:
@@ -461,29 +511,29 @@ int BN_GF2m_mod_solve_quad(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
int BN_GF2m_mod_arr(BIGNUM *r, const BIGNUM *a, const int p[]);
/* r = (a * b) mod p */
int BN_GF2m_mod_mul_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
const int p[], BN_CTX *ctx);
const int p[], BN_CTX *ctx);
/* r = (a * a) mod p */
int BN_GF2m_mod_sqr_arr(BIGNUM *r, const BIGNUM *a, const int p[],
BN_CTX *ctx);
BN_CTX *ctx);
/* r = (1 / b) mod p */
int BN_GF2m_mod_inv_arr(BIGNUM *r, const BIGNUM *b, const int p[],
BN_CTX *ctx);
BN_CTX *ctx);
/* r = (a / b) mod p */
int BN_GF2m_mod_div_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
const int p[], BN_CTX *ctx);
const int p[], BN_CTX *ctx);
/* r = (a ^ b) mod p */
int BN_GF2m_mod_exp_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
const int p[], BN_CTX *ctx);
const int p[], BN_CTX *ctx);
/* r = sqrt(a) mod p */
int BN_GF2m_mod_sqrt_arr(BIGNUM *r, const BIGNUM *a,
const int p[], BN_CTX *ctx);
const int p[], BN_CTX *ctx);
/* r^2 + r = a mod p */
int BN_GF2m_mod_solve_quad_arr(BIGNUM *r, const BIGNUM *a,
const int p[], BN_CTX *ctx);
const int p[], BN_CTX *ctx);
int BN_GF2m_poly2arr(const BIGNUM *a, int p[], int max);
int BN_GF2m_arr2poly(const int p[], BIGNUM *a);
# endif
#endif
/*
* faster mod functions for the 'NIST primes' 0 <= a < p^2
@@ -500,12 +550,12 @@ const BIGNUM *BN_get0_nist_prime_256(void);
const BIGNUM *BN_get0_nist_prime_384(void);
const BIGNUM *BN_get0_nist_prime_521(void);
int (*BN_nist_mod_func(const BIGNUM *p)) (BIGNUM *r, const BIGNUM *a,
const BIGNUM *field, BN_CTX *ctx);
int (*BN_nist_mod_func(const BIGNUM *p))(BIGNUM *r, const BIGNUM *a,
const BIGNUM *field, BN_CTX *ctx);
int BN_generate_dsa_nonce(BIGNUM *out, const BIGNUM *range,
const BIGNUM *priv, const unsigned char *message,
size_t message_len, BN_CTX *ctx);
const BIGNUM *priv, const unsigned char *message,
size_t message_len, BN_CTX *ctx);
/* Primes from RFC 2409 */
BIGNUM *BN_get_rfc2409_prime_768(BIGNUM *bn);
@@ -519,21 +569,20 @@ BIGNUM *BN_get_rfc3526_prime_4096(BIGNUM *bn);
BIGNUM *BN_get_rfc3526_prime_6144(BIGNUM *bn);
BIGNUM *BN_get_rfc3526_prime_8192(BIGNUM *bn);
# if OPENSSL_API_COMPAT < 0x10100000L
# define get_rfc2409_prime_768 BN_get_rfc2409_prime_768
# define get_rfc2409_prime_1024 BN_get_rfc2409_prime_1024
# define get_rfc3526_prime_1536 BN_get_rfc3526_prime_1536
# define get_rfc3526_prime_2048 BN_get_rfc3526_prime_2048
# define get_rfc3526_prime_3072 BN_get_rfc3526_prime_3072
# define get_rfc3526_prime_4096 BN_get_rfc3526_prime_4096
# define get_rfc3526_prime_6144 BN_get_rfc3526_prime_6144
# define get_rfc3526_prime_8192 BN_get_rfc3526_prime_8192
# endif
#ifndef OPENSSL_NO_DEPRECATED_1_1_0
#define get_rfc2409_prime_768 BN_get_rfc2409_prime_768
#define get_rfc2409_prime_1024 BN_get_rfc2409_prime_1024
#define get_rfc3526_prime_1536 BN_get_rfc3526_prime_1536
#define get_rfc3526_prime_2048 BN_get_rfc3526_prime_2048
#define get_rfc3526_prime_3072 BN_get_rfc3526_prime_3072
#define get_rfc3526_prime_4096 BN_get_rfc3526_prime_4096
#define get_rfc3526_prime_6144 BN_get_rfc3526_prime_6144
#define get_rfc3526_prime_8192 BN_get_rfc3526_prime_8192
#endif
int BN_bntest_rand(BIGNUM *rnd, int bits, int top, int bottom);
# ifdef __cplusplus
#ifdef __cplusplus
}
# endif
#endif
#endif

Some files were not shown because too many files have changed in this diff Show More