xref: /illumos-gate/usr/src/cmd/hal/hald/ids.c (revision 55fea89d)
118c2aff7Sartem /***************************************************************************
218c2aff7Sartem  * CVSID: $Id$
318c2aff7Sartem  *
418c2aff7Sartem  * ids.c : Lookup names from hardware identifiers
518c2aff7Sartem  *
618c2aff7Sartem  * Copyright (C) 2004 David Zeuthen, <david@fubar.dk>
718c2aff7Sartem  *
818c2aff7Sartem  * Licensed under the Academic Free License version 2.1
918c2aff7Sartem  *
1018c2aff7Sartem  * This program is free software; you can redistribute it and/or modify
1118c2aff7Sartem  * it under the terms of the GNU General Public License as published by
1218c2aff7Sartem  * the Free Software Foundation; either version 2 of the License, or
1318c2aff7Sartem  * (at your option) any later version.
1418c2aff7Sartem  *
1518c2aff7Sartem  * This program is distributed in the hope that it will be useful,
1618c2aff7Sartem  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1718c2aff7Sartem  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1818c2aff7Sartem  * GNU General Public License for more details.
1918c2aff7Sartem  *
2018c2aff7Sartem  * You should have received a copy of the GNU General Public License
2118c2aff7Sartem  * along with this program; if not, write to the Free Software
2218c2aff7Sartem  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
2318c2aff7Sartem  *
2418c2aff7Sartem  **************************************************************************/
2518c2aff7Sartem 
2618c2aff7Sartem #ifdef HAVE_CONFIG_H
2718c2aff7Sartem #  include <config.h>
2818c2aff7Sartem #endif
2918c2aff7Sartem 
3018c2aff7Sartem #include <ctype.h>
3118c2aff7Sartem #include <stdint.h>
3218c2aff7Sartem #include <string.h>
3318c2aff7Sartem #include <unistd.h>
3418c2aff7Sartem 
3518c2aff7Sartem #include <dbus/dbus.h>
3618c2aff7Sartem #include <dbus/dbus-glib.h>
3718c2aff7Sartem 
3818c2aff7Sartem #include "logger.h"
3918c2aff7Sartem 
4018c2aff7Sartem #include "ids.h"
4118c2aff7Sartem 
4218c2aff7Sartem /** Pointer to where the pci.ids file is loaded */
4318c2aff7Sartem static char *pci_ids = NULL;
4418c2aff7Sartem 
4518c2aff7Sartem /** Length of data store at at pci_ids */
4618c2aff7Sartem static unsigned int pci_ids_len;
4718c2aff7Sartem 
4818c2aff7Sartem /** Iterator position into pci_ids */
4918c2aff7Sartem static unsigned int pci_ids_iter_pos;
5018c2aff7Sartem 
5118c2aff7Sartem /** Initialize the pci.ids line iterator to the beginning of the file */
5218c2aff7Sartem static void
pci_ids_line_iter_init()5318c2aff7Sartem pci_ids_line_iter_init ()
5418c2aff7Sartem {
5518c2aff7Sartem 	pci_ids_iter_pos = 0;
5618c2aff7Sartem }
5718c2aff7Sartem 
5818c2aff7Sartem /** Maximum length of lines in pci.ids */
5918c2aff7Sartem #define PCI_IDS_MAX_LINE_LEN 512
6018c2aff7Sartem 
6118c2aff7Sartem /** Get the next line from pci.ids
6218c2aff7Sartem  *
6318c2aff7Sartem  *  @param  line_len            Pointer to where number of bytes in line will
6418c2aff7Sartem  *                              be stored
6518c2aff7Sartem  *  @return                     Pointer to the line; only valid until the
6618c2aff7Sartem  *                              next invocation of this function
6718c2aff7Sartem  */
6818c2aff7Sartem static char *
pci_ids_line_iter_get_line(unsigned int * line_len)6918c2aff7Sartem pci_ids_line_iter_get_line (unsigned int *line_len)
7018c2aff7Sartem {
7118c2aff7Sartem 	unsigned int i;
7218c2aff7Sartem 	static char line[PCI_IDS_MAX_LINE_LEN];
7318c2aff7Sartem 
7418c2aff7Sartem 	for (i = 0;
7518c2aff7Sartem 	     pci_ids_iter_pos < pci_ids_len &&
7618c2aff7Sartem 	     i < PCI_IDS_MAX_LINE_LEN - 1 &&
7718c2aff7Sartem 	     pci_ids[pci_ids_iter_pos] != '\n'; i++, pci_ids_iter_pos++) {
7818c2aff7Sartem 		line[i] = pci_ids[pci_ids_iter_pos];
7918c2aff7Sartem 	}
8018c2aff7Sartem 
8118c2aff7Sartem 	line[i] = '\0';
8218c2aff7Sartem 	if (line_len != NULL)
8318c2aff7Sartem 		*line_len = i;
8418c2aff7Sartem 
8518c2aff7Sartem 	pci_ids_iter_pos++;
8618c2aff7Sartem 
8718c2aff7Sartem 	return line;
8818c2aff7Sartem }
8918c2aff7Sartem 
9018c2aff7Sartem /** See if there are more lines to process in pci.ids
9118c2aff7Sartem  *
9218c2aff7Sartem  *  @return                     #TRUE iff there are more lines to process
9318c2aff7Sartem  */
9418c2aff7Sartem static dbus_bool_t
pci_ids_line_iter_has_more()9518c2aff7Sartem pci_ids_line_iter_has_more ()
9618c2aff7Sartem {
9718c2aff7Sartem 	return pci_ids_iter_pos < pci_ids_len;
9818c2aff7Sartem }
9918c2aff7Sartem 
10018c2aff7Sartem 
10118c2aff7Sartem /** Find the names for a PCI device.
10218c2aff7Sartem  *
10318c2aff7Sartem  *  The pointers returned are only valid until the next invocation of this
10418c2aff7Sartem  *  function.
10518c2aff7Sartem  *
10618c2aff7Sartem  *  @param  vendor_id           PCI vendor id or 0 if unknown
10718c2aff7Sartem  *  @param  product_id          PCI product id or 0 if unknown
10818c2aff7Sartem  *  @param  subsys_vendor_id    PCI subsystem vendor id or 0 if unknown
10918c2aff7Sartem  *  @param  subsys_product_id   PCI subsystem product id or 0 if unknown
11018c2aff7Sartem  *  @param  vendor_name         Set to pointer of result or NULL
11118c2aff7Sartem  *  @param  product_name        Set to pointer of result or NULL
11218c2aff7Sartem  *  @param  subsys_vendor_name  Set to pointer of result or NULL
11318c2aff7Sartem  *  @param  subsys_product_name Set to pointer of result or NULL
11418c2aff7Sartem  */
11518c2aff7Sartem void
ids_find_pci(int vendor_id,int product_id,int subsys_vendor_id,int subsys_product_id,char ** vendor_name,char ** product_name,char ** subsys_vendor_name,char ** subsys_product_name)11618c2aff7Sartem ids_find_pci (int vendor_id, int product_id,
11718c2aff7Sartem 	      int subsys_vendor_id, int subsys_product_id,
11818c2aff7Sartem 	      char **vendor_name, char **product_name,
11918c2aff7Sartem 	      char **subsys_vendor_name, char **subsys_product_name)
12018c2aff7Sartem {
12118c2aff7Sartem 	char *line;
12218c2aff7Sartem 	unsigned int i;
12318c2aff7Sartem 	unsigned int line_len;
12418c2aff7Sartem 	unsigned int num_tabs;
12518c2aff7Sartem 	char rep_vi[8];
12618c2aff7Sartem 	char rep_pi[8];
12718c2aff7Sartem 	char rep_svi[8];
12818c2aff7Sartem 	char rep_spi[8];
12918c2aff7Sartem 	dbus_bool_t vendor_matched = FALSE;
13018c2aff7Sartem 	dbus_bool_t product_matched = FALSE;
13118c2aff7Sartem 	static char store_vn[PCI_IDS_MAX_LINE_LEN];
13218c2aff7Sartem 	static char store_pn[PCI_IDS_MAX_LINE_LEN];
13318c2aff7Sartem 	static char store_svn[PCI_IDS_MAX_LINE_LEN];
13418c2aff7Sartem 	static char store_spn[PCI_IDS_MAX_LINE_LEN];
13518c2aff7Sartem 
13618c2aff7Sartem 	snprintf (rep_vi, 8, "%04x", vendor_id);
13718c2aff7Sartem 	snprintf (rep_pi, 8, "%04x", product_id);
13818c2aff7Sartem 	snprintf (rep_svi, 8, "%04x", subsys_vendor_id);
13918c2aff7Sartem 	snprintf (rep_spi, 8, "%04x", subsys_product_id);
14018c2aff7Sartem 
14118c2aff7Sartem 	*vendor_name = NULL;
14218c2aff7Sartem 	*product_name = NULL;
14318c2aff7Sartem 	*subsys_vendor_name = NULL;
14418c2aff7Sartem 	*subsys_product_name = NULL;
14518c2aff7Sartem 
14618c2aff7Sartem 	for (pci_ids_line_iter_init (); pci_ids_line_iter_has_more ();) {
14718c2aff7Sartem 		line = pci_ids_line_iter_get_line (&line_len);
14818c2aff7Sartem 
14918c2aff7Sartem 		/* skip lines with no content */
15018c2aff7Sartem 		if (line_len < 4)
15118c2aff7Sartem 			continue;
15218c2aff7Sartem 
15318c2aff7Sartem 		/* skip comments */
15418c2aff7Sartem 		if (line[0] == '#')
15518c2aff7Sartem 			continue;
15618c2aff7Sartem 
15718c2aff7Sartem 		/* count number of tabs */
15818c2aff7Sartem 		num_tabs = 0;
15918c2aff7Sartem 		for (i = 0; i < line_len; i++) {
16018c2aff7Sartem 			if (line[i] != '\t')
16118c2aff7Sartem 				break;
16218c2aff7Sartem 			num_tabs++;
16318c2aff7Sartem 		}
16418c2aff7Sartem 
16518c2aff7Sartem 		switch (num_tabs) {
16618c2aff7Sartem 		case 0:
16718c2aff7Sartem 			/* vendor names */
16818c2aff7Sartem 			vendor_matched = FALSE;
16918c2aff7Sartem 
170*55fea89dSDan Cross 			/* first check subsys_vendor_id, if haven't done
17118c2aff7Sartem 			 * already */
17218c2aff7Sartem 			if (*subsys_vendor_name == NULL
17318c2aff7Sartem 			    && subsys_vendor_id != 0) {
17418c2aff7Sartem 				if ((*((dbus_uint32_t *) line)) ==
17518c2aff7Sartem 				    (*((dbus_uint32_t *) rep_svi))) {
17618c2aff7Sartem 					/* found it */
17718c2aff7Sartem 					for (i = 4; i < line_len; i++) {
17818c2aff7Sartem 						if (!isspace (line[i]))
17918c2aff7Sartem 							break;
18018c2aff7Sartem 					}
18118c2aff7Sartem 					strncpy (store_svn, line + i,
18218c2aff7Sartem 						 PCI_IDS_MAX_LINE_LEN);
18318c2aff7Sartem 					*subsys_vendor_name = store_svn;
18418c2aff7Sartem 				}
18518c2aff7Sartem 			}
18618c2aff7Sartem 
18718c2aff7Sartem 			/* check vendor_id */
18818c2aff7Sartem 			if (vendor_id != 0) {
18918c2aff7Sartem 				if (memcmp (line, rep_vi, 4) == 0) {
19018c2aff7Sartem 					/* found it */
19118c2aff7Sartem 					vendor_matched = TRUE;
19218c2aff7Sartem 
19318c2aff7Sartem 					for (i = 4; i < line_len; i++) {
19418c2aff7Sartem 						if (!isspace (line[i]))
19518c2aff7Sartem 							break;
19618c2aff7Sartem 					}
19718c2aff7Sartem 					strncpy (store_vn, line + i,
19818c2aff7Sartem 						 PCI_IDS_MAX_LINE_LEN);
19918c2aff7Sartem 					*vendor_name = store_vn;
20018c2aff7Sartem 				}
20118c2aff7Sartem 			}
20218c2aff7Sartem 
20318c2aff7Sartem 			break;
20418c2aff7Sartem 
20518c2aff7Sartem 		case 1:
20618c2aff7Sartem 			product_matched = FALSE;
20718c2aff7Sartem 
20818c2aff7Sartem 			/* product names */
20918c2aff7Sartem 			if (!vendor_matched)
21018c2aff7Sartem 				continue;
21118c2aff7Sartem 
21218c2aff7Sartem 			/* check product_id */
21318c2aff7Sartem 			if (product_id != 0) {
21418c2aff7Sartem 				if (memcmp (line + 1, rep_pi, 4) == 0) {
21518c2aff7Sartem 					/* found it */
21618c2aff7Sartem 
21718c2aff7Sartem 					product_matched = TRUE;
21818c2aff7Sartem 
21918c2aff7Sartem 					for (i = 5; i < line_len; i++) {
22018c2aff7Sartem 						if (!isspace (line[i]))
22118c2aff7Sartem 							break;
22218c2aff7Sartem 					}
22318c2aff7Sartem 					strncpy (store_pn, line + i,
22418c2aff7Sartem 						 PCI_IDS_MAX_LINE_LEN);
22518c2aff7Sartem 					*product_name = store_pn;
22618c2aff7Sartem 				}
22718c2aff7Sartem 			}
22818c2aff7Sartem 			break;
22918c2aff7Sartem 
23018c2aff7Sartem 		case 2:
23118c2aff7Sartem 			/* subsystem_vendor subsystem_product */
23218c2aff7Sartem 			if (!vendor_matched || !product_matched)
23318c2aff7Sartem 				continue;
23418c2aff7Sartem 
23518c2aff7Sartem 			/* check product_id */
23618c2aff7Sartem 			if (subsys_vendor_id != 0
23718c2aff7Sartem 			    && subsys_product_id != 0) {
23818c2aff7Sartem 				if (memcmp (line + 2, rep_svi, 4) == 0
23918c2aff7Sartem 				    && memcmp (line + 7, rep_spi,
24018c2aff7Sartem 					       4) == 0) {
24118c2aff7Sartem 					/* found it */
24218c2aff7Sartem 					for (i = 11; i < line_len; i++) {
24318c2aff7Sartem 						if (!isspace (line[i]))
24418c2aff7Sartem 							break;
24518c2aff7Sartem 					}
24618c2aff7Sartem 					strncpy (store_spn, line + i,
24718c2aff7Sartem 						 PCI_IDS_MAX_LINE_LEN);
24818c2aff7Sartem 					*subsys_product_name = store_spn;
24918c2aff7Sartem 				}
25018c2aff7Sartem 			}
25118c2aff7Sartem 
25218c2aff7Sartem 			break;
25318c2aff7Sartem 
25418c2aff7Sartem 		default:
25518c2aff7Sartem 			break;
25618c2aff7Sartem 		}
25718c2aff7Sartem 
25818c2aff7Sartem 	}
25918c2aff7Sartem }
26018c2aff7Sartem 
26118c2aff7Sartem /** Free resources used by to store the PCI database
26218c2aff7Sartem  *
26318c2aff7Sartem  *  @param                      #FALSE if the PCI database wasn't loaded
26418c2aff7Sartem  */
26518c2aff7Sartem static dbus_bool_t
pci_ids_free()26618c2aff7Sartem pci_ids_free ()
26718c2aff7Sartem {
26818c2aff7Sartem 	if (pci_ids != NULL) {
26918c2aff7Sartem 		free (pci_ids);
27018c2aff7Sartem 		pci_ids = NULL;
27118c2aff7Sartem 		return TRUE;
27218c2aff7Sartem 	}
27318c2aff7Sartem 	return FALSE;
27418c2aff7Sartem }
27518c2aff7Sartem 
27618c2aff7Sartem /** Load the PCI database used for mapping vendor, product, subsys_vendor
27718c2aff7Sartem  *  and subsys_product numbers into names.
27818c2aff7Sartem  *
279*55fea89dSDan Cross  *  @param  path                Path of the pci.ids file, e.g.
28018c2aff7Sartem  *                              /usr/share/hwdata/pci.ids
28118c2aff7Sartem  *  @return                     #TRUE if the file was succesfully loaded
28218c2aff7Sartem  */
28318c2aff7Sartem static dbus_bool_t
pci_ids_load(const char * path)28418c2aff7Sartem pci_ids_load (const char *path)
28518c2aff7Sartem {
28618c2aff7Sartem 	FILE *fp;
28718c2aff7Sartem 	unsigned int num_read;
28818c2aff7Sartem 
28918c2aff7Sartem 	fp = fopen (path, "r");
29018c2aff7Sartem 	if (fp == NULL) {
29118c2aff7Sartem 		HAL_ERROR (("couldn't open PCI database at %s,", path));
29218c2aff7Sartem 		return FALSE;
29318c2aff7Sartem 	}
29418c2aff7Sartem 
29518c2aff7Sartem 	fseek (fp, 0, SEEK_END);
29618c2aff7Sartem 	pci_ids_len = ftell (fp);
29718c2aff7Sartem 	fseek (fp, 0, SEEK_SET);
29818c2aff7Sartem 
29918c2aff7Sartem 	pci_ids = malloc (pci_ids_len);
30018c2aff7Sartem 	if (pci_ids == NULL) {
30118c2aff7Sartem 		DIE (("Couldn't allocate %d bytes for PCI database file\n",
30218c2aff7Sartem 		      pci_ids_len));
30318c2aff7Sartem 	}
30418c2aff7Sartem 
30518c2aff7Sartem 	num_read = fread (pci_ids, sizeof (char), pci_ids_len, fp);
30618c2aff7Sartem 	if (pci_ids_len != num_read) {
30718c2aff7Sartem 		HAL_ERROR (("Error loading PCI database file"));
30818c2aff7Sartem 		pci_ids_free();
30918c2aff7Sartem 		fclose(fp);
31018c2aff7Sartem 		return FALSE;
31118c2aff7Sartem 	}
31218c2aff7Sartem 
31318c2aff7Sartem 	fclose(fp);
31418c2aff7Sartem 	return TRUE;
31518c2aff7Sartem }
31618c2aff7Sartem 
31718c2aff7Sartem /*==========================================================================*/
31818c2aff7Sartem 
31918c2aff7Sartem /** Pointer to where the usb.ids file is loaded */
32018c2aff7Sartem static char *usb_ids = NULL;
32118c2aff7Sartem 
32218c2aff7Sartem /** Length of data store at at usb_ids */
32318c2aff7Sartem static unsigned int usb_ids_len;
32418c2aff7Sartem 
32518c2aff7Sartem /** Iterator position into usb_ids */
32618c2aff7Sartem static unsigned int usb_ids_iter_pos;
32718c2aff7Sartem 
32818c2aff7Sartem /** Initialize the usb.ids line iterator to the beginning of the file */
32918c2aff7Sartem static void
usb_ids_line_iter_init()33018c2aff7Sartem usb_ids_line_iter_init ()
33118c2aff7Sartem {
33218c2aff7Sartem 	usb_ids_iter_pos = 0;
33318c2aff7Sartem }
33418c2aff7Sartem 
33518c2aff7Sartem /** Maximum length of lines in usb.ids */
33618c2aff7Sartem #define USB_IDS_MAX_LINE_LEN 512
33718c2aff7Sartem 
33818c2aff7Sartem /** Get the next line from usb.ids
33918c2aff7Sartem  *
34018c2aff7Sartem  *  @param  line_len            Pointer to where number of bytes in line will
34118c2aff7Sartem  *                              be stored
34218c2aff7Sartem  *  @return                     Pointer to the line; only valid until the
34318c2aff7Sartem  *                              next invocation of this function
34418c2aff7Sartem  */
34518c2aff7Sartem static char *
usb_ids_line_iter_get_line(unsigned int * line_len)34618c2aff7Sartem usb_ids_line_iter_get_line (unsigned int *line_len)
34718c2aff7Sartem {
34818c2aff7Sartem 	unsigned int i;
34918c2aff7Sartem 	static char line[USB_IDS_MAX_LINE_LEN];
35018c2aff7Sartem 
35118c2aff7Sartem 	for (i = 0;
35218c2aff7Sartem 	     usb_ids_iter_pos < usb_ids_len &&
35318c2aff7Sartem 	     i < USB_IDS_MAX_LINE_LEN - 1 &&
35418c2aff7Sartem 	     usb_ids[usb_ids_iter_pos] != '\n'; i++, usb_ids_iter_pos++) {
35518c2aff7Sartem 		line[i] = usb_ids[usb_ids_iter_pos];
35618c2aff7Sartem 	}
35718c2aff7Sartem 
35818c2aff7Sartem 	line[i] = '\0';
35918c2aff7Sartem 	if (line_len != NULL)
36018c2aff7Sartem 		*line_len = i;
36118c2aff7Sartem 
36218c2aff7Sartem 	usb_ids_iter_pos++;
36318c2aff7Sartem 
36418c2aff7Sartem 	return line;
36518c2aff7Sartem }
36618c2aff7Sartem 
36718c2aff7Sartem /** See if there are more lines to process in usb.ids
36818c2aff7Sartem  *
36918c2aff7Sartem  *  @return                     #TRUE iff there are more lines to process
37018c2aff7Sartem  */
37118c2aff7Sartem static dbus_bool_t
usb_ids_line_iter_has_more()37218c2aff7Sartem usb_ids_line_iter_has_more ()
37318c2aff7Sartem {
37418c2aff7Sartem 	return usb_ids_iter_pos < usb_ids_len;
37518c2aff7Sartem }
37618c2aff7Sartem 
37718c2aff7Sartem /** Find the names for a USB device.
37818c2aff7Sartem  *
37918c2aff7Sartem  *  The pointers returned are only valid until the next invocation of this
38018c2aff7Sartem  *  function.
38118c2aff7Sartem  *
38218c2aff7Sartem  *  @param  vendor_id           USB vendor id or 0 if unknown
38318c2aff7Sartem  *  @param  product_id          USB product id or 0 if unknown
38418c2aff7Sartem  *  @param  vendor_name         Set to pointer of result or NULL
38518c2aff7Sartem  *  @param  product_name        Set to pointer of result or NULL
38618c2aff7Sartem  */
38718c2aff7Sartem void
ids_find_usb(int vendor_id,int product_id,char ** vendor_name,char ** product_name)38818c2aff7Sartem ids_find_usb (int vendor_id, int product_id,
38918c2aff7Sartem 	      char **vendor_name, char **product_name)
39018c2aff7Sartem {
39118c2aff7Sartem 	char *line;
39218c2aff7Sartem 	unsigned int i;
39318c2aff7Sartem 	unsigned int line_len;
39418c2aff7Sartem 	unsigned int num_tabs;
39518c2aff7Sartem 	char rep_vi[8];
39618c2aff7Sartem 	char rep_pi[8];
39718c2aff7Sartem 	static char store_vn[USB_IDS_MAX_LINE_LEN];
39818c2aff7Sartem 	static char store_pn[USB_IDS_MAX_LINE_LEN];
39918c2aff7Sartem 	dbus_bool_t vendor_matched = FALSE;
40018c2aff7Sartem 
40118c2aff7Sartem 	snprintf (rep_vi, 8, "%04x", vendor_id);
40218c2aff7Sartem 	snprintf (rep_pi, 8, "%04x", product_id);
40318c2aff7Sartem 
40418c2aff7Sartem 	*vendor_name = NULL;
40518c2aff7Sartem 	*product_name = NULL;
40618c2aff7Sartem 
40718c2aff7Sartem 	for (usb_ids_line_iter_init (); usb_ids_line_iter_has_more ();) {
40818c2aff7Sartem 		line = usb_ids_line_iter_get_line (&line_len);
40918c2aff7Sartem 
41018c2aff7Sartem 		/* skip lines with no content */
41118c2aff7Sartem 		if (line_len < 4)
41218c2aff7Sartem 			continue;
41318c2aff7Sartem 
41418c2aff7Sartem 		/* skip comments */
41518c2aff7Sartem 		if (line[0] == '#')
41618c2aff7Sartem 			continue;
41718c2aff7Sartem 
41818c2aff7Sartem 		/* count number of tabs */
41918c2aff7Sartem 		num_tabs = 0;
42018c2aff7Sartem 		for (i = 0; i < line_len; i++) {
42118c2aff7Sartem 			if (line[i] != '\t')
42218c2aff7Sartem 				break;
42318c2aff7Sartem 			num_tabs++;
42418c2aff7Sartem 		}
42518c2aff7Sartem 
42618c2aff7Sartem 		switch (num_tabs) {
42718c2aff7Sartem 		case 0:
42818c2aff7Sartem 			/* vendor names */
42918c2aff7Sartem 			vendor_matched = FALSE;
43018c2aff7Sartem 
43118c2aff7Sartem 			/* check vendor_id */
43218c2aff7Sartem 			if (vendor_id != 0) {
43318c2aff7Sartem 				if (memcmp (line, rep_vi, 4) == 0) {
43418c2aff7Sartem 					/* found it */
43518c2aff7Sartem 					vendor_matched = TRUE;
43618c2aff7Sartem 
43718c2aff7Sartem 					for (i = 4; i < line_len; i++) {
43818c2aff7Sartem 						if (!isspace (line[i]))
43918c2aff7Sartem 							break;
44018c2aff7Sartem 					}
44118c2aff7Sartem 					strncpy (store_vn, line + i,
44218c2aff7Sartem 						 USB_IDS_MAX_LINE_LEN);
44318c2aff7Sartem 					*vendor_name = store_vn;
44418c2aff7Sartem 				}
44518c2aff7Sartem 			}
44618c2aff7Sartem 			break;
44718c2aff7Sartem 
44818c2aff7Sartem 		case 1:
44918c2aff7Sartem 			/* product names */
45018c2aff7Sartem 			if (!vendor_matched)
45118c2aff7Sartem 				continue;
45218c2aff7Sartem 
45318c2aff7Sartem 			/* check product_id */
45418c2aff7Sartem 			if (product_id != 0) {
45518c2aff7Sartem 				if (memcmp (line + 1, rep_pi, 4) == 0) {
45618c2aff7Sartem 					/* found it */
45718c2aff7Sartem 					for (i = 5; i < line_len; i++) {
45818c2aff7Sartem 						if (!isspace (line[i]))
45918c2aff7Sartem 							break;
46018c2aff7Sartem 					}
46118c2aff7Sartem 					strncpy (store_pn, line + i,
46218c2aff7Sartem 						 USB_IDS_MAX_LINE_LEN);
46318c2aff7Sartem 					*product_name = store_pn;
46418c2aff7Sartem 
46518c2aff7Sartem 					/* no need to continue the search */
46618c2aff7Sartem 					return;
46718c2aff7Sartem 				}
46818c2aff7Sartem 			}
46918c2aff7Sartem 			break;
47018c2aff7Sartem 
47118c2aff7Sartem 		default:
47218c2aff7Sartem 			break;
47318c2aff7Sartem 		}
47418c2aff7Sartem 
47518c2aff7Sartem 	}
47618c2aff7Sartem }
47718c2aff7Sartem 
47818c2aff7Sartem /** Free resources used by to store the USB database
47918c2aff7Sartem  *
48018c2aff7Sartem  *  @param                      #FALSE if the USB database wasn't loaded
48118c2aff7Sartem  */
48218c2aff7Sartem static dbus_bool_t
usb_ids_free()48318c2aff7Sartem usb_ids_free ()
48418c2aff7Sartem {
48518c2aff7Sartem 	if (usb_ids != NULL) {
48618c2aff7Sartem 		free (usb_ids);
48718c2aff7Sartem 		usb_ids = NULL;
48818c2aff7Sartem 		return TRUE;
48918c2aff7Sartem 	}
49018c2aff7Sartem 	return FALSE;
49118c2aff7Sartem }
49218c2aff7Sartem 
49318c2aff7Sartem /** Load the USB database used for mapping vendor, product, subsys_vendor
49418c2aff7Sartem  *  and subsys_product numbers into names.
49518c2aff7Sartem  *
496*55fea89dSDan Cross  *  @param  path                Path of the usb.ids file, e.g.
49718c2aff7Sartem  *                              /usr/share/hwdata/usb.ids
49818c2aff7Sartem  *  @return                     #TRUE if the file was succesfully loaded
49918c2aff7Sartem  */
50018c2aff7Sartem static dbus_bool_t
usb_ids_load(const char * path)50118c2aff7Sartem usb_ids_load (const char *path)
50218c2aff7Sartem {
50318c2aff7Sartem 	FILE *fp;
50418c2aff7Sartem 	unsigned int num_read;
50518c2aff7Sartem 
50618c2aff7Sartem 	fp = fopen (path, "r");
50718c2aff7Sartem 	if (fp == NULL) {
50818c2aff7Sartem 		printf ("couldn't open USB database at %s,", path);
50918c2aff7Sartem 		return FALSE;
51018c2aff7Sartem 	}
51118c2aff7Sartem 
51218c2aff7Sartem 	fseek (fp, 0, SEEK_END);
51318c2aff7Sartem 	usb_ids_len = ftell (fp);
51418c2aff7Sartem 	fseek (fp, 0, SEEK_SET);
51518c2aff7Sartem 
51618c2aff7Sartem 	usb_ids = malloc (usb_ids_len);
51718c2aff7Sartem 	if (usb_ids == NULL) {
51818c2aff7Sartem 		printf
51918c2aff7Sartem 		    ("Couldn't allocate %d bytes for USB database file\n",
52018c2aff7Sartem 		     usb_ids_len);
52118c2aff7Sartem 		fclose(fp);
52218c2aff7Sartem 		return FALSE;
52318c2aff7Sartem 	}
52418c2aff7Sartem 
52518c2aff7Sartem 	num_read = fread (usb_ids, sizeof (char), usb_ids_len, fp);
52618c2aff7Sartem 	if (usb_ids_len != num_read) {
52718c2aff7Sartem 		printf ("Error loading USB database file\n");
52818c2aff7Sartem 		usb_ids_free ();
52918c2aff7Sartem 		fclose(fp);
53018c2aff7Sartem 		return FALSE;
53118c2aff7Sartem 	}
53218c2aff7Sartem 
53318c2aff7Sartem 	fclose(fp);
53418c2aff7Sartem 	return TRUE;
53518c2aff7Sartem }
53618c2aff7Sartem 
53718c2aff7Sartem 
538*55fea89dSDan Cross void
ids_init(void)53918c2aff7Sartem ids_init (void)
54018c2aff7Sartem {
54118c2aff7Sartem 	/* Load /usr/share/hwdata/pci.ids */
54218c2aff7Sartem 	pci_ids_load (HWDATA_DIR "/pci.ids");
54318c2aff7Sartem 
54418c2aff7Sartem 	/* Load /usr/share/hwdata/usb.ids */
54518c2aff7Sartem 	usb_ids_load (HWDATA_DIR "/usb.ids");
54618c2aff7Sartem }
54718c2aff7Sartem 
54818c2aff7Sartem 
54918c2aff7Sartem /* This, somewhat incomplete, list is from this sources:
550*55fea89dSDan Cross  * http://www.plasma-online.de/english/identify/serial/pnp_id_pnp.html
55118c2aff7Sartem  * http://www-pc.uni-regensburg.de/hardware/TECHNIK/PCI_PNP/pnpid.txt
55218c2aff7Sartem  *
55318c2aff7Sartem  * Keep this sorted!
55418c2aff7Sartem  */
55518c2aff7Sartem struct pnp_id {
55618c2aff7Sartem 	char *id;
55718c2aff7Sartem    	char *desc;
55818c2aff7Sartem } static pnp_ids_list[] = {
55918c2aff7Sartem 	/* Crystal Semiconductor devices */
56018c2aff7Sartem 	{"CSC0000", "Crystal Semiconductor CS423x sound -- SB/WSS/OPL3 emulation"},
56118c2aff7Sartem 	{"CSC0001", "Crystal Semiconductor CS423x sound -- joystick"},
56218c2aff7Sartem 	{"CSC0003", "Crystal Semiconductor CS423x sound -- MPU401"},
56318c2aff7Sartem 	{"CSC0010", "Crystal Semiconductor CS423x sound -- control"},
56418c2aff7Sartem 	/* IBM devices */
56518c2aff7Sartem 	{"IBM0071", "IBM infrared communications device"},
56618c2aff7Sartem 	{"IBM3760", "IBM DSP"},
56718c2aff7Sartem 	{"IBM3780", "IBM pointing device"},
56818c2aff7Sartem         /* FinePoint devices */
56918c2aff7Sartem         {"FPI2004", "FinePoint Innovations Tablet"},
57018c2aff7Sartem         /* Fujitsu (Siemens Computers) devices */
57118c2aff7Sartem         {"FUJ02E5", "Wacom Serial Pen HID Tablet"},
57218c2aff7Sartem         {"FUJ02E6", "Fujitsu Serial TouchScreen"},
57318c2aff7Sartem 	/* interrupt controllers */
57418c2aff7Sartem 	{"PNP0000", "AT Interrupt Controller"},
57518c2aff7Sartem 	{"PNP0001", "EISA Interrupt Controller"},
57618c2aff7Sartem 	{"PNP0002", "MCA Interrupt Controller"},
57718c2aff7Sartem 	{"PNP0003", "APIC"},
57818c2aff7Sartem 	{"PNP0004", "Cyrix SLiC MP interrupt controller"},
57918c2aff7Sartem 	/* timers */
58018c2aff7Sartem 	{"PNP0100", "AT Timer"},
58118c2aff7Sartem 	{"PNP0101", "EISA Timer"},
58218c2aff7Sartem 	{"PNP0102", "MCA Timer"},
58318c2aff7Sartem 	/* DMA controllers */
58418c2aff7Sartem 	{"PNP0200", "AT DMA Controller"},
58518c2aff7Sartem 	{"PNP0201", "EISA DMA Controller"},
58618c2aff7Sartem 	{"PNP0202", "MCA DMA Controller"},
58718c2aff7Sartem 	/* keyboards */
58818c2aff7Sartem 	{"PNP0300", "IBM PC/XT keyboard controller (83-key)"},
58918c2aff7Sartem 	{"PNP0301", "IBM PC/AT keyboard controller (86-key)"},
59018c2aff7Sartem 	{"PNP0302", "IBM PC/XT keyboard controller (84-key)"},
59118c2aff7Sartem 	{"PNP0303", "IBM Enhanced (101/102-key, PS/2 mouse support)"},
59218c2aff7Sartem 	{"PNP0304", "Olivetti Keyboard (83-key)"},
59318c2aff7Sartem 	{"PNP0305", "Olivetti Keyboard (102-key)"},
59418c2aff7Sartem 	{"PNP0306", "Olivetti Keyboard (86-key)"},
59518c2aff7Sartem 	{"PNP0307", "Microsoft Windows(R) Keyboard"},
59618c2aff7Sartem 	{"PNP0308", "General Input Device Emulation Interface (GIDEI) legacy"},
59718c2aff7Sartem 	{"PNP0309", "Olivetti Keyboard (A101/102 key)"},
59818c2aff7Sartem 	{"PNP030A", "AT&T 302 keyboard"},
59918c2aff7Sartem 	{"PNP030B", "Reserved by Microsoft"},
60018c2aff7Sartem 	{"PNP0320", "Japanese 101-key keyboard"},
60118c2aff7Sartem 	{"PNP0321", "Japanese AX keyboard"},
60218c2aff7Sartem 	{"PNP0322", "Japanese 106-key keyboard A01"},
60318c2aff7Sartem 	{"PNP0323", "Japanese 106-key keyboard 002/003"},
60418c2aff7Sartem 	{"PNP0324", "Japanese 106-key keyboard 001"},
60518c2aff7Sartem 	{"PNP0325", "Japanese Toshiba Desktop keyboard"},
60618c2aff7Sartem 	{"PNP0326", "Japanese Toshiba Laptop keyboard"},
60718c2aff7Sartem 	{"PNP0327", "Japanese Toshiba Notebook keyboard"},
60818c2aff7Sartem 	{"PNP0340", "Korean 84-key keyboard"},
60918c2aff7Sartem 	{"PNP0341", "Korean 86-key keyboard"},
61018c2aff7Sartem 	{"PNP0342", "Korean Enhanced keyboard"},
61118c2aff7Sartem 	{"PNP0343", "Korean Enhanced keyboard 101b"},
61218c2aff7Sartem 	{"PNP0343", "Korean Enhanced keyboard 101c"},
61318c2aff7Sartem 	{"PNP0344", "Korean Enhanced keyboard 103"},
61418c2aff7Sartem 	/* parallel ports */
61518c2aff7Sartem 	{"PNP0400", "Standard LPT printer port"},
61618c2aff7Sartem 	{"PNP0401", "ECP printer port"},
61718c2aff7Sartem 	/* serial ports */
61818c2aff7Sartem 	{"PNP0500", "Standard PC COM port"},
61918c2aff7Sartem 	{"PNP0501", "16550A-compatible COM port"},
62018c2aff7Sartem 	{"PNP0502", "Multiport serial device (non-intelligent 16550)"},
62118c2aff7Sartem 	{"PNP0510", "Generic IRDA-compatible device"},
62218c2aff7Sartem 	{"PNP0511", "Generic IRDA-compatible device"},
62318c2aff7Sartem 	/* IDE controller */
62418c2aff7Sartem 	{"PNP0600", "Generic ESDI/IDE/ATA compatible hard disk controller"},
62518c2aff7Sartem 	{"PNP0601", "Plus Hardcard II"},
62618c2aff7Sartem 	{"PNP0602", "Plus Hardcard IIXL/EZ"},
62718c2aff7Sartem 	{"PNP0603", "Generic IDE supporting Microsoft Device Bay Specification"},
62818c2aff7Sartem 	{"PNP0604", "PC standard floppy disk controller"},
62918c2aff7Sartem 	{"PNP0605", "HP Omnibook floppy disk controller"},
63018c2aff7Sartem 	{"PNP0680", "Bus Master E-IDE controller"},
63118c2aff7Sartem 	{"PNP0700", "PC standard floppy disk controller"},
63218c2aff7Sartem 	{"PNP0701", "Standard floppy controller supporting MS Device Bay Spec"},
63318c2aff7Sartem 	/* system devices */
63418c2aff7Sartem 	{"PNP0800", "AT-style speaker sound"},
63518c2aff7Sartem 	/* obsolete devices */
63618c2aff7Sartem 	{"PNP0802", "Microsoft Sound System compatible device (obsolete, use PNPB0xx instead)"},
63718c2aff7Sartem 	/* display adapters / graphic cards */
63818c2aff7Sartem 	{"PNP0900", "VGA Compatible"},
63918c2aff7Sartem 	{"PNP0901", "Video Seven VRAM/VRAM II/1024i"},
64018c2aff7Sartem 	{"PNP0902", "IBM 8514/A Compatible"},
64118c2aff7Sartem 	{"PNP0903", "Trident VGA"},
64218c2aff7Sartem 	{"PNP0904", "Cirrus Logic Laptop VGA"},
64318c2aff7Sartem 	{"PNP0905", "Cirrus Logic VGA"},
64418c2aff7Sartem 	{"PNP0906", "Tseng Labs ET4000"},
64518c2aff7Sartem 	{"PNP0907", "Western Digital VGA"},
64618c2aff7Sartem 	{"PNP0908", "Western Digital Laptop VGA"},
64718c2aff7Sartem 	{"PNP0909", "S3 Inc. 911/924"},
64818c2aff7Sartem 	{"PNP090A", "ATI Ultra Pro/Plus (Mach 32)"},
64918c2aff7Sartem 	{"PNP090B", "ATI Ultra (Mach 8)"},
65018c2aff7Sartem 	{"PNP090C", "IBM XGA Compatible"},
65118c2aff7Sartem 	{"PNP090D", "ATI VGA Wonder"},
65218c2aff7Sartem 	{"PNP090E", "Weitek P9000 Graphics Adapter"},
65318c2aff7Sartem 	{"PNP090F", "Oak Technology VGA"},
65418c2aff7Sartem 	{"PNP0910", "Compaq QVision"},
65518c2aff7Sartem 	{"PNP0911", "IBM XGA/2"},
65618c2aff7Sartem 	{"PNP0912", "Tseng Labs ET4000 W32/W32i/W32p"},
65718c2aff7Sartem 	{"PNP0913", "S3 Inc. 801/928/964"},
65818c2aff7Sartem 	{"PNP0914", "Cirrus Logic 5429/5434 (memory mapped)"},
65918c2aff7Sartem 	{"PNP0915", "Compaq Advanced VGA (AVGA)"},
66018c2aff7Sartem 	{"PNP0916", "ATI Ultra Pro Turbo (Mach64)"},
66118c2aff7Sartem 	{"PNP0917", "Reserved by Microsoft"},
66218c2aff7Sartem 	{"PNP0918", "Matrox MGA"},
66318c2aff7Sartem 	{"PNP0919", "Compaq QVision 2000"},
66418c2aff7Sartem 	{"PNP091A", "Tseng Labs W128"},
66518c2aff7Sartem 	{"PNP0930", "Chips & Technologies Super VGA"},
66618c2aff7Sartem 	{"PNP0931", "Chips & Technologies Accelerator"},
66718c2aff7Sartem 	{"PNP0940", "NCR 77c22e Super VGA"},
66818c2aff7Sartem 	{"PNP0941", "NCR 77c32blt"},
66918c2aff7Sartem 	{"PNP09FF", "Plug and Play Monitors (VESA DDC)"},
67018c2aff7Sartem 	/* peripheral buses */
67118c2aff7Sartem 	{"PNP0A00", "ISA Bus"},
67218c2aff7Sartem 	{"PNP0A01", "EISA Bus"},
67318c2aff7Sartem 	{"PNP0A02", "MCA Bus"},
67418c2aff7Sartem 	{"PNP0A03", "PCI Bus"},
67518c2aff7Sartem 	{"PNP0A04", "VESA/VL Bus"},
67618c2aff7Sartem 	{"PNP0A05", "Generic ACPI Bus"},
67718c2aff7Sartem 	{"PNP0A06", "Generic ACPI Extended-IO Bus (EIO bus)"},
67818c2aff7Sartem 	/* system devices */
67918c2aff7Sartem 	{"PNP0B00", "AT Real-Time Clock"},
68018c2aff7Sartem 	{"PNP0C00", "Plug and Play BIOS (only created by the root enumerator)"},
68118c2aff7Sartem 	{"PNP0C01", "System Board"},
68218c2aff7Sartem 	{"PNP0C02", "General ID for reserving resources required by PnP motherboard registers. (Not device specific.)"},
68318c2aff7Sartem 	{"PNP0C03", "Plug and Play BIOS Event Notification Interrupt"},
68418c2aff7Sartem 	{"PNP0C04", "Math Coprocessor"},
68518c2aff7Sartem 	{"PNP0C05", "APM BIOS (Version independent)"},
68618c2aff7Sartem 	{"PNP0C06", "Reserved for identification of early Plug and Play BIOS implementation"},
68718c2aff7Sartem 	{"PNP0C07", "Reserved for identification of early Plug and Play BIOS implementation"},
68818c2aff7Sartem 	{"PNP0C08", "ACPI system board hardware"},
68918c2aff7Sartem 	{"PNP0C09", "ACPI Embedded Controller"},
69018c2aff7Sartem 	{"PNP0C0A", "ACPI Control Method Battery"},
69118c2aff7Sartem 	{"PNP0C0B", "ACPI Fan"},
69218c2aff7Sartem 	{"PNP0C0C", "ACPI power button device"},
69318c2aff7Sartem 	{"PNP0C0D", "ACPI lid device"},
69418c2aff7Sartem 	{"PNP0C0E", "ACPI sleep button device"},
69518c2aff7Sartem 	{"PNP0C0F", "PCI interrupt link device"},
69618c2aff7Sartem 	{"PNP0C10", "ACPI system indicator device"},
69718c2aff7Sartem 	{"PNP0C11", "ACPI thermal zone"},
69818c2aff7Sartem 	{"PNP0C12", "Device Bay Controller"},
69918c2aff7Sartem 	{"PNP0C13", "Plug and Play BIOS (used when ACPI mode cannot be used)"},
70018c2aff7Sartem 	{"PNP0CF0", "Compaq LTE Lite Support"},
70118c2aff7Sartem 	{"PNP0CF1", "Compaq LTE Elite Support"},
70218c2aff7Sartem 	/* PCMCIA controllers */
70318c2aff7Sartem 	{"PNP0E00", "Intel 82365-Compatible PCMCIA Controller"},
70418c2aff7Sartem 	{"PNP0E01", "Cirrus Logic CL-PD6720 PCMCIA Controller"},
70518c2aff7Sartem 	{"PNP0E02", "VLSI VL82C146 PCMCIA Controller"},
70618c2aff7Sartem 	{"PNP0E03", "Intel 82365-compatible CardBus controller"},
70718c2aff7Sartem 	/* mice */
70818c2aff7Sartem 	{"PNP0F00", "Microsoft Bus Mouse"},
70918c2aff7Sartem 	{"PNP0F01", "Microsoft Serial Mouse"},
71018c2aff7Sartem 	{"PNP0F02", "Microsoft InPort Mouse"},
71118c2aff7Sartem 	{"PNP0F03", "Microsoft PS/2-style Mouse"},
71218c2aff7Sartem 	{"PNP0F04", "Mouse Systems Mouse"},
71318c2aff7Sartem 	{"PNP0F05", "Mouse Systems 3-Button Mouse (COM2)"},
71418c2aff7Sartem 	{"PNP0F06", "Genius Mouse (COM1)"},
71518c2aff7Sartem 	{"PNP0F07", "Genius Mouse (COM2)"},
71618c2aff7Sartem 	{"PNP0F08", "Logitech Serial Mouse"},
71718c2aff7Sartem 	{"PNP0F09", "Microsoft BallPoint Serial Mouse"},
71818c2aff7Sartem 	{"PNP0F0A", "Microsoft Plug and Play Mouse"},
71918c2aff7Sartem 	{"PNP0F0B", "Microsoft Plug and Play BallPoint Mouse"},
72018c2aff7Sartem 	{"PNP0F0C", "Microsoft-compatible Serial Mouse"},
72118c2aff7Sartem 	{"PNP0F0D", "Microsoft-compatible InPort-compatible Mouse"},
72218c2aff7Sartem 	{"PNP0F0E", "Microsoft-compatible PS/2-style Mouse"},
72318c2aff7Sartem 	{"PNP0F0F", "Microsoft-compatible Serial BallPoint-compatible Mouse"},
72418c2aff7Sartem 	{"PNP0F10", "Texas Instruments QuickPort Mouse"},
72518c2aff7Sartem 	{"PNP0F11", "Microsoft-compatible Bus Mouse"},
72618c2aff7Sartem 	{"PNP0F12", "Logitech PS/2-style Mouse"},
72718c2aff7Sartem 	{"PNP0F13", "PS/2 Port for PS/2-style Mice"},
72818c2aff7Sartem 	{"PNP0F14", "Microsoft Kids Mouse"},
72918c2aff7Sartem 	{"PNP0F15", "Logitech bus mouse"},
73018c2aff7Sartem 	{"PNP0F16", "Logitech SWIFT device"},
73118c2aff7Sartem 	{"PNP0F17", "Logitech-compatible serial mouse"},
73218c2aff7Sartem 	{"PNP0F18", "Logitech-compatible bus mouse"},
73318c2aff7Sartem 	{"PNP0F19", "Logitech-compatible PS/2-style Mouse"},
73418c2aff7Sartem 	{"PNP0F1A", "Logitech-compatible SWIFT Device"},
73518c2aff7Sartem 	{"PNP0F1B", "HP Omnibook Mouse"},
73618c2aff7Sartem 	{"PNP0F1C", "Compaq LTE Trackball PS/2-style Mouse"},
73718c2aff7Sartem 	{"PNP0F1D", "Compaq LTE Trackball Serial Mouse"},
73818c2aff7Sartem 	{"PNP0F1E", "Microsoft Kids Trackball Mouse"},
73918c2aff7Sartem 	{"PNP0F1F", "Reserved by Microsoft Input Device Group"},
74018c2aff7Sartem 	{"PNP0F20", "Reserved by Microsoft Input Device Group"},
74118c2aff7Sartem 	{"PNP0F21", "Reserved by Microsoft Input Device Group"},
74218c2aff7Sartem 	{"PNP0F22", "Reserved by Microsoft Input Device Group"},
74318c2aff7Sartem 	{"PNP0F23", "Reserved by Microsoft Input Device Group"},
74418c2aff7Sartem 	{"PNP0FFF", "Reserved by Microsoft Systems"},
74518c2aff7Sartem 	{"PNP0XXX", "Unknown System Device"},
74618c2aff7Sartem 	/* network cards */
74718c2aff7Sartem 	{"PNP8000", "Network Adapter"},
74818c2aff7Sartem 	{"PNP8001", "Novell/Anthem NE3200"},
74918c2aff7Sartem 	{"PNP8004", "Compaq NE3200"},
75018c2aff7Sartem 	{"PNP8006", "Intel EtherExpress/32"},
75118c2aff7Sartem 	{"PNP8008", "HP EtherTwist EISA LAN Adapter/32 (HP27248A)"},
75218c2aff7Sartem 	{"PNP8065", "Ungermann-Bass NIUps or NIUps/EOTP"},
75318c2aff7Sartem 	{"PNP8072", "DEC (DE211) EtherWorks MC/TP"},
75418c2aff7Sartem 	{"PNP8073", "DEC (DE212) EtherWorks MC/TP_BNC"},
75518c2aff7Sartem 	{"PNP8074", "HP MC LAN Adapter/16 TP (PC27246)"},
75618c2aff7Sartem 	{"PNP8078", "DCA 10 Mb MCA"},
75718c2aff7Sartem 	{"PNP807F", "Racal NI9210"},
75818c2aff7Sartem 	{"PNP8081", "Pure Data Ethernet"},
75918c2aff7Sartem 	{"PNP8096", "Thomas-Conrad TC4046"},
76018c2aff7Sartem 	{"PNP80C9", "IBM Token Ring"},
76118c2aff7Sartem 	{"PNP80CA", "IBM Token Ring II"},
76218c2aff7Sartem 	{"PNP80CB", "IBM Token Ring II/Short"},
76318c2aff7Sartem 	{"PNP80CC", "IBM Token Ring 4/16Mbs"},
76418c2aff7Sartem 	{"PNP80D3", "Novell/Anthem NE1000"},
76518c2aff7Sartem 	{"PNP80D4", "Novell/Anthem NE2000"},
76618c2aff7Sartem 	{"PNP80D5", "NE1000 Compatible"},
76718c2aff7Sartem 	{"PNP80D6", "NE2000 Compatible"},
76818c2aff7Sartem 	{"PNP80D7", "Novell/Anthem NE1500T"},
76918c2aff7Sartem 	{"PNP80D8", "Novell/Anthem NE2100"},
77018c2aff7Sartem 	{"PNP80D9", "NE2000 Plus"},
77118c2aff7Sartem 	{"PNP80DD", "SMC ARCNETPC"},
77218c2aff7Sartem 	{"PNP80DE", "SMC ARCNET PC100, PC200"},
77318c2aff7Sartem 	{"PNP80DF", "SMC ARCNET PC110, PC210, PC250"},
77418c2aff7Sartem 	{"PNP80E0", "SMC ARCNET PC130/E"},
77518c2aff7Sartem 	{"PNP80E1", "SMC ARCNET PC120, PC220, PC260"},
77618c2aff7Sartem 	{"PNP80E2", "SMC ARCNET PC270/E"},
77718c2aff7Sartem 	{"PNP80E5", "SMC ARCNET PC600W, PC650W"},
77818c2aff7Sartem 	{"PNP80E7", "DEC DEPCA"},
77918c2aff7Sartem 	{"PNP80E8", "DEC (DE100) EtherWorks LC"},
78018c2aff7Sartem 	{"PNP80E9", "DEC (DE200) EtherWorks Turbo"},
78118c2aff7Sartem 	{"PNP80EA", "DEC (DE101) EtherWorks LC/TP"},
78218c2aff7Sartem 	{"PNP80EB", "DEC (DE201) EtherWorks Turbo/TP"},
78318c2aff7Sartem 	{"PNP80EC", "DEC (DE202) EtherWorks Turbo/TP_BNC"},
78418c2aff7Sartem 	{"PNP80ED", "DEC (DE102) EtherWorks LC/TP_BNC"},
78518c2aff7Sartem 	{"PNP80EE", "DEC EE101 (Built-In)"},
78618c2aff7Sartem 	{"PNP80EF", "DEC PC 433 WS (Built-In)"},
78718c2aff7Sartem 	{"PNP80F1", "3Com EtherLink Plus"},
78818c2aff7Sartem 	{"PNP80F3", "3Com EtherLink II or IITP (8 or 16-bit)"},
78918c2aff7Sartem 	{"PNP80F4", "3Com TokenLink"},
79018c2aff7Sartem 	{"PNP80F6", "3Com EtherLink 16"},
79118c2aff7Sartem 	{"PNP80F7", "3Com EtherLink III"},
79218c2aff7Sartem 	{"PNP80F8", "3Com Generic Etherlink Plug and Play Device"},
79318c2aff7Sartem 	{"PNP80FB", "Thomas Conrad TC6045"},
79418c2aff7Sartem 	{"PNP80FC", "Thomas Conrad TC6042"},
79518c2aff7Sartem 	{"PNP80FD", "Thomas Conrad TC6142"},
79618c2aff7Sartem 	{"PNP80FE", "Thomas Conrad TC6145"},
79718c2aff7Sartem 	{"PNP80FF", "Thomas Conrad TC6242"},
79818c2aff7Sartem 	{"PNP8100", "Thomas Conrad TC6245"},
79918c2aff7Sartem 	{"PNP8101", "Thomas-Conrad TC4045"},
80018c2aff7Sartem 	{"PNP8104", "Thomas-Conrad TC4035"},
80118c2aff7Sartem 	{"PNP8105", "DCA 10 MB"},
80218c2aff7Sartem 	{"PNP8106", "DCA 10 MB Fiber Optic"},
80318c2aff7Sartem 	{"PNP8107", "DCA 10 MB Twisted Pair"},
80418c2aff7Sartem 	{"PNP8113", "Racal NI6510"},
80518c2aff7Sartem 	{"PNP8114", "Racal NI5210/8 or NI5210/16"},
80618c2aff7Sartem 	{"PNP8119", "Ungermann-Bass pcNIU"},
80718c2aff7Sartem 	{"PNP811A", "Ungermann-Bass pcNIU/ex 128K"},
808*55fea89dSDan Cross 	{"PNP811B", "Ungermann-Bass pcNIU/ex 512K"},
80918c2aff7Sartem 	{"PNP811C", "Ungermann-Bass NIUpc"},
81018c2aff7Sartem 	{"PNP811D", "Ungermann-Bass NIUpc/3270"},
81118c2aff7Sartem 	{"PNP8120", "Ungermann-Bass NIUpc/EOTP"},
81218c2aff7Sartem 	{"PNP8123", "SMC StarCard PLUS (WD/8003S)"},
81318c2aff7Sartem 	{"PNP8124", "SMC StarCard PLUS With On Board Hub (WD/8003SH)"},
81418c2aff7Sartem 	{"PNP8125", "SMC EtherCard PLUS (WD/8003E)"},
81518c2aff7Sartem 	{"PNP8126", "SMC EtherCard PLUS With Boot ROM Socket (WD/8003EBT)"},
81618c2aff7Sartem 	{"PNP8127", "SMC EtherCard PLUS With Boot ROM Socket (WD/8003EB)"},
81718c2aff7Sartem 	{"PNP8128", "SMC EtherCard PLUS TP (WD/8003WT)"},
81818c2aff7Sartem 	{"PNP812A", "SMC EtherCard PLUS 16 With Boot ROM Socket (WD/8013EBT)"},
81918c2aff7Sartem 	{"PNP812D", "Intel EtherExpress 16 or 16TP"},
82018c2aff7Sartem 	{"PNP812F", "Intel TokenExpress 16/4"},
82118c2aff7Sartem 	{"PNP8130", "Intel TokenExpress MCA 16/4"},
82218c2aff7Sartem 	{"PNP8132", "Intel EtherExpress 16 (MCA)"},
82318c2aff7Sartem 	{"PNP8133", "Compaq Ethernet 16E"},
82418c2aff7Sartem 	{"PNP8137", "Artisoft AE-1"},
82518c2aff7Sartem 	{"PNP8138", "Artisoft AE-2 or AE-3"},
82618c2aff7Sartem 	{"PNP8141", "Amplicard AC 210/XT"},
82718c2aff7Sartem 	{"PNP8142", "Amplicard AC 210/AT"},
82818c2aff7Sartem 	{"PNP814B", "Everex SpeedLink /PC16 (EV2027)"},
82918c2aff7Sartem 	{"PNP8155", "HP PC LAN Adapter/8 TP (HP27245)"},
83018c2aff7Sartem 	{"PNP8156", "HP PC LAN Adapter/16 TP (HP27247A)"},
83118c2aff7Sartem 	{"PNP8157", "HP PC LAN Adapter/8 TL (HP27250)"},
83218c2aff7Sartem 	{"PNP8158", "HP PC LAN Adapter/16 TP Plus (HP27247B)"},
83318c2aff7Sartem 	{"PNP8159", "HP PC LAN Adapter/16 TL Plus (HP27252)"},
83418c2aff7Sartem 	{"PNP815F", "National Semiconductor Ethernode *16AT"},
83518c2aff7Sartem 	{"PNP8160", "National Semiconductor AT/LANTIC EtherNODE 16-AT3"},
83618c2aff7Sartem 	{"PNP8169", "NCR StarCard"},
83718c2aff7Sartem 	{"PNP816A", "NCR Token-Ring 4 Mbs ISA"},
83818c2aff7Sartem 	{"PNP816B", "NCR WaveLAN AT"},
83918c2aff7Sartem 	{"PNP816C", "NCR WaveLan MC"},
84018c2aff7Sartem 	{"PNP816D", "NCR Token-Ring 16/4 Mbs ISA"},
84118c2aff7Sartem 	{"PNP8191", "Olicom 16/4 Token-Ring Adapter"},
84218c2aff7Sartem 	{"PNP81A5", "Research Machines Ethernet"},
84318c2aff7Sartem 	{"PNP81B9", "ToshibaLAN (internal)"},
84418c2aff7Sartem 	{"PNP81C3", "SMC EtherCard PLUS Elite (WD/8003EP)"},
84518c2aff7Sartem 	{"PNP81C4", "SMC EtherCard PLUS 10T (WD/8003W)"},
84618c2aff7Sartem 	{"PNP81C5", "SMC EtherCard PLUS Elite 16 (WD/8013EP)"},
84718c2aff7Sartem 	{"PNP81C6", "SMC EtherCard PLUS Elite 16T (WD/8013W)"},
84818c2aff7Sartem 	{"PNP81C7", "SMC EtherCard PLUS Elite 16 Combo (WD/8013EW or 8013EWC)"},
84918c2aff7Sartem 	{"PNP81C8", "SMC EtherElite Ultra 16"},
85018c2aff7Sartem 	{"PNP81C9", "SMC TigerCard (8216L, 8216LC, 8216LT)"},
85118c2aff7Sartem 	{"PNP81CA", "SMC EtherEZ (8416)"},
85218c2aff7Sartem 	{"PNP81D7", "Madge Smart 16/4 PC Ringnode"},
85318c2aff7Sartem 	{"PNP81D8", "Madge Smart 16/4 Ringnode ISA"},
85418c2aff7Sartem 	{"PNP81E4", "Pure Data PDI9025-32 (Token Ring)"},
85518c2aff7Sartem 	{"PNP81E6", "Pure Data PDI508+ (ArcNet)"},
85618c2aff7Sartem 	{"PNP81E7", "Pure Data PDI516+ (ArcNet)"},
85718c2aff7Sartem 	{"PNP81EB", "Proteon Token Ring (P1390)"},
85818c2aff7Sartem 	{"PNP81EC", "Proteon Token Ring (P1392)"},
85918c2aff7Sartem 	{"PNP81ED", "Proteon Token Ring ISA (P1340)"},
86018c2aff7Sartem 	{"PNP81EE", "Proteon Token Ring ISA (P1342)"},
86118c2aff7Sartem 	{"PNP81EF", "Proteon Token Ring ISA (P1346)"},
86218c2aff7Sartem 	{"PNP81F0", "Proteon Token Ring ISA (P1347)"},
86318c2aff7Sartem 	{"PNP81FF", "Cabletron E2000 Series DNI"},
86418c2aff7Sartem 	{"PNP8200", "Cabletron E2100 Series DNI"},
86518c2aff7Sartem 	{"PNP8201", "Cabletron T2015 4/16 Mbit/s DNI"},
86618c2aff7Sartem 	{"PNP8209", "Zenith Data Systems Z-Note"},
86718c2aff7Sartem 	{"PNP820A", "Zenith Data Systems NE2000-Compatible"},
86818c2aff7Sartem 	{"PNP8213", "Xircom Pocket Ethernet II"},
86918c2aff7Sartem 	{"PNP8214", "Xircom Pocket Ethernet I"},
87018c2aff7Sartem 	{"PNP8215", "Xircom Pocket Ethernet III Adapter"},
87118c2aff7Sartem 	{"PNP821D", "RadiSys EXM-10"},
87218c2aff7Sartem 	{"PNP8227", "SMC 3000 Series"},
87318c2aff7Sartem 	{"PNP8228", "SMC 91C2 controller"},
87418c2aff7Sartem 	{"PNP8231", "AMD AM2100/AM1500T"},
87518c2aff7Sartem 	{"PNP824F", "RCE 10Base-T (16 bit)"},
87618c2aff7Sartem 	{"PNP8250", "RCE 10Base-T (8 bit)"},
87718c2aff7Sartem 	{"PNP8263", "Tulip NCC-16"},
87818c2aff7Sartem 	{"PNP8277", "Exos 105"},
87918c2aff7Sartem 	{"PNP828A", "Intel '595 based Ethernet"},
88018c2aff7Sartem 	{"PNP828B", "TI2000-style Token Ring"},
88118c2aff7Sartem 	{"PNP828C", "AMD PCNet Family cards"},
88218c2aff7Sartem 	{"PNP828D", "AMD PCNet32 (VL version)"},
88318c2aff7Sartem 	{"PNP8294", "IrDA Infrared NDIS driver (Microsoft-supplied)"},
88418c2aff7Sartem 	{"PNP82BD", "IBM PCMCIA-NIC"},
88518c2aff7Sartem 	{"PNP82C0", "Eagle Technology NE200T"},
88618c2aff7Sartem 	{"PNP82C2", "Xircom CE10"},
88718c2aff7Sartem 	{"PNP82C3", "Xircom CEM2"},
88818c2aff7Sartem 	{"PNP82C4", "Xircom CE2"},
88918c2aff7Sartem 	{"PNP8321", "DEC Ethernet (All Types)"},
89018c2aff7Sartem 	{"PNP8323", "SMC EtherCard (All Types except 8013/A)"},
89118c2aff7Sartem 	{"PNP8324", "ARCNET Compatible"},
89218c2aff7Sartem 	{"PNP8325", "SMC TokenCard PLUS (8115T)"},
89318c2aff7Sartem 	{"PNP8326", "Thomas Conrad (All Arcnet Types)"},
89418c2aff7Sartem 	{"PNP8327", "IBM Token Ring (All Types)"},
89518c2aff7Sartem 	{"PNP8328", "Ungermann-Bass NIU"},
89618c2aff7Sartem 	{"PNP8329", "Proteon ProNET-4/16 ISA Token Ring (P1392+,P1392,1390)"},
89718c2aff7Sartem 	{"PNP8385", "Remote Network Access [RNA] Driver"},
89818c2aff7Sartem 	{"PNP8387", "Remote Network Access [RNA] PPP Driver"},
89918c2aff7Sartem 	{"PNP8388", "Reserved for Microsoft Networking components"},
90018c2aff7Sartem 	{"PNP8389", "Peer IrLAN infrared driver (Microsoft-supplied)"},
90118c2aff7Sartem 	{"PNP8390", "Generic network adapter"},
90218c2aff7Sartem 	{"PNP8XXX", "Unknown Network Adapter"},
90318c2aff7Sartem 	/* modems */
90418c2aff7Sartem 	{"PNP9000", "Modem"},
90518c2aff7Sartem 	/* CD controller */
90618c2aff7Sartem 	{"PNPA000", "Adaptec 154x compatible SCSI controller"},
90718c2aff7Sartem 	{"PNPA001", "Adaptec 174x compatible SCSI controller"},
90818c2aff7Sartem 	{"PNPA002", "Future Domain 16-700 compatible controller"},
90918c2aff7Sartem 	{"PNPA003", "Mitsumi CD-ROM adapter (Panasonic spec., used on SBPro/SB16)"},
91018c2aff7Sartem 	{"PNPA01B", "Trantor 128 SCSI Controller"},
91118c2aff7Sartem 	{"PNPA01D", "Trantor T160 SCSI Controller"},
91218c2aff7Sartem 	{"PNPA01E", "Trantor T338 Parallel SCSI controller"},
91318c2aff7Sartem 	{"PNPA01F", "Trantor T348 Parallel SCSI controller"},
91418c2aff7Sartem 	{"PNPA020", "Trantor Media Vision SCSI controller"},
91518c2aff7Sartem 	{"PNPA022", "Always IN-2000 SCSI controller"},
91618c2aff7Sartem 	{"PNPA02B", "Sony proprietary CD-ROM controller"},
91718c2aff7Sartem 	{"PNPA02D", "Trantor T13b 8-bit SCSI controller"},
91818c2aff7Sartem 	{"PNPA02F", "Trantor T358 Parallel SCSI controller"},
91918c2aff7Sartem 	{"PNPA030", "Mitsumi LU-005 Single Speed CD-ROM controller + drive"},
92018c2aff7Sartem 	{"PNPA031", "Mitsumi FX-001 Single Speed CD-ROM controller + drive"},
92118c2aff7Sartem 	{"PNPA032", "Mitsumi FX-001 Double Speed CD-ROM controller + drive"},
92218c2aff7Sartem 	{"PNPAXXX", "Unknown SCSI, Proprietary CD Adapter"},
92318c2aff7Sartem 	/* multimedia devices */
92418c2aff7Sartem 	{"PNPB000", "Creative Labs Sound Blaster 1.5 (or compatible sound device)"},
92518c2aff7Sartem 	{"PNPB001", "Creative Labs Sound Blaster 2.0 (or compatible sound device)"},
92618c2aff7Sartem 	{"PNPB002", "Creative Labs Sound Blaster Pro (or compatible sound device)"},
92718c2aff7Sartem 	{"PNPB003", "Creative Labs Sound Blaster 16 (or compatible sound device)"},
92818c2aff7Sartem 	{"PNPB004", "MediaVision Thunderboard (or compatible sound device)"},
92918c2aff7Sartem 	{"PNPB005", "Adlib-compatible FM synthesizer device"},
93018c2aff7Sartem 	{"PNPB006", "MPU401 compatible"},
93118c2aff7Sartem 	{"PNPB007", "Microsoft Windows Sound System-compatible sound device"},
93218c2aff7Sartem 	{"PNPB008", "Compaq Business Audio"},
93318c2aff7Sartem 	{"PNPB009", "Plug and Play Microsoft Windows Sound System Device"},
93418c2aff7Sartem 	{"PNPB00A", "MediaVision Pro Audio Spectrum (Trantor SCSI enabled, Thunder Chip Disabled)"},
93518c2aff7Sartem 	{"PNPB00B", "MediaVision Pro Audio 3D"},
93618c2aff7Sartem 	{"PNPB00C", "MusicQuest MQX-32M"},
93718c2aff7Sartem 	{"PNPB00D", "MediaVision Pro Audio Spectrum Basic (No Trantor SCSI, Thunder Chip Enabled)"},
93818c2aff7Sartem 	{"PNPB00E", "MediaVision Pro Audio Spectrum (Trantor SCSI enabled, Thunder Chip Disabled)"},
93918c2aff7Sartem 	{"PNPB00F", "MediaVision Jazz-16 chipset (OEM Versions)"},
94018c2aff7Sartem 	{"PNPB010", "Orchid Videola - Auravision VxP500 chipset"},
94118c2aff7Sartem 	{"PNPB018", "MediaVision Pro Audio Spectrum 8-bit"},
94218c2aff7Sartem 	{"PNPB019", "MediaVision Pro Audio Spectrum Basic (No Trantor SCSI, Thunder Chip Enabled)"},
94318c2aff7Sartem 	{"PNPB020", "Yamaha OPL3-compatible FM synthesizer device"},
94418c2aff7Sartem 	{"PNPB02F", "Joystick/Game port"},
94518c2aff7Sartem 	{"PNPB077", "OAK Mozart Sound System"},
94618c2aff7Sartem 	{"PNPB078", "OAK Mozart Sound System MPU-401"},
94718c2aff7Sartem 	{"PNPBXXX", "Unknown Multimedia Device"},
94818c2aff7Sartem 	/* modems */
94918c2aff7Sartem 	{"PNPC000", "Compaq 14400 Modem (TBD)"},
95018c2aff7Sartem 	{"PNPC001", "Compaq 2400/9600 Modem (TBD)"},
95118c2aff7Sartem 	{"PNPCXXX", "Unknown Modem"},
95218c2aff7Sartem 	/* some other network cards */
95318c2aff7Sartem 	{"PNPD300", "SK-NET TR4/16+ Token-Ring"},
95418c2aff7Sartem 	{"PNPE000", "SK-NET G16, G16/TP Ethernet"},
95518c2aff7Sartem 	{"PNPF000", "SK-NET FDDI-FI FDDI LAN"},
95618c2aff7Sartem 	/* Toshiba devices */
95718c2aff7Sartem 	{"TOS6200", "Toshiba Notebook Extra HCI driver"},
95818c2aff7Sartem 	{"TOS6202", "Toshiba Notebook Extra HCI driver"},
95918c2aff7Sartem 	{"TOS6207", "Toshiba Notebook Extra HCI driver"},
96018c2aff7Sartem 	{"TOS7400", "Toshiba AcuPoint"},
96118c2aff7Sartem 	/* Wacom devices */
96218c2aff7Sartem 	{"WACf004", "Wacom Serial Tablet PC Pen Tablet/Digitizer"},
96318c2aff7Sartem 	{"WACf005", "Wacom Serial Tablet PC Pen Tablet/Digitizer"},
96418c2aff7Sartem 	{"WACf006", "Wacom Serial Tablet PC Pen Tablet/Digitizer"}
96518c2aff7Sartem };
96618c2aff7Sartem 
967*55fea89dSDan Cross static int
ids_comp_pnp(const void * id1,const void * id2)96818c2aff7Sartem ids_comp_pnp(const void *id1, const void *id2) {
96918c2aff7Sartem         struct pnp_id *pnp_id1 = (struct pnp_id *) id1;
97018c2aff7Sartem         struct pnp_id *pnp_id2 = (struct pnp_id *) id2;
97118c2aff7Sartem         return strcasecmp(pnp_id1->id, pnp_id2->id);
97218c2aff7Sartem }
97318c2aff7Sartem 
97418c2aff7Sartem void
ids_find_pnp(const char * pnp_id,char ** pnp_description)97518c2aff7Sartem ids_find_pnp (const char *pnp_id, char **pnp_description)
97618c2aff7Sartem {
97718c2aff7Sartem 	static gboolean sorted = FALSE;
97818c2aff7Sartem 	struct pnp_id search, *res;
979*55fea89dSDan Cross 
98018c2aff7Sartem 	if (!sorted) {
98118c2aff7Sartem 		/* sort the list, to be sure that all is in correc order */
982*55fea89dSDan Cross 		qsort(pnp_ids_list, sizeof(pnp_ids_list)/sizeof(pnp_ids_list[0]),
98318c2aff7Sartem 		      sizeof(struct pnp_id), ids_comp_pnp);
98418c2aff7Sartem 		sorted = TRUE;
98518c2aff7Sartem 	}
98618c2aff7Sartem 
98718c2aff7Sartem         search.id = (char *) pnp_id;
988*55fea89dSDan Cross         res = bsearch(&search, pnp_ids_list, sizeof(pnp_ids_list)/sizeof(pnp_ids_list[0]),
98918c2aff7Sartem 		      sizeof(struct pnp_id), ids_comp_pnp);
99018c2aff7Sartem 
99118c2aff7Sartem         if (res != NULL)
99218c2aff7Sartem         	*pnp_description = res->desc;
99318c2aff7Sartem 	else
994*55fea89dSDan Cross         	*pnp_description = NULL;
99518c2aff7Sartem         return;
99618c2aff7Sartem }
997