xref: /haiku/src/add-ons/kernel/busses/scsi/usb/settings.c (revision b3d94504c208adafebbf2ba62ae7fc4e0b7d68f7)
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