USB设备UDev和D-BUS

17
我正在尝试获取Ubuntu 10.10中当前插入的USB设备列表并监视发生的更改,例如使用UDev和D-BUS插入或拔出设备。我相对较新地使用D-BUS进行编程。我看到了一个例子:Linux:如何检测是否插入或拔出USB键盘,但那个例子使用了HAL,而我知道HAL已经不建议使用了。我找到了一些可行的代码,稍微修改了一下,但它只适用于存储设备,例如USB闪存驱动器、媒体播放器或CD-ROM设备。我想要整个系统,包括鼠标、键盘、USB相机、充电器,任何插入USB的设备,我希望我的程序都能获得这些信息。这基本上是我的代码(http://moserei.de/2010/01/08/accessing-devicekit-with-dbus-and-python.html):
import dbus
import gobject
from dbus.mainloop.glib import DBusGMainLoop

def device_added_callback(device):
    print 'Device %s was added' % (device)

def device_changed_callback(device):
    print 'Device %s was changed' % (device)

#must be done before connecting to DBus
DBusGMainLoop(set_as_default=True)

bus = dbus.SystemBus()

proxy = bus.get_object("org.freedesktop.UDisks", 
                       "/org/freedesktop/UDisks")
iface = dbus.Interface(proxy, "org.freedesktop.UDisks.Device")

devices = iface.get_dbus_method('EnumerateDevices')()

print '%s' % (devices)

#addes two signal listeners
iface.connect_to_signal('DeviceAdded', device_added_callback)
iface.connect_to_signal('DeviceChanged', device_changed_callback)

#start the main loop
mainloop = gobject.MainLoop()
mainloop.run()

希望能得到任何帮助。提前感谢您,Calota Romeo


1
为了将来参考(我正在寻找确切的代码,而不是通用的usb处理程序),您需要更改:iface = dbus.Interface(proxy,“org.freedesktop.UDisks.Device”)为iface = dbus.Interface(proxy,“org.freedesktop.UDisks”)至少在使用udisks 1.0.4时。 - Miro Kropacek
2个回答

11

udisks D-Bus服务显然只报告磁盘。

直接监控udev(通过libudev,通过pyudev)。

import pyudev
context = pyudev.Context()
monitor = pyudev.Monitor.from_netlink(context)
observer = pyudev.pygtk.GUDevMonitorObserver(monitor)
observer.connect('device-added', device_added_callback)
observer.connect('device-changed', device_changed_callback)
monitor.enable_receiving()
mainloop = gobject.MainLoop()
mainloop.run()

谢谢你的帮助,我根据你的答案成功做出了一些东西。 - Calota Romeo
回调函数实际上会是什么样子?我找不到关于“device-added”和“device-changed”信号将传递哪些参数给回调函数的信息。我想查看是否连接了具有特定“idVendor”和“idProduct”的设备,并且需要一些帮助。提前感谢。 - con-f-use
根据pyudev.glib中的列表,这两个信号将使用两个参数调用它们的回调函数,第二个参数是一个带有属性的设备,在device.attributes中。 - ephemient
1
我收到了 AttributeError:'module'对象没有属性'pygtk' 错误。你能详细说明一下吗?从中获取驱动器的 UUID 是可能的吗?这样,只有在添加特定驱动器时才能执行操作? - Redsandro
@Redsandro http://pyudev.readthedocs.org/en/latest/api/pyudev.html#monitorobserver-asynchronous-device-monitoring - mlt

2
这是我用来列出已插入的闪存驱动器的脚本。您可以根据自己的需求修改脚本。
import dbus  
bus = dbus.SystemBus()

proxy = bus.get_object("org.freedesktop.Hal", "/org/freedesktop/Hal/Manager")
iface = dbus.Interface(proxy, "org.freedesktop.Hal.Manager")

devices = iface.GetAllDevices ()

for device in devices:
  try:
      proxy1 = bus.get_object("org.freedesktop.Hal", device)
      iface1 = dbus.Interface(proxy1, "org.freedesktop.Hal.Device")
      props = iface1.GetAllProperties()

      removable = iface1.GetProperty("storage.removable")
      usb = iface1.GetProperty("storage.bus")
      if usb== "usb":
        print "\n".join(("%s: %s" % (k, props[k]) for k in props)) # shows available properties
  except:
    pass

这是我用来查看是否已插入任何USB设备的方法:
#!/usr/bin/python
import dbus
import gobject

class DeviceAddedListener:
                def __init__(self):
                                self.bus = dbus.SystemBus()
                                self.hal_manager_obj = self.bus.get_object("org.freedesktop.Hal", "/org/freedesktop/Hal/Manager")
                                self.hal_manager = dbus.Interface(self.hal_manager_obj,"org.freedesktop.Hal.Manager")

                                self.hal_manager.connect_to_signal("DeviceAdded", self._filter) 

                def _filter(self, udi):
                                device_obj = self.bus.get_object ("org.freedesktop.Hal", udi)
                                device = dbus.Interface(device_obj, "org.freedesktop.Hal.Device")
                                self.do_something(device)

                def do_something(self, device):
                                try:

                                                usb = device.GetProperty("storage.bus")
                                                info = device.GetProperty("info.product")
                                                removable = device.GetProperty("storage.removable")
                                                print info
                                except:
                                                pass#blah blah


if __name__ == '__main__':
                from dbus.mainloop.glib import DBusGMainLoop
                DBusGMainLoop(set_as_default=True)
                loop = gobject.MainLoop()
                DeviceAddedListener()
                loop.run()

这是UDisks的示例代码: Python UDisks - 枚举设备信息

3
依赖于HAL,但这已经被弃用并在最新的Linux发行版中不再存在。 - ephemient
@ephemient 是的,你说得对。但我认为使用“UDisks”不会有太大区别。@Calota 希望这对你有用。 - savruk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接