mirror of
https://github.com/moonlight-stream/moonlight-android.git
synced 2026-10-19 23:14:23 +00:00
Compare commits
360
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b48494cb96 | ||
|
|
98c12bebff | ||
|
|
801dba1ba8 | ||
|
|
4eb24a8d7b | ||
|
|
5c0c2390b2 | ||
|
|
b55b4b6d68 | ||
|
|
4dc95b563c | ||
|
|
31b700304a | ||
|
|
ddb674a9b9 | ||
|
|
abde6021e8 | ||
|
|
ad8614907c | ||
|
|
8974dcda6e | ||
|
|
6d4c64a575 | ||
|
|
68adf9ecc9 | ||
|
|
3df0103a8c | ||
|
|
8d720748c1 | ||
|
|
578f38f6a5 | ||
|
|
280454fdb0 | ||
|
|
0711e236c0 | ||
|
|
b9c5edddef | ||
|
|
3c6a0d12f5 | ||
|
|
583f662a87 | ||
|
|
3f114ac76c | ||
|
|
4b2221d374 | ||
|
|
c2e224ebf8 | ||
|
|
0dc4c4fe67 | ||
|
|
9221a0ca3a | ||
|
|
b3a7e32a08 | ||
|
|
1fa0e2a0f9 | ||
|
|
9d8b073ca5 | ||
|
|
03bdf30d0a | ||
|
|
6e15cc5fa3 | ||
|
|
9d26550264 | ||
|
|
7ffde1e8fc | ||
|
|
30d234d71e | ||
|
|
a75104f13d | ||
|
|
73d3180d20 | ||
|
|
f51be309a0 | ||
|
|
a7a424cf27 | ||
|
|
19dc67eb47 | ||
|
|
9869f3125f | ||
|
|
8a8efc0dcf | ||
|
|
54e1f2a124 | ||
|
|
f827e96e1a | ||
|
|
5835fb832c | ||
|
|
9484275ab6 | ||
|
|
2a0ccb88bb | ||
|
|
d3eb327f63 | ||
|
|
c122bcd45b | ||
|
|
16b6cf6edb | ||
|
|
325bc3349e | ||
|
|
7416477763 | ||
|
|
bcd8c8f77d | ||
|
|
d44432ed81 | ||
|
|
d46f5d4353 | ||
|
|
27ded2add8 | ||
|
|
9b0bfaf079 | ||
|
|
522d61d7e2 | ||
|
|
8550e99463 | ||
|
|
2f6deb72b3 | ||
|
|
10941746e4 | ||
|
|
4827b0e6de | ||
|
|
f10085f552 | ||
|
|
eb7f0887bf | ||
|
|
34a9132d60 | ||
|
|
24d3fb000a | ||
|
|
b7b6adaff7 | ||
|
|
85ed72802f | ||
|
|
e1fcb19b23 | ||
|
|
2df69bcdea | ||
|
|
454b443b81 | ||
|
|
f97704764a | ||
|
|
9ef23038ab | ||
|
|
e48c38f47a | ||
|
|
cf64d102de | ||
|
|
2716c68c7a | ||
|
|
f54f8c83e7 | ||
|
|
124bfdf418 | ||
|
|
01507d9995 | ||
|
|
070c82bc44 | ||
|
|
17df15293f | ||
|
|
6551076613 | ||
|
|
1b1b100e63 | ||
|
|
d73b9e16da | ||
|
|
cc788e4410 | ||
|
|
e70014bb28 | ||
|
|
082cc84a71 | ||
|
|
2ba7f0d989 | ||
|
|
9a7381b35f | ||
|
|
613ecfff44 | ||
|
|
f638548a02 | ||
|
|
224bab68bf | ||
|
|
6aca18bd76 | ||
|
|
3c58e2fbba | ||
|
|
aaaebde05e | ||
|
|
8ff9f70bd7 | ||
|
|
523ca862b9 | ||
|
|
78b8d1e9f3 | ||
|
|
83c698b36d | ||
|
|
27fe37f221 | ||
|
|
3722106daf | ||
|
|
3ea9ef1ef2 | ||
|
|
fcd27b48b2 | ||
|
|
6ff37a17ec | ||
|
|
f2c6e9e32e | ||
|
|
dbf1b88a3d | ||
|
|
3aab9eb13b | ||
|
|
3f9f8f7b3b | ||
|
|
f7520ba40c | ||
|
|
7b13f12817 | ||
|
|
57e19d75e2 | ||
|
|
4330a223c6 | ||
|
|
69387c32ad | ||
|
|
a102ec4ee8 | ||
|
|
2a094437dd | ||
|
|
4142907376 | ||
|
|
e63dc9a93b | ||
|
|
1fe19e912e | ||
|
|
56ad48446e | ||
|
|
a18aa26985 | ||
|
|
5443cc014a | ||
|
|
7d77e1c1f2 | ||
|
|
ca82cd9752 | ||
|
|
dbd86bb861 | ||
|
|
0af56b4981 | ||
|
|
f1be5365bb | ||
|
|
c356862ac1 | ||
|
|
fc77322f59 | ||
|
|
032e944d49 | ||
|
|
0da47da8d8 | ||
|
|
ebfe843299 | ||
|
|
827d2362b7 | ||
|
|
4fa1eb4088 | ||
|
|
885b59fd52 | ||
|
|
ff5d9f72aa | ||
|
|
030bb91789 | ||
|
|
34788b2808 | ||
|
|
abc4123c52 | ||
|
|
26f8c0842e | ||
|
|
d430d83ba8 | ||
|
|
a52f189fb1 | ||
|
|
dc1045b69e | ||
|
|
3a89dbf4ab | ||
|
|
d69b4eca1e | ||
|
|
568bba82f0 | ||
|
|
b52e6c88ec | ||
|
|
720595091e | ||
|
|
fe929c8e58 | ||
|
|
9ecec1eb3c | ||
|
|
79532f6f14 | ||
|
|
b400ba385e | ||
|
|
9915007f30 | ||
|
|
0168a55596 | ||
|
|
229eff49fb | ||
|
|
0e3b472f78 | ||
|
|
5f29b30d34 | ||
|
|
9480363362 | ||
|
|
5dd80edde4 | ||
|
|
2243cf2017 | ||
|
|
d7791c8543 | ||
|
|
30822c1ba5 | ||
|
|
d250f4dc60 | ||
|
|
bc27492206 | ||
|
|
2b63203a5b | ||
|
|
dc9a26f57b | ||
|
|
6f2d7464ba | ||
|
|
6996c101b4 | ||
|
|
99dc773c7a | ||
|
|
6ec3f9455a | ||
|
|
6589a568e2 | ||
|
|
55da48e28c | ||
|
|
081cca48fb | ||
|
|
6b6a93725c | ||
|
|
c280a52d33 | ||
|
|
b659439f0b | ||
|
|
6453b3c45c | ||
|
|
978a879c43 | ||
|
|
833ef3630b | ||
|
|
024b8c93bc | ||
|
|
d32c4f86a7 | ||
|
|
cafc4450b2 | ||
|
|
7d69b53958 | ||
|
|
4d3e883e49 | ||
|
|
8f9a687872 | ||
|
|
08d509d831 | ||
|
|
b06dec8449 | ||
|
|
28c93b934b | ||
|
|
394a57a26d | ||
|
|
3856b57a6f | ||
|
|
9a3a076890 | ||
|
|
314dfcddcf | ||
|
|
1a85bda997 | ||
|
|
e8b30d5a88 | ||
|
|
96bd1a7799 | ||
|
|
cb0a1f13bc | ||
|
|
e92fdeef47 | ||
|
|
62bae62386 | ||
|
|
2636d79b86 | ||
|
|
c9c1ef91fd | ||
|
|
ce7bba3e09 | ||
|
|
bfd53f39bd | ||
|
|
554fee037c | ||
|
|
67b2853ef0 | ||
|
|
0e29e13d03 | ||
|
|
35f2a238e9 | ||
|
|
fcb34ab6ee | ||
|
|
3fbf682785 | ||
|
|
16086a6d3f | ||
|
|
18b6aae381 | ||
|
|
642c353164 | ||
|
|
42f64e5e88 | ||
|
|
6af748b2cc | ||
|
|
4fe97b69c7 | ||
|
|
04d46272dd | ||
|
|
1c0290dc7a | ||
|
|
38588402e3 | ||
|
|
dfe3b8888d | ||
|
|
e8f4022f1e | ||
|
|
e37bb32c82 | ||
|
|
1f72c82acb | ||
|
|
e6876926a4 | ||
|
|
2b8a43ab13 | ||
|
|
8737466368 | ||
|
|
83916fa43e | ||
|
|
1fe5a12a45 | ||
|
|
fa7f3115ed | ||
|
|
4dc6143440 | ||
|
|
f1503aa56c | ||
|
|
67f344b755 | ||
|
|
f1bcc217a9 | ||
|
|
458460515d | ||
|
|
3a78095574 | ||
|
|
d6bbfa1af1 | ||
|
|
4e1b778f31 | ||
|
|
5f4496036c | ||
|
|
d4079940b4 | ||
|
|
803ad116fb | ||
|
|
27701eda49 | ||
|
|
71c831b02d | ||
|
|
0d72a0e009 | ||
|
|
69a4502f90 | ||
|
|
daaa7f4e63 | ||
|
|
d1579e9b0d | ||
|
|
5890fff240 | ||
|
|
d6f6307050 | ||
|
|
6bf9c31860 | ||
|
|
a2e628f3f8 | ||
|
|
8f5416ff31 | ||
|
|
db86f18133 | ||
|
|
419e4e656e | ||
|
|
eed4327d26 | ||
|
|
5c6eaf2602 | ||
|
|
71169ed740 | ||
|
|
dca8d93aa8 | ||
|
|
6cb152f602 | ||
|
|
ddefda3afa | ||
|
|
7f15f45beb | ||
|
|
46f887efec | ||
|
|
90afecd766 | ||
|
|
388343c3ee | ||
|
|
c8df37e89e | ||
|
|
cc85d5c343 | ||
|
|
f8437cdb8f | ||
|
|
c99a210905 | ||
|
|
e33673c9e9 | ||
|
|
79283e93cb | ||
|
|
a60e85a3a4 | ||
|
|
80910ed38d | ||
|
|
825a338474 | ||
|
|
19b6e94824 | ||
|
|
0b581011c5 | ||
|
|
6b7669bb75 | ||
|
|
67bcc56c6d | ||
|
|
7d8cfa3c6a | ||
|
|
f659af29da | ||
|
|
94b202f7b6 | ||
|
|
ca86fdafab | ||
|
|
370dbb1a10 | ||
|
|
f77543cd9b | ||
|
|
7104e0d725 | ||
|
|
230a67cac0 | ||
|
|
a695f38974 | ||
|
|
151c09f098 | ||
|
|
8200f5690d | ||
|
|
77a8cf2704 | ||
|
|
fe424961e1 | ||
|
|
b668cb78ff | ||
|
|
48278419b0 | ||
|
|
632da03667 | ||
|
|
d36b73fc1b | ||
|
|
292ed35555 | ||
|
|
02d0ad496f | ||
|
|
eb2fc7af40 | ||
|
|
6550deedbb | ||
|
|
80acd9b9eb | ||
|
|
b961636f02 | ||
|
|
f4df0714b5 | ||
|
|
91dd7b7049 | ||
|
|
121bef7d2d | ||
|
|
3a9eabf50b | ||
|
|
c8198b4091 | ||
|
|
e4538e4a51 | ||
|
|
b47f3ef397 | ||
|
|
6e096c0ac3 | ||
|
|
ee3b4686bf | ||
|
|
759b77eafe | ||
|
|
de15ec666f | ||
|
|
3de86f15af | ||
|
|
1b9dff719c | ||
|
|
abcf4e3d4a | ||
|
|
9823abe686 | ||
|
|
723e08f69b | ||
|
|
daf0a0891e | ||
|
|
49dc68f77f | ||
|
|
f81a1c36cc | ||
|
|
9a11a771dd | ||
|
|
b56a4b8b49 | ||
|
|
1aa963992b | ||
|
|
1b601324d0 | ||
|
|
1aea723ef0 | ||
|
|
1e828a10b9 | ||
|
|
970423f873 | ||
|
|
2d7493fd1e | ||
|
|
fa7eb1c4b1 | ||
|
|
4916af3697 | ||
|
|
8484bf1cb9 | ||
|
|
005afb3c73 | ||
|
|
84b0d004b9 | ||
|
|
aa41bf8d97 | ||
|
|
fba9a125bf | ||
|
|
27312bd146 | ||
|
|
8f0c267ab8 | ||
|
|
a15d6a6b42 | ||
|
|
8f9061b250 | ||
|
|
ec57499e08 | ||
|
|
381598c5b6 | ||
|
|
452d020da5 | ||
|
|
b5f875c2e5 | ||
|
|
a31daeda96 | ||
|
|
437f52f53a | ||
|
|
33f0f7ecf0 | ||
|
|
6777e79e70 | ||
|
|
16d1e6181b | ||
|
|
a6c8db6c2c | ||
|
|
24aa0fecbe | ||
|
|
1a776b1990 | ||
|
|
27df265c81 | ||
|
|
84c0372719 | ||
|
|
3879e57c4c | ||
|
|
dcc3dcdaba | ||
|
|
d166635c7b | ||
|
|
33d484b7d1 | ||
|
|
26bff28e4d | ||
|
|
56eddff8d6 | ||
|
|
37b9133eb6 | ||
|
|
4a64967b1f | ||
|
|
23152b1264 | ||
|
|
c11338039f | ||
|
|
e712669d32 | ||
|
|
3768ae33b7 |
@@ -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.
|
|
||||||
@@ -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
|
||||||
|
|
||||||
@@ -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
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
[](https://ci.appveyor.com/project/cgutman/moonlight-android/branch/master)
|
[](https://ci.appveyor.com/project/cgutman/moonlight-android/branch/master)
|
||||||
[](https://hosted.weblate.org/projects/moonlight/moonlight-android/)
|
[](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,
|
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.
|
whether in your own home or over the internet.
|
||||||
|
|||||||
+32
-20
@@ -1,16 +1,18 @@
|
|||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
ndkVersion "23.2.8568313"
|
ndkVersion "29.0.14206865"
|
||||||
|
|
||||||
compileSdk 33
|
compileSdk 37
|
||||||
|
|
||||||
|
namespace 'com.limelight'
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdk 16
|
minSdk 21
|
||||||
targetSdk 33
|
targetSdk 36
|
||||||
|
|
||||||
versionName "10.10"
|
versionName "12.2"
|
||||||
versionCode = 298
|
versionCode = 315
|
||||||
|
|
||||||
// Generate native debug symbols to allow Google Play to symbolicate our native crashes
|
// Generate native debug symbols to allow Google Play to symbolicate our native crashes
|
||||||
ndk.debugSymbolLevel = 'FULL'
|
ndk.debugSymbolLevel = 'FULL'
|
||||||
@@ -18,6 +20,11 @@ android {
|
|||||||
|
|
||||||
flavorDimensions.add("root")
|
flavorDimensions.add("root")
|
||||||
|
|
||||||
|
buildFeatures {
|
||||||
|
buildConfig = true
|
||||||
|
resValues = true
|
||||||
|
}
|
||||||
|
|
||||||
productFlavors {
|
productFlavors {
|
||||||
root {
|
root {
|
||||||
// Android O has native mouse capture, so don't show the rooted
|
// Android O has native mouse capture, so don't show the rooted
|
||||||
@@ -50,8 +57,9 @@ android {
|
|||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
encoding "UTF-8"
|
encoding "UTF-8"
|
||||||
sourceCompatibility JavaVersion.VERSION_11
|
sourceCompatibility JavaVersion.VERSION_17
|
||||||
targetCompatibility JavaVersion.VERSION_11
|
targetCompatibility JavaVersion.VERSION_17
|
||||||
|
coreLibraryDesugaringEnabled true
|
||||||
}
|
}
|
||||||
|
|
||||||
lint {
|
lint {
|
||||||
@@ -78,9 +86,6 @@ android {
|
|||||||
applicationIdSuffix ".debug"
|
applicationIdSuffix ".debug"
|
||||||
resValue "string", "app_label", "Moonlight (Debug)"
|
resValue "string", "app_label", "Moonlight (Debug)"
|
||||||
resValue "string", "app_label_root", "Moonlight (Root Debug)"
|
resValue "string", "app_label_root", "Moonlight (Root Debug)"
|
||||||
|
|
||||||
minifyEnabled true
|
|
||||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
|
||||||
}
|
}
|
||||||
release {
|
release {
|
||||||
// To whomever is releasing/using an APK in release mode with
|
// To whomever is releasing/using an APK in release mode with
|
||||||
@@ -118,7 +123,7 @@ android {
|
|||||||
resValue "string", "app_label_root", "Moonlight (Root)"
|
resValue "string", "app_label_root", "Moonlight (Root)"
|
||||||
|
|
||||||
minifyEnabled true
|
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"
|
path "src/main/jni/Android.mk"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
packaging {
|
||||||
|
resources {
|
||||||
|
// BouncyCastle includes duplicate LICENSE.md files
|
||||||
|
excludes += '/META-INF/*.md'
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'org.bouncycastle:bcprov-jdk15on:1.70'
|
implementation 'org.bouncycastle:bcprov-jdk18on:1.85.2'
|
||||||
implementation 'org.bouncycastle:bcpkix-jdk15on:1.70'
|
implementation 'org.bouncycastle:bcpkix-jdk18on:1.85'
|
||||||
implementation 'org.jcodec:jcodec:0.2.3'
|
implementation 'org.jcodec:jcodec:0.2.5'
|
||||||
implementation 'com.squareup.okhttp3:okhttp:3.12.13'
|
implementation 'com.squareup.okhttp3:okhttp:5.5.0'
|
||||||
implementation 'com.squareup.okio:okio:1.17.5'
|
implementation 'org.jmdns:jmdns:3.6.3'
|
||||||
// 3.5.8 requires minSdk 19, uses StandardCharsets.UTF_8 internally
|
implementation 'com.github.cgutman:ShieldControllerExtensions:1.0.1'
|
||||||
implementation 'org.jmdns:jmdns:3.5.7'
|
|
||||||
implementation 'com.github.cgutman:ShieldControllerExtensions:1.0'
|
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.5'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,20 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
package="com.limelight">
|
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
<uses-permission android:name="android.permission.VIBRATE" />
|
<uses-permission android:name="android.permission.VIBRATE" />
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
<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.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.READ_EPG_DATA"/>
|
||||||
<uses-permission android:name="com.android.providers.tv.permission.WRITE_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
|
<uses-feature
|
||||||
android:name="android.hardware.touchscreen"
|
android:name="android.hardware.touchscreen"
|
||||||
android:required="false" />
|
android:required="false" />
|
||||||
@@ -26,6 +30,12 @@
|
|||||||
<uses-feature
|
<uses-feature
|
||||||
android:name="android.software.leanback"
|
android:name="android.software.leanback"
|
||||||
android:required="false" />
|
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 -->
|
<!-- Disable legacy input emulation on ChromeOS -->
|
||||||
<uses-feature
|
<uses-feature
|
||||||
@@ -41,7 +51,6 @@
|
|||||||
android:banner="@drawable/atv_banner"
|
android:banner="@drawable/atv_banner"
|
||||||
android:appCategory="game"
|
android:appCategory="game"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:roundIcon="@mipmap/ic_launcher"
|
|
||||||
android:installLocation="auto"
|
android:installLocation="auto"
|
||||||
android:gwpAsanMode="always"
|
android:gwpAsanMode="always"
|
||||||
android:localeConfig="@xml/locales_config"
|
android:localeConfig="@xml/locales_config"
|
||||||
@@ -69,6 +78,11 @@
|
|||||||
android:name="com.android.graphics.intervention.wm.allowDownscale"
|
android:name="com.android.graphics.intervention.wm.allowDownscale"
|
||||||
android:value="false"/>
|
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"
|
<!-- Samsung DeX support requires explicit placement of android:resizeableActivity="true"
|
||||||
in each activity even though it is implied by targeting API 24+ -->
|
in each activity even though it is implied by targeting API 24+ -->
|
||||||
|
|
||||||
@@ -76,7 +90,12 @@
|
|||||||
android:name=".PcView"
|
android:name=".PcView"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:resizeableActivity="true"
|
android:resizeableActivity="true"
|
||||||
|
android:enableOnBackInvokedCallback="true"
|
||||||
android:configChanges="mcc|mnc|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize|layoutDirection">
|
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>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
@@ -92,37 +111,37 @@
|
|||||||
android:noHistory="true"
|
android:noHistory="true"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:resizeableActivity="true"
|
android:resizeableActivity="true"
|
||||||
|
android:enableOnBackInvokedCallback="true"
|
||||||
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize|layoutDirection">
|
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize|layoutDirection">
|
||||||
<meta-data
|
<meta-data android:name="WindowManagerPreference:FreeformWindowSize" android:value="system-default" />
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
<meta-data android:name="WindowManagerPreference:FreeformWindowOrientation" android:value="landscape" />
|
||||||
android:value="com.limelight.PcView" />
|
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".AppView"
|
android:name=".AppView"
|
||||||
android:resizeableActivity="true"
|
android:resizeableActivity="true"
|
||||||
|
android:enableOnBackInvokedCallback="true"
|
||||||
android:configChanges="mcc|mnc|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize|layoutDirection">
|
android:configChanges="mcc|mnc|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize|layoutDirection">
|
||||||
<meta-data
|
<meta-data android:name="WindowManagerPreference:FreeformWindowSize" android:value="system-default" />
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
<meta-data android:name="WindowManagerPreference:FreeformWindowOrientation" android:value="landscape" />
|
||||||
android:value="com.limelight.PcView" />
|
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".preferences.StreamSettings"
|
android:name=".preferences.StreamSettings"
|
||||||
android:resizeableActivity="true"
|
android:resizeableActivity="true"
|
||||||
|
android:enableOnBackInvokedCallback="true"
|
||||||
android:configChanges="mcc|mnc|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize|layoutDirection"
|
android:configChanges="mcc|mnc|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize|layoutDirection"
|
||||||
android:label="Streaming Settings">
|
android:label="Streaming Settings">
|
||||||
<meta-data
|
<meta-data android:name="WindowManagerPreference:FreeformWindowSize" android:value="system-default" />
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
<meta-data android:name="WindowManagerPreference:FreeformWindowOrientation" android:value="landscape" />
|
||||||
android:value="com.limelight.PcView" />
|
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".preferences.AddComputerManually"
|
android:name=".preferences.AddComputerManually"
|
||||||
android:resizeableActivity="true"
|
android:resizeableActivity="true"
|
||||||
android:windowSoftInputMode="stateVisible"
|
android:windowSoftInputMode="stateVisible"
|
||||||
|
android:enableOnBackInvokedCallback="true"
|
||||||
android:configChanges="mcc|mnc|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize|layoutDirection"
|
android:configChanges="mcc|mnc|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize|layoutDirection"
|
||||||
android:label="Add Computer Manually">
|
android:label="Add Computer Manually">
|
||||||
<meta-data
|
<meta-data android:name="WindowManagerPreference:FreeformWindowSize" android:value="system-default" />
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
<meta-data android:name="WindowManagerPreference:FreeformWindowOrientation" android:value="landscape" />
|
||||||
android:value="com.limelight.PcView" />
|
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".Game"
|
android:name=".Game"
|
||||||
@@ -130,13 +149,14 @@
|
|||||||
android:noHistory="true"
|
android:noHistory="true"
|
||||||
android:supportsPictureInPicture="true"
|
android:supportsPictureInPicture="true"
|
||||||
android:resizeableActivity="true"
|
android:resizeableActivity="true"
|
||||||
|
android:enableOnBackInvokedCallback="false"
|
||||||
android:launchMode="singleTask"
|
android:launchMode="singleTask"
|
||||||
android:excludeFromRecents="true"
|
android:excludeFromRecents="true"
|
||||||
android:theme="@style/StreamTheme"
|
android:theme="@style/StreamTheme"
|
||||||
android:preferMinimalPostProcessing="true">
|
android:preferMinimalPostProcessing="true">
|
||||||
<meta-data
|
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
<meta-data android:name="WindowManagerPreference:FreeformWindowSize" android:value="system-default" />
|
||||||
android:value="com.limelight.AppView" />
|
<meta-data android:name="WindowManagerPreference:FreeformWindowOrientation" android:value="landscape" />
|
||||||
|
|
||||||
<!-- Special metadata for NVIDIA Shield devices to prevent input buffering
|
<!-- Special metadata for NVIDIA Shield devices to prevent input buffering
|
||||||
and most importantly, opt out of mouse acceleration while streaming -->
|
and most importantly, opt out of mouse acceleration while streaming -->
|
||||||
@@ -161,10 +181,10 @@
|
|||||||
<activity
|
<activity
|
||||||
android:name=".HelpActivity"
|
android:name=".HelpActivity"
|
||||||
android:resizeableActivity="true"
|
android:resizeableActivity="true"
|
||||||
|
android:enableOnBackInvokedCallback="true"
|
||||||
android:configChanges="mcc|mnc|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize|layoutDirection">
|
android:configChanges="mcc|mnc|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize|layoutDirection">
|
||||||
<meta-data
|
<meta-data android:name="WindowManagerPreference:FreeformWindowSize" android:value="system-default" />
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
<meta-data android:name="WindowManagerPreference:FreeformWindowOrientation" android:value="landscape" />
|
||||||
android:value="com.limelight.PcView" />
|
|
||||||
</activity>
|
</activity>
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -71,12 +71,6 @@ public class HelpActivity extends Activity {
|
|||||||
|
|
||||||
refreshBackDispatchState();
|
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());
|
webView.loadUrl(getIntent().getData().toString());
|
||||||
|
|||||||
@@ -118,6 +118,7 @@ public class PcView extends Activity implements AdapterFragmentCallbacks {
|
|||||||
private final static int VIEW_DETAILS_ID = 8;
|
private final static int VIEW_DETAILS_ID = 8;
|
||||||
private final static int FULL_APP_LIST_ID = 9;
|
private final static int FULL_APP_LIST_ID = 9;
|
||||||
private final static int TEST_NETWORK_ID = 10;
|
private final static int TEST_NETWORK_ID = 10;
|
||||||
|
private final static int GAMESTREAM_EOL_ID = 11;
|
||||||
|
|
||||||
private void initializeViews() {
|
private void initializeViews() {
|
||||||
setContentView(R.layout.activity_pc_view);
|
setContentView(R.layout.activity_pc_view);
|
||||||
@@ -259,6 +260,11 @@ public class PcView extends Activity implements AdapterFragmentCallbacks {
|
|||||||
updateComputer(details);
|
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 ||
|
if (computer.details.state == ComputerDetails.State.OFFLINE ||
|
||||||
computer.details.state == ComputerDetails.State.UNKNOWN) {
|
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, 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) {
|
else if (computer.details.pairState != PairState.PAIRED) {
|
||||||
menu.add(Menu.NONE, PAIR_ID, 1, getResources().getString(R.string.pcview_menu_pair_pc));
|
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 {
|
else {
|
||||||
if (computer.details.runningGameId != 0) {
|
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));
|
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));
|
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
|
// Spin the dialog off in a thread because it blocks
|
||||||
Dialog.displayDialog(PcView.this, getResources().getString(R.string.pair_pairing_title),
|
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();
|
PairingManager pm = httpConn.getPairingManager();
|
||||||
|
|
||||||
@@ -656,6 +671,10 @@ public class PcView extends Activity implements AdapterFragmentCallbacks {
|
|||||||
ServerHelper.doNetworkTest(PcView.this);
|
ServerHelper.doNetworkTest(PcView.this);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
case GAMESTREAM_EOL_ID:
|
||||||
|
HelpLauncher.launchGameStreamEolFaq(PcView.this);
|
||||||
|
return true;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return super.onContextItemSelected(item);
|
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) {
|
if (existingEntry != null) {
|
||||||
// Replace the information in the existing entry
|
// Replace the information in the existing entry
|
||||||
existingEntry.details = details;
|
existingEntry.details = details;
|
||||||
|
|||||||
@@ -8,19 +8,26 @@ import android.content.ServiceConnection;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
|
||||||
|
import com.limelight.computers.ComputerDatabaseManager;
|
||||||
import com.limelight.computers.ComputerManagerListener;
|
import com.limelight.computers.ComputerManagerListener;
|
||||||
import com.limelight.computers.ComputerManagerService;
|
import com.limelight.computers.ComputerManagerService;
|
||||||
import com.limelight.nvstream.http.ComputerDetails;
|
import com.limelight.nvstream.http.ComputerDetails;
|
||||||
import com.limelight.nvstream.http.NvApp;
|
import com.limelight.nvstream.http.NvApp;
|
||||||
|
import com.limelight.nvstream.http.NvHTTP;
|
||||||
import com.limelight.nvstream.http.PairingManager;
|
import com.limelight.nvstream.http.PairingManager;
|
||||||
import com.limelight.nvstream.wol.WakeOnLanSender;
|
import com.limelight.nvstream.wol.WakeOnLanSender;
|
||||||
|
import com.limelight.utils.CacheHelper;
|
||||||
import com.limelight.utils.Dialog;
|
import com.limelight.utils.Dialog;
|
||||||
import com.limelight.utils.ServerHelper;
|
import com.limelight.utils.ServerHelper;
|
||||||
import com.limelight.utils.SpinnerDialog;
|
import com.limelight.utils.SpinnerDialog;
|
||||||
import com.limelight.utils.UiHelper;
|
import com.limelight.utils.UiHelper;
|
||||||
|
|
||||||
|
import org.xmlpull.v1.XmlPullParserException;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.StringReader;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public class ShortcutTrampoline extends Activity {
|
public class ShortcutTrampoline extends Activity {
|
||||||
@@ -33,6 +40,7 @@ public class ShortcutTrampoline extends Activity {
|
|||||||
private SpinnerDialog blockingLoadSpinner;
|
private SpinnerDialog blockingLoadSpinner;
|
||||||
|
|
||||||
private ComputerManagerService.ComputerManagerBinder managerBinder;
|
private ComputerManagerService.ComputerManagerBinder managerBinder;
|
||||||
|
|
||||||
private final ServiceConnection serviceConnection = new ServiceConnection() {
|
private final ServiceConnection serviceConnection = new ServiceConnection() {
|
||||||
public void onServiceConnected(ComponentName className, IBinder binder) {
|
public void onServiceConnected(ComponentName className, IBinder binder) {
|
||||||
final ComputerManagerService.ComputerManagerBinder localBinder =
|
final ComputerManagerService.ComputerManagerBinder localBinder =
|
||||||
@@ -214,9 +222,9 @@ public class ShortcutTrampoline extends Activity {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
protected boolean validateInput(String uuidString, String appIdString) {
|
protected boolean validateInput(String uuidString, String appIdString, String nameString) {
|
||||||
// Validate UUID
|
// Validate PC UUID/Name
|
||||||
if (uuidString == null) {
|
if (uuidString == null && nameString == null) {
|
||||||
Dialog.displayDialog(ShortcutTrampoline.this,
|
Dialog.displayDialog(ShortcutTrampoline.this,
|
||||||
getResources().getString(R.string.conn_error_title),
|
getResources().getString(R.string.conn_error_title),
|
||||||
getResources().getString(R.string.scut_invalid_uuid),
|
getResources().getString(R.string.scut_invalid_uuid),
|
||||||
@@ -224,6 +232,7 @@ public class ShortcutTrampoline extends Activity {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (uuidString != null && !uuidString.isEmpty()) {
|
||||||
try {
|
try {
|
||||||
UUID.fromString(uuidString);
|
UUID.fromString(uuidString);
|
||||||
} catch (IllegalArgumentException ex) {
|
} catch (IllegalArgumentException ex) {
|
||||||
@@ -233,6 +242,16 @@ public class ShortcutTrampoline extends Activity {
|
|||||||
true);
|
true);
|
||||||
return false;
|
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)
|
// Validate App ID (if provided)
|
||||||
if (appIdString != null && !appIdString.isEmpty()) {
|
if (appIdString != null && !appIdString.isEmpty()) {
|
||||||
@@ -255,16 +274,86 @@ public class ShortcutTrampoline extends Activity {
|
|||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
UiHelper.notifyNewRootView(this);
|
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);
|
uuidString = getIntent().getStringExtra(AppView.UUID_EXTRA);
|
||||||
|
String nameString = getIntent().getStringExtra(AppView.NAME_EXTRA);
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
uuidString = _computer.uuid;
|
||||||
|
|
||||||
|
// Set the AppView UUID intent, since it wasn't provided
|
||||||
|
setIntent(new Intent(getIntent()).putExtra(AppView.UUID_EXTRA, uuidString));
|
||||||
|
}
|
||||||
|
|
||||||
if (validateInput(uuidString, appIdString)) {
|
|
||||||
if (appIdString != null && !appIdString.isEmpty()) {
|
if (appIdString != null && !appIdString.isEmpty()) {
|
||||||
app = new NvApp(getIntent().getStringExtra(Game.EXTRA_APP_NAME),
|
app = new NvApp(getIntent().getStringExtra(Game.EXTRA_APP_NAME),
|
||||||
Integer.parseInt(appIdString),
|
Integer.parseInt(appIdString),
|
||||||
getIntent().getBooleanExtra(Game.EXTRA_APP_HDR, false));
|
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
|
// Bind to the computer manager service
|
||||||
bindService(new Intent(this, ComputerManagerService.class), serviceConnection,
|
bindService(new Intent(this, ComputerManagerService.class), serviceConnection,
|
||||||
@@ -273,7 +362,6 @@ public class ShortcutTrampoline extends Activity {
|
|||||||
blockingLoadSpinner = SpinnerDialog.displayDialog(this, getResources().getString(R.string.conn_establishing_title),
|
blockingLoadSpinner = SpinnerDialog.displayDialog(this, getResources().getString(R.string.conn_establishing_title),
|
||||||
getResources().getString(R.string.applist_connect_msg), true);
|
getResources().getString(R.string.applist_connect_msg), true);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onStop() {
|
protected void onStop() {
|
||||||
|
|||||||
@@ -26,15 +26,6 @@ public class AndroidAudioRenderer implements AudioRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private AudioTrack createAudioTrack(int channelConfig, int sampleRate, int bufferSize, boolean lowLatency) {
|
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);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
AudioAttributes.Builder attributesBuilder = new AudioAttributes.Builder()
|
AudioAttributes.Builder attributesBuilder = new AudioAttributes.Builder()
|
||||||
.setUsage(AudioAttributes.USAGE_GAME);
|
.setUsage(AudioAttributes.USAGE_GAME);
|
||||||
AudioFormat format = new AudioFormat.Builder()
|
AudioFormat format = new AudioFormat.Builder()
|
||||||
@@ -72,7 +63,6 @@ public class AndroidAudioRenderer implements AudioRenderer {
|
|||||||
AudioManager.AUDIO_SESSION_ID_GENERATE);
|
AudioManager.AUDIO_SESSION_ID_GENERATE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int setup(MoonBridge.AudioConfiguration audioConfiguration, int sampleRate, int samplesPerFrame) {
|
public int setup(MoonBridge.AudioConfiguration audioConfiguration, int sampleRate, int samplesPerFrame) {
|
||||||
@@ -91,20 +81,10 @@ public class AndroidAudioRenderer implements AudioRenderer {
|
|||||||
channelConfig = AudioFormat.CHANNEL_OUT_5POINT1;
|
channelConfig = AudioFormat.CHANNEL_OUT_5POINT1;
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
||||||
// AudioFormat.CHANNEL_OUT_7POINT1_SURROUND isn't available until Android 6.0,
|
// 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
|
// 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.
|
// in 5.0, so just hardcode the constant so we can work on Lollipop.
|
||||||
channelConfig = 0x000018fc; // AudioFormat.CHANNEL_OUT_7POINT1_SURROUND
|
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;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LimeLog.severe("Decoder returned unhandled channel count");
|
LimeLog.severe("Decoder returned unhandled channel count");
|
||||||
|
|||||||
@@ -12,12 +12,12 @@ import java.security.KeyFactory;
|
|||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
import java.security.KeyPairGenerator;
|
import java.security.KeyPairGenerator;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.PrivateKey;
|
||||||
import java.security.Provider;
|
import java.security.Provider;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.security.cert.CertificateException;
|
import java.security.cert.CertificateException;
|
||||||
import java.security.cert.CertificateFactory;
|
import java.security.cert.CertificateFactory;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.security.interfaces.RSAPrivateKey;
|
|
||||||
import java.security.spec.InvalidKeySpecException;
|
import java.security.spec.InvalidKeySpecException;
|
||||||
import java.security.spec.PKCS8EncodedKeySpec;
|
import java.security.spec.PKCS8EncodedKeySpec;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
@@ -48,7 +48,7 @@ public class AndroidCryptoProvider implements LimelightCryptoProvider {
|
|||||||
private final File keyFile;
|
private final File keyFile;
|
||||||
|
|
||||||
private X509Certificate cert;
|
private X509Certificate cert;
|
||||||
private RSAPrivateKey key;
|
private PrivateKey key;
|
||||||
private byte[] pemCertBytes;
|
private byte[] pemCertBytes;
|
||||||
|
|
||||||
private static final Object globalCryptoLock = new Object();
|
private static final Object globalCryptoLock = new Object();
|
||||||
@@ -94,7 +94,7 @@ public class AndroidCryptoProvider implements LimelightCryptoProvider {
|
|||||||
cert = (X509Certificate) certFactory.generateCertificate(new ByteArrayInputStream(certBytes));
|
cert = (X509Certificate) certFactory.generateCertificate(new ByteArrayInputStream(certBytes));
|
||||||
pemCertBytes = certBytes;
|
pemCertBytes = certBytes;
|
||||||
KeyFactory keyFactory = KeyFactory.getInstance("RSA", bcProvider);
|
KeyFactory keyFactory = KeyFactory.getInstance("RSA", bcProvider);
|
||||||
key = (RSAPrivateKey) keyFactory.generatePrivate(new PKCS8EncodedKeySpec(keyBytes));
|
key = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(keyBytes));
|
||||||
} catch (CertificateException e) {
|
} catch (CertificateException e) {
|
||||||
// May happen if the cert is corrupt
|
// May happen if the cert is corrupt
|
||||||
LimeLog.warning("Corrupted certificate");
|
LimeLog.warning("Corrupted certificate");
|
||||||
@@ -144,7 +144,7 @@ public class AndroidCryptoProvider implements LimelightCryptoProvider {
|
|||||||
try {
|
try {
|
||||||
ContentSigner sigGen = new JcaContentSignerBuilder("SHA256withRSA").setProvider(bcProvider).build(keyPair.getPrivate());
|
ContentSigner sigGen = new JcaContentSignerBuilder("SHA256withRSA").setProvider(bcProvider).build(keyPair.getPrivate());
|
||||||
cert = new JcaX509CertificateConverter().setProvider(bcProvider).getCertificate(certBuilder.build(sigGen));
|
cert = new JcaX509CertificateConverter().setProvider(bcProvider).getCertificate(certBuilder.build(sigGen));
|
||||||
key = (RSAPrivateKey) keyPair.getPrivate();
|
key = keyPair.getPrivate();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(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
|
// Use a lock here to ensure only one guy will be generating or loading
|
||||||
// the certificate and key at a time
|
// the certificate and key at a time
|
||||||
synchronized (globalCryptoLock) {
|
synchronized (globalCryptoLock) {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,6 @@
|
|||||||
package com.limelight.binding.input;
|
package com.limelight.binding.input;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.annotation.TargetApi;
|
import android.annotation.TargetApi;
|
||||||
import android.hardware.input.InputManager;
|
import android.hardware.input.InputManager;
|
||||||
import android.os.Build;
|
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_EQUALS = 61;
|
||||||
public static final int VK_ESCAPE = 27;
|
public static final int VK_ESCAPE = 27;
|
||||||
public static final int VK_F1 = 112;
|
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_END = 35;
|
||||||
public static final int VK_HOME = 36;
|
public static final int VK_HOME = 36;
|
||||||
public static final int VK_NUM_LOCK = 144;
|
public static final int VK_NUM_LOCK = 144;
|
||||||
@@ -104,19 +106,21 @@ public class KeyboardTranslator implements InputManager.InputDeviceListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean needsShift(int keycode) {
|
public boolean hasNormalizedMapping(int keycode, int deviceId) {
|
||||||
switch (keycode)
|
if (deviceId >= 0) {
|
||||||
{
|
KeyboardMapping mapping = keyboardMappings.get(deviceId);
|
||||||
case KeyEvent.KEYCODE_AT:
|
if (mapping != null) {
|
||||||
case KeyEvent.KEYCODE_POUND:
|
// Try to map this device-specific keycode onto a QWERTY layout.
|
||||||
case KeyEvent.KEYCODE_PLUS:
|
// GFE assumes incoming keycodes are from a QWERTY keyboard.
|
||||||
case KeyEvent.KEYCODE_STAR:
|
int qwertyKeyCode = mapping.getQwertyKeyCodeForDeviceKeyCode(keycode);
|
||||||
|
if (qwertyKeyCode != KeyEvent.KEYCODE_UNKNOWN) {
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Translates the given keycode and returns the GFE keycode
|
* Translates the given keycode and returns the GFE keycode
|
||||||
@@ -124,6 +128,7 @@ public class KeyboardTranslator implements InputManager.InputDeviceListener {
|
|||||||
* @param deviceId InputDevice.getId() or -1 if unknown
|
* @param deviceId InputDevice.getId() or -1 if unknown
|
||||||
* @return a GFE keycode for the given keycode
|
* @return a GFE keycode for the given keycode
|
||||||
*/
|
*/
|
||||||
|
@SuppressLint("InlinedApi")
|
||||||
public short translate(int keycode, int deviceId) {
|
public short translate(int keycode, int deviceId) {
|
||||||
int translated;
|
int translated;
|
||||||
|
|
||||||
@@ -159,6 +164,10 @@ public class KeyboardTranslator implements InputManager.InputDeviceListener {
|
|||||||
keycode <= KeyEvent.KEYCODE_F12) {
|
keycode <= KeyEvent.KEYCODE_F12) {
|
||||||
translated = (keycode - KeyEvent.KEYCODE_F1) + VK_F1;
|
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 {
|
else {
|
||||||
switch (keycode) {
|
switch (keycode) {
|
||||||
case KeyEvent.KEYCODE_ALT_LEFT:
|
case KeyEvent.KEYCODE_ALT_LEFT:
|
||||||
@@ -230,6 +239,10 @@ public class KeyboardTranslator implements InputManager.InputDeviceListener {
|
|||||||
translated = 0x5c;
|
translated = 0x5c;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case KeyEvent.KEYCODE_MENU:
|
||||||
|
translated = 0x5d;
|
||||||
|
break;
|
||||||
|
|
||||||
case KeyEvent.KEYCODE_MINUS:
|
case KeyEvent.KEYCODE_MINUS:
|
||||||
translated = 0xbd;
|
translated = 0xbd;
|
||||||
break;
|
break;
|
||||||
@@ -343,20 +356,15 @@ public class KeyboardTranslator implements InputManager.InputDeviceListener {
|
|||||||
translated = 0x6E;
|
translated = 0x6E;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case KeyEvent.KEYCODE_AT:
|
case KeyEvent.KEYCODE_PRINT:
|
||||||
translated = 2 + VK_0;
|
translated = 0x2A;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case KeyEvent.KEYCODE_POUND:
|
case KeyEvent.KEYCODE_SCREENSHOT:
|
||||||
translated = 3 + VK_0;
|
translated = 0x2C;
|
||||||
break;
|
|
||||||
|
|
||||||
case KeyEvent.KEYCODE_STAR:
|
|
||||||
translated = 8 + VK_0;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
System.out.println("No key for "+keycode);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-13
@@ -15,8 +15,8 @@ import android.view.View;
|
|||||||
// is unavailable on this system (ex: DeX, ChromeOS)
|
// is unavailable on this system (ex: DeX, ChromeOS)
|
||||||
@TargetApi(Build.VERSION_CODES.O)
|
@TargetApi(Build.VERSION_CODES.O)
|
||||||
public class AndroidNativePointerCaptureProvider extends AndroidPointerIconCaptureProvider implements InputManager.InputDeviceListener {
|
public class AndroidNativePointerCaptureProvider extends AndroidPointerIconCaptureProvider implements InputManager.InputDeviceListener {
|
||||||
private InputManager inputManager;
|
private final InputManager inputManager;
|
||||||
private View targetView;
|
private final View targetView;
|
||||||
|
|
||||||
public AndroidNativePointerCaptureProvider(Activity activity, View targetView) {
|
public AndroidNativePointerCaptureProvider(Activity activity, View targetView) {
|
||||||
super(activity, targetView);
|
super(activity, targetView);
|
||||||
@@ -44,7 +44,10 @@ public class AndroidNativePointerCaptureProvider extends AndroidPointerIconCaptu
|
|||||||
// with SOURCE_TOUCHSCREEN, SOURCE_KEYBOARD, and SOURCE_MOUSE.
|
// with SOURCE_TOUCHSCREEN, SOURCE_KEYBOARD, and SOURCE_MOUSE.
|
||||||
// Upon enabling pointer capture, that device will switch to
|
// Upon enabling pointer capture, that device will switch to
|
||||||
// SOURCE_KEYBOARD and SOURCE_TOUCHPAD.
|
// 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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,8 +62,19 @@ public class AndroidNativePointerCaptureProvider extends AndroidPointerIconCaptu
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void enableCapture() {
|
public void showCursor() {
|
||||||
super.enableCapture();
|
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
|
// Listen for device events to enable/disable capture
|
||||||
inputManager.registerInputDeviceListener(this, null);
|
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
|
@Override
|
||||||
public void onWindowFocusChanged(boolean focusActive) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+6
-7
@@ -4,14 +4,13 @@ import android.annotation.TargetApi;
|
|||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.view.MotionEvent;
|
|
||||||
import android.view.PointerIcon;
|
import android.view.PointerIcon;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.N)
|
@TargetApi(Build.VERSION_CODES.N)
|
||||||
public class AndroidPointerIconCaptureProvider extends InputCaptureProvider {
|
public class AndroidPointerIconCaptureProvider extends InputCaptureProvider {
|
||||||
private View targetView;
|
private final View targetView;
|
||||||
private Context context;
|
private final Context context;
|
||||||
|
|
||||||
public AndroidPointerIconCaptureProvider(Activity activity, View targetView) {
|
public AndroidPointerIconCaptureProvider(Activity activity, View targetView) {
|
||||||
this.context = activity;
|
this.context = activity;
|
||||||
@@ -23,14 +22,14 @@ public class AndroidPointerIconCaptureProvider extends InputCaptureProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void enableCapture() {
|
public void hideCursor() {
|
||||||
super.enableCapture();
|
super.hideCursor();
|
||||||
targetView.setPointerIcon(PointerIcon.getSystemIcon(context, PointerIcon.TYPE_NULL));
|
targetView.setPointerIcon(PointerIcon.getSystemIcon(context, PointerIcon.TYPE_NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void disableCapture() {
|
public void showCursor() {
|
||||||
super.disableCapture();
|
super.showCursor();
|
||||||
targetView.setPointerIcon(null);
|
targetView.setPointerIcon(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,12 +4,15 @@ import android.view.MotionEvent;
|
|||||||
|
|
||||||
public abstract class InputCaptureProvider {
|
public abstract class InputCaptureProvider {
|
||||||
protected boolean isCapturing;
|
protected boolean isCapturing;
|
||||||
|
protected boolean isCursorVisible;
|
||||||
|
|
||||||
public void enableCapture() {
|
public void enableCapture() {
|
||||||
isCapturing = true;
|
isCapturing = true;
|
||||||
|
hideCursor();
|
||||||
}
|
}
|
||||||
public void disableCapture() {
|
public void disableCapture() {
|
||||||
isCapturing = false;
|
isCapturing = false;
|
||||||
|
showCursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void destroy() {}
|
public void destroy() {}
|
||||||
@@ -22,6 +25,14 @@ public abstract class InputCaptureProvider {
|
|||||||
return isCapturing;
|
return isCapturing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void showCursor() {
|
||||||
|
isCursorVisible = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void hideCursor() {
|
||||||
|
isCursorVisible = false;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean eventHasRelativeMouseAxes(MotionEvent event) {
|
public boolean eventHasRelativeMouseAxes(MotionEvent event) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ public class ShieldCaptureProvider extends InputCaptureProvider {
|
|||||||
private static int AXIS_RELATIVE_X;
|
private static int AXIS_RELATIVE_X;
|
||||||
private static int AXIS_RELATIVE_Y;
|
private static int AXIS_RELATIVE_Y;
|
||||||
|
|
||||||
private Context context;
|
private final Context context;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
try {
|
try {
|
||||||
@@ -62,14 +62,14 @@ public class ShieldCaptureProvider extends InputCaptureProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void enableCapture() {
|
public void hideCursor() {
|
||||||
super.enableCapture();
|
super.hideCursor();
|
||||||
setCursorVisibility(false);
|
setCursorVisibility(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void disableCapture() {
|
public void showCursor() {
|
||||||
super.disableCapture();
|
super.showCursor();
|
||||||
setCursorVisibility(true);
|
setCursorVisibility(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,10 +8,12 @@ public abstract class AbstractController {
|
|||||||
|
|
||||||
private UsbDriverListener listener;
|
private UsbDriverListener listener;
|
||||||
|
|
||||||
protected short buttonFlags;
|
protected int buttonFlags, supportedButtonFlags;
|
||||||
protected float leftTrigger, rightTrigger;
|
protected float leftTrigger, rightTrigger;
|
||||||
protected float rightStickX, rightStickY;
|
protected float rightStickX, rightStickY;
|
||||||
protected float leftStickX, leftStickY;
|
protected float leftStickX, leftStickY;
|
||||||
|
protected short capabilities;
|
||||||
|
protected byte type;
|
||||||
|
|
||||||
public int getControllerId() {
|
public int getControllerId() {
|
||||||
return deviceId;
|
return deviceId;
|
||||||
@@ -25,6 +27,18 @@ public abstract class AbstractController {
|
|||||||
return productId;
|
return productId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getSupportedButtonFlags() {
|
||||||
|
return supportedButtonFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
public short getCapabilities() {
|
||||||
|
return capabilities;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
protected void setButtonFlag(int buttonFlag, int data) {
|
protected void setButtonFlag(int buttonFlag, int data) {
|
||||||
if (data != 0) {
|
if (data != 0) {
|
||||||
buttonFlags |= buttonFlag;
|
buttonFlags |= buttonFlag;
|
||||||
@@ -51,6 +65,8 @@ public abstract class AbstractController {
|
|||||||
|
|
||||||
public abstract void rumble(short lowFreqMotor, short highFreqMotor);
|
public abstract void rumble(short lowFreqMotor, short highFreqMotor);
|
||||||
|
|
||||||
|
public abstract void rumbleTriggers(short leftTrigger, short rightTrigger);
|
||||||
|
|
||||||
protected void notifyDeviceRemoved() {
|
protected void notifyDeviceRemoved() {
|
||||||
listener.deviceRemoved(this);
|
listener.deviceRemoved(this);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import android.hardware.usb.UsbInterface;
|
|||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
|
|
||||||
import com.limelight.LimeLog;
|
import com.limelight.LimeLog;
|
||||||
|
import com.limelight.nvstream.input.ControllerPacket;
|
||||||
|
import com.limelight.nvstream.jni.MoonBridge;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
@@ -25,6 +27,14 @@ public abstract class AbstractXboxController extends AbstractController {
|
|||||||
super(deviceId, listener, device.getVendorId(), device.getProductId());
|
super(deviceId, listener, device.getVendorId(), device.getProductId());
|
||||||
this.device = device;
|
this.device = device;
|
||||||
this.connection = connection;
|
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() {
|
private Thread createInputThread() {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.limelight.binding.input.driver;
|
package com.limelight.binding.input.driver;
|
||||||
|
|
||||||
public interface UsbDriverListener {
|
public interface UsbDriverListener {
|
||||||
void reportControllerState(int controllerId, short buttonFlags,
|
void reportControllerState(int controllerId, int buttonFlags,
|
||||||
float leftStickX, float leftStickY,
|
float leftStickX, float leftStickY,
|
||||||
float rightStickX, float rightStickY,
|
float rightStickX, float rightStickY,
|
||||||
float leftTrigger, float rightTrigger);
|
float leftTrigger, float rightTrigger);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.limelight.binding.input.driver;
|
package com.limelight.binding.input.driver;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
@@ -20,6 +21,7 @@ import com.limelight.LimeLog;
|
|||||||
import com.limelight.R;
|
import com.limelight.R;
|
||||||
import com.limelight.preferences.PreferenceConfiguration;
|
import com.limelight.preferences.PreferenceConfiguration;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
public class UsbDriverService extends Service implements UsbDriverListener {
|
public class UsbDriverService extends Service implements UsbDriverListener {
|
||||||
@@ -41,7 +43,8 @@ public class UsbDriverService extends Service implements UsbDriverListener {
|
|||||||
private int nextDeviceId;
|
private int nextDeviceId;
|
||||||
|
|
||||||
@Override
|
@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
|
// Call through to the client's listener
|
||||||
if (listener != null) {
|
if (listener != null) {
|
||||||
listener.reportControllerState(controllerId, buttonFlags, leftStickX, leftStickY, rightStickX, rightStickY, leftTrigger, rightTrigger);
|
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,
|
// just returning a false result or returning 0 enumerated devices,
|
||||||
// they throw an undocumented SecurityException from this call, crashing
|
// they throw an undocumented SecurityException from this call, crashing
|
||||||
// the whole app. :(
|
// 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) {
|
} catch (SecurityException e) {
|
||||||
Toast.makeText(this, this.getText(R.string.error_usb_prohibited), Toast.LENGTH_LONG).show();
|
Toast.makeText(this, this.getText(R.string.error_usb_prohibited), Toast.LENGTH_LONG).show();
|
||||||
if (stateListener != null) {
|
if (stateListener != null) {
|
||||||
@@ -183,6 +191,9 @@ public class UsbDriverService extends Service implements UsbDriverListener {
|
|||||||
else if (Xbox360Controller.canClaimDevice(device)) {
|
else if (Xbox360Controller.canClaimDevice(device)) {
|
||||||
controller = new Xbox360Controller(device, connection, nextDeviceId++, this);
|
controller = new Xbox360Controller(device, connection, nextDeviceId++, this);
|
||||||
}
|
}
|
||||||
|
else if (Xbox360WirelessDongle.canClaimDevice(device)) {
|
||||||
|
controller = new Xbox360WirelessDongle(device, connection, nextDeviceId++, this);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
// Unreachable
|
// Unreachable
|
||||||
return;
|
return;
|
||||||
@@ -200,10 +211,8 @@ public class UsbDriverService extends Service implements UsbDriverListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isRecognizedInputDevice(UsbDevice device) {
|
public static boolean isRecognizedInputDevice(UsbDevice device) {
|
||||||
// On KitKat and later, we can determine if this VID and PID combo
|
// Determine if this VID and PID combo matches an existing input device
|
||||||
// matches an existing input device and defer to the built-in controller
|
// and defer to the built-in controller support in that case.
|
||||||
// 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()) {
|
for (int id : InputDevice.getDeviceIds()) {
|
||||||
InputDevice inputDev = InputDevice.getDevice(id);
|
InputDevice inputDev = InputDevice.getDevice(id);
|
||||||
if (inputDev == null) {
|
if (inputDev == null) {
|
||||||
@@ -219,10 +228,6 @@ public class UsbDriverService extends Service implements UsbDriverListener {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean kernelSupportsXboxOne() {
|
public static boolean kernelSupportsXboxOne() {
|
||||||
String kernelVersion = System.getProperty("os.version");
|
String kernelVersion = System.getProperty("os.version");
|
||||||
@@ -248,13 +253,37 @@ public class UsbDriverService extends Service implements UsbDriverListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean shouldClaimDevice(UsbDevice device, boolean claimAllAvailable) {
|
public static boolean kernelSupportsXbox360W() {
|
||||||
return ((!kernelSupportsXboxOne() || !isRecognizedInputDevice(device) || claimAllAvailable) && XboxOneController.canClaimDevice(device)) ||
|
// Check if this kernel is 4.2+ to see if the xpad driver sets Xbox 360 wireless LEDs
|
||||||
((!isRecognizedInputDevice(device) || claimAllAvailable) && Xbox360Controller.canClaimDevice(device));
|
// 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() {
|
private void start() {
|
||||||
if (started) {
|
if (started || usbManager == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ public class Xbox360Controller extends AbstractXboxController {
|
|||||||
0x20d6, // PowerA
|
0x20d6, // PowerA
|
||||||
0x24c6, // PowerA
|
0x24c6, // PowerA
|
||||||
0x2f24, // GameSir
|
0x2f24, // GameSir
|
||||||
|
0x2dc8, // 8BitDo
|
||||||
};
|
};
|
||||||
|
|
||||||
public static boolean canClaimDevice(UsbDevice device) {
|
public static boolean canClaimDevice(UsbDevice device) {
|
||||||
@@ -156,4 +157,9 @@ public class Xbox360Controller extends AbstractXboxController {
|
|||||||
LimeLog.warning("Rumble transfer failed: "+res);
|
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.LimeLog;
|
||||||
import com.limelight.nvstream.input.ControllerPacket;
|
import com.limelight.nvstream.input.ControllerPacket;
|
||||||
|
import com.limelight.nvstream.jni.MoonBridge;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -24,10 +25,12 @@ public class XboxOneController extends AbstractXboxController {
|
|||||||
0x20d6, // PowerA
|
0x20d6, // PowerA
|
||||||
0x24c6, // PowerA
|
0x24c6, // PowerA
|
||||||
0x2e24, // Hyperkin
|
0x2e24, // Hyperkin
|
||||||
|
0x2dc8, // 8BitDo
|
||||||
};
|
};
|
||||||
|
|
||||||
private static final byte[] FW2015_INIT = {0x05, 0x20, 0x00, 0x01, 0x00};
|
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[] 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,
|
private static final byte[] HORI_INIT = {0x01, 0x20, 0x00, 0x09, 0x00, 0x04, 0x20, 0x3a,
|
||||||
0x00, 0x00, 0x00, (byte)0x80, 0x00};
|
0x00, 0x00, 0x00, (byte)0x80, 0x00};
|
||||||
private static final byte[] PDP_INIT1 = {0x0a, 0x20, 0x00, 0x03, 0x00, 0x01, 0x14};
|
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(0x0f0d, 0x0067, HORI_INIT),
|
||||||
new InitPacket(0x0000, 0x0000, FW2015_INIT),
|
new InitPacket(0x0000, 0x0000, FW2015_INIT),
|
||||||
new InitPacket(0x045e, 0x02ea, ONE_S_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, 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_INIT1),
|
||||||
new InitPacket(0x0e6f, 0x0000, PDP_INIT2),
|
new InitPacket(0x0e6f, 0x0000, PDP_INIT2),
|
||||||
new InitPacket(0x24c6, 0x541a, RUMBLE_INIT1),
|
new InitPacket(0x24c6, 0x541a, RUMBLE_INIT1),
|
||||||
@@ -54,9 +61,14 @@ public class XboxOneController extends AbstractXboxController {
|
|||||||
};
|
};
|
||||||
|
|
||||||
private byte seqNum = 0;
|
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) {
|
public XboxOneController(UsbDevice device, UsbDeviceConnection connection, int deviceId, UsbDriverListener listener) {
|
||||||
super(device, connection, deviceId, listener);
|
super(device, connection, deviceId, listener);
|
||||||
|
capabilities |= MoonBridge.LI_CCAP_TRIGGER_RUMBLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processButtons(ByteBuffer buffer) {
|
private void processButtons(ByteBuffer buffer) {
|
||||||
@@ -176,12 +188,14 @@ public class XboxOneController extends AbstractXboxController {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private void sendRumblePacket() {
|
||||||
public void rumble(short lowFreqMotor, short highFreqMotor) {
|
|
||||||
byte[] data = {
|
byte[] data = {
|
||||||
0x09, 0x00, seqNum++, 0x09, 0x00,
|
0x09, 0x00, seqNum++, 0x09, 0x00,
|
||||||
0x0F, 0x00, 0x00,
|
0x0F,
|
||||||
(byte)(lowFreqMotor >> 9), (byte)(highFreqMotor >> 9),
|
(byte)(leftTriggerMotor >> 9),
|
||||||
|
(byte)(rightTriggerMotor >> 9),
|
||||||
|
(byte)(lowFreqMotor >> 9),
|
||||||
|
(byte)(highFreqMotor >> 9),
|
||||||
(byte)0xFF, 0x00, (byte)0xFF
|
(byte)0xFF, 0x00, (byte)0xFF
|
||||||
};
|
};
|
||||||
int res = connection.bulkTransfer(outEndpt, data, data.length, 100);
|
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 {
|
private static class InitPacket {
|
||||||
final int vendorId;
|
final int vendorId;
|
||||||
final int productId;
|
final int productId;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ public interface EvdevListener {
|
|||||||
|
|
||||||
void mouseMove(int deltaX, int deltaY);
|
void mouseMove(int deltaX, int deltaY);
|
||||||
void mouseButtonEvent(int buttonId, boolean down);
|
void mouseButtonEvent(int buttonId, boolean down);
|
||||||
void mouseScroll(byte amount);
|
void mouseVScroll(byte amount);
|
||||||
|
void mouseHScroll(byte amount);
|
||||||
void keyboardEvent(boolean buttonDown, short keyCode);
|
void keyboardEvent(boolean buttonDown, short keyCode);
|
||||||
}
|
}
|
||||||
|
|||||||
+14
@@ -185,6 +185,10 @@ public class VirtualControllerConfigurationLoader {
|
|||||||
private static final int START_BACK_WIDTH = 12;
|
private static final int START_BACK_WIDTH = 12;
|
||||||
private static final int START_BACK_HEIGHT = 7;
|
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) {
|
public static void createDefaultLayout(final VirtualController controller, final Context context) {
|
||||||
|
|
||||||
DisplayMetrics screen = context.getResources().getDisplayMetrics();
|
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);
|
controller.setOpacity(config.oscOpacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
@@ -35,6 +35,7 @@ public abstract class VirtualControllerElement extends View {
|
|||||||
public static final int EID_RS = 13;
|
public static final int EID_RS = 13;
|
||||||
public static final int EID_LSB = 14;
|
public static final int EID_LSB = 14;
|
||||||
public static final int EID_RSB = 15;
|
public static final int EID_RSB = 15;
|
||||||
|
public static final int EID_GDB = 16;
|
||||||
|
|
||||||
protected VirtualController virtualController;
|
protected VirtualController virtualController;
|
||||||
protected final int elementId;
|
protected final int elementId;
|
||||||
|
|||||||
@@ -2,6 +2,9 @@ package com.limelight.binding.video;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
@@ -18,6 +21,7 @@ import com.limelight.nvstream.jni.MoonBridge;
|
|||||||
import com.limelight.preferences.PreferenceConfiguration;
|
import com.limelight.preferences.PreferenceConfiguration;
|
||||||
|
|
||||||
import android.annotation.TargetApi;
|
import android.annotation.TargetApi;
|
||||||
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.media.MediaCodec;
|
import android.media.MediaCodec;
|
||||||
import android.media.MediaCodecInfo;
|
import android.media.MediaCodecInfo;
|
||||||
@@ -38,28 +42,27 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
private static final boolean USE_FRAME_RENDER_TIME = false;
|
private static final boolean USE_FRAME_RENDER_TIME = false;
|
||||||
private static final boolean FRAME_RENDER_TIME_ONLY = USE_FRAME_RENDER_TIME && false;
|
private static final boolean FRAME_RENDER_TIME_ONLY = USE_FRAME_RENDER_TIME && false;
|
||||||
|
|
||||||
// Used on versions < 5.0
|
|
||||||
private ByteBuffer[] legacyInputBuffers;
|
|
||||||
|
|
||||||
private MediaCodecInfo avcDecoder;
|
private MediaCodecInfo avcDecoder;
|
||||||
private MediaCodecInfo hevcDecoder;
|
private MediaCodecInfo hevcDecoder;
|
||||||
|
private MediaCodecInfo av1Decoder;
|
||||||
|
|
||||||
private byte[] vpsBuffer;
|
private final ArrayList<byte[]> vpsBuffers = new ArrayList<>();
|
||||||
private byte[] spsBuffer;
|
private final ArrayList<byte[]> spsBuffers = new ArrayList<>();
|
||||||
private byte[] ppsBuffer;
|
private final ArrayList<byte[]> ppsBuffers = new ArrayList<>();
|
||||||
private boolean submittedCsd;
|
private boolean submittedCsd;
|
||||||
private boolean submitCsdNextCall;
|
private byte[] currentHdrMetadata;
|
||||||
|
|
||||||
private int nextInputBufferIndex = -1;
|
private int nextInputBufferIndex = -1;
|
||||||
private ByteBuffer nextInputBuffer;
|
private ByteBuffer nextInputBuffer;
|
||||||
|
|
||||||
private Context context;
|
private Context context;
|
||||||
|
private Activity activity;
|
||||||
private MediaCodec videoDecoder;
|
private MediaCodec videoDecoder;
|
||||||
private Thread rendererThread;
|
private Thread rendererThread;
|
||||||
private boolean needsSpsBitstreamFixup, isExynos4;
|
private boolean needsSpsBitstreamFixup, isExynos4;
|
||||||
private boolean adaptivePlayback, directSubmit, fusedIdrFrame;
|
private boolean adaptivePlayback, directSubmit, fusedIdrFrame;
|
||||||
private boolean constrainedHighProfile;
|
private boolean constrainedHighProfile;
|
||||||
private boolean refFrameInvalidationAvc, refFrameInvalidationHevc;
|
private boolean refFrameInvalidationAvc, refFrameInvalidationHevc, refFrameInvalidationAv1;
|
||||||
private byte optimalSlicesPerFrame;
|
private byte optimalSlicesPerFrame;
|
||||||
private boolean refFrameInvalidationActive;
|
private boolean refFrameInvalidationActive;
|
||||||
private int initialWidth, initialHeight;
|
private int initialWidth, initialHeight;
|
||||||
@@ -73,7 +76,6 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
private boolean foreground = true;
|
private boolean foreground = true;
|
||||||
private PerfOverlayListener perfListener;
|
private PerfOverlayListener perfListener;
|
||||||
|
|
||||||
private static final int CR_TIMEOUT_MS = 5000;
|
|
||||||
private static final int CR_MAX_TRIES = 10;
|
private static final int CR_MAX_TRIES = 10;
|
||||||
private static final int CR_RECOVERY_TYPE_NONE = 0;
|
private static final int CR_RECOVERY_TYPE_NONE = 0;
|
||||||
private static final int CR_RECOVERY_TYPE_FLUSH = 1;
|
private static final int CR_RECOVERY_TYPE_FLUSH = 1;
|
||||||
@@ -108,6 +110,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
|
|
||||||
private long lastTimestampUs;
|
private long lastTimestampUs;
|
||||||
private int lastFrameNumber;
|
private int lastFrameNumber;
|
||||||
|
private long baseTimestampUs;
|
||||||
private int refreshRate;
|
private int refreshRate;
|
||||||
private PreferenceConfiguration prefs;
|
private PreferenceConfiguration prefs;
|
||||||
|
|
||||||
@@ -131,10 +134,9 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
return decoder;
|
return decoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
|
||||||
private boolean decoderCanMeetPerformancePoint(MediaCodecInfo.VideoCapabilities caps, PreferenceConfiguration prefs) {
|
private boolean decoderCanMeetPerformancePoint(MediaCodecInfo.VideoCapabilities caps, PreferenceConfiguration prefs) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||||
MediaCodecInfo.VideoCapabilities.PerformancePoint targetPerfPoint = new MediaCodecInfo.VideoCapabilities.PerformancePoint(prefs.resolution.width, prefs.resolution.height, prefs.fps);
|
MediaCodecInfo.VideoCapabilities.PerformancePoint targetPerfPoint = new MediaCodecInfo.VideoCapabilities.PerformancePoint(prefs.width, prefs.height, prefs.fps);
|
||||||
List<MediaCodecInfo.VideoCapabilities.PerformancePoint> perfPoints = caps.getSupportedPerformancePoints();
|
List<MediaCodecInfo.VideoCapabilities.PerformancePoint> perfPoints = caps.getSupportedPerformancePoints();
|
||||||
if (perfPoints != null) {
|
if (perfPoints != null) {
|
||||||
for (MediaCodecInfo.VideoCapabilities.PerformancePoint perfPoint : perfPoints) {
|
for (MediaCodecInfo.VideoCapabilities.PerformancePoint perfPoint : perfPoints) {
|
||||||
@@ -155,7 +157,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
try {
|
try {
|
||||||
// We'll ask the decoder what it can do for us at this resolution and see if our
|
// We'll ask the decoder what it can do for us at this resolution and see if our
|
||||||
// requested frame rate falls below or inside the range of achievable frame rates.
|
// requested frame rate falls below or inside the range of achievable frame rates.
|
||||||
Range<Double> fpsRange = caps.getAchievableFrameRatesFor(prefs.resolution.width, prefs.resolution.height);
|
Range<Double> fpsRange = caps.getAchievableFrameRatesFor(prefs.width, prefs.height);
|
||||||
if (fpsRange != null) {
|
if (fpsRange != null) {
|
||||||
return prefs.fps <= fpsRange.getUpper();
|
return prefs.fps <= fpsRange.getUpper();
|
||||||
}
|
}
|
||||||
@@ -170,25 +172,33 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
// As a last resort, we will use areSizeAndRateSupported() which is explicitly NOT a
|
// As a last resort, we will use areSizeAndRateSupported() which is explicitly NOT a
|
||||||
// performance metric, but it can work at least for the purpose of determining if
|
// performance metric, but it can work at least for the purpose of determining if
|
||||||
// the codec is going to die when given a stream with the specified settings.
|
// the codec is going to die when given a stream with the specified settings.
|
||||||
return caps.areSizeAndRateSupported(prefs.resolution.width, prefs.resolution.height, prefs.fps);
|
return caps.areSizeAndRateSupported(prefs.width, prefs.height, prefs.fps);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean decoderCanMeetPerformancePointWithHevcAndNotAvc(MediaCodecInfo avcDecoderInfo, MediaCodecInfo hevcDecoderInfo, PreferenceConfiguration prefs) {
|
private boolean decoderCanMeetPerformancePointWithHevcAndNotAvc(MediaCodecInfo hevcDecoderInfo, MediaCodecInfo avcDecoderInfo, PreferenceConfiguration prefs) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
||||||
MediaCodecInfo.VideoCapabilities avcCaps = avcDecoderInfo.getCapabilitiesForType("video/avc").getVideoCapabilities();
|
MediaCodecInfo.VideoCapabilities avcCaps = avcDecoderInfo.getCapabilitiesForType("video/avc").getVideoCapabilities();
|
||||||
MediaCodecInfo.VideoCapabilities hevcCaps = hevcDecoderInfo.getCapabilitiesForType("video/hevc").getVideoCapabilities();
|
MediaCodecInfo.VideoCapabilities hevcCaps = hevcDecoderInfo.getCapabilitiesForType("video/hevc").getVideoCapabilities();
|
||||||
|
|
||||||
return !decoderCanMeetPerformancePoint(avcCaps, prefs) && decoderCanMeetPerformancePoint(hevcCaps, prefs);
|
return !decoderCanMeetPerformancePoint(avcCaps, prefs) && decoderCanMeetPerformancePoint(hevcCaps, prefs);
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
// No performance data
|
private boolean decoderCanMeetPerformancePointWithAv1AndNotHevc(MediaCodecInfo av1DecoderInfo, MediaCodecInfo hevcDecoderInfo, PreferenceConfiguration prefs) {
|
||||||
return false;
|
MediaCodecInfo.VideoCapabilities av1Caps = av1DecoderInfo.getCapabilitiesForType("video/av01").getVideoCapabilities();
|
||||||
|
MediaCodecInfo.VideoCapabilities hevcCaps = hevcDecoderInfo.getCapabilitiesForType("video/hevc").getVideoCapabilities();
|
||||||
|
|
||||||
|
return !decoderCanMeetPerformancePoint(hevcCaps, prefs) && decoderCanMeetPerformancePoint(av1Caps, prefs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean decoderCanMeetPerformancePointWithAv1AndNotAvc(MediaCodecInfo av1DecoderInfo, MediaCodecInfo avcDecoderInfo, PreferenceConfiguration prefs) {
|
||||||
|
MediaCodecInfo.VideoCapabilities avcCaps = avcDecoderInfo.getCapabilitiesForType("video/avc").getVideoCapabilities();
|
||||||
|
MediaCodecInfo.VideoCapabilities av1Caps = av1DecoderInfo.getCapabilitiesForType("video/av01").getVideoCapabilities();
|
||||||
|
|
||||||
|
return !decoderCanMeetPerformancePoint(avcCaps, prefs) && decoderCanMeetPerformancePoint(av1Caps, prefs);
|
||||||
}
|
}
|
||||||
|
|
||||||
private MediaCodecInfo findHevcDecoder(PreferenceConfiguration prefs, boolean meteredNetwork, boolean requestedHdr) {
|
private MediaCodecInfo findHevcDecoder(PreferenceConfiguration prefs, boolean meteredNetwork, boolean requestedHdr) {
|
||||||
// Don't return anything if HEVC is forced off
|
// Don't return anything if H.264 is forced
|
||||||
if (prefs.videoFormat == PreferenceConfiguration.FORCE_H265_OFF) {
|
if (prefs.videoFormat == PreferenceConfiguration.FormatOption.FORCE_H264) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,7 +213,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
LimeLog.info("Found HEVC decoder, but it's not whitelisted - "+hevcDecoderInfo.getName());
|
LimeLog.info("Found HEVC decoder, but it's not whitelisted - "+hevcDecoderInfo.getName());
|
||||||
|
|
||||||
// Force HEVC enabled if the user asked for it
|
// Force HEVC enabled if the user asked for it
|
||||||
if (prefs.videoFormat == PreferenceConfiguration.FORCE_H265_ON) {
|
if (prefs.videoFormat == PreferenceConfiguration.FormatOption.FORCE_HEVC) {
|
||||||
LimeLog.info("Forcing HEVC enabled despite non-whitelisted decoder");
|
LimeLog.info("Forcing HEVC enabled despite non-whitelisted decoder");
|
||||||
}
|
}
|
||||||
// HDR implies HEVC forced on, since HEVCMain10HDR10 is required for HDR.
|
// HDR implies HEVC forced on, since HEVCMain10HDR10 is required for HDR.
|
||||||
@@ -211,11 +221,11 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
LimeLog.info("Forcing HEVC enabled for HDR streaming");
|
LimeLog.info("Forcing HEVC enabled for HDR streaming");
|
||||||
}
|
}
|
||||||
// > 4K streaming also requires HEVC, so force it on there too.
|
// > 4K streaming also requires HEVC, so force it on there too.
|
||||||
else if (prefs.resolution.width > 4096 || prefs.resolution.height > 4096) {
|
else if (prefs.width > 4096 || prefs.height > 4096) {
|
||||||
LimeLog.info("Forcing HEVC enabled for over 4K streaming");
|
LimeLog.info("Forcing HEVC enabled for over 4K streaming");
|
||||||
}
|
}
|
||||||
// Use HEVC if the H.264 decoder is unable to meet the performance point
|
// Use HEVC if the H.264 decoder is unable to meet the performance point
|
||||||
else if (avcDecoder != null && decoderCanMeetPerformancePointWithHevcAndNotAvc(avcDecoder, hevcDecoderInfo, prefs)) {
|
else if (avcDecoder != null && decoderCanMeetPerformancePointWithHevcAndNotAvc(hevcDecoderInfo, avcDecoder, prefs)) {
|
||||||
LimeLog.info("Using non-whitelisted HEVC decoder to meet performance point");
|
LimeLog.info("Using non-whitelisted HEVC decoder to meet performance point");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -227,17 +237,50 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
return hevcDecoderInfo;
|
return hevcDecoderInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private MediaCodecInfo findAv1Decoder(PreferenceConfiguration prefs) {
|
||||||
|
// For now, don't use AV1 unless explicitly requested
|
||||||
|
if (prefs.videoFormat != PreferenceConfiguration.FormatOption.FORCE_AV1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
MediaCodecInfo decoderInfo = MediaCodecHelper.findProbableSafeDecoder("video/av01", -1);
|
||||||
|
if (decoderInfo != null) {
|
||||||
|
if (!MediaCodecHelper.isDecoderWhitelistedForAv1(decoderInfo)) {
|
||||||
|
LimeLog.info("Found AV1 decoder, but it's not whitelisted - "+decoderInfo.getName());
|
||||||
|
|
||||||
|
// Force HEVC enabled if the user asked for it
|
||||||
|
if (prefs.videoFormat == PreferenceConfiguration.FormatOption.FORCE_AV1) {
|
||||||
|
LimeLog.info("Forcing AV1 enabled despite non-whitelisted decoder");
|
||||||
|
}
|
||||||
|
// Use AV1 if the HEVC decoder is unable to meet the performance point
|
||||||
|
else if (hevcDecoder != null && decoderCanMeetPerformancePointWithAv1AndNotHevc(decoderInfo, hevcDecoder, prefs)) {
|
||||||
|
LimeLog.info("Using non-whitelisted AV1 decoder to meet performance point");
|
||||||
|
}
|
||||||
|
// Use AV1 if the H.264 decoder is unable to meet the performance point and we have no HEVC decoder
|
||||||
|
else if (hevcDecoder == null && decoderCanMeetPerformancePointWithAv1AndNotAvc(decoderInfo, avcDecoder, prefs)) {
|
||||||
|
LimeLog.info("Using non-whitelisted AV1 decoder to meet performance point");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return decoderInfo;
|
||||||
|
}
|
||||||
|
|
||||||
public void setRenderTarget(SurfaceHolder renderTarget) {
|
public void setRenderTarget(SurfaceHolder renderTarget) {
|
||||||
this.renderTarget = renderTarget;
|
this.renderTarget = renderTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MediaCodecDecoderRenderer(Context context, PreferenceConfiguration prefs,
|
public MediaCodecDecoderRenderer(Activity activity, PreferenceConfiguration prefs,
|
||||||
CrashListener crashListener, int consecutiveCrashCount,
|
CrashListener crashListener, int consecutiveCrashCount,
|
||||||
boolean meteredData, boolean requestedHdr,
|
boolean meteredData, boolean requestedHdr,
|
||||||
String glRenderer, PerfOverlayListener perfListener) {
|
String glRenderer, PerfOverlayListener perfListener) {
|
||||||
//dumpDecoders();
|
//dumpDecoders();
|
||||||
|
|
||||||
this.context = context;
|
this.context = activity;
|
||||||
|
this.activity = activity;
|
||||||
this.prefs = prefs;
|
this.prefs = prefs;
|
||||||
this.crashListener = crashListener;
|
this.crashListener = crashListener;
|
||||||
this.consecutiveCrashCount = consecutiveCrashCount;
|
this.consecutiveCrashCount = consecutiveCrashCount;
|
||||||
@@ -264,6 +307,14 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
LimeLog.info("No HEVC decoder found");
|
LimeLog.info("No HEVC decoder found");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
av1Decoder = findAv1Decoder(prefs);
|
||||||
|
if (av1Decoder != null) {
|
||||||
|
LimeLog.info("Selected AV1 decoder: "+av1Decoder.getName());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LimeLog.info("No AV1 decoder found");
|
||||||
|
}
|
||||||
|
|
||||||
// Set attributes that are queried in getCapabilities(). This must be done here
|
// Set attributes that are queried in getCapabilities(). This must be done here
|
||||||
// because getCapabilities() may be called before setup() in current versions of the common
|
// because getCapabilities() may be called before setup() in current versions of the common
|
||||||
// library. The limitation of this is that we don't know whether we're using HEVC or AVC.
|
// library. The limitation of this is that we don't know whether we're using HEVC or AVC.
|
||||||
@@ -271,7 +322,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
int hevcOptimalSlicesPerFrame = 0;
|
int hevcOptimalSlicesPerFrame = 0;
|
||||||
if (avcDecoder != null) {
|
if (avcDecoder != null) {
|
||||||
directSubmit = MediaCodecHelper.decoderCanDirectSubmit(avcDecoder.getName());
|
directSubmit = MediaCodecHelper.decoderCanDirectSubmit(avcDecoder.getName());
|
||||||
refFrameInvalidationAvc = MediaCodecHelper.decoderSupportsRefFrameInvalidationAvc(avcDecoder.getName(), prefs.resolution.height);
|
refFrameInvalidationAvc = MediaCodecHelper.decoderSupportsRefFrameInvalidationAvc(avcDecoder.getName(), prefs.height);
|
||||||
avcOptimalSlicesPerFrame = MediaCodecHelper.getDecoderOptimalSlicesPerFrame(avcDecoder.getName());
|
avcOptimalSlicesPerFrame = MediaCodecHelper.getDecoderOptimalSlicesPerFrame(avcDecoder.getName());
|
||||||
|
|
||||||
if (directSubmit) {
|
if (directSubmit) {
|
||||||
@@ -294,6 +345,14 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
LimeLog.info("Decoder "+hevcDecoder.getName()+" wants "+hevcOptimalSlicesPerFrame+" slices per frame");
|
LimeLog.info("Decoder "+hevcDecoder.getName()+" wants "+hevcOptimalSlicesPerFrame+" slices per frame");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (av1Decoder != null) {
|
||||||
|
refFrameInvalidationAv1 = MediaCodecHelper.decoderSupportsRefFrameInvalidationAv1(av1Decoder);
|
||||||
|
|
||||||
|
if (refFrameInvalidationAv1) {
|
||||||
|
LimeLog.info("Decoder "+av1Decoder.getName()+" will use reference frame invalidation for AV1");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Use the larger of the two slices per frame preferences
|
// Use the larger of the two slices per frame preferences
|
||||||
optimalSlicesPerFrame = (byte)Math.max(avcOptimalSlicesPerFrame, hevcOptimalSlicesPerFrame);
|
optimalSlicesPerFrame = (byte)Math.max(avcOptimalSlicesPerFrame, hevcOptimalSlicesPerFrame);
|
||||||
LimeLog.info("Requesting "+optimalSlicesPerFrame+" slices per frame");
|
LimeLog.info("Requesting "+optimalSlicesPerFrame+" slices per frame");
|
||||||
@@ -327,13 +386,49 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isAv1Supported() {
|
||||||
|
return av1Decoder != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAv1Main10Supported() {
|
||||||
|
if (av1Decoder == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (MediaCodecInfo.CodecProfileLevel profileLevel : av1Decoder.getCapabilitiesForType("video/av01").profileLevels) {
|
||||||
|
if (profileLevel.profile == MediaCodecInfo.CodecProfileLevel.AV1ProfileMain10HDR10) {
|
||||||
|
LimeLog.info("AV1 decoder "+av1Decoder.getName()+" supports AV1 Main 10 HDR10");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public int getPreferredColorSpace() {
|
public int getPreferredColorSpace() {
|
||||||
|
// Default to Rec 709 which is probably better supported on modern devices.
|
||||||
|
//
|
||||||
|
// We are sticking to Rec 601 on older devices unless the device has an HEVC decoder
|
||||||
|
// to avoid possible regressions (and they are < 5% of installed devices). If we have
|
||||||
|
// an HEVC decoder, we will use Rec 709 (even for H.264) since we can't choose a
|
||||||
|
// colorspace by codec (and it's probably safe to say a SoC with HEVC decoding is
|
||||||
|
// plenty modern enough to handle H.264 VUI colorspace info).
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O || hevcDecoder != null || av1Decoder != null) {
|
||||||
|
return MoonBridge.COLORSPACE_REC_709;
|
||||||
|
}
|
||||||
|
else {
|
||||||
return MoonBridge.COLORSPACE_REC_601;
|
return MoonBridge.COLORSPACE_REC_601;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public int getPreferredColorRange() {
|
public int getPreferredColorRange() {
|
||||||
|
if (prefs.fullRange) {
|
||||||
|
return MoonBridge.COLOR_RANGE_FULL;
|
||||||
|
}
|
||||||
|
else {
|
||||||
return MoonBridge.COLOR_RANGE_LIMITED;
|
return MoonBridge.COLOR_RANGE_LIMITED;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void notifyVideoForeground() {
|
public void notifyVideoForeground() {
|
||||||
foreground = true;
|
foreground = true;
|
||||||
@@ -355,17 +450,70 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
videoFormat.setInteger(MediaFormat.KEY_FRAME_RATE, refreshRate);
|
videoFormat.setInteger(MediaFormat.KEY_FRAME_RATE, refreshRate);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adaptive playback can also be enabled by the whitelist on pre-KitKat devices
|
// Populate keys for adaptive playback
|
||||||
// so we don't fill these pre-KitKat
|
if (adaptivePlayback) {
|
||||||
if (adaptivePlayback && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
|
||||||
videoFormat.setInteger(MediaFormat.KEY_MAX_WIDTH, initialWidth);
|
videoFormat.setInteger(MediaFormat.KEY_MAX_WIDTH, initialWidth);
|
||||||
videoFormat.setInteger(MediaFormat.KEY_MAX_HEIGHT, initialHeight);
|
videoFormat.setInteger(MediaFormat.KEY_MAX_HEIGHT, initialHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Android 7.0 adds color options to the MediaFormat
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
|
videoFormat.setInteger(MediaFormat.KEY_COLOR_RANGE,
|
||||||
|
getPreferredColorRange() == MoonBridge.COLOR_RANGE_FULL ?
|
||||||
|
MediaFormat.COLOR_RANGE_FULL : MediaFormat.COLOR_RANGE_LIMITED);
|
||||||
|
|
||||||
|
// If the stream is HDR-capable, the decoder will detect transitions in color standards
|
||||||
|
// rather than us hardcoding them into the MediaFormat.
|
||||||
|
if ((getActiveVideoFormat() & MoonBridge.VIDEO_FORMAT_MASK_10BIT) == 0) {
|
||||||
|
// Set color format keys when not in HDR mode, since we know they won't change
|
||||||
|
videoFormat.setInteger(MediaFormat.KEY_COLOR_TRANSFER, MediaFormat.COLOR_TRANSFER_SDR_VIDEO);
|
||||||
|
switch (getPreferredColorSpace()) {
|
||||||
|
case MoonBridge.COLORSPACE_REC_601:
|
||||||
|
videoFormat.setInteger(MediaFormat.KEY_COLOR_STANDARD, MediaFormat.COLOR_STANDARD_BT601_NTSC);
|
||||||
|
break;
|
||||||
|
case MoonBridge.COLORSPACE_REC_709:
|
||||||
|
videoFormat.setInteger(MediaFormat.KEY_COLOR_STANDARD, MediaFormat.COLOR_STANDARD_BT709);
|
||||||
|
break;
|
||||||
|
case MoonBridge.COLORSPACE_REC_2020:
|
||||||
|
videoFormat.setInteger(MediaFormat.KEY_COLOR_STANDARD, MediaFormat.COLOR_STANDARD_BT2020);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return videoFormat;
|
return videoFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void configureAndStartDecoder(MediaFormat format) {
|
private void configureAndStartDecoder(MediaFormat format) {
|
||||||
|
// Set HDR metadata if present
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
|
if (currentHdrMetadata != null) {
|
||||||
|
ByteBuffer hdrStaticInfo = ByteBuffer.allocate(25).order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
ByteBuffer hdrMetadata = ByteBuffer.wrap(currentHdrMetadata).order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
|
||||||
|
// Create a HDMI Dynamic Range and Mastering InfoFrame as defined by CTA-861.3
|
||||||
|
hdrStaticInfo.put((byte) 0); // Metadata type
|
||||||
|
hdrStaticInfo.putShort(hdrMetadata.getShort()); // RX
|
||||||
|
hdrStaticInfo.putShort(hdrMetadata.getShort()); // RY
|
||||||
|
hdrStaticInfo.putShort(hdrMetadata.getShort()); // GX
|
||||||
|
hdrStaticInfo.putShort(hdrMetadata.getShort()); // GY
|
||||||
|
hdrStaticInfo.putShort(hdrMetadata.getShort()); // BX
|
||||||
|
hdrStaticInfo.putShort(hdrMetadata.getShort()); // BY
|
||||||
|
hdrStaticInfo.putShort(hdrMetadata.getShort()); // White X
|
||||||
|
hdrStaticInfo.putShort(hdrMetadata.getShort()); // White Y
|
||||||
|
hdrStaticInfo.putShort(hdrMetadata.getShort()); // Max mastering luminance
|
||||||
|
hdrStaticInfo.putShort(hdrMetadata.getShort()); // Min mastering luminance
|
||||||
|
hdrStaticInfo.putShort(hdrMetadata.getShort()); // Max content luminance
|
||||||
|
hdrStaticInfo.putShort(hdrMetadata.getShort()); // Max frame average luminance
|
||||||
|
|
||||||
|
hdrStaticInfo.rewind();
|
||||||
|
format.setByteBuffer(MediaFormat.KEY_HDR_STATIC_INFO, hdrStaticInfo);
|
||||||
|
}
|
||||||
|
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||||
|
format.removeKey(MediaFormat.KEY_HDR_STATIC_INFO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LimeLog.info("Configuring with format: "+format);
|
LimeLog.info("Configuring with format: "+format);
|
||||||
|
|
||||||
videoDecoder.configure(format, renderTarget.getSurface(), null, 0);
|
videoDecoder.configure(format, renderTarget.getSurface(), null, 0);
|
||||||
@@ -374,25 +522,19 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
|
|
||||||
// After reconfiguration, we must resubmit CSD buffers
|
// After reconfiguration, we must resubmit CSD buffers
|
||||||
submittedCsd = false;
|
submittedCsd = false;
|
||||||
submitCsdNextCall = false;
|
vpsBuffers.clear();
|
||||||
vpsBuffer = null;
|
spsBuffers.clear();
|
||||||
spsBuffer = null;
|
ppsBuffers.clear();
|
||||||
ppsBuffer = null;
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
||||||
// This will contain the actual accepted input format attributes
|
// This will contain the actual accepted input format attributes
|
||||||
inputFormat = videoDecoder.getInputFormat();
|
inputFormat = videoDecoder.getInputFormat();
|
||||||
LimeLog.info("Input format: "+inputFormat);
|
LimeLog.info("Input format: "+inputFormat);
|
||||||
}
|
|
||||||
|
|
||||||
videoDecoder.setVideoScalingMode(MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT);
|
videoDecoder.setVideoScalingMode(MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT);
|
||||||
|
|
||||||
// Start the decoder
|
// Start the decoder
|
||||||
videoDecoder.start();
|
videoDecoder.start();
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
|
||||||
legacyInputBuffers = videoDecoder.getInputBuffers();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean tryConfigureDecoder(MediaCodecInfo selectedDecoderInfo, MediaFormat format, boolean throwOnCodecError) {
|
private boolean tryConfigureDecoder(MediaCodecInfo selectedDecoderInfo, MediaFormat format, boolean throwOnCodecError) {
|
||||||
@@ -475,6 +617,17 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
|
|
||||||
refFrameInvalidationActive = refFrameInvalidationHevc;
|
refFrameInvalidationActive = refFrameInvalidationHevc;
|
||||||
}
|
}
|
||||||
|
else if ((videoFormat & MoonBridge.VIDEO_FORMAT_MASK_AV1) != 0) {
|
||||||
|
mimeType = "video/av01";
|
||||||
|
selectedDecoderInfo = av1Decoder;
|
||||||
|
|
||||||
|
if (av1Decoder == null) {
|
||||||
|
LimeLog.severe("No available AV1 decoder!");
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
refFrameInvalidationActive = refFrameInvalidationAv1;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
// Unknown format
|
// Unknown format
|
||||||
LimeLog.severe("Unknown format");
|
LimeLog.severe("Unknown format");
|
||||||
@@ -601,7 +754,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
|
|
||||||
// For "non-recoverable" exceptions on L+, we can call reset() to recover
|
// For "non-recoverable" exceptions on L+, we can call reset() to recover
|
||||||
// without having to recreate the entire decoder again.
|
// without having to recreate the entire decoder again.
|
||||||
if (codecRecoveryType.get() == CR_RECOVERY_TYPE_RESET && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
if (codecRecoveryType.get() == CR_RECOVERY_TYPE_RESET) {
|
||||||
LimeLog.warning("Trying to reset decoder after CodecException");
|
LimeLog.warning("Trying to reset decoder after CodecException");
|
||||||
try {
|
try {
|
||||||
videoDecoder.reset();
|
videoDecoder.reset();
|
||||||
@@ -656,14 +809,10 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
else {
|
else {
|
||||||
// If we haven't quiesced all threads yet, wait to be signalled after recovery.
|
// If we haven't quiesced all threads yet, wait to be signalled after recovery.
|
||||||
// The final thread to be quiesced will handle the codec recovery.
|
// The final thread to be quiesced will handle the codec recovery.
|
||||||
LimeLog.info("Waiting to quiesce decoder threads: "+codecRecoveryThreadQuiescedFlags);
|
|
||||||
long startTime = SystemClock.uptimeMillis();
|
|
||||||
while (codecRecoveryType.get() != CR_RECOVERY_TYPE_NONE) {
|
while (codecRecoveryType.get() != CR_RECOVERY_TYPE_NONE) {
|
||||||
try {
|
try {
|
||||||
if (SystemClock.uptimeMillis() - startTime >= CR_TIMEOUT_MS) {
|
LimeLog.info("Waiting to quiesce decoder threads: "+codecRecoveryThreadQuiescedFlags);
|
||||||
throw new IllegalStateException("Decoder failed to recover within timeout");
|
codecRecoveryMonitor.wait(1000);
|
||||||
}
|
|
||||||
codecRecoveryMonitor.wait(CR_TIMEOUT_MS);
|
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
|
||||||
@@ -688,7 +837,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && e instanceof CodecException) {
|
if (e instanceof CodecException) {
|
||||||
CodecException codecExc = (CodecException) e;
|
CodecException codecExc = (CodecException) e;
|
||||||
|
|
||||||
if (codecExc.isTransient()) {
|
if (codecExc.isTransient()) {
|
||||||
@@ -802,6 +951,8 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
frameTimeNanos -= activity.getWindowManager().getDefaultDisplay().getAppVsyncOffsetNanos();
|
||||||
|
|
||||||
// Don't render unless a new frame is due. This prevents microstutter when streaming
|
// Don't render unless a new frame is due. This prevents microstutter when streaming
|
||||||
// at a frame rate that doesn't match the display (such as 60 FPS on 120 Hz).
|
// at a frame rate that doesn't match the display (such as 60 FPS on 120 Hz).
|
||||||
long actualFrameTimeDeltaNs = frameTimeNanos - lastRenderedFrameTimeNanos;
|
long actualFrameTimeDeltaNs = frameTimeNanos - lastRenderedFrameTimeNanos;
|
||||||
@@ -815,12 +966,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
Integer nextOutputBuffer = outputBufferQueue.poll();
|
Integer nextOutputBuffer = outputBufferQueue.poll();
|
||||||
if (nextOutputBuffer != null) {
|
if (nextOutputBuffer != null) {
|
||||||
try {
|
try {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
||||||
videoDecoder.releaseOutputBuffer(nextOutputBuffer, frameTimeNanos);
|
videoDecoder.releaseOutputBuffer(nextOutputBuffer, frameTimeNanos);
|
||||||
}
|
|
||||||
else {
|
|
||||||
videoDecoder.releaseOutputBuffer(nextOutputBuffer, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
lastRenderedFrameTimeNanos = frameTimeNanos;
|
lastRenderedFrameTimeNanos = frameTimeNanos;
|
||||||
activeWindowVideoStats.totalFramesRendered++;
|
activeWindowVideoStats.totalFramesRendered++;
|
||||||
@@ -896,24 +1042,14 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
if (prefs.framePacing == PreferenceConfiguration.FRAME_PACING_MAX_SMOOTHNESS ||
|
if (prefs.framePacing == PreferenceConfiguration.FRAME_PACING_MAX_SMOOTHNESS ||
|
||||||
prefs.framePacing == PreferenceConfiguration.FRAME_PACING_CAP_FPS) {
|
prefs.framePacing == PreferenceConfiguration.FRAME_PACING_CAP_FPS) {
|
||||||
// In max smoothness or cap FPS mode, we want to never drop frames
|
// In max smoothness or cap FPS mode, we want to never drop frames
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
||||||
// Use a PTS that will cause this frame to never be dropped
|
// Use a PTS that will cause this frame to never be dropped
|
||||||
videoDecoder.releaseOutputBuffer(lastIndex, 0);
|
videoDecoder.releaseOutputBuffer(lastIndex, 0);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
videoDecoder.releaseOutputBuffer(lastIndex, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
||||||
// Use a PTS that will cause this frame to be dropped if another comes in within
|
// Use a PTS that will cause this frame to be dropped if another comes in within
|
||||||
// the same V-sync period
|
// the same V-sync period
|
||||||
videoDecoder.releaseOutputBuffer(lastIndex, System.nanoTime());
|
videoDecoder.releaseOutputBuffer(lastIndex, System.nanoTime());
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
videoDecoder.releaseOutputBuffer(lastIndex, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
activeWindowVideoStats.totalFramesRendered++;
|
activeWindowVideoStats.totalFramesRendered++;
|
||||||
}
|
}
|
||||||
@@ -995,7 +1131,6 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
if (nextInputBufferIndex >= 0) {
|
if (nextInputBufferIndex >= 0) {
|
||||||
// Using the new getInputBuffer() API on Lollipop allows
|
// Using the new getInputBuffer() API on Lollipop allows
|
||||||
// the framework to do some performance optimizations for us
|
// the framework to do some performance optimizations for us
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
||||||
nextInputBuffer = videoDecoder.getInputBuffer(nextInputBufferIndex);
|
nextInputBuffer = videoDecoder.getInputBuffer(nextInputBufferIndex);
|
||||||
if (nextInputBuffer == null) {
|
if (nextInputBuffer == null) {
|
||||||
// According to the Android docs, getInputBuffer() can return null "if the
|
// According to the Android docs, getInputBuffer() can return null "if the
|
||||||
@@ -1004,13 +1139,6 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
nextInputBufferIndex = -1;
|
nextInputBufferIndex = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
nextInputBuffer = legacyInputBuffers[nextInputBufferIndex];
|
|
||||||
|
|
||||||
// Clear old input data pre-Lollipop
|
|
||||||
nextInputBuffer.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (IllegalStateException e) {
|
} catch (IllegalStateException e) {
|
||||||
handleDecoderException(e);
|
handleDecoderException(e);
|
||||||
return false;
|
return false;
|
||||||
@@ -1123,8 +1251,33 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setHdrMode(boolean enabled) {
|
public void setHdrMode(boolean enabled, byte[] hdrMetadata) {
|
||||||
// TODO: Set HDR metadata?
|
// HDR metadata is only supported in Android 7.0 and later, so don't bother
|
||||||
|
// restarting the codec on anything earlier than that.
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
|
if (currentHdrMetadata != null && (!enabled || hdrMetadata == null)) {
|
||||||
|
currentHdrMetadata = null;
|
||||||
|
}
|
||||||
|
else if (enabled && hdrMetadata != null && !Arrays.equals(currentHdrMetadata, hdrMetadata)) {
|
||||||
|
currentHdrMetadata = hdrMetadata;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Nothing to do
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we reach this point, we need to restart the MediaCodec instance to
|
||||||
|
// pick up the HDR metadata change. This will happen on the next input
|
||||||
|
// or output buffer.
|
||||||
|
|
||||||
|
// HACK: Reset codec recovery attempt counter, since this is an expected "recovery"
|
||||||
|
codecRecoveryAttempts = 0;
|
||||||
|
|
||||||
|
// Promote None/Flush to Restart and leave Reset alone
|
||||||
|
if (!codecRecoveryType.compareAndSet(CR_RECOVERY_TYPE_NONE, CR_RECOVERY_TYPE_RESTART)) {
|
||||||
|
codecRecoveryType.compareAndSet(CR_RECOVERY_TYPE_FLUSH, CR_RECOVERY_TYPE_RESTART);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean queueNextInputBuffer(long timestampUs, int codecFlags) {
|
private boolean queueNextInputBuffer(long timestampUs, int codecFlags) {
|
||||||
@@ -1181,7 +1334,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
sps.constraintSet4Flag = true;
|
sps.constraintSet4Flag = true;
|
||||||
sps.constraintSet5Flag = true;
|
sps.constraintSet5Flag = true;
|
||||||
}
|
}
|
||||||
else {
|
else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
||||||
// Force the constraints unset otherwise (some may be set by default)
|
// Force the constraints unset otherwise (some may be set by default)
|
||||||
sps.constraintSet4Flag = false;
|
sps.constraintSet4Flag = false;
|
||||||
sps.constraintSet5Flag = false;
|
sps.constraintSet5Flag = false;
|
||||||
@@ -1191,7 +1344,8 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
@Override
|
@Override
|
||||||
public int submitDecodeUnit(byte[] decodeUnitData, int decodeUnitLength, int decodeUnitType,
|
public 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) {
|
||||||
if (stopping) {
|
if (stopping) {
|
||||||
// Don't bother if we're stopping
|
// Don't bother if we're stopping
|
||||||
return MoonBridge.DR_OK;
|
return MoonBridge.DR_OK;
|
||||||
@@ -1207,6 +1361,13 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
activeWindowVideoStats.frameLossEvents++;
|
activeWindowVideoStats.frameLossEvents++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset CSD data for each IDR frame
|
||||||
|
if (lastFrameNumber != frameNumber && frameType == MoonBridge.FRAME_TYPE_IDR) {
|
||||||
|
vpsBuffers.clear();
|
||||||
|
spsBuffers.clear();
|
||||||
|
ppsBuffers.clear();
|
||||||
|
}
|
||||||
|
|
||||||
lastFrameNumber = frameNumber;
|
lastFrameNumber = frameNumber;
|
||||||
|
|
||||||
// Flip stats windows roughly every second
|
// Flip stats windows roughly every second
|
||||||
@@ -1222,6 +1383,8 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
decoder = avcDecoder.getName();
|
decoder = avcDecoder.getName();
|
||||||
} else if ((videoFormat & MoonBridge.VIDEO_FORMAT_MASK_H265) != 0) {
|
} else if ((videoFormat & MoonBridge.VIDEO_FORMAT_MASK_H265) != 0) {
|
||||||
decoder = hevcDecoder.getName();
|
decoder = hevcDecoder.getName();
|
||||||
|
} else if ((videoFormat & MoonBridge.VIDEO_FORMAT_MASK_AV1) != 0) {
|
||||||
|
decoder = av1Decoder.getName();
|
||||||
} else {
|
} else {
|
||||||
decoder = "(unknown)";
|
decoder = "(unknown)";
|
||||||
}
|
}
|
||||||
@@ -1237,6 +1400,12 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
(float)lastTwo.framesLost / lastTwo.totalFrames * 100)).append('\n');
|
(float)lastTwo.framesLost / lastTwo.totalFrames * 100)).append('\n');
|
||||||
sb.append(context.getString(R.string.perf_overlay_netlatency,
|
sb.append(context.getString(R.string.perf_overlay_netlatency,
|
||||||
(int)(rttInfo >> 32), (int)rttInfo)).append('\n');
|
(int)(rttInfo >> 32), (int)rttInfo)).append('\n');
|
||||||
|
if (lastTwo.framesWithHostProcessingLatency > 0) {
|
||||||
|
sb.append(context.getString(R.string.perf_overlay_hostprocessinglatency,
|
||||||
|
(float)lastTwo.minHostProcessingLatency / 10,
|
||||||
|
(float)lastTwo.maxHostProcessingLatency / 10,
|
||||||
|
(float)lastTwo.totalHostProcessingLatency / 10 / lastTwo.framesWithHostProcessingLatency)).append('\n');
|
||||||
|
}
|
||||||
sb.append(context.getString(R.string.perf_overlay_dectime, decodeTimeMs));
|
sb.append(context.getString(R.string.perf_overlay_dectime, decodeTimeMs));
|
||||||
perfListener.onPerfUpdate(sb.toString());
|
perfListener.onPerfUpdate(sb.toString());
|
||||||
}
|
}
|
||||||
@@ -1247,9 +1416,10 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
activeWindowVideoStats.measurementStartTimestamp = SystemClock.uptimeMillis();
|
activeWindowVideoStats.measurementStartTimestamp = SystemClock.uptimeMillis();
|
||||||
}
|
}
|
||||||
|
|
||||||
long timestampUs;
|
boolean csdSubmittedForThisFrame = false;
|
||||||
int codecFlags = 0;
|
|
||||||
|
|
||||||
|
// IDR frames require special handling for CSD buffer submission
|
||||||
|
if (frameType == MoonBridge.FRAME_TYPE_IDR) {
|
||||||
// H264 SPS
|
// H264 SPS
|
||||||
if (decodeUnitType == MoonBridge.BUFFER_TYPE_SPS && (videoFormat & MoonBridge.VIDEO_FORMAT_MASK_H264) != 0) {
|
if (decodeUnitType == MoonBridge.BUFFER_TYPE_SPS && (videoFormat & MoonBridge.VIDEO_FORMAT_MASK_H264) != 0) {
|
||||||
numSpsIn++;
|
numSpsIn++;
|
||||||
@@ -1268,7 +1438,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
// Since we only need one frame buffered, we'll set the level as low as we can
|
// Since we only need one frame buffered, we'll set the level as low as we can
|
||||||
// for known resolution combinations. Reference frame invalidation may need
|
// for known resolution combinations. Reference frame invalidation may need
|
||||||
// these, so leave them be for those decoders.
|
// these, so leave them be for those decoders.
|
||||||
if (!refFrameInvalidationActive) {
|
if (!refFrameInvalidationActive && Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
||||||
if (initialWidth <= 720 && initialHeight <= 480 && refreshRate <= 60) {
|
if (initialWidth <= 720 && initialHeight <= 480 && refreshRate <= 60) {
|
||||||
// Max 5 buffered frames at 720x480x60
|
// Max 5 buffered frames at 720x480x60
|
||||||
LimeLog.info("Patching level_idc to 31");
|
LimeLog.info("Patching level_idc to 31");
|
||||||
@@ -1303,9 +1473,13 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
sps.numRefFrames = 1;
|
sps.numRefFrames = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// GFE 2.5.11 changed the SPS to add additional extensions
|
// GFE 2.5.11 changed the SPS to add additional extensions. Some devices don't like these
|
||||||
// Some devices don't like these so we remove them here on old devices.
|
// so we remove them here on old devices unless these devices also support HEVC.
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O && sps.vuiParams != null) {
|
// See getPreferredColorSpace() for further information.
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O &&
|
||||||
|
sps.vuiParams != null &&
|
||||||
|
hevcDecoder == null &&
|
||||||
|
av1Decoder == null) {
|
||||||
sps.vuiParams.videoSignalTypePresentFlag = false;
|
sps.vuiParams.videoSignalTypePresentFlag = false;
|
||||||
sps.vuiParams.colourDescriptionPresentFlag = false;
|
sps.vuiParams.colourDescriptionPresentFlag = false;
|
||||||
sps.vuiParams.chromaLocInfoPresentFlag = false;
|
sps.vuiParams.chromaLocInfoPresentFlag = false;
|
||||||
@@ -1372,65 +1546,97 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
// Annex B NALUs (including NALUs with escape sequences)
|
// Annex B NALUs (including NALUs with escape sequences)
|
||||||
ByteBuffer escapedNalu = H264Utils.writeSPS(sps, decodeUnitLength);
|
ByteBuffer escapedNalu = H264Utils.writeSPS(sps, decodeUnitLength);
|
||||||
|
|
||||||
// Batch this to submit together with PPS
|
// Construct the patched SPS
|
||||||
spsBuffer = new byte[startSeqLen + 1 + escapedNalu.limit()];
|
byte[] naluBuffer = new byte[startSeqLen + 1 + escapedNalu.limit()];
|
||||||
System.arraycopy(decodeUnitData, 0, spsBuffer, 0, startSeqLen + 1);
|
System.arraycopy(decodeUnitData, 0, naluBuffer, 0, startSeqLen + 1);
|
||||||
escapedNalu.get(spsBuffer, startSeqLen + 1, escapedNalu.limit());
|
escapedNalu.get(naluBuffer, startSeqLen + 1, escapedNalu.limit());
|
||||||
|
|
||||||
|
// Batch this to submit together with other CSD per AOSP docs
|
||||||
|
spsBuffers.add(naluBuffer);
|
||||||
return MoonBridge.DR_OK;
|
return MoonBridge.DR_OK;
|
||||||
}
|
}
|
||||||
else if (decodeUnitType == MoonBridge.BUFFER_TYPE_VPS) {
|
else if (decodeUnitType == MoonBridge.BUFFER_TYPE_VPS) {
|
||||||
numVpsIn++;
|
numVpsIn++;
|
||||||
|
|
||||||
// Batch this to submit together with SPS and PPS per AOSP docs
|
// Batch this to submit together with other CSD per AOSP docs
|
||||||
vpsBuffer = new byte[decodeUnitLength];
|
byte[] naluBuffer = new byte[decodeUnitLength];
|
||||||
System.arraycopy(decodeUnitData, 0, vpsBuffer, 0, decodeUnitLength);
|
System.arraycopy(decodeUnitData, 0, naluBuffer, 0, decodeUnitLength);
|
||||||
|
vpsBuffers.add(naluBuffer);
|
||||||
return MoonBridge.DR_OK;
|
return MoonBridge.DR_OK;
|
||||||
}
|
}
|
||||||
// Only the HEVC SPS hits this path (H.264 is handled above)
|
// Only the HEVC SPS hits this path (H.264 is handled above)
|
||||||
else if (decodeUnitType == MoonBridge.BUFFER_TYPE_SPS) {
|
else if (decodeUnitType == MoonBridge.BUFFER_TYPE_SPS) {
|
||||||
numSpsIn++;
|
numSpsIn++;
|
||||||
|
|
||||||
// Batch this to submit together with VPS and PPS per AOSP docs
|
// Batch this to submit together with other CSD per AOSP docs
|
||||||
spsBuffer = new byte[decodeUnitLength];
|
byte[] naluBuffer = new byte[decodeUnitLength];
|
||||||
System.arraycopy(decodeUnitData, 0, spsBuffer, 0, decodeUnitLength);
|
System.arraycopy(decodeUnitData, 0, naluBuffer, 0, decodeUnitLength);
|
||||||
|
spsBuffers.add(naluBuffer);
|
||||||
return MoonBridge.DR_OK;
|
return MoonBridge.DR_OK;
|
||||||
}
|
}
|
||||||
else if (decodeUnitType == MoonBridge.BUFFER_TYPE_PPS) {
|
else if (decodeUnitType == MoonBridge.BUFFER_TYPE_PPS) {
|
||||||
numPpsIn++;
|
numPpsIn++;
|
||||||
|
|
||||||
// If this is the first CSD blob or we aren't supporting
|
// Batch this to submit together with other CSD per AOSP docs
|
||||||
// fused IDR frames, we will submit the CSD blob in a
|
byte[] naluBuffer = new byte[decodeUnitLength];
|
||||||
// separate input buffer.
|
System.arraycopy(decodeUnitData, 0, naluBuffer, 0, decodeUnitLength);
|
||||||
|
ppsBuffers.add(naluBuffer);
|
||||||
|
return MoonBridge.DR_OK;
|
||||||
|
}
|
||||||
|
else if ((videoFormat & (MoonBridge.VIDEO_FORMAT_MASK_H264 | MoonBridge.VIDEO_FORMAT_MASK_H265)) != 0) {
|
||||||
|
// If this is the first CSD blob or we aren't supporting fused IDR frames, we will
|
||||||
|
// submit the CSD blob in a separate input buffer for each IDR frame.
|
||||||
if (!submittedCsd || !fusedIdrFrame) {
|
if (!submittedCsd || !fusedIdrFrame) {
|
||||||
if (!fetchNextInputBuffer()) {
|
if (!fetchNextInputBuffer()) {
|
||||||
return MoonBridge.DR_NEED_IDR;
|
return MoonBridge.DR_NEED_IDR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// When we get the PPS, submit the VPS and SPS together with
|
// Submit all CSD when we receive the first non-CSD blob in an IDR frame
|
||||||
// the PPS, as required by AOSP docs on use of MediaCodec.
|
for (byte[] vpsBuffer : vpsBuffers) {
|
||||||
if (vpsBuffer != null) {
|
|
||||||
nextInputBuffer.put(vpsBuffer);
|
nextInputBuffer.put(vpsBuffer);
|
||||||
}
|
}
|
||||||
if (spsBuffer != null) {
|
for (byte[] spsBuffer : spsBuffers) {
|
||||||
nextInputBuffer.put(spsBuffer);
|
nextInputBuffer.put(spsBuffer);
|
||||||
}
|
}
|
||||||
|
for (byte[] ppsBuffer : ppsBuffers) {
|
||||||
// This is the CSD blob
|
nextInputBuffer.put(ppsBuffer);
|
||||||
codecFlags |= MediaCodec.BUFFER_FLAG_CODEC_CONFIG;
|
|
||||||
timestampUs = 0;
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
// Batch this to submit together with the next I-frame
|
|
||||||
ppsBuffer = new byte[decodeUnitLength];
|
|
||||||
System.arraycopy(decodeUnitData, 0, ppsBuffer, 0, decodeUnitLength);
|
|
||||||
|
|
||||||
// Next call will be I-frame data
|
if (!queueNextInputBuffer(0, MediaCodec.BUFFER_FLAG_CODEC_CONFIG)) {
|
||||||
submitCsdNextCall = true;
|
return MoonBridge.DR_NEED_IDR;
|
||||||
|
}
|
||||||
|
|
||||||
return MoonBridge.DR_OK;
|
// Remember that we already submitted CSD for this frame, so we don't do it
|
||||||
|
// again in the fused IDR case below.
|
||||||
|
csdSubmittedForThisFrame = true;
|
||||||
|
|
||||||
|
// Remember that we submitted CSD globally for this MediaCodec instance
|
||||||
|
submittedCsd = true;
|
||||||
|
|
||||||
|
if (needsBaselineSpsHack) {
|
||||||
|
needsBaselineSpsHack = false;
|
||||||
|
|
||||||
|
if (!replaySps()) {
|
||||||
|
return MoonBridge.DR_NEED_IDR;
|
||||||
|
}
|
||||||
|
|
||||||
|
LimeLog.info("SPS replay complete");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frameHostProcessingLatency != 0) {
|
||||||
|
if (activeWindowVideoStats.minHostProcessingLatency != 0) {
|
||||||
|
activeWindowVideoStats.minHostProcessingLatency = (char) Math.min(activeWindowVideoStats.minHostProcessingLatency, frameHostProcessingLatency);
|
||||||
|
} else {
|
||||||
|
activeWindowVideoStats.minHostProcessingLatency = frameHostProcessingLatency;
|
||||||
|
}
|
||||||
|
activeWindowVideoStats.framesWithHostProcessingLatency += 1;
|
||||||
|
}
|
||||||
|
activeWindowVideoStats.maxHostProcessingLatency = (char) Math.max(activeWindowVideoStats.maxHostProcessingLatency, frameHostProcessingLatency);
|
||||||
|
activeWindowVideoStats.totalHostProcessingLatency += frameHostProcessingLatency;
|
||||||
|
|
||||||
activeWindowVideoStats.totalFramesReceived++;
|
activeWindowVideoStats.totalFramesReceived++;
|
||||||
activeWindowVideoStats.totalFrames++;
|
activeWindowVideoStats.totalFrames++;
|
||||||
|
|
||||||
@@ -1438,43 +1644,46 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
// Count time from first packet received to enqueue time as receive time
|
// Count time from first packet received to enqueue time as receive time
|
||||||
// We will count DU queue time as part of decoding, because it is directly
|
// We will count DU queue time as part of decoding, because it is directly
|
||||||
// caused by a slow decoder.
|
// caused by a slow decoder.
|
||||||
activeWindowVideoStats.totalTimeMs += enqueueTimeMs - receiveTimeMs;
|
activeWindowVideoStats.totalTimeMs += (enqueueTimeUs - receiveTimeUs) / 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fetchNextInputBuffer()) {
|
if (!fetchNextInputBuffer()) {
|
||||||
return MoonBridge.DR_NEED_IDR;
|
return MoonBridge.DR_NEED_IDR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (submitCsdNextCall) {
|
int codecFlags = 0;
|
||||||
if (vpsBuffer != null) {
|
|
||||||
nextInputBuffer.put(vpsBuffer);
|
|
||||||
}
|
|
||||||
if (spsBuffer != null) {
|
|
||||||
nextInputBuffer.put(spsBuffer);
|
|
||||||
}
|
|
||||||
if (ppsBuffer != null) {
|
|
||||||
nextInputBuffer.put(ppsBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
submitCsdNextCall = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (frameType == MoonBridge.FRAME_TYPE_IDR) {
|
if (frameType == MoonBridge.FRAME_TYPE_IDR) {
|
||||||
codecFlags |= MediaCodec.BUFFER_FLAG_SYNC_FRAME;
|
codecFlags |= MediaCodec.BUFFER_FLAG_SYNC_FRAME;
|
||||||
|
|
||||||
|
// If we are using fused IDR frames, submit the CSD with each IDR frame
|
||||||
|
if (fusedIdrFrame && !csdSubmittedForThisFrame) {
|
||||||
|
for (byte[] vpsBuffer : vpsBuffers) {
|
||||||
|
nextInputBuffer.put(vpsBuffer);
|
||||||
|
}
|
||||||
|
for (byte[] spsBuffer : spsBuffers) {
|
||||||
|
nextInputBuffer.put(spsBuffer);
|
||||||
|
}
|
||||||
|
for (byte[] ppsBuffer : ppsBuffers) {
|
||||||
|
nextInputBuffer.put(ppsBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
timestampUs = enqueueTimeMs * 1000;
|
// The frame timestamps use an undefined epoch, so normalize them to uptime microseconds.
|
||||||
|
if (baseTimestampUs == 0) {
|
||||||
|
baseTimestampUs = (SystemClock.uptimeMillis() * 1000) - enqueueTimeUs;
|
||||||
|
}
|
||||||
|
|
||||||
|
long timestampUs = baseTimestampUs + enqueueTimeUs;
|
||||||
if (timestampUs <= lastTimestampUs) {
|
if (timestampUs <= lastTimestampUs) {
|
||||||
// We can't submit multiple buffers with the same timestamp
|
// We can't submit multiple buffers with the same timestamp
|
||||||
// so bump it up by one before queuing
|
// so bump it up by one before queuing
|
||||||
timestampUs = lastTimestampUs + 1;
|
timestampUs = lastTimestampUs + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
lastTimestampUs = timestampUs;
|
lastTimestampUs = timestampUs;
|
||||||
|
|
||||||
numFramesIn++;
|
numFramesIn++;
|
||||||
}
|
|
||||||
|
|
||||||
if (decodeUnitLength > nextInputBuffer.limit() - nextInputBuffer.position()) {
|
if (decodeUnitLength > nextInputBuffer.limit() - nextInputBuffer.position()) {
|
||||||
IllegalArgumentException exception = new IllegalArgumentException(
|
IllegalArgumentException exception = new IllegalArgumentException(
|
||||||
@@ -1493,20 +1702,6 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
return MoonBridge.DR_NEED_IDR;
|
return MoonBridge.DR_NEED_IDR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((codecFlags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
|
|
||||||
submittedCsd = true;
|
|
||||||
|
|
||||||
if (needsBaselineSpsHack) {
|
|
||||||
needsBaselineSpsHack = false;
|
|
||||||
|
|
||||||
if (!replaySps()) {
|
|
||||||
return MoonBridge.DR_NEED_IDR;
|
|
||||||
}
|
|
||||||
|
|
||||||
LimeLog.info("SPS replay complete");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return MoonBridge.DR_OK;
|
return MoonBridge.DR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1550,6 +1745,9 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
if (refFrameInvalidationHevc) {
|
if (refFrameInvalidationHevc) {
|
||||||
capabilities |= MoonBridge.CAPABILITY_REFERENCE_FRAME_INVALIDATION_HEVC;
|
capabilities |= MoonBridge.CAPABILITY_REFERENCE_FRAME_INVALIDATION_HEVC;
|
||||||
}
|
}
|
||||||
|
if (refFrameInvalidationAv1) {
|
||||||
|
capabilities |= MoonBridge.CAPABILITY_REFERENCE_FRAME_INVALIDATION_AV1;
|
||||||
|
}
|
||||||
|
|
||||||
// Enable direct submit on supported hardware
|
// Enable direct submit on supported hardware
|
||||||
if (directSubmit) {
|
if (directSubmit) {
|
||||||
@@ -1632,7 +1830,8 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
str += "Format: "+String.format("%x", renderer.videoFormat)+DELIMITER;
|
str += "Format: "+String.format("%x", renderer.videoFormat)+DELIMITER;
|
||||||
str += "AVC Decoder: "+((renderer.avcDecoder != null) ? renderer.avcDecoder.getName():"(none)")+DELIMITER;
|
str += "AVC Decoder: "+((renderer.avcDecoder != null) ? renderer.avcDecoder.getName():"(none)")+DELIMITER;
|
||||||
str += "HEVC Decoder: "+((renderer.hevcDecoder != null) ? renderer.hevcDecoder.getName():"(none)")+DELIMITER;
|
str += "HEVC Decoder: "+((renderer.hevcDecoder != null) ? renderer.hevcDecoder.getName():"(none)")+DELIMITER;
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && renderer.avcDecoder != null) {
|
str += "AV1 Decoder: "+((renderer.av1Decoder != null) ? renderer.av1Decoder.getName():"(none)")+DELIMITER;
|
||||||
|
if (renderer.avcDecoder != null) {
|
||||||
Range<Integer> avcWidthRange = renderer.avcDecoder.getCapabilitiesForType("video/avc").getVideoCapabilities().getSupportedWidths();
|
Range<Integer> avcWidthRange = renderer.avcDecoder.getCapabilitiesForType("video/avc").getVideoCapabilities().getSupportedWidths();
|
||||||
str += "AVC supported width range: "+avcWidthRange+DELIMITER;
|
str += "AVC supported width range: "+avcWidthRange+DELIMITER;
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
@@ -1644,7 +1843,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && renderer.hevcDecoder != null) {
|
if (renderer.hevcDecoder != null) {
|
||||||
Range<Integer> hevcWidthRange = renderer.hevcDecoder.getCapabilitiesForType("video/hevc").getVideoCapabilities().getSupportedWidths();
|
Range<Integer> hevcWidthRange = renderer.hevcDecoder.getCapabilitiesForType("video/hevc").getVideoCapabilities().getSupportedWidths();
|
||||||
str += "HEVC supported width range: "+hevcWidthRange+DELIMITER;
|
str += "HEVC supported width range: "+hevcWidthRange+DELIMITER;
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
@@ -1656,6 +1855,18 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (renderer.av1Decoder != null) {
|
||||||
|
Range<Integer> av1WidthRange = renderer.av1Decoder.getCapabilitiesForType("video/av01").getVideoCapabilities().getSupportedWidths();
|
||||||
|
str += "AV1 supported width range: "+av1WidthRange+DELIMITER;
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
try {
|
||||||
|
Range<Double> av1FpsRange = renderer.av1Decoder.getCapabilitiesForType("video/av01").getVideoCapabilities().getAchievableFrameRatesFor(renderer.initialWidth, renderer.initialHeight);
|
||||||
|
str += "AV1 achievable FPS range: " + av1FpsRange + DELIMITER;
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
str += "AV1 achievable FPS range: UNSUPPORTED!"+DELIMITER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
str += "Configured format: "+renderer.configuredFormat+DELIMITER;
|
str += "Configured format: "+renderer.configuredFormat+DELIMITER;
|
||||||
str += "Input format: "+renderer.inputFormat+DELIMITER;
|
str += "Input format: "+renderer.inputFormat+DELIMITER;
|
||||||
str += "Output format: "+renderer.outputFormat+DELIMITER;
|
str += "Output format: "+renderer.outputFormat+DELIMITER;
|
||||||
@@ -1693,7 +1904,6 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
str += "Average hardware decoder latency: "+renderer.getAverageDecoderLatency()+"ms"+DELIMITER;
|
str += "Average hardware decoder latency: "+renderer.getAverageDecoderLatency()+"ms"+DELIMITER;
|
||||||
str += "Frame pacing mode: "+renderer.prefs.framePacing+DELIMITER;
|
str += "Frame pacing mode: "+renderer.prefs.framePacing+DELIMITER;
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
||||||
if (originalException instanceof CodecException) {
|
if (originalException instanceof CodecException) {
|
||||||
CodecException ce = (CodecException) originalException;
|
CodecException ce = (CodecException) originalException;
|
||||||
|
|
||||||
@@ -1705,7 +1915,6 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
str += "Codec Error Code: " + ce.getErrorCode() + DELIMITER;
|
str += "Codec Error Code: " + ce.getErrorCode() + DELIMITER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
str += originalException.toString();
|
str += originalException.toString();
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package com.limelight.binding.video;
|
|||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileReader;
|
import java.io.FileReader;
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -78,12 +77,6 @@ public class MediaCodecHelper {
|
|||||||
refFrameInvalidationHevcPrefixes.add("omx.exynos");
|
refFrameInvalidationHevcPrefixes.add("omx.exynos");
|
||||||
refFrameInvalidationHevcPrefixes.add("c2.exynos");
|
refFrameInvalidationHevcPrefixes.add("c2.exynos");
|
||||||
|
|
||||||
// The Chromecast with Google TV 4K works well with HEVC RFI since we also use the
|
|
||||||
// vendor.low-latency.enable option.
|
|
||||||
if (Build.DEVICE.equalsIgnoreCase("sabrina")) {
|
|
||||||
refFrameInvalidationHevcPrefixes.add("omx.amlogic");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Qualcomm and NVIDIA may be added at runtime
|
// Qualcomm and NVIDIA may be added at runtime
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,6 +177,9 @@ public class MediaCodecHelper {
|
|||||||
// vendor.low-latency.enable. We will still use HEVC if decoderCanMeetPerformancePointWithHevcAndNotAvc()
|
// vendor.low-latency.enable. We will still use HEVC if decoderCanMeetPerformancePointWithHevcAndNotAvc()
|
||||||
// determines it's the only way to meet the performance requirements.
|
// determines it's the only way to meet the performance requirements.
|
||||||
//
|
//
|
||||||
|
// With the Android 12 update, Sabrina now uses HEVC (with RFI) based upon FEATURE_LowLatency
|
||||||
|
// support, which provides equivalent latency to H.264 now.
|
||||||
|
//
|
||||||
// FIXME: Should we do this for all Amlogic S905X SoCs?
|
// FIXME: Should we do this for all Amlogic S905X SoCs?
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && !Build.DEVICE.equalsIgnoreCase("sabrina")) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && !Build.DEVICE.equalsIgnoreCase("sabrina")) {
|
||||||
whitelistedHevcDecoders.add("omx.amlogic");
|
whitelistedHevcDecoders.add("omx.amlogic");
|
||||||
@@ -360,7 +356,14 @@ public class MediaCodecHelper {
|
|||||||
if (configInfo.reqGlEsVersion >= 0x30000) {
|
if (configInfo.reqGlEsVersion >= 0x30000) {
|
||||||
LimeLog.info("Added omx.nvidia/c2.nvidia to reference frame invalidation support list");
|
LimeLog.info("Added omx.nvidia/c2.nvidia to reference frame invalidation support list");
|
||||||
refFrameInvalidationAvcPrefixes.add("omx.nvidia");
|
refFrameInvalidationAvcPrefixes.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");
|
refFrameInvalidationHevcPrefixes.add("omx.nvidia");
|
||||||
|
}
|
||||||
|
|
||||||
refFrameInvalidationAvcPrefixes.add("c2.nvidia"); // Unconfirmed
|
refFrameInvalidationAvcPrefixes.add("c2.nvidia"); // Unconfirmed
|
||||||
refFrameInvalidationHevcPrefixes.add("c2.nvidia"); // Unconfirmed
|
refFrameInvalidationHevcPrefixes.add("c2.nvidia"); // Unconfirmed
|
||||||
|
|
||||||
@@ -526,6 +529,17 @@ public class MediaCodecHelper {
|
|||||||
setNewOption = true;
|
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.
|
// 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.
|
// 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
|
// https://cs.android.com/android/platform/superproject/+/master:hardware/qcom/sdm845/media/mm-video-v4l2/vidc/common/inc/vidc_vendor_extensions.h;l=67
|
||||||
@@ -542,17 +556,17 @@ public class MediaCodecHelper {
|
|||||||
// https://cs.android.com/android/_/android/platform/hardware/qcom/sm8150/media/+/0621ceb1c1b19564999db8293574a0e12952ff6c
|
// 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
|
// 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);
|
videoFormat.setInteger("vendor.qti-ext-dec-picture-order.enable", 1);
|
||||||
setNewOption = true;
|
setNewOption = true;
|
||||||
}
|
}
|
||||||
if (tryNumber < 4) {
|
if (tryNumber < 5) {
|
||||||
videoFormat.setInteger("vendor.qti-ext-dec-low-latency.enable", 1);
|
videoFormat.setInteger("vendor.qti-ext-dec-low-latency.enable", 1);
|
||||||
setNewOption = true;
|
setNewOption = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (isDecoderInList(kirinDecoderPrefixes, decoderInfo.getName())) {
|
else if (isDecoderInList(kirinDecoderPrefixes, decoderInfo.getName())) {
|
||||||
if (tryNumber < 3) {
|
if (tryNumber < 4) {
|
||||||
// Kirin low latency options
|
// Kirin low latency options
|
||||||
// https://developer.huawei.com/consumer/cn/forum/topic/0202325564295980115
|
// 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);
|
videoFormat.setInteger("vendor.hisi-ext-low-latency-video-dec.video-scene-for-low-latency-req", 1);
|
||||||
@@ -561,14 +575,14 @@ public class MediaCodecHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (isDecoderInList(exynosDecoderPrefixes, decoderInfo.getName())) {
|
else if (isDecoderInList(exynosDecoderPrefixes, decoderInfo.getName())) {
|
||||||
if (tryNumber < 3) {
|
if (tryNumber < 4) {
|
||||||
// Exynos low latency option for H.264 decoder
|
// Exynos low latency option for H.264 decoder
|
||||||
videoFormat.setInteger("vendor.rtc-ext-dec-low-latency.enable", 1);
|
videoFormat.setInteger("vendor.rtc-ext-dec-low-latency.enable", 1);
|
||||||
setNewOption = true;
|
setNewOption = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (isDecoderInList(amlogicDecoderPrefixes, decoderInfo.getName())) {
|
else if (isDecoderInList(amlogicDecoderPrefixes, decoderInfo.getName())) {
|
||||||
if (tryNumber < 3) {
|
if (tryNumber < 4) {
|
||||||
// Amlogic low latency vendor extension
|
// Amlogic low latency vendor extension
|
||||||
// https://github.com/codewalkerster/android_vendor_amlogic_common_prebuilt_libstagefrighthw/commit/41fefc4e035c476d58491324a5fe7666bfc2989e
|
// https://github.com/codewalkerster/android_vendor_amlogic_common_prebuilt_libstagefrighthw/commit/41fefc4e035c476d58491324a5fe7666bfc2989e
|
||||||
videoFormat.setInteger("vendor.low-latency.enable", 1);
|
videoFormat.setInteger("vendor.low-latency.enable", 1);
|
||||||
@@ -577,21 +591,14 @@ 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;
|
return setNewOption;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean decoderSupportsFusedIdrFrame(MediaCodecInfo decoderInfo, String mimeType) {
|
public static boolean decoderSupportsFusedIdrFrame(MediaCodecInfo decoderInfo, String mimeType) {
|
||||||
// If adaptive playback is supported, we can submit new CSD together with a keyframe
|
// If adaptive playback is supported, we can submit new CSD together with a keyframe
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
|
||||||
try {
|
try {
|
||||||
if (decoderInfo.getCapabilitiesForType(mimeType).
|
if (decoderInfo.getCapabilitiesForType(mimeType).
|
||||||
isFeatureSupported(CodecCapabilities.FEATURE_AdaptivePlayback))
|
isFeatureSupported(CodecCapabilities.FEATURE_AdaptivePlayback)) {
|
||||||
{
|
|
||||||
LimeLog.info("Decoder supports fused IDR frames (FEATURE_AdaptivePlayback)");
|
LimeLog.info("Decoder supports fused IDR frames (FEATURE_AdaptivePlayback)");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -599,14 +606,11 @@ public class MediaCodecHelper {
|
|||||||
// Tolerate buggy codecs
|
// Tolerate buggy codecs
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean decoderSupportsAdaptivePlayback(MediaCodecInfo decoderInfo, String mimeType) {
|
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())) {
|
if (isDecoderInList(blacklistedAdaptivePlaybackPrefixes, decoderInfo.getName())) {
|
||||||
LimeLog.info("Decoder blacklisted for adaptive playback");
|
LimeLog.info("Decoder blacklisted for adaptive playback");
|
||||||
return false;
|
return false;
|
||||||
@@ -624,7 +628,6 @@ public class MediaCodecHelper {
|
|||||||
// Tolerate buggy codecs
|
// Tolerate buggy codecs
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -688,14 +691,18 @@ public class MediaCodecHelper {
|
|||||||
return isDecoderInList(refFrameInvalidationHevcPrefixes, decoderInfo.getName());
|
return isDecoderInList(refFrameInvalidationHevcPrefixes, decoderInfo.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean decoderIsWhitelistedForHevc(MediaCodecInfo decoderInfo) {
|
public static boolean decoderSupportsRefFrameInvalidationAv1(MediaCodecInfo decoderInfo) {
|
||||||
// Google didn't have official support for HEVC (or more importantly, a CTS test) until
|
// We'll use the same heuristics as HEVC for now
|
||||||
// Lollipop. I've seen some MediaTek devices on 4.4 crash when attempting to use HEVC,
|
if (decoderSupportsAndroidRLowLatency(decoderInfo, "video/av01") ||
|
||||||
// so I'm restricting HEVC usage to Lollipop and higher.
|
decoderSupportsKnownVendorLowLatencyOption(decoderInfo.getName())) {
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
LimeLog.info("Enabling AV1 RFI based on low latency option support");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean decoderIsWhitelistedForHevc(MediaCodecInfo decoderInfo) {
|
||||||
//
|
//
|
||||||
// Software decoders are terrible and we never want to use them.
|
// Software decoders are terrible and we never want to use them.
|
||||||
// We want to catch decoders like:
|
// We want to catch decoders like:
|
||||||
@@ -715,19 +722,12 @@ public class MediaCodecHelper {
|
|||||||
// HEVC decoder present is fast and modern enough for streaming.
|
// HEVC decoder present is fast and modern enough for streaming.
|
||||||
//
|
//
|
||||||
// [5.3/H-1-1] MUST NOT drop more than 2 frames in 10 seconds (i.e less than 0.333 percent frame drop) for a 1080p 60 fps video session under load.
|
// [5.3/H-1-1] MUST NOT drop more than 2 frames in 10 seconds (i.e less than 0.333 percent frame drop) for a 1080p 60 fps video session under load.
|
||||||
//
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||||
// NB: We use reflection here because this field seems to be absent on Amazon Fire OS devices
|
LimeLog.info("Media performance class: " + Build.VERSION.MEDIA_PERFORMANCE_CLASS);
|
||||||
try {
|
if (Build.VERSION.MEDIA_PERFORMANCE_CLASS >= Build.VERSION_CODES.S) {
|
||||||
Field mediaClassField = Build.VERSION.class.getDeclaredField("MEDIA_PERFORMANCE_CLASS");
|
LimeLog.info("Allowing HEVC based on media performance class");
|
||||||
int mediaClass = mediaClassField.getInt(null);
|
|
||||||
if (mediaClass >= Build.VERSION_CODES.S) {
|
|
||||||
LimeLog.info("Allowing HEVC based on media performance class: " + mediaClass);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} catch (NoSuchFieldException e) {
|
|
||||||
LimeLog.info("Build.VERSION.MEDIA_PERFORMANCE_CLASS not present");
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the decoder supports FEATURE_LowLatency, we will assume it is fast and modern enough
|
// If the decoder supports FEATURE_LowLatency, we will assume it is fast and modern enough
|
||||||
@@ -741,20 +741,39 @@ public class MediaCodecHelper {
|
|||||||
return isDecoderInList(whitelistedHevcDecoders, decoderInfo.getName());
|
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")
|
@SuppressWarnings("deprecation")
|
||||||
@SuppressLint("NewApi")
|
@SuppressLint("NewApi")
|
||||||
private static LinkedList<MediaCodecInfo> getMediaCodecList() {
|
private static LinkedList<MediaCodecInfo> getMediaCodecList() {
|
||||||
LinkedList<MediaCodecInfo> infoList = new LinkedList<>();
|
LinkedList<MediaCodecInfo> infoList = new LinkedList<>();
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
||||||
MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
|
MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
|
||||||
Collections.addAll(infoList, mcl.getCodecInfos());
|
Collections.addAll(infoList, mcl.getCodecInfos());
|
||||||
}
|
|
||||||
else {
|
|
||||||
for (int i = 0; i < MediaCodecList.getCodecCount(); i++) {
|
|
||||||
infoList.add(MediaCodecList.getCodecInfoAt(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return infoList;
|
return infoList;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,10 @@ class VideoStats {
|
|||||||
int totalFramesRendered;
|
int totalFramesRendered;
|
||||||
int frameLossEvents;
|
int frameLossEvents;
|
||||||
int framesLost;
|
int framesLost;
|
||||||
|
char minHostProcessingLatency;
|
||||||
|
char maxHostProcessingLatency;
|
||||||
|
int totalHostProcessingLatency;
|
||||||
|
int framesWithHostProcessingLatency;
|
||||||
long measurementStartTimestamp;
|
long measurementStartTimestamp;
|
||||||
|
|
||||||
void add(VideoStats other) {
|
void add(VideoStats other) {
|
||||||
@@ -22,6 +26,15 @@ class VideoStats {
|
|||||||
this.frameLossEvents += other.frameLossEvents;
|
this.frameLossEvents += other.frameLossEvents;
|
||||||
this.framesLost += other.framesLost;
|
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) {
|
if (this.measurementStartTimestamp == 0) {
|
||||||
this.measurementStartTimestamp = other.measurementStartTimestamp;
|
this.measurementStartTimestamp = other.measurementStartTimestamp;
|
||||||
}
|
}
|
||||||
@@ -37,6 +50,10 @@ class VideoStats {
|
|||||||
this.totalFramesRendered = other.totalFramesRendered;
|
this.totalFramesRendered = other.totalFramesRendered;
|
||||||
this.frameLossEvents = other.frameLossEvents;
|
this.frameLossEvents = other.frameLossEvents;
|
||||||
this.framesLost = other.framesLost;
|
this.framesLost = other.framesLost;
|
||||||
|
this.minHostProcessingLatency = other.minHostProcessingLatency;
|
||||||
|
this.maxHostProcessingLatency = other.maxHostProcessingLatency;
|
||||||
|
this.totalHostProcessingLatency = other.totalHostProcessingLatency;
|
||||||
|
this.framesWithHostProcessingLatency = other.framesWithHostProcessingLatency;
|
||||||
this.measurementStartTimestamp = other.measurementStartTimestamp;
|
this.measurementStartTimestamp = other.measurementStartTimestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,6 +65,10 @@ class VideoStats {
|
|||||||
this.totalFramesRendered = 0;
|
this.totalFramesRendered = 0;
|
||||||
this.frameLossEvents = 0;
|
this.frameLossEvents = 0;
|
||||||
this.framesLost = 0;
|
this.framesLost = 0;
|
||||||
|
this.minHostProcessingLatency = 0;
|
||||||
|
this.maxHostProcessingLatency = 0;
|
||||||
|
this.totalHostProcessingLatency = 0;
|
||||||
|
this.framesWithHostProcessingLatency = 0;
|
||||||
this.measurementStartTimestamp = 0;
|
this.measurementStartTimestamp = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import java.util.LinkedList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import com.limelight.LimeLog;
|
||||||
import com.limelight.nvstream.http.ComputerDetails;
|
import com.limelight.nvstream.http.ComputerDetails;
|
||||||
import com.limelight.nvstream.http.NvHTTP;
|
import com.limelight.nvstream.http.NvHTTP;
|
||||||
|
|
||||||
@@ -18,18 +19,28 @@ import android.database.Cursor;
|
|||||||
import android.database.sqlite.SQLiteDatabase;
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
import android.database.sqlite.SQLiteException;
|
import android.database.sqlite.SQLiteException;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
public class ComputerDatabaseManager {
|
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_TABLE_NAME = "Computers";
|
||||||
private static final String COMPUTER_UUID_COLUMN_NAME = "UUID";
|
private static final String COMPUTER_UUID_COLUMN_NAME = "UUID";
|
||||||
private static final String COMPUTER_NAME_COLUMN_NAME = "ComputerName";
|
private static final String COMPUTER_NAME_COLUMN_NAME = "ComputerName";
|
||||||
private static final String ADDRESSES_COLUMN_NAME = "Addresses";
|
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 MAC_ADDRESS_COLUMN_NAME = "MacAddress";
|
||||||
private static final String SERVER_CERT_COLUMN_NAME = "ServerCert";
|
private static final String SERVER_CERT_COLUMN_NAME = "ServerCert";
|
||||||
|
|
||||||
private static final char ADDRESS_DELIMITER = ';';
|
|
||||||
private static final char PORT_DELIMITER = '_';
|
|
||||||
|
|
||||||
private SQLiteDatabase computerDb;
|
private SQLiteDatabase computerDb;
|
||||||
|
|
||||||
public ComputerDatabaseManager(Context c) {
|
public ComputerDatabaseManager(Context c) {
|
||||||
@@ -64,24 +75,54 @@ public class ComputerDatabaseManager {
|
|||||||
for (ComputerDetails computer : oldComputers) {
|
for (ComputerDetails computer : oldComputers) {
|
||||||
updateComputer(computer);
|
updateComputer(computer);
|
||||||
}
|
}
|
||||||
|
oldComputers = LegacyDatabaseReader3.migrateAllComputers(c);
|
||||||
|
for (ComputerDetails computer : oldComputers) {
|
||||||
|
updateComputer(computer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deleteComputer(ComputerDetails details) {
|
public void deleteComputer(ComputerDetails details) {
|
||||||
computerDb.delete(COMPUTER_TABLE_NAME, COMPUTER_UUID_COLUMN_NAME+"=?", new String[]{details.uuid});
|
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) {
|
public boolean updateComputer(ComputerDetails details) {
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
values.put(COMPUTER_UUID_COLUMN_NAME, details.uuid);
|
values.put(COMPUTER_UUID_COLUMN_NAME, details.uuid);
|
||||||
values.put(COMPUTER_NAME_COLUMN_NAME, details.name);
|
values.put(COMPUTER_NAME_COLUMN_NAME, details.name);
|
||||||
|
|
||||||
StringBuilder addresses = new StringBuilder();
|
try {
|
||||||
addresses.append(details.localAddress != null ? splitTupleToAddress(details.localAddress) : "");
|
JSONObject addresses = new JSONObject();
|
||||||
addresses.append(ADDRESS_DELIMITER).append(details.remoteAddress != null ? splitTupleToAddress(details.remoteAddress) : "");
|
addresses.put(AddressFields.LOCAL, tupleToJson(details.localAddress));
|
||||||
addresses.append(ADDRESS_DELIMITER).append(details.manualAddress != null ? splitTupleToAddress(details.manualAddress) : "");
|
addresses.put(AddressFields.REMOTE, tupleToJson(details.remoteAddress));
|
||||||
addresses.append(ADDRESS_DELIMITER).append(details.ipv6Address != null ? splitTupleToAddress(details.ipv6Address) : "");
|
addresses.put(AddressFields.MANUAL, tupleToJson(details.manualAddress));
|
||||||
|
addresses.put(AddressFields.IPv6, tupleToJson(details.ipv6Address));
|
||||||
values.put(ADDRESSES_COLUMN_NAME, addresses.toString());
|
values.put(ADDRESSES_COLUMN_NAME, addresses.toString());
|
||||||
|
} catch (JSONException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
values.put(MAC_ADDRESS_COLUMN_NAME, details.macAddress);
|
values.put(MAC_ADDRESS_COLUMN_NAME, details.macAddress);
|
||||||
try {
|
try {
|
||||||
if (details.serverCert != null) {
|
if (details.serverCert != null) {
|
||||||
@@ -97,44 +138,20 @@ public class ComputerDatabaseManager {
|
|||||||
return -1 != computerDb.insertWithOnConflict(COMPUTER_TABLE_NAME, null, values, SQLiteDatabase.CONFLICT_REPLACE);
|
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) {
|
private ComputerDetails getComputerFromCursor(Cursor c) {
|
||||||
ComputerDetails details = new ComputerDetails();
|
ComputerDetails details = new ComputerDetails();
|
||||||
|
|
||||||
details.uuid = c.getString(0);
|
details.uuid = c.getString(0);
|
||||||
details.name = c.getString(1);
|
details.name = c.getString(1);
|
||||||
|
try {
|
||||||
String[] addresses = c.getString(2).split(""+ADDRESS_DELIMITER, -1);
|
JSONObject addresses = new JSONObject(c.getString(2));
|
||||||
|
details.localAddress = tupleFromJson(addresses, AddressFields.LOCAL);
|
||||||
details.localAddress = splitAddressToTuple(readNonEmptyString(addresses[0]));
|
details.remoteAddress = tupleFromJson(addresses, AddressFields.REMOTE);
|
||||||
details.remoteAddress = splitAddressToTuple(readNonEmptyString(addresses[1]));
|
details.manualAddress = tupleFromJson(addresses, AddressFields.MANUAL);
|
||||||
details.manualAddress = splitAddressToTuple(readNonEmptyString(addresses[2]));
|
details.ipv6Address = tupleFromJson(addresses, AddressFields.IPv6);
|
||||||
details.ipv6Address = splitAddressToTuple(readNonEmptyString(addresses[3]));
|
} catch (JSONException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
// External port is persisted in the remote address field
|
// External port is persisted in the remote address field
|
||||||
if (details.remoteAddress != null) {
|
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) {
|
public ComputerDetails getComputerByUUID(String uuid) {
|
||||||
try (final Cursor c = computerDb.query(
|
try (final Cursor c = computerDb.query(
|
||||||
COMPUTER_TABLE_NAME, null, COMPUTER_UUID_COLUMN_NAME+"=?",
|
COMPUTER_TABLE_NAME, null, COMPUTER_UUID_COLUMN_NAME+"=?",
|
||||||
|
|||||||
@@ -64,6 +64,8 @@ public class ComputerManagerService extends Service {
|
|||||||
private boolean pollingActive = false;
|
private boolean pollingActive = false;
|
||||||
private final Lock defaultNetworkLock = new ReentrantLock();
|
private final Lock defaultNetworkLock = new ReentrantLock();
|
||||||
|
|
||||||
|
private ConnectivityManager.NetworkCallback networkCallback;
|
||||||
|
|
||||||
private DiscoveryService.DiscoveryBinder discoveryBinder;
|
private DiscoveryService.DiscoveryBinder discoveryBinder;
|
||||||
private final ServiceConnection discoveryServiceConnection = new ServiceConnection() {
|
private final ServiceConnection discoveryServiceConnection = new ServiceConnection() {
|
||||||
public void onServiceConnected(ComponentName className, IBinder binder) {
|
public void onServiceConnected(ComponentName className, IBinder binder) {
|
||||||
@@ -339,7 +341,6 @@ public class ComputerManagerService extends Service {
|
|||||||
// Acquire the default network lock since we could be changing global process state
|
// Acquire the default network lock since we could be changing global process state
|
||||||
defaultNetworkLock.lock();
|
defaultNetworkLock.lock();
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
||||||
// On Lollipop or later, we can bind our process to the underlying interface
|
// 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
|
// to ensure our STUN request goes out on that interface or not at all (which is
|
||||||
// preferable to getting a VPN endpoint address back).
|
// preferable to getting a VPN endpoint address back).
|
||||||
@@ -356,16 +357,13 @@ public class ComputerManagerService extends Service {
|
|||||||
boundToNetwork = true;
|
boundToNetwork = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
} else if (ConnectivityManager.setProcessDefaultNetwork(net)) {
|
||||||
else if (ConnectivityManager.setProcessDefaultNetwork(net)) {
|
|
||||||
boundToNetwork = true;
|
boundToNetwork = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Perform the STUN request if we're not on a VPN or if we bound to a network
|
// Perform the STUN request if we're not on a VPN or if we bound to a network
|
||||||
if (!activeNetworkIsVpn || boundToNetwork) {
|
if (!activeNetworkIsVpn || boundToNetwork) {
|
||||||
@@ -381,8 +379,7 @@ public class ComputerManagerService extends Service {
|
|||||||
if (boundToNetwork) {
|
if (boundToNetwork) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
connMgr.bindProcessToNetwork(null);
|
connMgr.bindProcessToNetwork(null);
|
||||||
}
|
} else {
|
||||||
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
||||||
ConnectivityManager.setProcessDefaultNetwork(null);
|
ConnectivityManager.setProcessDefaultNetwork(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -392,6 +389,7 @@ public class ComputerManagerService extends Service {
|
|||||||
defaultNetworkLock.unlock();
|
defaultNetworkLock.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private MdnsDiscoveryListener createDiscoveryListener() {
|
private MdnsDiscoveryListener createDiscoveryListener() {
|
||||||
return new MdnsDiscoveryListener() {
|
return new MdnsDiscoveryListener() {
|
||||||
@@ -429,11 +427,6 @@ public class ComputerManagerService extends Service {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void notifyComputerRemoved(MdnsComputer computer) {
|
|
||||||
// Nothing to do here
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void notifyDiscoveryFailure(Exception e) {
|
public void notifyDiscoveryFailure(Exception e) {
|
||||||
LimeLog.severe("mDNS discovery failed");
|
LimeLog.severe("mDNS discovery failed");
|
||||||
@@ -553,7 +546,8 @@ public class ComputerManagerService extends Service {
|
|||||||
// If the current address's port number matches the active address's port number, we can also assume
|
// If the current address's port number matches the active address's port number, we can also assume
|
||||||
// the HTTPS port will also match. This assumption is currently safe because Sunshine sets all ports
|
// the HTTPS port will also match. This assumption is currently safe because Sunshine sets all ports
|
||||||
// as offsets from the base HTTP port and doesn't allow custom HttpsPort responses for WAN vs LAN.
|
// as offsets from the base HTTP port and doesn't allow custom HttpsPort responses for WAN vs LAN.
|
||||||
boolean portMatchesActiveAddress = details.activeAddress != null && address.port == details.activeAddress.port;
|
boolean portMatchesActiveAddress = details.state == ComputerDetails.State.ONLINE &&
|
||||||
|
details.activeAddress != null && address.port == details.activeAddress.port;
|
||||||
|
|
||||||
NvHTTP http = new NvHTTP(address, portMatchesActiveAddress ? details.httpsPort : 0, idManager.getUniqueId(), details.serverCert,
|
NvHTTP http = new NvHTTP(address, portMatchesActiveAddress ? details.httpsPort : 0, idManager.getUniqueId(), details.serverCert,
|
||||||
PlatformBinding.getCryptoProvider(ComputerManagerService.this));
|
PlatformBinding.getCryptoProvider(ComputerManagerService.this));
|
||||||
@@ -743,10 +737,49 @@ public class ComputerManagerService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
releaseLocalDatabaseReference();
|
releaseLocalDatabaseReference();
|
||||||
|
|
||||||
|
// Monitor for network changes to invalidate our PC state
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
|
networkCallback = new ConnectivityManager.NetworkCallback() {
|
||||||
|
@Override
|
||||||
|
public void onAvailable(Network network) {
|
||||||
|
LimeLog.info("Resetting PC state for new available network");
|
||||||
|
synchronized (pollingTuples) {
|
||||||
|
for (PollingTuple tuple : pollingTuples) {
|
||||||
|
tuple.computer.state = ComputerDetails.State.UNKNOWN;
|
||||||
|
if (listener != null) {
|
||||||
|
listener.notifyComputerUpdated(tuple.computer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLost(Network network) {
|
||||||
|
LimeLog.info("Offlining PCs due to network loss");
|
||||||
|
synchronized (pollingTuples) {
|
||||||
|
for (PollingTuple tuple : pollingTuples) {
|
||||||
|
tuple.computer.state = ComputerDetails.State.OFFLINE;
|
||||||
|
if (listener != null) {
|
||||||
|
listener.notifyComputerUpdated(tuple.computer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||||
|
connMgr.registerDefaultNetworkCallback(networkCallback);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
|
ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||||
|
connMgr.unregisterNetworkCallback(networkCallback);
|
||||||
|
}
|
||||||
|
|
||||||
if (discoveryBinder != null) {
|
if (discoveryBinder != null) {
|
||||||
// Unbind from the discovery service
|
// Unbind from the discovery service
|
||||||
unbindService(discoveryServiceConnection);
|
unbindService(discoveryServiceConnection);
|
||||||
|
|||||||
@@ -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 java.util.List;
|
||||||
|
|
||||||
import com.limelight.nvstream.mdns.MdnsComputer;
|
import com.limelight.nvstream.mdns.MdnsComputer;
|
||||||
|
import com.limelight.nvstream.mdns.JmDNSDiscoveryAgent;
|
||||||
import com.limelight.nvstream.mdns.MdnsDiscoveryAgent;
|
import com.limelight.nvstream.mdns.MdnsDiscoveryAgent;
|
||||||
import com.limelight.nvstream.mdns.MdnsDiscoveryListener;
|
import com.limelight.nvstream.mdns.MdnsDiscoveryListener;
|
||||||
|
import com.limelight.nvstream.mdns.NsdManagerDiscoveryAgent;
|
||||||
|
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.wifi.WifiManager;
|
|
||||||
import android.net.wifi.WifiManager.MulticastLock;
|
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
|
||||||
public class DiscoveryService extends Service {
|
public class DiscoveryService extends Service {
|
||||||
|
|
||||||
private MdnsDiscoveryAgent discoveryAgent;
|
private MdnsDiscoveryAgent discoveryAgent;
|
||||||
private MdnsDiscoveryListener boundListener;
|
private MdnsDiscoveryListener boundListener;
|
||||||
private MulticastLock multicastLock;
|
|
||||||
|
|
||||||
public class DiscoveryBinder extends Binder {
|
public class DiscoveryBinder extends Binder {
|
||||||
public void setListener(MdnsDiscoveryListener listener) {
|
public void setListener(MdnsDiscoveryListener listener) {
|
||||||
@@ -26,13 +25,11 @@ public class DiscoveryService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void startDiscovery(int queryIntervalMs) {
|
public void startDiscovery(int queryIntervalMs) {
|
||||||
multicastLock.acquire();
|
|
||||||
discoveryAgent.startDiscovery(queryIntervalMs);
|
discoveryAgent.startDiscovery(queryIntervalMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stopDiscovery() {
|
public void stopDiscovery() {
|
||||||
discoveryAgent.stopDiscovery();
|
discoveryAgent.stopDiscovery();
|
||||||
multicastLock.release();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<MdnsComputer> getComputerSet() {
|
public List<MdnsComputer> getComputerSet() {
|
||||||
@@ -42,11 +39,7 @@ public class DiscoveryService extends Service {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
WifiManager wifiMgr = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
|
MdnsDiscoveryListener listener = new MdnsDiscoveryListener() {
|
||||||
multicastLock = wifiMgr.createMulticastLock("Limelight mDNS");
|
|
||||||
multicastLock.setReferenceCounted(false);
|
|
||||||
|
|
||||||
discoveryAgent = new MdnsDiscoveryAgent(new MdnsDiscoveryListener() {
|
|
||||||
@Override
|
@Override
|
||||||
public void notifyComputerAdded(MdnsComputer computer) {
|
public void notifyComputerAdded(MdnsComputer computer) {
|
||||||
if (boundListener != null) {
|
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
|
@Override
|
||||||
public void notifyDiscoveryFailure(Exception e) {
|
public void notifyDiscoveryFailure(Exception e) {
|
||||||
if (boundListener != null) {
|
if (boundListener != null) {
|
||||||
boundListener.notifyDiscoveryFailure(e);
|
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();
|
private final DiscoveryBinder binder = new DiscoveryBinder();
|
||||||
@@ -81,7 +82,6 @@ public class DiscoveryService extends Service {
|
|||||||
public boolean onUnbind(Intent intent) {
|
public boolean onUnbind(Intent intent) {
|
||||||
// Stop any discovery session
|
// Stop any discovery session
|
||||||
discoveryAgent.stopDiscovery();
|
discoveryAgent.stopDiscovery();
|
||||||
multicastLock.release();
|
|
||||||
|
|
||||||
// Unbind the listener
|
// Unbind the listener
|
||||||
boundListener = null;
|
boundListener = null;
|
||||||
|
|||||||
@@ -28,15 +28,9 @@ public class DiskAssetLoader {
|
|||||||
|
|
||||||
public DiskAssetLoader(Context context) {
|
public DiskAssetLoader(Context context) {
|
||||||
this.cacheDir = context.getCacheDir();
|
this.cacheDir = context.getCacheDir();
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
|
||||||
this.isLowRamDevice =
|
this.isLowRamDevice =
|
||||||
((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE)).isLowRamDevice();
|
((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE)).isLowRamDevice();
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
// Use conservative low RAM behavior on very old devices
|
|
||||||
this.isLowRamDevice = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean checkCacheExists(CachedAppAssetLoader.LoaderTuple tuple) {
|
public boolean checkCacheExists(CachedAppAssetLoader.LoaderTuple tuple) {
|
||||||
return CacheHelper.cacheFileExists(cacheDir, "boxart", tuple.computer.uuid, tuple.app.getAppId() + ".png");
|
return CacheHelper.cacheFileExists(cacheDir, "boxart", tuple.computer.uuid, tuple.app.getAppId() + ".png");
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import javax.crypto.SecretKey;
|
|||||||
public class ConnectionContext {
|
public class ConnectionContext {
|
||||||
public ComputerDetails.AddressTuple serverAddress;
|
public ComputerDetails.AddressTuple serverAddress;
|
||||||
public int httpsPort;
|
public int httpsPort;
|
||||||
|
public boolean isNvidiaServerSoftware;
|
||||||
public X509Certificate serverCert;
|
public X509Certificate serverCert;
|
||||||
public StreamConfiguration streamConfig;
|
public StreamConfiguration streamConfig;
|
||||||
public NvConnectionListener connListener;
|
public NvConnectionListener connListener;
|
||||||
@@ -18,6 +19,7 @@ public class ConnectionContext {
|
|||||||
// This is the version quad from the appversion tag of /serverinfo
|
// This is the version quad from the appversion tag of /serverinfo
|
||||||
public String serverAppVersion;
|
public String serverAppVersion;
|
||||||
public String serverGfeVersion;
|
public String serverGfeVersion;
|
||||||
|
public int serverCodecModeSupport;
|
||||||
|
|
||||||
// This is the sessionUrl0 tag from /resume and /launch
|
// This is the sessionUrl0 tag from /resume and /launch
|
||||||
public String rtspSessionUrl;
|
public String rtspSessionUrl;
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import java.io.IOException;
|
|||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.net.UnknownHostException;
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
@@ -33,7 +32,7 @@ import com.limelight.LimeLog;
|
|||||||
import com.limelight.nvstream.av.audio.AudioRenderer;
|
import com.limelight.nvstream.av.audio.AudioRenderer;
|
||||||
import com.limelight.nvstream.av.video.VideoDecoderRenderer;
|
import com.limelight.nvstream.av.video.VideoDecoderRenderer;
|
||||||
import com.limelight.nvstream.http.ComputerDetails;
|
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.LimelightCryptoProvider;
|
||||||
import com.limelight.nvstream.http.NvApp;
|
import com.limelight.nvstream.http.NvApp;
|
||||||
import com.limelight.nvstream.http.NvHTTP;
|
import com.limelight.nvstream.http.NvHTTP;
|
||||||
@@ -48,21 +47,13 @@ public class NvConnection {
|
|||||||
private ConnectionContext context;
|
private ConnectionContext context;
|
||||||
private static Semaphore connectionAllowed = new Semaphore(1);
|
private static Semaphore connectionAllowed = new Semaphore(1);
|
||||||
private final boolean isMonkey;
|
private final boolean isMonkey;
|
||||||
private final boolean batchMouseInput;
|
|
||||||
private final Context appContext;
|
private final Context appContext;
|
||||||
|
|
||||||
private static final int MOUSE_BATCH_PERIOD_MS = 5;
|
public NvConnection(Context appContext, ComputerDetails.AddressTuple host, int httpsPort, String uniqueId, StreamConfiguration config, LimelightCryptoProvider cryptoProvider, X509Certificate serverCert)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
this.appContext = appContext;
|
this.appContext = appContext;
|
||||||
this.cryptoProvider = cryptoProvider;
|
this.cryptoProvider = cryptoProvider;
|
||||||
this.uniqueId = uniqueId;
|
this.uniqueId = uniqueId;
|
||||||
this.batchMouseInput = batchMouseInput;
|
|
||||||
|
|
||||||
this.context = new ConnectionContext();
|
this.context = new ConnectionContext();
|
||||||
this.context.serverAddress = host;
|
this.context.serverAddress = host;
|
||||||
@@ -96,11 +87,6 @@ public class NvConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void stop() {
|
public void stop() {
|
||||||
// Stop sending additional input
|
|
||||||
if (mouseInputTimer != null) {
|
|
||||||
mouseInputTimer.cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Interrupt any pending connection. This is thread-safe.
|
// Interrupt any pending connection. This is thread-safe.
|
||||||
MoonBridge.interruptConnection();
|
MoonBridge.interruptConnection();
|
||||||
|
|
||||||
@@ -115,24 +101,6 @@ public class NvConnection {
|
|||||||
connectionAllowed.release();
|
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 {
|
private InetAddress resolveServerAddress() throws IOException {
|
||||||
// Try to find an address that works for this host
|
// Try to find an address that works for this host
|
||||||
InetAddress[] addrs = InetAddress.getAllByName(context.serverAddress.address);
|
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();
|
NetworkInfo activeNetworkInfo = connMgr.getActiveNetworkInfo();
|
||||||
if (activeNetworkInfo != null) {
|
if (activeNetworkInfo != null) {
|
||||||
switch (activeNetworkInfo.getType()) {
|
switch (activeNetworkInfo.getType()) {
|
||||||
@@ -263,6 +231,9 @@ public class NvConnection {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ComputerDetails details = h.getComputerDetails(serverInfo);
|
||||||
|
context.isNvidiaServerSoftware = details.nvidiaServer;
|
||||||
|
|
||||||
// May be missing for older servers
|
// May be missing for older servers
|
||||||
context.serverGfeVersion = h.getGfeVersion(serverInfo);
|
context.serverGfeVersion = h.getGfeVersion(serverInfo);
|
||||||
|
|
||||||
@@ -271,9 +242,11 @@ public class NvConnection {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
context.negotiatedHdr = context.streamConfig.getEnableHdr();
|
context.serverCodecModeSupport = (int)h.getServerCodecModeSupport(serverInfo);
|
||||||
if ((h.getServerCodecModeSupport(serverInfo) & 0x200) == 0 && context.negotiatedHdr) {
|
|
||||||
context.connListener.displayTransientMessage("Your GPU does not support streaming HDR. The stream will be SDR.");
|
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;
|
context.negotiatedHdr = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,13 +256,13 @@ public class NvConnection {
|
|||||||
|
|
||||||
// Check for a supported stream resolution
|
// Check for a supported stream resolution
|
||||||
if ((context.streamConfig.getWidth() > 4096 || context.streamConfig.getHeight() > 4096) &&
|
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.");
|
context.connListener.displayMessage("Your host PC does not support streaming at resolutions above 4K.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if ((context.streamConfig.getWidth() > 4096 || context.streamConfig.getHeight() > 4096) &&
|
else if ((context.streamConfig.getWidth() > 4096 || context.streamConfig.getHeight() > 4096) &&
|
||||||
!context.streamConfig.getHevcSupported()) {
|
(context.streamConfig.getSupportedVideoFormats() & ~MoonBridge.VIDEO_FORMAT_MASK_H264) == 0) {
|
||||||
context.connListener.displayMessage("Your streaming device must support HEVC to stream at resolutions above 4K.");
|
context.connListener.displayMessage("Your streaming device must support HEVC or AV1 to stream at resolutions above 4K.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (context.streamConfig.getHeight() >= 2160 && !h.supports4K(serverInfo)) {
|
else if (context.streamConfig.getHeight() >= 2160 && !h.supports4K(serverInfo)) {
|
||||||
@@ -338,14 +311,14 @@ public class NvConnection {
|
|||||||
if (h.getCurrentGame(serverInfo) != 0) {
|
if (h.getCurrentGame(serverInfo) != 0) {
|
||||||
try {
|
try {
|
||||||
if (h.getCurrentGame(serverInfo) == app.getAppId()) {
|
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");
|
context.connListener.displayMessage("Failed to resume existing session");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return quitAndLaunch(h, context);
|
return quitAndLaunch(h, context);
|
||||||
}
|
}
|
||||||
} catch (GfeHttpResponseException e) {
|
} catch (HostHttpResponseException e) {
|
||||||
if (e.getErrorCode() == 470) {
|
if (e.getErrorCode() == 470) {
|
||||||
// This is the error you get when you try to resume a session that's not yours.
|
// 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.
|
// 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");
|
context.connListener.displayMessage("Failed to quit previous session! You must quit it manually");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} catch (GfeHttpResponseException e) {
|
} catch (HostHttpResponseException e) {
|
||||||
if (e.getErrorCode() == 599) {
|
if (e.getErrorCode() == 599) {
|
||||||
context.connListener.displayMessage("This session wasn't started by this device," +
|
context.connListener.displayMessage("This session wasn't started by this device," +
|
||||||
" so it cannot be quit. End streaming on the original " +
|
" so it cannot be quit. End streaming on the original " +
|
||||||
@@ -396,7 +369,7 @@ public class NvConnection {
|
|||||||
private boolean launchNotRunningApp(NvHTTP h, ConnectionContext context)
|
private boolean launchNotRunningApp(NvHTTP h, ConnectionContext context)
|
||||||
throws IOException, XmlPullParserException {
|
throws IOException, XmlPullParserException {
|
||||||
// Launch the app since it's not running
|
// 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");
|
context.connListener.displayMessage("Failed to launch application");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -423,7 +396,7 @@ public class NvConnection {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
context.connListener.stageComplete(appName);
|
context.connListener.stageComplete(appName);
|
||||||
} catch (GfeHttpResponseException e) {
|
} catch (HostHttpResponseException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
context.connListener.displayMessage(e.getMessage());
|
context.connListener.displayMessage(e.getMessage());
|
||||||
context.connListener.stageFailed(appName, 0, e.getErrorCode());
|
context.connListener.stageFailed(appName, 0, e.getErrorCode());
|
||||||
@@ -454,15 +427,13 @@ public class NvConnection {
|
|||||||
MoonBridge.setupBridge(videoDecoderRenderer, audioRenderer, connectionListener);
|
MoonBridge.setupBridge(videoDecoderRenderer, audioRenderer, connectionListener);
|
||||||
int ret = MoonBridge.startConnection(context.serverAddress.address,
|
int ret = MoonBridge.startConnection(context.serverAddress.address,
|
||||||
context.serverAppVersion, context.serverGfeVersion, context.rtspSessionUrl,
|
context.serverAppVersion, context.serverGfeVersion, context.rtspSessionUrl,
|
||||||
|
context.serverCodecModeSupport,
|
||||||
context.negotiatedWidth, context.negotiatedHeight,
|
context.negotiatedWidth, context.negotiatedHeight,
|
||||||
context.streamConfig.getRefreshRate(), context.streamConfig.getBitrate(),
|
context.streamConfig.getRefreshRate(), context.streamConfig.getBitrate(),
|
||||||
context.negotiatedPacketSize, context.negotiatedRemoteStreaming,
|
context.negotiatedPacketSize, context.negotiatedRemoteStreaming,
|
||||||
context.streamConfig.getAudioConfiguration().toInt(),
|
context.streamConfig.getAudioConfiguration().toInt(),
|
||||||
context.streamConfig.getHevcSupported(),
|
context.streamConfig.getSupportedVideoFormats(),
|
||||||
context.negotiatedHdr,
|
|
||||||
context.streamConfig.getHevcBitratePercentageMultiplier(),
|
|
||||||
context.streamConfig.getClientRefreshRateX100(),
|
context.streamConfig.getClientRefreshRateX100(),
|
||||||
context.streamConfig.getEncryptionFlags(),
|
|
||||||
context.riKey.getEncoded(), ib.array(),
|
context.riKey.getEncoded(), ib.array(),
|
||||||
context.videoCapabilities,
|
context.videoCapabilities,
|
||||||
context.streamConfig.getColorSpace(),
|
context.streamConfig.getColorSpace(),
|
||||||
@@ -474,20 +445,6 @@ public class NvConnection {
|
|||||||
connectionAllowed.release();
|
connectionAllowed.release();
|
||||||
return;
|
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();
|
}).start();
|
||||||
@@ -496,65 +453,27 @@ public class NvConnection {
|
|||||||
public void sendMouseMove(final short deltaX, final short deltaY)
|
public void sendMouseMove(final short deltaX, final short deltaY)
|
||||||
{
|
{
|
||||||
if (!isMonkey) {
|
if (!isMonkey) {
|
||||||
synchronized (mouseInputLock) {
|
MoonBridge.sendMouseMove(deltaX, deltaY);
|
||||||
relMouseX += deltaX;
|
|
||||||
relMouseY += deltaY;
|
|
||||||
|
|
||||||
// Reset these to ensure we don't send this as a position update
|
|
||||||
relMouseWidth = 0;
|
|
||||||
relMouseHeight = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!batchMouseInput) {
|
|
||||||
flushMousePosition();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendMousePosition(short x, short y, short referenceWidth, short referenceHeight)
|
public void sendMousePosition(short x, short y, short referenceWidth, short referenceHeight)
|
||||||
{
|
{
|
||||||
if (!isMonkey) {
|
if (!isMonkey) {
|
||||||
synchronized (mouseInputLock) {
|
MoonBridge.sendMousePosition(x, y, referenceWidth, referenceHeight);
|
||||||
absMouseX = x;
|
|
||||||
absMouseY = y;
|
|
||||||
absMouseWidth = referenceWidth;
|
|
||||||
absMouseHeight = referenceHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!batchMouseInput) {
|
|
||||||
flushMousePosition();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendMouseMoveAsMousePosition(short deltaX, short deltaY, short referenceWidth, short referenceHeight)
|
public void sendMouseMoveAsMousePosition(short deltaX, short deltaY, short referenceWidth, short referenceHeight)
|
||||||
{
|
{
|
||||||
if (!isMonkey) {
|
if (!isMonkey) {
|
||||||
synchronized (mouseInputLock) {
|
MoonBridge.sendMouseMoveAsMousePosition(deltaX, deltaY, referenceWidth, referenceHeight);
|
||||||
// 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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendMouseButtonDown(final byte mouseButton)
|
public void sendMouseButtonDown(final byte mouseButton)
|
||||||
{
|
{
|
||||||
if (!isMonkey) {
|
if (!isMonkey) {
|
||||||
flushMousePosition();
|
|
||||||
MoonBridge.sendMouseButton(MouseButtonPacket.PRESS_EVENT, mouseButton);
|
MoonBridge.sendMouseButton(MouseButtonPacket.PRESS_EVENT, mouseButton);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -562,13 +481,12 @@ public class NvConnection {
|
|||||||
public void sendMouseButtonUp(final byte mouseButton)
|
public void sendMouseButtonUp(final byte mouseButton)
|
||||||
{
|
{
|
||||||
if (!isMonkey) {
|
if (!isMonkey) {
|
||||||
flushMousePosition();
|
|
||||||
MoonBridge.sendMouseButton(MouseButtonPacket.RELEASE_EVENT, mouseButton);
|
MoonBridge.sendMouseButton(MouseButtonPacket.RELEASE_EVENT, mouseButton);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendControllerInput(final short controllerNumber,
|
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 byte leftTrigger, final byte rightTrigger,
|
||||||
final short leftStickX, final short leftStickY,
|
final short leftStickX, final short leftStickY,
|
||||||
final short rightStickX, final short rightStickY)
|
final short rightStickX, final short rightStickY)
|
||||||
@@ -579,37 +497,88 @@ public class NvConnection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendControllerInput(final short buttonFlags,
|
public void sendKeyboardInput(final short keyMap, final byte keyDirection, final byte modifier, final byte flags) {
|
||||||
final byte leftTrigger, final byte rightTrigger,
|
|
||||||
final short leftStickX, final short leftStickY,
|
|
||||||
final short rightStickX, final short rightStickY)
|
|
||||||
{
|
|
||||||
if (!isMonkey) {
|
if (!isMonkey) {
|
||||||
MoonBridge.sendControllerInput(buttonFlags, leftTrigger, rightTrigger, leftStickX,
|
MoonBridge.sendKeyboardInput(keyMap, keyDirection, modifier, flags);
|
||||||
leftStickY, rightStickX, rightStickY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sendKeyboardInput(final short keyMap, final byte keyDirection, final byte modifier) {
|
|
||||||
if (!isMonkey) {
|
|
||||||
MoonBridge.sendKeyboardInput(keyMap, keyDirection, modifier);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendMouseScroll(final byte scrollClicks) {
|
public void sendMouseScroll(final byte scrollClicks) {
|
||||||
if (!isMonkey) {
|
if (!isMonkey) {
|
||||||
flushMousePosition();
|
MoonBridge.sendMouseHighResScroll((short)(scrollClicks * 120)); // WHEEL_DELTA
|
||||||
MoonBridge.sendMouseScroll(scrollClicks);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendMouseHScroll(final byte scrollClicks) {
|
||||||
|
if (!isMonkey) {
|
||||||
|
MoonBridge.sendMouseHighResHScroll((short)(scrollClicks * 120)); // WHEEL_DELTA
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendMouseHighResScroll(final short scrollAmount) {
|
public void sendMouseHighResScroll(final short scrollAmount) {
|
||||||
if (!isMonkey) {
|
if (!isMonkey) {
|
||||||
flushMousePosition();
|
|
||||||
MoonBridge.sendMouseHighResScroll(scrollAmount);
|
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) {
|
public void sendUtf8Text(final String text) {
|
||||||
if (!isMonkey) {
|
if (!isMonkey) {
|
||||||
MoonBridge.sendUtf8Text(text);
|
MoonBridge.sendUtf8Text(text);
|
||||||
|
|||||||
@@ -13,6 +13,11 @@ public interface NvConnectionListener {
|
|||||||
void displayTransientMessage(String message);
|
void displayTransientMessage(String message);
|
||||||
|
|
||||||
void rumble(short controllerNumber, short lowFreqMotor, short highFreqMotor);
|
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 maxPacketSize;
|
||||||
private int remote;
|
private int remote;
|
||||||
private MoonBridge.AudioConfiguration audioConfiguration;
|
private MoonBridge.AudioConfiguration audioConfiguration;
|
||||||
private boolean supportsHevc;
|
private int supportedVideoFormats;
|
||||||
private int hevcBitratePercentageMultiplier;
|
|
||||||
private boolean enableHdr;
|
|
||||||
private int attachedGamepadMask;
|
private int attachedGamepadMask;
|
||||||
private int encryptionFlags;
|
private int encryptionFlags;
|
||||||
private int colorRange;
|
private int colorRange;
|
||||||
private int colorSpace;
|
private int colorSpace;
|
||||||
|
private boolean persistGamepadsAfterDisconnect;
|
||||||
|
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
private StreamConfiguration config = new StreamConfiguration();
|
private StreamConfiguration config = new StreamConfiguration();
|
||||||
@@ -84,16 +83,6 @@ public class StreamConfiguration {
|
|||||||
return this;
|
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) {
|
public StreamConfiguration.Builder setAttachedGamepadMask(int attachedGamepadMask) {
|
||||||
config.attachedGamepadMask = attachedGamepadMask;
|
config.attachedGamepadMask = attachedGamepadMask;
|
||||||
return this;
|
return this;
|
||||||
@@ -109,18 +98,13 @@ public class StreamConfiguration {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public StreamConfiguration.Builder setClientRefreshRateX100(int refreshRateX100) {
|
public StreamConfiguration.Builder setPersistGamepadsAfterDisconnect(boolean value) {
|
||||||
config.clientRefreshRateX100 = refreshRateX100;
|
config.persistGamepadsAfterDisconnect = value;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public StreamConfiguration.Builder setAudioEncryption(boolean enable) {
|
public StreamConfiguration.Builder setClientRefreshRateX100(int refreshRateX100) {
|
||||||
if (enable) {
|
config.clientRefreshRateX100 = refreshRateX100;
|
||||||
config.encryptionFlags |= MoonBridge.ENCFLG_AUDIO;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
config.encryptionFlags &= ~MoonBridge.ENCFLG_AUDIO;
|
|
||||||
}
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,8 +113,8 @@ public class StreamConfiguration {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public StreamConfiguration.Builder setHevcSupported(boolean supportsHevc) {
|
public StreamConfiguration.Builder setSupportedVideoFormats(int supportedVideoFormats) {
|
||||||
config.supportsHevc = supportsHevc;
|
config.supportedVideoFormats = supportedVideoFormats;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,8 +146,7 @@ public class StreamConfiguration {
|
|||||||
this.sops = true;
|
this.sops = true;
|
||||||
this.enableAdaptiveResolution = false;
|
this.enableAdaptiveResolution = false;
|
||||||
this.audioConfiguration = MoonBridge.AUDIO_CONFIGURATION_STEREO;
|
this.audioConfiguration = MoonBridge.AUDIO_CONFIGURATION_STEREO;
|
||||||
this.supportsHevc = false;
|
this.supportedVideoFormats = MoonBridge.VIDEO_FORMAT_H264;
|
||||||
this.enableHdr = false;
|
|
||||||
this.attachedGamepadMask = 0;
|
this.attachedGamepadMask = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,28 +198,20 @@ public class StreamConfiguration {
|
|||||||
return audioConfiguration;
|
return audioConfiguration;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getHevcSupported() {
|
public int getSupportedVideoFormats() {
|
||||||
return supportsHevc;
|
return supportedVideoFormats;
|
||||||
}
|
|
||||||
|
|
||||||
public int getHevcBitratePercentageMultiplier() {
|
|
||||||
return hevcBitratePercentageMultiplier;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getEnableHdr() {
|
|
||||||
return enableHdr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getAttachedGamepadMask() {
|
public int getAttachedGamepadMask() {
|
||||||
return attachedGamepadMask;
|
return attachedGamepadMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getClientRefreshRateX100() {
|
public boolean getPersistGamepadsAfterDisconnect() {
|
||||||
return clientRefreshRateX100;
|
return persistGamepadsAfterDisconnect;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getEncryptionFlags() {
|
public int getClientRefreshRateX100() {
|
||||||
return encryptionFlags;
|
return clientRefreshRateX100;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getColorRange() {
|
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
|
// 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.
|
// for an IDR frame which contains several parameter sets and the I-frame data.
|
||||||
public abstract int submitDecodeUnit(byte[] decodeUnitData, int decodeUnitLength, int decodeUnitType,
|
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 void cleanup();
|
||||||
|
|
||||||
public abstract int getCapabilities();
|
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;
|
package com.limelight.nvstream.http;
|
||||||
|
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
|
||||||
public class ComputerDetails {
|
public class ComputerDetails {
|
||||||
@@ -20,13 +21,18 @@ public class ComputerDetails {
|
|||||||
throw new IllegalArgumentException("Invalid port");
|
throw new IllegalArgumentException("Invalid port");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If this was an escaped IPv6 address, remove the brackets
|
||||||
|
if (address.startsWith("[") && address.endsWith("]")) {
|
||||||
|
address = address.substring(1, address.length() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
this.address = address;
|
this.address = address;
|
||||||
this.port = port;
|
this.port = port;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return address.hashCode();
|
return Objects.hash(address, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -40,9 +46,16 @@ public class ComputerDetails {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
if (address.contains(":")) {
|
||||||
|
// IPv6
|
||||||
|
return "[" + address + "]:" + port;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// IPv4 and hostnames
|
||||||
return address + ":" + port;
|
return address + ":" + port;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Persistent attributes
|
// Persistent attributes
|
||||||
public String uuid;
|
public String uuid;
|
||||||
@@ -62,6 +75,7 @@ public class ComputerDetails {
|
|||||||
public PairingManager.PairState pairState;
|
public PairingManager.PairState pairState;
|
||||||
public int runningGameId;
|
public int runningGameId;
|
||||||
public String rawAppList;
|
public String rawAppList;
|
||||||
|
public boolean nvidiaServer;
|
||||||
|
|
||||||
public ComputerDetails() {
|
public ComputerDetails() {
|
||||||
// Use defaults
|
// Use defaults
|
||||||
@@ -130,6 +144,7 @@ public class ComputerDetails {
|
|||||||
this.httpsPort = details.httpsPort;
|
this.httpsPort = details.httpsPort;
|
||||||
this.pairState = details.pairState;
|
this.pairState = details.pairState;
|
||||||
this.runningGameId = details.runningGameId;
|
this.runningGameId = details.runningGameId;
|
||||||
|
this.nvidiaServer = details.nvidiaServer;
|
||||||
this.rawAppList = details.rawAppList;
|
this.rawAppList = details.rawAppList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -2,13 +2,13 @@ package com.limelight.nvstream.http;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
public class GfeHttpResponseException extends IOException {
|
public class HostHttpResponseException extends IOException {
|
||||||
private static final long serialVersionUID = 1543508830807804222L;
|
private static final long serialVersionUID = 1543508830807804222L;
|
||||||
|
|
||||||
private int errorCode;
|
private int errorCode;
|
||||||
private String errorMsg;
|
private String errorMsg;
|
||||||
|
|
||||||
public GfeHttpResponseException(int errorCode, String errorMsg) {
|
public HostHttpResponseException(int errorCode, String errorMsg) {
|
||||||
this.errorCode = errorCode;
|
this.errorCode = errorCode;
|
||||||
this.errorMsg = errorMsg;
|
this.errorMsg = errorMsg;
|
||||||
}
|
}
|
||||||
@@ -23,6 +23,6 @@ public class GfeHttpResponseException extends IOException {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getMessage() {
|
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;
|
package com.limelight.nvstream.http;
|
||||||
|
|
||||||
|
import java.security.PrivateKey;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.security.interfaces.RSAPrivateKey;
|
|
||||||
|
|
||||||
public interface LimelightCryptoProvider {
|
public interface LimelightCryptoProvider {
|
||||||
X509Certificate getClientCertificate();
|
X509Certificate getClientCertificate();
|
||||||
RSAPrivateKey getClientPrivateKey();
|
PrivateKey getClientPrivateKey();
|
||||||
byte[] getPemEncodedClientCertificate();
|
byte[] getPemEncodedClientCertificate();
|
||||||
String encodeBase64String(byte[] data);
|
String encodeBase64String(byte[] data);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import java.io.InputStream;
|
|||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
|
import java.net.Inet4Address;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.Proxy;
|
import java.net.Proxy;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
@@ -49,6 +50,7 @@ import com.limelight.BuildConfig;
|
|||||||
import com.limelight.LimeLog;
|
import com.limelight.LimeLog;
|
||||||
import com.limelight.nvstream.ConnectionContext;
|
import com.limelight.nvstream.ConnectionContext;
|
||||||
import com.limelight.nvstream.http.PairingManager.PairState;
|
import com.limelight.nvstream.http.PairingManager.PairState;
|
||||||
|
import com.limelight.nvstream.jni.MoonBridge;
|
||||||
|
|
||||||
import okhttp3.ConnectionPool;
|
import okhttp3.ConnectionPool;
|
||||||
import okhttp3.HttpUrl;
|
import okhttp3.HttpUrl;
|
||||||
@@ -176,6 +178,7 @@ public class NvHTTP {
|
|||||||
.readTimeout(READ_TIMEOUT, TimeUnit.MILLISECONDS)
|
.readTimeout(READ_TIMEOUT, TimeUnit.MILLISECONDS)
|
||||||
.connectTimeout(LONG_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS)
|
.connectTimeout(LONG_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS)
|
||||||
.proxy(Proxy.NO_PROXY)
|
.proxy(Proxy.NO_PROXY)
|
||||||
|
.fastFallback(false)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
httpClientShortConnectTimeout = httpClientLongConnectTimeout.newBuilder()
|
httpClientShortConnectTimeout = httpClientLongConnectTimeout.newBuilder()
|
||||||
@@ -209,9 +212,21 @@ public class NvHTTP {
|
|||||||
this.httpsPort = httpsPort;
|
this.httpsPort = httpsPort;
|
||||||
|
|
||||||
try {
|
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()
|
this.baseUrlHttp = new HttpUrl.Builder()
|
||||||
.scheme("http")
|
.scheme("http")
|
||||||
.host(address.address)
|
.host(addressString)
|
||||||
.port(address.port)
|
.port(address.port)
|
||||||
.build();
|
.build();
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
@@ -266,7 +281,7 @@ public class NvHTTP {
|
|||||||
return getXmlString(new StringReader(str), tagname, throwIfMissing);
|
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
|
// 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
|
// 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
|
// 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;
|
statusCode = 418;
|
||||||
statusMsg = "Missing audio capture device. Reinstall GeForce Experience.";
|
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) {
|
if (e.getCause() instanceof CertificateException) {
|
||||||
// Jump to the GfeHttpResponseException exception handler to retry
|
// Jump to the GfeHttpResponseException exception handler to retry
|
||||||
// over HTTP which will allow us to pair again to update the cert
|
// 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 {
|
else {
|
||||||
throw e;
|
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.
|
// We want this because it will throw us into the HTTP case if the client is unpaired.
|
||||||
getServerVersion(resp);
|
getServerVersion(resp);
|
||||||
}
|
}
|
||||||
catch (GfeHttpResponseException e) {
|
catch (HostHttpResponseException e) {
|
||||||
if (e.getErrorCode() == 401) {
|
if (e.getErrorCode() == 401) {
|
||||||
// Cert validation error - fall back to HTTP
|
// Cert validation error - fall back to HTTP
|
||||||
return openHttpConnectionToString(client, baseUrlHttp, "serverinfo");
|
return openHttpConnectionToString(client, baseUrlHttp, "serverinfo");
|
||||||
@@ -343,9 +358,8 @@ public class NvHTTP {
|
|||||||
return new ComputerDetails.AddressTuple(address, port);
|
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();
|
ComputerDetails details = new ComputerDetails();
|
||||||
String serverInfo = getServerInfo(likelyOnline);
|
|
||||||
|
|
||||||
details.name = getXmlString(serverInfo, "hostname", false);
|
details.name = getXmlString(serverInfo, "hostname", false);
|
||||||
if (details.name == null || details.name.isEmpty()) {
|
if (details.name == null || details.name.isEmpty()) {
|
||||||
@@ -369,12 +383,19 @@ public class NvHTTP {
|
|||||||
details.pairState = getPairState(serverInfo);
|
details.pairState = getPairState(serverInfo);
|
||||||
details.runningGameId = getCurrentGame(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
|
// We could reach it so it's online
|
||||||
details.state = ComputerDetails.State.ONLINE;
|
details.state = ComputerDetails.State.ONLINE;
|
||||||
|
|
||||||
return details;
|
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
|
// This hack is Android-specific but we do it on all platforms
|
||||||
// because it doesn't really matter
|
// because it doesn't really matter
|
||||||
private OkHttpClient performAndroidTlsHack(OkHttpClient client) {
|
private OkHttpClient performAndroidTlsHack(OkHttpClient client) {
|
||||||
@@ -383,16 +404,7 @@ public class NvHTTP {
|
|||||||
try {
|
try {
|
||||||
SSLContext sc = SSLContext.getInstance("TLS");
|
SSLContext sc = SSLContext.getInstance("TLS");
|
||||||
sc.init(new KeyManager[] { keyManager }, new TrustManager[] { trustManager }, new SecureRandom());
|
sc.init(new KeyManager[] { keyManager }, new TrustManager[] { trustManager }, new SecureRandom());
|
||||||
|
return client.newBuilder().sslSocketFactory(sc.getSocketFactory(), trustManager).build();
|
||||||
// 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();
|
|
||||||
} catch (NoSuchAlgorithmException | KeyManagementException e) {
|
} catch (NoSuchAlgorithmException | KeyManagementException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
@@ -435,7 +447,7 @@ public class NvHTTP {
|
|||||||
throw new FileNotFoundException(completeUrl.toString());
|
throw new FileNotFoundException(completeUrl.toString());
|
||||||
}
|
}
|
||||||
else {
|
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 {
|
public NvApp getAppById(int appId) throws IOException, XmlPullParserException {
|
||||||
LinkedList<NvApp> appList = getAppList();
|
LinkedList<NvApp> appList = getAppList();
|
||||||
for (NvApp appFromList : appList) {
|
for (NvApp appFromList : appList) {
|
||||||
@@ -585,10 +603,15 @@ public class NvHTTP {
|
|||||||
return null;
|
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,
|
* Get an app by name
|
||||||
* or even nothing at all! Look apps up by ID if at all possible
|
* NOTE: It is perfectly valid for multiple apps to have the same name,
|
||||||
* using the above function */
|
* 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 {
|
public NvApp getAppByName(String appName) throws IOException, XmlPullParserException {
|
||||||
LinkedList<NvApp> appList = getAppList();
|
LinkedList<NvApp> appList = getAppList();
|
||||||
for (NvApp appFromList : appList) {
|
for (NvApp appFromList : appList) {
|
||||||
@@ -669,7 +692,7 @@ public class NvHTTP {
|
|||||||
return openHttpConnectionToString(httpClientLongConnectTimeout, getHttpsUrl(true), "applist");
|
return openHttpConnectionToString(httpClientLongConnectTimeout, getHttpsUrl(true), "applist");
|
||||||
}
|
}
|
||||||
|
|
||||||
public LinkedList<NvApp> getAppList() throws GfeHttpResponseException, IOException, XmlPullParserException {
|
public LinkedList<NvApp> getAppList() throws HostHttpResponseException, IOException, XmlPullParserException {
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
// Use the raw function so the app list is printed
|
// Use the raw function so the app list is printed
|
||||||
return getAppListByReader(new StringReader(getAppListRaw()));
|
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,
|
return openHttpConnectionToString(enableReadTimeout ? httpClientLongConnectTimeout : httpClientLongConnectNoReadTimeout,
|
||||||
baseUrlHttp, "pair", "devicename=roth&updateState=1&" + additionalArguments);
|
baseUrlHttp, "pair", "devicename=roth&updateState=1&" + additionalArguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
String executePairingChallenge() throws GfeHttpResponseException, IOException {
|
String executePairingChallenge() throws HostHttpResponseException, IOException {
|
||||||
return openHttpConnectionToString(httpClientLongConnectTimeout, getHttpsUrl(true),
|
return openHttpConnectionToString(httpClientLongConnectTimeout, getHttpsUrl(true),
|
||||||
"pair", "devicename=roth&updateState=1&phrase=pairchallenge");
|
"pair", "devicename=roth&updateState=1&phrase=pairchallenge");
|
||||||
}
|
}
|
||||||
@@ -731,27 +754,30 @@ public class NvHTTP {
|
|||||||
return new String(hexChars);
|
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,
|
// 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
|
// 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
|
// used to use 60 here but that locked the frame rate to 60 FPS
|
||||||
// on GFE 3.20.3.
|
// 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();
|
||||||
|
|
||||||
|
boolean enableSops = context.streamConfig.getSops();
|
||||||
|
if (context.isNvidiaServerSoftware) {
|
||||||
// Using an unsupported resolution (not 720p, 1080p, or 4K) causes
|
// Using an unsupported resolution (not 720p, 1080p, or 4K) causes
|
||||||
// GFE to force SOPS to 720p60. This is fine for < 720p resolutions like
|
// 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.
|
// 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.
|
// 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
|
// FIXME: Detect support resolutions using the serverinfo response, not a hardcoded list
|
||||||
boolean enableSops = context.streamConfig.getSops();
|
|
||||||
if (context.negotiatedWidth * context.negotiatedHeight > 1280 * 720 &&
|
if (context.negotiatedWidth * context.negotiatedHeight > 1280 * 720 &&
|
||||||
context.negotiatedWidth * context.negotiatedHeight != 1920 * 1080 &&
|
context.negotiatedWidth * context.negotiatedHeight != 1920 * 1080 &&
|
||||||
context.negotiatedWidth * context.negotiatedHeight != 3840 * 2160) {
|
context.negotiatedWidth * context.negotiatedHeight != 3840 * 2160) {
|
||||||
LimeLog.info("Disabling SOPS due to non-standard resolution: "+context.negotiatedWidth+"x"+context.negotiatedHeight);
|
LimeLog.info("Disabling SOPS due to non-standard resolution: "+context.negotiatedWidth+"x"+context.negotiatedHeight);
|
||||||
enableSops = false;
|
enableSops = false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String xmlStr = openHttpConnectionToString(httpClientLongConnectNoReadTimeout, getHttpsUrl(true), "launch",
|
String xmlStr = openHttpConnectionToString(httpClientLongConnectNoReadTimeout, getHttpsUrl(true), verb,
|
||||||
"appid=" + appId +
|
"appid=" + appId +
|
||||||
"&mode=" + context.negotiatedWidth + "x" + context.negotiatedHeight + "x" + fps +
|
"&mode=" + context.negotiatedWidth + "x" + context.negotiatedHeight + "x" + fps +
|
||||||
"&additionalStates=1&sops=" + (enableSops ? 1 : 0) +
|
"&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") +
|
(!enableHdr ? "" : "&hdrMode=1&clientHdrCapVersion=0&clientHdrCapSupportedFlagsInUint32=0&clientHdrCapMetaDataId=NV_STATIC_METADATA_TYPE_1&clientHdrCapDisplayData=0x0x0x0x0x0x0x0x0x0x0") +
|
||||||
"&localAudioPlayMode=" + (context.streamConfig.getPlayLocalAudio() ? 1 : 0) +
|
"&localAudioPlayMode=" + (context.streamConfig.getPlayLocalAudio() ? 1 : 0) +
|
||||||
"&surroundAudioInfo=" + context.streamConfig.getAudioConfiguration().getSurroundAudioInfo() +
|
"&surroundAudioInfo=" + context.streamConfig.getAudioConfiguration().getSurroundAudioInfo() +
|
||||||
(context.streamConfig.getAttachedGamepadMask() != 0 ? "&remoteControllersBitmap=" + context.streamConfig.getAttachedGamepadMask() : "") +
|
"&remoteControllersBitmap=" + context.streamConfig.getAttachedGamepadMask() +
|
||||||
(context.streamConfig.getAttachedGamepadMask() != 0 ? "&gcmap=" + context.streamConfig.getAttachedGamepadMask() : ""));
|
"&gcmap=" + context.streamConfig.getAttachedGamepadMask() +
|
||||||
if (!getXmlString(xmlStr, "gamesession", true).equals("0")) {
|
"&gcpersist="+(context.streamConfig.getPersistGamepadsAfterDisconnect() ? 1 : 0) +
|
||||||
// sessionUrl0 will be missing for older GFE versions
|
MoonBridge.getLaunchUrlQueryParameters());
|
||||||
context.rtspSessionUrl = getXmlString(xmlStr, "sessionUrl0", false);
|
if ((verb.equals("launch") && !getXmlString(xmlStr, "gamesession", true).equals("0") ||
|
||||||
return true;
|
(verb.equals("resume") && !getXmlString(xmlStr, "resume", true).equals("0")))) {
|
||||||
}
|
|
||||||
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")) {
|
|
||||||
// sessionUrl0 will be missing for older GFE versions
|
// sessionUrl0 will be missing for older GFE versions
|
||||||
context.rtspSessionUrl = getXmlString(xmlStr, "sessionUrl0", false);
|
context.rtspSessionUrl = getXmlString(xmlStr, "sessionUrl0", false);
|
||||||
return true;
|
return true;
|
||||||
@@ -798,67 +812,9 @@ public class NvHTTP {
|
|||||||
if (getCurrentGame(getServerInfo(true)) != 0) {
|
if (getCurrentGame(getServerInfo(true)) != 0) {
|
||||||
// Generate a synthetic GfeResponseException letting the caller know
|
// Generate a synthetic GfeResponseException letting the caller know
|
||||||
// that they can't kill someone else's stream.
|
// that they can't kill someone else's stream.
|
||||||
throw new GfeHttpResponseException(599, "");
|
throw new HostHttpResponseException(599, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,9 +99,20 @@ public class PairingManager {
|
|||||||
return saltedPin;
|
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) {
|
private static boolean verifySignature(byte[] data, byte[] signature, Certificate cert) {
|
||||||
try {
|
try {
|
||||||
Signature sig = Signature.getInstance("SHA256withRSA");
|
Signature sig = PairingManager.getSha256SignatureInstanceForKey(cert.getPublicKey());
|
||||||
sig.initVerify(cert.getPublicKey());
|
sig.initVerify(cert.getPublicKey());
|
||||||
sig.update(data);
|
sig.update(data);
|
||||||
return sig.verify(signature);
|
return sig.verify(signature);
|
||||||
@@ -113,12 +124,10 @@ public class PairingManager {
|
|||||||
|
|
||||||
private static byte[] signData(byte[] data, PrivateKey key) {
|
private static byte[] signData(byte[] data, PrivateKey key) {
|
||||||
try {
|
try {
|
||||||
Signature sig = Signature.getInstance("SHA256withRSA");
|
Signature sig = PairingManager.getSha256SignatureInstanceForKey(key);
|
||||||
sig.initSign(key);
|
sig.initSign(key);
|
||||||
sig.update(data);
|
sig.update(data);
|
||||||
byte[] signature = new byte[256];
|
return sig.sign();
|
||||||
sig.sign(signature, 0, signature.length);
|
|
||||||
return signature;
|
|
||||||
} catch (NoSuchAlgorithmException | SignatureException | InvalidKeyException e) {
|
} catch (NoSuchAlgorithmException | SignatureException | InvalidKeyException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
@@ -245,7 +254,7 @@ public class PairingManager {
|
|||||||
// Get the server's signed secret
|
// Get the server's signed secret
|
||||||
byte[] serverSecretResp = hexToBytes(NvHTTP.getXmlString(secretResp, "pairingsecret", true));
|
byte[] serverSecretResp = hexToBytes(NvHTTP.getXmlString(secretResp, "pairingsecret", true));
|
||||||
byte[] serverSecret = Arrays.copyOfRange(serverSecretResp, 0, 16);
|
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
|
// Ensure the authenticity of the data
|
||||||
if (!verifySignature(serverSecret, serverSignature, serverCert)) {
|
if (!verifySignature(serverSecret, serverSignature, serverCert)) {
|
||||||
|
|||||||
@@ -1,19 +1,27 @@
|
|||||||
package com.limelight.nvstream.input;
|
package com.limelight.nvstream.input;
|
||||||
|
|
||||||
public class ControllerPacket {
|
public class ControllerPacket {
|
||||||
public static final short A_FLAG = 0x1000;
|
public static final int A_FLAG = 0x1000;
|
||||||
public static final short B_FLAG = 0x2000;
|
public static final int B_FLAG = 0x2000;
|
||||||
public static final short X_FLAG = 0x4000;
|
public static final int X_FLAG = 0x4000;
|
||||||
public static final short Y_FLAG = (short)0x8000;
|
public static final int Y_FLAG = 0x8000;
|
||||||
public static final short UP_FLAG = 0x0001;
|
public static final int UP_FLAG = 0x0001;
|
||||||
public static final short DOWN_FLAG = 0x0002;
|
public static final int DOWN_FLAG = 0x0002;
|
||||||
public static final short LEFT_FLAG = 0x0004;
|
public static final int LEFT_FLAG = 0x0004;
|
||||||
public static final short RIGHT_FLAG = 0x0008;
|
public static final int RIGHT_FLAG = 0x0008;
|
||||||
public static final short LB_FLAG = 0x0100;
|
public static final int LB_FLAG = 0x0100;
|
||||||
public static final short RB_FLAG = 0x0200;
|
public static final int RB_FLAG = 0x0200;
|
||||||
public static final short PLAY_FLAG = 0x0010;
|
public static final int PLAY_FLAG = 0x0010;
|
||||||
public static final short BACK_FLAG = 0x0020;
|
public static final int BACK_FLAG = 0x0020;
|
||||||
public static final short LS_CLK_FLAG = 0x0040;
|
public static final int LS_CLK_FLAG = 0x0040;
|
||||||
public static final short RS_CLK_FLAG = 0x0080;
|
public static final int RS_CLK_FLAG = 0x0080;
|
||||||
public static final short SPECIAL_BUTTON_FLAG = 0x0400;
|
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
|
||||||
}
|
}
|
||||||
@@ -7,4 +7,5 @@ public class KeyboardPacket {
|
|||||||
public static final byte MODIFIER_SHIFT = 0x01;
|
public static final byte MODIFIER_SHIFT = 0x01;
|
||||||
public static final byte MODIFIER_CTRL = 0x02;
|
public static final byte MODIFIER_CTRL = 0x02;
|
||||||
public static final byte MODIFIER_ALT = 0x04;
|
public static final byte MODIFIER_ALT = 0x04;
|
||||||
|
public static final byte MODIFIER_META = 0x08;
|
||||||
}
|
}
|
||||||
@@ -14,13 +14,13 @@ public class MoonBridge {
|
|||||||
public static final int VIDEO_FORMAT_H264 = 0x0001;
|
public static final int VIDEO_FORMAT_H264 = 0x0001;
|
||||||
public static final int VIDEO_FORMAT_H265 = 0x0100;
|
public static final int VIDEO_FORMAT_H265 = 0x0100;
|
||||||
public static final int VIDEO_FORMAT_H265_MAIN10 = 0x0200;
|
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_H264 = 0x000F;
|
||||||
public static final int VIDEO_FORMAT_MASK_H265 = 0xFF00;
|
public static final int VIDEO_FORMAT_MASK_H265 = 0x0F00;
|
||||||
|
public static final int VIDEO_FORMAT_MASK_AV1 = 0xF000;
|
||||||
public static final int ENCFLG_NONE = 0;
|
public static final int VIDEO_FORMAT_MASK_10BIT = 0x2200;
|
||||||
public static final int ENCFLG_AUDIO = 1;
|
|
||||||
public static final int ENCFLG_ALL = 0xFFFFFFFF;
|
|
||||||
|
|
||||||
public static final int BUFFER_TYPE_PICDATA = 0;
|
public static final int BUFFER_TYPE_PICDATA = 0;
|
||||||
public static final int BUFFER_TYPE_SPS = 1;
|
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_DIRECT_SUBMIT = 1;
|
||||||
public static final int CAPABILITY_REFERENCE_FRAME_INVALIDATION_AVC = 2;
|
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_HEVC = 4;
|
||||||
|
public static final int CAPABILITY_REFERENCE_FRAME_INVALIDATION_AV1 = 0x40;
|
||||||
|
|
||||||
public static final int DR_OK = 0;
|
public static final int DR_OK = 0;
|
||||||
public static final int DR_NEED_IDR = -1;
|
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 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 AudioRenderer audioRenderer;
|
||||||
private static VideoDecoderRenderer videoRenderer;
|
private static VideoDecoderRenderer videoRenderer;
|
||||||
private static NvConnectionListener connectionListener;
|
private static NvConnectionListener connectionListener;
|
||||||
@@ -165,11 +218,11 @@ public class MoonBridge {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static int bridgeDrSubmitDecodeUnit(byte[] decodeUnitData, int decodeUnitLength, int decodeUnitType,
|
public static int bridgeDrSubmitDecodeUnit(byte[] decodeUnitData, int decodeUnitLength, int decodeUnitType,
|
||||||
int frameNumber, int frameType,
|
int frameNumber, int frameType, char frameHostProcessingLatency,
|
||||||
long receiveTimeMs, long enqueueTimeMs) {
|
long receiveTimeUs, long enqueueTimeUs) {
|
||||||
if (videoRenderer != null) {
|
if (videoRenderer != null) {
|
||||||
return videoRenderer.submitDecodeUnit(decodeUnitData, decodeUnitLength,
|
return videoRenderer.submitDecodeUnit(decodeUnitData, decodeUnitLength,
|
||||||
decodeUnitType, frameNumber, frameType, receiveTimeMs, enqueueTimeMs);
|
decodeUnitType, frameNumber, frameType, frameHostProcessingLatency, receiveTimeUs, enqueueTimeUs);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return DR_OK;
|
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) {
|
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,
|
public static native int startConnection(String address, String appVersion, String gfeVersion,
|
||||||
String rtspSessionUrl,
|
String rtspSessionUrl, int serverCodecModeSupport,
|
||||||
int width, int height, int fps,
|
int width, int height, int fps,
|
||||||
int bitrate, int packetSize, int streamingRemotely,
|
int bitrate, int packetSize, int streamingRemotely,
|
||||||
int audioConfiguration, boolean supportsHevc,
|
int audioConfiguration, int supportedVideoFormats,
|
||||||
boolean enableHdr,
|
|
||||||
int hevcBitratePercentageMultiplier,
|
|
||||||
int clientRefreshRateX100,
|
int clientRefreshRateX100,
|
||||||
int encryptionFlags,
|
|
||||||
byte[] riAesKey, byte[] riAesIv,
|
byte[] riAesKey, byte[] riAesIv,
|
||||||
int videoCapabilities,
|
int videoCapabilities,
|
||||||
int colorSpace, int colorRange);
|
int colorSpace, int colorRange);
|
||||||
@@ -295,22 +363,32 @@ public class MoonBridge {
|
|||||||
public static native void sendMouseButton(byte buttonEvent, byte mouseButton);
|
public static native void sendMouseButton(byte buttonEvent, byte mouseButton);
|
||||||
|
|
||||||
public static native void sendMultiControllerInput(short controllerNumber,
|
public static native void sendMultiControllerInput(short controllerNumber,
|
||||||
short activeGamepadMask, short buttonFlags,
|
short activeGamepadMask, int buttonFlags,
|
||||||
byte leftTrigger, byte rightTrigger,
|
byte leftTrigger, byte rightTrigger,
|
||||||
short leftStickX, short leftStickY,
|
short leftStickX, short leftStickY,
|
||||||
short rightStickX, short rightStickY);
|
short rightStickX, short rightStickY);
|
||||||
|
|
||||||
public static native void sendControllerInput(short buttonFlags,
|
public static native int sendTouchEvent(byte eventType, int pointerId, float x, float y, float pressure,
|
||||||
byte leftTrigger, byte rightTrigger,
|
float contactAreaMajor, float contactAreaMinor, short rotation);
|
||||||
short leftStickX, short leftStickY,
|
|
||||||
short rightStickX, short rightStickY);
|
|
||||||
|
|
||||||
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 sendMouseHighResScroll(short scrollAmount);
|
||||||
|
|
||||||
|
public static native void sendMouseHighResHScroll(short scrollAmount);
|
||||||
|
|
||||||
public static native void sendUtf8Text(String text);
|
public static native void sendUtf8Text(String text);
|
||||||
|
|
||||||
public static native String getStageName(int stage);
|
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
|
// 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 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();
|
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;
|
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;
|
import com.limelight.LimeLog;
|
||||||
|
|
||||||
public class MdnsDiscoveryAgent implements ServiceListener {
|
import java.net.Inet4Address;
|
||||||
public static final String SERVICE_TYPE = "_nvstream._tcp.local.";
|
import java.net.Inet6Address;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
private MdnsDiscoveryListener listener;
|
public abstract class MdnsDiscoveryAgent {
|
||||||
private Thread discoveryThread;
|
protected MdnsDiscoveryListener listener;
|
||||||
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
|
protected HashSet<MdnsComputer> computers = new HashSet<>();
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@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 (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) {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public MdnsDiscoveryAgent(MdnsDiscoveryListener listener) {
|
public MdnsDiscoveryAgent(MdnsDiscoveryListener listener) {
|
||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleResolvedServiceInfo(ServiceInfo info) {
|
public abstract void startDiscovery(final int discoveryIntervalMs);
|
||||||
synchronized (pendingResolution) {
|
|
||||||
pendingResolution.remove(info.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
public abstract void stopDiscovery();
|
||||||
handleServiceInfo(info);
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
protected void reportNewComputer(String name, int port, Inet4Address[] v4Addrs, Inet6Address[] v6Addrs) {
|
||||||
// Invalid DNS response
|
LimeLog.info("mDNS: "+name+" has "+v4Addrs.length+" IPv4 addresses");
|
||||||
LimeLog.info("mDNS: Invalid response for machine: "+info.getName());
|
LimeLog.info("mDNS: "+name+" has "+v6Addrs.length+" IPv6 addresses");
|
||||||
return;
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Inet6Address getLocalAddress(Inet6Address[] addresses) {
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<MdnsComputer> getComputerSet() {
|
||||||
|
synchronized (computers) {
|
||||||
|
return new ArrayList<>(computers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static Inet6Address getLocalAddress(Inet6Address[] addresses) {
|
||||||
for (Inet6Address addr : addresses) {
|
for (Inet6Address addr : addresses) {
|
||||||
if (addr.isLinkLocalAddress() || addr.isSiteLocalAddress()) {
|
if (addr.isLinkLocalAddress() || addr.isSiteLocalAddress()) {
|
||||||
return addr;
|
return addr;
|
||||||
@@ -174,7 +72,7 @@ public class MdnsDiscoveryAgent implements ServiceListener {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Inet6Address getLinkLocalAddress(Inet6Address[] addresses) {
|
protected static Inet6Address getLinkLocalAddress(Inet6Address[] addresses) {
|
||||||
for (Inet6Address addr : addresses) {
|
for (Inet6Address addr : addresses) {
|
||||||
if (addr.isLinkLocalAddress()) {
|
if (addr.isLinkLocalAddress()) {
|
||||||
LimeLog.info("Found link-local address: "+addr.getHostAddress());
|
LimeLog.info("Found link-local address: "+addr.getHostAddress());
|
||||||
@@ -185,7 +83,7 @@ public class MdnsDiscoveryAgent implements ServiceListener {
|
|||||||
return null;
|
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
|
// 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).
|
// with a global address (this will work for SLAAC but not DHCPv6).
|
||||||
Inet6Address linkLocalAddr = getLinkLocalAddress(addresses);
|
Inet6Address linkLocalAddr = getLinkLocalAddress(addresses);
|
||||||
@@ -247,162 +145,4 @@ public class MdnsDiscoveryAgent implements ServiceListener {
|
|||||||
|
|
||||||
return null;
|
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 {
|
public interface MdnsDiscoveryListener {
|
||||||
void notifyComputerAdded(MdnsComputer computer);
|
void notifyComputerAdded(MdnsComputer computer);
|
||||||
void notifyComputerRemoved(MdnsComputer computer);
|
|
||||||
void notifyDiscoveryFailure(Exception e);
|
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 {
|
try {
|
||||||
sendPacketsForAddress(InetAddress.getByName("255.255.255.255"), address.port, sock, payload);
|
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)) {
|
for (InetAddress resolvedAddress : InetAddress.getAllByName(address.address)) {
|
||||||
|
try {
|
||||||
sendPacketsForAddress(resolvedAddress, address.port, sock, payload);
|
sendPacketsForAddress(resolvedAddress, address.port, sock, payload);
|
||||||
|
sentWolPacket = true;
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
lastException = e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// We may have addresses that don't resolve on this subnet,
|
// We may have addresses that don't resolve on this subnet,
|
||||||
|
|||||||
@@ -98,8 +98,31 @@ public class AddComputerManually extends Activity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private URI parseRawUserInputToUri(String rawUserInput) {
|
||||||
|
try {
|
||||||
|
// Try adding a scheme and parsing the remaining input.
|
||||||
|
// This handles input like 127.0.0.1:47989, [::1], [::1]:47989, and 127.0.0.1.
|
||||||
|
URI uri = new URI("moonlight://" + rawUserInput);
|
||||||
|
if (uri.getHost() != null && !uri.getHost().isEmpty()) {
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
} catch (URISyntaxException ignored) {}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Attempt to escape the input as an IPv6 literal.
|
||||||
|
// This handles input like ::1.
|
||||||
|
URI uri = new URI("moonlight://[" + rawUserInput + "]");
|
||||||
|
if (uri.getHost() != null && !uri.getHost().isEmpty()) {
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
} catch (URISyntaxException ignored) {}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private void doAddPc(String rawUserInput) throws InterruptedException {
|
private void doAddPc(String rawUserInput) throws InterruptedException {
|
||||||
boolean wrongSiteLocal = false;
|
boolean wrongSiteLocal = false;
|
||||||
|
boolean invalidInput = false;
|
||||||
boolean success;
|
boolean success;
|
||||||
int portTestResult;
|
int portTestResult;
|
||||||
|
|
||||||
@@ -109,17 +132,12 @@ public class AddComputerManually extends Activity {
|
|||||||
try {
|
try {
|
||||||
ComputerDetails details = new ComputerDetails();
|
ComputerDetails details = new ComputerDetails();
|
||||||
|
|
||||||
// Use URI-style parsing for the host address input
|
// Check if we parsed a host address successfully
|
||||||
URI uri = new URI("moonlight://" + rawUserInput);
|
URI uri = parseRawUserInputToUri(rawUserInput);
|
||||||
|
if (uri != null && uri.getHost() != null && !uri.getHost().isEmpty()) {
|
||||||
String host = uri.getHost();
|
String host = uri.getHost();
|
||||||
int port = uri.getPort();
|
int port = uri.getPort();
|
||||||
|
|
||||||
// URI allows empty hosts, but we don't want that
|
|
||||||
if (host == null || host.isEmpty()) {
|
|
||||||
throw new URISyntaxException(rawUserInput, "Host failed to parse");
|
|
||||||
}
|
|
||||||
|
|
||||||
// If a port was not specified, use the default
|
// If a port was not specified, use the default
|
||||||
if (port == -1) {
|
if (port == -1) {
|
||||||
port = NvHTTP.DEFAULT_HTTP_PORT;
|
port = NvHTTP.DEFAULT_HTTP_PORT;
|
||||||
@@ -130,6 +148,11 @@ public class AddComputerManually extends Activity {
|
|||||||
if (!success){
|
if (!success){
|
||||||
wrongSiteLocal = isWrongSubnetSiteLocalAddress(host);
|
wrongSiteLocal = isWrongSubnetSiteLocalAddress(host);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// Invalid user input
|
||||||
|
success = false;
|
||||||
|
invalidInput = true;
|
||||||
|
}
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
// Propagate the InterruptedException to the caller for proper handling
|
// Propagate the InterruptedException to the caller for proper handling
|
||||||
dialog.dismiss();
|
dialog.dismiss();
|
||||||
@@ -139,13 +162,11 @@ public class AddComputerManually extends Activity {
|
|||||||
// https://github.com/square/okhttp/blob/okhttp_27/okhttp/src/main/java/com/squareup/okhttp/HttpUrl.java#L705
|
// https://github.com/square/okhttp/blob/okhttp_27/okhttp/src/main/java/com/squareup/okhttp/HttpUrl.java#L705
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
success = false;
|
success = false;
|
||||||
} catch (URISyntaxException e) {
|
invalidInput = true;
|
||||||
e.printStackTrace();
|
|
||||||
success = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keep the SpinnerDialog open while testing connectivity
|
// Keep the SpinnerDialog open while testing connectivity
|
||||||
if (!success && !wrongSiteLocal) {
|
if (!success && !wrongSiteLocal && !invalidInput) {
|
||||||
// Run the test before dismissing the spinner because it can take a few seconds.
|
// Run the test before dismissing the spinner because it can take a few seconds.
|
||||||
portTestResult = MoonBridge.testClientConnectivity(ServerHelper.CONNECTION_TEST_SERVER, 443,
|
portTestResult = MoonBridge.testClientConnectivity(ServerHelper.CONNECTION_TEST_SERVER, 443,
|
||||||
MoonBridge.ML_PORT_FLAG_TCP_47984 | MoonBridge.ML_PORT_FLAG_TCP_47989);
|
MoonBridge.ML_PORT_FLAG_TCP_47984 | MoonBridge.ML_PORT_FLAG_TCP_47989);
|
||||||
@@ -156,7 +177,10 @@ public class AddComputerManually extends Activity {
|
|||||||
|
|
||||||
dialog.dismiss();
|
dialog.dismiss();
|
||||||
|
|
||||||
if (wrongSiteLocal) {
|
if (invalidInput) {
|
||||||
|
Dialog.displayDialog(this, getResources().getString(R.string.conn_error_title), getResources().getString(R.string.addpc_unknown_host), false);
|
||||||
|
}
|
||||||
|
else if (wrongSiteLocal) {
|
||||||
Dialog.displayDialog(this, getResources().getString(R.string.conn_error_title), getResources().getString(R.string.addpc_wrong_sitelocal), false);
|
Dialog.displayDialog(this, getResources().getString(R.string.conn_error_title), getResources().getString(R.string.addpc_wrong_sitelocal), false);
|
||||||
}
|
}
|
||||||
else if (!success) {
|
else if (!success) {
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import com.limelight.R;
|
|||||||
import static com.limelight.binding.input.virtual_controller.VirtualControllerConfigurationLoader.OSC_PREFERENCE;
|
import static com.limelight.binding.input.virtual_controller.VirtualControllerConfigurationLoader.OSC_PREFERENCE;
|
||||||
|
|
||||||
public class ConfirmDeleteOscPreference extends DialogPreference {
|
public class ConfirmDeleteOscPreference extends DialogPreference {
|
||||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
|
||||||
public ConfirmDeleteOscPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
public ConfirmDeleteOscPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||||
super(context, attrs, defStyleAttr, defStyleRes);
|
super(context, attrs, defStyleAttr, defStyleRes);
|
||||||
}
|
}
|
||||||
@@ -26,7 +25,6 @@ public class ConfirmDeleteOscPreference extends DialogPreference {
|
|||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
|
||||||
public ConfirmDeleteOscPreference(Context context) {
|
public ConfirmDeleteOscPreference(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,12 +11,10 @@ import android.provider.Settings;
|
|||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
|
||||||
public class LanguagePreference extends ListPreference {
|
public class LanguagePreference extends ListPreference {
|
||||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
|
||||||
public LanguagePreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
public LanguagePreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||||
super(context, attrs, defStyleAttr, defStyleRes);
|
super(context, attrs, defStyleAttr, defStyleRes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
|
||||||
public LanguagePreference(Context context, AttributeSet attrs, int defStyleAttr) {
|
public LanguagePreference(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||||
super(context, attrs, defStyleAttr);
|
super(context, attrs, defStyleAttr);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,19 @@ import android.view.Display;
|
|||||||
import com.limelight.nvstream.jni.MoonBridge;
|
import com.limelight.nvstream.jni.MoonBridge;
|
||||||
|
|
||||||
public class PreferenceConfiguration {
|
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_RES_FPS_PREF_STRING = "list_resolution_fps";
|
||||||
private static final String LEGACY_ENABLE_51_SURROUND_PREF_STRING = "checkbox_51_surround";
|
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 VIDEO_FORMAT_PREF_STRING = "video_format";
|
||||||
private static final String ONSCREEN_CONTROLLER_PREF_STRING = "checkbox_show_onscreen_controls";
|
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 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 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_HDR_PREF_STRING = "checkbox_enable_hdr";
|
||||||
private static final String ENABLE_PIP_PREF_STRING = "checkbox_enable_pip";
|
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 ENABLE_PERF_OVERLAY_STRING = "checkbox_enable_perf_overlay";
|
||||||
private static final String BIND_ALL_USB_STRING = "checkbox_usb_bind_all";
|
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 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";
|
private static final String MOUSE_NAV_BUTTONS_STRING = "checkbox_mouse_nav_buttons";
|
||||||
static final String UNLOCK_FPS_STRING = "checkbox_unlock_fps";
|
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_OSC_PREF_STRING = "checkbox_vibrate_osc";
|
||||||
private static final String VIBRATE_FALLBACK_PREF_STRING = "checkbox_vibrate_fallback";
|
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 FLIP_FACE_BUTTONS_PREF_STRING = "checkbox_flip_face_buttons";
|
||||||
private static final String TOUCHSCREEN_TRACKPAD_PREF_STRING = "checkbox_touchscreen_trackpad";
|
private static final String TOUCHSCREEN_TRACKPAD_PREF_STRING = "checkbox_touchscreen_trackpad";
|
||||||
private static final String LATENCY_TOAST_PREF_STRING = "checkbox_enable_post_stream_toast";
|
private static final String LATENCY_TOAST_PREF_STRING = "checkbox_enable_post_stream_toast";
|
||||||
@@ -48,6 +64,10 @@ public class PreferenceConfiguration {
|
|||||||
private static final String ABSOLUTE_MOUSE_MODE_PREF_STRING = "checkbox_absolute_mouse_mode";
|
private static final String ABSOLUTE_MOUSE_MODE_PREF_STRING = "checkbox_absolute_mouse_mode";
|
||||||
private static final String ENABLE_AUDIO_FX_PREF_STRING = "checkbox_enable_audiofx";
|
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 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_RESOLUTION = "1280x720";
|
||||||
static final String DEFAULT_FPS = "60";
|
static final String DEFAULT_FPS = "60";
|
||||||
@@ -61,17 +81,21 @@ public class PreferenceConfiguration {
|
|||||||
private static final boolean DEFAULT_MULTI_CONTROLLER = true;
|
private static final boolean DEFAULT_MULTI_CONTROLLER = true;
|
||||||
private static final boolean DEFAULT_USB_DRIVER = true;
|
private static final boolean DEFAULT_USB_DRIVER = true;
|
||||||
private static final String DEFAULT_VIDEO_FORMAT = "auto";
|
private static final String DEFAULT_VIDEO_FORMAT = "auto";
|
||||||
|
|
||||||
private static final boolean ONSCREEN_CONTROLLER_DEFAULT = false;
|
private static final boolean ONSCREEN_CONTROLLER_DEFAULT = false;
|
||||||
private static final boolean ONLY_L3_R3_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_HDR = false;
|
||||||
private static final boolean DEFAULT_ENABLE_PIP = false;
|
private static final boolean DEFAULT_ENABLE_PIP = false;
|
||||||
private static final boolean DEFAULT_ENABLE_PERF_OVERLAY = false;
|
private static final boolean DEFAULT_ENABLE_PERF_OVERLAY = false;
|
||||||
private static final boolean DEFAULT_BIND_ALL_USB = false;
|
private static final boolean DEFAULT_BIND_ALL_USB = false;
|
||||||
private static final boolean DEFAULT_MOUSE_EMULATION = true;
|
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_MOUSE_NAV_BUTTONS = false;
|
||||||
private static final boolean DEFAULT_UNLOCK_FPS = false;
|
private static final boolean DEFAULT_UNLOCK_FPS = false;
|
||||||
private static final boolean DEFAULT_VIBRATE_OSC = true;
|
private static final boolean DEFAULT_VIBRATE_OSC = true;
|
||||||
private static final boolean DEFAULT_VIBRATE_FALLBACK = false;
|
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_FLIP_FACE_BUTTONS = false;
|
||||||
private static final boolean DEFAULT_TOUCHSCREEN_TRACKPAD = true;
|
private static final boolean DEFAULT_TOUCHSCREEN_TRACKPAD = true;
|
||||||
private static final String DEFAULT_AUDIO_CONFIG = "2"; // Stereo
|
private static final String DEFAULT_AUDIO_CONFIG = "2"; // Stereo
|
||||||
@@ -80,27 +104,27 @@ public class PreferenceConfiguration {
|
|||||||
private static final boolean DEFAULT_ABSOLUTE_MOUSE_MODE = false;
|
private static final boolean DEFAULT_ABSOLUTE_MOUSE_MODE = false;
|
||||||
private static final boolean DEFAULT_ENABLE_AUDIO_FX = false;
|
private static final boolean DEFAULT_ENABLE_AUDIO_FX = false;
|
||||||
private static final boolean DEFAULT_REDUCE_REFRESH_RATE = 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;
|
private static final boolean DEFAULT_GAMEPAD_TOUCHPAD_AS_MOUSE = false;
|
||||||
public static final int AUTOSELECT_H265 = 0;
|
private static final boolean DEFAULT_GAMEPAD_MOTION_SENSORS = true;
|
||||||
public static final int FORCE_H265_OFF = 1;
|
private static final boolean DEFAULT_GAMEPAD_MOTION_FALLBACK = false;
|
||||||
|
|
||||||
public static final int FRAME_PACING_MIN_LATENCY = 0;
|
public static final int FRAME_PACING_MIN_LATENCY = 0;
|
||||||
public static final int FRAME_PACING_BALANCED = 1;
|
public static final int FRAME_PACING_BALANCED = 1;
|
||||||
public static final int FRAME_PACING_CAP_FPS = 2;
|
public static final int FRAME_PACING_CAP_FPS = 2;
|
||||||
public static final int FRAME_PACING_MAX_SMOOTHNESS = 3;
|
public static final int FRAME_PACING_MAX_SMOOTHNESS = 3;
|
||||||
|
|
||||||
public static final String RES_360P = "s_640x360";
|
public static final String RES_360P = "640x360";
|
||||||
public static final String RES_480P = "s_854x480";
|
public static final String RES_480P = "854x480";
|
||||||
public static final String RES_720P = "s_1280x720";
|
public static final String RES_720P = "1280x720";
|
||||||
public static final String RES_1080P = "s_1920x1080";
|
public static final String RES_1080P = "1920x1080";
|
||||||
public static final String RES_1440P = "s_2560x1440";
|
public static final String RES_1440P = "2560x1440";
|
||||||
public static final String RES_4K = "s_3840x2160";
|
public static final String RES_4K = "3840x2160";
|
||||||
|
public static final String RES_NATIVE = "Native";
|
||||||
|
|
||||||
public StreamResolution resolution;
|
public int width, height, fps;
|
||||||
public int fps;
|
|
||||||
public int bitrate;
|
public int bitrate;
|
||||||
public int videoFormat;
|
public FormatOption videoFormat;
|
||||||
public int deadzonePercentage;
|
public int deadzonePercentage;
|
||||||
public int oscOpacity;
|
public int oscOpacity;
|
||||||
public boolean stretchVideo, enableSops, playHostAudio, disableWarnings;
|
public boolean stretchVideo, enableSops, playHostAudio, disableWarnings;
|
||||||
@@ -108,26 +132,31 @@ public class PreferenceConfiguration {
|
|||||||
public boolean smallIconMode, multiController, usbDriver, flipFaceButtons;
|
public boolean smallIconMode, multiController, usbDriver, flipFaceButtons;
|
||||||
public boolean onscreenController;
|
public boolean onscreenController;
|
||||||
public boolean onlyL3R3;
|
public boolean onlyL3R3;
|
||||||
|
public boolean showGuideButton;
|
||||||
public boolean enableHdr;
|
public boolean enableHdr;
|
||||||
public boolean enablePip;
|
public boolean enablePip;
|
||||||
public boolean enablePerfOverlay;
|
public boolean enablePerfOverlay;
|
||||||
public boolean enableLatencyToast;
|
public boolean enableLatencyToast;
|
||||||
public boolean bindAllUsb;
|
public boolean bindAllUsb;
|
||||||
public boolean mouseEmulation;
|
public boolean mouseEmulation;
|
||||||
|
public AnalogStickForScrolling analogStickForScrolling;
|
||||||
public boolean mouseNavButtons;
|
public boolean mouseNavButtons;
|
||||||
public boolean unlockFps;
|
public boolean unlockFps;
|
||||||
public boolean vibrateOsc;
|
public boolean vibrateOsc;
|
||||||
public boolean vibrateFallbackToDevice;
|
public boolean vibrateFallbackToDevice;
|
||||||
|
public int vibrateFallbackToDeviceStrength;
|
||||||
public boolean touchscreenTrackpad;
|
public boolean touchscreenTrackpad;
|
||||||
public MoonBridge.AudioConfiguration audioConfiguration;
|
public MoonBridge.AudioConfiguration audioConfiguration;
|
||||||
public int framePacing;
|
public int framePacing;
|
||||||
public boolean absoluteMouseMode;
|
public boolean absoluteMouseMode;
|
||||||
public boolean enableAudioFx;
|
public boolean enableAudioFx;
|
||||||
public boolean reduceRefreshRate;
|
public boolean reduceRefreshRate;
|
||||||
|
public boolean fullRange;
|
||||||
|
public boolean gamepadMotionSensors;
|
||||||
|
public boolean gamepadTouchpadAsMouse;
|
||||||
|
public boolean gamepadMotionSensorsFallbackToDevice;
|
||||||
|
|
||||||
// This is used only for migration to the new type code format of resolution strings
|
public static boolean isNativeResolution(int width, int height) {
|
||||||
// It doesn't properly handle custom resolutions!
|
|
||||||
private static boolean legacyIsNativeResolution(int width, int height) {
|
|
||||||
// It's not a native resolution if it matches an existing resolution option
|
// It's not a native resolution if it matches an existing resolution option
|
||||||
if (width == 640 && height == 360) {
|
if (width == 640 && height == 360) {
|
||||||
return false;
|
return false;
|
||||||
@@ -177,8 +206,6 @@ public class PreferenceConfiguration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static String convertFromLegacyResolutionString(String resString) {
|
private static String convertFromLegacyResolutionString(String resString) {
|
||||||
if (!resString.contains("x")) {
|
|
||||||
// Convert from hardcoded strings to strings with dimensions embedded
|
|
||||||
if (resString.equalsIgnoreCase("360p")) {
|
if (resString.equalsIgnoreCase("360p")) {
|
||||||
return RES_360P;
|
return RES_360P;
|
||||||
}
|
}
|
||||||
@@ -202,51 +229,94 @@ public class PreferenceConfiguration {
|
|||||||
return RES_720P;
|
return RES_720P;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (Character.isDigit(resString.charAt(0))) {
|
|
||||||
// Convert to type code prefix format
|
private static int getWidthFromResolutionString(String resString) {
|
||||||
String[] dims = resString.split("x");
|
return Integer.parseInt(resString.split("x")[0]);
|
||||||
int width = Integer.parseInt(dims[0]);
|
|
||||||
int height = Integer.parseInt(dims[1]);
|
|
||||||
return new StreamResolution(width, height,
|
|
||||||
legacyIsNativeResolution(width, height) ? StreamResolution.ResolutionType.NATIVE : StreamResolution.ResolutionType.STANDARD)
|
|
||||||
.toPrefString();
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
return resString;
|
private static int getHeightFromResolutionString(String resString) {
|
||||||
|
return Integer.parseInt(resString.split("x")[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getResolutionString(int width, int height) {
|
||||||
|
switch (height) {
|
||||||
|
case 360:
|
||||||
|
return RES_360P;
|
||||||
|
case 480:
|
||||||
|
return RES_480P;
|
||||||
|
default:
|
||||||
|
case 720:
|
||||||
|
return RES_720P;
|
||||||
|
case 1080:
|
||||||
|
return RES_1080P;
|
||||||
|
case 1440:
|
||||||
|
return RES_1440P;
|
||||||
|
case 2160:
|
||||||
|
return RES_4K;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getDefaultBitrate(String resString, String fpsString) {
|
public static int getDefaultBitrate(String resString, String fpsString) {
|
||||||
StreamResolution res = new StreamResolution(resString);
|
int width = getWidthFromResolutionString(resString);
|
||||||
|
int height = getHeightFromResolutionString(resString);
|
||||||
int fps = Integer.parseInt(fpsString);
|
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:
|
// This logic is shamelessly stolen from Moonlight Qt:
|
||||||
// https://github.com/moonlight-stream/moonlight-qt/blob/master/app/settings/streamingpreferences.cpp
|
// https://github.com/moonlight-stream/moonlight-qt/blob/master/app/settings/streamingpreferences.cpp
|
||||||
|
|
||||||
if (res.width * res.height <= 640 * 360) {
|
// Don't scale bitrate linearly beyond 60 FPS. It's definitely not a linear
|
||||||
return (int)(1000 * (fps / 30.0));
|
// 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 (res.width * res.height <= 854 * 480) {
|
else if (pixels < pixelVals[i]) {
|
||||||
return (int)(1500 * (fps / 30.0));
|
if (i == 0) {
|
||||||
|
// Never go below the lowest resolution entry
|
||||||
|
resolutionFactor = factorVals[i];
|
||||||
}
|
}
|
||||||
// This covers 1280x720 and 1280x800 too
|
else {
|
||||||
else if (res.width * res.height <= 1366 * 768) {
|
// Interpolate between the entry greater than the chosen resolution (i) and the entry less than the chosen resolution (i-1)
|
||||||
return (int)(5000 * (fps / 30.0));
|
resolutionFactor = ((float)(pixels - pixelVals[i-1]) / (pixelVals[i] - pixelVals[i-1])) * (factorVals[i] - factorVals[i-1]) + factorVals[i-1];
|
||||||
}
|
}
|
||||||
else if (res.width * res.height <= 1920 * 1200) {
|
break;
|
||||||
return (int)(10000 * (fps / 30.0));
|
|
||||||
}
|
}
|
||||||
else if (res.width * res.height <= 2560 * 1600) {
|
else if (pixelVals[i] == -1) {
|
||||||
return (int)(20000 * (fps / 30.0));
|
// Never go above the highest resolution entry
|
||||||
|
resolutionFactor = factorVals[i-1];
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else /* if (res.width * res.height <= 3840 * 2160) */ {
|
|
||||||
return (int)(40000 * (fps / 30.0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return (int)Math.round(resolutionFactor * frameRateFactor) * 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean getDefaultSmallMode(Context context) {
|
public static boolean getDefaultSmallMode(Context context) {
|
||||||
@@ -276,22 +346,25 @@ public class PreferenceConfiguration {
|
|||||||
prefs.getString(FPS_PREF_STRING, DEFAULT_FPS));
|
prefs.getString(FPS_PREF_STRING, DEFAULT_FPS));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getVideoFormatValue(Context context) {
|
private static FormatOption getVideoFormatValue(Context context) {
|
||||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
|
|
||||||
String str = prefs.getString(VIDEO_FORMAT_PREF_STRING, DEFAULT_VIDEO_FORMAT);
|
String str = prefs.getString(VIDEO_FORMAT_PREF_STRING, DEFAULT_VIDEO_FORMAT);
|
||||||
if (str.equals("auto")) {
|
if (str.equals("auto")) {
|
||||||
return AUTOSELECT_H265;
|
return FormatOption.AUTO;
|
||||||
|
}
|
||||||
|
else if (str.equals("forceav1")) {
|
||||||
|
return FormatOption.FORCE_AV1;
|
||||||
}
|
}
|
||||||
else if (str.equals("forceh265")) {
|
else if (str.equals("forceh265")) {
|
||||||
return FORCE_H265_ON;
|
return FormatOption.FORCE_HEVC;
|
||||||
}
|
}
|
||||||
else if (str.equals("neverh265")) {
|
else if (str.equals("neverh265")) {
|
||||||
return FORCE_H265_OFF;
|
return FormatOption.FORCE_H264;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Should never get here
|
// Should never get here
|
||||||
return AUTOSELECT_H265;
|
return FormatOption.AUTO;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -326,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) {
|
public static void resetStreamingSettings(Context context) {
|
||||||
// We consider resolution, FPS, bitrate, HDR, and video format as "streaming settings" here
|
// We consider resolution, FPS, bitrate, HDR, and video format as "streaming settings" here
|
||||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
@@ -338,6 +426,7 @@ public class PreferenceConfiguration {
|
|||||||
.remove(VIDEO_FORMAT_PREF_STRING)
|
.remove(VIDEO_FORMAT_PREF_STRING)
|
||||||
.remove(ENABLE_HDR_PREF_STRING)
|
.remove(ENABLE_HDR_PREF_STRING)
|
||||||
.remove(UNLOCK_FPS_STRING)
|
.remove(UNLOCK_FPS_STRING)
|
||||||
|
.remove(FULL_RANGE_PREF_STRING)
|
||||||
.apply();
|
.apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -371,46 +460,55 @@ public class PreferenceConfiguration {
|
|||||||
String str = prefs.getString(LEGACY_RES_FPS_PREF_STRING, null);
|
String str = prefs.getString(LEGACY_RES_FPS_PREF_STRING, null);
|
||||||
if (str != null) {
|
if (str != null) {
|
||||||
if (str.equals("360p30")) {
|
if (str.equals("360p30")) {
|
||||||
config.resolution = new StreamResolution(640, 360, StreamResolution.ResolutionType.STANDARD);
|
config.width = 640;
|
||||||
|
config.height = 360;
|
||||||
config.fps = 30;
|
config.fps = 30;
|
||||||
}
|
}
|
||||||
else if (str.equals("360p60")) {
|
else if (str.equals("360p60")) {
|
||||||
config.resolution = new StreamResolution(640, 360, StreamResolution.ResolutionType.STANDARD);
|
config.width = 640;
|
||||||
|
config.height = 360;
|
||||||
config.fps = 60;
|
config.fps = 60;
|
||||||
}
|
}
|
||||||
else if (str.equals("720p30")) {
|
else if (str.equals("720p30")) {
|
||||||
config.resolution = new StreamResolution(1280, 720, StreamResolution.ResolutionType.STANDARD);
|
config.width = 1280;
|
||||||
|
config.height = 720;
|
||||||
config.fps = 30;
|
config.fps = 30;
|
||||||
}
|
}
|
||||||
else if (str.equals("720p60")) {
|
else if (str.equals("720p60")) {
|
||||||
config.resolution = new StreamResolution(1280, 720, StreamResolution.ResolutionType.STANDARD);
|
config.width = 1280;
|
||||||
|
config.height = 720;
|
||||||
config.fps = 60;
|
config.fps = 60;
|
||||||
}
|
}
|
||||||
else if (str.equals("1080p30")) {
|
else if (str.equals("1080p30")) {
|
||||||
config.resolution = new StreamResolution(1920, 1080, StreamResolution.ResolutionType.STANDARD);
|
config.width = 1920;
|
||||||
|
config.height = 1080;
|
||||||
config.fps = 30;
|
config.fps = 30;
|
||||||
}
|
}
|
||||||
else if (str.equals("1080p60")) {
|
else if (str.equals("1080p60")) {
|
||||||
config.resolution = new StreamResolution(1920, 1080, StreamResolution.ResolutionType.STANDARD);
|
config.width = 1920;
|
||||||
|
config.height = 1080;
|
||||||
config.fps = 60;
|
config.fps = 60;
|
||||||
}
|
}
|
||||||
else if (str.equals("4K30")) {
|
else if (str.equals("4K30")) {
|
||||||
config.resolution = new StreamResolution(3840, 2160, StreamResolution.ResolutionType.STANDARD);
|
config.width = 3840;
|
||||||
|
config.height = 2160;
|
||||||
config.fps = 30;
|
config.fps = 30;
|
||||||
}
|
}
|
||||||
else if (str.equals("4K60")) {
|
else if (str.equals("4K60")) {
|
||||||
config.resolution = new StreamResolution(3840, 2160, StreamResolution.ResolutionType.STANDARD);
|
config.width = 3840;
|
||||||
|
config.height = 2160;
|
||||||
config.fps = 60;
|
config.fps = 60;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Should never get here
|
// Should never get here
|
||||||
config.resolution = new StreamResolution(1280, 720, StreamResolution.ResolutionType.STANDARD);
|
config.width = 1280;
|
||||||
|
config.height = 720;
|
||||||
config.fps = 60;
|
config.fps = 60;
|
||||||
}
|
}
|
||||||
|
|
||||||
prefs.edit()
|
prefs.edit()
|
||||||
.remove(LEGACY_RES_FPS_PREF_STRING)
|
.remove(LEGACY_RES_FPS_PREF_STRING)
|
||||||
.putString(RESOLUTION_PREF_STRING, config.resolution.toPrefString())
|
.putString(RESOLUTION_PREF_STRING, getResolutionString(config.width, config.height))
|
||||||
.putString(FPS_PREF_STRING, ""+config.fps)
|
.putString(FPS_PREF_STRING, ""+config.fps)
|
||||||
.apply();
|
.apply();
|
||||||
}
|
}
|
||||||
@@ -419,12 +517,13 @@ public class PreferenceConfiguration {
|
|||||||
String resStr = prefs.getString(RESOLUTION_PREF_STRING, PreferenceConfiguration.DEFAULT_RESOLUTION);
|
String resStr = prefs.getString(RESOLUTION_PREF_STRING, PreferenceConfiguration.DEFAULT_RESOLUTION);
|
||||||
|
|
||||||
// Convert legacy resolution strings to the new style
|
// Convert legacy resolution strings to the new style
|
||||||
if (Character.isDigit(resStr.charAt(0)) || !resStr.contains("x")) {
|
if (!resStr.contains("x")) {
|
||||||
resStr = PreferenceConfiguration.convertFromLegacyResolutionString(resStr);
|
resStr = PreferenceConfiguration.convertFromLegacyResolutionString(resStr);
|
||||||
prefs.edit().putString(RESOLUTION_PREF_STRING, resStr).apply();
|
prefs.edit().putString(RESOLUTION_PREF_STRING, resStr).apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
config.resolution = new StreamResolution(resStr);
|
config.width = PreferenceConfiguration.getWidthFromResolutionString(resStr);
|
||||||
|
config.height = PreferenceConfiguration.getHeightFromResolutionString(resStr);
|
||||||
config.fps = Integer.parseInt(prefs.getString(FPS_PREF_STRING, PreferenceConfiguration.DEFAULT_FPS));
|
config.fps = Integer.parseInt(prefs.getString(FPS_PREF_STRING, PreferenceConfiguration.DEFAULT_FPS));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -434,6 +533,15 @@ public class PreferenceConfiguration {
|
|||||||
prefs.edit().putBoolean(SMALL_ICONS_PREF_STRING, getDefaultSmallMode(context)).apply();
|
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
|
// 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);
|
config.bitrate = prefs.getInt(BITRATE_PREF_STRING, prefs.getInt(BITRATE_PREF_OLD_STRING, 0) * 1000);
|
||||||
if (config.bitrate == 0) {
|
if (config.bitrate == 0) {
|
||||||
@@ -454,6 +562,8 @@ public class PreferenceConfiguration {
|
|||||||
config.videoFormat = getVideoFormatValue(context);
|
config.videoFormat = getVideoFormatValue(context);
|
||||||
config.framePacing = getFramePacingValue(context);
|
config.framePacing = getFramePacingValue(context);
|
||||||
|
|
||||||
|
config.analogStickForScrolling = getAnalogStickForScrollingValue(context);
|
||||||
|
|
||||||
config.deadzonePercentage = prefs.getInt(DEADZONE_PREF_STRING, DEFAULT_DEADZONE);
|
config.deadzonePercentage = prefs.getInt(DEADZONE_PREF_STRING, DEFAULT_DEADZONE);
|
||||||
|
|
||||||
config.oscOpacity = prefs.getInt(OSC_OPACITY_PREF_STRING, DEFAULT_OPACITY);
|
config.oscOpacity = prefs.getInt(OSC_OPACITY_PREF_STRING, DEFAULT_OPACITY);
|
||||||
@@ -470,6 +580,7 @@ public class PreferenceConfiguration {
|
|||||||
config.usbDriver = prefs.getBoolean(USB_DRIVER_PREF_SRING, DEFAULT_USB_DRIVER);
|
config.usbDriver = prefs.getBoolean(USB_DRIVER_PREF_SRING, DEFAULT_USB_DRIVER);
|
||||||
config.onscreenController = prefs.getBoolean(ONSCREEN_CONTROLLER_PREF_STRING, ONSCREEN_CONTROLLER_DEFAULT);
|
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.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.enableHdr = prefs.getBoolean(ENABLE_HDR_PREF_STRING, DEFAULT_ENABLE_HDR) && !isShieldAtvFirmwareWithBrokenHdr();
|
||||||
config.enablePip = prefs.getBoolean(ENABLE_PIP_PREF_STRING, DEFAULT_ENABLE_PIP);
|
config.enablePip = prefs.getBoolean(ENABLE_PIP_PREF_STRING, DEFAULT_ENABLE_PIP);
|
||||||
config.enablePerfOverlay = prefs.getBoolean(ENABLE_PERF_OVERLAY_STRING, DEFAULT_ENABLE_PERF_OVERLAY);
|
config.enablePerfOverlay = prefs.getBoolean(ENABLE_PERF_OVERLAY_STRING, DEFAULT_ENABLE_PERF_OVERLAY);
|
||||||
@@ -479,121 +590,18 @@ public class PreferenceConfiguration {
|
|||||||
config.unlockFps = prefs.getBoolean(UNLOCK_FPS_STRING, DEFAULT_UNLOCK_FPS);
|
config.unlockFps = prefs.getBoolean(UNLOCK_FPS_STRING, DEFAULT_UNLOCK_FPS);
|
||||||
config.vibrateOsc = prefs.getBoolean(VIBRATE_OSC_PREF_STRING, DEFAULT_VIBRATE_OSC);
|
config.vibrateOsc = prefs.getBoolean(VIBRATE_OSC_PREF_STRING, DEFAULT_VIBRATE_OSC);
|
||||||
config.vibrateFallbackToDevice = prefs.getBoolean(VIBRATE_FALLBACK_PREF_STRING, DEFAULT_VIBRATE_FALLBACK);
|
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.flipFaceButtons = prefs.getBoolean(FLIP_FACE_BUTTONS_PREF_STRING, DEFAULT_FLIP_FACE_BUTTONS);
|
||||||
config.touchscreenTrackpad = prefs.getBoolean(TOUCHSCREEN_TRACKPAD_PREF_STRING, DEFAULT_TOUCHSCREEN_TRACKPAD);
|
config.touchscreenTrackpad = prefs.getBoolean(TOUCHSCREEN_TRACKPAD_PREF_STRING, DEFAULT_TOUCHSCREEN_TRACKPAD);
|
||||||
config.enableLatencyToast = prefs.getBoolean(LATENCY_TOAST_PREF_STRING, DEFAULT_LATENCY_TOAST);
|
config.enableLatencyToast = prefs.getBoolean(LATENCY_TOAST_PREF_STRING, DEFAULT_LATENCY_TOAST);
|
||||||
config.absoluteMouseMode = prefs.getBoolean(ABSOLUTE_MOUSE_MODE_PREF_STRING, DEFAULT_ABSOLUTE_MOUSE_MODE);
|
config.absoluteMouseMode = prefs.getBoolean(ABSOLUTE_MOUSE_MODE_PREF_STRING, DEFAULT_ABSOLUTE_MOUSE_MODE);
|
||||||
config.enableAudioFx = prefs.getBoolean(ENABLE_AUDIO_FX_PREF_STRING, DEFAULT_ENABLE_AUDIO_FX);
|
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.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;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class StreamResolution {
|
|
||||||
public int width;
|
|
||||||
public int height;
|
|
||||||
public ResolutionType type;
|
|
||||||
public boolean portrait;
|
|
||||||
public boolean fullScreen;
|
|
||||||
|
|
||||||
private static final char RES_START_DELIMITER = '_';
|
|
||||||
private static final char RES_DIM_DELIMITER = 'x';
|
|
||||||
|
|
||||||
private static final char TYPE_CODE_STANDARD = 's';
|
|
||||||
private static final char TYPE_CODE_NATIVE = 'n';
|
|
||||||
|
|
||||||
private static final char OPTION_CODE_PORTRAIT = 'p';
|
|
||||||
private static final char OPTION_CODE_FULL_SCREEN = 'f';
|
|
||||||
|
|
||||||
public enum ResolutionType {
|
|
||||||
STANDARD,
|
|
||||||
NATIVE
|
|
||||||
}
|
|
||||||
|
|
||||||
private StreamResolution(int width, int height, ResolutionType type) {
|
|
||||||
this.width = width;
|
|
||||||
this.height = height;
|
|
||||||
this.type = type;
|
|
||||||
|
|
||||||
// Just guess for the options, since we don't know for sure
|
|
||||||
this.portrait = height > width;
|
|
||||||
this.fullScreen = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public StreamResolution(int width, int height, ResolutionType type, boolean portrait, boolean fullScreen) {
|
|
||||||
this.width = width;
|
|
||||||
this.height = height;
|
|
||||||
this.type = type;
|
|
||||||
this.portrait = portrait;
|
|
||||||
this.fullScreen = fullScreen;
|
|
||||||
}
|
|
||||||
|
|
||||||
StreamResolution(String resString) {
|
|
||||||
// Type code is the first character in the string
|
|
||||||
switch (resString.charAt(0)) {
|
|
||||||
case TYPE_CODE_NATIVE:
|
|
||||||
this.type = StreamResolution.ResolutionType.NATIVE;
|
|
||||||
break;
|
|
||||||
case TYPE_CODE_STANDARD:
|
|
||||||
this.type = StreamResolution.ResolutionType.STANDARD;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException("Invalid type code: " + resString.charAt(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse options until we reach the resolution start delimiter
|
|
||||||
int currentIndex = 1;
|
|
||||||
while (resString.charAt(currentIndex) != RES_START_DELIMITER) {
|
|
||||||
switch (resString.charAt(currentIndex)) {
|
|
||||||
case OPTION_CODE_PORTRAIT:
|
|
||||||
portrait = true;
|
|
||||||
break;
|
|
||||||
case OPTION_CODE_FULL_SCREEN:
|
|
||||||
fullScreen = true;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException("Invalid option code: " + resString.charAt(currentIndex));
|
|
||||||
}
|
|
||||||
|
|
||||||
currentIndex++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip the type code before splitting
|
|
||||||
String[] dims = resString.substring(currentIndex).split(""+RES_DIM_DELIMITER);
|
|
||||||
this.width = Integer.parseInt(dims[0]);
|
|
||||||
this.height = Integer.parseInt(dims[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toPrefString() {
|
|
||||||
String str = "";
|
|
||||||
|
|
||||||
// Start with the type code
|
|
||||||
switch (type) {
|
|
||||||
case NATIVE:
|
|
||||||
str += TYPE_CODE_NATIVE;
|
|
||||||
break;
|
|
||||||
case STANDARD:
|
|
||||||
str += TYPE_CODE_STANDARD;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException("Invalid type: "+type);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now any option codes that may apply
|
|
||||||
if (portrait) {
|
|
||||||
str += OPTION_CODE_PORTRAIT;
|
|
||||||
}
|
|
||||||
if (fullScreen) {
|
|
||||||
str += OPTION_CODE_FULL_SCREEN;
|
|
||||||
}
|
|
||||||
|
|
||||||
// And finally the dimensions
|
|
||||||
str += RES_START_DELIMITER;
|
|
||||||
str += width;
|
|
||||||
str += RES_DIM_DELIMITER;
|
|
||||||
str += height;
|
|
||||||
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -122,21 +122,32 @@ public class StreamSettings extends Activity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class SettingsFragment extends PreferenceFragment {
|
public static class SettingsFragment extends PreferenceFragment {
|
||||||
|
private int nativeResolutionStartIndex = Integer.MAX_VALUE;
|
||||||
|
private boolean nativeFramerateShown = false;
|
||||||
|
|
||||||
private void setValue(String preferenceKey, String value) {
|
private void setValue(String preferenceKey, String value) {
|
||||||
ListPreference pref = (ListPreference) findPreference(preferenceKey);
|
ListPreference pref = (ListPreference) findPreference(preferenceKey);
|
||||||
|
|
||||||
pref.setValue(value);
|
pref.setValue(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addResolutionEntry(int width, int height, PreferenceConfiguration.StreamResolution.ResolutionType type,
|
private void appendPreferenceEntry(ListPreference pref, String newEntryName, String newEntryValue) {
|
||||||
boolean insetsRemoved, boolean portrait) {
|
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);
|
ListPreference pref = (ListPreference) findPreference(PreferenceConfiguration.RESOLUTION_PREF_STRING);
|
||||||
PreferenceConfiguration.StreamResolution newRes =
|
|
||||||
new PreferenceConfiguration.StreamResolution(width, height, type, portrait, insetsRemoved);
|
|
||||||
|
|
||||||
String newName;
|
String newName;
|
||||||
|
|
||||||
if (type == PreferenceConfiguration.StreamResolution.ResolutionType.NATIVE) {
|
|
||||||
if (insetsRemoved) {
|
if (insetsRemoved) {
|
||||||
newName = getResources().getString(R.string.resolution_prefix_native_fullscreen);
|
newName = getResources().getString(R.string.resolution_prefix_native_fullscreen);
|
||||||
}
|
}
|
||||||
@@ -144,7 +155,7 @@ public class StreamSettings extends Activity {
|
|||||||
newName = getResources().getString(R.string.resolution_prefix_native);
|
newName = getResources().getString(R.string.resolution_prefix_native);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PreferenceConfiguration.isSquarishScreen(width, height)) {
|
if (PreferenceConfiguration.isSquarishScreen(nativeWidth, nativeHeight)) {
|
||||||
if (portrait) {
|
if (portrait) {
|
||||||
newName += " " + getResources().getString(R.string.resolution_prefix_native_portrait);
|
newName += " " + getResources().getString(R.string.resolution_prefix_native_portrait);
|
||||||
}
|
}
|
||||||
@@ -152,44 +163,54 @@ public class StreamSettings extends Activity {
|
|||||||
newName += " " + getResources().getString(R.string.resolution_prefix_native_landscape);
|
newName += " " + getResources().getString(R.string.resolution_prefix_native_landscape);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else {
|
|
||||||
newName = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
newName += " ("+width+"x"+height+")";
|
newName += " ("+nativeWidth+"x"+nativeHeight+")";
|
||||||
|
|
||||||
CharSequence[] values = pref.getEntryValues();
|
String newValue = nativeWidth+"x"+nativeHeight;
|
||||||
|
|
||||||
// Check if the new resolution is already present
|
// Check if the native resolution is already present
|
||||||
for (CharSequence value : values) {
|
for (CharSequence value : pref.getEntryValues()) {
|
||||||
PreferenceConfiguration.StreamResolution existingResolution = new PreferenceConfiguration.StreamResolution(value.toString());
|
if (newValue.equals(value.toString())) {
|
||||||
if (existingResolution.width == newRes.width && existingResolution.height == newRes.height) {
|
|
||||||
// It is present in the default list, so don't add it again
|
// It is present in the default list, so don't add it again
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CharSequence[] newEntries = Arrays.copyOf(pref.getEntries(), pref.getEntries().length + 1);
|
if (pref.getEntryValues().length < nativeResolutionStartIndex) {
|
||||||
CharSequence[] newValues = Arrays.copyOf(values, values.length + 1);
|
nativeResolutionStartIndex = pref.getEntryValues().length;
|
||||||
|
}
|
||||||
// Add the new resolution option
|
appendPreferenceEntry(pref, newName, newValue);
|
||||||
newEntries[newEntries.length - 1] = newName;
|
|
||||||
newValues[newValues.length - 1] = newRes.toPrefString();
|
|
||||||
|
|
||||||
pref.setEntries(newEntries);
|
|
||||||
pref.setEntryValues(newValues);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addNativeResolutionEntries(int nativeWidth, int nativeHeight, boolean insetsRemoved) {
|
private void addNativeResolutionEntries(int nativeWidth, int nativeHeight, boolean insetsRemoved) {
|
||||||
if (PreferenceConfiguration.isSquarishScreen(nativeWidth, nativeHeight)) {
|
if (PreferenceConfiguration.isSquarishScreen(nativeWidth, nativeHeight)) {
|
||||||
addResolutionEntry(nativeHeight, nativeWidth,
|
addNativeResolutionEntry(nativeHeight, nativeWidth, insetsRemoved, true);
|
||||||
PreferenceConfiguration.StreamResolution.ResolutionType.NATIVE,
|
|
||||||
insetsRemoved, true);
|
|
||||||
}
|
}
|
||||||
addResolutionEntry(nativeWidth, nativeHeight,
|
addNativeResolutionEntry(nativeWidth, nativeHeight, insetsRemoved, false);
|
||||||
PreferenceConfiguration.StreamResolution.ResolutionType.NATIVE,
|
}
|
||||||
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) {
|
private void removeValue(String preferenceKey, String value, Runnable onMatched) {
|
||||||
@@ -257,21 +278,12 @@ public class StreamSettings extends Activity {
|
|||||||
PreferenceScreen screen = getPreferenceScreen();
|
PreferenceScreen screen = getPreferenceScreen();
|
||||||
|
|
||||||
// hide on-screen controls category on non touch screen devices
|
// hide on-screen controls category on non touch screen devices
|
||||||
if (!getActivity().getPackageManager().
|
if (!getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN)) {
|
||||||
hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN)) {
|
|
||||||
{
|
|
||||||
PreferenceCategory category =
|
PreferenceCategory category =
|
||||||
(PreferenceCategory) findPreference("category_onscreen_controls");
|
(PreferenceCategory) findPreference("category_onscreen_controls");
|
||||||
screen.removePreference(category);
|
screen.removePreference(category);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
PreferenceCategory category =
|
|
||||||
(PreferenceCategory) findPreference("category_input_settings");
|
|
||||||
category.removePreference(findPreference("checkbox_touchscreen_trackpad"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hide remote desktop mouse mode on pre-Oreo (which doesn't have pointer capture)
|
// Hide remote desktop mouse mode on pre-Oreo (which doesn't have pointer capture)
|
||||||
// and NVIDIA SHIELD devices (which support raw mouse input in pointer capture mode)
|
// and NVIDIA SHIELD devices (which support raw mouse input in pointer capture mode)
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O ||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O ||
|
||||||
@@ -281,6 +293,30 @@ public class StreamSettings extends Activity {
|
|||||||
category.removePreference(findPreference("checkbox_absolute_mouse_mode"));
|
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),
|
// 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.
|
// and on Fire OS where it violates the Amazon App Store guidelines for some reason.
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O ||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O ||
|
||||||
@@ -297,26 +333,29 @@ public class StreamSettings extends Activity {
|
|||||||
(PreferenceCategory) findPreference("category_help");
|
(PreferenceCategory) findPreference("category_help");
|
||||||
screen.removePreference(category);
|
screen.removePreference(category);
|
||||||
}*/
|
}*/
|
||||||
|
PreferenceCategory category_gamepad_settings =
|
||||||
|
(PreferenceCategory) findPreference("category_gamepad_settings");
|
||||||
// Remove the vibration options if the device can't vibrate
|
// Remove the vibration options if the device can't vibrate
|
||||||
if (!((Vibrator)getActivity().getSystemService(Context.VIBRATOR_SERVICE)).hasVibrator()) {
|
if (!((Vibrator)getActivity().getSystemService(Context.VIBRATOR_SERVICE)).hasVibrator()) {
|
||||||
PreferenceCategory category =
|
category_gamepad_settings.removePreference(findPreference("checkbox_vibrate_fallback"));
|
||||||
(PreferenceCategory) findPreference("category_input_settings");
|
category_gamepad_settings.removePreference(findPreference("seekbar_vibrate_fallback_strength"));
|
||||||
category.removePreference(findPreference("checkbox_vibrate_fallback"));
|
|
||||||
|
|
||||||
// The entire OSC category may have already been removed by the touchscreen check above
|
// 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) {
|
if (category != null) {
|
||||||
category.removePreference(findPreference("checkbox_vibrate_osc"));
|
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
|
// Hide non-supported resolution/FPS combinations
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
Display display = getActivity().getWindowManager().getDefaultDisplay();
|
|
||||||
|
|
||||||
int maxSupportedResW = 0;
|
int maxSupportedResW = 0;
|
||||||
|
|
||||||
// Add a native resolution with any insets included for users that don't want content
|
// Add a native resolution with any insets included for users that don't want content
|
||||||
@@ -384,7 +423,7 @@ public class StreamSettings extends Activity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (candidate.getRefreshRate() > maxSupportedFps) {
|
if (candidate.getRefreshRate() > maxSupportedFps) {
|
||||||
maxSupportedFps = (int)candidate.getRefreshRate();
|
maxSupportedFps = candidate.getRefreshRate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -472,30 +511,15 @@ public class StreamSettings extends Activity {
|
|||||||
// Never remove 720p
|
// Never remove 720p
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
else {
|
||||||
// On Android 4.2 and later, we can get the true metrics via the
|
// We can get the true metrics via the getRealMetrics() function (unlike the lies
|
||||||
// getRealMetrics() function (unlike the lies that getWidth() and getHeight()
|
// that getWidth() and getHeight() tell to us).
|
||||||
// tell to us).
|
|
||||||
DisplayMetrics metrics = new DisplayMetrics();
|
DisplayMetrics metrics = new DisplayMetrics();
|
||||||
getActivity().getWindowManager().getDefaultDisplay().getRealMetrics(metrics);
|
display.getRealMetrics(metrics);
|
||||||
int width = Math.max(metrics.widthPixels, metrics.heightPixels);
|
int width = Math.max(metrics.widthPixels, metrics.heightPixels);
|
||||||
int height = Math.min(metrics.widthPixels, metrics.heightPixels);
|
int height = Math.min(metrics.widthPixels, metrics.heightPixels);
|
||||||
addNativeResolutionEntries(width, height, false);
|
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) {
|
if (!PreferenceConfiguration.readPreferences(this.getActivity()).unlockFps) {
|
||||||
// We give some extra room in case the FPS is rounded down
|
// We give some extra room in case the FPS is rounded down
|
||||||
@@ -522,28 +546,10 @@ public class StreamSettings extends Activity {
|
|||||||
}
|
}
|
||||||
// Never remove 30 FPS or 60 FPS
|
// Never remove 30 FPS or 60 FPS
|
||||||
}
|
}
|
||||||
|
addNativeFrameRateEntry(maxSupportedFps);
|
||||||
// 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");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Android L introduces the drop duplicate behavior of releaseOutputBuffer()
|
// Android L introduces the drop duplicate behavior of releaseOutputBuffer()
|
||||||
// that the unlock FPS option relies on to not massively increase latency.
|
// 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() {
|
findPreference(PreferenceConfiguration.UNLOCK_FPS_STRING).setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||||
@@ -565,7 +571,6 @@ public class StreamSettings extends Activity {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
// Remove HDR preference for devices below Nougat
|
// Remove HDR preference for devices below Nougat
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
|
||||||
@@ -575,7 +580,6 @@ public class StreamSettings extends Activity {
|
|||||||
category.removePreference(findPreference("checkbox_enable_hdr"));
|
category.removePreference(findPreference("checkbox_enable_hdr"));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Display display = getActivity().getWindowManager().getDefaultDisplay();
|
|
||||||
Display.HdrCapabilities hdrCaps = display.getHdrCapabilities();
|
Display.HdrCapabilities hdrCaps = display.getHdrCapabilities();
|
||||||
|
|
||||||
// We must now ensure our display is compatible with HDR10
|
// We must now ensure our display is compatible with HDR10
|
||||||
@@ -585,6 +589,7 @@ public class StreamSettings extends Activity {
|
|||||||
for (int hdrType : hdrCaps.getSupportedHdrTypes()) {
|
for (int hdrType : hdrCaps.getSupportedHdrTypes()) {
|
||||||
if (hdrType == Display.HdrCapabilities.HDR_TYPE_HDR10) {
|
if (hdrType == Display.HdrCapabilities.HDR_TYPE_HDR10) {
|
||||||
foundHdr10 = true;
|
foundHdr10 = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -613,10 +618,20 @@ public class StreamSettings extends Activity {
|
|||||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(SettingsFragment.this.getActivity());
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(SettingsFragment.this.getActivity());
|
||||||
String valueStr = (String) newValue;
|
String valueStr = (String) newValue;
|
||||||
PreferenceConfiguration.StreamResolution resolution = new PreferenceConfiguration.StreamResolution(valueStr);
|
|
||||||
|
// Detect if this value is the native resolution option
|
||||||
|
CharSequence[] values = ((ListPreference)preference).getEntryValues();
|
||||||
|
boolean isNativeRes = true;
|
||||||
|
for (int i = 0; i < values.length; i++) {
|
||||||
|
// Look for a match prior to the start of the native resolution entries
|
||||||
|
if (valueStr.equals(values[i].toString()) && i < nativeResolutionStartIndex) {
|
||||||
|
isNativeRes = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If this is native resolution, show the warning dialog
|
// If this is native resolution, show the warning dialog
|
||||||
if (resolution.type == PreferenceConfiguration.StreamResolution.ResolutionType.NATIVE) {
|
if (isNativeRes) {
|
||||||
Dialog.displayDialog(getActivity(),
|
Dialog.displayDialog(getActivity(),
|
||||||
getResources().getString(R.string.title_native_res_dialog),
|
getResources().getString(R.string.title_native_res_dialog),
|
||||||
getResources().getString(R.string.text_native_res_dialog),
|
getResources().getString(R.string.text_native_res_dialog),
|
||||||
@@ -636,6 +651,15 @@ public class StreamSettings extends Activity {
|
|||||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(SettingsFragment.this.getActivity());
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(SettingsFragment.this.getActivity());
|
||||||
String valueStr = (String) newValue;
|
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
|
// Write the new bitrate value
|
||||||
resetBitrateToDefault(prefs, null, valueStr);
|
resetBitrateToDefault(prefs, null, valueStr);
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ public class WebLauncherPreference extends Preference {
|
|||||||
initialize(attrs);
|
initialize(attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
|
||||||
public WebLauncherPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
public WebLauncherPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||||
super(context, attrs, defStyleAttr, defStyleRes);
|
super(context, attrs, defStyleAttr, defStyleRes);
|
||||||
initialize(attrs);
|
initialize(attrs);
|
||||||
|
|||||||
@@ -30,6 +30,6 @@ public class AdapterFragment extends Fragment {
|
|||||||
@Override
|
@Override
|
||||||
public void onActivityCreated(Bundle savedInstanceState) {
|
public void onActivityCreated(Bundle savedInstanceState) {
|
||||||
super.onActivityCreated(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);
|
super(context, attrs, defStyleAttr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(21)
|
|
||||||
public StreamView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
public StreamView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||||
super(context, attrs, defStyleAttr, defStyleRes);
|
super(context, attrs, defStyleAttr, defStyleRes);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,4 +44,8 @@ public class HelpLauncher {
|
|||||||
public static void launchTroubleshooting(Context context) {
|
public static void launchTroubleshooting(Context context) {
|
||||||
launchUrl(context, "https://github.com/moonlight-stream/moonlight-docs/wiki/Troubleshooting");
|
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();
|
NetworkInfo activeNetworkInfo = connMgr.getActiveNetworkInfo();
|
||||||
if (activeNetworkInfo != null) {
|
if (activeNetworkInfo != null) {
|
||||||
return activeNetworkInfo.getType() == ConnectivityManager.TYPE_VPN;
|
return activeNetworkInfo.getType() == ConnectivityManager.TYPE_VPN;
|
||||||
|
|||||||
@@ -6,13 +6,12 @@ import android.widget.Toast;
|
|||||||
|
|
||||||
import com.limelight.AppView;
|
import com.limelight.AppView;
|
||||||
import com.limelight.Game;
|
import com.limelight.Game;
|
||||||
import com.limelight.PcView;
|
|
||||||
import com.limelight.R;
|
import com.limelight.R;
|
||||||
import com.limelight.ShortcutTrampoline;
|
import com.limelight.ShortcutTrampoline;
|
||||||
import com.limelight.binding.PlatformBinding;
|
import com.limelight.binding.PlatformBinding;
|
||||||
import com.limelight.computers.ComputerManagerService;
|
import com.limelight.computers.ComputerManagerService;
|
||||||
import com.limelight.nvstream.http.ComputerDetails;
|
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.NvApp;
|
||||||
import com.limelight.nvstream.http.NvHTTP;
|
import com.limelight.nvstream.http.NvHTTP;
|
||||||
import com.limelight.nvstream.jni.MoonBridge;
|
import com.limelight.nvstream.jni.MoonBridge;
|
||||||
@@ -135,7 +134,7 @@ public class ServerHelper {
|
|||||||
} else {
|
} else {
|
||||||
message = parent.getResources().getString(R.string.applist_quit_fail) + " " + app.getAppName();
|
message = parent.getResources().getString(R.string.applist_quit_fail) + " " + app.getAppName();
|
||||||
}
|
}
|
||||||
} catch (GfeHttpResponseException e) {
|
} catch (HostHttpResponseException e) {
|
||||||
if (e.getErrorCode() == 599) {
|
if (e.getErrorCode() == 599) {
|
||||||
message = "This session wasn't started by this device," +
|
message = "This session wasn't started by this device," +
|
||||||
" so it cannot be quit. End streaming on the original " +
|
" so it cannot be quit. End streaming on the original " +
|
||||||
|
|||||||
@@ -2,15 +2,12 @@ package com.limelight.utils;
|
|||||||
|
|
||||||
import android.annotation.TargetApi;
|
import android.annotation.TargetApi;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.pm.ShortcutInfo;
|
import android.content.pm.ShortcutInfo;
|
||||||
import android.content.pm.ShortcutManager;
|
import android.content.pm.ShortcutManager;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.drawable.Icon;
|
import android.graphics.drawable.Icon;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
|
||||||
import com.limelight.AppView;
|
|
||||||
import com.limelight.ShortcutTrampoline;
|
|
||||||
import com.limelight.R;
|
import com.limelight.R;
|
||||||
import com.limelight.nvstream.http.ComputerDetails;
|
import com.limelight.nvstream.http.ComputerDetails;
|
||||||
import com.limelight.nvstream.http.NvApp;
|
import com.limelight.nvstream.http.NvApp;
|
||||||
|
|||||||
@@ -53,7 +53,11 @@ public class TvChannelHelper {
|
|||||||
intent.putExtra(TvContract.EXTRA_CHANNEL_ID, getChannelId(computer.uuid));
|
intent.putExtra(TvContract.EXTRA_CHANNEL_ID, getChannelId(computer.uuid));
|
||||||
try {
|
try {
|
||||||
context.startActivityForResult(intent, 0);
|
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_VERTICAL_PADDING_DP = 15;
|
||||||
private static final int TV_HORIZONTAL_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) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
try {
|
||||||
GameManager gameManager = context.getSystemService(GameManager.class);
|
GameManager gameManager = context.getSystemService(GameManager.class);
|
||||||
|
if (gameManager == null) {
|
||||||
|
return; // Not supported on this device (e.g., Meta Quest)
|
||||||
|
}
|
||||||
|
|
||||||
if (streaming) {
|
if (streaming) {
|
||||||
gameManager.setGameState(new GameState(loading, interruptible ? GameState.MODE_GAMEPLAY_INTERRUPTIBLE : GameState.MODE_GAMEPLAY_UNINTERRUPTIBLE));
|
gameManager.setGameState(new GameState(false, interruptible ? GameState.MODE_GAMEPLAY_INTERRUPTIBLE : GameState.MODE_GAMEPLAY_UNINTERRUPTIBLE));
|
||||||
|
} else {
|
||||||
|
gameManager.setGameState(new GameState(false, GameState.MODE_NONE));
|
||||||
}
|
}
|
||||||
else {
|
} catch (Throwable t) {
|
||||||
gameManager.setGameState(new GameState(loading, GameState.MODE_NONE));
|
// Swallow any failure. Some OEM builds ship partial/incompatible GameManager impls.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void notifyStreamConnecting(Context context) {
|
public static void notifyStreamConnecting(Context context) {
|
||||||
setGameModeStatus(context, true, true, true);
|
setGameModeStatus(context, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void notifyStreamConnected(Context context) {
|
public static void notifyStreamConnected(Context context) {
|
||||||
setGameModeStatus(context, true, false, false);
|
setGameModeStatus(context, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void notifyStreamEnteringPiP(Context context) {
|
public static void notifyStreamEnteringPiP(Context context) {
|
||||||
setGameModeStatus(context, true, false, true);
|
setGameModeStatus(context, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void notifyStreamExitingPiP(Context context) {
|
public static void notifyStreamExitingPiP(Context context) {
|
||||||
setGameModeStatus(context, true, false, false);
|
setGameModeStatus(context, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void notifyStreamEnded(Context context) {
|
public static void notifyStreamEnded(Context context) {
|
||||||
setGameModeStatus(context, false, false, false);
|
setGameModeStatus(context, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setLocale(Activity activity)
|
public static void setLocale(Activity activity)
|
||||||
@@ -115,7 +121,7 @@ public class UiHelper {
|
|||||||
UiModeManager modeMgr = (UiModeManager) activity.getSystemService(Context.UI_MODE_SERVICE);
|
UiModeManager modeMgr = (UiModeManager) activity.getSystemService(Context.UI_MODE_SERVICE);
|
||||||
|
|
||||||
// Set GameState.MODE_NONE initially for all activities
|
// 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) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||||
// Allow this non-streaming activity to layout under notches.
|
// Allow this non-streaming activity to layout under notches.
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
# Application.mk for Moonlight
|
# Application.mk for Moonlight
|
||||||
|
|
||||||
# Our minimum version is Android 4.1
|
# Our minimum version is Android 5.0
|
||||||
APP_PLATFORM := android-16
|
APP_PLATFORM := android-21
|
||||||
|
|
||||||
|
# We support 16KB pages
|
||||||
|
APP_SUPPORT_FLEXIBLE_PAGE_SIZES := true
|
||||||
|
|||||||
@@ -28,7 +28,9 @@ LOCAL_SRC_FILES := moonlight-common-c/src/AudioStream.c \
|
|||||||
moonlight-common-c/src/SimpleStun.c \
|
moonlight-common-c/src/SimpleStun.c \
|
||||||
moonlight-common-c/src/VideoDepacketizer.c \
|
moonlight-common-c/src/VideoDepacketizer.c \
|
||||||
moonlight-common-c/src/VideoStream.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/callbacks.c \
|
||||||
moonlight-common-c/enet/compress.c \
|
moonlight-common-c/enet/compress.c \
|
||||||
moonlight-common-c/enet/host.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 \
|
moonlight-common-c/enet/win32.c \
|
||||||
simplejni.c \
|
simplejni.c \
|
||||||
callbacks.c \
|
callbacks.c \
|
||||||
|
minisdl.c \
|
||||||
|
|
||||||
|
|
||||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/moonlight-common-c/enet/include \
|
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_PATH)/moonlight-common-c/src \
|
||||||
|
|
||||||
LOCAL_CFLAGS := -DHAS_SOCKLEN_T=1 -DLC_ANDROID -DHAVE_CLOCK_GETTIME=1
|
LOCAL_CFLAGS := -DHAS_SOCKLEN_T=1 -DLC_ANDROID -DHAVE_CLOCK_GETTIME=1
|
||||||
@@ -54,7 +58,11 @@ endif
|
|||||||
|
|
||||||
LOCAL_LDLIBS := -llog
|
LOCAL_LDLIBS := -llog
|
||||||
|
|
||||||
LOCAL_STATIC_LIBRARIES := libopus libssl libcrypto
|
LOCAL_STATIC_LIBRARIES := libopus libcrypto cpufeatures
|
||||||
LOCAL_LDFLAGS += -Wl,--exclude-libs,ALL
|
LOCAL_LDFLAGS += -Wl,--exclude-libs,ALL
|
||||||
|
|
||||||
|
LOCAL_BRANCH_PROTECTION := standard
|
||||||
|
|
||||||
include $(BUILD_SHARED_LIBRARY)
|
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
|
||||||
@@ -8,6 +8,8 @@
|
|||||||
#include <opus_multistream.h>
|
#include <opus_multistream.h>
|
||||||
#include <android/log.h>
|
#include <android/log.h>
|
||||||
|
|
||||||
|
#include <cpu-features.h>
|
||||||
|
|
||||||
static OpusMSDecoder* Decoder;
|
static OpusMSDecoder* Decoder;
|
||||||
static OPUS_MULTISTREAM_CONFIGURATION OpusConfig;
|
static OPUS_MULTISTREAM_CONFIGURATION OpusConfig;
|
||||||
|
|
||||||
@@ -33,6 +35,9 @@ static jmethodID BridgeClConnectionTerminatedMethod;
|
|||||||
static jmethodID BridgeClRumbleMethod;
|
static jmethodID BridgeClRumbleMethod;
|
||||||
static jmethodID BridgeClConnectionStatusUpdateMethod;
|
static jmethodID BridgeClConnectionStatusUpdateMethod;
|
||||||
static jmethodID BridgeClSetHdrModeMethod;
|
static jmethodID BridgeClSetHdrModeMethod;
|
||||||
|
static jmethodID BridgeClRumbleTriggersMethod;
|
||||||
|
static jmethodID BridgeClSetMotionEventStateMethod;
|
||||||
|
static jmethodID BridgeClSetControllerLEDMethod;
|
||||||
static jbyteArray DecodedFrameBuffer;
|
static jbyteArray DecodedFrameBuffer;
|
||||||
static jshortArray DecodedAudioBuffer;
|
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");
|
BridgeDrStartMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeDrStart", "()V");
|
||||||
BridgeDrStopMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeDrStop", "()V");
|
BridgeDrStopMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeDrStop", "()V");
|
||||||
BridgeDrCleanupMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeDrCleanup", "()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");
|
BridgeArInitMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeArInit", "(III)I");
|
||||||
BridgeArStartMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeArStart", "()V");
|
BridgeArStartMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeArStart", "()V");
|
||||||
BridgeArStopMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeArStop", "()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");
|
BridgeClConnectionTerminatedMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeClConnectionTerminated", "(I)V");
|
||||||
BridgeClRumbleMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeClRumble", "(SSS)V");
|
BridgeClRumbleMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeClRumble", "(SSS)V");
|
||||||
BridgeClConnectionStatusUpdateMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeClConnectionStatusUpdate", "(I)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) {
|
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,
|
ret = (*env)->CallStaticIntMethod(env, GlobalBridgeClass, BridgeDrSubmitDecodeUnitMethod,
|
||||||
DecodedFrameBuffer, currentEntry->length, currentEntry->bufferType,
|
DecodedFrameBuffer, currentEntry->length, currentEntry->bufferType,
|
||||||
decodeUnit->frameNumber, decodeUnit->frameType,
|
decodeUnit->frameNumber, decodeUnit->frameType, (jchar)decodeUnit->frameHostProcessingLatency,
|
||||||
(jlong)decodeUnit->receiveTimeMs, (jlong)decodeUnit->enqueueTimeMs);
|
(jlong)decodeUnit->receiveTimeUs, (jlong)decodeUnit->enqueueTimeUs);
|
||||||
if ((*env)->ExceptionCheck(env)) {
|
if ((*env)->ExceptionCheck(env)) {
|
||||||
// We will crash here
|
// We will crash here
|
||||||
(*JVM)->DetachCurrentThread(JVM);
|
(*JVM)->DetachCurrentThread(JVM);
|
||||||
@@ -180,8 +188,8 @@ int BridgeDrSubmitDecodeUnit(PDECODE_UNIT decodeUnit) {
|
|||||||
|
|
||||||
ret = (*env)->CallStaticIntMethod(env, GlobalBridgeClass, BridgeDrSubmitDecodeUnitMethod,
|
ret = (*env)->CallStaticIntMethod(env, GlobalBridgeClass, BridgeDrSubmitDecodeUnitMethod,
|
||||||
DecodedFrameBuffer, offset, BUFFER_TYPE_PICDATA,
|
DecodedFrameBuffer, offset, BUFFER_TYPE_PICDATA,
|
||||||
decodeUnit->frameNumber, decodeUnit->frameType,
|
decodeUnit->frameNumber, decodeUnit->frameType, (jchar)decodeUnit->frameHostProcessingLatency,
|
||||||
(jlong)decodeUnit->receiveTimeMs, (jlong)decodeUnit->enqueueTimeMs);
|
(jlong)decodeUnit->receiveTimeUs, (jlong)decodeUnit->enqueueTimeUs);
|
||||||
if ((*env)->ExceptionCheck(env)) {
|
if ((*env)->ExceptionCheck(env)) {
|
||||||
// We will crash here
|
// We will crash here
|
||||||
(*JVM)->DetachCurrentThread(JVM);
|
(*JVM)->DetachCurrentThread(JVM);
|
||||||
@@ -331,7 +339,50 @@ void BridgeClConnectionStatusUpdate(int connectionStatus) {
|
|||||||
void BridgeClSetHdrMode(bool enabled) {
|
void BridgeClSetHdrMode(bool enabled) {
|
||||||
JNIEnv* env = GetThreadEnv();
|
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)) {
|
if ((*env)->ExceptionCheck(env)) {
|
||||||
// We will crash here
|
// We will crash here
|
||||||
(*JVM)->DetachCurrentThread(JVM);
|
(*JVM)->DetachCurrentThread(JVM);
|
||||||
@@ -372,19 +423,42 @@ static CONNECTION_LISTENER_CALLBACKS BridgeConnListenerCallbacks = {
|
|||||||
.rumble = BridgeClRumble,
|
.rumble = BridgeClRumble,
|
||||||
.connectionStatusUpdate = BridgeClConnectionStatusUpdate,
|
.connectionStatusUpdate = BridgeClConnectionStatusUpdate,
|
||||||
.setHdrMode = BridgeClSetHdrMode,
|
.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
|
JNIEXPORT jint JNICALL
|
||||||
Java_com_limelight_nvstream_jni_MoonBridge_startConnection(JNIEnv *env, jclass clazz,
|
Java_com_limelight_nvstream_jni_MoonBridge_startConnection(JNIEnv *env, jclass clazz,
|
||||||
jstring address, jstring appVersion, jstring gfeVersion,
|
jstring address, jstring appVersion, jstring gfeVersion,
|
||||||
jstring rtspSessionUrl,
|
jstring rtspSessionUrl, jint serverCodecModeSupport,
|
||||||
jint width, jint height, jint fps,
|
jint width, jint height, jint fps,
|
||||||
jint bitrate, jint packetSize, jint streamingRemotely,
|
jint bitrate, jint packetSize, jint streamingRemotely,
|
||||||
jint audioConfiguration, jboolean supportsHevc,
|
jint audioConfiguration, jint supportedVideoFormats,
|
||||||
jboolean enableHdr,
|
|
||||||
jint hevcBitratePercentageMultiplier,
|
|
||||||
jint clientRefreshRateX100,
|
jint clientRefreshRateX100,
|
||||||
jint encryptionFlags,
|
|
||||||
jbyteArray riAesKey, jbyteArray riAesIv,
|
jbyteArray riAesKey, jbyteArray riAesIv,
|
||||||
jint videoCapabilities,
|
jint videoCapabilities,
|
||||||
jint colorSpace, jint colorRange) {
|
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),
|
.serverInfoAppVersion = (*env)->GetStringUTFChars(env, appVersion, 0),
|
||||||
.serverInfoGfeVersion = gfeVersion ? (*env)->GetStringUTFChars(env, gfeVersion, 0) : NULL,
|
.serverInfoGfeVersion = gfeVersion ? (*env)->GetStringUTFChars(env, gfeVersion, 0) : NULL,
|
||||||
.rtspSessionUrl = rtspSessionUrl ? (*env)->GetStringUTFChars(env, rtspSessionUrl, 0) : NULL,
|
.rtspSessionUrl = rtspSessionUrl ? (*env)->GetStringUTFChars(env, rtspSessionUrl, 0) : NULL,
|
||||||
|
.serverCodecModeSupport = serverCodecModeSupport,
|
||||||
};
|
};
|
||||||
STREAM_CONFIGURATION streamConfig = {
|
STREAM_CONFIGURATION streamConfig = {
|
||||||
.width = width,
|
.width = width,
|
||||||
@@ -402,11 +477,9 @@ Java_com_limelight_nvstream_jni_MoonBridge_startConnection(JNIEnv *env, jclass c
|
|||||||
.packetSize = packetSize,
|
.packetSize = packetSize,
|
||||||
.streamingRemotely = streamingRemotely,
|
.streamingRemotely = streamingRemotely,
|
||||||
.audioConfiguration = audioConfiguration,
|
.audioConfiguration = audioConfiguration,
|
||||||
.supportsHevc = supportsHevc,
|
.supportedVideoFormats = supportedVideoFormats,
|
||||||
.enableHdr = enableHdr,
|
|
||||||
.hevcBitratePercentageMultiplier = hevcBitratePercentageMultiplier,
|
|
||||||
.clientRefreshRateX100 = clientRefreshRateX100,
|
.clientRefreshRateX100 = clientRefreshRateX100,
|
||||||
.encryptionFlags = encryptionFlags,
|
.encryptionFlags = ENCFLG_AUDIO,
|
||||||
.colorSpace = colorSpace,
|
.colorSpace = colorSpace,
|
||||||
.colorRange = colorRange
|
.colorRange = colorRange
|
||||||
};
|
};
|
||||||
@@ -421,6 +494,11 @@ Java_com_limelight_nvstream_jni_MoonBridge_startConnection(JNIEnv *env, jclass c
|
|||||||
|
|
||||||
BridgeVideoRendererCallbacks.capabilities = videoCapabilities;
|
BridgeVideoRendererCallbacks.capabilities = videoCapabilities;
|
||||||
|
|
||||||
|
// Enable all encryption features if the platform has fast AES support
|
||||||
|
if (hasFastAes()) {
|
||||||
|
streamConfig.encryptionFlags = ENCFLG_ALL;
|
||||||
|
}
|
||||||
|
|
||||||
int ret = LiStartConnection(&serverInfo,
|
int ret = LiStartConnection(&serverInfo,
|
||||||
&streamConfig,
|
&streamConfig,
|
||||||
&BridgeConnListenerCallbacks,
|
&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
|
||||||
Binary file not shown.
Binary file not shown.
@@ -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 */
|
|
||||||
Binary file not shown.
Binary file not shown.
@@ -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;
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
Submodule app/src/main/jni/moonlight-core/moonlight-common-c updated: 50c0a51b10...874ac9548f
@@ -1,11 +1,5 @@
|
|||||||
LOCAL_PATH:= $(call my-dir)
|
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)
|
include $(CLEAR_VARS)
|
||||||
LOCAL_MODULE:= libcrypto
|
LOCAL_MODULE:= libcrypto
|
||||||
LOCAL_SRC_FILES:= $(TARGET_ARCH_ABI)/libcrypto.a
|
LOCAL_SRC_FILES:= $(TARGET_ARCH_ABI)/libcrypto.a
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
|
* 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
|
* this file except in compliance with the License. You can obtain a copy
|
||||||
* in the file LICENSE in the source distribution or at
|
* in the file LICENSE in the source distribution or at
|
||||||
* https://www.openssl.org/source/license.html
|
* https://www.openssl.org/source/license.html
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
|
* 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
|
* this file except in compliance with the License. You can obtain a copy
|
||||||
* in the file LICENSE in the source distribution or at
|
* in the file LICENSE in the source distribution or at
|
||||||
* https://www.openssl.org/source/license.html
|
* https://www.openssl.org/source/license.html
|
||||||
|
|||||||
@@ -1,14 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
* 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
|
* this file except in compliance with the License. You can obtain a copy
|
||||||
* in the file LICENSE in the source distribution or at
|
* in the file LICENSE in the source distribution or at
|
||||||
* https://www.openssl.org/source/license.html
|
* https://www.openssl.org/source/license.html
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef HEADER_AES_H
|
#ifndef OPENSSL_AES_H
|
||||||
|
#define OPENSSL_AES_H
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <openssl/macros.h>
|
||||||
|
#ifndef OPENSSL_NO_DEPRECATED_3_0
|
||||||
#define HEADER_AES_H
|
#define HEADER_AES_H
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <openssl/opensslconf.h>
|
#include <openssl/opensslconf.h>
|
||||||
|
|
||||||
@@ -17,15 +23,14 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define AES_BLOCK_SIZE 16
|
||||||
|
|
||||||
|
#ifndef OPENSSL_NO_DEPRECATED_3_0
|
||||||
|
|
||||||
#define AES_ENCRYPT 1
|
#define AES_ENCRYPT 1
|
||||||
#define AES_DECRYPT 0
|
#define AES_DECRYPT 0
|
||||||
|
|
||||||
/*
|
|
||||||
* 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_MAXNR 14
|
||||||
# define AES_BLOCK_SIZE 16
|
|
||||||
|
|
||||||
/* This should be a hidden type, but EVP requires that the size be known */
|
/* This should be a hidden type, but EVP requires that the size be known */
|
||||||
struct aes_key_st {
|
struct aes_key_st {
|
||||||
@@ -38,52 +43,64 @@ struct aes_key_st {
|
|||||||
};
|
};
|
||||||
typedef struct aes_key_st AES_KEY;
|
typedef struct aes_key_st AES_KEY;
|
||||||
|
|
||||||
const char *AES_options(void);
|
#endif
|
||||||
|
#ifndef OPENSSL_NO_DEPRECATED_3_0
|
||||||
int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
|
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);
|
AES_KEY *key);
|
||||||
int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
|
OSSL_DEPRECATEDIN_3_0
|
||||||
|
int AES_set_decrypt_key(const unsigned char *userKey, int bits,
|
||||||
AES_KEY *key);
|
AES_KEY *key);
|
||||||
|
OSSL_DEPRECATEDIN_3_0
|
||||||
void AES_encrypt(const unsigned char *in, unsigned char *out,
|
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,
|
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,
|
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,
|
void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
|
||||||
size_t length, const AES_KEY *key,
|
size_t length, const AES_KEY *key,
|
||||||
unsigned char *ivec, const int enc);
|
unsigned char *ivec, int enc);
|
||||||
|
OSSL_DEPRECATEDIN_3_0
|
||||||
void AES_cfb128_encrypt(const unsigned char *in, unsigned char *out,
|
void AES_cfb128_encrypt(const unsigned char *in, unsigned char *out,
|
||||||
size_t length, const AES_KEY *key,
|
size_t length, const AES_KEY *key,
|
||||||
unsigned char *ivec, int *num, const int enc);
|
unsigned char *ivec, int *num, int enc);
|
||||||
|
OSSL_DEPRECATEDIN_3_0
|
||||||
void AES_cfb1_encrypt(const unsigned char *in, unsigned char *out,
|
void AES_cfb1_encrypt(const unsigned char *in, unsigned char *out,
|
||||||
size_t length, const AES_KEY *key,
|
size_t length, const AES_KEY *key,
|
||||||
unsigned char *ivec, int *num, const int enc);
|
unsigned char *ivec, int *num, int enc);
|
||||||
|
OSSL_DEPRECATEDIN_3_0
|
||||||
void AES_cfb8_encrypt(const unsigned char *in, unsigned char *out,
|
void AES_cfb8_encrypt(const unsigned char *in, unsigned char *out,
|
||||||
size_t length, const AES_KEY *key,
|
size_t length, const AES_KEY *key,
|
||||||
unsigned char *ivec, int *num, const int enc);
|
unsigned char *ivec, int *num, int enc);
|
||||||
|
OSSL_DEPRECATEDIN_3_0
|
||||||
void AES_ofb128_encrypt(const unsigned char *in, unsigned char *out,
|
void AES_ofb128_encrypt(const unsigned char *in, unsigned char *out,
|
||||||
size_t length, const AES_KEY *key,
|
size_t length, const AES_KEY *key,
|
||||||
unsigned char *ivec, int *num);
|
unsigned char *ivec, int *num);
|
||||||
|
|
||||||
/* NB: the IV is _two_ blocks long */
|
/* NB: the IV is _two_ blocks long */
|
||||||
|
OSSL_DEPRECATEDIN_3_0
|
||||||
void AES_ige_encrypt(const unsigned char *in, unsigned char *out,
|
void AES_ige_encrypt(const unsigned char *in, unsigned char *out,
|
||||||
size_t length, const AES_KEY *key,
|
size_t length, const AES_KEY *key,
|
||||||
unsigned char *ivec, const int enc);
|
unsigned char *ivec, int enc);
|
||||||
/* NB: the IV is _four_ blocks long */
|
/* NB: the IV is _four_ blocks long */
|
||||||
|
OSSL_DEPRECATEDIN_3_0
|
||||||
void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out,
|
void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out,
|
||||||
size_t length, const AES_KEY *key,
|
size_t length, const AES_KEY *key, const AES_KEY *key2,
|
||||||
const AES_KEY *key2, const unsigned char *ivec,
|
const unsigned char *ivec, int enc);
|
||||||
const int enc);
|
OSSL_DEPRECATEDIN_3_0
|
||||||
|
|
||||||
int AES_wrap_key(AES_KEY *key, const unsigned char *iv,
|
int AES_wrap_key(AES_KEY *key, const unsigned char *iv,
|
||||||
unsigned char *out,
|
unsigned char *out, const unsigned char *in,
|
||||||
const unsigned char *in, unsigned int inlen);
|
unsigned int inlen);
|
||||||
|
OSSL_DEPRECATEDIN_3_0
|
||||||
int AES_unwrap_key(AES_KEY *key, const unsigned char *iv,
|
int AES_unwrap_key(AES_KEY *key, const unsigned char *iv,
|
||||||
unsigned char *out,
|
unsigned char *out, const unsigned char *in,
|
||||||
const unsigned char *in, unsigned int inlen);
|
unsigned int inlen);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,31 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
|
* WARNING: do not edit!
|
||||||
|
* Generated by Makefile from include/openssl/asn1.h.in
|
||||||
*
|
*
|
||||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
* Copyright 1995-2026 The OpenSSL Project Authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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
|
* this file except in compliance with the License. You can obtain a copy
|
||||||
* in the file LICENSE in the source distribution or at
|
* in the file LICENSE in the source distribution or at
|
||||||
* https://www.openssl.org/source/license.html
|
* https://www.openssl.org/source/license.html
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef HEADER_ASN1_H
|
/* clang-format off */
|
||||||
# define HEADER_ASN1_H
|
|
||||||
|
|
||||||
|
/* clang-format on */
|
||||||
|
|
||||||
|
#ifndef OPENSSL_ASN1_H
|
||||||
|
#define OPENSSL_ASN1_H
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <openssl/macros.h>
|
||||||
|
#ifndef OPENSSL_NO_DEPRECATED_3_0
|
||||||
|
#define HEADER_ASN1_H
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef OPENSSL_NO_STDIO
|
||||||
|
#include <stdio.h>
|
||||||
|
#endif
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <openssl/e_os2.h>
|
#include <openssl/e_os2.h>
|
||||||
#include <openssl/opensslconf.h>
|
#include <openssl/opensslconf.h>
|
||||||
@@ -18,10 +34,8 @@
|
|||||||
#include <openssl/asn1err.h>
|
#include <openssl/asn1err.h>
|
||||||
#include <openssl/symhacks.h>
|
#include <openssl/symhacks.h>
|
||||||
|
|
||||||
# include <openssl/ossl_typ.h>
|
#include <openssl/types.h>
|
||||||
# if OPENSSL_API_COMPAT < 0x10100000L
|
|
||||||
#include <openssl/bn.h>
|
#include <openssl/bn.h>
|
||||||
# endif
|
|
||||||
|
|
||||||
#ifdef OPENSSL_BUILD_SHLIBCRYPTO
|
#ifdef OPENSSL_BUILD_SHLIBCRYPTO
|
||||||
#undef OPENSSL_EXTERN
|
#undef OPENSSL_EXTERN
|
||||||
@@ -48,7 +62,7 @@ extern "C" {
|
|||||||
#define V_ASN1_UNDEF -1
|
#define V_ASN1_UNDEF -1
|
||||||
/* ASN.1 tag values */
|
/* ASN.1 tag values */
|
||||||
#define V_ASN1_EOC 0
|
#define V_ASN1_EOC 0
|
||||||
# define V_ASN1_BOOLEAN 1 /**/
|
#define V_ASN1_BOOLEAN 1
|
||||||
#define V_ASN1_INTEGER 2
|
#define V_ASN1_INTEGER 2
|
||||||
#define V_ASN1_BIT_STRING 3
|
#define V_ASN1_BIT_STRING 3
|
||||||
#define V_ASN1_OCTET_STRING 4
|
#define V_ASN1_OCTET_STRING 4
|
||||||
@@ -61,19 +75,19 @@ extern "C" {
|
|||||||
#define V_ASN1_UTF8STRING 12
|
#define V_ASN1_UTF8STRING 12
|
||||||
#define V_ASN1_SEQUENCE 16
|
#define V_ASN1_SEQUENCE 16
|
||||||
#define V_ASN1_SET 17
|
#define V_ASN1_SET 17
|
||||||
# define V_ASN1_NUMERICSTRING 18 /**/
|
#define V_ASN1_NUMERICSTRING 18
|
||||||
#define V_ASN1_PRINTABLESTRING 19
|
#define V_ASN1_PRINTABLESTRING 19
|
||||||
#define V_ASN1_T61STRING 20
|
#define V_ASN1_T61STRING 20
|
||||||
#define V_ASN1_TELETEXSTRING 20 /* alias */
|
#define V_ASN1_TELETEXSTRING 20 /* alias */
|
||||||
# define V_ASN1_VIDEOTEXSTRING 21 /**/
|
#define V_ASN1_VIDEOTEXSTRING 21
|
||||||
#define V_ASN1_IA5STRING 22
|
#define V_ASN1_IA5STRING 22
|
||||||
#define V_ASN1_UTCTIME 23
|
#define V_ASN1_UTCTIME 23
|
||||||
# define V_ASN1_GENERALIZEDTIME 24 /**/
|
#define V_ASN1_GENERALIZEDTIME 24
|
||||||
# define V_ASN1_GRAPHICSTRING 25 /**/
|
#define V_ASN1_GRAPHICSTRING 25
|
||||||
# define V_ASN1_ISO64STRING 26 /**/
|
#define V_ASN1_ISO64STRING 26
|
||||||
#define V_ASN1_VISIBLESTRING 26 /* alias */
|
#define V_ASN1_VISIBLESTRING 26 /* alias */
|
||||||
# define V_ASN1_GENERALSTRING 27 /**/
|
#define V_ASN1_GENERALSTRING 27
|
||||||
# define V_ASN1_UNIVERSALSTRING 28 /**/
|
#define V_ASN1_UNIVERSALSTRING 28
|
||||||
#define V_ASN1_BMPSTRING 30
|
#define V_ASN1_BMPSTRING 30
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -115,45 +129,40 @@ extern "C" {
|
|||||||
#define SMIME_OLDMIME 0x400
|
#define SMIME_OLDMIME 0x400
|
||||||
#define SMIME_CRLFEOL 0x800
|
#define SMIME_CRLFEOL 0x800
|
||||||
#define SMIME_STREAM 0x1000
|
#define SMIME_STREAM 0x1000
|
||||||
struct X509_algor_st;
|
|
||||||
DEFINE_STACK_OF(X509_ALGOR)
|
|
||||||
|
|
||||||
# define ASN1_STRING_FLAG_BITS_LEFT 0x08/* Set if 0x07 has bits left value */
|
/* Stacks for types not otherwise defined in this header */
|
||||||
/*
|
/* clang-format off */
|
||||||
* This indicates that the ASN1_STRING is not a real value but just a place
|
SKM_DEFINE_STACK_OF_INTERNAL(X509_ALGOR, X509_ALGOR, X509_ALGOR)
|
||||||
* holder for the location where indefinite length constructed data should be
|
#define sk_X509_ALGOR_num(sk) OPENSSL_sk_num(ossl_check_const_X509_ALGOR_sk_type(sk))
|
||||||
* inserted in the memory buffer
|
#define sk_X509_ALGOR_value(sk, idx) ((X509_ALGOR *)OPENSSL_sk_value(ossl_check_const_X509_ALGOR_sk_type(sk), (idx)))
|
||||||
*/
|
#define sk_X509_ALGOR_new(cmp) ((STACK_OF(X509_ALGOR) *)OPENSSL_sk_set_cmp_thunks(OPENSSL_sk_new(ossl_check_X509_ALGOR_compfunc_type(cmp)), sk_X509_ALGOR_cmpfunc_thunk))
|
||||||
# define ASN1_STRING_FLAG_NDEF 0x010
|
#define sk_X509_ALGOR_new_null() ((STACK_OF(X509_ALGOR) *)OPENSSL_sk_set_thunks(OPENSSL_sk_new_null(), sk_X509_ALGOR_freefunc_thunk))
|
||||||
|
#define sk_X509_ALGOR_new_reserve(cmp, n) ((STACK_OF(X509_ALGOR) *)OPENSSL_sk_set_cmp_thunks(OPENSSL_sk_new_reserve(ossl_check_X509_ALGOR_compfunc_type(cmp), (n)), sk_X509_ALGOR_cmpfunc_thunk))
|
||||||
|
#define sk_X509_ALGOR_reserve(sk, n) OPENSSL_sk_reserve(ossl_check_X509_ALGOR_sk_type(sk), (n))
|
||||||
|
#define sk_X509_ALGOR_free(sk) OPENSSL_sk_free(ossl_check_X509_ALGOR_sk_type(sk))
|
||||||
|
#define sk_X509_ALGOR_zero(sk) OPENSSL_sk_zero(ossl_check_X509_ALGOR_sk_type(sk))
|
||||||
|
#define sk_X509_ALGOR_delete(sk, i) ((X509_ALGOR *)OPENSSL_sk_delete(ossl_check_X509_ALGOR_sk_type(sk), (i)))
|
||||||
|
#define sk_X509_ALGOR_delete_ptr(sk, ptr) ((X509_ALGOR *)OPENSSL_sk_delete_ptr(ossl_check_X509_ALGOR_sk_type(sk), ossl_check_X509_ALGOR_type(ptr)))
|
||||||
|
#define sk_X509_ALGOR_push(sk, ptr) OPENSSL_sk_push(ossl_check_X509_ALGOR_sk_type(sk), ossl_check_X509_ALGOR_type(ptr))
|
||||||
|
#define sk_X509_ALGOR_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_X509_ALGOR_sk_type(sk), ossl_check_X509_ALGOR_type(ptr))
|
||||||
|
#define sk_X509_ALGOR_pop(sk) ((X509_ALGOR *)OPENSSL_sk_pop(ossl_check_X509_ALGOR_sk_type(sk)))
|
||||||
|
#define sk_X509_ALGOR_shift(sk) ((X509_ALGOR *)OPENSSL_sk_shift(ossl_check_X509_ALGOR_sk_type(sk)))
|
||||||
|
#define sk_X509_ALGOR_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_X509_ALGOR_sk_type(sk), ossl_check_X509_ALGOR_freefunc_type(freefunc))
|
||||||
|
#define sk_X509_ALGOR_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_X509_ALGOR_sk_type(sk), ossl_check_X509_ALGOR_type(ptr), (idx))
|
||||||
|
#define sk_X509_ALGOR_set(sk, idx, ptr) ((X509_ALGOR *)OPENSSL_sk_set(ossl_check_X509_ALGOR_sk_type(sk), (idx), ossl_check_X509_ALGOR_type(ptr)))
|
||||||
|
#define sk_X509_ALGOR_find(sk, ptr) OPENSSL_sk_find(ossl_check_X509_ALGOR_sk_type(sk), ossl_check_X509_ALGOR_type(ptr))
|
||||||
|
#define sk_X509_ALGOR_find_ex(sk, ptr) OPENSSL_sk_find_ex(ossl_check_X509_ALGOR_sk_type(sk), ossl_check_X509_ALGOR_type(ptr))
|
||||||
|
#define sk_X509_ALGOR_find_all(sk, ptr, pnum) OPENSSL_sk_find_all(ossl_check_X509_ALGOR_sk_type(sk), ossl_check_X509_ALGOR_type(ptr), pnum)
|
||||||
|
#define sk_X509_ALGOR_sort(sk) OPENSSL_sk_sort(ossl_check_X509_ALGOR_sk_type(sk))
|
||||||
|
#define sk_X509_ALGOR_is_sorted(sk) OPENSSL_sk_is_sorted(ossl_check_const_X509_ALGOR_sk_type(sk))
|
||||||
|
#define sk_X509_ALGOR_dup(sk) ((STACK_OF(X509_ALGOR) *)OPENSSL_sk_dup(ossl_check_const_X509_ALGOR_sk_type(sk)))
|
||||||
|
#define sk_X509_ALGOR_deep_copy(sk, copyfunc, freefunc) ((STACK_OF(X509_ALGOR) *)OPENSSL_sk_deep_copy(ossl_check_const_X509_ALGOR_sk_type(sk), ossl_check_X509_ALGOR_copyfunc_type(copyfunc), ossl_check_X509_ALGOR_freefunc_type(freefunc)))
|
||||||
|
#define sk_X509_ALGOR_set_cmp_func(sk, cmp) ((sk_X509_ALGOR_compfunc)OPENSSL_sk_set_cmp_func(ossl_check_X509_ALGOR_sk_type(sk), ossl_check_X509_ALGOR_compfunc_type(cmp)))
|
||||||
|
|
||||||
/*
|
/* clang-format on */
|
||||||
* This flag is used by the CMS code to indicate that a string is not
|
|
||||||
* complete and is a place holder for content when it had all been accessed.
|
|
||||||
* The flag will be reset when content has been written to it.
|
|
||||||
*/
|
|
||||||
|
|
||||||
# define ASN1_STRING_FLAG_CONT 0x020
|
|
||||||
/*
|
|
||||||
* This flag is used by ASN1 code to indicate an ASN1_STRING is an MSTRING
|
|
||||||
* type.
|
|
||||||
*/
|
|
||||||
# define ASN1_STRING_FLAG_MSTRING 0x040
|
|
||||||
/* String is embedded and only content should be freed */
|
|
||||||
# define ASN1_STRING_FLAG_EMBED 0x080
|
|
||||||
/* String should be parsed in RFC 5280's time format */
|
|
||||||
# define ASN1_STRING_FLAG_X509_TIME 0x100
|
|
||||||
/* This is the base type that holds just about everything :-) */
|
/* This is the base type that holds just about everything :-) */
|
||||||
struct asn1_string_st {
|
struct asn1_string_st;
|
||||||
int length;
|
|
||||||
int type;
|
|
||||||
unsigned char *data;
|
|
||||||
/*
|
|
||||||
* The value of the following field depends on the type being held. It
|
|
||||||
* is mostly being used for BIT_STRING so if the input data has a
|
|
||||||
* non-zero 'unused bits' value, it will be handled correctly
|
|
||||||
*/
|
|
||||||
long flags;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ASN1_ENCODING structure: this is used to save the received encoding of an
|
* ASN1_ENCODING structure: this is used to save the received encoding of an
|
||||||
@@ -183,17 +192,45 @@ typedef struct ASN1_ENCODING_st {
|
|||||||
(B_ASN1_PRINTABLESTRING | B_ASN1_T61STRING | B_ASN1_BMPSTRING | B_ASN1_UTF8STRING)
|
(B_ASN1_PRINTABLESTRING | B_ASN1_T61STRING | B_ASN1_BMPSTRING | B_ASN1_UTF8STRING)
|
||||||
#define PKCS9STRING_TYPE (DIRSTRING_TYPE | B_ASN1_IA5STRING)
|
#define PKCS9STRING_TYPE (DIRSTRING_TYPE | B_ASN1_IA5STRING)
|
||||||
|
|
||||||
typedef struct asn1_string_table_st {
|
struct asn1_string_table_st {
|
||||||
int nid;
|
int nid;
|
||||||
long minsize;
|
long minsize;
|
||||||
long maxsize;
|
long maxsize;
|
||||||
unsigned long mask;
|
unsigned long mask;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
} ASN1_STRING_TABLE;
|
};
|
||||||
|
|
||||||
DEFINE_STACK_OF(ASN1_STRING_TABLE)
|
/* clang-format off */
|
||||||
|
SKM_DEFINE_STACK_OF_INTERNAL(ASN1_STRING_TABLE, ASN1_STRING_TABLE, ASN1_STRING_TABLE)
|
||||||
|
#define sk_ASN1_STRING_TABLE_num(sk) OPENSSL_sk_num(ossl_check_const_ASN1_STRING_TABLE_sk_type(sk))
|
||||||
|
#define sk_ASN1_STRING_TABLE_value(sk, idx) ((ASN1_STRING_TABLE *)OPENSSL_sk_value(ossl_check_const_ASN1_STRING_TABLE_sk_type(sk), (idx)))
|
||||||
|
#define sk_ASN1_STRING_TABLE_new(cmp) ((STACK_OF(ASN1_STRING_TABLE) *)OPENSSL_sk_set_cmp_thunks(OPENSSL_sk_new(ossl_check_ASN1_STRING_TABLE_compfunc_type(cmp)), sk_ASN1_STRING_TABLE_cmpfunc_thunk))
|
||||||
|
#define sk_ASN1_STRING_TABLE_new_null() ((STACK_OF(ASN1_STRING_TABLE) *)OPENSSL_sk_set_thunks(OPENSSL_sk_new_null(), sk_ASN1_STRING_TABLE_freefunc_thunk))
|
||||||
|
#define sk_ASN1_STRING_TABLE_new_reserve(cmp, n) ((STACK_OF(ASN1_STRING_TABLE) *)OPENSSL_sk_set_cmp_thunks(OPENSSL_sk_new_reserve(ossl_check_ASN1_STRING_TABLE_compfunc_type(cmp), (n)), sk_ASN1_STRING_TABLE_cmpfunc_thunk))
|
||||||
|
#define sk_ASN1_STRING_TABLE_reserve(sk, n) OPENSSL_sk_reserve(ossl_check_ASN1_STRING_TABLE_sk_type(sk), (n))
|
||||||
|
#define sk_ASN1_STRING_TABLE_free(sk) OPENSSL_sk_free(ossl_check_ASN1_STRING_TABLE_sk_type(sk))
|
||||||
|
#define sk_ASN1_STRING_TABLE_zero(sk) OPENSSL_sk_zero(ossl_check_ASN1_STRING_TABLE_sk_type(sk))
|
||||||
|
#define sk_ASN1_STRING_TABLE_delete(sk, i) ((ASN1_STRING_TABLE *)OPENSSL_sk_delete(ossl_check_ASN1_STRING_TABLE_sk_type(sk), (i)))
|
||||||
|
#define sk_ASN1_STRING_TABLE_delete_ptr(sk, ptr) ((ASN1_STRING_TABLE *)OPENSSL_sk_delete_ptr(ossl_check_ASN1_STRING_TABLE_sk_type(sk), ossl_check_ASN1_STRING_TABLE_type(ptr)))
|
||||||
|
#define sk_ASN1_STRING_TABLE_push(sk, ptr) OPENSSL_sk_push(ossl_check_ASN1_STRING_TABLE_sk_type(sk), ossl_check_ASN1_STRING_TABLE_type(ptr))
|
||||||
|
#define sk_ASN1_STRING_TABLE_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_ASN1_STRING_TABLE_sk_type(sk), ossl_check_ASN1_STRING_TABLE_type(ptr))
|
||||||
|
#define sk_ASN1_STRING_TABLE_pop(sk) ((ASN1_STRING_TABLE *)OPENSSL_sk_pop(ossl_check_ASN1_STRING_TABLE_sk_type(sk)))
|
||||||
|
#define sk_ASN1_STRING_TABLE_shift(sk) ((ASN1_STRING_TABLE *)OPENSSL_sk_shift(ossl_check_ASN1_STRING_TABLE_sk_type(sk)))
|
||||||
|
#define sk_ASN1_STRING_TABLE_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_ASN1_STRING_TABLE_sk_type(sk), ossl_check_ASN1_STRING_TABLE_freefunc_type(freefunc))
|
||||||
|
#define sk_ASN1_STRING_TABLE_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_ASN1_STRING_TABLE_sk_type(sk), ossl_check_ASN1_STRING_TABLE_type(ptr), (idx))
|
||||||
|
#define sk_ASN1_STRING_TABLE_set(sk, idx, ptr) ((ASN1_STRING_TABLE *)OPENSSL_sk_set(ossl_check_ASN1_STRING_TABLE_sk_type(sk), (idx), ossl_check_ASN1_STRING_TABLE_type(ptr)))
|
||||||
|
#define sk_ASN1_STRING_TABLE_find(sk, ptr) OPENSSL_sk_find(ossl_check_ASN1_STRING_TABLE_sk_type(sk), ossl_check_ASN1_STRING_TABLE_type(ptr))
|
||||||
|
#define sk_ASN1_STRING_TABLE_find_ex(sk, ptr) OPENSSL_sk_find_ex(ossl_check_ASN1_STRING_TABLE_sk_type(sk), ossl_check_ASN1_STRING_TABLE_type(ptr))
|
||||||
|
#define sk_ASN1_STRING_TABLE_find_all(sk, ptr, pnum) OPENSSL_sk_find_all(ossl_check_ASN1_STRING_TABLE_sk_type(sk), ossl_check_ASN1_STRING_TABLE_type(ptr), pnum)
|
||||||
|
#define sk_ASN1_STRING_TABLE_sort(sk) OPENSSL_sk_sort(ossl_check_ASN1_STRING_TABLE_sk_type(sk))
|
||||||
|
#define sk_ASN1_STRING_TABLE_is_sorted(sk) OPENSSL_sk_is_sorted(ossl_check_const_ASN1_STRING_TABLE_sk_type(sk))
|
||||||
|
#define sk_ASN1_STRING_TABLE_dup(sk) ((STACK_OF(ASN1_STRING_TABLE) *)OPENSSL_sk_dup(ossl_check_const_ASN1_STRING_TABLE_sk_type(sk)))
|
||||||
|
#define sk_ASN1_STRING_TABLE_deep_copy(sk, copyfunc, freefunc) ((STACK_OF(ASN1_STRING_TABLE) *)OPENSSL_sk_deep_copy(ossl_check_const_ASN1_STRING_TABLE_sk_type(sk), ossl_check_ASN1_STRING_TABLE_copyfunc_type(copyfunc), ossl_check_ASN1_STRING_TABLE_freefunc_type(freefunc)))
|
||||||
|
#define sk_ASN1_STRING_TABLE_set_cmp_func(sk, cmp) ((sk_ASN1_STRING_TABLE_compfunc)OPENSSL_sk_set_cmp_func(ossl_check_ASN1_STRING_TABLE_sk_type(sk), ossl_check_ASN1_STRING_TABLE_compfunc_type(cmp)))
|
||||||
|
|
||||||
/* size limits: this stuff is taken straight from RFC2459 */
|
/* clang-format on */
|
||||||
|
|
||||||
|
/* size limits: this stuff is taken straight from RFC 5280 */
|
||||||
|
|
||||||
#define ub_name 32768
|
#define ub_name 32768
|
||||||
#define ub_common_name 64
|
#define ub_common_name 64
|
||||||
@@ -212,52 +249,81 @@ typedef struct ASN1_TLC_st ASN1_TLC;
|
|||||||
/* This is just an opaque pointer */
|
/* This is just an opaque pointer */
|
||||||
typedef struct ASN1_VALUE_st ASN1_VALUE;
|
typedef struct ASN1_VALUE_st ASN1_VALUE;
|
||||||
|
|
||||||
/* Declare ASN1 functions: the implement macro in in asn1t.h */
|
/* Declare ASN1 functions: the implement macro is in asn1t.h */
|
||||||
|
|
||||||
# define DECLARE_ASN1_FUNCTIONS(type) DECLARE_ASN1_FUNCTIONS_name(type, type)
|
/*
|
||||||
|
* The mysterious 'extern' that's passed to some macros is innocuous,
|
||||||
|
* and is there to quiet pre-C99 compilers that may complain about empty
|
||||||
|
* arguments in macro calls.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DECLARE_ASN1_FUNCTIONS_attr(attr, type) \
|
||||||
|
DECLARE_ASN1_FUNCTIONS_name_attr(attr, type, type)
|
||||||
|
#define DECLARE_ASN1_FUNCTIONS(type) \
|
||||||
|
DECLARE_ASN1_FUNCTIONS_attr(extern, type)
|
||||||
|
|
||||||
|
#define DECLARE_ASN1_ALLOC_FUNCTIONS_attr(attr, type) \
|
||||||
|
DECLARE_ASN1_ALLOC_FUNCTIONS_name_attr(attr, type, type)
|
||||||
#define DECLARE_ASN1_ALLOC_FUNCTIONS(type) \
|
#define DECLARE_ASN1_ALLOC_FUNCTIONS(type) \
|
||||||
DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, type)
|
DECLARE_ASN1_ALLOC_FUNCTIONS_attr(extern, type)
|
||||||
|
|
||||||
|
#define DECLARE_ASN1_FUNCTIONS_name_attr(attr, type, name) \
|
||||||
|
DECLARE_ASN1_ALLOC_FUNCTIONS_name_attr(attr, type, name) \
|
||||||
|
DECLARE_ASN1_ENCODE_FUNCTIONS_name_attr(attr, type, name)
|
||||||
#define DECLARE_ASN1_FUNCTIONS_name(type, name) \
|
#define DECLARE_ASN1_FUNCTIONS_name(type, name) \
|
||||||
DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \
|
DECLARE_ASN1_FUNCTIONS_name_attr(extern, type, name)
|
||||||
DECLARE_ASN1_ENCODE_FUNCTIONS(type, name, name)
|
|
||||||
|
|
||||||
# define DECLARE_ASN1_FUNCTIONS_fname(type, itname, name) \
|
|
||||||
DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \
|
|
||||||
DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name)
|
|
||||||
|
|
||||||
|
#define DECLARE_ASN1_ENCODE_FUNCTIONS_attr(attr, type, itname, name) \
|
||||||
|
DECLARE_ASN1_ENCODE_FUNCTIONS_only_attr(attr, type, name) \
|
||||||
|
DECLARE_ASN1_ITEM_attr(attr, itname)
|
||||||
#define DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name) \
|
#define DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name) \
|
||||||
type *d2i_##name(type **a, const unsigned char **in, long len); \
|
DECLARE_ASN1_ENCODE_FUNCTIONS_attr(extern, type, itname, name)
|
||||||
int i2d_##name(type *a, unsigned char **out); \
|
|
||||||
DECLARE_ASN1_ITEM(itname)
|
|
||||||
|
|
||||||
# define DECLARE_ASN1_ENCODE_FUNCTIONS_const(type, name) \
|
#define DECLARE_ASN1_ENCODE_FUNCTIONS_name_attr(attr, type, name) \
|
||||||
type *d2i_##name(type **a, const unsigned char **in, long len); \
|
DECLARE_ASN1_ENCODE_FUNCTIONS_attr(attr, type, name, name)
|
||||||
int i2d_##name(const type *a, unsigned char **out); \
|
#define DECLARE_ASN1_ENCODE_FUNCTIONS_name(type, name) \
|
||||||
DECLARE_ASN1_ITEM(name)
|
DECLARE_ASN1_ENCODE_FUNCTIONS_name_attr(extern, type, name)
|
||||||
|
|
||||||
|
#define DECLARE_ASN1_ENCODE_FUNCTIONS_only_attr(attr, type, name) \
|
||||||
|
attr type *d2i_##name(type **a, const unsigned char **in, long len); \
|
||||||
|
attr int i2d_##name(const type *a, unsigned char **out);
|
||||||
|
#define DECLARE_ASN1_ENCODE_FUNCTIONS_only(type, name) \
|
||||||
|
DECLARE_ASN1_ENCODE_FUNCTIONS_only_attr(extern, type, name)
|
||||||
|
|
||||||
|
#define DECLARE_ASN1_NDEF_FUNCTION_attr(attr, name) \
|
||||||
|
attr int i2d_##name##_NDEF(const name *a, unsigned char **out);
|
||||||
#define DECLARE_ASN1_NDEF_FUNCTION(name) \
|
#define DECLARE_ASN1_NDEF_FUNCTION(name) \
|
||||||
int i2d_##name##_NDEF(name *a, unsigned char **out);
|
DECLARE_ASN1_NDEF_FUNCTION_attr(extern, name)
|
||||||
|
|
||||||
# define DECLARE_ASN1_FUNCTIONS_const(name) \
|
|
||||||
DECLARE_ASN1_ALLOC_FUNCTIONS(name) \
|
|
||||||
DECLARE_ASN1_ENCODE_FUNCTIONS_const(name, name)
|
|
||||||
|
|
||||||
|
#define DECLARE_ASN1_ALLOC_FUNCTIONS_name_attr(attr, type, name) \
|
||||||
|
attr type *name##_new(void); \
|
||||||
|
attr void name##_free(type *a);
|
||||||
#define DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \
|
#define DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \
|
||||||
type *name##_new(void); \
|
DECLARE_ASN1_ALLOC_FUNCTIONS_name_attr(extern, type, name)
|
||||||
void name##_free(type *a);
|
|
||||||
|
|
||||||
|
#define DECLARE_ASN1_DUP_FUNCTION_attr(attr, type) \
|
||||||
|
DECLARE_ASN1_DUP_FUNCTION_name_attr(attr, type, type)
|
||||||
|
#define DECLARE_ASN1_DUP_FUNCTION(type) \
|
||||||
|
DECLARE_ASN1_DUP_FUNCTION_attr(extern, type)
|
||||||
|
|
||||||
|
#define DECLARE_ASN1_DUP_FUNCTION_name_attr(attr, type, name) \
|
||||||
|
attr type *name##_dup(const type *a);
|
||||||
|
#define DECLARE_ASN1_DUP_FUNCTION_name(type, name) \
|
||||||
|
DECLARE_ASN1_DUP_FUNCTION_name_attr(extern, type, name)
|
||||||
|
|
||||||
|
#define DECLARE_ASN1_PRINT_FUNCTION_attr(attr, stname) \
|
||||||
|
DECLARE_ASN1_PRINT_FUNCTION_fname_attr(attr, stname, stname)
|
||||||
#define DECLARE_ASN1_PRINT_FUNCTION(stname) \
|
#define DECLARE_ASN1_PRINT_FUNCTION(stname) \
|
||||||
DECLARE_ASN1_PRINT_FUNCTION_fname(stname, stname)
|
DECLARE_ASN1_PRINT_FUNCTION_attr(extern, stname)
|
||||||
|
|
||||||
# define DECLARE_ASN1_PRINT_FUNCTION_fname(stname, fname) \
|
#define DECLARE_ASN1_PRINT_FUNCTION_fname_attr(attr, stname, fname) \
|
||||||
int fname##_print_ctx(BIO *out, stname *x, int indent, \
|
attr int fname##_print_ctx(BIO *out, const stname *x, int indent, \
|
||||||
const ASN1_PCTX *pctx);
|
const ASN1_PCTX *pctx);
|
||||||
|
#define DECLARE_ASN1_PRINT_FUNCTION_fname(stname, fname) \
|
||||||
|
DECLARE_ASN1_PRINT_FUNCTION_fname_attr(extern, stname, fname)
|
||||||
|
|
||||||
#define D2I_OF(type) type *(*)(type **, const unsigned char **, long)
|
#define D2I_OF(type) type *(*)(type **, const unsigned char **, long)
|
||||||
# define I2D_OF(type) int (*)(type *,unsigned char **)
|
#define I2D_OF(type) int (*)(const type *, unsigned char **)
|
||||||
# define I2D_OF_const(type) int (*)(const type *,unsigned char **)
|
|
||||||
|
|
||||||
#define CHECKED_D2I_OF(type, d2i) \
|
#define CHECKED_D2I_OF(type, d2i) \
|
||||||
((d2i_of_void *)(1 ? d2i : ((D2I_OF(type))0)))
|
((d2i_of_void *)(1 ? d2i : ((D2I_OF(type))0)))
|
||||||
@@ -271,10 +337,14 @@ typedef struct ASN1_VALUE_st ASN1_VALUE;
|
|||||||
((void **)(1 ? p : (type **)0))
|
((void **)(1 ? p : (type **)0))
|
||||||
|
|
||||||
#define TYPEDEF_D2I_OF(type) typedef type *d2i_of_##type(type **, const unsigned char **, long)
|
#define TYPEDEF_D2I_OF(type) typedef type *d2i_of_##type(type **, const unsigned char **, long)
|
||||||
# define TYPEDEF_I2D_OF(type) typedef int i2d_of_##type(type *,unsigned char **)
|
#define TYPEDEF_I2D_OF(type) typedef int i2d_of_##type(const type *, unsigned char **)
|
||||||
# define TYPEDEF_D2I2D_OF(type) TYPEDEF_D2I_OF(type); TYPEDEF_I2D_OF(type)
|
#define TYPEDEF_D2I2D_OF(type) \
|
||||||
|
TYPEDEF_D2I_OF(type); \
|
||||||
|
TYPEDEF_I2D_OF(type)
|
||||||
|
|
||||||
TYPEDEF_D2I2D_OF(void);
|
typedef void *d2i_of_void(void **, const unsigned char **, long);
|
||||||
|
typedef int i2d_of_void(const void *, unsigned char **);
|
||||||
|
typedef int OSSL_i2d_of_void_ctx(const void *, unsigned char **, void *vctx);
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* The following macros and typedefs allow an ASN1_ITEM
|
* The following macros and typedefs allow an ASN1_ITEM
|
||||||
@@ -312,24 +382,6 @@ TYPEDEF_D2I2D_OF(void);
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
# ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION
|
|
||||||
|
|
||||||
/* ASN1_ITEM pointer exported type */
|
|
||||||
typedef const ASN1_ITEM ASN1_ITEM_EXP;
|
|
||||||
|
|
||||||
/* Macro to obtain ASN1_ITEM pointer from exported type */
|
|
||||||
# define ASN1_ITEM_ptr(iptr) (iptr)
|
|
||||||
|
|
||||||
/* Macro to include ASN1_ITEM pointer from base type */
|
|
||||||
# define ASN1_ITEM_ref(iptr) (&(iptr##_it))
|
|
||||||
|
|
||||||
# define ASN1_ITEM_rptr(ref) (&(ref##_it))
|
|
||||||
|
|
||||||
# define DECLARE_ASN1_ITEM(name) \
|
|
||||||
OPENSSL_EXTERN const ASN1_ITEM name##_it;
|
|
||||||
|
|
||||||
# else
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Platforms that can't easily handle shared global variables are declared as
|
* Platforms that can't easily handle shared global variables are declared as
|
||||||
* functions returning ASN1_ITEM pointers.
|
* functions returning ASN1_ITEM pointers.
|
||||||
@@ -346,10 +398,10 @@ typedef const ASN1_ITEM *ASN1_ITEM_EXP (void);
|
|||||||
|
|
||||||
#define ASN1_ITEM_rptr(ref) (ref##_it())
|
#define ASN1_ITEM_rptr(ref) (ref##_it())
|
||||||
|
|
||||||
|
#define DECLARE_ASN1_ITEM_attr(attr, name) \
|
||||||
|
attr const ASN1_ITEM *name##_it(void);
|
||||||
#define DECLARE_ASN1_ITEM(name) \
|
#define DECLARE_ASN1_ITEM(name) \
|
||||||
const ASN1_ITEM * name##_it(void);
|
DECLARE_ASN1_ITEM_attr(extern, name)
|
||||||
|
|
||||||
# endif
|
|
||||||
|
|
||||||
/* Parameters used by ASN1_STRING_print_ex() */
|
/* Parameters used by ASN1_STRING_print_ex() */
|
||||||
|
|
||||||
@@ -362,6 +414,11 @@ typedef const ASN1_ITEM *ASN1_ITEM_EXP (void);
|
|||||||
#define ASN1_STRFLGS_ESC_CTRL 2
|
#define ASN1_STRFLGS_ESC_CTRL 2
|
||||||
#define ASN1_STRFLGS_ESC_MSB 4
|
#define ASN1_STRFLGS_ESC_MSB 4
|
||||||
|
|
||||||
|
/* Lower 8 bits are reserved as an output type specifier */
|
||||||
|
#define ASN1_DTFLGS_TYPE_MASK 0x0FUL
|
||||||
|
#define ASN1_DTFLGS_RFC822 0x00UL
|
||||||
|
#define ASN1_DTFLGS_ISO8601 0x01UL
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This flag determines how we do escaping: normally RC2253 backslash only,
|
* This flag determines how we do escaping: normally RC2253 backslash only,
|
||||||
* set this to use backslash and quote.
|
* set this to use backslash and quote.
|
||||||
@@ -428,20 +485,9 @@ typedef const ASN1_ITEM *ASN1_ITEM_EXP (void);
|
|||||||
* isn't essential in RFC2253 but it is advisable anyway.
|
* isn't essential in RFC2253 but it is advisable anyway.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
# define ASN1_STRFLGS_RFC2253 (ASN1_STRFLGS_ESC_2253 | \
|
#define ASN1_STRFLGS_RFC2253 (ASN1_STRFLGS_ESC_2253 | ASN1_STRFLGS_ESC_CTRL | ASN1_STRFLGS_ESC_MSB | ASN1_STRFLGS_UTF8_CONVERT | ASN1_STRFLGS_DUMP_UNKNOWN | ASN1_STRFLGS_DUMP_DER)
|
||||||
ASN1_STRFLGS_ESC_CTRL | \
|
|
||||||
ASN1_STRFLGS_ESC_MSB | \
|
|
||||||
ASN1_STRFLGS_UTF8_CONVERT | \
|
|
||||||
ASN1_STRFLGS_DUMP_UNKNOWN | \
|
|
||||||
ASN1_STRFLGS_DUMP_DER)
|
|
||||||
|
|
||||||
DEFINE_STACK_OF(ASN1_INTEGER)
|
struct asn1_type_st {
|
||||||
|
|
||||||
DEFINE_STACK_OF(ASN1_GENERALSTRING)
|
|
||||||
|
|
||||||
DEFINE_STACK_OF(ASN1_UTF8STRING)
|
|
||||||
|
|
||||||
typedef struct asn1_type_st {
|
|
||||||
int type;
|
int type;
|
||||||
union {
|
union {
|
||||||
char *ptr;
|
char *ptr;
|
||||||
@@ -470,14 +516,42 @@ typedef struct asn1_type_st {
|
|||||||
ASN1_STRING *sequence;
|
ASN1_STRING *sequence;
|
||||||
ASN1_VALUE *asn1_value;
|
ASN1_VALUE *asn1_value;
|
||||||
} value;
|
} value;
|
||||||
} ASN1_TYPE;
|
};
|
||||||
|
|
||||||
DEFINE_STACK_OF(ASN1_TYPE)
|
/* clang-format off */
|
||||||
|
SKM_DEFINE_STACK_OF_INTERNAL(ASN1_TYPE, ASN1_TYPE, ASN1_TYPE)
|
||||||
|
#define sk_ASN1_TYPE_num(sk) OPENSSL_sk_num(ossl_check_const_ASN1_TYPE_sk_type(sk))
|
||||||
|
#define sk_ASN1_TYPE_value(sk, idx) ((ASN1_TYPE *)OPENSSL_sk_value(ossl_check_const_ASN1_TYPE_sk_type(sk), (idx)))
|
||||||
|
#define sk_ASN1_TYPE_new(cmp) ((STACK_OF(ASN1_TYPE) *)OPENSSL_sk_set_cmp_thunks(OPENSSL_sk_new(ossl_check_ASN1_TYPE_compfunc_type(cmp)), sk_ASN1_TYPE_cmpfunc_thunk))
|
||||||
|
#define sk_ASN1_TYPE_new_null() ((STACK_OF(ASN1_TYPE) *)OPENSSL_sk_set_thunks(OPENSSL_sk_new_null(), sk_ASN1_TYPE_freefunc_thunk))
|
||||||
|
#define sk_ASN1_TYPE_new_reserve(cmp, n) ((STACK_OF(ASN1_TYPE) *)OPENSSL_sk_set_cmp_thunks(OPENSSL_sk_new_reserve(ossl_check_ASN1_TYPE_compfunc_type(cmp), (n)), sk_ASN1_TYPE_cmpfunc_thunk))
|
||||||
|
#define sk_ASN1_TYPE_reserve(sk, n) OPENSSL_sk_reserve(ossl_check_ASN1_TYPE_sk_type(sk), (n))
|
||||||
|
#define sk_ASN1_TYPE_free(sk) OPENSSL_sk_free(ossl_check_ASN1_TYPE_sk_type(sk))
|
||||||
|
#define sk_ASN1_TYPE_zero(sk) OPENSSL_sk_zero(ossl_check_ASN1_TYPE_sk_type(sk))
|
||||||
|
#define sk_ASN1_TYPE_delete(sk, i) ((ASN1_TYPE *)OPENSSL_sk_delete(ossl_check_ASN1_TYPE_sk_type(sk), (i)))
|
||||||
|
#define sk_ASN1_TYPE_delete_ptr(sk, ptr) ((ASN1_TYPE *)OPENSSL_sk_delete_ptr(ossl_check_ASN1_TYPE_sk_type(sk), ossl_check_ASN1_TYPE_type(ptr)))
|
||||||
|
#define sk_ASN1_TYPE_push(sk, ptr) OPENSSL_sk_push(ossl_check_ASN1_TYPE_sk_type(sk), ossl_check_ASN1_TYPE_type(ptr))
|
||||||
|
#define sk_ASN1_TYPE_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_ASN1_TYPE_sk_type(sk), ossl_check_ASN1_TYPE_type(ptr))
|
||||||
|
#define sk_ASN1_TYPE_pop(sk) ((ASN1_TYPE *)OPENSSL_sk_pop(ossl_check_ASN1_TYPE_sk_type(sk)))
|
||||||
|
#define sk_ASN1_TYPE_shift(sk) ((ASN1_TYPE *)OPENSSL_sk_shift(ossl_check_ASN1_TYPE_sk_type(sk)))
|
||||||
|
#define sk_ASN1_TYPE_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_ASN1_TYPE_sk_type(sk), ossl_check_ASN1_TYPE_freefunc_type(freefunc))
|
||||||
|
#define sk_ASN1_TYPE_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_ASN1_TYPE_sk_type(sk), ossl_check_ASN1_TYPE_type(ptr), (idx))
|
||||||
|
#define sk_ASN1_TYPE_set(sk, idx, ptr) ((ASN1_TYPE *)OPENSSL_sk_set(ossl_check_ASN1_TYPE_sk_type(sk), (idx), ossl_check_ASN1_TYPE_type(ptr)))
|
||||||
|
#define sk_ASN1_TYPE_find(sk, ptr) OPENSSL_sk_find(ossl_check_ASN1_TYPE_sk_type(sk), ossl_check_ASN1_TYPE_type(ptr))
|
||||||
|
#define sk_ASN1_TYPE_find_ex(sk, ptr) OPENSSL_sk_find_ex(ossl_check_ASN1_TYPE_sk_type(sk), ossl_check_ASN1_TYPE_type(ptr))
|
||||||
|
#define sk_ASN1_TYPE_find_all(sk, ptr, pnum) OPENSSL_sk_find_all(ossl_check_ASN1_TYPE_sk_type(sk), ossl_check_ASN1_TYPE_type(ptr), pnum)
|
||||||
|
#define sk_ASN1_TYPE_sort(sk) OPENSSL_sk_sort(ossl_check_ASN1_TYPE_sk_type(sk))
|
||||||
|
#define sk_ASN1_TYPE_is_sorted(sk) OPENSSL_sk_is_sorted(ossl_check_const_ASN1_TYPE_sk_type(sk))
|
||||||
|
#define sk_ASN1_TYPE_dup(sk) ((STACK_OF(ASN1_TYPE) *)OPENSSL_sk_dup(ossl_check_const_ASN1_TYPE_sk_type(sk)))
|
||||||
|
#define sk_ASN1_TYPE_deep_copy(sk, copyfunc, freefunc) ((STACK_OF(ASN1_TYPE) *)OPENSSL_sk_deep_copy(ossl_check_const_ASN1_TYPE_sk_type(sk), ossl_check_ASN1_TYPE_copyfunc_type(copyfunc), ossl_check_ASN1_TYPE_freefunc_type(freefunc)))
|
||||||
|
#define sk_ASN1_TYPE_set_cmp_func(sk, cmp) ((sk_ASN1_TYPE_compfunc)OPENSSL_sk_set_cmp_func(ossl_check_ASN1_TYPE_sk_type(sk), ossl_check_ASN1_TYPE_compfunc_type(cmp)))
|
||||||
|
|
||||||
|
/* clang-format on */
|
||||||
|
|
||||||
typedef STACK_OF(ASN1_TYPE) ASN1_SEQUENCE_ANY;
|
typedef STACK_OF(ASN1_TYPE) ASN1_SEQUENCE_ANY;
|
||||||
|
|
||||||
DECLARE_ASN1_ENCODE_FUNCTIONS_const(ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY)
|
DECLARE_ASN1_ENCODE_FUNCTIONS_name(ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY)
|
||||||
DECLARE_ASN1_ENCODE_FUNCTIONS_const(ASN1_SEQUENCE_ANY, ASN1_SET_ANY)
|
DECLARE_ASN1_ENCODE_FUNCTIONS_name(ASN1_SEQUENCE_ANY, ASN1_SET_ANY)
|
||||||
|
|
||||||
/* This is used to contain a list of bit names */
|
/* This is used to contain a list of bit names */
|
||||||
typedef struct BIT_STRING_BITNAME_st {
|
typedef struct BIT_STRING_BITNAME_st {
|
||||||
@@ -487,35 +561,19 @@ typedef struct BIT_STRING_BITNAME_st {
|
|||||||
} BIT_STRING_BITNAME;
|
} BIT_STRING_BITNAME;
|
||||||
|
|
||||||
#define B_ASN1_TIME \
|
#define B_ASN1_TIME \
|
||||||
B_ASN1_UTCTIME | \
|
B_ASN1_UTCTIME | B_ASN1_GENERALIZEDTIME
|
||||||
B_ASN1_GENERALIZEDTIME
|
|
||||||
|
|
||||||
#define B_ASN1_PRINTABLE \
|
#define B_ASN1_PRINTABLE \
|
||||||
B_ASN1_NUMERICSTRING| \
|
B_ASN1_NUMERICSTRING | B_ASN1_PRINTABLESTRING | B_ASN1_T61STRING | B_ASN1_IA5STRING | B_ASN1_BIT_STRING | B_ASN1_UNIVERSALSTRING | B_ASN1_BMPSTRING | B_ASN1_UTF8STRING | B_ASN1_SEQUENCE | B_ASN1_UNKNOWN
|
||||||
B_ASN1_PRINTABLESTRING| \
|
|
||||||
B_ASN1_T61STRING| \
|
|
||||||
B_ASN1_IA5STRING| \
|
|
||||||
B_ASN1_BIT_STRING| \
|
|
||||||
B_ASN1_UNIVERSALSTRING|\
|
|
||||||
B_ASN1_BMPSTRING|\
|
|
||||||
B_ASN1_UTF8STRING|\
|
|
||||||
B_ASN1_SEQUENCE|\
|
|
||||||
B_ASN1_UNKNOWN
|
|
||||||
|
|
||||||
#define B_ASN1_DIRECTORYSTRING \
|
#define B_ASN1_DIRECTORYSTRING \
|
||||||
B_ASN1_PRINTABLESTRING| \
|
B_ASN1_PRINTABLESTRING | B_ASN1_TELETEXSTRING | B_ASN1_BMPSTRING | B_ASN1_UNIVERSALSTRING | B_ASN1_UTF8STRING
|
||||||
B_ASN1_TELETEXSTRING|\
|
|
||||||
B_ASN1_BMPSTRING|\
|
|
||||||
B_ASN1_UNIVERSALSTRING|\
|
|
||||||
B_ASN1_UTF8STRING
|
|
||||||
|
|
||||||
#define B_ASN1_DISPLAYTEXT \
|
#define B_ASN1_DISPLAYTEXT \
|
||||||
B_ASN1_IA5STRING| \
|
B_ASN1_IA5STRING | B_ASN1_VISIBLESTRING | B_ASN1_BMPSTRING | B_ASN1_UTF8STRING
|
||||||
B_ASN1_VISIBLESTRING| \
|
|
||||||
B_ASN1_BMPSTRING|\
|
|
||||||
B_ASN1_UTF8STRING
|
|
||||||
|
|
||||||
DECLARE_ASN1_FUNCTIONS_fname(ASN1_TYPE, ASN1_ANY, ASN1_TYPE)
|
DECLARE_ASN1_ALLOC_FUNCTIONS_name(ASN1_TYPE, ASN1_TYPE)
|
||||||
|
DECLARE_ASN1_ENCODE_FUNCTIONS(ASN1_TYPE, ASN1_ANY, ASN1_TYPE)
|
||||||
|
|
||||||
int ASN1_TYPE_get(const ASN1_TYPE *a);
|
int ASN1_TYPE_get(const ASN1_TYPE *a);
|
||||||
void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value);
|
void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value);
|
||||||
@@ -525,21 +583,47 @@ int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b);
|
|||||||
ASN1_TYPE *ASN1_TYPE_pack_sequence(const ASN1_ITEM *it, void *s, ASN1_TYPE **t);
|
ASN1_TYPE *ASN1_TYPE_pack_sequence(const ASN1_ITEM *it, void *s, ASN1_TYPE **t);
|
||||||
void *ASN1_TYPE_unpack_sequence(const ASN1_ITEM *it, const ASN1_TYPE *t);
|
void *ASN1_TYPE_unpack_sequence(const ASN1_ITEM *it, const ASN1_TYPE *t);
|
||||||
|
|
||||||
ASN1_OBJECT *ASN1_OBJECT_new(void);
|
/* clang-format off */
|
||||||
|
SKM_DEFINE_STACK_OF_INTERNAL(ASN1_OBJECT, ASN1_OBJECT, ASN1_OBJECT)
|
||||||
|
#define sk_ASN1_OBJECT_num(sk) OPENSSL_sk_num(ossl_check_const_ASN1_OBJECT_sk_type(sk))
|
||||||
|
#define sk_ASN1_OBJECT_value(sk, idx) ((ASN1_OBJECT *)OPENSSL_sk_value(ossl_check_const_ASN1_OBJECT_sk_type(sk), (idx)))
|
||||||
|
#define sk_ASN1_OBJECT_new(cmp) ((STACK_OF(ASN1_OBJECT) *)OPENSSL_sk_set_cmp_thunks(OPENSSL_sk_new(ossl_check_ASN1_OBJECT_compfunc_type(cmp)), sk_ASN1_OBJECT_cmpfunc_thunk))
|
||||||
|
#define sk_ASN1_OBJECT_new_null() ((STACK_OF(ASN1_OBJECT) *)OPENSSL_sk_set_thunks(OPENSSL_sk_new_null(), sk_ASN1_OBJECT_freefunc_thunk))
|
||||||
|
#define sk_ASN1_OBJECT_new_reserve(cmp, n) ((STACK_OF(ASN1_OBJECT) *)OPENSSL_sk_set_cmp_thunks(OPENSSL_sk_new_reserve(ossl_check_ASN1_OBJECT_compfunc_type(cmp), (n)), sk_ASN1_OBJECT_cmpfunc_thunk))
|
||||||
|
#define sk_ASN1_OBJECT_reserve(sk, n) OPENSSL_sk_reserve(ossl_check_ASN1_OBJECT_sk_type(sk), (n))
|
||||||
|
#define sk_ASN1_OBJECT_free(sk) OPENSSL_sk_free(ossl_check_ASN1_OBJECT_sk_type(sk))
|
||||||
|
#define sk_ASN1_OBJECT_zero(sk) OPENSSL_sk_zero(ossl_check_ASN1_OBJECT_sk_type(sk))
|
||||||
|
#define sk_ASN1_OBJECT_delete(sk, i) ((ASN1_OBJECT *)OPENSSL_sk_delete(ossl_check_ASN1_OBJECT_sk_type(sk), (i)))
|
||||||
|
#define sk_ASN1_OBJECT_delete_ptr(sk, ptr) ((ASN1_OBJECT *)OPENSSL_sk_delete_ptr(ossl_check_ASN1_OBJECT_sk_type(sk), ossl_check_ASN1_OBJECT_type(ptr)))
|
||||||
|
#define sk_ASN1_OBJECT_push(sk, ptr) OPENSSL_sk_push(ossl_check_ASN1_OBJECT_sk_type(sk), ossl_check_ASN1_OBJECT_type(ptr))
|
||||||
|
#define sk_ASN1_OBJECT_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_ASN1_OBJECT_sk_type(sk), ossl_check_ASN1_OBJECT_type(ptr))
|
||||||
|
#define sk_ASN1_OBJECT_pop(sk) ((ASN1_OBJECT *)OPENSSL_sk_pop(ossl_check_ASN1_OBJECT_sk_type(sk)))
|
||||||
|
#define sk_ASN1_OBJECT_shift(sk) ((ASN1_OBJECT *)OPENSSL_sk_shift(ossl_check_ASN1_OBJECT_sk_type(sk)))
|
||||||
|
#define sk_ASN1_OBJECT_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_ASN1_OBJECT_sk_type(sk), ossl_check_ASN1_OBJECT_freefunc_type(freefunc))
|
||||||
|
#define sk_ASN1_OBJECT_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_ASN1_OBJECT_sk_type(sk), ossl_check_ASN1_OBJECT_type(ptr), (idx))
|
||||||
|
#define sk_ASN1_OBJECT_set(sk, idx, ptr) ((ASN1_OBJECT *)OPENSSL_sk_set(ossl_check_ASN1_OBJECT_sk_type(sk), (idx), ossl_check_ASN1_OBJECT_type(ptr)))
|
||||||
|
#define sk_ASN1_OBJECT_find(sk, ptr) OPENSSL_sk_find(ossl_check_ASN1_OBJECT_sk_type(sk), ossl_check_ASN1_OBJECT_type(ptr))
|
||||||
|
#define sk_ASN1_OBJECT_find_ex(sk, ptr) OPENSSL_sk_find_ex(ossl_check_ASN1_OBJECT_sk_type(sk), ossl_check_ASN1_OBJECT_type(ptr))
|
||||||
|
#define sk_ASN1_OBJECT_find_all(sk, ptr, pnum) OPENSSL_sk_find_all(ossl_check_ASN1_OBJECT_sk_type(sk), ossl_check_ASN1_OBJECT_type(ptr), pnum)
|
||||||
|
#define sk_ASN1_OBJECT_sort(sk) OPENSSL_sk_sort(ossl_check_ASN1_OBJECT_sk_type(sk))
|
||||||
|
#define sk_ASN1_OBJECT_is_sorted(sk) OPENSSL_sk_is_sorted(ossl_check_const_ASN1_OBJECT_sk_type(sk))
|
||||||
|
#define sk_ASN1_OBJECT_dup(sk) ((STACK_OF(ASN1_OBJECT) *)OPENSSL_sk_dup(ossl_check_const_ASN1_OBJECT_sk_type(sk)))
|
||||||
|
#define sk_ASN1_OBJECT_deep_copy(sk, copyfunc, freefunc) ((STACK_OF(ASN1_OBJECT) *)OPENSSL_sk_deep_copy(ossl_check_const_ASN1_OBJECT_sk_type(sk), ossl_check_ASN1_OBJECT_copyfunc_type(copyfunc), ossl_check_ASN1_OBJECT_freefunc_type(freefunc)))
|
||||||
|
#define sk_ASN1_OBJECT_set_cmp_func(sk, cmp) ((sk_ASN1_OBJECT_compfunc)OPENSSL_sk_set_cmp_func(ossl_check_ASN1_OBJECT_sk_type(sk), ossl_check_ASN1_OBJECT_compfunc_type(cmp)))
|
||||||
|
|
||||||
|
/* clang-format on */
|
||||||
|
|
||||||
|
#ifndef OPENSSL_NO_DEPRECATED_4_0
|
||||||
|
OSSL_DEPRECATEDIN_4_0 ASN1_OBJECT *ASN1_OBJECT_new(void);
|
||||||
|
#endif /* OPENSSL_NO_DEPRECATED_4_0 */
|
||||||
void ASN1_OBJECT_free(ASN1_OBJECT *a);
|
void ASN1_OBJECT_free(ASN1_OBJECT *a);
|
||||||
int i2d_ASN1_OBJECT(const ASN1_OBJECT *a, unsigned char **pp);
|
DECLARE_ASN1_ENCODE_FUNCTIONS_name_attr(extern, ASN1_OBJECT, ASN1_OBJECT)
|
||||||
ASN1_OBJECT *d2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
|
|
||||||
long length);
|
|
||||||
|
|
||||||
DECLARE_ASN1_ITEM(ASN1_OBJECT)
|
|
||||||
|
|
||||||
DEFINE_STACK_OF(ASN1_OBJECT)
|
|
||||||
|
|
||||||
ASN1_STRING *ASN1_STRING_new(void);
|
ASN1_STRING *ASN1_STRING_new(void);
|
||||||
void ASN1_STRING_free(ASN1_STRING *a);
|
void ASN1_STRING_free(ASN1_STRING *a);
|
||||||
void ASN1_STRING_clear_free(ASN1_STRING *a);
|
void ASN1_STRING_clear_free(ASN1_STRING *a);
|
||||||
int ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str);
|
int ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str);
|
||||||
ASN1_STRING *ASN1_STRING_dup(const ASN1_STRING *a);
|
DECLARE_ASN1_DUP_FUNCTION(ASN1_STRING)
|
||||||
ASN1_STRING *ASN1_STRING_type_new(int type);
|
ASN1_STRING *ASN1_STRING_type_new(int type);
|
||||||
int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b);
|
int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b);
|
||||||
/*
|
/*
|
||||||
@@ -549,9 +633,10 @@ int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b);
|
|||||||
int ASN1_STRING_set(ASN1_STRING *str, const void *data, int len);
|
int ASN1_STRING_set(ASN1_STRING *str, const void *data, int len);
|
||||||
void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len);
|
void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len);
|
||||||
int ASN1_STRING_length(const ASN1_STRING *x);
|
int ASN1_STRING_length(const ASN1_STRING *x);
|
||||||
void ASN1_STRING_length_set(ASN1_STRING *x, int n);
|
#ifndef OPENSSL_NO_DEPRECATED_3_0
|
||||||
|
OSSL_DEPRECATEDIN_3_0 void ASN1_STRING_length_set(ASN1_STRING *x, int n);
|
||||||
|
#endif
|
||||||
int ASN1_STRING_type(const ASN1_STRING *x);
|
int ASN1_STRING_type(const ASN1_STRING *x);
|
||||||
DEPRECATEDIN_1_1_0(unsigned char *ASN1_STRING_data(ASN1_STRING *x))
|
|
||||||
const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x);
|
const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x);
|
||||||
|
|
||||||
DECLARE_ASN1_FUNCTIONS(ASN1_BIT_STRING)
|
DECLARE_ASN1_FUNCTIONS(ASN1_BIT_STRING)
|
||||||
@@ -566,11 +651,45 @@ int ASN1_BIT_STRING_name_print(BIO *out, ASN1_BIT_STRING *bs,
|
|||||||
int ASN1_BIT_STRING_num_asc(const char *name, BIT_STRING_BITNAME *tbl);
|
int ASN1_BIT_STRING_num_asc(const char *name, BIT_STRING_BITNAME *tbl);
|
||||||
int ASN1_BIT_STRING_set_asc(ASN1_BIT_STRING *bs, const char *name, int value,
|
int ASN1_BIT_STRING_set_asc(ASN1_BIT_STRING *bs, const char *name, int value,
|
||||||
BIT_STRING_BITNAME *tbl);
|
BIT_STRING_BITNAME *tbl);
|
||||||
|
int ASN1_BIT_STRING_get_length(const ASN1_BIT_STRING *abs, size_t *length,
|
||||||
|
int *unused_bits);
|
||||||
|
int ASN1_BIT_STRING_set1(ASN1_BIT_STRING *abs, const uint8_t *data,
|
||||||
|
size_t length, int unused_bits);
|
||||||
|
|
||||||
|
/* clang-format off */
|
||||||
|
SKM_DEFINE_STACK_OF_INTERNAL(ASN1_INTEGER, ASN1_INTEGER, ASN1_INTEGER)
|
||||||
|
#define sk_ASN1_INTEGER_num(sk) OPENSSL_sk_num(ossl_check_const_ASN1_INTEGER_sk_type(sk))
|
||||||
|
#define sk_ASN1_INTEGER_value(sk, idx) ((ASN1_INTEGER *)OPENSSL_sk_value(ossl_check_const_ASN1_INTEGER_sk_type(sk), (idx)))
|
||||||
|
#define sk_ASN1_INTEGER_new(cmp) ((STACK_OF(ASN1_INTEGER) *)OPENSSL_sk_set_cmp_thunks(OPENSSL_sk_new(ossl_check_ASN1_INTEGER_compfunc_type(cmp)), sk_ASN1_INTEGER_cmpfunc_thunk))
|
||||||
|
#define sk_ASN1_INTEGER_new_null() ((STACK_OF(ASN1_INTEGER) *)OPENSSL_sk_set_thunks(OPENSSL_sk_new_null(), sk_ASN1_INTEGER_freefunc_thunk))
|
||||||
|
#define sk_ASN1_INTEGER_new_reserve(cmp, n) ((STACK_OF(ASN1_INTEGER) *)OPENSSL_sk_set_cmp_thunks(OPENSSL_sk_new_reserve(ossl_check_ASN1_INTEGER_compfunc_type(cmp), (n)), sk_ASN1_INTEGER_cmpfunc_thunk))
|
||||||
|
#define sk_ASN1_INTEGER_reserve(sk, n) OPENSSL_sk_reserve(ossl_check_ASN1_INTEGER_sk_type(sk), (n))
|
||||||
|
#define sk_ASN1_INTEGER_free(sk) OPENSSL_sk_free(ossl_check_ASN1_INTEGER_sk_type(sk))
|
||||||
|
#define sk_ASN1_INTEGER_zero(sk) OPENSSL_sk_zero(ossl_check_ASN1_INTEGER_sk_type(sk))
|
||||||
|
#define sk_ASN1_INTEGER_delete(sk, i) ((ASN1_INTEGER *)OPENSSL_sk_delete(ossl_check_ASN1_INTEGER_sk_type(sk), (i)))
|
||||||
|
#define sk_ASN1_INTEGER_delete_ptr(sk, ptr) ((ASN1_INTEGER *)OPENSSL_sk_delete_ptr(ossl_check_ASN1_INTEGER_sk_type(sk), ossl_check_ASN1_INTEGER_type(ptr)))
|
||||||
|
#define sk_ASN1_INTEGER_push(sk, ptr) OPENSSL_sk_push(ossl_check_ASN1_INTEGER_sk_type(sk), ossl_check_ASN1_INTEGER_type(ptr))
|
||||||
|
#define sk_ASN1_INTEGER_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_ASN1_INTEGER_sk_type(sk), ossl_check_ASN1_INTEGER_type(ptr))
|
||||||
|
#define sk_ASN1_INTEGER_pop(sk) ((ASN1_INTEGER *)OPENSSL_sk_pop(ossl_check_ASN1_INTEGER_sk_type(sk)))
|
||||||
|
#define sk_ASN1_INTEGER_shift(sk) ((ASN1_INTEGER *)OPENSSL_sk_shift(ossl_check_ASN1_INTEGER_sk_type(sk)))
|
||||||
|
#define sk_ASN1_INTEGER_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_ASN1_INTEGER_sk_type(sk), ossl_check_ASN1_INTEGER_freefunc_type(freefunc))
|
||||||
|
#define sk_ASN1_INTEGER_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_ASN1_INTEGER_sk_type(sk), ossl_check_ASN1_INTEGER_type(ptr), (idx))
|
||||||
|
#define sk_ASN1_INTEGER_set(sk, idx, ptr) ((ASN1_INTEGER *)OPENSSL_sk_set(ossl_check_ASN1_INTEGER_sk_type(sk), (idx), ossl_check_ASN1_INTEGER_type(ptr)))
|
||||||
|
#define sk_ASN1_INTEGER_find(sk, ptr) OPENSSL_sk_find(ossl_check_ASN1_INTEGER_sk_type(sk), ossl_check_ASN1_INTEGER_type(ptr))
|
||||||
|
#define sk_ASN1_INTEGER_find_ex(sk, ptr) OPENSSL_sk_find_ex(ossl_check_ASN1_INTEGER_sk_type(sk), ossl_check_ASN1_INTEGER_type(ptr))
|
||||||
|
#define sk_ASN1_INTEGER_find_all(sk, ptr, pnum) OPENSSL_sk_find_all(ossl_check_ASN1_INTEGER_sk_type(sk), ossl_check_ASN1_INTEGER_type(ptr), pnum)
|
||||||
|
#define sk_ASN1_INTEGER_sort(sk) OPENSSL_sk_sort(ossl_check_ASN1_INTEGER_sk_type(sk))
|
||||||
|
#define sk_ASN1_INTEGER_is_sorted(sk) OPENSSL_sk_is_sorted(ossl_check_const_ASN1_INTEGER_sk_type(sk))
|
||||||
|
#define sk_ASN1_INTEGER_dup(sk) ((STACK_OF(ASN1_INTEGER) *)OPENSSL_sk_dup(ossl_check_const_ASN1_INTEGER_sk_type(sk)))
|
||||||
|
#define sk_ASN1_INTEGER_deep_copy(sk, copyfunc, freefunc) ((STACK_OF(ASN1_INTEGER) *)OPENSSL_sk_deep_copy(ossl_check_const_ASN1_INTEGER_sk_type(sk), ossl_check_ASN1_INTEGER_copyfunc_type(copyfunc), ossl_check_ASN1_INTEGER_freefunc_type(freefunc)))
|
||||||
|
#define sk_ASN1_INTEGER_set_cmp_func(sk, cmp) ((sk_ASN1_INTEGER_compfunc)OPENSSL_sk_set_cmp_func(ossl_check_ASN1_INTEGER_sk_type(sk), ossl_check_ASN1_INTEGER_compfunc_type(cmp)))
|
||||||
|
|
||||||
|
/* clang-format on */
|
||||||
|
|
||||||
DECLARE_ASN1_FUNCTIONS(ASN1_INTEGER)
|
DECLARE_ASN1_FUNCTIONS(ASN1_INTEGER)
|
||||||
ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp,
|
ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp,
|
||||||
long length);
|
long length);
|
||||||
ASN1_INTEGER *ASN1_INTEGER_dup(const ASN1_INTEGER *x);
|
DECLARE_ASN1_DUP_FUNCTION(ASN1_INTEGER)
|
||||||
int ASN1_INTEGER_cmp(const ASN1_INTEGER *x, const ASN1_INTEGER *y);
|
int ASN1_INTEGER_cmp(const ASN1_INTEGER *x, const ASN1_INTEGER *y);
|
||||||
|
|
||||||
DECLARE_ASN1_FUNCTIONS(ASN1_ENUMERATED)
|
DECLARE_ASN1_FUNCTIONS(ASN1_ENUMERATED)
|
||||||
@@ -594,12 +713,42 @@ int ASN1_TIME_diff(int *pday, int *psec,
|
|||||||
const ASN1_TIME *from, const ASN1_TIME *to);
|
const ASN1_TIME *from, const ASN1_TIME *to);
|
||||||
|
|
||||||
DECLARE_ASN1_FUNCTIONS(ASN1_OCTET_STRING)
|
DECLARE_ASN1_FUNCTIONS(ASN1_OCTET_STRING)
|
||||||
ASN1_OCTET_STRING *ASN1_OCTET_STRING_dup(const ASN1_OCTET_STRING *a);
|
DECLARE_ASN1_DUP_FUNCTION(ASN1_OCTET_STRING)
|
||||||
int ASN1_OCTET_STRING_cmp(const ASN1_OCTET_STRING *a,
|
int ASN1_OCTET_STRING_cmp(const ASN1_OCTET_STRING *a,
|
||||||
const ASN1_OCTET_STRING *b);
|
const ASN1_OCTET_STRING *b);
|
||||||
int ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *str, const unsigned char *data,
|
int ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *str, const unsigned char *data,
|
||||||
int len);
|
int len);
|
||||||
|
|
||||||
|
/* clang-format off */
|
||||||
|
SKM_DEFINE_STACK_OF_INTERNAL(ASN1_UTF8STRING, ASN1_UTF8STRING, ASN1_UTF8STRING)
|
||||||
|
#define sk_ASN1_UTF8STRING_num(sk) OPENSSL_sk_num(ossl_check_const_ASN1_UTF8STRING_sk_type(sk))
|
||||||
|
#define sk_ASN1_UTF8STRING_value(sk, idx) ((ASN1_UTF8STRING *)OPENSSL_sk_value(ossl_check_const_ASN1_UTF8STRING_sk_type(sk), (idx)))
|
||||||
|
#define sk_ASN1_UTF8STRING_new(cmp) ((STACK_OF(ASN1_UTF8STRING) *)OPENSSL_sk_set_cmp_thunks(OPENSSL_sk_new(ossl_check_ASN1_UTF8STRING_compfunc_type(cmp)), sk_ASN1_UTF8STRING_cmpfunc_thunk))
|
||||||
|
#define sk_ASN1_UTF8STRING_new_null() ((STACK_OF(ASN1_UTF8STRING) *)OPENSSL_sk_set_thunks(OPENSSL_sk_new_null(), sk_ASN1_UTF8STRING_freefunc_thunk))
|
||||||
|
#define sk_ASN1_UTF8STRING_new_reserve(cmp, n) ((STACK_OF(ASN1_UTF8STRING) *)OPENSSL_sk_set_cmp_thunks(OPENSSL_sk_new_reserve(ossl_check_ASN1_UTF8STRING_compfunc_type(cmp), (n)), sk_ASN1_UTF8STRING_cmpfunc_thunk))
|
||||||
|
#define sk_ASN1_UTF8STRING_reserve(sk, n) OPENSSL_sk_reserve(ossl_check_ASN1_UTF8STRING_sk_type(sk), (n))
|
||||||
|
#define sk_ASN1_UTF8STRING_free(sk) OPENSSL_sk_free(ossl_check_ASN1_UTF8STRING_sk_type(sk))
|
||||||
|
#define sk_ASN1_UTF8STRING_zero(sk) OPENSSL_sk_zero(ossl_check_ASN1_UTF8STRING_sk_type(sk))
|
||||||
|
#define sk_ASN1_UTF8STRING_delete(sk, i) ((ASN1_UTF8STRING *)OPENSSL_sk_delete(ossl_check_ASN1_UTF8STRING_sk_type(sk), (i)))
|
||||||
|
#define sk_ASN1_UTF8STRING_delete_ptr(sk, ptr) ((ASN1_UTF8STRING *)OPENSSL_sk_delete_ptr(ossl_check_ASN1_UTF8STRING_sk_type(sk), ossl_check_ASN1_UTF8STRING_type(ptr)))
|
||||||
|
#define sk_ASN1_UTF8STRING_push(sk, ptr) OPENSSL_sk_push(ossl_check_ASN1_UTF8STRING_sk_type(sk), ossl_check_ASN1_UTF8STRING_type(ptr))
|
||||||
|
#define sk_ASN1_UTF8STRING_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_ASN1_UTF8STRING_sk_type(sk), ossl_check_ASN1_UTF8STRING_type(ptr))
|
||||||
|
#define sk_ASN1_UTF8STRING_pop(sk) ((ASN1_UTF8STRING *)OPENSSL_sk_pop(ossl_check_ASN1_UTF8STRING_sk_type(sk)))
|
||||||
|
#define sk_ASN1_UTF8STRING_shift(sk) ((ASN1_UTF8STRING *)OPENSSL_sk_shift(ossl_check_ASN1_UTF8STRING_sk_type(sk)))
|
||||||
|
#define sk_ASN1_UTF8STRING_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_ASN1_UTF8STRING_sk_type(sk), ossl_check_ASN1_UTF8STRING_freefunc_type(freefunc))
|
||||||
|
#define sk_ASN1_UTF8STRING_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_ASN1_UTF8STRING_sk_type(sk), ossl_check_ASN1_UTF8STRING_type(ptr), (idx))
|
||||||
|
#define sk_ASN1_UTF8STRING_set(sk, idx, ptr) ((ASN1_UTF8STRING *)OPENSSL_sk_set(ossl_check_ASN1_UTF8STRING_sk_type(sk), (idx), ossl_check_ASN1_UTF8STRING_type(ptr)))
|
||||||
|
#define sk_ASN1_UTF8STRING_find(sk, ptr) OPENSSL_sk_find(ossl_check_ASN1_UTF8STRING_sk_type(sk), ossl_check_ASN1_UTF8STRING_type(ptr))
|
||||||
|
#define sk_ASN1_UTF8STRING_find_ex(sk, ptr) OPENSSL_sk_find_ex(ossl_check_ASN1_UTF8STRING_sk_type(sk), ossl_check_ASN1_UTF8STRING_type(ptr))
|
||||||
|
#define sk_ASN1_UTF8STRING_find_all(sk, ptr, pnum) OPENSSL_sk_find_all(ossl_check_ASN1_UTF8STRING_sk_type(sk), ossl_check_ASN1_UTF8STRING_type(ptr), pnum)
|
||||||
|
#define sk_ASN1_UTF8STRING_sort(sk) OPENSSL_sk_sort(ossl_check_ASN1_UTF8STRING_sk_type(sk))
|
||||||
|
#define sk_ASN1_UTF8STRING_is_sorted(sk) OPENSSL_sk_is_sorted(ossl_check_const_ASN1_UTF8STRING_sk_type(sk))
|
||||||
|
#define sk_ASN1_UTF8STRING_dup(sk) ((STACK_OF(ASN1_UTF8STRING) *)OPENSSL_sk_dup(ossl_check_const_ASN1_UTF8STRING_sk_type(sk)))
|
||||||
|
#define sk_ASN1_UTF8STRING_deep_copy(sk, copyfunc, freefunc) ((STACK_OF(ASN1_UTF8STRING) *)OPENSSL_sk_deep_copy(ossl_check_const_ASN1_UTF8STRING_sk_type(sk), ossl_check_ASN1_UTF8STRING_copyfunc_type(copyfunc), ossl_check_ASN1_UTF8STRING_freefunc_type(freefunc)))
|
||||||
|
#define sk_ASN1_UTF8STRING_set_cmp_func(sk, cmp) ((sk_ASN1_UTF8STRING_compfunc)OPENSSL_sk_set_cmp_func(ossl_check_ASN1_UTF8STRING_sk_type(sk), ossl_check_ASN1_UTF8STRING_compfunc_type(cmp)))
|
||||||
|
|
||||||
|
/* clang-format on */
|
||||||
|
|
||||||
DECLARE_ASN1_FUNCTIONS(ASN1_VISIBLESTRING)
|
DECLARE_ASN1_FUNCTIONS(ASN1_VISIBLESTRING)
|
||||||
DECLARE_ASN1_FUNCTIONS(ASN1_UNIVERSALSTRING)
|
DECLARE_ASN1_FUNCTIONS(ASN1_UNIVERSALSTRING)
|
||||||
DECLARE_ASN1_FUNCTIONS(ASN1_UTF8STRING)
|
DECLARE_ASN1_FUNCTIONS(ASN1_UTF8STRING)
|
||||||
@@ -609,6 +758,36 @@ DECLARE_ASN1_FUNCTIONS(ASN1_BMPSTRING)
|
|||||||
int UTF8_getc(const unsigned char *str, int len, unsigned long *val);
|
int UTF8_getc(const unsigned char *str, int len, unsigned long *val);
|
||||||
int UTF8_putc(unsigned char *str, int len, unsigned long value);
|
int UTF8_putc(unsigned char *str, int len, unsigned long value);
|
||||||
|
|
||||||
|
/* clang-format off */
|
||||||
|
SKM_DEFINE_STACK_OF_INTERNAL(ASN1_GENERALSTRING, ASN1_GENERALSTRING, ASN1_GENERALSTRING)
|
||||||
|
#define sk_ASN1_GENERALSTRING_num(sk) OPENSSL_sk_num(ossl_check_const_ASN1_GENERALSTRING_sk_type(sk))
|
||||||
|
#define sk_ASN1_GENERALSTRING_value(sk, idx) ((ASN1_GENERALSTRING *)OPENSSL_sk_value(ossl_check_const_ASN1_GENERALSTRING_sk_type(sk), (idx)))
|
||||||
|
#define sk_ASN1_GENERALSTRING_new(cmp) ((STACK_OF(ASN1_GENERALSTRING) *)OPENSSL_sk_set_cmp_thunks(OPENSSL_sk_new(ossl_check_ASN1_GENERALSTRING_compfunc_type(cmp)), sk_ASN1_GENERALSTRING_cmpfunc_thunk))
|
||||||
|
#define sk_ASN1_GENERALSTRING_new_null() ((STACK_OF(ASN1_GENERALSTRING) *)OPENSSL_sk_set_thunks(OPENSSL_sk_new_null(), sk_ASN1_GENERALSTRING_freefunc_thunk))
|
||||||
|
#define sk_ASN1_GENERALSTRING_new_reserve(cmp, n) ((STACK_OF(ASN1_GENERALSTRING) *)OPENSSL_sk_set_cmp_thunks(OPENSSL_sk_new_reserve(ossl_check_ASN1_GENERALSTRING_compfunc_type(cmp), (n)), sk_ASN1_GENERALSTRING_cmpfunc_thunk))
|
||||||
|
#define sk_ASN1_GENERALSTRING_reserve(sk, n) OPENSSL_sk_reserve(ossl_check_ASN1_GENERALSTRING_sk_type(sk), (n))
|
||||||
|
#define sk_ASN1_GENERALSTRING_free(sk) OPENSSL_sk_free(ossl_check_ASN1_GENERALSTRING_sk_type(sk))
|
||||||
|
#define sk_ASN1_GENERALSTRING_zero(sk) OPENSSL_sk_zero(ossl_check_ASN1_GENERALSTRING_sk_type(sk))
|
||||||
|
#define sk_ASN1_GENERALSTRING_delete(sk, i) ((ASN1_GENERALSTRING *)OPENSSL_sk_delete(ossl_check_ASN1_GENERALSTRING_sk_type(sk), (i)))
|
||||||
|
#define sk_ASN1_GENERALSTRING_delete_ptr(sk, ptr) ((ASN1_GENERALSTRING *)OPENSSL_sk_delete_ptr(ossl_check_ASN1_GENERALSTRING_sk_type(sk), ossl_check_ASN1_GENERALSTRING_type(ptr)))
|
||||||
|
#define sk_ASN1_GENERALSTRING_push(sk, ptr) OPENSSL_sk_push(ossl_check_ASN1_GENERALSTRING_sk_type(sk), ossl_check_ASN1_GENERALSTRING_type(ptr))
|
||||||
|
#define sk_ASN1_GENERALSTRING_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_ASN1_GENERALSTRING_sk_type(sk), ossl_check_ASN1_GENERALSTRING_type(ptr))
|
||||||
|
#define sk_ASN1_GENERALSTRING_pop(sk) ((ASN1_GENERALSTRING *)OPENSSL_sk_pop(ossl_check_ASN1_GENERALSTRING_sk_type(sk)))
|
||||||
|
#define sk_ASN1_GENERALSTRING_shift(sk) ((ASN1_GENERALSTRING *)OPENSSL_sk_shift(ossl_check_ASN1_GENERALSTRING_sk_type(sk)))
|
||||||
|
#define sk_ASN1_GENERALSTRING_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_ASN1_GENERALSTRING_sk_type(sk), ossl_check_ASN1_GENERALSTRING_freefunc_type(freefunc))
|
||||||
|
#define sk_ASN1_GENERALSTRING_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_ASN1_GENERALSTRING_sk_type(sk), ossl_check_ASN1_GENERALSTRING_type(ptr), (idx))
|
||||||
|
#define sk_ASN1_GENERALSTRING_set(sk, idx, ptr) ((ASN1_GENERALSTRING *)OPENSSL_sk_set(ossl_check_ASN1_GENERALSTRING_sk_type(sk), (idx), ossl_check_ASN1_GENERALSTRING_type(ptr)))
|
||||||
|
#define sk_ASN1_GENERALSTRING_find(sk, ptr) OPENSSL_sk_find(ossl_check_ASN1_GENERALSTRING_sk_type(sk), ossl_check_ASN1_GENERALSTRING_type(ptr))
|
||||||
|
#define sk_ASN1_GENERALSTRING_find_ex(sk, ptr) OPENSSL_sk_find_ex(ossl_check_ASN1_GENERALSTRING_sk_type(sk), ossl_check_ASN1_GENERALSTRING_type(ptr))
|
||||||
|
#define sk_ASN1_GENERALSTRING_find_all(sk, ptr, pnum) OPENSSL_sk_find_all(ossl_check_ASN1_GENERALSTRING_sk_type(sk), ossl_check_ASN1_GENERALSTRING_type(ptr), pnum)
|
||||||
|
#define sk_ASN1_GENERALSTRING_sort(sk) OPENSSL_sk_sort(ossl_check_ASN1_GENERALSTRING_sk_type(sk))
|
||||||
|
#define sk_ASN1_GENERALSTRING_is_sorted(sk) OPENSSL_sk_is_sorted(ossl_check_const_ASN1_GENERALSTRING_sk_type(sk))
|
||||||
|
#define sk_ASN1_GENERALSTRING_dup(sk) ((STACK_OF(ASN1_GENERALSTRING) *)OPENSSL_sk_dup(ossl_check_const_ASN1_GENERALSTRING_sk_type(sk)))
|
||||||
|
#define sk_ASN1_GENERALSTRING_deep_copy(sk, copyfunc, freefunc) ((STACK_OF(ASN1_GENERALSTRING) *)OPENSSL_sk_deep_copy(ossl_check_const_ASN1_GENERALSTRING_sk_type(sk), ossl_check_ASN1_GENERALSTRING_copyfunc_type(copyfunc), ossl_check_ASN1_GENERALSTRING_freefunc_type(freefunc)))
|
||||||
|
#define sk_ASN1_GENERALSTRING_set_cmp_func(sk, cmp) ((sk_ASN1_GENERALSTRING_compfunc)OPENSSL_sk_set_cmp_func(ossl_check_ASN1_GENERALSTRING_sk_type(sk), ossl_check_ASN1_GENERALSTRING_compfunc_type(cmp)))
|
||||||
|
|
||||||
|
/* clang-format on */
|
||||||
|
|
||||||
DECLARE_ASN1_FUNCTIONS_name(ASN1_STRING, ASN1_PRINTABLE)
|
DECLARE_ASN1_FUNCTIONS_name(ASN1_STRING, ASN1_PRINTABLE)
|
||||||
|
|
||||||
DECLARE_ASN1_FUNCTIONS_name(ASN1_STRING, DIRECTORYSTRING)
|
DECLARE_ASN1_FUNCTIONS_name(ASN1_STRING, DIRECTORYSTRING)
|
||||||
@@ -621,6 +800,10 @@ DECLARE_ASN1_FUNCTIONS(ASN1_UTCTIME)
|
|||||||
DECLARE_ASN1_FUNCTIONS(ASN1_GENERALIZEDTIME)
|
DECLARE_ASN1_FUNCTIONS(ASN1_GENERALIZEDTIME)
|
||||||
DECLARE_ASN1_FUNCTIONS(ASN1_TIME)
|
DECLARE_ASN1_FUNCTIONS(ASN1_TIME)
|
||||||
|
|
||||||
|
DECLARE_ASN1_DUP_FUNCTION(ASN1_TIME)
|
||||||
|
DECLARE_ASN1_DUP_FUNCTION(ASN1_UTCTIME)
|
||||||
|
DECLARE_ASN1_DUP_FUNCTION(ASN1_GENERALIZEDTIME)
|
||||||
|
|
||||||
DECLARE_ASN1_ITEM(ASN1_OCTET_STRING_NDEF)
|
DECLARE_ASN1_ITEM(ASN1_OCTET_STRING_NDEF)
|
||||||
|
|
||||||
ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t);
|
ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t);
|
||||||
@@ -662,7 +845,6 @@ BIGNUM *ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai, BIGNUM *bn);
|
|||||||
int ASN1_ENUMERATED_get_int64(int64_t *pr, const ASN1_ENUMERATED *a);
|
int ASN1_ENUMERATED_get_int64(int64_t *pr, const ASN1_ENUMERATED *a);
|
||||||
int ASN1_ENUMERATED_set_int64(ASN1_ENUMERATED *a, int64_t r);
|
int ASN1_ENUMERATED_set_int64(ASN1_ENUMERATED *a, int64_t r);
|
||||||
|
|
||||||
|
|
||||||
int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v);
|
int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v);
|
||||||
long ASN1_ENUMERATED_get(const ASN1_ENUMERATED *a);
|
long ASN1_ENUMERATED_get(const ASN1_ENUMERATED *a);
|
||||||
ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(const BIGNUM *bn, ASN1_ENUMERATED *ai);
|
ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(const BIGNUM *bn, ASN1_ENUMERATED *ai);
|
||||||
@@ -685,19 +867,23 @@ int ASN1_put_eoc(unsigned char **pp);
|
|||||||
int ASN1_object_size(int constructed, int length, int tag);
|
int ASN1_object_size(int constructed, int length, int tag);
|
||||||
|
|
||||||
/* Used to implement other functions */
|
/* Used to implement other functions */
|
||||||
void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, void *x);
|
void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, const void *x);
|
||||||
|
|
||||||
#define ASN1_dup_of(type, i2d, d2i, x) \
|
#define ASN1_dup_of(type, i2d, d2i, x) \
|
||||||
((type *)ASN1_dup(CHECKED_I2D_OF(type, i2d), \
|
((type *)ASN1_dup(CHECKED_I2D_OF(type, i2d), \
|
||||||
CHECKED_D2I_OF(type, d2i), \
|
|
||||||
CHECKED_PTR_OF(type, x)))
|
|
||||||
|
|
||||||
# define ASN1_dup_of_const(type,i2d,d2i,x) \
|
|
||||||
((type*)ASN1_dup(CHECKED_I2D_OF(const type, i2d), \
|
|
||||||
CHECKED_D2I_OF(type, d2i), \
|
CHECKED_D2I_OF(type, d2i), \
|
||||||
CHECKED_PTR_OF(const type, x)))
|
CHECKED_PTR_OF(const type, x)))
|
||||||
|
|
||||||
void *ASN1_item_dup(const ASN1_ITEM *it, void *x);
|
void *ASN1_item_dup(const ASN1_ITEM *it, const void *x);
|
||||||
|
int ASN1_item_sign_ex(const ASN1_ITEM *it, X509_ALGOR *algor1,
|
||||||
|
X509_ALGOR *algor2, ASN1_BIT_STRING *signature,
|
||||||
|
const void *data, const ASN1_OCTET_STRING *id,
|
||||||
|
EVP_PKEY *pkey, const EVP_MD *md, OSSL_LIB_CTX *libctx,
|
||||||
|
const char *propq);
|
||||||
|
int ASN1_item_verify_ex(const ASN1_ITEM *it, const X509_ALGOR *alg,
|
||||||
|
const ASN1_BIT_STRING *signature, const void *data,
|
||||||
|
const ASN1_OCTET_STRING *id, EVP_PKEY *pkey,
|
||||||
|
OSSL_LIB_CTX *libctx, const char *propq);
|
||||||
|
|
||||||
/* ASN1 alloc/free macros for when a type is only used internally */
|
/* ASN1 alloc/free macros for when a type is only used internally */
|
||||||
|
|
||||||
@@ -714,20 +900,17 @@ void *ASN1_d2i_fp(void *(*xnew) (void), d2i_of_void *d2i, FILE *in, void **x);
|
|||||||
in, \
|
in, \
|
||||||
CHECKED_PPTR_OF(type, x)))
|
CHECKED_PPTR_OF(type, x)))
|
||||||
|
|
||||||
|
void *ASN1_item_d2i_fp_ex(const ASN1_ITEM *it, FILE *in, void *x,
|
||||||
|
OSSL_LIB_CTX *libctx, const char *propq);
|
||||||
void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x);
|
void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x);
|
||||||
int ASN1_i2d_fp(i2d_of_void *i2d, FILE *out, void *x);
|
int ASN1_i2d_fp(i2d_of_void *i2d, FILE *out, const void *x);
|
||||||
|
|
||||||
#define ASN1_i2d_fp_of(type, i2d, out, x) \
|
#define ASN1_i2d_fp_of(type, i2d, out, x) \
|
||||||
(ASN1_i2d_fp(CHECKED_I2D_OF(type, i2d), \
|
(ASN1_i2d_fp(CHECKED_I2D_OF(type, i2d), \
|
||||||
out, \
|
|
||||||
CHECKED_PTR_OF(type, x)))
|
|
||||||
|
|
||||||
# define ASN1_i2d_fp_of_const(type,i2d,out,x) \
|
|
||||||
(ASN1_i2d_fp(CHECKED_I2D_OF(const type, i2d), \
|
|
||||||
out, \
|
out, \
|
||||||
CHECKED_PTR_OF(const type, x)))
|
CHECKED_PTR_OF(const type, x)))
|
||||||
|
|
||||||
int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x);
|
int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, const void *x);
|
||||||
int ASN1_STRING_print_ex_fp(FILE *fp, const ASN1_STRING *str, unsigned long flags);
|
int ASN1_STRING_print_ex_fp(FILE *fp, const ASN1_STRING *str, unsigned long flags);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -741,23 +924,22 @@ void *ASN1_d2i_bio(void *(*xnew) (void), d2i_of_void *d2i, BIO *in, void **x);
|
|||||||
in, \
|
in, \
|
||||||
CHECKED_PPTR_OF(type, x)))
|
CHECKED_PPTR_OF(type, x)))
|
||||||
|
|
||||||
void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x);
|
void *ASN1_item_d2i_bio_ex(const ASN1_ITEM *it, BIO *in, void *pval,
|
||||||
int ASN1_i2d_bio(i2d_of_void *i2d, BIO *out, unsigned char *x);
|
OSSL_LIB_CTX *libctx, const char *propq);
|
||||||
|
void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *pval);
|
||||||
|
int ASN1_i2d_bio(i2d_of_void *i2d, BIO *out, const void *x);
|
||||||
|
|
||||||
#define ASN1_i2d_bio_of(type, i2d, out, x) \
|
#define ASN1_i2d_bio_of(type, i2d, out, x) \
|
||||||
(ASN1_i2d_bio(CHECKED_I2D_OF(type, i2d), \
|
(ASN1_i2d_bio(CHECKED_I2D_OF(type, i2d), \
|
||||||
out, \
|
|
||||||
CHECKED_PTR_OF(type, x)))
|
|
||||||
|
|
||||||
# define ASN1_i2d_bio_of_const(type,i2d,out,x) \
|
|
||||||
(ASN1_i2d_bio(CHECKED_I2D_OF(const type, i2d), \
|
|
||||||
out, \
|
out, \
|
||||||
CHECKED_PTR_OF(const type, x)))
|
CHECKED_PTR_OF(const type, x)))
|
||||||
|
|
||||||
int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x);
|
int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, const void *x);
|
||||||
|
BIO *ASN1_item_i2d_mem_bio(const ASN1_ITEM *it, const ASN1_VALUE *val);
|
||||||
int ASN1_UTCTIME_print(BIO *fp, const ASN1_UTCTIME *a);
|
int ASN1_UTCTIME_print(BIO *fp, const ASN1_UTCTIME *a);
|
||||||
int ASN1_GENERALIZEDTIME_print(BIO *fp, const ASN1_GENERALIZEDTIME *a);
|
int ASN1_GENERALIZEDTIME_print(BIO *fp, const ASN1_GENERALIZEDTIME *a);
|
||||||
int ASN1_TIME_print(BIO *fp, const ASN1_TIME *a);
|
int ASN1_TIME_print(BIO *bp, const ASN1_TIME *tm);
|
||||||
|
int ASN1_TIME_print_ex(BIO *bp, const ASN1_TIME *tm, unsigned long flags);
|
||||||
int ASN1_STRING_print(BIO *bp, const ASN1_STRING *v);
|
int ASN1_STRING_print(BIO *bp, const ASN1_STRING *v);
|
||||||
int ASN1_STRING_print_ex(BIO *out, const ASN1_STRING *str, unsigned long flags);
|
int ASN1_STRING_print_ex(BIO *out, const ASN1_STRING *str, unsigned long flags);
|
||||||
int ASN1_buf_print(BIO *bp, const unsigned char *buf, size_t buflen, int off);
|
int ASN1_buf_print(BIO *bp, const unsigned char *buf, size_t buflen, int off);
|
||||||
@@ -780,6 +962,8 @@ int ASN1_TYPE_get_int_octetstring(const ASN1_TYPE *a, long *num,
|
|||||||
unsigned char *data, int max_len);
|
unsigned char *data, int max_len);
|
||||||
|
|
||||||
void *ASN1_item_unpack(const ASN1_STRING *oct, const ASN1_ITEM *it);
|
void *ASN1_item_unpack(const ASN1_STRING *oct, const ASN1_ITEM *it);
|
||||||
|
void *ASN1_item_unpack_ex(const ASN1_STRING *oct, const ASN1_ITEM *it,
|
||||||
|
OSSL_LIB_CTX *libctx, const char *propq);
|
||||||
|
|
||||||
ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it,
|
ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it,
|
||||||
ASN1_OCTET_STRING **oct);
|
ASN1_OCTET_STRING **oct);
|
||||||
@@ -804,11 +988,16 @@ void ASN1_STRING_TABLE_cleanup(void);
|
|||||||
|
|
||||||
/* Old API compatible functions */
|
/* Old API compatible functions */
|
||||||
ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it);
|
ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it);
|
||||||
|
ASN1_VALUE *ASN1_item_new_ex(const ASN1_ITEM *it, OSSL_LIB_CTX *libctx,
|
||||||
|
const char *propq);
|
||||||
void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it);
|
void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it);
|
||||||
|
ASN1_VALUE *ASN1_item_d2i_ex(ASN1_VALUE **val, const unsigned char **in,
|
||||||
|
long len, const ASN1_ITEM *it,
|
||||||
|
OSSL_LIB_CTX *libctx, const char *propq);
|
||||||
ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **val, const unsigned char **in,
|
ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **val, const unsigned char **in,
|
||||||
long len, const ASN1_ITEM *it);
|
long len, const ASN1_ITEM *it);
|
||||||
int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it);
|
int ASN1_item_i2d(const ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it);
|
||||||
int ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out,
|
int ASN1_item_ndef_i2d(const ASN1_VALUE *val, unsigned char **out,
|
||||||
const ASN1_ITEM *it);
|
const ASN1_ITEM *it);
|
||||||
|
|
||||||
void ASN1_add_oid_module(void);
|
void ASN1_add_oid_module(void);
|
||||||
@@ -839,7 +1028,7 @@ int ASN1_str2mask(const char *str, unsigned long *pmask);
|
|||||||
/* Don't show structure name even at top level */
|
/* Don't show structure name even at top level */
|
||||||
#define ASN1_PCTX_FLAGS_NO_STRUCT_NAME 0x100
|
#define ASN1_PCTX_FLAGS_NO_STRUCT_NAME 0x100
|
||||||
|
|
||||||
int ASN1_item_print(BIO *out, ASN1_VALUE *ifld, int indent,
|
int ASN1_item_print(BIO *out, const ASN1_VALUE *ifld, int indent,
|
||||||
const ASN1_ITEM *it, const ASN1_PCTX *pctx);
|
const ASN1_ITEM *it, const ASN1_PCTX *pctx);
|
||||||
ASN1_PCTX *ASN1_PCTX_new(void);
|
ASN1_PCTX *ASN1_PCTX_new(void);
|
||||||
void ASN1_PCTX_free(ASN1_PCTX *p);
|
void ASN1_PCTX_free(ASN1_PCTX *p);
|
||||||
@@ -864,22 +1053,43 @@ void *ASN1_SCTX_get_app_data(ASN1_SCTX *p);
|
|||||||
|
|
||||||
const BIO_METHOD *BIO_f_asn1(void);
|
const BIO_METHOD *BIO_f_asn1(void);
|
||||||
|
|
||||||
|
/* cannot constify val because of CMS_stream() */
|
||||||
BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it);
|
BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it);
|
||||||
|
|
||||||
int i2d_ASN1_bio_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
|
int i2d_ASN1_bio_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
|
||||||
const ASN1_ITEM *it);
|
const ASN1_ITEM *it);
|
||||||
int PEM_write_bio_ASN1_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
|
int PEM_write_bio_ASN1_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
|
||||||
const char *hdr, const ASN1_ITEM *it);
|
const char *hdr, const ASN1_ITEM *it);
|
||||||
|
/* cannot constify val because of CMS_dataFinal() */
|
||||||
int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
|
int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
|
||||||
int ctype_nid, int econt_nid,
|
int ctype_nid, int econt_nid,
|
||||||
STACK_OF(X509_ALGOR) *mdalgs, const ASN1_ITEM *it);
|
STACK_OF(X509_ALGOR) *mdalgs, const ASN1_ITEM *it);
|
||||||
|
int SMIME_write_ASN1_ex(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
|
||||||
|
int ctype_nid, int econt_nid,
|
||||||
|
STACK_OF(X509_ALGOR) *mdalgs, const ASN1_ITEM *it,
|
||||||
|
OSSL_LIB_CTX *libctx, const char *propq);
|
||||||
ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it);
|
ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it);
|
||||||
|
ASN1_VALUE *SMIME_read_ASN1_ex(BIO *bio, int flags, BIO **bcont,
|
||||||
|
const ASN1_ITEM *it, ASN1_VALUE **x,
|
||||||
|
OSSL_LIB_CTX *libctx, const char *propq);
|
||||||
int SMIME_crlf_copy(BIO *in, BIO *out, int flags);
|
int SMIME_crlf_copy(BIO *in, BIO *out, int flags);
|
||||||
int SMIME_text(BIO *in, BIO *out);
|
int SMIME_text(BIO *in, BIO *out);
|
||||||
|
|
||||||
const ASN1_ITEM *ASN1_ITEM_lookup(const char *name);
|
const ASN1_ITEM *ASN1_ITEM_lookup(const char *name);
|
||||||
const ASN1_ITEM *ASN1_ITEM_get(size_t i);
|
const ASN1_ITEM *ASN1_ITEM_get(size_t i);
|
||||||
|
|
||||||
|
/* Legacy compatibility */
|
||||||
|
#define DECLARE_ASN1_FUNCTIONS_fname(type, itname, name) \
|
||||||
|
DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \
|
||||||
|
DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name)
|
||||||
|
#define DECLARE_ASN1_FUNCTIONS_const(type) DECLARE_ASN1_FUNCTIONS(type)
|
||||||
|
#define DECLARE_ASN1_ENCODE_FUNCTIONS_const(type, name) \
|
||||||
|
DECLARE_ASN1_ENCODE_FUNCTIONS(type, name)
|
||||||
|
#define I2D_OF_const(type) I2D_OF(type)
|
||||||
|
#define ASN1_dup_of_const(type, i2d, d2i, x) ASN1_dup_of(type, i2d, d2i, x)
|
||||||
|
#define ASN1_i2d_fp_of_const(type, i2d, out, x) ASN1_i2d_fp_of(type, i2d, out, x)
|
||||||
|
#define ASN1_i2d_bio_of_const(type, i2d, out, x) ASN1_i2d_bio_of(type, i2d, out, x)
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -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,140 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
* Generated by util/mkerr.pl DO NOT EDIT
|
* 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
|
* this file except in compliance with the License. You can obtain a copy
|
||||||
* in the file LICENSE in the source distribution or at
|
* in the file LICENSE in the source distribution or at
|
||||||
* https://www.openssl.org/source/license.html
|
* https://www.openssl.org/source/license.html
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef HEADER_ASN1ERR_H
|
#ifndef OPENSSL_ASN1ERR_H
|
||||||
# define HEADER_ASN1ERR_H
|
#define OPENSSL_ASN1ERR_H
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <openssl/opensslconf.h>
|
||||||
#include <openssl/symhacks.h>
|
#include <openssl/symhacks.h>
|
||||||
|
#include <openssl/cryptoerr_legacy.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
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ASN1 reason codes.
|
* ASN1 reason codes.
|
||||||
@@ -165,6 +45,7 @@ int ERR_load_ASN1_strings(void);
|
|||||||
#define ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED 120
|
#define ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED 120
|
||||||
#define ASN1_R_FIELD_MISSING 121
|
#define ASN1_R_FIELD_MISSING 121
|
||||||
#define ASN1_R_FIRST_NUM_TOO_LARGE 122
|
#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_HEADER_TOO_LONG 123
|
||||||
#define ASN1_R_ILLEGAL_BITSTRING_FORMAT 175
|
#define ASN1_R_ILLEGAL_BITSTRING_FORMAT 175
|
||||||
#define ASN1_R_ILLEGAL_BOOLEAN 176
|
#define ASN1_R_ILLEGAL_BOOLEAN 176
|
||||||
@@ -199,6 +80,7 @@ int ERR_load_ASN1_strings(void);
|
|||||||
#define ASN1_R_INVALID_UNIVERSALSTRING_LENGTH 133
|
#define ASN1_R_INVALID_UNIVERSALSTRING_LENGTH 133
|
||||||
#define ASN1_R_INVALID_UTF8STRING 134
|
#define ASN1_R_INVALID_UTF8STRING 134
|
||||||
#define ASN1_R_INVALID_VALUE 219
|
#define ASN1_R_INVALID_VALUE 219
|
||||||
|
#define ASN1_R_LENGTH_TOO_LONG 231
|
||||||
#define ASN1_R_LIST_ERROR 188
|
#define ASN1_R_LIST_ERROR 188
|
||||||
#define ASN1_R_MIME_NO_CONTENT_TYPE 206
|
#define ASN1_R_MIME_NO_CONTENT_TYPE 206
|
||||||
#define ASN1_R_MIME_PARSE_ERROR 207
|
#define ASN1_R_MIME_PARSE_ERROR 207
|
||||||
@@ -239,6 +121,7 @@ int ERR_load_ASN1_strings(void);
|
|||||||
#define ASN1_R_TYPE_NOT_PRIMITIVE 195
|
#define ASN1_R_TYPE_NOT_PRIMITIVE 195
|
||||||
#define ASN1_R_UNEXPECTED_EOC 159
|
#define ASN1_R_UNEXPECTED_EOC 159
|
||||||
#define ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH 215
|
#define ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH 215
|
||||||
|
#define ASN1_R_UNKNOWN_DIGEST 229
|
||||||
#define ASN1_R_UNKNOWN_FORMAT 160
|
#define ASN1_R_UNKNOWN_FORMAT 160
|
||||||
#define ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM 161
|
#define ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM 161
|
||||||
#define ASN1_R_UNKNOWN_OBJECT_TYPE 162
|
#define ASN1_R_UNKNOWN_OBJECT_TYPE 162
|
||||||
@@ -249,6 +132,7 @@ int ERR_load_ASN1_strings(void);
|
|||||||
#define ASN1_R_UNSUPPORTED_CIPHER 228
|
#define ASN1_R_UNSUPPORTED_CIPHER 228
|
||||||
#define ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE 167
|
#define ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE 167
|
||||||
#define ASN1_R_UNSUPPORTED_TYPE 196
|
#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_INTEGER_TYPE 225
|
||||||
#define ASN1_R_WRONG_PUBLIC_KEY_TYPE 200
|
#define ASN1_R_WRONG_PUBLIC_KEY_TYPE 200
|
||||||
#define ASN1_R_WRONG_TAG 168
|
#define ASN1_R_WRONG_TAG 168
|
||||||
|
|||||||
@@ -1,14 +1,27 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
|
* WARNING: do not edit!
|
||||||
|
* Generated by Makefile from include/openssl/asn1t.h.in
|
||||||
*
|
*
|
||||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
* Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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
|
* this file except in compliance with the License. You can obtain a copy
|
||||||
* in the file LICENSE in the source distribution or at
|
* in the file LICENSE in the source distribution or at
|
||||||
* https://www.openssl.org/source/license.html
|
* https://www.openssl.org/source/license.html
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef HEADER_ASN1T_H
|
/* clang-format off */
|
||||||
|
|
||||||
|
/* clang-format on */
|
||||||
|
|
||||||
|
#ifndef OPENSSL_ASN1T_H
|
||||||
|
#define OPENSSL_ASN1T_H
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <openssl/macros.h>
|
||||||
|
#ifndef OPENSSL_NO_DEPRECATED_3_0
|
||||||
#define HEADER_ASN1T_H
|
#define HEADER_ASN1T_H
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <openssl/e_os2.h>
|
#include <openssl/e_os2.h>
|
||||||
@@ -25,23 +38,54 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION
|
/*-
|
||||||
|
* These are the possible values for the itype field of the
|
||||||
|
* ASN1_ITEM structure and determine how it is interpreted.
|
||||||
|
*
|
||||||
|
* For PRIMITIVE types the underlying type
|
||||||
|
* determines the behaviour if items is NULL.
|
||||||
|
*
|
||||||
|
* Otherwise templates must contain a single
|
||||||
|
* template and the type is treated in the
|
||||||
|
* same way as the type specified in the template.
|
||||||
|
*
|
||||||
|
* For SEQUENCE types the templates field points
|
||||||
|
* to the members, the size field is the
|
||||||
|
* structure size.
|
||||||
|
*
|
||||||
|
* For CHOICE types the templates field points
|
||||||
|
* to each possible member (typically a union)
|
||||||
|
* and the 'size' field is the offset of the
|
||||||
|
* selector.
|
||||||
|
*
|
||||||
|
* The 'funcs' field is used for application-specific
|
||||||
|
* data and functions.
|
||||||
|
*
|
||||||
|
* The EXTERN type uses a new style d2i/i2d.
|
||||||
|
* The new style should be used where possible
|
||||||
|
* because it avoids things like the d2i IMPLICIT
|
||||||
|
* hack.
|
||||||
|
*
|
||||||
|
* MSTRING is a multiple string type, it is used
|
||||||
|
* for a CHOICE of character strings where the
|
||||||
|
* actual strings all occupy an ASN1_STRING
|
||||||
|
* structure. In this case the 'utype' field
|
||||||
|
* has a special meaning, it is used as a mask
|
||||||
|
* of acceptable types using the B_ASN1 constants.
|
||||||
|
*
|
||||||
|
* NDEF_SEQUENCE is the same as SEQUENCE except
|
||||||
|
* that it will use indefinite length constructed
|
||||||
|
* encoding if requested.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
/* Macro to obtain ASN1_ADB pointer from a type (only used internally) */
|
#define ASN1_ITYPE_PRIMITIVE 0x0
|
||||||
# define ASN1_ADB_ptr(iptr) ((const ASN1_ADB *)(iptr))
|
#define ASN1_ITYPE_SEQUENCE 0x1
|
||||||
|
#define ASN1_ITYPE_CHOICE 0x2
|
||||||
/* Macros for start and end of ASN1_ITEM definition */
|
/* unused value 0x3 */
|
||||||
|
#define ASN1_ITYPE_EXTERN 0x4
|
||||||
# define ASN1_ITEM_start(itname) \
|
#define ASN1_ITYPE_MSTRING 0x5
|
||||||
const ASN1_ITEM itname##_it = {
|
#define ASN1_ITYPE_NDEF_SEQUENCE 0x6
|
||||||
|
|
||||||
# define static_ASN1_ITEM_start(itname) \
|
|
||||||
static const ASN1_ITEM itname##_it = {
|
|
||||||
|
|
||||||
# define ASN1_ITEM_end(itname) \
|
|
||||||
};
|
|
||||||
|
|
||||||
# else
|
|
||||||
|
|
||||||
/* Macro to obtain ASN1_ADB pointer from a type (only used internally) */
|
/* Macro to obtain ASN1_ADB pointer from a type (only used internally) */
|
||||||
#define ASN1_ADB_ptr(iptr) ((const ASN1_ADB *)((iptr)()))
|
#define ASN1_ADB_ptr(iptr) ((const ASN1_ADB *)((iptr)()))
|
||||||
@@ -57,12 +101,11 @@ extern "C" {
|
|||||||
static ASN1_ITEM_start(itname)
|
static ASN1_ITEM_start(itname)
|
||||||
|
|
||||||
#define ASN1_ITEM_end(itname) \
|
#define ASN1_ITEM_end(itname) \
|
||||||
}; \
|
} \
|
||||||
|
; \
|
||||||
return &local_it; \
|
return &local_it; \
|
||||||
}
|
}
|
||||||
|
|
||||||
# endif
|
|
||||||
|
|
||||||
/* Macros to aid ASN1 template writing */
|
/* Macros to aid ASN1 template writing */
|
||||||
|
|
||||||
#define ASN1_ITEM_TEMPLATE(tname) \
|
#define ASN1_ITEM_TEMPLATE(tname) \
|
||||||
@@ -77,8 +120,7 @@ extern "C" {
|
|||||||
0, \
|
0, \
|
||||||
NULL, \
|
NULL, \
|
||||||
0, \
|
0, \
|
||||||
#tname \
|
#tname ASN1_ITEM_end(tname)
|
||||||
ASN1_ITEM_end(tname)
|
|
||||||
#define static_ASN1_ITEM_TEMPLATE_END(tname) \
|
#define static_ASN1_ITEM_TEMPLATE_END(tname) \
|
||||||
; \
|
; \
|
||||||
static_ASN1_ITEM_start(tname) \
|
static_ASN1_ITEM_start(tname) \
|
||||||
@@ -88,8 +130,7 @@ extern "C" {
|
|||||||
0, \
|
0, \
|
||||||
NULL, \
|
NULL, \
|
||||||
0, \
|
0, \
|
||||||
#tname \
|
#tname ASN1_ITEM_end(tname)
|
||||||
ASN1_ITEM_end(tname)
|
|
||||||
|
|
||||||
/* This is a ASN1 type which just embeds a template */
|
/* This is a ASN1 type which just embeds a template */
|
||||||
|
|
||||||
@@ -130,8 +171,7 @@ extern "C" {
|
|||||||
sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE), \
|
sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE), \
|
||||||
NULL, \
|
NULL, \
|
||||||
sizeof(stname), \
|
sizeof(stname), \
|
||||||
#tname \
|
#tname ASN1_ITEM_end(tname)
|
||||||
ASN1_ITEM_end(tname)
|
|
||||||
|
|
||||||
#define static_ASN1_SEQUENCE_END_name(stname, tname) \
|
#define static_ASN1_SEQUENCE_END_name(stname, tname) \
|
||||||
; \
|
; \
|
||||||
@@ -142,8 +182,7 @@ extern "C" {
|
|||||||
sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE), \
|
sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE), \
|
||||||
NULL, \
|
NULL, \
|
||||||
sizeof(stname), \
|
sizeof(stname), \
|
||||||
#stname \
|
#stname ASN1_ITEM_end(tname)
|
||||||
ASN1_ITEM_end(tname)
|
|
||||||
|
|
||||||
#define ASN1_NDEF_SEQUENCE(tname) \
|
#define ASN1_NDEF_SEQUENCE(tname) \
|
||||||
ASN1_SEQUENCE(tname)
|
ASN1_SEQUENCE(tname)
|
||||||
@@ -152,19 +191,23 @@ extern "C" {
|
|||||||
ASN1_SEQUENCE_cb(tname, cb)
|
ASN1_SEQUENCE_cb(tname, cb)
|
||||||
|
|
||||||
#define ASN1_SEQUENCE_cb(tname, cb) \
|
#define ASN1_SEQUENCE_cb(tname, cb) \
|
||||||
static const ASN1_AUX tname##_aux = {NULL, 0, 0, 0, cb, 0}; \
|
static const ASN1_AUX tname##_aux = { NULL, 0, 0, 0, cb, 0, NULL }; \
|
||||||
ASN1_SEQUENCE(tname)
|
ASN1_SEQUENCE(tname)
|
||||||
|
|
||||||
# define ASN1_BROKEN_SEQUENCE(tname) \
|
#define ASN1_SEQUENCE_const_cb(tname, const_cb) \
|
||||||
static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_BROKEN, 0, 0, 0, 0}; \
|
static const ASN1_AUX tname##_aux = { NULL, ASN1_AFLG_CONST_CB, 0, 0, NULL, 0, const_cb }; \
|
||||||
|
ASN1_SEQUENCE(tname)
|
||||||
|
|
||||||
|
#define ASN1_SEQUENCE_cb_const_cb(tname, cb, const_cb) \
|
||||||
|
static const ASN1_AUX tname##_aux = { NULL, ASN1_AFLG_CONST_CB, 0, 0, cb, 0, const_cb }; \
|
||||||
ASN1_SEQUENCE(tname)
|
ASN1_SEQUENCE(tname)
|
||||||
|
|
||||||
#define ASN1_SEQUENCE_ref(tname, cb) \
|
#define ASN1_SEQUENCE_ref(tname, cb) \
|
||||||
static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_REFCOUNT, offsetof(tname, references), offsetof(tname, lock), cb, 0}; \
|
static const ASN1_AUX tname##_aux = { NULL, ASN1_AFLG_REFCOUNT, offsetof(tname, references), offsetof(tname, lock), cb, 0, NULL }; \
|
||||||
ASN1_SEQUENCE(tname)
|
ASN1_SEQUENCE(tname)
|
||||||
|
|
||||||
#define ASN1_SEQUENCE_enc(tname, enc, cb) \
|
#define ASN1_SEQUENCE_enc(tname, enc, cb) \
|
||||||
static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_ENCODING, 0, 0, cb, offsetof(tname, enc)}; \
|
static const ASN1_AUX tname##_aux = { NULL, ASN1_AFLG_ENCODING, 0, 0, cb, offsetof(tname, enc), NULL }; \
|
||||||
ASN1_SEQUENCE(tname)
|
ASN1_SEQUENCE(tname)
|
||||||
|
|
||||||
#define ASN1_NDEF_SEQUENCE_END(tname) \
|
#define ASN1_NDEF_SEQUENCE_END(tname) \
|
||||||
@@ -176,8 +219,7 @@ extern "C" {
|
|||||||
sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE), \
|
sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE), \
|
||||||
NULL, \
|
NULL, \
|
||||||
sizeof(tname), \
|
sizeof(tname), \
|
||||||
#tname \
|
#tname ASN1_ITEM_end(tname)
|
||||||
ASN1_ITEM_end(tname)
|
|
||||||
#define static_ASN1_NDEF_SEQUENCE_END(tname) \
|
#define static_ASN1_NDEF_SEQUENCE_END(tname) \
|
||||||
; \
|
; \
|
||||||
static_ASN1_ITEM_start(tname) \
|
static_ASN1_ITEM_start(tname) \
|
||||||
@@ -187,12 +229,7 @@ extern "C" {
|
|||||||
sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE), \
|
sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE), \
|
||||||
NULL, \
|
NULL, \
|
||||||
sizeof(tname), \
|
sizeof(tname), \
|
||||||
#tname \
|
#tname ASN1_ITEM_end(tname)
|
||||||
ASN1_ITEM_end(tname)
|
|
||||||
|
|
||||||
# define ASN1_BROKEN_SEQUENCE_END(stname) ASN1_SEQUENCE_END_ref(stname, stname)
|
|
||||||
# define static_ASN1_BROKEN_SEQUENCE_END(stname) \
|
|
||||||
static_ASN1_SEQUENCE_END_ref(stname, stname)
|
|
||||||
|
|
||||||
#define ASN1_SEQUENCE_END_enc(stname, tname) ASN1_SEQUENCE_END_ref(stname, tname)
|
#define ASN1_SEQUENCE_END_enc(stname, tname) ASN1_SEQUENCE_END_ref(stname, tname)
|
||||||
|
|
||||||
@@ -208,8 +245,7 @@ extern "C" {
|
|||||||
sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE), \
|
sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE), \
|
||||||
&tname##_aux, \
|
&tname##_aux, \
|
||||||
sizeof(stname), \
|
sizeof(stname), \
|
||||||
#tname \
|
#tname ASN1_ITEM_end(tname)
|
||||||
ASN1_ITEM_end(tname)
|
|
||||||
#define static_ASN1_SEQUENCE_END_ref(stname, tname) \
|
#define static_ASN1_SEQUENCE_END_ref(stname, tname) \
|
||||||
; \
|
; \
|
||||||
static_ASN1_ITEM_start(tname) \
|
static_ASN1_ITEM_start(tname) \
|
||||||
@@ -219,8 +255,7 @@ extern "C" {
|
|||||||
sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE), \
|
sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE), \
|
||||||
&tname##_aux, \
|
&tname##_aux, \
|
||||||
sizeof(stname), \
|
sizeof(stname), \
|
||||||
#stname \
|
#stname ASN1_ITEM_end(tname)
|
||||||
ASN1_ITEM_end(tname)
|
|
||||||
|
|
||||||
#define ASN1_NDEF_SEQUENCE_END_cb(stname, tname) \
|
#define ASN1_NDEF_SEQUENCE_END_cb(stname, tname) \
|
||||||
; \
|
; \
|
||||||
@@ -231,8 +266,7 @@ extern "C" {
|
|||||||
sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE), \
|
sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE), \
|
||||||
&tname##_aux, \
|
&tname##_aux, \
|
||||||
sizeof(stname), \
|
sizeof(stname), \
|
||||||
#stname \
|
#stname ASN1_ITEM_end(tname)
|
||||||
ASN1_ITEM_end(tname)
|
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* This pair helps declare a CHOICE type. We can do:
|
* This pair helps declare a CHOICE type. We can do:
|
||||||
@@ -261,7 +295,7 @@ extern "C" {
|
|||||||
static const ASN1_TEMPLATE tname##_ch_tt[]
|
static const ASN1_TEMPLATE tname##_ch_tt[]
|
||||||
|
|
||||||
#define ASN1_CHOICE_cb(tname, cb) \
|
#define ASN1_CHOICE_cb(tname, cb) \
|
||||||
static const ASN1_AUX tname##_aux = {NULL, 0, 0, 0, cb, 0}; \
|
static const ASN1_AUX tname##_aux = { NULL, 0, 0, 0, cb, 0, NULL }; \
|
||||||
ASN1_CHOICE(tname)
|
ASN1_CHOICE(tname)
|
||||||
|
|
||||||
#define ASN1_CHOICE_END(stname) ASN1_CHOICE_END_name(stname, stname)
|
#define ASN1_CHOICE_END(stname) ASN1_CHOICE_END_name(stname, stname)
|
||||||
@@ -281,8 +315,7 @@ extern "C" {
|
|||||||
sizeof(tname##_ch_tt) / sizeof(ASN1_TEMPLATE), \
|
sizeof(tname##_ch_tt) / sizeof(ASN1_TEMPLATE), \
|
||||||
NULL, \
|
NULL, \
|
||||||
sizeof(stname), \
|
sizeof(stname), \
|
||||||
#stname \
|
#stname ASN1_ITEM_end(tname)
|
||||||
ASN1_ITEM_end(tname)
|
|
||||||
|
|
||||||
#define static_ASN1_CHOICE_END_selector(stname, tname, selname) \
|
#define static_ASN1_CHOICE_END_selector(stname, tname, selname) \
|
||||||
; \
|
; \
|
||||||
@@ -293,8 +326,7 @@ extern "C" {
|
|||||||
sizeof(tname##_ch_tt) / sizeof(ASN1_TEMPLATE), \
|
sizeof(tname##_ch_tt) / sizeof(ASN1_TEMPLATE), \
|
||||||
NULL, \
|
NULL, \
|
||||||
sizeof(stname), \
|
sizeof(stname), \
|
||||||
#stname \
|
#stname ASN1_ITEM_end(tname)
|
||||||
ASN1_ITEM_end(tname)
|
|
||||||
|
|
||||||
#define ASN1_CHOICE_END_cb(stname, tname, selname) \
|
#define ASN1_CHOICE_END_cb(stname, tname, selname) \
|
||||||
; \
|
; \
|
||||||
@@ -305,14 +337,14 @@ extern "C" {
|
|||||||
sizeof(tname##_ch_tt) / sizeof(ASN1_TEMPLATE), \
|
sizeof(tname##_ch_tt) / sizeof(ASN1_TEMPLATE), \
|
||||||
&tname##_aux, \
|
&tname##_aux, \
|
||||||
sizeof(stname), \
|
sizeof(stname), \
|
||||||
#stname \
|
#stname ASN1_ITEM_end(tname)
|
||||||
ASN1_ITEM_end(tname)
|
|
||||||
|
|
||||||
/* This helps with the template wrapper form of ASN1_ITEM */
|
/* This helps with the template wrapper form of ASN1_ITEM */
|
||||||
|
|
||||||
#define ASN1_EX_TEMPLATE_TYPE(flags, tag, name, type) { \
|
#define ASN1_EX_TEMPLATE_TYPE(flags, tag, name, type) { \
|
||||||
(flags), (tag), 0, \
|
(flags), (tag), 0, \
|
||||||
#name, ASN1_ITEM_ref(type) }
|
#name, ASN1_ITEM_ref(type) \
|
||||||
|
}
|
||||||
|
|
||||||
/* These help with SEQUENCE or CHOICE components */
|
/* These help with SEQUENCE or CHOICE components */
|
||||||
|
|
||||||
@@ -320,7 +352,8 @@ extern "C" {
|
|||||||
|
|
||||||
#define ASN1_EX_TYPE(flags, tag, stname, field, type) { \
|
#define ASN1_EX_TYPE(flags, tag, stname, field, type) { \
|
||||||
(flags), (tag), offsetof(stname, field), \
|
(flags), (tag), offsetof(stname, field), \
|
||||||
#field, ASN1_ITEM_ref(type) }
|
#field, ASN1_ITEM_ref(type) \
|
||||||
|
}
|
||||||
|
|
||||||
/* implicit and explicit helper macros */
|
/* implicit and explicit helper macros */
|
||||||
|
|
||||||
@@ -332,13 +365,9 @@ extern "C" {
|
|||||||
|
|
||||||
/* Any defined by macros: the field used is in the table itself */
|
/* Any defined by macros: the field used is in the table itself */
|
||||||
|
|
||||||
# ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION
|
|
||||||
# define ASN1_ADB_OBJECT(tblname) { ASN1_TFLG_ADB_OID, -1, 0, #tblname, (const ASN1_ITEM *)&(tblname##_adb) }
|
|
||||||
# define ASN1_ADB_INTEGER(tblname) { ASN1_TFLG_ADB_INT, -1, 0, #tblname, (const ASN1_ITEM *)&(tblname##_adb) }
|
|
||||||
# else
|
|
||||||
#define ASN1_ADB_OBJECT(tblname) { ASN1_TFLG_ADB_OID, -1, 0, #tblname, tblname##_adb }
|
#define ASN1_ADB_OBJECT(tblname) { ASN1_TFLG_ADB_OID, -1, 0, #tblname, tblname##_adb }
|
||||||
#define ASN1_ADB_INTEGER(tblname) { ASN1_TFLG_ADB_INT, -1, 0, #tblname, tblname##_adb }
|
#define ASN1_ADB_INTEGER(tblname) { ASN1_TFLG_ADB_INT, -1, 0, #tblname, tblname##_adb }
|
||||||
# endif
|
|
||||||
/* Plain simple type */
|
/* Plain simple type */
|
||||||
#define ASN1_SIMPLE(stname, field, type) ASN1_EX_TYPE(0, 0, stname, field, type)
|
#define ASN1_SIMPLE(stname, field, type) ASN1_EX_TYPE(0, 0, stname, field, type)
|
||||||
/* Embedded simple type */
|
/* Embedded simple type */
|
||||||
@@ -418,28 +447,11 @@ extern "C" {
|
|||||||
#define ASN1_ADB(name) \
|
#define ASN1_ADB(name) \
|
||||||
static const ASN1_ADB_TABLE name##_adbtbl[]
|
static const ASN1_ADB_TABLE name##_adbtbl[]
|
||||||
|
|
||||||
# ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION
|
|
||||||
|
|
||||||
# define ASN1_ADB_END(name, flags, field, adb_cb, def, none) \
|
|
||||||
;\
|
|
||||||
static const ASN1_ADB name##_adb = {\
|
|
||||||
flags,\
|
|
||||||
offsetof(name, field),\
|
|
||||||
adb_cb,\
|
|
||||||
name##_adbtbl,\
|
|
||||||
sizeof(name##_adbtbl) / sizeof(ASN1_ADB_TABLE),\
|
|
||||||
def,\
|
|
||||||
none\
|
|
||||||
}
|
|
||||||
|
|
||||||
# else
|
|
||||||
|
|
||||||
#define ASN1_ADB_END(name, flags, field, adb_cb, def, none) \
|
#define ASN1_ADB_END(name, flags, field, adb_cb, def, none) \
|
||||||
; \
|
; \
|
||||||
static const ASN1_ITEM *name##_adb(void) \
|
static const ASN1_ITEM *name##_adb(void) \
|
||||||
{ \
|
{ \
|
||||||
static const ASN1_ADB internal_adb = \
|
static const ASN1_ADB internal_adb = { \
|
||||||
{\
|
|
||||||
flags, \
|
flags, \
|
||||||
offsetof(name, field), \
|
offsetof(name, field), \
|
||||||
adb_cb, \
|
adb_cb, \
|
||||||
@@ -452,8 +464,6 @@ extern "C" {
|
|||||||
} \
|
} \
|
||||||
void dummy_function(void)
|
void dummy_function(void)
|
||||||
|
|
||||||
# endif
|
|
||||||
|
|
||||||
#define ADB_ENTRY(val, template) { val, template }
|
#define ADB_ENTRY(val, template) { val, template }
|
||||||
|
|
||||||
#define ASN1_ADB_TEMPLATE(name) \
|
#define ASN1_ADB_TEMPLATE(name) \
|
||||||
@@ -584,64 +594,12 @@ struct ASN1_ITEM_st {
|
|||||||
const ASN1_TEMPLATE *templates; /* If SEQUENCE or CHOICE this contains
|
const ASN1_TEMPLATE *templates; /* If SEQUENCE or CHOICE this contains
|
||||||
* the contents */
|
* the contents */
|
||||||
long tcount; /* Number of templates if SEQUENCE or CHOICE */
|
long tcount; /* Number of templates if SEQUENCE or CHOICE */
|
||||||
const void *funcs; /* functions that handle this type */
|
const void *funcs; /* further data and type-specific functions */
|
||||||
|
/* funcs can be ASN1_PRIMITIVE_FUNCS*, ASN1_EXTERN_FUNCS*, or ASN1_AUX* */
|
||||||
long size; /* Structure size (usually) */
|
long size; /* Structure size (usually) */
|
||||||
const char *sname; /* Structure name */
|
const char *sname; /* Structure name */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*-
|
|
||||||
* These are values for the itype field and
|
|
||||||
* determine how the type is interpreted.
|
|
||||||
*
|
|
||||||
* For PRIMITIVE types the underlying type
|
|
||||||
* determines the behaviour if items is NULL.
|
|
||||||
*
|
|
||||||
* Otherwise templates must contain a single
|
|
||||||
* template and the type is treated in the
|
|
||||||
* same way as the type specified in the template.
|
|
||||||
*
|
|
||||||
* For SEQUENCE types the templates field points
|
|
||||||
* to the members, the size field is the
|
|
||||||
* structure size.
|
|
||||||
*
|
|
||||||
* For CHOICE types the templates field points
|
|
||||||
* to each possible member (typically a union)
|
|
||||||
* and the 'size' field is the offset of the
|
|
||||||
* selector.
|
|
||||||
*
|
|
||||||
* The 'funcs' field is used for application
|
|
||||||
* specific functions.
|
|
||||||
*
|
|
||||||
* The EXTERN type uses a new style d2i/i2d.
|
|
||||||
* The new style should be used where possible
|
|
||||||
* because it avoids things like the d2i IMPLICIT
|
|
||||||
* hack.
|
|
||||||
*
|
|
||||||
* MSTRING is a multiple string type, it is used
|
|
||||||
* for a CHOICE of character strings where the
|
|
||||||
* actual strings all occupy an ASN1_STRING
|
|
||||||
* structure. In this case the 'utype' field
|
|
||||||
* has a special meaning, it is used as a mask
|
|
||||||
* of acceptable types using the B_ASN1 constants.
|
|
||||||
*
|
|
||||||
* NDEF_SEQUENCE is the same as SEQUENCE except
|
|
||||||
* that it will use indefinite length constructed
|
|
||||||
* encoding if requested.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
# define ASN1_ITYPE_PRIMITIVE 0x0
|
|
||||||
|
|
||||||
# define ASN1_ITYPE_SEQUENCE 0x1
|
|
||||||
|
|
||||||
# define ASN1_ITYPE_CHOICE 0x2
|
|
||||||
|
|
||||||
# define ASN1_ITYPE_EXTERN 0x4
|
|
||||||
|
|
||||||
# define ASN1_ITYPE_MSTRING 0x5
|
|
||||||
|
|
||||||
# define ASN1_ITYPE_NDEF_SEQUENCE 0x6
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Cache for ASN1 tag and length, so we don't keep re-reading it for things
|
* Cache for ASN1 tag and length, so we don't keep re-reading it for things
|
||||||
* like CHOICE
|
* like CHOICE
|
||||||
@@ -661,21 +619,27 @@ typedef int ASN1_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
|
|||||||
const ASN1_ITEM *it, int tag, int aclass, char opt,
|
const ASN1_ITEM *it, int tag, int aclass, char opt,
|
||||||
ASN1_TLC *ctx);
|
ASN1_TLC *ctx);
|
||||||
|
|
||||||
typedef int ASN1_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
|
typedef int ASN1_ex_d2i_ex(ASN1_VALUE **pval, const unsigned char **in, long len,
|
||||||
|
const ASN1_ITEM *it, int tag, int aclass, char opt,
|
||||||
|
ASN1_TLC *ctx, OSSL_LIB_CTX *libctx,
|
||||||
|
const char *propq);
|
||||||
|
typedef int ASN1_ex_i2d(const ASN1_VALUE **pval, unsigned char **out,
|
||||||
const ASN1_ITEM *it, int tag, int aclass);
|
const ASN1_ITEM *it, int tag, int aclass);
|
||||||
typedef int ASN1_ex_new_func(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
typedef int ASN1_ex_new_func(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||||
|
typedef int ASN1_ex_new_ex_func(ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||||
|
OSSL_LIB_CTX *libctx, const char *propq);
|
||||||
typedef void ASN1_ex_free_func(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
typedef void ASN1_ex_free_func(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||||
|
|
||||||
typedef int ASN1_ex_print_func(BIO *out, ASN1_VALUE **pval,
|
typedef int ASN1_ex_print_func(BIO *out, const ASN1_VALUE **pval,
|
||||||
int indent, const char *fname,
|
int indent, const char *fname,
|
||||||
const ASN1_PCTX *pctx);
|
const ASN1_PCTX *pctx);
|
||||||
|
|
||||||
typedef int ASN1_primitive_i2c(ASN1_VALUE **pval, unsigned char *cont,
|
typedef int ASN1_primitive_i2c(const ASN1_VALUE **pval, unsigned char *cont,
|
||||||
int *putype, const ASN1_ITEM *it);
|
int *putype, const ASN1_ITEM *it);
|
||||||
typedef int ASN1_primitive_c2i(ASN1_VALUE **pval, const unsigned char *cont,
|
typedef int ASN1_primitive_c2i(ASN1_VALUE **pval, const unsigned char *cont,
|
||||||
int len, int utype, char *free_cont,
|
int len, int utype, char *free_cont,
|
||||||
const ASN1_ITEM *it);
|
const ASN1_ITEM *it);
|
||||||
typedef int ASN1_primitive_print(BIO *out, ASN1_VALUE **pval,
|
typedef int ASN1_primitive_print(BIO *out, const ASN1_VALUE **pval,
|
||||||
const ASN1_ITEM *it, int indent,
|
const ASN1_ITEM *it, int indent,
|
||||||
const ASN1_PCTX *pctx);
|
const ASN1_PCTX *pctx);
|
||||||
|
|
||||||
@@ -687,6 +651,8 @@ typedef struct ASN1_EXTERN_FUNCS_st {
|
|||||||
ASN1_ex_d2i *asn1_ex_d2i;
|
ASN1_ex_d2i *asn1_ex_d2i;
|
||||||
ASN1_ex_i2d *asn1_ex_i2d;
|
ASN1_ex_i2d *asn1_ex_i2d;
|
||||||
ASN1_ex_print_func *asn1_ex_print;
|
ASN1_ex_print_func *asn1_ex_print;
|
||||||
|
ASN1_ex_new_ex_func *asn1_ex_new_ex;
|
||||||
|
ASN1_ex_d2i_ex *asn1_ex_d2i_ex;
|
||||||
} ASN1_EXTERN_FUNCS;
|
} ASN1_EXTERN_FUNCS;
|
||||||
|
|
||||||
typedef struct ASN1_PRIMITIVE_FUNCS_st {
|
typedef struct ASN1_PRIMITIVE_FUNCS_st {
|
||||||
@@ -711,18 +677,25 @@ typedef struct ASN1_PRIMITIVE_FUNCS_st {
|
|||||||
* error has occurred and the main operation should be abandoned. If major
|
* error has occurred and the main operation should be abandoned. If major
|
||||||
* changes in the default behaviour are required then an external type is
|
* changes in the default behaviour are required then an external type is
|
||||||
* more appropriate.
|
* more appropriate.
|
||||||
|
* For the operations ASN1_OP_I2D_PRE, ASN1_OP_I2D_POST, ASN1_OP_PRINT_PRE, and
|
||||||
|
* ASN1_OP_PRINT_POST, meanwhile a variant of the callback with const parameter
|
||||||
|
* 'in' is provided to make clear statically that its input is not modified. If
|
||||||
|
* and only if this variant is in use the flag ASN1_AFLG_CONST_CB must be set.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef int ASN1_aux_cb(int operation, ASN1_VALUE **in, const ASN1_ITEM *it,
|
typedef int ASN1_aux_cb(int operation, ASN1_VALUE **in, const ASN1_ITEM *it,
|
||||||
void *exarg);
|
void *exarg);
|
||||||
|
typedef int ASN1_aux_const_cb(int operation, const ASN1_VALUE **in,
|
||||||
|
const ASN1_ITEM *it, void *exarg);
|
||||||
|
|
||||||
typedef struct ASN1_AUX_st {
|
typedef struct ASN1_AUX_st {
|
||||||
void *app_data;
|
void *app_data;
|
||||||
int flags;
|
int flags;
|
||||||
int ref_offset; /* Offset of reference value */
|
int ref_offset; /* Offset of reference value */
|
||||||
int ref_lock; /* Lock type to use */
|
int ref_lock; /* Offset of lock value */
|
||||||
ASN1_aux_cb *asn1_cb;
|
ASN1_aux_cb *asn1_cb;
|
||||||
int enc_offset; /* Offset of ASN1_ENCODING structure */
|
int enc_offset; /* Offset of ASN1_ENCODING structure */
|
||||||
|
ASN1_aux_const_cb *asn1_const_cb; /* for ASN1_OP_I2D_ and ASN1_OP_PRINT_ */
|
||||||
} ASN1_AUX;
|
} ASN1_AUX;
|
||||||
|
|
||||||
/* For print related callbacks exarg points to this structure */
|
/* For print related callbacks exarg points to this structure */
|
||||||
@@ -750,6 +723,8 @@ typedef struct ASN1_STREAM_ARG_st {
|
|||||||
#define ASN1_AFLG_ENCODING 2
|
#define ASN1_AFLG_ENCODING 2
|
||||||
/* The Sequence length is invalid */
|
/* The Sequence length is invalid */
|
||||||
#define ASN1_AFLG_BROKEN 4
|
#define ASN1_AFLG_BROKEN 4
|
||||||
|
/* Use the new asn1_const_cb */
|
||||||
|
#define ASN1_AFLG_CONST_CB 8
|
||||||
|
|
||||||
/* operation values for asn1_cb */
|
/* operation values for asn1_cb */
|
||||||
|
|
||||||
@@ -767,19 +742,23 @@ typedef struct ASN1_STREAM_ARG_st {
|
|||||||
#define ASN1_OP_STREAM_POST 11
|
#define ASN1_OP_STREAM_POST 11
|
||||||
#define ASN1_OP_DETACHED_PRE 12
|
#define ASN1_OP_DETACHED_PRE 12
|
||||||
#define ASN1_OP_DETACHED_POST 13
|
#define ASN1_OP_DETACHED_POST 13
|
||||||
|
#define ASN1_OP_DUP_PRE 14
|
||||||
|
#define ASN1_OP_DUP_POST 15
|
||||||
|
#define ASN1_OP_GET0_LIBCTX 16
|
||||||
|
#define ASN1_OP_GET0_PROPQ 17
|
||||||
|
|
||||||
/* Macro to implement a primitive type */
|
/* Macro to implement a primitive type */
|
||||||
#define IMPLEMENT_ASN1_TYPE(stname) IMPLEMENT_ASN1_TYPE_ex(stname, stname, 0)
|
#define IMPLEMENT_ASN1_TYPE(stname) IMPLEMENT_ASN1_TYPE_ex(stname, stname, 0)
|
||||||
#define IMPLEMENT_ASN1_TYPE_ex(itname, vname, ex) \
|
#define IMPLEMENT_ASN1_TYPE_ex(itname, vname, ex) \
|
||||||
ASN1_ITEM_start(itname) \
|
ASN1_ITEM_start(itname) \
|
||||||
ASN1_ITYPE_PRIMITIVE, V_##vname, NULL, 0, NULL, ex, #itname \
|
ASN1_ITYPE_PRIMITIVE, \
|
||||||
ASN1_ITEM_end(itname)
|
V_##vname, NULL, 0, NULL, ex, #itname ASN1_ITEM_end(itname)
|
||||||
|
|
||||||
/* Macro to implement a multi string type */
|
/* Macro to implement a multi string type */
|
||||||
#define IMPLEMENT_ASN1_MSTRING(itname, mask) \
|
#define IMPLEMENT_ASN1_MSTRING(itname, mask) \
|
||||||
ASN1_ITEM_start(itname) \
|
ASN1_ITEM_start(itname) \
|
||||||
ASN1_ITYPE_MSTRING, mask, NULL, 0, NULL, sizeof(ASN1_STRING), #itname \
|
ASN1_ITYPE_MSTRING, \
|
||||||
ASN1_ITEM_end(itname)
|
mask, NULL, 0, NULL, sizeof(ASN1_STRING), #itname ASN1_ITEM_end(itname)
|
||||||
|
|
||||||
#define IMPLEMENT_EXTERN_ASN1(sname, tag, fptrs) \
|
#define IMPLEMENT_EXTERN_ASN1(sname, tag, fptrs) \
|
||||||
ASN1_ITEM_start(sname) \
|
ASN1_ITEM_start(sname) \
|
||||||
@@ -789,8 +768,7 @@ typedef struct ASN1_STREAM_ARG_st {
|
|||||||
0, \
|
0, \
|
||||||
&fptrs, \
|
&fptrs, \
|
||||||
0, \
|
0, \
|
||||||
#sname \
|
#sname ASN1_ITEM_end(sname)
|
||||||
ASN1_ITEM_end(sname)
|
|
||||||
|
|
||||||
/* Macro to implement standard functions in terms of ASN1_ITEM structures */
|
/* Macro to implement standard functions in terms of ASN1_ITEM structures */
|
||||||
|
|
||||||
@@ -836,15 +814,15 @@ typedef struct ASN1_STREAM_ARG_st {
|
|||||||
{ \
|
{ \
|
||||||
return (stname *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, ASN1_ITEM_rptr(itname)); \
|
return (stname *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, ASN1_ITEM_rptr(itname)); \
|
||||||
} \
|
} \
|
||||||
int i2d_##fname(stname *a, unsigned char **out) \
|
int i2d_##fname(const stname *a, unsigned char **out) \
|
||||||
{ \
|
{ \
|
||||||
return ASN1_item_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(itname));\
|
return ASN1_item_i2d((const ASN1_VALUE *)a, out, ASN1_ITEM_rptr(itname)); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define IMPLEMENT_ASN1_NDEF_FUNCTION(stname) \
|
#define IMPLEMENT_ASN1_NDEF_FUNCTION(stname) \
|
||||||
int i2d_##stname##_NDEF(stname *a, unsigned char **out) \
|
int i2d_##stname##_NDEF(const stname *a, unsigned char **out) \
|
||||||
{ \
|
{ \
|
||||||
return ASN1_item_ndef_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(stname));\
|
return ASN1_item_ndef_i2d((const ASN1_VALUE *)a, out, ASN1_ITEM_rptr(stname)); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define IMPLEMENT_STATIC_ASN1_ENCODE_FUNCTIONS(stname) \
|
#define IMPLEMENT_STATIC_ASN1_ENCODE_FUNCTIONS(stname) \
|
||||||
@@ -854,28 +832,14 @@ typedef struct ASN1_STREAM_ARG_st {
|
|||||||
return (stname *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, \
|
return (stname *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, \
|
||||||
ASN1_ITEM_rptr(stname)); \
|
ASN1_ITEM_rptr(stname)); \
|
||||||
} \
|
} \
|
||||||
static int i2d_##stname(stname *a, unsigned char **out) \
|
static int i2d_##stname(const stname *a, unsigned char **out) \
|
||||||
{ \
|
{ \
|
||||||
return ASN1_item_i2d((ASN1_VALUE *)a, out, \
|
return ASN1_item_i2d((const ASN1_VALUE *)a, out, \
|
||||||
ASN1_ITEM_rptr(stname)); \
|
ASN1_ITEM_rptr(stname)); \
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* This includes evil casts to remove const: they will go away when full ASN1
|
|
||||||
* constification is done.
|
|
||||||
*/
|
|
||||||
# define IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(stname, itname, fname) \
|
|
||||||
stname *d2i_##fname(stname **a, const unsigned char **in, long len) \
|
|
||||||
{ \
|
|
||||||
return (stname *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, ASN1_ITEM_rptr(itname));\
|
|
||||||
} \
|
|
||||||
int i2d_##fname(const stname *a, unsigned char **out) \
|
|
||||||
{ \
|
|
||||||
return ASN1_item_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(itname));\
|
|
||||||
}
|
|
||||||
|
|
||||||
#define IMPLEMENT_ASN1_DUP_FUNCTION(stname) \
|
#define IMPLEMENT_ASN1_DUP_FUNCTION(stname) \
|
||||||
stname * stname##_dup(stname *x) \
|
stname *stname##_dup(const stname *x) \
|
||||||
{ \
|
{ \
|
||||||
return ASN1_item_dup(ASN1_ITEM_rptr(stname), x); \
|
return ASN1_item_dup(ASN1_ITEM_rptr(stname), x); \
|
||||||
}
|
}
|
||||||
@@ -884,20 +848,13 @@ typedef struct ASN1_STREAM_ARG_st {
|
|||||||
IMPLEMENT_ASN1_PRINT_FUNCTION_fname(stname, stname, stname)
|
IMPLEMENT_ASN1_PRINT_FUNCTION_fname(stname, stname, stname)
|
||||||
|
|
||||||
#define IMPLEMENT_ASN1_PRINT_FUNCTION_fname(stname, itname, fname) \
|
#define IMPLEMENT_ASN1_PRINT_FUNCTION_fname(stname, itname, fname) \
|
||||||
int fname##_print_ctx(BIO *out, stname *x, int indent, \
|
int fname##_print_ctx(BIO *out, const stname *x, int indent, \
|
||||||
const ASN1_PCTX *pctx) \
|
const ASN1_PCTX *pctx) \
|
||||||
{ \
|
{ \
|
||||||
return ASN1_item_print(out, (ASN1_VALUE *)x, indent, \
|
return ASN1_item_print(out, (const ASN1_VALUE *)x, indent, \
|
||||||
ASN1_ITEM_rptr(itname), pctx); \
|
ASN1_ITEM_rptr(itname), pctx); \
|
||||||
}
|
}
|
||||||
|
|
||||||
# define IMPLEMENT_ASN1_FUNCTIONS_const(name) \
|
|
||||||
IMPLEMENT_ASN1_FUNCTIONS_const_fname(name, name, name)
|
|
||||||
|
|
||||||
# define IMPLEMENT_ASN1_FUNCTIONS_const_fname(stname, itname, fname) \
|
|
||||||
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(stname, itname, fname) \
|
|
||||||
IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname)
|
|
||||||
|
|
||||||
/* external definitions for primitive types */
|
/* external definitions for primitive types */
|
||||||
|
|
||||||
DECLARE_ASN1_ITEM(ASN1_BOOLEAN)
|
DECLARE_ASN1_ITEM(ASN1_BOOLEAN)
|
||||||
@@ -915,7 +872,7 @@ DECLARE_ASN1_ITEM(ZINT64)
|
|||||||
DECLARE_ASN1_ITEM(UINT64)
|
DECLARE_ASN1_ITEM(UINT64)
|
||||||
DECLARE_ASN1_ITEM(ZUINT64)
|
DECLARE_ASN1_ITEM(ZUINT64)
|
||||||
|
|
||||||
# if OPENSSL_API_COMPAT < 0x10200000L
|
#ifndef OPENSSL_NO_DEPRECATED_3_0
|
||||||
/*
|
/*
|
||||||
* LONG and ZLONG are strongly discouraged for use as stored data, as the
|
* LONG and ZLONG are strongly discouraged for use as stored data, as the
|
||||||
* underlying C type (long) differs in size depending on the architecture.
|
* underlying C type (long) differs in size depending on the architecture.
|
||||||
@@ -925,7 +882,35 @@ DECLARE_ASN1_ITEM(LONG)
|
|||||||
DECLARE_ASN1_ITEM(ZLONG)
|
DECLARE_ASN1_ITEM(ZLONG)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DEFINE_STACK_OF(ASN1_VALUE)
|
/* clang-format off */
|
||||||
|
SKM_DEFINE_STACK_OF_INTERNAL(ASN1_VALUE, ASN1_VALUE, ASN1_VALUE)
|
||||||
|
#define sk_ASN1_VALUE_num(sk) OPENSSL_sk_num(ossl_check_const_ASN1_VALUE_sk_type(sk))
|
||||||
|
#define sk_ASN1_VALUE_value(sk, idx) ((ASN1_VALUE *)OPENSSL_sk_value(ossl_check_const_ASN1_VALUE_sk_type(sk), (idx)))
|
||||||
|
#define sk_ASN1_VALUE_new(cmp) ((STACK_OF(ASN1_VALUE) *)OPENSSL_sk_set_cmp_thunks(OPENSSL_sk_new(ossl_check_ASN1_VALUE_compfunc_type(cmp)), sk_ASN1_VALUE_cmpfunc_thunk))
|
||||||
|
#define sk_ASN1_VALUE_new_null() ((STACK_OF(ASN1_VALUE) *)OPENSSL_sk_set_thunks(OPENSSL_sk_new_null(), sk_ASN1_VALUE_freefunc_thunk))
|
||||||
|
#define sk_ASN1_VALUE_new_reserve(cmp, n) ((STACK_OF(ASN1_VALUE) *)OPENSSL_sk_set_cmp_thunks(OPENSSL_sk_new_reserve(ossl_check_ASN1_VALUE_compfunc_type(cmp), (n)), sk_ASN1_VALUE_cmpfunc_thunk))
|
||||||
|
#define sk_ASN1_VALUE_reserve(sk, n) OPENSSL_sk_reserve(ossl_check_ASN1_VALUE_sk_type(sk), (n))
|
||||||
|
#define sk_ASN1_VALUE_free(sk) OPENSSL_sk_free(ossl_check_ASN1_VALUE_sk_type(sk))
|
||||||
|
#define sk_ASN1_VALUE_zero(sk) OPENSSL_sk_zero(ossl_check_ASN1_VALUE_sk_type(sk))
|
||||||
|
#define sk_ASN1_VALUE_delete(sk, i) ((ASN1_VALUE *)OPENSSL_sk_delete(ossl_check_ASN1_VALUE_sk_type(sk), (i)))
|
||||||
|
#define sk_ASN1_VALUE_delete_ptr(sk, ptr) ((ASN1_VALUE *)OPENSSL_sk_delete_ptr(ossl_check_ASN1_VALUE_sk_type(sk), ossl_check_ASN1_VALUE_type(ptr)))
|
||||||
|
#define sk_ASN1_VALUE_push(sk, ptr) OPENSSL_sk_push(ossl_check_ASN1_VALUE_sk_type(sk), ossl_check_ASN1_VALUE_type(ptr))
|
||||||
|
#define sk_ASN1_VALUE_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_ASN1_VALUE_sk_type(sk), ossl_check_ASN1_VALUE_type(ptr))
|
||||||
|
#define sk_ASN1_VALUE_pop(sk) ((ASN1_VALUE *)OPENSSL_sk_pop(ossl_check_ASN1_VALUE_sk_type(sk)))
|
||||||
|
#define sk_ASN1_VALUE_shift(sk) ((ASN1_VALUE *)OPENSSL_sk_shift(ossl_check_ASN1_VALUE_sk_type(sk)))
|
||||||
|
#define sk_ASN1_VALUE_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_ASN1_VALUE_sk_type(sk), ossl_check_ASN1_VALUE_freefunc_type(freefunc))
|
||||||
|
#define sk_ASN1_VALUE_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_ASN1_VALUE_sk_type(sk), ossl_check_ASN1_VALUE_type(ptr), (idx))
|
||||||
|
#define sk_ASN1_VALUE_set(sk, idx, ptr) ((ASN1_VALUE *)OPENSSL_sk_set(ossl_check_ASN1_VALUE_sk_type(sk), (idx), ossl_check_ASN1_VALUE_type(ptr)))
|
||||||
|
#define sk_ASN1_VALUE_find(sk, ptr) OPENSSL_sk_find(ossl_check_ASN1_VALUE_sk_type(sk), ossl_check_ASN1_VALUE_type(ptr))
|
||||||
|
#define sk_ASN1_VALUE_find_ex(sk, ptr) OPENSSL_sk_find_ex(ossl_check_ASN1_VALUE_sk_type(sk), ossl_check_ASN1_VALUE_type(ptr))
|
||||||
|
#define sk_ASN1_VALUE_find_all(sk, ptr, pnum) OPENSSL_sk_find_all(ossl_check_ASN1_VALUE_sk_type(sk), ossl_check_ASN1_VALUE_type(ptr), pnum)
|
||||||
|
#define sk_ASN1_VALUE_sort(sk) OPENSSL_sk_sort(ossl_check_ASN1_VALUE_sk_type(sk))
|
||||||
|
#define sk_ASN1_VALUE_is_sorted(sk) OPENSSL_sk_is_sorted(ossl_check_const_ASN1_VALUE_sk_type(sk))
|
||||||
|
#define sk_ASN1_VALUE_dup(sk) ((STACK_OF(ASN1_VALUE) *)OPENSSL_sk_dup(ossl_check_const_ASN1_VALUE_sk_type(sk)))
|
||||||
|
#define sk_ASN1_VALUE_deep_copy(sk, copyfunc, freefunc) ((STACK_OF(ASN1_VALUE) *)OPENSSL_sk_deep_copy(ossl_check_const_ASN1_VALUE_sk_type(sk), ossl_check_ASN1_VALUE_copyfunc_type(copyfunc), ossl_check_ASN1_VALUE_freefunc_type(freefunc)))
|
||||||
|
#define sk_ASN1_VALUE_set_cmp_func(sk, cmp) ((sk_ASN1_VALUE_compfunc)OPENSSL_sk_set_cmp_func(ossl_check_ASN1_VALUE_sk_type(sk), ossl_check_ASN1_VALUE_compfunc_type(cmp)))
|
||||||
|
|
||||||
|
/* clang-format on */
|
||||||
|
|
||||||
/* Functions used internally by the ASN1 code */
|
/* Functions used internally by the ASN1 code */
|
||||||
|
|
||||||
@@ -936,9 +921,14 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
|
|||||||
const ASN1_ITEM *it, int tag, int aclass, char opt,
|
const ASN1_ITEM *it, int tag, int aclass, char opt,
|
||||||
ASN1_TLC *ctx);
|
ASN1_TLC *ctx);
|
||||||
|
|
||||||
int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
|
int ASN1_item_ex_i2d(const ASN1_VALUE **pval, unsigned char **out,
|
||||||
const ASN1_ITEM *it, int tag, int aclass);
|
const ASN1_ITEM *it, int tag, int aclass);
|
||||||
|
|
||||||
|
/* Legacy compatibility */
|
||||||
|
#define IMPLEMENT_ASN1_FUNCTIONS_const(name) IMPLEMENT_ASN1_FUNCTIONS(name)
|
||||||
|
#define IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(stname, itname, fname) \
|
||||||
|
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(stname, itname, fname)
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -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
|
* this file except in compliance with the License. You can obtain a copy
|
||||||
* in the file LICENSE in the source distribution or at
|
* in the file LICENSE in the source distribution or at
|
||||||
* https://www.openssl.org/source/license.html
|
* https://www.openssl.org/source/license.html
|
||||||
@@ -9,8 +9,14 @@
|
|||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#ifndef 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
|
#define HEADER_ASYNC_H
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
#if defined(BASETYPES) || defined(_WINDEF_H)
|
#if defined(BASETYPES) || defined(_WINDEF_H)
|
||||||
@@ -24,19 +30,24 @@
|
|||||||
#endif
|
#endif
|
||||||
#include <openssl/asyncerr.h>
|
#include <openssl/asyncerr.h>
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct async_job_st ASYNC_JOB;
|
typedef struct async_job_st ASYNC_JOB;
|
||||||
typedef struct async_wait_ctx_st ASYNC_WAIT_CTX;
|
typedef struct async_wait_ctx_st ASYNC_WAIT_CTX;
|
||||||
|
typedef int (*ASYNC_callback_fn)(void *arg);
|
||||||
|
|
||||||
#define ASYNC_ERR 0
|
#define ASYNC_ERR 0
|
||||||
#define ASYNC_NO_JOBS 1
|
#define ASYNC_NO_JOBS 1
|
||||||
#define ASYNC_PAUSE 2
|
#define ASYNC_PAUSE 2
|
||||||
#define ASYNC_FINISH 3
|
#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);
|
int ASYNC_init_thread(size_t max_size, size_t init_size);
|
||||||
void ASYNC_cleanup_thread(void);
|
void ASYNC_cleanup_thread(void);
|
||||||
|
|
||||||
@@ -52,6 +63,14 @@ 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,
|
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,
|
int ASYNC_WAIT_CTX_get_changed_fds(ASYNC_WAIT_CTX *ctx, OSSL_ASYNC_FD *addfd,
|
||||||
size_t *numaddfds, OSSL_ASYNC_FD *delfd,
|
size_t *numaddfds, OSSL_ASYNC_FD *delfd,
|
||||||
size_t *numdelfds);
|
size_t *numdelfds);
|
||||||
@@ -60,6 +79,14 @@ int ASYNC_WAIT_CTX_clear_fd(ASYNC_WAIT_CTX *ctx, const void *key);
|
|||||||
|
|
||||||
int ASYNC_is_capable(void);
|
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 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);
|
int ASYNC_pause_job(void);
|
||||||
@@ -69,7 +96,6 @@ ASYNC_WAIT_CTX *ASYNC_get_wait_ctx(ASYNC_JOB *job);
|
|||||||
void ASYNC_block_pause(void);
|
void ASYNC_block_pause(void);
|
||||||
void ASYNC_unblock_pause(void);
|
void ASYNC_unblock_pause(void);
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,35 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
* Generated by util/mkerr.pl DO NOT EDIT
|
* 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
|
* this file except in compliance with the License. You can obtain a copy
|
||||||
* in the file LICENSE in the source distribution or at
|
* in the file LICENSE in the source distribution or at
|
||||||
* https://www.openssl.org/source/license.html
|
* https://www.openssl.org/source/license.html
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef HEADER_ASYNCERR_H
|
#ifndef OPENSSL_ASYNCERR_H
|
||||||
# define HEADER_ASYNCERR_H
|
#define OPENSSL_ASYNCERR_H
|
||||||
|
#pragma once
|
||||||
|
|
||||||
# ifndef HEADER_SYMHACKS_H
|
#include <openssl/opensslconf.h>
|
||||||
#include <openssl/symhacks.h>
|
#include <openssl/symhacks.h>
|
||||||
# endif
|
#include <openssl/cryptoerr_legacy.h>
|
||||||
|
|
||||||
# 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
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ASYNC reason codes.
|
* ASYNC reason codes.
|
||||||
|
|||||||
@@ -1,14 +1,26 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
|
* WARNING: do not edit!
|
||||||
|
* Generated by Makefile from include/openssl/bio.h.in
|
||||||
*
|
*
|
||||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
* Copyright 1995-2026 The OpenSSL Project Authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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
|
* this file except in compliance with the License. You can obtain a copy
|
||||||
* in the file LICENSE in the source distribution or at
|
* in the file LICENSE in the source distribution or at
|
||||||
* https://www.openssl.org/source/license.html
|
* https://www.openssl.org/source/license.html
|
||||||
*/
|
*/
|
||||||
|
/* clang-format off */
|
||||||
|
|
||||||
#ifndef HEADER_BIO_H
|
/* clang-format on */
|
||||||
|
|
||||||
|
#ifndef OPENSSL_BIO_H
|
||||||
|
#define OPENSSL_BIO_H
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <openssl/macros.h>
|
||||||
|
#ifndef OPENSSL_NO_DEPRECATED_3_0
|
||||||
#define HEADER_BIO_H
|
#define HEADER_BIO_H
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <openssl/e_os2.h>
|
#include <openssl/e_os2.h>
|
||||||
|
|
||||||
@@ -19,6 +31,7 @@
|
|||||||
|
|
||||||
#include <openssl/crypto.h>
|
#include <openssl/crypto.h>
|
||||||
#include <openssl/bioerr.h>
|
#include <openssl/bioerr.h>
|
||||||
|
#include <openssl/core.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -55,8 +68,14 @@ extern "C" {
|
|||||||
#ifndef OPENSSL_NO_SCTP
|
#ifndef OPENSSL_NO_SCTP
|
||||||
#define BIO_TYPE_DGRAM_SCTP (24 | BIO_TYPE_SOURCE_SINK | BIO_TYPE_DESCRIPTOR)
|
#define BIO_TYPE_DGRAM_SCTP (24 | BIO_TYPE_SOURCE_SINK | BIO_TYPE_DESCRIPTOR)
|
||||||
#endif
|
#endif
|
||||||
|
#define BIO_TYPE_CORE_TO_PROV (25 | BIO_TYPE_SOURCE_SINK)
|
||||||
|
#define BIO_TYPE_DGRAM_PAIR (26 | BIO_TYPE_SOURCE_SINK)
|
||||||
|
#define BIO_TYPE_DGRAM_MEM (27 | BIO_TYPE_SOURCE_SINK)
|
||||||
|
|
||||||
|
/* Custom type starting index returned by BIO_get_new_index() */
|
||||||
#define BIO_TYPE_START 128
|
#define BIO_TYPE_START 128
|
||||||
|
/* Custom type maximum index that can be returned by BIO_get_new_index() */
|
||||||
|
#define BIO_TYPE_MASK 0xFF
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* BIO_FILENAME_READ|BIO_CLOSE to open or close on free.
|
* BIO_FILENAME_READ|BIO_CLOSE to open or close on free.
|
||||||
@@ -89,7 +108,7 @@ extern "C" {
|
|||||||
|
|
||||||
/* dgram BIO stuff */
|
/* dgram BIO stuff */
|
||||||
#define BIO_CTRL_DGRAM_CONNECT 31 /* BIO dgram special */
|
#define BIO_CTRL_DGRAM_CONNECT 31 /* BIO dgram special */
|
||||||
# define BIO_CTRL_DGRAM_SET_CONNECTED 32/* allow for an externally connected
|
#define BIO_CTRL_DGRAM_SET_CONNECTED 32 /* allow for an externally connected \
|
||||||
* socket to be passed in */
|
* socket to be passed in */
|
||||||
#define BIO_CTRL_DGRAM_SET_RECV_TIMEOUT 33 /* setsockopt, essentially */
|
#define BIO_CTRL_DGRAM_SET_RECV_TIMEOUT 33 /* setsockopt, essentially */
|
||||||
#define BIO_CTRL_DGRAM_GET_RECV_TIMEOUT 34 /* getsockopt, essentially */
|
#define BIO_CTRL_DGRAM_GET_RECV_TIMEOUT 34 /* getsockopt, essentially */
|
||||||
@@ -97,7 +116,7 @@ extern "C" {
|
|||||||
#define BIO_CTRL_DGRAM_GET_SEND_TIMEOUT 36 /* getsockopt, essentially */
|
#define BIO_CTRL_DGRAM_GET_SEND_TIMEOUT 36 /* getsockopt, essentially */
|
||||||
|
|
||||||
#define BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP 37 /* flag whether the last */
|
#define BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP 37 /* flag whether the last */
|
||||||
# define BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP 38/* I/O operation tiemd out */
|
#define BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP 38 /* I/O operation timed out */
|
||||||
|
|
||||||
/* #ifdef IP_MTU_DISCOVER */
|
/* #ifdef IP_MTU_DISCOVER */
|
||||||
#define BIO_CTRL_DGRAM_MTU_DISCOVER 39 /* set DF bit on egress packets */
|
#define BIO_CTRL_DGRAM_MTU_DISCOVER 39 /* set DF bit on egress packets */
|
||||||
@@ -106,18 +125,18 @@ extern "C" {
|
|||||||
#define BIO_CTRL_DGRAM_QUERY_MTU 40 /* as kernel for current MTU */
|
#define BIO_CTRL_DGRAM_QUERY_MTU 40 /* as kernel for current MTU */
|
||||||
#define BIO_CTRL_DGRAM_GET_FALLBACK_MTU 47
|
#define BIO_CTRL_DGRAM_GET_FALLBACK_MTU 47
|
||||||
#define BIO_CTRL_DGRAM_GET_MTU 41 /* get cached value for MTU */
|
#define BIO_CTRL_DGRAM_GET_MTU 41 /* get cached value for MTU */
|
||||||
# define BIO_CTRL_DGRAM_SET_MTU 42/* set cached value for MTU.
|
#define BIO_CTRL_DGRAM_SET_MTU 42 /* set cached value for MTU. \
|
||||||
* want to use this if asking
|
* want to use this if asking \
|
||||||
* the kernel fails */
|
* the kernel fails */
|
||||||
|
|
||||||
# define BIO_CTRL_DGRAM_MTU_EXCEEDED 43/* check whether the MTU was
|
#define BIO_CTRL_DGRAM_MTU_EXCEEDED 43 /* check whether the MTU was \
|
||||||
* exceed in the previous write
|
* exceed in the previous write \
|
||||||
* operation */
|
* operation */
|
||||||
|
|
||||||
#define BIO_CTRL_DGRAM_GET_PEER 46
|
#define BIO_CTRL_DGRAM_GET_PEER 46
|
||||||
#define BIO_CTRL_DGRAM_SET_PEER 44 /* Destination for the data */
|
#define BIO_CTRL_DGRAM_SET_PEER 44 /* Destination for the data */
|
||||||
|
|
||||||
# define BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT 45/* Next DTLS handshake timeout
|
#define BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT 45 /* Next DTLS handshake timeout \
|
||||||
* to adjust socket timeouts */
|
* to adjust socket timeouts */
|
||||||
#define BIO_CTRL_DGRAM_SET_DONT_FRAG 48
|
#define BIO_CTRL_DGRAM_SET_DONT_FRAG 48
|
||||||
|
|
||||||
@@ -141,6 +160,59 @@ extern "C" {
|
|||||||
|
|
||||||
#define BIO_CTRL_DGRAM_SET_PEEK_MODE 71
|
#define BIO_CTRL_DGRAM_SET_PEEK_MODE 71
|
||||||
|
|
||||||
|
/*
|
||||||
|
* internal BIO:
|
||||||
|
* # define BIO_CTRL_SET_KTLS_SEND 72
|
||||||
|
* # define BIO_CTRL_SET_KTLS_SEND_CTRL_MSG 74
|
||||||
|
* # define BIO_CTRL_CLEAR_KTLS_CTRL_MSG 75
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define BIO_CTRL_GET_KTLS_SEND 73
|
||||||
|
#define BIO_CTRL_GET_KTLS_RECV 76
|
||||||
|
|
||||||
|
#define BIO_CTRL_DGRAM_SCTP_WAIT_FOR_DRY 77
|
||||||
|
#define BIO_CTRL_DGRAM_SCTP_MSG_WAITING 78
|
||||||
|
|
||||||
|
/* BIO_f_prefix controls */
|
||||||
|
#define BIO_CTRL_SET_PREFIX 79
|
||||||
|
#define BIO_CTRL_SET_INDENT 80
|
||||||
|
#define BIO_CTRL_GET_INDENT 81
|
||||||
|
|
||||||
|
#define BIO_CTRL_DGRAM_GET_LOCAL_ADDR_CAP 82
|
||||||
|
#define BIO_CTRL_DGRAM_GET_LOCAL_ADDR_ENABLE 83
|
||||||
|
#define BIO_CTRL_DGRAM_SET_LOCAL_ADDR_ENABLE 84
|
||||||
|
#define BIO_CTRL_DGRAM_GET_EFFECTIVE_CAPS 85
|
||||||
|
#define BIO_CTRL_DGRAM_GET_CAPS 86
|
||||||
|
#define BIO_CTRL_DGRAM_SET_CAPS 87
|
||||||
|
#define BIO_CTRL_DGRAM_GET_NO_TRUNC 88
|
||||||
|
#define BIO_CTRL_DGRAM_SET_NO_TRUNC 89
|
||||||
|
|
||||||
|
/*
|
||||||
|
* internal BIO:
|
||||||
|
* # define BIO_CTRL_SET_KTLS_TX_ZEROCOPY_SENDFILE 90
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define BIO_CTRL_GET_RPOLL_DESCRIPTOR 91
|
||||||
|
#define BIO_CTRL_GET_WPOLL_DESCRIPTOR 92
|
||||||
|
#define BIO_CTRL_DGRAM_DETECT_PEER_ADDR 93
|
||||||
|
#define BIO_CTRL_DGRAM_SET0_LOCAL_ADDR 94
|
||||||
|
|
||||||
|
#define BIO_DGRAM_CAP_NONE 0U
|
||||||
|
#define BIO_DGRAM_CAP_HANDLES_SRC_ADDR (1U << 0)
|
||||||
|
#define BIO_DGRAM_CAP_HANDLES_DST_ADDR (1U << 1)
|
||||||
|
#define BIO_DGRAM_CAP_PROVIDES_SRC_ADDR (1U << 2)
|
||||||
|
#define BIO_DGRAM_CAP_PROVIDES_DST_ADDR (1U << 3)
|
||||||
|
|
||||||
|
#ifndef OPENSSL_NO_KTLS
|
||||||
|
#define BIO_get_ktls_send(b) \
|
||||||
|
(BIO_ctrl(b, BIO_CTRL_GET_KTLS_SEND, 0, NULL) > 0)
|
||||||
|
#define BIO_get_ktls_recv(b) \
|
||||||
|
(BIO_ctrl(b, BIO_CTRL_GET_KTLS_RECV, 0, NULL) > 0)
|
||||||
|
#else
|
||||||
|
#define BIO_get_ktls_send(b) (0)
|
||||||
|
#define BIO_get_ktls_recv(b) (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
/* modifiers */
|
/* modifiers */
|
||||||
#define BIO_FP_READ 0x02
|
#define BIO_FP_READ 0x02
|
||||||
#define BIO_FP_WRITE 0x04
|
#define BIO_FP_WRITE 0x04
|
||||||
@@ -152,14 +224,22 @@ extern "C" {
|
|||||||
#define BIO_FLAGS_IO_SPECIAL 0x04
|
#define BIO_FLAGS_IO_SPECIAL 0x04
|
||||||
#define BIO_FLAGS_RWS (BIO_FLAGS_READ | BIO_FLAGS_WRITE | BIO_FLAGS_IO_SPECIAL)
|
#define BIO_FLAGS_RWS (BIO_FLAGS_READ | BIO_FLAGS_WRITE | BIO_FLAGS_IO_SPECIAL)
|
||||||
#define BIO_FLAGS_SHOULD_RETRY 0x08
|
#define BIO_FLAGS_SHOULD_RETRY 0x08
|
||||||
# ifndef BIO_FLAGS_UPLINK
|
#ifndef OPENSSL_NO_DEPRECATED_3_0
|
||||||
/*
|
/* This #define was replaced by an internal constant and should not be used. */
|
||||||
* "UPLINK" flag denotes file descriptors provided by application. It
|
|
||||||
* defaults to 0, as most platforms don't require UPLINK interface.
|
|
||||||
*/
|
|
||||||
#define BIO_FLAGS_UPLINK 0
|
#define BIO_FLAGS_UPLINK 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* the BIO FLAGS values 0x10 to 0x80 are reserved for internal use */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* BIO FLAGS in the range 0x0100..0x8000 are BIO-type specific.
|
||||||
|
* Their meaning is defined by the particular BIO implementation and
|
||||||
|
* is not shared across different BIO types. The same bit value may
|
||||||
|
* have a different meaning or no meaning at all in other BIOs.
|
||||||
|
* Such flags may be part of the public API or internal to the BIO.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* This is used with base64 BIO */
|
||||||
#define BIO_FLAGS_BASE64_NO_NL 0x100
|
#define BIO_FLAGS_BASE64_NO_NL 0x100
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -223,6 +303,8 @@ void BIO_clear_flags(BIO *b, int flags);
|
|||||||
#define BIO_CB_PUTS 0x04
|
#define BIO_CB_PUTS 0x04
|
||||||
#define BIO_CB_GETS 0x05
|
#define BIO_CB_GETS 0x05
|
||||||
#define BIO_CB_CTRL 0x06
|
#define BIO_CB_CTRL 0x06
|
||||||
|
#define BIO_CB_RECVMMSG 0x07
|
||||||
|
#define BIO_CB_SENDMMSG 0x08
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The callback is called before and after the underling operation, The
|
* The callback is called before and after the underling operation, The
|
||||||
@@ -233,16 +315,23 @@ void BIO_clear_flags(BIO *b, int flags);
|
|||||||
#define BIO_cb_pre(a) (!((a) & BIO_CB_RETURN))
|
#define BIO_cb_pre(a) (!((a) & BIO_CB_RETURN))
|
||||||
#define BIO_cb_post(a) ((a) & BIO_CB_RETURN)
|
#define BIO_cb_post(a) ((a) & BIO_CB_RETURN)
|
||||||
|
|
||||||
|
#ifndef OPENSSL_NO_DEPRECATED_3_0
|
||||||
typedef long (*BIO_callback_fn)(BIO *b, int oper, const char *argp, int argi,
|
typedef long (*BIO_callback_fn)(BIO *b, int oper, const char *argp, int argi,
|
||||||
long argl, long ret);
|
long argl, long ret);
|
||||||
|
OSSL_DEPRECATEDIN_3_0 BIO_callback_fn BIO_get_callback(const BIO *b);
|
||||||
|
OSSL_DEPRECATEDIN_3_0 void BIO_set_callback(BIO *b, BIO_callback_fn callback);
|
||||||
|
OSSL_DEPRECATEDIN_3_0 long BIO_debug_callback(BIO *bio, int cmd,
|
||||||
|
const char *argp, int argi,
|
||||||
|
long argl, long ret);
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef long (*BIO_callback_fn_ex)(BIO *b, int oper, const char *argp,
|
typedef long (*BIO_callback_fn_ex)(BIO *b, int oper, const char *argp,
|
||||||
size_t len, int argi,
|
size_t len, int argi,
|
||||||
long argl, int ret, size_t *processed);
|
long argl, int ret, size_t *processed);
|
||||||
BIO_callback_fn BIO_get_callback(const BIO *b);
|
|
||||||
void BIO_set_callback(BIO *b, BIO_callback_fn callback);
|
|
||||||
|
|
||||||
BIO_callback_fn_ex BIO_get_callback_ex(const BIO *b);
|
BIO_callback_fn_ex BIO_get_callback_ex(const BIO *b);
|
||||||
void BIO_set_callback_ex(BIO *b, BIO_callback_fn_ex callback);
|
void BIO_set_callback_ex(BIO *b, BIO_callback_fn_ex callback);
|
||||||
|
long BIO_debug_callback_ex(BIO *bio, int oper, const char *argp, size_t len,
|
||||||
|
int argi, long argl, int ret, size_t *processed);
|
||||||
|
|
||||||
char *BIO_get_callback_arg(const BIO *b);
|
char *BIO_get_callback_arg(const BIO *b);
|
||||||
void BIO_set_callback_arg(BIO *b, char *arg);
|
void BIO_set_callback_arg(BIO *b, char *arg);
|
||||||
@@ -255,12 +344,43 @@ int BIO_method_type(const BIO *b);
|
|||||||
typedef int BIO_info_cb(BIO *, int, int);
|
typedef int BIO_info_cb(BIO *, int, int);
|
||||||
typedef BIO_info_cb bio_info_cb; /* backward compatibility */
|
typedef BIO_info_cb bio_info_cb; /* backward compatibility */
|
||||||
|
|
||||||
DEFINE_STACK_OF(BIO)
|
/* clang-format off */
|
||||||
|
SKM_DEFINE_STACK_OF_INTERNAL(BIO, BIO, BIO)
|
||||||
|
#define sk_BIO_num(sk) OPENSSL_sk_num(ossl_check_const_BIO_sk_type(sk))
|
||||||
|
#define sk_BIO_value(sk, idx) ((BIO *)OPENSSL_sk_value(ossl_check_const_BIO_sk_type(sk), (idx)))
|
||||||
|
#define sk_BIO_new(cmp) ((STACK_OF(BIO) *)OPENSSL_sk_set_cmp_thunks(OPENSSL_sk_new(ossl_check_BIO_compfunc_type(cmp)), sk_BIO_cmpfunc_thunk))
|
||||||
|
#define sk_BIO_new_null() ((STACK_OF(BIO) *)OPENSSL_sk_set_thunks(OPENSSL_sk_new_null(), sk_BIO_freefunc_thunk))
|
||||||
|
#define sk_BIO_new_reserve(cmp, n) ((STACK_OF(BIO) *)OPENSSL_sk_set_cmp_thunks(OPENSSL_sk_new_reserve(ossl_check_BIO_compfunc_type(cmp), (n)), sk_BIO_cmpfunc_thunk))
|
||||||
|
#define sk_BIO_reserve(sk, n) OPENSSL_sk_reserve(ossl_check_BIO_sk_type(sk), (n))
|
||||||
|
#define sk_BIO_free(sk) OPENSSL_sk_free(ossl_check_BIO_sk_type(sk))
|
||||||
|
#define sk_BIO_zero(sk) OPENSSL_sk_zero(ossl_check_BIO_sk_type(sk))
|
||||||
|
#define sk_BIO_delete(sk, i) ((BIO *)OPENSSL_sk_delete(ossl_check_BIO_sk_type(sk), (i)))
|
||||||
|
#define sk_BIO_delete_ptr(sk, ptr) ((BIO *)OPENSSL_sk_delete_ptr(ossl_check_BIO_sk_type(sk), ossl_check_BIO_type(ptr)))
|
||||||
|
#define sk_BIO_push(sk, ptr) OPENSSL_sk_push(ossl_check_BIO_sk_type(sk), ossl_check_BIO_type(ptr))
|
||||||
|
#define sk_BIO_unshift(sk, ptr) OPENSSL_sk_unshift(ossl_check_BIO_sk_type(sk), ossl_check_BIO_type(ptr))
|
||||||
|
#define sk_BIO_pop(sk) ((BIO *)OPENSSL_sk_pop(ossl_check_BIO_sk_type(sk)))
|
||||||
|
#define sk_BIO_shift(sk) ((BIO *)OPENSSL_sk_shift(ossl_check_BIO_sk_type(sk)))
|
||||||
|
#define sk_BIO_pop_free(sk, freefunc) OPENSSL_sk_pop_free(ossl_check_BIO_sk_type(sk), ossl_check_BIO_freefunc_type(freefunc))
|
||||||
|
#define sk_BIO_insert(sk, ptr, idx) OPENSSL_sk_insert(ossl_check_BIO_sk_type(sk), ossl_check_BIO_type(ptr), (idx))
|
||||||
|
#define sk_BIO_set(sk, idx, ptr) ((BIO *)OPENSSL_sk_set(ossl_check_BIO_sk_type(sk), (idx), ossl_check_BIO_type(ptr)))
|
||||||
|
#define sk_BIO_find(sk, ptr) OPENSSL_sk_find(ossl_check_BIO_sk_type(sk), ossl_check_BIO_type(ptr))
|
||||||
|
#define sk_BIO_find_ex(sk, ptr) OPENSSL_sk_find_ex(ossl_check_BIO_sk_type(sk), ossl_check_BIO_type(ptr))
|
||||||
|
#define sk_BIO_find_all(sk, ptr, pnum) OPENSSL_sk_find_all(ossl_check_BIO_sk_type(sk), ossl_check_BIO_type(ptr), pnum)
|
||||||
|
#define sk_BIO_sort(sk) OPENSSL_sk_sort(ossl_check_BIO_sk_type(sk))
|
||||||
|
#define sk_BIO_is_sorted(sk) OPENSSL_sk_is_sorted(ossl_check_const_BIO_sk_type(sk))
|
||||||
|
#define sk_BIO_dup(sk) ((STACK_OF(BIO) *)OPENSSL_sk_dup(ossl_check_const_BIO_sk_type(sk)))
|
||||||
|
#define sk_BIO_deep_copy(sk, copyfunc, freefunc) ((STACK_OF(BIO) *)OPENSSL_sk_deep_copy(ossl_check_const_BIO_sk_type(sk), ossl_check_BIO_copyfunc_type(copyfunc), ossl_check_BIO_freefunc_type(freefunc)))
|
||||||
|
#define sk_BIO_set_cmp_func(sk, cmp) ((sk_BIO_compfunc)OPENSSL_sk_set_cmp_func(ossl_check_BIO_sk_type(sk), ossl_check_BIO_compfunc_type(cmp)))
|
||||||
|
|
||||||
|
/* clang-format on */
|
||||||
|
|
||||||
/* Prefix and suffix callback in ASN1 BIO */
|
/* Prefix and suffix callback in ASN1 BIO */
|
||||||
typedef int asn1_ps_func(BIO *b, unsigned char **pbuf, int *plen,
|
typedef int asn1_ps_func(BIO *b, unsigned char **pbuf, int *plen,
|
||||||
void *parg);
|
void *parg);
|
||||||
|
|
||||||
|
typedef void (*BIO_dgram_sctp_notification_handler_fn)(BIO *b,
|
||||||
|
void *context,
|
||||||
|
void *buf);
|
||||||
#ifndef OPENSSL_NO_SCTP
|
#ifndef OPENSSL_NO_SCTP
|
||||||
/* SCTP parameter structs */
|
/* SCTP parameter structs */
|
||||||
struct bio_dgram_sctp_sndinfo {
|
struct bio_dgram_sctp_sndinfo {
|
||||||
@@ -286,6 +406,36 @@ struct bio_dgram_sctp_prinfo {
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* BIO_sendmmsg/BIO_recvmmsg-related definitions */
|
||||||
|
typedef struct bio_msg_st {
|
||||||
|
void *data;
|
||||||
|
size_t data_len;
|
||||||
|
BIO_ADDR *peer, *local;
|
||||||
|
uint64_t flags;
|
||||||
|
} BIO_MSG;
|
||||||
|
|
||||||
|
typedef struct bio_mmsg_cb_args_st {
|
||||||
|
BIO_MSG *msg;
|
||||||
|
size_t stride, num_msg;
|
||||||
|
uint64_t flags;
|
||||||
|
size_t *msgs_processed;
|
||||||
|
} BIO_MMSG_CB_ARGS;
|
||||||
|
|
||||||
|
#define BIO_POLL_DESCRIPTOR_TYPE_NONE 0
|
||||||
|
#define BIO_POLL_DESCRIPTOR_TYPE_SOCK_FD 1
|
||||||
|
#define BIO_POLL_DESCRIPTOR_TYPE_SSL 2
|
||||||
|
#define BIO_POLL_DESCRIPTOR_CUSTOM_START 8192
|
||||||
|
|
||||||
|
typedef struct bio_poll_descriptor_st {
|
||||||
|
uint32_t type;
|
||||||
|
union {
|
||||||
|
int fd;
|
||||||
|
void *custom;
|
||||||
|
uintptr_t custom_ui;
|
||||||
|
SSL *ssl;
|
||||||
|
} value;
|
||||||
|
} BIO_POLL_DESCRIPTOR;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* #define BIO_CONN_get_param_hostname BIO_ctrl
|
* #define BIO_CONN_get_param_hostname BIO_ctrl
|
||||||
*/
|
*/
|
||||||
@@ -320,7 +470,7 @@ struct bio_dgram_sctp_prinfo {
|
|||||||
#define BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT 127
|
#define BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT 127
|
||||||
#define BIO_C_FILE_SEEK 128
|
#define BIO_C_FILE_SEEK 128
|
||||||
#define BIO_C_GET_CIPHER_CTX 129
|
#define BIO_C_GET_CIPHER_CTX 129
|
||||||
# define BIO_C_SET_BUF_MEM_EOF_RETURN 130/* return end of input
|
#define BIO_C_SET_BUF_MEM_EOF_RETURN 130 /* return end of input \
|
||||||
* value */
|
* value */
|
||||||
#define BIO_C_SET_BIND_MODE 131
|
#define BIO_C_SET_BIND_MODE 131
|
||||||
#define BIO_C_GET_BIND_MODE 132
|
#define BIO_C_GET_BIND_MODE 132
|
||||||
@@ -352,10 +502,18 @@ struct bio_dgram_sctp_prinfo {
|
|||||||
|
|
||||||
#define BIO_C_SET_CONNECT_MODE 155
|
#define BIO_C_SET_CONNECT_MODE 155
|
||||||
|
|
||||||
|
#define BIO_C_SET_TFO 156 /* like BIO_C_SET_NBIO */
|
||||||
|
|
||||||
|
#define BIO_C_SET_SOCK_TYPE 157
|
||||||
|
#define BIO_C_GET_SOCK_TYPE 158
|
||||||
|
#define BIO_C_GET_DGRAM_BIO 159
|
||||||
|
#define BIO_C_SET_SEND_FLAGS 160
|
||||||
|
|
||||||
#define BIO_set_app_data(s, arg) BIO_set_ex_data(s, 0, arg)
|
#define BIO_set_app_data(s, arg) BIO_set_ex_data(s, 0, arg)
|
||||||
#define BIO_get_app_data(s) BIO_get_ex_data(s, 0)
|
#define BIO_get_app_data(s) BIO_get_ex_data(s, 0)
|
||||||
|
|
||||||
#define BIO_set_nbio(b, n) BIO_ctrl(b, BIO_C_SET_NBIO, (n), NULL)
|
#define BIO_set_nbio(b, n) BIO_ctrl(b, BIO_C_SET_NBIO, (n), NULL)
|
||||||
|
#define BIO_set_tfo(b, n) BIO_ctrl(b, BIO_C_SET_TFO, (n), NULL)
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_SOCK
|
#ifndef OPENSSL_NO_SOCK
|
||||||
/* IP families we support, for BIO_s_connect() and BIO_s_accept() */
|
/* IP families we support, for BIO_s_connect() and BIO_s_accept() */
|
||||||
@@ -376,7 +534,11 @@ struct bio_dgram_sctp_prinfo {
|
|||||||
#define BIO_get_conn_port(b) ((const char *)BIO_ptr_ctrl(b, BIO_C_GET_CONNECT, 1))
|
#define BIO_get_conn_port(b) ((const char *)BIO_ptr_ctrl(b, BIO_C_GET_CONNECT, 1))
|
||||||
#define BIO_get_conn_address(b) ((const BIO_ADDR *)BIO_ptr_ctrl(b, BIO_C_GET_CONNECT, 2))
|
#define BIO_get_conn_address(b) ((const BIO_ADDR *)BIO_ptr_ctrl(b, BIO_C_GET_CONNECT, 2))
|
||||||
#define BIO_get_conn_ip_family(b) BIO_ctrl(b, BIO_C_GET_CONNECT, 3, NULL)
|
#define BIO_get_conn_ip_family(b) BIO_ctrl(b, BIO_C_GET_CONNECT, 3, NULL)
|
||||||
|
#define BIO_get_conn_mode(b) BIO_ctrl(b, BIO_C_GET_CONNECT, 4, NULL)
|
||||||
#define BIO_set_conn_mode(b, n) BIO_ctrl(b, BIO_C_SET_CONNECT_MODE, (n), NULL)
|
#define BIO_set_conn_mode(b, n) BIO_ctrl(b, BIO_C_SET_CONNECT_MODE, (n), NULL)
|
||||||
|
#define BIO_set_sock_type(b, t) BIO_ctrl(b, BIO_C_SET_SOCK_TYPE, (t), NULL)
|
||||||
|
#define BIO_get_sock_type(b) BIO_ctrl(b, BIO_C_GET_SOCK_TYPE, 0, NULL)
|
||||||
|
#define BIO_get0_dgram_bio(b, p) BIO_ctrl(b, BIO_C_GET_DGRAM_BIO, 0, (void *)(BIO **)(p))
|
||||||
|
|
||||||
/* BIO_s_accept() */
|
/* BIO_s_accept() */
|
||||||
#define BIO_set_accept_name(b, name) BIO_ctrl(b, BIO_C_SET_ACCEPT, 0, \
|
#define BIO_set_accept_name(b, name) BIO_ctrl(b, BIO_C_SET_ACCEPT, 0, \
|
||||||
@@ -393,6 +555,7 @@ struct bio_dgram_sctp_prinfo {
|
|||||||
(char *)(bio))
|
(char *)(bio))
|
||||||
#define BIO_set_accept_ip_family(b, f) BIO_int_ctrl(b, BIO_C_SET_ACCEPT, 4, f)
|
#define BIO_set_accept_ip_family(b, f) BIO_int_ctrl(b, BIO_C_SET_ACCEPT, 4, f)
|
||||||
#define BIO_get_accept_ip_family(b) BIO_ctrl(b, BIO_C_GET_ACCEPT, 4, NULL)
|
#define BIO_get_accept_ip_family(b) BIO_ctrl(b, BIO_C_GET_ACCEPT, 4, NULL)
|
||||||
|
#define BIO_set_tfo_accept(b, n) BIO_ctrl(b, BIO_C_SET_ACCEPT, 5, (n) ? (void *)"a" : NULL)
|
||||||
|
|
||||||
/* Aliases kept for backward compatibility */
|
/* Aliases kept for backward compatibility */
|
||||||
#define BIO_BIND_NORMAL 0
|
#define BIO_BIND_NORMAL 0
|
||||||
@@ -400,11 +563,10 @@ struct bio_dgram_sctp_prinfo {
|
|||||||
#define BIO_BIND_REUSEADDR_IF_UNUSED BIO_SOCK_REUSEADDR
|
#define BIO_BIND_REUSEADDR_IF_UNUSED BIO_SOCK_REUSEADDR
|
||||||
#define BIO_set_bind_mode(b, mode) BIO_ctrl(b, BIO_C_SET_BIND_MODE, mode, NULL)
|
#define BIO_set_bind_mode(b, mode) BIO_ctrl(b, BIO_C_SET_BIND_MODE, mode, NULL)
|
||||||
#define BIO_get_bind_mode(b) BIO_ctrl(b, BIO_C_GET_BIND_MODE, 0, NULL)
|
#define BIO_get_bind_mode(b) BIO_ctrl(b, BIO_C_GET_BIND_MODE, 0, NULL)
|
||||||
|
#endif /* OPENSSL_NO_SOCK */
|
||||||
|
|
||||||
/* BIO_s_accept() and BIO_s_connect() */
|
|
||||||
#define BIO_do_connect(b) BIO_do_handshake(b)
|
#define BIO_do_connect(b) BIO_do_handshake(b)
|
||||||
#define BIO_do_accept(b) BIO_do_handshake(b)
|
#define BIO_do_accept(b) BIO_do_handshake(b)
|
||||||
# endif /* OPENSSL_NO_SOCK */
|
|
||||||
|
|
||||||
#define BIO_do_handshake(b) BIO_ctrl(b, BIO_C_DO_STATE_MACHINE, 0, NULL)
|
#define BIO_do_handshake(b) BIO_ctrl(b, BIO_C_DO_STATE_MACHINE, 0, NULL)
|
||||||
|
|
||||||
@@ -478,7 +640,6 @@ int BIO_read_filename(BIO *b, const char *name);
|
|||||||
#define BIO_dup_state(b, ret) BIO_ctrl(b, BIO_CTRL_DUP, 0, (char *)(ret))
|
#define BIO_dup_state(b, ret) BIO_ctrl(b, BIO_CTRL_DUP, 0, (char *)(ret))
|
||||||
|
|
||||||
#define BIO_reset(b) (int)BIO_ctrl(b, BIO_CTRL_RESET, 0, NULL)
|
#define BIO_reset(b) (int)BIO_ctrl(b, BIO_CTRL_RESET, 0, NULL)
|
||||||
# define BIO_eof(b) (int)BIO_ctrl(b,BIO_CTRL_EOF,0,NULL)
|
|
||||||
#define BIO_set_close(b, c) (int)BIO_ctrl(b, BIO_CTRL_SET_CLOSE, (c), NULL)
|
#define BIO_set_close(b, c) (int)BIO_ctrl(b, BIO_CTRL_SET_CLOSE, (c), NULL)
|
||||||
#define BIO_get_close(b) (int)BIO_ctrl(b, BIO_CTRL_GET_CLOSE, 0, NULL)
|
#define BIO_get_close(b) (int)BIO_ctrl(b, BIO_CTRL_GET_CLOSE, 0, NULL)
|
||||||
#define BIO_pending(b) (int)BIO_ctrl(b, BIO_CTRL_PENDING, 0, NULL)
|
#define BIO_pending(b) (int)BIO_ctrl(b, BIO_CTRL_PENDING, 0, NULL)
|
||||||
@@ -521,13 +682,42 @@ int BIO_ctrl_reset_read_request(BIO *b);
|
|||||||
(int)BIO_ctrl(b, BIO_CTRL_DGRAM_GET_PEER, 0, (char *)(peer))
|
(int)BIO_ctrl(b, BIO_CTRL_DGRAM_GET_PEER, 0, (char *)(peer))
|
||||||
#define BIO_dgram_set_peer(b, peer) \
|
#define BIO_dgram_set_peer(b, peer) \
|
||||||
(int)BIO_ctrl(b, BIO_CTRL_DGRAM_SET_PEER, 0, (char *)(peer))
|
(int)BIO_ctrl(b, BIO_CTRL_DGRAM_SET_PEER, 0, (char *)(peer))
|
||||||
|
#define BIO_dgram_detect_peer_addr(b, peer) \
|
||||||
|
(int)BIO_ctrl(b, BIO_CTRL_DGRAM_DETECT_PEER_ADDR, 0, (char *)(peer))
|
||||||
#define BIO_dgram_get_mtu_overhead(b) \
|
#define BIO_dgram_get_mtu_overhead(b) \
|
||||||
(unsigned int)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_MTU_OVERHEAD, 0, NULL)
|
(unsigned int)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_MTU_OVERHEAD, 0, NULL)
|
||||||
|
#define BIO_dgram_get_local_addr_cap(b) \
|
||||||
|
(int)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_LOCAL_ADDR_CAP, 0, NULL)
|
||||||
|
#define BIO_dgram_get_local_addr_enable(b, penable) \
|
||||||
|
(int)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_LOCAL_ADDR_ENABLE, 0, (char *)(penable))
|
||||||
|
#define BIO_dgram_set_local_addr_enable(b, enable) \
|
||||||
|
(int)BIO_ctrl((b), BIO_CTRL_DGRAM_SET_LOCAL_ADDR_ENABLE, (enable), NULL)
|
||||||
|
#define BIO_dgram_get_effective_caps(b) \
|
||||||
|
(uint32_t)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_EFFECTIVE_CAPS, 0, NULL)
|
||||||
|
#define BIO_dgram_get_caps(b) \
|
||||||
|
(uint32_t)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_CAPS, 0, NULL)
|
||||||
|
#define BIO_dgram_set_caps(b, caps) \
|
||||||
|
(int)BIO_ctrl((b), BIO_CTRL_DGRAM_SET_CAPS, (long)(caps), NULL)
|
||||||
|
#define BIO_dgram_get_no_trunc(b) \
|
||||||
|
(unsigned int)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_NO_TRUNC, 0, NULL)
|
||||||
|
#define BIO_dgram_set_no_trunc(b, enable) \
|
||||||
|
(int)BIO_ctrl((b), BIO_CTRL_DGRAM_SET_NO_TRUNC, (enable), NULL)
|
||||||
|
#define BIO_dgram_get_mtu(b) \
|
||||||
|
(unsigned int)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_MTU, 0, NULL)
|
||||||
|
#define BIO_dgram_set_mtu(b, mtu) \
|
||||||
|
(int)BIO_ctrl((b), BIO_CTRL_DGRAM_SET_MTU, (mtu), NULL)
|
||||||
|
#define BIO_dgram_set0_local_addr(b, addr) \
|
||||||
|
(int)BIO_ctrl((b), BIO_CTRL_DGRAM_SET0_LOCAL_ADDR, 0, (addr))
|
||||||
|
|
||||||
|
/* ctrl macros for BIO_f_prefix */
|
||||||
|
#define BIO_set_prefix(b, p) BIO_ctrl((b), BIO_CTRL_SET_PREFIX, 0, (void *)(p))
|
||||||
|
#define BIO_set_indent(b, i) BIO_ctrl((b), BIO_CTRL_SET_INDENT, (i), NULL)
|
||||||
|
#define BIO_get_indent(b) BIO_ctrl((b), BIO_CTRL_GET_INDENT, 0, NULL)
|
||||||
|
|
||||||
#define BIO_get_ex_new_index(l, p, newf, dupf, freef) \
|
#define BIO_get_ex_new_index(l, p, newf, dupf, freef) \
|
||||||
CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_BIO, l, p, newf, dupf, freef)
|
CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_BIO, l, p, newf, dupf, freef)
|
||||||
int BIO_set_ex_data(BIO *bio, int idx, void *data);
|
int BIO_set_ex_data(BIO *bio, int idx, void *data);
|
||||||
void *BIO_get_ex_data(BIO *bio, int idx);
|
void *BIO_get_ex_data(const BIO *bio, int idx);
|
||||||
uint64_t BIO_number_read(BIO *bio);
|
uint64_t BIO_number_read(BIO *bio);
|
||||||
uint64_t BIO_number_written(BIO *bio);
|
uint64_t BIO_number_written(BIO *bio);
|
||||||
|
|
||||||
@@ -543,9 +733,11 @@ int BIO_asn1_get_suffix(BIO *b, asn1_ps_func **psuffix,
|
|||||||
|
|
||||||
const BIO_METHOD *BIO_s_file(void);
|
const BIO_METHOD *BIO_s_file(void);
|
||||||
BIO *BIO_new_file(const char *filename, const char *mode);
|
BIO *BIO_new_file(const char *filename, const char *mode);
|
||||||
|
BIO *BIO_new_from_core_bio(OSSL_LIB_CTX *libctx, OSSL_CORE_BIO *corebio);
|
||||||
#ifndef OPENSSL_NO_STDIO
|
#ifndef OPENSSL_NO_STDIO
|
||||||
BIO *BIO_new_fp(FILE *stream, int close_flag);
|
BIO *BIO_new_fp(FILE *stream, int close_flag);
|
||||||
#endif
|
#endif
|
||||||
|
BIO *BIO_new_ex(OSSL_LIB_CTX *libctx, const BIO_METHOD *method);
|
||||||
BIO *BIO_new(const BIO_METHOD *type);
|
BIO *BIO_new(const BIO_METHOD *type);
|
||||||
int BIO_free(BIO *a);
|
int BIO_free(BIO *a);
|
||||||
void BIO_set_data(BIO *a, void *ptr);
|
void BIO_set_data(BIO *a, void *ptr);
|
||||||
@@ -558,12 +750,22 @@ void BIO_vfree(BIO *a);
|
|||||||
int BIO_up_ref(BIO *a);
|
int BIO_up_ref(BIO *a);
|
||||||
int BIO_read(BIO *b, void *data, int dlen);
|
int BIO_read(BIO *b, void *data, int dlen);
|
||||||
int BIO_read_ex(BIO *b, void *data, size_t dlen, size_t *readbytes);
|
int BIO_read_ex(BIO *b, void *data, size_t dlen, size_t *readbytes);
|
||||||
|
__owur int BIO_recvmmsg(BIO *b, BIO_MSG *msg,
|
||||||
|
size_t stride, size_t num_msg, uint64_t flags,
|
||||||
|
size_t *msgs_processed);
|
||||||
int BIO_gets(BIO *bp, char *buf, int size);
|
int BIO_gets(BIO *bp, char *buf, int size);
|
||||||
|
int BIO_get_line(BIO *bio, char *buf, int size);
|
||||||
int BIO_write(BIO *b, const void *data, int dlen);
|
int BIO_write(BIO *b, const void *data, int dlen);
|
||||||
int BIO_write_ex(BIO *b, const void *data, size_t dlen, size_t *written);
|
int BIO_write_ex(BIO *b, const void *data, size_t dlen, size_t *written);
|
||||||
|
__owur int BIO_sendmmsg(BIO *b, BIO_MSG *msg,
|
||||||
|
size_t stride, size_t num_msg, uint64_t flags,
|
||||||
|
size_t *msgs_processed);
|
||||||
|
__owur int BIO_get_rpoll_descriptor(BIO *b, BIO_POLL_DESCRIPTOR *desc);
|
||||||
|
__owur int BIO_get_wpoll_descriptor(BIO *b, BIO_POLL_DESCRIPTOR *desc);
|
||||||
int BIO_puts(BIO *bp, const char *buf);
|
int BIO_puts(BIO *bp, const char *buf);
|
||||||
int BIO_indent(BIO *b, int indent, int max);
|
int BIO_indent(BIO *b, int indent, int max);
|
||||||
long BIO_ctrl(BIO *bp, int cmd, long larg, void *parg);
|
long BIO_ctrl(BIO *bp, int cmd, long larg, void *parg);
|
||||||
|
int BIO_eof(BIO *b);
|
||||||
long BIO_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp);
|
long BIO_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp);
|
||||||
void *BIO_ptr_ctrl(BIO *bp, int cmd, long larg);
|
void *BIO_ptr_ctrl(BIO *bp, int cmd, long larg);
|
||||||
long BIO_int_ctrl(BIO *bp, int cmd, long larg, int iarg);
|
long BIO_int_ctrl(BIO *bp, int cmd, long larg, int iarg);
|
||||||
@@ -583,10 +785,10 @@ int BIO_nread(BIO *bio, char **buf, int num);
|
|||||||
int BIO_nwrite0(BIO *bio, char **buf);
|
int BIO_nwrite0(BIO *bio, char **buf);
|
||||||
int BIO_nwrite(BIO *bio, char **buf, int num);
|
int BIO_nwrite(BIO *bio, char **buf, int num);
|
||||||
|
|
||||||
long BIO_debug_callback(BIO *bio, int cmd, const char *argp, int argi,
|
|
||||||
long argl, long ret);
|
|
||||||
|
|
||||||
const BIO_METHOD *BIO_s_mem(void);
|
const BIO_METHOD *BIO_s_mem(void);
|
||||||
|
#ifndef OPENSSL_NO_DGRAM
|
||||||
|
const BIO_METHOD *BIO_s_dgram_mem(void);
|
||||||
|
#endif
|
||||||
const BIO_METHOD *BIO_s_secmem(void);
|
const BIO_METHOD *BIO_s_secmem(void);
|
||||||
BIO *BIO_new_mem_buf(const void *buf, int len);
|
BIO *BIO_new_mem_buf(const void *buf, int len);
|
||||||
#ifndef OPENSSL_NO_SOCK
|
#ifndef OPENSSL_NO_SOCK
|
||||||
@@ -600,9 +802,13 @@ const BIO_METHOD *BIO_s_bio(void);
|
|||||||
const BIO_METHOD *BIO_s_null(void);
|
const BIO_METHOD *BIO_s_null(void);
|
||||||
const BIO_METHOD *BIO_f_null(void);
|
const BIO_METHOD *BIO_f_null(void);
|
||||||
const BIO_METHOD *BIO_f_buffer(void);
|
const BIO_METHOD *BIO_f_buffer(void);
|
||||||
|
const BIO_METHOD *BIO_f_readbuffer(void);
|
||||||
const BIO_METHOD *BIO_f_linebuffer(void);
|
const BIO_METHOD *BIO_f_linebuffer(void);
|
||||||
const BIO_METHOD *BIO_f_nbio_test(void);
|
const BIO_METHOD *BIO_f_nbio_test(void);
|
||||||
|
const BIO_METHOD *BIO_f_prefix(void);
|
||||||
|
const BIO_METHOD *BIO_s_core(void);
|
||||||
#ifndef OPENSSL_NO_DGRAM
|
#ifndef OPENSSL_NO_DGRAM
|
||||||
|
const BIO_METHOD *BIO_s_dgram_pair(void);
|
||||||
const BIO_METHOD *BIO_s_datagram(void);
|
const BIO_METHOD *BIO_s_datagram(void);
|
||||||
int BIO_dgram_non_fatal_error(int error);
|
int BIO_dgram_non_fatal_error(int error);
|
||||||
BIO *BIO_new_dgram(int fd, int close_flag);
|
BIO *BIO_new_dgram(int fd, int close_flag);
|
||||||
@@ -611,9 +817,7 @@ const BIO_METHOD *BIO_s_datagram_sctp(void);
|
|||||||
BIO *BIO_new_dgram_sctp(int fd, int close_flag);
|
BIO *BIO_new_dgram_sctp(int fd, int close_flag);
|
||||||
int BIO_dgram_is_sctp(BIO *bio);
|
int BIO_dgram_is_sctp(BIO *bio);
|
||||||
int BIO_dgram_sctp_notification_cb(BIO *b,
|
int BIO_dgram_sctp_notification_cb(BIO *b,
|
||||||
void (*handle_notifications) (BIO *bio,
|
BIO_dgram_sctp_notification_handler_fn handle_notifications,
|
||||||
void *context,
|
|
||||||
void *buf),
|
|
||||||
void *context);
|
void *context);
|
||||||
int BIO_dgram_sctp_wait_for_dry(BIO *b);
|
int BIO_dgram_sctp_wait_for_dry(BIO *b);
|
||||||
int BIO_dgram_sctp_msg_waiting(BIO *b);
|
int BIO_dgram_sctp_msg_waiting(BIO *b);
|
||||||
@@ -623,25 +827,32 @@ int BIO_dgram_sctp_msg_waiting(BIO *b);
|
|||||||
#ifndef OPENSSL_NO_SOCK
|
#ifndef OPENSSL_NO_SOCK
|
||||||
int BIO_sock_should_retry(int i);
|
int BIO_sock_should_retry(int i);
|
||||||
int BIO_sock_non_fatal_error(int error);
|
int BIO_sock_non_fatal_error(int error);
|
||||||
|
int BIO_err_is_non_fatal(unsigned int errcode);
|
||||||
|
int BIO_socket_wait(int fd, int for_read, time_t max_time);
|
||||||
#endif
|
#endif
|
||||||
|
long BIO_set_send_flags(BIO *b, int flags);
|
||||||
|
int BIO_wait(BIO *bio, time_t max_time, unsigned int nap_milliseconds);
|
||||||
|
int BIO_do_connect_retry(BIO *bio, int timeout, int nap_milliseconds);
|
||||||
|
|
||||||
int BIO_fd_should_retry(int i);
|
int BIO_fd_should_retry(int i);
|
||||||
int BIO_fd_non_fatal_error(int error);
|
int BIO_fd_non_fatal_error(int error);
|
||||||
int BIO_dump_cb(int (*cb)(const void *data, size_t len, void *u),
|
int BIO_dump_cb(int (*cb)(const void *data, size_t len, void *u),
|
||||||
void *u, const char *s, int len);
|
void *u, const void *s, int len);
|
||||||
int BIO_dump_indent_cb(int (*cb)(const void *data, size_t len, void *u),
|
int BIO_dump_indent_cb(int (*cb)(const void *data, size_t len, void *u),
|
||||||
void *u, const char *s, int len, int indent);
|
void *u, const void *s, int len, int indent);
|
||||||
int BIO_dump(BIO *b, const char *bytes, int len);
|
int BIO_dump(BIO *b, const void *bytes, int len);
|
||||||
int BIO_dump_indent(BIO *b, const char *bytes, int len, int indent);
|
int BIO_dump_indent(BIO *b, const void *bytes, int len, int indent);
|
||||||
#ifndef OPENSSL_NO_STDIO
|
#ifndef OPENSSL_NO_STDIO
|
||||||
int BIO_dump_fp(FILE *fp, const char *s, int len);
|
int BIO_dump_fp(FILE *fp, const void *s, int len);
|
||||||
int BIO_dump_indent_fp(FILE *fp, const char *s, int len, int indent);
|
int BIO_dump_indent_fp(FILE *fp, const void *s, int len, int indent);
|
||||||
#endif
|
#endif
|
||||||
int BIO_hex_string(BIO *out, int indent, int width, unsigned char *data,
|
int BIO_hex_string(BIO *out, int indent, int width, const void *data,
|
||||||
int datalen);
|
int datalen);
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_SOCK
|
#ifndef OPENSSL_NO_SOCK
|
||||||
BIO_ADDR *BIO_ADDR_new(void);
|
BIO_ADDR *BIO_ADDR_new(void);
|
||||||
|
int BIO_ADDR_copy(BIO_ADDR *dst, const BIO_ADDR *src);
|
||||||
|
BIO_ADDR *BIO_ADDR_dup(const BIO_ADDR *ap);
|
||||||
int BIO_ADDR_rawmake(BIO_ADDR *ap, int family,
|
int BIO_ADDR_rawmake(BIO_ADDR *ap, int family,
|
||||||
const void *where, size_t wherelen, unsigned short port);
|
const void *where, size_t wherelen, unsigned short port);
|
||||||
void BIO_ADDR_free(BIO_ADDR *);
|
void BIO_ADDR_free(BIO_ADDR *);
|
||||||
@@ -661,12 +872,14 @@ const BIO_ADDR *BIO_ADDRINFO_address(const BIO_ADDRINFO *bai);
|
|||||||
void BIO_ADDRINFO_free(BIO_ADDRINFO *bai);
|
void BIO_ADDRINFO_free(BIO_ADDRINFO *bai);
|
||||||
|
|
||||||
enum BIO_hostserv_priorities {
|
enum BIO_hostserv_priorities {
|
||||||
BIO_PARSE_PRIO_HOST, BIO_PARSE_PRIO_SERV
|
BIO_PARSE_PRIO_HOST,
|
||||||
|
BIO_PARSE_PRIO_SERV
|
||||||
};
|
};
|
||||||
int BIO_parse_hostserv(const char *hostserv, char **host, char **service,
|
int BIO_parse_hostserv(const char *hostserv, char **host, char **service,
|
||||||
enum BIO_hostserv_priorities hostserv_prio);
|
enum BIO_hostserv_priorities hostserv_prio);
|
||||||
enum BIO_lookup_type {
|
enum BIO_lookup_type {
|
||||||
BIO_LOOKUP_CLIENT, BIO_LOOKUP_SERVER
|
BIO_LOOKUP_CLIENT,
|
||||||
|
BIO_LOOKUP_SERVER
|
||||||
};
|
};
|
||||||
int BIO_lookup(const char *host, const char *service,
|
int BIO_lookup(const char *host, const char *service,
|
||||||
enum BIO_lookup_type lookup_type,
|
enum BIO_lookup_type lookup_type,
|
||||||
@@ -678,16 +891,19 @@ int BIO_sock_error(int sock);
|
|||||||
int BIO_socket_ioctl(int fd, long type, void *arg);
|
int BIO_socket_ioctl(int fd, long type, void *arg);
|
||||||
int BIO_socket_nbio(int fd, int mode);
|
int BIO_socket_nbio(int fd, int mode);
|
||||||
int BIO_sock_init(void);
|
int BIO_sock_init(void);
|
||||||
# if OPENSSL_API_COMPAT < 0x10100000L
|
#ifndef OPENSSL_NO_DEPRECATED_1_1_0
|
||||||
# define BIO_sock_cleanup() while(0) continue
|
#define BIO_sock_cleanup() \
|
||||||
|
while (0) \
|
||||||
|
continue
|
||||||
#endif
|
#endif
|
||||||
int BIO_set_tcp_ndelay(int sock, int turn_on);
|
int BIO_set_tcp_ndelay(int sock, int turn_on);
|
||||||
|
#ifndef OPENSSL_NO_DEPRECATED_1_1_0
|
||||||
DEPRECATEDIN_1_1_0(struct hostent *BIO_gethostbyname(const char *name))
|
OSSL_DEPRECATEDIN_1_1_0 struct hostent *BIO_gethostbyname(const char *name);
|
||||||
DEPRECATEDIN_1_1_0(int BIO_get_port(const char *str, unsigned short *port_ptr))
|
OSSL_DEPRECATEDIN_1_1_0 int BIO_get_port(const char *str, unsigned short *port_ptr);
|
||||||
DEPRECATEDIN_1_1_0(int BIO_get_host_ip(const char *str, unsigned char *ip))
|
OSSL_DEPRECATEDIN_1_1_0 int BIO_get_host_ip(const char *str, unsigned char *ip);
|
||||||
DEPRECATEDIN_1_1_0(int BIO_get_accept_socket(char *host_port, int mode))
|
OSSL_DEPRECATEDIN_1_1_0 int BIO_get_accept_socket(char *host_port, int mode);
|
||||||
DEPRECATEDIN_1_1_0(int BIO_accept(int sock, char **ip_port))
|
OSSL_DEPRECATEDIN_1_1_0 int BIO_accept(int sock, char **ip_port);
|
||||||
|
#endif
|
||||||
|
|
||||||
union BIO_sock_info_u {
|
union BIO_sock_info_u {
|
||||||
BIO_ADDR *addr;
|
BIO_ADDR *addr;
|
||||||
@@ -703,6 +919,7 @@ int BIO_sock_info(int sock,
|
|||||||
#define BIO_SOCK_KEEPALIVE 0x04
|
#define BIO_SOCK_KEEPALIVE 0x04
|
||||||
#define BIO_SOCK_NONBLOCK 0x08
|
#define BIO_SOCK_NONBLOCK 0x08
|
||||||
#define BIO_SOCK_NODELAY 0x10
|
#define BIO_SOCK_NODELAY 0x10
|
||||||
|
#define BIO_SOCK_TFO 0x20
|
||||||
|
|
||||||
int BIO_socket(int domain, int socktype, int protocol, int options);
|
int BIO_socket(int domain, int socktype, int protocol, int options);
|
||||||
int BIO_connect(int sock, const BIO_ADDR *addr, int options);
|
int BIO_connect(int sock, const BIO_ADDR *addr, int options);
|
||||||
@@ -720,6 +937,11 @@ BIO *BIO_new_fd(int fd, int close_flag);
|
|||||||
|
|
||||||
int BIO_new_bio_pair(BIO **bio1, size_t writebuf1,
|
int BIO_new_bio_pair(BIO **bio1, size_t writebuf1,
|
||||||
BIO **bio2, size_t writebuf2);
|
BIO **bio2, size_t writebuf2);
|
||||||
|
#ifndef OPENSSL_NO_DGRAM
|
||||||
|
int BIO_new_bio_dgram_pair(BIO **bio1, size_t writebuf1,
|
||||||
|
BIO **bio2, size_t writebuf2);
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If successful, returns 1 and in *bio1, *bio2 two BIO pair endpoints.
|
* If successful, returns 1 and in *bio1, *bio2 two BIO pair endpoints.
|
||||||
* Otherwise returns 0 and sets *bio1 and *bio2 to NULL. Size 0 uses default
|
* Otherwise returns 0 and sets *bio1 and *bio2 to NULL. Size 0 uses default
|
||||||
@@ -734,6 +956,7 @@ void BIO_copy_next_retry(BIO *b);
|
|||||||
|
|
||||||
#define ossl_bio__attr__(x)
|
#define ossl_bio__attr__(x)
|
||||||
#if defined(__GNUC__) && defined(__STDC_VERSION__) \
|
#if defined(__GNUC__) && defined(__STDC_VERSION__) \
|
||||||
|
&& !defined(__MINGW32__) && !defined(__MINGW64__) \
|
||||||
&& !defined(__APPLE__)
|
&& !defined(__APPLE__)
|
||||||
/*
|
/*
|
||||||
* Because we support the 'z' modifier, which made its appearance in C99,
|
* Because we support the 'z' modifier, which made its appearance in C99,
|
||||||
@@ -760,41 +983,56 @@ ossl_bio__attr__((__format__(ossl_bio__printf__, 3, 0)));
|
|||||||
#undef ossl_bio__attr__
|
#undef ossl_bio__attr__
|
||||||
#undef ossl_bio__printf__
|
#undef ossl_bio__printf__
|
||||||
|
|
||||||
|
|
||||||
BIO_METHOD *BIO_meth_new(int type, const char *name);
|
BIO_METHOD *BIO_meth_new(int type, const char *name);
|
||||||
void BIO_meth_free(BIO_METHOD *biom);
|
void BIO_meth_free(BIO_METHOD *biom);
|
||||||
int (*BIO_meth_get_write(const BIO_METHOD *biom)) (BIO *, const char *, int);
|
|
||||||
int (*BIO_meth_get_write_ex(const BIO_METHOD *biom)) (BIO *, const char *, size_t,
|
|
||||||
size_t *);
|
|
||||||
int BIO_meth_set_write(BIO_METHOD *biom,
|
int BIO_meth_set_write(BIO_METHOD *biom,
|
||||||
int (*write)(BIO *, const char *, int));
|
int (*write)(BIO *, const char *, int));
|
||||||
int BIO_meth_set_write_ex(BIO_METHOD *biom,
|
int BIO_meth_set_write_ex(BIO_METHOD *biom,
|
||||||
int (*bwrite)(BIO *, const char *, size_t, size_t *));
|
int (*bwrite)(BIO *, const char *, size_t, size_t *));
|
||||||
int (*BIO_meth_get_read(const BIO_METHOD *biom)) (BIO *, char *, int);
|
int BIO_meth_set_sendmmsg(BIO_METHOD *biom,
|
||||||
int (*BIO_meth_get_read_ex(const BIO_METHOD *biom)) (BIO *, char *, size_t, size_t *);
|
int (*f)(BIO *, BIO_MSG *, size_t, size_t,
|
||||||
|
uint64_t, size_t *));
|
||||||
int BIO_meth_set_read(BIO_METHOD *biom,
|
int BIO_meth_set_read(BIO_METHOD *biom,
|
||||||
int (*read)(BIO *, char *, int));
|
int (*read)(BIO *, char *, int));
|
||||||
int BIO_meth_set_read_ex(BIO_METHOD *biom,
|
int BIO_meth_set_read_ex(BIO_METHOD *biom,
|
||||||
int (*bread)(BIO *, char *, size_t, size_t *));
|
int (*bread)(BIO *, char *, size_t, size_t *));
|
||||||
int (*BIO_meth_get_puts(const BIO_METHOD *biom)) (BIO *, const char *);
|
int BIO_meth_set_recvmmsg(BIO_METHOD *biom,
|
||||||
|
int (*f)(BIO *, BIO_MSG *, size_t, size_t,
|
||||||
|
uint64_t, size_t *));
|
||||||
int BIO_meth_set_puts(BIO_METHOD *biom,
|
int BIO_meth_set_puts(BIO_METHOD *biom,
|
||||||
int (*puts)(BIO *, const char *));
|
int (*puts)(BIO *, const char *));
|
||||||
int (*BIO_meth_get_gets(const BIO_METHOD *biom)) (BIO *, char *, int);
|
|
||||||
int BIO_meth_set_gets(BIO_METHOD *biom,
|
int BIO_meth_set_gets(BIO_METHOD *biom,
|
||||||
int (*gets) (BIO *, char *, int));
|
int (*ossl_gets)(BIO *, char *, int));
|
||||||
long (*BIO_meth_get_ctrl(const BIO_METHOD *biom)) (BIO *, int, long, void *);
|
|
||||||
int BIO_meth_set_ctrl(BIO_METHOD *biom,
|
int BIO_meth_set_ctrl(BIO_METHOD *biom,
|
||||||
long (*ctrl)(BIO *, int, long, void *));
|
long (*ctrl)(BIO *, int, long, void *));
|
||||||
int (*BIO_meth_get_create(const BIO_METHOD *bion)) (BIO *);
|
|
||||||
int BIO_meth_set_create(BIO_METHOD *biom, int (*create)(BIO *));
|
int BIO_meth_set_create(BIO_METHOD *biom, int (*create)(BIO *));
|
||||||
int (*BIO_meth_get_destroy(const BIO_METHOD *biom)) (BIO *);
|
|
||||||
int BIO_meth_set_destroy(BIO_METHOD *biom, int (*destroy)(BIO *));
|
int BIO_meth_set_destroy(BIO_METHOD *biom, int (*destroy)(BIO *));
|
||||||
long (*BIO_meth_get_callback_ctrl(const BIO_METHOD *biom))
|
|
||||||
(BIO *, int, BIO_info_cb *);
|
|
||||||
int BIO_meth_set_callback_ctrl(BIO_METHOD *biom,
|
int BIO_meth_set_callback_ctrl(BIO_METHOD *biom,
|
||||||
long (*callback_ctrl)(BIO *, int,
|
long (*callback_ctrl)(BIO *, int,
|
||||||
BIO_info_cb *));
|
BIO_info_cb *));
|
||||||
|
#ifndef OPENSSL_NO_DEPRECATED_3_5
|
||||||
|
OSSL_DEPRECATEDIN_3_5 int (*BIO_meth_get_write(const BIO_METHOD *biom))(BIO *, const char *,
|
||||||
|
int);
|
||||||
|
OSSL_DEPRECATEDIN_3_5 int (*BIO_meth_get_write_ex(const BIO_METHOD *biom))(BIO *, const char *,
|
||||||
|
size_t, size_t *);
|
||||||
|
OSSL_DEPRECATEDIN_3_5 int (*BIO_meth_get_sendmmsg(const BIO_METHOD *biom))(BIO *, BIO_MSG *,
|
||||||
|
size_t, size_t,
|
||||||
|
uint64_t, size_t *);
|
||||||
|
OSSL_DEPRECATEDIN_3_5 int (*BIO_meth_get_read(const BIO_METHOD *biom))(BIO *, char *, int);
|
||||||
|
OSSL_DEPRECATEDIN_3_5 int (*BIO_meth_get_read_ex(const BIO_METHOD *biom))(BIO *, char *,
|
||||||
|
size_t, size_t *);
|
||||||
|
OSSL_DEPRECATEDIN_3_5 int (*BIO_meth_get_recvmmsg(const BIO_METHOD *biom))(BIO *, BIO_MSG *,
|
||||||
|
size_t, size_t,
|
||||||
|
uint64_t, size_t *);
|
||||||
|
OSSL_DEPRECATEDIN_3_5 int (*BIO_meth_get_puts(const BIO_METHOD *biom))(BIO *, const char *);
|
||||||
|
OSSL_DEPRECATEDIN_3_5 int (*BIO_meth_get_gets(const BIO_METHOD *biom))(BIO *, char *, int);
|
||||||
|
OSSL_DEPRECATEDIN_3_5 long (*BIO_meth_get_ctrl(const BIO_METHOD *biom))(BIO *, int,
|
||||||
|
long, void *);
|
||||||
|
OSSL_DEPRECATEDIN_3_5 int (*BIO_meth_get_create(const BIO_METHOD *bion))(BIO *);
|
||||||
|
OSSL_DEPRECATEDIN_3_5 int (*BIO_meth_get_destroy(const BIO_METHOD *biom))(BIO *);
|
||||||
|
OSSL_DEPRECATEDIN_3_5 long (*BIO_meth_get_callback_ctrl(const BIO_METHOD *biom))(BIO *, int,
|
||||||
|
BIO_info_cb *);
|
||||||
|
#endif
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,84 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
* Generated by util/mkerr.pl DO NOT EDIT
|
* 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
|
* this file except in compliance with the License. You can obtain a copy
|
||||||
* in the file LICENSE in the source distribution or at
|
* in the file LICENSE in the source distribution or at
|
||||||
* https://www.openssl.org/source/license.html
|
* https://www.openssl.org/source/license.html
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef HEADER_BIOERR_H
|
#ifndef OPENSSL_BIOERR_H
|
||||||
# define HEADER_BIOERR_H
|
#define OPENSSL_BIOERR_H
|
||||||
|
#pragma once
|
||||||
|
|
||||||
# ifndef HEADER_SYMHACKS_H
|
#include <openssl/opensslconf.h>
|
||||||
#include <openssl/symhacks.h>
|
#include <openssl/symhacks.h>
|
||||||
# endif
|
#include <openssl/cryptoerr_legacy.h>
|
||||||
|
|
||||||
# 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
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* BIO reason codes.
|
* BIO reason codes.
|
||||||
@@ -89,6 +25,7 @@ int ERR_load_BIO_strings(void);
|
|||||||
#define BIO_R_BAD_FOPEN_MODE 101
|
#define BIO_R_BAD_FOPEN_MODE 101
|
||||||
#define BIO_R_BROKEN_PIPE 124
|
#define BIO_R_BROKEN_PIPE 124
|
||||||
#define BIO_R_CONNECT_ERROR 103
|
#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_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET 107
|
||||||
#define BIO_R_GETSOCKNAME_ERROR 132
|
#define BIO_R_GETSOCKNAME_ERROR 132
|
||||||
#define BIO_R_GETSOCKNAME_TRUNCATED_ADDRESS 133
|
#define BIO_R_GETSOCKNAME_TRUNCATED_ADDRESS 133
|
||||||
@@ -98,20 +35,27 @@ int ERR_load_BIO_strings(void);
|
|||||||
#define BIO_R_IN_USE 123
|
#define BIO_R_IN_USE 123
|
||||||
#define BIO_R_LENGTH_TOO_LONG 102
|
#define BIO_R_LENGTH_TOO_LONG 102
|
||||||
#define BIO_R_LISTEN_V6_ONLY 136
|
#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_LOOKUP_RETURNED_NOTHING 142
|
||||||
#define BIO_R_MALFORMED_HOST_OR_SERVICE 130
|
#define BIO_R_MALFORMED_HOST_OR_SERVICE 130
|
||||||
#define BIO_R_NBIO_CONNECT_ERROR 110
|
#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_ACCEPT_ADDR_OR_SERVICE_SPECIFIED 143
|
||||||
#define BIO_R_NO_HOSTNAME_OR_SERVICE_SPECIFIED 144
|
#define BIO_R_NO_HOSTNAME_OR_SERVICE_SPECIFIED 144
|
||||||
#define BIO_R_NO_PORT_DEFINED 113
|
#define BIO_R_NO_PORT_DEFINED 113
|
||||||
#define BIO_R_NO_SUCH_FILE 128
|
#define BIO_R_NO_SUCH_FILE 128
|
||||||
# define BIO_R_NULL_PARAMETER 115
|
#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_BIND_SOCKET 117
|
||||||
#define BIO_R_UNABLE_TO_CREATE_SOCKET 118
|
#define BIO_R_UNABLE_TO_CREATE_SOCKET 118
|
||||||
#define BIO_R_UNABLE_TO_KEEPALIVE 137
|
#define BIO_R_UNABLE_TO_KEEPALIVE 137
|
||||||
#define BIO_R_UNABLE_TO_LISTEN_SOCKET 119
|
#define BIO_R_UNABLE_TO_LISTEN_SOCKET 119
|
||||||
#define BIO_R_UNABLE_TO_NODELAY 138
|
#define BIO_R_UNABLE_TO_NODELAY 138
|
||||||
#define BIO_R_UNABLE_TO_REUSEADDR 139
|
#define BIO_R_UNABLE_TO_REUSEADDR 139
|
||||||
|
#define BIO_R_UNABLE_TO_TFO 109
|
||||||
#define BIO_R_UNAVAILABLE_IP_FAMILY 145
|
#define BIO_R_UNAVAILABLE_IP_FAMILY 145
|
||||||
#define BIO_R_UNINITIALIZED 120
|
#define BIO_R_UNINITIALIZED 120
|
||||||
#define BIO_R_UNKNOWN_INFO_TYPE 140
|
#define BIO_R_UNKNOWN_INFO_TYPE 140
|
||||||
@@ -120,5 +64,7 @@ int ERR_load_BIO_strings(void);
|
|||||||
#define BIO_R_UNSUPPORTED_PROTOCOL_FAMILY 131
|
#define BIO_R_UNSUPPORTED_PROTOCOL_FAMILY 131
|
||||||
#define BIO_R_WRITE_TO_READ_ONLY_BIO 126
|
#define BIO_R_WRITE_TO_READ_ONLY_BIO 126
|
||||||
#define BIO_R_WSASTARTUP 122
|
#define BIO_R_WSASTARTUP 122
|
||||||
|
#define BIO_R_PORT_MISMATCH 150
|
||||||
|
#define BIO_R_PEER_ADDR_NOT_AVAILABLE 151
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user