Blame src/common_device_name.c

Packit 7d1034
/*
Packit 7d1034
 * (C) Copyright IBM Corporation 2006
Packit 7d1034
 * All Rights Reserved.
Packit 7d1034
 *
Packit 7d1034
 * Permission is hereby granted, free of charge, to any person obtaining a
Packit 7d1034
 * copy of this software and associated documentation files (the "Software"),
Packit 7d1034
 * to deal in the Software without restriction, including without limitation
Packit 7d1034
 * on the rights to use, copy, modify, merge, publish, distribute, sub
Packit 7d1034
 * license, and/or sell copies of the Software, and to permit persons to whom
Packit 7d1034
 * the Software is furnished to do so, subject to the following conditions:
Packit 7d1034
 *
Packit 7d1034
 * The above copyright notice and this permission notice (including the next
Packit 7d1034
 * paragraph) shall be included in all copies or substantial portions of the
Packit 7d1034
 * Software.
Packit 7d1034
 *
Packit 7d1034
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Packit 7d1034
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Packit 7d1034
 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
Packit 7d1034
 * IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
Packit 7d1034
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
Packit 7d1034
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
Packit 7d1034
 * DEALINGS IN THE SOFTWARE.
Packit 7d1034
 */
Packit 7d1034
Packit 7d1034
/**
Packit 7d1034
 * \file common_device_name.c
Packit 7d1034
 * Support routines used to determine the vendor or device names associated
Packit 7d1034
 * with a particular device or vendor.
Packit 7d1034
 */
Packit 7d1034
Packit 7d1034
#ifdef HAVE_CONFIG_H
Packit 7d1034
#include "config.h"
Packit 7d1034
#endif
Packit 7d1034
Packit 7d1034
#include <stdio.h>
Packit 7d1034
#include <stdlib.h>
Packit 7d1034
#include <ctype.h>
Packit 7d1034
Packit 7d1034
#if defined(HAVE_STRING_H)
Packit 7d1034
# include <string.h>
Packit 7d1034
#elif defined(HAVE_STRINGS_H)
Packit 7d1034
# include <strings.h>
Packit 7d1034
#endif
Packit 7d1034
Packit 7d1034
#if defined(HAVE_INTTYPES_H)
Packit 7d1034
# include <inttypes.h>
Packit 7d1034
#elif defined(HAVE_STDINT_H)
Packit 7d1034
# include <stdint.h>
Packit 7d1034
#endif
Packit 7d1034
Packit 7d1034
#include "pciaccess.h"
Packit 7d1034
#include "pciaccess_private.h"
Packit 7d1034
Packit 7d1034
#define DO_MATCH(a,b)  (((a) == PCI_MATCH_ANY) || ((a) == (b)))
Packit 7d1034
Packit 7d1034
#ifdef HAVE_ZLIB
Packit 7d1034
Packit 7d1034
#include <zlib.h>
Packit 7d1034
typedef gzFile pci_id_file;
Packit 7d1034
Packit 7d1034
static pci_id_file
Packit 7d1034
pci_id_file_open(void)
Packit 7d1034
{
Packit 7d1034
    pci_id_file result;
Packit 7d1034
Packit 7d1034
    result = gzopen(PCIIDS_PATH "/pci.ids.gz", "rb");
Packit 7d1034
    if (result)
Packit 7d1034
        return result;
Packit 7d1034
Packit 7d1034
    return gzopen(PCIIDS_PATH "/pci.ids", "rb");
Packit 7d1034
}
Packit 7d1034
Packit 7d1034
#define pci_id_file_gets(l, s, f)	gzgets(f, l, s)
Packit 7d1034
#define pci_id_file_close(f)		gzclose(f)
Packit 7d1034
Packit 7d1034
#else /* not zlib */
Packit 7d1034
Packit 7d1034
typedef FILE * pci_id_file;
Packit 7d1034
Packit 7d1034
static pci_id_file
Packit 7d1034
pci_id_file_open(void)
Packit 7d1034
{
Packit 7d1034
#ifndef __sun
Packit 7d1034
    pci_id_file result;
Packit 7d1034
Packit 7d1034
    result = fopen(PCIIDS_PATH "/pci.ids", "re");
Packit 7d1034
    if (result)
Packit 7d1034
        return result;
Packit 7d1034
#endif
Packit 7d1034
Packit 7d1034
    return fopen(PCIIDS_PATH "/pci.ids", "r");
Packit 7d1034
}
Packit 7d1034
Packit 7d1034
#define pci_id_file_gets(l, s, f)	fgets(l, s, f)
Packit 7d1034
#define pci_id_file_close(f)		fclose(f)
Packit 7d1034
Packit 7d1034
#endif
Packit 7d1034
Packit 7d1034
/**
Packit 7d1034
 * Node for sorting vendor IDs.
Packit 7d1034
 *
Packit 7d1034
 * Each structure forms an internal node of an n-way tree.  Each node selects
Packit 7d1034
 * \c pci_id_node::bits number of bits from the vendor ID.  Starting from the
Packit 7d1034
 * root of the tree, a slice of the low-order bits of the vendor ID are
Packit 7d1034
 * selected and used as an index into the \c pci_id_node::children array.
Packit 7d1034
 *
Packit 7d1034
 * At the leaf nodes (i.e., the node entered when all 16 bits of the vendor ID
Packit 7d1034
 * have been used), the \c pci_id_node::children is actually an array of
Packit 7d1034
 * pointers to \c pci_id_leaf structures.
Packit 7d1034
 *
Packit 7d1034
 * \todo
Packit 7d1034
 * Determine if there is a cleaner way (in the source code) to have the
Packit 7d1034
 * \c children array change type based on whether the node is internal or
Packit 7d1034
 * a leaf.
Packit 7d1034
 *
Packit 7d1034
 * \todo
Packit 7d1034
 * Currently \c bits is always 4.  Decide if this value can ever change
Packit 7d1034
 * (i.e., to pull-up levels of the n-way tree when all the children's children
Packit 7d1034
 * are full).  If it can, rip it out and hard-code it to 4 everywhere.
Packit 7d1034
 */
Packit 7d1034
struct pci_id_node {
Packit 7d1034
    unsigned bits;
Packit 7d1034
    struct pci_id_node * children[16];
Packit 7d1034
};
Packit 7d1034
Packit 7d1034
struct pci_id_leaf {
Packit 7d1034
    uint16_t     vendor;
Packit 7d1034
    const char * vendor_name;
Packit 7d1034
Packit 7d1034
    size_t num_devices;
Packit 7d1034
    struct pci_device_leaf * devices;
Packit 7d1034
};
Packit 7d1034
Packit 7d1034
struct pci_device_leaf {
Packit 7d1034
    struct pci_id_match   id;
Packit 7d1034
    const char * device_name;
Packit 7d1034
};
Packit 7d1034
Packit 7d1034
/**
Packit 7d1034
 * Root of the PCI vendor ID search tree.
Packit 7d1034
 */
Packit 7d1034
_pci_hidden struct pci_id_node * tree = NULL;
Packit 7d1034
Packit 7d1034
/**
Packit 7d1034
 * Get a pointer to the leaf node for a vendor ID.
Packit 7d1034
 *
Packit 7d1034
 * If the vendor ID does not exist in the tree, it is added.
Packit 7d1034
 */
Packit 7d1034
static struct pci_id_leaf *
Packit 7d1034
insert( uint16_t vendor )
Packit 7d1034
{
Packit 7d1034
    struct pci_id_node * n;
Packit 7d1034
    unsigned bits = 0;
Packit 7d1034
Packit 7d1034
    if ( tree == NULL ) {
Packit 7d1034
	tree = calloc( 1, sizeof( struct pci_id_node ) );
Packit 7d1034
Packit 7d1034
	if ( tree == NULL )
Packit 7d1034
	    return NULL;
Packit 7d1034
Packit 7d1034
	tree->bits = 4;
Packit 7d1034
    }
Packit 7d1034
Packit 7d1034
    n = tree;
Packit 7d1034
    while ( n != NULL ) {
Packit 7d1034
	const unsigned used_bits = n->bits;
Packit 7d1034
	const unsigned mask = (1 << used_bits) - 1;
Packit 7d1034
	const unsigned idx = (vendor & (mask << bits)) >> bits;
Packit 7d1034
Packit 7d1034
Packit 7d1034
	if ( bits >= 16 ) {
Packit 7d1034
	    break;
Packit 7d1034
	}
Packit 7d1034
Packit 7d1034
	bits += used_bits;
Packit 7d1034
Packit 7d1034
	if ( n->children[ idx ] == NULL ) {
Packit 7d1034
	    if ( bits < 16 ) {
Packit 7d1034
		struct pci_id_node * child =
Packit 7d1034
		    calloc( 1, sizeof( struct pci_id_node ) );
Packit 7d1034
Packit 7d1034
		if ( tree == NULL )
Packit 7d1034
		    return NULL;
Packit 7d1034
Packit 7d1034
		child->bits = 4;
Packit 7d1034
Packit 7d1034
		n->children[ idx ] = child;
Packit 7d1034
	    }
Packit 7d1034
	    else {
Packit 7d1034
		struct pci_id_leaf * leaf =
Packit 7d1034
		    calloc( 1, sizeof( struct pci_id_leaf ) );
Packit 7d1034
Packit 7d1034
		if ( tree == NULL )
Packit 7d1034
		    return NULL;
Packit 7d1034
Packit 7d1034
		leaf->vendor = vendor;
Packit 7d1034
Packit 7d1034
		n->children[ idx ] = (struct pci_id_node *) leaf;
Packit 7d1034
	    }
Packit 7d1034
	}
Packit 7d1034
Packit 7d1034
	n = n->children[ idx ];
Packit 7d1034
    }
Packit 7d1034
Packit 7d1034
    return (struct pci_id_leaf *) n;
Packit 7d1034
}
Packit 7d1034
Packit 7d1034
Packit 7d1034
/**
Packit 7d1034
 * Populate a vendor node with all the devices associated with that vendor
Packit 7d1034
 *
Packit 7d1034
 * \param vend  Vendor node that is to be filled from the pci.ids file.
Packit 7d1034
 *
Packit 7d1034
 * \todo
Packit 7d1034
 * The parsing in this function should be more rhobust.  There are some error
Packit 7d1034
 * cases (i.e., a 0-tab line followed by a 2-tab line) that aren't handled
Packit 7d1034
 * correctly.  I don't think there are any security problems with the code,
Packit 7d1034
 * but it's not impossible.
Packit 7d1034
 */
Packit 7d1034
static void
Packit 7d1034
populate_vendor( struct pci_id_leaf * vend, int fill_device_data )
Packit 7d1034
{
Packit 7d1034
    pci_id_file f;
Packit 7d1034
    char buf[128];
Packit 7d1034
    unsigned vendor = PCI_MATCH_ANY;
Packit 7d1034
Packit 7d1034
Packit 7d1034
    /* If the device tree for this vendor is already populated, don't do
Packit 7d1034
     * anything.  This avoids wasted processing and potential memory leaks.
Packit 7d1034
     */
Packit 7d1034
    if (vend->num_devices != 0) {
Packit 7d1034
	return;
Packit 7d1034
    }
Packit 7d1034
Packit 7d1034
    f = pci_id_file_open();
Packit 7d1034
Packit 7d1034
    /* If the pci.ids file could not be opened, there's nothing we can do.
Packit 7d1034
     */
Packit 7d1034
    if (f == NULL) {
Packit 7d1034
	return;
Packit 7d1034
    }
Packit 7d1034
Packit 7d1034
    while( pci_id_file_gets( buf, sizeof( buf ), f ) != NULL ) {
Packit 7d1034
	unsigned num_tabs;
Packit 7d1034
	char * new_line;
Packit 7d1034
	size_t length;
Packit 7d1034
Packit 7d1034
	/* Each line either starts with zero, one, or two tabs followed by
Packit 7d1034
	 * a series of 4 hex digits.  Any lines not matching that are ignored.
Packit 7d1034
	 */
Packit 7d1034
Packit 7d1034
	for ( num_tabs = 0 ; num_tabs < 3 ; num_tabs++ ) {
Packit 7d1034
	    if ( buf[ num_tabs ] != '\t' ) {
Packit 7d1034
		break;
Packit 7d1034
	    }
Packit 7d1034
	}
Packit 7d1034
Packit 7d1034
	if ( !isxdigit( buf[ num_tabs + 0 ] )
Packit 7d1034
	     || !isxdigit( buf[ num_tabs + 1 ] )
Packit 7d1034
	     || !isxdigit( buf[ num_tabs + 2 ] )
Packit 7d1034
	     || !isxdigit( buf[ num_tabs + 3 ] ) ) {
Packit 7d1034
	    continue;
Packit 7d1034
	}
Packit 7d1034
Packit 7d1034
	new_line = strchr( buf, '\n' );
Packit 7d1034
	if ( new_line != NULL ) {
Packit 7d1034
	    *new_line = '\0';
Packit 7d1034
	}
Packit 7d1034
Packit 7d1034
	length = strlen( buf );
Packit 7d1034
	(void) memset( buf + length, 0, sizeof( buf ) - length );
Packit 7d1034
Packit 7d1034
Packit 7d1034
	if ( num_tabs == 0 ) {
Packit 7d1034
	    vendor = (unsigned) strtoul( & buf[ num_tabs ], NULL, 16 );
Packit 7d1034
	    if ( vend->vendor == vendor ) {
Packit 7d1034
		/* vendor_name may already be set from a previous invocation
Packit 7d1034
		 * of this function with fill_device_data = 0.
Packit 7d1034
		 */
Packit 7d1034
		if (vend->vendor_name == NULL) {
Packit 7d1034
		    vend->vendor_name = strdup( & buf[ num_tabs + 6 ] );
Packit 7d1034
		}
Packit 7d1034
Packit 7d1034
		/* If we're not going to fill in all of the device data as
Packit 7d1034
		 * well, then bail out now.  We have all the information that
Packit 7d1034
		 * we need.
Packit 7d1034
		 */
Packit 7d1034
		if ( ! fill_device_data ) {
Packit 7d1034
		    break;
Packit 7d1034
		}
Packit 7d1034
	    }
Packit 7d1034
	}
Packit 7d1034
	else if ( vendor == vend->vendor ) {
Packit 7d1034
	    struct pci_device_leaf * d;
Packit 7d1034
	    struct pci_device_leaf * dev;
Packit 7d1034
	    struct pci_device_leaf * last_dev;
Packit 7d1034
Packit 7d1034
Packit 7d1034
Packit 7d1034
	    d = realloc( vend->devices, (vend->num_devices + 1)
Packit 7d1034
			 * sizeof( struct pci_device_leaf ) );
Packit 7d1034
	    if ( d == NULL ) {
Packit 7d1034
		goto cleanup;
Packit 7d1034
	    }
Packit 7d1034
Packit 7d1034
	    last_dev = & d[ vend->num_devices - 1 ];
Packit 7d1034
	    dev = & d[ vend->num_devices ];
Packit 7d1034
	    vend->num_devices++;
Packit 7d1034
	    vend->devices = d;
Packit 7d1034
Packit 7d1034
	    if ( num_tabs == 1 ) {
Packit 7d1034
		dev->id.vendor_id = vend->vendor;
Packit 7d1034
		dev->id.device_id = (unsigned) strtoul( & buf[ num_tabs ],
Packit 7d1034
							NULL, 16 );
Packit 7d1034
		dev->id.subvendor_id = PCI_MATCH_ANY;
Packit 7d1034
		dev->id.subdevice_id = PCI_MATCH_ANY;
Packit 7d1034
Packit 7d1034
		dev->id.device_class = 0;
Packit 7d1034
		dev->id.device_class_mask = 0;
Packit 7d1034
		dev->id.match_data = 0;
Packit 7d1034
Packit 7d1034
		dev->device_name = strdup( & buf[ num_tabs + 6 ] );
Packit 7d1034
	    }
Packit 7d1034
	    else {
Packit 7d1034
		dev->id = last_dev->id;
Packit 7d1034
Packit 7d1034
		dev->id.subvendor_id= (unsigned) strtoul( & buf[ num_tabs ],
Packit 7d1034
							  NULL, 16 );
Packit 7d1034
		dev->id.subdevice_id = (unsigned) strtoul( & buf[ num_tabs + 5 ],
Packit 7d1034
							   NULL, 16 );
Packit 7d1034
		dev->device_name = strdup( & buf[ num_tabs + 5 + 6 ] );
Packit 7d1034
	    }
Packit 7d1034
	}
Packit 7d1034
    }
Packit 7d1034
Packit 7d1034
  cleanup:
Packit 7d1034
    pci_id_file_close( f );
Packit 7d1034
}
Packit 7d1034
Packit 7d1034
Packit 7d1034
/**
Packit 7d1034
 * Find the name of the specified device.
Packit 7d1034
 *
Packit 7d1034
 * Finds the actual product name of the specified device.  If a subvendor ID
Packit 7d1034
 * and subdevice ID are specified in \c m, the returned name will be the name
Packit 7d1034
 * of the subdevice.
Packit 7d1034
 */
Packit 7d1034
static const char *
Packit 7d1034
find_device_name( const struct pci_id_match * m )
Packit 7d1034
{
Packit 7d1034
    struct pci_id_leaf * vend;
Packit 7d1034
    unsigned i;
Packit 7d1034
Packit 7d1034
Packit 7d1034
    if ( m->vendor_id == PCI_MATCH_ANY ) {
Packit 7d1034
	return NULL;
Packit 7d1034
    }
Packit 7d1034
Packit 7d1034
Packit 7d1034
    vend = insert( m->vendor_id );
Packit 7d1034
    if ( vend == NULL ) {
Packit 7d1034
	return NULL;
Packit 7d1034
    }
Packit 7d1034
Packit 7d1034
    if ( vend->num_devices == 0 ) {
Packit 7d1034
	populate_vendor( vend, 1 );
Packit 7d1034
    }
Packit 7d1034
Packit 7d1034
Packit 7d1034
    for ( i = 0 ; i < vend->num_devices ; i++ ) {
Packit 7d1034
	struct pci_device_leaf * d = & vend->devices[ i ];
Packit 7d1034
Packit 7d1034
	if ( DO_MATCH( m->vendor_id, d->id.vendor_id )
Packit 7d1034
	     && DO_MATCH( m->device_id, d->id.device_id )
Packit 7d1034
	     && DO_MATCH( m->subvendor_id, d->id.subvendor_id )
Packit 7d1034
	     && DO_MATCH( m->subdevice_id, d->id.subdevice_id ) ) {
Packit 7d1034
	    return d->device_name;
Packit 7d1034
	}
Packit 7d1034
    }
Packit 7d1034
Packit 7d1034
    return NULL;
Packit 7d1034
}
Packit 7d1034
Packit 7d1034
Packit 7d1034
/**
Packit 7d1034
 * Find the vendor name of the specified device.
Packit 7d1034
 *
Packit 7d1034
 * Finds the actual vendor name of the specified device.  If a subvendor ID
Packit 7d1034
 * and subdevice ID are specified in \c m, the returned name will be the name
Packit 7d1034
 * associated with the subvendor.
Packit 7d1034
 */
Packit 7d1034
static const char *
Packit 7d1034
find_vendor_name( const struct pci_id_match * m )
Packit 7d1034
{
Packit 7d1034
    struct pci_id_leaf * vend;
Packit 7d1034
Packit 7d1034
Packit 7d1034
    if ( m->vendor_id == PCI_MATCH_ANY ) {
Packit 7d1034
	return NULL;
Packit 7d1034
    }
Packit 7d1034
Packit 7d1034
Packit 7d1034
    vend = insert( m->vendor_id );
Packit 7d1034
    if ( vend == NULL ) {
Packit 7d1034
	return NULL;
Packit 7d1034
    }
Packit 7d1034
Packit 7d1034
    if ( vend->vendor_name == NULL ) {
Packit 7d1034
	populate_vendor( vend, 0 );
Packit 7d1034
    }
Packit 7d1034
Packit 7d1034
Packit 7d1034
    return vend->vendor_name;
Packit 7d1034
}
Packit 7d1034
Packit 7d1034
Packit 7d1034
/**
Packit 7d1034
 * Get a name based on an arbitrary PCI search structure.
Packit 7d1034
 */
Packit 7d1034
void
Packit 7d1034
pci_get_strings( const struct pci_id_match * m,
Packit 7d1034
		 const char ** device_name,
Packit 7d1034
		 const char ** vendor_name,
Packit 7d1034
		 const char ** subdevice_name,
Packit 7d1034
		 const char ** subvendor_name )
Packit 7d1034
{
Packit 7d1034
    struct pci_id_match  temp;
Packit 7d1034
Packit 7d1034
Packit 7d1034
    temp = *m;
Packit 7d1034
    temp.subvendor_id = PCI_MATCH_ANY;
Packit 7d1034
    temp.subdevice_id = PCI_MATCH_ANY;
Packit 7d1034
Packit 7d1034
    if ( device_name != NULL ) {
Packit 7d1034
	*device_name = find_device_name( & temp );
Packit 7d1034
    }
Packit 7d1034
Packit 7d1034
    if ( vendor_name != NULL ) {
Packit 7d1034
	*vendor_name = find_vendor_name( & temp );
Packit 7d1034
    }
Packit 7d1034
Packit 7d1034
    if ( subdevice_name != NULL ) {
Packit 7d1034
	*subdevice_name = find_device_name( m );
Packit 7d1034
    }
Packit 7d1034
Packit 7d1034
    if ( subvendor_name != NULL ) {
Packit 7d1034
	*subvendor_name = find_vendor_name( m );
Packit 7d1034
    }
Packit 7d1034
}
Packit 7d1034
Packit 7d1034
Packit 7d1034
/**
Packit 7d1034
 * Get the name associated with the device's primary device ID.
Packit 7d1034
 */
Packit 7d1034
const char *
Packit 7d1034
pci_device_get_device_name( const struct pci_device * dev )
Packit 7d1034
{
Packit 7d1034
    struct pci_id_match m;
Packit 7d1034
Packit 7d1034
Packit 7d1034
    m.vendor_id = dev->vendor_id;
Packit 7d1034
    m.device_id = dev->device_id;
Packit 7d1034
    m.subvendor_id = PCI_MATCH_ANY;
Packit 7d1034
    m.subdevice_id = PCI_MATCH_ANY;
Packit 7d1034
    m.device_class = 0;
Packit 7d1034
    m.device_class_mask = 0;
Packit 7d1034
    m.match_data = 0;
Packit 7d1034
Packit 7d1034
    return find_device_name( & m );
Packit 7d1034
}
Packit 7d1034
Packit 7d1034
Packit 7d1034
/**
Packit 7d1034
 * Get the name associated with the device's subdevice ID.
Packit 7d1034
 */
Packit 7d1034
const char *
Packit 7d1034
pci_device_get_subdevice_name( const struct pci_device * dev )
Packit 7d1034
{
Packit 7d1034
    struct pci_id_match m;
Packit 7d1034
Packit 7d1034
Packit 7d1034
    if ( (dev->subvendor_id == 0) || (dev->subdevice_id == 0) ) {
Packit 7d1034
	return NULL;
Packit 7d1034
    }
Packit 7d1034
Packit 7d1034
    m.vendor_id = dev->vendor_id;
Packit 7d1034
    m.device_id = dev->device_id;
Packit 7d1034
    m.subvendor_id = dev->subvendor_id;
Packit 7d1034
    m.subdevice_id = dev->subdevice_id;
Packit 7d1034
    m.device_class = 0;
Packit 7d1034
    m.device_class_mask = 0;
Packit 7d1034
    m.match_data = 0;
Packit 7d1034
Packit 7d1034
    return find_device_name( & m );
Packit 7d1034
}
Packit 7d1034
Packit 7d1034
Packit 7d1034
/**
Packit 7d1034
 * Get the name associated with the device's primary vendor ID.
Packit 7d1034
 */
Packit 7d1034
const char *
Packit 7d1034
pci_device_get_vendor_name( const struct pci_device * dev )
Packit 7d1034
{
Packit 7d1034
    struct pci_id_match m;
Packit 7d1034
Packit 7d1034
Packit 7d1034
    m.vendor_id = dev->vendor_id;
Packit 7d1034
    m.device_id = PCI_MATCH_ANY;
Packit 7d1034
    m.subvendor_id = PCI_MATCH_ANY;
Packit 7d1034
    m.subdevice_id = PCI_MATCH_ANY;
Packit 7d1034
    m.device_class = 0;
Packit 7d1034
    m.device_class_mask = 0;
Packit 7d1034
    m.match_data = 0;
Packit 7d1034
Packit 7d1034
    return find_vendor_name( & m );
Packit 7d1034
}
Packit 7d1034
Packit 7d1034
Packit 7d1034
/**
Packit 7d1034
 * Get the name associated with the device's subvendor ID.
Packit 7d1034
 */
Packit 7d1034
const char *
Packit 7d1034
pci_device_get_subvendor_name( const struct pci_device * dev )
Packit 7d1034
{
Packit 7d1034
    struct pci_id_match m;
Packit 7d1034
Packit 7d1034
Packit 7d1034
    if ( dev->subvendor_id == 0 ) {
Packit 7d1034
	return NULL;
Packit 7d1034
    }
Packit 7d1034
Packit 7d1034
Packit 7d1034
    m.vendor_id = dev->subvendor_id;
Packit 7d1034
    m.device_id = PCI_MATCH_ANY;
Packit 7d1034
    m.subvendor_id = PCI_MATCH_ANY;
Packit 7d1034
    m.subdevice_id = PCI_MATCH_ANY;
Packit 7d1034
    m.device_class = 0;
Packit 7d1034
    m.device_class_mask = 0;
Packit 7d1034
    m.match_data = 0;
Packit 7d1034
Packit 7d1034
    return find_vendor_name( & m );
Packit 7d1034
}