首页 > 代码库 > 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行可以看出handleSessionSignalD-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) 

   ......

启动了hpssdhpdiohpssd前者会从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在收到这个消息后,会怎么处理,且看以后分析。