#!/usr/bin/python3
# Generate a dh_modalias input file covering all modaliases from all modules from
# the currently running kernel which need any firmware shipped by this package.
#
# (C) 2012 Canonical Ltd.
# Author: Martin Pitt <martin.pitt@ubuntu.com>

import os
import sys
import subprocess

def parse_modinfo(output):
    '''Parse output of modinfo into a dictionary.'''

    data = {}
    for line in output.splitlines():
        try:
            k, v = line.split(':', 1)
        except ValueError:
            continue
        # ignore aliases which are not hardware specifiers
        if k == 'alias' and ':' not in v:
            continue
        data.setdefault(k, []).append(v.strip())

    return data

def gen_firmware_map(moddir):
    '''Generate firmware/module mapping.

    Return map firmware -> module -> [modaliases].
    '''
    fw_map = {}

    for root, dirs, files in os.walk(moddir):
        for f in files:
            if not f.endswith('.ko'):
                continue

            modinfo = subprocess.Popen(['modinfo', os.path.join(root, f)],
                    stdout=subprocess.PIPE)
            out = modinfo.communicate()[0].decode('UTF-8', errors='ignore')
            assert modinfo.returncode == 0

            info = parse_modinfo(out)
            if 'alias' not in info:
                continue
            for fw in info.get('firmware', []):
                module = f[:-3].replace('-', '_')
                l = fw_map.setdefault(fw, {}).setdefault(module, []) 
                l.extend(info['alias'])

    return fw_map

def get_shipped_firmware():
    '''Iterate over the firmware files that this package ships'''

    os.chdir('debian/linux-firmware-nonfree/lib/firmware/')
    for root, dirs, files in os.walk('.'):
        for f in files:
            # chop off the initial ./ prefix
            yield os.path.join(root, f)[2:]

if __name__ == '__main__':
    fwmap = gen_firmware_map(sys.argv[1])
    #for fw, modinfo in fwmap.items():
    #    print('--- %s ----' % fw)
    #    print(modinfo)

    # search the modules whose firmware is shipped by our package, and
    # output their aliases
    for fw in get_shipped_firmware():
        if fw in fwmap:
            for mod, aliases in fwmap[fw].items():
                for alias in aliases:
                    print('alias %s %s' % (alias, mod))
        else:
            print('%s is not referenced by any module' % fw, file=sys.stderr)
