Blob Blame History Raw
From b96ff001587de11eaf98ace71b196cc5ab4cf007 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Mon, 14 Jul 2014 08:04:54 -0400
Subject: [PATCH 1/5] seat: be a little more forgiving in the case there's no
 open terminal

We can end up in a situation where a seat object doesn't have a terminal
associated with it.  In that case we shouldn't crash, but continue on
with no input available for that seat.

https://bugs.freedesktop.org/show_bug.cgi?id=80553
---
 src/libply-splash-core/ply-seat.c | 23 +++++++++++++++++++----
 1 file changed, 19 insertions(+), 4 deletions(-)

diff --git a/src/libply-splash-core/ply-seat.c b/src/libply-splash-core/ply-seat.c
index 2ac8bf7..cd7e5bc 100644
--- a/src/libply-splash-core/ply-seat.c
+++ b/src/libply-splash-core/ply-seat.c
@@ -127,68 +127,83 @@ ply_seat_open (ply_seat_t          *seat,
   if (renderer_type != PLY_RENDERER_TYPE_NONE)
     {
       ply_renderer_t *renderer;
 
       renderer = ply_renderer_new (renderer_type, device, seat->terminal);
 
       if (!ply_renderer_open (renderer))
         {
           ply_trace ("could not open renderer for %s", device);
           ply_renderer_free (renderer);
 
           seat->renderer = NULL;
           seat->renderer_active = false;
 
           if (renderer_type != PLY_RENDERER_TYPE_AUTO)
             return false;
         }
       else
         {
           seat->renderer = renderer;
           seat->renderer_active = true;
         }
     }
 
   if (seat->renderer != NULL)
     {
       seat->keyboard = ply_keyboard_new_for_renderer (seat->renderer);
       add_pixel_displays (seat);
 
     }
-  else
+  else if (seat->terminal != NULL)
     {
       seat->keyboard = ply_keyboard_new_for_terminal (seat->terminal);
     }
-  add_text_displays (seat);
 
-  ply_keyboard_watch_for_input (seat->keyboard);
-  seat->keyboard_active = true;
+  if (seat->terminal != NULL)
+    {
+      add_text_displays (seat);
+    }
+  else
+    {
+      ply_trace ("not adding text display for seat, since seat has no associated terminal");
+    }
+
+  if (seat->keyboard != NULL)
+    {
+      ply_keyboard_watch_for_input (seat->keyboard);
+      seat->keyboard_active = true;
+    }
+  else
+    {
+      ply_trace ("not watching seat for input");
+    }
 
   return true;
 }
 
 bool
 ply_seat_is_open (ply_seat_t *seat)
 {
   return ply_list_get_length (seat->pixel_displays) > 0 ||
          ply_list_get_length (seat->text_displays) > 0;
 }
 
 void
 ply_seat_deactivate_keyboard (ply_seat_t *seat)
 {
   if (!seat->keyboard_active)
     return;
 
   seat->keyboard_active = false;
 
   if (seat->keyboard == NULL)
     return;
 
   ply_trace ("deactivating keybord");
   ply_keyboard_stop_watching_for_input (seat->keyboard);
 }
 
 void
 ply_seat_deactivate_renderer (ply_seat_t *seat)
 {
   if (!seat->renderer_active)
-- 
2.3.7


From b5ed92bc2efd0b52e901a67ea8e5afa809ca3598 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Fri, 3 Jul 2015 09:29:39 -0400
Subject: [PATCH 2/5] main: show cursor on crash

---
 src/main.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/main.c b/src/main.c
index 77fa96f..db5c281 100644
--- a/src/main.c
+++ b/src/main.c
@@ -2051,66 +2051,69 @@ on_error_message (ply_buffer_t *debug_buffer,
 {
   ply_buffer_append_bytes (debug_buffer, bytes, number_of_bytes);
 }
 
 static void
 dump_debug_buffer_to_file (void)
 {
   int fd;
   const char *bytes;
   size_t size;
 
   fd = open (debug_buffer_path,
              O_WRONLY | O_CREAT | O_TRUNC, 0600);
 
   if (fd < 0)
     return;
 
   size = ply_buffer_get_size (debug_buffer);
   bytes = ply_buffer_get_bytes (debug_buffer);
   ply_write (fd, bytes, size);
   close (fd);
 }
 
  #include <termios.h>
  #include <unistd.h>
 static void
 on_crash (int signum)
 {
     struct termios term_attributes;
     int fd;
+    static const char *show_cursor_sequence = "\033[?25h";
 
     fd = open ("/dev/tty1", O_RDWR | O_NOCTTY);
     if (fd < 0) fd = open ("/dev/hvc0", O_RDWR | O_NOCTTY);
 
     ioctl (fd, KDSETMODE, KD_TEXT);
 
+    write (fd, show_cursor_sequence, sizeof (show_cursor_sequence) - 1);
+
     tcgetattr (fd, &term_attributes);
 
     term_attributes.c_iflag |= BRKINT | IGNPAR | ICRNL | IXON;
     term_attributes.c_oflag |= OPOST;
     term_attributes.c_lflag |= ECHO | ICANON | ISIG | IEXTEN;
 
     tcsetattr (fd, TCSAFLUSH, &term_attributes);
 
     close (fd);
 
     if (debug_buffer != NULL)
       {
         dump_debug_buffer_to_file ();
         sleep (30);
       }
 
     if (pid_file != NULL)
       {
         unlink (pid_file);
         free (pid_file);
         pid_file = NULL;
       }
 
     signal (signum, SIG_DFL);
     raise(signum);
 }
 
 static void
 write_pid_file (const char *filename)
 {
-- 
2.3.7


From 4278596f4f5a6856aff50e97b7c0ff05aed67372 Mon Sep 17 00:00:00 2001
From: Frederic Crozat <fcrozat@suse.com>
Date: Thu, 12 Jun 2014 15:01:37 +0200
Subject: [PATCH 3/5] device-manager: only call ply_terminal_free

ply_terminal_free will call ply_terminal_close anyway and is guarded
against NULL terminal (ply_terminal_close is not).
---
 src/libply-splash-core/ply-device-manager.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/libply-splash-core/ply-device-manager.c b/src/libply-splash-core/ply-device-manager.c
index 8f5360c..17607f4 100644
--- a/src/libply-splash-core/ply-device-manager.c
+++ b/src/libply-splash-core/ply-device-manager.c
@@ -415,61 +415,60 @@ free_seats (ply_device_manager_t *manager)
 {
   ply_list_node_t *node;
 
   ply_trace ("removing seats");
   node = ply_list_get_first_node (manager->seats);
   while (node != NULL)
     {
       ply_seat_t *seat;
       ply_list_node_t *next_node;
 
       seat = ply_list_node_get_data (node);
       next_node = ply_list_get_next_node (manager->seats, node);
 
       if (manager->seat_removed_handler != NULL)
         manager->seat_removed_handler (manager->seat_event_handler_data, seat);
 
       ply_seat_free (seat);
       ply_list_remove_node (manager->seats, node);
 
       node = next_node;
     }
 }
 
 static void
 free_terminal (char                 *device,
                ply_terminal_t       *terminal,
                ply_device_manager_t *manager)
 {
   ply_hashtable_remove (manager->terminals, device);
 
-  ply_terminal_close (terminal);
   ply_terminal_free (terminal);
 }
 
 static void
 free_terminals (ply_device_manager_t *manager)
 {
   ply_hashtable_foreach (manager->terminals,
                          (ply_hashtable_foreach_func_t *)
                          free_terminal,
                          manager);
 }
 
 static ply_terminal_t *
 get_terminal (ply_device_manager_t *manager,
               const char           *device_name)
 {
   char *full_name = NULL;
   ply_terminal_t *terminal;
 
   if (strncmp (device_name, "/dev/", strlen ("/dev/")) == 0)
     full_name = strdup (device_name);
   else
     asprintf (&full_name, "/dev/%s", device_name);
 
   if (strcmp (full_name, "/dev/tty0") == 0 ||
       strcmp (full_name, "/dev/tty") == 0 ||
       strcmp (full_name, ply_terminal_get_name (manager->local_console_terminal)) == 0)
     {
       terminal = manager->local_console_terminal;
 
-- 
2.3.7


From e7048fdd1a40ed683fc706a40816cc490a693ba9 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Wed, 7 Jan 2015 16:24:57 -0500
Subject: [PATCH 4/5] device-manager: try fb device if drm device failed

If the drm device failed to work, then fall back to the fb device.

Right now, we ignore fb devices that have associated drm devices.

This may fix vmwgfx.
---
 src/libply-splash-core/ply-device-manager.c | 39 ++++++++++++++++++++++++++++-
 1 file changed, 38 insertions(+), 1 deletion(-)

diff --git a/src/libply-splash-core/ply-device-manager.c b/src/libply-splash-core/ply-device-manager.c
index 17607f4..cc153e2 100644
--- a/src/libply-splash-core/ply-device-manager.c
+++ b/src/libply-splash-core/ply-device-manager.c
@@ -88,95 +88,132 @@ attach_to_event_loop (ply_device_manager_t *manager,
 }
 
 static bool
 device_is_for_local_console (ply_device_manager_t *manager,
                              struct udev_device   *device)
 {
   const char *device_path;
   struct udev_device *bus_device;
   char *bus_device_path;
   const char *boot_vga;
   bool for_local_console;
 
   /* Look at the associated bus device to see if this card is the
    * card the kernel is using for its console. */
   device_path = udev_device_get_syspath (device);
   asprintf (&bus_device_path, "%s/device", device_path);
   bus_device = udev_device_new_from_syspath (manager->udev_context, bus_device_path);
 
   boot_vga = udev_device_get_sysattr_value (bus_device, "boot_vga");
   free (bus_device_path);
 
   if (boot_vga != NULL && strcmp (boot_vga, "1") == 0)
     for_local_console = true;
   else
     for_local_console = false;
 
   return for_local_console;
 }
 
 static bool
+drm_device_in_use (ply_device_manager_t *manager,
+                   const char           *device_path)
+{
+  ply_list_node_t *node;
+
+  node = ply_list_get_first_node (manager->seats);
+  while (node != NULL)
+    {
+      ply_seat_t *seat;
+      ply_renderer_t *renderer;
+      ply_list_node_t *next_node;
+      const char *renderer_device_path;
+
+      seat = ply_list_node_get_data (node);
+      next_node = ply_list_get_next_node (manager->seats, node);
+      renderer = ply_seat_get_renderer (seat);
+
+      if (renderer != NULL)
+        {
+          renderer_device_path = ply_renderer_get_device_name (renderer);
+
+          if (renderer_device_path != NULL)
+            {
+              if (strcmp (device_path, renderer_device_path) == 0)
+                {
+                  return true;
+                }
+            }
+        }
+
+      node = next_node;
+    }
+
+  return false;
+}
+
+static bool
 fb_device_has_drm_device (ply_device_manager_t *manager,
                           struct udev_device   *fb_device)
 {
   struct udev_enumerate *card_matches;
   struct udev_list_entry *card_entry;
   const char *id_path;
   bool has_drm_device = false;
 
   /* We want to see if the framebuffer is associated with a DRM-capable
    * graphics card, if it is, we'll use the DRM device */
   card_matches = udev_enumerate_new (manager->udev_context);
   udev_enumerate_add_match_is_initialized(card_matches);
   udev_enumerate_add_match_parent (card_matches, udev_device_get_parent (fb_device));
   udev_enumerate_add_match_subsystem (card_matches, "drm");
   id_path = udev_device_get_property_value (fb_device, "ID_PATH");
   udev_enumerate_add_match_property (card_matches, "ID_PATH", id_path);
 
   ply_trace ("trying to find associated drm node for fb device (path: %s)", id_path);
 
   udev_enumerate_scan_devices (card_matches);
 
   /* there should only ever be at most one match so we don't iterate through
    * the list, but just look at the first entry */
   card_entry = udev_enumerate_get_list_entry (card_matches);
 
   if (card_entry != NULL)
     {
       struct udev_device *card_device = NULL;
       const char *card_node;
       const char *card_path;
 
       card_path = udev_list_entry_get_name (card_entry);
       card_device = udev_device_new_from_syspath (manager->udev_context, card_path);
       card_node = udev_device_get_devnode (card_device);
-      if (card_node != NULL)
+      if (card_node != NULL && drm_device_in_use (manager, card_node))
         has_drm_device = true;
       else
         ply_trace ("no card node!");
 
       udev_device_unref (card_device);
     }
   else
     {
       ply_trace ("no card entry!");
     }
 
   udev_enumerate_unref (card_matches);
   return has_drm_device;
 }
 
 static void
 create_seat_for_udev_device (ply_device_manager_t *manager,
                              struct udev_device   *device)
 {
   bool for_local_console;
   const char *device_path;
   ply_terminal_t *terminal = NULL;
 
   for_local_console = device_is_for_local_console (manager, device);
 
   ply_trace ("device is for local console: %s", for_local_console? "yes" : "no");
 
   if (for_local_console)
     terminal = manager->local_console_terminal;
 
-- 
2.3.7


From b9989b912fb394c00d3d4740eb72a25f80a8bc71 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Fri, 3 Jul 2015 10:38:47 -0400
Subject: [PATCH 5/5] device-manager: don't try to load graphical splash after
 using text splash

We only support loading one splash at a time at the moment, so this
commit makes sure we don't load a graphical splash after already loading
a text splash
---
 src/libply-splash-core/ply-device-manager.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/src/libply-splash-core/ply-device-manager.c b/src/libply-splash-core/ply-device-manager.c
index cc153e2..a7890d0 100644
--- a/src/libply-splash-core/ply-device-manager.c
+++ b/src/libply-splash-core/ply-device-manager.c
@@ -379,61 +379,69 @@ create_seats_for_subsystem (ply_device_manager_t *manager,
   return found_device;
 }
 
 static void
 on_udev_event (ply_device_manager_t *manager)
 {
   struct udev_device *device;
   const char *action;
 
   device = udev_monitor_receive_device (manager->udev_monitor);
   if (device == NULL)
     return;
 
   action = udev_device_get_action (device);
 
   ply_trace ("got %s event for device %s", action, udev_device_get_sysname (device));
 
   if (action == NULL)
     return;
 
   if (strcmp (action, "add") == 0)
     {
       const char *subsystem;
       bool coldplug_complete = manager->udev_queue_fd_watch == NULL;
 
       subsystem = udev_device_get_subsystem (device);
 
       if (strcmp (subsystem, SUBSYSTEM_DRM) == 0 ||
           coldplug_complete)
         {
-          create_seat_for_udev_device (manager, device);
+          ply_list_t *local_pixel_displays = NULL;
+
+          if (manager->local_console_seat != NULL)
+            local_pixel_displays = ply_seat_get_pixel_displays (manager->local_console_seat);
+
+          if (coldplug_complete && manager->local_console_seat != NULL && local_pixel_displays == NULL)
+            ply_trace ("ignoring since we're already using text splash for local console");
+          else
+            create_seat_for_udev_device (manager, device);
         }
       else
         {
           ply_trace ("ignoring since we only handle subsystem %s devices after coldplug completes", subsystem);
         }
     }
   else if (strcmp (action, "remove") == 0)
     {
       free_seat_for_udev_device (manager, device);
     }
 
   udev_device_unref (device);
 }
 
 static void
 watch_for_udev_events (ply_device_manager_t *manager)
 {
   int fd;
   assert (manager != NULL);
   assert (manager->udev_monitor == NULL);
 
   ply_trace ("watching for udev graphics device add and remove events");
 
   manager->udev_monitor = udev_monitor_new_from_netlink (manager->udev_context, "udev");
 
   udev_monitor_filter_add_match_subsystem_devtype (manager->udev_monitor, SUBSYSTEM_DRM, NULL);
   udev_monitor_filter_add_match_subsystem_devtype (manager->udev_monitor, SUBSYSTEM_FRAME_BUFFER, NULL);
   udev_monitor_filter_add_match_tag (manager->udev_monitor, "seat");
   udev_monitor_enable_receiving (manager->udev_monitor);
 
-- 
2.3.7