1*b3d94504SStephan Aßmus /* 2*b3d94504SStephan Aßmus * Copyright (c) 2003-2005 by Siarzhuk Zharski <imker@gmx.li> 3*b3d94504SStephan Aßmus * Distributed under the terms of the BSD License. 4*b3d94504SStephan Aßmus * 5*b3d94504SStephan Aßmus */ 6*b3d94504SStephan Aßmus 7*b3d94504SStephan Aßmus /** driver settings support implementation */ 8*b3d94504SStephan Aßmus 9*b3d94504SStephan Aßmus #include "usb_scsi.h" 10*b3d94504SStephan Aßmus #include "settings.h" 11*b3d94504SStephan Aßmus //#include "proto_common.h" 12*b3d94504SStephan Aßmus 13*b3d94504SStephan Aßmus #include <stdlib.h> /* strtoul */ 14*b3d94504SStephan Aßmus #include <strings.h> /* strncpy */ 15*b3d94504SStephan Aßmus #include <driver_settings.h> 16*b3d94504SStephan Aßmus #include "tracing.h" 17*b3d94504SStephan Aßmus 18*b3d94504SStephan Aßmus #define DEF_DEVS 2 /**< default amount of reserved devices */ 19*b3d94504SStephan Aßmus #define S_DEF_DEVS "2" /**< default amount of reserved devices */ 20*b3d94504SStephan Aßmus #define DEF_LUNS 4 /**< default amount of reserved LUNs */ 21*b3d94504SStephan Aßmus #define S_DEF_LUNS "4" /**< default amount of reserved LUNs */ 22*b3d94504SStephan Aßmus /** count of device entries, to be reserved for fake devices */ 23*b3d94504SStephan Aßmus int reserved_devices = DEF_DEVS; 24*b3d94504SStephan Aßmus /** count of Logical Unit Numbers, to be reserved for fake devices */ 25*b3d94504SStephan Aßmus int reserved_luns = DEF_LUNS; 26*b3d94504SStephan Aßmus 27*b3d94504SStephan Aßmus bool b_reservation_on = true; 28*b3d94504SStephan Aßmus bool b_ignore_sysinit2 = false; 29*b3d94504SStephan Aßmus /** 30*b3d94504SStephan Aßmus support of some kind rudimentary "quick" search. Indexes in 31*b3d94504SStephan Aßmus settings_keys array. 32*b3d94504SStephan Aßmus */ 33*b3d94504SStephan Aßmus enum SKKeys{ 34*b3d94504SStephan Aßmus skkVendor = 0, 35*b3d94504SStephan Aßmus skkDevice, 36*b3d94504SStephan Aßmus // skkName, 37*b3d94504SStephan Aßmus // skkTransport, 38*b3d94504SStephan Aßmus skkProtocol, 39*b3d94504SStephan Aßmus skkCommandSet, 40*b3d94504SStephan Aßmus skkFakeInq, 41*b3d94504SStephan Aßmus skk6ByteCmd, 42*b3d94504SStephan Aßmus skkTransTU, 43*b3d94504SStephan Aßmus skkNoTU, 44*b3d94504SStephan Aßmus skkNoGetMaxLUN, 45*b3d94504SStephan Aßmus skkNoPreventMedia, 46*b3d94504SStephan Aßmus skkUseModeSense10, 47*b3d94504SStephan Aßmus skkForceReadOnly, 48*b3d94504SStephan Aßmus skkProtoBulk, 49*b3d94504SStephan Aßmus skkProtoCB, 50*b3d94504SStephan Aßmus skkProtoCBI, 51*b3d94504SStephan Aßmus // skkProtoFreecom, 52*b3d94504SStephan Aßmus skkCmdSetSCSI, 53*b3d94504SStephan Aßmus skkCmdSetUFI, 54*b3d94504SStephan Aßmus skkCmdSetATAPI, 55*b3d94504SStephan Aßmus skkCmdSetRBC, 56*b3d94504SStephan Aßmus skkCmdSetQIC157, 57*b3d94504SStephan Aßmus 58*b3d94504SStephan Aßmus skkKeysCount, 59*b3d94504SStephan Aßmus // skkTransportBase = skkSubClassSCSI, 60*b3d94504SStephan Aßmus skkProtoBegin = skkProtoBulk, 61*b3d94504SStephan Aßmus skkProtoEnd = skkProtoCBI, 62*b3d94504SStephan Aßmus skkCmdSetBegin = skkCmdSetSCSI, 63*b3d94504SStephan Aßmus skkCmdSetEnd = skkCmdSetQIC157, 64*b3d94504SStephan Aßmus }; 65*b3d94504SStephan Aßmus /** 66*b3d94504SStephan Aßmus helper struct, used in our "quick" search algorithm 67*b3d94504SStephan Aßmus */ 68*b3d94504SStephan Aßmus struct _settings_key{ 69*b3d94504SStephan Aßmus union _hash{ 70*b3d94504SStephan Aßmus char name[32]; 71*b3d94504SStephan Aßmus uint16 key; 72*b3d94504SStephan Aßmus }hash; 73*b3d94504SStephan Aßmus uint32 property; 74*b3d94504SStephan Aßmus }settings_keys[] = { /**< array of keys, used in our settings files */ 75*b3d94504SStephan Aßmus {{"vendor" }, 0}, /* MUST BE SYNCHRONISED WITH skk*** indexes!!! */ 76*b3d94504SStephan Aßmus {{"device" }, 0}, 77*b3d94504SStephan Aßmus // {{"name" }, 0}, 78*b3d94504SStephan Aßmus // {{"transport"}, 0}, 79*b3d94504SStephan Aßmus {{"protocol"}, 0}, 80*b3d94504SStephan Aßmus {{"commandset"}, 0}, 81*b3d94504SStephan Aßmus {{"fake_inquiry" }, 0}, 82*b3d94504SStephan Aßmus {{"use_rw6_byte_cmd" }, 0}, 83*b3d94504SStephan Aßmus {{"trans_test_unit" }, 0}, 84*b3d94504SStephan Aßmus {{"no_test_unit" }, 0}, 85*b3d94504SStephan Aßmus {{"no_get_max_lun"}, 0}, 86*b3d94504SStephan Aßmus {{"no_prevent_media"}, 0}, 87*b3d94504SStephan Aßmus {{"use_mode_sense_10"}, 0}, 88*b3d94504SStephan Aßmus {{"force_read_only"}, 0}, 89*b3d94504SStephan Aßmus {{"BULK" }, PROTO_BULK_ONLY}, 90*b3d94504SStephan Aßmus {{"CB" }, PROTO_CB}, 91*b3d94504SStephan Aßmus {{"CBI" }, PROTO_CBI}, 92*b3d94504SStephan Aßmus // {{"Freecom"}, PROTO_FREECOM}, 93*b3d94504SStephan Aßmus {{"SCSI" }, CMDSET_SCSI}, 94*b3d94504SStephan Aßmus {{"UFI" }, CMDSET_UFI}, 95*b3d94504SStephan Aßmus {{"ATAPI" }, CMDSET_ATAPI}, 96*b3d94504SStephan Aßmus {{"RBC" }, CMDSET_RBC}, 97*b3d94504SStephan Aßmus {{"QIC157" }, CMDSET_QIC157}, 98*b3d94504SStephan Aßmus }; 99*b3d94504SStephan Aßmus /** 100*b3d94504SStephan Aßmus \define:SK_EQUAL 101*b3d94504SStephan Aßmus checks is the __name parameter correspond to value, pointed by __id index 102*b3d94504SStephan Aßmus in settings_keys array. The magic of our "quick" search algorithm =-)) 103*b3d94504SStephan Aßmus */ 104*b3d94504SStephan Aßmus #define CAST_SK(__name) (*(uint16 *)(__name)) 105*b3d94504SStephan Aßmus #define SK_EQUAL(__name, __id) ((CAST_SK(__name) == (settings_keys[__id].hash.key)) && \ 106*b3d94504SStephan Aßmus (0 == strcmp(__name, settings_keys[__id].hash.name))) 107*b3d94504SStephan Aßmus /** 108*b3d94504SStephan Aßmus \fn:load_module_settings 109*b3d94504SStephan Aßmus loads driver settings from extarnal settings file through BeOS driver 110*b3d94504SStephan Aßmus settings API. Called on initialization of the module 111*b3d94504SStephan Aßmus */ 112*b3d94504SStephan Aßmus void load_module_settings() 113*b3d94504SStephan Aßmus { 114*b3d94504SStephan Aßmus void *sh = load_driver_settings(MODULE_NAME); 115*b3d94504SStephan Aßmus if(sh){ 116*b3d94504SStephan Aßmus load_log_settings(sh); 117*b3d94504SStephan Aßmus /* devices "reservation". Workaround for plug-n-play device attaching*/ 118*b3d94504SStephan Aßmus reserved_devices = strtoul(get_driver_parameter(sh, "reserve_devices", 119*b3d94504SStephan Aßmus S_DEF_DEVS, S_DEF_DEVS), NULL, 0); 120*b3d94504SStephan Aßmus reserved_luns = strtoul(get_driver_parameter(sh, "reserve_luns", 121*b3d94504SStephan Aßmus S_DEF_LUNS, S_DEF_LUNS), NULL, 0); 122*b3d94504SStephan Aßmus b_ignore_sysinit2 = get_driver_boolean_parameter(sh, "ignore_sysinit2", 123*b3d94504SStephan Aßmus b_ignore_sysinit2, false); 124*b3d94504SStephan Aßmus if(reserved_devices > MAX_DEVICES_COUNT) 125*b3d94504SStephan Aßmus reserved_devices = MAX_DEVICES_COUNT; 126*b3d94504SStephan Aßmus if(reserved_luns > MAX_LUNS_COUNT) 127*b3d94504SStephan Aßmus reserved_luns = MAX_LUNS_COUNT; 128*b3d94504SStephan Aßmus b_reservation_on = (reserved_devices != 0); 129*b3d94504SStephan Aßmus 130*b3d94504SStephan Aßmus unload_driver_settings(sh); 131*b3d94504SStephan Aßmus } else { 132*b3d94504SStephan Aßmus TRACE("settings:load:file '%s' was not found. Using default setting...\n", 133*b3d94504SStephan Aßmus MODULE_NAME); 134*b3d94504SStephan Aßmus } 135*b3d94504SStephan Aßmus } 136*b3d94504SStephan Aßmus /** 137*b3d94504SStephan Aßmus \fn:strncpy_value 138*b3d94504SStephan Aßmus \param to: buffer for copied string 139*b3d94504SStephan Aßmus \param dp: driver_parameter, from wich copied string come 140*b3d94504SStephan Aßmus \param size: maximal size of copied string 141*b3d94504SStephan Aßmus copies a string, containing value[0] of this parameter, from driver_parameter, 142*b3d94504SStephan Aßmus pointed by dp, to buffer pointed by to. Semantic of this function is similar 143*b3d94504SStephan Aßmus to standard strncpy() one. 144*b3d94504SStephan Aßmus */ 145*b3d94504SStephan Aßmus /*static void 146*b3d94504SStephan Aßmus strncpy_value(char *to, driver_parameter *dp, size_t size) 147*b3d94504SStephan Aßmus { 148*b3d94504SStephan Aßmus to[0] = 0; 149*b3d94504SStephan Aßmus if(dp->value_count > 0){ 150*b3d94504SStephan Aßmus strncpy(to, dp->values[0], size); 151*b3d94504SStephan Aßmus } 152*b3d94504SStephan Aßmus }*/ 153*b3d94504SStephan Aßmus /** 154*b3d94504SStephan Aßmus \fn:parse_transport 155*b3d94504SStephan Aßmus \param dp: driver_parameter, containing device transport information 156*b3d94504SStephan Aßmus \return: a bitmasked value from PROP_-defined flags for USB subclass and \ 157*b3d94504SStephan Aßmus protocol 158*b3d94504SStephan Aßmus parse the transport driver_parameter for known USB subclasses, protocols and 159*b3d94504SStephan Aßmus compose a bitmasked value from those settings 160*b3d94504SStephan Aßmus */ 161*b3d94504SStephan Aßmus static uint32 162*b3d94504SStephan Aßmus parse_transport(driver_parameter *dp, 163*b3d94504SStephan Aßmus int skkBase, int skkEnd, 164*b3d94504SStephan Aßmus uint32 vendor_prop, char *vendor_prop_name) 165*b3d94504SStephan Aßmus { 166*b3d94504SStephan Aßmus uint32 ret = 0; 167*b3d94504SStephan Aßmus if(dp->value_count > 0){ 168*b3d94504SStephan Aßmus char *value = dp->values[0]; 169*b3d94504SStephan Aßmus int skkIdx = skkBase; 170*b3d94504SStephan Aßmus for(; skkIdx <= skkEnd; skkIdx++){ 171*b3d94504SStephan Aßmus if(SK_EQUAL(value, skkIdx)){ 172*b3d94504SStephan Aßmus ret |= settings_keys[skkIdx].property; 173*b3d94504SStephan Aßmus break; 174*b3d94504SStephan Aßmus } 175*b3d94504SStephan Aßmus } /* for(...) enumerate protocol and commandset keys */ 176*b3d94504SStephan Aßmus if(skkIdx > skkEnd){ /* not found - assume vendor prop */ 177*b3d94504SStephan Aßmus ret |= vendor_prop; 178*b3d94504SStephan Aßmus strncpy(vendor_prop_name, value, VENDOR_PROP_NAME_LEN); 179*b3d94504SStephan Aßmus } 180*b3d94504SStephan Aßmus if(dp->value_count > 1){ 181*b3d94504SStephan Aßmus TRACE("settings:parse_transport:accept '%s', ignore extra...\n", value); 182*b3d94504SStephan Aßmus } 183*b3d94504SStephan Aßmus } 184*b3d94504SStephan Aßmus return ret; 185*b3d94504SStephan Aßmus } 186*b3d94504SStephan Aßmus /** 187*b3d94504SStephan Aßmus \fn:lookup_device_info 188*b3d94504SStephan Aßmus \param product_id: product id of device to be checked for private settings 189*b3d94504SStephan Aßmus \param dp: driver_parameter, containing device information 190*b3d94504SStephan Aßmus \param udd: on return contains name,protocol etc. information about device 191*b3d94504SStephan Aßmus \return: "true" if private settings for device found - "false" otherwise 192*b3d94504SStephan Aßmus looks through device parameter, pointed by dp, obtains the name and other 193*b3d94504SStephan Aßmus parameters of private device settings if available 194*b3d94504SStephan Aßmus */ 195*b3d94504SStephan Aßmus static bool 196*b3d94504SStephan Aßmus lookup_device_info(uint16 product_id, 197*b3d94504SStephan Aßmus driver_parameter *dp, 198*b3d94504SStephan Aßmus usb_device_settings *uds) 199*b3d94504SStephan Aßmus { 200*b3d94504SStephan Aßmus bool b_found = false; 201*b3d94504SStephan Aßmus if(dp){ 202*b3d94504SStephan Aßmus int i = 0; 203*b3d94504SStephan Aßmus for(; i < dp->value_count; i++){ 204*b3d94504SStephan Aßmus uint16 id = strtoul(dp->values[0], NULL, 0) & 0xffff; 205*b3d94504SStephan Aßmus if(product_id == id){ 206*b3d94504SStephan Aßmus int prm = 0; 207*b3d94504SStephan Aßmus uds->product_id = product_id; 208*b3d94504SStephan Aßmus for(; prm < dp->parameter_count; prm++){ 209*b3d94504SStephan Aßmus /* if(SK_EQUAL(dp->parameters[prm].name, skkName)){ 210*b3d94504SStephan Aßmus strncpy_value(udd->product_name, &dp->parameters[prm], INQ_PRODUCT_LEN); 211*b3d94504SStephan Aßmus } else*/ 212*b3d94504SStephan Aßmus /* if(SK_EQUAL(dp->parameters[prm].name, skkTransport)){ 213*b3d94504SStephan Aßmus udd->properties |= parse_transport(&dp->parameters[prm]); 214*b3d94504SStephan Aßmus } else*/ 215*b3d94504SStephan Aßmus if(SK_EQUAL(dp->parameters[prm].name, skkProtocol)){ 216*b3d94504SStephan Aßmus uds->properties |= parse_transport(&dp->parameters[prm], 217*b3d94504SStephan Aßmus skkProtoBegin, skkProtoEnd, 218*b3d94504SStephan Aßmus PROTO_VENDOR, 219*b3d94504SStephan Aßmus uds->vendor_protocol); 220*b3d94504SStephan Aßmus } else 221*b3d94504SStephan Aßmus if(SK_EQUAL(dp->parameters[prm].name, skkCommandSet)){ 222*b3d94504SStephan Aßmus uds->properties |= parse_transport(&dp->parameters[prm], 223*b3d94504SStephan Aßmus skkCmdSetBegin, skkCmdSetEnd, 224*b3d94504SStephan Aßmus CMDSET_VENDOR, 225*b3d94504SStephan Aßmus uds->vendor_commandset); 226*b3d94504SStephan Aßmus } else 227*b3d94504SStephan Aßmus if(SK_EQUAL(dp->parameters[prm].name, skkFakeInq)){ 228*b3d94504SStephan Aßmus uds->properties |= FIX_NO_INQUIRY; 229*b3d94504SStephan Aßmus } else 230*b3d94504SStephan Aßmus if(SK_EQUAL(dp->parameters[prm].name, skk6ByteCmd)){ 231*b3d94504SStephan Aßmus uds->properties |= FIX_FORCE_RW_TO_6; 232*b3d94504SStephan Aßmus } else 233*b3d94504SStephan Aßmus if(SK_EQUAL(dp->parameters[prm].name, skkTransTU)){ 234*b3d94504SStephan Aßmus uds->properties |= FIX_TRANS_TEST_UNIT; 235*b3d94504SStephan Aßmus } else 236*b3d94504SStephan Aßmus if(SK_EQUAL(dp->parameters[prm].name, skkNoTU)){ 237*b3d94504SStephan Aßmus uds->properties |= FIX_NO_TEST_UNIT; 238*b3d94504SStephan Aßmus } else 239*b3d94504SStephan Aßmus if(SK_EQUAL(dp->parameters[prm].name, skkNoPreventMedia)){ 240*b3d94504SStephan Aßmus uds->properties |= FIX_NO_PREVENT_MEDIA; 241*b3d94504SStephan Aßmus } else 242*b3d94504SStephan Aßmus if(SK_EQUAL(dp->parameters[prm].name, skkUseModeSense10)){ 243*b3d94504SStephan Aßmus uds->properties |= FIX_FORCE_MS_TO_10; 244*b3d94504SStephan Aßmus } else 245*b3d94504SStephan Aßmus if(SK_EQUAL(dp->parameters[prm].name, skkForceReadOnly)){ 246*b3d94504SStephan Aßmus uds->properties |= FIX_FORCE_READ_ONLY; 247*b3d94504SStephan Aßmus } else 248*b3d94504SStephan Aßmus if(SK_EQUAL(dp->parameters[prm].name, skkNoGetMaxLUN)){ 249*b3d94504SStephan Aßmus uds->properties |= FIX_NO_GETMAXLUN; 250*b3d94504SStephan Aßmus } else { 251*b3d94504SStephan Aßmus TRACE("settings:device:ignore unknown parameter:%s\n", 252*b3d94504SStephan Aßmus dp->parameters[prm].name); 253*b3d94504SStephan Aßmus } 254*b3d94504SStephan Aßmus } /* for(...) enumerate device parameters */ 255*b3d94504SStephan Aßmus b_found = true; 256*b3d94504SStephan Aßmus break; 257*b3d94504SStephan Aßmus } /* if(product_id == id){ */ 258*b3d94504SStephan Aßmus } /*enumerate parameter values (product ids) */ 259*b3d94504SStephan Aßmus } /* if(dp) */ 260*b3d94504SStephan Aßmus return b_found; 261*b3d94504SStephan Aßmus } 262*b3d94504SStephan Aßmus /** 263*b3d94504SStephan Aßmus \fn:lookup_vendor_info 264*b3d94504SStephan Aßmus \param vendor_id: vendor id of device to be checked for private settings 265*b3d94504SStephan Aßmus \param product_id: product id of device to be checked for private settings 266*b3d94504SStephan Aßmus \param dp: driver_parameter, containing vendor information 267*b3d94504SStephan Aßmus \param udd: on return contains name, protocol etc. information about device 268*b3d94504SStephan Aßmus \return: "true" if private settings for device found - "false" otherwise 269*b3d94504SStephan Aßmus looks through vendor parameter, pointed by dp, obtains the name of vendor and 270*b3d94504SStephan Aßmus device information if available 271*b3d94504SStephan Aßmus */ 272*b3d94504SStephan Aßmus static bool 273*b3d94504SStephan Aßmus lookup_vendor_info(uint16 vendor_id, 274*b3d94504SStephan Aßmus uint16 product_id, 275*b3d94504SStephan Aßmus driver_parameter *dp, 276*b3d94504SStephan Aßmus usb_device_settings *uds) 277*b3d94504SStephan Aßmus { 278*b3d94504SStephan Aßmus bool b_found = false; 279*b3d94504SStephan Aßmus if(dp && dp->value_count > 0 && dp->values[0]){ 280*b3d94504SStephan Aßmus uint16 id = strtoul(dp->values[0], NULL, 0) & 0xffff; 281*b3d94504SStephan Aßmus if(vendor_id == id){ 282*b3d94504SStephan Aßmus int i = 0; 283*b3d94504SStephan Aßmus for( i = 0; i < dp->parameter_count; i++){ 284*b3d94504SStephan Aßmus if(!b_found && SK_EQUAL(dp->parameters[i].name, skkDevice)){ 285*b3d94504SStephan Aßmus b_found = lookup_device_info(product_id, &dp->parameters[i], uds); 286*b3d94504SStephan Aßmus } /*else 287*b3d94504SStephan Aßmus if(SK_EQUAL(dp->parameters[i].name, skkName)){ 288*b3d94504SStephan Aßmus strncpy_value(udd->vendor_name, &dp->parameters[i], INQ_VENDOR_LEN); 289*b3d94504SStephan Aßmus } */else { 290*b3d94504SStephan Aßmus TRACE("settings:vendor:ignore unknown parameter:%s\n", 291*b3d94504SStephan Aßmus dp->parameters[i].name); 292*b3d94504SStephan Aßmus } 293*b3d94504SStephan Aßmus } /*for(...) enumerate "vendor" parameters*/ 294*b3d94504SStephan Aßmus } /*if(vendor_id == id){*/ 295*b3d94504SStephan Aßmus } /* if(dp && ... etc */ 296*b3d94504SStephan Aßmus return b_found; 297*b3d94504SStephan Aßmus } 298*b3d94504SStephan Aßmus /** 299*b3d94504SStephan Aßmus \fn:lookup_device_settings 300*b3d94504SStephan Aßmus \param vendor_id: vendor id of device to be checked for private settings 301*b3d94504SStephan Aßmus \param product_id: product id of device to be checked for private settings 302*b3d94504SStephan Aßmus \param udd: on return contains name,protocol etc. information about device 303*b3d94504SStephan Aßmus \return: "true" if private settings for device found - "false" otherwise 304*b3d94504SStephan Aßmus looks through driver settings file for private device description and load it 305*b3d94504SStephan Aßmus if available into struct pointed by udd 306*b3d94504SStephan Aßmus */ 307*b3d94504SStephan Aßmus bool lookup_device_settings(const usb_device_descriptor *udd, 308*b3d94504SStephan Aßmus usb_device_settings *uds) 309*b3d94504SStephan Aßmus { 310*b3d94504SStephan Aßmus bool b_found = false; 311*b3d94504SStephan Aßmus if(uds){ 312*b3d94504SStephan Aßmus void *sh = load_driver_settings(MODULE_NAME); 313*b3d94504SStephan Aßmus if(sh){ 314*b3d94504SStephan Aßmus const driver_settings *ds = get_driver_settings(sh); 315*b3d94504SStephan Aßmus if(ds){ 316*b3d94504SStephan Aßmus int i = 0; 317*b3d94504SStephan Aßmus for(i = 0; i < ds->parameter_count; i++){ 318*b3d94504SStephan Aßmus if(SK_EQUAL(ds->parameters[i].name, skkVendor)){ 319*b3d94504SStephan Aßmus b_found = lookup_vendor_info(udd->vendor_id, 320*b3d94504SStephan Aßmus udd->product_id, 321*b3d94504SStephan Aßmus &ds->parameters[i], uds); 322*b3d94504SStephan Aßmus if(b_found){ 323*b3d94504SStephan Aßmus uds->vendor_id = udd->vendor_id; 324*b3d94504SStephan Aßmus break; //we've got it - stop enumeration. 325*b3d94504SStephan Aßmus } 326*b3d94504SStephan Aßmus } 327*b3d94504SStephan Aßmus } /*for(...) - enumerate "root" parameters*/ 328*b3d94504SStephan Aßmus } /* if(ds) */ 329*b3d94504SStephan Aßmus unload_driver_settings(sh); 330*b3d94504SStephan Aßmus } /* if(sh) */ 331*b3d94504SStephan Aßmus if(b_found){ 332*b3d94504SStephan Aßmus //TRACE("settings:loaded settings:'%s(%04x)/%s(%04x)/%08x'\n", 333*b3d94504SStephan Aßmus TRACE("settings:loaded settings:'%04x/%04x/%08x'\n", 334*b3d94504SStephan Aßmus /*descr->vendor_name,*/ uds->vendor_id, 335*b3d94504SStephan Aßmus /*descr->product_name,*/ 336*b3d94504SStephan Aßmus uds->product_id, uds->properties); 337*b3d94504SStephan Aßmus } 338*b3d94504SStephan Aßmus } /* if(descr)*/ 339*b3d94504SStephan Aßmus return b_found; 340*b3d94504SStephan Aßmus } 341