xref: /titanic_52/usr/src/cmd/hal/hald/solaris/devinfo_usb.c (revision 3fb52c733c5435ce279a4641b57941b1befa5c9f)
118c2aff7Sartem /***************************************************************************
218c2aff7Sartem  *
318c2aff7Sartem  * devinfo_usb.h : USB devices
418c2aff7Sartem  *
5d5c32991SNorm Jacobs  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
618c2aff7Sartem  * Use is subject to license terms.
718c2aff7Sartem  *
818c2aff7Sartem  * Licensed under the Academic Free License version 2.1
918c2aff7Sartem  *
1018c2aff7Sartem  **************************************************************************/
1118c2aff7Sartem 
1200687e57Sartem #ifdef HAVE_CONFIG_H
1300687e57Sartem #  include <config.h>
1400687e57Sartem #endif
1500687e57Sartem 
1618c2aff7Sartem #include <stdio.h>
1718c2aff7Sartem #include <string.h>
1818c2aff7Sartem #include <libdevinfo.h>
19b453864fSLin Guo - Sun Microsystems #include <unistd.h>
20b453864fSLin Guo - Sun Microsystems #include <dirent.h>
2118c2aff7Sartem #include <sys/types.h>
2218c2aff7Sartem #include <sys/mkdev.h>
2318c2aff7Sartem #include <sys/stat.h>
24112cd14aSqz150045 #include <sys/usb/usbai.h>
2518c2aff7Sartem 
2618c2aff7Sartem #include "../osspec.h"
2718c2aff7Sartem #include "../logger.h"
2818c2aff7Sartem #include "../hald.h"
2918c2aff7Sartem #include "../hald_dbus.h"
3018c2aff7Sartem #include "../device_info.h"
3118c2aff7Sartem #include "../util.h"
3218c2aff7Sartem #include "../ids.h"
3318c2aff7Sartem #include "hotplug.h"
3418c2aff7Sartem #include "devinfo.h"
3518c2aff7Sartem #include "devinfo_usb.h"
3618c2aff7Sartem 
37112cd14aSqz150045 static HalDevice *devinfo_usb_if_add(HalDevice *d, di_node_t node, gchar *devfs_path,
38112cd14aSqz150045 				     gchar *if_devfs_path, int ifnum);
39112cd14aSqz150045 static HalDevice *devinfo_usb_scsa2usb_add(HalDevice *d, di_node_t node);
40112cd14aSqz150045 static HalDevice *devinfo_usb_printer_add(HalDevice *usbd, di_node_t node);
41b453864fSLin Guo - Sun Microsystems static HalDevice *devinfo_usb_input_add(HalDevice *usbd, di_node_t node);
423622ad5aSLin Guo - Sun Microsystems static HalDevice *devinfo_usb_video4linux_add(HalDevice *usbd, di_node_t node);
4342a7bdedSjacobs const gchar *devinfo_printer_prnio_get_prober(HalDevice *d, int *timeout);
44b453864fSLin Guo - Sun Microsystems const gchar *devinfo_keyboard_get_prober(HalDevice *d, int *timeout);
45112cd14aSqz150045 static void set_usb_properties(HalDevice *d, di_node_t node, gchar *devfs_path, char *driver_name);
4618c2aff7Sartem 
4718c2aff7Sartem DevinfoDevHandler devinfo_usb_handler = {
4818c2aff7Sartem 	devinfo_usb_add,
4918c2aff7Sartem 	NULL,
5018c2aff7Sartem 	NULL,
5118c2aff7Sartem 	NULL,
5218c2aff7Sartem 	NULL,
5318c2aff7Sartem 	NULL
5418c2aff7Sartem };
5518c2aff7Sartem 
5642a7bdedSjacobs DevinfoDevHandler devinfo_usb_printer_handler = {
5742a7bdedSjacobs 	devinfo_usb_add,
5842a7bdedSjacobs 	NULL,
5942a7bdedSjacobs 	NULL,
6042a7bdedSjacobs 	NULL,
6142a7bdedSjacobs 	NULL,
6242a7bdedSjacobs 	devinfo_printer_prnio_get_prober
6342a7bdedSjacobs };
6442a7bdedSjacobs 
65b453864fSLin Guo - Sun Microsystems DevinfoDevHandler devinfo_usb_keyboard_handler = {
66b453864fSLin Guo - Sun Microsystems 	devinfo_usb_add,
67b453864fSLin Guo - Sun Microsystems 	NULL,
68b453864fSLin Guo - Sun Microsystems 	NULL,
69b453864fSLin Guo - Sun Microsystems 	NULL,
70b453864fSLin Guo - Sun Microsystems 	NULL,
71b453864fSLin Guo - Sun Microsystems 	devinfo_keyboard_get_prober
72b453864fSLin Guo - Sun Microsystems };
73b453864fSLin Guo - Sun Microsystems 
74c74d5d46Sjacobs static gboolean
75c74d5d46Sjacobs is_usb_node(di_node_t node)
76c74d5d46Sjacobs {
77c74d5d46Sjacobs 	int rc;
78c74d5d46Sjacobs 	char *s;
79c74d5d46Sjacobs 
80c74d5d46Sjacobs 	/*
81c74d5d46Sjacobs 	 * USB device nodes will have "compatible" propety values that
82c74d5d46Sjacobs 	 * begins with "usb".
83c74d5d46Sjacobs 	 */
84c74d5d46Sjacobs 	rc = di_prop_lookup_strings(DDI_DEV_T_ANY, node, "compatible", &s);
85c74d5d46Sjacobs 	while (rc-- > 0) {
86c74d5d46Sjacobs 		if (strncmp(s, "usb", 3) == 0) {
87c74d5d46Sjacobs 			return (TRUE);
88c74d5d46Sjacobs 		}
89c74d5d46Sjacobs 		s += (strlen(s) + 1);
90c74d5d46Sjacobs 	}
91c74d5d46Sjacobs 
92c74d5d46Sjacobs 	return (FALSE);
93c74d5d46Sjacobs }
94c74d5d46Sjacobs 
95b453864fSLin Guo - Sun Microsystems static char *
963622ad5aSLin Guo - Sun Microsystems get_usb_devlink(char *devfs_path, const char *dir_name)
97b453864fSLin Guo - Sun Microsystems {
98b453864fSLin Guo - Sun Microsystems 	char *result = NULL;
99b453864fSLin Guo - Sun Microsystems 	DIR *dp;
100b453864fSLin Guo - Sun Microsystems 
1013622ad5aSLin Guo - Sun Microsystems 	if ((dp = opendir(dir_name)) != NULL) {
102b453864fSLin Guo - Sun Microsystems 		struct dirent *ep;
103b453864fSLin Guo - Sun Microsystems 
104b453864fSLin Guo - Sun Microsystems 		while ((ep = readdir(dp)) != NULL) {
105b453864fSLin Guo - Sun Microsystems 			char path[MAXPATHLEN], lpath[MAXPATHLEN];
106b453864fSLin Guo - Sun Microsystems 
1073622ad5aSLin Guo - Sun Microsystems 			strncpy(path, dir_name, strlen(dir_name));
1083622ad5aSLin Guo - Sun Microsystems 			strncat(path, ep->d_name, strlen(ep->d_name));
109b453864fSLin Guo - Sun Microsystems 			memset(lpath, 0, sizeof (lpath));
110b453864fSLin Guo - Sun Microsystems 			if ((readlink(path, lpath, sizeof (lpath)) > 0) &&
111b453864fSLin Guo - Sun Microsystems 			    (strstr(lpath, devfs_path) != NULL)) {
112b453864fSLin Guo - Sun Microsystems 				result = strdup(path);
113b453864fSLin Guo - Sun Microsystems 				break;
114b453864fSLin Guo - Sun Microsystems 			}
1153622ad5aSLin Guo - Sun Microsystems 			memset(path, 0, sizeof (path));
116b453864fSLin Guo - Sun Microsystems 		}
117b453864fSLin Guo - Sun Microsystems 		closedir(dp);
118b453864fSLin Guo - Sun Microsystems 	}
119b453864fSLin Guo - Sun Microsystems 
120b453864fSLin Guo - Sun Microsystems 	return (result);
121b453864fSLin Guo - Sun Microsystems }
122b453864fSLin Guo - Sun Microsystems 
12318c2aff7Sartem HalDevice *
12418c2aff7Sartem devinfo_usb_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type)
12518c2aff7Sartem {
12618c2aff7Sartem 	HalDevice *d, *nd = NULL;
12718c2aff7Sartem 	char	*s;
128c74d5d46Sjacobs 	int	*i;
12918c2aff7Sartem 	char	*driver_name, *binding_name;
13018c2aff7Sartem 	char	if_devfs_path[HAL_PATH_MAX];
131112cd14aSqz150045 	di_devlink_handle_t hdl;
132112cd14aSqz150045 	double	k;
13318c2aff7Sartem 
134c74d5d46Sjacobs 	if (is_usb_node(node) == FALSE) {
13518c2aff7Sartem 		return (NULL);
13618c2aff7Sartem 	}
13718c2aff7Sartem 
138112cd14aSqz150045 	driver_name = di_driver_name (node);
139112cd14aSqz150045 
140112cd14aSqz150045 	if (di_prop_lookup_ints (DDI_DEV_T_ANY, node, "interface", &i) < 0) {
141112cd14aSqz150045 		/* It is a USB device node. */
142112cd14aSqz150045 
14318c2aff7Sartem 		d = hal_device_new ();
14418c2aff7Sartem 
14518c2aff7Sartem 		devinfo_set_default_properties (d, parent, node, devfs_path);
146112cd14aSqz150045 		hal_device_property_set_string (d, "info.subsystem", "usb_device");
14718c2aff7Sartem 		PROP_STR(d, node, s, "usb-product-name", "info.product");
14818c2aff7Sartem 		PROP_STR(d, node, s, "usb-product-name", "usb_device.product");
14918c2aff7Sartem 		PROP_STR(d, node, s, "usb-vendor-name", "usb_device.vendor");
15018c2aff7Sartem 		PROP_INT(d, node, i, "usb-vendor-id", "usb_device.vendor_id");
15118c2aff7Sartem 		PROP_INT(d, node, i, "usb-product-id", "usb_device.product_id");
15218c2aff7Sartem 		PROP_INT(d, node, i, "usb-revision-id", "usb_device.device_revision_bcd");
15318c2aff7Sartem 		PROP_STR(d, node, s, "usb-serialno", "usb_device.serial");
154112cd14aSqz150045 		PROP_INT(d, node, i, "usb-port-count", "usb_device.num_ports");
155112cd14aSqz150045 		PROP_INT(d, node, i, "usb-num-configs", "usb_device.num_configurations");
156112cd14aSqz150045 		PROP_INT(d, node, i, "assigned-address", "usb_device.bus_number");
15718c2aff7Sartem 
158112cd14aSqz150045 		if  (di_prop_lookup_ints (DDI_DEV_T_ANY, node, "usb-release", &i) > 0) {
159112cd14aSqz150045 			k = (double)bcd(*i);
160112cd14aSqz150045 			hal_device_property_set_double (d, "usb_device.version", k / 100);
161112cd14aSqz150045 		}
16218c2aff7Sartem 
163112cd14aSqz150045 		if (di_prop_lookup_ints (DDI_DEV_T_ANY, node, "low-speed", &i) >= 0) {
164112cd14aSqz150045 			k = 1.5;
165112cd14aSqz150045 		} else if (di_prop_lookup_ints (DDI_DEV_T_ANY, node, "high-speed", &i) >= 0) {
166112cd14aSqz150045 			k = 480.0;
167112cd14aSqz150045 		} else {
168112cd14aSqz150045 			/* It is the full speed device. */
169112cd14aSqz150045 			k = 12.0;
170112cd14aSqz150045 		}
171112cd14aSqz150045 		hal_device_property_set_double (d, "usb_device.speed", k);
172112cd14aSqz150045 
173112cd14aSqz150045 		set_usb_properties (d, node, devfs_path, driver_name);
174112cd14aSqz150045 
175112cd14aSqz150045 		/* wait for the ugen node's creation */
176112cd14aSqz150045 		if ((driver_name != NULL) && (strcmp (driver_name, "usb_mid") == 0)) {
177112cd14aSqz150045 			if (hdl = di_devlink_init (devfs_path, DI_MAKE_LINK)) {
178112cd14aSqz150045 				di_devlink_fini (&hdl);
179112cd14aSqz150045 			}
180112cd14aSqz150045 		}
181112cd14aSqz150045 
182112cd14aSqz150045 		devinfo_add_enqueue (d, devfs_path, &devinfo_usb_handler);
183112cd14aSqz150045 
184112cd14aSqz150045 		/* add to TDL so preprobing callouts and prober can access it */
185112cd14aSqz150045 		hal_device_store_add (hald_get_tdl (), d);
186112cd14aSqz150045 
18718c2aff7Sartem 		if (((binding_name = di_binding_name (node)) != NULL) &&
18818c2aff7Sartem 		    (strncmp (binding_name, "usbif,", sizeof ("usbif,") - 1) == 0)) {
189112cd14aSqz150045 
190112cd14aSqz150045 			snprintf (if_devfs_path, sizeof (if_devfs_path), "%s:if%d",
191112cd14aSqz150045 			    devfs_path, 0);
192112cd14aSqz150045 			if ((nd = devinfo_usb_if_add (d, node, if_devfs_path,
193112cd14aSqz150045 			    if_devfs_path, 0)) != NULL) {
19418c2aff7Sartem 				d = nd;
19518c2aff7Sartem 				nd = NULL;
19618c2aff7Sartem 				devfs_path = if_devfs_path;
19718c2aff7Sartem 			}
19818c2aff7Sartem 		}
199112cd14aSqz150045 	} else {
200112cd14aSqz150045 		/* It is a USB interface node or IA node. */
201112cd14aSqz150045 		int *j;
202112cd14aSqz150045 
203112cd14aSqz150045 		if (di_prop_lookup_ints (DDI_DEV_T_ANY, node, "interface-count", &j) > 0) {
204112cd14aSqz150045 			/*
205112cd14aSqz150045 			 * The USB IA node properties are not defined in
206112cd14aSqz150045 			 * HAL spec so far. So IA node udi has "ia" sign
207112cd14aSqz150045 			 * now, different from the IF node udi with "if".
208112cd14aSqz150045 			 */
209112cd14aSqz150045 			snprintf (if_devfs_path, sizeof (if_devfs_path),
210112cd14aSqz150045 			    "%s:ia%d", devfs_path, *i);
211112cd14aSqz150045 		} else {
212112cd14aSqz150045 			snprintf (if_devfs_path, sizeof (if_devfs_path),
213112cd14aSqz150045 			    "%s:if%d", devfs_path, *i);
214112cd14aSqz150045 		}
215112cd14aSqz150045 
216112cd14aSqz150045 		d = devinfo_usb_if_add (parent, node, devfs_path, if_devfs_path, *i);
217112cd14aSqz150045 	}
21818c2aff7Sartem 
21918c2aff7Sartem 	/* driver specific */
220b453864fSLin Guo - Sun Microsystems 	if (driver_name != NULL) {
221b453864fSLin Guo - Sun Microsystems 		if (strcmp (driver_name, "scsa2usb") == 0) {
222112cd14aSqz150045 			nd = devinfo_usb_scsa2usb_add (d, node);
223b453864fSLin Guo - Sun Microsystems 		} else if (strcmp (driver_name, "usbprn") == 0) {
224112cd14aSqz150045 			nd = devinfo_usb_printer_add (d, node);
225b453864fSLin Guo - Sun Microsystems 		} else if (strcmp(driver_name, "hid") == 0) {
226b453864fSLin Guo - Sun Microsystems 			if (hdl = di_devlink_init(devfs_path, DI_MAKE_LINK)) {
227b453864fSLin Guo - Sun Microsystems 				di_devlink_fini(&hdl);
228b453864fSLin Guo - Sun Microsystems 			}
229b453864fSLin Guo - Sun Microsystems 			nd = devinfo_usb_input_add(d, node);
2303622ad5aSLin Guo - Sun Microsystems 		} else if (strcmp(driver_name, "usbvc") == 0) {
2313622ad5aSLin Guo - Sun Microsystems 			if (hdl = di_devlink_init(devfs_path, DI_MAKE_LINK)) {
2323622ad5aSLin Guo - Sun Microsystems 				di_devlink_fini(&hdl);
2333622ad5aSLin Guo - Sun Microsystems 			}
2343622ad5aSLin Guo - Sun Microsystems 			nd = devinfo_usb_video4linux_add(d, node);
235b453864fSLin Guo - Sun Microsystems 		}
23618c2aff7Sartem 	}
23718c2aff7Sartem 
23818c2aff7Sartem out:
23918c2aff7Sartem 	if (nd != NULL) {
24018c2aff7Sartem 		return (nd);
24118c2aff7Sartem 	} else {
24218c2aff7Sartem 		return (d);
24318c2aff7Sartem 	}
24418c2aff7Sartem }
24518c2aff7Sartem 
246112cd14aSqz150045 
247112cd14aSqz150045 static void
248112cd14aSqz150045 set_usb_properties(HalDevice *d, di_node_t node, gchar *devfs_path, char *driver_name)
249112cd14aSqz150045 {
250112cd14aSqz150045 	usb_dev_descr_t	*dev_descrp = NULL;	/* device descriptor */
251112cd14aSqz150045 	usb_cfg_descr_t	*cfg_descrp = NULL;	/* configuration descriptor */
252112cd14aSqz150045 	unsigned char	*rdata = NULL;
253112cd14aSqz150045 	char *p;
254112cd14aSqz150045 	int i = 0;
255112cd14aSqz150045 
256112cd14aSqz150045 	hal_device_property_set_int (d, "usb_device.port_number",
257112cd14aSqz150045 	    atoi (devfs_path + strlen (devfs_path) -1));
258112cd14aSqz150045 
259112cd14aSqz150045 	if (di_prop_lookup_bytes (DDI_DEV_T_ANY, node, "usb-dev-descriptor",
260112cd14aSqz150045 	    &rdata) > 0) {
261112cd14aSqz150045 		dev_descrp = (usb_dev_descr_t *)rdata;
262112cd14aSqz150045 
263112cd14aSqz150045 		if (dev_descrp != NULL) {
264112cd14aSqz150045 			hal_device_property_set_int (d, "usb_device.device_class",
265112cd14aSqz150045 			    dev_descrp->bDeviceClass);
266112cd14aSqz150045 			hal_device_property_set_int (d, "usb_device.device_subclass",
267112cd14aSqz150045 			    dev_descrp->bDeviceSubClass);
268112cd14aSqz150045 			hal_device_property_set_int (d, "usb_device.device_protocol",
269112cd14aSqz150045 			    dev_descrp->bDeviceProtocol);
270112cd14aSqz150045 		}
271112cd14aSqz150045 	}
272112cd14aSqz150045 
273112cd14aSqz150045 	if (di_prop_lookup_bytes (DDI_DEV_T_ANY, node, "usb-raw-cfg-descriptors",
274112cd14aSqz150045 	    &rdata) > 0) {
275112cd14aSqz150045 		cfg_descrp = (usb_cfg_descr_t *)(rdata);
276112cd14aSqz150045 
277112cd14aSqz150045 		if (cfg_descrp != NULL) {
278112cd14aSqz150045 			hal_device_property_set_int (d, "usb_device.configuration_value",
279112cd14aSqz150045 			    cfg_descrp->bConfigurationValue);
280112cd14aSqz150045 			hal_device_property_set_int (d, "usb_device.max_power",
281112cd14aSqz150045 			    cfg_descrp->bMaxPower);
282112cd14aSqz150045 			hal_device_property_set_int (d, "usb_device.num_interfaces",
283112cd14aSqz150045 			    cfg_descrp->bNumInterfaces);
284112cd14aSqz150045 			hal_device_property_set_bool (d, "usb_device.can_wake_up",
285112cd14aSqz150045 			    (cfg_descrp->bmAttributes & 0x20) ? TRUE : FALSE);
286112cd14aSqz150045 			hal_device_property_set_bool (d, "usb_device.is_self_powered",
287112cd14aSqz150045 			    (cfg_descrp->bmAttributes & 0x40) ? TRUE : FALSE);
288112cd14aSqz150045 		}
289112cd14aSqz150045 	}
290112cd14aSqz150045 
291112cd14aSqz150045 	/* get the node's usb tree level by counting hub numbers */
292112cd14aSqz150045 	do {
293112cd14aSqz150045 		if (p = strstr (devfs_path, "/hub@")) {
294112cd14aSqz150045 			devfs_path = p + strlen ("/hub@");
295112cd14aSqz150045 			i ++;
296112cd14aSqz150045 		}
297112cd14aSqz150045 	} while (p != NULL);
298112cd14aSqz150045 
299112cd14aSqz150045 	if ((driver_name != NULL) && (strcmp (driver_name, "hubd") == 0) && (i > 0))
300112cd14aSqz150045 		i --;
301112cd14aSqz150045 
302112cd14aSqz150045 	hal_device_property_set_int (d, "usb_device.level_number", i);
303112cd14aSqz150045 }
304112cd14aSqz150045 
305112cd14aSqz150045 
306112cd14aSqz150045 static usb_if_descr_t *
307112cd14aSqz150045 parse_usb_if_descr(di_node_t node, int ifnum)
308112cd14aSqz150045 {
309112cd14aSqz150045 	unsigned char	*rdata = NULL;
310112cd14aSqz150045 	usb_if_descr_t	*if_descrp=NULL;	/* interface descriptor */
311112cd14aSqz150045 	di_node_t	tmp_node = DI_NODE_NIL;
312112cd14aSqz150045 	uint8_t num, length, type;
313112cd14aSqz150045 	int rlen;
314112cd14aSqz150045 	gchar *devpath = NULL;
315112cd14aSqz150045 
316112cd14aSqz150045 	if ((rlen = di_prop_lookup_bytes (DDI_DEV_T_ANY, node,
317112cd14aSqz150045 	     "usb-raw-cfg-descriptors", &rdata)) < 0) {
318112cd14aSqz150045 
319112cd14aSqz150045 		char *p;
320112cd14aSqz150045 		int i;
321112cd14aSqz150045 
322112cd14aSqz150045 		if ((devpath = di_devfs_path (node)) == NULL)
323112cd14aSqz150045 			goto out;
324112cd14aSqz150045 
325112cd14aSqz150045 		/* Look up its parent that may be a USB IA or USB mid. */
326112cd14aSqz150045 		for (i = 0; i < 2; i++) {
327112cd14aSqz150045 			p = strrchr (devpath, '/');
328112cd14aSqz150045 			if (p == NULL)
329112cd14aSqz150045 				goto out;
330112cd14aSqz150045 			*p = '\0';
331112cd14aSqz150045 
332112cd14aSqz150045 			if ((tmp_node = di_init (devpath, DINFOCPYALL)) == DI_NODE_NIL)
333112cd14aSqz150045 				goto out;
334112cd14aSqz150045 
335112cd14aSqz150045 			if ((rlen = di_prop_lookup_bytes (DDI_DEV_T_ANY, tmp_node,
336112cd14aSqz150045 			     "usb-raw-cfg-descriptors", &rdata)) > 0)
337112cd14aSqz150045 				break;
338112cd14aSqz150045 
339112cd14aSqz150045 			di_fini (tmp_node);
340112cd14aSqz150045 		}
341112cd14aSqz150045 	}
342112cd14aSqz150045 
343112cd14aSqz150045 	if (rdata == NULL)
344112cd14aSqz150045 		goto out;
345112cd14aSqz150045 
346112cd14aSqz150045 	do {
347112cd14aSqz150045 		length = (uint8_t)*rdata;
348112cd14aSqz150045 		type = (uint8_t)*(rdata + 1);
349112cd14aSqz150045 		if (type == USB_DESCR_TYPE_IF) {
350112cd14aSqz150045 			num = (uint8_t)*(rdata + 2);
351112cd14aSqz150045 			if (num == ifnum) {
352112cd14aSqz150045 				if_descrp = (usb_if_descr_t *)rdata;
353112cd14aSqz150045 				break;
354112cd14aSqz150045 			}
355112cd14aSqz150045 		}
356112cd14aSqz150045 		rdata += length;
357112cd14aSqz150045 		rlen -= length;
358112cd14aSqz150045 	} while ((length > 0 ) && (rlen > 0));
359112cd14aSqz150045 
360112cd14aSqz150045 out:
361112cd14aSqz150045 	if (devpath != NULL)
362112cd14aSqz150045 		di_devfs_path_free (devpath);
363112cd14aSqz150045 	if (tmp_node != DI_NODE_NIL)
364112cd14aSqz150045 		di_fini (tmp_node);
365112cd14aSqz150045 	return (if_descrp);
366112cd14aSqz150045 }
367112cd14aSqz150045 
368112cd14aSqz150045 
36918c2aff7Sartem static HalDevice *
370112cd14aSqz150045 devinfo_usb_if_add(HalDevice *parent, di_node_t node, gchar *devfs_path,
371112cd14aSqz150045 		   gchar *if_devfs_path, int ifnum)
37218c2aff7Sartem {
37318c2aff7Sartem 	HalDevice	*d = NULL;
37418c2aff7Sartem 	char		udi[HAL_PATH_MAX];
375112cd14aSqz150045 	const char	*parent_info;
376112cd14aSqz150045 	usb_if_descr_t	*if_descrp=NULL;	/* interface descriptor */
37718c2aff7Sartem 
37818c2aff7Sartem 	d = hal_device_new ();
37918c2aff7Sartem 
380112cd14aSqz150045 	devinfo_set_default_properties (d, parent, node, if_devfs_path);
381112cd14aSqz150045 
382112cd14aSqz150045 	/* Set the existed physical device path. */
383112cd14aSqz150045 	hal_device_property_set_string (d, "solaris.devfs_path", devfs_path);
384112cd14aSqz150045 	hal_device_property_set_string (d, "info.subsystem", "usb");
38518c2aff7Sartem 	hal_device_property_set_string (d, "info.product", "USB Device Interface");
38618c2aff7Sartem 
387112cd14aSqz150045 	/* Set usb interface properties to interface node. */
388112cd14aSqz150045 	if (strstr (if_devfs_path, ":ia") == NULL) {
389112cd14aSqz150045 		if_descrp = parse_usb_if_descr (node, ifnum);
390112cd14aSqz150045 
391112cd14aSqz150045 		if (if_descrp != NULL) {
392112cd14aSqz150045 			hal_device_property_set_int (d, "usb.interface.class",
393112cd14aSqz150045 			    if_descrp->bInterfaceClass);
394112cd14aSqz150045 			hal_device_property_set_int (d, "usb.interface.subclass",
395112cd14aSqz150045 			    if_descrp->bInterfaceSubClass);
396112cd14aSqz150045 			hal_device_property_set_int (d, "usb.interface.protocol",
397112cd14aSqz150045 			    if_descrp->bInterfaceProtocol);
398112cd14aSqz150045 			hal_device_property_set_int (d, "usb.interface.number",
399112cd14aSqz150045 			    if_descrp->bInterfaceNumber);
400112cd14aSqz150045 		}
401112cd14aSqz150045 	}
402112cd14aSqz150045 
40318c2aff7Sartem 	/* copy parent's usb_device.* properties */
404112cd14aSqz150045 	parent_info = hal_device_property_get_string (parent, "info.subsystem");
405112cd14aSqz150045 	if (parent_info != NULL) {
406112cd14aSqz150045 		if (strcmp (parent_info, "usb_device") == 0) {
40718c2aff7Sartem 			hal_device_merge_with_rewrite (d, parent, "usb.", "usb_device.");
408112cd14aSqz150045 		} else if (strcmp (parent_info, "usb") == 0) {
409112cd14aSqz150045 			/* for the case that the parent is IA node */
410112cd14aSqz150045 			hal_device_merge_with_rewrite (d, parent, "usb.", "usb.");
411112cd14aSqz150045 		}
412112cd14aSqz150045 	}
413112cd14aSqz150045 
414112cd14aSqz150045 	devinfo_add_enqueue (d, devfs_path, &devinfo_usb_handler);
415112cd14aSqz150045 
416112cd14aSqz150045 	/* add to TDL so preprobing callouts and prober can access it */
417112cd14aSqz150045 	hal_device_store_add (hald_get_tdl (), d);
41818c2aff7Sartem 
41918c2aff7Sartem 	return (d);
42018c2aff7Sartem }
42118c2aff7Sartem 
42242a7bdedSjacobs 
42342a7bdedSjacobs static void
424b453864fSLin Guo - Sun Microsystems get_dev_link_path(di_node_t node, char *nodetype, char *re, char **devlink, char **minor_path, char **minor_name)
42518c2aff7Sartem {
42642a7bdedSjacobs 	di_devlink_handle_t devlink_hdl;
42742a7bdedSjacobs 	int	major;
42842a7bdedSjacobs 	di_minor_t minor;
42942a7bdedSjacobs 	dev_t	devt;
43018c2aff7Sartem 
43142a7bdedSjacobs 	*devlink = NULL;
43242a7bdedSjacobs 	*minor_path = NULL;
433b453864fSLin Guo - Sun Microsystems 	*minor_name = NULL;
43418c2aff7Sartem 
43542a7bdedSjacobs 	if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) {
43642a7bdedSjacobs 		return;
43718c2aff7Sartem 	}
43818c2aff7Sartem 
43942a7bdedSjacobs 	major = di_driver_major(node);
44042a7bdedSjacobs 	minor = DI_MINOR_NIL;
44142a7bdedSjacobs 	while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) {
44242a7bdedSjacobs 		devt = di_minor_devt(minor);
44342a7bdedSjacobs 		if (major != major(devt)) {
44442a7bdedSjacobs 			continue;
44542a7bdedSjacobs 		}
44618c2aff7Sartem 
44742a7bdedSjacobs 		if (di_minor_type(minor) != DDM_MINOR) {
44842a7bdedSjacobs 			continue;
44942a7bdedSjacobs 		}
45018c2aff7Sartem 
45142a7bdedSjacobs 		if ((*minor_path = di_devfs_minor_path(minor)) == NULL) {
45242a7bdedSjacobs 			continue;
45342a7bdedSjacobs 		}
45442a7bdedSjacobs 
455b453864fSLin Guo - Sun Microsystems 		if (strcmp(di_minor_nodetype(minor), nodetype) == 0) {
456b453864fSLin Guo - Sun Microsystems 			*devlink = get_devlink(devlink_hdl, re, *minor_path);
457b453864fSLin Guo - Sun Microsystems 			/*
4583622ad5aSLin Guo - Sun Microsystems 			 * During hotplugging, devlink could be NULL for usb
459b453864fSLin Guo - Sun Microsystems 			 * devices due to devlink database has not yet been
460b453864fSLin Guo - Sun Microsystems 			 * updated when hal try to read from it although the
461b453864fSLin Guo - Sun Microsystems 			 * actually dev link path has been created. In such a
462b453864fSLin Guo - Sun Microsystems 			 * situation, we will read the devlink name from
463b453864fSLin Guo - Sun Microsystems 			 * /dev/usb directory.
464b453864fSLin Guo - Sun Microsystems 			 */
465*3fb52c73SRaymond Chen 			if ((*devlink == NULL) && (re != NULL) &&
4663622ad5aSLin Guo - Sun Microsystems 			    ((strstr(re, "hid") != NULL) || (strstr(re, "video") != NULL))) {
4673622ad5aSLin Guo - Sun Microsystems 				*devlink = get_usb_devlink(*minor_path, "/dev/usb/");
468b453864fSLin Guo - Sun Microsystems 			}
469b453864fSLin Guo - Sun Microsystems 
470b453864fSLin Guo - Sun Microsystems 			if (*devlink != NULL) {
471b453864fSLin Guo - Sun Microsystems 				*minor_name = di_minor_name(minor);
47242a7bdedSjacobs 				break;
47342a7bdedSjacobs 			}
474b453864fSLin Guo - Sun Microsystems 		}
475b453864fSLin Guo - Sun Microsystems 
47642a7bdedSjacobs 		di_devfs_path_free (*minor_path);
477c74d5d46Sjacobs 		*minor_path = NULL;
47842a7bdedSjacobs 	}
47942a7bdedSjacobs 	di_devlink_fini (&devlink_hdl);
48018c2aff7Sartem }
48118c2aff7Sartem 
48218c2aff7Sartem static HalDevice *
4833622ad5aSLin Guo - Sun Microsystems devinfo_usb_video4linux_add(HalDevice *usbd, di_node_t node)
4843622ad5aSLin Guo - Sun Microsystems {
4853622ad5aSLin Guo - Sun Microsystems 	HalDevice *d = NULL;
4863622ad5aSLin Guo - Sun Microsystems 	int	major;
4873622ad5aSLin Guo - Sun Microsystems 	di_minor_t minor;
4883622ad5aSLin Guo - Sun Microsystems 	dev_t	devt;
4893622ad5aSLin Guo - Sun Microsystems 	char	*devlink = NULL;
4903622ad5aSLin Guo - Sun Microsystems 	char	*dev_videolink = NULL;
4913622ad5aSLin Guo - Sun Microsystems 	char	*minor_path = NULL;
4923622ad5aSLin Guo - Sun Microsystems 	char	*minor_name = NULL;
4933622ad5aSLin Guo - Sun Microsystems 	char	udi[HAL_PATH_MAX];
4943622ad5aSLin Guo - Sun Microsystems 	char	*s;
4953622ad5aSLin Guo - Sun Microsystems 
4963622ad5aSLin Guo - Sun Microsystems 	get_dev_link_path(node, "usb_video",
497*3fb52c73SRaymond Chen 	    "^usb/video[0-9]+",  &devlink, &minor_path, &minor_name);
4983622ad5aSLin Guo - Sun Microsystems 
4993622ad5aSLin Guo - Sun Microsystems 	if ((minor_path == NULL) || (devlink == NULL)) {
5003622ad5aSLin Guo - Sun Microsystems 
5013622ad5aSLin Guo - Sun Microsystems 		goto out;
5023622ad5aSLin Guo - Sun Microsystems 	}
5033622ad5aSLin Guo - Sun Microsystems 
5043622ad5aSLin Guo - Sun Microsystems 	HAL_DEBUG(("devlink %s, minor_name %s", devlink, minor_name));
5053622ad5aSLin Guo - Sun Microsystems 	if (strcmp(minor_name, "usbvc") != 0) {
5063622ad5aSLin Guo - Sun Microsystems 
5073622ad5aSLin Guo - Sun Microsystems 		goto out;
5083622ad5aSLin Guo - Sun Microsystems 	}
5093622ad5aSLin Guo - Sun Microsystems 
5103622ad5aSLin Guo - Sun Microsystems 	d = hal_device_new();
5113622ad5aSLin Guo - Sun Microsystems 
5123622ad5aSLin Guo - Sun Microsystems 	devinfo_set_default_properties(d, usbd, node, minor_path);
5133622ad5aSLin Guo - Sun Microsystems 	hal_device_property_set_string(d, "info.subsystem", "video4linux");
5143622ad5aSLin Guo - Sun Microsystems 	hal_device_property_set_string(d, "info.category", "video4linux");
5153622ad5aSLin Guo - Sun Microsystems 
5163622ad5aSLin Guo - Sun Microsystems 	hal_device_add_capability(d, "video4linux");
5173622ad5aSLin Guo - Sun Microsystems 
5183622ad5aSLin Guo - Sun Microsystems 	/* Get logic link under /dev (/dev/video+) */
5193622ad5aSLin Guo - Sun Microsystems 	dev_videolink = get_usb_devlink(strstr(devlink, "usb"), "/dev/");
5203622ad5aSLin Guo - Sun Microsystems 
5213622ad5aSLin Guo - Sun Microsystems 	hal_device_property_set_string(d, "video4linux.device", dev_videolink);
5223622ad5aSLin Guo - Sun Microsystems 
5233622ad5aSLin Guo - Sun Microsystems 	hal_util_compute_udi(hald_get_gdl(), udi, sizeof (udi),
5243622ad5aSLin Guo - Sun Microsystems 	    "%s_video4linux", hal_device_get_udi(usbd));
5253622ad5aSLin Guo - Sun Microsystems 
5263622ad5aSLin Guo - Sun Microsystems 	hal_device_set_udi(d, udi);
5273622ad5aSLin Guo - Sun Microsystems 	hal_device_property_set_string(d, "info.udi", udi);
5283622ad5aSLin Guo - Sun Microsystems 	PROP_STR(d, node, s, "usb-product-name", "info.product");
5293622ad5aSLin Guo - Sun Microsystems 
5303622ad5aSLin Guo - Sun Microsystems 	devinfo_add_enqueue(d, minor_path, &devinfo_usb_handler);
5313622ad5aSLin Guo - Sun Microsystems 
5323622ad5aSLin Guo - Sun Microsystems 
5333622ad5aSLin Guo - Sun Microsystems out:
5343622ad5aSLin Guo - Sun Microsystems 	if (devlink) {
5353622ad5aSLin Guo - Sun Microsystems 		free(devlink);
5363622ad5aSLin Guo - Sun Microsystems 	}
5373622ad5aSLin Guo - Sun Microsystems 
5383622ad5aSLin Guo - Sun Microsystems 	if (minor_path) {
5393622ad5aSLin Guo - Sun Microsystems 		di_devfs_path_free(minor_path);
5403622ad5aSLin Guo - Sun Microsystems 	}
5413622ad5aSLin Guo - Sun Microsystems 
5423622ad5aSLin Guo - Sun Microsystems 	return (d);
5433622ad5aSLin Guo - Sun Microsystems }
5443622ad5aSLin Guo - Sun Microsystems 
5453622ad5aSLin Guo - Sun Microsystems static HalDevice *
546b453864fSLin Guo - Sun Microsystems devinfo_usb_input_add(HalDevice *usbd, di_node_t node)
547b453864fSLin Guo - Sun Microsystems {
548b453864fSLin Guo - Sun Microsystems 	HalDevice *d = NULL;
549b453864fSLin Guo - Sun Microsystems 	int	major;
550b453864fSLin Guo - Sun Microsystems 	di_minor_t minor;
551b453864fSLin Guo - Sun Microsystems 	dev_t	devt;
552b453864fSLin Guo - Sun Microsystems 	char	*devlink = NULL;
553b453864fSLin Guo - Sun Microsystems 	char	*minor_path = NULL;
554b453864fSLin Guo - Sun Microsystems 	char	*minor_name = NULL;
555b453864fSLin Guo - Sun Microsystems 	char	udi[HAL_PATH_MAX];
556b453864fSLin Guo - Sun Microsystems 
557b453864fSLin Guo - Sun Microsystems 	get_dev_link_path(node, "ddi_pseudo",
558*3fb52c73SRaymond Chen 	    "^usb/hid[0-9]+",  &devlink, &minor_path, &minor_name);
559b453864fSLin Guo - Sun Microsystems 
560b453864fSLin Guo - Sun Microsystems 	if ((minor_path == NULL) || (devlink == NULL)) {
561b453864fSLin Guo - Sun Microsystems 
562b453864fSLin Guo - Sun Microsystems 		goto out;
563b453864fSLin Guo - Sun Microsystems 	}
564b453864fSLin Guo - Sun Microsystems 
565b453864fSLin Guo - Sun Microsystems 	HAL_DEBUG(("devlink %s, minor_name %s", devlink, minor_name));
566b453864fSLin Guo - Sun Microsystems 	if ((strcmp(minor_name, "keyboard") != 0) &&
567b453864fSLin Guo - Sun Microsystems 	    (strcmp(minor_name, "mouse") != 0)) {
568b453864fSLin Guo - Sun Microsystems 
569b453864fSLin Guo - Sun Microsystems 		goto out;
570b453864fSLin Guo - Sun Microsystems 	}
571b453864fSLin Guo - Sun Microsystems 
572b453864fSLin Guo - Sun Microsystems 	d = hal_device_new();
573b453864fSLin Guo - Sun Microsystems 
574b453864fSLin Guo - Sun Microsystems 	devinfo_set_default_properties(d, usbd, node, minor_path);
575b453864fSLin Guo - Sun Microsystems 	hal_device_property_set_string(d, "info.subsystem", "input");
576b453864fSLin Guo - Sun Microsystems 	hal_device_property_set_string(d, "info.category", "input");
577b453864fSLin Guo - Sun Microsystems 
578b453864fSLin Guo - Sun Microsystems 	hal_device_add_capability(d, "input");
579b453864fSLin Guo - Sun Microsystems 
580b453864fSLin Guo - Sun Microsystems 	if (strcmp(minor_name, "keyboard") == 0) {
581b453864fSLin Guo - Sun Microsystems 		hal_device_add_capability(d, "input.keyboard");
582b453864fSLin Guo - Sun Microsystems 		hal_device_add_capability(d, "input.keys");
583b453864fSLin Guo - Sun Microsystems 		hal_device_add_capability(d, "button");
584b453864fSLin Guo - Sun Microsystems 	} else if (strcmp(minor_name, "mouse") == 0) {
585b453864fSLin Guo - Sun Microsystems 		hal_device_add_capability (d, "input.mouse");
586b453864fSLin Guo - Sun Microsystems 	}
587b453864fSLin Guo - Sun Microsystems 
588b453864fSLin Guo - Sun Microsystems 	hal_device_property_set_string(d, "input.device", devlink);
589b453864fSLin Guo - Sun Microsystems 	hal_device_property_set_string(d, "input.originating_device",
590b453864fSLin Guo - Sun Microsystems 	    hal_device_get_udi(usbd));
591b453864fSLin Guo - Sun Microsystems 
592b453864fSLin Guo - Sun Microsystems 	hal_util_compute_udi(hald_get_gdl(), udi, sizeof (udi),
593b453864fSLin Guo - Sun Microsystems 	    "%s_logicaldev_input", hal_device_get_udi(usbd));
594b453864fSLin Guo - Sun Microsystems 
595b453864fSLin Guo - Sun Microsystems 	hal_device_set_udi(d, udi);
596b453864fSLin Guo - Sun Microsystems 	hal_device_property_set_string(d, "info.udi", udi);
597b453864fSLin Guo - Sun Microsystems 
598b453864fSLin Guo - Sun Microsystems 	if (strcmp(minor_name, "keyboard") == 0) {
599b453864fSLin Guo - Sun Microsystems 		devinfo_add_enqueue(d, minor_path, &devinfo_usb_keyboard_handler);
600b453864fSLin Guo - Sun Microsystems 	} else {
601b453864fSLin Guo - Sun Microsystems 		devinfo_add_enqueue(d, minor_path, &devinfo_usb_handler);
602b453864fSLin Guo - Sun Microsystems 	}
603b453864fSLin Guo - Sun Microsystems 
604b453864fSLin Guo - Sun Microsystems 	/* add to TDL so preprobing callouts and prober can access it */
605b453864fSLin Guo - Sun Microsystems 	hal_device_store_add(hald_get_tdl(), d);
606b453864fSLin Guo - Sun Microsystems 
607b453864fSLin Guo - Sun Microsystems out:
608b453864fSLin Guo - Sun Microsystems 	if (devlink) {
609b453864fSLin Guo - Sun Microsystems 		free(devlink);
610b453864fSLin Guo - Sun Microsystems 	}
611b453864fSLin Guo - Sun Microsystems 
612b453864fSLin Guo - Sun Microsystems 	if (minor_path) {
613b453864fSLin Guo - Sun Microsystems 		di_devfs_path_free(minor_path);
614b453864fSLin Guo - Sun Microsystems 	}
615b453864fSLin Guo - Sun Microsystems 
616b453864fSLin Guo - Sun Microsystems 	return (d);
617b453864fSLin Guo - Sun Microsystems }
618b453864fSLin Guo - Sun Microsystems 
619b453864fSLin Guo - Sun Microsystems static HalDevice *
620112cd14aSqz150045 devinfo_usb_scsa2usb_add(HalDevice *usbd, di_node_t node)
62118c2aff7Sartem {
62218c2aff7Sartem 	HalDevice *d = NULL;
62318c2aff7Sartem 	di_devlink_handle_t devlink_hdl;
62418c2aff7Sartem 	int	major;
62518c2aff7Sartem 	di_minor_t minor;
62618c2aff7Sartem 	dev_t	devt;
62718c2aff7Sartem 	char	*minor_path = NULL;
628b453864fSLin Guo - Sun Microsystems 	char	*minor_name = NULL;
62918c2aff7Sartem 	char	*devlink = NULL;
63018c2aff7Sartem 	char	udi[HAL_PATH_MAX];
63118c2aff7Sartem 
632*3fb52c73SRaymond Chen 	get_dev_link_path(node, "ddi_ctl:devctl:scsi",
633*3fb52c73SRaymond Chen 	    "^usb/mass-storage[0-9]+", &devlink, &minor_path, &minor_name);
63418c2aff7Sartem 
63542a7bdedSjacobs 	if ((devlink == NULL) || (minor_path == NULL)) {
63618c2aff7Sartem 		goto out;
63718c2aff7Sartem 	}
63818c2aff7Sartem 
63918c2aff7Sartem 	d = hal_device_new ();
64018c2aff7Sartem 
64118c2aff7Sartem 	devinfo_set_default_properties (d, usbd, node, minor_path);
64218c2aff7Sartem 	hal_device_property_set_string (d, "scsi_host.solaris.device", devlink);
64318c2aff7Sartem 	hal_device_property_set_string (d, "info.category", "scsi_host");
64418c2aff7Sartem 	hal_device_property_set_int (d, "scsi_host.host", 0);
64518c2aff7Sartem 
64618c2aff7Sartem 	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
64700687e57Sartem 	    "%s/scsi_host%d", hal_device_get_udi (usbd),
64818c2aff7Sartem 	    hal_device_property_get_int (d, "scsi_host.host"));
64918c2aff7Sartem 	hal_device_set_udi (d, udi);
65018c2aff7Sartem 	hal_device_property_set_string (d, "info.udi", udi);
65118c2aff7Sartem 	hal_device_property_set_string (d, "info.product", "SCSI Host Adapter");
65218c2aff7Sartem 
65318c2aff7Sartem 	devinfo_add_enqueue (d, minor_path, &devinfo_usb_handler);
65418c2aff7Sartem 
65518c2aff7Sartem out:
65618c2aff7Sartem 	if (devlink) {
65718c2aff7Sartem 		free(devlink);
65818c2aff7Sartem 	}
65918c2aff7Sartem 	if (minor_path) {
66018c2aff7Sartem 		di_devfs_path_free (minor_path);
66118c2aff7Sartem 	}
66218c2aff7Sartem 
66318c2aff7Sartem 	return (d);
66418c2aff7Sartem }
66518c2aff7Sartem 
66642a7bdedSjacobs static HalDevice *
667112cd14aSqz150045 devinfo_usb_printer_add(HalDevice *parent, di_node_t node)
66842a7bdedSjacobs {
669d5c32991SNorm Jacobs 	char *properties[] = { "vendor", "product", "serial", NULL };
670d5c32991SNorm Jacobs 	int i;
67142a7bdedSjacobs 	HalDevice *d = NULL;
67242a7bdedSjacobs 	char	udi[HAL_PATH_MAX];
67342a7bdedSjacobs 	char *s;
674b453864fSLin Guo - Sun Microsystems 	char *devlink = NULL, *minor_path = NULL, *minor_name = NULL;
675d5c32991SNorm Jacobs 	const char	*subsystem;
67642a7bdedSjacobs 
677b453864fSLin Guo - Sun Microsystems 	get_dev_link_path(node, "ddi_printer", "printers/.+", &devlink, &minor_path, &minor_name);
67842a7bdedSjacobs 
67942a7bdedSjacobs 	if ((devlink == NULL) || (minor_path == NULL)) {
68042a7bdedSjacobs 		goto out;
68142a7bdedSjacobs 	}
68242a7bdedSjacobs 
68342a7bdedSjacobs 	d = hal_device_new ();
68442a7bdedSjacobs 
68542a7bdedSjacobs 	devinfo_set_default_properties (d, parent, node, minor_path);
68642a7bdedSjacobs 	hal_device_property_set_string (d, "info.category", "printer");
68742a7bdedSjacobs 	hal_device_add_capability (d, "printer");
68842a7bdedSjacobs 
68942a7bdedSjacobs 	/* add printer properties */
69042a7bdedSjacobs 	hal_device_property_set_string (d, "printer.device", devlink);
691d5c32991SNorm Jacobs 
692d5c32991SNorm Jacobs 	/* copy parent's selected usb* properties to printer properties */
693d5c32991SNorm Jacobs 	subsystem = hal_device_property_get_string (parent, "info.subsystem");
694d5c32991SNorm Jacobs 	for (i = 0; properties[i] != NULL; i++) {
695d5c32991SNorm Jacobs 		char src[32], dst[32]; /* "subsystem.property" names */
696d5c32991SNorm Jacobs 
697d5c32991SNorm Jacobs 		snprintf(src, sizeof (src), "%s.%s", subsystem, properties[i]);
698d5c32991SNorm Jacobs 		snprintf(dst, sizeof (dst), "printer.%s", properties[i]);
699d5c32991SNorm Jacobs 		hal_device_copy_property(parent, src, d, dst);
700d5c32991SNorm Jacobs 	}
70142a7bdedSjacobs 
70242a7bdedSjacobs 	devinfo_add_enqueue (d, minor_path, &devinfo_usb_printer_handler);
70342a7bdedSjacobs 
70442a7bdedSjacobs out:
70542a7bdedSjacobs 	if (devlink) {
70642a7bdedSjacobs 		free(devlink);
70742a7bdedSjacobs 	}
70842a7bdedSjacobs 	if (minor_path) {
70942a7bdedSjacobs 		di_devfs_path_free (minor_path);
71042a7bdedSjacobs 	}
71142a7bdedSjacobs 
71242a7bdedSjacobs 	return (d);
71342a7bdedSjacobs }
71442a7bdedSjacobs 
71542a7bdedSjacobs const gchar *
71642a7bdedSjacobs devinfo_printer_prnio_get_prober (HalDevice *d, int *timeout)
71742a7bdedSjacobs {
71842a7bdedSjacobs 	*timeout = 5 * 1000;	/* 5 second timeout */
71942a7bdedSjacobs 	return ("hald-probe-printer");
72042a7bdedSjacobs }
721b453864fSLin Guo - Sun Microsystems 
722b453864fSLin Guo - Sun Microsystems const gchar *
723b453864fSLin Guo - Sun Microsystems devinfo_keyboard_get_prober(HalDevice *d, int *timeout)
724b453864fSLin Guo - Sun Microsystems {
725b453864fSLin Guo - Sun Microsystems 	*timeout = 5 * 1000;	/* 5 second timeout */
726b453864fSLin Guo - Sun Microsystems 	return ("hald-probe-xkb");
727b453864fSLin Guo - Sun Microsystems }
728