12912Sartem /*************************************************************************** 22912Sartem * 32912Sartem * devinfo_usb.h : USB devices 42912Sartem * 5*8529SNorm.Jacobs@Sun.COM * Copyright 2009 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 123121Sartem #ifdef HAVE_CONFIG_H 133121Sartem # include <config.h> 143121Sartem #endif 153121Sartem 162912Sartem #include <stdio.h> 172912Sartem #include <string.h> 182912Sartem #include <libdevinfo.h> 192912Sartem #include <sys/types.h> 202912Sartem #include <sys/mkdev.h> 212912Sartem #include <sys/stat.h> 226112Sqz150045 #include <sys/usb/usbai.h> 232912Sartem 242912Sartem #include "../osspec.h" 252912Sartem #include "../logger.h" 262912Sartem #include "../hald.h" 272912Sartem #include "../hald_dbus.h" 282912Sartem #include "../device_info.h" 292912Sartem #include "../util.h" 302912Sartem #include "../ids.h" 312912Sartem #include "hotplug.h" 322912Sartem #include "devinfo.h" 332912Sartem #include "devinfo_usb.h" 342912Sartem 356112Sqz150045 static HalDevice *devinfo_usb_if_add(HalDevice *d, di_node_t node, gchar *devfs_path, 366112Sqz150045 gchar *if_devfs_path, int ifnum); 376112Sqz150045 static HalDevice *devinfo_usb_scsa2usb_add(HalDevice *d, di_node_t node); 386112Sqz150045 static HalDevice *devinfo_usb_printer_add(HalDevice *usbd, di_node_t node); 393536Sjacobs const gchar *devinfo_printer_prnio_get_prober (HalDevice *d, int *timeout); 406112Sqz150045 static void set_usb_properties(HalDevice *d, di_node_t node, gchar *devfs_path, char *driver_name); 412912Sartem 422912Sartem DevinfoDevHandler devinfo_usb_handler = { 436112Sqz150045 devinfo_usb_add, 442912Sartem NULL, 452912Sartem NULL, 462912Sartem NULL, 472912Sartem NULL, 486112Sqz150045 NULL 492912Sartem }; 502912Sartem 513536Sjacobs DevinfoDevHandler devinfo_usb_printer_handler = { 526112Sqz150045 devinfo_usb_add, 533536Sjacobs NULL, 543536Sjacobs NULL, 553536Sjacobs NULL, 563536Sjacobs NULL, 576112Sqz150045 devinfo_printer_prnio_get_prober 583536Sjacobs }; 593536Sjacobs 603710Sjacobs static gboolean 613710Sjacobs is_usb_node(di_node_t node) 623710Sjacobs { 633710Sjacobs int rc; 643710Sjacobs char *s; 653710Sjacobs 663710Sjacobs /* 673710Sjacobs * USB device nodes will have "compatible" propety values that 683710Sjacobs * begins with "usb". 693710Sjacobs */ 706112Sqz150045 rc = di_prop_lookup_strings(DDI_DEV_T_ANY, node, "compatible", &s); 713710Sjacobs while (rc-- > 0) { 723710Sjacobs if (strncmp(s, "usb", 3) == 0) { 733710Sjacobs return (TRUE); 743710Sjacobs } 753710Sjacobs s += (strlen(s) + 1); 763710Sjacobs } 773710Sjacobs 783710Sjacobs return (FALSE); 793710Sjacobs } 803710Sjacobs 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; 863710Sjacobs int *i; 872912Sartem char *driver_name, *binding_name; 886112Sqz150045 char if_devfs_path[HAL_PATH_MAX]; 896112Sqz150045 di_devlink_handle_t hdl; 906112Sqz150045 double k; 912912Sartem 926112Sqz150045 if (is_usb_node(node) == FALSE) { 932912Sartem return (NULL); 942912Sartem } 952912Sartem 966112Sqz150045 driver_name = di_driver_name (node); 976112Sqz150045 986112Sqz150045 if (di_prop_lookup_ints (DDI_DEV_T_ANY, node, "interface", &i) < 0) { 996112Sqz150045 /* It is a USB device node. */ 1006112Sqz150045 1016112Sqz150045 d = hal_device_new (); 1022912Sartem 1036112Sqz150045 devinfo_set_default_properties (d, parent, node, devfs_path); 1046112Sqz150045 hal_device_property_set_string (d, "info.subsystem", "usb_device"); 1056112Sqz150045 PROP_STR(d, node, s, "usb-product-name", "info.product"); 1066112Sqz150045 PROP_STR(d, node, s, "usb-product-name", "usb_device.product"); 1076112Sqz150045 PROP_STR(d, node, s, "usb-vendor-name", "usb_device.vendor"); 1086112Sqz150045 PROP_INT(d, node, i, "usb-vendor-id", "usb_device.vendor_id"); 1096112Sqz150045 PROP_INT(d, node, i, "usb-product-id", "usb_device.product_id"); 1106112Sqz150045 PROP_INT(d, node, i, "usb-revision-id", "usb_device.device_revision_bcd"); 1116112Sqz150045 PROP_STR(d, node, s, "usb-serialno", "usb_device.serial"); 1126112Sqz150045 PROP_INT(d, node, i, "usb-port-count", "usb_device.num_ports"); 1136112Sqz150045 PROP_INT(d, node, i, "usb-num-configs", "usb_device.num_configurations"); 1146112Sqz150045 PROP_INT(d, node, i, "assigned-address", "usb_device.bus_number"); 1156112Sqz150045 1166112Sqz150045 if (di_prop_lookup_ints (DDI_DEV_T_ANY, node, "usb-release", &i) > 0) { 1176112Sqz150045 k = (double)bcd(*i); 1186112Sqz150045 hal_device_property_set_double (d, "usb_device.version", k / 100); 1196112Sqz150045 } 1206112Sqz150045 1216112Sqz150045 if (di_prop_lookup_ints (DDI_DEV_T_ANY, node, "low-speed", &i) >= 0) { 1226112Sqz150045 k = 1.5; 1236112Sqz150045 } else if (di_prop_lookup_ints (DDI_DEV_T_ANY, node, "high-speed", &i) >= 0) { 1246112Sqz150045 k = 480.0; 1256112Sqz150045 } else { 1266112Sqz150045 /* It is the full speed device. */ 1276112Sqz150045 k = 12.0; 1286112Sqz150045 } 1296112Sqz150045 hal_device_property_set_double (d, "usb_device.speed", k); 1306112Sqz150045 1316112Sqz150045 set_usb_properties (d, node, devfs_path, driver_name); 1322912Sartem 1336112Sqz150045 /* wait for the ugen node's creation */ 1346112Sqz150045 if ((driver_name != NULL) && (strcmp (driver_name, "usb_mid") == 0)) { 1356112Sqz150045 if (hdl = di_devlink_init (devfs_path, DI_MAKE_LINK)) { 1366112Sqz150045 di_devlink_fini (&hdl); 1376112Sqz150045 } 1386112Sqz150045 } 1396112Sqz150045 1406112Sqz150045 devinfo_add_enqueue (d, devfs_path, &devinfo_usb_handler); 1416112Sqz150045 1426112Sqz150045 /* add to TDL so preprobing callouts and prober can access it */ 1436112Sqz150045 hal_device_store_add (hald_get_tdl (), d); 1446112Sqz150045 1456112Sqz150045 if (((binding_name = di_binding_name (node)) != NULL) && 1466112Sqz150045 (strncmp (binding_name, "usbif,", sizeof ("usbif,") - 1) == 0)) { 1476112Sqz150045 1486112Sqz150045 snprintf (if_devfs_path, sizeof (if_devfs_path), "%s:if%d", 1496112Sqz150045 devfs_path, 0); 1506112Sqz150045 if ((nd = devinfo_usb_if_add (d, node, if_devfs_path, 1516112Sqz150045 if_devfs_path, 0)) != NULL) { 1522912Sartem 1536112Sqz150045 d = nd; 1546112Sqz150045 nd = NULL; 1556112Sqz150045 devfs_path = if_devfs_path; 1566112Sqz150045 } 1572912Sartem } 1586112Sqz150045 } else { 1596112Sqz150045 /* It is a USB interface node or IA node. */ 1606112Sqz150045 int *j; 1616112Sqz150045 1626112Sqz150045 if (di_prop_lookup_ints (DDI_DEV_T_ANY, node, "interface-count", &j) > 0) { 1636112Sqz150045 /* 1646112Sqz150045 * The USB IA node properties are not defined in 1656112Sqz150045 * HAL spec so far. So IA node udi has "ia" sign 1666112Sqz150045 * now, different from the IF node udi with "if". 1676112Sqz150045 */ 1686112Sqz150045 snprintf (if_devfs_path, sizeof (if_devfs_path), 1696112Sqz150045 "%s:ia%d", devfs_path, *i); 1706112Sqz150045 } else { 1716112Sqz150045 snprintf (if_devfs_path, sizeof (if_devfs_path), 1726112Sqz150045 "%s:if%d", devfs_path, *i); 1736112Sqz150045 } 1746112Sqz150045 1756112Sqz150045 d = devinfo_usb_if_add (parent, node, devfs_path, if_devfs_path, *i); 1762912Sartem } 1772912Sartem 1782912Sartem /* driver specific */ 1792912Sartem if ((driver_name != NULL) && (strcmp (driver_name, "scsa2usb") == 0)) { 1806112Sqz150045 nd = devinfo_usb_scsa2usb_add (d, node); 1813536Sjacobs } else if ((driver_name != NULL) && 1826112Sqz150045 (strcmp (driver_name, "usbprn") == 0)) { 1836112Sqz150045 nd = devinfo_usb_printer_add (d, node); 1842912Sartem } 1852912Sartem 1862912Sartem out: 1872912Sartem if (nd != NULL) { 1882912Sartem return (nd); 1892912Sartem } else { 1902912Sartem return (d); 1912912Sartem } 1922912Sartem } 1932912Sartem 1946112Sqz150045 1956112Sqz150045 static void 1966112Sqz150045 set_usb_properties(HalDevice *d, di_node_t node, gchar *devfs_path, char *driver_name) 1976112Sqz150045 { 1986112Sqz150045 usb_dev_descr_t *dev_descrp = NULL; /* device descriptor */ 1996112Sqz150045 usb_cfg_descr_t *cfg_descrp = NULL; /* configuration descriptor */ 2006112Sqz150045 unsigned char *rdata = NULL; 2016112Sqz150045 char *p; 2026112Sqz150045 int i = 0; 2036112Sqz150045 2046112Sqz150045 hal_device_property_set_int (d, "usb_device.port_number", 2056112Sqz150045 atoi (devfs_path + strlen (devfs_path) -1)); 2066112Sqz150045 2076112Sqz150045 if (di_prop_lookup_bytes (DDI_DEV_T_ANY, node, "usb-dev-descriptor", 2086112Sqz150045 &rdata) > 0) { 2096112Sqz150045 dev_descrp = (usb_dev_descr_t *)rdata; 2106112Sqz150045 2116112Sqz150045 if (dev_descrp != NULL) { 2126112Sqz150045 hal_device_property_set_int (d, "usb_device.device_class", 2136112Sqz150045 dev_descrp->bDeviceClass); 2146112Sqz150045 hal_device_property_set_int (d, "usb_device.device_subclass", 2156112Sqz150045 dev_descrp->bDeviceSubClass); 2166112Sqz150045 hal_device_property_set_int (d, "usb_device.device_protocol", 2176112Sqz150045 dev_descrp->bDeviceProtocol); 2186112Sqz150045 } 2196112Sqz150045 } 2206112Sqz150045 2216112Sqz150045 if (di_prop_lookup_bytes (DDI_DEV_T_ANY, node, "usb-raw-cfg-descriptors", 2226112Sqz150045 &rdata) > 0) { 2236112Sqz150045 cfg_descrp = (usb_cfg_descr_t *)(rdata); 2246112Sqz150045 2256112Sqz150045 if (cfg_descrp != NULL) { 2266112Sqz150045 hal_device_property_set_int (d, "usb_device.configuration_value", 2276112Sqz150045 cfg_descrp->bConfigurationValue); 2286112Sqz150045 hal_device_property_set_int (d, "usb_device.max_power", 2296112Sqz150045 cfg_descrp->bMaxPower); 2306112Sqz150045 hal_device_property_set_int (d, "usb_device.num_interfaces", 2316112Sqz150045 cfg_descrp->bNumInterfaces); 2326112Sqz150045 hal_device_property_set_bool (d, "usb_device.can_wake_up", 2336112Sqz150045 (cfg_descrp->bmAttributes & 0x20) ? TRUE : FALSE); 2346112Sqz150045 hal_device_property_set_bool (d, "usb_device.is_self_powered", 2356112Sqz150045 (cfg_descrp->bmAttributes & 0x40) ? TRUE : FALSE); 2366112Sqz150045 } 2376112Sqz150045 } 2386112Sqz150045 2396112Sqz150045 /* get the node's usb tree level by counting hub numbers */ 2406112Sqz150045 do { 2416112Sqz150045 if (p = strstr (devfs_path, "/hub@")) { 2426112Sqz150045 devfs_path = p + strlen ("/hub@"); 2436112Sqz150045 i ++; 2446112Sqz150045 } 2456112Sqz150045 } while (p != NULL); 2466112Sqz150045 2476112Sqz150045 if ((driver_name != NULL) && (strcmp (driver_name, "hubd") == 0) && (i > 0)) 2486112Sqz150045 i --; 2496112Sqz150045 2506112Sqz150045 hal_device_property_set_int (d, "usb_device.level_number", i); 2516112Sqz150045 } 2526112Sqz150045 2536112Sqz150045 2546112Sqz150045 static usb_if_descr_t * 2556112Sqz150045 parse_usb_if_descr(di_node_t node, int ifnum) 2562912Sartem { 2576112Sqz150045 unsigned char *rdata = NULL; 2586112Sqz150045 usb_if_descr_t *if_descrp=NULL; /* interface descriptor */ 2596112Sqz150045 di_node_t tmp_node = DI_NODE_NIL; 2606112Sqz150045 uint8_t num, length, type; 2616112Sqz150045 int rlen; 2626112Sqz150045 gchar *devpath = NULL; 2636112Sqz150045 2646112Sqz150045 if ((rlen = di_prop_lookup_bytes (DDI_DEV_T_ANY, node, 2656112Sqz150045 "usb-raw-cfg-descriptors", &rdata)) < 0) { 2666112Sqz150045 2676112Sqz150045 char *p; 2686112Sqz150045 int i; 2696112Sqz150045 2706112Sqz150045 if ((devpath = di_devfs_path (node)) == NULL) 2716112Sqz150045 goto out; 2726112Sqz150045 2736112Sqz150045 /* Look up its parent that may be a USB IA or USB mid. */ 2746112Sqz150045 for (i = 0; i < 2; i++) { 2756112Sqz150045 p = strrchr (devpath, '/'); 2766112Sqz150045 if (p == NULL) 2776112Sqz150045 goto out; 2786112Sqz150045 *p = '\0'; 2796112Sqz150045 2806112Sqz150045 if ((tmp_node = di_init (devpath, DINFOCPYALL)) == DI_NODE_NIL) 2816112Sqz150045 goto out; 2826112Sqz150045 2836112Sqz150045 if ((rlen = di_prop_lookup_bytes (DDI_DEV_T_ANY, tmp_node, 2846112Sqz150045 "usb-raw-cfg-descriptors", &rdata)) > 0) 2856112Sqz150045 break; 2866112Sqz150045 2876112Sqz150045 di_fini (tmp_node); 2886112Sqz150045 } 2896112Sqz150045 } 2902912Sartem 2916112Sqz150045 if (rdata == NULL) 2926112Sqz150045 goto out; 2936112Sqz150045 2946112Sqz150045 do { 2956112Sqz150045 length = (uint8_t)*rdata; 2966112Sqz150045 type = (uint8_t)*(rdata + 1); 2976112Sqz150045 if (type == USB_DESCR_TYPE_IF) { 2986112Sqz150045 num = (uint8_t)*(rdata + 2); 2996112Sqz150045 if (num == ifnum) { 3006112Sqz150045 if_descrp = (usb_if_descr_t *)rdata; 3016112Sqz150045 break; 3026112Sqz150045 } 3036112Sqz150045 } 3046112Sqz150045 rdata += length; 3056112Sqz150045 rlen -= length; 3066112Sqz150045 } while ((length > 0 ) && (rlen > 0)); 3076112Sqz150045 3086112Sqz150045 out: 3096112Sqz150045 if (devpath != NULL) 3106112Sqz150045 di_devfs_path_free (devpath); 3116112Sqz150045 if (tmp_node != DI_NODE_NIL) 3126112Sqz150045 di_fini (tmp_node); 3136112Sqz150045 return (if_descrp); 3146112Sqz150045 } 3156112Sqz150045 3166112Sqz150045 3176112Sqz150045 static HalDevice * 3186112Sqz150045 devinfo_usb_if_add(HalDevice *parent, di_node_t node, gchar *devfs_path, 3196112Sqz150045 gchar *if_devfs_path, int ifnum) 3206112Sqz150045 { 3216112Sqz150045 HalDevice *d = NULL; 3226112Sqz150045 char udi[HAL_PATH_MAX]; 3236112Sqz150045 const char *parent_info; 3246112Sqz150045 usb_if_descr_t *if_descrp=NULL; /* interface descriptor */ 3252912Sartem 3262912Sartem d = hal_device_new (); 3272912Sartem 3286112Sqz150045 devinfo_set_default_properties (d, parent, node, if_devfs_path); 3296112Sqz150045 3306112Sqz150045 /* Set the existed physical device path. */ 3316112Sqz150045 hal_device_property_set_string (d, "solaris.devfs_path", devfs_path); 3326112Sqz150045 hal_device_property_set_string (d, "info.subsystem", "usb"); 3336112Sqz150045 hal_device_property_set_string (d, "info.product", "USB Device Interface"); 3346112Sqz150045 3356112Sqz150045 /* Set usb interface properties to interface node. */ 3366112Sqz150045 if (strstr (if_devfs_path, ":ia") == NULL) { 3376112Sqz150045 if_descrp = parse_usb_if_descr (node, ifnum); 3386112Sqz150045 3396112Sqz150045 if (if_descrp != NULL) { 3406112Sqz150045 hal_device_property_set_int (d, "usb.interface.class", 3416112Sqz150045 if_descrp->bInterfaceClass); 3426112Sqz150045 hal_device_property_set_int (d, "usb.interface.subclass", 3436112Sqz150045 if_descrp->bInterfaceSubClass); 3446112Sqz150045 hal_device_property_set_int (d, "usb.interface.protocol", 3456112Sqz150045 if_descrp->bInterfaceProtocol); 3466112Sqz150045 hal_device_property_set_int (d, "usb.interface.number", 3476112Sqz150045 if_descrp->bInterfaceNumber); 3486112Sqz150045 } 3496112Sqz150045 } 3502912Sartem 3512912Sartem /* copy parent's usb_device.* properties */ 3526112Sqz150045 parent_info = hal_device_property_get_string (parent, "info.subsystem"); 3536112Sqz150045 if (parent_info != NULL) { 3546112Sqz150045 if (strcmp (parent_info, "usb_device") == 0) { 3556112Sqz150045 hal_device_merge_with_rewrite (d, parent, "usb.", "usb_device."); 3566112Sqz150045 } else if (strcmp (parent_info, "usb") == 0) { 3576112Sqz150045 /* for the case that the parent is IA node */ 3586112Sqz150045 hal_device_merge_with_rewrite (d, parent, "usb.", "usb."); 3596112Sqz150045 } 3606112Sqz150045 } 3616112Sqz150045 3626112Sqz150045 devinfo_add_enqueue (d, devfs_path, &devinfo_usb_handler); 3636112Sqz150045 3646112Sqz150045 /* add to TDL so preprobing callouts and prober can access it */ 3656112Sqz150045 hal_device_store_add (hald_get_tdl (), d); 3662912Sartem 3672912Sartem return (d); 3682912Sartem } 3692912Sartem 3702912Sartem 3713536Sjacobs static void 3723536Sjacobs get_dev_link_path(di_node_t node, char *nodetype, char *re, char **devlink, char **minor_path) 3733536Sjacobs { 3743536Sjacobs di_devlink_handle_t devlink_hdl; 3756112Sqz150045 int major; 3766112Sqz150045 di_minor_t minor; 3776112Sqz150045 dev_t devt; 3782912Sartem 3793536Sjacobs *devlink = NULL; 3806112Sqz150045 *minor_path = NULL; 3813536Sjacobs 3826112Sqz150045 if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) { 3836112Sqz150045 printf("di_devlink_init() failed\n"); 3846112Sqz150045 return; 3856112Sqz150045 } 3862912Sartem 3876112Sqz150045 major = di_driver_major(node); 3886112Sqz150045 minor = DI_MINOR_NIL; 3896112Sqz150045 while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) { 3906112Sqz150045 devt = di_minor_devt(minor); 3916112Sqz150045 if (major != major(devt)) { 3926112Sqz150045 continue; 3936112Sqz150045 } 3943536Sjacobs 3956112Sqz150045 if (di_minor_type(minor) != DDM_MINOR) { 3966112Sqz150045 continue; 3976112Sqz150045 } 3982912Sartem 3996112Sqz150045 if ((*minor_path = di_devfs_minor_path(minor)) == NULL) { 4006112Sqz150045 continue; 4016112Sqz150045 } 4022912Sartem 4033536Sjacobs if ((strcmp (di_minor_nodetype(minor), nodetype) == 0) && 4043536Sjacobs ((*devlink = get_devlink(devlink_hdl, re, *minor_path)) != NULL)) { 4053536Sjacobs break; 4063536Sjacobs } 4073536Sjacobs di_devfs_path_free (*minor_path); 4083710Sjacobs *minor_path = NULL; 4093536Sjacobs } 4103536Sjacobs di_devlink_fini (&devlink_hdl); 4112912Sartem } 4122912Sartem 4132912Sartem static HalDevice * 4146112Sqz150045 devinfo_usb_scsa2usb_add(HalDevice *usbd, di_node_t node) 4152912Sartem { 4162912Sartem HalDevice *d = NULL; 4172912Sartem di_devlink_handle_t devlink_hdl; 4186112Sqz150045 int major; 4196112Sqz150045 di_minor_t minor; 4206112Sqz150045 dev_t devt; 4216112Sqz150045 char *minor_path = NULL; 4222912Sartem char *devlink = NULL; 4236112Sqz150045 char udi[HAL_PATH_MAX]; 4242912Sartem 4253536Sjacobs get_dev_link_path(node, "ddi_ctl:devctl:scsi", NULL, &devlink, &minor_path); 4262912Sartem 4273536Sjacobs if ((devlink == NULL) || (minor_path == NULL)) { 4282912Sartem goto out; 4292912Sartem } 4302912Sartem 4312912Sartem d = hal_device_new (); 4322912Sartem 4332912Sartem devinfo_set_default_properties (d, usbd, node, minor_path); 4346112Sqz150045 hal_device_property_set_string (d, "scsi_host.solaris.device", devlink); 4356112Sqz150045 hal_device_property_set_string (d, "info.category", "scsi_host"); 4366112Sqz150045 hal_device_property_set_int (d, "scsi_host.host", 0); 4372912Sartem 4386112Sqz150045 hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi), 4396112Sqz150045 "%s/scsi_host%d", hal_device_get_udi (usbd), 4406112Sqz150045 hal_device_property_get_int (d, "scsi_host.host")); 4416112Sqz150045 hal_device_set_udi (d, udi); 4426112Sqz150045 hal_device_property_set_string (d, "info.udi", udi); 4436112Sqz150045 hal_device_property_set_string (d, "info.product", "SCSI Host Adapter"); 4442912Sartem 4452912Sartem devinfo_add_enqueue (d, minor_path, &devinfo_usb_handler); 4462912Sartem 4472912Sartem out: 4482912Sartem if (devlink) { 4492912Sartem free(devlink); 4502912Sartem } 4512912Sartem if (minor_path) { 4522912Sartem di_devfs_path_free (minor_path); 4532912Sartem } 4542912Sartem 4552912Sartem return (d); 4562912Sartem } 4572912Sartem 4583536Sjacobs static HalDevice * 4596112Sqz150045 devinfo_usb_printer_add(HalDevice *parent, di_node_t node) 4603536Sjacobs { 461*8529SNorm.Jacobs@Sun.COM char *properties[] = { "vendor", "product", "serial", NULL }; 462*8529SNorm.Jacobs@Sun.COM int i; 4633536Sjacobs HalDevice *d = NULL; 4646112Sqz150045 char udi[HAL_PATH_MAX]; 4653536Sjacobs char *s; 4663536Sjacobs char *devlink = NULL, *minor_path = NULL; 467*8529SNorm.Jacobs@Sun.COM const char *subsystem; 4683536Sjacobs 4693536Sjacobs get_dev_link_path(node, "ddi_printer", "printers/.+", &devlink, &minor_path); 4703536Sjacobs 4713536Sjacobs if ((devlink == NULL) || (minor_path == NULL)) { 4723536Sjacobs goto out; 4733536Sjacobs } 4743536Sjacobs 4753536Sjacobs d = hal_device_new (); 4763536Sjacobs 4773536Sjacobs devinfo_set_default_properties (d, parent, node, minor_path); 4786112Sqz150045 hal_device_property_set_string (d, "info.category", "printer"); 4793536Sjacobs hal_device_add_capability (d, "printer"); 4803536Sjacobs 4813536Sjacobs /* add printer properties */ 4826112Sqz150045 hal_device_property_set_string (d, "printer.device", devlink); 483*8529SNorm.Jacobs@Sun.COM 484*8529SNorm.Jacobs@Sun.COM /* copy parent's selected usb* properties to printer properties */ 485*8529SNorm.Jacobs@Sun.COM subsystem = hal_device_property_get_string (parent, "info.subsystem"); 486*8529SNorm.Jacobs@Sun.COM for (i = 0; properties[i] != NULL; i++) { 487*8529SNorm.Jacobs@Sun.COM char src[32], dst[32]; /* "subsystem.property" names */ 488*8529SNorm.Jacobs@Sun.COM 489*8529SNorm.Jacobs@Sun.COM snprintf(src, sizeof (src), "%s.%s", subsystem, properties[i]); 490*8529SNorm.Jacobs@Sun.COM snprintf(dst, sizeof (dst), "printer.%s", properties[i]); 491*8529SNorm.Jacobs@Sun.COM hal_device_copy_property(parent, src, d, dst); 492*8529SNorm.Jacobs@Sun.COM } 4933536Sjacobs 4943536Sjacobs devinfo_add_enqueue (d, minor_path, &devinfo_usb_printer_handler); 4953536Sjacobs 4963536Sjacobs out: 4973536Sjacobs if (devlink) { 4983536Sjacobs free(devlink); 4993536Sjacobs } 5003536Sjacobs if (minor_path) { 5013536Sjacobs di_devfs_path_free (minor_path); 5023536Sjacobs } 5033536Sjacobs 5043536Sjacobs return (d); 5053536Sjacobs } 5063536Sjacobs 5073536Sjacobs const gchar * 5083536Sjacobs devinfo_printer_prnio_get_prober (HalDevice *d, int *timeout) 5093536Sjacobs { 5103536Sjacobs *timeout = 5 * 1000; /* 5 second timeout */ 5113536Sjacobs return ("hald-probe-printer"); 5123536Sjacobs } 513