@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.
Files changed (142) hide show
  1. package/.claude/settings.local.json +7 -0
  2. package/.github/workflows/docs.yml +45 -0
  3. package/.github/workflows/publish.yml +11 -1
  4. package/README.md +27 -0
  5. package/build/cast/decoder.d.ts +48 -0
  6. package/build/cast/decoder.d.ts.map +1 -0
  7. package/build/cast/decoder.js +152 -0
  8. package/build/cast/decoder.js.map +1 -0
  9. package/build/cast/session.d.ts +87 -0
  10. package/build/cast/session.d.ts.map +1 -0
  11. package/build/cast/session.js +565 -0
  12. package/build/cast/session.js.map +1 -0
  13. package/build/commands/logcat.d.ts.map +1 -1
  14. package/build/commands/logcat.js +7 -6
  15. package/build/commands/logcat.js.map +1 -1
  16. package/build/commands/screenshot.d.ts.map +1 -1
  17. package/build/commands/screenshot.js +17 -20
  18. package/build/commands/screenshot.js.map +1 -1
  19. package/build/commands/stay-awake.d.ts +2 -15
  20. package/build/commands/stay-awake.d.ts.map +1 -1
  21. package/build/commands/stay-awake.js +14 -77
  22. package/build/commands/stay-awake.js.map +1 -1
  23. package/build/daemon/cast-manager.d.ts +42 -0
  24. package/build/daemon/cast-manager.d.ts.map +1 -0
  25. package/build/daemon/cast-manager.js +243 -0
  26. package/build/daemon/cast-manager.js.map +1 -0
  27. package/build/daemon/client.d.ts +40 -0
  28. package/build/daemon/client.d.ts.map +1 -0
  29. package/build/daemon/client.js +133 -0
  30. package/build/daemon/client.js.map +1 -0
  31. package/build/daemon/daemon.d.ts +20 -0
  32. package/build/daemon/daemon.d.ts.map +1 -0
  33. package/build/daemon/daemon.js +130 -0
  34. package/build/daemon/daemon.js.map +1 -0
  35. package/build/daemon/deploy.d.ts +44 -0
  36. package/build/daemon/deploy.d.ts.map +1 -0
  37. package/build/daemon/deploy.js +230 -0
  38. package/build/daemon/deploy.js.map +1 -0
  39. package/build/daemon/logcat-manager.d.ts +39 -0
  40. package/build/daemon/logcat-manager.d.ts.map +1 -0
  41. package/build/daemon/logcat-manager.js +194 -0
  42. package/build/daemon/logcat-manager.js.map +1 -0
  43. package/build/daemon/server.d.ts +19 -0
  44. package/build/daemon/server.d.ts.map +1 -0
  45. package/build/daemon/server.js +482 -0
  46. package/build/daemon/server.js.map +1 -0
  47. package/build/daemon/stay-awake-manager.d.ts +22 -0
  48. package/build/daemon/stay-awake-manager.d.ts.map +1 -0
  49. package/build/daemon/stay-awake-manager.js +74 -0
  50. package/build/daemon/stay-awake-manager.js.map +1 -0
  51. package/build/index.js +272 -45
  52. package/build/index.js.map +1 -1
  53. package/build/public/dashboard.js +749 -0
  54. package/build/public/index.html +12 -0
  55. package/build/public/style.css +106 -0
  56. package/build/utils/adb.d.ts +6 -0
  57. package/build/utils/adb.d.ts.map +1 -1
  58. package/build/utils/adb.js +62 -66
  59. package/build/utils/adb.js.map +1 -1
  60. package/build/utils/casting-apk.d.ts +40 -0
  61. package/build/utils/casting-apk.d.ts.map +1 -0
  62. package/build/utils/casting-apk.js +252 -0
  63. package/build/utils/casting-apk.js.map +1 -0
  64. package/build/utils/config.d.ts +5 -3
  65. package/build/utils/config.d.ts.map +1 -1
  66. package/build/utils/config.js +18 -38
  67. package/build/utils/config.js.map +1 -1
  68. package/build/utils/exec.d.ts +5 -0
  69. package/build/utils/exec.d.ts.map +1 -1
  70. package/build/utils/exec.js +17 -0
  71. package/build/utils/exec.js.map +1 -1
  72. package/build/utils/filename.d.ts +7 -1
  73. package/build/utils/filename.d.ts.map +1 -1
  74. package/build/utils/filename.js +17 -2
  75. package/build/utils/filename.js.map +1 -1
  76. package/build/utils/filename.test.js +33 -1
  77. package/build/utils/filename.test.js.map +1 -1
  78. package/build/utils/jpeg-comment.d.ts +14 -0
  79. package/build/utils/jpeg-comment.d.ts.map +1 -0
  80. package/build/utils/jpeg-comment.js +28 -0
  81. package/build/utils/jpeg-comment.js.map +1 -0
  82. package/build/utils/test-properties.d.ts +34 -0
  83. package/build/utils/test-properties.d.ts.map +1 -0
  84. package/build/utils/test-properties.js +73 -0
  85. package/build/utils/test-properties.js.map +1 -0
  86. package/package.json +11 -5
  87. package/packages/cast2-protocol/README.md +86 -0
  88. package/packages/cast2-protocol/docs/_config.yml +4 -0
  89. package/packages/cast2-protocol/docs/feature-flags.md +102 -0
  90. package/packages/cast2-protocol/docs/index.md +24 -0
  91. package/packages/cast2-protocol/docs/open-investigations.md +149 -0
  92. package/packages/cast2-protocol/docs/protocol.md +602 -0
  93. package/packages/cast2-protocol/package.json +46 -0
  94. package/packages/cast2-protocol/src/constants.ts +65 -0
  95. package/packages/cast2-protocol/src/index.ts +7 -0
  96. package/packages/cast2-protocol/src/mgik.ts +69 -0
  97. package/packages/cast2-protocol/src/mud.ts +294 -0
  98. package/packages/cast2-protocol/src/pose.ts +99 -0
  99. package/packages/cast2-protocol/src/resolutions.ts +34 -0
  100. package/packages/cast2-protocol/src/types.ts +64 -0
  101. package/packages/cast2-protocol/src/xrsp.ts +73 -0
  102. package/packages/cast2-protocol/tests/mgik.test.ts +80 -0
  103. package/packages/cast2-protocol/tests/mud.test.ts +295 -0
  104. package/packages/cast2-protocol/tests/pose.test.ts +173 -0
  105. package/packages/cast2-protocol/tests/xrsp.test.ts +90 -0
  106. package/packages/cast2-protocol/tsconfig.json +20 -0
  107. package/pnpm-workspace.yaml +2 -0
  108. package/src/cast/decoder.ts +178 -0
  109. package/src/cast/session.ts +708 -0
  110. package/src/commands/logcat.ts +6 -5
  111. package/src/commands/screenshot.ts +19 -13
  112. package/src/commands/stay-awake.ts +22 -91
  113. package/src/daemon/adbkit-apkreader.d.ts +14 -0
  114. package/src/daemon/cast-manager.ts +282 -0
  115. package/src/daemon/client.ts +166 -0
  116. package/src/daemon/daemon.ts +169 -0
  117. package/src/daemon/deploy.ts +307 -0
  118. package/src/daemon/logcat-manager.ts +229 -0
  119. package/src/daemon/server.ts +595 -0
  120. package/src/daemon/stay-awake-manager.ts +83 -0
  121. package/src/index.ts +326 -56
  122. package/src/public/dashboard.js +288 -0
  123. package/src/public/index.html +12 -0
  124. package/src/public/style.css +106 -0
  125. package/src/utils/adb.ts +70 -57
  126. package/src/utils/casting-apk.ts +276 -0
  127. package/src/utils/config.ts +18 -36
  128. package/src/utils/exec.ts +20 -0
  129. package/src/utils/filename.test.ts +41 -1
  130. package/src/utils/filename.ts +18 -2
  131. package/src/utils/jpeg-comment.ts +30 -0
  132. package/src/utils/test-properties.ts +94 -0
  133. package/tests/cast/auto-layer.test.ts +87 -0
  134. package/tests/cast/decoder.test.ts +82 -0
  135. package/tests/cast/session-restart.test.ts +107 -0
  136. package/tests/config.test.ts +17 -22
  137. package/tests/daemon/api-status.test.ts +82 -0
  138. package/tests/daemon/cast-manager.test.ts +69 -0
  139. package/tests/daemon/mjpeg-stream.test.ts +144 -0
  140. package/tests/daemon/pose-endpoint.test.ts +63 -0
  141. package/tests/daemon/start-guard.test.ts +77 -0
  142. 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": "1.4.1",
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 pack && pnpm install -g $PWD/myerscarpenter-quest-dev-$(node -p \"require('./package.json').version\").tgz && rm myerscarpenter-quest-dev-$(node -p \"require('./package.json').version\").tgz",
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
- "exiftool-vendored": "^35.1.0",
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,4 @@
1
+ theme: jekyll-theme-minimal
2
+ title: Cast 2.0 Protocol
3
+ description: Protocol documentation for Meta Quest Cast 2.0 video streaming
4
+ baseurl: /quest-dev
@@ -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?