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.1 < prev    next >
Encoding:
Text File  |  2005-03-04  |  20.1 KB  |  1,187 lines

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