source: projects/hwdata/trunk/inf2mondb.py @ 7989

Revision 7989, 8.8 KB checked in by daisuke, 9 years ago (diff)

forked.

  • Property svn:executable set to *
Line 
1#!/usr/bin/python
2#
3# inf2mondb.py: convert MicroSoft .inf files for monitors to MonitorDB
4#
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
8#
9# Copyright 2002 Red Hat, Inc.
10# Copyright 2006 Dell, Inc.
11#
12# This software may be freely redistributed under the terms of the GNU
13# library public license.
14#
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.
18"""
19"""
20
21
22import sys
23import string
24import re
25import ConfigParser
26
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)
32class myFile(object):
33    def __init__(self, *args):
34        self.fd = open(*args)
35
36    def close(self):
37        return self.fd.close()
38   
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")
44        return line
45
46
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
49# the option name
50OPTCRE = re.compile(
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 =)
55                                              # optionally followed
56                                              # by any # space/tab
57        r'(?P<value>.*)$'                     # everything up to eol
58        )
59
60def usage():
61    print "No monitor.inf file specified."
62    sys.exit(1)
63   
64percentSplit = re.compile(r'%(?P<field>.*)%')
65def percent_to_string(ini, strings, name):
66    mo = percentSplit.match(name)
67    if (mo):
68        field = mo.group('field')
69        try:
70            val = strings[field.lower()]
71        except KeyError:
72            return ""
73        return val.strip()
74    return ""
75
76
77def main():
78    defaultDB = "/usr/share/hwdata/MonitorsDB"
79   
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 "
86                        "database.")
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",
92                    dest="database",
93                    default=defaultDB,
94                    help="Used with --new to specify a different "
95                        "monitors database.  "
96                        "The default is " + defaultDB + ".",
97                    metavar="FILE")
98    parser.add_option("-i", "--inflist",
99                    dest="inflist",
100                    default=None,
101                    help="Read list of inf files from inflist",
102                    metavar="FILE")
103   
104    (options, args) = parser.parse_args()
105   
106    ini = ConfigParser.ConfigParser()
107    ini.optionxform = __builtins__.str
108    ini.OPTCRE = OPTCRE
109    if options.inflist is not None:
110        f = open(options.inflist)
111        lines = f.readlines()
112        f.close
113        for a in lines:
114            f = myFile(a.strip())
115            ini.readfp(f)
116            f.close
117
118    for a in args:
119        f = myFile(a)
120        ini.readfp(f)
121        f.close()
122
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.
126   
127    # Dictionary of booleans showing whether certain monitor EDIDs are known.
128    # knownids[knownID] = True
129    # knownids[unknownID] isn't defined.
130    knownids = {}
131   
132    if options.newonly:
133        try:
134            mdb = open(options.database, 'r')
135        except IOError, (errno, str):
136            print "Unable to open %s: %s" % (options.database, str)
137            sys.exit(1)
138   
139        knowns = mdb.readlines()
140        mdb.close()
141   
142        for known in knowns:
143            if len(string.strip(known)) == 0 or known[0] == '#':
144                continue
145            knownids[string.lower(string.strip(string.split(known, ';')[2]))] = True
146   
147
148    # a dictionary of manufacturers we're looking at
149    manufacturers = {}
150    # a big fat dictionary of strings to use later on.
151    strings = {}
152
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]*)')
159   
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]
169   
170        elif section.lower() == "strings":
171            for key in ini.options(section):
172                strings[key.lower()] = string.strip(ini.get(section, key)).replace('"','')
173            # exceptions
174            strings["dell"] = "Dell"
175   
176   
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)
182                v = v.split(',')
183                install_key = v[0].strip()
184   
185                line = ini.get(mfr, monitor_name)
186                # Find monitor inf IDs and EISA ids
187   
188                edid = "0"
189                mo = monitor1Re.match(line)
190                if mo:
191                    edid = mo.group('id')
192                else:
193                    mo = monitor2Re.match(line)
194                    if mo:
195                        edid = mo.group('id').strip()
196   
197                if knownids.has_key(edid.lower()):
198                    continue
199   
200                if ini.has_section(install_key):
201                    line = ini.get(install_key, "AddReg")
202                    if line:
203                        sline = line.split(',')
204                        registry = sline[0]
205                        try:
206                            resolution = sline[1]
207                        except IndexError:
208                            resolution = ""
209                        try:
210                            dpms = sline[2]
211                        except IndexError:
212                            dpms = ""
213   
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('"')
218                                    try:
219                                        syncline = sline[3]
220                                    except IndexError:
221                                        syncline = ","
222                                       
223                                    syncline = syncline.split(',')
224                                    hsync = syncline[0].strip()
225                                    vsync = syncline[1].strip()
226   
227                                    output = "%s; %s; %s; %s; %s" % (percent_to_string(ini, strings, monitor_vendor_name),
228                                                                     percent_to_string(ini, strings, monitor_name),
229                                                                     edid, hsync, vsync)
230                                    if dpms.lower().strip() == "dpms":
231                                        output = output + "; 1"
232   
233                                    if not knownids.has_key(edid.lower()):
234                                        print output
235                                        knownids[edid.lower()] = True
236
237
238
239if __name__ == "__main__":
240    sys.exit(main())
Note: See TracBrowser for help on using the repository browser.