1#!/usr/bin/env python
2# Copyright 2014 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""Dump DAPM widgets status as a 'dot' graph file.
7
8To generate widget status for a device run
9  ssh $REMOTE asoc_dapm_graph > dot.txt && dot -Kfdp -Tpng dot.txt -o widgets.png
10"""
11
12from __future__ import print_function
13import os
14import platform
15import re
16import sys
17import time
18
19ROOTDIR = '/sys/kernel/debug/asoc/'
20# Some widget names are widely used by many codecs, adding them to the graph
21# creates a mess.
22IGNORE_WIDGETS = ('Playback', 'Capture', 'bias_level')
23
24
25def handle_widgets(path):
26  """Reads DAPM widget information from sysfs and generates dot graph entry.
27
28  Args:
29    path: path for sysfs file that exports information about DAPM widget.
30  """
31  for w in os.listdir(path):
32    if w in IGNORE_WIDGETS:
33      continue
34
35    with open(os.path.join(path, w)) as f:
36      lines = f.readlines()
37
38    active = lines[0].startswith(w + ': On ')
39    color = 'green' if active else 'red'
40    print('\t"%s" [color = %s]' % (w, color))
41
42    for l in lines[1:]:
43      l = l.rstrip()
44      # The string format is (in/out) "switch" "widget".
45      edge = list(filter(None, re.split(r' (in|out)  "(.+)" "(.+)"', l)))
46
47      if len(edge) != 3:
48        continue
49
50      direction = edge[0]
51      source = edge[2]
52
53      if source in IGNORE_WIDGETS:
54        continue
55
56      # We need to output the edge only once (e.g. inbound).
57      if direction != 'in':
58        continue
59
60      print('\t"%s" -> "%s"' % (source, w))
61
62
63def handle_card(path):
64  """Generates dot graph file for the given card.
65
66  Args:
67    path: path to sysfs directory that exports DAPM information for a sound card.
68  """
69  host = platform.uname()[1]
70  print('// Generated %s at %s.' % (time.strftime("%c"), host))
71  print('// To visualize the graph run "dot -Kfdp -Tpng $SCRIPT_OUTPUT_FILE -o widgets.png".')
72  print('digraph G {')
73  print('\tbgcolor = grey')
74  for root, dirs, files in os.walk(path):
75    if 'dapm' in dirs:
76      handle_widgets(os.path.join(root, 'dapm'))
77      dirs.remove('dapm')
78  print('}')
79
80
81def main(argv):
82  for c in os.listdir(ROOTDIR):
83    path = os.path.join(ROOTDIR, c)
84    # We assume that directories in ROOTDIR are cards.
85    if os.path.isdir(path):
86      handle_card(path)
87      sys.exit(0)
88
89  print('No cards found', file=sys.stderr)
90  sys.exit(1)
91
92
93if __name__ == '__main__':
94  main(sys.argv[1:])
95
96