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