2
#========================================================================
8
# Parses Xlog.*.log format files and allows looking up data from it
11
# Bryce W. Harrington <bryce@canonical.com>
14
# Copyright (C) 2010-2012 Bryce W. Harrington
15
# All Rights Reserved.
17
# Permission is hereby granted, free of charge, to any person obtaining
18
# a copy of this software and associated documentation files (the
19
# "Software"), to deal in the Software without restriction, including
20
# without limitation the rights to use, copy, modify, merge, publish,
21
# distribute, sublicense, and/or sell copies of the Software, and to
22
# permit persons to whom the Software is furnished to do so, subject to
23
# the following conditions:
25
# The above copyright notice and this permission notice shall be included
26
# in all copies or substantial portions of the Software.
28
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
29
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
30
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
31
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
32
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
33
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
34
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36
#========================================================================
41
from subprocess import Popen, PIPE, check_output, CalledProcessError
44
class XorgLog(object):
46
def __init__(self, logfile=None):
55
self.xserver_version = None
57
self.boot_logfile = None
58
self.kernel_version = None
59
self.video_driver = None
60
self.xorg_conf_path = None
61
self.logfile = logfile
66
def parse(self, filename):
69
display_name = "Unknown"
70
in_file = open(filename, errors='ignore')
71
gathering_module = False
74
for line in in_file.readlines():
76
m = re.search(r'\(..\)', line)
78
if gathering_module and module is not None:
79
self.modules.append(module)
80
gathering_module = False
83
'\(II\) Loading.*modules\/drivers\/(.+)_drv\.so', line)
86
m = re.search(r'\(II\) Module (\w+):', line)
98
gathering_module = True
101
m = re.search(r'vendor="(.*:?)"', line)
103
module['vendor'] = m.group(1)
105
m = re.search(r'module version = (.*)', line)
107
module['version'] = m.group(1)
109
if module['name'] == 'nvidia':
111
version = check_output(
112
"nvidia-settings -v",
114
universal_newlines=True)
115
m = re.search(r'.*version\s+([0-9\.]+).*', version)
117
module['version'] = m.group(1)
118
except CalledProcessError:
121
m = re.search(r'class: (.*)', line)
123
module['class'] = m.group(1)
125
m = re.search(r'ABI class:\s+(.*:?), version\s+(.*:?)', line)
127
if m.group(1)[:5] == "X.Org":
128
module['abi_name'] = m.group(1)[6:]
130
module['abi_name'] = m.group(1)
131
module['abi_version'] = m.group(2)
135
m = re.search(r'Current Operating System: (.*)$', line)
138
self.kernel_version = uname.split()[2]
141
m = re.search(r'Kernel command line: (.*)$', line)
143
self.kernel_command_line = m.group(1)
146
m = re.search(r'Build Date: (.*)$', line)
148
self.kernel_command_line = m.group(1)
151
m = re.search(r'Log file: "(.*)", Time: (.*)$', line)
153
self.boot_logfile = m.group(1)
154
self.boot_time = m.group(2)
156
m = re.search(r'xorg-server ([^ ]+) .*$', line)
158
self.xserver_version = m.group(1)
161
m = re.search(r'Using a default monitor configuration.', line)
162
if m and self.xorg_conf_path is None:
163
self.xorg_conf_path = 'default'
166
m = re.search(r'Using config file: "(.*)"', line)
168
self.xorg_conf_path = m.group(1)
172
m = re.search(r'\(II\) (.*)\(\d+\): EDID for output (.*)', line)
174
self.displays[display_name] = display
175
self.video_driver = m.group(1)
176
display_name = m.group(2)
177
display = {'Output': display_name}
181
r'\(II\) (.*)\(\d+\): Assigned Display Device: (.*)$', line)
183
self.displays[display_name] = display
184
self.video_driver = m.group(1)
185
display_name = m.group(2)
186
display = {'Output': display_name}
189
m = re.search(r'\(II\) (.*)\(\d+\): Setting mode "(.*?):', line)
191
self.displays[display_name] = display
192
self.video_driver = m.group(1)
193
display_name = m.group(2)
194
display = {'Output': display_name}
198
r'Manufacturer: (.*) *Model: (.*) *Serial#: (.*)', line)
200
display['display manufacturer'] = m.group(1)
201
display['display model'] = m.group(2)
202
display['display serial no.'] = m.group(3)
204
m = re.search(r'EDID Version: (.*)', line)
206
display['display edid version'] = m.group(1)
208
m = re.search(r'EDID vendor \"(.*)\", prod id (.*)', line)
210
display['vendor'] = m.group(1)
211
display['product id'] = m.group(2)
214
r'Max Image Size \[(.*)\]: *horiz.: (.*) *vert.: (.*)', line)
216
display['size max horizontal'] = "%s %s" % (
217
m.group(2), m.group(1))
218
display['size max vertical'] = "%s %s" % (
219
m.group(3), m.group(1))
221
m = re.search(r'Image Size: *(.*) x (.*) (.*)', line)
223
display['size horizontal'] = "%s %s" % (m.group(1), m.group(3))
224
display['size vertical'] = "%s %s" % (m.group(2), m.group(3))
226
m = re.search(r'(.*) is preferred mode', line)
228
display['mode preferred'] = m.group(1)
230
m = re.search(r'Modeline \"(\d+)x(\d+)\"x([0-9\.]+) *(.*)$', line)
232
key = "mode %sx%s@%s" % (m.group(1), m.group(2), m.group(3))
233
display[key] = m.group(4)
236
# Errors and Warnings
237
m = re.search(r'\(WW\) (.*)$', line)
239
self.warnings.append(m.group(1))
242
m = re.search(r'\(EE\) (.*)$', line)
244
self.errors.append(m.group(1))
247
if display_name not in self.displays.keys():
248
self.displays[display_name] = display
251
def errors_filtered(self):
253
'error, (NI) not implemented, (??) unknown.',
254
'Failed to load module "fglrx" (module does not exist, 0)',
255
'Failed to load module "nv" (module does not exist, 0)',
257
return [err for err in self.errors if err not in excludes]
259
def warnings_filtered(self):
261
'warning, (EE) error, (NI) not implemented, (??) unknown.',
262
'The directory "/usr/share/fonts/X11/cyrillic" does not exist.',
263
'The directory "/usr/share/fonts/X11/100dpi/" does not exist.',
264
'The directory "/usr/share/fonts/X11/75dpi/" does not exist.',
265
'The directory "/usr/share/fonts/X11/100dpi" does not exist.',
266
'The directory "/usr/share/fonts/X11/75dpi" does not exist.',
267
'Warning, couldn\'t open module nv',
268
'Warning, couldn\'t open module fglrx',
269
'Falling back to old probe method for vesa',
270
'Falling back to old probe method for fbdev',
272
return [err for err in self.warnings if err not in excludes]
275
def get_driver_info(xlog):
276
'''Return the running driver and version'''
277
print('-' * 13, 'VIDEO DRIVER INFORMATION', '-' * 13)
278
if xlog.video_driver:
279
for module in xlog.modules:
280
if module['name'] == xlog.video_driver.lower():
281
print("Video Driver: %s" % module['name'])
282
print("Driver Version: %s" % module['version'])
286
print("ERROR: No video driver loaded! Possibly in failsafe mode!",
292
return os.path.isdir('/proc/acpi/button/lid')
295
def hybrid_graphics_check(xlog):
296
'''Check for Hybrid Graphics'''
297
card_id1 = re.compile('.*0300: *(.+):(.+) \(.+\)')
298
card_id2 = re.compile('.*0300: *(.+):(.+)')
299
cards_dict = {'8086': 'Intel', '10de': 'NVIDIA', '1002': 'AMD'}
304
output = Popen(['lspci', '-n'], stdout=PIPE, universal_newlines=True)
305
card_list = output.communicate()[0].split('\n')
307
# List of discovered cards
308
for line in card_list:
309
m1 = card_id1.match(line)
310
m2 = card_id2.match(line)
312
id1 = m1.group(1).strip().lower()
313
id2 = m1.group(2).strip().lower()
317
id1 = m2.group(1).strip().lower()
318
id2 = m2.group(2).strip().lower()
322
print('-' * 13, 'HYBRID GRAPHICS CHECK', '-' * 16)
324
formatted_name = cards_dict.get(card.split(':')[0], 'Unknown')
325
formatted_cards.append(formatted_name)
326
print('Graphics Chipset: %s (%s)' % (formatted_name, card))
328
for module in xlog.modules:
329
if module['ddx'] and module['name'] not in drivers:
330
drivers.append(module['name'])
331
print('Loaded DDX Drivers: %s' %
334
has_hybrid_graphics = (len(cards) > 1 and is_laptop()
335
and (cards_dict.get('8086') in formatted_cards
336
or cards_dict.get('1002') in formatted_cards))
338
print('Hybrid Graphics: %s' % (has_hybrid_graphics
345
xlog = XorgLog("/var/log/Xorg.0.log")
348
results.append(get_driver_info(xlog))
349
results.append(hybrid_graphics_check(xlog))
351
return 1 if 1 in results else 0
353
if __name__ == "__main__":