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 static gboolean 61 is_usb_node(di_node_t node) 62 { 63 int rc; 64 char *s; 65 66 /* 67 * USB device nodes will have "compatible" propety values that 68 * begins with "usb". 69 */ 70 rc = di_prop_lookup_strings(DDI_DEV_T_ANY, node, "compatible", &s); 71 while (rc-- > 0) { 72 if (strncmp(s, "usb", 3) == 0) { 73 return (TRUE); 74 } 75 s += (strlen(s) + 1); 76 } 77 78 return (FALSE); 79 } 80 81 HalDevice * 82 devinfo_usb_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type) 83 { 84 HalDevice *d, *nd = NULL; 85 char *s; 86 int *i; 87 char *driver_name, *binding_name; 88 char if_devfs_path[HAL_PATH_MAX]; 89 90 if (is_usb_node(node) == FALSE) { 91 return (NULL); 92 } 93 94 d = hal_device_new (); 95 96 devinfo_set_default_properties (d, parent, node, devfs_path); 97 hal_device_property_set_string (d, "info.bus", "usb_device"); 98 PROP_STR(d, node, s, "usb-product-name", "info.product"); 99 PROP_STR(d, node, s, "usb-product-name", "usb_device.product"); 100 PROP_STR(d, node, s, "usb-vendor-name", "usb_device.vendor"); 101 PROP_INT(d, node, i, "usb-vendor-id", "usb_device.vendor_id"); 102 PROP_INT(d, node, i, "usb-product-id", "usb_device.product_id"); 103 PROP_INT(d, node, i, "usb-revision-id", "usb_device.device_revision_bcd"); 104 PROP_INT(d, node, i, "usb-release-id", "usb_device.version_bcd"); 105 PROP_STR(d, node, s, "usb-serialno", "usb_device.serial"); 106 107 /* class, subclass */ 108 /* hal_device_property_set_int (d, "usb_device.device_class", 8); */ 109 110 /* binding name tells us if driver is bound to interface or device */ 111 if (((binding_name = di_binding_name(node)) != NULL) && 112 (strncmp(binding_name, "usbif,", sizeof ("usbif,") - 1) == 0)) { 113 snprintf(if_devfs_path, sizeof (if_devfs_path), "%s:if%d", devfs_path, 0); 114 if ((nd = devinfo_usb_if_add(d, node, if_devfs_path, 0)) != NULL) { 115 d = nd; 116 nd = NULL; 117 devfs_path = if_devfs_path; 118 } 119 } 120 121 /* driver specific */ 122 driver_name = di_driver_name (node); 123 if ((driver_name != NULL) && (strcmp (driver_name, "scsa2usb") == 0)) { 124 nd = devinfo_usb_scsa2usb_add (d, node, devfs_path); 125 } else if ((driver_name != NULL) && 126 (strcmp (driver_name, "usbprn") == 0)) { 127 nd = devinfo_usb_printer_add (d, node, devfs_path); 128 } else { 129 devinfo_add_enqueue (d, devfs_path, &devinfo_usb_handler); 130 } 131 132 out: 133 if (nd != NULL) { 134 return (nd); 135 } else { 136 return (d); 137 } 138 } 139 140 static HalDevice * 141 devinfo_usb_if_add(HalDevice *parent, di_node_t node, gchar *devfs_path, int ifnum) 142 { 143 HalDevice *d = NULL; 144 char udi[HAL_PATH_MAX]; 145 146 devinfo_add_enqueue (parent, devfs_path, &devinfo_usb_handler); 147 148 d = hal_device_new (); 149 150 devinfo_set_default_properties (d, parent, node, devfs_path); 151 hal_device_property_set_string (d, "info.bus", "usb"); 152 hal_device_property_set_string (d, "info.product", "USB Device Interface"); 153 154 /* copy parent's usb_device.* properties */ 155 hal_device_merge_with_rewrite (d, parent, "usb.", "usb_device."); 156 157 return (d); 158 } 159 160 161 static void 162 get_dev_link_path(di_node_t node, char *nodetype, char *re, char **devlink, char **minor_path) 163 { 164 di_devlink_handle_t devlink_hdl; 165 int major; 166 di_minor_t minor; 167 dev_t devt; 168 169 *devlink = NULL; 170 *minor_path = NULL; 171 172 if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) { 173 printf("di_devlink_init() failed\n"); 174 return; 175 } 176 177 major = di_driver_major(node); 178 minor = DI_MINOR_NIL; 179 while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) { 180 devt = di_minor_devt(minor); 181 if (major != major(devt)) { 182 continue; 183 } 184 185 if (di_minor_type(minor) != DDM_MINOR) { 186 continue; 187 } 188 189 if ((*minor_path = di_devfs_minor_path(minor)) == NULL) { 190 continue; 191 } 192 193 if ((strcmp (di_minor_nodetype(minor), nodetype) == 0) && 194 ((*devlink = get_devlink(devlink_hdl, re, *minor_path)) != NULL)) { 195 break; 196 } 197 di_devfs_path_free (*minor_path); 198 *minor_path = NULL; 199 } 200 di_devlink_fini (&devlink_hdl); 201 } 202 203 static HalDevice * 204 devinfo_usb_scsa2usb_add(HalDevice *usbd, di_node_t node, gchar *devfs_path) 205 { 206 HalDevice *d = NULL; 207 di_devlink_handle_t devlink_hdl; 208 int major; 209 di_minor_t minor; 210 dev_t devt; 211 char *minor_path = NULL; 212 char *devlink = NULL; 213 char udi[HAL_PATH_MAX]; 214 215 devinfo_add_enqueue (usbd, devfs_path, &devinfo_usb_handler); 216 217 get_dev_link_path(node, "ddi_ctl:devctl:scsi", NULL, &devlink, &minor_path); 218 219 if ((devlink == NULL) || (minor_path == NULL)) { 220 goto out; 221 } 222 223 d = hal_device_new (); 224 225 devinfo_set_default_properties (d, usbd, node, minor_path); 226 hal_device_property_set_string (d, "scsi_host.solaris.device", devlink); 227 hal_device_property_set_string (d, "info.category", "scsi_host"); 228 hal_device_property_set_int (d, "scsi_host.host", 0); 229 230 hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi), 231 "%s/scsi_host%d", hal_device_get_udi (usbd), 232 hal_device_property_get_int (d, "scsi_host.host")); 233 hal_device_set_udi (d, udi); 234 hal_device_property_set_string (d, "info.udi", udi); 235 hal_device_property_set_string (d, "info.product", "SCSI Host Adapter"); 236 237 devinfo_add_enqueue (d, minor_path, &devinfo_usb_handler); 238 239 out: 240 if (devlink) { 241 free(devlink); 242 } 243 if (minor_path) { 244 di_devfs_path_free (minor_path); 245 } 246 247 return (d); 248 } 249 250 static HalDevice * 251 devinfo_usb_printer_add(HalDevice *parent, di_node_t node, gchar *devfs_path) 252 { 253 HalDevice *d = NULL; 254 char udi[HAL_PATH_MAX]; 255 char *s; 256 char *devlink = NULL, *minor_path = NULL; 257 258 devinfo_add_enqueue (parent, devfs_path, &devinfo_usb_handler); 259 260 get_dev_link_path(node, "ddi_printer", "printers/.+", &devlink, &minor_path); 261 262 if ((devlink == NULL) || (minor_path == NULL)) { 263 goto out; 264 } 265 266 d = hal_device_new (); 267 268 devinfo_set_default_properties (d, parent, node, minor_path); 269 hal_device_property_set_string (d, "info.category", "printer"); 270 hal_device_add_capability (d, "printer"); 271 272 /* copy parent's usb_device.* properties */ 273 hal_device_merge_with_rewrite (d, parent, "usb.", "usb_device."); 274 275 /* add printer properties */ 276 hal_device_property_set_string (d, "printer.device", devlink); 277 PROP_STR(d, node, s, "usb-vendor-name", "printer.vendor"); 278 PROP_STR(d, node, s, "usb-product-name", "printer.product"); 279 PROP_STR(d, node, s, "usb-serialno", "printer.serial"); 280 281 devinfo_add_enqueue (d, minor_path, &devinfo_usb_printer_handler); 282 283 out: 284 if (devlink) { 285 free(devlink); 286 } 287 if (minor_path) { 288 di_devfs_path_free (minor_path); 289 } 290 291 return (d); 292 } 293 294 const gchar * 295 devinfo_printer_prnio_get_prober (HalDevice *d, int *timeout) 296 { 297 *timeout = 5 * 1000; /* 5 second timeout */ 298 return ("hald-probe-printer"); 299 } 300