home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2007 September / PCWSEP07.iso / Software / Linux / Linux Mint 3.0 Light / LinuxMint-3.0-Light.iso / casper / filesystem.squashfs / usr / sbin / ndiswrapper-1.8 < prev    next >
Encoding:
Text File  |  2006-06-22  |  22.1 KB  |  1,002 lines

  1. #!/usr/bin/perl
  2.  
  3. #/*
  4. #*  Copyright (C) 2005 Pontus Fuchs, Giridhar Pemmasani
  5. #*
  6. #*
  7. #*  This program is free software; you can redistribute it and/or modify
  8. #*  it under the terms of the GNU General Public License as published by
  9. #*  the Free Software Foundation; either version 2 of the License, or
  10. #*  (at your option) any later version.
  11. #*
  12. #*  This program is distributed in the hope that it will be useful,
  13. #*  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. #*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. #*  GNU General Public License for more details.
  16. #*
  17. #*/
  18.  
  19.  
  20. #use strict;
  21. use Fcntl ':mode';
  22. use File::Basename;
  23. use File::Copy;
  24. use File::Path;
  25.  
  26. my $WRAP_PCI_BUS = 5;
  27. my $WRAP_PCMCIA_BUS = 8;
  28. my $WRAP_USB_BUS = 15;
  29.  
  30. my @sections;
  31. my %strings;
  32. my %version;
  33. my $driver_name;
  34. my $confdir = "/etc/ndiswrapper";
  35. my $instdir;
  36. my %fuzzlist;
  37. my %buslist;
  38. # bustype is either PCI or USB, whereas BusType used in INF file can
  39. # be different
  40. my $bus;
  41. my $classguid;
  42.  
  43. #Blacklist of files not to install.
  44. my @copy_blacklist;
  45.  
  46. #Fixup list for parameters. 
  47. my %param_fixlist = ("EnableRadio|0" => "EnableRadio|1",
  48.              "IBSSGMode|0" => "IBSSGMode|2",
  49.                      "PrivacyMode|0" => "PrivacyMode|2",
  50.              "AdhocGMode|1" => "AdhocGMode|0");
  51.  
  52. if(@ARGV < 1) {
  53.     usage();
  54.     exit();
  55. }
  56.  
  57. my $modconf;
  58. if (`uname -r` =~ /(\d+)\.(\d+)\.(\d+)/) {
  59.     if ($2 > 4) {
  60.     if (-d "/etc/modprobe.d") {
  61.         $modconf = "/etc/modprobe.d/ndiswrapper" 
  62.     } else {
  63.         $modconf = "/etc/modprobe.conf" 
  64.     }
  65.     } else {
  66.     if (-d "/etc/modutils") {
  67.         $modconf = "/etc/modutils/ndiswrapper";
  68.     } else {
  69.         $modconf = "/etc/modules.conf";
  70.     }
  71.     }
  72. }
  73.  
  74. my $res;
  75. if($ARGV[0] eq "-i" and @ARGV == 2) {
  76.     $res = install($ARGV[1]);
  77. } elsif($ARGV[0] eq "-d" and @ARGV == 3) {
  78.     $res = devid_driver($ARGV[1], $ARGV[2]);
  79. } elsif($ARGV[0] eq "-e" and @ARGV == 2) {
  80.     $res = remove($ARGV[1]);
  81. } elsif($ARGV[0] eq "-l" and @ARGV == 1) {
  82.     $res = list();
  83. } elsif($ARGV[0] eq "-m" and @ARGV == 1) {
  84.     $res = modalias();
  85. } elsif($ARGV[0] eq "-v" and @ARGV == 1) {
  86.     printf "utils "; system("/sbin/loadndisdriver -v");
  87.     printf "driver ";
  88.     system("modinfo ndiswrapper | grep -E '^version|^vermagic'");
  89.     $res = 0;
  90. } elsif($ARGV[0] eq "-da" and @ARGV == 1) {
  91.     $res = genmoddevconf(0);
  92. } elsif($ARGV[0] eq "-di" and @ARGV == 1) {
  93.     $res = genmoddevconf(1);
  94. } else {
  95.     usage();
  96.     exit();
  97. }
  98.  
  99. exit $res;
  100.  
  101. sub usage {
  102.     print "Usage: ndiswrapper OPTION\n\n" .
  103.       "Manage ndis drivers for ndiswrapper.\n"  .
  104.     "-i inffile        Install driver described by 'inffile'\n" .
  105.     "-d devid driver   Use installed 'driver' for 'devid'\n" .
  106.     "-e driver         Remove 'driver'\n" .
  107.     "-l                List installed drivers\n" .
  108.     "-m                Write configuration for modprobe\n" .
  109.     "-da               Write module alias configuration for all devices\n" .
  110.     "-di               Write module install configuration for all devices\n" .
  111.     "-v                Report version information\n" .
  112.     "\n\nwhere 'devid' is either PCIID or USBID of the form XXXX:XXXX\n";
  113. }
  114.  
  115. sub install {
  116.     my $inf = shift;
  117.     $driver_name = lc($inf);
  118.     $driver_name =~ s/\.inf//;
  119.     $driver_name = basename($driver_name);
  120.     $instdir = dirname($inf);
  121.     chomp($instdir);
  122.     chomp($driver_name);
  123.  
  124.     if (isInstalled($driver_name)) {
  125.     print "$driver_name is already installed. Use -e to remove it\n";
  126.     return -1;
  127.     }
  128.     if (opendir(DH, $confdir)) {
  129.     closedir(DH);
  130.     } else {
  131.     mkdir($confdir);
  132.     }
  133.  
  134.     print "Installing $driver_name\n";
  135.     if (!mkdir("$confdir/$driver_name")) {
  136.     print "Unable to create directory $confdir/$driver_name." .
  137.       "Make sure you are running as root\n";
  138.     return -1;
  139.     }
  140.  
  141.     loadinf($inf);
  142.     initStrings();
  143.     parseVersion();
  144.     copy("$inf", "$confdir/$driver_name/$driver_name.inf") or
  145.       die "couldn't copy $inf";
  146.     processPCIFuzz();
  147. }
  148.  
  149. sub isInstalled {
  150.     my $installed;
  151.     my $name = shift;
  152.     my $stat = (stat("$confdir"))[2];
  153.     if (!S_ISDIR($stat)) {
  154.     return 0;
  155.     }
  156.     open(LS, "ls -1 $confdir|");
  157.     while(my $f = <LS>) {
  158.     chomp($f);
  159.     $stat = (stat("$confdir/$f"))[2];
  160.     if (S_ISDIR($stat) and $name eq $f) {
  161.         $installed = 1;
  162.     }
  163.     }
  164.     close(LS);    
  165.     return $installed;
  166. }
  167.  
  168. sub remove {
  169.     my $name = shift;
  170.     if (!isInstalled($name)) {
  171.     print "Driver $name is not installed." . 
  172.       "Use -l to list installed drivers\n";
  173.     return;
  174.     }
  175.     rmtree("$confdir/$name", 0, 1);
  176. }
  177.  
  178. sub devid_driver {
  179.     my ($devid, $driver) = @_;
  180.     my $done = 0;
  181.  
  182.     $devid = uc($devid);
  183.     if (!($devid =~ /[0-9A-Z]{4}:[0-9A-Z]{4}/)) {
  184.     print "'$devid' is not a valid device ID\n";
  185.     return;
  186.     }
  187.     open(LS, "ls -1 $confdir/$driver/ |");
  188.     while (my $f = <LS>) {
  189.     chomp($f);
  190.     if ($f =~ /\.([0-9A-F]+).conf$/) {
  191.         symlink("$f", "$confdir/$driver/$devid.$1.conf");
  192.         print "Driver '$driver' is used for '$devid'\n";
  193.         $done = 1;
  194.         last;
  195.     }
  196.     }
  197.     close(LS);    
  198.     if ($done == 0) {
  199.     print "Driver '$driver' is not installed properly!\n";
  200.     }
  201.     return;
  202. }
  203.  
  204. sub genmoddevconf {
  205.     my $mode = shift;
  206.     my $vendor, $device, $subvendor, $subdevice, $bustype, $busid;
  207.     my $line;
  208.  
  209.     my $moddevconf;
  210.     if (-d "/etc/modprobe.d") {
  211.     $moddevconf = "/etc/modprobe.d/ndiswrapper";
  212.     } elsif (-d "/etc/modules.d") {
  213.     $moddevconf = "/etc/modules.d/ndiswrapper";
  214.     } else {
  215.     $moddevconf = "/etc/ndiswrapper/ndiswrapper";
  216.     }
  217.  
  218.     if (!open(CONF, "| sort >$moddevconf")) {
  219.     print "Unable to create modules alias file $moddevconf\n";
  220.     return -1;
  221.     }
  222.     open(LS, "ls -1 $confdir|");
  223.     while (my $driver = <LS>) {
  224.     chomp($driver);
  225.     my $stat = (stat("$confdir/$driver"))[2];
  226.     if (S_ISDIR($stat)) {
  227.         open(LS2, "ls -1 $confdir/$driver/ |");
  228.         while (my $file = <LS2>) {
  229.         chomp ($file);
  230.         my $line = $file;
  231.         if ($file =~ s/.conf//) {
  232.             if ($file =~ /(.{4}):(.{4}):(.{4}):(.{4})\.([05F])/) {
  233.             $vendor = $1;
  234.             $device = $2;
  235.             $subvendor = "0000$3";
  236.             $subdevice = "0000$4";
  237.             $busid = "$5";
  238.             } elsif($file =~ /(.{4}):(.{4})\.([05F])/) {
  239.             $vendor = $1;
  240.             $device = $2;
  241.             $subvendor = "*";
  242.             $subdevice = "*";
  243.             $busid = "$3";
  244.             }
  245.             my $devstring;
  246.             if ($busid eq "0" or $busid eq "F") {
  247.             $devstring = sprintf("usb:v%sp%sd*dc*dsc*dp*ic*isc*ip*",
  248.                          $vendor, $device);
  249.             } elsif ($busid eq "5") {
  250.             $devstring = sprintf("pci:v0000%sd0000%ssv%ssd%sbc*sc*i*",
  251.                          $vendor, $device, $subvendor,
  252.                          $subdevice);
  253.             } else {
  254.             print stderr "wrong bustype ($busid) for " .
  255.               "configuration file $line - ignoring it\n";
  256.             next;
  257.             }
  258.             if ($mode == 0) {
  259.             printf CONF "alias %s ndiswrapper\n", $devstring;
  260.             } else {
  261.             printf CONF "install %s /sbin/modprobe ndiswrapper\n",
  262.               $devstring;
  263.             }
  264.         }
  265.         }
  266.         close(LS2);
  267.     }
  268.     }
  269.  
  270.     close(CONF);
  271.     close(LS);
  272.  
  273.     print "Module configuration information is stored in $moddevconf\n";
  274.     return 0;
  275. }
  276.  
  277. sub list {
  278.     my $s;
  279.     my $cards = getPresentCards();
  280.  
  281.     if (!$cards) {
  282.     print "WARNING: Cannot locate lspci and lsusb." .
  283.       "Unable to see if hardware is present.\n";
  284.     }
  285.  
  286.     my $stat = (stat("$confdir"))[2];
  287.     if (!S_ISDIR($stat)) {
  288.     print "No drivers installed\n$s";
  289.     return;
  290.     }
  291.     open(LS, "ls -1 $confdir|");
  292.     while (my $f = <LS>) {
  293.     chomp($f);
  294.     my $stat = (stat("$confdir/$f"))[2];
  295.     if (S_ISDIR($stat)) {
  296.         $s .= "$f\t".installStatus($cards, $f)."\n";
  297.     }
  298.     }
  299.     if ($s) {
  300.     print "Installed drivers:\n$s";
  301.     } else {
  302.     print "No drivers installed\n$s";
  303.     }
  304.     close(LS);    
  305. }
  306.  
  307. sub modalias {
  308.     my $alias = 0;
  309.  
  310.     open(MODPROBE, "modprobe -c|");
  311.     while (my $line = <MODPROBE>) {
  312.     if ($line =~ /^alias\s.+\sndiswrapper/) {
  313.         print "modprobe config already contains alias directive\n\n";
  314.         $alias = 1;
  315.     } elsif ($line =~ /^install\s.*ndiswrapper/) {
  316.         printf stderr "module configuration contains directive $line;" .
  317.           "you should delete that";
  318.     } elsif ($line =~ /^post-install\s+ndiswrapper/) {
  319.         printf stderr "module configuration contains directive $line;" .
  320.           "you should delete that";
  321.     }
  322.     }
  323.     close(MODPROBE);
  324.  
  325.     if ($alias) {
  326.     return;
  327.     }
  328.  
  329.     print "Adding \"alias wlan0 ndiswrapper\" to $modconf\n";
  330.     system("echo \"alias wlan0 ndiswrapper\" >>$modconf");
  331.     if (-x "/sbin/update-modules") {
  332.     system("/sbin/update-modules");
  333.     }
  334. }
  335.  
  336. sub getPresentCards {
  337. #01:00.0 Class 0300: 1002:4c66 (rev 01)
  338. #        Subsystem: 1043:1732
  339.     my @cards;
  340.     my @lspci = ("/sbin/lspci", "/usr/sbin/lspci", "lspci");
  341.     for (my $i = 0; $i < @lspci; $i++) {
  342.     if (open(LSPCI, "$lspci[$i] -vn|")) {
  343.         my $card;
  344.         while(my $line = <LSPCI>) {
  345.         if($line =~ /^[0-9]+.*:\s(.{4}):(.{4}).*/) {
  346.             my %c;
  347.             $card = \%c;
  348.             $card->{vendor} = $1;
  349.             $card->{device} = $2;
  350.         }
  351.         if ($line =~ /.+Subsystem:\s*(.{4}):(.{4}).*/) {
  352.             $card->{subvendor} = $1;
  353.             $card->{subdevice} = $2;
  354.             push(@cards, $card);
  355.         }
  356.         }
  357.         last;
  358.     }
  359.     }
  360.  
  361.     my @lsusb = ("/sbin/lsusb", "/usr/sbin/lsusb", "lsusb");
  362.     for(my $i = 0; $i < @lsusb; $i++) {
  363.     if (open(LSUSB, "$lsusb[$i] |")) {
  364.         my $card;
  365.         while(my $line = <LSUSB>) {
  366.         if($line =~ /.*: ID\s(.{4}):(.{4}).*/) {
  367.             my %c;
  368.             $card = \%c;
  369.             $card->{vendor} = $1;
  370.             $card->{device} = $2;
  371.  
  372.             push(@cards, $card);
  373.         }
  374.         }
  375.         last;
  376.     }
  377.     }
  378.     return \@cards;
  379. }
  380.  
  381. sub installStatus {
  382.     my ($cards, $driver) = @_; 
  383.  
  384.     my $sys = 0;
  385.     my $conf = 0;
  386.     my $inf = 0;
  387.  
  388.     if (!$cards) {
  389.     return;
  390.     }
  391.  
  392.     open(LS2, "ls -1 $confdir/$driver|");
  393.  
  394.     while (my $device = <LS2>)     {
  395.     chomp($device);
  396.     my $d = $device;
  397.  
  398.     $sys = 1 if $d =~ /\.sys$/;
  399.     $inf = 1 if $d =~ /\.inf$/;
  400.     $conf = 1 if $conf eq 0 and $d =~ /\.conf$/;
  401.     $d =~ s/.conf//;
  402.     if ($d =~ /(.{4}):(.{4}):(.{4}):(.{4})/) {
  403.         for (my $i = 0; $$cards[$i]; $i++) {
  404.         if ($$cards[$i]->{vendor} == $1 and
  405.             $$cards[$i]->{device} == $2 and
  406.             $$cards[$i]->{subvendor} == $3 and
  407.             $$cards[$i]->{subdevice} == $4) {
  408.             $conf = 3;
  409.             last;
  410.         }
  411.         }
  412.     } elsif($d =~ /(.{4}):(.{4})/) {
  413.         for (my $i = 0; $$cards[$i]; $i++) {
  414.         if ($$cards[$i]->{vendor} == $1 and
  415.             $$cards[$i]->{device} == $2) {
  416.             my $stat = (lstat("$confdir/$driver/$device"))[2];
  417.             if (S_ISLNK($stat)) {
  418.             $conf = 2;
  419.             } else {
  420.             $conf = 3;
  421.             }
  422.             last;
  423.         }
  424.         }
  425.     }
  426.     }
  427.     close(LS2);    
  428.  
  429.     my $ret;
  430.     if ($sys eq 0 || $inf eq 0 || $conf eq 0) {
  431.     $ret = "invalid driver!";
  432.     } else {
  433.     $ret = "\tdriver installed " if $conf eq 1;
  434.     $ret = "\tdriver installed, hardware present " if $conf eq 2;
  435.     $ret = "\tdriver installed, hardware present " if $conf eq 3;
  436.     }
  437.     return $ret;
  438. }
  439.  
  440. #
  441. # Create symlink for PCI general device if not existing
  442. #
  443. sub processPCIFuzz {
  444.     my @devs = keys(%fuzzlist);
  445.     for (my $i = 0; $i < @devs; $i++) {
  446.     my $dev = $devs[$i];
  447.     if ($dev ne $fuzzlist{$dev}) {
  448.         my $bt = $buslist{$dev};
  449.         my $src = "$confdir/$driver_name/$fuzzlist{$dev}.$bt.conf";
  450.         my $dst = "$confdir/$driver_name/$dev.$bt.conf";
  451.         symlink("$src", "$dst");
  452.     }
  453.     }
  454. }
  455.  
  456. #
  457. # Collect a list of supported PCI-Id's so we can add fuzzy entries if needed.
  458. #
  459. sub addPCIFuzzEntry {
  460.     my ($vendor, $device, $subvendor, $subdevice, $bus) = @_;
  461.  
  462.     my $s = "$vendor:$device";
  463.  
  464.     if (!$subvendor or !$fuzzlist{$s}) {
  465.     my $s2 = $s;
  466.     if ($subvendor) {
  467.         $s2 .= ":$subvendor:$subdevice";
  468.     }
  469.     $fuzzlist{$s} = $s2;
  470.     $buslist{$s} = $bus;
  471.     }
  472. }
  473.  
  474. sub parseVersion {
  475.     my $s = getSection("version");
  476.     if (!$s) {
  477.     return;
  478.     }
  479.     my @lines = split("\n", $s->{data});
  480.  
  481.     for (my $i = 0; $i < @lines; $i++) {
  482.     (my $key, my $val) = getKeyVal($lines[$i]);
  483.     if ($key eq "Provider") {
  484.         $val =~ s/"(.+)"/$1/; 
  485.         $version{$key} = $val;
  486.     }
  487.     if ($key eq "DriverVer") {
  488.         $val =~ s/"(.+)"/$1/; 
  489.         $version{$key} = $val;
  490.     }
  491.     if ($key eq "ClassGUID") {
  492.         $val =~ s/\{(.+)\}/$1/; 
  493.         $classguid = lc($val);
  494.     }
  495.     }
  496.     parseMfr();
  497. }
  498.  
  499. #
  500. # Parse the [Manufacturer] section.
  501. #
  502. sub parseMfr {
  503.     #Examples:
  504.     #Vendor
  505.     #Vendor,ME,NT,NT.5.1
  506.     #Vendor.NTx86
  507.  
  508.     my $manu = getSection("manufacturer");
  509.     if (!$manu) {
  510.     return -1;
  511.     }
  512.  
  513.     my @lines = split("\n", $manu->{data});
  514.     for (my $i = 0; $i < @lines; $i++) {
  515.     my $line = remComment($lines[$i]);
  516.     (my $key, my $val) = getKeyVal($line, "=");
  517.  
  518.     if ($key eq $version{"Provider"}) {
  519.         $strings{$key} = trim($val);
  520.     }
  521.  
  522.     if ($val) {
  523.         my $section;
  524.         my @flavours = map { stripquotes(trim($_)) } split(",", $val);
  525.         my $flavour = "";
  526.         if(@flavours == 1) {
  527.         #Vendor
  528.         $section = $flavours[0];                
  529.         } else {
  530.         #Vendor,flavour1, flavour2 etc;
  531.         for (my $i = 1; $i < @flavours; $i++) {
  532.             my $flav = $flavours[$i];
  533.             $flav =~ s/\s*(\S+)\s*/$1/;
  534.             if (uc($flav) eq "NT.5.1") {
  535.             #This is the best (XP)
  536.             $section = $flavours[0] . "." . $flav;
  537.             $flavour = $flav;
  538.             } elsif (substr(uc($flav),0,2) eq "NT" and
  539.                  $section eq "") {
  540.             #This is the second best (win2k)
  541.             $section = $flavours[0] . "." . $flav;
  542.             $flavour = $flav;
  543.             }
  544.         }
  545.         }
  546.         my $res = parseVendor($flavour, $section);
  547.         if ($res) {
  548.         return $res;
  549.         }
  550.     }
  551.     }
  552. }
  553.  
  554. #
  555. # Parse a vendor section. This section contains the device-ids.
  556. # Each poiting to a section with config info.
  557. #    
  558. sub parseVendor {
  559.     my ($flavour, $vendor_name) = @_;
  560.     my $vend = getSection($vendor_name);
  561.  
  562.     if (!$vend) {
  563.     print "no vendor\n";
  564.     return -1;
  565.     }
  566.  
  567.     my @lines = split("\n", $vend->{data});
  568.     for (my $i = 0; $i < @lines; $i++) {
  569.     my $line = remComment($lines[$i]);
  570.     (my $name, my $val) = getKeyVal($line, "=");
  571.  
  572.     if ($val) {
  573.         my $section;
  574.         my $id;
  575.         ($section, $id) = split(",", $val);
  576.         $section = trim($section);
  577.         $id = substStr(trim($id));
  578.         my $bt, $vendor, $device, $subvendor, $subdevice;
  579.         ($bus, $vendor, $device, $subvendor, $subdevice) = parseID($id);
  580.         if ($vendor) {
  581.         parseDevice($flavour, $section, $vendor, $device,
  582.                 $subvendor, $subdevice);
  583.         }
  584.     }
  585.     }
  586. }
  587.  
  588. #
  589. # This section contains pointers to registry sections and copyfiles sections. 
  590. #
  591. sub parseDevice {
  592.     my ($flavour, $device_sect, $device, $vendor, $subvendor, $subdevice) = @_;
  593.     my $dev;
  594.  
  595.     # for RNDIS INF file (for USR5420), vendor section names device
  596.     # section as RNDIS.NT.5.1, but copyfiles section is RNDIS.NT, so
  597.     # first strip flavour from device_sect and then look for matching
  598.     # section
  599.  
  600.     if ($device_sect eq "RNDIS.NT.5.1") {
  601.     $dev = getSection("RNDIS.NT");
  602.     }
  603.     if (!$dev) {
  604.     $dev = getSection("$device_sect.$flavour");
  605.     }
  606.     if (!$dev) {
  607.     $dev = getSection("$device_sect.NT");
  608.     }
  609.     if (!$dev) {
  610.     $dev = getSection("$device_sect.NTx86");
  611.     }
  612.  
  613.     if (!$dev) {
  614.     $dev = getSection("$device_sect");
  615.     }
  616.     if (!$dev) {
  617.     print "no dev $device_sect $flavour\n";
  618.     return -1;
  619.     }
  620.     # print "$device:$vendor:$subvendor:$subdevice  $flavour\n";
  621.     my @copy_files;
  622.     my $addreg;
  623.     my @lines = split("\n", $dev->{data});
  624.  
  625.     for (my $i = 0; $i < @lines; $i++) {
  626.     my $line = $lines[$i];
  627.     $line =~ s/^;\s*//;
  628.     $line = trim(remComment($line));
  629.     (my $key, my $val) = getKeyVal($line, "=");
  630.     if ($key) {
  631.         if (lc($key) eq "addreg") {
  632.         $addreg = $val;
  633.         } elsif (lc($key) eq "copyfiles") {
  634.         push @copy_files, $val;
  635.         } elsif ($key eq "BusType") {
  636.         $strings{$key} = $val;
  637.         }
  638.     }
  639.     }        
  640.  
  641.     my $filename = "$device:$vendor";
  642.     if ($subvendor) {
  643.     $filename .= ":$subvendor:$subdevice"
  644.     }
  645.  
  646.     my $bt = sprintf("%X", $bus);
  647.     $filename .= ".$bt.conf";
  648.     if ($bus == $WRAP_PCI_BUS || $bus == $WRAP_PCMCIA_BUS) {
  649.     addPCIFuzzEntry($device, $vendor, $subvendor, $subdevice, $bt);
  650.     }
  651.  
  652.     if (!open(CONF, ">$confdir/$driver_name/$filename")) {
  653.     print "Unable to create file $filename";
  654.     return -1;
  655.     }
  656.  
  657.     my $ver=$version{"DriverVer"};
  658.     my $provider=$version{"Provider"};
  659.     my $providerstring = trim(stripquotes(substStr(trim($provider))));
  660.  
  661.     printf CONF "NdisVersion|0x50001\n";
  662.     printf CONF "Environment|1\n";
  663.     if ($strings{"BusType"} ne "") {
  664.     printf CONF "BusType|$strings{\"BusType\"}\n";
  665.     }
  666.     printf CONF "class_guid|$classguid\n";
  667.     printf CONF "mac_address|XX:XX:XX:XX:XX:XX\n";
  668.     printf CONF "driver_version|$providerstring,$ver\n";
  669.     printf CONF "\n";
  670.     close(CONF);
  671.  
  672.     if (!open(CONF, "|sort|uniq >>$confdir/$driver_name/$filename")) {
  673.     print "Unable to create file $filename";
  674.     return -1;
  675.     }
  676.  
  677.     my @addregs = split(",", $addreg);
  678.     for (my $i = 0; $i < @addregs; $i++) {
  679.     my $reg = trim($addregs[$i]);
  680.     addReg($reg);
  681.     }
  682.     for (my $i = 0; $i < @copy_files; $i++) {
  683.     my @copy_sec = split(",", $copy_files[$i]);
  684.     for (my $j = 0; $j < @copy_sec; $j++) {
  685.         my $file = trim($copy_sec[$j]);
  686.         copyfiles($file);
  687.     }
  688.     }
  689.     close(CONF);
  690. }
  691.  
  692. #
  693. # Process a copyfiles section.
  694. #
  695. sub copyfiles {
  696.     my $copy_name = shift;
  697.     my $copy;
  698.  
  699.     if ($copy_name =~ /^\@/) {
  700.     $copy_name =~ s/^\@//;
  701.     return copy_file($copy_name);
  702.     }
  703.  
  704.     $copy = getSection($copy_name);
  705.     if (!$copy) {
  706.     printf "Parse error in inf. Unable to find section $copy_name\n";
  707.     return -1;
  708.     }
  709.  
  710.     my @lines = split("\n", $copy->{data});
  711.  
  712.     for (my $i = 0; $i < @lines; $i++) {
  713.     my $line = $lines[$i];
  714.     $line = trim($line);
  715.  
  716.     last if ($line =~ /^\[/);
  717.     my @files = split(",", $line);
  718.     for (my $j = 0; $j < @files; $j++) {
  719.         my $file = $files[$j];
  720.         $file = trim($file);
  721.         if ($file and length($file) > 0) {
  722.         copy_file($file);
  723.         }
  724.     }
  725.     }
  726.     return 0;
  727. }
  728.  
  729. sub copy_file {
  730.     my $file = shift;
  731.     $file =~ s/^;//;
  732.     $file = trim(remComment($file));
  733.     $file =~ s/,+.*//;
  734.     $file = trim($file);
  735.     my $nocopy = 0;
  736.     for (my $k = 0; $k < @copy_blacklist; $k++) {
  737.     if ($copy_blacklist[$k] eq lc($file)) {
  738.         $nocopy = 1;
  739.     }
  740.     }
  741.     my $dir = finddir($file);
  742.     if ($dir) {
  743.     $dir = findfile("", $dir);
  744.     }
  745.  
  746.     my $realname = findfile($dir, $file);
  747.  
  748.     if ($realname) {
  749.     my $newname = lc($realname);
  750.     if ($dir) {
  751.         $realname = "$dir/$realname";
  752.     }
  753.     if (!$nocopy) {
  754.         copy("$instdir/$realname", "$confdir/$driver_name/$newname");
  755.         chmod(0644, "$confdir/$driver_name/$newname");
  756.     }
  757.     }
  758. }
  759.  
  760. sub finddir {
  761.     my $filename = shift;
  762.     my $sourcedisksfiles = getSection("sourcedisksfiles");
  763.     if (!$sourcedisksfiles) {
  764.     return "";
  765.     }
  766.     my @lines = split("\n", $sourcedisksfiles->{data});
  767.     for (my $i = 0; $i < @lines; $i++) {
  768.     my $line = trim(remComment($lines[$i]));
  769.     $line =~ /(.+)=.+,+(.*)/;
  770.     my $file = trim($1);
  771.     my $dir = trim($2);
  772.     if ($file and $dir and lc($filename) eq lc($file)) {
  773.         return $dir;
  774.     }
  775.     }
  776.     return "";
  777. }
  778.  
  779. #
  780. # Find a file in a case-insensitive way.
  781. #
  782. sub findfile {
  783.     my ($dir, $file) = @_;
  784.  
  785.     if (!opendir(DIR, "$instdir/$dir")) {
  786.     print "Unable to open $instdir\n";
  787.     return "";
  788.     }
  789.     my @allfiles = readdir(DIR);
  790.     for (my $i = 0; $i < @allfiles; $i++) {
  791.     if (lc($allfiles[$i]) eq lc($file)) {
  792.         closedir(DIR);    
  793.         return $allfiles[$i]; 
  794.     }
  795.     }
  796.     closedir(DIR);    
  797.     return "";
  798. }
  799.  
  800. #
  801. # This section contains pointers to the section with the parameters to be
  802. # added to the registry.
  803. #
  804. sub addReg {
  805.     my $reg_name = shift;
  806.     my $reg = getSection($reg_name);
  807.     if (!$reg) {
  808.     printf "Parse error in inf. Unable to find section $reg_name\n";
  809.     return -1;
  810.     }
  811.  
  812.     my $param;
  813.     my $type;
  814.     my $val;
  815.     my $found;
  816.     my $gotParam = 0;
  817.     my @lines = split("\n", $reg->{data});
  818.     for (my $i = 0; $i < @lines; $i++) {
  819.     my $line = trim(remComment($lines[$i]));
  820.     if ($line) {
  821.         $line =~ /([^,]*),([^,]*),([^,]*),([^,]*),(.*)/; 
  822.         my $hkr = trim($1);
  823.         my $p1 = stripquotes(substStr(trim($2)));
  824.         my $p2 = stripquotes(substStr(trim($3)));
  825.         my $p3 = stripquotes(substStr(trim($4)));
  826.         my $p4 = stripquotes(substStr(trim($5)));
  827.  
  828.         if ($p1) {
  829.         if($p1 =~ /ndi\\params\\(.+)/i) {
  830.             $1 =~ /(.+)\\.*/;
  831.             if ($1 ne $param) {
  832.             $found = 0;
  833.             $param = $1;
  834.             $type = "";
  835.             $val = "";
  836.             }
  837.             if (lc($p2) eq "type") {
  838.             $found++;
  839.             $type = $p4;
  840.             } elsif (lc($p2) eq "default") {
  841.             $found++;
  842.             $val = $p4;
  843.             }
  844.  
  845.             if ($found == 2) {
  846.             $gotParam = 1;
  847.             }
  848.         }
  849.         } else {
  850.         $param = $p2;
  851.         $val = $p4;
  852.         $gotParam = 1;
  853.         }
  854.  
  855.         if ($gotParam and $param ne "" and $param ne "BusType") {
  856.         my $s = "$param|$val";
  857.         if ($param_fixlist{"$s"}) {
  858.             my $sOld = $s;
  859.             $s = $param_fixlist{"$s"};
  860.             print "Forcing parameter $sOld to $s\n"; 
  861.         }
  862.         print CONF "$s\n";
  863.         $param = "";
  864.         $gotParam = 0;
  865.         }
  866.     }
  867.     }
  868. }
  869.  
  870. sub substStr {
  871.     my $s = shift;
  872.     if ($s =~ /^\%(.+)$\%/) {
  873.     $s = getString($1);
  874.     }
  875.     return $s;
  876. }
  877.  
  878. #
  879. # Parse a device-id line.
  880. #
  881. sub parseID {
  882.     my $s = uc(shift);
  883.     if ($s =~ /PCI\\VEN_(\w+)&DEV_(\w+)&SUBSYS_(\w{4})(\S{4})/) {
  884.     return ($WRAP_PCI_BUS, $1, $2, $4, $3);
  885.     } elsif ($s =~ /PCI\\VEN_(\w+)&DEV_(\w+)/) {
  886.     return ($WRAP_PCI_BUS, $1, $2);
  887.     } elsif ($s =~ /USB\\VID_(\w+)&PID_(\w+)/) {
  888.     return ($WRAP_USB_BUS, $1, $2);
  889.     }
  890. }
  891.  
  892. #
  893. # remove whitsepace at front and end.
  894. #
  895. sub trim {
  896.     my $s = shift;
  897.     $s =~ s/^\s*//;
  898.     $s =~ s/\s*$//;
  899.     return $s;
  900. }
  901.  
  902. sub stripquotes {
  903.     my $s = shift;
  904.     $s =~ s/"(.*)"/$1/;
  905.     return $s;
  906. }
  907.  
  908. sub getKeyVal {
  909.     my $line = shift;
  910.  
  911.     $line = remComment($line);
  912.     (my $key, my $val) = split("=", $line);
  913.     if ($line =~ /(.+)=(.+)/) {
  914.     return (trim($1), trim($2));
  915.     }
  916. }
  917.  
  918. sub remComment {
  919.     my $s = shift;
  920.     $s=~ s/([^;]*);.*/$1/;
  921.     return $s;
  922. }
  923.  
  924. #
  925. # Initialize the string symbol table
  926. #
  927. sub initStrings {
  928.     my $s = getSection("strings");
  929.     if (!$s) {
  930.     return;
  931.     }
  932.     my @lines = split("\n", $s->{data});
  933.  
  934.     for (my $i = 0; $i < @lines; $i++) {
  935.     (my $key, my $val) = getKeyVal($lines[$i]);
  936.     if ($key) {
  937.         $val =~ s/"(.+)"/$1/; 
  938.         $strings{$key} = $val;
  939.     }
  940.     }
  941. }
  942.  
  943. #
  944. # fetch a string from the symbol table
  945. #
  946. sub getString {
  947.     my $s = shift;
  948.     return $strings{$s};
  949. }
  950.  
  951. #
  952. # Loacate a section.
  953. #
  954. sub getSection {
  955.     my $needle = shift;
  956.  
  957.     for (my $i = 0; $i < @sections;  $i++) {
  958.     if ( lc($sections[$i]->{name}) eq lc($needle)) {
  959.         return $sections[$i];
  960.     }
  961.     }
  962.     return 0;
  963. }
  964.  
  965. #
  966. # Load inf and split into different sections.
  967. #
  968. sub loadinf {
  969.     my $filename = shift;
  970.     my %def_section;
  971.     my $section = \%def_section;
  972.  
  973.     if (!open(INF, $filename)) {
  974.     return -1;
  975.     }
  976.  
  977.     my $i = 0;
  978.     $section->{name} = "none";
  979.     while (my $s = <INF>) {
  980.     #Convert from unicode
  981.     $s =~ s/\xff\xfe//;
  982.     $s =~ s/\0//g;
  983.  
  984.     $s =~ s/\s*$//;    #Remove trailing whitespace and \r
  985.     $s .= "\n";
  986.     if ($s =~ /^\[(.+)\]/) {
  987.         $sections[$i++] = $section;        
  988.         my %new_section;
  989.         $section = \%new_section;
  990.         $section->{name} = $1;
  991.     } else {
  992.         $section->{data} .= $s;
  993.     }
  994.     }
  995.     $sections[$i++] = $section;  
  996.     close(INF);
  997. }
  998.  
  999. ## Local Variables: ##
  1000. ## cperl-indent-level: 4 ##
  1001. ## End: ##
  1002.