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