#! /usr/bin/perl
# lst2xml: Transform old (pci.lst) Discover data to new XML-based format
# AUTHORS: Eric Gillespie <epg@progeny.com>
# John R. Daily <jdaily@progeny.com>
# Josh Bressers <bress@progeny.com>
#
# Copyright 2002 Progeny Linux Systems, Inc.
# Copyright 2002 Hewlett-Packard Company
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
# $Progeny$
use strict;
use warnings;
my %CLASSES = (
'isdn'=>'isdn',
'bridge'=>'bridge',
'ethernet'=>'network',
'unknown'=>'unknown',
'video'=>'video',
'ide'=>'ide',
'scsi'=>'scsi',
'usb'=>'usb',
'sound'=>'sound',
'modem'=>'modem',
'tvcard'=>'multimedia',
'joystick'=>'gameport',
'scanner'=>'scanner',
'printer'=>'printer',
'webcam'=>'webcam',
'floppy'=>'floppy',
'mouse'=>0 # We don't care about this in Discover
);
my %PCI_CLASSES = (
'isdn'=>'0204',
'bridge'=>'0600',
'network'=>'0200',
'unknown'=>'0000',
'video'=>'0300',
'ide'=>'0101',
'scsi'=>'0100',
'usb'=>'0c03',
'sound'=>'0401',
'modem'=>'0703',
'multimedia'=>'0400', # Used to be 'tvcard'
'gameport'=>'0904' # Used to be 'joystick'
);
my %PCMCIA_CLASSES = (
'isdn'=>'isdn',
'bridge'=>'bridge',
'network'=>'network',
'unknown'=>'unknown',
'video'=>'video',
'sound'=>'sound',
'modem'=>'modem',
'multimedia'=>'multimedia',
'gameport'=>'gameport'
);
my %USB_CLASSES = (
'unknown'=>'0000',
'scanner'=>'ffff', # XXX ???
'printer'=>'0101',
'isdn'=>'1030',
'webcam'=>'ff00',
'network'=>'0206',
'modem'=>'0202',
'gameport'=>'0300',
'floppy'=>'0804'
);
my %REMAP_CLASSES = (
'isdn'=>'broadband',
'bridge'=>'bridge',
'ethernet'=>'network',
'unknown'=>'miscellaneous',
'video'=>'display',
'ide'=>'bridge',
'scsi'=>'bridge',
'usb'=>'bridge',
'sound'=>'audio',
'modem'=>'modem',
'multimedia'=>'video',
'tvcard'=>'video',
'joystick'=>'bridge',
'gameport'=>'bridge',
'scanner'=>'imaging',
'printer'=>'printer',
'webcam'=>'video',
'floppy'=>'removabledisk',
'network'=>'network'
);
sub encode_non_ascii {
my ($value) = @_;
my ($i, $newval, @chars);
@chars = unpack('C*', $value);
for($i = 0; $i < @chars; $i++) {
if ($chars[$i] > 127) {
$newval = sprintf("&#x%X;", $chars[$i]);
if ($i == 0) {
$value = $newval . substr($value, 1);
} elsif ($i == @chars - 1) {
$value = substr($value, 0, $i) . $newval;
} else {
$value = substr($value, 0, $i) . $newval .
substr($value, $i+1);
}
}
}
return $value;
}
sub make_busclass {
my $bus = shift;
my $bus_upper = shift;
my $id;
my $class;
my $try;
my @keys;
if (not open(BUSCLASSFOO, ">${bus}-busclass.xml")) {
die("Could not open ${bus}-busclass.xml\n");
}
print(BUSCLASSFOO <<EOF);
<?xml version='1.0' encoding='UTF-8'?>
<busclass_list bus="$bus">
EOF
$try = '@keys = keys(%';
$try .= $bus_upper;
$try .= '_CLASSES);';
eval $try;
foreach $class (@keys) {
$try = '$id = $'; # 'cperl-mode is sub-optimal
$try .= $bus_upper;
$try .= '_CLASSES{$class};';
eval $try;
print(BUSCLASSFOO " <busclass id=\"" . $id .
"\" name=\'$REMAP_CLASSES{$class}\'/>\n");
}
print(BUSCLASSFOO "</busclass_list>\n");
close(BUSCLASSFOO);
}
unless (@ARGV) {
die "Need valid file as first argument\n";
}
MAIN: {
my @data;
my $busclass;
my $bus;
my $bus_upper;
my $class;
my $new_class;
my $class_name;
my $filename;
my $interface_type;
my $model_id;
my $module;
my $serverbin;
my $text;
my $try;
my $vendor;
my $vendor_id;
foreach $filename (@ARGV) {
if (not -e $filename) {
die "Need valid file as first argument\n";
}
if (not $filename =~ /\/?(\w+)\.lst/) {
die "Need file with name <foo>.lst, where <foo> is a type "
. "of hardware\n";
}
$bus = $1;
$bus_upper = $1;
$bus_upper =~ tr/a-z/A-Z/;
make_busclass($bus, $bus_upper);
if (not open(VENDORS, ">${bus}-vendor.xml")) {
die "Must be able to open ${bus}-vendor.xml "
. "for writing\n";
}
if (not open(HARDWARE, ">${bus}-device.xml")) {
die "Must be able to open ${bus}-device.xml "
. "for writing\n";
}
if (not open(LST, $filename)) {
die "Must be able to open $filename for reading\n";
}
print HARDWARE <<EOF;
<?xml version='1.0' encoding='UTF-8'?>
<device_list bus='$bus'>
EOF
print VENDORS <<EOF;
<?xml version='1.0' encoding='UTF-8'?>
<vendor_list bus='$bus'>
EOF
while(<LST>) {
$class = $model_id = $vendor_id = $class_name = $module =
$text = $serverbin = '';
s/&/&/g;
s/</</g;
s/>/>/g;
s/"/"/g;
s/'/'/g;
#"cperl-mode is suboptimal
$_ = encode_non_ascii($_);
if (/^(\w+) (.*)$/) {
$vendor_id = $1;
$vendor = $2;
print(VENDORS " <vendor id=\'$vendor_id\' name=\'$vendor\'/>\n");
} elsif (/^\s+\w/) {
s/^\s+//;
s/\s+$//;
@data = split(/\t+/);
if (@data != 4) {
print(STDERR "Error: Wrong number of fields in $_\n");
next;
}
$model_id = $data[0];
$class_name = $data[1];
$module = $data[2];
$text = $data[3];
if ($class_name eq 'pmc') {
next;
}
$new_class = $CLASSES{$class_name};
if (not defined($new_class)) {
die("Couldn't find $class_name in CLASSES\n");
}
if (not $new_class) {
# A device we don't care about, such as mice
next;
}
$try = '$busclass = $'; # 'cperl-mode is sub-optimal
$try .= $bus_upper;
$try .= '_CLASSES{$new_class};';
eval $try;
if (not defined($busclass)) {
die("Couldn't find $new_class " .
"in ${bus_upper}_CLASSES\n");
}
$vendor_id = substr($model_id, 0, 4);
$model_id = substr($model_id, 4);
if ($module =~ /:/) {
@data = split(/:/, $module);
$interface_type = "xfree86";
$module = $data[1];
if ($module =~ /(.*)\((.*)\)/) {
$module = $2;
$serverbin = $1;
} else {
$serverbin = $module;
$module = '';
}
} elsif ($module eq 'unknown' || $module eq 'ignore') {
$interface_type = "";
} else {
$interface_type = "linux";
}
print HARDWARE <<EOF;
<device model='$model_id' vendor='$vendor_id' model_name='$text'>
EOF
if ($interface_type) {
print HARDWARE <<EOF;
<data class='$interface_type'>
EOF
}
if ($interface_type eq 'linux') {
print HARDWARE <<EOF;
<data class='module'>
<data class='name'>$module</data>
</data>
EOF
} elsif ($interface_type eq 'xfree86') {
if ($serverbin eq 'XFree86') {
print HARDWARE <<EOF;
<data version='[4, inf)' class='server'>
<data class='name'>$serverbin</data>
<data class='device'>
<data class='driver'>$module</data>
</data>
</data>
EOF
} else {
print HARDWARE <<EOF;
<data class='server' version="[3, 4)">
<data class='name'>$serverbin</data>
</data>
EOF
}
}
if ($interface_type) {
print HARDWARE <<EOF;
</data>
EOF
}
print HARDWARE <<EOF;
</device>
EOF
}
}
print HARDWARE "</device_list>\n";
print VENDORS "</vendor_list>\n";
close(LST);
close(HARDWARE);
close(VENDORS);
}
}
# vim:set ai et sts=4 sw=4:
|