Logo Search packages:      
Sourcecode: hal version File versions

static void block_class_pre_process ( ClassDeviceHandler self,
HalDevice *  d,
const char *  sysfs_path,
struct sysfs_class_device *  class_device 
) [static]

Todo:
add more SCSI types

Todo:
block device on non-IDE and non-SCSI device; how to find the name and the media-type?

Definition at line 1159 of file block_class_device.c.

References cdrom_get_properties(), class_device_get_major_minor(), get_last_element(), hal_device_add_capability(), HAL_INFO, HAL_WARNING, parse_dec(), and read_single_line().

{
      int major, minor;
      HalDevice *parent;
      HalDevice *stordev = NULL;
      HalDevice *physdev = NULL;
      HalDevice *scsidev = NULL;
      const char *stordev_udi;
      const char *device_file;
      dbus_bool_t has_removable_media = FALSE;
      dbus_bool_t is_hotpluggable = FALSE;
      dbus_bool_t requires_eject = FALSE;
      char attr_path[SYSFS_PATH_MAX];
      struct sysfs_attribute *attr;

      parent = hal_device_store_find (hald_get_gdl (),
                              hal_device_property_get_string (
                                    d, "info.parent"));
      assert (parent != NULL);

      /* add capabilities for device */
      hal_device_property_set_string (d, "info.category", "block");
      hal_device_add_capability (d, "block");

      class_device_get_major_minor (sysfs_path, &major, &minor);
      hal_device_property_set_int (d, "block.major", major);
      hal_device_property_set_int (d, "block.minor", minor);

      device_file = hal_device_property_get_string (d, "block.device");

      /* Determine physical device that is backing this block device */
      if (hal_device_property_get_bool (d, "block.is_volume")) {
            /* Take the block parent */
            stordev_udi = hal_device_property_get_string (
                  parent, "block.storage_device");
            stordev = hal_device_store_find (hald_get_gdl (), stordev_udi);
      } else {
            const char *udi_it;
            const char *physdev_udi = NULL;

            /* Set ourselves to be the storage.* keeper */
            stordev_udi = d->udi;
            stordev = d;

            /* Defaults */
            hal_device_property_set_string (stordev, "storage.bus", "unknown");
            hal_device_property_set_bool (stordev, "storage.media_check_enabled", 
                                    (hald_get_conf ())->storage_media_check_enabled);
            hal_device_property_set_bool (stordev, "storage.no_partitions_hint", FALSE);

            hal_device_property_set_bool (
                  stordev, 
                  "storage.automount_enabled_hint", 
                  (hald_get_conf ())->storage_automount_enabled_hint);

            hal_device_property_set_string (stordev, 
                                    "storage.model", "");
            hal_device_property_set_string (stordev, 
                                    "storage.vendor", "");

            /* walk up the device chain to find the physical device, 
             * start with our parent. On the way, optionally pick up
             * the scsi if it exists */
            udi_it = parent->udi;

            while (udi_it != NULL) {
                  HalDevice *d_it;
                  const char *bus;

                  /* Find device */
                  d_it = hal_device_store_find (hald_get_gdl (), udi_it);
                  assert (d_it != NULL);

                  /* Check info.bus */
                  bus = hal_device_property_get_string (d_it,"info.bus");

                  if (strcmp (bus, "scsi") == 0) {
                        scsidev = d_it;
                        physdev = d_it;
                        physdev_udi = udi_it;
                        hal_device_property_set_string (stordev, "storage.bus", "scsi");
                  }

                  if (strcmp (bus, "usb") == 0) {
                        physdev = d_it;
                        physdev_udi = udi_it;
                        is_hotpluggable = TRUE;
                        hal_device_property_set_string (stordev, "storage.bus", "usb");
                                                
                        break;
                  } else if (strcmp (bus, "ieee1394") == 0) {
                        physdev = d_it;
                        physdev_udi = udi_it;
                        is_hotpluggable = TRUE;
                        hal_device_property_set_string (stordev, "storage.bus", "ieee1394");
                        break;
                  } else if (strcmp (bus, "ide") == 0) {
                        physdev = d_it;
                        physdev_udi = udi_it;
                        hal_device_property_set_string (stordev, "storage.bus", "ide");
                        break;
                  }

                  /* Go to parent */
                  udi_it = hal_device_property_get_string (
                        d_it, "info.parent");
            }

            if (physdev_udi != NULL) {
                  hal_device_property_set_string (
                        stordev, 
                        "storage.physical_device",
                        physdev_udi);
            }
      }

      hal_device_property_set_string (d, "block.storage_device",
                              stordev_udi);

      if (hal_device_property_get_bool (d, "block.is_volume")) {
            /* block device that is a partition; e.g. a storage volume */
            struct volume_id *vid;
            const char *last_elem;
            const char *s;
            unsigned int partition_number;

            hal_device_add_capability (d, "volume");
            hal_device_property_set_string (d, "info.category", "volume");
            hal_device_property_set_string (d, "info.product", "Volume");
            hal_device_property_set_string (d, "volume.fstype", "");
            hal_device_property_set_string (d, "volume.fsusage", "");
            hal_device_property_set_string (d, "volume.fsversion", "");
            hal_device_property_set_string (d, "volume.label", "");
            hal_device_property_set_string (d, "volume.uuid", "");
            hal_device_property_set_bool (d, "volume.is_disc", FALSE);
            hal_device_property_set_bool (d, "volume.is_mounted", FALSE);
            hal_device_property_set_bool (d, "volume.is_partition", TRUE);

            /* get partition number */
            last_elem = get_last_element (sysfs_path);
            for (s = last_elem; *s != '\0' && !isdigit(*s); s++)
                  ;
            partition_number = (unsigned int) atoi (s);
            hal_device_property_set_int (d, "volume.partition.number", partition_number);

            /* only check for volume_id if we are allowed to poll, otherwise we may
             * cause inifite loops of hotplug events, cf. broken ide-cs driver and
             * broken zip drives. Merely accessing the top-level block device if it
             * or any of it partitions are not mounted causes the loop.
             *
             * Also allow this for devices without removable media
             */
            if (hal_device_property_get_bool (stordev, "storage.media_check_enabled") ||
                !hal_device_property_get_bool (stordev, "storage.removable")) {
                  dbus_uint64_t size = 0;
                  const char *stordev_device_file;

                  volume_set_size (d, FALSE);
                  size = hal_device_property_get_uint64 (d, "volume.size");

                  vid = volume_id_open_node(device_file);
                  if (vid != NULL) {
                        if (volume_id_probe(vid, VOLUME_ID_ALL, 0, size) == 0) {
                              set_volume_id_values(d, vid);
                        }
                        volume_id_close(vid);
                  }

                  /* get partition type - presently we only support PC style partition tables */
                  stordev_device_file = hal_device_property_get_string (stordev, "block.device");
                  vid = volume_id_open_node (stordev_device_file);
                  if (vid != NULL) {
                        if (volume_id_probe(vid, VOLUME_ID_MSDOSPARTTABLE, 0, size) == 0) {
                              HAL_INFO (("Number of partitions = %d", vid->partition_count));

                              if (partition_number > 0 && partition_number <= vid->partition_count) {
                                    struct volume_id_partition *p;
                                    p = &vid->partitions[partition_number-1];


                                    hal_device_property_set_int (
                                          d, "volume.partition.msdos_part_table_type",
                                          p->partition_type_raw);
                                    
                                    /* NOTE: We trust the type from the partition table
                                     * if it explicitly got correct entries for RAID and
                                     * LVM partitions.
                                     *
                                     * Btw, in general it's not a good idea to trust the
                                     * partition table type as many geek^Wexpert users use 
                                     * FAT filesystems on type 0x83 which is Linux.
                                     *
                                     * Linux RAID autodetect is 0xfd and Linux LVM is 0x8e
                                     */
                                    if (p->partition_type_raw == 0xfd ||
                                        p->partition_type_raw == 0x8e ) {
                                          hal_device_property_set_string (
                                                d, "volume.fsusage", "raid");
                                    }
                                          
                              } else {
                                    HAL_WARNING (("partition_number=%d not in [0;%d[", 
                                                partition_number, vid->partition_count));
                              }
                        }
                        
                        volume_id_close(vid);
                  }

            } else {
                  /* gee, so at least set volume.fstype to auto..
                   *
                   * GRRRR!!!
                   */
                  hal_device_property_set_string (d, "volume.fstype", "auto");
                  hal_device_property_set_string (d, "volume.fsusage", "filesystem");
                  volume_set_size (d, FALSE);
            }
            return;
      }


      /************************************************************
       * FOLLOWING CODE ONLY APPLY FOR TOPLEVEL BLOCK DEVICES
       *       (e.g. for setting storage.* properties)
       ************************************************************/


      snprintf (attr_path, SYSFS_PATH_MAX, "%s/removable", sysfs_path);
      attr = sysfs_open_attribute (attr_path);
      if (sysfs_read_attribute (attr) >= 0) {
            if (attr->value [0] == '0')
                  has_removable_media = FALSE;
            else
                  has_removable_media = TRUE;

            sysfs_close_attribute (attr);
      }     

      /* defaults */
      hal_device_property_set_string (stordev, "storage.drive_type", "disk");

      /* We are a disk or cdrom drive; maybe we even offer 
       * removable media 
       */
      hal_device_property_set_string (d, "info.category", "block");

      HAL_INFO (("Bus type is %s!",
               hal_device_property_get_string (parent, "info.bus")));

      if (strcmp (hal_device_property_get_string (parent, "info.bus"), "ide") == 0) {
            const char *ide_name;
            char *model;
            char *media;

            /* Be conservative and don't poll IDE drives at all */
            hal_device_property_set_bool (d, "storage.media_check_enabled", FALSE);

            ide_name = get_last_element (hal_device_property_get_string (d, "linux.sysfs_path"));
            model = read_single_line ("/proc/ide/%s/model", ide_name);
            if (model != NULL) {
                  hal_device_property_set_string (stordev, "storage.model", model);
                  hal_device_property_set_string (d, "info.product", model);
            }

            /* According to the function proc_ide_read_media() in 
             * drivers/ide/ide-proc.c in the Linux sources, media
             * can only assume "disk", "cdrom", "tape", "floppy", 
             * "UNKNOWN"
             */
            
            media = read_single_line ("/proc/ide/%s/media", ide_name);
            if (media != NULL) {
                  hal_device_property_set_string (stordev, "storage.drive_type", media);
                  
                  /* Set for removable media */
                  if (strcmp (media, "disk") == 0) {
                        /* left blank */
                  } else if (strcmp (media, "cdrom") == 0) {
                        has_removable_media = TRUE;
                        /* cdroms are the only IDE devices that are safe to poll */
                        hal_device_property_set_bool (d, "storage.media_check_enabled", TRUE);
                  } else if (strcmp (media, "floppy") == 0) {
                        has_removable_media = TRUE;
                  } else if (strcmp (media, "tape") == 0) {
                        has_removable_media = TRUE;
                  }                 
            }

            /* only check for drive_id if we are allowed to poll, otherwise we may
             * cause inifite loops of hotplug events, cf. broken ide-cs driver and
             * broken zip drives. Merely accessing the top-level block device if it
             * or any of it partitions are not mounted causes the loop.
             *
             * Also allow this when we don't have removable media.
             */
            if (hal_device_property_get_bool (stordev, "storage.media_check_enabled") ||
                !has_removable_media) {
                  const char *device_file;
                  struct drive_id *did;

                  device_file = hal_device_property_get_string (d, "block.device");
                  did = drive_id_open_node(device_file);
                  
                  if (drive_id_probe(did, DRIVE_ID_ATA) == 0) {
                        if (did->serial[0] != '\0')
                              hal_device_property_set_string (stordev, "storage.serial", did->serial);
                        if (did->firmware[0] != '\0')
                              hal_device_property_set_string (stordev, "storage.firmware_version", 
                                                      did->firmware);
                  }
                  drive_id_close(did);
            }

            
      } else if (strcmp (hal_device_property_get_string (parent,
                                           "info.bus"),
                     "scsi") == 0) {
            const char *device_file;
            struct drive_id *did;
            const char *sysfs_path;
            
            sysfs_path = hal_device_property_get_string (
                  d, "linux.sysfs_path");
            
            snprintf (attr_path, SYSFS_PATH_MAX,
                    "%s/device/vendor", sysfs_path);
            attr = sysfs_open_attribute (attr_path);
            if (sysfs_read_attribute (attr) >= 0) {
                  strip_space (attr->value);
                  hal_device_property_set_string (d, "info.vendor",
                                          attr->value);
                  hal_device_property_set_string (stordev,
                                          "storage.vendor",
                                          attr->value);
                  sysfs_close_attribute (attr);
            }
            
            snprintf (attr_path, SYSFS_PATH_MAX,
                    "%s/device/model", sysfs_path);
            attr = sysfs_open_attribute (attr_path);
            if (sysfs_read_attribute (attr) >= 0) {
                  strip_space (attr->value);
                  hal_device_property_set_string (d,
                                          "info.product",
                                          attr->value);
                  hal_device_property_set_string (stordev,
                                          "storage.model",
                                          attr->value);
                  sysfs_close_attribute (attr);
            }

            device_file = hal_device_property_get_string (d, "block.device");

            /* Only do drive_id on real SCSI devices - not on USB which uses emulated SCSI
             * since an INQUIRY on most USB devices may crash the storage device if the
             * transfer length isn't exactly 36 bytes.
             *
             * (See also Red Hat bug #145256)
             */
            if (strcmp (hal_device_property_get_string (stordev, "storage.bus"), "scsi") == 0) {

                  did = drive_id_open_node(device_file);
                  if (drive_id_probe(did, DRIVE_ID_SCSI) == 0) {
                        if (did->serial[0] != '\0')
                              hal_device_property_set_string (stordev,
                                                      "storage.serial",
                                                      did->serial);
                        if (did->revision[0] != '\0')
                              hal_device_property_set_string (stordev, 
                                                      "storage.revision",
                                                      did->revision);
                  }
                  drive_id_close(did);
            } 

            /* see if this is really a SATA disk */
#if 0
            /* commented out until the value of ATA_IOC_GET_IO32 is available */
            {
                  int fd;
                  unsigned char unused;

                  if ((fd = open (device_file, O_RDONLY|O_NDELAY)) != -1) {
                        if (ioctl (fd, ATA_IOC_GET_IO32, &unused) >= 0) {
                              hal_device_property_set_string (stordev, "storage.bus", "sata");
                        }
                        close (fd);
                  }
            }
#endif

            snprintf (attr_path, SYSFS_PATH_MAX,
                    "%s/device/type", sysfs_path);
            attr = sysfs_open_attribute (attr_path);
            if (sysfs_read_attribute (attr) >= 0) {
                  int type = parse_dec (attr->value);
                  switch (type) {
                  case 0:     /* Disk */
                        hal_device_property_set_string (
                              stordev, 
                              "storage.drive_type", 
                              "disk");
                        break;
                  case 1:     /* Tape */
                        hal_device_property_set_string (
                              stordev,
                              "storage.drive_type", 
                              "tape");
                        has_removable_media = TRUE;
                        break;
                  case 5:     /* CD-ROM */
                        hal_device_property_set_string (
                              stordev, 
                              "storage.drive_type", 
                              "cdrom");
                        has_removable_media = TRUE;
                        break;
                  default:
                        /** @todo add more SCSI types */
                        HAL_WARNING (("Don't know how to "
                                    "handle SCSI type %d", 
                                    type));
                  }
            }

            /* Check for USB floppy drive by looking at USB Mass Storage interface class
             * instead of Protocol: Uniform Floppy Interface (UFI) in /proc as we did before.
             *
             * (should fix RH bug 133834)
             */
            if (physdev != NULL) {
                  if (hal_device_property_get_int (physdev, "usb.interface.class") == 8 &&
                      hal_device_property_get_int (physdev, "usb.interface.subclass") == 4 ) {

                        hal_device_property_set_string (d, "storage.drive_type", "floppy");

                        /* My experiments with my USB LaCie Floppy disk
                         * drive is that polling indeed work (Yay!), so
                         * we don't set storage.media_check_enabled to 
                         * FALSE - for devices where this doesn't work,
                         * we can override it with .fdi files
                         */
                        has_removable_media = TRUE;

                  }
            }

      } else {
            /** @todo block device on non-IDE and non-SCSI device;
             *  how to find the name and the media-type? 
             */
            
            /* guestimate product name */
            hal_device_property_set_string (d, "info.product", "Disk");
            
      }

      hal_device_property_set_bool (stordev, "storage.removable", has_removable_media);

      if (hal_device_has_property (stordev, "storage.drive_type") &&
          strcmp (hal_device_property_get_string (stordev, "storage.drive_type"), "cdrom") == 0) {
            cdrom_get_properties (stordev, device_file);
            hal_device_add_capability (stordev, "storage.cdrom");
            hal_device_property_set_bool (stordev, "storage.no_partitions_hint", TRUE);
            requires_eject = TRUE;
      }


      if (hal_device_has_property (stordev, "storage.drive_type") &&
          strcmp (hal_device_property_get_string (stordev, "storage.drive_type"), "floppy") == 0) {
            hal_device_property_set_bool (stordev, "storage.no_partitions_hint", TRUE);
      }

      hal_device_property_set_string (stordev, "info.category", "storage");
      hal_device_add_capability (stordev, "storage");

      hal_device_property_set_bool (stordev, "storage.hotpluggable", is_hotpluggable);
      hal_device_property_set_bool (stordev, "storage.requires_eject", requires_eject);
      hal_device_property_set_bool (stordev, "block.no_partitions", 
                              hal_device_property_get_bool (
                                    stordev, "storage.no_partitions_hint"));


      /* FINALLY, merge information derived from a .fdi file, from the 
       * physical device that is backing this block device.
       *
       * - physdev is either NULL or the physical device (ide,
       *   usb, iee1394 etc.) of which we are the offspring
       *
       * - scsidev is either NULL or the SCSI device inbetween
       *   us and the physical device 
       */
      
      /* Merge storage.lun%d.* to storage.* from physical device for the
       * appropriate LUN */
      if (physdev != NULL) {

            /* Merge storage.* from physdev to stordev */
            hal_device_merge_with_rewrite (stordev, physdev, 
                                     "storage.", "storage.");
            
            /* If there's a scsi device inbetween merge all 
             * storage_lun%d.* properties */
            if (scsidev != NULL) {
                  int lun;
                  char propname[64];
                  
                  lun = hal_device_property_get_int (
                        scsidev, "scsi.lun");
            
                  /* See 6in1-card-reader.fdi for an example */
                  
                  snprintf (propname, sizeof (propname), 
                          "storage_lun%d.", lun);
                  
                  hal_device_merge_with_rewrite (stordev, physdev, 
                                           "storage.", propname);
            }
      }
}


Generated by  Doxygen 1.6.0   Back to index