Cette révision appartient à :
2026-04-26 15:36:25 +02:00
révision 696ca4412a
5 fichiers modifiés avec 332 ajouts et 0 suppressions
+125
Voir le fichier
@@ -0,0 +1,125 @@
#!/bin/bash
# /usr/local/bin/usb-bind-wrapper
# Usage: usb-bind-wrapper bind <device>
# usb-bind-wrapper unbind <device>
# Example: usb-bind-wrapper unbind 1-1
set -euo pipefail
if [ "$(id -u)" -ne 0 ]; then
echo "Ce script doit être exécuté via sudo (ex: sudo /usr/local/bin/usb-bind-wrapper.sh ...)"
exit 1
fi
if [ $# -ne 2 ]; then
echo "Usage: $0 {bind|unbind|status} <usb-id>"
exit 2
fi
if [ "$1" = "status" ]; then
DEV="$2"
if [ -L "/sys/bus/usb/drivers/usb/$DEV" ]; then
echo "bound"
exit 0
else
echo "unbound"
exit 1
fi
fi
ACTION="$1"
DEV="$2"
# Validation simple du format (ex: 1-1 ou 1-1.2)
if [[ ! "$DEV" =~ ^[0-9]+(-[0-9]+)(\.[0-9]+)?$ ]]; then
echo "Identifiant USB invalide : $DEV"
exit 3
fi
case "$ACTION" in
bind)
SYS_PATH="/sys/bus/usb/drivers/usb/bind"
;;
unbind)
SYS_PATH="/sys/bus/usb/drivers/usb/unbind"
;;
*)
echo "Action invalide : $ACTION (utiliser bind ou unbind)"
exit 4
;;
esac
if [ ! -w "$SYS_PATH" ]; then
echo "Impossible d'écrire dans $SYS_PATH (vérifie que le chemin existe et les permissions)"
exit 5
fi
# Exécute l'écriture (sécurisée)
printf '%s\n' "$DEV" > "$SYS_PATH"
echo "OK: $ACTION $DEV"
exit 0
root@chambre:~# cat /usr/local/bin/usb-bind-wrapper
#!/bin/bash
# /usr/local/bin/usb-bind-wrapper
# Usage: usb-bind-wrapper bind <device>
# usb-bind-wrapper unbind <device>
# Example: usb-bind-wrapper unbind 1-1
set -euo pipefail
if [ "$(id -u)" -ne 0 ]; then
echo "Ce script doit être exécuté via sudo (ex: sudo /usr/local/bin/usb-bind-wrapper ...)"
exit 1
fi
if [ $# -ne 2 ]; then
echo "Usage: $0 {bind|unbind|status} <usb-id>"
exit 2
fi
if [ "$1" = "status" ]; then
DEV="$2"
if [ -L "/sys/bus/usb/drivers/usb/$DEV" ]; then
echo "bound"
exit 0
else
echo "unbound"
exit 1
fi
fi
ACTION="$1"
DEV="$2"
# Validation simple du format (ex: 1-1 ou 1-1.2)
if [[ ! "$DEV" =~ ^[0-9]+(-[0-9]+)(\.[0-9]+)?$ ]]; then
echo "Identifiant USB invalide : $DEV"
exit 3
fi
case "$ACTION" in
bind)
SYS_PATH="/sys/bus/usb/drivers/usb/bind"
;;
unbind)
SYS_PATH="/sys/bus/usb/drivers/usb/unbind"
;;
*)
echo "Action invalide : $ACTION (utiliser bind ou unbind)"
exit 4
;;
esac
if [ ! -w "$SYS_PATH" ]; then
echo "Impossible d'écrire dans $SYS_PATH (vérifie que le chemin existe et les permissions)"
exit 5
fi
# Exécute l'écriture (sécurisée)
printf '%s\n' "$DEV" > "$SYS_PATH"
echo "OK: $ACTION $DEV"
exit 0
+95
Voir le fichier
@@ -0,0 +1,95 @@
function injectUsbMenu() {
if (document.getElementById("usbControlItem")) return;
const menu = document.querySelector('.dropdown-menu');
if (!menu) return;
const anchor = document.querySelector('#dashboard-menu-item');
const li = document.createElement("li");
li.id = "usbControlItem";
li.className = "context-menu";
li.innerHTML = `
<a id="usbControlLink" href="#notarget">
<i class="fa-solid fa-sharp fa-power-off sx"></i>
<span>USB Control</span>
<span id="usbControlDot"
style="display:inline-block;width:12px;height:12px;border-radius:50%;background:#b22;margin-left:3px;margin-right:3px">
</span>
<span id="usbControlLabel">...</span>
</a>
`;
if (anchor && anchor.parentNode) {
anchor.parentNode.insertBefore(li, anchor.nextSibling);
} else {
menu.appendChild(li);
}
}
document.addEventListener("DOMContentLoaded", injectUsbMenu);
setTimeout(injectUsbMenu, 1000);
document.addEventListener('DOMContentLoaded', function() {
const item = document.getElementById('usbControlItem');
const dot = document.getElementById('usbControlDot');
const label = document.getElementById('usbControlLabel');
const link = document.getElementById('usbControlLink');
if (!item || !dot || !label || !link) return;
let isOn = false;
let locked = false;
// --- Fonction utilitaire : met à jour la pastille
function updateUI() {
dot.style.background = isOn ? '#2b2' : '#b22';
label.textContent = isOn ? 'ON' : 'OFF';
}
// --- Fonction pour changer l’état
function toggleUSB() {
event.stopPropagation();
if (locked) return;
locked = true;
label.textContent = '...';
fetch(`/usb-toggle.php?action=${isOn ? 'unbind' : 'bind'}`)
.then(res => res.json())
.then(data => {
if (data.status === 'ok') {
isOn = !isOn;
updateUI();
} else {
alert('Erreur: ' + data.msg);
}
})
.catch(err => alert('Erreur réseau: ' + err))
.finally(() => {
locked = false;
});
}
// --- Lecture de l’état au démarrage
fetch('/usb-toggle.php?action=status')
.then(res => res.json())
.then(data => {
if (data.status === 'ok') {
isOn = (data.state === 'bound');
updateUI();
}
})
.catch(() => {
label.textContent = '?';
});
function mouseLeave() {
link.blur();
}
item.addEventListener('click', toggleUSB);
link.addEventListener('mouseleave', mouseLeave);
});
+27
Voir le fichier
@@ -0,0 +1,27 @@
<?php
header('Content-Type: application/json');
$dev = '1-1';
$action = $_GET['action'] ?? '';
if (!in_array($action, ['bind', 'unbind', 'status'])) {
echo json_encode(['status' => 'error', 'msg' => 'Action invalide']);
exit;
}
if ($action === 'status') {
exec("sudo /usr/local/bin/usb-bind-wrapper.sh status $dev 2>&1", $out, $rc);
$state = trim($out[0] ?? '');
echo json_encode(['status' => 'ok', 'state' => $state]);
exit;
}
$cmd = escapeshellcmd("sudo /usr/local/bin/usb-bind-wrapper.sh $action $dev");
exec($cmd . " 2>&1", $out, $rc);
if ($rc === 0) {
echo json_encode(['status' => 'ok', 'msg' => ucfirst($action) . " $dev réussi"]);
} else {
echo json_encode(['status' => 'error', 'msg' => implode("\n", $out)]);
}
?>