
Protocole IPC de l'agent Logi Options+ rétro-conçu. Basculer les périphériques multi-hôtes Logitech par programmation via socket Unix (macOS) ou tube nommé (Windows).
Documentation rétro-ingénierée du protocole IPC de l'agent Logi Options+. Permet un contrôle programmatique des périphériques multi-hôtes Logitech (changement d'hôte, requêtes sur les périphériques) sans accès HID brut, à la fois sur macOS et Windows.
Ce protocole n'a pas été documenté publiquement avant ce projet.
macOS bloque l'accès HID brut aux périphériques d'entrée Bluetooth au niveau du noyau. Aucune permission, entitlement ou astuce ne contourne cela. L'agent Logi Options+ possède des entitlements signés par Apple (com.apple.security.device.bluetooth) qui lui accordent l'accès Bluetooth HID. Ce projet communique avec l'agent via son canal IPC à la place.
| Fichier | Description |
|---|---|
logi-options-ipc-reverse-engineering.md | Chronique complète de la rétro-ingénierie |
software-kvm-setup.md | Guide de configuration d'un KVM logiciel bidirectionnel (Windows + Mac) |
switch_to_windows.py | Script côté Mac qui bascule les périphériques Logitech et l'entrée du moniteur via IPC par socket Unix |
api-reference.md | Référence de l'API de l'agent : endpoints fonctionnels, types protobuf, capacités des périphériques |
kvm.ahk | Script AutoHotkey v2 : raccourcis Win+1/2/3 qui appellent kvm_daemon_windows.py --switch (s'exécute dans la barre d'état système) |
kvm_daemon_windows.py | Basculement de périphériques Windows via tube nommé, basculement de moniteur via DDC/CI |
kvm_config.ini | Configuration Windows (raccourcis, entrées moniteur) |
query_feature_index.py | Découvre l'index de la fonctionnalité HID++ ChangeHost pour les périphériques Logitech (Windows) |
query_agent_windows.py | Interroge l'agent sous Windows via tube nommé |
config.ini | Configuration héritée d'UnifiedSwitch (remplacée par kvm_daemon_windows.py) |
python3 switch_to_windows.py 0 # Basculer vers l'hôte 0 (DisplayPort)
python3 switch_to_windows.py 1 # Basculer vers l'hôte 1 (HDMI)
python3 switch_to_windows.py --dry-run 0 # Afficher ce qui se passerait
Nécessite Logi Options+ en cours d'exécution et m1ddc installé (brew install m1ddc).
# Démarrer l'écouteur de raccourcis AHK (s'exécute dans la barre d'état système, sans console)
# Nécessite AutoHotkey v2 : winget install AutoHotkey.AutoHotkey
start kvm.ahk
# Ou basculer directement depuis la ligne de commande
python kvm_daemon_windows.py --switch 1
# Afficher les périphériques découverts et les raccourcis configurés sans basculer
python kvm_daemon_windows.py --dry-run
Nécessite Logi Options+ en cours d'exécution. Installer les dépendances : pip install pywin32.
Le script AHK écoute Win+1/2/3 et appelle kvm_daemon_windows.py --switch N pour chacun. Le script Python découvre automatiquement les périphériques depuis l'agent (aucun ID de périphérique ou chemin HID codé en dur). Modifiez kvm_config.ini pour configurer les raccourcis et les valeurs d'entrée DDC/CI du moniteur.
L'agent écoute sur :
/tmp/logitech_kiros_agent-<hash>\\.\pipe\logitech_kiros_agent-<hash>Même protocole filaire sur les deux plateformes. Format de trame binaire :
LE32(total_len) + BE32(proto_name_len) + "json" + BE32(msg_len) + JSON_message
Basculer un périphérique vers un autre hôte :
{
"msg_id": "1",
"verb": "SET",
"path": "/change_host/<device_id>/host",
"payload": {
"@type": "type.googleapis.com/logi.protocol.devices.ChangeHost",
"host": 0
}
}
Le payload est un champ google.protobuf.Any sérialisé en JSON inline avec une annotation @type. L'agent utilise un analyseur JSON protobuf strict ; les champs inconnus provoquent INVALID_MESSAGE_RECEIVED.
Les requêtes utilisent msg_id (snake_case). Les réponses utilisent msgId (camelCase). Les verbes sont des chaînes : "GET", "SET", "SUBSCRIBE", "BROADCAST".
Voir logi-options-ipc-reverse-engineering.md pour la documentation complète du protocole.
Pour une automatisation de longue durée, reconnectez-vous sur BrokenPipeError et redécouvrez le chemin du socket/tube.
Ces points s'appliquent lors de l'envoi de commandes HID++ directement, pas via l'agent.
kvm_daemon_windows.pyles évite tous en passant par le tube nommé de l'agent.
La collection HID++ varie selon le périphérique. Le MX Master 3S expose HID++ sur COL02. Le MX Keys S utilise COL05. Les deux utilisent la page d'usage FF43:0202. Vérifiez avec :
Get-PnpDeviceProperty -InstanceId "<instance_id>" -KeyName DEVPKEY_Device_HardwareIds
# Chercher UP:FF43_U:0202
Les indices de fonctionnalité diffèrent selon le périphérique. ChangeHost (0x1814) est à l'indice 0x0A sur MX Keys S mais 0x09 sur MX Mechanical. Interrogez à l'exécution via IRoot::GetFeature :
Envoyer : {0x11, 0x00, 0x00, 0x0D, 0x18, 0x14, ...} (20 octets)
Lire : réponse octet 4 = indice de la fonctionnalité
Le réappariement du périphérique modifie les chemins HID. Passer du récepteur Bolt au BT LE direct change complètement le chemin. Exécutez query_agent_windows.py pour obtenir les chemins actuels depuis l'agent.
La collection GATT BT LE du fournisseur devient "Inconnue". Windows échoue occasionnellement à initialiser le service GATT HID++. Le périphérique fonctionne normalement mais le canal de commande du fournisseur est mort. Solution : basculer le Bluetooth sur Off/On dans les paramètres Windows. C'est un problème Windows/firmware.
| Version | Statut |
|---|---|
| Logi Options+ 2.0.840907 | Fonctionne (macOS Tahoe, Windows 11) |
Le protocole filaire et les chemins d'API principaux (/devices/list, /change_host/<id>/host) ont été stables. Le réappariement des périphériques a cassé les chemins HID et les numéros de collection mais le protocole IPC lui-même n'a pas été affecté.
Ce projet est uniquement à des fins éducatives et de recherche. Il documente un protocole non documenté et non supporté que Logitech peut modifier ou supprimer à tout moment. Les auteurs ne sont pas responsables des dommages, pertes de données, périphériques rendus inutilisables ou fonctionnalités cassées résultant de l'utilisation de ce code ou de cette documentation. Utilisation à vos risques et périls.
Ce projet n'est pas affilié à Logitech ni approuvé par Logitech.
| Scénario | Ce qui se passe | Détection |
|---|
| Agent non en cours d'exécution | Le socket/tube n'existe pas | connect() lève FileNotFoundError ou ConnectionRefusedError |
| Redémarrage de l'agent en cours de session | La connexion est interrompue | send() lève BrokenPipeError ; recv() renvoie vide |
| Périphérique sur un autre hôte | NO_SUCH_PATH | Vérifier result.code |
| Périphérique inaccessible | TIMEOUT après ~3s | Vérifier result.code |
| Payload malformé | INVALID_MESSAGE_RECEIVED | @type manquant ou champs inconnus |
| Changement du hash du socket | Ancien chemin disparu | Toujours découvrir dynamiquement, jamais coder en dur |
| Socket obsolète après redémarrage | ConnectionRefusedError | Réessayer après un court délai |
| Clients simultanés | Fonctionne correctement | L'agent gère plusieurs connexions |