1 /*************************************************************************** 2 * 3 * devinfo_usb.h : USB devices 4 * 5 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 6 * Use is subject to license terms. 7 * 8 * Licensed under the Academic Free License version 2.1 9 * 10 **************************************************************************/ 11 12 #pragma ident "%Z%%M% %I% %E% SMI" 13 14 #ifdef HAVE_CONFIG_H 15 # include <config.h> 16 #endif 17 18 #include <stdio.h> 19 #include <string.h> 20 #include <libdevinfo.h> 21 #include <sys/types.h> 22 #include <sys/mkdev.h> 23 #include <sys/stat.h> 24 25 #include "../osspec.h" 26 #include "../logger.h" 27 #include "../hald.h" 28 #include "../hald_dbus.h" 29 #include "../device_info.h" 30 #include "../util.h" 31 #include "../ids.h" 32 #include "hotplug.h" 33 #include "devinfo.h" 34 #include "devinfo_usb.h" 35 36 HalDevice *devinfo_usb_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type); 37 static HalDevice *devinfo_usb_if_add(HalDevice *d, di_node_t node, gchar *devfs_path, int ifnum); 38 static HalDevice *devinfo_usb_scsa2usb_add(HalDevice *d, di_node_t node, gchar *devfs_path); 39 static HalDevice *devinfo_usb_printer_add(HalDevice *usbd, di_node_t node, gchar *devfs_path); 40 const gchar *devinfo_printer_prnio_get_prober (HalDevice *d, int *timeout); 41 42 DevinfoDevHandler devinfo_usb_handler = { 43 devinfo_usb_add, 44 NULL, 45 NULL, 46 NULL, 47 NULL, 48 NULL 49 }; 50 51 DevinfoDevHandler devinfo_usb_printer_handler = { 52 devinfo_usb_add, 53 NULL, 54 NULL, 55 NULL, 56 NULL, 57 devinfo_printer_prnio_get_prober 58 }; 59 60 HalDevice * 61 devinfo_usb_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type) 62 { 63 HalDevice *d, *nd = NULL; 64 char *s; 65 int *i, *vid; 66 char *driver_name, *binding_name; 67 char if_devfs_path[HAL_PATH_MAX]; 68 69 /* 70 * we distinguish USB devices by presence of "usb-vendor-id" 71 * property. should USB devices have "device_type"? 72 */ 73 if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "usb-vendor-id", &vid) <= 0) { 74 return (NULL); 75 } 76 77 d = hal_device_new (); 78 79 devinfo_set_default_properties (d, parent, node, devfs_path); 80 hal_device_property_set_string (d, "info.bus", "usb_device"); 81 PROP_STR(d, node, s, "usb-product-name", "info.product"); 82 PROP_STR(d, node, s, "usb-product-name", "usb_device.product"); 83 PROP_STR(d, node, s, "usb-vendor-name", "usb_device.vendor"); 84 PROP_INT(d, node, i, "usb-vendor-id", "usb_device.vendor_id"); 85 PROP_INT(d, node, i, "usb-product-id", "usb_device.product_id"); 86 PROP_INT(d, node, i, "usb-revision-id", "usb_device.device_revision_bcd"); 87 PROP_INT(d, node, i, "usb-release-id", "usb_device.version_bcd"); 88 PROP_STR(d, node, s, "usb-serialno", "usb_device.serial"); 89 90 /* class, subclass */ 91 /* hal_device_property_set_int (d, "usb_device.device_class", 8); */ 92 93 /* binding name tells us if driver is bound to interface or device */ 94 if (((binding_name = di_binding_name(node)) != NULL) && 95 (strncmp(binding_name, "usbif,", sizeof ("usbif,") - 1) == 0)) { 96 snprintf(if_devfs_path, sizeof (if_devfs_path), "%s:if%d", devfs_path, 0); 97 if ((nd = devinfo_usb_if_add(d, node, if_devfs_path, 0)) != NULL) { 98 d = nd; 99 nd = NULL; 100 devfs_path = if_devfs_path; 101 } 102 } 103 104 /* driver specific */ 105 driver_name = di_driver_name (node); 106 if ((driver_name != NULL) && (strcmp (driver_name, "scsa2usb") == 0)) { 107 nd = devinfo_usb_scsa2usb_add (d, node, devfs_path); 108 } else if ((driver_name != NULL) && 109 (strcmp (driver_name, "usbprn") == 0)) { 110 nd = devinfo_usb_printer_add (d, node, devfs_path); 111 } else { 112 devinfo_add_enqueue (d, devfs_path, &devinfo_usb_handler); 113 } 114 115 out: 116 if (nd != NULL) { 117 return (nd); 118 } else { 119 return (d); 120 } 121 } 122 123 static HalDevice * 124 devinfo_usb_if_add(HalDevice *parent, di_node_t node, gchar *devfs_path, int ifnum) 125 { 126 HalDevice *d = NULL; 127 char udi[HAL_PATH_MAX]; 128 129 devinfo_add_enqueue (parent, devfs_path, &devinfo_usb_handler); 130 131 d = hal_device_new (); 132 133 devinfo_set_default_properties (d, parent, node, devfs_path); 134 hal_device_property_set_string (d, "info.bus", "usb"); 135 hal_device_property_set_string (d, "info.product", "USB Device Interface"); 136 137 /* copy parent's usb_device.* properties */ 138 hal_device_merge_with_rewrite (d, parent, "usb.", "usb_device."); 139 140 return (d); 141 } 142 143 144 static void 145 get_dev_link_path(di_node_t node, char *nodetype, char *re, char **devlink, char **minor_path) 146 { 147 di_devlink_handle_t devlink_hdl; 148 int major; 149 di_minor_t minor; 150 dev_t devt; 151 152 *devlink = NULL; 153 *minor_path = NULL; 154 155 if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) { 156 printf("di_devlink_init() failed\n"); 157 return; 158 } 159 160 major = di_driver_major(node); 161 minor = DI_MINOR_NIL; 162 while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) { 163 devt = di_minor_devt(minor); 164 if (major != major(devt)) { 165 continue; 166 } 167 168 if (di_minor_type(minor) != DDM_MINOR) { 169 continue; 170 } 171 172 if ((*minor_path = di_devfs_minor_path(minor)) == NULL) { 173 continue; 174 } 175 176 if ((strcmp (di_minor_nodetype(minor), nodetype) == 0) && 177 ((*devlink = get_devlink(devlink_hdl, re, *minor_path)) != NULL)) { 178 break; 179 } 180 di_devfs_path_free (*minor_path); 181 minor_path = NULL; 182 } 183 di_devlink_fini (&devlink_hdl); 184 } 185 186 static HalDevice * 187 devinfo_usb_scsa2usb_add(HalDevice *usbd, di_node_t node, gchar *devfs_path) 188 { 189 HalDevice *d = NULL; 190 di_devlink_handle_t devlink_hdl; 191 int major; 192 di_minor_t minor; 193 dev_t devt; 194 char *minor_path = NULL; 195 char *devlink = NULL; 196 char udi[HAL_PATH_MAX]; 197 198 devinfo_add_enqueue (usbd, devfs_path, &devinfo_usb_handler); 199 200 get_dev_link_path(node, "ddi_ctl:devctl:scsi", NULL, &devlink, &minor_path); 201 202 if ((devlink == NULL) || (minor_path == NULL)) { 203 goto out; 204 } 205 206 d = hal_device_new (); 207 208 devinfo_set_default_properties (d, usbd, node, minor_path); 209 hal_device_property_set_string (d, "scsi_host.solaris.device", devlink); 210 hal_device_property_set_string (d, "info.category", "scsi_host"); 211 hal_device_property_set_int (d, "scsi_host.host", 0); 212 213 hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi), 214 "%s/scsi_host%d", hal_device_get_udi (usbd), 215 hal_device_property_get_int (d, "scsi_host.host")); 216 hal_device_set_udi (d, udi); 217 hal_device_property_set_string (d, "info.udi", udi); 218 hal_device_property_set_string (d, "info.product", "SCSI Host Adapter"); 219 220 devinfo_add_enqueue (d, minor_path, &devinfo_usb_handler); 221 222 out: 223 if (devlink) { 224 free(devlink); 225 } 226 if (minor_path) { 227 di_devfs_path_free (minor_path); 228 } 229 230 return (d); 231 } 232 233 static HalDevice * 234 devinfo_usb_printer_add(HalDevice *parent, di_node_t node, gchar *devfs_path) 235 { 236 HalDevice *d = NULL; 237 char udi[HAL_PATH_MAX]; 238 char *s; 239 char *devlink = NULL, *minor_path = NULL; 240 241 devinfo_add_enqueue (parent, devfs_path, &devinfo_usb_handler); 242 243 get_dev_link_path(node, "ddi_printer", "printers/.+", &devlink, &minor_path); 244 245 if ((devlink == NULL) || (minor_path == NULL)) { 246 goto out; 247 } 248 249 d = hal_device_new (); 250 251 devinfo_set_default_properties (d, parent, node, minor_path); 252 hal_device_property_set_string (d, "info.category", "printer"); 253 hal_device_add_capability (d, "printer"); 254 255 /* copy parent's usb_device.* properties */ 256 hal_device_merge_with_rewrite (d, parent, "usb.", "usb_device."); 257 258 /* add printer properties */ 259 hal_device_property_set_string (d, "printer.device", devlink); 260 PROP_STR(d, node, s, "usb-vendor-name", "printer.vendor"); 261 PROP_STR(d, node, s, "usb-product-name", "printer.product"); 262 PROP_STR(d, node, s, "usb-serialno", "printer.serial"); 263 264 devinfo_add_enqueue (d, minor_path, &devinfo_usb_printer_handler); 265 266 out: 267 if (devlink) { 268 free(devlink); 269 } 270 if (minor_path) { 271 di_devfs_path_free (minor_path); 272 } 273 274 return (d); 275 } 276 277 const gchar * 278 devinfo_printer_prnio_get_prober (HalDevice *d, int *timeout) 279 { 280 *timeout = 5 * 1000; /* 5 second timeout */ 281 return ("hald-probe-printer"); 282 } 283