3 # inf2mondb.py: convert MicroSoft .inf files for monitors to MonitorDB
5 # originally by Matt Wilson <msw@redhat.com>
6 # option parsing and database comparison by Fred New
7 # ini parsing completely rewritten by Matt Domsch <Matt_Domsch@dell.com> 2006
9 # Copyright 2002 Red Hat, Inc.
10 # Copyright 2006 Dell, Inc.
12 # This software may be freely redistributed under the terms of the GNU
13 # library public license.
15 # You should have received a copy of the GNU Library Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 # this is a class to deal with various file line endings and leading whitespace
28 # converts all \r line endings to \n.
29 # It also strips leading whitespace.
30 # NOTE: be sure to always return _something_, even if it is just "\n", or we
31 # break the file API. (nothing == eof)
33 def __init__(self, *args):
37 return self.fd.close()
39 def readline(self, *args):
40 line = self.fd.readline(*args)
41 line = line.replace('\r', '\n')
42 line = line.replace('\n\n', '\n')
43 line = line.lstrip(" \t")
47 # we will use this to override default option parsing in ConfigParser to handle
48 # Microsoft-style "INI" files. (Which do not necessarily have " = value " after
51 r'(?P<option>[^:=\s][^:=]*)' # very permissive!
52 r'\s*(?P<vi>[:=]{0,1})\s*' # any number of space/tab,
53 # optionally followed by
54 # separator (either : or =)
57 r'(?P<value>.*)$' # everything up to eol
61 print "No monitor.inf file specified."
64 percentSplit = re.compile(r'%(?P<field>.*)%')
65 def percent_to_string(ini, strings, name):
66 mo = percentSplit.match(name)
68 field = mo.group('field')
70 val = strings[field.lower()]
78 defaultDB = "/usr/share/hwdata/MonitorsDB"
80 from optparse import OptionParser
81 parser = OptionParser(usage= sys.argv[0] + " [options] filename.inf")
82 parser.add_option("-n", "--new",
83 action="store_true", dest="newonly", default=False,
84 help="Compare results with the monitors database and only "
85 "show DB lines that don't already appear in the "
87 parser.add_option("-v", "--verbose",
88 action="store_true", dest="verbose", default=False,
89 help="Used with --new to permit us to see which monitors "
90 "already appear in the monitors database.")
91 parser.add_option("-d", "--database",
94 help="Used with --new to specify a different "
96 "The default is " + defaultDB + ".",
98 parser.add_option("-i", "--inflist",
101 help="Read list of inf files from inflist",
104 (options, args) = parser.parse_args()
106 ini = ConfigParser.ConfigParser()
107 ini.optionxform = __builtins__.str
109 if options.inflist is not None:
110 f = open(options.inflist)
111 lines = f.readlines()
114 f = myFile(a.strip())
123 # First, build a dictionary of monitors we already know about.
124 # When we get ready to print the monitors we found in the .inf
125 # file, we can decide whether it is new or not.
127 # Dictionary of booleans showing whether certain monitor EDIDs are known.
128 # knownids[knownID] = True
129 # knownids[unknownID] isn't defined.
134 mdb = open(options.database, 'r')
135 except IOError, (errno, str):
136 print "Unable to open %s: %s" % (options.database, str)
139 knowns = mdb.readlines()
143 if len(string.strip(known)) == 0 or known[0] == '#':
145 knownids[string.lower(string.strip(string.split(known, ';')[2]))] = True
148 # a dictionary of manufacturers we're looking at
150 # a big fat dictionary of strings to use later on.
153 # This RE is for EISA info lines
154 # %D5259A%=D5259A, Monitor\HWP0487
155 monitor1Re = re.compile(r'.*,.*Monitor\\(?P<id>[^\s]*)')
156 # This one is for legacy entries
157 # %3020% =PB3020, MonID_PB3020
158 monitor2Re = re.compile(r'.*,.*MonID_(?P<id>[^\s]*)')
160 for section in ini.sections():
161 if section.lower() == "manufacturer":
162 for mfr in ini.options(section):
163 # generate the vendor.arch funny entries
164 manufacturer_values = string.split(ini.get(section, mfr), ',')
165 manufacturers[manufacturer_values[0]] = mfr
166 while len(manufacturer_values) > 1:
167 manufacturers["%s.%s" % (manufacturer_values[0], manufacturer_values[-1])] = mfr
168 manufacturer_values = manufacturer_values[0:-1]
170 elif section.lower() == "strings":
171 for key in ini.options(section):
172 strings[key.lower()] = string.strip(ini.get(section, key)).replace('"','')
174 strings["dell"] = "Dell"
177 for mfr in manufacturers.keys():
178 if ini.has_section(mfr):
179 monitor_vendor_name = manufacturers[mfr]
180 for monitor_name in ini.options(mfr):
181 v = ini.get(mfr, monitor_name)
183 install_key = v[0].strip()
185 line = ini.get(mfr, monitor_name)
186 # Find monitor inf IDs and EISA ids
189 mo = monitor1Re.match(line)
191 edid = mo.group('id')
193 mo = monitor2Re.match(line)
195 edid = mo.group('id').strip()
197 if knownids.has_key(edid.lower()):
200 if ini.has_section(install_key):
201 line = ini.get(install_key, "AddReg")
203 sline = line.split(',')
206 resolution = sline[1]
214 if ini.has_section(registry):
215 for line in ini.options(registry):
216 if string.find(line, 'HKR,"MODES') >= 0:
217 sline = line.split('"')
223 syncline = syncline.split(',')
224 hsync = syncline[0].strip()
225 vsync = syncline[1].strip()
227 output = "%s; %s; %s; %s; %s" % (percent_to_string(ini, strings, monitor_vendor_name),
228 percent_to_string(ini, strings, monitor_name),
230 if dpms.lower().strip() == "dpms":
231 output = output + "; 1"
233 if not knownids.has_key(edid.lower()):
235 knownids[edid.lower()] = True
239 if __name__ == "__main__":