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