+/**
+ * Compares two devices (to support binary search).
+ */
+static int cmpdev (const void *a, const void *b)
+{
+ const dev_t *da = a, *db = b;
+ dev_t delta = *da - *db;
+
+ if (sizeof (delta) > sizeof (int))
+ return delta ? ((delta > 0) ? 1 : -1) : 0;
+ return (signed)delta;
+}
+
+static void DestroyDevice (void *data)
+{
+ struct device *d = data;
+
+ vlc_gc_decref (d->item);
+ free (d);
+}
+
+static char *decode_property (struct udev_device *, const char *);
+
+/**
+ * Adds a udev device.
+ */
+static int AddDevice (services_discovery_t *sd, struct udev_device *dev)
+{
+ services_discovery_sys_t *p_sys = sd->p_sys;
+
+ char *mrl = p_sys->subsys->get_mrl (dev);
+ if (mrl == NULL)
+ return 0; /* don't know if it was an error... */
+ char *name = p_sys->subsys->get_name (dev);
+ input_item_t *item = input_item_NewWithType (VLC_OBJECT (sd), mrl,
+ name ? name : mrl,
+ 0, NULL, 0, -1, ITEM_TYPE_CARD);
+ msg_Dbg (sd, "adding %s (%s)", mrl, name);
+ free (name);
+ free (mrl);
+ if (item == NULL)
+ return -1;
+
+ struct device *d = malloc (sizeof (*d));
+ if (d == NULL)
+ {
+ vlc_gc_decref (item);
+ return -1;
+ }
+ d->item = item;
+ d->devnum = udev_device_get_devnum (dev);
+
+ struct device **dp = tsearch (d, &p_sys->root, cmpdev);
+ if (dp == NULL) /* Out-of-memory */
+ {
+ DestroyDevice (d);
+ return -1;
+ }
+ if (*dp != d) /* Overwrite existing device */
+ {
+ services_discovery_RemoveItem (sd, (*dp)->item);
+ DestroyDevice (*dp);
+ *dp = d;
+ }
+
+ name = p_sys->subsys->get_cat (dev);
+ services_discovery_AddItem (sd, item, name ? name : "Generic");
+ free (name);
+ return 0;
+}
+
+/**
+ * Removes a udev device (if present).
+ */
+static void RemoveDevice (services_discovery_t *sd, struct udev_device *dev)
+{
+ services_discovery_sys_t *p_sys = sd->p_sys;
+
+ dev_t num = udev_device_get_devnum (dev);
+ struct device **dp = tfind (&(dev_t){ num }, &p_sys->root, cmpdev);
+ if (dp == NULL)
+ return;
+
+ struct device *d = *dp;
+ services_discovery_RemoveItem (sd, d->item);
+ tdelete (d, &p_sys->root, cmpdev);
+ DestroyDevice (d);
+}
+
+static void HandleDevice (services_discovery_t *sd, struct udev_device *dev,
+ bool add)
+{
+ if (!add)
+ RemoveDevice (sd, dev);
+ else
+ AddDevice (sd, dev);
+}
+