最近更新: 2012-01-19

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 需要配合 HAL D-Bus 服務。 Ubuntu 桌面會預裝 HAL 服務,但是 Debian 桌面好像不會,你得要自己安裝 hal 套件。

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 反而退步了。而且因為切換時等於是拔出再插入,切回時,系統還會再花約一秒的時間初始設備。所以實際使用時,總覺得切換時的反應慢了一拍。

樂多舊網址: http://blog.roodo.com/rocksaying/archives/18797680.html