on macOS
brew install hidapi
brew install ddcctl
on Linux
modprobe i2c-dev
pip install monitorcontrol
on both
pip install hid
| #!/usr/bin/env python | |
| import sys | |
| import hid | |
| import os | |
| host = int(sys.argv[1]) - 1 | |
| monitor_input_sources = [17, 18, 27] # HDMI 1, HDMI 2, USB-C | |
| hid_devices = [ | |
| { | |
| 'name': 'Logi Bolt Receiver', | |
| 'receivers': hid.enumerate(0x046D, 0xC548), | |
| 'command': [ # MX Keys Mini as first device on the receiver | |
| bytes([0x11, 0x01, 0x09, 0x1A, 0x00] + [0] * 15), # change host to 1 | |
| bytes([0x11, 0x01, 0x09, 0x1F, 0x01] + [0] * 15), # change host to 2 | |
| bytes([0x11, 0x01, 0x09, 0x1D, 0x02] + [0] * 15)] # change host to 3 | |
| }, { | |
| 'name': 'Logitech Unified Receiver', | |
| 'receivers': hid.enumerate(0x046D, 0xC52B), | |
| 'command': [ # MX Anywhere 3 as first device on the receiver | |
| bytes([0x11, 0x01, 0x0A, 0x1A, 0x00] + [0] * 15), # change host to 1 | |
| bytes([0x11, 0x01, 0x0A, 0x1E, 0x01] + [0] * 15), # change host to 2 | |
| bytes([0x11, 0x01, 0x0A, 0x19, 0x02] + [0] * 15)] # change host to 3 | |
| }, { | |
| 'name': 'MX Keys Mini Bluetooth', | |
| 'receivers': hid.enumerate(0x046D, 0xB36E), | |
| 'command': [ | |
| bytes([0x11, 0xFF, 0x09, 0x1E, 0x00] + [0] * 15), # change host to 1 | |
| bytes([0x11, 0x01, 0x09, 0x1F, 0x01] + [0] * 15), # change host to 2 | |
| bytes([0x11, 0xFF, 0x09, 0x1D, 0x02] + [0] * 15)] # change host to 3 | |
| }, { | |
| 'name': 'MX Anywhere 3 Bluetooth', | |
| 'receivers': hid.enumerate(0x046D, 0xB025), | |
| 'command': [ | |
| bytes([0x11, 0xFF, 0x0A, 0x1A, 0x00] + [0] * 15), # change host to 1 | |
| bytes([0x11, 0x01, 0x0A, 0x1E, 0x01] + [0] * 15), # change host to 2 | |
| bytes([0x11, 0xFF, 0x0A, 0x19, 0x02] + [0] * 15)] # change host to 3 | |
| } | |
| ] | |
| for d in hid_devices: | |
| for r in d['receivers']: | |
| if r['usage_page'] >= 0xFF00: # and r['usage'] == 1 and | |
| print('found:', d['name'], 'path:', r['path']) | |
| try: | |
| receiver = hid.Device(path=r['path']) | |
| receiver.nonblocking = 1 | |
| data = d['command'][host] | |
| print("sending:", data) | |
| receiver.write(data) | |
| receiver.close() | |
| except hid.HIDException as err: | |
| print(err) | |
| if sys.platform == 'darwin': | |
| os.system(f'/usr/local/bin/ddcctl -d 1 -i {monitor_input_sources[host]}') | |
| else: | |
| import monitorcontrol | |
| try: | |
| m = monitorcontrol.get_monitors()[0] | |
| i = monitor_input_sources[host] | |
| print('display input source:', i) | |
| with m: | |
| m.set_input_source(i) | |
| except Exception as e: | |
| print(e) |