diff options
author | David Herrmann <dh.herrmann@gmail.com> | 2014-09-20 09:50:10 +0200 |
---|---|---|
committer | David Herrmann <dh.herrmann@gmail.com> | 2014-09-20 11:46:49 +0200 |
commit | 6221d249d1f03d235a23a284c597c86676b32d2f (patch) | |
tree | 3582aa87859ab5e03edecd354233ba1bfa674769 | |
parent | a3eabec96b872bbf581c9bfa81ecc9c2819b8de8 (diff) |
terminal: grdev: refresh device state on hotplug events
Whenever we get udev hotplug events, re-read the device state so we
properly detect any changed in the display setups.
-rw-r--r-- | src/libsystemd-terminal/grdev-drm.c | 32 | ||||
-rw-r--r-- | src/libsystemd-terminal/grdev-internal.h | 1 | ||||
-rw-r--r-- | src/libsystemd-terminal/grdev.c | 2 |
3 files changed, 33 insertions, 2 deletions
diff --git a/src/libsystemd-terminal/grdev-drm.c b/src/libsystemd-terminal/grdev-drm.c index 3481584fbf..f0f0448635 100644 --- a/src/libsystemd-terminal/grdev-drm.c +++ b/src/libsystemd-terminal/grdev-drm.c @@ -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); + } +} diff --git a/src/libsystemd-terminal/grdev-internal.h b/src/libsystemd-terminal/grdev-internal.h index 0064f0be02..96830a714c 100644 --- a/src/libsystemd-terminal/grdev-internal.h +++ b/src/libsystemd-terminal/grdev-internal.h @@ -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 diff --git a/src/libsystemd-terminal/grdev.c b/src/libsystemd-terminal/grdev.c index bb89ee7170..3e3833fc95 100644 --- a/src/libsystemd-terminal/grdev.c +++ b/src/libsystemd-terminal/grdev.c @@ -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) { |