home *** CD-ROM | disk | FTP | other *** search
- #!/usr/bin/perl
-
- #/*
- #* Copyright (C) 2005-2006 Pontus Fuchs, Giridhar Pemmasani
- #*
- #*
- #* This program is free software; you can redistribute it and/or modify
- #* it under the terms of the GNU General Public License as published by
- #* the Free Software Foundation; either version 2 of the License, or
- #* (at your option) any later version.
- #*
- #* This program is distributed in the hope that it will be useful,
- #* but WITHOUT ANY WARRANTY; without even the implied warranty of
- #* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- #* GNU General Public License for more details.
- #*
- #*/
-
- use strict;
- use Fcntl ':mode';
- use File::Basename;
- use File::Copy;
- use File::Path;
- use Cwd;
-
- $ENV{PATH} = "/sbin:/usr/sbin:$ENV{PATH}";
-
- my $WRAP_PCI_BUS = 5;
- my $WRAP_PCMCIA_BUS = 8;
- my $WRAP_USB_BUS = 15;
-
- my %sections;
- my %parsed_sections;
- my $confdir = "/etc/ndiswrapper";
- my $src_dir;
- my $driver_name;
-
- my $re_dev_id = "([[:xdigit:]]{4})";
- my $re_sub_dev_conf = "$re_dev_id:$re_dev_id:$re_dev_id:$re_dev_id" .
- "\.([[:xdigit:]]+)\.conf";
- my $re_dev_conf = "$re_dev_id:$re_dev_id\.([[:xdigit:]]+)\.conf";
-
- # fixup list for parameters.
- my %param_fixlist = ("EnableRadio|0" => "1",
- "IBSSGMode|0" => "2",
- "PrivacyMode|0" => "2",
- "MapRegisters|256" => "64",
- "AdhocGMode|1" => "0");
-
- if (@ARGV < 1) {
- usage();
- exit(1);
- }
-
- my $modconf;
- if (`uname -r` =~ /(\d+)\.(\d+)\.(\d+)/) {
- if ($2 > 4) {
- if (-d "/etc/modprobe.d") {
- $modconf = "/etc/modprobe.d/ndiswrapper"
- } else {
- $modconf = "/etc/modprobe.conf"
- }
- } else {
- if (-d "/etc/modutils") {
- $modconf = "/etc/modutils/ndiswrapper";
- } else {
- $modconf = "/etc/modules.conf";
- }
- }
- }
-
- my $res;
- my $dbg_file;
-
- $dbg_file = ">/dev/null";
-
- # "-D" is for development/debugging only
- if ($ARGV[0] eq "-D") {
- $dbg_file = ">/tmp/ndiswrapper.dbg";
- $confdir = "/tmp/ndiswrapper";
- shift;
- }
-
- open(DBG, $dbg_file) or die "couldn't open $dbg_file: $!";
-
- if ($ARGV[0] eq "-i" and @ARGV == 2) {
- $res = install($ARGV[1]);
- } elsif (($ARGV[0] eq "-a" or $ARGV[0] eq "-d") and @ARGV == 3) {
- $res = device_driver_alias($ARGV[1], $ARGV[2]);
- } elsif (($ARGV[0] eq "-e" or $ARGV[0] eq "-r") and @ARGV == 2) {
- $res = remove_driver($ARGV[1]);
- } elsif ($ARGV[0] eq "-l" and @ARGV == 1) {
- $res = list_drivers();
- } elsif ($ARGV[0] eq "-m" and @ARGV == 1) {
- $res = add_module_alias();
- } elsif ($ARGV[0] eq "-v" and @ARGV == 1) {
- printf "utils "; system("loadndisdriver -v");
- printf "driver ";
- system("modinfo ndiswrapper | grep -E '^version|^vermagic'");
- $res = 0;
- } elsif ($ARGV[0] eq "-ma" and @ARGV == 1) {
- $res = generate_module_device_map(0);
- } elsif ($ARGV[0] eq "-mi" and @ARGV == 1) {
- $res = generate_module_device_map(1);
- } else {
- usage();
- }
- close(DBG);
- exit($res);
-
- sub usage() {
- print "install/manage Windows drivers for ndiswrapper\n\n" .
- "usage: ndiswrapper OPTION\n" .
- "-i inffile install driver described by 'inffile'\n" .
- "-a devid driver use installed 'driver' for 'devid'\n" .
- "-r driver remove 'driver'\n" .
- "-l list installed drivers\n" .
- "-m write configuration for modprobe\n" .
- "-ma write module alias configuration for all devices\n" .
- "-mi write module install configuration for all devices\n" .
- "-v report version information\n\n" .
- "where 'devid' is either PCIID or USBID of the form XXXX:XXXX,\n" .
- "as reported by 'lspci -n' or 'lsusb' for the card\n";
- }
-
- sub remove_driver {
- my $driver = shift;
- if (!rmtree("$confdir/$driver", 0, 1)) {
- warn "couldn't delete $confdir/$driver: $!\n";
- }
- return 0;
- }
-
- sub install {
- my $inf = shift;
- chomp($inf);
- $src_dir = dirname($inf);
- $driver_name = lc(basename($inf));
- $driver_name =~ s/\.inf//;
-
- if (! -d $confdir) {
- mkdir($confdir) or die "couldn't create $confdir: $!";
- }
- (-d "$confdir/$driver_name") and
- die "driver $driver_name is already installed\n";
- mkdir("$confdir/$driver_name") or
- die "couldn't create $confdir/$driver_name: $!";
- print "installing $driver_name ...\n";
- read_sections($inf);
- parse_section("Strings");
- parse_section("Version");
- parse_mfr();
- copy_file(basename($inf));
- create_fuzzy_conf($driver_name);
- return 0;
- }
-
- # return lines in section
- sub get_section {
- my $name = shift;
- foreach my $key (keys %sections) {
- if (lc($key) eq lc($name)) {
- printf DBG "section: $key\n";
- return \@{$sections{$key}};
- }
- }
- printf DBG "couldn't find section \"$name\"\n";
- return 0;
- }
-
- # load inf and split into different sections.
- sub read_sections {
- my $filename = shift;
- open(INF, $filename) or die "couldn't open $filename: $!";
-
- my $name = "none";
- @{$sections{$name}} = ();
- while (my $line = <INF>) {
- # convert from unicode
- $line =~ s/\xff\xfe//;
- $line =~ s/\0//g;
-
- chomp($line);
- $line = trim($line);
- next if ($line =~ /^$/);
- if ($line =~ /^\[(.+)\]/) {
- $name = $1;
- @{$sections{$name}} = ();
- } else {
- push(@{$sections{$name}}, $line);
- }
- }
- close(INF);
- foreach $name (keys %sections) {
- printf DBG "section: %s\n", $name;
- foreach my $line (@{$sections{$name}}) {
- printf DBG "%s: %s\n", $name, $line;
- }
- }
- }
-
- sub parse_section {
- my $name = shift;
- my $lines = get_section($name);
- if (!$lines) {
- return;
- }
- $parsed_sections{$name} = ();
- foreach my $line (@{$lines}) {
- (my $key, my $val) = parse_key_value($line);
- if ($key) {
- $val = strip_quotes($val);
- $parsed_sections{$name}->{$key} = $val;
- printf DBG "$name: %s = %s\n", $key, $val;
- }
- }
- }
-
- sub parse_mfr() {
- my $lines = get_section("Manufacturer");
- $lines or die "couldn't get manufacturer section - " .
- "installation may be incomplete\n";
- foreach my $line (@{$lines}) {
- (my $strkey, my $val) = parse_key_value($line);
- if ($strkey) {
- (my $models, my @targets) = split(",", $val);
- if ($models) {
- printf DBG "mfr: %s, %s\n", $line, $models;
- parse_models($models);
- }
- }
- }
- }
-
- sub parse_models {
- my $models = shift;
- my $lines = get_target_os_section($models);
- if (!$lines) {
- warn "couldn't find models section \"$models\" -\n" .
- "installation may be incomplete\n";
- return -1;
- }
- foreach my $line (@{$lines}) {
- $line = del_comment($line);
- next if (length($line) eq 0);
- (my $dev_desc, my $val) = parse_key_value($line);
- my @fields = split(",", $val);
- if (@fields le 1) {
- printf "couldn't find install directive: %s\n", $line;
- next;
- }
- my $install_section = trim($fields[0]);
- my $hwid = trim($fields[1]);
- if ($hwid =~ /^%.+%$/) {
- $hwid = get_string_value($hwid);
- }
- # TODO: deal with compatible IDs as hwid?
- (my $bus_type, my $vendor, my $device, my $subvendor, my $subdevice) =
- parse_hwid($hwid);
- printf DBG "models: %s, %s\n", $install_section, $hwid, $vendor;
- next if (!$vendor);
- parse_install($install_section, $bus_type, $vendor, $device,
- $subvendor, $subdevice);
- }
- }
-
- sub parse_install {
- (my $secn, my $bus_type, my $vendor, my $device,
- my $subvendor, my $subdevice) = @_;
- my $lines = get_target_os_section($secn);
- if (!$lines) {
- warn "couldn't find install section \"$secn\" -\n" .
- "installation may be incomplete\n";
- return -1;
- }
-
- my $filename = "$vendor:$device";
- if ($subvendor) {
- $filename .= ":$subvendor:$subdevice"
- }
- $filename .= sprintf(".%X.conf", $bus_type);
-
- my @addregs;
- my @copyfiles;
- foreach my $line (@{$lines}) {
- $line =~ s/^;\s*//;
- $line = trim(del_comment($line));
- (my $key, my $val) = parse_key_value($line);
- my @array;
- if ($key) {
- if (lc($key) eq "addreg") {
- @array = split(",", $val);
- foreach my $reg (@array) {
- push @addregs, trim($reg);
- }
- } elsif (lc($key) eq "copyfiles") {
- printf DBG "copyfiles: %s\n", $val;
- @array = split(",", $val);
- foreach my $copy_file (@array) {
- my @copy_sec = split(",", $copy_file);
- foreach my $file (@copy_sec) {
- push @copyfiles, trim($file);
- }
- }
- } elsif (lc($key) eq "bustype") {
- printf DBG "bustype: %s\n", $val;
- $bus_type = $val;
- }
- }
- }
-
- open(CONF, ">$confdir/$driver_name/$filename") or
- die "couldn't create file $filename: $!";
-
- my $version = get_section_value("Version", "DriverVer");
- my $provider = get_section_value("Version", "Provider");
- my $classguid = get_section_value("Version", "ClassGUID");
- my $providerstring = trim(strip_quotes(get_string_value(trim($provider))));
- $classguid =~ s/^\s*{//;
- $classguid =~ s/}\s*$//;
-
- printf CONF "NdisVersion|0x50001\n";
- printf CONF "Environment|1\n";
- printf CONF "class_guid|%s\n", $classguid;
- printf CONF "mac_address|XX:XX:XX:XX:XX:XX\n";
- printf CONF "driver_version|%s,%s\n", $providerstring, $version;
- printf CONF "BusType|%s\n", $bus_type;
- printf CONF "SlotNumber|01\n";
- printf CONF "\n";
- close(CONF);
-
- open(CONF, "|sort|uniq >>$confdir/$driver_name/$filename") or
- die "couldn't create file $confdir/$driver_name/$filename: $!";
-
- foreach my $reg (@addregs) {
- parse_registry($reg);
- }
- foreach my $file (@copyfiles) {
- parse_copy_file($file);
- }
- # RTL8185L driver crashes if DriverDesc setting is not found
- if ($vendor == "10EC" && $device == "8185") {
- printf CONF "DriverDesc|Realtek RTL8185 54M Wireless LAN Network Adapter\n";
- }
- close(CONF);
- }
-
- sub parse_registry {
- my $reg = shift;
- my $conf = shift;
- my $lines = get_section($reg);
- if (!$lines) {
- warn "couldn't find section \"$reg\" -\n" .
- "installation may be incomplete\n";
- return -1;
- }
-
- foreach my $line (@{$lines}) {
- $line = del_comment($line);
- my @fields = split(",", $line);
- next if (@fields lt 4);
- my $value;
- my $param = trim($fields[1]);
- if ($param =~ /^ndi\\/i) {
- if ($param =~ /^ndi\\params\\(.+)/i) {
- $param = strip_quotes(trim($1));
- $param =~ s/\\.*$//;
- next if (lc(trim($fields[2])) ne "default");
- $value = strip_quotes(trim($fields[4]));
- } else {
- printf DBG "ignoring parameter $line\n";
- next;
- }
- } else {
- $param = strip_quotes(trim($fields[2]));
- next if (length($param) eq 0);
- $value = strip_quotes(trim($fields[4]));
- }
- $value = get_string_value($value);
- if (length($param) gt 0) {
- if ($param_fixlist{"$param|$value"}) {
- my $orig_value = $value;
- $value = $param_fixlist{"$param|$value"};
- printf "forcing parameter $param from $orig_value to $value\n";
- }
- printf CONF "%s|%s\n", $param, $value;
- }
- }
- }
-
- sub parse_copy_file {
- my $copy_name = shift;
-
- if ($copy_name =~ /^\@/) {
- $copy_name =~ s/^\@//;
- return copy_file($copy_name);
- }
-
- my $lines = get_section($copy_name);
- if (!$lines) {
- warn "couldn't find section \"$copy_name\" -\n" .
- "installation may be incomplete\n";
- return -1;
- }
- foreach my $line (@{$lines}) {
- $line = trim($line);
-
- my @files = split(",", $line);
- if (@files == 0) {
- printf DBG "copyfiles section $copy_name has no files\n";
- return -1;
- }
- my $file;
- if (@files > 1 and length($files[1]) > 0) {
- $file = $files[1];
- } else {
- $file = $files[0];
- }
- printf DBG "file: '%s'\n", $file;
- # some inf files have file names commented out; get file names from them
- $file =~ s/^\s*;//;
- # remove (trailing) comment
- $file = del_comment($file);
- $file = trim($file);
- if (length($file) > 0) {
- if (valid_copy_file_name($file)) {
- copy_file($file);
- } else {
- printf DBG "invalid file '%s' ignored\n", $file;
- }
- }
- }
- return 0;
- }
-
- sub parse_hwid {
- my $hwid = uc(shift);
- if ($hwid =~ /(PCI\\)?VEN_(\w+)&DEV_(\w+)&SUBSYS_(\w{4})(\S{4})/) {
- return ($WRAP_PCI_BUS, $2, $3, $4, $5);
- } elsif ($hwid =~ /(PCI\\)?VEN_(\w+)&DEV_(\w+)/) {
- return ($WRAP_PCI_BUS, $2, $3, 0, 0);
- } elsif ($hwid =~ /(USB\\)?VID_(\w+)&PID_(\w+)/) {
- return ($WRAP_USB_BUS, $2, $3, 0, 0);
- } else {
- return 0;
- }
- }
-
- sub parse_key_value {
- my $line = shift;
-
- $line = del_comment($line);
- if ($line =~ /([^=]+)=(.+)/) {
- return (trim($1), trim($2));
- } else {
- return 0;
- }
- }
-
- sub get_target_os_section {
- my $secn = shift;
- my $arch = `uname -m`;
- chomp($arch);
- if ($arch =~ /64$/) {
- $arch = "AMD64";
- } else {
- $arch = "X86";
- }
- chomp($secn);
- $secn =~ s/^\s*"\s*//;
- $secn =~ s/\s*"\s*$//;
- printf DBG "secn: \"%s\"\n", $secn;
- $secn =~ s/\.NT($arch)?(\.5\.1)?$//;
- printf DBG "secn: \"%s\"\n", $secn;
-
- my $lines = get_section($secn . ".NT" . $arch . ".5.1");
- return $lines if ($lines);
-
- $lines = get_section($secn . ".NT" . $arch);
- return $lines if ($lines);
-
- $lines = get_section($secn . ".NT.5.1");
- return $lines if ($lines);
-
- $lines = get_section($secn . ".NT");
- return $lines if ($lines);
-
- $lines = get_section($secn);
- return $lines if ($lines);
-
- printf DBG "couldn't find section \"$secn\" for \"$arch\"\n";
- return 0;
- }
-
- sub get_section_value {
- (my $secn, my $name) = @_;
- return $parsed_sections{$secn}->{$name};
- }
-
- sub get_string_value {
- my $key = shift;
- if ($key =~ /%(.+)%/) {
- $key = $1;
- return get_section_value("Strings", $key);
- } else {
- return $key;
- }
- }
-
- sub copy_file {
- my $file = shift;
-
- $file = trim(del_comment($file));
- my $real_file = get_file($file);
- if (length($real_file) gt 0) {
- $file = lc($real_file);
- copy("$src_dir/$real_file", "$confdir/$driver_name/$file") or
- warn "couldn't copy \"$src_dir/$real_file\" to " .
- "\"$confdir/$driver_name\": $! -\n" .
- "installation may be incomplete\n";
- chmod(0644, "$confdir/$driver_name/$file");
- } else {
- warn "couldn't find \"$file\" in \"$src_dir\"; make sure " .
- "all driver files, including .inf, .sys (and .bin, if any) " .
- "are in \"$src_dir\" -\n" .
- "installation may be incomplete\n";
- }
- }
-
- # for conf files with subvendor and subdevice, create conf files with just
- # vendor and device
- sub create_fuzzy_conf {
- my $driver = shift;
- my $cwd = cwd();
- chdir("$confdir/$driver") or die "couldn't chdir to $confdir/$driver: $!";
- open(LS, "ls -1 . |") or die "couldn't open $confdir/$driver: $!";
- while (my $file = <LS>) {
- chomp($file);
- if ($file =~ /^(.{4}):(.{4}):(.{4}):(.{4})\.([^.]+)\.conf$/) {
- my $fuzzy_file = "$1:$2.$5.conf";
- printf DBG "file: $file, fuzzy file: $fuzzy_file\n";
- if (! -e "$confdir/$driver/$fuzzy_file") {
- symlink("$file", "$fuzzy_file") or
- warn "couldn't link $confdir/$driver/$file " .
- "to $confdir/$driver/$fuzzy_file: $!\n";
- }
- }
- }
- close(LS);
- chdir($cwd) or warn "couldn't chdir to $cwd: $!";
- return 0;
- }
-
- # find a file in a case-insensitive way.
- sub get_file {
- my $file = lc(shift);
- if (opendir(DIR, "$src_dir")) {
- my @allfiles = readdir(DIR);
- foreach my $real_file (@allfiles) {
- if (lc($real_file) eq $file) {
- closedir(DIR);
- return $real_file;
- }
- }
- closedir(DIR);
- } else {
- warn "couldn't open \"$src_dir\": $! - installation may be incomplete\n";
- }
- return "";
- }
-
- sub strip_quotes {
- my $s = shift;
- $s =~ s/"(.*)"/$1/;
- return $s;
- }
-
- sub del_comment {
- my $s = shift;
- $s =~ s/;.*//;
- return $s;
- }
-
- # remove whitsepace at front and end.
- sub trim {
- my $s = shift;
- $s =~ s/^\s*//;
- $s =~ s/\s*$//;
- return $s;
- }
-
- sub valid_copy_file_name {
- my $file = shift;
- printf DBG "file name: %s\n", $file;
- # as of now, copy file name extensions known: .sys, .bin, .out
- return 1 if (lc($file) =~ /^[a-z0-9_]*\.((sys)|(bin)|(out))$/);
- return 0;
- }
-
- sub device_driver_alias {
- my ($devid, $driver) = @_;
- my $done = 0;
-
- $devid = uc($devid);
- if (!($devid =~ /^$re_dev_id:$re_dev_id$/)) {
- printf "'$devid' is not a valid device ID\n";
- return 1;
- }
- open(LS, "ls -1 $confdir/$driver/ |") or
- die "couldn't open $confdir/$driver: $!";
- while (my $f = <LS>) {
- chomp($f);
- if ($f =~ /\.([[:xdigit:]]+)\.conf$/) {
- if (symlink("$f", "$confdir/$driver/$devid.$1.conf")) {
- printf "driver '$driver' is used for '$devid'\n";
- $done = 1;
- last;
- } else {
- warn "couldn't create symlink for \"$f\": $! -\n" .
- "installation may be incomplete\n";
- }
- }
- }
- close(LS);
- if ($done == 0) {
- printf "driver '$driver' is not installed (properly)!\n";
- return 1;
- }
- return 0;
- }
-
- sub generate_module_device_map {
- my $mode = shift;
- my $vendor, my $device, my $subvendor, my $subdevice, my $bustype, my $busid;
-
- my $device_map;
- if (-d "/etc/modprobe.d") {
- $device_map = "/etc/modprobe.d/ndiswrapper";
- } elsif (-d "/etc/modules.d") {
- $device_map = "/etc/modules.d/ndiswrapper";
- } else {
- $device_map = "/etc/ndiswrapper/ndiswrapper";
- }
-
- open(CONF, "| sort >$device_map") or
- die "couldn't create modules alias file $device_map: $!";
- open(LS, "ls -1 $confdir|") or
- die "couldn't open $confdir: $!";
- while (my $driver = <LS>) {
- chomp($driver);
- my $stat = (stat("$confdir/$driver"))[2];
- if (S_ISDIR($stat)) {
- open(LS2, "ls -1 $confdir/$driver/ |") or
- die "couldn't open $confdir/$driver: $!";
- while (my $file = <LS2>) {
- chomp ($file);
- if ($file =~ /.conf$/) {
- if ($file =~ /^(.{4}):(.{4}):(.{4}):(.{4})\.([^.]+)\.conf$/) {
- ($vendor, $device, $subvendor, $subdevice, $busid) =
- (uc($1), uc($2), "0000$3", "0000$4", hex($5));
- } elsif ($file =~ /(.{4}):(.{4})\.([^.]+)\.conf$/) {
- ($vendor, $device, $subvendor, $subdevice, $busid) =
- (uc($1), uc($2), "*", "*", hex($3));
- }
- my $devstring;
- if ($busid eq $WRAP_USB_BUS or $busid eq 0) {
- $devstring = sprintf("usb:v%sp%sd*dc*dsc*dp*ic*isc*ip*",
- $vendor, $device);
- } elsif ($busid eq $WRAP_PCI_BUS) {
- $devstring = sprintf("pci:v0000%sd0000%ssv%ssd%sbc*sc*i*",
- $vendor, $device, $subvendor,
- $subdevice);
- } else {
- warn "wrong bustype ($busid) for " .
- "configuration file $file - ignoring it\n";
- next;
- }
- if ($mode == 0) {
- printf CONF "alias %s ndiswrapper\n", $devstring;
- } else {
- printf CONF "install %s /sbin/modprobe ndiswrapper\n",
- $devstring;
- }
- }
- }
- close(LS2);
- }
- }
- close(LS);
- close(CONF);
-
- printf "module configuration information is stored in $device_map\n";
- return 0;
- }
-
- sub list_drivers {
- my $cards = get_cards();
-
- open(LS, "ls -1 $confdir|") or die "couldn't open $confdir: $!";
- while (my $driver = <LS>) {
- chomp($driver);
- if (-e "$confdir/$driver") {
- printf "%s : %s\n", $driver, install_status($cards, $driver);
- }
- }
- close(LS);
- return 0;
- }
-
- sub add_module_alias {
- my $alias = 0;
-
- open(MODPROBE, "modprobe -c|") or die "couldn't run modprobe: $!";
- while (my $line = <MODPROBE>) {
- if ($line =~ /^alias\s.+\sndiswrapper/) {
- printf "module configuration already contains alias directive\n\n";
- $alias = 1;
- } elsif ($line =~ /^install\s.*ndiswrapper/) {
- warn "module configuration contains directive $line;" .
- "you should delete that";
- } elsif ($line =~ /^post-install\s+ndiswrapper/) {
- warn "module configuration contains directive $line;" .
- "you should delete that";
- }
- }
- close(MODPROBE);
-
- if ($alias) {
- return 0;
- }
-
- printf "adding \"alias wlan0 ndiswrapper\" to $modconf ...\n";
- system("echo \"alias wlan0 ndiswrapper\" >>$modconf") == 0 or
- die "couldn't add module alias: $!";
- if (-x "/sbin/update-modules") {
- system("/sbin/update-modules");
- }
- return 0;
- }
-
- sub get_cards {
- #01:00.0 Class 0300: 1002:4c66 (rev 01)
- # Subsystem: 1043:1732
- my @cards = ();
- if (open(LSPCI, "lspci -vn|")) {
- my $card;
- while (my $line = <LSPCI>) {
- if ($line =~ /^[0-9a-f]+.+\s$re_dev_id:$re_dev_id/) {
- $card = {vendor => uc($1), device => uc($2)};
- printf DBG "card: %s, %s\n", $1, $2;
- } elsif ($line =~ /.+Subsystem:\s$re_dev_id:$re_dev_id/) {
- $card->{subvendor} = uc($1);
- $card->{subdevice} = uc($2);
- printf DBG "sub: %s, %s\n", $1, $2;
- push(@cards, $card);
- }
- }
- close(LSPCI);
- }
-
- if (open(LSUSB, "lsusb |")) {
- my $card;
- while (my $line = <LSUSB>) {
- if ($line =~ /.+: ID\s$re_dev_id:$re_dev_id/) {
- $card = {vendor => uc($1), device => uc($2)};
- push(@cards, $card);
- }
- }
- close(LSUSB);
- }
- return \@cards;
- }
-
- sub install_status {
- my ($cards, $driver) = @_;
-
- if (!$cards or !$driver) {
- return;
- }
-
- my $sys, my $conf, my $inf;
- my $vendor, my $device, my $subvendor, my $subdevice, my $busid, my $ret;
-
- $sys = $conf = $inf = 0;
- open(LS2, "ls -1 $confdir/$driver|") or
- die "couldn't open $confdir/$driver: $!";
- while (my $file = <LS2>) {
- chomp($file);
- if ($file =~ /\.sys$/) {
- $sys = 1;
- } elsif ($file =~ /\.inf$/) {
- $inf = 1;
- } elsif ($file =~ /^$re_sub_dev_conf$/) {
- $busid = hex($5);
- $conf = 1 if ($busid eq $WRAP_PCI_BUS);
- } elsif ($file =~ /^$re_dev_conf$/) {
- $busid = hex($3);
- $conf = 1 if ($busid eq $WRAP_USB_BUS or $busid eq 0 or
- $busid eq $WRAP_PCI_BUS);
- }
- }
- close(LS2);
- printf DBG "status: $sys, $inf, $conf\n";
- if ($sys eq 0 or $inf eq 0 or $conf eq 0) {
- $ret = "invalid driver!";
- return $ret;
- }
- $ret = "driver installed";
- open(LS2, "ls -1 $confdir/$driver|") or
- die "couldn't open $confdir/$driver: $!";
-
- while (my $file = <LS2>) {
- chomp($file);
- next if ($file !~ /\.conf$/);
- $conf = 0;
- if ($file =~ /^$re_sub_dev_conf$/) {
- ($vendor, $device, $subvendor, $subdevice, $busid) =
- (uc($1), uc($2), uc($3), uc($4), hex($5));
- $conf = 1;
- foreach my $card (@{$cards}) {
- if ($card->{vendor} eq $vendor and
- $card->{device} eq $device and
- $card->{subvendor} eq $subvendor and
- $card->{subdevice} eq $subdevice and
- $busid eq $WRAP_PCI_BUS) {
- $ret .= "\n\tdevice ($vendor:$device" .
- ":$subvendor:$subdevice) present";
- $conf = 2;
- last;
- }
- }
- } elsif ($file =~ /^$re_dev_conf/) {
- ($vendor, $device, $subvendor, $subdevice, $busid) =
- (uc($1), uc($2), "\\*", "\\*", hex($3));
- $conf = 1;
- foreach my $card (@{$cards}) {
- if ($card->{vendor} eq $vendor and
- $card->{device} eq $device and
- ($busid eq $WRAP_USB_BUS or $busid eq 0 or
- $busid eq $WRAP_PCI_BUS)) {
- $ret .= "\n\tdevice ($vendor:$device) present";
- $conf = 2;
- last;
- }
- }
- }
- next if ($conf le 1);
- # find if kernel knows of an alternate driver for this device
- my $devstring;
- if ($busid eq $WRAP_USB_BUS or $busid eq 0) {
- $devstring = sprintf("usb:v%sp%sd", $vendor, $device);
- } elsif ($busid eq $WRAP_PCI_BUS) {
- $devstring = sprintf("pci:v0000%sd0000%ssv", $vendor, $device);
- } else {
- next;
- }
- open(MODPROBE, "modprobe -c|") or next;
- while (my $line = <MODPROBE>) {
- my $alt;
- chomp($line);
- next if $line !~ /$devstring/;
- $alt = (split(' ', $line))[-1];
- chomp($alt);
- if (length($alt) gt 0 and $alt ne "ndiswrapper") {
- $ret .= " (alternate driver: $alt)";
- last;
- }
- }
- close(MODPROBE);
- }
- close(LS2);
- printf DBG "driver: $driver, $ret\n";
- return $ret;
- }
-
- ## Local Variables: ##
- ## cperl-indent-level: 4 ##
- ## End: ##
-