From 5b79623823350d79e58b0375ccdef294e24d4848 Mon Sep 17 00:00:00 2001 From: Thierry Vignaud Date: Tue, 20 May 2014 19:47:18 +0200 Subject: partially podify some modules --- perl-install/detect_devices.pm | 368 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 365 insertions(+), 3 deletions(-) (limited to 'perl-install/detect_devices.pm') diff --git a/perl-install/detect_devices.pm b/perl-install/detect_devices.pm index f9fe0d392..2e1a7c4d1 100644 --- a/perl-install/detect_devices.pm +++ b/perl-install/detect_devices.pm @@ -16,6 +16,39 @@ use modules; use c; use feature 'state'; + +=head2 SYNOPSYS + +The B modules offers a high level API for detecting devices.* +It mostly relies on the L modules for gluing libldetect back into the Perl world, and thus +being able to enumerate DMI/HID/PCI/USB devices. + +Other devices are mostly detected through /proc & /sys. + +Then the L enables to map modules into categories such as: + +=over + +=item network/ethernet, + +=item network/wireless, + +=item network/wifi, + +=item disk/sata, + +=item disk/scsi, + +=item ... + +=back + +This enables to detect a category by mapping drivers to categories. + +=head2 Listing block devices + +=cut + #-##################################################################################### #- Globals #-##################################################################################### @@ -25,6 +58,14 @@ my %serialprobe; #- Functions #-###################################################################################### +=over + +=item get() + +Returns a list of all block devices (IDE, SCSI, SATA, virtual, RAID, ...) + +=cut + sub get() { #- Detect the default BIOS boot harddrive is kind of tricky. We may have IDE, #- SCSI and RAID devices on the same machine. From what I see so far, the default @@ -190,6 +231,12 @@ sub get_scsi_driver { } } +=item getSCSI() + +Returns a list of all SCSI device. + +=cut + sub getSCSI() { my $dev_dir = '/sys/bus/scsi/devices'; @@ -303,6 +350,11 @@ sub _get_hd_vendor { return ("Hitachi", $info) if $info =~ /^HD[ST][0-9]/; } +=item getIDE() + +Returns a list of all IDE device. + +=cut sub getIDE() { my @idi; @@ -337,6 +389,7 @@ sub block_devices() { : map { $_->{dev} } do { require fs::proc_partitions; fs::proc_partitions::read_raw() }; } +#Returns a list of all CCISS devices (Compaq Smart Array). sub getCompaqSmartArray() { my (@idi, $f); @@ -385,6 +438,12 @@ sub getATARAID() { values %l; } +=item getXenBlk() + +Returns a list of all Xen block devices (/dev/xvd*). + +=cut + sub getXenBlk() { -d '/sys/bus/xen/devices' or return; map { @@ -393,6 +452,12 @@ sub getXenBlk() { } glob("/sys/block/xvd*"); } +=item getVirtIO() + +Returns a list of all VirtIO block devices (/dev/vd*). + +=cut + sub getVirtIO() { -d '/sys/bus/virtio/devices' or return; map { @@ -418,6 +483,12 @@ sub getMmcBlk() { # cpu_freq = arch() =~ /^alpha/ ? "cycle frequency [Hz]" : # arch() =~ /^ppc/ ? "clock" : "cpu MHz" +=item getCPUs() + +Returns a list of all CPUs. + +=cut + sub getCPUs() { my (@cpus, $cpu); foreach (cat_("/proc/cpuinfo")) { @@ -436,6 +507,14 @@ sub ix86_cpu_frequency() { cat_('/proc/cpuinfo') =~ /cpu MHz\s*:\s*(\d+)/ && $1; } +=item probe_category($category) + +Returns a list of devices which drivers are in the asked category. + +eg: my @eth_cards = probe_category('network/ethernet'); + +=cut + sub probe_category { my ($category) = @_; @@ -601,6 +680,14 @@ sub serialPort2text { $_[0] =~ /ttyS(\d+)/ ? "$_[0] / COM" . ($1 + 1) : $_[0]; } +=back + +=head2 Network + +=over + +=cut + sub getSerialModem { my ($modules_conf, $o_mouse) = @_; my $mouse = $o_mouse || {}; @@ -628,6 +715,11 @@ sub getSerialModem { @modems; } +=item getModem() + +Return list of modems (serial, WinModems) +=cut + our $detect_serial_modem = 1; sub getModem { my ($modules_conf) = @_; @@ -676,6 +768,12 @@ sub getECI() { grep { member(sprintf("%04x%04x%04x%04x", $_->{vendor}, $_->{id}, $_->{subvendor}, $_->{subid}), @ids) } usb_probe(); } +=item get_xdsl_usb_devices() + +Return list of xDSL devices. + +=cut + sub get_xdsl_usb_devices() { my @bewan = detect_devices::getBewan(); $_->{driver} = $_->{bus} eq 'USB' ? 'unicorn_usb_atm' : 'unicorn_pci_atm' foreach @bewan; @@ -687,6 +785,12 @@ sub get_xdsl_usb_devices() { @usb, @bewan, @eci; } +=item is_lan_interface($device) + +Is it a LAN interface (blacklist some interfaces (PPP, ...)? + +=cut + sub is_lan_interface { #- we want LAN like interfaces here (eg: ath|br|eth|fddi|plip|ra|tr|usb|wlan). #- there's also bnep%d for bluetooth, bcp%d... @@ -701,6 +805,12 @@ sub is_lan_interface { $_[0] !~ /^(?:hso|ippp|isdn|plip|ppp|pan)/; } +=item is_useful_interface($device) + +Is it a usefull interface (blacklist some interfaces (loopback, sit, wifi, ...)? + +=cut + sub is_useful_interface { #- sit0 which is *always* created by net/ipv6/sit.c, thus is always created since net.agent loads ipv6 module #- wifi%d are created by 3rdparty/hostap/hostap_hw.c (pseudo statistics devices, #14523) @@ -709,6 +819,12 @@ sub is_useful_interface { $_[0] !~ /^(?:lo|sit0|wifi|wmaster|ax|rose|nr|bce|scc)/; } +=item is_wireless_interface($device) + +Is it a WiFi interface? + +=cut + sub is_wireless_interface { my ($interface) = @_; #- some wireless drivers don't always support the SIOCGIWNAME ioctl @@ -721,6 +837,12 @@ sub is_wireless_interface { || -e "/sys/class/net/$interface/phy80211"; } +=item get_all_net_devices() + +Returns list of all network devices + +=cut + sub get_all_net_devices() { #- we need both detection schemes since: #- get_netdevices() use the SIOCGIFCONF ioctl that does not list interfaces that are down @@ -731,15 +853,49 @@ sub get_all_net_devices() { ); } +=item get_lan_interfaces() + +Returns list of all LAN devices + +=cut + sub get_lan_interfaces() { grep { is_lan_interface($_) } get_all_net_devices() } + +=item get_net_interfaces() + +Returns list of all usefull network devices + +=cut + sub get_net_interfaces() { grep { is_useful_interface($_) } get_all_net_devices() } + +=item get_wireless_interface() + +Returns list of all Wireless devices + +=cut + sub get_wireless_interface() { find { is_wireless_interface($_) } get_lan_interfaces() } +=item is_bridge_interface($interface) + +Is it a bridge? + +=cut + sub is_bridge_interface { my ($interface) = @_; -f "/sys/class/net/$interface/bridge/bridge_id"; } +=back + +=head2 Enumerating devices + +=over + +=cut + sub get_ids_from_sysfs_device { my ($dev_path) = @_; my $dev_cat = sub { chomp_(cat_("$dev_path/$_[0]")) }; @@ -867,6 +1023,13 @@ sub pci_probe__real() { $l; } c::pci_probe()); } + +=item pci_probe() + +Cache the result of c::pci_probe() and return the list of items in the PCI devices. + +=cut + sub pci_probe() { state $done; if (!$done) { @@ -889,6 +1052,13 @@ sub usb_probe__real() { $l; } c::usb_probe()); } + +=item usb_probe() + +Cache the result of c::usb_probe() and return the list of items in the USB devices. + +=cut + sub usb_probe() { if ($::isStandalone && @usb) { @usb; @@ -897,6 +1067,12 @@ sub usb_probe() { } } +=item firewire_probe() + +Return list of Firewire controllers + +=cut + sub firewire_probe() { my $dev_dir = '/sys/bus/ieee1394/devices'; my @l = map { @@ -936,6 +1112,12 @@ sub firewire_probe() { @l; } +=item pcmcia_controller_probe() + +Return list of PCMCIA controllers + +=cut + sub pcmcia_controller_probe() { my ($controller) = probe_category('bus/pcmcia'); if (!$controller && !$::testing && !$::noauto && arch() =~ /i.86/) { @@ -945,6 +1127,12 @@ sub pcmcia_controller_probe() { $controller; } +=item pcmcia_probe() + +Return list of PCMCIA devices (eg: ethernet PCMCIA cards, ...) + +=cut + sub pcmcia_probe() { require modalias; require modules; @@ -972,6 +1160,12 @@ sub pcmcia_probe() { } all($dev_dir); } +=item dmi_probe() + +Cache the result of c::dmi_probe() (aka dmidecode) and return the list of items in the DMI table + +=cut + sub dmi_probe() { state $dmi_probe; if (arch() !~ /86/) { @@ -981,7 +1175,15 @@ sub dmi_probe() { @$dmi_probe; } +=item probeall() + +Returns a list of all PCI/USB/Firewire/PCMCIA/DMI/HID devices. +It's usually called through a higher level filtering function. + +=cut + # pcmcia_probe provides field "device", used in network.pm +# => probeall with $probe_type is unsafe sub probeall() { return if $::noauto; @@ -1071,6 +1273,11 @@ sub hasPCMCIA() { $::o->{pcmcia} } my (@dmis, $dmidecode_already_runned); +=item dmidecode() + +Return list of DMI categories from DMI table + +=cut # we return a list b/c several DMIs have the same name: sub dmidecode() { return @dmis if $dmidecode_already_runned; @@ -1103,13 +1310,25 @@ sub dmidecode() { $dmidecode_already_runned = 1; @dmis; } + +=item dmi_detect_memory($category) + +Return only one category from DMI table + +=cut + sub dmidecode_category { my ($cat) = @_; my @l = grep { $_->{name} eq $cat } dmidecode(); wantarray() ? @l : $l[0] || {}; } -#- size in MB +=item dmi_detect_memory() + +Return RAM size in MB according to DMI table + +=cut + sub dmi_detect_memory() { my @l1 = map { $_->{'Enabled Size'} =~ /(\d+) MB/ && $1 } dmidecode_category('Memory Module'); my @l2 = map { $_->{'Form Factor'} =~ /^(SIMM|SIP|DIP|DIMM|FB-DIMM|RIMM|SODIMM|SRIMM)$/ && @@ -1118,6 +1337,18 @@ sub dmi_detect_memory() { max(sum(@l1), sum(@l2)); } +=back + +=head2 Test helpers + +=over + +=item computer_info() + +Analyze "Chassis" & "Bios" in dmidecode output and return a hash of flags/values (isLaptop, isServer, BIOS_Year) + +=cut + sub computer_info() { my $Chassis = dmidecode_category('Chassis')->{Type} =~ /(\S+)/ && $1; @@ -1132,8 +1363,44 @@ sub computer_info() { }; } -#- try to detect a laptop, we assume pcmcia service is an indication of a laptop or -#- the following regexp to match graphics card apparently only used for such systems. +=item isLaptop() + +try to detect a laptop. We assume the following is an indication of a laptop: + +=over 4 + +=item * + +pcmcia service + +=item * + +computer_info() (really dmidecode) telling us it's a laptop + +=item * + +ACPI lid button + +=item * + +a regexp to match graphics card apparently only used for such systems. + +=item * + +Mobility CPU + +=item * + +having Type as Laptop in some device + +=item * + +Intel ipw2100/2200/3945 Wireless + +=back + +=cut + sub isLaptop() { arch() =~ /ppc/ ? get_mac_model() =~ /Book/ : @@ -1150,6 +1417,12 @@ sub isLaptop() { || (any { member($_->{driver}, qw(ipw2100 ipw2200 ipw3945)) } pci_probe()); } +=item isServer() + +Is it a server? + +=cut + sub isServer() { computer_info()->{isServer} || (any { $_->{Type} =~ /ECC/ } dmidecode_category('Memory Module')) @@ -1161,6 +1434,12 @@ sub isServer() { || (any { $_->{'model name'} =~ /(Xeon|Opteron)/i } getCPUs()); } +=item isHyperv() + +Are we running under Hyper-V hypervisor? + +=cut + sub isHyperv() { dmidecode_category('System')->{Manufacturer} =~ /Microsoft Corporation/i && dmidecode_category('System')->{'Product Name'} =~ /Virtual Machine/i; @@ -1210,33 +1489,75 @@ sub is_xbox() { any { $_->{vendor} == 0x10de && $_->{id} == 0x02a5 } pci_probe(); } +=item is_virtualbox() + +Are we running under VirtualBox hypervisor? + +=cut + sub is_virtualbox() { any { $_->{driver} eq 'vboxadd' } detect_devices::pci_probe(); } +=item is_vmware() + +Are we running under VMware hypervisor? + +=cut + sub is_vmware() { any { $_->{driver} =~ /Card:VMware/ } detect_devices::pci_probe(); } +=item is_netbook_nettop() + +Is it a NetBook? + +=cut + sub is_netbook_nettop() { my @cpus = getCPUs(); (any { $_->{'model name'} =~ /(\bIntel\(R\) Atom\(TM\)\B)/i } @cpus) || (any { $_->{'model name'} =~ /(\bIntel\(R\) Celeron\(R\) M processor\b|\bVIA C7-M Processor\b|\bGeode\(TM\)\B)/i && $_->{'cpu MHz'} < 1500 } @cpus); } +=item has_low_resources() + +Is it a low ressource machine? + +=cut + sub has_low_resources() { availableRamMB() < 100 || arch() =~ /i.86/ && ix86_cpu_frequency() < 350; } +=item need_light_desktop() + +Does it need a light desktop (netbook or low ressources machine)? + +=cut + sub need_light_desktop() { has_low_resources() || is_netbook_nettop(); } +=item has_cpu_flag($flag) + +Does CPU has this flag + +=cut + sub has_cpu_flag { my ($flag) = @_; cat_('/proc/cpuinfo') =~ /^flags.*\b$flag\b/m; } +=item sub matching_types() + +Returns a hash of flags (laptop, hyperv, touchpad, 64bit, wireless, ...) + +=cut + sub matching_types() { +{ mips_lemote => is_mips_lemote(), @@ -1251,6 +1572,12 @@ sub matching_types() { }; } +=item sub hasCPUMicrocode() + +Does CPU need microcode updates? + +=cut + sub hasCPUMicrocode() { state $hasCPUMicrocode; if (!defined $hasCPUMicrocode) { @@ -1259,14 +1586,41 @@ sub hasCPUMicrocode() { return $hasCPUMicrocode; } +=item sub hasCPUFreq() + +Does CPU support cpufreq? + +=cut + sub hasCPUFreq() { require cpufreq; to_bool(cpufreq::get_modules()) || cat_('/proc/cpuinfo') =~ /AuthenticAMD/ && arch() =~ /x86_64/ || cat_('/proc/cpuinfo') =~ /model name.*Intel\(R\) Core\(TM\)2 CPU/; } + +=item sub hasWacom() + +is there a Wacom tablet? + +=cut + sub hasWacom() { find { $_->{vendor} == 0x056a || $_->{driver} =~ /wacom/ } usb_probe() } + +=item sub hasTouchpad() + +is there a touchpad? + +=cut + sub hasTouchpad() { any { $_->{Synaptics} || $_->{ALPS} || $_->{Elantech} } getInputDevices() } + +=item sub hasNumpad() + +is there a numeric pad? + +=cut + sub hasNumpad() { any { $_->{Numpad} } getInputDevices() } sub usbWacom() { grep { $_->{vendor} eq '056a' } getInputDevices() } @@ -1391,6 +1745,14 @@ sub suggest_mount_point { $name; } +=back + +=head2 SEE ALSO + +See L for the overall view. + +=cut + 1; #- Local Variables: -- cgit v1.2.1