@myerscarpenter/quest-dev 1.4.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +7 -0
- package/.github/workflows/docs.yml +45 -0
- package/.github/workflows/publish.yml +11 -1
- package/README.md +27 -0
- package/build/cast/decoder.d.ts +48 -0
- package/build/cast/decoder.d.ts.map +1 -0
- package/build/cast/decoder.js +152 -0
- package/build/cast/decoder.js.map +1 -0
- package/build/cast/session.d.ts +87 -0
- package/build/cast/session.d.ts.map +1 -0
- package/build/cast/session.js +565 -0
- package/build/cast/session.js.map +1 -0
- package/build/commands/logcat.d.ts.map +1 -1
- package/build/commands/logcat.js +7 -6
- package/build/commands/logcat.js.map +1 -1
- package/build/commands/screenshot.d.ts.map +1 -1
- package/build/commands/screenshot.js +17 -20
- package/build/commands/screenshot.js.map +1 -1
- package/build/commands/stay-awake.d.ts +2 -15
- package/build/commands/stay-awake.d.ts.map +1 -1
- package/build/commands/stay-awake.js +14 -77
- package/build/commands/stay-awake.js.map +1 -1
- package/build/daemon/cast-manager.d.ts +42 -0
- package/build/daemon/cast-manager.d.ts.map +1 -0
- package/build/daemon/cast-manager.js +243 -0
- package/build/daemon/cast-manager.js.map +1 -0
- package/build/daemon/client.d.ts +40 -0
- package/build/daemon/client.d.ts.map +1 -0
- package/build/daemon/client.js +133 -0
- package/build/daemon/client.js.map +1 -0
- package/build/daemon/daemon.d.ts +20 -0
- package/build/daemon/daemon.d.ts.map +1 -0
- package/build/daemon/daemon.js +130 -0
- package/build/daemon/daemon.js.map +1 -0
- package/build/daemon/deploy.d.ts +44 -0
- package/build/daemon/deploy.d.ts.map +1 -0
- package/build/daemon/deploy.js +230 -0
- package/build/daemon/deploy.js.map +1 -0
- package/build/daemon/logcat-manager.d.ts +39 -0
- package/build/daemon/logcat-manager.d.ts.map +1 -0
- package/build/daemon/logcat-manager.js +194 -0
- package/build/daemon/logcat-manager.js.map +1 -0
- package/build/daemon/server.d.ts +19 -0
- package/build/daemon/server.d.ts.map +1 -0
- package/build/daemon/server.js +482 -0
- package/build/daemon/server.js.map +1 -0
- package/build/daemon/stay-awake-manager.d.ts +22 -0
- package/build/daemon/stay-awake-manager.d.ts.map +1 -0
- package/build/daemon/stay-awake-manager.js +74 -0
- package/build/daemon/stay-awake-manager.js.map +1 -0
- package/build/index.js +272 -45
- package/build/index.js.map +1 -1
- package/build/public/dashboard.js +749 -0
- package/build/public/index.html +12 -0
- package/build/public/style.css +106 -0
- package/build/utils/adb.d.ts +6 -0
- package/build/utils/adb.d.ts.map +1 -1
- package/build/utils/adb.js +62 -66
- package/build/utils/adb.js.map +1 -1
- package/build/utils/casting-apk.d.ts +40 -0
- package/build/utils/casting-apk.d.ts.map +1 -0
- package/build/utils/casting-apk.js +252 -0
- package/build/utils/casting-apk.js.map +1 -0
- package/build/utils/config.d.ts +5 -3
- package/build/utils/config.d.ts.map +1 -1
- package/build/utils/config.js +18 -38
- package/build/utils/config.js.map +1 -1
- package/build/utils/exec.d.ts +5 -0
- package/build/utils/exec.d.ts.map +1 -1
- package/build/utils/exec.js +17 -0
- package/build/utils/exec.js.map +1 -1
- package/build/utils/filename.d.ts +7 -1
- package/build/utils/filename.d.ts.map +1 -1
- package/build/utils/filename.js +17 -2
- package/build/utils/filename.js.map +1 -1
- package/build/utils/filename.test.js +33 -1
- package/build/utils/filename.test.js.map +1 -1
- package/build/utils/jpeg-comment.d.ts +14 -0
- package/build/utils/jpeg-comment.d.ts.map +1 -0
- package/build/utils/jpeg-comment.js +28 -0
- package/build/utils/jpeg-comment.js.map +1 -0
- package/build/utils/test-properties.d.ts +34 -0
- package/build/utils/test-properties.d.ts.map +1 -0
- package/build/utils/test-properties.js +73 -0
- package/build/utils/test-properties.js.map +1 -0
- package/package.json +11 -5
- package/packages/cast2-protocol/README.md +86 -0
- package/packages/cast2-protocol/docs/_config.yml +4 -0
- package/packages/cast2-protocol/docs/feature-flags.md +102 -0
- package/packages/cast2-protocol/docs/index.md +24 -0
- package/packages/cast2-protocol/docs/open-investigations.md +149 -0
- package/packages/cast2-protocol/docs/protocol.md +602 -0
- package/packages/cast2-protocol/package.json +46 -0
- package/packages/cast2-protocol/src/constants.ts +65 -0
- package/packages/cast2-protocol/src/index.ts +7 -0
- package/packages/cast2-protocol/src/mgik.ts +69 -0
- package/packages/cast2-protocol/src/mud.ts +294 -0
- package/packages/cast2-protocol/src/pose.ts +99 -0
- package/packages/cast2-protocol/src/resolutions.ts +34 -0
- package/packages/cast2-protocol/src/types.ts +64 -0
- package/packages/cast2-protocol/src/xrsp.ts +73 -0
- package/packages/cast2-protocol/tests/mgik.test.ts +80 -0
- package/packages/cast2-protocol/tests/mud.test.ts +295 -0
- package/packages/cast2-protocol/tests/pose.test.ts +173 -0
- package/packages/cast2-protocol/tests/xrsp.test.ts +90 -0
- package/packages/cast2-protocol/tsconfig.json +20 -0
- package/pnpm-workspace.yaml +2 -0
- package/src/cast/decoder.ts +178 -0
- package/src/cast/session.ts +708 -0
- package/src/commands/logcat.ts +6 -5
- package/src/commands/screenshot.ts +19 -13
- package/src/commands/stay-awake.ts +22 -91
- package/src/daemon/adbkit-apkreader.d.ts +14 -0
- package/src/daemon/cast-manager.ts +282 -0
- package/src/daemon/client.ts +166 -0
- package/src/daemon/daemon.ts +169 -0
- package/src/daemon/deploy.ts +307 -0
- package/src/daemon/logcat-manager.ts +229 -0
- package/src/daemon/server.ts +595 -0
- package/src/daemon/stay-awake-manager.ts +83 -0
- package/src/index.ts +326 -56
- package/src/public/dashboard.js +288 -0
- package/src/public/index.html +12 -0
- package/src/public/style.css +106 -0
- package/src/utils/adb.ts +70 -57
- package/src/utils/casting-apk.ts +276 -0
- package/src/utils/config.ts +18 -36
- package/src/utils/exec.ts +20 -0
- package/src/utils/filename.test.ts +41 -1
- package/src/utils/filename.ts +18 -2
- package/src/utils/jpeg-comment.ts +30 -0
- package/src/utils/test-properties.ts +94 -0
- package/tests/cast/auto-layer.test.ts +87 -0
- package/tests/cast/decoder.test.ts +82 -0
- package/tests/cast/session-restart.test.ts +107 -0
- package/tests/config.test.ts +17 -22
- package/tests/daemon/api-status.test.ts +82 -0
- package/tests/daemon/cast-manager.test.ts +69 -0
- package/tests/daemon/mjpeg-stream.test.ts +144 -0
- package/tests/daemon/pose-endpoint.test.ts +63 -0
- package/tests/daemon/start-guard.test.ts +77 -0
- package/vitest.config.ts +10 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Meta Scriptable Testing API (content://com.oculus.rc) utilities.
|
|
3
|
+
*
|
|
4
|
+
* Shared between stay-awake and cast commands for managing test mode
|
|
5
|
+
* properties (guardian, autosleep, dialogs, proximity).
|
|
6
|
+
*/
|
|
7
|
+
export interface TestProperties {
|
|
8
|
+
disable_guardian: boolean;
|
|
9
|
+
disable_dialogs: boolean;
|
|
10
|
+
disable_autosleep: boolean;
|
|
11
|
+
set_proximity_close: boolean;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Build ADB args for SET_PROPERTY call.
|
|
15
|
+
*/
|
|
16
|
+
export declare function buildSetPropertyArgs(pin: string, enabled: boolean): string[];
|
|
17
|
+
/**
|
|
18
|
+
* Parse GET_PROPERTY Bundle output into structured data.
|
|
19
|
+
* Input: "Bundle[{disable_guardian=true, set_proximity_close=true, ...}]"
|
|
20
|
+
*/
|
|
21
|
+
export declare function parseTestProperties(output: string): TestProperties;
|
|
22
|
+
/**
|
|
23
|
+
* Call SET_PROPERTY to enable or disable test mode.
|
|
24
|
+
*/
|
|
25
|
+
export declare function setTestProperties(pin: string, enabled: boolean): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* Call GET_PROPERTY and return parsed test properties.
|
|
28
|
+
*/
|
|
29
|
+
export declare function getTestProperties(): Promise<TestProperties>;
|
|
30
|
+
/**
|
|
31
|
+
* Format test properties for display.
|
|
32
|
+
*/
|
|
33
|
+
export declare function formatTestProperties(props: TestProperties): string;
|
|
34
|
+
//# sourceMappingURL=test-properties.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-properties.d.ts","sourceRoot":"","sources":["../../src/utils/test-properties.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,MAAM,WAAW,cAAc;IAC7B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,eAAe,EAAE,OAAO,CAAC;IACzB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,mBAAmB,EAAE,OAAO,CAAC;CAC9B;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,EAAE,CAW5E;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAoBlE;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,IAAI,CAAC,CAGf;AAED;;GAEG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,cAAc,CAAC,CAOjE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,CAQlE"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Meta Scriptable Testing API (content://com.oculus.rc) utilities.
|
|
3
|
+
*
|
|
4
|
+
* Shared between stay-awake and cast commands for managing test mode
|
|
5
|
+
* properties (guardian, autosleep, dialogs, proximity).
|
|
6
|
+
*/
|
|
7
|
+
import { execCommand, execCommandFull } from "./exec.js";
|
|
8
|
+
import { adbArgs } from "./adb.js";
|
|
9
|
+
/**
|
|
10
|
+
* Build ADB args for SET_PROPERTY call.
|
|
11
|
+
*/
|
|
12
|
+
export function buildSetPropertyArgs(pin, enabled) {
|
|
13
|
+
return [
|
|
14
|
+
"shell", "content", "call",
|
|
15
|
+
"--uri", "content://com.oculus.rc",
|
|
16
|
+
"--method", "SET_PROPERTY",
|
|
17
|
+
"--extra", `disable_guardian:b:${enabled}`,
|
|
18
|
+
"--extra", `disable_dialogs:b:${enabled}`,
|
|
19
|
+
"--extra", `disable_autosleep:b:${enabled}`,
|
|
20
|
+
"--extra", `set_proximity_close:b:${enabled}`,
|
|
21
|
+
"--extra", `PIN:s:${pin}`,
|
|
22
|
+
];
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Parse GET_PROPERTY Bundle output into structured data.
|
|
26
|
+
* Input: "Bundle[{disable_guardian=true, set_proximity_close=true, ...}]"
|
|
27
|
+
*/
|
|
28
|
+
export function parseTestProperties(output) {
|
|
29
|
+
const defaults = {
|
|
30
|
+
disable_guardian: false,
|
|
31
|
+
disable_dialogs: false,
|
|
32
|
+
disable_autosleep: false,
|
|
33
|
+
set_proximity_close: false,
|
|
34
|
+
};
|
|
35
|
+
const match = output.match(/Bundle\[\{(.+)\}\]/);
|
|
36
|
+
if (!match)
|
|
37
|
+
return defaults;
|
|
38
|
+
const pairs = match[1].split(",").map((s) => s.trim());
|
|
39
|
+
for (const pair of pairs) {
|
|
40
|
+
const [key, value] = pair.split("=");
|
|
41
|
+
if (key && value && key in defaults) {
|
|
42
|
+
defaults[key] = value === "true";
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return defaults;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Call SET_PROPERTY to enable or disable test mode.
|
|
49
|
+
*/
|
|
50
|
+
export async function setTestProperties(pin, enabled) {
|
|
51
|
+
const args = adbArgs(...buildSetPropertyArgs(pin, enabled));
|
|
52
|
+
await execCommand("adb", args);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Call GET_PROPERTY and return parsed test properties.
|
|
56
|
+
*/
|
|
57
|
+
export async function getTestProperties() {
|
|
58
|
+
const result = await execCommandFull("adb", adbArgs("shell", "content", "call", "--uri", "content://com.oculus.rc", "--method", "GET_PROPERTY"));
|
|
59
|
+
return parseTestProperties(result.stdout);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Format test properties for display.
|
|
63
|
+
*/
|
|
64
|
+
export function formatTestProperties(props) {
|
|
65
|
+
const lines = [
|
|
66
|
+
` Guardian disabled: ${props.disable_guardian}`,
|
|
67
|
+
` Dialogs disabled: ${props.disable_dialogs}`,
|
|
68
|
+
` Autosleep disabled: ${props.disable_autosleep}`,
|
|
69
|
+
` Proximity close: ${props.set_proximity_close}`,
|
|
70
|
+
];
|
|
71
|
+
return lines.join("\n");
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=test-properties.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-properties.js","sourceRoot":"","sources":["../../src/utils/test-properties.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACzD,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AASnC;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAAW,EAAE,OAAgB;IAChE,OAAO;QACL,OAAO,EAAE,SAAS,EAAE,MAAM;QAC1B,OAAO,EAAE,yBAAyB;QAClC,UAAU,EAAE,cAAc;QAC1B,SAAS,EAAE,sBAAsB,OAAO,EAAE;QAC1C,SAAS,EAAE,qBAAqB,OAAO,EAAE;QACzC,SAAS,EAAE,uBAAuB,OAAO,EAAE;QAC3C,SAAS,EAAE,yBAAyB,OAAO,EAAE;QAC7C,SAAS,EAAE,SAAS,GAAG,EAAE;KAC1B,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAc;IAChD,MAAM,QAAQ,GAAmB;QAC/B,gBAAgB,EAAE,KAAK;QACvB,eAAe,EAAE,KAAK;QACtB,iBAAiB,EAAE,KAAK;QACxB,mBAAmB,EAAE,KAAK;KAC3B,CAAC;IAEF,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;IACjD,IAAI,CAAC,KAAK;QAAE,OAAO,QAAQ,CAAC;IAE5B,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IACvD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACrC,IAAI,GAAG,IAAI,KAAK,IAAI,GAAG,IAAI,QAAQ,EAAE,CAAC;YACpC,QAAQ,CAAC,GAA2B,CAAC,GAAG,KAAK,KAAK,MAAM,CAAC;QAC3D,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,GAAW,EACX,OAAgB;IAEhB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,oBAAoB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;IAC5D,MAAM,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;AACjC,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,KAAK,EAAE,OAAO,CACjD,OAAO,EAAE,SAAS,EAAE,MAAM,EAC1B,OAAO,EAAE,yBAAyB,EAClC,UAAU,EAAE,cAAc,CAC3B,CAAC,CAAC;IACH,OAAO,mBAAmB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AAC5C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAAqB;IACxD,MAAM,KAAK,GAAG;QACZ,yBAAyB,KAAK,CAAC,gBAAgB,EAAE;QACjD,wBAAwB,KAAK,CAAC,eAAe,EAAE;QAC/C,yBAAyB,KAAK,CAAC,iBAAiB,EAAE;QAClD,wBAAwB,KAAK,CAAC,mBAAmB,EAAE;KACpD,CAAC;IACF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@myerscarpenter/quest-dev",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "CLI tools for Meta Quest development — stay awake, screenshots, URL opening, logcat, and battery via ADB",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -9,13 +9,13 @@
|
|
|
9
9
|
"main": "./build/index.js",
|
|
10
10
|
"scripts": {
|
|
11
11
|
"clean": "rm -rf build",
|
|
12
|
-
"build": "pnpm run clean && tsc && chmod +x build/index.js",
|
|
12
|
+
"build": "pnpm -r run build && pnpm run clean && tsc && mkdir -p build/public && cp src/public/index.html src/public/style.css build/public/ && npx esbuild src/public/dashboard.js --bundle --format=iife --outfile=build/public/dashboard.js && chmod +x build/index.js",
|
|
13
13
|
"start": "pnpm run build && node build/index.js",
|
|
14
14
|
"test": "vitest run",
|
|
15
15
|
"test:watch": "vitest",
|
|
16
16
|
"test:ui": "vitest --ui",
|
|
17
17
|
"test:coverage": "vitest run --coverage",
|
|
18
|
-
"install:global": "pnpm run build && pnpm
|
|
18
|
+
"install:global": "pnpm -r run build && pnpm run build && pnpm link --global",
|
|
19
19
|
"version:patch": "pnpm version patch",
|
|
20
20
|
"version:minor": "pnpm version minor",
|
|
21
21
|
"version:major": "pnpm version major"
|
|
@@ -31,14 +31,19 @@
|
|
|
31
31
|
"xr",
|
|
32
32
|
"screenshot"
|
|
33
33
|
],
|
|
34
|
-
"author": "",
|
|
34
|
+
"author": "Myers Carpenter <myers@maski.org>",
|
|
35
35
|
"license": "MIT",
|
|
36
36
|
"repository": {
|
|
37
37
|
"type": "git",
|
|
38
38
|
"url": "https://github.com/myers/quest-dev"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"
|
|
41
|
+
"@myerscarpenter/cast2-protocol": "workspace:*",
|
|
42
|
+
"@fastify/static": "^9.0.0",
|
|
43
|
+
"adbkit-apkreader": "^3.2.0",
|
|
44
|
+
"fastify": "^5.8.2",
|
|
45
|
+
"htm": "^3.1.1",
|
|
46
|
+
"preact": "^10.29.0",
|
|
42
47
|
"which": "^4.0.0",
|
|
43
48
|
"yargs": "^18.0.0"
|
|
44
49
|
},
|
|
@@ -48,6 +53,7 @@
|
|
|
48
53
|
"@types/yargs": "^17.0.33",
|
|
49
54
|
"@vitest/ui": "^4.0.3",
|
|
50
55
|
"c8": "^10.1.3",
|
|
56
|
+
"esbuild": "^0.27.4",
|
|
51
57
|
"typescript": "^5.9.2",
|
|
52
58
|
"vitest": "^4.0.3"
|
|
53
59
|
},
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# @myerscarpenter/cast2-protocol
|
|
2
|
+
|
|
3
|
+
Pure TypeScript implementation of the Meta Quest **Cast 2.0** binary protocol — XRSP framing, MGIK sub-headers, MUD message builders/parsers, pose math, and resolution presets.
|
|
4
|
+
|
|
5
|
+
Zero runtime dependencies. Works in Node.js ≥ 18.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @myerscarpenter/cast2-protocol
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import {
|
|
17
|
+
packXrsp,
|
|
18
|
+
packMgikSub,
|
|
19
|
+
buildInit,
|
|
20
|
+
buildPose,
|
|
21
|
+
buildConfig,
|
|
22
|
+
createPoseState,
|
|
23
|
+
updatePose,
|
|
24
|
+
CAST_PORT,
|
|
25
|
+
RESOLUTIONS,
|
|
26
|
+
} from "@myerscarpenter/cast2-protocol";
|
|
27
|
+
|
|
28
|
+
// Build an INIT command
|
|
29
|
+
const subMagic = 0xdeadbeef; // learned from Quest's first message
|
|
30
|
+
const payload = buildInit(subMagic, /* seq */ 0);
|
|
31
|
+
const frame = packXrsp(/* seq */ 0, payload);
|
|
32
|
+
|
|
33
|
+
// Pose management
|
|
34
|
+
let pose = createPoseState();
|
|
35
|
+
pose = updatePose(pose, { dYaw: 0.5, dForward: 1.0 });
|
|
36
|
+
const posePayload = buildPose(subMagic, 1, pose);
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## API Overview
|
|
40
|
+
|
|
41
|
+
### XRSP (framing layer)
|
|
42
|
+
- `packXrsp(seq, payload, flags?, topic?)` — pack an XRSP frame
|
|
43
|
+
- `parseXrspHeader(data)` — parse 8-byte XRSP header
|
|
44
|
+
- `xrspPayloadSize(header)` — compute payload size from header
|
|
45
|
+
|
|
46
|
+
### MGIK (sub-header)
|
|
47
|
+
- `packMgikSub(subMagic, msgSeq)` — pack 24-byte MGIK sub-header
|
|
48
|
+
- `parseMgikSub(data)` — parse MGIK sub-header
|
|
49
|
+
- `detectSubMagic(payload)` — detect sub_magic from Quest's initial message
|
|
50
|
+
- `isMgikMagic(payload)` — check for "MGIK" magic bytes
|
|
51
|
+
|
|
52
|
+
### MUD (message builders)
|
|
53
|
+
- `buildInit`, `buildConfig`, `buildKeepalive`, `buildShortAck`
|
|
54
|
+
- `buildPose`, `buildDisplayConfig`, `buildDisconnect`
|
|
55
|
+
- `buildSetProperty`, `buildVirtualMouse`
|
|
56
|
+
- `buildInputForwardingState`, `buildStartInputForwarding`, `buildActivateLayer`
|
|
57
|
+
- `buildMud` — arbitrary MUD message
|
|
58
|
+
- `parseLayerConfiguration` — parse LayerConfiguration responses
|
|
59
|
+
- `packMudString` / `parseMudString` — length-prefixed string encoding
|
|
60
|
+
|
|
61
|
+
### Pose Math
|
|
62
|
+
- `createPoseState()` — identity pose at origin
|
|
63
|
+
- `eulerToQuat(yaw, pitch)` — euler angles to quaternion
|
|
64
|
+
- `updatePose(state, delta)` — apply incremental movement
|
|
65
|
+
- `setPoseOffset(state, offset)` — set absolute offset
|
|
66
|
+
- `screenToYawPitch(x, y, ...)` — screen coordinates to yaw/pitch
|
|
67
|
+
|
|
68
|
+
### Resolutions
|
|
69
|
+
- `RESOLUTIONS` — preset map (`720p`, `1080p`, `native`)
|
|
70
|
+
- `resolveResolution(name?, width?, height?)` — resolve to width/height
|
|
71
|
+
|
|
72
|
+
### Constants
|
|
73
|
+
All protocol constants are exported: `CAST_PORT`, `QUEST_CAST_PORT`, `XRSP_HEADER_SIZE`, `MGIK_MAGIC`, command IDs (`CMD_POSE`, `CMD_INIT`, etc.), eye selectors (`EYE_LEFT`, `EYE_RIGHT`, `EYE_STEREO`), layer types, and more.
|
|
74
|
+
|
|
75
|
+
### Types
|
|
76
|
+
- `XrspHeader`, `MgikSubHeader`, `LayerInfo`
|
|
77
|
+
- `PoseState`, `PoseDelta`, `PoseOffset`
|
|
78
|
+
- `Resolution`
|
|
79
|
+
|
|
80
|
+
## Documentation
|
|
81
|
+
|
|
82
|
+
Full protocol documentation is available at [myers.github.io/quest-dev](https://myers.github.io/quest-dev/).
|
|
83
|
+
|
|
84
|
+
## License
|
|
85
|
+
|
|
86
|
+
MIT
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: MQDH Feature Flags
|
|
3
|
+
layout: default
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# MQDH Feature Flags (Gatekeepers)
|
|
7
|
+
|
|
8
|
+
Known feature flags used by Meta Quest Developer Hub for Cast 2.0 configuration.
|
|
9
|
+
|
|
10
|
+
## Magic Island / Casting
|
|
11
|
+
|
|
12
|
+
| Flag | Description |
|
|
13
|
+
|------|-------------|
|
|
14
|
+
| `mqdh_xplat_magic_island_feature_wireless_casting_2` | Wireless casting support |
|
|
15
|
+
| `mqdh_xplat_magic_island_feature_input_forwarding_2` | Input forwarding (mouse/keyboard/cursor) |
|
|
16
|
+
| `mqdh_xplat_magic_island_feature_gaze_click` | Gaze-based click via VirtualCamera pose |
|
|
17
|
+
| `mqdh_xplat_magic_island_text_forwarding` | Text input forwarding |
|
|
18
|
+
| `mqdh_xplat_magic_island_mic_audio` | Microphone audio |
|
|
19
|
+
| `mqdh_xplat_magic_island_force_reapply_fov` | Force reapply FOV |
|
|
20
|
+
| `mqdh_xplat_magic_island_system_monitor` | System monitor overlay |
|
|
21
|
+
| `mqdh_xplat_magic_island_panel_streaming` | Panel app streaming |
|
|
22
|
+
| `mqdh_xplat_magic_island_feature_casting_tour` | Casting onboarding tour |
|
|
23
|
+
| `xplat_magic_island_image_stabilization` | Image stabilization |
|
|
24
|
+
|
|
25
|
+
## Metacam / Screen Capture
|
|
26
|
+
|
|
27
|
+
| Flag | Description |
|
|
28
|
+
|------|-------------|
|
|
29
|
+
| `mqdh_metacam_screen_capture_v63` | Screen capture (OS v63+) |
|
|
30
|
+
| `mqdh_metacam_video_capture` | Video capture |
|
|
31
|
+
|
|
32
|
+
## Input Forwarding (legacy)
|
|
33
|
+
|
|
34
|
+
| Flag | Description |
|
|
35
|
+
|------|-------------|
|
|
36
|
+
| `mqdh_input_forwarding_feature` | Legacy input forwarding feature flag |
|
|
37
|
+
|
|
38
|
+
## Link
|
|
39
|
+
|
|
40
|
+
| Flag | Description |
|
|
41
|
+
|------|-------------|
|
|
42
|
+
| `mqdh_link_terminate_via_qlh` | Terminate Link via Quest Link Hub |
|
|
43
|
+
| `mqdh_link_dogfood_hub` | Link dogfood hub |
|
|
44
|
+
|
|
45
|
+
## Device Management
|
|
46
|
+
|
|
47
|
+
| Flag | Description |
|
|
48
|
+
|------|-------------|
|
|
49
|
+
| `mqdh_auto_disable_proximity_sensor` | Auto-disable prox sensor |
|
|
50
|
+
| `mqdh_disable_proximity_sensor_with_duration` | Timed prox sensor disable |
|
|
51
|
+
| `mqdh_collect_hmd_logs` | Collect headset logs |
|
|
52
|
+
| `mqdh_redesign_device_manager` | Redesigned device manager UI |
|
|
53
|
+
| `mqdh_quick_ble_connect_v2` | Quick BLE connect v2 |
|
|
54
|
+
| `mqdh_ble_security_fixes` | BLE security fixes |
|
|
55
|
+
| `mqdh_ignore_ble_already_connected` | Ignore BLE already connected state |
|
|
56
|
+
| `mqdh_release_channel` | Release channel support |
|
|
57
|
+
| `mqdh_release_channel_selector` | Release channel selector UI |
|
|
58
|
+
| `mqdh_system_apk` | System APK management |
|
|
59
|
+
| `mqdh_device_setup_ab_test` | Device setup A/B test |
|
|
60
|
+
|
|
61
|
+
## App / UI
|
|
62
|
+
|
|
63
|
+
| Flag | Description |
|
|
64
|
+
|------|-------------|
|
|
65
|
+
| `mqdh_redesign_home` | Redesigned home screen |
|
|
66
|
+
| `mqdh_redesign_settings` | Redesigned settings |
|
|
67
|
+
| `mqdh_logcat_redesign` | Redesigned logcat viewer |
|
|
68
|
+
| `mqdh_development_view` | Development view |
|
|
69
|
+
| `mqdh_enable_link_card` | Link card UI |
|
|
70
|
+
| `mqdh_enable_expanded_link_card` | Expanded link card UI |
|
|
71
|
+
| `mqdh_file_mananger_sync` | File manager sync (typo in original) |
|
|
72
|
+
| `mqdh_live_build_test_status` | Live build test status |
|
|
73
|
+
| `mqdh_in_app_sentiment_survey` | In-app sentiment survey |
|
|
74
|
+
| `mqdh_ai_companion` | AI companion feature |
|
|
75
|
+
| `mqdh_xr_projects_flythrough` | XR projects flythrough |
|
|
76
|
+
| `mqdh_enable_3p_network_impairment_tool` | Network impairment tool |
|
|
77
|
+
| `mqdh_audience_attestation_selection` | Audience attestation |
|
|
78
|
+
|
|
79
|
+
## Auto-Update
|
|
80
|
+
|
|
81
|
+
| Flag | Description |
|
|
82
|
+
|------|-------------|
|
|
83
|
+
| `mqdh_force_update_enabled_v2` | Force update enabled |
|
|
84
|
+
| `mqdh_force_update_internal_user` | Internal user update |
|
|
85
|
+
| `mqdh_force_update_safe_listed_user` | Safe-listed user |
|
|
86
|
+
| `mqdh_autoupdate_modal_workflow_public_v3` | Auto-update modal v3 |
|
|
87
|
+
| `mqdh_automated_adb_path_fixing_v2` | Automated ADB path fix |
|
|
88
|
+
|
|
89
|
+
## Dogfooding
|
|
90
|
+
|
|
91
|
+
| Flag | Description |
|
|
92
|
+
|------|-------------|
|
|
93
|
+
| `mqdh_dogfooding_hub` | Dogfooding hub |
|
|
94
|
+
| `mqdh_dogfooding_hub_bluetooth` | Dogfooding via BT |
|
|
95
|
+
| `mqdh_dogfooding_skip_nux` | Skip NUX for dogfood |
|
|
96
|
+
|
|
97
|
+
## Telemetry
|
|
98
|
+
|
|
99
|
+
| Flag | Description |
|
|
100
|
+
|------|-------------|
|
|
101
|
+
| `mqdh_unified_telemetry_consent_ui` | Telemetry consent UI |
|
|
102
|
+
| `mqdh_unified_telemetry_internal_only_test` | Internal telemetry test |
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Cast 2.0 Protocol Documentation
|
|
3
|
+
layout: default
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Cast 2.0 Protocol Documentation
|
|
7
|
+
|
|
8
|
+
Cast 2.0 is the binary protocol used by Meta Quest headsets for wireless video casting. It layers MGIK message framing inside XRSP transport frames, carrying H.264 video, pose data, input forwarding, and control commands over TCP.
|
|
9
|
+
|
|
10
|
+
This documentation covers the protocol wire format, message types, and known capabilities.
|
|
11
|
+
|
|
12
|
+
## Reference
|
|
13
|
+
|
|
14
|
+
- [Cast 2.0 Protocol Reference](protocol.md) — Wire format, handshake sequence, message types
|
|
15
|
+
- [MQDH Feature Flags](feature-flags.md) — Feature flag reference for Meta Quest Developer Hub
|
|
16
|
+
- [Unsupported Capabilities](open-investigations.md) — Audio, panel streaming, WiFi casting, and other known but unimplemented features
|
|
17
|
+
|
|
18
|
+
## Package
|
|
19
|
+
|
|
20
|
+
The TypeScript implementation is available as [`@myerscarpenter/cast2-protocol`](https://www.npmjs.com/package/@myerscarpenter/cast2-protocol) on npm.
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install @myerscarpenter/cast2-protocol
|
|
24
|
+
```
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Unsupported Capabilities
|
|
3
|
+
layout: default
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Unsupported Capabilities
|
|
7
|
+
|
|
8
|
+
Cast 2.0 supports more than video and pose. These are protocol capabilities that are known to exist but are **not yet implemented** in this package or in quest-dev.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Audio Streaming
|
|
13
|
+
|
|
14
|
+
The protocol carries audio alongside video. The Quest initializes its audio capture pipeline on every casting session but produces no output until the host explicitly enables it.
|
|
15
|
+
|
|
16
|
+
**Protocol support:**
|
|
17
|
+
- 48 kHz, stereo, 16-bit PCM (uncompressed)
|
|
18
|
+
- Two independent sources: app/system audio and microphone, mixed before transmission
|
|
19
|
+
- Host sends `SetAudioState(1)` (MUD type 503) to enable app audio
|
|
20
|
+
- Host sends `SetMicAudioState(1)` (MUD type 505) to enable microphone
|
|
21
|
+
- Mic requires the `magic_casting:support_mic_audio` server feature flag
|
|
22
|
+
- AudioSegment wire format: `i32(type=102) + i32(layerId) + i64(timestamp_us) + PCM payload`
|
|
23
|
+
- Read buffer is 7680 bytes (1920 samples per read)
|
|
24
|
+
- Default bitrate 160kbps, latency target 50ms
|
|
25
|
+
|
|
26
|
+
**Open questions:**
|
|
27
|
+
- What's the actual PCM frame size per packet?
|
|
28
|
+
- Is there a handshake or does audio just start flowing after `SetAudioState(1)`?
|
|
29
|
+
- Can app audio and mic be enabled independently?
|
|
30
|
+
- What latency is achievable over TCP?
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Panel Streaming
|
|
35
|
+
|
|
36
|
+
Panel streaming is a separate mode from eye buffer casting. Instead of streaming the VR compositor output, it streams individual 2D panel apps as separate layers, each with its own VirtualDisplay and input device.
|
|
37
|
+
|
|
38
|
+
**Protocol support:**
|
|
39
|
+
- Activated via broadcast intent: `com.oculus.magicislandcastingservice.ENABLE_PANEL_STREAMING`
|
|
40
|
+
- Deactivated via: `com.oculus.magicislandcastingservice.DISABLE_PANEL_STREAMING`
|
|
41
|
+
- Creates per-panel VirtualDevice (VirtualDisplay + VirtualMouse + VirtualKeyboard)
|
|
42
|
+
- Each 2D app gets a VOLUMETRIC_WINDOW(3) LayerConfig with name `{token}.{packageName}`
|
|
43
|
+
- CursorEvent input routes through VirtualDevice API, bypassing the normal InputFrameOverride path
|
|
44
|
+
- Requires the `panel_streaming` feature flag
|
|
45
|
+
|
|
46
|
+
**Open questions:**
|
|
47
|
+
- Does enabling panel streaming during an active cast session work?
|
|
48
|
+
- What LayerConfig messages appear on the wire?
|
|
49
|
+
- Does the video stream change (resolution, format, multiple streams)?
|
|
50
|
+
- Does CursorEvent produce actual clicks in panel apps?
|
|
51
|
+
- Is ActivateLayer (301) needed to select which panel to stream?
|
|
52
|
+
- Can panel streaming and eye buffer casting coexist?
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## WiFi Casting (No ADB Tunnel)
|
|
57
|
+
|
|
58
|
+
All current implementations use ADB USB tunneling (`adb reverse tcp:4445 tcp:4445`). The protocol also supports casting over WiFi.
|
|
59
|
+
|
|
60
|
+
**Open questions:**
|
|
61
|
+
- Does WiFi casting use the same protocol or add TLS?
|
|
62
|
+
- Is there a discovery/pairing phase before the TCP connection?
|
|
63
|
+
- Same port (4445) or different?
|
|
64
|
+
- Does MQDH use mDNS or another service discovery mechanism?
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Congestion Control
|
|
69
|
+
|
|
70
|
+
The protocol includes a congestion control system with configurable parameters. Not yet tested.
|
|
71
|
+
|
|
72
|
+
**Known properties (configurable via SetProperty):**
|
|
73
|
+
- `congestionControlWindow`: 1.0s
|
|
74
|
+
- `congestionControlDecreaseThreshold`: 2.0
|
|
75
|
+
- `congestionControlIncreaseThreshold`: 1.2
|
|
76
|
+
- `congestionControlMultiplicativeDecrease`: 0.85
|
|
77
|
+
- `congestionControlAdditiveIncrease`: 250,000 bits/sec
|
|
78
|
+
- `captureEncoderBitrate`: 40,000,000 bits/sec (40Mbps default)
|
|
79
|
+
|
|
80
|
+
**Open questions:**
|
|
81
|
+
- How does the Quest signal congestion to the host?
|
|
82
|
+
- Does adjusting these properties via SetProperty change stream quality?
|
|
83
|
+
- Is the encoder bitrate dynamically reduced under load?
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## FOV Adjustment
|
|
88
|
+
|
|
89
|
+
Two commands carry FOV-related fields.
|
|
90
|
+
|
|
91
|
+
**Protocol support:**
|
|
92
|
+
- `SetDeviceEyeFovConfig(inward, outward, up, down)` — 4 i32 params
|
|
93
|
+
- `UpdateCastingConfig` includes a `fovAdjustment` float field
|
|
94
|
+
- All zeros = use device defaults
|
|
95
|
+
|
|
96
|
+
**Open questions:**
|
|
97
|
+
- What visible effect does changing FOV have on the stream?
|
|
98
|
+
- Are the units degrees or radians?
|
|
99
|
+
- Does FOV adjustment change resolution or just crop?
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Image Stabilization
|
|
104
|
+
|
|
105
|
+
`UpdateCastingConfig` has an `imageStabilizationMode` field (defaults to 0). Related to the `image_stabilization` feature flag.
|
|
106
|
+
|
|
107
|
+
**Open questions:**
|
|
108
|
+
- What values are valid?
|
|
109
|
+
- What does stabilization mean in a VR casting context?
|
|
110
|
+
- Does enabling it affect latency?
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Lifecycle Commands
|
|
115
|
+
|
|
116
|
+
Three empty-payload MUD messages exist for development tooling:
|
|
117
|
+
|
|
118
|
+
| MUD Type | Command | Description |
|
|
119
|
+
|----------|---------|-------------|
|
|
120
|
+
| 500 | ReloadApp | Reload the casting service runtime |
|
|
121
|
+
| 502 | ToggleInspector | Toggle performance overlay |
|
|
122
|
+
| 504 | OpenDebugger | Open debugger port |
|
|
123
|
+
|
|
124
|
+
Not used by any known host implementation.
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## Dialog System
|
|
129
|
+
|
|
130
|
+
MUD types for a dialog system exist but are not used during normal casting:
|
|
131
|
+
|
|
132
|
+
| MUD Type | Command |
|
|
133
|
+
|----------|---------|
|
|
134
|
+
| 400 | ShowDialog |
|
|
135
|
+
| 401 | DialogButtonPress |
|
|
136
|
+
| 402 | SystemDialogResult |
|
|
137
|
+
|
|
138
|
+
Likely triggered by error conditions or permission prompts during casting.
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Tracking Mode Control
|
|
143
|
+
|
|
144
|
+
`setTrackingMode(int32 mode)` accepts mode values 0-255. Effects on the tracking system are unknown.
|
|
145
|
+
|
|
146
|
+
**Open questions:**
|
|
147
|
+
- What do different mode values do?
|
|
148
|
+
- Is there a mode that disables head tracking?
|
|
149
|
+
- Does this interact with the pose injection pipeline?
|