package list_modules;

use MDK::Common;

our @ISA = qw(Exporter);
our @EXPORT = qw(load_dependencies dependencies_closure category2modules module2category sub_categories);

# the categories have 2 purposes
# - choosing modules to include on stage1's (cf update_kernel and mdk-stage1/pci-resource/update-pci-ids.pl)
# - performing a load_category or probe_category (detect_devices.pm and many files in perl-install)

our %l = (
  ################################################################################
  network => 
  {
    atm => [ qw(ambassador eni firestream fore_200e he horizon idt77252 iphase lanai nicstar solos-pci zatm) ],
    main => [
        qw(3c501 3c503 3c505 3c507 3c509 3c515 3c990 3c990fx),
        qw(82596 ac3200 acenic aironet4500_card altera_tse amd8111e at1700 atl2 atp ax88796c),
        qw(bcm4400 cassini cs89x0 cx82310_eth de600 de620),
        qw(depca dmfe dwc-xlgmac e2100 ec_bhf eepro eexpress enic eth16i),
        qw(ewrk3 fm10k funeth genet hp hp-plus hp100 i40e i40evf iavf ice ionic),
        qw(iph5526), #- fibre channel
        qw(i40evf jme lance ne nfp ni5010 ni52 ni65 mv88e6060 nvnet),
        qw(prism2_plx qlge r6040 rcpci realtek-smi rhineget),
        qw(sb1000 sc92031 sfc-siena sh_eth smc-ultra smsc911x smc9194 smsc9420 smsc95xx),
        qw(tc35815 tlan uli526x ),
        qw(b44 com20020-pci de2104x),
        qw(defxx), # most unused
        qw(dgrs e100 eepro100 epic100 fealnx hamachi mana mlx5_core mlxsw_pci natsemi),
        qw(ne2k-pci pcnet32 plip qede sis900 skfp starfire stmmac-platform tulip),
        qw(txgbe typhoon via-rhine winbond-840 xgene-enet xilinx_emac forcedeth),
        qw(sungem sunhme), # drivers for ultrasparc, but compiled in ix86 kernels...
      qw(3c59x 8139too 8139cp cpmac niu sundance), #rtl8139
      # add all phys
      qw(adin adin1100 amd aquantia at803x ax88796b bcm7xxx bcm84881 bcm87xx broadcom cicada cortina davicom dp83848 dp83867 dp83869 dp83td510 et1011c fixed_phy icplus intel-xway),
      qw(lxt marwell macb macb_pci marwell10g marvell-88x2222 mdio-bcm-unimac mdio-bitbang mdio-cavium mdio_devres mdio-gpio mdio-i2c),
      qw(mdio-mscc-mii mdio-thunder mdio-xpcs mediatek-ge micrel microchip microchip_t1 microchip_t1s motorcomm mscc national ncn26000 nxp-tja11xx phylink),
      qw(phy-bcm-kona-usb2 phy-cpcap-usb phy-exynos-usb2 phy-intel-emmc phy-intel-lgm-emmc phy-can-transceiver phy-lgm-usb phy-pxa-28nm-hsic),
      qw(phy-pxa-28nm-usb2 phy-qcom-usb-hs phy-qcom-usb-hsic phy-tusb1210),
      qw(qsemi r8152 r8153_ecm r815x realtek rockchip sfp smsc spi_ks8995 ste10Xp teranetics vitesse xilinx_gmii2rgmii),
    ],
    firewire => [ qw(eth1394 pcilynx) ],
    gigabit => [
      qw(amd-xgbe alx aqc111 atl1 atl1c atl1e atlantic at91_ether ax88179_178a bcmsysport be2net bna bnx2 bnx2x bnxt_en cxgb cxgb3 cxgb4 dl2k dwc-xlgmac e1000 e1000e et131x),
      qw(gve hinic hfi1 igb igc ionic ipg ixgb ixgbe lan78xx liquidio liquidio_vf macb mlx4_core mlx4_en mlx5_core mvmdio myri_sbus myri10ge netxen_nic nixge ns83820 pch_gbe),
      qw(qla3xxx r8169 s2io samsung-sxgbe sfc sfc-falcon sfc-siena sxg_nic sis190 sk98lin skge sky2 slicoss spidernet stmmac tehuti tg3 txgbe via-velocity vxge yellowfin),
      qw(bcm5820 bcm5700), #- encrypted
    ],

    raw => [
      qw(ppp_generic ppp_async ppp_deflate bsd_comp mhi_pci_generic thunderbolt-net),
    ],
    pcmcia => [ 
      qw(3c574_cs 3c589_cs axnet_cs fmvj18x_cs),
      qw(ibmtr_cs libertas_cs nmclan_cs pcnet_cs smc91c92_cs),
      qw(xirc2ps_cs xircom_cb xircom_tulip_cb),
    ],
   #- generic NIC detection for USB seems broken (class, subclass, 
   #- protocol reported are not accurate) so we match network adapters against
   #- known drivers :-(
    usb => [ 
      qw(aqc111 asix catc cdc_ether ch9200 dm9601 huawei_cdc_ncm kaweth mcs7830 pegasus rtl8150 smsc75xx smsc95xx usbnet),
    ],
    wireless => [
      qw(8812au 8821ce acx-pci acx-usb adm8211 agnx airo airo_cs aironet4500_cs),
      qw(aironet_cs ar5523 ar9170usb arlan arusb_lnx at76c50x_usb ath10k_pci ath10k_sdio ath10k_usb ath11k_pci ath5k ath6kl ath6kl_sdio ath6kl_usb ath9k ath9k_htc ath9k_pci_owl_loader),
      qw(ath_pci atmel_cs atmel_pci b43 b43legacy bcm43xx bcm_wimax bcma brcm80211 brcmsmac brcmfmac carl9170 com20020_cs),
      qw(dyc_ar5 hostap_cs hostap_pci hostap_plx i2400m_usb ipw2100),
      qw(ipw2200 ipw3945 iwl3945 iwl4965 iwlagn iwldvm iwlmei iwlmvm iwlwifi libertas_spi madwifi_pci),
      qw(mt76x2e mt76x2u mt7601u mt76x02 mt76x0e mt76x0u mt7603e mt7615e mt7663u mt7915e mt7921e mt7921s mt7921u mwifiex_pcie mwifiex_sdio mwifiex_usb mwl8k ndiswrapper netwave_cs orinoco orinoco_cs),
      qw(orinoco_nortel orinoco_pci orinoco_plx orinoco_tmd orinoco_usb p54pci p54spi),
      qw(p54usb plfxlc prism2_cs prism2_pci prism2_usb prism54 qmi_wwan qtnfmac qtnfmac_pcie r8180),
      qw(r8187se rtl8188ee rtl8192ce r8192_pci r8192s_usb r8192u_usb r8712u r8723bs r8822be ray_cs rndis_wlan rsi_sdio rsi_usb rt2400 rt2400pci rt2500),
      qw(rt2500pci rt2500usb rt2570 rt2800pci rt2800usb rt2860 rt2860sta rt2870),
      qw(rt3070sta rt61 rt61pci rt73 rt73usb rtl8180 rtl8187 rtl8187se rtl818x_pci r8188eu r8192ee r8723au rtl_pci rtl_usb rtusb rtwpci rtw88_8723d rtw88_8723de rtw88_8723du rtw88_8821ce rtw88_8821cu rtw88_8822be rtw88_8822bu rtw88_8822ce rtw88_8822cu),
      qw(rtw88_8723ds rtw88_8821cs rtw88_8822bs rtw88_8822cs rtw89_8852ae rtw89_8852be rtw89_8852ce),
      qw(rtl8192se rtl8192cu rtl8192de rtl8192ee rtl8723ae rtl8723be rtl8821ae rtl8xxxu spectrum_cs sr9700 sr9800 ssb usb8xxx usbvnet_rfmd vt6655_stage vt6656_stage vt_ar5k w35und),
      qw(wavelan_cs wcn36xx wfx wil6210 wilc1000-sdio wl wl1251_sdio wl1251_spi wl12xx wl18xx wl3501_cs wlcore_sdio wvlan_cs zd1201 zd1211rw),
    ],
    isdn => [
      qw(avmfritz c4 cdc-acm b1pci divas hfc4s8s_l1 hfc_usb hfc4s8s_l1 hisax hisax_st5481 hisax_fcpcipnp hysdn sedlfax t1pci tpam w6692pci),
      qw(avmfritz hfcpci hfcmulti hfcsusb mISDNinfineon netjet), # mISDN
      qw(fcpci fcdsl fcdsl fcdsl2 fcdslsl fcdslslusb fcdslusb fcdslusba fcusb fcusb2 fxusb fxusb_CZ)
    ],
    cellular => [
      qw(cdc_mbim hso nozomi option sierra),
    ],
    modem => [
      qw(ltmodem mwave sm56 ft1000),
    ],
    slmodem => [
      qw(slamr slusb snd-ali5451 snd-atiixp-modem snd-intel8x0m snd-via82xx-modem),
    ],
    wan => [ qw(c101 cosa cyclomx cycx_drv dlci dscc4 farsync hdlc hostess_sv11 lapbether lmc n2 pc300 pci200syn sbni sdla sdladrv sealevel syncppp wanxl z85230) ],
    usb_dsl => [ qw(cxacru speedtch ueagle-atm usbatm xusbatm) ],
    virtual => [ qw(ena hv_netvsc i2c-virtio vboxdrv virtio-iommu virtio_net virtio_pci_modern_dev vmxnet3 xen-netfront) ],
  },

  ################################################################################
  disk => 
  {
    # ide drivers compiled as modules:
    ide => [
        qw(aec62xx alim15x3 amd74xx atiixp cmd64x),
        qw(delkin_cb dtc2278 hpt34x hpt366 ns87415 ht6560b it8172 it8213 it821x jmicron),
        qw(opti621 pdc202xx_new pdc202xx_old piix qd65xx rz1000 sc1200 serverworks siimage sis5513 slc90e66),
        qw(tc86c001 triflex trm290 tx4938ide tx4939ide umc8672 via82cxxx ide-pci-generic ide-generic),
    ],
    scsi => [
	'53c7,8xx',
        qw(a100u2w advansys aha152x aha1542 aha1740 am53c974 atp870u),
        qw(be2iscsi bfa BusLogic dc395x dc395x_trm dmx3191d dtc eata eata_dma),
        qw(eata_pio efct fdomain fdomain_cs fdomain_pci g_NCR5380 in2000 initio mpi3m  mpt2sas mpt3sas mvsas myrb myrs NCR53c406a),
        qw(nsp32 pas16 pci2220i pm80xx pm8001 psi240i qla1280 qla2x00 qla2xxx),
        qw(qlogicfas qlogicfc rsxx seagate shasta skd sim710 snic stex sym53c416),
        qw(t128 tmscsim u14-34f ultrastor wd7000 xen-scsiback xen-scsifront),
      qw(aic7xxx aic7xxx_old aic79xx pci2000 qlogicfas408 sym53c8xx wd719x lpfc lpfcdd), # ncr53c8xx
    ],
    sata => [
      # note that ata_piix manage RAID devices on ICH6R
      qw(ahci ahci_dwc aic94xx ata_adma ata_piix pata_pdc2027x pdc_adma),
      qw(sata_dwc_460ex sata_fsl sata_inic162x sata_mv sata_nv sata_promise),
      qw(sata_qstor sata_rcar sata_sil sata_sil24 sata_sis sata_svw sata_sx4 sata_uli sata_via sata_vsc sx8),
      # new drivers: old ide drivers ported over libata:
      qw(ata_generic mv-ahci pata_ali pata_amd pata_artop pata_atiixp pata_atp867x),
      qw(pata_bf54x pata_cmd640 pata_cmd64x pata_cs5520 pata_cs5530),
      qw(pata_cs5535 pata_cs5536 pata_cypress pata_efar pata_hpt366),
      qw(pata_hpt37x pata_hpt3x2n pata_hpt3x3 pata_isapnp pata_it8172),
      qw(pata_it8213 pata_it821x pata_jmicron pata_legacy pata_marvell),
      qw(pata_mpiix pata_netcell pata_ninja32 pata_ns87410),
      qw(pata_ns87415 pata_oldpiix pata_opti pata_optidma),
      qw(pata_pdc2027x pata_pdc202xx_old pata_piccolo pata_platform pata_qdi),
      qw(pata_radisys pata_rdc pata_rz1000 pata_sc1200 pata_sch),
      qw(pata_serverworks pata_sil680 pata_sis pata_sl82c105),
      qw(pata_triflex pata_via pata_winbond),
      qw(pata_acpi),
    ],
    hardware_raid => [
        # 3w-xxxx drives ATA-RAID, 3w-9xxx and arcmsr drive SATA-RAID
        qw(3w-9xxx 3w-sas 3w-xxxx a320raid aacraid arcmsr cciss cpqarray),
        qw(cpqfc csiostor DAC960 dpt_i2o esas2r gdth hpsa hptiop i2o_block imm ipr ips isci),
        qw(it8212 it821x iteraid megaide megaraid megaraid_mbox),
        qw(megaraid_sas mptfc mptsas mptscsih mptspi pdc-ultra pmcraid ppa),
        qw(qla2100 qla2200 qla2300 qla2322 qla4xxx qla6312 qla6322 smartpqi),
    ],
    virtual => [ qw(hv_storvsc virtio_blk virtio_scsi vmw_pvscsi xenblk xen-blkfront) ],
    pcmcia => [ qw(aha152x_cs fdomain_cs nsp_cs qlogic_cs ide-cs pata_pcmcia sym53c500_cs) ],
    raw => [ qw(ide-gd_mod sd_mod) ],
    usb => [ qw(keucr uas ums-alauda ums-cypress ums-datafab ums-eneub6250 ums-freecom ums-isd200),
	     qw(ums-jumpshot ums-karma ums-onetouch ums-realtek ums-sddr09 ums-sddr55 ums-usbat usb-storage) ],
    firewire => [ qw(sbp2) ],
    cdrom => [ qw(ide-cd_mod sr_mod) ],
    card_reader => [ qw(rts5208 rtsx_pci rtsx_usb sdhci sdhci-pci tifm_sd tifm_7xx1 toshsd ushc via-sdmmc) ],
  },

  ################################################################################

  bus => 
  {
    usb => [ qw(bcma-hcd c67x00 dwc3-haps dwc3 dwc3-pci ehci-hcd ehci-pci ehci-platform ehci-tegra fhci fusbh200-hcd hwa-hc
		imx21-hcd isp116x-hcd isp1362-hcd isp1760 ohci-hcd ohci-pci ohci-platform oxu210hp-hcd
		r8a66597-hcd renesas-usbhs sl811_cs sl811-hcd ssb-hcd u132-hcd
		uhci-hcd usb-ohci usb-uhci vhci-hcd whci-hcd xen-hcd xhci-hcd xhci-pci xhci-pci-renesas xhci-plat-hcd) ],
    bluetooth => [ qw(ath3k bcm203x bfusb bluecard_cs bpa10x bt3c_cs btusb dtl1_cs) ],
    firewire => [ qw(ohci1394) ],
    i2c => [
      qw(i2c_algo_bit i2c-ali1535 i2c-ali1563 i2c-ali15x3 i2c-amd756 i2c-amd8111 i2c-amd-mp2-pci i2c-amd-mp2-plat i2c-i801 i2c-i810 i2c_designware_platform i2c-nforce2),
      qw(i2c-piix4 i2c-prosavage i2c-savage4 i2c-sis5595 i2c-sis630 i2c-sis96x i2c_smbus i2c-via i2c-viapro i2c-voodoo3),
      qw(i2c-hydra i2c-ibm_iic i2c-mpc i2c-amd-mp2-pci i2c-amd-mp2-plat),
    ],
    pcmcia => [
      qw(au1x00_ss i82365 i82092 pd6729 tcic vrc4171_card vrc4173_cardu yenta_socket), # cb_enabler
    ],
    hid => [ qw(amd-mp2-pcie amd_sfh amd-sfhtp-hid ff-memless hid hid-a4tech hid-alps hid-apple hid-appleir hid-asus hid-aureal hid-axff hid-belkin hid-betopff hid_bigbenff
	    hid-cherry hid-chicony hid-cmedia hid-corsair hid-cougar hid-cp2112 hid-creative-sb0540 hid-cypress hid-dr hid-drff hid-elan hid-elecom hid-elo hid-emsff hid-evision
	    hid-ezkey hid-gaff hid-gembird hid-generic hid-gfrm hid-google-hammer hid-gt683r hid-gyration hid-holtek-kbd hid-holtekff hid-holtek-mouse
	    hid-hyperv hid-icade hid-ite hid-jabra hid-kensington hid-keytouch hid-kye hid-lcpower hid-led hid-lenovo hid-lenovo-tpkbd hid-lg-g15
	    hid-logitech hid-logitech-dj hid-logitech-hidpp hid-macally hid-magicmouse hid-megaworld hid-mf hid-microsoft hid-monterey
	    hid-multilaser hid-multitouch hid-nintendo hid-ntrig hid-ortek hid-penmount hid-petalynx hid-picolcd
	    hid-pl hid-plantronics hid-playstation hid-primax hid-prodikeys hid_razer hid_redragon hid-retrode hid-roccat hid-roccat-arvo hid-roccat-common hid-rmi
	    hid-roccat-isku hid-roccat-kone hid-roccat-koneplus hid-roccat-konepure hid-roccat-kovaplus hid-roccat-lua
	    hid-roccat-pyra hid-roccat-ryos hid-roccat-savu hid-saitek hid-samsung hid-semitek hid-sensor-hub hid_sensor_accel_3d hid_sensor_gyro_3d hid_sensor_trigger hid-sjoy hid-sony
	    hid-speedlink hid_steam hid-steelseries hid-sunplus hid-thrustmaster hid-tivo hid-tmff hid-topseed hid-twinhan
	    hid-uclogic hid_vivaldi hid-waltop hid-wiimote hid-xiaomi hid-xinmo hid-zpff hid-zydacron wacom
	    i2c-hid-acpi 
	    intel-ish-ipc intel-ishtp-hid intel-ishtp intel-ishtp-loader ipts ithc
	    surface_hid surface_kbd) ],

   #serial_cs
   #ftl_cs 3c575_cb apa1480_cb epic_cb serial_cb tulip_cb iflash2+_mtd iflash2_mtd
   #cb_enabler
  },

  fs => 
  {
    network => [ qw(af_packet nfs nfsv2 nfsv3 nfsv4 smbfs) ],
    cdrom => [ qw(isofs) ],
    loopback => [ qw(isofs loop squashfs) ],
    local => [
      qw(btrfs exfat ext3 ext4 f2fs jfs nilfs2 ntfs ntfs3 reiserfs vfat xfs),
    ],
    various => [ qw(efivarfs efibc capsule-loader overlay romfs ufs fuse) ],

  },

  ################################################################################
  multimedia => 
  {
    sound => [
          qw(ad1816 ad1848 ad1889 ali5455 audigy audio awe_wave cmpci cs4232 cs4281 cs46xx cx88-alsa),
          qw(emu10k1 es1370 es1371 esssolo1 forte gus i810_audio ice1712 kahlua mad16 maestro),
          qw(maestro3 mpu401 msnd_pinnacle nm256_audio nvaudio opl3 opl3sa opl3sa2 pas2 pss),
          qw(rme96xx sam9407 sb sgalaxy snd-pci-acp3x snd-ad1816a snd-ad1848 snd-ad1889 snd-ali5451 snd-als100 snd-als300),
          qw(snd-als4000 snd-atiixp snd-au8810 snd-au8820 snd-au8830 snd-audigyls snd-aw2 snd-azt2316 snd-azt2320 snd-azt3328 snd-azx),
          qw(snd-asihpi snd-at73c213 snd-bcd2000 snd-bebob snd-bt87x snd-ca0106 snd-cmi8330 snd-cmi8788 snd-cmipci),
          qw(snd-cs4231 snd-cs4232 snd-cs4236 snd-cs4281 snd-cs46xx snd-cs5530 snd-cs5535audio),
          qw(snd_ctxfi),
          qw(snd-darla20 snd-darla24 snd-dt019x snd-echo3g snd-emu10k1 snd-emu10k1x),
          qw(snd-ens1370 snd-ens1371 snd-es1688 snd-es18xx snd-es1938 snd-es1968 snd-es968),
          qw(snd-fireworks snd-fm801 snd-gina20 snd-gina24 snd-gina3g),
          qw(snd-gusclassic snd-gusextreme snd-gusmax),
          qw(snd-hda-intel snd-hdsp snd-hdspm snd-ice1712 snd-ice1724),
          qw(snd-indi snd-indigo snd-indigodj snd-indigodjx snd-indigoio snd-indigoiox snd-intel8x0 snd-interwave),
          qw(snd-interwave-stb snd-korg1212 snd-layla20 snd-layla24 snd-layla3g snd-lola snd-lx6464es),
          qw(snd-maestro3 snd-mia snd-mixart snd-mona snd-mpu401 snd-nm256),
          qw(snd-opl3sa2 snd-opti92x-ad1848 snd-opti92x-cs4231 snd-opti93x snd-oxygen snd_pci_acp5x snd-pcsp snd-pcxhr snd-riptide snd-rme32),
          qw(snd-rme96 snd-rme9652 snd-sb16 snd-sb8 snd-sbawe snd-sc6000 snd-sgalaxy snd-sis7019),
          qw(snd-soc-cs35l56-i2c snd-soc-cs35l56 snd-soc-cs35l56-sdw snd-soc-cs35l56-shared snd-soc-cs35l56-spi snd-soc-cs42l42-sdw snd-soc-idt821034),
          qw(snd-soc-max98363 snd-soc-rt1318-sdw snd-soc-rt712-sdca-dmic snd-soc-rt712-sdca snd-soc-sma1303 snd-soc-avs-max98927 snd-soc-avs-probe),
          qw(snd-sof-amd-renoir snd-sof-acpi-intel-bdw snd-sof-intel-hda-mlink snd-sof-acpi-intel-byt snd-sof-pci snd-sonicvibes),
          qw(snd-sscape snd-trident snd-usb-variax snd-via82xx snd-virtuoso snd-vx222 snd-vxp440 snd-vxpocket snd-wavefront),
          qw(snd_xen_front snd-ymfpci sonicvibes soundwire-amd sscape trident via82cxxx_audio virtio_snd wavefront ymfpci),
  ],
    tv => [ qw(bt878 bttv cx23885 cx25821 cx8800 cx8802 cx88-blackbird dpc7146),
            qw(em28xx ivtv mxb pvrusb2 saa7134 saa7164 zr36067) ],
    dvb => [
        qw(b2c2-flexcop-pci b2c2-flexcop-usb budget budget-av),
        qw(budget-ci cinergyT2 dm1105 dvb-dibusb dvb-ttpci),
        qw(dvb-ttusb-budget dvb-usb-a800 dvb-usb-af9015 dvb-usb-ce6230),
        qw(dvb-usb-cinergyT2 dvb-usb-cxusb dvb-usb-dib0700),
        qw(dvb-usb-dibusb-mb dvb-usb-dibusb-mc dvb-usb-digitv),
        qw(dvb-usb-dtt200u dvb-usb-dtv5100 dvb-usb-ec168 dvb-usb-friio dvb-usb-gp8ps),
        qw(dvb-usb-nova-t-usb2 dvb-usb-ttusb2 dvb-usb-umt-010),
        qw(dvb-usb-vp702x dvb-usb-vp7045 earth-pt1 firedtv hexium_gemini),
        qw(hexium_orion netup-unidvb pluto2 skystar2 smsusb ttusb_dec),
    ],
    photo => [ qw(dc2xx mdc800) ],
    radio => [ qw(radio-gemtek-pci radio-keene radio-maestro radio-ma901
	    radio-maxiradio radio-miropcm20 radio-mr800 radio-raremono radio-shark
	    radio-usb-si470x shark2) ],
    scanner => [ qw(scanner microtek) ],
    firewire => [ qw(snd-dice snd-firewire-digi00x snd-firewire-speakers snd-isight snd-oxfw snd-scs1x snd-firewire-tascam) ],
    gameport => [ qw(cs461x ns558 emu10k1-gp fm801-gp lightning ns558 vortex) ],
    usb_sound => [ qw(audio dabusb dsbr100 snd-usb-audio snd-usb-6fire snd-usb-caiaq snd-usb-hiface snd-usb-usx2y usb-midi) ],
    webcam => [
        qw(cafe_ccic cpia2 cpia_usb cyber2000fb et61x251 gspca),
        qw(gspca_benq gspca_conex gspca_cpia1 gspca_dtcs033 gspca_etoms
        gspca_finepix gspca_gl860 gspca_jeilinj gspca_jl2005bcd
        gspca_kinect gspca_konica gspca_m5602 gspca_mars
        gspca_mr97310a gspca_nw80x gspca_ov519 gspca_ov534
        gspca_ov534_9 gspca_pac207 gspca_pac7302 gspca_pac7311
        gspca_se401 gspca_sn9c2028 gspca_sn9c20x gspca_sonixb
        gspca_sonixj gspca_spca1528 gspca_spca500 gspca_spca501
        gspca_spca505 gspca_spca506 gspca_spca508 gspca_spca561
        gspca_sq905 gspca_sq905c gspca_sq930x gspca_stk014 gspca_stk1135
        gspca_stv0680 gspca_stv06xx gspca_sunplus gspca_t613
        gspca_topro gspca_touptek gspca_tv8532 gspca_vc032x gspca_vicam
        gspca_xirlink_cit gspca_zc3xx),
        qw(ibmcam konicawc mod_quickcam ov511 ov511-alt ov518_decomp),
        qw(ov51x-jpeg ovfx2 pwc qc-usb-messenger quickcam quickcam_messenger),
        # both STV06xx & stv06xx b/c drivers/media/video/gspca/stv06xx/stv06xx.h
        # wrongly use upcase letters:
        qw(se401 sn9c102 STV06xx stv06xx stv680 tcm825x ultracam),
        qw(usbvideo usbvision uvcvideo vicam w9968cf zc0301 zc3xx),
    ],
  },

  # USB input stuff get automagically loaded by hotplug and thus
  # magically work through /dev/input/mice multiplexing:
  input => {
      joystick => [
          qw(iforce iforce-serio iforce-usb xpad),
          # there're more drivers in drivers/input/joystick but they support non USB or PCI devices
          # and thus cannot be detected but by slow (and maybe dangerous?) load_category:
          qw(a3d adi analog cobra db9 gamecon gf2k grip grip_mp guillemot interact),
          qw(joydump magellan pxrc qwiic-joystick sidewinder spaceball spaceorb stinger tmdc turbografx warrior)
      ],
      remote => [ qw(ati_remote) ],
      # USB tablets and touchscreens:
      tablet => [ qw(acecad aiptek wacom wacom_serial4 kbtab) ],
      touchscreen => [ qw(ads7846_ts bu21013_ts bu21029_ts gunze hp680_ts_input itmtouch mk712 mtouch sur40 usbtouchscreen) ],
  },

  various => 
  # just here for classification, unused categories (nor auto-detect, nor load_thiskind)
  {
    raid => [
      qw(dm-bio-prison dm-bufio dm-cache dm-clone dm-crypt dm-log dm-log-userspace dm-mirror dm-mod dm-multipath dm-persistent-data dm-queue-length dm-raid),
      qw(dm-region-hash dm-round-robindm-service-time dm-snapshot dm-zero faulty linear lvm-mod md-mod multipath md-mod raid0 raid10 raid1 raid456),
      # needed by raid456 and dm-raid 456 target
      qw(async_memcpy async_pq async_raid6_recov async_tx async_xor raid6_pq xor),
    ],
    mouse => [
      qw(atixlmouse busmouse cyapatp elan_i2c generic_serial inport ioc3_serial logibm logibusmouse msbusmouse psmouse pcips2 qpmouse synclinkmp),
      qw(mousedev usbhid usbmouse synaptics_usb),
    ],
    char => [
      qw(applicom n_r3964 nvram pc110pad ppdev),
      qw(wdt_pci i810-tco sx), #- what are these???
    ],
    crypto => [
      qw(aes_generic aesni_intel cbc ccm cryptd n5pf padlock-aes padlock-sha sha256_generic virtio_crypto virtio_rng xts),
      qw(aria-aesni-avx2-x86_64 aria-gfni-avx512-x86_64 amd-rng intel-rng),
      qw(af_alg algif_aead algif_hash algif_rng algif_skcipher),
      qw(lib80211_crypt_ccmp lib80211_crypt_tkip lib80211_crypt_wep michael_mic),
    ],
    laptop => [
      qw(i8k sonypi toshiba),
    ],
    serial => [
      qw(8250_pci 8250 epca esp isicom istallion jsm moxa mxser mxser_new stallion sx synclink synclinkmp),
    ],
    other => [
      qw(defxx ide-floppy ide-tape loop lp nbd sg st),
      qw(parport_pc parport_serial),
      qw(btaudio),
      qw(mmc_block sdhci-acpi), # eMMC
      'cryptoloop',
      'ulpi',

      # Virtualization:
      qw(hv_balloon pci-hyperv pci-hyperv-intf),
      qw(mlx5-vfio-pci),
      # Don't include vboxvideo, it doesn't work properly in stage1 or stage2 (mga#23467)
      qw(vboxsf vboxguest vmw_balloon),
      qw(nd_virtio virtio virtiofs virtio_balloon virtio-console virtio_input virtio_pci virtio_pmem virtio_ring vhost_iotlb vhost_scsi vhost_vsock hyperv-keyboard),
      qw(xen-front-pgdir-shbuf),

      # xfs and btrfs needs crc32c(-intel), f2fs needs crc32(_generic)
      qw(crc32c crc32_generic),
      'nvme',

      qw(evdev), qw(usblp printer), 'floppy', 'microcode', 'usb_common',
      qw(acpi_cpufreq processor),
      qw(bcm_sf2),
      qw(intel-lpss intel-lpss-acpi intel-lpss-pci),
      qw(usbip-host),
      qw(vgem),

      # drivers/platform/x86:
      qw(acerhdf acer-wireless acer-wmi alienware-wmi amilo-rfkill apple-gmux asus-laptop asus-nb-wmi asus-wireless asus-wmi classmate-laptop compal-laptop),
      qw(dcdbas dell-laptop dell-rbtn dell-smbios dell-smo8800 dell-wmi-aio dell-wmi-descriptor dell-wmi dell-wmi-ddv dell-wmi-led eeepc-laptop eeepc-wmi fujitsu-laptop),
      qw(fujitsu-tablet gpd-pocket-fan hdaps hp_accel hp-wireless hp-wmi huawei-wmi i2c-multi-instantiate ibm_rtl ideapad-laptop intel_atomisp2_pm),
      qw(intel_bxtwc_tmu intel_chtdc_ti_pwrbtn intel-hid intel_int0002_vgpio intel_ips intel_menlow intel_oaktrail intel_pmc_ipc intel_punit_ipc intel-rst),
      qw(intel-smartconnect intel_telemetry_core intel_telemetry_debugfs intel_telemetry_pltdrv intel-vbtn intel-wmi-thunderbolt lenovo-ymc lg-laptop mlx-platform),
      qw(msi-ec msi-laptop msi-wmi mxm-wmi panasonic-laptop peaq-wmi samsung-laptop samsung-q10 shuttle-wmi sony-laptop surface3_button surface3-wmi),
      qw(surfacepro3_button system76_acpi thinkpad_acpi topstar-laptop toshiba_acpi toshiba_bluetooth toshiba_haps toshiba-wmi wmi-bmof wmi xiaomi-wmi),
      # no more a platform driver:
      qw(pvpanic),

      # drivers/platform/chrome:
      qw(chromeos_laptop),

      #- these need checking
      qw(rrunner meye),

      qw(mei pch_phub),
    ],
    agpgart => [
      qw(ali-agp amd64-agp amd-k7-agp ati-agp efficeon-agp intel-agp),
	 qw(k7-agp mch-agp nvidia-agp sis-agp sworks-agp via-agp),
    ],
  },
);

my %moddeps;

sub load_dependencies {
    my ($file, $o_root) = @_;

    %moddeps = ();
    foreach (cat_($o_root . $file)) {
	my ($m, $d) = split ':';
	my $path = $m;
	my ($filename, @fdeps) = map {
	    s![^ ]*/!!g;
	    s!\.ko!!g;
	    s!\.[gx]z!!g;
	    $_;
	} $m, split(' ', $d);

	my ($modname, @deps) = map { filename2modname($_) } $filename, @fdeps;
	$moddeps{$modname}{deps} = \@deps;
	$moddeps{$modname}{filename} = $filename;
	if (!begins_with($path, "/")) {
		#- with newer module-init-tools, modules.dep can contain
		#- relative paths
		$path = dirname($file) . '/' . $path;
	}
 	$moddeps{$modname}{path} = $path;
    }
}

sub dependencies_closure {
    my @l = map { dependencies_closure($_) } @{exists $moddeps{$_[0]} && $moddeps{$_[0]}{deps} || []};
    (@l, $_[0]);
}

sub filename2modname {
    my ($modname) = @_;
    $modname =~ s/-/_/g;
    $modname;
}

sub load_default_moddeps() {
    require c;
    load_dependencies('/lib/modules/' . c::kernel_version() . '/modules.dep');
}

sub modname2filename {
    load_default_moddeps() if !%moddeps;
    $moddeps{$_[0]}{filename};
}

sub modname2path {
    load_default_moddeps() if !%moddeps;
    $moddeps{$_[0]}{path};
}

sub category2modules {
    map {
	my ($t1, $t2s) = m|(.*)/(.*)|;
	my @sub = $t2s eq '*' ? keys %{$l{$t1}} : split('\|', $t2s);
	map {
	    my $l = $l{$t1}{$_} or die "bad category $t1/$_\n" . backtrace();
	    map { filename2modname($_) } @$l;
	} @sub;
    } split(' ', $_[0]);
}

sub all_modules() {
    map { @$_ } map { values %$_ } values %l;
}

sub module2category {
    my ($module) = @_;
    $module = filename2modname($module);
    foreach my $t1 (keys %l) {
	my $h = $l{$t1};
	foreach my $t2 (keys %$h) {
	  $module eq filename2modname($_) and return "$t1/$t2" foreach @{$h->{$t2}};
      }
    }
    return;
}

sub ethernet_categories() {
    'network/main|gigabit|pcmcia|usb|wireless|firewire';
}

sub sub_categories {
    my ($t1) = @_;
    keys %{$l{$t1}};
}

1;
