terminal: grdev: refresh device state on hotplug events
authorDavid Herrmann <dh.herrmann@gmail.com>
Sat, 20 Sep 2014 07:50:10 +0000 (09:50 +0200)
committerDavid Herrmann <dh.herrmann@gmail.com>
Sat, 20 Sep 2014 09:46:49 +0000 (11:46 +0200)
Whenever we get udev hotplug events, re-read the device state so we
properly detect any changed in the display setups.

src/libsystemd-terminal/grdev-drm.c
src/libsystemd-terminal/grdev-internal.h
src/libsystemd-terminal/grdev.c

index 3481584fbf760bc4e3331b9a2e76a6c4b0e5240d..f0f0448635051e8ae3a4006dd15049ffa17d6a62 100644 (file)
@@ -2096,8 +2096,11 @@ static void grdrm_card_hotplug(grdrm_card *card) {
         int r;
 
         assert(card);
-        assert(!card->ready);
 
+        if (!card->running)
+                return;
+
+        card->ready = false;
         r = grdrm_card_resync(card);
         if (r < 0) {
                 log_debug("grdrm: %s/%s: cannot re-sync card: %s",
@@ -2955,3 +2958,30 @@ int grdev_drm_card_new(grdev_card **out, grdev_session *session, struct udev_dev
 
         return session->managed ? managed_card_new(out, session, ud) : unmanaged_card_new(out, session, ud);
 }
+
+void grdev_drm_card_hotplug(grdev_card *basecard, struct udev_device *ud) {
+        const char *p, *action;
+        grdrm_card *card;
+        dev_t devnum;
+
+        assert(basecard);
+        assert(grdev_is_drm_card(basecard));
+        assert(ud);
+
+        card = grdrm_card_from_base(basecard);
+
+        action = udev_device_get_action(ud);
+        if (!action || streq(action, "add") || streq(action, "remove")) {
+                /* If we get add/remove events on DRM nodes without devnum, we
+                 * got hotplugged DRM objects so refresh the device. */
+                devnum = udev_device_get_devnum(ud);
+                if (devnum == 0)
+                        grdrm_card_hotplug(card);
+        } else if (streq_ptr(action, "change")) {
+                /* A change event with HOTPLUG=1 is sent whenever a connector
+                 * changed state. Refresh the device to update our state. */
+                p = udev_device_get_property_value(ud, "HOTPLUG");
+                if (streq_ptr(p, "1"))
+                        grdrm_card_hotplug(card);
+        }
+}
index 0064f0be02738fd553d088706c99f44112b49a95..96830a714ca0988b2b54513463e5ae87d0fe1a13 100644 (file)
@@ -47,6 +47,7 @@ typedef struct grdev_card               grdev_card;
 bool grdev_is_drm_card(grdev_card *card);
 grdev_card *grdev_find_drm_card(grdev_session *session, dev_t devnum);
 int grdev_drm_card_new(grdev_card **out, grdev_session *session, struct udev_device *ud);
+void grdev_drm_card_hotplug(grdev_card *card, struct udev_device *ud);
 
 /*
  * Displays
index bb89ee7170c9cc9ac886870009f8abcd6a461bdb..3e3833fc95caa9170ba1e805bf7da969b4efbc4d 100644 (file)
@@ -1150,7 +1150,7 @@ void grdev_session_hotplug_drm(grdev_session *session, struct udev_device *ud) {
         if (!card)
                 return;
 
-        /* TODO: hotplug card */
+        grdev_drm_card_hotplug(card, ud);
 }
 
 static void session_configure(grdev_session *session) {