GSList * hal_device_store_match_multiple_key_value_string (HalDeviceStore *store, const char *key, const char *value) { GSList *iter; GSList *matches = NULL; g_return_val_if_fail (store != NULL, NULL); g_return_val_if_fail (key != NULL, NULL); g_return_val_if_fail (value != NULL, NULL); for (iter = store->devices; iter != NULL; iter = iter->next) { HalDevice *d = HAL_DEVICE (iter->data); int type; if (!hal_device_has_property (d, key)) continue; type = hal_device_property_get_type (d, key); if (type != HAL_PROPERTY_TYPE_STRING) continue; if (strcmp (hal_device_property_get_string (d, key), value) == 0) matches = g_slist_prepend (matches, d); } return matches; }
static void hf_volume_device_update_mount_properties (HalDevice *device, const struct statfs *mounts, int n_mounts) { const struct statfs *mount = NULL; g_return_if_fail(HAL_IS_DEVICE(device)); if (mounts) { const char *special; special = hal_device_property_get_string(device, "block.device"); if (special) { mount = hf_volume_mounts_find(mounts, n_mounts, special); if (mount && strcmp(special, mount->f_mntfromname)) hal_device_property_set_string(device, "volume.freebsd.real_mounted_device", mount->f_mntfromname); else hal_device_property_remove(device, "volume.freebsd.real_mounted_device"); } } hal_device_property_set_bool(device, "volume.is_mounted", mount != NULL); hal_device_property_set_bool(device, "volume.is_mounted_read_only", mount && (mount->f_flags & MNT_RDONLY) != 0); hal_device_property_set_string(device, "volume.mount_point", mount ? mount->f_mntonname : NULL); }
/* generate hotplug event for each device in this branch */ void devinfo_remove_branch (gchar *devfs_path, HalDevice *d) { GSList *i; GSList *children; HalDevice *child; char *child_devfs_path; if (d == NULL) { d = hal_device_store_match_key_value_string (hald_get_gdl (), "solaris.devfs_path", devfs_path); if (d == NULL) return; } HAL_INFO (("remove_branch: %s %s\n", devfs_path, hal_device_get_udi (d))); /* first remove children */ children = hal_device_store_match_multiple_key_value_string (hald_get_gdl(), "info.parent", hal_device_get_udi (d)); for (i = children; i != NULL; i = g_slist_next (i)) { child = HAL_DEVICE (i->data); HAL_INFO (("remove_branch: child %s\n", hal_device_get_udi (child))); devinfo_remove_branch ((gchar *)hal_device_property_get_string (child, "solaris.devfs_path"), child); } g_slist_free (children); HAL_INFO (("remove_branch: done with children")); /* then remove self */ HAL_INFO (("remove_branch: queueing %s", devfs_path)); devinfo_remove_enqueue (devfs_path, NULL); }
static void hotplug_event_begin_devfs_add (HotplugEvent *hotplug_event, HalDevice *d) { HalDevice *parent; const gchar *parent_udi; void (*begin_add_func) (HalDevice *, HalDevice *, DevinfoDevHandler *, void *); if (d != NULL) { /* XXX */ HAL_ERROR (("devpath %s already present in store, ignore event", hotplug_event->un.devfs.devfs_path)); goto out; } /* find parent */ parent_udi = hal_device_property_get_string (hotplug_event->d, "info.parent"); if (parent_udi == NULL || strlen(parent_udi) == 0) { parent = NULL; } else { parent = hal_device_store_match_key_value_string (hald_get_gdl (), "info.udi", parent_udi); } /* only root node is allowed to be orphan */ if (parent == NULL) { if (strcmp(hotplug_event->un.devfs.devfs_path, "/") != 0) { HAL_ERROR (("Parent is NULL devfs_path=%s parent_udi=%s", hotplug_event->un.devfs.devfs_path, parent_udi ? parent_udi : "<null>")); goto out; } } /* children of ignored parent should be ignored */ if (parent != NULL && hal_device_property_get_bool (parent, "info.ignore")) { HAL_INFO (("parent ignored %s", parent_udi)); goto out; } /* custom or generic add function */ begin_add_func = hotplug_event->un.devfs.handler->hotplug_begin_add; if (begin_add_func == NULL) { begin_add_func = hotplug_event_begin_add_devinfo; } begin_add_func (hotplug_event->d, parent, hotplug_event->un.devfs.handler, (void *) hotplug_event); return; out: g_object_unref (hotplug_event->d); hotplug_event_end ((void *) hotplug_event); return; }
HalDevice * devinfo_audio_dsp_add(HalDevice *parent, const char *devnode, char *devfs_path, char *device_type) { HalDevice *d = NULL; char *device_file, *parent_udi, *card_id, *device_id; int16_t unit; if (strstr (devnode, "oss_dsp_") != devnode) return NULL; d = hal_device_new (); devinfo_set_default_properties (d, parent, devnode, devfs_path); hal_device_add_capability (d, "oss"); hal_device_property_set_string (d, "info.category", "oss"); hal_device_property_set_string (d, "info.subsystem", "sound"); card_id = hal_device_property_get_string (parent, "sound.card_id"); hal_device_property_set_string (d, "oss.card_id", card_id); unit = hal_device_property_get_int (parent, "sound.card"); hal_device_property_set_int (d, "oss.card", unit); hal_device_property_set_int (d, "oss.device", unit); device_id = hal_device_property_get_string (parent, "netbsd.sound.hardware"); hal_device_property_set_string (d, "oss.device_id", device_id); hal_device_property_set_string (d, "oss.type", "pcm"); device_file = g_strdup_printf (_PATH_SOUND "%d", unit); hal_device_property_set_string (d, "oss.device_file", device_file); g_free (device_file); parent_udi = hal_device_property_get_string (parent, "info.udi"); if (parent_udi) hal_device_property_set_string (d, "sound.originating_device", parent_udi); devinfo_add_enqueue (d, devfs_path, &devinfo_audio_dsp_handler); return d; }
void devinfo_set_default_properties (HalDevice *d, HalDevice *parent, di_node_t node, char *devfs_path) { char *driver_name, *s; const char *s1; char udi[HAL_PATH_MAX]; if (parent != NULL) { hal_device_property_set_string (d, "info.parent", hal_device_get_udi (parent)); } else { hal_device_property_set_string (d, "info.parent", "/org/freedesktop/Hal/devices/local"); } hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi), "/org/freedesktop/Hal/devices%s_%d", devfs_path, di_instance (node)); hal_device_set_udi (d, udi); hal_device_property_set_string (d, "info.udi", udi); if (di_prop_lookup_strings (DDI_DEV_T_ANY, node, "model", &s) > 0) { hal_device_property_set_string (d, "info.product", s); } else { hal_device_property_set_string (d, "info.product", di_node_name (node)); } hal_device_property_set_string (d, "solaris.devfs_path", devfs_path); if ((driver_name = di_driver_name (node)) != NULL) { hal_device_property_set_string (d, "info.solaris.driver", driver_name); } /* inherit parent's claim attributes */ if (hal_device_property_get_bool (parent, "info.claimed")) { s1 = hal_device_property_get_string (parent, "info.claimed.service"); if (s1 != NULL) { hal_device_property_set_bool (d, "info.claimed", TRUE); hal_device_property_set_string (d, "info.claimed.service", s1); } } }
static void store_changed (HalDeviceStore *store, HalDevice *device, gboolean added, gpointer user_data) { AsyncMatchInfo *info = (AsyncMatchInfo *) user_data; if (!added) return; if (!hal_device_has_property (device, info->key)) return; if (strcmp (hal_device_property_get_string (device, info->key), info->value) != 0) return; info->callback (store, device, info->user_data); destroy_async_match_info (info); }
HalDevice * hal_device_store_match_key_value_string (HalDeviceStore *store, const char *key, const char *value) { GSList *iter; GSList *devices; GHashTable *index; g_return_val_if_fail (store != NULL, NULL); g_return_val_if_fail (key != NULL, NULL); g_return_val_if_fail (value != NULL, NULL); index = g_hash_table_lookup (store->property_index, key); if (index) { devices = g_hash_table_lookup (index, value); if (devices) return (HalDevice*) devices->data; else return NULL; } else { for (iter = store->devices; iter != NULL; iter = iter->next) { HalDevice *d = HAL_DEVICE (iter->data); int type; if (!hal_device_has_property (d, key)) continue; type = hal_device_property_get_type (d, key); if (type != HAL_PROPERTY_TYPE_STRING) continue; if (strcmp (hal_device_property_get_string (d, key), value) == 0) return d; } } return NULL; }
static gboolean hf_net_update_timeout_cb (gpointer data) { GSList *l; if (hf_is_waiting) return TRUE; HF_LIST_FOREACH(l, hald_get_gdl()->devices) { HalDevice *device = l->data; const char *interface; interface = hal_device_property_get_string(device, "net.interface"); if (interface) { device_property_atomic_update_begin(); hf_net_device_set_link_up(device, hf_net_get_link_up(interface)); device_property_atomic_update_end(); } }
static void drvctl_lofi_add(gchar *devfs_path, gchar *name) { di_node_t node; const char *parent_udi; HalDevice *d, *parent; HAL_INFO (("lofi_add: %s %s", name, devfs_path)); if ((d = hal_device_store_match_key_value_string (hald_get_gdl (), "solaris.devfs_path", devfs_path)) == NULL) { HAL_INFO (("device not found in GDL %s", devfs_path)); return; } parent_udi = hal_device_property_get_string (d, "info.parent"); if ((parent_udi == NULL) || (strlen(parent_udi) == 0)) { HAL_INFO (("parent not found in GDL %s", parent_udi)); return; } if ((parent = hal_device_store_match_key_value_string (hald_get_gdl (), "info.udi", parent_udi)) == NULL) { HAL_INFO (("parent not found in GDL %s", parent_udi)); return; } if ((node = di_init (devfs_path, DINFOCPYALL)) == DI_NODE_NIL) { HAL_INFO (("device not found in devinfo %s", devfs_path)); return; } HAL_INFO (("device %s parent %s", hal_device_get_udi (d), parent_udi)); devinfo_lofi_add_major (parent, node, devfs_path, NULL, TRUE, d); di_fini (node); hotplug_event_process_queue (); }
static void property_index_modify_string (HalDeviceStore *store, HalDevice *device, const char *key, gboolean added) { GHashTable *index; const char *value; GSList *devices; value = hal_device_property_get_string (device, key); index = g_hash_table_lookup (store->property_index, key); if (!index) return; devices = g_hash_table_lookup (index, value); if (added) { /*add*/ HAL_DEBUG (("adding %p to (%s,%s)", device, key, value)); devices = g_slist_prepend (devices, device); } else { /*remove*/ HAL_DEBUG (("removing %p from (%s,%s)", device, key, value)); devices = g_slist_remove_all (devices, device); } g_hash_table_insert (index, (gpointer) value, devices); }
static void match_device_async (HalDeviceStore *store, HalDevice *device, const char *key, gboolean removed, gboolean added, gpointer user_data) { AsyncMatchInfo *info = (AsyncMatchInfo *) user_data; /* Only want to do it for added or changed properties */ if (removed) return; /* Keys have to match */ if (strcmp (info->key, key) != 0) return; /* Values have to match */ if (strcmp (hal_device_property_get_string (device, key), info->value) != 0) return; info->callback (store, device, info->user_data); destroy_async_match_info (info); }
HalDevice * devinfo_audio_add(HalDevice *parent, const char *devnode, char *devfs_path, char *device_type) { HalDevice *d = NULL, *mixer, *dsp; prop_dictionary_t dict; const char *driver, *parent_udi; char *childnode; int16_t unit; char *audioctl; struct audio_device audiodev; int fd; if (drvctl_find_device (devnode, &dict) == FALSE || dict == NULL) return NULL; if (prop_dictionary_get_int16 (dict, "device-unit", &unit) == false || prop_dictionary_get_cstring_nocopy (dict, "device-driver", &driver) == false) { prop_object_release (dict); return NULL; } if (strcmp (driver, "audio") != 0) { prop_object_release (dict); return NULL; } audioctl = g_strdup_printf (_PATH_AUDIOCTL "%d", unit); fd = open (audioctl, O_RDONLY); if (fd < 0) { HAL_WARNING (("couldn't open %s: %s", audioctl, strerror(errno))); goto done; } if (ioctl (fd, AUDIO_GETDEV, &audiodev) == -1) { HAL_WARNING (("couldn't query %s: %s", audioctl, strerror(errno))); goto done; } d = hal_device_new (); devinfo_set_default_properties (d, parent, devnode, devfs_path); hal_device_add_capability (d, "sound"); hal_device_property_set_string (d, "info.category", "sound"); hal_device_property_set_string (d, "info.subsystem", "sound"); hal_device_property_set_int (d, "sound.card", unit); hal_device_property_set_string (d, "sound.card_id", audiodev.name); hal_device_property_set_string (d, "netbsd.sound.hardware", audiodev.config); parent_udi = hal_device_property_get_string (parent, "info.udi"); if (parent_udi) hal_device_property_set_string (d, "sound.originating_device", parent_udi); devinfo_add_enqueue (d, devfs_path, &devinfo_audio_handler); childnode = g_strdup_printf ("oss_mixer_%d", unit); devinfo_add_node (d, childnode); g_free (childnode); childnode = g_strdup_printf ("oss_dsp_%d", unit); devinfo_add_node (d, childnode); g_free (childnode); done: if (dict) prop_object_release (dict); if (audioctl) g_free (audioctl); if (fd >= 0) close (fd); return d; }
HalDevice * devinfo_mass_disklabel_add(HalDevice *parent, const char *devnode, char *devfs_path, char *device_type) { HalDevice *d = NULL; struct disklabel label; struct partition *part; struct stat st; const char *driver; char *devpath, *rdevpath, *partname; char *childnode; char unit; struct volume_id *vid; uint64_t psize, msize; int i, fd; partname = devnode; unit = partname[strlen (partname) - 1] - 'a'; if (unit >= MAXPARTITIONS) return NULL; devpath = g_strdup_printf ("/dev/%s", partname); rdevpath = g_strdup_printf ("/dev/r%s", partname); fd = open (rdevpath, O_RDONLY); if (fd < 0) { HAL_WARNING (("couldn't open %s: %s", rdevpath, strerror (errno))); g_free (rdevpath); return NULL; } if (ioctl (fd, DIOCGDINFO, &label) == -1) { HAL_WARNING (("DIOCGDINFO failed on %s: %s", rdevpath, strerror (errno))); g_free (rdevpath); close (fd); return NULL; } part = &label.d_partitions[unit]; d = hal_device_new (); devinfo_set_default_properties (d, parent, devnode, devfs_path); hal_device_add_capability (d, "block"); hal_device_property_set_string (d, "info.subsystem", "block"); hal_device_property_set_string (d, "info.category", "volume"); hal_device_property_set_string (d, "block.device", devpath); hal_device_property_set_string (d, "block.storage_device", hal_device_property_get_string (parent, "info.udi")); if (stat (devpath, &st) == 0) { hal_device_property_set_int (d, "block.major", major (st.st_rdev)); hal_device_property_set_int (d, "block.minor", minor (st.st_rdev)); } hal_device_property_set_bool (d, "block.is_volume", TRUE); hal_device_property_set_bool (d, "block.no_partitions", FALSE); hal_device_property_set_bool (d, "block.have_scanned", TRUE); hal_device_add_capability (d, "volume"); hal_device_property_set_bool (d, "volume.ignore", FALSE); hal_device_property_set_bool (d, "volume.is_mounted", FALSE); hal_device_property_set_bool (d, "volume.is_mounted_read_only", FALSE); hal_device_property_set_string (d, "volume.mount_point", ""); hal_device_property_set_string (d, "volume.fsusage", "filesystem"); hal_device_property_set_string (d, "volume.fstype", devinfo_mass_get_fstype (part->p_fstype)); hal_device_property_set_bool (d, "volume.is_disc", FALSE); hal_device_property_set_string (d, "volume.label", ""); hal_device_property_set_string (d, "volume.partition.label", ""); hal_device_property_set_string (d, "volume.uuid", ""); hal_device_property_set_string (d, "volume.partition.uuid", ""); psize = (uint64_t)part->p_size * (uint64_t)label.d_secsize; msize = (uint64_t)label.d_secsize * (uint64_t)label.d_secperunit; hal_device_property_set_uint64 (d, "volume.size", psize); hal_device_property_set_int (d, "volume.block_size", label.d_secsize); hal_device_property_set_uint64 (d, "volume.num_blocks", part->p_size); hal_device_property_set_uint64 (d, "volume.partition.media_size", msize); hal_device_property_set_bool (d, "volume.is_partition", TRUE); hal_device_property_set_int (d, "volume.partition.number", unit); hal_device_property_set_string (d, "volume.partition.scheme", "mbr"); vid = volume_id_open_fd (fd); if (vid) { if (volume_id_probe_all (vid, 0, psize) == 0) { const char *type,*fstype; hal_device_property_set_string (d, "volume.label", vid->label); hal_device_property_set_string (d, "volume.partition.label", vid->label); hal_device_property_set_string (d, "volume.uuid", vid->uuid); hal_device_property_set_string (d, "volume.partition.uuid", vid->uuid); if ( type && volume_id_get_type (vid, &type)) { fstype=devinfo_mass_get_fstype (part->p_fstype); if (strcmp (type, fstype)) { HAL_INFO (("%s disklabel reports [%s] but libvolume_id says it is " "[%s], assuming disklabel is incorrect", devpath, fstype, type)); hal_device_property_set_string (d, "volume.fstype", type); } } } volume_id_close (vid); } devinfo_add_enqueue (d, devfs_path, &devinfo_mass_disklabel_handler); close (fd); g_free (rdevpath); g_free (devpath); return d; }
HalDevice * devinfo_mass_add(HalDevice *parent, const char *devnode, char *devfs_path, char *device_type) { HalDevice *d = NULL, *gparent = NULL; prop_dictionary_t dict; struct disklabel label; struct stat st; const char *driver; char *rdevpath, *devpath; char *childnode; char *parent_devnode, *gparent_devnode = NULL; char *gparent_udi; int16_t unit; int i, fd; struct scsipi_inquiry_data inqbuf; struct scsipi_inquiry cmd; bool scsiinq_status; char *storage_model = NULL, *storage_vendor = NULL; if (drvctl_find_device (devnode, &dict) == FALSE || dict == NULL) return NULL; if (prop_dictionary_get_int16 (dict, "device-unit", &unit) == false || prop_dictionary_get_cstring_nocopy (dict, "device-driver", &driver) == false) { prop_object_release (dict); return NULL; } if (strcmp (driver, "wd") != 0 && strcmp (driver, "sd") != 0 && strcmp (driver, "ld") != 0) { prop_object_release (dict); return NULL; } sleep (1); devpath = g_strdup_printf ("/dev/%s%c", devnode, RAW_PART + 'a'); rdevpath = g_strdup_printf ("/dev/r%s%c", devnode, RAW_PART + 'a'); HAL_INFO ((" going to open %s", rdevpath)); fd = open (rdevpath, O_RDONLY); if (fd < 0) { HAL_WARNING (("couldn't open %s: %s", rdevpath, strerror (errno))); g_free (rdevpath); g_free (devpath); return NULL; } HAL_INFO ((" going to DIOCGDINFO %s", rdevpath)); if (ioctl (fd, DIOCGDINFO, &label) == -1) { HAL_WARNING (("DIOCGDINFO failed on %s: %s", rdevpath, strerror (errno))); g_free (rdevpath); g_free (devpath); close (fd); return NULL; } if (strcmp (driver, "sd") == 0) { memset(&cmd, 0, sizeof (cmd)); memset(&inqbuf, 0, sizeof (inqbuf)); cmd.opcode = INQUIRY; cmd.length = sizeof (inqbuf); scsiinq_status = scsi_command (fd, &cmd, sizeof (cmd), &inqbuf, sizeof (inqbuf), 10000, SCCMD_READ); } else scsiinq_status = false; close (fd); d = hal_device_new (); devinfo_set_default_properties (d, parent, devnode, devfs_path); hal_device_add_capability (d, "block"); hal_device_property_set_string (d, "info.subsystem", "block"); hal_device_property_set_string (d, "block.device", devpath); if (stat (devpath, &st) == 0) { hal_device_property_set_int (d, "block.major", major (st.st_rdev)); hal_device_property_set_int (d, "block.minor", minor (st.st_rdev)); } hal_device_property_set_bool (d, "block.is_volume", FALSE); hal_device_property_set_bool (d, "block.no_partitions", FALSE); hal_device_property_set_bool (d, "block.have_scanned", TRUE); hal_device_add_capability (d, "storage"); hal_device_property_set_string (d, "info.category", "storage"); parent_devnode = hal_device_property_get_string (parent, "netbsd.device"); gparent_udi = hal_device_property_get_string (parent, "info.parent"); if (gparent_udi) { gparent = hal_device_store_find (hald_get_gdl (), gparent_udi); if (gparent) gparent_devnode = hal_device_property_get_string (gparent, "netbsd.device"); } if (gparent_devnode && strstr (gparent_devnode, "umass") == gparent_devnode) hal_device_property_set_string (d, "storage.bus", "usb"); else if (parent_devnode && strstr (parent_devnode, "atabus") == parent_devnode) hal_device_property_set_string (d, "storage.bus", "ide"); else hal_device_property_set_string (d, "storage.bus", "scsi"); hal_device_property_set_string (d, "storage.device_type", "disk"); hal_device_property_set_bool (d, "storage.removable", label.d_flags & D_REMOVABLE ? TRUE : FALSE); if (label.d_flags & D_REMOVABLE) { hal_device_property_set_bool (d, "storage.removable.media_available", TRUE); hal_device_property_set_uint64 (d, "storage.removable.media_size", (uint64_t)label.d_secsize * (uint64_t)label.d_secperunit); hal_device_property_set_uint64 (d, "storage.size", 0); hal_device_property_set_bool (d, "storage.hotpluggable", TRUE); hal_device_property_set_bool (d, "storage.automount_enabled_hint", TRUE); } else { hal_device_property_set_bool (d, "storage.removable.media_available", FALSE); hal_device_property_set_uint64 (d, "storage.removable.media_size", 0); hal_device_property_set_uint64 (d, "storage.size", (uint64_t)label.d_secsize * (uint64_t)label.d_secperunit); hal_device_property_set_bool (d, "storage.hotpluggable", FALSE); hal_device_property_set_bool (d, "storage.automount_enabled_hint", FALSE); } hal_device_property_set_bool (d, "storage.no_partitions_hint", FALSE); hal_device_property_set_bool (d, "storage.requires_eject", FALSE); hal_device_property_set_bool (d, "storage.removable.support_async_notification", FALSE); hal_device_property_set_string (d, "storage.partitioning_scheme", "mbr"); hal_device_property_set_string (d, "storage.originating_device", hal_device_property_get_string (d, "info.udi")); if (scsiinq_status == true) { storage_model = rtrim_copy(inqbuf.product, sizeof (inqbuf.product)); storage_vendor = rtrim_copy(inqbuf.vendor, sizeof (inqbuf.vendor)); } if (storage_model) { hal_device_property_set_string (d, "storage.model", storage_model); free (storage_model); } else hal_device_property_set_string (d, "storage.model", label.d_packname); if (storage_vendor) { hal_device_property_set_string (d, "storage.vendor", storage_vendor); free (storage_vendor); } else hal_device_property_set_string (d, "storage.vendor", label.d_typename); devinfo_add_enqueue (d, devfs_path, &devinfo_mass_handler); for (i = 0; i < MAXPARTITIONS; i++) { const char *fstype; fstype = devinfo_mass_get_fstype(label.d_partitions[i].p_fstype); if (fstype == NULL) continue; childnode = g_strdup_printf ("%s%c", devnode, 'a' + i); HAL_INFO ((" adding %s on %s", childnode, rdevpath)); devinfo_mass_disklabel_add (d, childnode, childnode, childnode); g_free (childnode); } HAL_INFO ((" returning")); g_free (rdevpath); g_free (devpath); done: prop_object_release (dict); return d; }