summaryrefslogtreecommitdiffstats
path: root/perl-install/detect_devices.pm
diff options
context:
space:
mode:
Diffstat (limited to 'perl-install/detect_devices.pm')
-rw-r--r--perl-install/detect_devices.pm611
1 files changed, 501 insertions, 110 deletions
diff --git a/perl-install/detect_devices.pm b/perl-install/detect_devices.pm
index da48ba9f9..48dadadbb 100644
--- a/perl-install/detect_devices.pm
+++ b/perl-install/detect_devices.pm
@@ -1,4 +1,4 @@
-package detect_devices; # $Id: detect_devices.pm 267151 2010-03-30 14:27:41Z blino $
+package detect_devices;
use diagnostics;
use strict;
@@ -16,6 +16,39 @@ use modules;
use c;
use feature 'state';
+
+=head1 SYNOPSYS
+
+The B<detect_devices> modules offers a high level API for detecting devices.*
+It mostly relies on the L<c> 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 C</proc> & C</sys>.
+
+Then the L<list_modules> enables to map modules into categories such as:
+
+=over 4
+
+=item * C<network/ethernet,>
+
+=item * C<network/wireless,>
+
+=item * C<network/wifi,>
+
+=item * C<disk/sata,>
+
+=item * C<disk/scsi,>
+
+=item * ...
+
+=back
+
+This enables to detect a category by mapping drivers to categories.
+
+=head1 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
@@ -33,7 +74,7 @@ sub get() {
#- 2. The first SCSI device if SCSI exists. Or
#- 3. The first RAID device if RAID exists.
- getIDE(), getSCSI(), getVirtIO(), getDAC960(), getCompaqSmartArray(), getATARAID();
+ getIDE(), getSCSI(), getMmcBlk(), getNVMe(), getXenBlk(), getVirtIO(), getDAC960(), getCompaqSmartArray();
}
sub hds() { grep { may_be_a_hd($_) } get() }
sub tapes() { grep { $_->{media_type} eq 'tape' } get() }
@@ -55,18 +96,21 @@ sub floppies {
state @fds;
state $legacy_already_detected;
- $o_not_detect_legacy_floppies = 1 if arch() =~ /mips|arm/;
+ $o_not_detect_legacy_floppies = 1 if arch() =~ /arm/;
if (!$o_not_detect_legacy_floppies && !$legacy_already_detected) {
$legacy_already_detected = 1;
- eval { modules::load("floppy") if $::isInstall };
+ if ($::isInstall) {
+ eval { modules::load("floppy") };
+ system(qw(udevadm settle)) if !$@;
+ }
#- do not bother probing /dev/fd0 and loading floppy device uselessly,
#- it takes time and it is already done by boot process (if not in install):
#- /dev/fd0 is created by start_udev (/etc/udev/devices.d/default.nodes)
#- then hal probes /dev/fd0 and triggers floppy module loading through kernel's kmod
if (any { (split)[1] eq 'fd' } cat_("/proc/devices")) {
@fds = map {
- my $info = c::floppy_info(devices::make("fd$_"));
+ my $info = c::floppy_info("/dev/fd$_");
if_($info && $info ne '(null)', { device => "fd$_", media_type => 'fd', info => $info });
} qw(0 1);
}
@@ -190,6 +234,12 @@ sub get_scsi_driver {
}
}
+=item getSCSI()
+
+Returns a list of all SCSI device.
+
+=cut
+
sub getSCSI() {
my $dev_dir = '/sys/bus/scsi/devices';
@@ -230,7 +280,7 @@ sub getSCSI() {
$s;
};
- # Old hp scanners report themselves as "Processor"s
+ # Old HP scanners report themselves as "Processor"s
# (see linux/include/scsi/scsi.h and sans-find-scanner.1)
my $raw_type = $scsi_types[$get->('type')];
@@ -273,6 +323,7 @@ my %hd_vendors = (
"Compaq" => "Compaq",
"CONNER" => "Conner Peripherals",
"IBM" => "IBM",
+ "INTEL" => "Intel",
"FUJITSU" => "Fujitsu",
"HITACHI" => "Hitachi",
"Lite-On" => "Lite-On Technology Corp.",
@@ -303,6 +354,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;
@@ -312,7 +368,6 @@ sub getIDE() {
#- Great. 2.2 kernel, things are much easier and less error prone.
foreach my $d (sort @{[glob_('/proc/ide/hd*')]}) {
- cat_("$d/driver") =~ /ide-scsi/ and next; #- already appears in /proc/scsi/scsi
my $t = chomp_(cat_("$d/media"));
my $type = ${{ disk => 'hd', cdrom => 'cdrom', tape => 'tape', floppy => 'fd' }}{$t} or next;
my $info = chomp_(cat_("$d/model")) || "(none)";
@@ -338,6 +393,12 @@ sub block_devices() {
: map { $_->{dev} } do { require fs::proc_partitions; fs::proc_partitions::read_raw() };
}
+=item getCompaqSmartArray()
+
+Returns a list of all CCISS devices (Compaq Smart Array).
+
+=cut
+
sub getCompaqSmartArray() {
my (@idi, $f);
@@ -376,16 +437,26 @@ sub getDAC960() {
values %idi;
}
-sub getATARAID() {
- my %l;
- foreach (syslog()) {
- my ($device) = m|^\s*(ataraid/d\d+):| or next;
- $l{$device} = { info => 'ATARAID block device', media_type => 'hd', device => $device, bus => 'ataraid' };
- log::l("ATARAID: $device");
- }
- values %l;
+=item getXenBlk()
+
+Returns a list of all Xen block devices (C</dev/xvd*>).
+
+=cut
+
+sub getXenBlk() {
+ -d '/sys/bus/xen/devices' or return;
+ map {
+ s/block://;
+ { device => basename($_), info => "Xen block device", media_type => 'hd', bus => 'xen' };
+ } glob("/sys/block/xvd*");
}
+=item getVirtIO()
+
+Returns a list of all VirtIO block devices (/dev/C<vd*>).
+
+=cut
+
sub getVirtIO() {
-d '/sys/bus/virtio/devices' or return;
map {
@@ -394,14 +465,27 @@ sub getVirtIO() {
glob("/sys/bus/virtio/devices/*/block/*");
}
-# cpu_name : arch() =~ /^alpha/ ? "cpu " :
-# arch() =~ /^ppc/ ? "processor" : "vendor_id"
+sub getMmcBlk() {
+ -d '/sys/bus/mmc/devices' or return;
+ map {
+ { device => basename($_), info => "MMC block device", media_type => 'hd', bus => 'mmc' };
+ }
+ glob("/sys/bus/mmc/devices/*/block/*");
+}
+
+sub getNVMe() {
+ -d '/sys/class/nvme' or return;
+ map {
+ { device => basename($_), info => "NVMe block device", media_type => 'hd', bus => 'pci_express' };
+ }
+ glob("/sys/block/nvme*");
+}
+
+=item getCPUs()
-# cpu_model : arch() =~ /^alpha/ ? "cpu model" :
-# arch() =~ /^ppc/ ? "cpu " : "model name"
+Returns a list of all CPUs.
-# cpu_freq = arch() =~ /^alpha/ ? "cycle frequency [Hz]" :
-# arch() =~ /^ppc/ ? "clock" : "cpu MHz"
+=cut
sub getCPUs() {
my (@cpus, $cpu);
@@ -421,15 +505,20 @@ 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) = @_;
require list_modules;
my @modules = list_modules::category2modules($category);
- if_($category =~ /sound/ && arch() =~ /ppc/ && get_mac_model() !~ /IBM/,
- { driver => 'snd_powermac', description => 'Macintosh built-in' },
- ),
grep {
if ($category eq 'network/isdn') {
my $b = $_->{driver} =~ /ISDN:([^,]*),?([^,]*)(?:,firmware=(.*))?/;
@@ -456,6 +545,8 @@ sub isTVcardConfigurable { member($_[0]{driver}, qw(bttv cx88 saa7134)) }
sub getTVcards() { probe_category('multimedia/tv') }
sub getInputDevices() {
+ state @input_devices;
+ return @input_devices if @input_devices;
my (@devices, $device);
my $event;
foreach (cat_('/proc/bus/input/devices')) {
@@ -550,18 +641,23 @@ sub getInputDevices() {
#- KEY=30000 0 0 0 0 0 0 0 0 #=> BTN_LEFT BTN_RIGHT
#- KEY=70000 0 0 0 0 0 0 0 0 #=> BTN_LEFT BTN_RIGHT BTN_MIDDLE
#- KEY=1f0000 0 0 0 0 0 0 0 0 #=> BTN_LEFT BTN_RIGHT BTN_MIDDLE BTN_SIDE BTN_EXTRA
- if (! -f "/dev/input/$event") {
+ if (!$> && ! -f "/dev/input/$event") {
devices::make("/dev/input/$event");
}
- my @KEYS = c::EVIocGBitKey("/dev/input/$event");
- $device->{SIDE} = 1 if $KEYS[0] & (1 << 0x13);
+ if (-r "/dev/input/$event") {
+ my @KEYS = c::EVIocGBitKey("/dev/input/$event");
+ $device->{SIDE} = 1 if $KEYS[0] & (1 << 0x13);
+ } else {
+ my $KEY = hex($1);
+ $device->{SIDE} = 1 if $KEY & (1 << 0x13);
+ }
} elsif (/^\s*$/) {
push @devices, $device if $device;
undef $device;
}
}
- @devices;
+ @input_devices = @devices;
}
sub getInputDevices_and_usb() {
@@ -581,11 +677,19 @@ sub serialPort2text {
$_[0] =~ /ttyS(\d+)/ ? "$_[0] / COM" . ($1 + 1) : $_[0];
}
+=back
+
+=head1 Network
+
+=over
+
+=cut
+
sub getSerialModem {
- my ($modules_conf, $o_mouse) = @_;
+ my ($_modules_conf, $o_mouse) = @_;
my $mouse = $o_mouse || {};
$mouse->{device} = readlink "/dev/mouse";
- my $serdev = arch() =~ /ppc/ ? "macserial" : arch() =~ /mips/ ? "8250" : "serial";
+ my $serdev = "serial";
eval { modules::load($serdev) };
@@ -601,13 +705,16 @@ sub getSerialModem {
}
my @devs = pcmcia_probe();
foreach my $modem (@modems) {
- #- add an alias for macserial on PPC
- $modules_conf->set_alias('serial', $serdev) if arch() =~ /ppc/ && $modem->{device};
foreach (@devs) { $_->{device} and $modem->{device} = $_->{device} }
}
@modems;
}
+=item getModem()
+
+Return list of modems (serial, WinModems)
+=cut
+
our $detect_serial_modem = 1;
sub getModem {
my ($modules_conf) = @_;
@@ -656,6 +763,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;
@@ -667,6 +780,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...
@@ -681,6 +800,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)
@@ -689,6 +814,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
@@ -696,9 +827,17 @@ sub is_wireless_interface {
#- wlan-ng (prism2_*) need some special tweaks to support it
#- use sysfs as fallback to detect wireless interfaces,
#- i.e interfaces for which get_wireless_stats() is available
- c::isNetDeviceWirelessAware($interface) || -e "/sys/class/net/$interface/wireless";
+ c::isNetDeviceWirelessAware($interface)
+ || -e "/sys/class/net/$interface/wireless"
+ || -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
@@ -709,15 +848,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 useful 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
+
+=head1 Enumerating devices
+
+=over
+
+=cut
+
sub get_ids_from_sysfs_device {
my ($dev_path) = @_;
my $dev_cat = sub { chomp_(cat_("$dev_path/$_[0]")) };
@@ -772,7 +945,7 @@ sub getUPS() {
# USB UPSs;
(map { ($_->{name} = $_->{description}) =~ s/.*\|//; $_ }
map {
- if ($_->{description} =~ /^American Power Conversion\|Back-UPS/ && $_->{driver} eq 'usbhid') {
+ if ($_->{description} =~ /Back-UPS/ && $_->{driver} eq 'usbhid') {
#- FIXME: should not be hardcoded, use $_->{sysfs_device} . */usb:(hiddev\d+)
#- the device should also be assigned to the ups user
$_->{port} = "/dev/hiddev0";
@@ -839,14 +1012,19 @@ my (@pci, @usb);
sub pci_probe__real() {
add_addons($pcitable_addons, map {
- my %l;
- @l{qw(vendor id subvendor subid pci_domain pci_bus pci_device pci_function pci_revision is_pciexpress media_type nice_media_type driver description)} = split "\t";
- $l{$_} = hex $l{$_} foreach qw(vendor id subvendor subid);
- $l{bus} = 'PCI';
- $l{sysfs_device} = '/sys/bus/pci/devices/' . get_pci_sysfs_path(\%l);
- \%l;
+ my $l = $_;
+ $l->{bus} = 'PCI';
+ $l->{sysfs_device} = '/sys/bus/pci/devices/' . get_pci_sysfs_path($l);
+ $l;
} c::pci_probe());
}
+
+=item pci_probe()
+
+Cache the result of C<c::pci_probe()> and return the list of items in the PCI devices.
+
+=cut
+
sub pci_probe() {
state $done;
if (!$done) {
@@ -859,18 +1037,23 @@ sub pci_probe() {
}
sub usb_probe__real() {
- -e "/proc/bus/usb/devices" or return;
+ -e "/sys/kernel/debug/usb/devices" or return;
add_addons($usbtable_addons, map {
- my %l;
- @l{qw(vendor id media_type driver description pci_bus pci_device usb_port)} = split "\t";
- $l{media_type} = join('|', grep { $_ ne '(null)' } split('\|', $l{media_type}));
- $l{$_} = hex $l{$_} foreach qw(vendor id);
- $l{sysfs_device} = "/sys/bus/usb/devices/$l{pci_bus}-" . ($l{usb_port} + 1);
- $l{bus} = 'USB';
- \%l;
+ my $l = $_;
+ $l->{media_type} = join('|', grep { $_ ne '(null)' } split('\|', $l->{media_type}));
+ $l->{sysfs_device} = "/sys/bus/usb/devices/$l->{pci_bus}-" . ($l->{usb_port} + 1);
+ $l->{bus} = 'USB';
+ $l;
} c::usb_probe());
}
+
+=item usb_probe()
+
+Cache the result of C<c::usb_probe()> and return the list of items in the USB devices.
+
+=cut
+
sub usb_probe() {
if ($::isStandalone && @usb) {
@usb;
@@ -879,6 +1062,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 {
@@ -918,6 +1107,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/) {
@@ -927,6 +1122,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;
@@ -954,23 +1155,61 @@ sub pcmcia_probe() {
} all($dev_dir);
}
+=item dmi_probe()
+
+Cache the result of c::dmi_probe() (aka C<dmidecode>) and return the list of items in the DMI table
+
+=cut
+
sub dmi_probe() {
state $dmi_probe;
- if (arch() !~ /86/) {
- return [];
- }
- $dmi_probe ||= [ map {
- /(.*?)\t(.*)/ && { bus => 'DMI', driver => $1, description => $2 };
- } $> ? () : c::dmi_probe() ];
+ return if arch() !~ /86/;
+ $dmi_probe ||= $> ? [] : [ c::dmi_probe() ];
@$dmi_probe;
}
+=item acpi_probe()
+
+Return list of devices that are only discoverable via ACPI
+
+=cut
+
+my %acpi_device_info = (
+ "80860F28" => { vendor => 0x8086, id => 0x0f28, description => 'Intel Corporation|Bay Trail SST Audio DSP',
+ nice_media_type => 'Audio device', driver => 'snd_sof_acpi_intel_byt' },
+ "808622A8" => { vendor => 0x8086, id => 0x22a8, description => 'Intel Corporation|Cherry Trail SST Audio DSP',
+ nice_media_type => 'Audio device', driver => 'snd_sof_acpi_intel_byt' },
+ "INT3438" => { vendor => 0x8086, id => 0x3438, description => 'Intel Corporation|Broadwell SST Audio DSP',
+ nice_media_type => 'Audio device', driver => 'snd_sof_acpi_intel_bdw' }
+);
+
+sub acpi_probe() {
+ my $dev_dir = '/sys/bus/acpi/devices';
+ my @l;
+ foreach (glob("$dev_dir/*")) {
+ my $dev_name = basename($_);
+ my ($prefix, $suffix) = split(':', $dev_name);
+ my $e = $acpi_device_info{$prefix};
+ if ($e) {
+ add2hash($e, { bus => 'ACPI', sysfs_device => "$dev_dir/$dev_name" });
+ push @l, $e;
+ }
+ }
+ @l;
+}
+
+=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;
- pci_probe(), usb_probe(), firewire_probe(), pcmcia_probe(), dmi_probe(), getInputDevices_and_usb();
+ pci_probe(), usb_probe(), firewire_probe(), pcmcia_probe(), dmi_probe(), acpi_probe(), getInputDevices_and_usb();
}
sub probeall_update_cache() {
return if $::noauto;
@@ -1056,30 +1295,27 @@ 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;
return if $>;
- my ($ver, @l) = arch() =~ /86/ ? run_program::get_stdout('dmidecode') : ();
-
- my $tab = "\t";
+ my ($_ver, @l) = arch() =~ /86/ ? run_program::get_stdout('dmidecode') : ();
- my ($major, $minor) = $ver =~ /(\d+)\.(\d+)/;
-
- if ($major > 2 || $major == 2 && $minor > 7) {
- #- new dmidecode output is less indented
- $tab = '';
- #- drop header
- shift @l while @l && $l[0] ne "\n";
- }
+ #- drop header
+ shift @l while @l && $l[0] ne "\n";
foreach (@l) {
next if /TRUNCATED/;
- if (/^$tab\t(.*)/) {
+ if (/^\t(.*)/) {
$dmis[-1]{string} .= "$1\n";
- $dmis[-1]{$1} = $2 if /^$tab\t(.*): (.*)$/;
- } elsif (my ($s) = /^$tab(.*)/) {
+ $dmis[-1]{$1} = $2 if /^\t(.*): (.*)$/;
+ } elsif (my ($s) = /^(.*)/) {
next if $s =~ /^$/ || $s =~ /\bDMI type \d+/;
$s =~ s/ Information$//;
push @dmis, { name => $s };
@@ -1088,13 +1324,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)$/ &&
@@ -1103,6 +1351,18 @@ sub dmi_detect_memory() {
max(sum(@l1), sum(@l2));
}
+=back
+
+=head1 Test helpers
+
+=over
+
+=item computer_info()
+
+Analyse "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;
@@ -1117,11 +1377,45 @@ 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 *
+
+C<computer_info()> (really C<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/ :
computer_info()->{isLaptop}
|| glob_("/sys/bus/acpi/devices/PNP0C0D:*") #- ACPI lid button
|| (matching_desc__regexp('C&T.*655[45]\d') || matching_desc__regexp('C&T.*68554') ||
@@ -1135,6 +1429,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'))
@@ -1147,31 +1447,7 @@ sub isServer() {
}
sub BIGMEM() {
- arch() !~ /x86_64|ia64/ && $> == 0 && dmi_detect_memory() > 4 * 1024;
-}
-
-sub is_i586() {
- return 0 if arch() !~ /86/;
- my $cpuinfo = cat_('/proc/cpuinfo');
- $cpuinfo =~ /^cpu family\s*:\s*(\d+)/m && $1 < 6 ||
- $cpuinfo =~ /^model name\s*:\s*Transmeta.* TM5800/m || # mdvbz#37866
- !has_cpu_flag('cmov');
-}
-
-sub is_mips_lemote() {
- to_bool(cat_('/proc/cpuinfo') =~ /lemote/);
-}
-
-sub is_mips_ict() {
- to_bool(cat_('/proc/cpuinfo') =~ /ict/);
-}
-
-sub is_mips_gdium() {
- to_bool(cat_('/proc/cpuinfo') =~ /gdium/);
-}
-
-sub is_mips_st_ls2f() {
- to_bool(cat_('/proc/cpuinfo') =~ /st-ls2f/);
+ arch() !~ /x86_64/ && $> == 0 && dmi_detect_memory() > 4 * 1024;
}
sub is_arm_openrd_client() {
@@ -1190,63 +1466,169 @@ sub is_xbox() {
any { $_->{vendor} == 0x10de && $_->{id} == 0x02a5 } pci_probe();
}
+=item virt_technology()
+
+Returns the virtualization technology (eg: kvm, oracle, ...)
+
+=cut
+
+sub virt_technology() {
+ state $tech;
+ $tech ||= chomp_(run_program::get_stdout('systemd-detect-virt'));
+}
+
+=item is_hyperv()
+
+Are we running under Hyper-V hypervisor?
+
+=cut
+
+sub is_hyperv() {
+ virt_technology() eq 'microsoft';
+}
+
+=item is_qemu()
+
+Are we running under Qemu hypervisor?
+
+=cut
+
+sub is_qemu() {
+ member(virt_technology(), qw(kvm qemu));
+}
+
+=item is_virtualbox()
+
+Are we running under VirtualBox hypervisor?
+
+=cut
+
sub is_virtualbox() {
- any { $_->{driver} eq 'vboxadd' } detect_devices::pci_probe();
+ virt_technology() eq 'oracle';
}
+=item is_vmware()
+
+Are we running under VMware hypervisor?
+
+=cut
+
sub is_vmware() {
- any { $_->{driver} =~ /Card:VMware/ } detect_devices::pci_probe();
+ virt_technology() eq 'vmware';
}
+=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 resource 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 resources 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(),
- mips_ict => is_mips_ict(),
- mips_st_ls2f => is_mips_st_ls2f(),
- laptop => isLaptop(),
- 'numpad' => hasNumpad(),
- 'touchpad' => hasTouchpad(),
'64bit' => to_bool(arch() =~ /64/),
+ hyperv => is_hyperv(),
+ laptop => isLaptop(),
+ numpad => hasNumpad(),
+ touchpad => hasTouchpad(),
+ qemu => is_qemu(),
+ virtualbox => is_virtualbox(),
+ vmware => is_vmware(),
wireless => to_bool(get_wireless_interface() || probe_category('network/wireless')),
};
}
+=item sub hasCPUMicrocode()
+
+Does CPU need microcode updates?
+
+=cut
+
sub hasCPUMicrocode() {
state $hasCPUMicrocode;
if (!defined $hasCPUMicrocode) {
- eval { modules::load('microcode') };
$hasCPUMicrocode = to_bool(find { 'microcode' } modules::loaded_modules());
}
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() }
@@ -1258,6 +1640,7 @@ sub has_53c94() { find { /53c94/ } all_files_rec("/proc/device-tree") }
sub usbKeyboard2country_code {
my ($usb_kbd) = @_;
my ($F, $tmp);
+ # FIXME: usbfs is dead! we should poke somewhere in /sys/ !!!!
sysopen($F, sprintf("/proc/bus/usb/%03d/%03d", $usb_kbd->{pci_bus}, $usb_kbd->{pci_device}), 0) and
sysseek $F, 0x28, 0 and
sysread $F, $tmp, 1 and
@@ -1319,7 +1702,7 @@ sub probeall_unavailable_modules() {
!member($driver, 'hub', 'unknown', 'amd64_agp') &&
!modules::module_is_available($driver) ?
$driver :
- ();
+ @{[]};
} probeall();
}
@@ -1370,6 +1753,14 @@ sub suggest_mount_point {
$name;
}
+=back
+
+=head1 SEE ALSO
+
+See L<hardware_detection> for the overall view.
+
+=cut
+
1;
#- Local Variables: