1 /*************************************************************************** 2 * 3 * devinfo_usb.h : USB devices 4 * 5 * Copyright 2006 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 40 DevinfoDevHandler devinfo_usb_handler = { 41 devinfo_usb_add, 42 NULL, 43 NULL, 44 NULL, 45 NULL, 46 NULL 47 }; 48 49 HalDevice * 50 devinfo_usb_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type) 51 { 52 HalDevice *d, *nd = NULL; 53 char *s; 54 int *i, *vid; 55 char *driver_name, *binding_name; 56 char if_devfs_path[HAL_PATH_MAX]; 57 58 /* 59 * we distinguish USB devices by presence of "usb-vendor-id" 60 * property. should USB devices have "device_type"? 61 */ 62 if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "usb-vendor-id", &vid) <= 0) { 63 return (NULL); 64 } 65 66 d = hal_device_new (); 67 68 devinfo_set_default_properties (d, parent, node, devfs_path); 69 hal_device_property_set_string (d, "info.bus", "usb_device"); 70 PROP_STR(d, node, s, "usb-product-name", "info.product"); 71 PROP_STR(d, node, s, "usb-product-name", "usb_device.product"); 72 PROP_STR(d, node, s, "usb-vendor-name", "usb_device.vendor"); 73 PROP_INT(d, node, i, "usb-vendor-id", "usb_device.vendor_id"); 74 PROP_INT(d, node, i, "usb-product-id", "usb_device.product_id"); 75 PROP_INT(d, node, i, "usb-revision-id", "usb_device.device_revision_bcd"); 76 PROP_INT(d, node, i, "usb-release-id", "usb_device.version_bcd"); 77 PROP_STR(d, node, s, "usb-serialno", "usb_device.serial"); 78 79 /* class, subclass */ 80 /* hal_device_property_set_int (d, "usb_device.device_class", 8); */ 81 82 /* binding name tells us if driver is bound to interface or device */ 83 if (((binding_name = di_binding_name(node)) != NULL) && 84 (strncmp(binding_name, "usbif,", sizeof ("usbif,") - 1) == 0)) { 85 snprintf(if_devfs_path, sizeof (if_devfs_path), "%s:if%d", devfs_path, 0); 86 if ((nd = devinfo_usb_if_add(d, node, if_devfs_path, 0)) != NULL) { 87 d = nd; 88 nd = NULL; 89 devfs_path = if_devfs_path; 90 } 91 } 92 93 /* driver specific */ 94 driver_name = di_driver_name (node); 95 if ((driver_name != NULL) && (strcmp (driver_name, "scsa2usb") == 0)) { 96 nd = devinfo_usb_scsa2usb_add (d, node, devfs_path); 97 } else { 98 devinfo_add_enqueue (d, devfs_path, &devinfo_usb_handler); 99 } 100 101 out: 102 if (nd != NULL) { 103 return (nd); 104 } else { 105 return (d); 106 } 107 } 108 109 static HalDevice * 110 devinfo_usb_if_add(HalDevice *parent, di_node_t node, gchar *devfs_path, int ifnum) 111 { 112 HalDevice *d = NULL; 113 char udi[HAL_PATH_MAX]; 114 115 devinfo_add_enqueue (parent, devfs_path, &devinfo_usb_handler); 116 117 d = hal_device_new (); 118 119 devinfo_set_default_properties (d, parent, node, devfs_path); 120 hal_device_property_set_string (d, "info.bus", "usb"); 121 122 hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi), 123 "%s_if%d", hal_device_get_udi (parent), ifnum); 124 hal_device_set_udi (d, udi); 125 hal_device_property_set_string (d, "info.udi", udi); 126 hal_device_property_set_string (d, "info.product", "USB Device Interface"); 127 128 /* copy parent's usb_device.* properties */ 129 hal_device_merge_with_rewrite (d, parent, "usb.", "usb_device."); 130 131 return (d); 132 } 133 134 static int 135 walk_devlinks(di_devlink_t devlink, void *arg) 136 { 137 char **path = (char **)arg; 138 139 *path = strdup(di_devlink_path(devlink)); 140 141 return (DI_WALK_TERMINATE); 142 } 143 144 static char * 145 get_devlink(di_devlink_handle_t devlink_hdl, char *path) 146 { 147 char *devlink = NULL; 148 149 (void) di_devlink_walk(devlink_hdl, NULL, path, 150 DI_PRIMARY_LINK, &devlink, walk_devlinks); 151 152 return (devlink); 153 } 154 155 static HalDevice * 156 devinfo_usb_scsa2usb_add(HalDevice *usbd, di_node_t node, gchar *devfs_path) 157 { 158 HalDevice *d = NULL; 159 di_devlink_handle_t devlink_hdl; 160 int major; 161 di_minor_t minor; 162 dev_t devt; 163 char *minor_path = NULL; 164 char *devlink = NULL; 165 char udi[HAL_PATH_MAX]; 166 167 devinfo_add_enqueue (usbd, devfs_path, &devinfo_usb_handler); 168 169 if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) { 170 printf("di_devlink_init() failed\n"); 171 return (NULL); 172 } 173 174 major = di_driver_major(node); 175 minor = DI_MINOR_NIL; 176 while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) { 177 devt = di_minor_devt(minor); 178 if (major != major(devt)) { 179 continue; 180 } 181 if ((minor_path = di_devfs_minor_path(minor)) == NULL) { 182 continue; 183 } 184 if (di_minor_type(minor) != DDM_MINOR) { 185 continue; 186 } 187 if (strcmp (di_minor_nodetype(minor), 188 "ddi_ctl:devctl:scsi") == 0) { 189 devlink = get_devlink(devlink_hdl, minor_path); 190 if (devlink == NULL) { 191 devlink = strdup(""); 192 } 193 break; 194 } 195 di_devfs_path_free (minor_path); 196 minor_path = NULL; 197 } 198 199 di_devlink_fini (&devlink_hdl); 200 201 if (devlink == NULL) { 202 goto out; 203 } 204 205 d = hal_device_new (); 206 207 devinfo_set_default_properties (d, usbd, node, minor_path); 208 hal_device_property_set_string (d, "scsi_host.solaris.device", devlink); 209 hal_device_property_set_string (d, "info.category", "scsi_host"); 210 hal_device_property_set_int (d, "scsi_host.host", 0); 211 212 hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi), 213 "%s/scsi_host%d", hal_device_get_udi (usbd), 214 hal_device_property_get_int (d, "scsi_host.host")); 215 hal_device_set_udi (d, udi); 216 hal_device_property_set_string (d, "info.udi", udi); 217 hal_device_property_set_string (d, "info.product", "SCSI Host Adapter"); 218 219 devinfo_add_enqueue (d, minor_path, &devinfo_usb_handler); 220 221 out: 222 if (devlink) { 223 free(devlink); 224 } 225 if (minor_path) { 226 di_devfs_path_free (minor_path); 227 } 228 229 return (d); 230 } 231 232