12912Sartem /*************************************************************************** 22912Sartem * 32912Sartem * devinfo_usb.h : USB devices 42912Sartem * 5*6112Sqz150045 * Copyright 2008 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> 24*6112Sqz150045 #include <sys/usb/usbai.h> 252912Sartem 262912Sartem #include "../osspec.h" 272912Sartem #include "../logger.h" 282912Sartem #include "../hald.h" 292912Sartem #include "../hald_dbus.h" 302912Sartem #include "../device_info.h" 312912Sartem #include "../util.h" 322912Sartem #include "../ids.h" 332912Sartem #include "hotplug.h" 342912Sartem #include "devinfo.h" 352912Sartem #include "devinfo_usb.h" 362912Sartem 37*6112Sqz150045 static HalDevice *devinfo_usb_if_add(HalDevice *d, di_node_t node, gchar *devfs_path, 38*6112Sqz150045 gchar *if_devfs_path, int ifnum); 39*6112Sqz150045 static HalDevice *devinfo_usb_scsa2usb_add(HalDevice *d, di_node_t node); 40*6112Sqz150045 static HalDevice *devinfo_usb_printer_add(HalDevice *usbd, di_node_t node); 413536Sjacobs const gchar *devinfo_printer_prnio_get_prober (HalDevice *d, int *timeout); 42*6112Sqz150045 static void set_usb_properties(HalDevice *d, di_node_t node, gchar *devfs_path, char *driver_name); 432912Sartem 442912Sartem DevinfoDevHandler devinfo_usb_handler = { 45*6112Sqz150045 devinfo_usb_add, 462912Sartem NULL, 472912Sartem NULL, 482912Sartem NULL, 492912Sartem NULL, 50*6112Sqz150045 NULL 512912Sartem }; 522912Sartem 533536Sjacobs DevinfoDevHandler devinfo_usb_printer_handler = { 54*6112Sqz150045 devinfo_usb_add, 553536Sjacobs NULL, 563536Sjacobs NULL, 573536Sjacobs NULL, 583536Sjacobs NULL, 59*6112Sqz150045 devinfo_printer_prnio_get_prober 603536Sjacobs }; 613536Sjacobs 623710Sjacobs static gboolean 633710Sjacobs is_usb_node(di_node_t node) 643710Sjacobs { 653710Sjacobs int rc; 663710Sjacobs char *s; 673710Sjacobs 683710Sjacobs /* 693710Sjacobs * USB device nodes will have "compatible" propety values that 703710Sjacobs * begins with "usb". 713710Sjacobs */ 72*6112Sqz150045 rc = di_prop_lookup_strings(DDI_DEV_T_ANY, node, "compatible", &s); 733710Sjacobs while (rc-- > 0) { 743710Sjacobs if (strncmp(s, "usb", 3) == 0) { 753710Sjacobs return (TRUE); 763710Sjacobs } 773710Sjacobs s += (strlen(s) + 1); 783710Sjacobs } 793710Sjacobs 803710Sjacobs return (FALSE); 813710Sjacobs } 823710Sjacobs 832912Sartem HalDevice * 842912Sartem devinfo_usb_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type) 852912Sartem { 862912Sartem HalDevice *d, *nd = NULL; 872912Sartem char *s; 883710Sjacobs int *i; 892912Sartem char *driver_name, *binding_name; 90*6112Sqz150045 char if_devfs_path[HAL_PATH_MAX]; 91*6112Sqz150045 di_devlink_handle_t hdl; 92*6112Sqz150045 double k; 932912Sartem 94*6112Sqz150045 if (is_usb_node(node) == FALSE) { 952912Sartem return (NULL); 962912Sartem } 972912Sartem 98*6112Sqz150045 driver_name = di_driver_name (node); 99*6112Sqz150045 100*6112Sqz150045 if (di_prop_lookup_ints (DDI_DEV_T_ANY, node, "interface", &i) < 0) { 101*6112Sqz150045 /* It is a USB device node. */ 102*6112Sqz150045 103*6112Sqz150045 d = hal_device_new (); 1042912Sartem 105*6112Sqz150045 devinfo_set_default_properties (d, parent, node, devfs_path); 106*6112Sqz150045 hal_device_property_set_string (d, "info.subsystem", "usb_device"); 107*6112Sqz150045 PROP_STR(d, node, s, "usb-product-name", "info.product"); 108*6112Sqz150045 PROP_STR(d, node, s, "usb-product-name", "usb_device.product"); 109*6112Sqz150045 PROP_STR(d, node, s, "usb-vendor-name", "usb_device.vendor"); 110*6112Sqz150045 PROP_INT(d, node, i, "usb-vendor-id", "usb_device.vendor_id"); 111*6112Sqz150045 PROP_INT(d, node, i, "usb-product-id", "usb_device.product_id"); 112*6112Sqz150045 PROP_INT(d, node, i, "usb-revision-id", "usb_device.device_revision_bcd"); 113*6112Sqz150045 PROP_STR(d, node, s, "usb-serialno", "usb_device.serial"); 114*6112Sqz150045 PROP_INT(d, node, i, "usb-port-count", "usb_device.num_ports"); 115*6112Sqz150045 PROP_INT(d, node, i, "usb-num-configs", "usb_device.num_configurations"); 116*6112Sqz150045 PROP_INT(d, node, i, "assigned-address", "usb_device.bus_number"); 117*6112Sqz150045 118*6112Sqz150045 if (di_prop_lookup_ints (DDI_DEV_T_ANY, node, "usb-release", &i) > 0) { 119*6112Sqz150045 k = (double)bcd(*i); 120*6112Sqz150045 hal_device_property_set_double (d, "usb_device.version", k / 100); 121*6112Sqz150045 } 122*6112Sqz150045 123*6112Sqz150045 if (di_prop_lookup_ints (DDI_DEV_T_ANY, node, "low-speed", &i) >= 0) { 124*6112Sqz150045 k = 1.5; 125*6112Sqz150045 } else if (di_prop_lookup_ints (DDI_DEV_T_ANY, node, "high-speed", &i) >= 0) { 126*6112Sqz150045 k = 480.0; 127*6112Sqz150045 } else { 128*6112Sqz150045 /* It is the full speed device. */ 129*6112Sqz150045 k = 12.0; 130*6112Sqz150045 } 131*6112Sqz150045 hal_device_property_set_double (d, "usb_device.speed", k); 132*6112Sqz150045 133*6112Sqz150045 set_usb_properties (d, node, devfs_path, driver_name); 1342912Sartem 135*6112Sqz150045 /* wait for the ugen node's creation */ 136*6112Sqz150045 if ((driver_name != NULL) && (strcmp (driver_name, "usb_mid") == 0)) { 137*6112Sqz150045 if (hdl = di_devlink_init (devfs_path, DI_MAKE_LINK)) { 138*6112Sqz150045 di_devlink_fini (&hdl); 139*6112Sqz150045 } 140*6112Sqz150045 } 141*6112Sqz150045 142*6112Sqz150045 devinfo_add_enqueue (d, devfs_path, &devinfo_usb_handler); 143*6112Sqz150045 144*6112Sqz150045 /* add to TDL so preprobing callouts and prober can access it */ 145*6112Sqz150045 hal_device_store_add (hald_get_tdl (), d); 146*6112Sqz150045 147*6112Sqz150045 if (((binding_name = di_binding_name (node)) != NULL) && 148*6112Sqz150045 (strncmp (binding_name, "usbif,", sizeof ("usbif,") - 1) == 0)) { 149*6112Sqz150045 150*6112Sqz150045 snprintf (if_devfs_path, sizeof (if_devfs_path), "%s:if%d", 151*6112Sqz150045 devfs_path, 0); 152*6112Sqz150045 if ((nd = devinfo_usb_if_add (d, node, if_devfs_path, 153*6112Sqz150045 if_devfs_path, 0)) != NULL) { 1542912Sartem 155*6112Sqz150045 d = nd; 156*6112Sqz150045 nd = NULL; 157*6112Sqz150045 devfs_path = if_devfs_path; 158*6112Sqz150045 } 1592912Sartem } 160*6112Sqz150045 } else { 161*6112Sqz150045 /* It is a USB interface node or IA node. */ 162*6112Sqz150045 int *j; 163*6112Sqz150045 164*6112Sqz150045 if (di_prop_lookup_ints (DDI_DEV_T_ANY, node, "interface-count", &j) > 0) { 165*6112Sqz150045 /* 166*6112Sqz150045 * The USB IA node properties are not defined in 167*6112Sqz150045 * HAL spec so far. So IA node udi has "ia" sign 168*6112Sqz150045 * now, different from the IF node udi with "if". 169*6112Sqz150045 */ 170*6112Sqz150045 snprintf (if_devfs_path, sizeof (if_devfs_path), 171*6112Sqz150045 "%s:ia%d", devfs_path, *i); 172*6112Sqz150045 } else { 173*6112Sqz150045 snprintf (if_devfs_path, sizeof (if_devfs_path), 174*6112Sqz150045 "%s:if%d", devfs_path, *i); 175*6112Sqz150045 } 176*6112Sqz150045 177*6112Sqz150045 d = devinfo_usb_if_add (parent, node, devfs_path, if_devfs_path, *i); 1782912Sartem } 1792912Sartem 1802912Sartem /* driver specific */ 1812912Sartem if ((driver_name != NULL) && (strcmp (driver_name, "scsa2usb") == 0)) { 182*6112Sqz150045 nd = devinfo_usb_scsa2usb_add (d, node); 1833536Sjacobs } else if ((driver_name != NULL) && 184*6112Sqz150045 (strcmp (driver_name, "usbprn") == 0)) { 185*6112Sqz150045 nd = devinfo_usb_printer_add (d, node); 1862912Sartem } 1872912Sartem 1882912Sartem out: 1892912Sartem if (nd != NULL) { 1902912Sartem return (nd); 1912912Sartem } else { 1922912Sartem return (d); 1932912Sartem } 1942912Sartem } 1952912Sartem 196*6112Sqz150045 197*6112Sqz150045 static void 198*6112Sqz150045 set_usb_properties(HalDevice *d, di_node_t node, gchar *devfs_path, char *driver_name) 199*6112Sqz150045 { 200*6112Sqz150045 usb_dev_descr_t *dev_descrp = NULL; /* device descriptor */ 201*6112Sqz150045 usb_cfg_descr_t *cfg_descrp = NULL; /* configuration descriptor */ 202*6112Sqz150045 unsigned char *rdata = NULL; 203*6112Sqz150045 char *p; 204*6112Sqz150045 int i = 0; 205*6112Sqz150045 206*6112Sqz150045 hal_device_property_set_int (d, "usb_device.port_number", 207*6112Sqz150045 atoi (devfs_path + strlen (devfs_path) -1)); 208*6112Sqz150045 209*6112Sqz150045 if (di_prop_lookup_bytes (DDI_DEV_T_ANY, node, "usb-dev-descriptor", 210*6112Sqz150045 &rdata) > 0) { 211*6112Sqz150045 dev_descrp = (usb_dev_descr_t *)rdata; 212*6112Sqz150045 213*6112Sqz150045 if (dev_descrp != NULL) { 214*6112Sqz150045 hal_device_property_set_int (d, "usb_device.device_class", 215*6112Sqz150045 dev_descrp->bDeviceClass); 216*6112Sqz150045 hal_device_property_set_int (d, "usb_device.device_subclass", 217*6112Sqz150045 dev_descrp->bDeviceSubClass); 218*6112Sqz150045 hal_device_property_set_int (d, "usb_device.device_protocol", 219*6112Sqz150045 dev_descrp->bDeviceProtocol); 220*6112Sqz150045 } 221*6112Sqz150045 } 222*6112Sqz150045 223*6112Sqz150045 if (di_prop_lookup_bytes (DDI_DEV_T_ANY, node, "usb-raw-cfg-descriptors", 224*6112Sqz150045 &rdata) > 0) { 225*6112Sqz150045 cfg_descrp = (usb_cfg_descr_t *)(rdata); 226*6112Sqz150045 227*6112Sqz150045 if (cfg_descrp != NULL) { 228*6112Sqz150045 hal_device_property_set_int (d, "usb_device.configuration_value", 229*6112Sqz150045 cfg_descrp->bConfigurationValue); 230*6112Sqz150045 hal_device_property_set_int (d, "usb_device.max_power", 231*6112Sqz150045 cfg_descrp->bMaxPower); 232*6112Sqz150045 hal_device_property_set_int (d, "usb_device.num_interfaces", 233*6112Sqz150045 cfg_descrp->bNumInterfaces); 234*6112Sqz150045 hal_device_property_set_bool (d, "usb_device.can_wake_up", 235*6112Sqz150045 (cfg_descrp->bmAttributes & 0x20) ? TRUE : FALSE); 236*6112Sqz150045 hal_device_property_set_bool (d, "usb_device.is_self_powered", 237*6112Sqz150045 (cfg_descrp->bmAttributes & 0x40) ? TRUE : FALSE); 238*6112Sqz150045 } 239*6112Sqz150045 } 240*6112Sqz150045 241*6112Sqz150045 /* get the node's usb tree level by counting hub numbers */ 242*6112Sqz150045 do { 243*6112Sqz150045 if (p = strstr (devfs_path, "/hub@")) { 244*6112Sqz150045 devfs_path = p + strlen ("/hub@"); 245*6112Sqz150045 i ++; 246*6112Sqz150045 } 247*6112Sqz150045 } while (p != NULL); 248*6112Sqz150045 249*6112Sqz150045 if ((driver_name != NULL) && (strcmp (driver_name, "hubd") == 0) && (i > 0)) 250*6112Sqz150045 i --; 251*6112Sqz150045 252*6112Sqz150045 hal_device_property_set_int (d, "usb_device.level_number", i); 253*6112Sqz150045 } 254*6112Sqz150045 255*6112Sqz150045 256*6112Sqz150045 static usb_if_descr_t * 257*6112Sqz150045 parse_usb_if_descr(di_node_t node, int ifnum) 2582912Sartem { 259*6112Sqz150045 unsigned char *rdata = NULL; 260*6112Sqz150045 usb_if_descr_t *if_descrp=NULL; /* interface descriptor */ 261*6112Sqz150045 di_node_t tmp_node = DI_NODE_NIL; 262*6112Sqz150045 uint8_t num, length, type; 263*6112Sqz150045 int rlen; 264*6112Sqz150045 gchar *devpath = NULL; 265*6112Sqz150045 266*6112Sqz150045 if ((rlen = di_prop_lookup_bytes (DDI_DEV_T_ANY, node, 267*6112Sqz150045 "usb-raw-cfg-descriptors", &rdata)) < 0) { 268*6112Sqz150045 269*6112Sqz150045 char *p; 270*6112Sqz150045 int i; 271*6112Sqz150045 272*6112Sqz150045 if ((devpath = di_devfs_path (node)) == NULL) 273*6112Sqz150045 goto out; 274*6112Sqz150045 275*6112Sqz150045 /* Look up its parent that may be a USB IA or USB mid. */ 276*6112Sqz150045 for (i = 0; i < 2; i++) { 277*6112Sqz150045 p = strrchr (devpath, '/'); 278*6112Sqz150045 if (p == NULL) 279*6112Sqz150045 goto out; 280*6112Sqz150045 *p = '\0'; 281*6112Sqz150045 282*6112Sqz150045 if ((tmp_node = di_init (devpath, DINFOCPYALL)) == DI_NODE_NIL) 283*6112Sqz150045 goto out; 284*6112Sqz150045 285*6112Sqz150045 if ((rlen = di_prop_lookup_bytes (DDI_DEV_T_ANY, tmp_node, 286*6112Sqz150045 "usb-raw-cfg-descriptors", &rdata)) > 0) 287*6112Sqz150045 break; 288*6112Sqz150045 289*6112Sqz150045 di_fini (tmp_node); 290*6112Sqz150045 } 291*6112Sqz150045 } 2922912Sartem 293*6112Sqz150045 if (rdata == NULL) 294*6112Sqz150045 goto out; 295*6112Sqz150045 296*6112Sqz150045 do { 297*6112Sqz150045 length = (uint8_t)*rdata; 298*6112Sqz150045 type = (uint8_t)*(rdata + 1); 299*6112Sqz150045 if (type == USB_DESCR_TYPE_IF) { 300*6112Sqz150045 num = (uint8_t)*(rdata + 2); 301*6112Sqz150045 if (num == ifnum) { 302*6112Sqz150045 if_descrp = (usb_if_descr_t *)rdata; 303*6112Sqz150045 break; 304*6112Sqz150045 } 305*6112Sqz150045 } 306*6112Sqz150045 rdata += length; 307*6112Sqz150045 rlen -= length; 308*6112Sqz150045 } while ((length > 0 ) && (rlen > 0)); 309*6112Sqz150045 310*6112Sqz150045 out: 311*6112Sqz150045 if (devpath != NULL) 312*6112Sqz150045 di_devfs_path_free (devpath); 313*6112Sqz150045 if (tmp_node != DI_NODE_NIL) 314*6112Sqz150045 di_fini (tmp_node); 315*6112Sqz150045 return (if_descrp); 316*6112Sqz150045 } 317*6112Sqz150045 318*6112Sqz150045 319*6112Sqz150045 static HalDevice * 320*6112Sqz150045 devinfo_usb_if_add(HalDevice *parent, di_node_t node, gchar *devfs_path, 321*6112Sqz150045 gchar *if_devfs_path, int ifnum) 322*6112Sqz150045 { 323*6112Sqz150045 HalDevice *d = NULL; 324*6112Sqz150045 char udi[HAL_PATH_MAX]; 325*6112Sqz150045 const char *parent_info; 326*6112Sqz150045 usb_if_descr_t *if_descrp=NULL; /* interface descriptor */ 3272912Sartem 3282912Sartem d = hal_device_new (); 3292912Sartem 330*6112Sqz150045 devinfo_set_default_properties (d, parent, node, if_devfs_path); 331*6112Sqz150045 332*6112Sqz150045 /* Set the existed physical device path. */ 333*6112Sqz150045 hal_device_property_set_string (d, "solaris.devfs_path", devfs_path); 334*6112Sqz150045 hal_device_property_set_string (d, "info.subsystem", "usb"); 335*6112Sqz150045 hal_device_property_set_string (d, "info.product", "USB Device Interface"); 336*6112Sqz150045 337*6112Sqz150045 /* Set usb interface properties to interface node. */ 338*6112Sqz150045 if (strstr (if_devfs_path, ":ia") == NULL) { 339*6112Sqz150045 if_descrp = parse_usb_if_descr (node, ifnum); 340*6112Sqz150045 341*6112Sqz150045 if (if_descrp != NULL) { 342*6112Sqz150045 hal_device_property_set_int (d, "usb.interface.class", 343*6112Sqz150045 if_descrp->bInterfaceClass); 344*6112Sqz150045 hal_device_property_set_int (d, "usb.interface.subclass", 345*6112Sqz150045 if_descrp->bInterfaceSubClass); 346*6112Sqz150045 hal_device_property_set_int (d, "usb.interface.protocol", 347*6112Sqz150045 if_descrp->bInterfaceProtocol); 348*6112Sqz150045 hal_device_property_set_int (d, "usb.interface.number", 349*6112Sqz150045 if_descrp->bInterfaceNumber); 350*6112Sqz150045 } 351*6112Sqz150045 } 3522912Sartem 3532912Sartem /* copy parent's usb_device.* properties */ 354*6112Sqz150045 parent_info = hal_device_property_get_string (parent, "info.subsystem"); 355*6112Sqz150045 if (parent_info != NULL) { 356*6112Sqz150045 if (strcmp (parent_info, "usb_device") == 0) { 357*6112Sqz150045 hal_device_merge_with_rewrite (d, parent, "usb.", "usb_device."); 358*6112Sqz150045 } else if (strcmp (parent_info, "usb") == 0) { 359*6112Sqz150045 /* for the case that the parent is IA node */ 360*6112Sqz150045 hal_device_merge_with_rewrite (d, parent, "usb.", "usb."); 361*6112Sqz150045 } 362*6112Sqz150045 } 363*6112Sqz150045 364*6112Sqz150045 devinfo_add_enqueue (d, devfs_path, &devinfo_usb_handler); 365*6112Sqz150045 366*6112Sqz150045 /* add to TDL so preprobing callouts and prober can access it */ 367*6112Sqz150045 hal_device_store_add (hald_get_tdl (), d); 3682912Sartem 3692912Sartem return (d); 3702912Sartem } 3712912Sartem 3722912Sartem 3733536Sjacobs static void 3743536Sjacobs get_dev_link_path(di_node_t node, char *nodetype, char *re, char **devlink, char **minor_path) 3753536Sjacobs { 3763536Sjacobs di_devlink_handle_t devlink_hdl; 377*6112Sqz150045 int major; 378*6112Sqz150045 di_minor_t minor; 379*6112Sqz150045 dev_t devt; 3802912Sartem 3813536Sjacobs *devlink = NULL; 382*6112Sqz150045 *minor_path = NULL; 3833536Sjacobs 384*6112Sqz150045 if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) { 385*6112Sqz150045 printf("di_devlink_init() failed\n"); 386*6112Sqz150045 return; 387*6112Sqz150045 } 3882912Sartem 389*6112Sqz150045 major = di_driver_major(node); 390*6112Sqz150045 minor = DI_MINOR_NIL; 391*6112Sqz150045 while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) { 392*6112Sqz150045 devt = di_minor_devt(minor); 393*6112Sqz150045 if (major != major(devt)) { 394*6112Sqz150045 continue; 395*6112Sqz150045 } 3963536Sjacobs 397*6112Sqz150045 if (di_minor_type(minor) != DDM_MINOR) { 398*6112Sqz150045 continue; 399*6112Sqz150045 } 4002912Sartem 401*6112Sqz150045 if ((*minor_path = di_devfs_minor_path(minor)) == NULL) { 402*6112Sqz150045 continue; 403*6112Sqz150045 } 4042912Sartem 4053536Sjacobs if ((strcmp (di_minor_nodetype(minor), nodetype) == 0) && 4063536Sjacobs ((*devlink = get_devlink(devlink_hdl, re, *minor_path)) != NULL)) { 4073536Sjacobs break; 4083536Sjacobs } 4093536Sjacobs di_devfs_path_free (*minor_path); 4103710Sjacobs *minor_path = NULL; 4113536Sjacobs } 4123536Sjacobs di_devlink_fini (&devlink_hdl); 4132912Sartem } 4142912Sartem 4152912Sartem static HalDevice * 416*6112Sqz150045 devinfo_usb_scsa2usb_add(HalDevice *usbd, di_node_t node) 4172912Sartem { 4182912Sartem HalDevice *d = NULL; 4192912Sartem di_devlink_handle_t devlink_hdl; 420*6112Sqz150045 int major; 421*6112Sqz150045 di_minor_t minor; 422*6112Sqz150045 dev_t devt; 423*6112Sqz150045 char *minor_path = NULL; 4242912Sartem char *devlink = NULL; 425*6112Sqz150045 char udi[HAL_PATH_MAX]; 4262912Sartem 4273536Sjacobs get_dev_link_path(node, "ddi_ctl:devctl:scsi", NULL, &devlink, &minor_path); 4282912Sartem 4293536Sjacobs if ((devlink == NULL) || (minor_path == NULL)) { 4302912Sartem goto out; 4312912Sartem } 4322912Sartem 4332912Sartem d = hal_device_new (); 4342912Sartem 4352912Sartem devinfo_set_default_properties (d, usbd, node, minor_path); 436*6112Sqz150045 hal_device_property_set_string (d, "scsi_host.solaris.device", devlink); 437*6112Sqz150045 hal_device_property_set_string (d, "info.category", "scsi_host"); 438*6112Sqz150045 hal_device_property_set_int (d, "scsi_host.host", 0); 4392912Sartem 440*6112Sqz150045 hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi), 441*6112Sqz150045 "%s/scsi_host%d", hal_device_get_udi (usbd), 442*6112Sqz150045 hal_device_property_get_int (d, "scsi_host.host")); 443*6112Sqz150045 hal_device_set_udi (d, udi); 444*6112Sqz150045 hal_device_property_set_string (d, "info.udi", udi); 445*6112Sqz150045 hal_device_property_set_string (d, "info.product", "SCSI Host Adapter"); 4462912Sartem 4472912Sartem devinfo_add_enqueue (d, minor_path, &devinfo_usb_handler); 4482912Sartem 4492912Sartem out: 4502912Sartem if (devlink) { 4512912Sartem free(devlink); 4522912Sartem } 4532912Sartem if (minor_path) { 4542912Sartem di_devfs_path_free (minor_path); 4552912Sartem } 4562912Sartem 4572912Sartem return (d); 4582912Sartem } 4592912Sartem 4603536Sjacobs static HalDevice * 461*6112Sqz150045 devinfo_usb_printer_add(HalDevice *parent, di_node_t node) 4623536Sjacobs { 4633536Sjacobs HalDevice *d = NULL; 464*6112Sqz150045 char udi[HAL_PATH_MAX]; 4653536Sjacobs char *s; 4663536Sjacobs char *devlink = NULL, *minor_path = NULL; 4673536Sjacobs 4683536Sjacobs get_dev_link_path(node, "ddi_printer", "printers/.+", &devlink, &minor_path); 4693536Sjacobs 4703536Sjacobs if ((devlink == NULL) || (minor_path == NULL)) { 4713536Sjacobs goto out; 4723536Sjacobs } 4733536Sjacobs 4743536Sjacobs d = hal_device_new (); 4753536Sjacobs 4763536Sjacobs devinfo_set_default_properties (d, parent, node, minor_path); 477*6112Sqz150045 hal_device_property_set_string (d, "info.category", "printer"); 4783536Sjacobs hal_device_add_capability (d, "printer"); 4793536Sjacobs 4803536Sjacobs /* copy parent's usb_device.* properties */ 4813536Sjacobs hal_device_merge_with_rewrite (d, parent, "usb.", "usb_device."); 4823536Sjacobs 4833536Sjacobs /* add printer properties */ 484*6112Sqz150045 hal_device_property_set_string (d, "printer.device", devlink); 4853536Sjacobs PROP_STR(d, node, s, "usb-vendor-name", "printer.vendor"); 4863536Sjacobs PROP_STR(d, node, s, "usb-product-name", "printer.product"); 4873536Sjacobs PROP_STR(d, node, s, "usb-serialno", "printer.serial"); 4883536Sjacobs 4893536Sjacobs devinfo_add_enqueue (d, minor_path, &devinfo_usb_printer_handler); 4903536Sjacobs 4913536Sjacobs out: 4923536Sjacobs if (devlink) { 4933536Sjacobs free(devlink); 4943536Sjacobs } 4953536Sjacobs if (minor_path) { 4963536Sjacobs di_devfs_path_free (minor_path); 4973536Sjacobs } 4983536Sjacobs 4993536Sjacobs return (d); 5003536Sjacobs } 5013536Sjacobs 5023536Sjacobs const gchar * 5033536Sjacobs devinfo_printer_prnio_get_prober (HalDevice *d, int *timeout) 5043536Sjacobs { 5053536Sjacobs *timeout = 5 * 1000; /* 5 second timeout */ 5063536Sjacobs return ("hald-probe-printer"); 5073536Sjacobs } 508