KVM 與 USB 軌跡球的中鍵模擬
我在「Synergy - 軟體KVM 使用說明」中提到我的工作需要一套 KVM。我首先嘗試了 Synergy 這套軟體 KVM。它確實做得很好,只是我目前的工作內容常常要退出使用端 X 視窗或切到文字終端機。在這種情形下,Synergy 就不能繼續為我服務了。我不得已,只好再添購一組硬體的 USB KVM;型號是「Uptech KVM211U」。
這陣子使用下來,這種 USB KVM 的相容性問題不大,連我的 USB 軌跡球都能接。但還是有一點的問題,那就是 KVM 在切換終端時,實際上就是在插拔 USB 設備。於是每次按下 KVM 的切換鍵時,作業系統都會出現 USB 鍵盤與滑鼠拔出或連接的情形。 這對我來說就是個困擾了。因我為軌跡球設定了一些操作行為,例如指定中鍵模擬滾輪。不幸的是,當 KVM 切走時(拔出滑鼠),這個設定就會失效;KVM 切回時(插入滑鼠),我得再執行一次設定工作。
下列是在 Linux 系統中, KVM 切換時的系統訊息。切走時顯示 USB 設備離線。切回時顯示新增 USB 鍵盤與 USB 軌跡球。
[21772.590052] usb 2-3.1: USB disconnect, address 5 [21772.768025] usb 2-3.4: USB disconnect, address 6 [21783.132035] usb 2-3.1: new low speed USB device using ohci_hcd and address 7 [21783.268244] usb 2-3.1: configuration #1 chosen from 1 choice [21783.286150] input: USB Keyboard as /devices/pci0000:00/0000:00:0b.0/usb2/2-3/2-3.1/2-3.1:1.0/input/input10 [21783.552033] usb 2-3.4: new low speed USB device using ohci_hcd and address 8 [21783.678212] usb 2-3.4: configuration #1 chosen from 1 choice [21783.689886] input: Logitech USB Trackball as /devices/pci0000:00/0000:00:0b.0/usb2/2-3/2-3.4/2-3.4:1.0/input/input12
我苦練十餘年的編程功力,這時候就要派上用場了(天之聲: 就為了這點小事...)。所以我利用 Linux 的 HAL 服務,寫了一個軌跡球組態守護程式(daemon),它會傾聽 HAL 放出的設備新增訊號,一但發現軌跡球被插入了,它就會接著執行中鍵模擬滾輪的設定工作。我終於不必每次按 KVM 切換後還得再動手跑一次設定。程式 trackman_init 的源碼於下列:
#!/usr/bin/python
# coding: utf-8
import os,sys
reload(sys)
sys.setdefaultencoding('utf-8')
import gobject, dbus
from dbus.mainloop.glib import DBusGMainLoop
HAL_SERVICE_NAME = "org.freedesktop.Hal"
HAL_MANAGER_PATH = "/org/freedesktop/Hal/Manager"
HAL_MANAGER_IFACE = "org.freedesktop.Hal.Manager"
HAL_DEVICE_IFACE = "org.freedesktop.Hal.Device"
TRACKBALL_PRODUCT_NAME = "Logitech USB Trackball"
def init_wheel_emulation():
print("init wheel emulation.")
os.system('xinput set-prop "Logitech USB Trackball" "Evdev Wheel Emulation Button" 8')
os.system('xinput set-prop "Logitech USB Trackball" "Evdev Wheel Emulation" 1')
os.system('xinput set-prop "Logitech USB Trackball" "Evdev Wheel Emulation Axes" 6 7 4 5')
def detect_trackball_device(bus, device_path):
device = dbus.Interface(
bus.get_object(HAL_SERVICE_NAME, device_path),
HAL_DEVICE_IFACE)
info_product = device.GetProperty("info.product")
if info_product == TRACKBALL_PRODUCT_NAME:
#init_wheel_emulation()
return True
return False
class DeviceAddedSignalRecipient:
def __init__(self):
self.bus = dbus.SystemBus()
self.bus.add_signal_receiver(self.device_added_handler,
dbus_interface=HAL_MANAGER_IFACE, signal_name = "DeviceAdded")
def device_added_handler(self, device_path):
#print "Signal recivied: %s" % device_path
if detect_trackball_device(bus, device_path):
init_wheel_emulation()
if __name__ == "__main__":
DBusGMainLoop(set_as_default=True)
loop = gobject.MainLoop()
bus = dbus.SystemBus()
hal_manager = dbus.Interface(
bus.get_object(HAL_SERVICE_NAME, HAL_MANAGER_PATH),
HAL_MANAGER_IFACE)
device_paths = hal_manager.FindDeviceByCapability("input.mouse")
for device_path in device_paths:
if detect_trackball_device(bus, device_path):
init_wheel_emulation()
break
recipient = DeviceAddedSignalRecipient()
try:
loop.run()
except KeyboardInterrupt:
print("Exit program.")
sys.exit()
trackman_init 的工作很簡單。因為 KVM 切回控制權時的狀況等於插入鍵盤滑鼠,所以利用 HAL D-Bus 服務提供的 DeviceAdded 訊號,獲知設備新增的事件。當設備新增事件發生時,就查看新插入設備的產品名稱是否為羅技軌跡球(GetProperty("info.product") == "Logitech USB Trackball"
)。若是就調用 xinput 設定中鍵模擬滾輪的行為。設定方式請參考「Logitech Trackman Marble on Ubuntu 10.04」。另外,trackman_init 啟動時也會利用 HAL D-Bus 服務的 FindDeviceByCapability("input.mouse")
找出已連接的滑鼠設備,並進一步判斷產品種類與啟用設定。
把 trackman_init 加到偏好設定的「始動應用程式」項目中,讓桌面啟動時一併執行,它就會一直在背景幫我傾聽軌跡球的插入事件並啟用滾輪模擬設定。
我以前用過基於 PS/2 設備的 KVM ,我記得那種 KVM 切換後,電腦端仍然以為鍵盤與滑鼠還連接著,並不會離線。PS/2 設備基本上也不支持熱插拔。不知道為何這些 USB KVM 反而退步了。而且因為切換時等於是拔出再插入,切回時,系統還會再花約一秒的時間初始設備。所以實際使用時,總覺得切換時的反應慢了一拍。