首页 > 代码库 > Linux下hp打印机驱动hplip分析
Linux下hp打印机驱动hplip分析
Hplip分析
版本是2.14,源码位置:http://hplipopensource.com。图的来源:http://hplipopensource.com/node/128。
1.D-Bus初始化流程
D-Bus的初始化同样是在ui4/devmgr5.py开始的。
ui4/devmgr5.py
01 class DevMgr5(QMainWindow, Ui_MainWindow):
02 ......
03 # TODO: Make sbus init mandatory success, else exit
04 def initDBus(self):
05 self.dbus_loop = DBusQtMainLoop(set_as_default=True)
06 self.dbus_avail, self.service, self.session_bus = device.init_dbus(self.dbus_loop)
07 ......
08 # Receive events from the session bus
09 self.session_bus.add_signal_receiver(self.handleSessionSignal, sender_keyword=‘sender‘,
10 destination_keyword=‘dest‘, interface_keyword=‘interface‘,
11 member_keyword=‘member‘, path_keyword=‘path‘)
12 ......
这里调用了base/device.py中的init_dbus()。从第9行可以看出handleSessionSignal是D-Bus服务器端回调函数。
base/device.py
01 #
02 # DBus Support
03 #
04
05 def init_dbus(dbus_loop=None):
06 ......
07 try:
08 if dbus_loop is None:
09 session_bus = dbus.SessionBus()
10 else:
11 session_bus = dbus.SessionBus(dbus_loop)
12 ......
13 try:
14 log.debug("Connecting to com.hplip.StatusService (try #1)...")
15 service = session_bus.get_object(‘com.hplip.StatusService‘, "/com/hplip/StatusService")
16 dbus_avail = True
17 except dbus.exceptions.DBusException, e:
18 try:
19 os.waitpid(-1, os.WNOHANG)
20 except OSError:
21 pass
22
23 path = utils.which(‘hp-systray‘)
24 ......
25 log.debug("Running hp-systray: %s --force-startup" % path)
26
27 os.spawnlp(os.P_NOWAIT, path, ‘hp-systray‘, ‘--force-startup‘)
28
29 log.debug("Waiting for hp-systray to start...")
30 time.sleep(1)
31
32 t = 2
33 while True:
34 try:
35 log.debug("Connecting to com.hplip.StatusService (try #%d)..." % t)
36 service = session_bus.get_object(‘com.hplip.StatusService‘, "/com/hplip/StatusService")
37 ......
38
39 return dbus_avail, service, session_bus
40
41 ......
42
第27行启动了hp-systray作为d-bus的服务器端。D-bus服务器端启动完毕。
2.D-bus服务器hp-systray端启动
启动命令如下:
$ hp-systray --force-startup -g
if __name__ == ‘__main__‘:
......
if child_pid1:
# parent (UI)
os.close(w1)
......
else: # qt4
try:
import ui4.systemtray as systray
except ImportError:
log.error("Unable to load Qt4 support. Is it installed?")
mod.unlockInstance()
sys.exit(1)
try:
systray.run(r1)
finally:
mod.unlockInstance()
else:
# child (dbus & device i/o [qt4] or dbus [qt3])
os.close(r1)
if ui_toolkit == ‘qt4‘:
r2, w2 = os.pipe()
r3, w3 = os.pipe()
child_pid2 = os.fork()
if child_pid2:
# parent (dbus)
os.close(r2)
import hpssd
hpssd.run(w1, w2, r3)
else:
# child (device i/o)
os.close(w2)
import hpdio
hpdio.run(r2, w3)
......
启动了hpssd和hpdio。hpssd前者会从w3管道从读取hpdio写入的打印机状态信息。下面单说hpdio如何获取打印机状态当hpdio run起来的时候会做以下调用run(hpdio.py)->queryDevice(device.py)->status.StatusType10(status.py)->StatusType10Status(status.py)来获取打印机状态。从这里可以看出打印机的状态是在PJL中定义的。获取最底层也是使用PJL来获取的。
3.刷新状态的流程
toolbox.py
01 else: # qt4
02 ......
03 from ui4.devmgr5 import DevMgr5
04 ......
第三行可以看出启动了ui4目录下的devmgr5这个python。
ui4/devmgr5.py
01 class DevMgr5(QMainWindow, Ui_MainWindow):
02 ......
03 def initUI(self):
04 ......
05 self.DeviceRefreshAction.setIcon(QIcon(load_pixmap("refresh1", "16x16")))
06 self.connect(self.DeviceRefreshAction, SIGNAL("triggered()"), self.DeviceRefreshAction_activated)
07 ......
08 def DeviceRefreshAction_activated(self):
09 self.DeviceRefreshAction.setEnabled(False)
10 self.requestDeviceUpdate()
11 self.DeviceRefreshAction.setEnabled(True)
12 ......
13 def requestDeviceUpdate(self, dev=None, item=None):
14 """ Submit device update request to update thread. """
15
16 if dev is None:
17 dev = self.cur_device
18
19 if dev is not None:
20 dev.error_state = ERROR_STATE_REFRESHING
21 self.updateDevice(dev, update_tab=False)
22
23 self.sendMessage(dev.device_uri, ‘‘, EVENT_DEVICE_UPDATE_REQUESTED)
24 ......
25 def sendMessage(self, device_uri, printer_name, event_code, username=prop.username,
26 job_id=0, title=‘‘):
27
28 device.Event(device_uri, printer_name, event_code, username,
29 job_id, title).send_via_dbus(self.session_bus)
30 .....
从第06行可以看出DeviceRefreshAction的槽是DeviceRefreshAction_activated在行8行,接着调用了requestDeviceUpdate,然后调用了sendMessage,然后调用了device.Event。这个在device.py中。
base/device.py
01 class Event(object):
02 ......
03 def send_via_dbus(self, session_bus, interface=‘com.hplip.StatusService‘):
04 if session_bus is not None and dbus_avail:
05 log.debug("Sending event %d to %s (via dbus)..." % (self.event_code, interface))
06 msg = lowlevel.SignalMessage(‘/‘, interface, ‘Event‘)
07 msg.append(signature=self.dbus_fmt, *self.as_tuple())
08 session_bus.send_message(msg)
09 ......
10
这里调用的send_message是获取的d-bus实例的send_message,它在hpdio.py中。
hpdio.py
01 def send_message(device_uri, event_code, bytes_written=0):
02 args = [device_uri, ‘‘, event_code, prop.username, 0, ‘‘, ‘‘, bytes_written]
03 msg = lowlevel.SignalMessage(‘/‘, ‘com.hplip.StatusService‘, ‘Event‘)
04 msg.append(signature=‘ssisissi‘, *args)
05 SessionBus().send_message(msg)
这里是标准的d-bus通信。D-bus在收到这个消息后,会怎么处理,且看以后分析。