home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / lib / hplip / base / device.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2006-08-31  |  44.5 KB  |  1,580 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.4)
  3.  
  4. import socket
  5. import re
  6. import gzip
  7. import os.path as os
  8. import time
  9. import struct
  10. import threading
  11. import urllib
  12. import StringIO
  13. import httplib
  14. from g import *
  15. from codes import *
  16. import msg
  17. import utils
  18. import status
  19. import pml
  20. import slp
  21. import service
  22. from prnt import pcl, ldl, cups
  23. DEFAULT_PROBE_BUS = 'usb,par,cups'
  24. VALID_BUSES = ('par', 'net', 'cups', 'usb', 'bt', 'fw')
  25. DEFAULT_FILTER = 'none'
  26. VALID_FILTERS = ('none', 'print', 'scan', 'fax', 'pcard', 'copy')
  27. pat_deviceuri = re.compile('(.*?):/(.*?)/(\\S*?)\\?(?:serial=(\\S*)|device=(\\S*)|ip=(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}[^&]*))(?:&port=(\\d))?', re.IGNORECASE)
  28. http_pat_url = re.compile('/(.*?)/(\\S*?)\\?(?:serial=(\\S*)|device=(\\S*))&loc=(\\S*)', re.IGNORECASE)
  29. pat_dynamic_ctr = re.compile('CTR:\\d*\\s.*;', re.IGNORECASE)
  30. MAX_BUFFER = 8192
  31.  
  32. def makeuri(hpiod_sock, hpssd_sock, param, port = 1):
  33.     ip_pat = re.compile('\\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)
  34.     dev_pat = re.compile('/dev/.+', re.IGNORECASE)
  35.     usb_pat = re.compile('(\\d+):(\\d+)', re.IGNORECASE)
  36.     (cups_uri, sane_uri, fax_uri) = ('', '', '')
  37.     found = False
  38.     
  39.     try:
  40.         param = socket.gethostbyname(param)
  41.     except socket.gaierror:
  42.         log.debug('Gethostbyname() failed.')
  43.  
  44.     if dev_pat.search(param) is not None:
  45.         log.debug('Trying parallel')
  46.         
  47.         try:
  48.             (fields, data, result_code) = msg.xmitMessage(hpiod_sock, 'MakeURI', None, {
  49.                 'device-file': param,
  50.                 'bus': 'par' })
  51.         except Error:
  52.             result_code = ERROR_INTERNAL
  53.  
  54.         if result_code == ERROR_SUCCESS:
  55.             cups_uri = fields.get('device-uri', '')
  56.             found = True
  57.         
  58.     elif usb_pat.search(param) is not None:
  59.         log.debug('Trying USB')
  60.         match_obj = usb_pat.search(param)
  61.         usb_bus_id = match_obj.group(1)
  62.         usb_dev_id = match_obj.group(2)
  63.         
  64.         try:
  65.             (fields, data, result_code) = msg.xmitMessage(hpiod_sock, 'MakeURI', None, {
  66.                 'usb-bus': usb_bus_id,
  67.                 'usb-dev': usb_dev_id,
  68.                 'bus': 'usb' })
  69.         except Error:
  70.             result_code = ERROR_INTERNAL
  71.  
  72.         if result_code == ERROR_SUCCESS:
  73.             cups_uri = fields.get('device-uri', '')
  74.             found = True
  75.         
  76.     elif ip_pat.search(param) is not None:
  77.         log.debug('Trying IP address')
  78.         
  79.         try:
  80.             (fields, data, result_code) = msg.xmitMessage(hpiod_sock, 'MakeURI', None, {
  81.                 'hostname': param,
  82.                 'port': port,
  83.                 'bus': 'net' })
  84.         except Error:
  85.             result_code = ERROR_INTERNAL
  86.  
  87.         if result_code == ERROR_SUCCESS:
  88.             cups_uri = fields.get('device-uri', '')
  89.             found = True
  90.         
  91.     else:
  92.         log.debug('Trying serial number')
  93.         devices = probeDevices(hpssd_sock, bus = 'usb,par')
  94.         for d in devices:
  95.             log.debug(d)
  96.             (back_end, is_hp, bus, model, serial, dev_file, host, port) = parseDeviceURI(d)
  97.             if bus == 'par':
  98.                 (mq, data, result_code) = msg.xmitMessage(hpssd_sock, 'QueryModel', None, {
  99.                     'device-uri': d })
  100.                 (fields, data, result_code) = msg.xmitMessage(hpiod_sock, 'DeviceOpen', None, {
  101.                     'device-uri': d,
  102.                     'io-mode': mq.get('io-mode', '0'),
  103.                     'io-mfp-mode': mq.get('io-mfp-mode', '2'),
  104.                     'io-control': mq.get('io-control', '0'),
  105.                     'io-scan-port': mq.get('io-scan-port', '0') })
  106.                 if result_code == ERROR_SUCCESS:
  107.                     device_id = fields['device-id']
  108.                     (fields, data, result_code) = msg.xmitMessage(hpiod_sock, 'DeviceID', None, {
  109.                         'device-id': device_id })
  110.                     serial = parseDeviceID(data).get('SN', '')
  111.                 
  112.                 (fields, data, result_code) = msg.xmitMessage(hpiod_sock, 'DeviceClose', None, {
  113.                     'device-id': device_id })
  114.             
  115.             if serial.lower() == param.lower():
  116.                 found = True
  117.                 cups_uri = d
  118.                 break
  119.                 continue
  120.         
  121.     if found:
  122.         (fields, data, result_code) = msg.xmitMessage(hpssd_sock, 'QueryModel', None, {
  123.             'device-uri': cups_uri })
  124.         if fields.get('scan-type', 0):
  125.             sane_uri = cups_uri.replace('hp:', 'hpaio:')
  126.         
  127.         if fields.get('fax-type', 0):
  128.             fax_uri = cups_uri.replace('hp:', 'hpfax:')
  129.         
  130.     
  131.     return (cups_uri, sane_uri, fax_uri)
  132.  
  133.  
  134. def getInteractiveDeviceURI(bus = 'cups,usb,par', filter = 'none', back_end_filter = [
  135.     'hp']):
  136.     bus = bus.lower()
  137.     probed_devices = probeDevices(bus = bus, filter = filter)
  138.     cups_printers = cups.getPrinters()
  139.     log.debug(probed_devices)
  140.     log.debug(cups_printers)
  141.     max_deviceid_size = 0
  142.     x = 0
  143.     devices = { }
  144.     for d in probed_devices:
  145.         printers = []
  146.         (back_end, is_hp, bus, model, serial, dev_file, host, port) = parseDeviceURI(d)
  147.         if back_end in back_end_filter:
  148.             for p in cups_printers:
  149.                 if p.device_uri == d:
  150.                     printers.append(p.name)
  151.                     continue
  152.             
  153.             devices[x] = (d, printers)
  154.             x += 1
  155.             max_deviceid_size = max(len(d), max_deviceid_size)
  156.             continue
  157.     
  158.     if x == 0:
  159.         log.error('No devices found.')
  160.         raise Error(ERROR_NO_PROBED_DEVICES_FOUND)
  161.     elif x == 1:
  162.         log.info(utils.bold('Using device: %s' % devices[0][0]))
  163.         return devices[0][0]
  164.     else:
  165.         log.info(utils.bold('\nChoose device from probed devices connected on bus(es): %s:\n' % bus))
  166.         formatter = utils.TextFormatter(({
  167.             'width': 4 }, {
  168.             'width': max_deviceid_size,
  169.             'margin': 2 }, {
  170.             'width': 100 - max_deviceid_size - 8,
  171.             'margin': 2 }))
  172.         log.info(formatter.compose(('Num.', 'Device-URI', 'CUPS printer(s)')))
  173.         log.info(formatter.compose(('-' * 4, '-' * max_deviceid_size, '-' * (80 - max_deviceid_size - 10))))
  174.         for y in range(x):
  175.             log.info(formatter.compose((str(y), devices[y][0], ', '.join(devices[y][1]))))
  176.         
  177.         while None:
  178.             user_input = raw_input(utils.bold('\nEnter number 0...%d for device (q=quit) ?' % (x - 1)))
  179.             if user_input == '':
  180.                 log.warn("Invalid input - enter a numeric value or 'q' to quit.")
  181.                 continue
  182.             
  183.             if user_input.strip()[0] in ('q', 'Q'):
  184.                 return None
  185.             
  186.             
  187.             try:
  188.                 i = int(user_input)
  189.             except ValueError:
  190.                 log.warn("Invalid input - enter a numeric value or 'q' to quit.")
  191.                 continue
  192.  
  193.             if i < 0 or i > x - 1:
  194.                 log.warn("Invalid input - enter a value between 0 and %d or 'q' to quit." % (x - 1))
  195.                 continue
  196.             
  197.             break
  198.         return devices[i][0]
  199.  
  200.  
  201. def probeDevices(sock = None, bus = 'cups,usb,par', timeout = 5, ttl = 4, filter = 'none', format = 'default'):
  202.     close_sock = False
  203.     if sock is None:
  204.         close_sock = True
  205.         sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  206.         
  207.         try:
  208.             sock.connect((prop.hpssd_host, prop.hpssd_port))
  209.         except socket.error:
  210.             raise Error(ERROR_UNABLE_TO_CONTACT_SERVICE)
  211.         except:
  212.             None<EXCEPTION MATCH>socket.error
  213.         
  214.  
  215.     None<EXCEPTION MATCH>socket.error
  216.     (fields, data, result_code) = msg.xmitMessage(sock, 'ProbeDevicesFiltered', None, {
  217.         'bus': bus,
  218.         'timeout': timeout,
  219.         'ttl': ttl,
  220.         'format': format,
  221.         'filter': filter })
  222.     if close_sock:
  223.         sock.close()
  224.     
  225.     if result_code > ERROR_SUCCESS:
  226.         return ''
  227.     
  228.     temp = data.splitlines()
  229.     probed_devices = []
  230.     for t in temp:
  231.         probed_devices.append(t.split(',')[0])
  232.     
  233.     return probed_devices
  234.  
  235.  
  236. def getSupportedCUPSDevices(back_end_filter = [
  237.     'hp']):
  238.     devices = { }
  239.     printers = cups.getPrinters()
  240.     for p in printers:
  241.         
  242.         try:
  243.             (back_end, is_hp, bus, model, serial, dev_file, host, port) = parseDeviceURI(p.device_uri)
  244.         except Error:
  245.             continue
  246.  
  247.         if back_end in back_end_filter:
  248.             
  249.             try:
  250.                 devices[p.device_uri]
  251.             except KeyError:
  252.                 devices[p.device_uri] = [
  253.                     p.name]
  254.  
  255.             devices[p.device_uri].append(p.name)
  256.             continue
  257.     
  258.     return devices
  259.  
  260.  
  261. def parseDeviceID(device_id):
  262.     d = { }
  263.     x = _[1]
  264.     for z in x:
  265.         y = z.split(':')
  266.         
  267.         try:
  268.             d.setdefault(y[0].strip(), y[1])
  269.         continue
  270.         except IndexError:
  271.             []
  272.             []
  273.             []
  274.             d.setdefault(y[0].strip(), None)
  275.             continue
  276.         
  277.  
  278.     
  279.     d.setdefault('MDL', '')
  280.     d.setdefault('SN', '')
  281.     if 'SERIAL' in d:
  282.         d['SN'] = d['SERIAL']
  283.         del d['SERIAL']
  284.     elif 'SERN' in d:
  285.         d['SN'] = d['SERN']
  286.         del d['SERN']
  287.     
  288.     if d['SN'].startswith('X'):
  289.         d['SN'] = ''
  290.     
  291.     return d
  292.  
  293.  
  294. def parseDynamicCounter(ctr_field, convert_to_int = True):
  295.     (counter, value) = ctr_field.split(' ')
  296.     
  297.     try:
  298.         if not counter.lstrip('0'):
  299.             pass
  300.         counter = int('0')
  301.         if convert_to_int:
  302.             if not value.lstrip('0'):
  303.                 pass
  304.             value = int('0')
  305.     except ValueError:
  306.         if convert_to_int:
  307.             (counter, value) = (0, 0)
  308.         else:
  309.             (counter, value) = (0, '')
  310.     except:
  311.         convert_to_int
  312.  
  313.     return (counter, value)
  314.  
  315.  
  316. def parseDeviceURI(device_uri):
  317.     m = pat_deviceuri.match(device_uri)
  318.     if m is None:
  319.         raise Error(ERROR_INVALID_DEVICE_URI)
  320.     
  321.     if not m.group(1).lower():
  322.         pass
  323.     back_end = ''
  324.     is_hp = back_end in ('hp', 'hpfax', 'hpaio')
  325.     if not m.group(2).lower():
  326.         pass
  327.     bus = ''
  328.     if bus not in ('usb', 'net', 'bt', 'fw', 'par'):
  329.         raise Error(ERROR_INVALID_DEVICE_URI)
  330.     
  331.     if not m.group(3):
  332.         pass
  333.     model = ''
  334.     if not m.group(4):
  335.         pass
  336.     serial = ''
  337.     if not m.group(5):
  338.         pass
  339.     dev_file = ''
  340.     if not m.group(6):
  341.         pass
  342.     host = ''
  343.     if not m.group(7):
  344.         pass
  345.     port = 1
  346.     if bus == 'net':
  347.         
  348.         try:
  349.             port = int(port)
  350.         except (ValueError, TypeError):
  351.             port = 1
  352.  
  353.         if port == 0:
  354.             port = 1
  355.         
  356.     
  357.     return (back_end, is_hp, bus, model, serial, dev_file, host, port)
  358.  
  359.  
  360. def validateBusList(bus):
  361.     for x in bus.split(','):
  362.         bb = x.lower().strip()
  363.         if bb not in VALID_BUSES:
  364.             log.error('Invalid bus name: %s' % bb)
  365.             return False
  366.             continue
  367.     
  368.     return True
  369.  
  370.  
  371. def validateFilterList(filter):
  372.     for f in filter.split(','):
  373.         if f not in VALID_FILTERS:
  374.             log.error("Invalid term '%s' in filter list" % f)
  375.             return False
  376.             continue
  377.     
  378.     return True
  379.  
  380. AGENT_types = {
  381.     AGENT_TYPE_NONE: 'invalid',
  382.     AGENT_TYPE_BLACK: 'black',
  383.     AGENT_TYPE_CMY: 'cmy',
  384.     AGENT_TYPE_KCM: 'kcm',
  385.     AGENT_TYPE_CYAN: 'cyan',
  386.     AGENT_TYPE_MAGENTA: 'magenta',
  387.     AGENT_TYPE_YELLOW: 'yellow',
  388.     AGENT_TYPE_CYAN_LOW: 'photo_cyan',
  389.     AGENT_TYPE_MAGENTA_LOW: 'photo_magenta',
  390.     AGENT_TYPE_YELLOW_LOW: 'photo_yellow',
  391.     AGENT_TYPE_GGK: 'photo_gray',
  392.     AGENT_TYPE_BLUE: 'photo_blue',
  393.     AGENT_TYPE_KCMY_CM: 'kcmy_cm',
  394.     AGENT_TYPE_LC_LM: 'photo_cyan_and_photo_magenta',
  395.     AGENT_TYPE_Y_M: 'yellow_and_magenta',
  396.     AGENT_TYPE_C_K: 'cyan_and_black',
  397.     AGENT_TYPE_LG_PK: 'light_gray_and_photo_black',
  398.     AGENT_TYPE_LG: 'light_gray',
  399.     AGENT_TYPE_G: 'medium_gray',
  400.     AGENT_TYPE_PG: 'photo_gray',
  401.     AGENT_TYPE_UNSPECIFIED: 'unspecified' }
  402. AGENT_kinds = {
  403.     AGENT_KIND_NONE: 'invalid',
  404.     AGENT_KIND_HEAD: 'head',
  405.     AGENT_KIND_SUPPLY: 'supply',
  406.     AGENT_KIND_HEAD_AND_SUPPLY: 'cartridge',
  407.     AGENT_KIND_TONER_CARTRIDGE: 'toner',
  408.     AGENT_KIND_MAINT_KIT: 'maint_kit',
  409.     AGENT_KIND_ADF_KIT: 'adf_kit',
  410.     AGENT_KIND_DRUM_KIT: 'drum_kit',
  411.     AGENT_KIND_TRANSFER_KIT: 'transfer_kit',
  412.     AGENT_KIND_INT_BATTERY: 'battery',
  413.     AGENT_KIND_UNKNOWN: 'unknown' }
  414. AGENT_healths = {
  415.     AGENT_HEALTH_OK: 'ok',
  416.     AGENT_HEALTH_MISINSTALLED: 'misinstalled',
  417.     AGENT_HEALTH_FAIR_MODERATE: '',
  418.     AGENT_HEALTH_INCORRECT: 'incorrect',
  419.     AGENT_HEALTH_FAILED: 'failed',
  420.     AGENT_HEALTH_OVERTEMP: 'overtemp',
  421.     AGENT_HEALTH_CHARGING: 'charging',
  422.     AGENT_HEALTH_DISCHARGING: 'discharging' }
  423. AGENT_levels = {
  424.     AGENT_LEVEL_TRIGGER_MAY_BE_LOW: 'low',
  425.     AGENT_LEVEL_TRIGGER_PROBABLY_OUT: 'low',
  426.     AGENT_LEVEL_TRIGGER_ALMOST_DEFINITELY_OUT: 'out' }
  427. MODEL_UI_REPLACEMENTS = {
  428.     'laserjet': 'LaserJet',
  429.     'psc': 'PSC',
  430.     'officejet': 'Officejet',
  431.     'deskjet': 'Deskjet',
  432.     'hp': 'HP',
  433.     'business': 'Business',
  434.     'inkjet': 'Inkjet',
  435.     'photosmart': 'Photosmart',
  436.     'color': 'Color',
  437.     'series': 'series',
  438.     'printer': 'Printer',
  439.     'mfp': 'MFP',
  440.     'mopier': 'Mopier' }
  441.  
  442. def normalizeModelUIName(model):
  443.     if not model.lower().startswith('hp'):
  444.         z = 'HP ' + model.replace('_', ' ')
  445.     else:
  446.         z = model.replace('_', ' ')
  447.     y = []
  448.     for x in z.split():
  449.         xx = x.lower()
  450.         y.append(MODEL_UI_REPLACEMENTS.get(xx, xx))
  451.     
  452.     return ' '.join(y)
  453.  
  454.  
  455. def normalizeModelName(model):
  456.     return model.replace(' ', '_').replace('__', '_').replace('~', '').replace('/', '_').strip('_')
  457.  
  458.  
  459. def isLocal(bus):
  460.     return bus in ('par', 'usb', 'fw', 'bt')
  461.  
  462. string_cache = { }
  463.  
  464. class Device(object):
  465.     
  466.     def __init__(self, device_uri, printer_name = None, hpssd_sock = None, hpiod_sock = None, callback = None):
  467.         if device_uri is None:
  468.             printers = cups.getPrinters()
  469.             for p in printers:
  470.                 if p.name.lower() == printer_name.lower():
  471.                     device_uri = p.device_uri
  472.                     break
  473.                 
  474.             else:
  475.                 raise Error(ERROR_DEVICE_NOT_FOUND)
  476.         
  477.         self.device_uri = device_uri
  478.         self.callback = callback
  479.         self.close_socket = False
  480.         self.query_device_thread = None
  481.         
  482.         try:
  483.             (self.back_end, self.is_hp, self.bus, self.model, self.serial, self.dev_file, self.host, self.port) = parseDeviceURI(self.device_uri)
  484.         except Error:
  485.             self.io_state = IO_STATE_NON_HP
  486.             raise Error(ERROR_INVALID_DEVICE_URI)
  487.  
  488.         log.debug('URI: backend=%s, is_hp=%s, bus=%s, model=%s, serial=%s, dev=%s, host=%s, port=%d' % (self.back_end, self.is_hp, self.bus, self.model, self.serial, self.dev_file, self.host, self.port))
  489.         self.model_ui = normalizeModelUIName(self.model)
  490.         self.model = normalizeModelName(self.model)
  491.         log.debug('Model/UI model: %s/%s' % (self.model, self.model_ui))
  492.         if hpiod_sock is None:
  493.             self.hpiod_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  494.             
  495.             try:
  496.                 self.hpiod_sock.connect((prop.hpiod_host, prop.hpiod_port))
  497.                 self.close_hpiod_socket = True
  498.             except socket.error:
  499.                 raise Error(ERROR_UNABLE_TO_CONTACT_SERVICE)
  500.  
  501.         else:
  502.             self.hpiod_sock = hpiod_sock
  503.         log.debug('hpiod socket: %d' % self.hpiod_sock.fileno())
  504.         if hpssd_sock is None:
  505.             self.hpssd_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  506.             
  507.             try:
  508.                 self.hpssd_sock.connect((prop.hpssd_host, prop.hpssd_port))
  509.                 self.close_hpssd_socket = True
  510.             except socket.error:
  511.                 raise Error(ERROR_UNABLE_TO_CONTACT_SERVICE)
  512.  
  513.         else:
  514.             self.hpssd_sock = hpssd_sock
  515.         log.debug('hpssd socket: %d' % self.hpssd_sock.fileno())
  516.         service.setAlertsEx(self.hpssd_sock)
  517.         self.mq = { }
  518.         self.dq = { }
  519.         self.cups_printers = []
  520.         self.channels = { }
  521.         self.device_id = -1
  522.         self.r_values = None
  523.         self.deviceID = ''
  524.         self.panel_check = True
  525.         self.io_state = IO_STATE_HP_READY
  526.         self.is_local = isLocal(self.bus)
  527.         self.supported = False
  528.         self.queryModel()
  529.         if not (self.supported):
  530.             log.error('Unsupported model: %s' % self.model)
  531.             self.sendEvent(STATUS_DEVICE_UNSUPPORTED)
  532.         else:
  533.             self.supported = True
  534.         self.mq.update({
  535.             'model': self.model,
  536.             'model-ui': self.model_ui })
  537.         self.error_state = ERROR_STATE_ERROR
  538.         self.device_state = DEVICE_STATE_NOT_FOUND
  539.         self.status_code = EVENT_ERROR_DEVICE_NOT_FOUND
  540.         printers = cups.getPrinters()
  541.         for p in printers:
  542.             if self.device_uri == p.device_uri:
  543.                 self.cups_printers.append(p.name)
  544.                 self.state = p.state
  545.                 if self.io_state == IO_STATE_NON_HP:
  546.                     self.model = p.makemodel.split(',')[0]
  547.                 
  548.             
  549.         
  550.         
  551.         try:
  552.             self.first_cups_printer = self.cups_printers[0]
  553.         except IndexError:
  554.             self.first_cups_printer = ''
  555.  
  556.         if self.mq.get('fax-type', FAX_TYPE_NONE) != FAX_TYPE_NONE:
  557.             self.dq.update({
  558.                 'fax-uri': self.device_uri.replace('hp:/', 'hpfax:/').replace('hpaio:/', 'hpfax:/') })
  559.         
  560.         if self.mq.get('scan-type', SCAN_TYPE_NONE) != SCAN_TYPE_NONE:
  561.             self.dq.update({
  562.                 'scan-uri': self.device_uri.replace('hp:/', 'hpaio:/').replace('hpfax:/', 'hpaio:/') })
  563.         
  564.         self.dq.update({
  565.             'back-end': self.back_end,
  566.             'is-hp': self.is_hp,
  567.             'serial': self.serial,
  568.             'dev-file': self.dev_file,
  569.             'host': self.host,
  570.             'port': self.port,
  571.             'cups-printer': ','.join(self.cups_printers),
  572.             'status-code': self.status_code,
  573.             'status-desc': '',
  574.             'deviceid': '',
  575.             'panel': 0,
  576.             'panel-line1': '',
  577.             'panel-line2': '',
  578.             '3bit-status-code': 0,
  579.             '3bit-status-name': 'IOTrap',
  580.             'device-state': self.device_state,
  581.             'error-state': self.error_state,
  582.             'device-uri': self.device_uri,
  583.             'cups-uri': self.device_uri.replace('hpfax:/', 'hp:/').replace('hpaio:/', 'hp:/') })
  584.         self.device_vars = {
  585.             'URI': self.device_uri,
  586.             'DEVICE_URI': self.device_uri,
  587.             'SCAN_URI': self.device_uri.replace('hp:', 'hpaio:'),
  588.             'SANE_URI': self.device_uri.replace('hp:', 'hpaio:'),
  589.             'FAX_URI': self.device_uri.replace('hp:', 'hpfax:'),
  590.             'PRINTER': self.first_cups_printer,
  591.             'HOME': prop.home_dir }
  592.  
  593.     
  594.     def xmitHpiodMessage(self, msg_type, other_fields = { }, payload = None, timeout = prop.read_timeout):
  595.         return msg.xmitMessage(self.hpiod_sock, msg_type, payload, other_fields, timeout)
  596.  
  597.     
  598.     def xmitHpssdMessage(self, msg_type, other_fields = { }, payload = None, timeout = prop.read_timeout):
  599.         return msg.xmitMessage(self.hpssd_sock, msg_type, payload, other_fields, timeout)
  600.  
  601.     
  602.     def quit(self):
  603.         if self.close_hpiod_socket:
  604.             self.hpiod_sock.close()
  605.         
  606.         if self.close_hpssd_socket:
  607.             self.hpssd_sock.close()
  608.         
  609.  
  610.     
  611.     def queryModel(self):
  612.         if not self.mq:
  613.             (self.mq, data, result_code) = self.xmitHpssdMessage('QueryModel', {
  614.                 'device-uri': self.device_uri })
  615.         
  616.         self.supported = bool(self.mq)
  617.         if self.supported:
  618.             for m in self.mq:
  619.                 self.__dict__[m.replace('-', '_')] = self.mq[m]
  620.             
  621.         
  622.  
  623.     
  624.     def queryString(self, string_id):
  625.         if string_id not in string_cache:
  626.             (fields, data, result_code) = self.xmitHpssdMessage('QueryString', {
  627.                 'string-id': string_id })
  628.             if result_code == ERROR_SUCCESS:
  629.                 string_cache[string_id] = data
  630.                 return data
  631.             else:
  632.                 return ''
  633.         else:
  634.             return string_cache[string_id]
  635.  
  636.     
  637.     def open(self, network_timeout = 3):
  638.         if self.supported and self.io_state in (IO_STATE_HP_READY, IO_STATE_HP_NOT_AVAIL):
  639.             log.debug('Opening device: %s' % self.device_uri)
  640.             prev_device_state = self.device_state
  641.             self.io_state = IO_STATE_HP_NOT_AVAIL
  642.             self.device_state = DEVICE_STATE_NOT_FOUND
  643.             self.error_state = ERROR_STATE_ERROR
  644.             self.status_code = EVENT_ERROR_DEVICE_NOT_FOUND
  645.             self.device_id = -1
  646.             (fields, data, result_code) = self.xmitHpiodMessage('DeviceOpen', {
  647.                 'device-uri': self.device_uri,
  648.                 'io-mode': self.mq.get('io-mode', '0'),
  649.                 'io-mfp-mode': self.mq.get('io-mfp-mode', '2'),
  650.                 'io-control': self.mq.get('io-control', '0'),
  651.                 'io-scan-port': self.mq.get('io-scan-port', '0') })
  652.             if result_code != ERROR_SUCCESS:
  653.                 self.sendEvent(EVENT_ERROR_DEVICE_NOT_FOUND, typ = 'error')
  654.                 log.error('Unable to communicate with device: %s' % self.device_uri)
  655.                 raise Error(ERROR_DEVICE_NOT_FOUND)
  656.             else:
  657.                 self.device_id = fields['device-id']
  658.                 log.debug('device-id=%d' % self.device_id)
  659.                 self.io_state = IO_STATE_HP_OPEN
  660.                 self.error_state = ERROR_STATE_CLEAR
  661.                 log.debug('Opened device: %s (backend=%s,is_hp=%s,bus=%s,model=%s,dev=%s,serial=%s,host=%s,port=%d)' % (self.back_end, self.device_uri, self.is_hp, self.bus, self.model, self.dev_file, self.serial, self.host, self.port))
  662.                 if prev_device_state == DEVICE_STATE_NOT_FOUND:
  663.                     self.device_state = DEVICE_STATE_JUST_FOUND
  664.                 else:
  665.                     self.device_state = DEVICE_STATE_FOUND
  666.                 self.getDeviceID()
  667.                 self.getSerialNumber()
  668.                 return self.device_id
  669.         
  670.  
  671.     
  672.     def close(self):
  673.         if self.io_state == IO_STATE_HP_OPEN:
  674.             log.debug('Closing device...')
  675.             if len(self.channels) > 0:
  676.                 for c in self.channels.keys():
  677.                     self._Device__closeChannel(c)
  678.                 
  679.             
  680.             (fields, data, result_code) = self.xmitHpiodMessage('DeviceClose', {
  681.                 'device-id': self.device_id })
  682.             self.channels.clear()
  683.             self.io_state = IO_STATE_HP_READY
  684.         
  685.  
  686.     
  687.     def __openChannel(self, service_name):
  688.         self.open()
  689.         if not self.mq['io-mode'] == IO_MODE_UNI:
  690.             service_name = service_name.upper()
  691.             if service_name not in self.channels:
  692.                 log.debug('Opening %s channel...' % service_name)
  693.                 (fields, data, result_code) = self.xmitHpiodMessage('ChannelOpen', {
  694.                     'device-id': self.device_id,
  695.                     'service-name': service_name })
  696.                 
  697.                 try:
  698.                     channel_id = fields['channel-id']
  699.                 except KeyError:
  700.                     raise Error(ERROR_INTERNAL)
  701.  
  702.                 self.channels[service_name] = channel_id
  703.                 log.debug('channel-id=%d' % channel_id)
  704.                 return channel_id
  705.             else:
  706.                 return self.channels[service_name]
  707.         else:
  708.             return -1
  709.  
  710.     
  711.     def openChannel(self, service_name):
  712.         return self._Device__openChannel(service_name)
  713.  
  714.     
  715.     def openPrint(self):
  716.         return self._Device__openChannel('PRINT')
  717.  
  718.     
  719.     def openFax(self):
  720.         return self._Device__openChannel('HP-FAX-SEND')
  721.  
  722.     
  723.     def openPCard(self):
  724.         return self._Device__openChannel('HP-CARD-ACCESS')
  725.  
  726.     
  727.     def openFax(self):
  728.         return self._Device__openChannel('HP-FAX-SEND')
  729.  
  730.     
  731.     def openEWS(self):
  732.         return self._Device__openChannel('HP-EWS')
  733.  
  734.     
  735.     def closePrint(self):
  736.         return self._Device__closeChannel('PRINT')
  737.  
  738.     
  739.     def closePCard(self):
  740.         return self._Device__closeChannel('HP-CARD-ACCESS')
  741.  
  742.     
  743.     def closeFax(self):
  744.         return self._Device__closeChannel('HP-FAX')
  745.  
  746.     
  747.     def openPML(self):
  748.         return self._Device__openChannel('HP-MESSAGE')
  749.  
  750.     
  751.     def closePML(self):
  752.         return self._Device__closeChannel('HP-MESSAGE')
  753.  
  754.     
  755.     def closeEWS(self):
  756.         return self._Device__closeChannel('HP-EWS')
  757.  
  758.     
  759.     def openCfgUpload(self):
  760.         return self._Device__openChannel('HP-CONFIGURATION-UPLOAD')
  761.  
  762.     
  763.     def closeCfgUpload(self):
  764.         return self._Device__closeChannel('HP-CONFIGURATION-UPLOAD')
  765.  
  766.     
  767.     def openCfgDownload(self):
  768.         return self._Device__openChannel('HP-CONFIGURATION-DOWNLOAD')
  769.  
  770.     
  771.     def closeCfgDownload(self):
  772.         return self._Device__closeChannel('HP-CONFIGURATION-DOWNLOAD')
  773.  
  774.     
  775.     def __closeChannel(self, service_name):
  776.         if not (self.mq['io-mode'] == IO_MODE_UNI) and self.io_state == IO_STATE_HP_OPEN:
  777.             service_name = service_name.upper()
  778.             if service_name in self.channels:
  779.                 log.debug('Closing %s channel...' % service_name)
  780.                 (fields, data, result_code) = self.xmitHpiodMessage('ChannelClose', {
  781.                     'device-id': self.device_id,
  782.                     'channel-id': self.channels[service_name] })
  783.                 del self.channels[service_name]
  784.             
  785.         
  786.  
  787.     
  788.     def closeChannel(self, service_name):
  789.         return self._Device__closeChannel(service_name)
  790.  
  791.     
  792.     def getDeviceID(self):
  793.         (fields, data, result_code) = self.xmitHpiodMessage('DeviceID', {
  794.             'device-id': self.device_id })
  795.         if result_code != ERROR_SUCCESS:
  796.             self.raw_deviceID = ''
  797.             self.deviceID = { }
  798.         else:
  799.             self.raw_deviceID = data
  800.             self.deviceID = parseDeviceID(data)
  801.         return self.deviceID
  802.  
  803.     
  804.     def getSerialNumber(self):
  805.         if self.serial:
  806.             return None
  807.         
  808.         
  809.         try:
  810.             self.serial = self.deviceID['SN']
  811.         except KeyError:
  812.             pass
  813.  
  814.         if self.serial:
  815.             return None
  816.         
  817.         if self.mq.get('status-type', STATUS_TYPE_NONE) != STATUS_TYPE_NONE and not (self.mq.get('io-mode', IO_MODE_UNI) == IO_MODE_UNI):
  818.             
  819.             try:
  820.                 (error_code, self.serial) = self.getPML(pml.OID_SERIAL_NUMBER)
  821.             except Error:
  822.                 self.serial = ''
  823.             finally:
  824.                 self.closePML()
  825.  
  826.         
  827.         if self.serial is None:
  828.             self.serial = ''
  829.         
  830.  
  831.     
  832.     def getThreeBitStatus(self):
  833.         (fields, data, result_code) = self.xmitHpiodMessage('DeviceStatus', {
  834.             'device-id': self.device_id })
  835.         if result_code != ERROR_SUCCESS:
  836.             self.three_bit_status_code = 0
  837.             self.three_bit_status_name = 'IOTrap'
  838.         else:
  839.             self.three_bit_status_code = fields['status-code']
  840.             self.three_bit_status_name = fields['status-name']
  841.  
  842.     
  843.     def getStatusFromDeviceID(self):
  844.         self.getDeviceID()
  845.         return status.parseStatus(parseDeviceID(self.raw_deviceID))
  846.  
  847.     
  848.     def queryDevice(self, quick = False):
  849.         if not (self.supported):
  850.             self.dq = { }
  851.             return None
  852.         
  853.         r_type = self.mq.get('r-type', 0)
  854.         tech_type = self.mq.get('tech-type', TECH_TYPE_NONE)
  855.         status_type = self.mq.get('status-type', STATUS_TYPE_NONE)
  856.         io_mode = self.mq.get('io-mode', IO_MODE_UNI)
  857.         if io_mode == IO_MODE_UNI and self.back_end != 'net':
  858.             status_type = STATUS_TYPE_NONE
  859.         
  860.         agents = []
  861.         if self.device_state != DEVICE_STATE_NOT_FOUND:
  862.             
  863.             try:
  864.                 self.getThreeBitStatus()
  865.             except Error:
  866.                 e = None
  867.                 log.error('Error getting 3-bit status.')
  868.                 raise Error(ERROR_DEVICE_IO_ERROR)
  869.  
  870.             if self.tech_type in (TECH_TYPE_MONO_INK, TECH_TYPE_COLOR_INK):
  871.                 
  872.                 try:
  873.                     self.getDeviceID()
  874.                 except Error:
  875.                     e = None
  876.                     log.error('Error getting device ID.')
  877.                     raise Error(ERROR_DEVICE_IO_ERROR)
  878.  
  879.             
  880.             
  881.             try:
  882.                 status_desc = self.queryString(self.status_code)
  883.             except Error:
  884.                 status_desc = ''
  885.  
  886.             self.dq.update({
  887.                 'serial': self.serial,
  888.                 'cups-printer': ','.join(self.cups_printers),
  889.                 'status-code': self.status_code,
  890.                 'status-desc': status_desc,
  891.                 'deviceid': self.raw_deviceID,
  892.                 'panel': 0,
  893.                 'panel-line1': '',
  894.                 'panel-line2': '',
  895.                 '3bit-status-code': self.three_bit_status_code,
  896.                 '3bit-status-name': self.three_bit_status_name,
  897.                 'device-state': self.device_state,
  898.                 'error-state': self.error_state })
  899.             status_block = { }
  900.             if status_type == STATUS_TYPE_NONE:
  901.                 log.warn('No status available for device.')
  902.                 status_block = {
  903.                     'status-code': STATUS_PRINTER_IDLE }
  904.             elif status_type in (STATUS_TYPE_VSTATUS, STATUS_TYPE_S, STATUS_TYPE_S_SNMP):
  905.                 log.debug('Type 1/2 (S: or VSTATUS:) status')
  906.                 status_block = status.parseStatus(self.deviceID)
  907.             elif status_type == STATUS_TYPE_LJ:
  908.                 log.debug('Type 3 LaserJet status')
  909.                 status_block = status.StatusType3(self, self.deviceID)
  910.             elif status_type == STATUS_TYPE_S_W_BATTERY:
  911.                 log.debug('Type 4 S: status with battery check')
  912.                 status_block = status.parseStatus(self.deviceID)
  913.                 status.BatteryCheck(self, status_block)
  914.             elif status_type == STATUS_TYPE_LJ_XML:
  915.                 log.debug('Type 6: LJ XML')
  916.                 status_block = status.StatusType6(self)
  917.             else:
  918.                 log.error('Unimplemented status type: %d' % status_type)
  919.             if status_block:
  920.                 log.debug(status_block)
  921.                 self.dq.update(status_block)
  922.                 
  923.                 try:
  924.                     status_block['agents']
  925.                 except KeyError:
  926.                     pass
  927.  
  928.                 agents = status_block['agents']
  929.                 del self.dq['agents']
  930.             
  931.             status_code = self.dq.get('status-code', STATUS_UNKNOWN)
  932.             if not quick and self.mq.get('fax-type', 0) and status_code == STATUS_PRINTER_IDLE:
  933.                 (tx_active, rx_active) = status.getFaxStatus(self)
  934.                 if tx_active:
  935.                     status_code = STATUS_FAX_TX_ACTIVE
  936.                 elif rx_active:
  937.                     status_code = STATUS_FAX_RX_ACTIVE
  938.                 
  939.             
  940.             typ = 'event'
  941.             self.error_state = STATUS_TO_ERROR_STATE_MAP.get(status_code, ERROR_STATE_CLEAR)
  942.             if self.error_state == ERROR_STATE_ERROR:
  943.                 typ = 'error'
  944.             
  945.             self.sendEvent(status_code, typ = typ)
  946.             
  947.             try:
  948.                 self.dq.update({
  949.                     'status-desc': self.queryString(status_code),
  950.                     'error-state': self.error_state })
  951.             except (KeyError, Error):
  952.                 self.dq.update({
  953.                     'status-desc': '',
  954.                     'error-state': ERROR_STATE_CLEAR })
  955.  
  956.             if not quick:
  957.                 (r_value, rg, rr, r_value_str) = (0, '000', '000000', '000000000')
  958.                 if status_type != STATUS_TYPE_NONE:
  959.                     if self.panel_check:
  960.                         self.panel_check = bool(self.mq.get('panel-check-type', 0))
  961.                     
  962.                     if self.panel_check and status_type in (STATUS_TYPE_NONE, STATUS_TYPE_LJ, STATUS_TYPE_S_W_BATTERY, STATUS_TYPE_S_SNMP):
  963.                         
  964.                         try:
  965.                             (self.panel_check, line1, line2) = status.PanelCheck(self)
  966.                         finally:
  967.                             self.closePML()
  968.  
  969.                         self.dq.update({
  970.                             'panel': int(self.panel_check),
  971.                             'panel-line1': line1,
  972.                             'panel-line2': line2 })
  973.                     
  974.                     if r_type > 0:
  975.                         if self.r_values is None:
  976.                             (fields, data, result_code) = self.xmitHpssdMessage('GetValue', {
  977.                                 'device-uri': self.device_uri,
  978.                                 'key': 'r_value' })
  979.                             if result_code == ERROR_SUCCESS and data:
  980.                                 
  981.                                 try:
  982.                                     r_value = int(data.strip())
  983.                                 except:
  984.                                     pass
  985.  
  986.                                 log.debug('r_value=%d' % r_value)
  987.                                 r_value_str = str(r_value)
  988.                                 r_value_str = ''.join([
  989.                                     '0' * (9 - len(r_value_str)),
  990.                                     r_value_str])
  991.                                 (rg, rr) = (r_value_str[:3], r_value_str[3:])
  992.                                 r_value = int(rr)
  993.                                 self.r_values = (r_value, r_value_str, rg, rr)
  994.                             
  995.                             if self.r_values is None:
  996.                                 if status_type == STATUS_TYPE_S and self.is_local:
  997.                                     
  998.                                     try:
  999.                                         r_value = self.getDynamicCounter(140)
  1000.                                         if r_value is not None:
  1001.                                             log.debug('r_value=%d' % r_value)
  1002.                                             r_value_str = str(r_value)
  1003.                                             r_value_str = ''.join([
  1004.                                                 '0' * (9 - len(r_value_str)),
  1005.                                                 r_value_str])
  1006.                                             (rg, rr) = (r_value_str[:3], r_value_str[3:])
  1007.                                             r_value = int(rr)
  1008.                                             self.r_values = (r_value, r_value_str, rg, rr)
  1009.                                             (fields, data, result_code) = self.xmitHpssdMessage('SetValue', {
  1010.                                                 'device-uri': self.device_uri,
  1011.                                                 'key': 'r_value',
  1012.                                                 'value': r_value })
  1013.                                         else:
  1014.                                             log.error('Error attempting to read r-value (2).')
  1015.                                             r_value = 0
  1016.                                     except Error:
  1017.                                         log.error('Error attempting to read r-value (1).')
  1018.                                         r_value = 0
  1019.                                     finally:
  1020.                                         self.closePrint()
  1021.  
  1022.                                 elif status_type == STATUS_TYPE_S and not (self.is_local) or status_type == STATUS_TYPE_S_SNMP:
  1023.                                     
  1024.                                     try:
  1025.                                         (result_code, r_value) = self.getPML(pml.OID_R_SETTING)
  1026.                                         if r_value is not None:
  1027.                                             log.debug('r_value=%d' % r_value)
  1028.                                             r_value_str = str(r_value)
  1029.                                             r_value_str = ''.join([
  1030.                                                 '0' * (9 - len(r_value_str)),
  1031.                                                 r_value_str])
  1032.                                             (rg, rr) = (r_value_str[:3], r_value_str[3:])
  1033.                                             r_value = int(rr)
  1034.                                             self.r_values = (r_value, r_value_str, rg, rr)
  1035.                                             (fields, data, result_code) = self.xmitHpssdMessage('SetValue', {
  1036.                                                 'device-uri': self.device_uri,
  1037.                                                 'key': 'r_value',
  1038.                                                 'value': r_value })
  1039.                                         else:
  1040.                                             r_value = 0
  1041.                                     finally:
  1042.                                         self.closePML()
  1043.  
  1044.                                 
  1045.                             
  1046.                         else:
  1047.                             (r_value, r_value_str, rg, rr) = self.r_values
  1048.                     
  1049.                 
  1050.                 self.dq.update({
  1051.                     'r': r_value,
  1052.                     'rs': r_value_str,
  1053.                     'rg': rg,
  1054.                     'rr': rr })
  1055.             
  1056.             if not quick:
  1057.                 a = 1
  1058.                 while True:
  1059.                     mq_agent_kind = self.mq.get('r%d-agent%d-kind' % (r_value, a), 0)
  1060.                     if mq_agent_kind == 0:
  1061.                         break
  1062.                     
  1063.                     mq_agent_type = self.mq.get('r%d-agent%d-type' % (r_value, a), 0)
  1064.                     mq_agent_sku = self.mq.get('r%d-agent%d-sku' % (r_value, a), '')
  1065.                     found = False
  1066.                     for agent in agents:
  1067.                         agent_kind = agent['kind']
  1068.                         agent_type = agent['type']
  1069.                         if agent_kind == mq_agent_kind and agent_type == mq_agent_type:
  1070.                             found = True
  1071.                             break
  1072.                         
  1073.                     
  1074.                     if found:
  1075.                         agent_health = agent.get('health', AGENT_HEALTH_OK)
  1076.                         agent_level_trigger = agent.get('level-trigger', AGENT_LEVEL_TRIGGER_SUFFICIENT_0)
  1077.                         query = 'agent_%s_%s' % (AGENT_types.get(agent_type, 'unknown'), AGENT_kinds.get(agent_kind, 'unknown'))
  1078.                         
  1079.                         try:
  1080.                             agent_desc = self.queryString(query)
  1081.                         except Error:
  1082.                             agent_desc = ''
  1083.  
  1084.                         query = 'agent_health_ok'
  1085.                         if status_code == STATUS_PRINTER_IDLE:
  1086.                             if agent_health == AGENT_HEALTH_OK and agent_health == AGENT_HEALTH_FAIR_MODERATE and agent_kind == AGENT_KIND_HEAD and agent_level_trigger >= AGENT_LEVEL_TRIGGER_MAY_BE_LOW:
  1087.                                 query = 'agent_level_%s' % AGENT_levels.get(agent_level_trigger, 'unknown')
  1088.                                 if tech_type in (TECH_TYPE_MONO_INK, TECH_TYPE_COLOR_INK):
  1089.                                     code = agent_type + STATUS_PRINTER_LOW_INK_BASE
  1090.                                 else:
  1091.                                     code = agent_type + STATUS_PRINTER_LOW_TONER_BASE
  1092.                                 self.dq['status-code'] = code
  1093.                                 
  1094.                                 try:
  1095.                                     self.dq['status-desc'] = self.queryString(code)
  1096.                                 except Error:
  1097.                                     self.dq['status-desc'] = ''
  1098.  
  1099.                                 self.dq['error-state'] = STATUS_TO_ERROR_STATE_MAP.get(code, ERROR_STATE_LOW_SUPPLIES)
  1100.                                 self.sendEvent(code)
  1101.                                 if agent_level_trigger in (AGENT_LEVEL_TRIGGER_PROBABLY_OUT, AGENT_LEVEL_TRIGGER_ALMOST_DEFINITELY_OUT):
  1102.                                     query = 'agent_level_out'
  1103.                                 else:
  1104.                                     query = 'agent_level_low'
  1105.                             
  1106.                         
  1107.                         try:
  1108.                             agent_health_desc = self.queryString(query)
  1109.                         except Error:
  1110.                             agent_health_desc = ''
  1111.  
  1112.                         self.dq.update({
  1113.                             'agent%d-kind' % a: agent_kind,
  1114.                             'agent%d-type' % a: agent_type,
  1115.                             'agent%d-known' % a: agent.get('known', False),
  1116.                             'agent%d-sku' % a: mq_agent_sku,
  1117.                             'agent%d-level' % a: agent.get('level', 0),
  1118.                             'agent%d-level-trigger' % a: agent_level_trigger,
  1119.                             'agent%d-ack' % a: agent.get('ack', False),
  1120.                             'agent%d-hp-ink' % a: agent.get('hp-ink', False),
  1121.                             'agent%d-health' % a: agent_health,
  1122.                             'agent%d-dvc' % a: agent.get('dvc', 0),
  1123.                             'agent%d-virgin' % a: agent.get('virgin', False),
  1124.                             'agent%d-desc' % a: agent_desc,
  1125.                             'agent%d-id' % a: agent.get('id', 0),
  1126.                             'agent%d-health-desc' % a: agent_health_desc })
  1127.                     else:
  1128.                         agent_health = AGENT_HEALTH_MISINSTALLED
  1129.                         agent_level_trigger = AGENT_LEVEL_TRIGGER_ALMOST_DEFINITELY_OUT
  1130.                         query = 'agent_%s_%s' % (AGENT_types.get(mq_agent_type, 'unknown'), AGENT_kinds.get(mq_agent_kind, 'unknown'))
  1131.                         
  1132.                         try:
  1133.                             agent_desc = self.queryString(query)
  1134.                         except Error:
  1135.                             agent_desc = ''
  1136.  
  1137.                         
  1138.                         try:
  1139.                             agent_health_desc = self.queryString('agent_health_misinstalled')
  1140.                         except Error:
  1141.                             agent_health_desc = ''
  1142.  
  1143.                         self.dq.update({
  1144.                             'agent%d-kind' % a: mq_agent_kind,
  1145.                             'agent%d-type' % a: mq_agent_type,
  1146.                             'agent%d-known' % a: False,
  1147.                             'agent%d-sku' % a: mq_agent_sku,
  1148.                             'agent%d-level' % a: 0,
  1149.                             'agent%d-level-trigger' % a: agent_level_trigger,
  1150.                             'agent%d-ack' % a: False,
  1151.                             'agent%d-hp-ink' % a: False,
  1152.                             'agent%d-health' % a: agent_health,
  1153.                             'agent%d-dvc' % a: 0,
  1154.                             'agent%d-virgin' % a: False,
  1155.                             'agent%d-desc' % a: agent_desc,
  1156.                             'agent%d-id' % a: 0,
  1157.                             'agent%d-health-desc' % a: agent_health_desc })
  1158.                     a += 1
  1159.                 r_value = 0
  1160.                 if r_type > 0 and self.r_values is not None:
  1161.                     r_value = self.r_values[0]
  1162.                 
  1163.                 a = 1
  1164.                 while True:
  1165.                     mq_agent_kind = self.mq.get('r%d-agent%d-kind' % (r_value, a), 0)
  1166.                     if mq_agent_kind == 0:
  1167.                         break
  1168.                     
  1169.                     mq_agent_type = self.mq.get('r%d-agent%d-type' % (r_value, a), 0)
  1170.                     mq_agent_sku = self.mq.get('r%d-agent%d-sku' % (r_value, a), '')
  1171.                     query = 'agent_%s_%s' % (AGENT_types.get(mq_agent_type, 'unknown'), AGENT_kinds.get(mq_agent_kind, 'unknown'))
  1172.                     
  1173.                     try:
  1174.                         agent_desc = self.queryString(query)
  1175.                     except Error:
  1176.                         agent_desc = ''
  1177.  
  1178.                     self.dq.update({
  1179.                         'agent%d-kind' % a: mq_agent_kind,
  1180.                         'agent%d-type' % a: mq_agent_type,
  1181.                         'agent%d-known' % a: False,
  1182.                         'agent%d-sku' % a: mq_agent_sku,
  1183.                         'agent%d-level' % a: 0,
  1184.                         'agent%d-level-trigger' % a: AGENT_LEVEL_TRIGGER_ALMOST_DEFINITELY_OUT,
  1185.                         'agent%d-ack' % a: False,
  1186.                         'agent%d-hp-ink' % a: False,
  1187.                         'agent%d-health' % a: AGENT_HEALTH_MISINSTALLED,
  1188.                         'agent%d-dvc' % a: 0,
  1189.                         'agent%d-virgin' % a: False,
  1190.                         'agent%d-health-desc' % a: self.queryString('agent_health_unknown'),
  1191.                         'agent%d-desc' % a: agent_desc,
  1192.                         'agent%d-id' % a: 0 })
  1193.                     a += 1
  1194.             
  1195.         
  1196.         for d in self.dq:
  1197.             self.__dict__[d.replace('-', '_')] = self.dq[d]
  1198.         
  1199.         log.debug(self.dq)
  1200.  
  1201.     
  1202.     def isBusyOrInErrorState(self):
  1203.         self.queryDevice(quick = True)
  1204.         return self.error_state in (ERROR_STATE_ERROR, ERROR_STATE_BUSY)
  1205.  
  1206.     
  1207.     def isIdleAndNoError(self):
  1208.         self.queryDevice(quick = True)
  1209.         return self.error_state not in (ERROR_STATE_ERROR, ERROR_STATE_BUSY)
  1210.  
  1211.     
  1212.     def getPML(self, oid, desired_int_size = pml.INT_SIZE_INT):
  1213.         channel_id = self.openPML()
  1214.         (fields, data, result_code) = self.xmitHpiodMessage('GetPML', {
  1215.             'device-id': self.device_id,
  1216.             'channel-id': channel_id,
  1217.             'oid': pml.PMLToSNMP(oid[0]),
  1218.             'type': oid[1] })
  1219.         pml_result_code = fields.get('pml-result-code', pml.ERROR_OK)
  1220.         if pml_result_code >= pml.ERROR_UNKNOWN_REQUEST:
  1221.             return (pml_result_code, None)
  1222.         
  1223.         return (pml_result_code, pml.ConvertFromPMLDataFormat(data, oid[1], desired_int_size))
  1224.  
  1225.     
  1226.     def setPML(self, oid, value):
  1227.         channel_id = self.openPML()
  1228.         value = pml.ConvertToPMLDataFormat(value, oid[1])
  1229.         (fields, data, result_code) = self.xmitHpiodMessage('SetPML', {
  1230.             'device-id': self.device_id,
  1231.             'channel-id': channel_id,
  1232.             'oid': pml.PMLToSNMP(oid[0]),
  1233.             'type': oid[1] }, value)
  1234.         return fields.get('pml-result-code', pml.ERROR_OK)
  1235.  
  1236.     
  1237.     def getDynamicCounter(self, counter, convert_to_int = True):
  1238.         if 'DYN' in self.deviceID.get('CMD', '').split(','):
  1239.             self.printData(pcl.buildDynamicCounter(counter), direct = True)
  1240.             (value, tries, times_seen, sleepy_time, max_tries) = (0, 0, 0, 0.10000000000000001, 5)
  1241.             time.sleep(0.10000000000000001)
  1242.             while True:
  1243.                 if self.callback:
  1244.                     self.callback()
  1245.                 
  1246.                 sleepy_time += 0.10000000000000001
  1247.                 tries += 1
  1248.                 time.sleep(sleepy_time)
  1249.                 self.getDeviceID()
  1250.                 if 'CTR' in self.deviceID and pat_dynamic_ctr.search(self.raw_deviceID) is not None:
  1251.                     (dev_counter, value) = parseDynamicCounter(self.deviceID['CTR'], convert_to_int)
  1252.                     if counter == dev_counter:
  1253.                         self.printData(pcl.buildDynamicCounter(0), direct = True)
  1254.                         if not convert_to_int:
  1255.                             value = '#' + value
  1256.                         
  1257.                         return value
  1258.                     
  1259.                 
  1260.                 if tries > max_tries:
  1261.                     self.printData(pcl.buildDynamicCounter(0), direct = True)
  1262.                     return None
  1263.                 
  1264.                 self.printData(pcl.buildDynamicCounter(counter), direct = True)
  1265.         else:
  1266.             raise Error(ERROR_DEVICE_DOES_NOT_SUPPORT_OPERATION)
  1267.  
  1268.     
  1269.     def readPrint(self, bytes_to_read, stream = None, timeout = prop.read_timeout):
  1270.         return self._Device__readChannel(self.openPrint, bytes_to_read, stream, timeout)
  1271.  
  1272.     
  1273.     def readPCard(self, bytes_to_read, stream = None, timeout = prop.read_timeout):
  1274.         return self._Device__readChannel(self.openPCard, bytes_to_read, stream, timeout)
  1275.  
  1276.     
  1277.     def readFax(self, bytes_to_read, stream = None, timeout = prop.read_timeout):
  1278.         return self._Device__readChannel(self.openFax, bytes_to_read, stream, timeout)
  1279.  
  1280.     
  1281.     def readCfgUpload(self, bytes_to_read, stream = None, timeout = prop.read_timeout):
  1282.         return self._Device__readChannel(self.openCfgUpload, bytes_to_read, stream, timeout)
  1283.  
  1284.     
  1285.     def readEWS(self, bytes_to_read, stream = None, timeout = prop.read_timeout):
  1286.         return self._Device__readChannel(self.openEWS, bytes_to_read, stream, timeout, True)
  1287.  
  1288.     
  1289.     def __readChannel(self, opener, bytes_to_read, stream = None, timeout = prop.read_timeout, allow_short_read = False):
  1290.         channel_id = opener()
  1291.         log.debug('Reading channel %d...' % channel_id)
  1292.         num_bytes = 0
  1293.         if stream is None:
  1294.             buffer = ''
  1295.         
  1296.         while True:
  1297.             (fields, data, result_code) = self.xmitHpiodMessage('ChannelDataIn', {
  1298.                 'device-id': self.device_id,
  1299.                 'channel-id': channel_id,
  1300.                 'bytes-to-read': bytes_to_read,
  1301.                 'timeout': timeout })
  1302.             l = len(data)
  1303.             if result_code != ERROR_SUCCESS:
  1304.                 log.error('Channel read error')
  1305.                 raise Error(ERROR_DEVICE_IO_ERROR)
  1306.             
  1307.             if not l:
  1308.                 log.debug('End of data')
  1309.                 break
  1310.             
  1311.             if stream is None:
  1312.                 buffer = ''.join([
  1313.                     buffer,
  1314.                     data])
  1315.             else:
  1316.                 stream.write(data)
  1317.             num_bytes += l
  1318.             if self.callback is not None:
  1319.                 self.callback()
  1320.             
  1321.             if num_bytes == bytes_to_read or allow_short_read:
  1322.                 log.debug('Read complete')
  1323.                 break
  1324.                 continue
  1325.         if stream is None:
  1326.             log.debug('Returned %d total bytes in buffer.' % num_bytes)
  1327.             return buffer
  1328.         else:
  1329.             log.debug('Wrote %d total bytes to stream.' % num_bytes)
  1330.             return num_bytes
  1331.  
  1332.     
  1333.     def writePrint(self, data):
  1334.         return self._Device__writeChannel(self.openPrint, data)
  1335.  
  1336.     
  1337.     def writePCard(self, data):
  1338.         return self._Device__writeChannel(self.openPCard, data)
  1339.  
  1340.     
  1341.     def writeFax(self, data):
  1342.         return self._Device__writeChannel(self.openFax, data)
  1343.  
  1344.     
  1345.     def writeEWS(self, data):
  1346.         return self._Device__writeChannel(self.openEWS, data)
  1347.  
  1348.     
  1349.     def writeCfgDownload(self, data):
  1350.         return self._Device__writeChannel(self.openCfgDownload, data)
  1351.  
  1352.     
  1353.     def __writeChannel(self, opener, data):
  1354.         channel_id = opener()
  1355.         log.debug('Writing channel %d...' % channel_id)
  1356.         buffer = data
  1357.         bytes_out = 0
  1358.         total_bytes_to_write = len(data)
  1359.         while len(buffer) > 0:
  1360.             (fields, data, result_code) = self.xmitHpiodMessage('ChannelDataOut', {
  1361.                 'device-id': self.device_id,
  1362.                 'channel-id': channel_id }, buffer[:prop.max_message_len])
  1363.             if result_code != ERROR_SUCCESS:
  1364.                 log.error('Channel write error')
  1365.                 raise Error(ERROR_DEVICE_IO_ERROR)
  1366.             
  1367.             buffer = buffer[prop.max_message_len:]
  1368.             bytes_out += fields['bytes-written']
  1369.             if self.callback is not None:
  1370.                 self.callback()
  1371.                 continue
  1372.         if total_bytes_to_write != bytes_out:
  1373.             raise Error(ERROR_DEVICE_IO_ERROR)
  1374.         
  1375.         return bytes_out
  1376.  
  1377.     
  1378.     def writeEmbeddedPML(self, oid, value, style = 1, direct = True):
  1379.         if style == 1:
  1380.             func = pcl.buildEmbeddedPML2
  1381.         else:
  1382.             func = pcl.buildEmbeddedPML
  1383.         data = func(pcl.buildPCLCmd('&', 'b', 'W', pml.buildEmbeddedPMLSetPacket(oid[0], value, oid[1])))
  1384.         self.printData(data, direct = True)
  1385.  
  1386.     
  1387.     def printGzipFile(self, file_name, printer_name = None, direct = False, raw = True, remove = False):
  1388.         return self.printFile(file_name, printer_name, direct, raw, remove)
  1389.  
  1390.     
  1391.     def printParsedGzipPostscript(self, print_file, printer_name = None):
  1392.         
  1393.         try:
  1394.             os.stat(print_file)
  1395.         except OSError:
  1396.             log.error('File not found: %s' % print_file)
  1397.             return None
  1398.  
  1399.         (temp_file_fd, temp_file_name) = utils.make_temp_file()
  1400.         f = gzip.open(print_file, 'r')
  1401.         x = f.readline()
  1402.         while not x.startswith('%PY_BEGIN'):
  1403.             os.write(temp_file_fd, x)
  1404.             x = f.readline()
  1405.         sub_lines = []
  1406.         x = f.readline()
  1407.         while not x.startswith('%PY_END'):
  1408.             sub_lines.append(x)
  1409.             x = f.readline()
  1410.         SUBS = {
  1411.             'VERSION': prop.version,
  1412.             'MODEL': self.model_ui,
  1413.             'URI': self.device_uri,
  1414.             'BUS': self.bus,
  1415.             'SERIAL': self.serial,
  1416.             'IP': self.host,
  1417.             'PORT': self.port,
  1418.             'DEVNODE': self.dev_file }
  1419.         if self.bus == 'net':
  1420.             SUBS['DEVNODE'] = 'n/a'
  1421.         else:
  1422.             SUBS['IP'] = 'n/a'
  1423.             SUBS['PORT'] = 'n/a'
  1424.         for s in sub_lines:
  1425.             os.write(temp_file_fd, s % SUBS)
  1426.         
  1427.         os.write(temp_file_fd, f.read())
  1428.         f.close()
  1429.         os.close(temp_file_fd)
  1430.         self.printFile(temp_file_name, printer_name, direct = False, raw = False, remove = True)
  1431.  
  1432.     
  1433.     def printFile(self, file_name, printer_name = None, direct = False, raw = True, remove = False):
  1434.         is_gzip = os.path.splitext(file_name)[-1].lower() == '.gz'
  1435.         if printer_name is None:
  1436.             
  1437.             try:
  1438.                 printer_name = self.cups_printers[0]
  1439.             except IndexError:
  1440.                 raise Error(ERROR_NO_CUPS_QUEUE_FOUND_FOR_DEVICE)
  1441.             except:
  1442.                 None<EXCEPTION MATCH>IndexError
  1443.             
  1444.  
  1445.         None<EXCEPTION MATCH>IndexError
  1446.         log.debug("Printing file '%s' to queue '%s' (gzip=%s, direct=%s, raw=%s, remove=%s)" % (file_name, printer_name, is_gzip, direct, raw, remove))
  1447.         if direct:
  1448.             if is_gzip:
  1449.                 self.writePrint(gzip.open(file_name, 'r').read())
  1450.             else:
  1451.                 self.writePrint(file(file_name, 'r').read())
  1452.         elif raw:
  1453.             lp_opt = '-oraw'
  1454.         else:
  1455.             lp_opt = ''
  1456.         if is_gzip:
  1457.             c = 'gunzip -c %s | lp -c -d%s %s' % (file_name, printer_name, lp_opt)
  1458.         else:
  1459.             c = 'lp -c -d%s %s %s' % (printer_name, lp_opt, file_name)
  1460.         log.debug(c)
  1461.         os.system(c)
  1462.         if remove:
  1463.             os.remove(file_name)
  1464.         
  1465.  
  1466.     
  1467.     def printTestPage(self, printer_name = None):
  1468.         return self.printParsedGzipPostscript(os.path.join(prop.home_dir, 'data', 'ps', 'testpage.ps.gz'), printer_name)
  1469.  
  1470.     
  1471.     def printData(self, data, printer_name = None, direct = True, raw = True):
  1472.         if direct:
  1473.             self.writePrint(data)
  1474.         else:
  1475.             (temp_file_fd, temp_file_name) = utils.make_temp_file()
  1476.             os.write(temp_file_fd, data)
  1477.             os.close(temp_file_fd)
  1478.             self.printFile(temp_file_name, printer_name, direct, raw, remove = True)
  1479.  
  1480.     
  1481.     def cancelJob(self, jobid):
  1482.         cups.cancelJob(jobid)
  1483.         self.sendEvent(STATUS_PRINTER_CANCELING, jobid)
  1484.  
  1485.     
  1486.     def sendEvent(self, event, jobid = 0, typ = 'event'):
  1487.         msg.sendEvent(self.hpssd_sock, 'Event', None, {
  1488.             'job-id': jobid,
  1489.             'event-type': typ,
  1490.             'event-code': event,
  1491.             'username': prop.username,
  1492.             'device-uri': self.device_uri,
  1493.             'retry-timeout': 0 })
  1494.  
  1495.     
  1496.     def queryHistory(self):
  1497.         (fields, data, result_code) = self.xmitHpssdMessage('QueryHistory', {
  1498.             'device-uri': self.device_uri })
  1499.         result = []
  1500.         lines = data.strip().splitlines()
  1501.         lines.reverse()
  1502.         for x in lines:
  1503.             (yr, mt, dy, hr, mi, sec, wd, yd, dst, job, user, ec, ess, esl) = x.strip().split(',', 13)
  1504.             result.append((int(yr), int(mt), int(dy), int(hr), int(mi), int(sec), int(wd), int(yd), int(dst), int(job), user, int(ec), ess, esl))
  1505.         
  1506.         return result
  1507.  
  1508.     
  1509.     def getEWSUrl(self, url, stream):
  1510.         
  1511.         try:
  1512.             if self.is_local:
  1513.                 url2 = '%s&loc=%s' % (self.device_uri, url)
  1514.                 data = self
  1515.             else:
  1516.                 url2 = 'http://%s%s' % (self.host, url)
  1517.                 data = None
  1518.             log.debug('Opening: %s' % url2)
  1519.             opener = LocalOpener({ })
  1520.             
  1521.             try:
  1522.                 f = opener.open(url2, data)
  1523.             except Error:
  1524.                 log.error('Status read failed: %s' % url2)
  1525.                 stream.seek(0)
  1526.                 stream.truncate()
  1527.  
  1528.             
  1529.             try:
  1530.                 stream.write(f.read())
  1531.             finally:
  1532.                 f.close()
  1533.  
  1534.         finally:
  1535.             self.closeEWS()
  1536.  
  1537.  
  1538.  
  1539.  
  1540. class xStringIO(StringIO.StringIO):
  1541.     
  1542.     def makefile(self, x, y):
  1543.         return self
  1544.  
  1545.  
  1546.  
  1547. class LocalOpener(urllib.URLopener):
  1548.     
  1549.     def open_hp(self, url, dev):
  1550.         log.debug('open_hp(%s)' % url)
  1551.         match_obj = http_pat_url.search(url)
  1552.         if not match_obj.group(1):
  1553.             pass
  1554.         bus = ''
  1555.         if not match_obj.group(2):
  1556.             pass
  1557.         model = ''
  1558.         if not match_obj.group(3):
  1559.             pass
  1560.         serial = ''
  1561.         if not match_obj.group(4):
  1562.             pass
  1563.         device = ''
  1564.         if not match_obj.group(5):
  1565.             pass
  1566.         loc = ''
  1567.         dev.openEWS()
  1568.         dev.writeEWS('GET %s HTTP/1.0\nContent-Length:0\nHost:localhost\nUser-Agent:hplip\n\n' % loc)
  1569.         reply = xStringIO()
  1570.         dev.readEWS(MAX_BUFFER, reply)
  1571.         reply.seek(0)
  1572.         response = httplib.HTTPResponse(reply)
  1573.         response.begin()
  1574.         if response.status != httplib.OK:
  1575.             raise Error(ERROR_DEVICE_STATUS_NOT_AVAILABLE)
  1576.         else:
  1577.             return response.fp
  1578.  
  1579.  
  1580.