Revision 9a765881bf3dcd32847d7108cf48cb04a4ed993f authored by Bjørn Mork on 10 October 2016, 19:12:49 UTC, committed by David S. Miller on 13 October 2016, 14:05:06 UTC
The Quectel EC21 and EC25 need the same "set DTR" request as devices
based on the MDM9230 chipset, but has no USB3 support. Our best guess
is that the "set DTR" functionality depends on chipset and/or
baseband firmware generation. But USB3 is still an optional feature.

Since we cannot enable this unconditionally for all older devices, and
there doesn't appear to be anything we can use in the USB descriptors
to identify these chips, we are forced to use a device specific quirk
flag.

Reported-and-tested-by: Sebastian Sjoholm <sebastian.sjoholm@gmail.com>
Signed-off-by: Bjørn Mork <bjorn@mork.no>
Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 4013bee
Raw File
build_OID_registry
#!/usr/bin/perl -w
#
# Build a static ASN.1 Object Identified (OID) registry
#
# Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
# Written by David Howells (dhowells@redhat.com)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public Licence
# as published by the Free Software Foundation; either version
# 2 of the Licence, or (at your option) any later version.
#

use strict;

my @names = ();
my @oids = ();

if ($#ARGV != 1) {
    print STDERR "Format: ", $0, " <in-h-file> <out-c-file>\n";
    exit(2);
}

#
# Open the file to read from
#
open IN_FILE, "<$ARGV[0]" || die;
while (<IN_FILE>) {
    chomp;
    if (m!\s+OID_([a-zA-z][a-zA-Z0-9_]+),\s+/[*]\s+([012][.0-9]*)\s+[*]/!) {
	push @names, $1;
	push @oids, $2;
    }
}
close IN_FILE || die;

#
# Open the files to write into
#
open C_FILE, ">$ARGV[1]" or die;
print C_FILE "/*\n";
print C_FILE " * Automatically generated by ", $0, ".  Do not edit\n";
print C_FILE " */\n";

#
# Split the data up into separate lists and also determine the lengths of the
# encoded data arrays.
#
my @indices = ();
my @lengths = ();
my $total_length = 0;

for (my $i = 0; $i <= $#names; $i++) {
    my $name = $names[$i];
    my $oid = $oids[$i];

    my @components = split(/[.]/, $oid);

    # Determine the encoded length of this OID
    my $size = $#components;
    for (my $loop = 2; $loop <= $#components; $loop++) {
	my $c = $components[$loop];

	# We will base128 encode the number
	my $tmp = ($c == 0) ? 0 : int(log($c)/log(2));
	$tmp = int($tmp / 7);
	$size += $tmp;
    }
    push @lengths, $size;
    push @indices, $total_length;
    $total_length += $size;
}

#
# Emit the look-up-by-OID index table
#
print C_FILE "\n";
if ($total_length <= 255) {
    print C_FILE "static const unsigned char oid_index[OID__NR + 1] = {\n";
} else {
    print C_FILE "static const unsigned short oid_index[OID__NR + 1] = {\n";
}
for (my $i = 0; $i <= $#names; $i++) {
    print C_FILE "\t[OID_", $names[$i], "] = ", $indices[$i], ",\n"
}
print C_FILE "\t[OID__NR] = ", $total_length, "\n";
print C_FILE "};\n";

#
# Encode the OIDs
#
my @encoded_oids = ();

for (my $i = 0; $i <= $#names; $i++) {
    my @octets = ();

    my @components = split(/[.]/, $oids[$i]);

    push @octets, $components[0] * 40 + $components[1];

    for (my $loop = 2; $loop <= $#components; $loop++) {
	my $c = $components[$loop];

	# Base128 encode the number
	my $tmp = ($c == 0) ? 0 : int(log($c)/log(2));
	$tmp = int($tmp / 7);

	for (; $tmp > 0; $tmp--) {
	    push @octets, (($c >> $tmp * 7) & 0x7f) | 0x80;
	}
	push @octets, $c & 0x7f;
    }

    push @encoded_oids, \@octets;
}

#
# Create a hash value for each OID
#
my @hash_values = ();
for (my $i = 0; $i <= $#names; $i++) {
    my @octets = @{$encoded_oids[$i]};

    my $hash = $#octets;
    foreach (@octets) {
	$hash += $_ * 33;
    }

    $hash = ($hash >> 24) ^ ($hash >> 16) ^ ($hash >> 8) ^ ($hash);

    push @hash_values, $hash & 0xff;
}

#
# Emit the OID data
#
print C_FILE "\n";
print C_FILE "static const unsigned char oid_data[", $total_length, "] = {\n";
for (my $i = 0; $i <= $#names; $i++) {
    my @octets = @{$encoded_oids[$i]};
    print C_FILE "\t";
    print C_FILE $_, ", " foreach (@octets);
    print C_FILE "\t// ", $names[$i];
    print C_FILE "\n";
}
print C_FILE "};\n";

#
# Build the search index table (ordered by length then hash then content)
#
my @index_table = ( 0 .. $#names );

@index_table = sort {
    my @octets_a = @{$encoded_oids[$a]};
    my @octets_b = @{$encoded_oids[$b]};

    return $hash_values[$a] <=> $hash_values[$b]
	if ($hash_values[$a] != $hash_values[$b]);
    return $#octets_a <=> $#octets_b
	if ($#octets_a != $#octets_b);
    for (my $i = $#octets_a; $i >= 0; $i--) {
	return $octets_a[$i] <=> $octets_b[$i]
	    if ($octets_a[$i] != $octets_b[$i]);
    }
    return 0;

} @index_table;

#
# Emit the search index and hash value table
#
print C_FILE "\n";
print C_FILE "static const struct {\n";
print C_FILE "\tunsigned char hash;\n";
if ($#names <= 255) {
    print C_FILE "\tenum OID oid : 8;\n";
} else {
    print C_FILE "\tenum OID oid : 16;\n";
}
print C_FILE "} oid_search_table[OID__NR] = {\n";
for (my $i = 0; $i <= $#names; $i++) {
    my @octets = @{$encoded_oids[$index_table[$i]]};
    printf(C_FILE "\t[%3u] = { %3u, OID_%-35s }, // ",
	   $i,
	   $hash_values[$index_table[$i]],
	   $names[$index_table[$i]]);
    printf C_FILE "%02x", $_ foreach (@octets);
    print C_FILE "\n";
}
print C_FILE "};\n";

#
# Emit the OID debugging name table
#
#print C_FILE "\n";
#print C_FILE "const char *const oid_name_table[OID__NR + 1] = {\n";
#
#for (my $i = 0; $i <= $#names; $i++) {
#    print C_FILE "\t\"", $names[$i], "\",\n"
#}
#print C_FILE "\t\"Unknown-OID\"\n";
#print C_FILE "};\n";

#
# Polish off
#
close C_FILE or die;
back to top