usba_devdb.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#define USBA_FRAMEWORK
/*
* Reader Writer locks have problem with warlock. warlock is unable to
* decode that the structure is local and doesn't need locking
*/
/* function prototypes */
static int usb_devdb_compare_pathnames(char *, char *);
static int usba_devdb_compare(const void *, const void *);
static int usba_devdb_build_device_database();
static void usba_devdb_destroy_device_database();
/*
* usba_devdb_initialization
* Initialize this module that builds the usb device database
*/
void
{
"usba_devdb_initialization");
/* now create the avl tree */
sizeof (usba_devdb_info_t),
(void) usba_devdb_build_device_database();
}
/*
* usba_devdb_destroy
* Free up all the resources being used by this module
*/
void
{
"usba_devdb_destroy");
}
/*
* usba_devdb_get_var_type:
* returns the field from the token
*/
static config_field_t
usba_devdb_get_var_type(char *str)
{
cfgvar = &usba_cfg_varlist[0];
break;
} else {
cfgvar++;
}
}
}
/*
* usba_devdb_get_conf_rec:
* Fetch one record from the file
*/
static token_t
{
char tokval[MAXPATHLEN];
enum {
} parse_state = USB_NEWVAR;
sizeof (usba_configrec_t), KM_SLEEP);
switch (token) {
case STAR:
case POUND:
/* skip comments */
break;
case NEWLINE:
break;
case NAME:
case STRING:
switch (parse_state) {
case USB_NEWVAR:
"Syntax Error: Invalid field %s",
tokval);
} else {
}
break;
case USB_VAR_VALUE:
if ((cfgvar == USB_VENDOR) ||
(cfgvar == USB_PRODUCT) ||
(cfgvar == USB_CFGNDX)) {
"Syntax Error: Invalid value %s"
" for field: %s\n", tokval,
switch (cfgvar) {
case USB_SELECTION:
break;
case USB_SRNO:
break;
case USB_PATH:
break;
case USB_DRIVER:
break;
default:
}
} else {
"Syntax Error: Invalid value %s"
" for field: %s\n", tokval,
}
break;
case USB_ERROR:
/* just skip */
break;
default:
"Syntax Error: at %s", tokval);
break;
}
break;
case EQUALS:
if (parse_state == USB_CONFIG_VAR) {
"Syntax Error: unexpected '='");
} else {
}
} else if (parse_state != USB_ERROR) {
"Syntax Error: unexpected '='");
}
break;
case HEXVAL:
case DECVAL:
USB_NONE)) {
switch (cfgvar) {
case USB_VENDOR:
break;
case USB_PRODUCT:
break;
case USB_CFGNDX:
break;
default:
"Syntax Error: Invalid value for "
"%s",
}
} else if (parse_state != USB_ERROR) {
}
break;
default:
tokval);
break;
}
}
return (token);
}
/*
* usba_devdb_free_rec:
* Free the record allocated in usba_devdb_get_conf_rec.
* We use kobj_free_string as kobj_get_string allocates memory
* in mod_sysfile_arena.
*/
static void
{
}
}
}
}
}
/*
* usb_devdb_compare_pathnames:
* Compare the two pathnames. If we are building the tree, we do a
* straight string compare to enable correct tree generation. If we
* are searching for a matching node, we compare only the selected
* portion of the pathname to give a correct match.
*/
static int
{
int rval;
if (usba_build_devdb == B_TRUE) {
/* this is a straight string compare */
if (rval < 0) {
return (-1);
} else if (rval > 0) {
return (+1);
} else {
return (0);
}
} else {
/*
* Comparing on this is tricky.
* p1 is the string hubd is looking for &
* p2 is the string in the device db.
* First compare till .../hubd@P
* Second compare is just P in "device@P"
*/
if (rval < 0) {
return (-1);
} else if (rval > 0) {
return (+1);
} else {
/* now compare the ports */
return (-1);
return (+1);
} else {
/* finally got a match */
return (0);
}
}
}
return (0);
} else {
return (-1);
} else {
return (+1);
}
}
}
/*
* usba_devdb_compare
* Compares the two nodes. Returns -1 when p1 < p2, 0 when p1 == p2
* and +1 when p1 > p2. This function is invoked by avl_find
* Here p1 is always the node that we are trying to insert or match in
* the device database.
*/
static int
{
int rval;
"usba_devdb_compare: p1=0x%p u1=0x%p p2=0x%p u2=0x%p",
/* first match vendor id */
return (-1);
return (+1);
} else {
/* idvendor match, now check idproduct */
return (-1);
return (+1);
} else {
/* idproduct match, now check serial no. */
if (rval > 0) {
return (+1);
} else if (rval < 0) {
return (-1);
} else {
/* srno. matches */
return (usb_devdb_compare_pathnames(
}
return (usb_devdb_compare_pathnames(
} else {
return (-1);
} else {
return (+1);
}
}
}
}
}
/*
* usba_devdb_build_device_database
* Builds a height balanced tree of all the records present in the file.
* Records that are "not enabled" and are duplicate are discarded.
*/
static int
{
"usba_devdb_build_device_database: Start");
do {
"enable") != 0)) {
/* we don't store disabled entries */
continue;
}
sizeof (usba_devdb_info_t), KM_SLEEP);
NULL) {
/* insert new node */
} else {
/*
* we don't maintain duplicate entries
*/
sizeof (usba_devdb_info_t));
}
}
}
"usba_devdb_build_device_database: End");
/* XXX: return the no. of errors encountered */
return (0);
}
/*
* usba_devdb_destroy_device_database
* Destory all records in the tree
*/
static void
{
"usba_devdb_destroy_device_database");
/* while there are nodes in the tree, keep destroying them */
while ((dbnode = (usba_devdb_info_t *)
/*
* destroy record
* destroy tree node
*/
}
}
/*
* usba_devdb_get_user_preferences
* Returns configrec structure to the caller that contains user
* preferences for the device pointed by the parameters.
* a pathname. If search fails, we search for a rule that is generic
* i.e. without serial no. and pathname.
*/
char *pathname)
{
"usba_devdb_get_user_preferences");
/* fill in the requested parameters */
/* try to find a perfect match in the device database */
#ifdef __lock_lint
#endif
/* look for a generic rule */
&where);
#ifdef __lock_lint
#endif
}
if (dbnode) {
} else {
return (NULL);
}
}
/*
* usba_devdb_refresh
* Reinitializes the device database. It destroys the old one and creates
* a new one by re-reading the file.
*/
int
{
/* destroy all nodes in the existing database */
/* now build a new one */
(void) usba_devdb_build_device_database();
return (0);
}