~ubuntu-branches/ubuntu/raring/hplip/raring

« back to all changes in this revision

Viewing changes to base/device.py

  • Committer: Bazaar Package Importer
  • Author(s): Mark Purcell
  • Date: 2009-12-14 20:08:44 UTC
  • mfrom: (2.1.118 lucid)
  • Revision ID: james.westby@ubuntu.com-20091214200844-z8qhqwgppbu3t7ze
Tags: 3.9.10-4
KBSD patch from KiBi (Closes: #560796)

Show diffs side-by-side

added added

removed removed

Lines of Context:
47
47
    if not os.getenv("HPLIP_BUILD"):
48
48
        log.error("HPMUDEXT could not be loaded. Please check HPLIP installation.")
49
49
        sys.exit(1)
50
 
 
 
50
else:
 
51
    # Workaround for build machine
 
52
    try:
 
53
        MAX_BUFFER = hpmudext.HPMUD_BUFFER_SIZE
 
54
    except AttributeError:
 
55
        MAX_BUFFER = 8192
51
56
 
52
57
dbus_avail = False
53
58
dbus_disabled = False
58
63
except ImportError:
59
64
    log.warn("python-dbus not installed.")
60
65
 
 
66
import warnings
 
67
# Ignore: .../dbus/connection.py:242: DeprecationWarning: object.__init__() takes no parameters
 
68
# (occurring on Python 2.6/dBus 0.83/Ubuntu 9.04)
 
69
warnings.simplefilter("ignore", DeprecationWarning)
 
70
 
61
71
 
62
72
DEFAULT_PROBE_BUS = ['usb', 'par', 'cups']
63
73
VALID_BUSES = ('par', 'net', 'cups', 'usb') #, 'bt', 'fw')
66
76
VALID_FILTERS = ('print', 'scan', 'fax', 'pcard', 'copy')
67
77
DEFAULT_BE_FILTER = ('hp',)
68
78
 
69
 
pat_deviceuri = re.compile(r"""(.*):/(.*?)/(\S*?)\?(?:serial=(\S*)|device=(\S*)|ip=(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}[^&]*))(?:&port=(\d))?""", re.IGNORECASE)
 
79
pat_deviceuri = re.compile(r"""(.*):/(.*?)/(\S*?)\?(?:serial=(\S*)|device=(\S*)|ip=(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}[^&]*)|zc=(\S+))(?:&port=(\d))?""", re.IGNORECASE)
70
80
http_pat_url = re.compile(r"""/(.*?)/(\S*?)\?(?:serial=(\S*)|device=(\S*))&loc=(\S*)""", re.IGNORECASE)
71
81
direct_pat = re.compile(r'direct (.*?) "(.*?)" "(.*?)" "(.*?)"', re.IGNORECASE)
72
82
 
74
84
# Note: If ; not present, CTR value is invalid
75
85
pat_dynamic_ctr = re.compile(r"""CTR:\d*\s.*;""", re.IGNORECASE)
76
86
 
77
 
MAX_BUFFER = 8192
78
 
 
79
87
# Cache for model data
80
88
model_dat = models.ModelData()
81
89
 
82
90
ip_pat = re.compile(r"""\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b""", re.IGNORECASE)
83
 
 
84
91
dev_pat = re.compile(r"""/dev/.+""", re.IGNORECASE)
85
92
usb_pat = re.compile(r"""(\d+):(\d+)""", re.IGNORECASE)
86
93
 
297
304
    cups_uri, sane_uri, fax_uri = '', '', ''
298
305
    found = False
299
306
 
300
 
    # see if the param represents a hostname
301
 
    try:
302
 
        param = socket.gethostbyname(param)
303
 
    except socket.gaierror:
304
 
        log.debug("Gethostbyname() failed. Trying other patterns...")
305
 
 
306
307
    if dev_pat.search(param) is not None: # parallel
307
308
        log.debug("Trying parallel with %s" % param)
308
309
 
342
343
        else:
343
344
            log.debug("Not found.")
344
345
 
345
 
    else: # serial
 
346
    else: # Try Zeroconf hostname
 
347
        log.debug("Trying ZC hostname %s" % param)
 
348
 
 
349
        result_code, uri = hpmudext.make_zc_uri(param, port)
 
350
 
 
351
        if result_code == hpmudext.HPMUD_R_OK and uri:
 
352
            log.debug("Found: %s" % uri)
 
353
            found = True
 
354
            cups_uri = uri
 
355
        else:
 
356
            log.debug("Not found.")
 
357
 
 
358
    if not found:
346
359
        log.debug("Trying serial number %s" % param)
347
360
        devices = probeDevices(bus=['usb', 'par'])
348
361
 
351
364
 
352
365
            # usb has serial in URI...
353
366
            try:
354
 
                back_end, is_hp, bus, model, serial, dev_file, host, port = \
 
367
                back_end, is_hp, bus, model, serial, dev_file, host, zc, port = \
355
368
                    parseDeviceURI(d)
356
369
            except Error:
357
370
                continue
413
426
def queryModelByURI(device_uri):
414
427
    try:
415
428
        back_end, is_hp, bus, model, \
416
 
            serial, dev_file, host, port = \
 
429
            serial, dev_file, host, zc, port = \
417
430
            parseDeviceURI(device_uri)
418
431
    except Error:
419
432
        raise Error(ERROR_INVALID_DEVICE_URI)
426
439
#
427
440
 
428
441
def probeDevices(bus=DEFAULT_PROBE_BUS, timeout=10,
429
 
                 ttl=4, filter=DEFAULT_FILTER,  search='', net_search='slp',
 
442
                 ttl=4, filter=DEFAULT_FILTER,  search='', net_search='mdns',
430
443
                 back_end_filter=('hp',)):
431
444
 
432
445
    num_devices, ret_devices = 0, {}
473
486
                            model = models.normalizeModelName(device_id.get('MDL', '?UNKNOWN?'))
474
487
 
475
488
                            if num_ports_on_jd == 1:
476
 
                                device_uri = 'hp:/net/%s?ip=%s' % (model, ip)
 
489
                                if net_search == 'slp':
 
490
                                    device_uri = 'hp:/net/%s?ip=%s' % (model, ip)
 
491
                                else:
 
492
                                    device_uri = 'hp:/net/%s?zc=%s' % (model, hn)
477
493
                            else:
478
 
                                device_uri = 'hp:/net/%s?ip=%s&port=%d' % (model, ip, (port+1))
 
494
                                if net_search == 'slp':
 
495
                                    device_uri = 'hp:/net/%s?ip=%s&port=%d' % (model, ip, (port + 1))
 
496
                                else:
 
497
                                    device_uri = 'hp:/net/%s?zc=%s&port=%d' % (model, hn, (port + 1))
479
498
 
480
499
                            include = True
481
500
                            mq = queryModelByModel(model)
514
533
                    log.debug(uri)
515
534
 
516
535
                    try:
517
 
                        back_end, is_hp, bb, model, serial, dev_file, host, port = \
 
536
                        back_end, is_hp, bb, model, serial, dev_file, host, zc, port = \
518
537
                            parseDeviceURI(uri)
519
538
                    except Error:
520
539
                        continue
548
567
 
549
568
                if device_uri != '':
550
569
                    try:
551
 
                        back_end, is_hp, bs, model, serial, dev_file, host, port = \
 
570
                        back_end, is_hp, bs, model, serial, dev_file, host, zc, port = \
552
571
                            parseDeviceURI(device_uri)
553
572
                    except Error:
554
573
                        log.debug("Unrecognized URI: %s" % device_uri)
603
622
 
604
623
    for p in printers:
605
624
        try:
606
 
            back_end, is_hp, bus, model, serial, dev_file, host, port = \
 
625
            back_end, is_hp, bus, model, serial, dev_file, host, zc, port = \
607
626
                parseDeviceURI(p.device_uri)
608
627
 
609
628
        except Error:
649
668
 
650
669
    for p in printers:
651
670
        try:
652
 
            back_end, is_hp, bus, model, serial, dev_file, host, port = \
 
671
            back_end, is_hp, bus, model, serial, dev_file, host, zc, port = \
653
672
                parseDeviceURI(p.device_uri)
654
673
 
655
674
        except Error:
692
711
 
693
712
    for p in printers:
694
713
        try:
695
 
            back_end, is_hp, bus, model, serial, dev_file, host, port = \
 
714
            back_end, is_hp, bus, model, serial, dev_file, host, zc, port = \
696
715
                parseDeviceURI(p.device_uri)
697
716
 
698
717
        except Error:
785
804
    serial = m.group(4) or ''
786
805
    dev_file = m.group(5) or ''
787
806
    host = m.group(6) or ''
788
 
    port = m.group(7) or 1
 
807
    zc = ''
 
808
    if not host:
 
809
        zc = host = m.group(7) or ''
 
810
    port = m.group(8) or 1
789
811
 
790
812
    if bus == 'net':
791
813
        try:
796
818
        if port == 0:
797
819
            port = 1
798
820
 
799
 
    return back_end, is_hp, bus, model, serial, dev_file, host, port
 
821
    log.debug("%s: back_end:%s is_hp:%s bus:%s model:%s serial:%s dev_file:%s host:%s zc:%s port:%s" %
 
822
        (device_uri, back_end, is_hp, bus, model, serial, dev_file, host, zc, port))
 
823
 
 
824
    return back_end, is_hp, bus, model, serial, dev_file, host, zc, port
800
825
 
801
826
 
802
827
def isLocal(bus):
920
945
 
921
946
AGENT_types = { AGENT_TYPE_NONE        : 'invalid',
922
947
                AGENT_TYPE_BLACK       : 'black',
 
948
                AGENT_TYPE_BLACK_B8800 : 'black',
923
949
                AGENT_TYPE_CMY         : 'cmy',
924
950
                AGENT_TYPE_KCM         : 'kcm',
925
951
                AGENT_TYPE_CYAN        : 'cyan',
1032
1058
 
1033
1059
        try:
1034
1060
            self.back_end, self.is_hp, self.bus, self.model, \
1035
 
                self.serial, self.dev_file, self.host, self.port = \
 
1061
                self.serial, self.dev_file, self.host, self.zc, self.port = \
1036
1062
                parseDeviceURI(self.device_uri)
1037
1063
        except Error:
1038
1064
            self.io_state = IO_STATE_NON_HP
1080
1106
        self.device_state = DEVICE_STATE_NOT_FOUND
1081
1107
        self.status_code = EVENT_ERROR_DEVICE_NOT_FOUND
1082
1108
 
1083
 
        for p in printers:
1084
 
            if self.device_uri == p.device_uri:
1085
 
                self.cups_printers.append(p.name)
1086
 
                self.state = p.state # ?
1087
 
 
1088
 
                if self.io_state == IO_STATE_NON_HP:
1089
 
                    self.model = p.makemodel.split(',')[0]
1090
 
 
1091
 
        try:
1092
 
            self.first_cups_printer = self.cups_printers[0]
1093
 
        except IndexError:
1094
 
            self.first_cups_printer = ''
 
1109
        self.updateCUPSPrinters()
1095
1110
 
1096
1111
        if self.mq.get('fax-type', FAX_TYPE_NONE) != FAX_TYPE_NONE:
1097
1112
            self.dq.update({ 'fax-uri' : self.device_uri.replace('hp:/', 'hpfax:/').replace('hpaio:/', 'hpfax:/')})
1106
1121
            'dev-file'         : self.dev_file,
1107
1122
            'host'             : self.host,
1108
1123
            'port'             : self.port,
1109
 
            'cups-printer'     : ','.join(self.cups_printers),
 
1124
            'cups-printers'    : self.cups_printers,
1110
1125
            'status-code'      : self.status_code,
1111
1126
            'status-desc'      : '',
1112
1127
            'deviceid'         : '',
1161
1176
 
1162
1177
 
1163
1178
    def open(self, open_for_printing=False):
1164
 
#       print "open()"
1165
 
#       raise Error(ERROR_DEVICE_NOT_FOUND)
1166
 
#       return
1167
 
 
1168
1179
        if self.supported and self.io_state in (IO_STATE_HP_READY, IO_STATE_HP_NOT_AVAIL):
1169
1180
            prev_device_state = self.device_state
1170
1181
            self.io_state = IO_STATE_HP_NOT_AVAIL
1294
1305
    def openPML(self):
1295
1306
        return self.__openChannel(hpmudext.HPMUD_S_PML_CHANNEL)
1296
1307
 
 
1308
    def openWifiConfig(self):
 
1309
        return self.__openChannel(hpmudext.HPMUD_S_WIFI_CHANNEL)
 
1310
 
1297
1311
    def closePML(self):
1298
1312
        return self.__closeChannel(hpmudext.HPMUD_S_PML_CHANNEL)
1299
1313
 
1318
1332
    def closeSoapFax(self):
1319
1333
        return self.__closeChannel(hpmudext.HPMUD_S_SOAP_FAX)
1320
1334
 
 
1335
    def closeWifiConfig(self):
 
1336
        return self.__closeChannel(hpmudext.HPMUD_S_WIFI_CHANNEL)
 
1337
 
1321
1338
    def __closeChannel(self, service_name):
1322
1339
        #if not self.mq['io-mode'] == IO_MODE_UNI and \
1323
1340
        if self.io_state == IO_STATE_HP_OPEN:
1486
1503
 
1487
1504
 
1488
1505
    def __queryFax(self, quick=False, reread_cups_printers=False):
1489
 
#       print "__queryFax()"
1490
 
#       raise Error(ERROR_DEVICE_IO_ERROR)
1491
 
#       return
1492
 
 
1493
1506
        io_mode = self.mq.get('io-mode', IO_MODE_UNI)
1494
1507
        self.status_code = STATUS_PRINTER_IDLE
1495
1508
 
1508
1521
 
1509
1522
                status_desc = self.queryString(self.status_code)
1510
1523
 
1511
 
                #print self.status_code
1512
 
 
1513
1524
                self.dq.update({
1514
1525
                    'serial'           : self.serial,
1515
 
                    'cups-printer'     : ','.join(self.cups_printers),
 
1526
                    'cups-printers'    : self.cups_printers,
1516
1527
                    'status-code'      : self.status_code,
1517
1528
                    'status-desc'      : status_desc,
1518
1529
                    'deviceid'         : self.raw_deviceID,
1533
1544
            elif rx_active:
1534
1545
                self.status_code = STATUS_FAX_RX_ACTIVE
1535
1546
 
1536
 
            #print self.status_code
1537
 
 
1538
1547
            self.error_state = STATUS_TO_ERROR_STATE_MAP.get(self.status_code, ERROR_STATE_CLEAR)
1539
1548
            self.error_code = self.status_code
1540
1549
            self.sendEvent(self.error_code)
1541
1550
 
1542
 
            #print "Error state=", self.error_state, self.device_uri
1543
 
 
1544
1551
            try:
1545
1552
                self.dq.update({'status-desc' : self.queryString(self.status_code),
1546
1553
                                'error-state' : self.error_state,
1571
1578
                                  'panel-line2': line2,})
1572
1579
 
1573
1580
            if not quick and reread_cups_printers:
1574
 
                self.cups_printers = []
1575
 
                log.debug("Re-reading CUPS printer queue information.")
1576
 
                printers = cups.getPrinters()
1577
 
                for p in printers:
1578
 
                    if self.device_uri == p.device_uri:
1579
 
                        self.cups_printers.append(p.name)
1580
 
                        self.state = p.state # ?
1581
 
 
1582
 
                        if self.io_state == IO_STATE_NON_HP:
1583
 
                            self.model = p.makemodel.split(',')[0]
1584
 
 
1585
 
                self.dq.update({'cups-printer' : ','.join(self.cups_printers)})
1586
 
 
1587
 
                try:
1588
 
                    self.first_cups_printer = self.cups_printers[0]
1589
 
                except IndexError:
1590
 
                    self.first_cups_printer = ''
1591
 
 
 
1581
                self.updateCUPSPrinters()
1592
1582
 
1593
1583
        for d in self.dq:
1594
1584
            self.__dict__[d.replace('-','_')] = self.dq[d]
1595
1585
 
1596
1586
        self.last_event = Event(self.device_uri, '', self.status_code, prop.username, 0, '', time.time())
1597
 
        #print self.last_event
1598
1587
 
1599
1588
        log.debug(self.dq)
1600
1589
 
1601
 
        #import pprint
1602
 
 
1603
 
        #pprint.pprint(self.dq)
 
1590
 
 
1591
 
 
1592
    def updateCUPSPrinters(self):
 
1593
        self.cups_printers = []
 
1594
        log.debug("Re-reading CUPS printer queue information.")
 
1595
        printers = cups.getPrinters()
 
1596
        for p in printers:
 
1597
            if self.device_uri == p.device_uri:
 
1598
                self.cups_printers.append(p.name)
 
1599
                self.state = p.state # ?
 
1600
 
 
1601
                if self.io_state == IO_STATE_NON_HP:
 
1602
                    self.model = p.makemodel.split(',')[0]
 
1603
 
 
1604
        self.dq.update({'cups-printers' : self.cups_printers})
 
1605
 
 
1606
        try:
 
1607
            self.first_cups_printer = self.cups_printers[0]
 
1608
        except IndexError:
 
1609
            self.first_cups_printer = ''
1604
1610
 
1605
1611
 
1606
1612
 
1607
1613
 
1608
1614
    def queryDevice(self, quick=False, reread_cups_printers=False):
1609
 
#       print "queryDevice()"
1610
 
#       raise Error(ERROR_DEVICE_IO_ERROR)
1611
 
#       return
1612
 
 
1613
1615
        if not self.supported:
1614
1616
            self.dq = {}
1615
1617
 
1651
1653
 
1652
1654
            self.dq.update({
1653
1655
                'serial'           : self.serial,
1654
 
                'cups-printer'     : ','.join(self.cups_printers),
 
1656
                'cups-printers'    : self.cups_printers,
1655
1657
                'status-code'      : self.status_code,
1656
1658
                'status-desc'      : status_desc,
1657
1659
                'deviceid'         : self.raw_deviceID,
1684
1686
                log.debug("Type 8: LJ PJL")
1685
1687
                status_block = status.StatusType8(self)
1686
1688
 
 
1689
            elif status_type == STATUS_TYPE_LEDM:
 
1690
                log.debug("Type 10: LEDM")
 
1691
                status_block = status.StatusType10(self)
 
1692
 
1687
1693
            else:
1688
1694
                log.error("Unimplemented status type: %d" % status_type)
1689
1695
 
1726
1732
            self.error_code = status_code
1727
1733
            self.sendEvent(self.error_code)
1728
1734
 
1729
 
            #print "Error state=", self.error_state, self.device_uri
1730
 
 
1731
1735
            try:
1732
1736
                self.dq.update({'status-desc' : self.queryString(status_code),
1733
1737
                                'error-state' : self.error_state,
1773
1777
                              })
1774
1778
 
1775
1779
            if not quick and reread_cups_printers:
1776
 
                self.cups_printers = []
1777
 
                log.debug("Re-reading CUPS printer queue information.")
1778
 
                printers = cups.getPrinters()
1779
 
                for p in printers:
1780
 
                    if self.device_uri == p.device_uri:
1781
 
                        self.cups_printers.append(p.name)
1782
 
                        self.state = p.state # ?
1783
 
 
1784
 
                        if self.io_state == IO_STATE_NON_HP:
1785
 
                            self.model = p.makemodel.split(',')[0]
1786
 
 
1787
 
                self.dq.update({'cups-printer' : ','.join(self.cups_printers)})
1788
 
 
1789
 
                try:
1790
 
                    self.first_cups_printer = self.cups_printers[0]
1791
 
                except IndexError:
1792
 
                    self.first_cups_printer = ''
 
1780
                self.updateCUPSPrinters()
1793
1781
 
1794
1782
            if not quick:
1795
1783
                # Make sure there is some valid agent data for this r_value
2108
2096
    def readSoapFax(self, bytes_to_read, stream=None, timeout=prop.read_timeout, allow_short_read=True):
2109
2097
        return self.__readChannel(self.openSoapFax, bytes_to_read, stream, timeout, allow_short_read)
2110
2098
 
 
2099
    def readWifiConfig(self, bytes_to_read, stream=None, timeout=prop.read_timeout, allow_short_read=True):
 
2100
        return self.__readChannel(self.openWifiConfig, bytes_to_read, stream, timeout, allow_short_read)
 
2101
 
2111
2102
    def __readChannel(self, opener, bytes_to_read, stream=None,
2112
2103
                      timeout=prop.read_timeout, allow_short_read=False):
2113
 
#       print "__readChannel()"
2114
 
#       raise Error(ERROR_DEVICE_IO_ERROR)
2115
 
#       return 0
2116
2104
 
2117
2105
        channel_id = opener()
2118
2106
 
2119
 
        log.debug("Reading channel %d..." % channel_id)
 
2107
        log.debug("Reading channel %d (device-id=%d, bytes_to_read=%d, allow_short=%s, timeout=%d)..." %
 
2108
            (channel_id, self.device_id, bytes_to_read, allow_short_read, timeout))
2120
2109
 
2121
2110
        num_bytes = 0
2122
2111
 
2127
2116
            result_code, data = \
2128
2117
                hpmudext.read_channel(self.device_id, channel_id, bytes_to_read, timeout)
2129
2118
 
 
2119
            log.debug("Result code=%d" % result_code)
 
2120
 
2130
2121
            l = len(data)
2131
2122
 
2132
2123
            if result_code == hpmudext.HPMUD_R_IO_TIMEOUT:
2185
2176
    def writeSoapFax(self, data):
2186
2177
        return self.__writeChannel(self.openSoapFax, data)
2187
2178
 
 
2179
    def writeWifiConfig(self, data):
 
2180
        return self.__writeChannel(self.openWifiConfig, data)
2188
2181
 
2189
2182
    def __writeChannel(self, opener, data):
2190
 
#       print "__writeChannel()"
2191
 
#       raise Error(ERROR_DEVICE_IO_ERROR)
2192
 
#       return 0
2193
 
 
2194
2183
        channel_id = opener()
2195
 
 
2196
2184
        buffer, bytes_out, total_bytes_to_write = data, 0, len(data)
2197
 
        log.debug("Writing %d bytes to channel %d..." % (total_bytes_to_write,channel_id))
 
2185
 
 
2186
        log.debug("Writing %d bytes to channel %d (device-id=%d)..." % (total_bytes_to_write, channel_id, self.device_id))
2198
2187
 
2199
2188
        while len(buffer) > 0:
2200
2189
            result_code, bytes_written = \
2201
2190
                hpmudext.write_channel(self.device_id, channel_id,
2202
2191
                    buffer[:prop.max_message_len])
2203
2192
 
 
2193
            log.debug("Result code=%d" % result_code)
 
2194
 
2204
2195
            if result_code != hpmudext.HPMUD_R_OK:
2205
2196
                log.error("Channel write error")
2206
2197
                raise Error(ERROR_DEVICE_IO_ERROR)
2287
2278
        is_gzip = os.path.splitext(file_name)[-1].lower() == '.gz'
2288
2279
 
2289
2280
        if printer_name is None:
2290
 
            try:
2291
 
                printer_name = self.cups_printers[0]
2292
 
            except IndexError:
 
2281
            printer_name = self.first_cups_printer
 
2282
 
 
2283
            if not printer_name:
2293
2284
                raise Error(ERROR_NO_CUPS_QUEUE_FOUND_FOR_DEVICE)
2294
2285
 
2295
2286
        log.debug("Printing file '%s' to queue '%s' (gzip=%s, direct=%s, raw=%s, remove=%s)" %
2401
2392
                data = self
2402
2393
            else:
2403
2394
                url2 = "http://%s%s" % (self.host, url)
 
2395
                if self.zc:
 
2396
                    status, ip = hpmudext.get_zc_ip_address(self.zc)
 
2397
                    if status == hpmudext.HPMUD_R_OK:
 
2398
                        url2 = "http://%s%s" % (ip, url)
2404
2399
                data = None
2405
2400
 
2406
2401
            log.debug("Opening: %s" % url2)