summaryrefslogtreecommitdiffstats
path: root/generate_usbclass.pl
blob: de533edd381af7c6971c5d612826c60f22b66a91 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#!/usr/bin/perl

print q(/* This is auto-generated from </usr/share/usb.ids>, don't modify! */

#define NULL 0

struct node {
  int id;
  const char *name;
  int nb_subnodes;
  struct node *subnodes;
};

);

my (@l, $sub, $subsub);
while (<>) {
    chomp;
    if (/^C\s+([\da-f]+)\s+(.*)/) {  #- I want alphanumeric but I can't get this [:alnum:] to work :-(
	push @l, [ $1, $2, $sub = [] ];
	undef $subsub;
    } elsif (/^\t([\da-f]+)\s+(.*)/ && defined $sub) {
	my ($sub_id, $sub_descr) = ($1, $2);
	$sub_id =~ /^[\da-f]{2}$/ or die "bad line $.: sub category number badly formatted ($_)\n";
	push @$sub, [ $sub_id, $sub_descr, $subsub = [] ];
    } elsif (/^\t\t([\da-f]+)\s+(.*)/ && defined $subsub) {
	push @$subsub, [ $1, $2, [] ];
    } elsif (/^\S/) {
	undef $sub;
	undef $subsub;
    }
}

sub dump_it {
    my ($l, $name, $prefix) = @_;

    my @l = sort { $a->[0] cmp $b->[0] } @$l or return;

    dump_it($_->[2], $name . '_' . $_->[0], "$prefix  ") foreach @l;

    print "${prefix}static struct node $name\[] = {\n";
    foreach (@l) {
	my $nb = @{$_->[2]};
	my $sub = $nb ? $name . '_' . $_->[0] : 'NULL';
	printf qq($prefix  { 0x%x, "%s", $nb, $sub },\n), hex($_->[0]), $_->[1];
    }
    print "$prefix};\n";
}

dump_it(\@l, "classes", '');

print '

static int nb_classes = sizeof(classes) / sizeof(*classes);

static void lookup(const char **p, int *a_class, int kind, int nb_nodes, struct node *nodes) {
  int i;
  for (i = 0; i < nb_nodes; i++)
    if (nodes[i].id == a_class[kind]) {
      p[kind] = nodes[i].name;
      return lookup(p, a_class, kind + 1, nodes[i].nb_subnodes, nodes[i].subnodes);
    }
}

struct class_text {
  const char *class_text;
  const char *sub_text;
  const char *prot_text;
};

extern struct class_text __attribute__ ((visibility("default"))) usb_class2text(unsigned long class_id) {
  const char *p[3] = { NULL, NULL, NULL };
  int a_class[3] = { (class_id >> 16) & 0xff, (class_id >> 8) & 0xff, class_id & 0xff };
  if (a_class[0] != 0xff) lookup(p, a_class, 0, nb_classes, classes);
  {
    struct class_text r = { p[0], p[1], p[2] };
    return r;
  }
}

';