12912Sartem /*************************************************************************** 22912Sartem * 32912Sartem * devinfo_usb.h : USB devices 42912Sartem * 53536Sjacobs * 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); 393536Sjacobs static HalDevice *devinfo_usb_printer_add(HalDevice *usbd, di_node_t node, gchar *devfs_path); 403536Sjacobs 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 513536Sjacobs DevinfoDevHandler devinfo_usb_printer_handler = { 523536Sjacobs devinfo_usb_add, 533536Sjacobs NULL, 543536Sjacobs NULL, 553536Sjacobs NULL, 563536Sjacobs NULL, 573536Sjacobs devinfo_printer_prnio_get_prober 583536Sjacobs }; 593536Sjacobs 60*3710Sjacobs static gboolean 61*3710Sjacobs is_usb_node(di_node_t node) 62*3710Sjacobs { 63*3710Sjacobs int rc; 64*3710Sjacobs char *s; 65*3710Sjacobs 66*3710Sjacobs /* 67*3710Sjacobs * USB device nodes will have "compatible" propety values that 68*3710Sjacobs * begins with "usb". 69*3710Sjacobs */ 70*3710Sjacobs rc = di_prop_lookup_strings(DDI_DEV_T_ANY, node, "compatible", &s); 71*3710Sjacobs while (rc-- > 0) { 72*3710Sjacobs if (strncmp(s, "usb", 3) == 0) { 73*3710Sjacobs return (TRUE); 74*3710Sjacobs } 75*3710Sjacobs s += (strlen(s) + 1); 76*3710Sjacobs } 77*3710Sjacobs 78*3710Sjacobs return (FALSE); 79*3710Sjacobs } 80*3710Sjacobs 812912Sartem HalDevice * 822912Sartem devinfo_usb_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type) 832912Sartem { 842912Sartem HalDevice *d, *nd = NULL; 852912Sartem char *s; 86*3710Sjacobs int *i; 872912Sartem char *driver_name, *binding_name; 882912Sartem char if_devfs_path[HAL_PATH_MAX]; 892912Sartem 90*3710Sjacobs if (is_usb_node(node) == FALSE) { 912912Sartem return (NULL); 922912Sartem } 932912Sartem 942912Sartem d = hal_device_new (); 952912Sartem 962912Sartem devinfo_set_default_properties (d, parent, node, devfs_path); 972912Sartem hal_device_property_set_string (d, "info.bus", "usb_device"); 982912Sartem PROP_STR(d, node, s, "usb-product-name", "info.product"); 992912Sartem PROP_STR(d, node, s, "usb-product-name", "usb_device.product"); 1002912Sartem PROP_STR(d, node, s, "usb-vendor-name", "usb_device.vendor"); 1012912Sartem PROP_INT(d, node, i, "usb-vendor-id", "usb_device.vendor_id"); 1022912Sartem PROP_INT(d, node, i, "usb-product-id", "usb_device.product_id"); 1032912Sartem PROP_INT(d, node, i, "usb-revision-id", "usb_device.device_revision_bcd"); 1042912Sartem PROP_INT(d, node, i, "usb-release-id", "usb_device.version_bcd"); 1052912Sartem PROP_STR(d, node, s, "usb-serialno", "usb_device.serial"); 1062912Sartem 1072912Sartem /* class, subclass */ 1082912Sartem /* hal_device_property_set_int (d, "usb_device.device_class", 8); */ 1092912Sartem 1102912Sartem /* binding name tells us if driver is bound to interface or device */ 1112912Sartem if (((binding_name = di_binding_name(node)) != NULL) && 1122912Sartem (strncmp(binding_name, "usbif,", sizeof ("usbif,") - 1) == 0)) { 1132912Sartem snprintf(if_devfs_path, sizeof (if_devfs_path), "%s:if%d", devfs_path, 0); 1142912Sartem if ((nd = devinfo_usb_if_add(d, node, if_devfs_path, 0)) != NULL) { 1152912Sartem d = nd; 1162912Sartem nd = NULL; 1172912Sartem devfs_path = if_devfs_path; 1182912Sartem } 1192912Sartem } 1202912Sartem 1212912Sartem /* driver specific */ 1222912Sartem driver_name = di_driver_name (node); 1232912Sartem if ((driver_name != NULL) && (strcmp (driver_name, "scsa2usb") == 0)) { 1242912Sartem nd = devinfo_usb_scsa2usb_add (d, node, devfs_path); 1253536Sjacobs } else if ((driver_name != NULL) && 126*3710Sjacobs (strcmp (driver_name, "usbprn") == 0)) { 1273536Sjacobs nd = devinfo_usb_printer_add (d, node, devfs_path); 1282912Sartem } else { 1292912Sartem devinfo_add_enqueue (d, devfs_path, &devinfo_usb_handler); 1302912Sartem } 1312912Sartem 1322912Sartem out: 1332912Sartem if (nd != NULL) { 1342912Sartem return (nd); 1352912Sartem } else { 1362912Sartem return (d); 1372912Sartem } 1382912Sartem } 1392912Sartem 1402912Sartem static HalDevice * 1412912Sartem devinfo_usb_if_add(HalDevice *parent, di_node_t node, gchar *devfs_path, int ifnum) 1422912Sartem { 1432912Sartem HalDevice *d = NULL; 1442912Sartem char udi[HAL_PATH_MAX]; 1452912Sartem 1462912Sartem devinfo_add_enqueue (parent, devfs_path, &devinfo_usb_handler); 1472912Sartem 1482912Sartem d = hal_device_new (); 1492912Sartem 1502912Sartem devinfo_set_default_properties (d, parent, node, devfs_path); 1512912Sartem hal_device_property_set_string (d, "info.bus", "usb"); 1522912Sartem hal_device_property_set_string (d, "info.product", "USB Device Interface"); 1532912Sartem 1542912Sartem /* copy parent's usb_device.* properties */ 1552912Sartem hal_device_merge_with_rewrite (d, parent, "usb.", "usb_device."); 1562912Sartem 1572912Sartem return (d); 1582912Sartem } 1592912Sartem 1602912Sartem 1613536Sjacobs static void 1623536Sjacobs get_dev_link_path(di_node_t node, char *nodetype, char *re, char **devlink, char **minor_path) 1633536Sjacobs { 1643536Sjacobs di_devlink_handle_t devlink_hdl; 1653536Sjacobs int major; 1663536Sjacobs di_minor_t minor; 1673536Sjacobs dev_t devt; 1682912Sartem 1693536Sjacobs *devlink = NULL; 1703536Sjacobs *minor_path = NULL; 1713536Sjacobs 1723536Sjacobs if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) { 1733536Sjacobs printf("di_devlink_init() failed\n"); 1743536Sjacobs return; 1753536Sjacobs } 1762912Sartem 1773536Sjacobs major = di_driver_major(node); 1783536Sjacobs minor = DI_MINOR_NIL; 1793536Sjacobs while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) { 1803536Sjacobs devt = di_minor_devt(minor); 1813536Sjacobs if (major != major(devt)) { 1823536Sjacobs continue; 1833536Sjacobs } 1843536Sjacobs 1853536Sjacobs if (di_minor_type(minor) != DDM_MINOR) { 1863536Sjacobs continue; 1873536Sjacobs } 1882912Sartem 1893536Sjacobs if ((*minor_path = di_devfs_minor_path(minor)) == NULL) { 1903536Sjacobs continue; 1913536Sjacobs } 1922912Sartem 1933536Sjacobs if ((strcmp (di_minor_nodetype(minor), nodetype) == 0) && 1943536Sjacobs ((*devlink = get_devlink(devlink_hdl, re, *minor_path)) != NULL)) { 1953536Sjacobs break; 1963536Sjacobs } 1973536Sjacobs di_devfs_path_free (*minor_path); 198*3710Sjacobs *minor_path = NULL; 1993536Sjacobs } 2003536Sjacobs di_devlink_fini (&devlink_hdl); 2012912Sartem } 2022912Sartem 2032912Sartem static HalDevice * 2042912Sartem devinfo_usb_scsa2usb_add(HalDevice *usbd, di_node_t node, gchar *devfs_path) 2052912Sartem { 2062912Sartem HalDevice *d = NULL; 2072912Sartem di_devlink_handle_t devlink_hdl; 2082912Sartem int major; 2092912Sartem di_minor_t minor; 2102912Sartem dev_t devt; 2112912Sartem char *minor_path = NULL; 2122912Sartem char *devlink = NULL; 2132912Sartem char udi[HAL_PATH_MAX]; 2142912Sartem 2152912Sartem devinfo_add_enqueue (usbd, devfs_path, &devinfo_usb_handler); 2162912Sartem 2173536Sjacobs get_dev_link_path(node, "ddi_ctl:devctl:scsi", NULL, &devlink, &minor_path); 2182912Sartem 2193536Sjacobs if ((devlink == NULL) || (minor_path == NULL)) { 2202912Sartem goto out; 2212912Sartem } 2222912Sartem 2232912Sartem d = hal_device_new (); 2242912Sartem 2252912Sartem devinfo_set_default_properties (d, usbd, node, minor_path); 2262912Sartem hal_device_property_set_string (d, "scsi_host.solaris.device", devlink); 2272912Sartem hal_device_property_set_string (d, "info.category", "scsi_host"); 2282912Sartem hal_device_property_set_int (d, "scsi_host.host", 0); 2292912Sartem 2302912Sartem hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi), 2313121Sartem "%s/scsi_host%d", hal_device_get_udi (usbd), 2322912Sartem hal_device_property_get_int (d, "scsi_host.host")); 2332912Sartem hal_device_set_udi (d, udi); 2342912Sartem hal_device_property_set_string (d, "info.udi", udi); 2352912Sartem hal_device_property_set_string (d, "info.product", "SCSI Host Adapter"); 2362912Sartem 2372912Sartem devinfo_add_enqueue (d, minor_path, &devinfo_usb_handler); 2382912Sartem 2392912Sartem out: 2402912Sartem if (devlink) { 2412912Sartem free(devlink); 2422912Sartem } 2432912Sartem if (minor_path) { 2442912Sartem di_devfs_path_free (minor_path); 2452912Sartem } 2462912Sartem 2472912Sartem return (d); 2482912Sartem } 2492912Sartem 2503536Sjacobs static HalDevice * 2513536Sjacobs devinfo_usb_printer_add(HalDevice *parent, di_node_t node, gchar *devfs_path) 2523536Sjacobs { 2533536Sjacobs HalDevice *d = NULL; 2543536Sjacobs char udi[HAL_PATH_MAX]; 2553536Sjacobs char *s; 2563536Sjacobs char *devlink = NULL, *minor_path = NULL; 2573536Sjacobs 2583536Sjacobs devinfo_add_enqueue (parent, devfs_path, &devinfo_usb_handler); 2593536Sjacobs 2603536Sjacobs get_dev_link_path(node, "ddi_printer", "printers/.+", &devlink, &minor_path); 2613536Sjacobs 2623536Sjacobs if ((devlink == NULL) || (minor_path == NULL)) { 2633536Sjacobs goto out; 2643536Sjacobs } 2653536Sjacobs 2663536Sjacobs d = hal_device_new (); 2673536Sjacobs 2683536Sjacobs devinfo_set_default_properties (d, parent, node, minor_path); 2693536Sjacobs hal_device_property_set_string (d, "info.category", "printer"); 2703536Sjacobs hal_device_add_capability (d, "printer"); 2713536Sjacobs 2723536Sjacobs /* copy parent's usb_device.* properties */ 2733536Sjacobs hal_device_merge_with_rewrite (d, parent, "usb.", "usb_device."); 2743536Sjacobs 2753536Sjacobs /* add printer properties */ 2763536Sjacobs hal_device_property_set_string (d, "printer.device", devlink); 2773536Sjacobs PROP_STR(d, node, s, "usb-vendor-name", "printer.vendor"); 2783536Sjacobs PROP_STR(d, node, s, "usb-product-name", "printer.product"); 2793536Sjacobs PROP_STR(d, node, s, "usb-serialno", "printer.serial"); 2803536Sjacobs 2813536Sjacobs devinfo_add_enqueue (d, minor_path, &devinfo_usb_printer_handler); 2823536Sjacobs 2833536Sjacobs out: 2843536Sjacobs if (devlink) { 2853536Sjacobs free(devlink); 2863536Sjacobs } 2873536Sjacobs if (minor_path) { 2883536Sjacobs di_devfs_path_free (minor_path); 2893536Sjacobs } 2903536Sjacobs 2913536Sjacobs return (d); 2923536Sjacobs } 2933536Sjacobs 2943536Sjacobs const gchar * 2953536Sjacobs devinfo_printer_prnio_get_prober (HalDevice *d, int *timeout) 2963536Sjacobs { 2973536Sjacobs *timeout = 5 * 1000; /* 5 second timeout */ 2983536Sjacobs return ("hald-probe-printer"); 2993536Sjacobs } 300