/** * udev rule generation and installation */ import { $ } from 'bun'; import type { DeviceId } from '../types/common.js'; import { logger } from '../utils/logger.js'; const UDEV_RULES_PATH = '/etc/udev/rules.d/99-usbip-supervisor.rules'; /** * Generate udev rule for a device */ export function generateDeviceRule(device: DeviceId, action: 'add' | 'remove'): string { const { vendorId, productId } = device; // Rule that runs a script when device is added/removed return `ACTION=="${action}", SUBSYSTEM=="usb", ATTRS{idVendor}=="${vendorId}", ATTRS{idProduct}=="${productId}", RUN+="/usr/local/bin/usbip-supervisor-notify ${action} ${vendorId} ${productId}"`; } /** * Generate all udev rules for devices */ export function generateUdevRules(devices: DeviceId[]): string { const rules: string[] = [ '# USB/IP Supervisor - Auto-generated udev rules', '# Do not edit manually', '', ]; for (const device of devices) { rules.push(`# Device: ${device.description || `${device.vendorId}:${device.productId}`}`); rules.push(generateDeviceRule(device, 'add')); rules.push(generateDeviceRule(device, 'remove')); rules.push(''); } return rules.join('\n'); } /** * Install udev rules (requires root) */ export async function installUdevRules(devices: DeviceId[]): Promise { try { const rules = generateUdevRules(devices); // Write rules file await Bun.write(UDEV_RULES_PATH, rules); // Reload udev rules await $`udevadm control --reload-rules`.quiet(); await $`udevadm trigger`.quiet(); logger.info(`Installed udev rules to ${UDEV_RULES_PATH}`); return true; } catch (error) { logger.error(`Failed to install udev rules: ${error}`); logger.warn('You may need to run with sudo privileges'); return false; } } /** * Check if udev rules are installed */ export async function checkUdevRulesInstalled(): Promise { try { const file = Bun.file(UDEV_RULES_PATH); return await file.exists(); } catch { return false; } } /** * Create notification script for udev */ export function generateNotificationScript(socketPath: string): string { return `#!/bin/bash # USB/IP Supervisor udev notification script ACTION="$1" VENDOR_ID="$2" PRODUCT_ID="$3" # Send notification to supervisor via socket echo "$ACTION:$VENDOR_ID:$PRODUCT_ID" | nc -U ${socketPath} || true `; } /** * Install notification script */ export async function installNotificationScript(socketPath: string): Promise { const scriptPath = '/usr/local/bin/usbip-supervisor-notify'; try { const script = generateNotificationScript(socketPath); await Bun.write(scriptPath, script); // Make executable await $`chmod +x ${scriptPath}`.quiet(); logger.info(`Installed notification script to ${scriptPath}`); return true; } catch (error) { logger.error(`Failed to install notification script: ${error}`); return false; } }