12912Sartem /***************************************************************************
22912Sartem  *
32912Sartem  * devinfo_usb.h : USB devices
42912Sartem  *
5*3536Sjacobs  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
62912Sartem  * Use is subject to license terms.
72912Sartem  *
82912Sartem  * Licensed under the Academic Free License version 2.1
92912Sartem  *
102912Sartem  **************************************************************************/
112912Sartem 
122916Sartem #pragma ident	"%Z%%M%	%I%	%E% SMI"
132912Sartem 
143121Sartem #ifdef HAVE_CONFIG_H
153121Sartem #  include <config.h>
163121Sartem #endif
173121Sartem 
182912Sartem #include <stdio.h>
192912Sartem #include <string.h>
202912Sartem #include <libdevinfo.h>
212912Sartem #include <sys/types.h>
222912Sartem #include <sys/mkdev.h>
232912Sartem #include <sys/stat.h>
242912Sartem 
252912Sartem #include "../osspec.h"
262912Sartem #include "../logger.h"
272912Sartem #include "../hald.h"
282912Sartem #include "../hald_dbus.h"
292912Sartem #include "../device_info.h"
302912Sartem #include "../util.h"
312912Sartem #include "../ids.h"
322912Sartem #include "hotplug.h"
332912Sartem #include "devinfo.h"
342912Sartem #include "devinfo_usb.h"
352912Sartem 
362912Sartem HalDevice *devinfo_usb_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type);
372912Sartem static HalDevice *devinfo_usb_if_add(HalDevice *d, di_node_t node, gchar *devfs_path, int ifnum);
382912Sartem static HalDevice *devinfo_usb_scsa2usb_add(HalDevice *d, di_node_t node, gchar *devfs_path);
39*3536Sjacobs static HalDevice *devinfo_usb_printer_add(HalDevice *usbd, di_node_t node, gchar *devfs_path);
40*3536Sjacobs const gchar *devinfo_printer_prnio_get_prober (HalDevice *d, int *timeout);
412912Sartem 
422912Sartem DevinfoDevHandler devinfo_usb_handler = {
432912Sartem         devinfo_usb_add,
442912Sartem 	NULL,
452912Sartem 	NULL,
462912Sartem 	NULL,
472912Sartem 	NULL,
482912Sartem         NULL
492912Sartem };
502912Sartem 
51*3536Sjacobs DevinfoDevHandler devinfo_usb_printer_handler = {
52*3536Sjacobs         devinfo_usb_add,
53*3536Sjacobs 	NULL,
54*3536Sjacobs 	NULL,
55*3536Sjacobs 	NULL,
56*3536Sjacobs 	NULL,
57*3536Sjacobs         devinfo_printer_prnio_get_prober
58*3536Sjacobs };
59*3536Sjacobs 
602912Sartem HalDevice *
612912Sartem devinfo_usb_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type)
622912Sartem {
632912Sartem 	HalDevice *d, *nd = NULL;
642912Sartem 	char	*s;
652912Sartem 	int	*i, *vid;
662912Sartem 	char	*driver_name, *binding_name;
672912Sartem         char    if_devfs_path[HAL_PATH_MAX];
682912Sartem 
692912Sartem 	/*
702912Sartem 	 * we distinguish USB devices by presence of "usb-vendor-id"
712912Sartem 	 * property. should USB devices have "device_type"?
722912Sartem 	 */
732912Sartem         if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "usb-vendor-id", &vid) <= 0) {
742912Sartem 		return (NULL);
752912Sartem 	}
762912Sartem 
772912Sartem 	d = hal_device_new ();
782912Sartem 
792912Sartem 	devinfo_set_default_properties (d, parent, node, devfs_path);
802912Sartem 	hal_device_property_set_string (d, "info.bus", "usb_device");
812912Sartem 	PROP_STR(d, node, s, "usb-product-name", "info.product");
822912Sartem 	PROP_STR(d, node, s, "usb-product-name", "usb_device.product");
832912Sartem 	PROP_STR(d, node, s, "usb-vendor-name", "usb_device.vendor");
842912Sartem 	PROP_INT(d, node, i, "usb-vendor-id", "usb_device.vendor_id");
852912Sartem 	PROP_INT(d, node, i, "usb-product-id", "usb_device.product_id");
862912Sartem 	PROP_INT(d, node, i, "usb-revision-id", "usb_device.device_revision_bcd");
872912Sartem 	PROP_INT(d, node, i, "usb-release-id", "usb_device.version_bcd");
882912Sartem 	PROP_STR(d, node, s, "usb-serialno", "usb_device.serial");
892912Sartem 
902912Sartem 	/* class, subclass */
912912Sartem 	/* hal_device_property_set_int (d, "usb_device.device_class", 8); */
922912Sartem 
932912Sartem 	/* binding name tells us if driver is bound to interface or device */
942912Sartem 	if (((binding_name = di_binding_name(node)) != NULL) &&
952912Sartem 	    (strncmp(binding_name, "usbif,", sizeof ("usbif,") - 1) == 0)) {
962912Sartem 		snprintf(if_devfs_path, sizeof (if_devfs_path), "%s:if%d", devfs_path, 0);
972912Sartem 		if ((nd = devinfo_usb_if_add(d, node, if_devfs_path, 0)) != NULL) {
982912Sartem 			d = nd;
992912Sartem 			nd = NULL;
1002912Sartem 			devfs_path = if_devfs_path;
1012912Sartem 		}
1022912Sartem 	}
1032912Sartem 
1042912Sartem 	/* driver specific */
1052912Sartem 	driver_name = di_driver_name (node);
1062912Sartem 	if ((driver_name != NULL) && (strcmp (driver_name, "scsa2usb") == 0)) {
1072912Sartem 		nd = devinfo_usb_scsa2usb_add (d, node, devfs_path);
108*3536Sjacobs 	} else if ((driver_name != NULL) &&
109*3536Sjacobs 		   (strcmp (driver_name, "usbprn") == 0)) {
110*3536Sjacobs 		nd = devinfo_usb_printer_add (d, node, devfs_path);
1112912Sartem 	} else {
1122912Sartem 		devinfo_add_enqueue (d, devfs_path, &devinfo_usb_handler);
1132912Sartem 	}
1142912Sartem 
1152912Sartem out:
1162912Sartem 	if (nd != NULL) {
1172912Sartem 		return (nd);
1182912Sartem 	} else {
1192912Sartem 		return (d);
1202912Sartem 	}
1212912Sartem }
1222912Sartem 
1232912Sartem static HalDevice *
1242912Sartem devinfo_usb_if_add(HalDevice *parent, di_node_t node, gchar *devfs_path, int ifnum)
1252912Sartem {
1262912Sartem 	HalDevice *d = NULL;
1272912Sartem         char    udi[HAL_PATH_MAX];
1282912Sartem 
1292912Sartem 	devinfo_add_enqueue (parent, devfs_path, &devinfo_usb_handler);
1302912Sartem 
1312912Sartem 	d = hal_device_new ();
1322912Sartem 
1332912Sartem 	devinfo_set_default_properties (d, parent, node, devfs_path);
1342912Sartem         hal_device_property_set_string (d, "info.bus", "usb");
1352912Sartem         hal_device_property_set_string (d, "info.product", "USB Device Interface");
1362912Sartem 
1372912Sartem 	/* copy parent's usb_device.* properties */
1382912Sartem 	hal_device_merge_with_rewrite (d, parent, "usb.", "usb_device.");
1392912Sartem 
1402912Sartem 	return (d);
1412912Sartem }
1422912Sartem 
1432912Sartem 
144*3536Sjacobs static void
145*3536Sjacobs get_dev_link_path(di_node_t node, char *nodetype, char *re, char **devlink, char **minor_path)
146*3536Sjacobs {
147*3536Sjacobs 	di_devlink_handle_t devlink_hdl;
148*3536Sjacobs         int     major;
149*3536Sjacobs         di_minor_t minor;
150*3536Sjacobs         dev_t   devt;
1512912Sartem 
152*3536Sjacobs 	*devlink = NULL;
153*3536Sjacobs         *minor_path = NULL;
154*3536Sjacobs 
155*3536Sjacobs         if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) {
156*3536Sjacobs                 printf("di_devlink_init() failed\n");
157*3536Sjacobs                 return;
158*3536Sjacobs         }
1592912Sartem 
160*3536Sjacobs         major = di_driver_major(node);
161*3536Sjacobs         minor = DI_MINOR_NIL;
162*3536Sjacobs         while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) {
163*3536Sjacobs                 devt = di_minor_devt(minor);
164*3536Sjacobs                 if (major != major(devt)) {
165*3536Sjacobs                         continue;
166*3536Sjacobs                 }
167*3536Sjacobs 
168*3536Sjacobs                 if (di_minor_type(minor) != DDM_MINOR) {
169*3536Sjacobs                         continue;
170*3536Sjacobs                 }
1712912Sartem 
172*3536Sjacobs                 if ((*minor_path = di_devfs_minor_path(minor)) == NULL) {
173*3536Sjacobs                         continue;
174*3536Sjacobs                 }
1752912Sartem 
176*3536Sjacobs 		if ((strcmp (di_minor_nodetype(minor), nodetype) == 0) &&
177*3536Sjacobs 		    ((*devlink = get_devlink(devlink_hdl, re, *minor_path)) != NULL)) {
178*3536Sjacobs 			break;
179*3536Sjacobs 		}
180*3536Sjacobs 		di_devfs_path_free (*minor_path);
181*3536Sjacobs 		minor_path = NULL;
182*3536Sjacobs 	}
183*3536Sjacobs 	di_devlink_fini (&devlink_hdl);
1842912Sartem }
1852912Sartem 
1862912Sartem static HalDevice *
1872912Sartem devinfo_usb_scsa2usb_add(HalDevice *usbd, di_node_t node, gchar *devfs_path)
1882912Sartem {
1892912Sartem 	HalDevice *d = NULL;
1902912Sartem 	di_devlink_handle_t devlink_hdl;
1912912Sartem         int     major;
1922912Sartem         di_minor_t minor;
1932912Sartem         dev_t   devt;
1942912Sartem         char    *minor_path = NULL;
1952912Sartem 	char	*devlink = NULL;
1962912Sartem         char    udi[HAL_PATH_MAX];
1972912Sartem 
1982912Sartem 	devinfo_add_enqueue (usbd, devfs_path, &devinfo_usb_handler);
1992912Sartem 
200*3536Sjacobs 	get_dev_link_path(node, "ddi_ctl:devctl:scsi", NULL,  &devlink, &minor_path);
2012912Sartem 
202*3536Sjacobs 	if ((devlink == NULL) || (minor_path == NULL)) {
2032912Sartem 		goto out;
2042912Sartem 	}
2052912Sartem 
2062912Sartem 	d = hal_device_new ();
2072912Sartem 
2082912Sartem 	devinfo_set_default_properties (d, usbd, node, minor_path);
2092912Sartem        	hal_device_property_set_string (d, "scsi_host.solaris.device", devlink);
2102912Sartem         hal_device_property_set_string (d, "info.category", "scsi_host");
2112912Sartem         hal_device_property_set_int (d, "scsi_host.host", 0);
2122912Sartem 
2132912Sartem         hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
2143121Sartem 		"%s/scsi_host%d", hal_device_get_udi (usbd),
2152912Sartem 		hal_device_property_get_int (d, "scsi_host.host"));
2162912Sartem         hal_device_set_udi (d, udi);
2172912Sartem         hal_device_property_set_string (d, "info.udi", udi);
2182912Sartem         hal_device_property_set_string (d, "info.product", "SCSI Host Adapter");
2192912Sartem 
2202912Sartem 	devinfo_add_enqueue (d, minor_path, &devinfo_usb_handler);
2212912Sartem 
2222912Sartem out:
2232912Sartem 	if (devlink) {
2242912Sartem 		free(devlink);
2252912Sartem 	}
2262912Sartem 	if (minor_path) {
2272912Sartem 		di_devfs_path_free (minor_path);
2282912Sartem 	}
2292912Sartem 
2302912Sartem 	return (d);
2312912Sartem }
2322912Sartem 
233*3536Sjacobs static HalDevice *
234*3536Sjacobs devinfo_usb_printer_add(HalDevice *parent, di_node_t node, gchar *devfs_path)
235*3536Sjacobs {
236*3536Sjacobs 	HalDevice *d = NULL;
237*3536Sjacobs         char    udi[HAL_PATH_MAX];
238*3536Sjacobs 	char *s;
239*3536Sjacobs 	char *devlink = NULL, *minor_path = NULL;
240*3536Sjacobs 
241*3536Sjacobs 	devinfo_add_enqueue (parent, devfs_path, &devinfo_usb_handler);
242*3536Sjacobs 
243*3536Sjacobs 	get_dev_link_path(node, "ddi_printer", "printers/.+", &devlink, &minor_path);
244*3536Sjacobs 
245*3536Sjacobs 	if ((devlink == NULL) || (minor_path == NULL)) {
246*3536Sjacobs 		goto out;
247*3536Sjacobs 	}
248*3536Sjacobs 
249*3536Sjacobs 	d = hal_device_new ();
250*3536Sjacobs 
251*3536Sjacobs 	devinfo_set_default_properties (d, parent, node, minor_path);
252*3536Sjacobs         hal_device_property_set_string (d, "info.category", "printer");
253*3536Sjacobs 	hal_device_add_capability (d, "printer");
254*3536Sjacobs 
255*3536Sjacobs 	/* copy parent's usb_device.* properties */
256*3536Sjacobs 	hal_device_merge_with_rewrite (d, parent, "usb.", "usb_device.");
257*3536Sjacobs 
258*3536Sjacobs 	/* add printer properties */
259*3536Sjacobs         hal_device_property_set_string (d, "printer.device", devlink);
260*3536Sjacobs 	PROP_STR(d, node, s, "usb-vendor-name", "printer.vendor");
261*3536Sjacobs 	PROP_STR(d, node, s, "usb-product-name", "printer.product");
262*3536Sjacobs 	PROP_STR(d, node, s, "usb-serialno", "printer.serial");
263*3536Sjacobs 
264*3536Sjacobs 	devinfo_add_enqueue (d, minor_path, &devinfo_usb_printer_handler);
265*3536Sjacobs 
266*3536Sjacobs out:
267*3536Sjacobs 	if (devlink) {
268*3536Sjacobs 		free(devlink);
269*3536Sjacobs 	}
270*3536Sjacobs 	if (minor_path) {
271*3536Sjacobs 		di_devfs_path_free (minor_path);
272*3536Sjacobs 	}
273*3536Sjacobs 
274*3536Sjacobs 	return (d);
275*3536Sjacobs }
276*3536Sjacobs 
277*3536Sjacobs const gchar *
278*3536Sjacobs devinfo_printer_prnio_get_prober (HalDevice *d, int *timeout)
279*3536Sjacobs {
280*3536Sjacobs 	*timeout = 5 * 1000;	/* 5 second timeout */
281*3536Sjacobs 	return ("hald-probe-printer");
282*3536Sjacobs }
283