@mcesystems/usbmuxd-instance-manager 1.0.72 → 1.0.73
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/README.md +74 -1
- package/dist/cli.js +194 -85
- package/dist/cli.js.map +4 -4
- package/dist/cli.mjs +193 -84
- package/dist/cli.mjs.map +4 -4
- package/dist/index.js +170 -61
- package/dist/index.js.map +4 -4
- package/dist/index.mjs +169 -60
- package/dist/index.mjs.map +4 -4
- package/dist/types/InstanceManager.d.ts +2 -0
- package/dist/types/InstanceManager.d.ts.map +1 -1
- package/dist/types/LockdownSync.d.ts +16 -0
- package/dist/types/LockdownSync.d.ts.map +1 -0
- package/dist/types/types/index.d.ts +12 -0
- package/dist/types/types/index.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -37,16 +37,100 @@ module.exports = __toCommonJS(index_exports);
|
|
|
37
37
|
|
|
38
38
|
// src/UsbmuxdService.ts
|
|
39
39
|
var import_node_events2 = require("node:events");
|
|
40
|
-
var
|
|
40
|
+
var import_tool_debug_g43 = require("@mcesystems/tool-debug-g4");
|
|
41
41
|
var import_usb_device_listener = __toESM(require("@mcesystems/usb-device-listener"));
|
|
42
42
|
|
|
43
43
|
// src/InstanceManager.ts
|
|
44
|
-
var
|
|
44
|
+
var import_node_child_process2 = require("node:child_process");
|
|
45
45
|
var import_node_events = require("node:events");
|
|
46
|
+
var import_node_util2 = require("node:util");
|
|
47
|
+
var import_tool_debug_g42 = require("@mcesystems/tool-debug-g4");
|
|
48
|
+
|
|
49
|
+
// src/LockdownSync.ts
|
|
50
|
+
var import_node_child_process = require("node:child_process");
|
|
51
|
+
var import_node_fs = require("node:fs");
|
|
52
|
+
var import_node_path = require("node:path");
|
|
46
53
|
var import_node_util = require("node:util");
|
|
47
54
|
var import_tool_debug_g4 = require("@mcesystems/tool-debug-g4");
|
|
48
55
|
var { logInfo, logWarning } = (0, import_tool_debug_g4.createLoggers)("usbmuxd-instance-manager");
|
|
49
56
|
var execAsync = (0, import_node_util.promisify)(import_node_child_process.exec);
|
|
57
|
+
var ALPINE_LOCKDOWN_DIR = "/var/lib/lockdown";
|
|
58
|
+
var SYSTEM_CONFIG_PLIST = "SystemConfiguration.plist";
|
|
59
|
+
function windowsPathToWsl(windowsPath) {
|
|
60
|
+
const normalized = windowsPath.replace(/\\/g, "/").trim();
|
|
61
|
+
const driveMatch = normalized.match(/^([a-zA-Z]):\/?(.*)$/);
|
|
62
|
+
if (driveMatch) {
|
|
63
|
+
const drive = driveMatch[1].toLowerCase();
|
|
64
|
+
const rest = driveMatch[2] || "";
|
|
65
|
+
return `/mnt/${drive}${rest ? `/${rest}` : ""}`;
|
|
66
|
+
}
|
|
67
|
+
return normalized;
|
|
68
|
+
}
|
|
69
|
+
async function syncToAlpine(udid, config) {
|
|
70
|
+
if (!config.lockdownSyncEnabled || !config.lockdownWindowsPath?.trim()) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const windowsDir = config.lockdownWindowsPath.trim();
|
|
74
|
+
const windowsFile = (0, import_node_path.join)(windowsDir, `${udid}.plist`);
|
|
75
|
+
if (!(0, import_node_fs.existsSync)(windowsFile)) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const distro = config.wslDistribution || "alpine-usbmuxd-build";
|
|
79
|
+
const wslSource = windowsPathToWsl(windowsFile);
|
|
80
|
+
const wslDestDir = ALPINE_LOCKDOWN_DIR;
|
|
81
|
+
try {
|
|
82
|
+
await execAsync(
|
|
83
|
+
`wsl -d ${distro} -- sh -c "mkdir -p ${wslDestDir} && cp '${wslSource}' '${wslDestDir}/'"`
|
|
84
|
+
);
|
|
85
|
+
logInfo(`Lockdown sync: copied ${udid}.plist to Alpine`);
|
|
86
|
+
} catch (error) {
|
|
87
|
+
try {
|
|
88
|
+
await execAsync(
|
|
89
|
+
`wsl -d ${distro} -- sh -c "mkdir -p ${wslDestDir} && sudo cp '${wslSource}' '${wslDestDir}/'"`
|
|
90
|
+
);
|
|
91
|
+
logInfo(`Lockdown sync: copied ${udid}.plist to Alpine (via sudo)`);
|
|
92
|
+
} catch (sudoError) {
|
|
93
|
+
logWarning(
|
|
94
|
+
`Lockdown sync to Alpine failed for ${udid}: ${error}. Sudo fallback failed: ${sudoError}. Ensure /var/lib/lockdown is writable or use passwordless sudo.`
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
async function syncFromAlpine(udids, config) {
|
|
100
|
+
if (!config.lockdownSyncEnabled || !config.lockdownWindowsPath?.trim()) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const windowsDir = config.lockdownWindowsPath.trim();
|
|
104
|
+
try {
|
|
105
|
+
(0, import_node_fs.mkdirSync)(windowsDir, { recursive: true });
|
|
106
|
+
} catch (error) {
|
|
107
|
+
logWarning(`Lockdown sync: could not create Windows dir ${windowsDir}: ${error}`);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const distro = config.wslDistribution || "alpine-usbmuxd-build";
|
|
111
|
+
const wslDestDir = windowsPathToWsl(windowsDir);
|
|
112
|
+
for (const udid of udids) {
|
|
113
|
+
const plist = `${udid}.plist`;
|
|
114
|
+
try {
|
|
115
|
+
await execAsync(
|
|
116
|
+
`wsl -d ${distro} -- sh -c "test -f '${ALPINE_LOCKDOWN_DIR}/${plist}' && cp '${ALPINE_LOCKDOWN_DIR}/${plist}' '${wslDestDir}/'"`
|
|
117
|
+
);
|
|
118
|
+
logInfo(`Lockdown sync: copied ${plist} from Alpine to Windows`);
|
|
119
|
+
} catch {
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
try {
|
|
123
|
+
await execAsync(
|
|
124
|
+
`wsl -d ${distro} -- sh -c "test -f '${ALPINE_LOCKDOWN_DIR}/${SYSTEM_CONFIG_PLIST}' && cp '${ALPINE_LOCKDOWN_DIR}/${SYSTEM_CONFIG_PLIST}' '${wslDestDir}/'"`
|
|
125
|
+
);
|
|
126
|
+
logInfo(`Lockdown sync: copied ${SYSTEM_CONFIG_PLIST} from Alpine to Windows`);
|
|
127
|
+
} catch {
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// src/InstanceManager.ts
|
|
132
|
+
var { logInfo: logInfo2, logWarning: logWarning2 } = (0, import_tool_debug_g42.createLoggers)("usbmuxd-instance-manager");
|
|
133
|
+
var execAsync2 = (0, import_node_util2.promisify)(import_node_child_process2.exec);
|
|
50
134
|
var USBIPD_PATH = '"C:\\Program Files\\usbipd-win\\usbipd.exe"';
|
|
51
135
|
function parseUsbipdList(output) {
|
|
52
136
|
const devices = [];
|
|
@@ -78,7 +162,9 @@ var DEFAULT_CONFIG = {
|
|
|
78
162
|
wslDistribution: "alpine-usbmuxd-build",
|
|
79
163
|
// Alpine WSL2 distribution name
|
|
80
164
|
verboseLogging: true,
|
|
81
|
-
appleVendorId: "05AC"
|
|
165
|
+
appleVendorId: "05AC",
|
|
166
|
+
lockdownWindowsPath: "C:\\ProgramData\\mce\\lockdown",
|
|
167
|
+
lockdownSyncEnabled: true
|
|
82
168
|
};
|
|
83
169
|
var InstanceManager = class extends import_node_events.EventEmitter {
|
|
84
170
|
config;
|
|
@@ -90,6 +176,8 @@ var InstanceManager = class extends import_node_events.EventEmitter {
|
|
|
90
176
|
isRunning = false;
|
|
91
177
|
/** Tracks which devices have been attached to WSL */
|
|
92
178
|
attachedDevices = /* @__PURE__ */ new Set();
|
|
179
|
+
/** Device IDs currently in the attach flow (ignore disconnect until attach completes) */
|
|
180
|
+
pendingAttachDevices = /* @__PURE__ */ new Set();
|
|
93
181
|
/** Cached WSL IP address for connecting from Windows */
|
|
94
182
|
wslIpAddress = null;
|
|
95
183
|
constructor(config = {}) {
|
|
@@ -106,28 +194,28 @@ var InstanceManager = class extends import_node_events.EventEmitter {
|
|
|
106
194
|
}
|
|
107
195
|
const distro = this.config.wslDistribution || "alpine-usbmuxd-build";
|
|
108
196
|
try {
|
|
109
|
-
const { stdout } = await
|
|
197
|
+
const { stdout } = await execAsync2(`wsl -d ${distro} -- ip -4 addr show eth0`);
|
|
110
198
|
const match = stdout.match(/inet\s+(\d+\.\d+\.\d+\.\d+)/);
|
|
111
199
|
if (match) {
|
|
112
200
|
this.wslIpAddress = match[1];
|
|
113
|
-
|
|
201
|
+
logInfo2(`Detected WSL IP address: ${this.wslIpAddress}`);
|
|
114
202
|
return this.wslIpAddress;
|
|
115
203
|
}
|
|
116
204
|
} catch (error) {
|
|
117
|
-
|
|
205
|
+
logWarning2(`Failed to detect WSL IP via ip addr: ${error}`);
|
|
118
206
|
}
|
|
119
207
|
try {
|
|
120
|
-
const { stdout } = await
|
|
208
|
+
const { stdout } = await execAsync2(`wsl -d ${distro} -- hostname -I`);
|
|
121
209
|
const ip = stdout.trim().split(/\s+/)[0];
|
|
122
210
|
if (ip && /^\d+\.\d+\.\d+\.\d+$/.test(ip)) {
|
|
123
211
|
this.wslIpAddress = ip;
|
|
124
|
-
|
|
212
|
+
logInfo2(`Detected WSL IP address (hostname): ${this.wslIpAddress}`);
|
|
125
213
|
return this.wslIpAddress;
|
|
126
214
|
}
|
|
127
215
|
} catch (error) {
|
|
128
|
-
|
|
216
|
+
logWarning2(`Failed to detect WSL IP via hostname: ${error}`);
|
|
129
217
|
}
|
|
130
|
-
|
|
218
|
+
logWarning2("Could not detect WSL IP, falling back to localhost");
|
|
131
219
|
this.wslIpAddress = "127.0.0.1";
|
|
132
220
|
return this.wslIpAddress;
|
|
133
221
|
}
|
|
@@ -150,6 +238,8 @@ var InstanceManager = class extends import_node_events.EventEmitter {
|
|
|
150
238
|
return;
|
|
151
239
|
}
|
|
152
240
|
this.isRunning = false;
|
|
241
|
+
const udids = Array.from(this.deviceMappings.keys());
|
|
242
|
+
await syncFromAlpine(udids, this.config);
|
|
153
243
|
const detachPromises = Array.from(this.attachedDevices).map(
|
|
154
244
|
(busId) => this.detachDeviceFromWsl(busId)
|
|
155
245
|
);
|
|
@@ -167,28 +257,28 @@ var InstanceManager = class extends import_node_events.EventEmitter {
|
|
|
167
257
|
*/
|
|
168
258
|
async findBusIdForDevice(device) {
|
|
169
259
|
try {
|
|
170
|
-
const { stdout } = await
|
|
260
|
+
const { stdout } = await execAsync2(`${USBIPD_PATH} list`);
|
|
171
261
|
const usbipdDevices = parseUsbipdList(stdout);
|
|
172
262
|
const deviceVid = device.vid.toString(16).toUpperCase().padStart(4, "0");
|
|
173
263
|
const devicePid = device.pid.toString(16).toUpperCase().padStart(4, "0");
|
|
174
|
-
|
|
175
|
-
|
|
264
|
+
logInfo2(`Looking for device with VID:PID ${deviceVid}:${devicePid}`);
|
|
265
|
+
logInfo2(`Found ${usbipdDevices.length} devices from usbipd list`);
|
|
176
266
|
const match = usbipdDevices.find((d) => d.vid === deviceVid && d.pid === devicePid);
|
|
177
267
|
if (match) {
|
|
178
|
-
|
|
268
|
+
logInfo2(
|
|
179
269
|
`Found usbipd bus ID ${match.busId} for device ${device.deviceId} (${deviceVid}:${devicePid})`
|
|
180
270
|
);
|
|
181
271
|
return match.busId;
|
|
182
272
|
}
|
|
183
273
|
for (const d of usbipdDevices) {
|
|
184
|
-
|
|
274
|
+
logInfo2(` usbipd device: ${d.busId} ${d.vid}:${d.pid} "${d.description}"`);
|
|
185
275
|
}
|
|
186
|
-
|
|
276
|
+
logWarning2(
|
|
187
277
|
`Could not find usbipd bus ID for device ${device.deviceId} (${deviceVid}:${devicePid})`
|
|
188
278
|
);
|
|
189
279
|
return null;
|
|
190
280
|
} catch (error) {
|
|
191
|
-
|
|
281
|
+
logWarning2(`Failed to run usbipd list: ${error}`);
|
|
192
282
|
return null;
|
|
193
283
|
}
|
|
194
284
|
}
|
|
@@ -199,15 +289,15 @@ var InstanceManager = class extends import_node_events.EventEmitter {
|
|
|
199
289
|
const distro = this.config.wslDistribution;
|
|
200
290
|
try {
|
|
201
291
|
if (distro) {
|
|
202
|
-
|
|
203
|
-
await
|
|
292
|
+
logInfo2(`Starting WSL distribution: ${distro}...`);
|
|
293
|
+
await execAsync2(`wsl -d ${distro} -- echo "WSL started"`);
|
|
204
294
|
} else {
|
|
205
|
-
|
|
206
|
-
await
|
|
295
|
+
logInfo2("Starting default WSL distribution...");
|
|
296
|
+
await execAsync2(`wsl -- echo "WSL started"`);
|
|
207
297
|
}
|
|
208
298
|
return true;
|
|
209
299
|
} catch (error) {
|
|
210
|
-
|
|
300
|
+
logWarning2(`Failed to start WSL: ${error}`);
|
|
211
301
|
return false;
|
|
212
302
|
}
|
|
213
303
|
}
|
|
@@ -219,19 +309,24 @@ var InstanceManager = class extends import_node_events.EventEmitter {
|
|
|
219
309
|
const distro = this.config.wslDistribution;
|
|
220
310
|
try {
|
|
221
311
|
await this.ensureWslRunning();
|
|
222
|
-
|
|
223
|
-
await
|
|
312
|
+
logInfo2(`Binding device ${busId}...`);
|
|
313
|
+
await execAsync2(`${USBIPD_PATH} bind --busid ${busId} --force`);
|
|
224
314
|
if (distro) {
|
|
225
|
-
|
|
226
|
-
await
|
|
315
|
+
logInfo2(`Attaching device ${busId} to WSL distribution ${distro}...`);
|
|
316
|
+
await execAsync2(`${USBIPD_PATH} attach --wsl=${distro} --busid=${busId}`);
|
|
227
317
|
} else {
|
|
228
|
-
|
|
229
|
-
await
|
|
318
|
+
logInfo2(`Attaching device ${busId} to default WSL...`);
|
|
319
|
+
await execAsync2(`${USBIPD_PATH} attach --wsl --busid=${busId}`);
|
|
230
320
|
}
|
|
231
|
-
|
|
321
|
+
logInfo2(`Device ${busId} attached to WSL successfully`);
|
|
232
322
|
return true;
|
|
233
323
|
} catch (error) {
|
|
234
|
-
|
|
324
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
325
|
+
if (message.includes("already attached to a client")) {
|
|
326
|
+
logInfo2(`Device ${busId} is already attached to WSL, continuing`);
|
|
327
|
+
return true;
|
|
328
|
+
}
|
|
329
|
+
logWarning2(`Failed to attach device ${busId} to WSL: ${error}`);
|
|
235
330
|
return false;
|
|
236
331
|
}
|
|
237
332
|
}
|
|
@@ -240,10 +335,15 @@ var InstanceManager = class extends import_node_events.EventEmitter {
|
|
|
240
335
|
*/
|
|
241
336
|
async detachDeviceFromWsl(busId) {
|
|
242
337
|
try {
|
|
243
|
-
await
|
|
244
|
-
|
|
338
|
+
await execAsync2(`${USBIPD_PATH} detach --busid=${busId}`);
|
|
339
|
+
logInfo2(`Device ${busId} detached from WSL`);
|
|
245
340
|
} catch (error) {
|
|
246
|
-
|
|
341
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
342
|
+
if (message.includes("no device with busid") || message.includes("There is no device")) {
|
|
343
|
+
logInfo2(`Device ${busId} already detached`);
|
|
344
|
+
} else {
|
|
345
|
+
logWarning2(`Failed to detach device ${busId}: ${error}`);
|
|
346
|
+
}
|
|
247
347
|
}
|
|
248
348
|
}
|
|
249
349
|
/**
|
|
@@ -252,18 +352,24 @@ var InstanceManager = class extends import_node_events.EventEmitter {
|
|
|
252
352
|
*/
|
|
253
353
|
async onDeviceConnected(device) {
|
|
254
354
|
if (this.deviceMappings.has(device.deviceId)) {
|
|
255
|
-
|
|
355
|
+
logWarning2(`Device ${device.deviceId} is already connected`);
|
|
256
356
|
return;
|
|
257
357
|
}
|
|
358
|
+
await syncToAlpine(device.deviceId, this.config);
|
|
258
359
|
const busId = await this.findBusIdForDevice(device);
|
|
259
360
|
if (!busId) {
|
|
260
|
-
|
|
361
|
+
logWarning2(`Cannot attach device ${device.deviceId} - bus ID not found`);
|
|
261
362
|
}
|
|
262
363
|
if (busId && !this.attachedDevices.has(busId)) {
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
this.
|
|
266
|
-
|
|
364
|
+
this.pendingAttachDevices.add(device.deviceId);
|
|
365
|
+
try {
|
|
366
|
+
const attached = await this.attachDeviceToWsl(busId);
|
|
367
|
+
if (attached) {
|
|
368
|
+
this.attachedDevices.add(busId);
|
|
369
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
370
|
+
}
|
|
371
|
+
} finally {
|
|
372
|
+
this.pendingAttachDevices.delete(device.deviceId);
|
|
267
373
|
}
|
|
268
374
|
}
|
|
269
375
|
let targetInstance = this.findInstanceWithCapacity();
|
|
@@ -301,23 +407,23 @@ var InstanceManager = class extends import_node_events.EventEmitter {
|
|
|
301
407
|
async pairDevice(udid, goIosPath = "ios") {
|
|
302
408
|
const mapping = this.deviceMappings.get(udid);
|
|
303
409
|
if (!mapping) {
|
|
304
|
-
|
|
410
|
+
logWarning2(`Cannot pair device ${udid} - not found in mappings`);
|
|
305
411
|
return false;
|
|
306
412
|
}
|
|
307
413
|
try {
|
|
308
414
|
const socketAddress = `${mapping.host}:${mapping.port}`;
|
|
309
|
-
|
|
310
|
-
const { stderr } = await
|
|
415
|
+
logInfo2(`Pairing device ${udid} via ${socketAddress}...`);
|
|
416
|
+
const { stderr } = await execAsync2(`"${goIosPath}" pair --udid=${udid}`, {
|
|
311
417
|
env: { ...process.env, USBMUXD_SOCKET_ADDRESS: socketAddress }
|
|
312
418
|
});
|
|
313
419
|
if (stderr?.includes("error")) {
|
|
314
|
-
|
|
420
|
+
logWarning2(`Pairing warning for ${udid}: ${stderr}`);
|
|
315
421
|
}
|
|
316
|
-
|
|
422
|
+
logInfo2(`Device ${udid} paired successfully`);
|
|
317
423
|
this.emit("device-paired", { udid, mapping });
|
|
318
424
|
return true;
|
|
319
425
|
} catch (error) {
|
|
320
|
-
|
|
426
|
+
logWarning2(`Failed to pair device ${udid}: ${error}`);
|
|
321
427
|
return false;
|
|
322
428
|
}
|
|
323
429
|
}
|
|
@@ -326,9 +432,12 @@ var InstanceManager = class extends import_node_events.EventEmitter {
|
|
|
326
432
|
* Detaches from WSL, removes device from instance, and stops instance if empty
|
|
327
433
|
*/
|
|
328
434
|
async onDeviceDisconnected(device) {
|
|
435
|
+
if (this.pendingAttachDevices.has(device.deviceId)) {
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
329
438
|
const mapping = this.deviceMappings.get(device.deviceId);
|
|
330
439
|
if (!mapping) {
|
|
331
|
-
|
|
440
|
+
logWarning2(`Device ${device.deviceId} was not tracked`);
|
|
332
441
|
return;
|
|
333
442
|
}
|
|
334
443
|
if (mapping.busId) {
|
|
@@ -337,7 +446,7 @@ var InstanceManager = class extends import_node_events.EventEmitter {
|
|
|
337
446
|
}
|
|
338
447
|
const instance = this.instances.get(mapping.instanceId);
|
|
339
448
|
if (!instance) {
|
|
340
|
-
|
|
449
|
+
logWarning2(`Instance ${mapping.instanceId} not found`);
|
|
341
450
|
this.deviceMappings.delete(device.deviceId);
|
|
342
451
|
return;
|
|
343
452
|
}
|
|
@@ -392,7 +501,7 @@ var InstanceManager = class extends import_node_events.EventEmitter {
|
|
|
392
501
|
this.config.usbmuxdPath,
|
|
393
502
|
...usbmuxdArgs
|
|
394
503
|
];
|
|
395
|
-
const process2 = (0,
|
|
504
|
+
const process2 = (0, import_node_child_process2.spawn)("wsl", wslArgs, {
|
|
396
505
|
stdio: ["ignore", "pipe", "pipe"],
|
|
397
506
|
windowsHide: false
|
|
398
507
|
// Show console for debugging
|
|
@@ -514,7 +623,7 @@ var InstanceManager = class extends import_node_events.EventEmitter {
|
|
|
514
623
|
};
|
|
515
624
|
|
|
516
625
|
// src/UsbmuxdService.ts
|
|
517
|
-
var { logInfo:
|
|
626
|
+
var { logInfo: logInfo3, logError } = (0, import_tool_debug_g43.createLoggers)("usbmuxd-instance-manager");
|
|
518
627
|
var UsbmuxdService = class extends import_node_events2.EventEmitter {
|
|
519
628
|
manager;
|
|
520
629
|
usbListener;
|
|
@@ -573,17 +682,17 @@ var UsbmuxdService = class extends import_node_events2.EventEmitter {
|
|
|
573
682
|
}
|
|
574
683
|
const config = this.manager.getConfig();
|
|
575
684
|
const appleVid = Number.parseInt(config.appleVendorId, 16);
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
685
|
+
logInfo3("Starting service...");
|
|
686
|
+
logInfo3(`Batch size: ${config.batchSize} devices per instance`);
|
|
687
|
+
logInfo3(`Base port: ${config.basePort}`);
|
|
688
|
+
logInfo3(`Max instances: ${config.maxInstances}`);
|
|
689
|
+
logInfo3(`usbmuxd path: ${config.usbmuxdPath}`);
|
|
690
|
+
logInfo3(`Monitoring Apple devices (VID: ${config.appleVendorId})`);
|
|
582
691
|
this.usbListener.onDeviceAdd(async (device) => {
|
|
583
692
|
if (device.vid !== appleVid) {
|
|
584
693
|
return;
|
|
585
694
|
}
|
|
586
|
-
|
|
695
|
+
logInfo3(`Apple device connected: ${device.deviceId} (${device.deviceName || "Unknown"})`);
|
|
587
696
|
try {
|
|
588
697
|
await this.manager.onDeviceConnected(device);
|
|
589
698
|
} catch (error) {
|
|
@@ -594,7 +703,7 @@ var UsbmuxdService = class extends import_node_events2.EventEmitter {
|
|
|
594
703
|
if (device.vid !== appleVid) {
|
|
595
704
|
return;
|
|
596
705
|
}
|
|
597
|
-
|
|
706
|
+
logInfo3(`Apple device disconnected: ${device.deviceId}`);
|
|
598
707
|
try {
|
|
599
708
|
await this.manager.onDeviceDisconnected(device);
|
|
600
709
|
} catch (error) {
|
|
@@ -608,8 +717,8 @@ var UsbmuxdService = class extends import_node_events2.EventEmitter {
|
|
|
608
717
|
});
|
|
609
718
|
this.isListening = true;
|
|
610
719
|
this.manager.start();
|
|
611
|
-
|
|
612
|
-
|
|
720
|
+
logInfo3("Service started successfully");
|
|
721
|
+
logInfo3("Waiting for iOS devices...");
|
|
613
722
|
} catch (error) {
|
|
614
723
|
logError("Failed to start USB listener:", error);
|
|
615
724
|
throw error;
|
|
@@ -623,11 +732,11 @@ var UsbmuxdService = class extends import_node_events2.EventEmitter {
|
|
|
623
732
|
if (!this.isListening) {
|
|
624
733
|
return;
|
|
625
734
|
}
|
|
626
|
-
|
|
735
|
+
logInfo3("Stopping service...");
|
|
627
736
|
this.usbListener.stopListening();
|
|
628
737
|
this.isListening = false;
|
|
629
738
|
await this.manager.stop();
|
|
630
|
-
|
|
739
|
+
logInfo3("Service stopped");
|
|
631
740
|
}
|
|
632
741
|
/**
|
|
633
742
|
* Get device port mapping
|