[Spice-devel] [PATCH v5] spice: set device address and device display ID in QXL interface

2019-02-15 Thread Lukáš Hrázký
Calls the new SPICE QXL interface function spice_qxl_set_device_info to
set the hardware address of the graphics device represented by the QXL
interface (e.g. a PCI path) and the device display IDs (the IDs of the
device's monitors that belong to this QXL interface).

Also stops using the deprecated spice_qxl_set_max_monitors, the new
interface function replaces it.

Signed-off-by: Lukáš Hrázký 
---
Hi,

sorry about the noise, v4 still isn't passing the check. I didn't know
the check script is in the git tree. This one should pass.

Changes since v4:
* Really fix comments according to the check script.

Cheers,
Lukas


 hw/display/qxl.c   | 14 ++-
 include/ui/spice-display.h |  4 +++
 ui/spice-core.c| 51 ++
 ui/spice-display.c | 11 
 4 files changed, 79 insertions(+), 1 deletion(-)

diff --git a/hw/display/qxl.c b/hw/display/qxl.c
index da8fd5a40a..c8ce5781e0 100644
--- a/hw/display/qxl.c
+++ b/hw/display/qxl.c
@@ -276,7 +276,8 @@ static void qxl_spice_monitors_config_async(PCIQXLDevice 
*qxl, int replay)
 QXL_COOKIE_TYPE_POST_LOAD_MONITORS_CONFIG,
 0));
 } else {
-#if SPICE_SERVER_VERSION >= 0x000c06 /* release 0.12.6 */
+/* >= release 0.12.6, < release 0.14.2 */
+#if SPICE_SERVER_VERSION >= 0x000c06 && SPICE_SERVER_VERSION < 0x000e02
 if (qxl->max_outputs) {
 spice_qxl_set_max_monitors(>ssd.qxl, qxl->max_outputs);
 }
@@ -2188,6 +2189,17 @@ static void qxl_realize_common(PCIQXLDevice *qxl, Error 
**errp)
SPICE_INTERFACE_QXL_MAJOR, SPICE_INTERFACE_QXL_MINOR);
 return;
 }
+
+#if SPICE_SERVER_VERSION >= 0x000e02 /* release 0.14.2 */
+char device_address[256] = "";
+if (qemu_spice_fill_device_address(qxl->vga.con, device_address, 256)) {
+spice_qxl_set_device_info(>ssd.qxl,
+  device_address,
+  0,
+  qxl->max_outputs);
+}
+#endif
+
 qemu_add_vm_change_state_handler(qxl_vm_change_state_handler, qxl);
 
 qxl->update_irq = qemu_bh_new(qxl_update_irq_bh, qxl);
diff --git a/include/ui/spice-display.h b/include/ui/spice-display.h
index 87a84a59d4..53c3612c32 100644
--- a/include/ui/spice-display.h
+++ b/include/ui/spice-display.h
@@ -179,3 +179,7 @@ void qemu_spice_wakeup(SimpleSpiceDisplay *ssd);
 void qemu_spice_display_start(void);
 void qemu_spice_display_stop(void);
 int qemu_spice_display_is_running(SimpleSpiceDisplay *ssd);
+
+bool qemu_spice_fill_device_address(QemuConsole *con,
+char *device_address,
+size_t size);
diff --git a/ui/spice-core.c b/ui/spice-core.c
index a40fb2c00d..37fae3c424 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -34,6 +34,7 @@
 #include "qemu/option.h"
 #include "migration/misc.h"
 #include "hw/hw.h"
+#include "hw/pci/pci_bus.h"
 #include "ui/spice-display.h"
 
 /* core bits */
@@ -863,6 +864,56 @@ bool qemu_spice_have_display_interface(QemuConsole *con)
 return false;
 }
 
+/*
+ * Recursively (in reverse order) appends addresses of PCI devices as it moves
+ * up in the PCI hierarchy.
+ *
+ * @returns true on success, false when the buffer wasn't large enough
+ */
+static bool append_pci_address(char *buf, size_t buf_size, const PCIDevice 
*pci)
+{
+PCIBus *bus = pci_get_bus(pci);
+/*
+ * equivalent to if (!pci_bus_is_root(bus)), but the function is not built
+ * with PCI_CONFIG=n, avoid using an #ifdef by checking directly
+ */
+if (bus->parent_dev != NULL) {
+append_pci_address(buf, buf_size, bus->parent_dev);
+}
+
+size_t len = strlen(buf);
+ssize_t written = snprintf(buf + len, buf_size - len, "/%02x.%x",
+PCI_SLOT(pci->devfn), PCI_FUNC(pci->devfn));
+
+return written > 0 && written < buf_size - len;
+}
+
+bool qemu_spice_fill_device_address(QemuConsole *con,
+char *device_address,
+size_t size)
+{
+DeviceState *dev = DEVICE(object_property_get_link(OBJECT(con),
+   "device",
+   _abort));
+PCIDevice *pci = (PCIDevice *) object_dynamic_cast(OBJECT(dev),
+   TYPE_PCI_DEVICE);
+
+if (pci == NULL) {
+warn_report("Setting device address of a display device to SPICE: "
+"Not a PCI device.");
+return false;
+}
+
+strncpy(device_address, "pci/", size);
+if (!append_pci_address(device_address, size, pci)) {
+warn_report("Setting device address of a display device 

[Spice-devel] [PATCH v4] spice: set device address and device display ID in QXL interface

2019-02-15 Thread Lukáš Hrázký
Calls the new SPICE QXL interface function spice_qxl_set_device_info to
set the hardware address of the graphics device represented by the QXL
interface (e.g. a PCI path) and the device display IDs (the IDs of the
device's monitors that belong to this QXL interface).

Also stops using the deprecated spice_qxl_set_max_monitors, the new
interface function replaces it.

Signed-off-by: Lukáš Hrázký 
---
Hi,

Changes since v3:
* Fix comments according to patchew check script.

Cheers,
Lukas


 hw/display/qxl.c   | 14 ++-
 include/ui/spice-display.h |  4 
 ui/spice-core.c| 49 ++
 ui/spice-display.c | 11 +
 4 files changed, 77 insertions(+), 1 deletion(-)

diff --git a/hw/display/qxl.c b/hw/display/qxl.c
index da8fd5a40a..c8ce5781e0 100644
--- a/hw/display/qxl.c
+++ b/hw/display/qxl.c
@@ -276,7 +276,8 @@ static void qxl_spice_monitors_config_async(PCIQXLDevice 
*qxl, int replay)
 QXL_COOKIE_TYPE_POST_LOAD_MONITORS_CONFIG,
 0));
 } else {
-#if SPICE_SERVER_VERSION >= 0x000c06 /* release 0.12.6 */
+/* >= release 0.12.6, < release 0.14.2 */
+#if SPICE_SERVER_VERSION >= 0x000c06 && SPICE_SERVER_VERSION < 0x000e02
 if (qxl->max_outputs) {
 spice_qxl_set_max_monitors(>ssd.qxl, qxl->max_outputs);
 }
@@ -2188,6 +2189,17 @@ static void qxl_realize_common(PCIQXLDevice *qxl, Error 
**errp)
SPICE_INTERFACE_QXL_MAJOR, SPICE_INTERFACE_QXL_MINOR);
 return;
 }
+
+#if SPICE_SERVER_VERSION >= 0x000e02 /* release 0.14.2 */
+char device_address[256] = "";
+if (qemu_spice_fill_device_address(qxl->vga.con, device_address, 256)) {
+spice_qxl_set_device_info(>ssd.qxl,
+  device_address,
+  0,
+  qxl->max_outputs);
+}
+#endif
+
 qemu_add_vm_change_state_handler(qxl_vm_change_state_handler, qxl);
 
 qxl->update_irq = qemu_bh_new(qxl_update_irq_bh, qxl);
diff --git a/include/ui/spice-display.h b/include/ui/spice-display.h
index 87a84a59d4..53c3612c32 100644
--- a/include/ui/spice-display.h
+++ b/include/ui/spice-display.h
@@ -179,3 +179,7 @@ void qemu_spice_wakeup(SimpleSpiceDisplay *ssd);
 void qemu_spice_display_start(void);
 void qemu_spice_display_stop(void);
 int qemu_spice_display_is_running(SimpleSpiceDisplay *ssd);
+
+bool qemu_spice_fill_device_address(QemuConsole *con,
+char *device_address,
+size_t size);
diff --git a/ui/spice-core.c b/ui/spice-core.c
index a40fb2c00d..4b501d485e 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -34,6 +34,7 @@
 #include "qemu/option.h"
 #include "migration/misc.h"
 #include "hw/hw.h"
+#include "hw/pci/pci_bus.h"
 #include "ui/spice-display.h"
 
 /* core bits */
@@ -863,6 +864,54 @@ bool qemu_spice_have_display_interface(QemuConsole *con)
 return false;
 }
 
+/*
+ * Recursively (in reverse order) appends addresses of PCI devices as it moves
+ * up in the PCI hierarchy.
+ *
+ * @returns true on success, false when the buffer wasn't large enough
+ */
+static bool append_pci_address(char *buf, size_t buf_size, const PCIDevice 
*pci)
+{
+PCIBus *bus = pci_get_bus(pci);
+/* equivalent to if (!pci_bus_is_root(bus)), but the function is not built
+   with PCI_CONFIG=n, avoid using an #ifdef by checking directly */
+if (bus->parent_dev != NULL) {
+append_pci_address(buf, buf_size, bus->parent_dev);
+}
+
+size_t len = strlen(buf);
+ssize_t written = snprintf(buf + len, buf_size - len, "/%02x.%x",
+PCI_SLOT(pci->devfn), PCI_FUNC(pci->devfn));
+
+return written > 0 && written < buf_size - len;
+}
+
+bool qemu_spice_fill_device_address(QemuConsole *con,
+char *device_address,
+size_t size)
+{
+DeviceState *dev = DEVICE(object_property_get_link(OBJECT(con),
+   "device",
+   _abort));
+PCIDevice *pci = (PCIDevice *) object_dynamic_cast(OBJECT(dev),
+   TYPE_PCI_DEVICE);
+
+if (pci == NULL) {
+warn_report("Setting device address of a display device to SPICE: "
+"Not a PCI device.");
+return false;
+}
+
+strncpy(device_address, "pci/", size);
+if (!append_pci_address(device_address, size, pci)) {
+warn_report("Setting device address of a display device to SPICE: "
+"Too many PCI devices in the chain.");
+return false;
+}
+
+return true;
+}
+
 int qemu_

[Spice-devel] [PATCH] spice: set device address and device display ID in QXL interface

2019-02-11 Thread Lukáš Hrázký
Calls the new SPICE QXL interface function spice_qxl_set_device_info to
set the hardware address of the graphics device represented by the QXL
interface (e.g. a PCI path) and the device display IDs (the IDs of the
device's monitors that belong to this QXL interface).

Also stops using the deprecated spice_qxl_set_max_monitors, the new
interface function replaces it.

Signed-off-by: Lukáš Hrázký 
---
Hi,

I've fixed the undefined reference by checking the parent_dev pointer
directly instead of through pci_bus_is_root(), that was the only
function needed that's not built with PCI_CONFIG=n. Added a comment to
explain it too.

Changes since v2:
* Check the parent_dev pointer directly instead of calling
  pci_bus_is_root().

Cheers,
Lukas


 hw/display/qxl.c   | 14 ++-
 include/ui/spice-display.h |  4 
 ui/spice-core.c| 49 ++
 ui/spice-display.c | 11 +
 4 files changed, 77 insertions(+), 1 deletion(-)

diff --git a/hw/display/qxl.c b/hw/display/qxl.c
index da8fd5a40a..c8ce5781e0 100644
--- a/hw/display/qxl.c
+++ b/hw/display/qxl.c
@@ -276,7 +276,8 @@ static void qxl_spice_monitors_config_async(PCIQXLDevice 
*qxl, int replay)
 QXL_COOKIE_TYPE_POST_LOAD_MONITORS_CONFIG,
 0));
 } else {
-#if SPICE_SERVER_VERSION >= 0x000c06 /* release 0.12.6 */
+/* >= release 0.12.6, < release 0.14.2 */
+#if SPICE_SERVER_VERSION >= 0x000c06 && SPICE_SERVER_VERSION < 0x000e02
 if (qxl->max_outputs) {
 spice_qxl_set_max_monitors(>ssd.qxl, qxl->max_outputs);
 }
@@ -2188,6 +2189,17 @@ static void qxl_realize_common(PCIQXLDevice *qxl, Error 
**errp)
SPICE_INTERFACE_QXL_MAJOR, SPICE_INTERFACE_QXL_MINOR);
 return;
 }
+
+#if SPICE_SERVER_VERSION >= 0x000e02 /* release 0.14.2 */
+char device_address[256] = "";
+if (qemu_spice_fill_device_address(qxl->vga.con, device_address, 256)) {
+spice_qxl_set_device_info(>ssd.qxl,
+  device_address,
+  0,
+  qxl->max_outputs);
+}
+#endif
+
 qemu_add_vm_change_state_handler(qxl_vm_change_state_handler, qxl);
 
 qxl->update_irq = qemu_bh_new(qxl_update_irq_bh, qxl);
diff --git a/include/ui/spice-display.h b/include/ui/spice-display.h
index 87a84a59d4..53c3612c32 100644
--- a/include/ui/spice-display.h
+++ b/include/ui/spice-display.h
@@ -179,3 +179,7 @@ void qemu_spice_wakeup(SimpleSpiceDisplay *ssd);
 void qemu_spice_display_start(void);
 void qemu_spice_display_stop(void);
 int qemu_spice_display_is_running(SimpleSpiceDisplay *ssd);
+
+bool qemu_spice_fill_device_address(QemuConsole *con,
+char *device_address,
+size_t size);
diff --git a/ui/spice-core.c b/ui/spice-core.c
index a40fb2c00d..a2f8e15030 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -34,6 +34,7 @@
 #include "qemu/option.h"
 #include "migration/misc.h"
 #include "hw/hw.h"
+#include "hw/pci/pci_bus.h"
 #include "ui/spice-display.h"
 
 /* core bits */
@@ -863,6 +864,54 @@ bool qemu_spice_have_display_interface(QemuConsole *con)
 return false;
 }
 
+/*
+ * Recursively (in reverse order) appends addresses of PCI devices as it moves
+ * up in the PCI hierarchy.
+ *
+ * @returns true on success, false when the buffer wasn't large enough
+ */
+static bool append_pci_address(char *buf, size_t buf_size, const PCIDevice 
*pci)
+{
+PCIBus *bus = pci_get_bus(pci);
+// equivalent to if (!pci_bus_is_root(bus)), but the function is not built
+// with PCI_CONFIG=n, avoid using an #ifdef by checking directly
+if (bus->parent_dev != NULL) {
+append_pci_address(buf, buf_size, bus->parent_dev);
+}
+
+size_t len = strlen(buf);
+ssize_t written = snprintf(buf + len, buf_size - len, "/%02x.%x",
+PCI_SLOT(pci->devfn), PCI_FUNC(pci->devfn));
+
+return written > 0 && written < buf_size - len;
+}
+
+bool qemu_spice_fill_device_address(QemuConsole *con,
+char *device_address,
+size_t size)
+{
+DeviceState *dev = DEVICE(object_property_get_link(OBJECT(con),
+   "device",
+   _abort));
+PCIDevice *pci = (PCIDevice *) object_dynamic_cast(OBJECT(dev),
+   TYPE_PCI_DEVICE);
+
+if (pci == NULL) {
+warn_report("Setting device address of a display device to SPICE: "
+"Not a PCI device.");
+return false;
+}
+
+strncpy(device_address, "pci/", size);
+if (!append_pci_addre

Re: [Spice-devel] [PATCH spice-server] red-stream-device: Fix "make syntax-check"

2019-01-31 Thread Lukáš Hrázký
Hi,

On Thu, 2019-01-31 at 11:44 +0100, Christophe Fergeau wrote:
> On Wed, Jan 30, 2019 at 03:13:06PM +, Frediano Ziglio wrote:
> > Avoid using strncpy, considered not secure.
> > In this case a simple memcpy is used, we are going to terminate
> > the string in any case on the next line.
> > 
> > Signed-off-by: Frediano Ziglio 
> > ---
> >  server/red-stream-device.c | 6 +++---
> >  1 file changed, 3 insertions(+), 3 deletions(-)
> > 
> > diff --git a/server/red-stream-device.c b/server/red-stream-device.c
> > index 440b2689..2a210cc7 100644
> > --- a/server/red-stream-device.c
> > +++ b/server/red-stream-device.c
> > @@ -330,9 +330,9 @@ handle_msg_device_display_info(StreamDevice *dev, 
> > SpiceCharDeviceInstance *sin)
> >  return true;
> >  }
> >  
> > -strncpy(dev->device_display_info.device_address,
> > -(char*) display_info_msg->device_address,
> > -device_address_len);
> > +memcpy(dev->device_display_info.device_address,
> > +   (char*) display_info_msg->device_address,
> > +   device_address_len);
> 
> I'd use g_strlcpy instead, as by using memcpy, it's no longer obvious
> that display_info_msg->device_address is not expected to contain null
> bytes.

g_strlcpy requires the string to be terminated with a '\0', but you
can't rely on that as the data come from the network. It would mean
writing the zero to the received data buffer, which is not so nice.

Cheers,
Lukas

> Christophe
> ___
> Spice-devel mailing list
> Spice-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/spice-devel
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH spice-server] red-stream-device: Fix "make syntax-check"

2019-01-30 Thread Lukáš Hrázký
Just sent the same patch... oh well.

Acked-by: Lukáš Hrázký 


On Wed, 2019-01-30 at 15:13 +, Frediano Ziglio wrote:
> Avoid using strncpy, considered not secure.
> In this case a simple memcpy is used, we are going to terminate
> the string in any case on the next line.
> 
> Signed-off-by: Frediano Ziglio 
> ---
>  server/red-stream-device.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/server/red-stream-device.c b/server/red-stream-device.c
> index 440b2689..2a210cc7 100644
> --- a/server/red-stream-device.c
> +++ b/server/red-stream-device.c
> @@ -330,9 +330,9 @@ handle_msg_device_display_info(StreamDevice *dev, 
> SpiceCharDeviceInstance *sin)
>  return true;
>  }
>  
> -strncpy(dev->device_display_info.device_address,
> -(char*) display_info_msg->device_address,
> -device_address_len);
> +memcpy(dev->device_display_info.device_address,
> +   (char*) display_info_msg->device_address,
> +   device_address_len);
>  
>  // make sure the string is terminated
>  dev->device_display_info.device_address[device_address_len - 1] = '\0';
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH spice] red-stream-device: use memcpy instead of strncpy

2019-01-30 Thread Lukáš Hrázký
Signed-off-by: Lukáš Hrázký 
---
 server/red-stream-device.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/server/red-stream-device.c b/server/red-stream-device.c
index 440b2689..2a210cc7 100644
--- a/server/red-stream-device.c
+++ b/server/red-stream-device.c
@@ -330,9 +330,9 @@ handle_msg_device_display_info(StreamDevice *dev, 
SpiceCharDeviceInstance *sin)
 return true;
 }
 
-strncpy(dev->device_display_info.device_address,
-(char*) display_info_msg->device_address,
-device_address_len);
+memcpy(dev->device_display_info.device_address,
+   (char*) display_info_msg->device_address,
+   device_address_len);
 
 // make sure the string is terminated
 dev->device_display_info.device_address[device_address_len - 1] = '\0';
-- 
2.20.1

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH linux vdagent v5 0/7] Use the PCI addr and display ID

2019-01-29 Thread Lukáš Hrázký
For the series:

Acked-by: Lukáš Hrázký 


On Wed, 2019-01-23 at 16:18 -0600, Jonathon Jongsma wrote:
> This is a patch set that handles the PCI address and device dispay ID
> sent down to the agent by the server, and uses that to maintain a map
> for looking up a particular xrandr output for a given spice display id.
> 
> This patch series builds on the patch from Lukas titled "Receive the
> graphics_device_info message".
> 
> Changes in v5:
>  - more line length changes
>  - squashed last several patches into one
> 
> Changes in v4:
>  - rebased on Lukas's latest patch
>  - Added a new commit that fixes the cursor when using with mjpeg streaming.
>  - various small fixes from previous reviews (e.g. line length, etc)
> 
> Changes in v3:
>  - Fixed a bug where the X Display was not set properly and caused a
>crash
>  - moved call to vdagent_x11_send_daemon_guest_xorg_res() to outside the
>loop to avoid sending multiple times when more than one device is
>received. (Patch 9)
> 
> Changes in v2:
>  - Removed some ACKed and merged patches
>- Fix typo in comment
>- Fix confusion between output index and crtc index
>  - added a patch to send new display IDs when device info changes
>  - multiple changes from review
>- factored out function find_device_at_pci_address()
>- No more initializing X/XRandr
>- removed goto
>- improved logging
>- etc.
> 
> 
> Jonathon Jongsma (7):
>   Add lookup_xrand_output_for_device_info()
>   Look up and store xrandr output in display map
>   Make clearer distinctions between output ids
>   Use guest output map to determine xrandr output
>   Factor a function out of get_current_mon_config()
>   Use new function in vdagent_x11_send_daemon_guest_xorg_res()
>   Send display_id down to the vdagentd daemon
> 
>  Makefile.am   |  14 ++
>  configure.ac  |   1 +
>  src/vdagent/device-info.c | 506 ++
>  src/vdagent/device-info.h |  30 +++
>  src/vdagent/x11-priv.h|   2 +-
>  src/vdagent/x11-randr.c   | 348 +-
>  src/vdagent/x11.c |  20 +-
>  src/vdagentd-proto.h  |   1 +
>  src/vdagentd/uinput.c |  23 +-
>  tests/test-device-info.c  | 262 
>  10 files changed, 1073 insertions(+), 134 deletions(-)
>  create mode 100644 src/vdagent/device-info.c
>  create mode 100644 src/vdagent/device-info.h
>  create mode 100644 tests/test-device-info.c
> 
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH spice-streaming-agent v5 5/6] Send the GraphicsDeviceInfo to the server

2019-01-29 Thread Lukáš Hrázký
Adds serialization of the GraphicsDeviceInfo message and sends it to the
server when it starts to stream.

Signed-off-by: Lukáš Hrázký 
Acked-by: Jonathon Jongsma 
---
 configure.ac  |  2 +-
 src/spice-streaming-agent.cpp | 65 ++-
 2 files changed, 57 insertions(+), 10 deletions(-)

diff --git a/configure.ac b/configure.ac
index fd18efe..c259f7e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -30,7 +30,7 @@ PKG_PROG_PKG_CONFIG
 dnl =
 dnl Check deps
 
-SPICE_PROTOCOL_MIN_VER=0.12.14
+SPICE_PROTOCOL_MIN_VER=0.12.16
 PKG_CHECK_MODULES([SPICE_PROTOCOL], [spice-protocol >= 
$SPICE_PROTOCOL_MIN_VER])
 AC_SUBST([SPICE_PROTOCOL_MIN_VER])
 
diff --git a/src/spice-streaming-agent.cpp b/src/spice-streaming-agent.cpp
index cd23111..9507a54 100644
--- a/src/spice-streaming-agent.cpp
+++ b/src/spice-streaming-agent.cpp
@@ -31,6 +31,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -93,6 +94,39 @@ public:
 }
 };
 
+class DeviceDisplayInfoMessage : public 
OutboundMessage
+{
+public:
+DeviceDisplayInfoMessage(const DeviceDisplayInfo ) : 
OutboundMessage(info) {}
+
+static size_t size(const DeviceDisplayInfo )
+{
+return sizeof(PayloadType) +
+   std::min(info.device_address.length(), 
static_cast(max_device_address_len)) +
+   1;
+}
+
+void write_message_body(StreamPort _port, const DeviceDisplayInfo 
)
+{
+std::string device_address = info.device_address;
+if (device_address.length() > max_device_address_len) {
+syslog(LOG_WARNING,
+   "device address of stream id %u is longer than %u bytes, 
trimming.",
+   info.stream_id, max_device_address_len);
+device_address = device_address.substr(0, max_device_address_len);
+}
+StreamMsgDeviceDisplayInfo strm_msg_info{};
+strm_msg_info.stream_id = info.stream_id;
+strm_msg_info.device_display_id = info.device_display_id;
+strm_msg_info.device_address_len = device_address.length() + 1;
+stream_port.write(_msg_info, sizeof(strm_msg_info));
+stream_port.write(device_address.c_str(), device_address.length() + 1);
+}
+
+private:
+static constexpr uint32_t max_device_address_len = 255;
+};
+
 static bool streaming_requested = false;
 static bool quit_requested = false;
 static std::set client_codecs;
@@ -217,17 +251,30 @@ do_capture(StreamPort _port, FrameLog _log)
 throw std::runtime_error("cannot find a suitable capture system");
 }
 
+std::vector display_info;
 try {
-std::vector display_info = 
capture->get_device_display_info();
-syslog(LOG_DEBUG, "Got device info of %lu devices from the 
plugin", display_info.size());
-for (const auto  : display_info) {
-syslog(LOG_DEBUG, "   id %u: device address %s, device display 
id: %u",
-   info.stream_id,
-   info.device_address.c_str(),
-   info.device_display_id);
-}
+display_info = capture->get_device_display_info();
 } catch (const Error ) {
-syslog(LOG_ERR, "Error while getting device info: %s", e.what());
+syslog(LOG_ERR, "Error while getting device display info: %s", 
e.what());
+}
+
+syslog(LOG_DEBUG, "Got device info of %zu devices from the plugin", 
display_info.size());
+for (const auto  : display_info) {
+syslog(LOG_DEBUG, "   stream id %u: device address: %s, device 
display id: %u",
+   info.stream_id,
+   info.device_address.c_str(),
+   info.device_display_id);
+}
+
+if (display_info.size() > 0) {
+if (display_info.size() > 1) {
+syslog(LOG_WARNING, "Warning: the Frame Capture plugin 
returned device display "
+   "info for more than one display device, but we 
currently only support "
+   "a single device. Sending information for first device 
to the server.");
+}
+stream_port.send(display_info[0]);
+} else {
+syslog(LOG_ERR, "Empty device display info from the plugin");
 }
 
 while (!quit_requested && streaming_requested) {
-- 
2.20.1

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH spice-streaming-agent v4 4/6] Interface + implementation of getting device display info

2019-01-28 Thread Lukáš Hrázký
Adds an interface method to the FrameCapture class to get the device
display info (device address and device display id) for each display of
the graphics device that is captured.

Also adds functions to the API implementing this functionality for X11
in variants with and without DRM (the non-DRM version is rather limited
and may not work for more complex setups) as well as some helper
functions to make it easier for plugins to implement this and avoid code
duplication.

Implements the new interface method for the two built-in plugins
(mjpeg-fallback and gst-plugin).

Signed-off-by: Lukáš Hrázký 
Acked-by: Jonathon Jongsma 
---
 configure.ac  |   2 +
 include/spice-streaming-agent/Makefile.am |   2 +
 .../spice-streaming-agent/display-info.hpp|  52 +++
 .../spice-streaming-agent/frame-capture.hpp   |  13 +
 .../x11-display-info.hpp  |  57 
 src/Makefile.am   |   7 +
 src/display-info.cpp  | 101 ++
 src/gst-plugin.cpp|  14 +
 src/mjpeg-fallback.cpp|  17 +-
 src/spice-streaming-agent.cpp |  13 +
 src/unittests/Makefile.am |   6 +
 src/utils.cpp |  46 +++
 src/utils.hpp |   4 +
 src/x11-display-info.cpp  | 302 ++
 14 files changed, 634 insertions(+), 2 deletions(-)
 create mode 100644 include/spice-streaming-agent/display-info.hpp
 create mode 100644 include/spice-streaming-agent/x11-display-info.hpp
 create mode 100644 src/display-info.cpp
 create mode 100644 src/utils.cpp
 create mode 100644 src/x11-display-info.cpp

diff --git a/configure.ac b/configure.ac
index e66e6d8..fd18efe 100644
--- a/configure.ac
+++ b/configure.ac
@@ -34,8 +34,10 @@ SPICE_PROTOCOL_MIN_VER=0.12.14
 PKG_CHECK_MODULES([SPICE_PROTOCOL], [spice-protocol >= 
$SPICE_PROTOCOL_MIN_VER])
 AC_SUBST([SPICE_PROTOCOL_MIN_VER])
 
+PKG_CHECK_MODULES(DRM, libdrm)
 PKG_CHECK_MODULES(X11, x11)
 PKG_CHECK_MODULES(XFIXES, xfixes)
+PKG_CHECK_MODULES(XRANDR, xrandr)
 
 PKG_CHECK_MODULES(JPEG, libjpeg, , [
 AC_CHECK_LIB(jpeg, jpeg_destroy_decompress,
diff --git a/include/spice-streaming-agent/Makefile.am 
b/include/spice-streaming-agent/Makefile.am
index bcd679b..96c1a57 100644
--- a/include/spice-streaming-agent/Makefile.am
+++ b/include/spice-streaming-agent/Makefile.am
@@ -1,8 +1,10 @@
 NULL =
 public_includedir = $(includedir)/spice-streaming-agent
 public_include_HEADERS = \
+   display-info.hpp \
error.hpp \
frame-capture.hpp \
plugin.hpp \
+   x11-display-info.hpp \
$(NULL)
 
diff --git a/include/spice-streaming-agent/display-info.hpp 
b/include/spice-streaming-agent/display-info.hpp
new file mode 100644
index 000..f16212b
--- /dev/null
+++ b/include/spice-streaming-agent/display-info.hpp
@@ -0,0 +1,52 @@
+/* \copyright
+ * Copyright 2018 Red Hat Inc. All rights reserved.
+ */
+
+#ifndef SPICE_STREAMING_AGENT_DISPLAY_INFO_HPP
+#define SPICE_STREAMING_AGENT_DISPLAY_INFO_HPP
+
+#include 
+#include 
+
+
+namespace spice __attribute__ ((visibility ("default"))) {
+namespace streaming_agent {
+
+/**
+ * Lists graphics cards listed in the DRM sybsystem in /sys/class/drm.
+ * Throws an instance of Error in case of an I/O error.
+ *
+ * @return a vector of paths of all graphics cards present in /sys/class/drm
+ */
+std::vector list_cards();
+
+/**
+ * Reads a single number in hex format from a file.
+ * Throws an instance of Error in case of an I/O or parsing error.
+ *
+ * @param path the path to the file
+ * @return the number parsed from the file
+ */
+uint32_t read_hex_number_from_file(const std::string );
+
+/**
+ * Resolves any symlinks and then extracts the PCI path from the canonical path
+ * to a card. Returns the path in the following format:
+ * "pci//./.../."
+ *
+ *  is the PCI domain, followed by . of any PCI bridges
+ * in the chain leading to the device. The last . is the
+ * graphics device. All of , ,  are hexadecimal numbers
+ * with the following number of digits:
+ *   : 4
+ *   : 2
+ *   : 1
+ *
+ * @param device_path the path to the card
+ * @return the device address
+ */
+std::string get_device_address(const std::string _path);
+
+}} // namespace spice::streaming_agent
+
+#endif // SPICE_STREAMING_AGENT_DISPLAY_INFO_HPP
diff --git a/include/spice-streaming-agent/frame-capture.hpp 
b/include/spice-streaming-agent/frame-capture.hpp
index 51a2987..c244fb9 100644
--- a/include/spice-streaming-agent/frame-capture.hpp
+++ b/include/spice-streaming-agent/frame-capture.hpp
@@ -6,7 +6,11 @@
  */
 #ifndef SPICE_STREAMING_AGENT_FRAME_CAPTURE_HPP
 #define SPICE_STREAMING_AGENT_FRAME_CAPTURE_HPP
+
+#include 
 #include 
+#include 
+#include 
 
 #include 
 
@@ -29,6 +33,13 @@ struct FrameInfo
 bool stream_start;
 };
 
+struct DeviceDisplayInfo
+{
+uint32_t stre

[Spice-devel] [PATCH spice v4 2/6] Receive the GraphicsDeviceInfo message from the streaming agent

2019-01-28 Thread Lukáš Hrázký
Receives the GraphicsDeviceInfo message from the streaming agent and
stores the data in a list on the streaming device.

Signed-off-by: Lukáš Hrázký 
---
 server/display-limits.h|  3 ++
 server/red-qxl.c   |  2 +-
 server/red-stream-device.c | 78 +-
 server/red-stream-device.h |  8 
 4 files changed, 88 insertions(+), 3 deletions(-)

diff --git a/server/display-limits.h b/server/display-limits.h
index e875149b..d79d3211 100644
--- a/server/display-limits.h
+++ b/server/display-limits.h
@@ -25,4 +25,7 @@
 /** Maximum number of streams created by spice-server */
 #define NUM_STREAMS 50
 
+/** Maximum length of the device address string */
+#define MAX_DEVICE_ADDRESS_LEN 256
+
 #endif /* DISPLAY_LIMITS_H_ */
diff --git a/server/red-qxl.c b/server/red-qxl.c
index 7f8ac35d..37f3d9c8 100644
--- a/server/red-qxl.c
+++ b/server/red-qxl.c
@@ -37,11 +37,11 @@
 #include "dispatcher.h"
 #include "red-parse-qxl.h"
 #include "red-channel-client.h"
+#include "display-limits.h"
 
 #include "red-qxl.h"
 
 
-#define MAX_DEVICE_ADDRESS_LEN 256
 #define MAX_MONITORS_COUNT 16
 
 struct QXLState {
diff --git a/server/red-stream-device.c b/server/red-stream-device.c
index 3b553510..38df8e4c 100644
--- a/server/red-stream-device.c
+++ b/server/red-stream-device.c
@@ -39,6 +39,7 @@ struct StreamDevice {
 StreamMsgCapabilities capabilities;
 StreamMsgCursorSet cursor_set;
 StreamMsgCursorMove cursor_move;
+StreamMsgDeviceDisplayInfo device_display_info;
 uint8_t buf[STREAM_MSG_CAPABILITIES_MAX_BYTES];
 } *msg;
 uint32_t msg_pos;
@@ -51,6 +52,7 @@ struct StreamDevice {
 CursorChannel *cursor_channel;
 SpiceTimer *close_timer;
 uint32_t frame_mmtime;
+StreamDeviceDisplayInfo device_display_info;
 };
 
 struct StreamDeviceClass {
@@ -66,8 +68,8 @@ static void char_device_set_state(RedCharDevice *char_dev, 
int state);
 typedef bool StreamMsgHandler(StreamDevice *dev, SpiceCharDeviceInstance *sin)
 SPICE_GNUC_WARN_UNUSED_RESULT;
 
-static StreamMsgHandler handle_msg_format, handle_msg_data, 
handle_msg_cursor_set,
-handle_msg_cursor_move, handle_msg_capabilities;
+static StreamMsgHandler handle_msg_format, handle_msg_device_display_info, 
handle_msg_data,
+handle_msg_cursor_set, handle_msg_cursor_move, handle_msg_capabilities;
 
 static bool handle_msg_invalid(StreamDevice *dev, SpiceCharDeviceInstance *sin,
const char *error_msg) 
SPICE_GNUC_WARN_UNUSED_RESULT;
@@ -150,6 +152,13 @@ stream_device_partial_read(StreamDevice *dev, 
SpiceCharDeviceInstance *sin)
 handled = handle_msg_format(dev, sin);
 }
 break;
+case STREAM_TYPE_DEVICE_DISPLAY_INFO:
+if (dev->hdr.size > sizeof(StreamMsgDeviceDisplayInfo) + 
MAX_DEVICE_ADDRESS_LEN) {
+handled = handle_msg_invalid(dev, sin, "StreamMsgDeviceDisplayInfo 
too large");
+} else {
+handled = handle_msg_device_display_info(dev, sin);
+}
+break;
 case STREAM_TYPE_DATA:
 if (dev->hdr.size > 32*1024*1024) {
 handled = handle_msg_invalid(dev, sin, "STREAM_DATA too large");
@@ -275,6 +284,71 @@ handle_msg_format(StreamDevice *dev, 
SpiceCharDeviceInstance *sin)
 return true;
 }
 
+static bool
+handle_msg_device_display_info(StreamDevice *dev, SpiceCharDeviceInstance *sin)
+{
+SpiceCharDeviceInterface *sif = spice_char_device_get_interface(sin);
+
+if (spice_extra_checks) {
+spice_assert(dev->hdr_pos >= sizeof(StreamDevHeader));
+spice_assert(dev->hdr.type == STREAM_TYPE_DEVICE_DISPLAY_INFO);
+}
+
+if (dev->msg_len < dev->hdr.size) {
+dev->msg = g_realloc(dev->msg, dev->hdr.size);
+dev->msg_len = dev->hdr.size;
+}
+
+/* read from device */
+ssize_t n = sif->read(sin, dev->msg->buf + dev->msg_pos, dev->hdr.size - 
dev->msg_pos);
+if (n <= 0) {
+return dev->msg_pos == dev->hdr.size;
+}
+
+dev->msg_pos += n;
+if (dev->msg_pos != dev->hdr.size) { /* some bytes are still missing */
+return false;
+}
+
+StreamMsgDeviceDisplayInfo *display_info_msg = 
>msg->device_display_info;
+
+size_t device_address_len = 
GUINT32_FROM_LE(display_info_msg->device_address_len);
+if (device_address_len > MAX_DEVICE_ADDRESS_LEN) {
+g_warning("Received a device address longer than %u (%zu), "
+  "will be truncated!", MAX_DEVICE_ADDRESS_LEN, 
device_address_len);
+device_address_len = sizeof(dev->device_display_info.device_address);
+}
+
+if (device_address_len == 0) {
+g_warning("Zero length device_address in  DeviceDisplayInfo message, 
ignoring.");
+return true;
+}
+
+if (display_info_msg-&g

[Spice-devel] [PATCH vd_agent v4 6/6] Receive the graphics_device_info message

2019-01-28 Thread Lukáš Hrázký
The graphics_device_info message contains the device display ID
information (device address and device display ID). Stores the data in a
hash table in vdagent.

Signed-off-by: Lukáš Hrázký 
Acked-by: Jonathon Jongsma 
---
 configure.ac |  2 +-
 src/vdagent/vdagent.c|  3 ++
 src/vdagent/x11-priv.h   |  1 +
 src/vdagent/x11-randr.c  | 65 
 src/vdagent/x11.c| 13 
 src/vdagent/x11.h|  1 +
 src/vdagentd-proto-strings.h |  1 +
 src/vdagentd-proto.h |  1 +
 src/vdagentd/vdagentd.c  | 16 +
 9 files changed, 102 insertions(+), 1 deletion(-)

diff --git a/configure.ac b/configure.ac
index 7cb44db..7faebfd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -102,7 +102,7 @@ AC_ARG_ENABLE([static-uinput],
 
 PKG_CHECK_MODULES([GLIB2], [glib-2.0 >= 2.34])
 PKG_CHECK_MODULES(X, [xfixes xrandr >= 1.3 xinerama x11])
-PKG_CHECK_MODULES(SPICE, [spice-protocol >= 0.12.13])
+PKG_CHECK_MODULES(SPICE, [spice-protocol >= 0.12.16])
 PKG_CHECK_MODULES(ALSA, [alsa >= 1.0.22])
 PKG_CHECK_MODULES([DBUS], [dbus-1])
 
diff --git a/src/vdagent/vdagent.c b/src/vdagent/vdagent.c
index 90247f9..7cc6287 100644
--- a/src/vdagent/vdagent.c
+++ b/src/vdagent/vdagent.c
@@ -240,6 +240,9 @@ static void daemon_read_complete(struct udscs_connection 
**connp,
   ((VDAgentFileXferDataMessage 
*)data)->id);
 }
 break;
+case VDAGENTD_GRAPHICS_DEVICE_INFO:
+vdagent_x11_handle_graphics_device_info(agent->x11, data, 
header->size);
+break;
 case VDAGENTD_CLIENT_DISCONNECTED:
 vdagent_clipboards_release_all(agent->clipboards);
 if (vdagent_finalize_file_xfer(agent)) {
diff --git a/src/vdagent/x11-priv.h b/src/vdagent/x11-priv.h
index b31b0a5..0e954cf 100644
--- a/src/vdagent/x11-priv.h
+++ b/src/vdagent/x11-priv.h
@@ -139,6 +139,7 @@ struct vdagent_x11 {
 int xrandr_minor;
 int has_xinerama;
 int dont_send_guest_xorg_res;
+GHashTable *graphics_display_infos;
 };
 
 extern int (*vdagent_x11_prev_error_handler)(Display *, XErrorEvent *);
diff --git a/src/vdagent/x11-randr.c b/src/vdagent/x11-randr.c
index 192b888..405fca9 100644
--- a/src/vdagent/x11-randr.c
+++ b/src/vdagent/x11-randr.c
@@ -727,6 +727,71 @@ static void dump_monitors_config(struct vdagent_x11 *x11,
 }
 }
 
+typedef struct GraphicsDisplayInfo {
+char device_address[256];
+uint32_t device_display_id;
+} GraphicsDisplayInfo;
+
+// handle the device info message from the server. This will allow us to
+// maintain a mapping from spice display id to xrandr output
+void vdagent_x11_handle_graphics_device_info(struct vdagent_x11 *x11, uint8_t 
*data, size_t size)
+{
+VDAgentGraphicsDeviceInfo *graphics_device_info = 
(VDAgentGraphicsDeviceInfo *)data;
+VDAgentDeviceDisplayInfo *device_display_info = 
graphics_device_info->display_info;
+
+void *buffer_end = data + size;
+
+syslog(LOG_INFO, "Received Graphics Device Info:");
+
+for (size_t i = 0; i < graphics_device_info->count; ++i) {
+if ((void*) device_display_info > buffer_end ||
+(void*) (_display_info->device_address +
+device_display_info->device_address_len) > buffer_end) {
+syslog(LOG_ERR, "Malformed graphics_display_info message, "
+   "extends beyond the end of the buffer");
+break;
+}
+
+GraphicsDisplayInfo *value = g_malloc(sizeof(GraphicsDisplayInfo));
+value->device_address[0] = '\0';
+
+size_t device_address_len = device_display_info->device_address_len;
+if (device_address_len > sizeof(value->device_address)) {
+syslog(LOG_ERR, "Received a device address longer than %lu, "
+   "will be truncated!", device_address_len);
+device_address_len = sizeof(value->device_address);
+}
+
+strncpy(value->device_address,
+(char*) device_display_info->device_address,
+device_address_len);
+
+if (device_address_len > 0) {
+value->device_address[device_address_len - 1] = '\0';  // make 
sure the string is terminated
+} else {
+syslog(LOG_WARNING, "Zero length device_address received for 
channel_id: %u, monitor_id: %u",
+   device_display_info->channel_id, 
device_display_info->monitor_id);
+}
+
+value->device_display_id = device_display_info->device_display_id;
+
+syslog(LOG_INFO, "   channel_id: %u monitor_id: %u device_address: %s, 
"
+   "device_display_id: %u",
+   device_display_info->channel_id,
+   device_display_info->monitor_id,
+   value->device_address,
+  

[Spice-devel] [PATCH spice v4 1/6] Send the graphics device info to the vd_agent

2019-01-28 Thread Lukáš Hrázký
Sends the device address and device display IDs to the vdagent. The
message is sent either in reaction to the SPICE_MSGC_MAIN_AGENT_START
message or when the graphics device info changes.

Signed-off-by: Lukáš Hrázký 
Acked-by: Jonathon Jongsma 
---
 configure.ac  |  2 +-
 meson.build   |  2 +-
 server/red-qxl.c  | 20 +
 server/red-qxl.h  |  3 ++
 server/reds-private.h |  1 +
 server/reds.c | 67 +++
 server/reds.h |  1 +
 7 files changed, 94 insertions(+), 2 deletions(-)

diff --git a/configure.ac b/configure.ac
index 903993a1..fa79af7f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -161,7 +161,7 @@ AS_IF([test x"$have_smartcard" = "xyes"], [
 AS_VAR_APPEND([SPICE_REQUIRES], [" libcacard >= 0.1.2"])
 ])
 
-SPICE_PROTOCOL_MIN_VER=0.12.15
+SPICE_PROTOCOL_MIN_VER=0.12.16
 PKG_CHECK_MODULES([SPICE_PROTOCOL], [spice-protocol >= 
$SPICE_PROTOCOL_MIN_VER])
 AC_SUBST([SPICE_PROTOCOL_MIN_VER])
 
diff --git a/meson.build b/meson.build
index 3184a6f5..5f402a5f 100644
--- a/meson.build
+++ b/meson.build
@@ -82,7 +82,7 @@ endif
 #
 # check for mandatory dependencies
 #
-spice_protocol_version='0.12.15'
+spice_protocol_version='0.12.16'
 
 glib_version = '2.38'
 glib_version_info = '>= @0@'.format(glib_version)
diff --git a/server/red-qxl.c b/server/red-qxl.c
index 907f78d6..7f8ac35d 100644
--- a/server/red-qxl.c
+++ b/server/red-qxl.c
@@ -889,6 +889,26 @@ void spice_qxl_set_device_info(QXLInstance *instance,
 
 instance->st->monitors_count = device_display_id_count;
 instance->st->max_monitors = device_display_id_count;
+
+reds_send_device_display_info(red_qxl_get_server(instance->st));
+}
+
+const char* red_qxl_get_device_address(const QXLInstance *qxl)
+{
+const QXLState *qxl_state = qxl->st;
+return qxl_state->device_address;
+}
+
+const uint32_t* red_qxl_get_device_display_ids(const QXLInstance *qxl)
+{
+const QXLState *qxl_state = qxl->st;
+return qxl_state->device_display_ids;
+}
+
+size_t red_qxl_get_monitors_count(const QXLInstance *qxl)
+{
+const QXLState *qxl_state = qxl->st;
+return qxl_state->monitors_count;
 }
 
 void red_qxl_init(RedsState *reds, QXLInstance *qxl)
diff --git a/server/red-qxl.h b/server/red-qxl.h
index 6014d32a..94753948 100644
--- a/server/red-qxl.h
+++ b/server/red-qxl.h
@@ -40,6 +40,9 @@ void red_qxl_put_gl_scanout(QXLInstance *qxl, 
SpiceMsgDisplayGlScanoutUnix *scan
 void red_qxl_gl_draw_async_complete(QXLInstance *qxl);
 int red_qxl_check_qxl_version(QXLInstance *qxl, int major, int minor);
 SpiceServer* red_qxl_get_server(QXLState *qxl);
+const char* red_qxl_get_device_address(const QXLInstance *qxl);
+const uint32_t* red_qxl_get_device_display_ids(const QXLInstance *qxl);
+size_t red_qxl_get_monitors_count(const QXLInstance *qxl);
 
 /* Wrappers around QXLInterface vfuncs */
 void red_qxl_get_init_info(QXLInstance *qxl, QXLDevInitInfo *info);
diff --git a/server/reds-private.h b/server/reds-private.h
index 920edc5c..9dbc7fa9 100644
--- a/server/reds-private.h
+++ b/server/reds-private.h
@@ -81,6 +81,7 @@ struct RedsState {
 SpiceWatch *secure_listen_watch;
 RedCharDeviceVDIPort *agent_dev;
 int pending_mouse_event;
+bool pending_device_display_info_message;
 GList *clients;
 MainChannel *main_channel;
 InputsChannel *inputs_channel;
diff --git a/server/reds.c b/server/reds.c
index e95c62d5..c4ec2a3f 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -257,6 +257,7 @@ typedef struct __attribute__ ((__packed__)) VDInternalBuf {
 VDAgentMessage header;
 union {
 VDAgentMouseState mouse_state;
+VDAgentGraphicsDeviceInfo graphics_device_info;
 }
 u;
 } VDInternalBuf;
@@ -894,6 +895,65 @@ static RedPipeItem 
*vdi_port_read_one_msg_from_device(RedCharDevice *self,
 return NULL;
 }
 
+void reds_send_device_display_info(RedsState *reds)
+{
+if (!reds->agent_dev->priv->agent_attached) {
+return;
+}
+g_debug("Sending device display info to the agent:");
+
+size_t message_size = sizeof(VDAgentGraphicsDeviceInfo);
+QXLInstance *qxl;
+FOREACH_QXL_INSTANCE(reds, qxl) {
+message_size +=
+(sizeof(VDAgentDeviceDisplayInfo) + 
strlen(red_qxl_get_device_address(qxl)) + 1) *
+red_qxl_get_monitors_count(qxl);
+}
+
+RedCharDeviceWriteBuffer *char_dev_buf = 
vdagent_new_write_buffer(reds->agent_dev,
+ VD_AGENT_GRAPHICS_DEVICE_INFO,
+ message_size,
+ true);
+
+if (!char_dev_buf) {
+reds->pending_device_display_info_message = true;
+return;
+}
+
+VDInternalBuf *internal_buf = (VDInternalBuf *)char_dev_buf->buf;
+VDAgentGraphicsDeviceInfo *graphics_device_info = 
_buf->u.graphics_

[Spice-devel] [PATCH spice-streaming-agent v4 5/6] Send the GraphicsDeviceInfo to the server

2019-01-28 Thread Lukáš Hrázký
Adds serialization of the GraphicsDeviceInfo message and sends it to the
server when it starts to stream.

Signed-off-by: Lukáš Hrázký 
Reviewed-by: Jonathon Jongsma 
---
 configure.ac  |  2 +-
 src/spice-streaming-agent.cpp | 60 +--
 2 files changed, 52 insertions(+), 10 deletions(-)

diff --git a/configure.ac b/configure.ac
index fd18efe..c259f7e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -30,7 +30,7 @@ PKG_PROG_PKG_CONFIG
 dnl =
 dnl Check deps
 
-SPICE_PROTOCOL_MIN_VER=0.12.14
+SPICE_PROTOCOL_MIN_VER=0.12.16
 PKG_CHECK_MODULES([SPICE_PROTOCOL], [spice-protocol >= 
$SPICE_PROTOCOL_MIN_VER])
 AC_SUBST([SPICE_PROTOCOL_MIN_VER])
 
diff --git a/src/spice-streaming-agent.cpp b/src/spice-streaming-agent.cpp
index cd23111..a9fde2a 100644
--- a/src/spice-streaming-agent.cpp
+++ b/src/spice-streaming-agent.cpp
@@ -31,6 +31,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -93,6 +94,39 @@ public:
 }
 };
 
+class DeviceDisplayInfoMessage : public 
OutboundMessage
+{
+public:
+DeviceDisplayInfoMessage(const DeviceDisplayInfo ) : 
OutboundMessage(info) {}
+
+static size_t size(const DeviceDisplayInfo )
+{
+return sizeof(PayloadType) +
+   std::min(info.device_address.length(), 
static_cast(max_device_address_len)) +
+   1;
+}
+
+void write_message_body(StreamPort _port, const DeviceDisplayInfo 
)
+{
+std::string device_address = info.device_address;
+if (device_address.length() > max_device_address_len) {
+syslog(LOG_WARNING,
+   "device address of stream id %u is longer than %u bytes, 
trimming.",
+   info.stream_id, max_device_address_len);
+device_address = device_address.substr(0, max_device_address_len);
+}
+StreamMsgDeviceDisplayInfo strm_msg_info{};
+strm_msg_info.stream_id = info.stream_id;
+strm_msg_info.device_display_id = info.device_display_id;
+strm_msg_info.device_address_len = device_address.length() + 1;
+stream_port.write(_msg_info, sizeof(strm_msg_info));
+stream_port.write(device_address.c_str(), device_address.length() + 1);
+}
+
+private:
+static constexpr uint32_t max_device_address_len = 255;
+};
+
 static bool streaming_requested = false;
 static bool quit_requested = false;
 static std::set client_codecs;
@@ -217,17 +251,25 @@ do_capture(StreamPort _port, FrameLog _log)
 throw std::runtime_error("cannot find a suitable capture system");
 }
 
+std::vector display_info;
 try {
-std::vector display_info = 
capture->get_device_display_info();
-syslog(LOG_DEBUG, "Got device info of %lu devices from the 
plugin", display_info.size());
-for (const auto  : display_info) {
-syslog(LOG_DEBUG, "   id %u: device address %s, device display 
id: %u",
-   info.stream_id,
-   info.device_address.c_str(),
-   info.device_display_id);
-}
+display_info = capture->get_device_display_info();
 } catch (const Error ) {
-syslog(LOG_ERR, "Error while getting device info: %s", e.what());
+syslog(LOG_ERR, "Error while getting device display info: %s", 
e.what());
+}
+
+syslog(LOG_DEBUG, "Got device info of %zu devices from the plugin", 
display_info.size());
+for (const auto  : display_info) {
+syslog(LOG_DEBUG, "   stream id %u: device address: %s, device 
display id: %u",
+   info.stream_id,
+   info.device_address.c_str(),
+   info.device_display_id);
+}
+
+if (display_info.size() > 0) {
+stream_port.send(display_info[0]);
+} else {
+syslog(LOG_ERR, "Empty device display info from the plugin");
 }
 
 while (!quit_requested && streaming_requested) {
-- 
2.20.1

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH v4 0/6] Monitor ID between host and guest

2019-01-28 Thread Lukáš Hrázký
Hello,

this series introduces a new mechanism to identify monitors across the
host and guest boundary, using the pair (device_address and
device_display_id). device_address is a HW address of a graphics device
(a PCI address to be specific, though other address domains can be
used as well), device_display_id is an ID of the monitor on that device.

This information is gathered from QEMU (regular spice) or
spice-streaming-agent (for the streaming channels) and a mapping of
(channel_id, monitor_id) -> (device_address, device_display_id) is sent
from spice server to the vd_agent. vd_agent uses this mapping to
translate the former ID in incoming messages to the latter.

This series follows up on the "QXL interface to set monitor ID" series
[1] and then Jonathon Jongsma's "Use the PCI addr and display ID" [2]
follows up on this to make a complete solution.

You can also find the code in the following branches:
https://gitlab.freedesktop.org/lukash/spice/commits/monitor-id-v3-4
https://gitlab.freedesktop.org/lukash/spice-streaming-agent/commits/monitor-id-v3-4
https://gitlab.freedesktop.org/lukash/vd_agent/commits/monitor-id-v3-4

Cheers,
Lukas


Changes since v3:
* spice-protocol patches were merged.
* Bumped minimum required version of spice-protocol to 0.12.16 for
  spice, spice-streaming-agent and vd_agent.
* spice-streaming-agent: Include cstdlib.h in display-info.cpp.
* spice-streaming-agent: use a constant for maximum device address
  length instead of a number literal.
* spice-streaming-agent: explicitly compare with zero for
  std::string::compare()
* spice-streaming-agent: rename local variable output to xoutput.


[1] https://lists.freedesktop.org/archives/spice-devel/2019-January/046997.html
[2] https://lists.freedesktop.org/archives/spice-devel/2019-January/047547.html

-- 
2.20.1

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH spice v4 3/6] Send the graphics device info from streaming agent to the vd_agent

2019-01-28 Thread Lukáš Hrázký
Adds the graphics device info from the streaming device(s) to the
VDAgentGraphicsDeviceInfo message sent to the vd_agent.

Signed-off-by: Lukáš Hrázký 
Acked-by: Jonathon Jongsma 
---
 server/red-stream-device.c | 18 +++
 server/red-stream-device.h |  7 +
 server/reds.c  | 63 --
 3 files changed, 86 insertions(+), 2 deletions(-)

diff --git a/server/red-stream-device.c b/server/red-stream-device.c
index 38df8e4c..440b2689 100644
--- a/server/red-stream-device.c
+++ b/server/red-stream-device.c
@@ -346,6 +346,8 @@ handle_msg_device_display_info(StreamDevice *dev, 
SpiceCharDeviceInstance *sin)
 dev->device_display_info.device_address,
 dev->device_display_info.device_display_id);
 
+
reds_send_device_display_info(red_char_device_get_server(RED_CHAR_DEVICE(dev)));
+
 return true;
 }
 
@@ -805,6 +807,22 @@ stream_device_init(StreamDevice *dev)
 dev->msg_len = sizeof(*dev->msg);
 }
 
+StreamDeviceDisplayInfo *stream_device_get_device_display_info(StreamDevice 
*dev)
+{
+return >device_display_info;
+}
+
+int32_t stream_device_get_stream_channel_id(StreamDevice *dev)
+{
+if (dev->stream_channel == NULL) {
+return -1;
+}
+
+int32_t channel_id;
+g_object_get(dev->stream_channel, "id", _id, NULL);
+return channel_id;
+}
+
 static StreamDevice *
 stream_device_new(SpiceCharDeviceInstance *sin, RedsState *reds)
 {
diff --git a/server/red-stream-device.h b/server/red-stream-device.h
index 996be016..d7ab5e41 100644
--- a/server/red-stream-device.h
+++ b/server/red-stream-device.h
@@ -56,6 +56,13 @@ StreamDevice *stream_device_connect(RedsState *reds, 
SpiceCharDeviceInstance *si
  */
 void stream_device_create_channel(StreamDevice *dev);
 
+StreamDeviceDisplayInfo *stream_device_get_device_display_info(StreamDevice 
*dev);
+
+/**
+ * Returns -1 if the StreamDevice doesn't have a channel yet.
+ */
+int32_t stream_device_get_stream_channel_id(StreamDevice *dev);
+
 G_END_DECLS
 
 #endif /* STREAM_DEVICE_H */
diff --git a/server/reds.c b/server/reds.c
index c4ec2a3f..d7a71dc1 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -902,14 +902,33 @@ void reds_send_device_display_info(RedsState *reds)
 }
 g_debug("Sending device display info to the agent:");
 
-size_t message_size = sizeof(VDAgentGraphicsDeviceInfo);
 QXLInstance *qxl;
+RedCharDevice *dev;
+
+size_t message_size = sizeof(VDAgentGraphicsDeviceInfo);
+
+// size for the qxl device info
 FOREACH_QXL_INSTANCE(reds, qxl) {
 message_size +=
 (sizeof(VDAgentDeviceDisplayInfo) + 
strlen(red_qxl_get_device_address(qxl)) + 1) *
 red_qxl_get_monitors_count(qxl);
 }
 
+// size for the stream device info
+GLIST_FOREACH(reds->char_devices, RedCharDevice, dev) {
+if (IS_STREAM_DEVICE(dev)) {
+size_t device_address_len =
+
strlen(stream_device_get_device_display_info(STREAM_DEVICE(dev))->device_address);
+
+if (device_address_len == 0) {
+// the device info wasn't set (yet), don't send it
+continue;
+}
+
+message_size += (sizeof(VDAgentDeviceDisplayInfo) + 
device_address_len + 1);
+}
+}
+
 RedCharDeviceWriteBuffer *char_dev_buf = 
vdagent_new_write_buffer(reds->agent_dev,
  VD_AGENT_GRAPHICS_DEVICE_INFO,
  message_size,
@@ -925,6 +944,8 @@ void reds_send_device_display_info(RedsState *reds)
 graphics_device_info->count = 0;
 
 VDAgentDeviceDisplayInfo *device_display_info = 
graphics_device_info->display_info;
+
+// add the qxl devices to the message
 FOREACH_QXL_INSTANCE(reds, qxl) {
 for (size_t i = 0; i < red_qxl_get_monitors_count(qxl); ++i) {
 device_display_info->channel_id = qxl->id;
@@ -936,7 +957,45 @@ void reds_send_device_display_info(RedsState *reds)
 device_display_info->device_address_len =
 strlen((char*) device_display_info->device_address) + 1;
 
-g_debug("   channel_id: %u monitor_id: %u, device_address: %s, 
device_display_id: %u",
+g_debug("   (qxl)channel_id: %u monitor_id: %u, 
device_address: %s, device_display_id: %u",
+device_display_info->channel_id,
+device_display_info->monitor_id,
+device_display_info->device_address,
+device_display_info->device_display_id);
+
+device_display_info = (VDAgentDeviceDisplayInfo*) ((char*) 
device_display_info +
+sizeof(VDAgentDeviceDisplayInfo) + 
device_display_info->device_address_len);
+
+graphics_device_info->count++;
+}
+}
+
+// add the stream devices 

[Spice-devel] [PATCH] QXL interface: improve the spice_qxl_set_device_info documentation

2019-01-28 Thread Lukáš Hrázký
Instead of one unsupported example, present two real world examples.

Signed-off-by: Lukáš Hrázký 
---
 server/spice-qxl.h | 32 ++--
 1 file changed, 22 insertions(+), 10 deletions(-)

diff --git a/server/spice-qxl.h b/server/spice-qxl.h
index e7af5e5e..2f47910b 100644
--- a/server/spice-qxl.h
+++ b/server/spice-qxl.h
@@ -122,7 +122,7 @@ void spice_qxl_gl_draw_async(QXLInstance *instance,
  * @instance the QXL instance to set the path to
  * @device_address the path of the device this QXL instance belongs to
  * @device_display_id_start the starting device display ID of this interface,
- *  i.e. the one monitor ID 0 maps to
+ *  i.e. the device display ID of monitor ID 0
  * @device_display_id_count the total number of device display IDs on this
  *  interface
  *
@@ -145,16 +145,28 @@ void spice_qxl_gl_draw_async(QXLInstance *instance,
  *
  * The device_display_id_{start,count} denotes the sequence of device display
  * IDs that map to the zero-based sequence of monitor IDs provided by monitors
- * config on this interface. For example with device_display_id_start = 2 and
- * device_display_id_count = 3 you get the following mapping:
- * monitor_id  ->  device_display_id
- *  0  ->  2
- *  1  ->  3
- *  2  ->  4
+ * config on this interface.
  *
- * Note this example is unsupported in practice. The only supported cases are
- * either a single device display ID (count = 1) or multiple device display IDs
- * in a sequence starting from 0.
+ * Example 1:
+ *   A QXL graphics device with 3 heads (monitors).
+ *
+ *   device_display_id_start = 0
+ *   device_display_id_count = 3
+ *
+ *   Results in the following mapping of monitor_id  ->  device_display_id:
+ *   0  ->  0
+ *   1  ->  1
+ *   2  ->  2
+ *
+ * Example 2:
+ *   A virtio graphics device, multiple monitors, a QXL interface for each
+ *   monitor. On the QXL interface for the third monitor:
+ *
+ *   device_display_id_start = 2
+ *   device_display_id_count = 1
+ *
+ *   Results in the following mapping of monitor_id  ->  device_display_id:
+ *   0  ->  2
  */
 void spice_qxl_set_device_info(QXLInstance *instance,
const char *device_address,
-- 
2.20.1

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH linux vdagent v4 9/9] Make cursor work with mjpeg streaming

2019-01-18 Thread Lukáš Hrázký
I'd also squash this up to 7/9. It just reworks what was not a complete
solution.

Cheers,
Lukas


On Thu, 2019-01-17 at 16:14 -0600, Jonathon Jongsma wrote:
> In the case where we have an mjpeg plugin running in the streaming
> agent, we have two spice displays representing the same guest display.
> In that scenario, the session agent may maintain the following guest
> output mapping:
>  spice channel 0 (QXL) => X output 0
>  spice channel 1 (streaming-agent) => X output 0
> 
> While this is not necessarily a supported scenario, it would be nice if
> the cursor input worked properly in this case. The root problem is that
> when the session agent sends down the guest xorg resolutions to the
> system daemon, it simply loops through the list of xorg displays, and
> for each X display it looks up the first spice display ID associated
> with it and sends that down to the daemon. In the scenario mentioned
> above, since there is only a single X display configured (albeit
> represented by two different spice displays), we would send down a
> single display resolution to the system daemon:
>  - { width=1280, height=1024, x=0, y=0, display_id=0 }
> 
> Notice that there is no entry for display_id=1. When the agent receives
> a cursor input message for display channel 1, that message will get
> passed to the systemn daemon, which will attempt to look up display_id 1
> in order to convert the event coordinates to global coordinates. Finding
> no entry for display_id=1, the mouse events do not work.
> 
> In this patch, when we want to send the guest resolutions down to the
> system daemon, we still loop through the list of X outputs, but for each
> output we also loop through the guest output mapping table and send a
> resolution structure down to the daemon for each registered output
> mapping.  This means that in the previously mentioned scenario, we would
> send down the following information:
>  - { width=1280, height=1024, x=0, y=0, display_id=0 }
>  - { width=1280, height=1024, x=0, y=0, display_id=1 }
> 
>  This means that when the client sends a mouse event for display_id=1,
>  the system daemon knows the coordinates of the guest display associated
>  with that ID and can process the mouse event properly.
> ---
>  src/vdagent/x11-randr.c | 106 
>  1 file changed, 53 insertions(+), 53 deletions(-)
> 
> diff --git a/src/vdagent/x11-randr.c b/src/vdagent/x11-randr.c
> index 283dbc8..fe48c46 100644
> --- a/src/vdagent/x11-randr.c
> +++ b/src/vdagent/x11-randr.c
> @@ -688,35 +688,6 @@ static int config_size(int num_of_monitors)
> num_of_monitors * sizeof(VDAgentMonConfig);
>  }
>  
> -static int get_display_id_for_output_index(struct vdagent_x11 *x11, int 
> output_index)
> -{
> -// invalid output index
> -if (output_index >= x11->randr.res->noutput) {
> -syslog(LOG_WARNING, "Invalid output index %d (>%d)", output_index, 
> x11->randr.res->noutput);
> -return -1;
> -}
> -
> -if (g_hash_table_size(x11->guest_output_map) == 0) {
> -syslog(LOG_DEBUG, "No guest output map, using output index as 
> display id");
> -return output_index;
> -}
> -
> -int display_id = -1;
> -RROutput output_id = x11->randr.res->outputs[output_index];
> -GHashTableIter iter;
> -gpointer key, value;
> -g_hash_table_iter_init(, x11->guest_output_map);
> -while (g_hash_table_iter_next(, , )) {
> -gint64 *other_id = value;
> -if (*other_id == output_id) {
> -return GPOINTER_TO_INT(key);
> -}
> -}
> -
> -syslog(LOG_WARNING, "Unable to find a display id for output index %d)", 
> output_index);
> -return display_id;
> -}
> -
>  // gets monitor information about the specified output index and returns 
> true if there was no error
>  static bool get_monitor_info_for_output_index(struct vdagent_x11 *x11, int 
> output_index, int *x, int *y, int *width, int *height)
>  {
> @@ -1093,7 +1064,7 @@ exit:
>  
>  void vdagent_x11_send_daemon_guest_xorg_res(struct vdagent_x11 *x11, int 
> update)
>  {
> -struct vdagentd_guest_xorg_resolution *res = NULL;
> +GArray *res_array = g_array_new(FALSE, FALSE, sizeof(struct 
> vdagentd_guest_xorg_resolution));
>  int i, width = 0, height = 0, screen_count = 0;
>  
>  if (x11->has_xrandr) {
> @@ -1101,17 +1072,39 @@ void vdagent_x11_send_daemon_guest_xorg_res(struct 
> vdagent_x11 *x11, int update)
>  update_randr_res(x11, 0);
>  
>  screen_count = x11->randr.res->noutput;
> -res = g_new(struct vdagentd_guest_xorg_resolution, screen_count);
>  
>  for (i = 0; i < screen_count; i++) {
> -struct vdagentd_guest_xorg_resolution *curr = [i];
> -if (!get_monitor_info_for_output_index(x11, i, >x, 
> >y,
> -   >width, 
> >height))
> +struct vdagentd_guest_xorg_resolution curr;
> +if 

Re: [Spice-devel] [PATCH linux vdagent v4 8/9] Send display IDs to daemon when device info changes

2019-01-18 Thread Lukáš Hrázký
I'd squash this to the previous patch.


On Thu, 2019-01-17 at 16:14 -0600, Jonathon Jongsma wrote:
> When the agent gets a new device info message (from the daemon), we need
> to re-calculate the guest output map and send that information back down
> to the daemon so that it can handle mouse input events correctly.
> ---
>  src/vdagent/x11-randr.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/src/vdagent/x11-randr.c b/src/vdagent/x11-randr.c
> index 5749ae7..283dbc8 100644
> --- a/src/vdagent/x11-randr.c
> +++ b/src/vdagent/x11-randr.c
> @@ -865,6 +865,9 @@ void vdagent_x11_handle_graphics_device_info(struct 
> vdagent_x11 *x11, uint8_t *d
>  device_display_info = (VDAgentDeviceDisplayInfo*) ((char*) 
> device_display_info +
>  sizeof(VDAgentDeviceDisplayInfo) + 
> device_display_info->device_address_len);
>  }
> +
> +// make sure daemon is up-to-date with (possibly updated) device IDs
> +vdagent_x11_send_daemon_guest_xorg_res(x11, 1);
>  }
>  
>  static int get_output_index_for_display_id(struct vdagent_x11 *x11, int 
> display_id)
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH linux vdagent v4 7/9] Send display_id down to the vdagentd daemon

2019-01-18 Thread Lukáš Hrázký
On Thu, 2019-01-17 at 16:14 -0600, Jonathon Jongsma wrote:
> Add a display_id field to the structure that we use to send down the
> list of guest display resolutions to the vdagentd daemon. This allows us
> to map the spice display id to the proper X display for determining
> mouse locations, etc.
> ---
>  src/vdagent/x11-randr.c | 35 ---
>  src/vdagentd-proto.h|  1 +
>  src/vdagentd/uinput.c   | 23 ++-
>  3 files changed, 51 insertions(+), 8 deletions(-)
> 
> diff --git a/src/vdagent/x11-randr.c b/src/vdagent/x11-randr.c
> index f3972c8..5749ae7 100644
> --- a/src/vdagent/x11-randr.c
> +++ b/src/vdagent/x11-randr.c
> @@ -688,6 +688,34 @@ static int config_size(int num_of_monitors)
> num_of_monitors * sizeof(VDAgentMonConfig);
>  }
>  
> +static int get_display_id_for_output_index(struct vdagent_x11 *x11, int 
> output_index)
> +{
> +// invalid output index
> +if (output_index >= x11->randr.res->noutput) {
> +syslog(LOG_WARNING, "Invalid output index %d (>%d)", output_index, 
> x11->randr.res->noutput);
> +return -1;
> +}
> +
> +if (g_hash_table_size(x11->guest_output_map) == 0) {
> +syslog(LOG_DEBUG, "No guest output map, using output index as 
> display id");
> +return output_index;
> +}
> +
> +int display_id = -1;
> +RROutput output_id = x11->randr.res->outputs[output_index];
> +GHashTableIter iter;
> +gpointer key, value;
> +g_hash_table_iter_init(, x11->guest_output_map);
> +while (g_hash_table_iter_next(, , )) {
> +gint64 *other_id = value;
> +if (*other_id == output_id) {
> +return GPOINTER_TO_INT(key);
> +}
> +}
> +
> +syslog(LOG_WARNING, "Unable to find a display id for output index %d)", 
> output_index);
> +return display_id;
> +}
>  
>  // gets monitor information about the specified output index and returns 
> true if there was no error
>  static bool get_monitor_info_for_output_index(struct vdagent_x11 *x11, int 
> output_index, int *x, int *y, int *width, int *height)
> @@ -1075,11 +1103,12 @@ void vdagent_x11_send_daemon_guest_xorg_res(struct 
> vdagent_x11 *x11, int update)
>  for (i = 0; i < screen_count; i++) {
>  struct vdagentd_guest_xorg_resolution *curr = [i];
>  if (!get_monitor_info_for_output_index(x11, i, >x, 
> >y,
> -   >width, 
> >height)
> +   >width, 
> >height))

Oh, so this definitely belongs to the previous patch.

Besides that,
Reviewed-by: Lukáš Hrázký 

>  {
>  g_free(res);
>  goto no_info;
>  }
> +curr->display_id = get_display_id_for_output_index(x11, i);
>  }
>  width  = x11->width[0];
>  height = x11->height[0];
> @@ -1131,8 +1160,8 @@ no_info:
>  if (x11->debug) {
>  syslog(LOG_DEBUG, "Sending guest screen resolutions to vdagentd:");
>  for (i = 0; i < screen_count; i++) {
> -syslog(LOG_DEBUG, "   screen %d %dx%d%+d%+d", i,
> -   res[i].width, res[i].height, res[i].x, res[i].y);
> +syslog(LOG_DEBUG, "   screen %d %dx%d%+d%+d, id=%d", i,
> +   res[i].width, res[i].height, res[i].x, res[i].y, 
> res[i].display_id);
>  }
>  }
>  
> diff --git a/src/vdagentd-proto.h b/src/vdagentd-proto.h
> index 243a9c6..7eff71d 100644
> --- a/src/vdagentd-proto.h
> +++ b/src/vdagentd-proto.h
> @@ -53,6 +53,7 @@ struct vdagentd_guest_xorg_resolution {
>  int height;
>  int x;
>  int y;
> +int display_id;
>  };
>  
>  #endif
> diff --git a/src/vdagentd/uinput.c b/src/vdagentd/uinput.c
> index 4f854bf..ff37e1e 100644
> --- a/src/vdagentd/uinput.c
> +++ b/src/vdagentd/uinput.c
> @@ -175,6 +175,18 @@ static void uinput_send_event(struct vdagentd_uinput 
> **uinputp,
>  }
>  }
>  
> +static struct vdagentd_guest_xorg_resolution* lookup_screen_info(struct 
> vdagentd_uinput *uinput, int display_id)
> +{
> +int i;
> +for (i = 0; i < uinput->screen_count; i++) {
> +if (uinput->screen_info[i].display_id == display_id) {
> +return >screen_info[i];
> +}
> +}
> +syslog(LOG_WARNING, "Unable to find output index for display id %d", 
> display_id);
> +return NULL;
> +}
> +
>  void vdagentd_uinput_do_mouse(struct 

Re: [Spice-devel] [PATCH linux vdagent v4 6/9] Use new function in vdagent_x11_send_daemon_guest_xorg_res()

2019-01-18 Thread Lukáš Hrázký
Reviewed-by: Lukáš Hrázký 


On Thu, 2019-01-17 at 16:14 -0600, Jonathon Jongsma wrote:
> Rather than getting the current guest resolution in a
> VDAgentMonitorsConfig struct and then translating it to a new struct
> type for sending down to the daemon, simply use the new function that
> was factored out in a previous commit and populate the message struct
> directly.
> ---
>  src/vdagent/x11-randr.c | 20 
>  1 file changed, 8 insertions(+), 12 deletions(-)
> 
> diff --git a/src/vdagent/x11-randr.c b/src/vdagent/x11-randr.c
> index 05a001e..f3972c8 100644
> --- a/src/vdagent/x11-randr.c
> +++ b/src/vdagent/x11-randr.c
> @@ -1066,25 +1066,21 @@ void vdagent_x11_send_daemon_guest_xorg_res(struct 
> vdagent_x11 *x11, int update)
>  int i, width = 0, height = 0, screen_count = 0;
>  
>  if (x11->has_xrandr) {
> -VDAgentMonitorsConfig *curr;
> -
>  if (update)
>  update_randr_res(x11, 0);
>  
> -curr = get_current_mon_config(x11);
> -if (!curr)
> -goto no_info;
> -
> -screen_count = curr->num_of_monitors;
> +screen_count = x11->randr.res->noutput;
>  res = g_new(struct vdagentd_guest_xorg_resolution, screen_count);
>  
>  for (i = 0; i < screen_count; i++) {
> -res[i].width  = curr->monitors[i].width;
> -res[i].height = curr->monitors[i].height;
> -res[i].x = curr->monitors[i].x;
> -res[i].y = curr->monitors[i].y;
> +struct vdagentd_guest_xorg_resolution *curr = [i];
> +if (!get_monitor_info_for_output_index(x11, i, >x, 
> >y,
> +   >width, 
> >height)
> +{
> +g_free(res);
> +goto no_info;
> +}
>  }
> -g_free(curr);
>  width  = x11->width[0];
>  height = x11->height[0];
>  } else if (x11->has_xinerama) {
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH linux vdagent v4 5/9] Factor a function out of get_current_mon_config()

2019-01-18 Thread Lukáš Hrázký
On Thu, 2019-01-17 at 16:14 -0600, Jonathon Jongsma wrote:
> When sending the guest xorg resolution to the vdagentd daemon, we get
> the current resolution with this function, which returns a
> VDAgentMonitorsConfig structure that must then be converted to the
> structure that we send to the daemon. Rather than re-using this function
> that returns the wrong type, factor out most of the functionality into a
> separate function. This function can be used by a new function to return
> a type appropriate for sending the xorg resolution to the daemon.
> 
> This is necessary because in the next few commits I'll be changing the
> vdagentd protocol to send an additional display_id parameter to the
> daemon.
> ---
>  src/vdagent/x11-randr.c | 73 +
>  1 file changed, 52 insertions(+), 21 deletions(-)
> 
> diff --git a/src/vdagent/x11-randr.c b/src/vdagent/x11-randr.c
> index 5eff225..05a001e 100644
> --- a/src/vdagent/x11-randr.c
> +++ b/src/vdagent/x11-randr.c
> @@ -688,38 +688,69 @@ static int config_size(int num_of_monitors)
> num_of_monitors * sizeof(VDAgentMonConfig);
>  }
>  
> +
> +// gets monitor information about the specified output index and returns 
> true if there was no error
> +static bool get_monitor_info_for_output_index(struct vdagent_x11 *x11, int 
> output_index, int *x, int *y, int *width, int *height)

Lines above too long.

> +{
> +g_return_val_if_fail (output_index < x11->randr.res->noutput, false);
> +g_return_val_if_fail (x != NULL, false);
> +g_return_val_if_fail (y != NULL, false);
> +g_return_val_if_fail (width != NULL, false);
> +g_return_val_if_fail (height != NULL, false);
> +
> +int j;
> +XRRCrtcInfo *crtc = NULL;
> +XRRModeInfo *mode;
> +
> +if (x11->randr.outputs[output_index]->ncrtc == 0)
> +goto zeroed; /* Monitor disabled */
> +
> +for (j = 0; crtc == NULL && j < x11->randr.outputs[output_index]->ncrtc; 
> j++) {
> +crtc = crtc_from_id(x11, x11->randr.outputs[output_index]->crtcs[j]);
> +}
> +if (!crtc) {
> +// error. stale xrandr info?
> +return false;
> +}
> +
> +mode = mode_from_id(x11, crtc->mode);
> +if (!mode)
> +goto zeroed; /* monitor disabled */
> +
> +*x = crtc->x;
> +*y = crtc->y;
> +*width = mode->width;
> +*height = mode->height;
> +return true;
> +
> +zeroed:
> +*x = 0;
> +*y = 0;
> +*width = 0;
> +*height = 0;
> +return true;
> +}
> +
>  static VDAgentMonitorsConfig *get_current_mon_config(struct vdagent_x11 *x11)
>  {
>  int i, num_of_monitors = 0;
> -XRRModeInfo *mode;
>  XRRScreenResources *res = x11->randr.res;
>  VDAgentMonitorsConfig *mon_config;
>  
>  mon_config = g_malloc0(config_size(res->noutput));
>  
>  for (i = 0 ; i < res->noutput; i++) {
> -int j;
> -XRRCrtcInfo *crtc = NULL;
> -
> -if (x11->randr.outputs[i]->ncrtc == 0)
> -continue; /* Monitor disabled, already zero-ed by calloc */
> -if (x11->randr.outputs[i]->crtc == 0)
> -continue; /* Monitor disabled */
> -
> -for (j = 0; crtc == NULL && j < x11->randr.outputs[i]->ncrtc; j++) {
> -crtc = crtc_from_id(x11, x11->randr.outputs[i]->crtcs[j]);
> -}
> -if (!crtc)
> +int x, y, width, height;
> +if (!get_monitor_info_for_output_index(x11, i, , , , 
> )) {
> +syslog(LOG_WARNING, "Unable to get monitor info for output id 
> %d", i);
>  goto error;
> +}
>  
> -mode = mode_from_id(x11, crtc->mode);
> -if (!mode)
> -continue; /* Monitor disabled, already zero-ed by calloc */
> -
> -mon_config->monitors[i].x  = crtc->x;
> -mon_config->monitors[i].y  = crtc->y;
> -mon_config->monitors[i].width  = mode->width;
> -mon_config->monitors[i].height = mode->height;
> +VDAgentMonConfig *mon = _config->monitors[i];
> +mon->x = x;
> +mon->y = y;
> +mon->width = width;
> +mon->height = height;
>  num_of_monitors = i + 1;
>  }
>  mon_config->num_of_monitors = num_of_monitors;

Reviewed-by: Lukáš Hrázký 
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH linux vdagent v4 4/9] Use guest output map to determine xrandr output

2019-01-18 Thread Lukáš Hrázký
}
>  
> @@ -943,11 +998,16 @@ void vdagent_x11_set_monitor_config(struct vdagent_x11 
> *x11,
> i, width, height, x, y);
>  }
>  
> -if (!xrandr_add_and_set(x11, i, x, y, width, height) &&
> +int output_index = get_output_index_for_display_id(x11, i);
> +if (output_index != -1) {
> +if (!xrandr_add_and_set(x11, output_index, x, y, width, height) 
> &&
>  enabled_monitors(mon_config) == 1) {
> -set_screen_to_best_size(x11, width, height,
> -_w, _h);
> -break;
> +set_screen_to_best_size(x11, width, height,
> +_w, _h);
> +break;
> +}
> +} else {
> +syslog(LOG_WARNING, "Unable to find a guest output index for 
> spice display %i", i);
>  }
>  }

Reviewed-by: Lukáš Hrázký 
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH linux vdagent v4 2/9] Look up and store xrandr output in display map

2019-01-18 Thread Lukáš Hrázký
  GUINT_TO_POINTER(device_display_info->channel_id + 
> device_display_info->monitor_id),
>  value);
> +} else {
> +syslog(LOG_INFO, "channel_id: %u monitor_id: %u device_address: 
> %s, "
> +   "device_display_id: %u xrandr output ID NOT FOUND",
> +   device_display_info->channel_id,
> +   device_display_info->monitor_id,
> +   device_display_info->device_address,
> +   device_display_info->device_display_id);
> +}
>  
>  device_display_info = (VDAgentDeviceDisplayInfo*) ((char*) 
> device_display_info +
>  sizeof(VDAgentDeviceDisplayInfo) + 
> device_display_info->device_address_len);
> diff --git a/src/vdagent/x11.c b/src/vdagent/x11.c
> index ab822f8..484be5e 100644
> --- a/src/vdagent/x11.c
> +++ b/src/vdagent/x11.c
> @@ -196,12 +196,6 @@ static gchar *vdagent_x11_get_wm_name(struct vdagent_x11 
> *x11)
>  #endif
>  }
>  
> -static void graphics_display_info_destroy(gpointer gdi)
> -{
> -g_free(gdi);
> -}
> -
> -
>  struct vdagent_x11 *vdagent_x11_create(struct udscs_connection *vdagentd,
>  int debug, int sync)
>  {
> @@ -218,6 +212,12 @@ struct vdagent_x11 *vdagent_x11_create(struct 
> udscs_connection *vdagentd,
>  x11->vdagentd = vdagentd;
>  x11->debug = debug;
>  
> +x11->guest_output_map = g_hash_table_new_full(_direct_hash,
> +  _direct_equal,
> +  NULL,
> +  _free);
> +
> +
>  x11->display = XOpenDisplay(NULL);
>  if (!x11->display) {
>  syslog(LOG_ERR, "could not connect to X-server");
> @@ -322,12 +322,6 @@ struct vdagent_x11 *vdagent_x11_create(struct 
> udscs_connection *vdagentd,
> __func__, net_wm_name, vdagent_x11_has_icons_on_desktop(x11));
>  g_free(net_wm_name);
>  
> -x11->graphics_display_infos = g_hash_table_new_full(_direct_hash,
> -  _direct_equal,
> -  NULL,
> -  
> _display_info_destroy);
> -
> -
>  /* Flush output buffers and consume any pending events */
>  vdagent_x11_do_read(x11);
>  
> @@ -349,7 +343,7 @@ void vdagent_x11_destroy(struct vdagent_x11 *x11, int 
> vdagentd_disconnected)
>  }
>  #endif
>  
> -g_hash_table_destroy(x11->graphics_display_infos);
> +g_hash_table_destroy(x11->guest_output_map);
>  XCloseDisplay(x11->display);
>  g_free(x11->randr.failed_conf);
>  g_free(x11);

Reviewed-by: Lukáš Hrázký 
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH linux vdagent v4 1/9] Add lookup_xrand_output_for_device_info()

2019-01-18 Thread Lukáš Hrázký
   PciDevice db3 = {0, 0, 3, 0};
> +PciAddress a2 = {1, NULL};
> +a2.domain = 0;
> +a2.devices = g_list_append(a2.devices, );
> +a2.devices = g_list_append(a2.devices, );
> +a2.devices = g_list_append(a2.devices, );
> +
> +assert(compare_addresses(, ));
> +}
> +// different number of devices
> +{
> +PciDevice da1 = {0, 0, 3, 0};
> +PciDevice da2 = {0, 1, 1, 0};
> +PciDevice da3 = {0, 2, 3, 0};
> +PciAddress a1 = {0, NULL};
> +a1.domain = 0;
> +a1.devices = g_list_append(a1.devices, );
> +a1.devices = g_list_append(a1.devices, );
> +a1.devices = g_list_append(a1.devices, );
> +
> +PciDevice db1 = {0, 0, 3, 0};
> +PciDevice db2 = {0, 1, 1, 0};
> +PciAddress a2 = {0, NULL};
> +a2.domain = 0;
> +a2.devices = g_list_append(a2.devices, );
> +a2.devices = g_list_append(a2.devices, );
> +
> +assert(!compare_addresses(, ));
> +}
> +// mismatched function
> +{
> +PciDevice da1 = {0, 0, 2, 0};
> +PciAddress a1 = {0, NULL};
> +a1.domain = 0;
> +a1.devices = g_list_append(a1.devices, );
> +
> +PciDevice db1 = {0, 0, 2, 1};
> +PciAddress a2 = {0, NULL};
> +a2.domain = 0;
> +a2.devices = g_list_append(a2.devices, );
> +
> +assert(!compare_addresses(, ));
> +}
> +// mismatched slot
> +{
> +PciDevice da1 = {0, 0, 2, 0};
> +PciAddress a1 = {0, NULL};
> +a1.domain = 0;
> +a1.devices = g_list_append(a1.devices, );
> +
> +PciDevice db1 = {0, 0, 1, 0};
> +PciAddress a2 = {0, NULL};
> +a2.domain = 0;
> +a2.devices = g_list_append(a2.devices, );
> +
> +assert(!compare_addresses(, ));
> +}
> +// mismatched domain
> +{
> +PciDevice da1 = {0, 0, 2, 0};
> +PciAddress a1 = {0, NULL};
> +a1.domain = 1;
> +a1.devices = g_list_append(a1.devices, );
> +
> +PciDevice db1 = {0, 0, 2, 0};
> +PciAddress a2 = {0, NULL};
> +a2.domain = 0;
> +a2.devices = g_list_append(a2.devices, );
> +
> +assert(!compare_addresses(, ));
> +}
> +}
> +
> +static void test_spice_parsing()
> +{
> +PciAddress *addr = parse_pci_address_from_spice("pci//02.0");
> +assert(addr != NULL);
> +assert(addr->domain == 0);
> +assert(g_list_length(addr->devices) == 1);
> +assert_device(addr->devices->data, 0, 0, 2, 0);
> +pci_address_free(addr);
> +
> +addr = parse_pci_address_from_spice("pci//ff.f");
> +assert(addr != NULL);
> +assert(addr->domain == 65535);
> +assert(g_list_length(addr->devices) == 1);
> +assert_device(addr->devices->data, 0, 0, 255, 15);
> +pci_address_free(addr);
> +
> +addr = parse_pci_address_from_spice("pci//02.1/03.0");
> +assert(addr != NULL);
> +assert(addr->domain == 0);
> +assert(g_list_length(addr->devices) == 2);
> +assert_device(addr->devices->data, 0, 0, 2, 1);
> +assert_device(addr->devices->next->data, 0, 0, 3, 0);
> +pci_address_free(addr);
> +
> +addr = parse_pci_address_from_spice("pci/000a/01.0/02.1/03.0");
> +assert(addr != NULL);
> +assert(addr->domain == 10);
> +assert(g_list_length(addr->devices) == 3);
> +assert_device(addr->devices->data, 0, 0, 1, 0);
> +assert_device(addr->devices->next->data, 0, 0, 2, 1);
> +assert_device(addr->devices->next->next->data, 0, 0, 3, 0);
> +pci_address_free(addr);
> +
> +addr = parse_pci_address_from_spice("pcx//02.1/03.0");
> +assert(addr == NULL);
> +
> +addr = parse_pci_address_from_spice("/02.0");
> +assert(addr == NULL);
> +
> +addr = parse_pci_address_from_spice("/02.1/03.0");
> +assert(addr == NULL);
> +}
> +
> +static void test_sysfs_parsing()
> +{
> +PciAddress *addr = 
> parse_pci_address_from_sysfs_path("../../devices/pci:00/:00:02.0/drm/card0");
> +assert(addr != NULL);
> +assert(addr->domain == 0);
> +assert(g_list_length(addr->devices) == 1);
> +assert_device(addr->devices->data, 0, 0, 2, 0);
> +pci_address_free(addr);
> +
> +addr = 
> parse_pci_address_from_sysfs_path("../../devices/pci:ff/:ff:ff.f/drm/card0");
> +assert(addr != NULL);
> +assert(addr->domain == 65535);
> +assert(g_list_length(addr->devices) == 1);
> +assert_device(addr->devices->data, 65535, 255, 255, 15);
> +pci_address_free(addr);
> +
> +addr = 
> parse_pci_address_from_sysfs_path("../../devices/pci:00/:00:03.0/:01:01.0/:02:03.0/virtio2/drm/card0");

Some lines above too long as well, but I'd keep these, as they would be
harder to read when split.

Reviewed-by: Lukáš Hrázký 

Cheers,
Lukas

> +assert(addr != NULL);
> +assert(addr->domain == 0);
> +assert(g_list_length(addr->devices) == 3);
> +assert_device(addr->devices->data, 0, 0, 3, 0);
> +assert_device(addr->devices->next->data, 0, 1, 1, 0);
> +assert_device(addr->devices->next->next->data, 0, 2, 3, 0);
> +pci_address_free(addr);
> +}
> +
> +// verify that we parse the BDF notation correctly
> +static bool test_bdf(const char* string, int domain, uint8_t bus, uint8_t 
> slot, uint8_t function)
> +{
> +PciDevice pci_dev;
> +return (parse_pci_device(string, NULL, _dev)
> +&& (pci_dev.domain == domain)
> +&& (pci_dev.bus == bus)
> +&& (pci_dev.slot == slot)
> +&& (pci_dev.function == function));
> +}
> +
> +static void test_bdf_parsing()
> +{
> +// valid input
> +assert(test_bdf(":00:02.1", 0, 0, 2, 1));
> +assert(test_bdf("00:00:02.1", 0, 0, 2, 1));
> +assert(test_bdf(":00:03.0", 0, 0, 3, 0));
> +assert(test_bdf(":00:1d.1", 0, 0, 29, 1));
> +assert(test_bdf(":09:02.1", 0, 9, 2, 1));
> +assert(test_bdf(":1d:02.1", 0, 29, 2, 1));
> +assert(test_bdf(":00:02.d", 0, 0, 2, 13));
> +assert(test_bdf("000f:00:02.d", 15, 0, 2, 13));
> +assert(test_bdf("000f:00:02.d", 15, 0, 2, 13));
> +assert(test_bdf("000f:00:02.d", 15, 0, 2, 13));
> +assert(test_bdf("000f:00:02.d", 15, 0, 2, 13));
> +assert(test_bdf(":ff:ff.f", 65535, 255, 255, 15));
> +assert(test_bdf("0:0:2.1", 0, 0, 2, 1));
> +
> +// invalid input
> +assert(!test_bdf(":00:02:0", 0, 0, 2, 0));
> +assert(!test_bdf("-0001:00:02.1", -1, 0, 2, 1));
> +assert(!test_bdf(".00.02.0", 0, 0, 2, 0));
> +assert(!test_bdf("000f:00:02", 15, 0, 2, 0));
> +assert(!test_bdf("000f:00", 15, 0, 0, 0));
> +assert(!test_bdf("000f", 15, 0, 0, 0));
> +assert(!test_bdf("random string", 0, 0, 0, 0));
> +assert(!test_bdf("12345", 12345, 0, 0, 0));
> +}
> +
> +int main(int argc, char **argv)
> +{
> +test_bdf_parsing();
> +test_sysfs_parsing();
> +test_spice_parsing();
> +test_compare_addresses();
> +}
> +
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH spice-streaming-agent 7/8 v3] Send the GraphicsDeviceInfo to the server

2019-01-18 Thread Lukáš Hrázký
On Thu, 2019-01-17 at 14:29 -0600, Jonathon Jongsma wrote:
> On Wed, 2019-01-16 at 13:52 +0100, Lukáš Hrázký wrote:
> > Adds serialization of the GraphicsDeviceInfo message and sends it to
> > the
> > server when it starts to stream.
> > 
> > Signed-off-by: Lukáš Hrázký 
> > ---
> >  src/spice-streaming-agent.cpp | 54 +--
> > 
> >  1 file changed, 45 insertions(+), 9 deletions(-)
> > 
> > diff --git a/src/spice-streaming-agent.cpp b/src/spice-streaming-
> > agent.cpp
> > index 3024d98..891e4cb 100644
> > --- a/src/spice-streaming-agent.cpp
> > +++ b/src/spice-streaming-agent.cpp
> > @@ -31,6 +31,7 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >  #include 
> >  #include 
> >  #include 
> > @@ -93,6 +94,33 @@ public:
> >  }
> >  };
> >  
> > +class DeviceDisplayInfoMessage : public
> > OutboundMessage > STREAM_TYPE_DEVICE_DISPLAY_INFO>
> > +{
> > +public:
> > +DeviceDisplayInfoMessage(const DeviceDisplayInfo ) :
> > OutboundMessage(info) {}
> > +
> > +static size_t size(const DeviceDisplayInfo )
> > +{
> > +return sizeof(PayloadType) +
> > std::min(info.device_address.length(), 255lu) + 1;
> 
> Where does this 255 come from? Can we at least use a constant or
> something?

Oh, yes. I should have put that into a constant.

The same limit is also in the server and the vd_agent, Frediano
suggested to put it into spice-protocol. I'm not entirely sure, as it
looks a bit ad-hoc and I didn't find a good place in spice-protocol to
put it in, so I didn't do it. Practically it will also probably never
have any impact...

> > +}
> > +
> > +void write_message_body(StreamPort _port, const
> > DeviceDisplayInfo )
> > +{
> > +std::string device_address = info.device_address;
> > +if (device_address.length() > 255) {
> > +syslog(LOG_WARNING,
> > +   "device address of stream id %u is longer than
> > 255 bytes, trimming.", info.stream_id);
> > +device_address = device_address.substr(0, 255);
> > +}
> > +StreamMsgDeviceDisplayInfo strm_msg_info{};
> > +strm_msg_info.stream_id = info.stream_id;
> > +strm_msg_info.device_display_id = info.device_display_id;
> > +strm_msg_info.device_address_len = device_address.length() +
> > 1;
> > +stream_port.write(_msg_info, sizeof(strm_msg_info));
> > +stream_port.write(device_address.c_str(),
> > device_address.length() + 1);
> > +}
> > +};
> > +
> >  static bool streaming_requested = false;
> >  static bool quit_requested = false;
> >  static std::set client_codecs;
> > @@ -217,17 +245,25 @@ do_capture(StreamPort _port, FrameLog
> > _log)
> >  throw std::runtime_error("cannot find a suitable capture
> > system");
> >  }
> >  
> > +std::vector display_info;
> >  try {
> > -std::vector display_info = capture-
> > > get_device_display_info();
> > 
> > -syslog(LOG_DEBUG, "Got device info of %lu devices from
> > the plugin", display_info.size());
> > -for (const auto  : display_info) {
> > -syslog(LOG_DEBUG, "   id %u: device address %s,
> > device display id: %u",
> > -   info.id,
> > -   info.device_address.c_str(),
> > -   info.device_display_id);
> > -}
> > +display_info = capture->get_device_display_info();
> >  } catch (const Error ) {
> > -syslog(LOG_ERR, "Error while getting device info: %s",
> > e.what());
> > +syslog(LOG_ERR, "Error while getting device display
> > info: %s", e.what());
> > +}
> > +
> > +syslog(LOG_DEBUG, "Got device info of %zu devices from the
> > plugin", display_info.size());
> > +for (const auto  : display_info) {
> > +syslog(LOG_DEBUG, "   stream id %u: device address: %s,
> > device display id: %u",
> > +   info.stream_id,
> > +   info.device_address.c_str(),
> > +   info.device_display_id);
> > +}
> > +
> > +if (display_info.size() > 0) {
> > +stream_port.send(display_info[
> > 0]);
> 
> Shouldn't we have some handling here in case size() is greater than 1?
> at least print a warning or something?

You mean if there are more than one display/monitor in the info vector
to print a warning we have more than one display and only stream the
first one? I'm not sure why, but I can add it... 

> > +} else {
> > +syslog(LOG_ERR, "Empty device display info from the
> > plugin");
> >  }
> >  
> >  while (!quit_requested && streaming_requested) {
> 
> 
> Reviewed-by: Jonathon Jongsma 
> 
> 
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH spice-streaming-agent 6/8 v3] Interface + implementation of getting device display info

2019-01-18 Thread Lukáš Hrázký
On Thu, 2019-01-17 at 14:09 -0600, Jonathon Jongsma wrote:
> A couple minor comments below.
> 
> On Wed, 2019-01-16 at 13:52 +0100, Lukáš Hrázký wrote:
> > Adds an interface method to the FrameCapture class to get the device
> > display info (device address and device display id) for each display
> > of
> > the graphics device that is captured.
> > 
> > Also adds functions to the API implementing this functionality for
> > X11
> > in variants with and without DRM (the non-DRM version is rather
> > limited
> > and may not work for more complex setups) as well as some helper
> > functions to make it easier for plugins to implement this and avoid
> > code
> > duplication.
> > 
> > Implements the new interface method for the two built-in plugins
> > (mjpeg-fallback and gst-plugin).
> > 
> > Signed-off-by: Lukáš Hrázký 
> > ---
> >  configure.ac  |   2 +
> >  include/spice-streaming-agent/Makefile.am |   2 +
> >  .../spice-streaming-agent/display-info.hpp|  52 +++
> >  .../spice-streaming-agent/frame-capture.hpp   |  13 +
> >  .../x11-display-info.hpp  |  57 
> >  src/Makefile.am   |   7 +
> >  src/display-info.cpp  | 100 ++
> >  src/gst-plugin.cpp|  14 +
> >  src/mjpeg-fallback.cpp|  17 +-
> >  src/spice-streaming-agent.cpp |  13 +
> >  src/unittests/Makefile.am |   6 +
> >  src/utils.cpp |  46 +++
> >  src/utils.hpp |   4 +
> >  src/x11-display-info.cpp  | 302
> > ++
> >  14 files changed, 633 insertions(+), 2 deletions(-)
> >  create mode 100644 include/spice-streaming-agent/display-info.hpp
> >  create mode 100644 include/spice-streaming-agent/x11-display-
> > info.hpp
> >  create mode 100644 src/display-info.cpp
> >  create mode 100644 src/utils.cpp
> >  create mode 100644 src/x11-display-info.cpp
> > 
> > diff --git a/configure.ac b/configure.ac
> > index e66e6d8..fd18efe 100644
> > --- a/configure.ac
> > +++ b/configure.ac
> > @@ -34,8 +34,10 @@ SPICE_PROTOCOL_MIN_VER=0.12.14
> >  PKG_CHECK_MODULES([SPICE_PROTOCOL], [spice-protocol >=
> > $SPICE_PROTOCOL_MIN_VER])
> >  AC_SUBST([SPICE_PROTOCOL_MIN_VER])
> >  
> > +PKG_CHECK_MODULES(DRM, libdrm)
> >  PKG_CHECK_MODULES(X11, x11)
> >  PKG_CHECK_MODULES(XFIXES, xfixes)
> > +PKG_CHECK_MODULES(XRANDR, xrandr)
> >  
> >  PKG_CHECK_MODULES(JPEG, libjpeg, , [
> >  AC_CHECK_LIB(jpeg, jpeg_destroy_decompress,
> > diff --git a/include/spice-streaming-agent/Makefile.am
> > b/include/spice-streaming-agent/Makefile.am
> > index bcd679b..96c1a57 100644
> > --- a/include/spice-streaming-agent/Makefile.am
> > +++ b/include/spice-streaming-agent/Makefile.am
> > @@ -1,8 +1,10 @@
> >  NULL =
> >  public_includedir = $(includedir)/spice-streaming-agent
> >  public_include_HEADERS = \
> > +   display-info.hpp \
> > error.hpp \
> > frame-capture.hpp \
> > plugin.hpp \
> > +   x11-display-info.hpp \
> > $(NULL)
> >  
> > diff --git a/include/spice-streaming-agent/display-info.hpp
> > b/include/spice-streaming-agent/display-info.hpp
> > new file mode 100644
> > index 000..f16212b
> > --- /dev/null
> > +++ b/include/spice-streaming-agent/display-info.hpp
> > @@ -0,0 +1,52 @@
> > +/* \copyright
> > + * Copyright 2018 Red Hat Inc. All rights reserved.
> > + */
> > +
> > +#ifndef SPICE_STREAMING_AGENT_DISPLAY_INFO_HPP
> > +#define SPICE_STREAMING_AGENT_DISPLAY_INFO_HPP
> > +
> > +#include 
> > +#include 
> > +
> > +
> > +namespace spice __attribute__ ((visibility ("default"))) {
> > +namespace streaming_agent {
> > +
> > +/**
> > + * Lists graphics cards listed in the DRM sybsystem in
> > /sys/class/drm.
> > + * Throws an instance of Error in case of an I/O error.
> > + *
> > + * @return a vector of paths of all graphics cards present in
> > /sys/class/drm
> > + */
> > +std::vector list_cards();
> > +
> > +/**
> > + * Reads a single number in hex format from a file.
> > + * Throws an instance of Error in case of an I/O or parsing error.
> > + *
> > + * @param path the path to the file
> > + * @return the number parsed from the file
> > + */
> > +uint32_t read_hex_numbe

Re: [Spice-devel] [PATCH spice 5/8 v3] Send the graphics device info from streaming agent to the vd_agent

2019-01-18 Thread Lukáš Hrázký
On Thu, 2019-01-17 at 13:10 -0600, Jonathon Jongsma wrote:
> On Wed, 2019-01-16 at 13:52 +0100, Lukáš Hrázký wrote:
> > Adds the graphics device info from the streaming device(s) to the
> > VDAgentGraphicsDeviceInfo message sent to the vd_agent.
> > 
> > Signed-off-by: Lukáš Hrázký 
> > ---
> >  server/red-stream-device.c | 18 +++
> >  server/red-stream-device.h |  7 +
> >  server/reds.c  | 63
> > --
> >  3 files changed, 86 insertions(+), 2 deletions(-)
> > 
> > diff --git a/server/red-stream-device.c b/server/red-stream-device.c
> > index 6c90d77d..e7ed9f76 100644
> > --- a/server/red-stream-device.c
> > +++ b/server/red-stream-device.c
> > @@ -342,6 +342,8 @@ handle_msg_device_display_info(StreamDevice *dev,
> > SpiceCharDeviceInstance *sin)
> >  dev->device_display_info.device_address,
> >  dev->device_display_info.device_display_id);
> >  
> > +reds_send_device_display_info(red_char_device_get_server(RED_CHA
> > R_DEVICE(dev)));
> > +
> >  return true;
> >  }
> >  
> > @@ -799,6 +801,22 @@ stream_device_init(StreamDevice *dev)
> >  dev->msg_len = sizeof(*dev->msg);
> >  }
> >  
> > +StreamDeviceDisplayInfo
> > *stream_device_get_device_display_info(StreamDevice *dev)
> > +{
> > +return >device_display_info;
> > +}
> > +
> > +int32_t stream_device_get_stream_channel_id(StreamDevice *dev)
> > +{
> > +if (dev->stream_channel == NULL) {
> > +return -1;
> > +}
> > +
> > +int32_t channel_id;
> > +g_object_get(dev->stream_channel, "id", _id, NULL);
> > +return channel_id;
> > +}
> > +
> 
> Did you consider using a similar interface to the one used for the QXL
> displays? e.g. _get_device_address() / _get_device_display_ids() / etc?
> 
> I know that the stream device currently (and probably always) only has
> a single display per channel, but part of me wishes the interfaces had
> some consistency.  Not a big issue, just curious.

IIRC I did have a similar interface while I had it handle info for
multiple streams, but after I realized I'm not sure how multiple
streams will be implemented and dumbed it down to a single info
message, I simlified the interface as well. The interface also depends
on that. It is an interface internal to the server, so it can be
changed when multi-monitor support is implemented for streaming...

> Acked-by: Jonathon Jongsma 

Thanks,
Lukas

> >  static StreamDevice *
> >  stream_device_new(SpiceCharDeviceInstance *sin, RedsState *reds)
> >  {
> > diff --git a/server/red-stream-device.h b/server/red-stream-device.h
> > index 996be016..d7ab5e41 100644
> > --- a/server/red-stream-device.h
> > +++ b/server/red-stream-device.h
> > @@ -56,6 +56,13 @@ StreamDevice *stream_device_connect(RedsState
> > *reds, SpiceCharDeviceInstance *si
> >   */
> >  void stream_device_create_channel(StreamDevice *dev);
> >  
> > +StreamDeviceDisplayInfo
> > *stream_device_get_device_display_info(StreamDevice *dev);
> > +
> > +/**
> > + * Returns -1 if the StreamDevice doesn't have a channel yet.
> > + */
> > +int32_t stream_device_get_stream_channel_id(StreamDevice *dev);
> > +
> >  G_END_DECLS
> >  
> >  #endif /* STREAM_DEVICE_H */
> > diff --git a/server/reds.c b/server/reds.c
> > index 88a82419..22e81d73 100644
> > --- a/server/reds.c
> > +++ b/server/reds.c
> > @@ -902,14 +902,33 @@ void reds_send_device_display_info(RedsState
> > *reds)
> >  }
> >  g_debug("Sending device display info to the agent:");
> >  
> > -size_t message_size = sizeof(VDAgentGraphicsDeviceInfo);
> >  QXLInstance *qxl;
> > +RedCharDevice *dev;
> > +
> > +size_t message_size = sizeof(VDAgentGraphicsDeviceInfo);
> > +
> > +// size for the qxl device info
> >  FOREACH_QXL_INSTANCE(reds, qxl) {
> >  message_size +=
> >  (sizeof(VDAgentDeviceDisplayInfo) +
> > strlen(red_qxl_get_device_address(qxl)) + 1) *
> >  red_qxl_get_monitors_count(qxl);
> >  }
> >  
> > +// size for the stream device info
> > +GLIST_FOREACH(reds->char_devices, RedCharDevice, dev) {
> > +if (IS_STREAM_DEVICE(dev)) {
> > +size_t device_address_len =
> > +strlen(stream_device_get_device_display_info(STREAM_
> > DEVICE(dev))->device_address);
&g

Re: [Spice-devel] [PATCH spice-protocol 2/8 v3] Add the StreamMsgGraphicsDeviceInfo message

2019-01-18 Thread Lukáš Hrázký
Hi,

On Thu, 2019-01-17 at 11:23 -0600, Jonathon Jongsma wrote:
> Accidentally sent this on the v2 series, but I'll repeat it here:
> 
> Commit subject mentions the wrong type name?
> StreamMsgGraphicsDeviceInfo != StreamMsgDeviceDisplayInfo

You're right, I'll fix it.

> On Wed, 2019-01-16 at 13:52 +0100, Lukáš Hrázký wrote:
> > The message contains information about the graphics device and
> > monitor
> > belonging to a particular video stream (which maps to a channel) from
> > the streaming agent.
> > 
> > Signed-off-by: Lukáš Hrázký 
> > Acked-by: Frediano Ziglio 
> > ---
> >  spice/stream-device.h | 31 +++
> >  1 file changed, 31 insertions(+)
> > 
> > diff --git a/spice/stream-device.h b/spice/stream-device.h
> > index 6add42b..c70690a 100644
> > --- a/spice/stream-device.h
> > +++ b/spice/stream-device.h
> > @@ -90,6 +90,8 @@ typedef enum StreamMsgType {
> >  STREAM_TYPE_CURSOR_SET,
> >  /* guest cursor position */
> >  STREAM_TYPE_CURSOR_MOVE,
> > +/* the graphics device display information message (device
> > address and display id) */
> > +STREAM_TYPE_DEVICE_DISPLAY_INFO,
> >  } StreamMsgType;
> >  
> >  typedef enum StreamCapabilities {
> > @@ -140,6 +142,35 @@ typedef struct StreamMsgData {
> >  uint8_t data[0];
> >  } StreamMsgData;
> >  
> > +/* This message contains information about the graphics device and
> > monitor
> > + * belonging to a particular video stream (which maps to a channel)
> > from
> > + * the streaming agent.
> > + *
> > + * The device_address is the hardware address of the device (e.g.
> > PCI),
> > + * device_display_id is the id of the monitor on the device.
> > + *
> > + * The supported device address format is:
> > + * "pci//./.../."
> > + *
> > + * The "pci" identifies the rest of the string as a PCI address. It
> > is the only
> > + * supported address at the moment, other identifiers can be
> > introduced later.
> > + *  is the PCI domain, followed by . of any
> > PCI bridges
> > + * in the chain leading to the device. The last . is
> > the
> > + * graphics device. All of , ,  are
> > hexadecimal numbers
> > + * with the following number of digits:
> > + *   : 4
> > + *   : 2
> > + *   : 1
> > + *
> > + * Sent from the streaming agent to the server.
> > + */
> > +typedef struct StreamMsgDeviceDisplayInfo {
> > +uint32_t stream_id;
> > +uint32_t device_display_id;
> > +uint32_t device_address_len;
> > +uint8_t device_address[0];  // a zero-terminated string
> > +} StreamMsgDeviceDisplayInfo;
> > +
> >  /* Tell to stop current stream and possibly start a new one.
> >   * This message is sent by the host to the guest.
> >   * Allows to communicate the codecs supported by the clients.
> 
> 
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH spice-streaming-agent 6/8 v3] Interface + implementation of getting device display info

2019-01-16 Thread Lukáš Hrázký
Adds an interface method to the FrameCapture class to get the device
display info (device address and device display id) for each display of
the graphics device that is captured.

Also adds functions to the API implementing this functionality for X11
in variants with and without DRM (the non-DRM version is rather limited
and may not work for more complex setups) as well as some helper
functions to make it easier for plugins to implement this and avoid code
duplication.

Implements the new interface method for the two built-in plugins
(mjpeg-fallback and gst-plugin).

Signed-off-by: Lukáš Hrázký 
---
 configure.ac  |   2 +
 include/spice-streaming-agent/Makefile.am |   2 +
 .../spice-streaming-agent/display-info.hpp|  52 +++
 .../spice-streaming-agent/frame-capture.hpp   |  13 +
 .../x11-display-info.hpp  |  57 
 src/Makefile.am   |   7 +
 src/display-info.cpp  | 100 ++
 src/gst-plugin.cpp|  14 +
 src/mjpeg-fallback.cpp|  17 +-
 src/spice-streaming-agent.cpp |  13 +
 src/unittests/Makefile.am |   6 +
 src/utils.cpp |  46 +++
 src/utils.hpp |   4 +
 src/x11-display-info.cpp  | 302 ++
 14 files changed, 633 insertions(+), 2 deletions(-)
 create mode 100644 include/spice-streaming-agent/display-info.hpp
 create mode 100644 include/spice-streaming-agent/x11-display-info.hpp
 create mode 100644 src/display-info.cpp
 create mode 100644 src/utils.cpp
 create mode 100644 src/x11-display-info.cpp

diff --git a/configure.ac b/configure.ac
index e66e6d8..fd18efe 100644
--- a/configure.ac
+++ b/configure.ac
@@ -34,8 +34,10 @@ SPICE_PROTOCOL_MIN_VER=0.12.14
 PKG_CHECK_MODULES([SPICE_PROTOCOL], [spice-protocol >= 
$SPICE_PROTOCOL_MIN_VER])
 AC_SUBST([SPICE_PROTOCOL_MIN_VER])
 
+PKG_CHECK_MODULES(DRM, libdrm)
 PKG_CHECK_MODULES(X11, x11)
 PKG_CHECK_MODULES(XFIXES, xfixes)
+PKG_CHECK_MODULES(XRANDR, xrandr)
 
 PKG_CHECK_MODULES(JPEG, libjpeg, , [
 AC_CHECK_LIB(jpeg, jpeg_destroy_decompress,
diff --git a/include/spice-streaming-agent/Makefile.am 
b/include/spice-streaming-agent/Makefile.am
index bcd679b..96c1a57 100644
--- a/include/spice-streaming-agent/Makefile.am
+++ b/include/spice-streaming-agent/Makefile.am
@@ -1,8 +1,10 @@
 NULL =
 public_includedir = $(includedir)/spice-streaming-agent
 public_include_HEADERS = \
+   display-info.hpp \
error.hpp \
frame-capture.hpp \
plugin.hpp \
+   x11-display-info.hpp \
$(NULL)
 
diff --git a/include/spice-streaming-agent/display-info.hpp 
b/include/spice-streaming-agent/display-info.hpp
new file mode 100644
index 000..f16212b
--- /dev/null
+++ b/include/spice-streaming-agent/display-info.hpp
@@ -0,0 +1,52 @@
+/* \copyright
+ * Copyright 2018 Red Hat Inc. All rights reserved.
+ */
+
+#ifndef SPICE_STREAMING_AGENT_DISPLAY_INFO_HPP
+#define SPICE_STREAMING_AGENT_DISPLAY_INFO_HPP
+
+#include 
+#include 
+
+
+namespace spice __attribute__ ((visibility ("default"))) {
+namespace streaming_agent {
+
+/**
+ * Lists graphics cards listed in the DRM sybsystem in /sys/class/drm.
+ * Throws an instance of Error in case of an I/O error.
+ *
+ * @return a vector of paths of all graphics cards present in /sys/class/drm
+ */
+std::vector list_cards();
+
+/**
+ * Reads a single number in hex format from a file.
+ * Throws an instance of Error in case of an I/O or parsing error.
+ *
+ * @param path the path to the file
+ * @return the number parsed from the file
+ */
+uint32_t read_hex_number_from_file(const std::string );
+
+/**
+ * Resolves any symlinks and then extracts the PCI path from the canonical path
+ * to a card. Returns the path in the following format:
+ * "pci//./.../."
+ *
+ *  is the PCI domain, followed by . of any PCI bridges
+ * in the chain leading to the device. The last . is the
+ * graphics device. All of , ,  are hexadecimal numbers
+ * with the following number of digits:
+ *   : 4
+ *   : 2
+ *   : 1
+ *
+ * @param device_path the path to the card
+ * @return the device address
+ */
+std::string get_device_address(const std::string _path);
+
+}} // namespace spice::streaming_agent
+
+#endif // SPICE_STREAMING_AGENT_DISPLAY_INFO_HPP
diff --git a/include/spice-streaming-agent/frame-capture.hpp 
b/include/spice-streaming-agent/frame-capture.hpp
index 51a2987..c244fb9 100644
--- a/include/spice-streaming-agent/frame-capture.hpp
+++ b/include/spice-streaming-agent/frame-capture.hpp
@@ -6,7 +6,11 @@
  */
 #ifndef SPICE_STREAMING_AGENT_FRAME_CAPTURE_HPP
 #define SPICE_STREAMING_AGENT_FRAME_CAPTURE_HPP
+
+#include 
 #include 
+#include 
+#include 
 
 #include 
 
@@ -29,6 +33,13 @@ struct FrameInfo
 bool stream_start;
 };
 
+struct DeviceDisplayInfo
+{
+uint32_t stream_id;
+std::string device

[Spice-devel] [PATCH spice 4/8 v3] Receive the GraphicsDeviceInfo message from the streaming agent

2019-01-16 Thread Lukáš Hrázký
Receives the GraphicsDeviceInfo message from the streaming agent and
stores the data in a list on the streaming device.

Signed-off-by: Lukáš Hrázký 
---
 server/display-limits.h|  3 ++
 server/red-qxl.c   |  2 +-
 server/red-stream-device.c | 78 +-
 server/red-stream-device.h |  8 
 4 files changed, 88 insertions(+), 3 deletions(-)

diff --git a/server/display-limits.h b/server/display-limits.h
index e875149b..d79d3211 100644
--- a/server/display-limits.h
+++ b/server/display-limits.h
@@ -25,4 +25,7 @@
 /** Maximum number of streams created by spice-server */
 #define NUM_STREAMS 50
 
+/** Maximum length of the device address string */
+#define MAX_DEVICE_ADDRESS_LEN 256
+
 #endif /* DISPLAY_LIMITS_H_ */
diff --git a/server/red-qxl.c b/server/red-qxl.c
index a56d9a52..943ccb08 100644
--- a/server/red-qxl.c
+++ b/server/red-qxl.c
@@ -37,11 +37,11 @@
 #include "dispatcher.h"
 #include "red-parse-qxl.h"
 #include "red-channel-client.h"
+#include "display-limits.h"
 
 #include "red-qxl.h"
 
 
-#define MAX_DEVICE_ADDRESS_LEN 256
 #define MAX_MONITORS_COUNT 16
 
 struct QXLState {
diff --git a/server/red-stream-device.c b/server/red-stream-device.c
index 215ddbe7..6c90d77d 100644
--- a/server/red-stream-device.c
+++ b/server/red-stream-device.c
@@ -37,6 +37,7 @@ struct StreamDevice {
 StreamMsgCapabilities capabilities;
 StreamMsgCursorSet cursor_set;
 StreamMsgCursorMove cursor_move;
+StreamMsgDeviceDisplayInfo device_display_info;
 uint8_t buf[STREAM_MSG_CAPABILITIES_MAX_BYTES];
 } *msg;
 uint32_t msg_pos;
@@ -49,6 +50,7 @@ struct StreamDevice {
 CursorChannel *cursor_channel;
 SpiceTimer *close_timer;
 uint32_t frame_mmtime;
+StreamDeviceDisplayInfo device_display_info;
 };
 
 struct StreamDeviceClass {
@@ -64,8 +66,8 @@ static void char_device_set_state(RedCharDevice *char_dev, 
int state);
 typedef bool StreamMsgHandler(StreamDevice *dev, SpiceCharDeviceInstance *sin)
 SPICE_GNUC_WARN_UNUSED_RESULT;
 
-static StreamMsgHandler handle_msg_format, handle_msg_data, 
handle_msg_cursor_set,
-handle_msg_cursor_move, handle_msg_capabilities;
+static StreamMsgHandler handle_msg_format, handle_msg_device_display_info, 
handle_msg_data,
+handle_msg_cursor_set, handle_msg_cursor_move, handle_msg_capabilities;
 
 static bool handle_msg_invalid(StreamDevice *dev, SpiceCharDeviceInstance *sin,
const char *error_msg) 
SPICE_GNUC_WARN_UNUSED_RESULT;
@@ -146,6 +148,13 @@ stream_device_partial_read(StreamDevice *dev, 
SpiceCharDeviceInstance *sin)
 handled = handle_msg_format(dev, sin);
 }
 break;
+case STREAM_TYPE_DEVICE_DISPLAY_INFO:
+if (dev->hdr.size > sizeof(StreamMsgDeviceDisplayInfo) + 
MAX_DEVICE_ADDRESS_LEN) {
+handled = handle_msg_invalid(dev, sin, "StreamMsgDeviceDisplayInfo 
too large");
+} else {
+handled = handle_msg_device_display_info(dev, sin);
+}
+break;
 case STREAM_TYPE_DATA:
 if (dev->hdr.size > 32*1024*1024) {
 handled = handle_msg_invalid(dev, sin, "STREAM_DATA too large");
@@ -271,6 +280,71 @@ handle_msg_format(StreamDevice *dev, 
SpiceCharDeviceInstance *sin)
 return true;
 }
 
+static bool
+handle_msg_device_display_info(StreamDevice *dev, SpiceCharDeviceInstance *sin)
+{
+SpiceCharDeviceInterface *sif = spice_char_device_get_interface(sin);
+
+if (spice_extra_checks) {
+spice_assert(dev->hdr_pos >= sizeof(StreamDevHeader));
+spice_assert(dev->hdr.type == STREAM_TYPE_DEVICE_DISPLAY_INFO);
+}
+
+if (dev->msg_len < dev->hdr.size) {
+dev->msg = g_realloc(dev->msg, dev->hdr.size);
+dev->msg_len = dev->hdr.size;
+}
+
+/* read from device */
+ssize_t n = sif->read(sin, dev->msg->buf + dev->msg_pos, dev->hdr.size - 
dev->msg_pos);
+if (n <= 0) {
+return dev->msg_pos == dev->hdr.size;
+}
+
+dev->msg_pos += n;
+if (dev->msg_pos != dev->hdr.size) { /* some bytes are still missing */
+return false;
+}
+
+StreamMsgDeviceDisplayInfo *display_info_msg = 
>msg->device_display_info;
+
+size_t device_address_len = 
GUINT32_FROM_LE(display_info_msg->device_address_len);
+if (device_address_len > MAX_DEVICE_ADDRESS_LEN) {
+g_warning("Received a device address longer than %u (%zu), "
+  "will be truncated!", MAX_DEVICE_ADDRESS_LEN, 
device_address_len);
+device_address_len = sizeof(dev->device_display_info.device_address);
+}
+
+if (device_address_len == 0) {
+g_warning("Zero length device_address in  DeviceDisplayInfo message, 
ignoring.");
+return true;
+}
+
+if (display_info_msg-&g

[Spice-devel] [PATCH spice 5/8 v3] Send the graphics device info from streaming agent to the vd_agent

2019-01-16 Thread Lukáš Hrázký
Adds the graphics device info from the streaming device(s) to the
VDAgentGraphicsDeviceInfo message sent to the vd_agent.

Signed-off-by: Lukáš Hrázký 
---
 server/red-stream-device.c | 18 +++
 server/red-stream-device.h |  7 +
 server/reds.c  | 63 --
 3 files changed, 86 insertions(+), 2 deletions(-)

diff --git a/server/red-stream-device.c b/server/red-stream-device.c
index 6c90d77d..e7ed9f76 100644
--- a/server/red-stream-device.c
+++ b/server/red-stream-device.c
@@ -342,6 +342,8 @@ handle_msg_device_display_info(StreamDevice *dev, 
SpiceCharDeviceInstance *sin)
 dev->device_display_info.device_address,
 dev->device_display_info.device_display_id);
 
+
reds_send_device_display_info(red_char_device_get_server(RED_CHAR_DEVICE(dev)));
+
 return true;
 }
 
@@ -799,6 +801,22 @@ stream_device_init(StreamDevice *dev)
 dev->msg_len = sizeof(*dev->msg);
 }
 
+StreamDeviceDisplayInfo *stream_device_get_device_display_info(StreamDevice 
*dev)
+{
+return >device_display_info;
+}
+
+int32_t stream_device_get_stream_channel_id(StreamDevice *dev)
+{
+if (dev->stream_channel == NULL) {
+return -1;
+}
+
+int32_t channel_id;
+g_object_get(dev->stream_channel, "id", _id, NULL);
+return channel_id;
+}
+
 static StreamDevice *
 stream_device_new(SpiceCharDeviceInstance *sin, RedsState *reds)
 {
diff --git a/server/red-stream-device.h b/server/red-stream-device.h
index 996be016..d7ab5e41 100644
--- a/server/red-stream-device.h
+++ b/server/red-stream-device.h
@@ -56,6 +56,13 @@ StreamDevice *stream_device_connect(RedsState *reds, 
SpiceCharDeviceInstance *si
  */
 void stream_device_create_channel(StreamDevice *dev);
 
+StreamDeviceDisplayInfo *stream_device_get_device_display_info(StreamDevice 
*dev);
+
+/**
+ * Returns -1 if the StreamDevice doesn't have a channel yet.
+ */
+int32_t stream_device_get_stream_channel_id(StreamDevice *dev);
+
 G_END_DECLS
 
 #endif /* STREAM_DEVICE_H */
diff --git a/server/reds.c b/server/reds.c
index 88a82419..22e81d73 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -902,14 +902,33 @@ void reds_send_device_display_info(RedsState *reds)
 }
 g_debug("Sending device display info to the agent:");
 
-size_t message_size = sizeof(VDAgentGraphicsDeviceInfo);
 QXLInstance *qxl;
+RedCharDevice *dev;
+
+size_t message_size = sizeof(VDAgentGraphicsDeviceInfo);
+
+// size for the qxl device info
 FOREACH_QXL_INSTANCE(reds, qxl) {
 message_size +=
 (sizeof(VDAgentDeviceDisplayInfo) + 
strlen(red_qxl_get_device_address(qxl)) + 1) *
 red_qxl_get_monitors_count(qxl);
 }
 
+// size for the stream device info
+GLIST_FOREACH(reds->char_devices, RedCharDevice, dev) {
+if (IS_STREAM_DEVICE(dev)) {
+size_t device_address_len =
+
strlen(stream_device_get_device_display_info(STREAM_DEVICE(dev))->device_address);
+
+if (device_address_len == 0) {
+// the device info wasn't set (yet), don't send it
+continue;
+}
+
+message_size += (sizeof(VDAgentDeviceDisplayInfo) + 
device_address_len + 1);
+}
+}
+
 RedCharDeviceWriteBuffer *char_dev_buf = 
vdagent_new_write_buffer(reds->agent_dev,
  VD_AGENT_GRAPHICS_DEVICE_INFO,
  message_size,
@@ -925,6 +944,8 @@ void reds_send_device_display_info(RedsState *reds)
 graphics_device_info->count = 0;
 
 VDAgentDeviceDisplayInfo *device_display_info = 
graphics_device_info->display_info;
+
+// add the qxl devices to the message
 FOREACH_QXL_INSTANCE(reds, qxl) {
 for (size_t i = 0; i < red_qxl_get_monitors_count(qxl); ++i) {
 device_display_info->channel_id = qxl->id;
@@ -936,7 +957,45 @@ void reds_send_device_display_info(RedsState *reds)
 device_display_info->device_address_len =
 strlen((char*) device_display_info->device_address) + 1;
 
-g_debug("   channel_id: %u monitor_id: %u, device_address: %s, 
device_display_id: %u",
+g_debug("   (qxl)channel_id: %u monitor_id: %u, 
device_address: %s, device_display_id: %u",
+device_display_info->channel_id,
+device_display_info->monitor_id,
+device_display_info->device_address,
+device_display_info->device_display_id);
+
+device_display_info = (VDAgentDeviceDisplayInfo*) ((char*) 
device_display_info +
+sizeof(VDAgentDeviceDisplayInfo) + 
device_display_info->device_address_len);
+
+graphics_device_info->count++;
+}
+}
+
+// add the stream devices to the message
+GLIST_FOREACH(reds->

[Spice-devel] [PATCH spice-protocol 2/8 v3] Add the StreamMsgGraphicsDeviceInfo message

2019-01-16 Thread Lukáš Hrázký
The message contains information about the graphics device and monitor
belonging to a particular video stream (which maps to a channel) from
the streaming agent.

Signed-off-by: Lukáš Hrázký 
Acked-by: Frediano Ziglio 
---
 spice/stream-device.h | 31 +++
 1 file changed, 31 insertions(+)

diff --git a/spice/stream-device.h b/spice/stream-device.h
index 6add42b..c70690a 100644
--- a/spice/stream-device.h
+++ b/spice/stream-device.h
@@ -90,6 +90,8 @@ typedef enum StreamMsgType {
 STREAM_TYPE_CURSOR_SET,
 /* guest cursor position */
 STREAM_TYPE_CURSOR_MOVE,
+/* the graphics device display information message (device address and 
display id) */
+STREAM_TYPE_DEVICE_DISPLAY_INFO,
 } StreamMsgType;
 
 typedef enum StreamCapabilities {
@@ -140,6 +142,35 @@ typedef struct StreamMsgData {
 uint8_t data[0];
 } StreamMsgData;
 
+/* This message contains information about the graphics device and monitor
+ * belonging to a particular video stream (which maps to a channel) from
+ * the streaming agent.
+ *
+ * The device_address is the hardware address of the device (e.g. PCI),
+ * device_display_id is the id of the monitor on the device.
+ *
+ * The supported device address format is:
+ * "pci//./.../."
+ *
+ * The "pci" identifies the rest of the string as a PCI address. It is the only
+ * supported address at the moment, other identifiers can be introduced later.
+ *  is the PCI domain, followed by . of any PCI bridges
+ * in the chain leading to the device. The last . is the
+ * graphics device. All of , ,  are hexadecimal numbers
+ * with the following number of digits:
+ *   : 4
+ *   : 2
+ *   : 1
+ *
+ * Sent from the streaming agent to the server.
+ */
+typedef struct StreamMsgDeviceDisplayInfo {
+uint32_t stream_id;
+uint32_t device_display_id;
+uint32_t device_address_len;
+uint8_t device_address[0];  // a zero-terminated string
+} StreamMsgDeviceDisplayInfo;
+
 /* Tell to stop current stream and possibly start a new one.
  * This message is sent by the host to the guest.
  * Allows to communicate the codecs supported by the clients.
-- 
2.20.1

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH vd_agent 8/8 v3] Receive the graphics_device_info message

2019-01-16 Thread Lukáš Hrázký
The graphics_device_info message contains the device display ID
information (device address and device display ID). Stores the data in a
hash table in vdagent.

Signed-off-by: Lukáš Hrázký 
---
 src/vdagent/vdagent.c|  3 ++
 src/vdagent/x11-priv.h   |  1 +
 src/vdagent/x11-randr.c  | 65 
 src/vdagent/x11.c| 13 
 src/vdagent/x11.h|  1 +
 src/vdagentd-proto-strings.h |  1 +
 src/vdagentd-proto.h |  1 +
 src/vdagentd/vdagentd.c  | 16 +
 8 files changed, 101 insertions(+)

diff --git a/src/vdagent/vdagent.c b/src/vdagent/vdagent.c
index 9642a30..aa52ee9 100644
--- a/src/vdagent/vdagent.c
+++ b/src/vdagent/vdagent.c
@@ -240,6 +240,9 @@ static void daemon_read_complete(struct udscs_connection 
**connp,
   ((VDAgentFileXferDataMessage 
*)data)->id);
 }
 break;
+case VDAGENTD_GRAPHICS_DEVICE_INFO:
+vdagent_x11_handle_graphics_device_info(agent->x11, data, 
header->size);
+break;
 case VDAGENTD_CLIENT_DISCONNECTED:
 vdagent_clipboards_release_all(agent->clipboards);
 if (vdagent_finalize_file_xfer(agent)) {
diff --git a/src/vdagent/x11-priv.h b/src/vdagent/x11-priv.h
index b31b0a5..0e954cf 100644
--- a/src/vdagent/x11-priv.h
+++ b/src/vdagent/x11-priv.h
@@ -139,6 +139,7 @@ struct vdagent_x11 {
 int xrandr_minor;
 int has_xinerama;
 int dont_send_guest_xorg_res;
+GHashTable *graphics_display_infos;
 };
 
 extern int (*vdagent_x11_prev_error_handler)(Display *, XErrorEvent *);
diff --git a/src/vdagent/x11-randr.c b/src/vdagent/x11-randr.c
index 192b888..405fca9 100644
--- a/src/vdagent/x11-randr.c
+++ b/src/vdagent/x11-randr.c
@@ -727,6 +727,71 @@ static void dump_monitors_config(struct vdagent_x11 *x11,
 }
 }
 
+typedef struct GraphicsDisplayInfo {
+char device_address[256];
+uint32_t device_display_id;
+} GraphicsDisplayInfo;
+
+// handle the device info message from the server. This will allow us to
+// maintain a mapping from spice display id to xrandr output
+void vdagent_x11_handle_graphics_device_info(struct vdagent_x11 *x11, uint8_t 
*data, size_t size)
+{
+VDAgentGraphicsDeviceInfo *graphics_device_info = 
(VDAgentGraphicsDeviceInfo *)data;
+VDAgentDeviceDisplayInfo *device_display_info = 
graphics_device_info->display_info;
+
+void *buffer_end = data + size;
+
+syslog(LOG_INFO, "Received Graphics Device Info:");
+
+for (size_t i = 0; i < graphics_device_info->count; ++i) {
+if ((void*) device_display_info > buffer_end ||
+(void*) (_display_info->device_address +
+device_display_info->device_address_len) > buffer_end) {
+syslog(LOG_ERR, "Malformed graphics_display_info message, "
+   "extends beyond the end of the buffer");
+break;
+}
+
+GraphicsDisplayInfo *value = g_malloc(sizeof(GraphicsDisplayInfo));
+value->device_address[0] = '\0';
+
+size_t device_address_len = device_display_info->device_address_len;
+if (device_address_len > sizeof(value->device_address)) {
+syslog(LOG_ERR, "Received a device address longer than %lu, "
+   "will be truncated!", device_address_len);
+device_address_len = sizeof(value->device_address);
+}
+
+strncpy(value->device_address,
+(char*) device_display_info->device_address,
+device_address_len);
+
+if (device_address_len > 0) {
+value->device_address[device_address_len - 1] = '\0';  // make 
sure the string is terminated
+} else {
+syslog(LOG_WARNING, "Zero length device_address received for 
channel_id: %u, monitor_id: %u",
+   device_display_info->channel_id, 
device_display_info->monitor_id);
+}
+
+value->device_display_id = device_display_info->device_display_id;
+
+syslog(LOG_INFO, "   channel_id: %u monitor_id: %u device_address: %s, 
"
+   "device_display_id: %u",
+   device_display_info->channel_id,
+   device_display_info->monitor_id,
+   value->device_address,
+   value->device_display_id);
+
+g_hash_table_insert(x11->graphics_display_infos,
+GUINT_TO_POINTER(device_display_info->channel_id + 
device_display_info->monitor_id),
+value);
+
+device_display_info = (VDAgentDeviceDisplayInfo*) ((char*) 
device_display_info +
+sizeof(VDAgentDeviceDisplayInfo) + 
device_display_info->device_address_len);
+}
+}
+
+
 /*
  * Set monitor configuration according to client request.
  *
diff --git a/src/vdagent/x11.c b/src/vdagent/x11.c
index 53d3c4

[Spice-devel] [PATCH spice-streaming-agent 7/8 v3] Send the GraphicsDeviceInfo to the server

2019-01-16 Thread Lukáš Hrázký
Adds serialization of the GraphicsDeviceInfo message and sends it to the
server when it starts to stream.

Signed-off-by: Lukáš Hrázký 
---
 src/spice-streaming-agent.cpp | 54 +--
 1 file changed, 45 insertions(+), 9 deletions(-)

diff --git a/src/spice-streaming-agent.cpp b/src/spice-streaming-agent.cpp
index 3024d98..891e4cb 100644
--- a/src/spice-streaming-agent.cpp
+++ b/src/spice-streaming-agent.cpp
@@ -31,6 +31,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -93,6 +94,33 @@ public:
 }
 };
 
+class DeviceDisplayInfoMessage : public 
OutboundMessage
+{
+public:
+DeviceDisplayInfoMessage(const DeviceDisplayInfo ) : 
OutboundMessage(info) {}
+
+static size_t size(const DeviceDisplayInfo )
+{
+return sizeof(PayloadType) + std::min(info.device_address.length(), 
255lu) + 1;
+}
+
+void write_message_body(StreamPort _port, const DeviceDisplayInfo 
)
+{
+std::string device_address = info.device_address;
+if (device_address.length() > 255) {
+syslog(LOG_WARNING,
+   "device address of stream id %u is longer than 255 bytes, 
trimming.", info.stream_id);
+device_address = device_address.substr(0, 255);
+}
+StreamMsgDeviceDisplayInfo strm_msg_info{};
+strm_msg_info.stream_id = info.stream_id;
+strm_msg_info.device_display_id = info.device_display_id;
+strm_msg_info.device_address_len = device_address.length() + 1;
+stream_port.write(_msg_info, sizeof(strm_msg_info));
+stream_port.write(device_address.c_str(), device_address.length() + 1);
+}
+};
+
 static bool streaming_requested = false;
 static bool quit_requested = false;
 static std::set client_codecs;
@@ -217,17 +245,25 @@ do_capture(StreamPort _port, FrameLog _log)
 throw std::runtime_error("cannot find a suitable capture system");
 }
 
+std::vector display_info;
 try {
-std::vector display_info = 
capture->get_device_display_info();
-syslog(LOG_DEBUG, "Got device info of %lu devices from the 
plugin", display_info.size());
-for (const auto  : display_info) {
-syslog(LOG_DEBUG, "   id %u: device address %s, device display 
id: %u",
-   info.id,
-   info.device_address.c_str(),
-   info.device_display_id);
-}
+display_info = capture->get_device_display_info();
 } catch (const Error ) {
-syslog(LOG_ERR, "Error while getting device info: %s", e.what());
+syslog(LOG_ERR, "Error while getting device display info: %s", 
e.what());
+}
+
+syslog(LOG_DEBUG, "Got device info of %zu devices from the plugin", 
display_info.size());
+for (const auto  : display_info) {
+syslog(LOG_DEBUG, "   stream id %u: device address: %s, device 
display id: %u",
+   info.stream_id,
+   info.device_address.c_str(),
+   info.device_display_id);
+}
+
+if (display_info.size() > 0) {
+stream_port.send(display_info[0]);
+} else {
+syslog(LOG_ERR, "Empty device display info from the plugin");
 }
 
 while (!quit_requested && streaming_requested) {
-- 
2.20.1

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH spice-protocol 1/8 v3] Add the VDAgentGraphicsDeviceInfo message

2019-01-16 Thread Lukáš Hrázký
The message serves for passing the device address and device display ID
information for all display channels from SPICE server to the vd_agent.

Signed-off-by: Lukáš Hrázký 
Acked-by: Frediano Ziglio 
---
 spice/vd_agent.h | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/spice/vd_agent.h b/spice/vd_agent.h
index dda7044..42ec77a 100644
--- a/spice/vd_agent.h
+++ b/spice/vd_agent.h
@@ -91,6 +91,7 @@ enum {
 VD_AGENT_CLIENT_DISCONNECTED,
 VD_AGENT_MAX_CLIPBOARD,
 VD_AGENT_AUDIO_VOLUME_SYNC,
+VD_AGENT_GRAPHICS_DEVICE_INFO,
 VD_AGENT_END_MESSAGE,
 };
 
@@ -248,6 +249,27 @@ typedef struct SPICE_ATTR_PACKED VDAgentAudioVolumeSync {
 uint16_t volume[0];
 } VDAgentAudioVolumeSync;
 
+typedef struct SPICE_ATTR_PACKED VDAgentDeviceDisplayInfo {
+uint32_t channel_id;
+uint32_t monitor_id;
+uint32_t device_display_id;
+uint32_t device_address_len;
+uint8_t device_address[0];  // a zero-terminated string
+} VDAgentDeviceDisplayInfo;
+
+
+/* This message contains the mapping of (channel_id, monitor_id) pair to a
+ * "physical" (virtualized) device and its monitor identified by device_address
+ * and device_display_id.
+ *
+ * It's used on the vd_agent to identify the guest monitors for the
+ * mouse_position and monitors_config messages.
+ */
+typedef struct SPICE_ATTR_PACKED VDAgentGraphicsDeviceInfo {
+uint32_t count;
+VDAgentDeviceDisplayInfo display_info[0];
+} VDAgentGraphicsDeviceInfo;
+
 enum {
 VD_AGENT_CAP_MOUSE_STATE = 0,
 VD_AGENT_CAP_MONITORS_CONFIG,
@@ -264,6 +286,7 @@ enum {
 VD_AGENT_CAP_MONITORS_CONFIG_POSITION,
 VD_AGENT_CAP_FILE_XFER_DISABLED,
 VD_AGENT_CAP_FILE_XFER_DETAILED_ERRORS,
+VD_AGENT_CAP_GRAPHICS_DEVICE_INFO,
 VD_AGENT_END_CAP,
 };
 
-- 
2.20.1

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH spice 4/8 v2] Receive the GraphicsDeviceInfo message from the streaming agent

2019-01-16 Thread Lukáš Hrázký
On Tue, 2019-01-15 at 08:31 -0500, Frediano Ziglio wrote:
> > 
> > Receives the GraphicsDeviceInfo message from the streaming agent and
> > stores the data in a list on the streaming device.
> > 
> > Signed-off-by: Lukáš Hrázký 
> > ---
> >  server/display-limits.h|  3 ++
> >  server/red-qxl.c   |  2 +-
> >  server/red-stream-device.c | 67 --
> >  server/red-stream-device.h |  8 +
> >  server/reds.c  |  1 +
> >  5 files changed, 78 insertions(+), 3 deletions(-)
> > 
> > diff --git a/server/display-limits.h b/server/display-limits.h
> > index e875149b..d79d3211 100644
> > --- a/server/display-limits.h
> > +++ b/server/display-limits.h
> > @@ -25,4 +25,7 @@
> >  /** Maximum number of streams created by spice-server */
> >  #define NUM_STREAMS 50
> >  
> > +/** Maximum length of the device address string */
> > +#define MAX_DEVICE_ADDRESS_LEN 256
> > +
> >  #endif /* DISPLAY_LIMITS_H_ */
> > diff --git a/server/red-qxl.c b/server/red-qxl.c
> > index a56d9a52..943ccb08 100644
> > --- a/server/red-qxl.c
> > +++ b/server/red-qxl.c
> > @@ -37,11 +37,11 @@
> >  #include "dispatcher.h"
> >  #include "red-parse-qxl.h"
> >  #include "red-channel-client.h"
> > +#include "display-limits.h"
> >  
> >  #include "red-qxl.h"
> >  
> >  
> > -#define MAX_DEVICE_ADDRESS_LEN 256
> >  #define MAX_MONITORS_COUNT 16
> >  
> >  struct QXLState {
> > diff --git a/server/red-stream-device.c b/server/red-stream-device.c
> > index 215ddbe7..20bf115d 100644
> > --- a/server/red-stream-device.c
> > +++ b/server/red-stream-device.c
> > @@ -37,6 +37,7 @@ struct StreamDevice {
> >  StreamMsgCapabilities capabilities;
> >  StreamMsgCursorSet cursor_set;
> >  StreamMsgCursorMove cursor_move;
> > +StreamMsgDeviceDisplayInfo device_display_info;
> >  uint8_t buf[STREAM_MSG_CAPABILITIES_MAX_BYTES];
> >  } *msg;
> >  uint32_t msg_pos;
> > @@ -49,6 +50,7 @@ struct StreamDevice {
> >  CursorChannel *cursor_channel;
> >  SpiceTimer *close_timer;
> >  uint32_t frame_mmtime;
> > +StreamDeviceDisplayInfo device_display_info;
> >  };
> >  
> >  struct StreamDeviceClass {
> > @@ -64,8 +66,8 @@ static void char_device_set_state(RedCharDevice *char_dev,
> > int state);
> >  typedef bool StreamMsgHandler(StreamDevice *dev, SpiceCharDeviceInstance
> >  *sin)
> >  SPICE_GNUC_WARN_UNUSED_RESULT;
> >  
> > -static StreamMsgHandler handle_msg_format, handle_msg_data,
> > handle_msg_cursor_set,
> > -handle_msg_cursor_move, handle_msg_capabilities;
> > +static StreamMsgHandler handle_msg_format, handle_msg_device_display_info,
> > handle_msg_data,
> > +handle_msg_cursor_set, handle_msg_cursor_move, handle_msg_capabilities;
> >  
> >  static bool handle_msg_invalid(StreamDevice *dev, SpiceCharDeviceInstance
> >  *sin,
> > const char *error_msg)
> > SPICE_GNUC_WARN_UNUSED_RESULT;
> > @@ -146,6 +148,13 @@ stream_device_partial_read(StreamDevice *dev,
> > SpiceCharDeviceInstance *sin)
> >  handled = handle_msg_format(dev, sin);
> >  }
> >  break;
> > +case STREAM_TYPE_DEVICE_DISPLAY_INFO:
> > +if (dev->hdr.size > sizeof(StreamMsgDeviceDisplayInfo) +
> > MAX_DEVICE_ADDRESS_LEN) {
> > +handled = handle_msg_invalid(dev, sin,
> > "StreamMsgDeviceDisplayInfo too large");
> > +} else {
> > +handled = handle_msg_device_display_info(dev, sin);
> > +}
> > +break;
> >  case STREAM_TYPE_DATA:
> >  if (dev->hdr.size > 32*1024*1024) {
> >  handled = handle_msg_invalid(dev, sin, "STREAM_DATA too 
> > large");
> > @@ -271,6 +280,60 @@ handle_msg_format(StreamDevice *dev,
> > SpiceCharDeviceInstance *sin)
> >  return true;
> >  }
> >  
> > +static bool
> > +handle_msg_device_display_info(StreamDevice *dev, SpiceCharDeviceInstance
> > *sin)
> > +{
> > +SpiceCharDeviceInterface *sif = spice_char_device_get_interface(sin);
> > +
> > +if (spice_extra_checks) {
> > +spice_assert(dev->hdr_pos >= sizeof(StreamDevHeader));
> > +spice_assert(dev->hdr.type == STREAM_TYPE_DEVICE_DISPLAY_

[Spice-devel] [PATCH vd_agent 8/8 v2] Receive the graphics_device_info message

2019-01-14 Thread Lukáš Hrázký
The graphics_device_info message contains the device display ID
information (device address and device display ID). Stores the data in a
hash table in vdagent.

Signed-off-by: Lukáš Hrázký 
---
 src/vdagent/vdagent.c|  3 ++
 src/vdagent/x11-priv.h   |  1 +
 src/vdagent/x11-randr.c  | 57 
 src/vdagent/x11.c| 13 
 src/vdagent/x11.h|  1 +
 src/vdagentd-proto-strings.h |  1 +
 src/vdagentd-proto.h |  1 +
 src/vdagentd/vdagentd.c  | 16 ++
 8 files changed, 93 insertions(+)

diff --git a/src/vdagent/vdagent.c b/src/vdagent/vdagent.c
index 9642a30..aa52ee9 100644
--- a/src/vdagent/vdagent.c
+++ b/src/vdagent/vdagent.c
@@ -240,6 +240,9 @@ static void daemon_read_complete(struct udscs_connection 
**connp,
   ((VDAgentFileXferDataMessage 
*)data)->id);
 }
 break;
+case VDAGENTD_GRAPHICS_DEVICE_INFO:
+vdagent_x11_handle_graphics_device_info(agent->x11, data, 
header->size);
+break;
 case VDAGENTD_CLIENT_DISCONNECTED:
 vdagent_clipboards_release_all(agent->clipboards);
 if (vdagent_finalize_file_xfer(agent)) {
diff --git a/src/vdagent/x11-priv.h b/src/vdagent/x11-priv.h
index b31b0a5..0e954cf 100644
--- a/src/vdagent/x11-priv.h
+++ b/src/vdagent/x11-priv.h
@@ -139,6 +139,7 @@ struct vdagent_x11 {
 int xrandr_minor;
 int has_xinerama;
 int dont_send_guest_xorg_res;
+GHashTable *graphics_display_infos;
 };
 
 extern int (*vdagent_x11_prev_error_handler)(Display *, XErrorEvent *);
diff --git a/src/vdagent/x11-randr.c b/src/vdagent/x11-randr.c
index 192b888..478e78b 100644
--- a/src/vdagent/x11-randr.c
+++ b/src/vdagent/x11-randr.c
@@ -727,6 +727,63 @@ static void dump_monitors_config(struct vdagent_x11 *x11,
 }
 }
 
+typedef struct GraphicsDisplayInfo {
+char device_address[256];
+uint32_t device_display_id;
+} GraphicsDisplayInfo;
+
+// handle the device info message from the server. This will allow us to
+// maintain a mapping from spice display id to xrandr output
+void vdagent_x11_handle_graphics_device_info(struct vdagent_x11 *x11, uint8_t 
*data, size_t size)
+{
+VDAgentGraphicsDeviceInfo *graphics_device_info = 
(VDAgentGraphicsDeviceInfo *)data;
+VDAgentDeviceDisplayInfo *device_display_info = 
graphics_device_info->display_info;
+
+void *buffer_end = data + size;
+
+syslog(LOG_INFO, "Received Graphics Device Info:");
+
+for (size_t i = 0; i < graphics_device_info->count; ++i) {
+if ((void*) device_display_info > buffer_end ||
+(void*) (_display_info->device_address +
+device_display_info->device_address_len) > buffer_end) {
+syslog(LOG_ERR, "Malformed graphics_display_info message, "
+   "extends beyond the end of the buffer");
+break;
+}
+
+GraphicsDisplayInfo *value = g_malloc(sizeof(GraphicsDisplayInfo));
+
+size_t device_address_len = device_display_info->device_address_len;
+if (device_address_len > sizeof(value->device_address)) {
+syslog(LOG_ERR, "Received a device address longer than %lu, "
+   "will be truncated!", device_address_len);
+device_address_len = sizeof(value->device_address);
+}
+
+strncpy(value->device_address,
+(char*) device_display_info->device_address,
+device_address_len);
+value->device_address[device_address_len - 1] = '\0';  // make sure 
the string is terminated
+value->device_display_id = device_display_info->device_display_id;
+
+syslog(LOG_INFO, "   channel_id: %u monitor_id: %u device_address: %s, 
"
+   "device_display_id: %u",
+   device_display_info->channel_id,
+   device_display_info->monitor_id,
+   value->device_address,
+   value->device_display_id);
+
+g_hash_table_insert(x11->graphics_display_infos,
+GUINT_TO_POINTER(device_display_info->channel_id + 
device_display_info->monitor_id),
+value);
+
+device_display_info = (VDAgentDeviceDisplayInfo*) ((char*) 
device_display_info +
+sizeof(VDAgentDeviceDisplayInfo) + 
device_display_info->device_address_len);
+}
+}
+
+
 /*
  * Set monitor configuration according to client request.
  *
diff --git a/src/vdagent/x11.c b/src/vdagent/x11.c
index 53d3c48..2473383 100644
--- a/src/vdagent/x11.c
+++ b/src/vdagent/x11.c
@@ -196,6 +196,12 @@ static gchar *vdagent_x11_get_wm_name(struct vdagent_x11 
*x11)
 #endif
 }
 
+static void graphics_display_info_destroy(gpointer gdi)
+{
+g_free(gdi);
+}
+
+
 struct vdagent_x11 *vdagent_x11_create(struct udscs_connection *vdagentd,
 int

[Spice-devel] [PATCH spice-protocol 1/8 v2] Add the VDAgentGraphicsDeviceInfo message

2019-01-14 Thread Lukáš Hrázký
The message serves for passing the device address and device display ID
information for all display channels from SPICE server to the vd_agent.

Signed-off-by: Lukáš Hrázký 
---
 spice/vd_agent.h | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/spice/vd_agent.h b/spice/vd_agent.h
index dda7044..42ec77a 100644
--- a/spice/vd_agent.h
+++ b/spice/vd_agent.h
@@ -91,6 +91,7 @@ enum {
 VD_AGENT_CLIENT_DISCONNECTED,
 VD_AGENT_MAX_CLIPBOARD,
 VD_AGENT_AUDIO_VOLUME_SYNC,
+VD_AGENT_GRAPHICS_DEVICE_INFO,
 VD_AGENT_END_MESSAGE,
 };
 
@@ -248,6 +249,27 @@ typedef struct SPICE_ATTR_PACKED VDAgentAudioVolumeSync {
 uint16_t volume[0];
 } VDAgentAudioVolumeSync;
 
+typedef struct SPICE_ATTR_PACKED VDAgentDeviceDisplayInfo {
+uint32_t channel_id;
+uint32_t monitor_id;
+uint32_t device_display_id;
+uint32_t device_address_len;
+uint8_t device_address[0];  // a zero-terminated string
+} VDAgentDeviceDisplayInfo;
+
+
+/* This message contains the mapping of (channel_id, monitor_id) pair to a
+ * "physical" (virtualized) device and its monitor identified by device_address
+ * and device_display_id.
+ *
+ * It's used on the vd_agent to identify the guest monitors for the
+ * mouse_position and monitors_config messages.
+ */
+typedef struct SPICE_ATTR_PACKED VDAgentGraphicsDeviceInfo {
+uint32_t count;
+VDAgentDeviceDisplayInfo display_info[0];
+} VDAgentGraphicsDeviceInfo;
+
 enum {
 VD_AGENT_CAP_MOUSE_STATE = 0,
 VD_AGENT_CAP_MONITORS_CONFIG,
@@ -264,6 +286,7 @@ enum {
 VD_AGENT_CAP_MONITORS_CONFIG_POSITION,
 VD_AGENT_CAP_FILE_XFER_DISABLED,
 VD_AGENT_CAP_FILE_XFER_DETAILED_ERRORS,
+VD_AGENT_CAP_GRAPHICS_DEVICE_INFO,
 VD_AGENT_END_CAP,
 };
 
-- 
2.20.1

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH spice 5/8 v2] Send the graphics device info from streaming agent to the vd_agent

2019-01-14 Thread Lukáš Hrázký
Adds the graphics device info from the streaming device(s) to the
VDAgentGraphicsDeviceInfo message sent to the vd_agent.

Signed-off-by: Lukáš Hrázký 
---
 server/red-stream-device.c | 18 +++
 server/red-stream-device.h |  7 +
 server/reds.c  | 63 --
 3 files changed, 86 insertions(+), 2 deletions(-)

diff --git a/server/red-stream-device.c b/server/red-stream-device.c
index 20bf115d..0e36ba34 100644
--- a/server/red-stream-device.c
+++ b/server/red-stream-device.c
@@ -331,6 +331,8 @@ handle_msg_device_display_info(StreamDevice *dev, 
SpiceCharDeviceInstance *sin)
 dev->device_display_info.device_address,
 dev->device_display_info.device_display_id);
 
+
reds_send_device_display_info(red_char_device_get_server(RED_CHAR_DEVICE(dev)));
+
 return true;
 }
 
@@ -788,6 +790,22 @@ stream_device_init(StreamDevice *dev)
 dev->msg_len = sizeof(*dev->msg);
 }
 
+StreamDeviceDisplayInfo *stream_device_get_device_display_info(StreamDevice 
*dev)
+{
+return >device_display_info;
+}
+
+int32_t stream_device_get_stream_channel_id(StreamDevice *dev)
+{
+if (dev->stream_channel == NULL) {
+return -1;
+}
+
+int32_t channel_id;
+g_object_get(dev->stream_channel, "id", _id, NULL);
+return channel_id;
+}
+
 static StreamDevice *
 stream_device_new(SpiceCharDeviceInstance *sin, RedsState *reds)
 {
diff --git a/server/red-stream-device.h b/server/red-stream-device.h
index 996be016..d7ab5e41 100644
--- a/server/red-stream-device.h
+++ b/server/red-stream-device.h
@@ -56,6 +56,13 @@ StreamDevice *stream_device_connect(RedsState *reds, 
SpiceCharDeviceInstance *si
  */
 void stream_device_create_channel(StreamDevice *dev);
 
+StreamDeviceDisplayInfo *stream_device_get_device_display_info(StreamDevice 
*dev);
+
+/**
+ * Returns -1 if the StreamDevice doesn't have a channel yet.
+ */
+int32_t stream_device_get_stream_channel_id(StreamDevice *dev);
+
 G_END_DECLS
 
 #endif /* STREAM_DEVICE_H */
diff --git a/server/reds.c b/server/reds.c
index 48796ba6..67aa862a 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -903,14 +903,33 @@ void reds_send_device_display_info(RedsState *reds)
 }
 g_debug("Sending device display info to the agent:");
 
-size_t message_size = sizeof(VDAgentGraphicsDeviceInfo);
 QXLInstance *qxl;
+RedCharDevice *dev;
+
+size_t message_size = sizeof(VDAgentGraphicsDeviceInfo);
+
+// size for the qxl device info
 FOREACH_QXL_INSTANCE(reds, qxl) {
 message_size +=
 (sizeof(VDAgentDeviceDisplayInfo) + 
strlen(red_qxl_get_device_address(qxl)) + 1) *
 red_qxl_get_monitors_count(qxl);
 }
 
+// size for the stream device info
+GLIST_FOREACH(reds->char_devices, RedCharDevice, dev) {
+if (IS_STREAM_DEVICE(dev)) {
+size_t device_address_len =
+
strlen(stream_device_get_device_display_info(STREAM_DEVICE(dev))->device_address);
+
+if (device_address_len == 0) {
+// the device info wasn't set (yet), don't send it
+continue;
+}
+
+message_size += (sizeof(VDAgentDeviceDisplayInfo) + 
device_address_len + 1);
+}
+}
+
 RedCharDeviceWriteBuffer *char_dev_buf = 
vdagent_new_write_buffer(reds->agent_dev,
  VD_AGENT_GRAPHICS_DEVICE_INFO,
  message_size,
@@ -926,6 +945,8 @@ void reds_send_device_display_info(RedsState *reds)
 graphics_device_info->count = 0;
 
 VDAgentDeviceDisplayInfo *device_display_info = 
graphics_device_info->display_info;
+
+// add the qxl devices to the message
 FOREACH_QXL_INSTANCE(reds, qxl) {
 for (size_t i = 0; i < red_qxl_get_monitors_count(qxl); ++i) {
 device_display_info->channel_id = qxl->id;
@@ -937,7 +958,45 @@ void reds_send_device_display_info(RedsState *reds)
 device_display_info->device_address_len =
 strlen((char*) device_display_info->device_address) + 1;
 
-g_debug("   channel_id: %u monitor_id: %u, device_address: %s, 
device_display_id: %u",
+g_debug("   (qxl)channel_id: %u monitor_id: %u, 
device_address: %s, device_display_id: %u",
+device_display_info->channel_id,
+device_display_info->monitor_id,
+device_display_info->device_address,
+device_display_info->device_display_id);
+
+device_display_info = (VDAgentDeviceDisplayInfo*) ((char*) 
device_display_info +
+sizeof(VDAgentDeviceDisplayInfo) + 
device_display_info->device_address_len);
+
+graphics_device_info->count++;
+}
+}
+
+// add the stream devices to the message
+GLIST_FOREACH(reds->

[Spice-devel] [PATCH spice-streaming-agent 7/8 v2] Interface + implementation of getting device display info

2019-01-14 Thread Lukáš Hrázký
Adds an interface method to the FrameCapture class to get the device
display info (device address and device display id) for each display of
the graphics device that is captured.

Also adds functions to the API implementing this functionality for X11
in variants with and without DRM (the non-DRM version is rather limited
and may not work for more complex setups) as well as some helper
functions to make it easier for plugins to implement this and avoid code
duplication.

Implements the new interface method for the two built-in plugins
(mjpeg-fallback and gst-plugin).

Signed-off-by: Lukáš Hrázký 
---
 configure.ac  |   2 +
 include/spice-streaming-agent/Makefile.am |   2 +
 .../spice-streaming-agent/display-info.hpp|  52 +++
 .../spice-streaming-agent/frame-capture.hpp   |  13 +
 .../x11-display-info.hpp  |  57 
 src/Makefile.am   |   7 +
 src/display-info.cpp  | 100 ++
 src/gst-plugin.cpp|  14 +
 src/mjpeg-fallback.cpp|  17 +-
 src/spice-streaming-agent.cpp |  49 +++
 src/unittests/Makefile.am |   6 +
 src/utils.cpp |  46 +++
 src/utils.hpp |   4 +
 src/x11-display-info.cpp  | 302 ++
 14 files changed, 669 insertions(+), 2 deletions(-)
 create mode 100644 include/spice-streaming-agent/display-info.hpp
 create mode 100644 include/spice-streaming-agent/x11-display-info.hpp
 create mode 100644 src/display-info.cpp
 create mode 100644 src/utils.cpp
 create mode 100644 src/x11-display-info.cpp

diff --git a/configure.ac b/configure.ac
index e66e6d8..fd18efe 100644
--- a/configure.ac
+++ b/configure.ac
@@ -34,8 +34,10 @@ SPICE_PROTOCOL_MIN_VER=0.12.14
 PKG_CHECK_MODULES([SPICE_PROTOCOL], [spice-protocol >= 
$SPICE_PROTOCOL_MIN_VER])
 AC_SUBST([SPICE_PROTOCOL_MIN_VER])
 
+PKG_CHECK_MODULES(DRM, libdrm)
 PKG_CHECK_MODULES(X11, x11)
 PKG_CHECK_MODULES(XFIXES, xfixes)
+PKG_CHECK_MODULES(XRANDR, xrandr)
 
 PKG_CHECK_MODULES(JPEG, libjpeg, , [
 AC_CHECK_LIB(jpeg, jpeg_destroy_decompress,
diff --git a/include/spice-streaming-agent/Makefile.am 
b/include/spice-streaming-agent/Makefile.am
index bcd679b..96c1a57 100644
--- a/include/spice-streaming-agent/Makefile.am
+++ b/include/spice-streaming-agent/Makefile.am
@@ -1,8 +1,10 @@
 NULL =
 public_includedir = $(includedir)/spice-streaming-agent
 public_include_HEADERS = \
+   display-info.hpp \
error.hpp \
frame-capture.hpp \
plugin.hpp \
+   x11-display-info.hpp \
$(NULL)
 
diff --git a/include/spice-streaming-agent/display-info.hpp 
b/include/spice-streaming-agent/display-info.hpp
new file mode 100644
index 000..f16212b
--- /dev/null
+++ b/include/spice-streaming-agent/display-info.hpp
@@ -0,0 +1,52 @@
+/* \copyright
+ * Copyright 2018 Red Hat Inc. All rights reserved.
+ */
+
+#ifndef SPICE_STREAMING_AGENT_DISPLAY_INFO_HPP
+#define SPICE_STREAMING_AGENT_DISPLAY_INFO_HPP
+
+#include 
+#include 
+
+
+namespace spice __attribute__ ((visibility ("default"))) {
+namespace streaming_agent {
+
+/**
+ * Lists graphics cards listed in the DRM sybsystem in /sys/class/drm.
+ * Throws an instance of Error in case of an I/O error.
+ *
+ * @return a vector of paths of all graphics cards present in /sys/class/drm
+ */
+std::vector list_cards();
+
+/**
+ * Reads a single number in hex format from a file.
+ * Throws an instance of Error in case of an I/O or parsing error.
+ *
+ * @param path the path to the file
+ * @return the number parsed from the file
+ */
+uint32_t read_hex_number_from_file(const std::string );
+
+/**
+ * Resolves any symlinks and then extracts the PCI path from the canonical path
+ * to a card. Returns the path in the following format:
+ * "pci//./.../."
+ *
+ *  is the PCI domain, followed by . of any PCI bridges
+ * in the chain leading to the device. The last . is the
+ * graphics device. All of , ,  are hexadecimal numbers
+ * with the following number of digits:
+ *   : 4
+ *   : 2
+ *   : 1
+ *
+ * @param device_path the path to the card
+ * @return the device address
+ */
+std::string get_device_address(const std::string _path);
+
+}} // namespace spice::streaming_agent
+
+#endif // SPICE_STREAMING_AGENT_DISPLAY_INFO_HPP
diff --git a/include/spice-streaming-agent/frame-capture.hpp 
b/include/spice-streaming-agent/frame-capture.hpp
index 51a2987..c244fb9 100644
--- a/include/spice-streaming-agent/frame-capture.hpp
+++ b/include/spice-streaming-agent/frame-capture.hpp
@@ -6,7 +6,11 @@
  */
 #ifndef SPICE_STREAMING_AGENT_FRAME_CAPTURE_HPP
 #define SPICE_STREAMING_AGENT_FRAME_CAPTURE_HPP
+
+#include 
 #include 
+#include 
+#include 
 
 #include 
 
@@ -29,6 +33,13 @@ struct FrameInfo
 bool stream_start;
 };
 
+struct DeviceDisplayInfo
+{
+uint32_t stream_id;
+std::string device

[Spice-devel] [PATCH spice 3/8 v2] Send the graphics device info to the vd_agent

2019-01-14 Thread Lukáš Hrázký
Sends the device address and device display IDs to the vdagent. The
message is sent either in reaction to the SPICE_MSGC_MAIN_AGENT_START
message or when the graphics device info changes.

Signed-off-by: Lukáš Hrázký 
---
 server/red-qxl.c  | 20 +
 server/red-qxl.h  |  3 ++
 server/reds-private.h |  1 +
 server/reds.c | 67 +++
 server/reds.h |  1 +
 5 files changed, 92 insertions(+)

diff --git a/server/red-qxl.c b/server/red-qxl.c
index 291fd803..a56d9a52 100644
--- a/server/red-qxl.c
+++ b/server/red-qxl.c
@@ -889,6 +889,26 @@ void spice_qxl_set_device_info(QXLInstance *instance,
 
 instance->st->monitors_count = device_display_id_count;
 instance->st->max_monitors = device_display_id_count;
+
+reds_send_device_display_info(red_qxl_get_server(instance->st));
+}
+
+const char* red_qxl_get_device_address(const QXLInstance *qxl)
+{
+const QXLState *qxl_state = qxl->st;
+return qxl_state->device_address;
+}
+
+const uint32_t* red_qxl_get_device_display_ids(const QXLInstance *qxl)
+{
+const QXLState *qxl_state = qxl->st;
+return qxl_state->device_display_ids;
+}
+
+size_t red_qxl_get_monitors_count(const QXLInstance *qxl)
+{
+const QXLState *qxl_state = qxl->st;
+return qxl_state->monitors_count;
 }
 
 void red_qxl_init(RedsState *reds, QXLInstance *qxl)
diff --git a/server/red-qxl.h b/server/red-qxl.h
index 6014d32a..94753948 100644
--- a/server/red-qxl.h
+++ b/server/red-qxl.h
@@ -40,6 +40,9 @@ void red_qxl_put_gl_scanout(QXLInstance *qxl, 
SpiceMsgDisplayGlScanoutUnix *scan
 void red_qxl_gl_draw_async_complete(QXLInstance *qxl);
 int red_qxl_check_qxl_version(QXLInstance *qxl, int major, int minor);
 SpiceServer* red_qxl_get_server(QXLState *qxl);
+const char* red_qxl_get_device_address(const QXLInstance *qxl);
+const uint32_t* red_qxl_get_device_display_ids(const QXLInstance *qxl);
+size_t red_qxl_get_monitors_count(const QXLInstance *qxl);
 
 /* Wrappers around QXLInterface vfuncs */
 void red_qxl_get_init_info(QXLInstance *qxl, QXLDevInitInfo *info);
diff --git a/server/reds-private.h b/server/reds-private.h
index 920edc5c..9dbc7fa9 100644
--- a/server/reds-private.h
+++ b/server/reds-private.h
@@ -81,6 +81,7 @@ struct RedsState {
 SpiceWatch *secure_listen_watch;
 RedCharDeviceVDIPort *agent_dev;
 int pending_mouse_event;
+bool pending_device_display_info_message;
 GList *clients;
 MainChannel *main_channel;
 InputsChannel *inputs_channel;
diff --git a/server/reds.c b/server/reds.c
index cdbb94cb..88a82419 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -257,6 +257,7 @@ typedef struct __attribute__ ((__packed__)) VDInternalBuf {
 VDAgentMessage header;
 union {
 VDAgentMouseState mouse_state;
+VDAgentGraphicsDeviceInfo graphics_device_info;
 }
 u;
 } VDInternalBuf;
@@ -894,6 +895,65 @@ static RedPipeItem 
*vdi_port_read_one_msg_from_device(RedCharDevice *self,
 return NULL;
 }
 
+void reds_send_device_display_info(RedsState *reds)
+{
+if (!reds->agent_dev->priv->agent_attached) {
+return;
+}
+g_debug("Sending device display info to the agent:");
+
+size_t message_size = sizeof(VDAgentGraphicsDeviceInfo);
+QXLInstance *qxl;
+FOREACH_QXL_INSTANCE(reds, qxl) {
+message_size +=
+(sizeof(VDAgentDeviceDisplayInfo) + 
strlen(red_qxl_get_device_address(qxl)) + 1) *
+red_qxl_get_monitors_count(qxl);
+}
+
+RedCharDeviceWriteBuffer *char_dev_buf = 
vdagent_new_write_buffer(reds->agent_dev,
+ VD_AGENT_GRAPHICS_DEVICE_INFO,
+ message_size,
+ true);
+
+if (!char_dev_buf) {
+reds->pending_device_display_info_message = true;
+return;
+}
+
+VDInternalBuf *internal_buf = (VDInternalBuf *)char_dev_buf->buf;
+VDAgentGraphicsDeviceInfo *graphics_device_info = 
_buf->u.graphics_device_info;
+graphics_device_info->count = 0;
+
+VDAgentDeviceDisplayInfo *device_display_info = 
graphics_device_info->display_info;
+FOREACH_QXL_INSTANCE(reds, qxl) {
+for (size_t i = 0; i < red_qxl_get_monitors_count(qxl); ++i) {
+device_display_info->channel_id = qxl->id;
+device_display_info->monitor_id = i;
+device_display_info->device_display_id = 
red_qxl_get_device_display_ids(qxl)[i];
+
+strcpy((char*) device_display_info->device_address, 
red_qxl_get_device_address(qxl));
+
+device_display_info->device_address_len =
+strlen((char*) device_display_info->device_address) + 1;
+
+g_debug("   channel_id: %u monitor_id: %u, device_address: %s, 
device_display_id: %u",
+device_display_info->channel_id,
+  

[Spice-devel] [PATCH 0/8 v2] Monitor ID between host and guest

2019-01-14 Thread Lukáš Hrázký
Hello,

this series introduces a new mechanism to identify monitors across the
host and guest boundary, using the pair (device_address and
device_display_id). device_address is a HW address of a graphics device
(a PCI address to be specific, though other address domains can be
used as well), device_display_id is an ID of the monitor on that device.

This information is gathered from QEMU (regular spice) or
spice-streaming-agent (for the streaming channels) and a mapping of
(channel_id, monitor_id) -> (device_address, device_display_id) is sent
from spice server to the vd_agent. vd_agent uses this mapping to
translate the former ID in incoming messages to the latter.

This series follows up on the "QXL interface to set monitor ID" series
[1] and then Jonathon Jongsma's "Use the PCI addr and display ID" [2]
follows up on this to make a complete solution.

You can also find the code in the following branches:
https://gitlab.freedesktop.org/lukash/spice-protocol/commits/monitor-id-v3-2
https://gitlab.freedesktop.org/lukash/spice/commits/monitor-id-v3-2
https://gitlab.freedesktop.org/lukash/spice-streaming-agent/commits/monitor-id-v3-2
https://gitlab.freedesktop.org/lukash/vd_agent/commits/monitor-id-v3-2

Cheers,
Lukas


Changes since v1:
* Documentation, coding style updates.
* Renamed StreamMsgDeviceDisplayInfo::id to stream_id.
* Renamed VDAgentGraphicsDeviceInfo::device_info to display_info.
* Moved MAX_DEVICE_ADDRESS_LEN to display-limits.h.
* Fixed the format string for size_t (%lu -> %zu).
* Fixed endianness conversion in receiving the display info message in
  the server.
* Fixed buffer overflow when terminating the device_address string in
  the server.
* Handle stream_channel == NULL in stream_device_get_stream_channel_id.
* Put two supported case examples instead of one unsupported to
  spice_qxl_set_device_info() interface documentation.
* Renamed x-display-info.{c,h}pp to x11-display-info.{c,h}pp in
  spice-streaming-agent.
* Fixed sscanf %n in spice-streaming-agent.
* Made drm_fd and drm_resources private in DrmOutputGetter in
  spice-streaming-agent.


[1] https://lists.freedesktop.org/archives/spice-devel/2019-January/046997.html
[2] https://lists.freedesktop.org/archives/spice-devel/2019-January/046939.html

-- 
2.20.1

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH spice-protocol 2/8 v2] Add the StreamMsgGraphicsDeviceInfo message

2019-01-14 Thread Lukáš Hrázký
The message contains information about the graphics device and monitor
belonging to a particular video stream (which maps to a channel) from
the streaming agent.

Signed-off-by: Lukáš Hrázký 
---
 spice/stream-device.h | 31 +++
 1 file changed, 31 insertions(+)

diff --git a/spice/stream-device.h b/spice/stream-device.h
index 6add42b..c70690a 100644
--- a/spice/stream-device.h
+++ b/spice/stream-device.h
@@ -90,6 +90,8 @@ typedef enum StreamMsgType {
 STREAM_TYPE_CURSOR_SET,
 /* guest cursor position */
 STREAM_TYPE_CURSOR_MOVE,
+/* the graphics device display information message (device address and 
display id) */
+STREAM_TYPE_DEVICE_DISPLAY_INFO,
 } StreamMsgType;
 
 typedef enum StreamCapabilities {
@@ -140,6 +142,35 @@ typedef struct StreamMsgData {
 uint8_t data[0];
 } StreamMsgData;
 
+/* This message contains information about the graphics device and monitor
+ * belonging to a particular video stream (which maps to a channel) from
+ * the streaming agent.
+ *
+ * The device_address is the hardware address of the device (e.g. PCI),
+ * device_display_id is the id of the monitor on the device.
+ *
+ * The supported device address format is:
+ * "pci//./.../."
+ *
+ * The "pci" identifies the rest of the string as a PCI address. It is the only
+ * supported address at the moment, other identifiers can be introduced later.
+ *  is the PCI domain, followed by . of any PCI bridges
+ * in the chain leading to the device. The last . is the
+ * graphics device. All of , ,  are hexadecimal numbers
+ * with the following number of digits:
+ *   : 4
+ *   : 2
+ *   : 1
+ *
+ * Sent from the streaming agent to the server.
+ */
+typedef struct StreamMsgDeviceDisplayInfo {
+uint32_t stream_id;
+uint32_t device_display_id;
+uint32_t device_address_len;
+uint8_t device_address[0];  // a zero-terminated string
+} StreamMsgDeviceDisplayInfo;
+
 /* Tell to stop current stream and possibly start a new one.
  * This message is sent by the host to the guest.
  * Allows to communicate the codecs supported by the clients.
-- 
2.20.1

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH spice-streaming-agent 6/8 v2] Export symbols in the binary to use by the plugins

2019-01-14 Thread Lukáš Hrázký
This commits adds the -export-dynamic linker flag to export dynamic
symbols to be used by the streaming agent's plugins. It also adds the
-fvisibility=hidden compiler flag to hide all symbols by default (along
with -fvisibility-inline-hidden for C++ inline functions).

Then it adds the visibility("default") attribute to the namespace
containing the Error class, as that one needs to be exported and have
its typeinfo defined for exception catching to work.

Signed-off-by: Lukáš Hrázký 
Acked-by: Frediano Ziglio 
---
 include/spice-streaming-agent/error.hpp | 2 +-
 src/Makefile.am | 4 
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/include/spice-streaming-agent/error.hpp 
b/include/spice-streaming-agent/error.hpp
index 3202d78..c0d4755 100644
--- a/include/spice-streaming-agent/error.hpp
+++ b/include/spice-streaming-agent/error.hpp
@@ -11,7 +11,7 @@
 #include 
 
 
-namespace spice {
+namespace spice __attribute__ ((visibility ("default"))) {
 namespace streaming_agent {
 
 class Error : public std::runtime_error
diff --git a/src/Makefile.am b/src/Makefile.am
index dc64c29..bae3f9d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -22,10 +22,13 @@ AM_CPPFLAGS = \
$(NULL)
 
 AM_CFLAGS = \
+   -fvisibility=hidden \
$(WARN_CFLAGS) \
$(NULL)
 
 AM_CXXFLAGS = \
+   -fvisibility=hidden \
+   -fvisibility-inlines-hidden \
$(WARN_CXXFLAGS) \
$(NULL)
 
@@ -38,6 +41,7 @@ libstreaming_utils_a_SOURCES = \
$(NULL)
 
 spice_streaming_agent_LDFLAGS = \
+   -export-dynamic \
$(RELRO_LDFLAGS) \
$(NO_INDIRECT_LDFLAGS) \
$(NULL)
-- 
2.20.1

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH spice-streaming-agent 6/8] Interface + implementation of getting device display info

2019-01-11 Thread Lukáš Hrázký
On Fri, 2019-01-11 at 06:13 -0500, Frediano Ziglio wrote:
> > 
> > Adds an interface method to the FrameCapture class to get the device
> > display info (device address and device display id) for each display of
> > the graphics device that is captured.
> > 
> > Also adds functions to the API implementing this functionality for X11
> > in variants with and without DRM (the non-DRM version is rather limited
> > and may not work for more complex setups) as well as some helper
> > functions to make it easier for plugins to implement this and avoid code
> > duplication.
> > 
> > Implements the new interface method for the two built-in plugins
> > (mjpeg-fallback and gst-plugin).
> > 
> > Signed-off-by: Lukáš Hrázký 
> > ---
> >  configure.ac  |   2 +
> >  include/spice-streaming-agent/Makefile.am |   2 +
> >  .../spice-streaming-agent/display-info.hpp|  52 +++
> >  .../spice-streaming-agent/frame-capture.hpp   |  13 +
> >  .../spice-streaming-agent/x-display-info.hpp  |  57 
> >  src/Makefile.am   |   7 +
> >  src/display-info.cpp  | 100 ++
> >  src/gst-plugin.cpp|  14 +
> >  src/mjpeg-fallback.cpp|  17 +-
> >  src/spice-streaming-agent.cpp |  13 +
> >  src/unittests/Makefile.am |   6 +
> >  src/utils.cpp |  45 +++
> >  src/utils.hpp |   4 +
> >  src/x-display-info.cpp| 301 ++
> >  14 files changed, 631 insertions(+), 2 deletions(-)
> >  create mode 100644 include/spice-streaming-agent/display-info.hpp
> >  create mode 100644 include/spice-streaming-agent/x-display-info.hpp
> >  create mode 100644 src/display-info.cpp
> >  create mode 100644 src/utils.cpp
> >  create mode 100644 src/x-display-info.cpp
> > 
> > diff --git a/configure.ac b/configure.ac
> > index e66e6d8..fd18efe 100644
> > --- a/configure.ac
> > +++ b/configure.ac
> > @@ -34,8 +34,10 @@ SPICE_PROTOCOL_MIN_VER=0.12.14
> >  PKG_CHECK_MODULES([SPICE_PROTOCOL], [spice-protocol >=
> >  $SPICE_PROTOCOL_MIN_VER])
> >  AC_SUBST([SPICE_PROTOCOL_MIN_VER])
> >  
> > +PKG_CHECK_MODULES(DRM, libdrm)
> >  PKG_CHECK_MODULES(X11, x11)
> >  PKG_CHECK_MODULES(XFIXES, xfixes)
> > +PKG_CHECK_MODULES(XRANDR, xrandr)
> >  
> >  PKG_CHECK_MODULES(JPEG, libjpeg, , [
> >  AC_CHECK_LIB(jpeg, jpeg_destroy_decompress,
> > diff --git a/include/spice-streaming-agent/Makefile.am
> > b/include/spice-streaming-agent/Makefile.am
> > index bcd679b..1125fb4 100644
> > --- a/include/spice-streaming-agent/Makefile.am
> > +++ b/include/spice-streaming-agent/Makefile.am
> > @@ -1,8 +1,10 @@
> >  NULL =
> >  public_includedir = $(includedir)/spice-streaming-agent
> >  public_include_HEADERS = \
> > +   display-info.hpp \
> > error.hpp \
> > frame-capture.hpp \
> > plugin.hpp \
> > +   x-display-info.hpp \
> 
> I would use "x11-" prefix instead of just "x-".

Ok.

> > $(NULL)
> >  
> > diff --git a/include/spice-streaming-agent/display-info.hpp
> > b/include/spice-streaming-agent/display-info.hpp
> > new file mode 100644
> > index 000..f16212b
> > --- /dev/null
> > +++ b/include/spice-streaming-agent/display-info.hpp
> > @@ -0,0 +1,52 @@
> > +/* \copyright
> > + * Copyright 2018 Red Hat Inc. All rights reserved.
> > + */
> > +
> > +#ifndef SPICE_STREAMING_AGENT_DISPLAY_INFO_HPP
> > +#define SPICE_STREAMING_AGENT_DISPLAY_INFO_HPP
> > +
> > +#include 
> > +#include 
> > +
> > +
> > +namespace spice __attribute__ ((visibility ("default"))) {
> > +namespace streaming_agent {
> > +
> > +/**
> > + * Lists graphics cards listed in the DRM sybsystem in /sys/class/drm.
> > + * Throws an instance of Error in case of an I/O error.
> > + *
> > + * @return a vector of paths of all graphics cards present in 
> > /sys/class/drm
> > + */
> > +std::vector list_cards();
> > +
> > +/**
> > + * Reads a single number in hex format from a file.
> > + * Throws an instance of Error in case of an I/O or parsing error.
> > + *
> > + * @param path the path to the file
> > + * @return the number parsed from the file
> > + */
> > +uint32_t read_hex_number_from_file(const std::string );
> > +
> > +

Re: [Spice-devel] [PATCH spice-protocol 2/8] Add the StreamMsgGraphicsDeviceInfo message

2019-01-11 Thread Lukáš Hrázký
On Fri, 2019-01-11 at 05:45 -0500, Frediano Ziglio wrote:
> > On Thu, 2019-01-10 at 14:28 -0600, Jonathon Jongsma wrote:
> > > On Wed, 2019-01-09 at 12:43 +0100, Lukáš Hrázký wrote:
> > > > On Wed, 2019-01-09 at 02:38 -0500, Frediano Ziglio wrote:
> > > > > > 
> > > > > > The message contains information about the graphics device and
> > > > > > monitor
> > > > > > belonging to a particular video stream (which maps to a channel)
> > > > > > from
> > > > > > the streaming agent.
> > > > > > 
> > > > > > Signed-off-by: Lukáš Hrázký 
> > > > > > ---
> > > > > >  spice/stream-device.h | 9 +
> > > > > >  1 file changed, 9 insertions(+)
> > > > > > 
> > > > > > diff --git a/spice/stream-device.h b/spice/stream-device.h
> > > > > > index 6add42b..77d76af 100644
> > > > > > --- a/spice/stream-device.h
> > > > > > +++ b/spice/stream-device.h
> > > > > > @@ -90,6 +90,8 @@ typedef enum StreamMsgType {
> > > > > >  STREAM_TYPE_CURSOR_SET,
> > > > > >  /* guest cursor position */
> > > > > >  STREAM_TYPE_CURSOR_MOVE,
> > > > > > +/* the graphics device display information message (device
> > > > > > address and
> > > > > > display id) */
> > > > > > +STREAM_TYPE_DEVICE_DISPLAY_INFO,
> > > > > >  } StreamMsgType;
> > > > > >  
> > > > > >  typedef enum StreamCapabilities {
> > > > > > @@ -140,6 +142,13 @@ typedef struct StreamMsgData {
> > > > > >  uint8_t data[0];
> > > > > >  } StreamMsgData;
> > > > > >  
> > > > > > +typedef struct StreamMsgDeviceDisplayInfo {
> > > > > 
> > > > > No much documentation, when it is supposed to be sent?
> > > > > In which state?
> > > > > From the agent, from the server or both?
> > > > 
> > > > I'll add some documentation.
> > > > 
> > > > > No capabilities for a new message?
> > > > 
> > > > No, the streaming agent protocol is not stable yet. Better to not add
> > > > a
> > > > capability and make the code more complex if it's not necessary.
> > > > We've
> > > > discussed this before...
> > > > 
> > > > > > +uint32_t id;
> > > > > 
> > > > > I suppose is not the same "device_display_id", not clear what is
> > > > > it.
> > > > 
> > > > Right, this is basically the equivalent of monitor_id, here it is
> > > > kind
> > > > of the ID of the stream to which the display info belongs. It's
> > > > basically just a sequence of 0, 1, 2, ... and since only a single
> > > > stream/monitor is supported at the moment, only a single message of
> > > > this type is sent and it has id = 0.
> > > > 
> > > > Suggestions how to name it? monitor_id? stream_id?
> > > 
> > > I think stream_id may be ok.
> > 
> > I'll wait for Frediano to confirm he's fine with stream_id as well...
> > 
> 
> Fine with me.
> As a base role I think protocol files should be written thinking about
> and external user. External users should rely on few files (headers if
> specific documentation is not provided). If I look at field name "id"
> just don't say much, just an unique identifier amongst all
> StreamMsgDeviceDisplayInfo. Often people says "look at the code", I
> always find it wrong and an excuse to not document the APIs/protocol.
> If I look at the current code this "id" is the Xrand ID. Is it right?
> No, that's why people should write document and stick to it.

You're right. I knew the name "id" is not descriptive enough when
writing it, but wasn't sure what to use at the time and never got back
to fix it.

> > > > > > +uint32_t device_display_id;
> > > > > > +uint32_t device_address_len;
> > > > > 
> > > > > No limit? Is 4gb fine? I suppose you want a length to be able to
> > > > > extend the message in the future, otherwise you can use the size
> > > > > of the message.
> > > > 
> > > > How do you want me to set a limit here? In a comment?
> > > > 
> > > > I 

Re: [Spice-devel] [PATCH spice 1/3] QXL interface: add a function to identify monitors in the guest

2019-01-11 Thread Lukáš Hrázký
On Wed, 2019-01-09 at 11:36 -0600, Jonathon Jongsma wrote:
> On Tue, 2019-01-08 at 16:26 +0100, Lukáš Hrázký wrote:
> > Adds a function to let QEMU provide information to identify graphics
> > devices and their monitors in the guest. The function
> > (spice_qxl_set_device_info) sets the device address (e.g. a PCI path)
> > and monitor ID -> device display ID mapping of displays exposed by
> > given
> > QXL interface.
> 
> 
> In my previous review, I asked for a slightly more explicit explanation
> of the phrase "monitor ID" in the commit log. In this case, "monitor
> ID" is an ID specific to the QXL instance starting at 0 and represents
> the displays that are associated with that particular QXL instance.
> 
> Perhaps it makes sense to rename this "Qxl monitor ID"?

Sorry, I might have forgotten to incorporate some comments on the old
series :/

To reiterate, though, what do you find unclear about the "monitor ID"?
I mean maybe it should be spelled "monitor_id" to make it clearer what
it refers to... Not sure if "Qxl monitor ID" helps, since it is not
strictly related to QXL, but more to the QXL interface (which is used
for all graphic cards, which makes it more confusing)...

> > Signed-off-by: Lukáš Hrázký 
> > ---
> >  server/red-qxl.c | 44 ++
> >  server/spice-qxl.h   | 46
> > 
> >  server/spice-server.syms |  5 +
> >  3 files changed, 95 insertions(+)
> > 
> > diff --git a/server/red-qxl.c b/server/red-qxl.c
> > index 97940611..0ea424cd 100644
> > --- a/server/red-qxl.c
> > +++ b/server/red-qxl.c
> > @@ -41,6 +41,9 @@
> >  #include "red-qxl.h"
> >  
> >  
> > +#define MAX_DEVICE_ADDRESS_LEN 256
> > +#define MAX_MONITORS_COUNT 16
> > +
> >  struct QXLState {
> >  QXLWorker qxl_worker;
> >  QXLInstance *qxl;
> > @@ -53,6 +56,9 @@ struct QXLState {
> >  unsigned int max_monitors;
> >  RedsState *reds;
> >  RedWorker *worker;
> > +char device_address[MAX_DEVICE_ADDRESS_LEN];
> > +uint32_t device_display_ids[MAX_MONITORS_COUNT];
> > +size_t monitors_count;  // length of ^^^
> >  
> >  pthread_mutex_t scanout_mutex;
> >  SpiceMsgDisplayGlScanoutUnix scanout;
> > @@ -846,6 +852,44 @@ void red_qxl_gl_draw_async_complete(QXLInstance
> > *qxl)
> >  red_qxl_async_complete(qxl, cookie);
> >  }
> >  
> > +SPICE_GNUC_VISIBLE
> > +void spice_qxl_set_device_info(QXLInstance *instance,
> > +   const char *device_address,
> > +   uint32_t device_display_id_start,
> > +   uint32_t device_display_id_count)
> > +{
> > +g_return_if_fail(device_address != NULL);
> 
> Just a thought: what if qemu calls this function twice for the same
> instance. In theory this shouldn't happen, but should we be defensive
> and handle it somehow? Print a warning? Just overwrite the previous
> mapping? Right now it looks like we would just overwrite.

I'm pretty sure overwriting is the correct behavior here, no logging
needed? There may be a situation where the info changes in the future,
for whatever reasons. At least this part of the code should be fine
with it (though I'm not sure atm. if e.g. the client would cope well).

> > +
> > +size_t da_len = strnlen(device_address, MAX_DEVICE_ADDRESS_LEN);
> > +if (da_len >= MAX_DEVICE_ADDRESS_LEN) {
> > +spice_error("Device address too long: %lu > %u", da_len,
> > MAX_DEVICE_ADDRESS_LEN);
> 
> Technically, I think the format string for a size_t variable is %zu,
> not %lu

You're right, didn't know that. I think I have some fixing to do :)

> > +return;
> > +}
> > +
> > +if (device_display_id_count > MAX_MONITORS_COUNT) {
> > +spice_error("Device display ID count (%u) is greater than
> > limit %u",
> > +device_display_id_count,
> > +MAX_MONITORS_COUNT);
> > +return;
> > +}
> > +
> > +strncpy(instance->st->device_address, device_address,
> > MAX_DEVICE_ADDRESS_LEN);
> > +
> > +g_debug("QXL Instance %d setting device address \"%s\" and
> > monitor -> device display mapping:",
> > +instance->id,
> > +device_address);
> > +
> > +// store the mapping monitor_id -> device_display_id
> > +for (uint32_t monitor_id = 0; moni

Re: [Spice-devel] [PATCH spice 3/8] Send the graphics device info to the vd_agent

2019-01-11 Thread Lukáš Hrázký
On Thu, 2019-01-10 at 15:07 -0600, Jonathon Jongsma wrote:
> On Tue, 2019-01-08 at 16:28 +0100, Lukáš Hrázký wrote:
> > Sends the device address and device display IDs to the vdagent. The
> > message is sent either in reaction to the SPICE_MSGC_MAIN_AGENT_START
> > message or when the graphics device info changes.
> > 
> > TODO: doesn't resend the message on agent reconnect, FIXIT.
> > 
> > Signed-off-by: Lukáš Hrázký 
> > ---
> >  server/red-qxl.c  | 20 +
> >  server/red-qxl.h  |  3 ++
> >  server/reds-private.h |  1 +
> >  server/reds.c | 67
> > +++
> >  server/reds.h |  1 +
> >  5 files changed, 92 insertions(+)
> > 
> > diff --git a/server/red-qxl.c b/server/red-qxl.c
> > index 6ffd8286..ebc14a46 100644
> > --- a/server/red-qxl.c
> > +++ b/server/red-qxl.c
> > @@ -889,6 +889,26 @@ void spice_qxl_set_device_info(QXLInstance
> > *instance,
> >  
> >  instance->st->monitors_count = device_display_id_count;
> >  instance->st->max_monitors = device_display_id_count;
> > +
> > +reds_send_device_display_info(red_qxl_get_server(instance->st));
> > +}
> > +
> > +const char* red_qxl_get_device_address(const QXLInstance *qxl)
> > +{
> > +const QXLState *qxl_state = qxl->st;
> > +return qxl_state->device_address;
> > +}
> > +
> > +const uint32_t* red_qxl_get_device_display_ids(const QXLInstance
> > *qxl)
> > +{
> > +const QXLState *qxl_state = qxl->st;
> > +return qxl_state->device_display_ids;
> > +}
> > +
> > +size_t red_qxl_get_monitors_count(const QXLInstance *qxl)
> > +{
> > +const QXLState *qxl_state = qxl->st;
> > +return qxl_state->monitors_count;
> >  }
> >  
> >  void red_qxl_init(RedsState *reds, QXLInstance *qxl)
> > diff --git a/server/red-qxl.h b/server/red-qxl.h
> > index 6014d32a..94753948 100644
> > --- a/server/red-qxl.h
> > +++ b/server/red-qxl.h
> > @@ -40,6 +40,9 @@ void red_qxl_put_gl_scanout(QXLInstance *qxl,
> > SpiceMsgDisplayGlScanoutUnix *scan
> >  void red_qxl_gl_draw_async_complete(QXLInstance *qxl);
> >  int red_qxl_check_qxl_version(QXLInstance *qxl, int major, int
> > minor);
> >  SpiceServer* red_qxl_get_server(QXLState *qxl);
> > +const char* red_qxl_get_device_address(const QXLInstance *qxl);
> > +const uint32_t* red_qxl_get_device_display_ids(const QXLInstance
> > *qxl);
> > +size_t red_qxl_get_monitors_count(const QXLInstance *qxl);
> >  
> >  /* Wrappers around QXLInterface vfuncs */
> >  void red_qxl_get_init_info(QXLInstance *qxl, QXLDevInitInfo *info);
> > diff --git a/server/reds-private.h b/server/reds-private.h
> > index 920edc5c..9dbc7fa9 100644
> > --- a/server/reds-private.h
> > +++ b/server/reds-private.h
> > @@ -81,6 +81,7 @@ struct RedsState {
> >  SpiceWatch *secure_listen_watch;
> >  RedCharDeviceVDIPort *agent_dev;
> >  int pending_mouse_event;
> > +bool pending_device_display_info_message;
> >  GList *clients;
> >  MainChannel *main_channel;
> >  InputsChannel *inputs_channel;
> > diff --git a/server/reds.c b/server/reds.c
> > index cdbb94cb..b85758b6 100644
> > --- a/server/reds.c
> > +++ b/server/reds.c
> > @@ -257,6 +257,7 @@ typedef struct __attribute__ ((__packed__))
> > VDInternalBuf {
> >  VDAgentMessage header;
> >  union {
> >  VDAgentMouseState mouse_state;
> > +VDAgentGraphicsDeviceInfo graphics_device_info;
> >  }
> >  u;
> >  } VDInternalBuf;
> > @@ -894,6 +895,65 @@ static RedPipeItem
> > *vdi_port_read_one_msg_from_device(RedCharDevice *self,
> >  return NULL;
> >  }
> >  
> > +void reds_send_device_display_info(RedsState *reds)
> 
> Personally I think a more consistent name would be better here. When I
> see a function called reds_send_*(), my assumption is that it sends a
> message to the client (cf. reds_send_mm_time()). But this function
> sends to to the agent. The other functions in this file that send
> messages to the agent are all named something like reds_handle_* (e.g.
> reds_handle_agent_mouse_event()) or reds_on_* (e.g.
> reds_on_main_agent_data()). Granted, those functions are responding to
> incoming events/messages from the client, so the on_/handle_ names may
> make more sense. But I don't think it would be terrible to name this
> function something like reds_handle_device_display_info() or
> reds_o

Re: [Spice-devel] [PATCH spice-protocol 2/8] Add the StreamMsgGraphicsDeviceInfo message

2019-01-11 Thread Lukáš Hrázký
On Thu, 2019-01-10 at 14:28 -0600, Jonathon Jongsma wrote:
> On Wed, 2019-01-09 at 12:43 +0100, Lukáš Hrázký wrote:
> > On Wed, 2019-01-09 at 02:38 -0500, Frediano Ziglio wrote:
> > > > 
> > > > The message contains information about the graphics device and
> > > > monitor
> > > > belonging to a particular video stream (which maps to a channel)
> > > > from
> > > > the streaming agent.
> > > > 
> > > > Signed-off-by: Lukáš Hrázký 
> > > > ---
> > > >  spice/stream-device.h | 9 +
> > > >  1 file changed, 9 insertions(+)
> > > > 
> > > > diff --git a/spice/stream-device.h b/spice/stream-device.h
> > > > index 6add42b..77d76af 100644
> > > > --- a/spice/stream-device.h
> > > > +++ b/spice/stream-device.h
> > > > @@ -90,6 +90,8 @@ typedef enum StreamMsgType {
> > > >  STREAM_TYPE_CURSOR_SET,
> > > >  /* guest cursor position */
> > > >  STREAM_TYPE_CURSOR_MOVE,
> > > > +/* the graphics device display information message (device
> > > > address and
> > > > display id) */
> > > > +STREAM_TYPE_DEVICE_DISPLAY_INFO,
> > > >  } StreamMsgType;
> > > >  
> > > >  typedef enum StreamCapabilities {
> > > > @@ -140,6 +142,13 @@ typedef struct StreamMsgData {
> > > >  uint8_t data[0];
> > > >  } StreamMsgData;
> > > >  
> > > > +typedef struct StreamMsgDeviceDisplayInfo {
> > > 
> > > No much documentation, when it is supposed to be sent?
> > > In which state?
> > > From the agent, from the server or both?
> > 
> > I'll add some documentation.
> > 
> > > No capabilities for a new message?
> > 
> > No, the streaming agent protocol is not stable yet. Better to not add
> > a
> > capability and make the code more complex if it's not necessary.
> > We've
> > discussed this before...
> > 
> > > > +uint32_t id;
> > > 
> > > I suppose is not the same "device_display_id", not clear what is
> > > it.
> > 
> > Right, this is basically the equivalent of monitor_id, here it is
> > kind
> > of the ID of the stream to which the display info belongs. It's
> > basically just a sequence of 0, 1, 2, ... and since only a single
> > stream/monitor is supported at the moment, only a single message of
> > this type is sent and it has id = 0.
> > 
> > Suggestions how to name it? monitor_id? stream_id?
> 
> I think stream_id may be ok.

I'll wait for Frediano to confirm he's fine with stream_id as well...

> > > > +uint32_t device_display_id;
> > > > +uint32_t device_address_len;
> > > 
> > > No limit? Is 4gb fine? I suppose you want a length to be able to
> > > extend the message in the future, otherwise you can use the size
> > > of the message.
> > 
> > How do you want me to set a limit here? In a comment?
> > 
> > I initially had these wrapped in a message that contained an array of
> > these, hence the length. It is still unclear how this will exactly
> > work
> > with multi-monitor support. This message is likely going to change
> > with
> > that... Should I change it now?
> 
> Personally I would not try to accomodate multimonitor until we know
> what we need.
> 
> > 
> > > > +uint8_t device_address[0];  // a zero-terminated string
> > > 
> > > Encoding? Utf-8?
> > 
> > The contents are the address of the device, I don't think utf really
> > matters here.
> 
> Well, the address format is defined as 
> 
> "pci//./.../."
> 
> So, aside from the string "pci/", the rest is just hex numbers and
> dots. So we don't need to encode a bunch of special characters, just
> characters within the ASCII range. But I don't suppose it would hurt to
> document it as utf-8...

Yes. I would aslo assume utf-8 is the default and there hardly is any
other consideration anyway. If it's not explicitly stated anywhere, I
would just document strings in general being utf-8 encoded in the
protocol and not document it per string?

Cheers,
Lukas

> > > I suppose by "zero-terminated" you mean if not terminated is a
> > > protocol violation.
> > 
> > Yes. Do you prefer something else?
> > 
> > Cheers,
> > Lukas
> > 
> > > > +} StreamMsgDeviceDisplayInfo;
> > > > +
> > > >  /* Tell to stop current stream and possibly start a new one.
> > > >   * This message is sent by the host to the guest.
> > > >   * Allows to communicate the codecs supported by the clients.
> > > 
> > > Frediano
> > 
> > ___
> > Spice-devel mailing list
> > Spice-devel@lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/spice-devel
> 
> 
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH spice-protocol 1/8] Add the VDAgentGraphicsDeviceInfo message

2019-01-11 Thread Lukáš Hrázký
Hi,

On Thu, 2019-01-10 at 14:13 -0600, Jonathon Jongsma wrote:
> On Tue, 2019-01-08 at 16:28 +0100, Lukáš Hrázký wrote:
> > The message serves for passing the device address and device display
> > ID
> > information for all display channels from SPICE server to the
> > vd_agent.
> > 
> > Signed-off-by: Lukáš Hrázký 
> > ---
> >  spice/vd_agent.h | 15 +++
> >  1 file changed, 15 insertions(+)
> > 
> > diff --git a/spice/vd_agent.h b/spice/vd_agent.h
> > index dda7044..5e618b7 100644
> > --- a/spice/vd_agent.h
> > +++ b/spice/vd_agent.h
> > @@ -91,6 +91,7 @@ enum {
> >  VD_AGENT_CLIENT_DISCONNECTED,
> >  VD_AGENT_MAX_CLIPBOARD,
> >  VD_AGENT_AUDIO_VOLUME_SYNC,
> > +VD_AGENT_GRAPHICS_DEVICE_INFO,
> >  VD_AGENT_END_MESSAGE,
> >  };
> >  
> > @@ -248,6 +249,19 @@ typedef struct SPICE_ATTR_PACKED
> > VDAgentAudioVolumeSync {
> >  uint16_t volume[0];
> >  } VDAgentAudioVolumeSync;
> >  
> > +typedef struct SPICE_ATTR_PACKED VDAgentDeviceDisplayInfo {
> > +uint32_t channel_id;
> > +uint32_t monitor_id;
> > +uint32_t device_display_id;
> > +uint32_t device_address_len;
> > +uint8_t device_address[0];  // a zero-terminated string
> > +} VDAgentDeviceDisplayInfo;
> > +
> > +typedef struct SPICE_ATTR_PACKED VDAgentGraphicsDeviceInfo {
> > +uint32_t count;
> > +VDAgentDeviceDisplayInfo device_info[0];
> 
> Just had a thought. I wonder if we should change this member name.
> Given that the type VDAgentGraphicsDeviceInfo ends with the phrase
> "DeviceInfo", a variable of this type is fairly likely to be named
> something like "device_info". In that case, we'd have code like
> device_info.device_info[0], which is a little awkward. 
> 
> Since the type of the member ends with "DisplayInfo", maybe it could be
> something like this instead?
> 
>  VDAgentDeviceDisplayInfo display_info[0]
> 
> Or device_display_info? though that gets a bit too long. If you prefer
> to keep it device_info, I won't argue.

Yes, display_info makes more sense and I think it was actually my
initial intention, but I got confused with the names myself (renaming
it a couple of times as well...). I'll change it.

Thanks,
Lukas

> Jonathon
> 
> > +} VDAgentGraphicsDeviceInfo;
> > +
> >  enum {
> >  VD_AGENT_CAP_MOUSE_STATE = 0,
> >  VD_AGENT_CAP_MONITORS_CONFIG,
> > @@ -264,6 +278,7 @@ enum {
> >  VD_AGENT_CAP_MONITORS_CONFIG_POSITION,
> >  VD_AGENT_CAP_FILE_XFER_DISABLED,
> >  VD_AGENT_CAP_FILE_XFER_DETAILED_ERRORS,
> > +VD_AGENT_CAP_GRAPHICS_DEVICE_INFO,
> >  VD_AGENT_END_CAP,
> >  };
> >  
> 
> 
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH spice 4/8] Receive the GraphicsDeviceInfo message from the streaming agent

2019-01-11 Thread Lukáš Hrázký
Hi,

On Thu, 2019-01-10 at 15:27 -0600, Jonathon Jongsma wrote:
> On Tue, 2019-01-08 at 16:28 +0100, Lukáš Hrázký wrote:
> > Receives the GraphicsDeviceInfo message from the streaming agent and
> > stores the data in a list on the streaming device.
> > 
> > Signed-off-by: Lukáš Hrázký 
> > ---
> >  server/red-qxl.c   |  1 -
> >  server/red-stream-device.c | 66
> > --
> >  server/red-stream-device.h |  8 +
> >  server/reds.h  |  3 ++
> >  4 files changed, 74 insertions(+), 4 deletions(-)
> > 
> > diff --git a/server/red-qxl.c b/server/red-qxl.c
> > index ebc14a46..e174758f 100644
> > --- a/server/red-qxl.c
> > +++ b/server/red-qxl.c
> > @@ -41,7 +41,6 @@
> >  #include "red-qxl.h"
> >  
> >  
> > -#define MAX_DEVICE_ADDRESS_LEN 256
> >  #define MAX_MONITORS_COUNT 16
> >  
> >  struct QXLState {
> > diff --git a/server/red-stream-device.c b/server/red-stream-device.c
> > index 215ddbe7..bbd6874f 100644
> > --- a/server/red-stream-device.c
> > +++ b/server/red-stream-device.c
> > @@ -23,7 +23,6 @@
> >  
> >  #include "stream-channel.h"
> >  #include "cursor-channel.h"
> > -#include "reds.h"
> 
> As far as I can see, we're only adding new code in this file while
> removing an include. That tells me that this include change is
> unrelated to the other changes?

That include was actually moved to the header, see also the discussion
with Frediano if interested, I'll be changing it and this won't be here
anymore.

> >  #define MAX_GUEST_CAPABILITIES_BYTES ((STREAM_CAP_END+7)/8)
> >  
> > @@ -37,6 +36,7 @@ struct StreamDevice {
> >  StreamMsgCapabilities capabilities;
> >  StreamMsgCursorSet cursor_set;
> >  StreamMsgCursorMove cursor_move;
> > +StreamMsgDeviceDisplayInfo device_display_info;
> >  uint8_t buf[STREAM_MSG_CAPABILITIES_MAX_BYTES];
> >  } *msg;
> >  uint32_t msg_pos;
> > @@ -49,6 +49,7 @@ struct StreamDevice {
> >  CursorChannel *cursor_channel;
> >  SpiceTimer *close_timer;
> >  uint32_t frame_mmtime;
> > +StreamDeviceDisplayInfo device_display_info;
> 
> It strikes me as slightly confusing to have both
> StreamDevice.device_display_info and
> StreamDevice.msg.device_display_info

Well, one is in the message as it's being read from the virtio port,
the other is the struct that holds the data in memory. They contain the
same thing. I don't think it's confusing given you understand the
memory structure and how the messages are read and actually kind of
makes sense... It does tell you it's the same thing, just demarshalled
into memory.

Any suggestions to improve it?

Cheers,
Lukas

> >  };
> >  
> >  struct StreamDeviceClass {
> > @@ -64,8 +65,8 @@ static void char_device_set_state(RedCharDevice
> > *char_dev, int state);
> >  typedef bool StreamMsgHandler(StreamDevice *dev,
> > SpiceCharDeviceInstance *sin)
> >  SPICE_GNUC_WARN_UNUSED_RESULT;
> >  
> > -static StreamMsgHandler handle_msg_format, handle_msg_data,
> > handle_msg_cursor_set,
> > -handle_msg_cursor_move, handle_msg_capabilities;
> > +static StreamMsgHandler handle_msg_format,
> > handle_msg_device_display_info, handle_msg_data,
> > +handle_msg_cursor_set, handle_msg_cursor_move,
> > handle_msg_capabilities;
> >  
> >  static bool handle_msg_invalid(StreamDevice *dev,
> > SpiceCharDeviceInstance *sin,
> > const char *error_msg)
> > SPICE_GNUC_WARN_UNUSED_RESULT;
> > @@ -146,6 +147,13 @@ stream_device_partial_read(StreamDevice *dev,
> > SpiceCharDeviceInstance *sin)
> >  handled = handle_msg_format(dev, sin);
> >  }
> >  break;
> > +case STREAM_TYPE_DEVICE_DISPLAY_INFO:
> > +if (dev->hdr.size > sizeof(StreamMsgDeviceDisplayInfo) +
> > MAX_DEVICE_ADDRESS_LEN) {
> > +handled = handle_msg_invalid(dev, sin,
> > "StreamMsgDeviceDisplayInfo too large");
> > +} else {
> > +handled = handle_msg_device_display_info(dev, sin);
> > +}
> > +break;
> >  case STREAM_TYPE_DATA:
> >  if (dev->hdr.size > 32*1024*1024) {
> >  handled = handle_msg_invalid(dev, sin, "STREAM_DATA too
> > large");
> > @@ -271,6 +279,58 @@ handle_msg_format(StreamDevice *dev,
> > SpiceCharDeviceInstance *sin)
> >  return true;
> >  }
> >  
> > +static 

Re: [Spice-devel] [PATCH linux vdagent v3 3/9] Look up and store xrandr output in display map

2019-01-09 Thread Lukáš Hrázký
On Mon, 2019-01-07 at 15:50 -0600, Jonathon Jongsma wrote:
> Instead of storing each device address and device display ID in the hash
> table, simply use the lookup_xrandr_output_for_device_info() function to
> look up the ID of the xrandr output and store that in the hash table.
> ---
>  src/vdagent/x11-priv.h  |  2 +-
>  src/vdagent/x11-randr.c | 47 +++--
>  src/vdagent/x11.c   | 20 ++
>  3 files changed, 30 insertions(+), 39 deletions(-)
> 
> diff --git a/src/vdagent/x11-priv.h b/src/vdagent/x11-priv.h
> index 0e954cf..e487aa2 100644
> --- a/src/vdagent/x11-priv.h
> +++ b/src/vdagent/x11-priv.h
> @@ -139,7 +139,7 @@ struct vdagent_x11 {
>  int xrandr_minor;
>  int has_xinerama;
>  int dont_send_guest_xorg_res;
> -GHashTable *graphics_display_infos;
> +GHashTable *guest_output_map;
>  };
>  
>  extern int (*vdagent_x11_prev_error_handler)(Display *, XErrorEvent *);
> diff --git a/src/vdagent/x11-randr.c b/src/vdagent/x11-randr.c
> index 4fed458..4daacc6 100644
> --- a/src/vdagent/x11-randr.c
> +++ b/src/vdagent/x11-randr.c
> @@ -728,11 +728,6 @@ static void dump_monitors_config(struct vdagent_x11 *x11,
>  }
>  }
>  
> -typedef struct GraphicsDisplayInfo {
> -char device_address[256];
> -uint32_t device_display_id;
> -} GraphicsDisplayInfo;
> -
>  // handle the device info message from the server. This will allow us to
>  // maintain a mapping from spice display id to xrandr output
>  void vdagent_x11_handle_graphics_device_info(struct vdagent_x11 *x11, 
> uint8_t *data, size_t size)
> @@ -753,31 +748,33 @@ void vdagent_x11_handle_graphics_device_info(struct 
> vdagent_x11 *x11, uint8_t *d
>  break;
>  }
>  
> -GraphicsDisplayInfo *value = g_malloc(sizeof(GraphicsDisplayInfo));
> -
> -size_t device_address_len = device_display_info->device_address_len;
> -if (device_address_len > sizeof(value->device_address)) {
> -syslog(LOG_ERR, "Received a device address longer than %lu, "
> -   "will be truncated!", device_address_len);
> -device_address_len = sizeof(value->device_address);
> -}
> +// make sure the string is terminated:
> +
> device_display_info->device_address[device_display_info->device_address_len] 
> = '\0';
>  
> -strncpy(value->device_address,
> -(char*) device_display_info->device_address,
> -device_address_len);
> -value->device_address[device_address_len] = '\0';  // make sure the 
> string is terminated
> -value->device_display_id = device_display_info->device_display_id;
> +RROutput x_output;
> +if (lookup_xrandr_output_for_device_info(device_display_info, 
> x11->display, x11->randr.res, _output)) {

By adding this function call which logs quite a bit, the indented
logging below no longer works well, as it is interrupted by the
unindented log lines from this function.

We can drop the indent but it was quite helpful to visually separate
the logged block, now with quite a bit more log lines it will be much
harder to read. Not sure what else to do though.

Cheers,
Lukas

> +gint64 *value = g_new(gint64, 1);
> +*value = x_output;
>  
> -syslog(LOG_INFO, "   channel_id: %u monitor_id: %u device_address: 
> %s, "
> -   "device_display_id: %u",
> -   device_display_info->channel_id,
> -   device_display_info->monitor_id,
> -   value->device_address,
> -   value->device_display_id);
> +syslog(LOG_INFO, "   channel_id: %u monitor_id: %u 
> device_address: %s, "
> +   "device_display_id: %u xrandr output ID: %lu",
> +   device_display_info->channel_id,
> +   device_display_info->monitor_id,
> +   device_display_info->device_address,
> +   device_display_info->device_display_id,
> +   x_output);
>  
> -g_hash_table_insert(x11->graphics_display_infos,
> +g_hash_table_insert(x11->guest_output_map,
>  GUINT_TO_POINTER(device_display_info->channel_id + 
> device_display_info->monitor_id),
>  value);
> +} else {
> +syslog(LOG_INFO, "   channel_id: %u monitor_id: %u 
> device_address: %s, "
> +   "device_display_id: %u xrandr output ID NOT FOUND",
> +   device_display_info->channel_id,
> +   device_display_info->monitor_id,
> +   device_display_info->device_address,
> +   device_display_info->device_display_id);
> +}
>  
>  device_display_info = (VDAgentDeviceDisplayInfo*) ((char*) 
> device_display_info +
>  sizeof(VDAgentDeviceDisplayInfo) + 
> device_display_info->device_address_len);
> diff --git a/src/vdagent/x11.c b/src/vdagent/x11.c
> index 2473383..a456678 

Re: [Spice-devel] [PATCH linux vdagent v2 1/9] Add lookup_xrand_output_for_device_info()

2019-01-09 Thread Lukáš Hrázký
Hello,

On Thu, 2019-01-03 at 16:45 -0600, Jonathon Jongsma wrote:
> Add a function to look up an xrandr output for a given device display
> id. This uses sysfs and the drm subsystem to lookup information about a
> graphics device output. It then compares the drm output name to xrandr
> output names to try to match that device output to an xrandr output.
> This is necesary for guests that have multiple graphics devices.
> ---
>  Makefile.am   |  14 ++
>  configure.ac  |   1 +
>  src/vdagent/device-info.c | 480 ++
>  src/vdagent/device-info.h |  26 +++
>  tests/test-device-info.c  | 262 +
>  5 files changed, 783 insertions(+)
>  create mode 100644 src/vdagent/device-info.c
>  create mode 100644 src/vdagent/device-info.h
>  create mode 100644 tests/test-device-info.c
> 
> diff --git a/Makefile.am b/Makefile.am
> index 3e405bc..d2f2258 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -12,6 +12,7 @@ common_sources =\
>   $(NULL)
>  
>  src_spice_vdagent_CFLAGS =   \
> + $(DRM_CFLAGS)   \
>   $(X_CFLAGS) \
>   $(SPICE_CFLAGS) \
>   $(GLIB2_CFLAGS) \
> @@ -22,6 +23,7 @@ src_spice_vdagent_CFLAGS =  \
>   $(NULL)
>  
>  src_spice_vdagent_LDADD =\
> + $(DRM_LIBS) \
>   $(X_LIBS)   \
>   $(SPICE_LIBS)   \
>   $(GLIB2_LIBS)   \
> @@ -35,6 +37,8 @@ src_spice_vdagent_SOURCES = \
>   src/vdagent/audio.h \
>   src/vdagent/clipboard.c \
>   src/vdagent/clipboard.h \
> + src/vdagent/device-info.c   \
> + src/vdagent/device-info.h   \
>   src/vdagent/file-xfers.c\
>   src/vdagent/file-xfers.h\
>   src/vdagent/x11-priv.h  \
> @@ -137,3 +141,13 @@ EXTRA_DIST = \
>  DISTCHECK_CONFIGURE_FLAGS =  \
>   --with-init-script=redhat   \
>   $(NULL)
> +
> +tests_test_device_info_LDADD = $(src_spice_vdagent_LDADD)
> +tests_test_device_info_CFLAGS = $(src_spice_vdagent_CFLAGS)
> +
> +check_PROGRAMS = \
> + tests/test-device-info  \
> + $(NULL)
> +
> +TESTS = $(check_PROGRAMS)
> +
> diff --git a/configure.ac b/configure.ac
> index 7cb44db..55b031e 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -105,6 +105,7 @@ PKG_CHECK_MODULES(X, [xfixes xrandr >= 1.3 xinerama x11])
>  PKG_CHECK_MODULES(SPICE, [spice-protocol >= 0.12.13])
>  PKG_CHECK_MODULES(ALSA, [alsa >= 1.0.22])
>  PKG_CHECK_MODULES([DBUS], [dbus-1])
> +PKG_CHECK_MODULES([DRM], [libdrm])
>  
>  if test "$with_session_info" = "auto" || test "$with_session_info" = 
> "systemd"; then
>  PKG_CHECK_MODULES([LIBSYSTEMD_LOGIN],
> diff --git a/src/vdagent/device-info.c b/src/vdagent/device-info.c
> new file mode 100644
> index 000..ead3f24
> --- /dev/null
> +++ b/src/vdagent/device-info.c
> @@ -0,0 +1,480 @@
> +/*  device-info.c utility function for looking up the xrandr output id for a
> + *  given device address and display id
> + *
> + * Copyright 2018 Red Hat, Inc.
> + *
> + * Red Hat Authors:
> + * Jonathon Jongsma 
> + *
> + * This program is free software: you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation, either version 3 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see .
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include "device-info.h"
> +
> +#define PCI_VENDOR_ID_REDHAT 0x1b36
> +#define PCI_VENDOR_ID_REDHAT_QUMRANET 0x1af4 // virtio-gpu
> +#define PCI_VENDOR_ID_INTEL 0x8086
> +#define PCI_VENDOR_ID_NVIDIA 0x10de
> +
> +#define PCI_DEVICE_ID_QXL 0x0100
> +#define PCI_DEVICE_ID_VIRTIO_GPU 0x1050
> +
> +typedef struct PciDevice {
> +int domain;
> +uint8_t bus;
> +uint8_t slot;
> +uint8_t function;
> +} PciDevice;
> +
> +typedef struct PciAddress {
> +int domain;
> +GList *devices; /* PciDevice */
> +} PciAddress;
> +
> +static PciAddress* pci_address_new()
> +{
> +return 

Re: [Spice-devel] [PATCH spice 5/8] Send the graphics device info from streaming agent to the vd_agent

2019-01-09 Thread Lukáš Hrázký
On Wed, 2019-01-09 at 03:25 -0500, Frediano Ziglio wrote:
> > 
> > Adds the graphics device info from the streaming device(s) to the
> > VDAgentGraphicsDeviceInfo message sent to the vd_agent.
> > 
> > Signed-off-by: Lukáš Hrázký 
> > ---
> >  server/red-stream-device.c | 14 ++
> >  server/red-stream-device.h |  4 +++
> >  server/reds.c  | 56 --
> >  3 files changed, 72 insertions(+), 2 deletions(-)
> > 
> > diff --git a/server/red-stream-device.c b/server/red-stream-device.c
> > index bbd6874f..567e7485 100644
> > --- a/server/red-stream-device.c
> > +++ b/server/red-stream-device.c
> > @@ -328,6 +328,8 @@ handle_msg_device_display_info(StreamDevice *dev,
> > SpiceCharDeviceInstance *sin)
> >  dev->device_display_info.device_address,
> >  dev->device_display_info.device_display_id);
> >  
> > +
> > reds_send_device_display_info(red_char_device_get_server(RED_CHAR_DEVICE(dev)));
> > +
> >  return true;
> >  }
> >  
> > @@ -785,6 +787,18 @@ stream_device_init(StreamDevice *dev)
> >  dev->msg_len = sizeof(*dev->msg);
> >  }
> >  
> > +StreamDeviceDisplayInfo *stream_device_get_device_display_info(StreamDevice
> > *dev)
> > +{
> > +return >device_display_info;
> > +}
> > +
> > +uint32_t stream_device_get_stream_channel_id(StreamDevice *dev)
> > +{
> > +uint32_t channel_id;
> > +g_object_get(dev->stream_channel, "id", _id, NULL);
> 
> stream_channel could be NULL if the agent is not connected

Right. It worked for this case, as the function was only called after
the DeviceDIsplayInfo was sent (and stream_channel existed by then),
but I'll fix the function to return -1 in case the stream_channel is
NULL.

> > +return channel_id;
> > +}
> > +
> >  static StreamDevice *
> >  stream_device_new(SpiceCharDeviceInstance *sin, RedsState *reds)
> >  {
> > diff --git a/server/red-stream-device.h b/server/red-stream-device.h
> > index 9e71cb88..0a3ac7f7 100644
> > --- a/server/red-stream-device.h
> > +++ b/server/red-stream-device.h
> > @@ -56,6 +56,10 @@ StreamDevice *stream_device_connect(RedsState *reds,
> > SpiceCharDeviceInstance *si
> >   */
> >  void stream_device_create_channel(StreamDevice *dev);
> >  
> > +StreamDeviceDisplayInfo *stream_device_get_device_display_info(StreamDevice
> > *dev);
> > +
> > +uint32_t stream_device_get_stream_channel_id(StreamDevice *dev);
> > +
> >  G_END_DECLS
> >  
> >  #endif /* STREAM_DEVICE_H */
> > diff --git a/server/reds.c b/server/reds.c
> > index b85758b6..d26fdf65 100644
> > --- a/server/reds.c
> > +++ b/server/reds.c
> > @@ -902,14 +902,33 @@ void reds_send_device_display_info(RedsState *reds)
> >  }
> >  g_debug("Sending device display info to the agent:");
> >  
> > -size_t message_size = sizeof(VDAgentGraphicsDeviceInfo);
> >  QXLInstance *qxl;
> > +RedCharDevice *dev;
> > +
> > +size_t message_size = sizeof(VDAgentGraphicsDeviceInfo);
> > +
> > +// size for the qxl device info
> >  FOREACH_QXL_INSTANCE(reds, qxl) {
> >  message_size +=
> >  (sizeof(VDAgentDeviceDisplayInfo) +
> >  strlen(red_qxl_get_device_address(qxl)) + 1) *
> >  red_qxl_get_monitors_count(qxl);
> >  }
> >  
> > +// size for the stream device info
> > +GLIST_FOREACH(reds->char_devices, RedCharDevice, dev) {
> > +if (IS_STREAM_DEVICE(dev)) {
> > +size_t device_address_len =
> > +
> > strlen(stream_device_get_device_display_info(STREAM_DEVICE(dev))->device_address);
> > +
> > +if (device_address_len == 0) {
> > +// the device info wasn't set (yet), don't send it
> > +continue;
> > +}
> > +
> > +message_size += (sizeof(VDAgentDeviceDisplayInfo) +
> > device_address_len + 1);
> > +}
> > +}
> > +
> >  RedCharDeviceWriteBuffer *char_dev_buf =
> >  vdagent_new_write_buffer(reds->agent_dev,
> >   VD_AGENT_GRAPHICS_DEVICE_INFO,
> >   message_size,
> > @@ -925,6 +944,8 @@ void reds_send_device_display_info(RedsState *reds)
> >  graphics_device_info->count = 0;
> >  
> >  VDAgentDeviceDisplayInfo *device_display_info =
&g

Re: [Spice-devel] [PATCH spice 3/8] Send the graphics device info to the vd_agent

2019-01-09 Thread Lukáš Hrázký
On Wed, 2019-01-09 at 02:50 -0500, Frediano Ziglio wrote:
> > 
> > Sends the device address and device display IDs to the vdagent. The
> > message is sent either in reaction to the SPICE_MSGC_MAIN_AGENT_START
> > message or when the graphics device info changes.
> > 
> > TODO: doesn't resend the message on agent reconnect, FIXIT.
> 
> Why is this a problem? What if the agent get restarted?

Ah, sorry, forgot this TODO here. It is the agent reconnect issue we
discussed (off-list). I'll remove this TODO, we are taking care of it.

> > 
> > Signed-off-by: Lukáš Hrázký 
> > ---
> >  server/red-qxl.c  | 20 +
> >  server/red-qxl.h  |  3 ++
> >  server/reds-private.h |  1 +
> >  server/reds.c | 67 +++
> >  server/reds.h |  1 +
> >  5 files changed, 92 insertions(+)
> > 
> > diff --git a/server/red-qxl.c b/server/red-qxl.c
> > index 6ffd8286..ebc14a46 100644
> > --- a/server/red-qxl.c
> > +++ b/server/red-qxl.c
> > @@ -889,6 +889,26 @@ void spice_qxl_set_device_info(QXLInstance *instance,
> >  
> >  instance->st->monitors_count = device_display_id_count;
> >  instance->st->max_monitors = device_display_id_count;
> > +
> > +reds_send_device_display_info(red_qxl_get_server(instance->st));
> > +}
> > +
> > +const char* red_qxl_get_device_address(const QXLInstance *qxl)
> > +{
> > +const QXLState *qxl_state = qxl->st;
> > +return qxl_state->device_address;
> > +}
> > +
> > +const uint32_t* red_qxl_get_device_display_ids(const QXLInstance *qxl)
> > +{
> > +const QXLState *qxl_state = qxl->st;
> > +return qxl_state->device_display_ids;
> > +}
> > +
> > +size_t red_qxl_get_monitors_count(const QXLInstance *qxl)
> > +{
> > +const QXLState *qxl_state = qxl->st;
> > +return qxl_state->monitors_count;
> >  }
> >  
> >  void red_qxl_init(RedsState *reds, QXLInstance *qxl)
> > diff --git a/server/red-qxl.h b/server/red-qxl.h
> > index 6014d32a..94753948 100644
> > --- a/server/red-qxl.h
> > +++ b/server/red-qxl.h
> > @@ -40,6 +40,9 @@ void red_qxl_put_gl_scanout(QXLInstance *qxl,
> > SpiceMsgDisplayGlScanoutUnix *scan
> >  void red_qxl_gl_draw_async_complete(QXLInstance *qxl);
> >  int red_qxl_check_qxl_version(QXLInstance *qxl, int major, int minor);
> >  SpiceServer* red_qxl_get_server(QXLState *qxl);
> > +const char* red_qxl_get_device_address(const QXLInstance *qxl);
> > +const uint32_t* red_qxl_get_device_display_ids(const QXLInstance *qxl);
> > +size_t red_qxl_get_monitors_count(const QXLInstance *qxl);
> >  
> >  /* Wrappers around QXLInterface vfuncs */
> >  void red_qxl_get_init_info(QXLInstance *qxl, QXLDevInitInfo *info);
> > diff --git a/server/reds-private.h b/server/reds-private.h
> > index 920edc5c..9dbc7fa9 100644
> > --- a/server/reds-private.h
> > +++ b/server/reds-private.h
> > @@ -81,6 +81,7 @@ struct RedsState {
> >  SpiceWatch *secure_listen_watch;
> >  RedCharDeviceVDIPort *agent_dev;
> >  int pending_mouse_event;
> > +bool pending_device_display_info_message;
> >  GList *clients;
> >  MainChannel *main_channel;
> >  InputsChannel *inputs_channel;
> > diff --git a/server/reds.c b/server/reds.c
> > index cdbb94cb..b85758b6 100644
> > --- a/server/reds.c
> > +++ b/server/reds.c
> > @@ -257,6 +257,7 @@ typedef struct __attribute__ ((__packed__)) 
> > VDInternalBuf
> > {
> >  VDAgentMessage header;
> >  union {
> >  VDAgentMouseState mouse_state;
> > +VDAgentGraphicsDeviceInfo graphics_device_info;
> >  }
> >  u;
> >  } VDInternalBuf;
> > @@ -894,6 +895,65 @@ static RedPipeItem
> > *vdi_port_read_one_msg_from_device(RedCharDevice *self,
> >  return NULL;
> >  }
> >  
> > +void reds_send_device_display_info(RedsState *reds)
> > +{
> > +if (!reds->agent_dev->priv->agent_attached) {
> > +return;
> > +}
> 
> I would expect a check for agent capabilities, isn't it necessary?
> Looking at agent code the message won't be ignored, at least it will
> produce an unwanted warning.

It does produce a warning, which I find harmless and better than
introducing a capability, which makes the code more complex and really
has no practical benefit.

Cheers,
Lukas

> > +g_debug("Sending device display info to the agent:");
> > +
> > +size_t message_size = sizeof(VDAge

Re: [Spice-devel] [PATCH spice-protocol 1/8] Add the VDAgentGraphicsDeviceInfo message

2019-01-09 Thread Lukáš Hrázký
On Wed, 2019-01-09 at 06:30 -0500, Frediano Ziglio wrote:
> > 
> > On Wed, 2019-01-09 at 02:41 -0500, Frediano Ziglio wrote:
> > > > 
> > > > The message serves for passing the device address and device display ID
> > > > information for all display channels from SPICE server to the vd_agent.
> > > > 
> > > > Signed-off-by: Lukáš Hrázký 
> > > > ---
> > > >  spice/vd_agent.h | 15 +++
> > > >  1 file changed, 15 insertions(+)
> > > > 
> > > > diff --git a/spice/vd_agent.h b/spice/vd_agent.h
> > > > index dda7044..5e618b7 100644
> > > > --- a/spice/vd_agent.h
> > > > +++ b/spice/vd_agent.h
> > > > @@ -91,6 +91,7 @@ enum {
> > > >  VD_AGENT_CLIENT_DISCONNECTED,
> > > >  VD_AGENT_MAX_CLIPBOARD,
> > > >  VD_AGENT_AUDIO_VOLUME_SYNC,
> > > > +VD_AGENT_GRAPHICS_DEVICE_INFO,
> > > >  VD_AGENT_END_MESSAGE,
> > > >  };
> > > >  
> > > > @@ -248,6 +249,19 @@ typedef struct SPICE_ATTR_PACKED
> > > > VDAgentAudioVolumeSync
> > > > {
> > > >  uint16_t volume[0];
> > > >  } VDAgentAudioVolumeSync;
> > > >  
> > > > +typedef struct SPICE_ATTR_PACKED VDAgentDeviceDisplayInfo {
> > > > +uint32_t channel_id;
> > > > +uint32_t monitor_id;
> > > 
> > > Other parts of the SPICE protocol use 8 bit for these.
> > > Do you want to extend them in the future?
> > > Maybe better to put some comment on possible limits?
> > 
> > channel_id is 8 bits on the client <-> server line, monitor_id is 32
> 
> Yes, confused for monitor_id.
> 
> > bits though. What comment on limits? You need to use existing valid
> > IDs, otherwise it won't work. I don't see any other limitation.
> > 
> > I can change them (or just channel_id) to 8 bits if you want... I'd
> > just leave them like this myself though.
> > 
> 
> or a comment like "// currently limited to 255".

Ok, but I find no value in a comment like this. The fact that a valid
ID will atm. never be greater than 255 does not really impose a limit
here. If you are putting an ID greater than 255 in here, you are
putting a non-existent ID, but that's all. There are always non-
existent IDs that will not work. No difference.

> > > > +uint32_t device_display_id;
> > > > +uint32_t device_address_len;
> > > > +uint8_t device_address[0];  // a zero-terminated string
> > > 
> > > Similar comments for spice-protocol for these last 2 fields.
> > 
> > Not sure what you mean by this...
> > 
> 
> Comments on patch 2/8.

About zero-termination? The length is actually needed here.

> > Cheers,
> > Lukas
> > 
> > > > +} VDAgentDeviceDisplayInfo;
> > > > +
> > > > +typedef struct SPICE_ATTR_PACKED VDAgentGraphicsDeviceInfo {
> > > > +uint32_t count;
> > > > +VDAgentDeviceDisplayInfo device_info[0];
> > > > +} VDAgentGraphicsDeviceInfo;
> > > > +
> > > >  enum {
> > > >  VD_AGENT_CAP_MOUSE_STATE = 0,
> > > >  VD_AGENT_CAP_MONITORS_CONFIG,
> > > > @@ -264,6 +278,7 @@ enum {
> > > >  VD_AGENT_CAP_MONITORS_CONFIG_POSITION,
> > > >  VD_AGENT_CAP_FILE_XFER_DISABLED,
> > > >  VD_AGENT_CAP_FILE_XFER_DETAILED_ERRORS,
> > > > +VD_AGENT_CAP_GRAPHICS_DEVICE_INFO,
> > > >  VD_AGENT_END_CAP,
> > > >  };
> > > >  
> > > 
> > > Frediano
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH spice-protocol 1/8] Add the VDAgentGraphicsDeviceInfo message

2019-01-09 Thread Lukáš Hrázký
On Wed, 2019-01-09 at 02:41 -0500, Frediano Ziglio wrote:
> > 
> > The message serves for passing the device address and device display ID
> > information for all display channels from SPICE server to the vd_agent.
> > 
> > Signed-off-by: Lukáš Hrázký 
> > ---
> >  spice/vd_agent.h | 15 +++
> >  1 file changed, 15 insertions(+)
> > 
> > diff --git a/spice/vd_agent.h b/spice/vd_agent.h
> > index dda7044..5e618b7 100644
> > --- a/spice/vd_agent.h
> > +++ b/spice/vd_agent.h
> > @@ -91,6 +91,7 @@ enum {
> >  VD_AGENT_CLIENT_DISCONNECTED,
> >  VD_AGENT_MAX_CLIPBOARD,
> >  VD_AGENT_AUDIO_VOLUME_SYNC,
> > +VD_AGENT_GRAPHICS_DEVICE_INFO,
> >  VD_AGENT_END_MESSAGE,
> >  };
> >  
> > @@ -248,6 +249,19 @@ typedef struct SPICE_ATTR_PACKED VDAgentAudioVolumeSync
> > {
> >  uint16_t volume[0];
> >  } VDAgentAudioVolumeSync;
> >  
> > +typedef struct SPICE_ATTR_PACKED VDAgentDeviceDisplayInfo {
> > +uint32_t channel_id;
> > +uint32_t monitor_id;
> 
> Other parts of the SPICE protocol use 8 bit for these.
> Do you want to extend them in the future?
> Maybe better to put some comment on possible limits?

channel_id is 8 bits on the client <-> server line, monitor_id is 32
bits though. What comment on limits? You need to use existing valid
IDs, otherwise it won't work. I don't see any other limitation.

I can change them (or just channel_id) to 8 bits if you want... I'd
just leave them like this myself though.

> > +uint32_t device_display_id;
> > +uint32_t device_address_len;
> > +uint8_t device_address[0];  // a zero-terminated string
> 
> Similar comments for spice-protocol for these last 2 fields.

Not sure what you mean by this...

Cheers,
Lukas

> > +} VDAgentDeviceDisplayInfo;
> > +
> > +typedef struct SPICE_ATTR_PACKED VDAgentGraphicsDeviceInfo {
> > +uint32_t count;
> > +VDAgentDeviceDisplayInfo device_info[0];
> > +} VDAgentGraphicsDeviceInfo;
> > +
> >  enum {
> >  VD_AGENT_CAP_MOUSE_STATE = 0,
> >  VD_AGENT_CAP_MONITORS_CONFIG,
> > @@ -264,6 +278,7 @@ enum {
> >  VD_AGENT_CAP_MONITORS_CONFIG_POSITION,
> >  VD_AGENT_CAP_FILE_XFER_DISABLED,
> >  VD_AGENT_CAP_FILE_XFER_DETAILED_ERRORS,
> > +VD_AGENT_CAP_GRAPHICS_DEVICE_INFO,
> >  VD_AGENT_END_CAP,
> >  };
> >  
> 
> Frediano
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH spice-streaming-agent 6/8] Interface + implementation of getting device display info

2019-01-08 Thread Lukáš Hrázký
Adds an interface method to the FrameCapture class to get the device
display info (device address and device display id) for each display of
the graphics device that is captured.

Also adds functions to the API implementing this functionality for X11
in variants with and without DRM (the non-DRM version is rather limited
and may not work for more complex setups) as well as some helper
functions to make it easier for plugins to implement this and avoid code
duplication.

Implements the new interface method for the two built-in plugins
(mjpeg-fallback and gst-plugin).

Signed-off-by: Lukáš Hrázký 
---
 configure.ac  |   2 +
 include/spice-streaming-agent/Makefile.am |   2 +
 .../spice-streaming-agent/display-info.hpp|  52 +++
 .../spice-streaming-agent/frame-capture.hpp   |  13 +
 .../spice-streaming-agent/x-display-info.hpp  |  57 
 src/Makefile.am   |   7 +
 src/display-info.cpp  | 100 ++
 src/gst-plugin.cpp|  14 +
 src/mjpeg-fallback.cpp|  17 +-
 src/spice-streaming-agent.cpp |  13 +
 src/unittests/Makefile.am |   6 +
 src/utils.cpp |  45 +++
 src/utils.hpp |   4 +
 src/x-display-info.cpp| 301 ++
 14 files changed, 631 insertions(+), 2 deletions(-)
 create mode 100644 include/spice-streaming-agent/display-info.hpp
 create mode 100644 include/spice-streaming-agent/x-display-info.hpp
 create mode 100644 src/display-info.cpp
 create mode 100644 src/utils.cpp
 create mode 100644 src/x-display-info.cpp

diff --git a/configure.ac b/configure.ac
index e66e6d8..fd18efe 100644
--- a/configure.ac
+++ b/configure.ac
@@ -34,8 +34,10 @@ SPICE_PROTOCOL_MIN_VER=0.12.14
 PKG_CHECK_MODULES([SPICE_PROTOCOL], [spice-protocol >= 
$SPICE_PROTOCOL_MIN_VER])
 AC_SUBST([SPICE_PROTOCOL_MIN_VER])
 
+PKG_CHECK_MODULES(DRM, libdrm)
 PKG_CHECK_MODULES(X11, x11)
 PKG_CHECK_MODULES(XFIXES, xfixes)
+PKG_CHECK_MODULES(XRANDR, xrandr)
 
 PKG_CHECK_MODULES(JPEG, libjpeg, , [
 AC_CHECK_LIB(jpeg, jpeg_destroy_decompress,
diff --git a/include/spice-streaming-agent/Makefile.am 
b/include/spice-streaming-agent/Makefile.am
index bcd679b..1125fb4 100644
--- a/include/spice-streaming-agent/Makefile.am
+++ b/include/spice-streaming-agent/Makefile.am
@@ -1,8 +1,10 @@
 NULL =
 public_includedir = $(includedir)/spice-streaming-agent
 public_include_HEADERS = \
+   display-info.hpp \
error.hpp \
frame-capture.hpp \
plugin.hpp \
+   x-display-info.hpp \
$(NULL)
 
diff --git a/include/spice-streaming-agent/display-info.hpp 
b/include/spice-streaming-agent/display-info.hpp
new file mode 100644
index 000..f16212b
--- /dev/null
+++ b/include/spice-streaming-agent/display-info.hpp
@@ -0,0 +1,52 @@
+/* \copyright
+ * Copyright 2018 Red Hat Inc. All rights reserved.
+ */
+
+#ifndef SPICE_STREAMING_AGENT_DISPLAY_INFO_HPP
+#define SPICE_STREAMING_AGENT_DISPLAY_INFO_HPP
+
+#include 
+#include 
+
+
+namespace spice __attribute__ ((visibility ("default"))) {
+namespace streaming_agent {
+
+/**
+ * Lists graphics cards listed in the DRM sybsystem in /sys/class/drm.
+ * Throws an instance of Error in case of an I/O error.
+ *
+ * @return a vector of paths of all graphics cards present in /sys/class/drm
+ */
+std::vector list_cards();
+
+/**
+ * Reads a single number in hex format from a file.
+ * Throws an instance of Error in case of an I/O or parsing error.
+ *
+ * @param path the path to the file
+ * @return the number parsed from the file
+ */
+uint32_t read_hex_number_from_file(const std::string );
+
+/**
+ * Resolves any symlinks and then extracts the PCI path from the canonical path
+ * to a card. Returns the path in the following format:
+ * "pci//./.../."
+ *
+ *  is the PCI domain, followed by . of any PCI bridges
+ * in the chain leading to the device. The last . is the
+ * graphics device. All of , ,  are hexadecimal numbers
+ * with the following number of digits:
+ *   : 4
+ *   : 2
+ *   : 1
+ *
+ * @param device_path the path to the card
+ * @return the device address
+ */
+std::string get_device_address(const std::string _path);
+
+}} // namespace spice::streaming_agent
+
+#endif // SPICE_STREAMING_AGENT_DISPLAY_INFO_HPP
diff --git a/include/spice-streaming-agent/frame-capture.hpp 
b/include/spice-streaming-agent/frame-capture.hpp
index 51a2987..81415e5 100644
--- a/include/spice-streaming-agent/frame-capture.hpp
+++ b/include/spice-streaming-agent/frame-capture.hpp
@@ -6,7 +6,11 @@
  */
 #ifndef SPICE_STREAMING_AGENT_FRAME_CAPTURE_HPP
 #define SPICE_STREAMING_AGENT_FRAME_CAPTURE_HPP
+
+#include 
 #include 
+#include 
+#include 
 
 #include 
 
@@ -29,6 +33,13 @@ struct FrameInfo
 bool stream_start;
 };
 
+struct DeviceDisplayInfo
+{
+uint32_t id;
+std::string device

[Spice-devel] [PATCH vd_agent 8/8] Receive the graphics_device_info message

2019-01-08 Thread Lukáš Hrázký
The graphics_device_info message contains the device display ID
information (device address and device display ID). Stores the data in a
hash table in vdagent.

Signed-off-by: Lukáš Hrázký 
---
 src/vdagent/vdagent.c|  3 ++
 src/vdagent/x11-priv.h   |  1 +
 src/vdagent/x11-randr.c  | 58 
 src/vdagent/x11.c| 13 
 src/vdagent/x11.h|  1 +
 src/vdagentd-proto-strings.h |  1 +
 src/vdagentd-proto.h |  1 +
 src/vdagentd/vdagentd.c  | 16 ++
 8 files changed, 94 insertions(+)

diff --git a/src/vdagent/vdagent.c b/src/vdagent/vdagent.c
index 9642a30..aa52ee9 100644
--- a/src/vdagent/vdagent.c
+++ b/src/vdagent/vdagent.c
@@ -240,6 +240,9 @@ static void daemon_read_complete(struct udscs_connection 
**connp,
   ((VDAgentFileXferDataMessage 
*)data)->id);
 }
 break;
+case VDAGENTD_GRAPHICS_DEVICE_INFO:
+vdagent_x11_handle_graphics_device_info(agent->x11, data, 
header->size);
+break;
 case VDAGENTD_CLIENT_DISCONNECTED:
 vdagent_clipboards_release_all(agent->clipboards);
 if (vdagent_finalize_file_xfer(agent)) {
diff --git a/src/vdagent/x11-priv.h b/src/vdagent/x11-priv.h
index b31b0a5..0e954cf 100644
--- a/src/vdagent/x11-priv.h
+++ b/src/vdagent/x11-priv.h
@@ -139,6 +139,7 @@ struct vdagent_x11 {
 int xrandr_minor;
 int has_xinerama;
 int dont_send_guest_xorg_res;
+GHashTable *graphics_display_infos;
 };
 
 extern int (*vdagent_x11_prev_error_handler)(Display *, XErrorEvent *);
diff --git a/src/vdagent/x11-randr.c b/src/vdagent/x11-randr.c
index 192b888..f4eb3b0 100644
--- a/src/vdagent/x11-randr.c
+++ b/src/vdagent/x11-randr.c
@@ -31,6 +31,7 @@
 
 #include 
 
+#include "device-info.h"
 #include "vdagentd-proto.h"
 #include "x11.h"
 #include "x11-priv.h"
@@ -727,6 +728,63 @@ static void dump_monitors_config(struct vdagent_x11 *x11,
 }
 }
 
+typedef struct GraphicsDisplayInfo {
+char device_address[256];
+uint32_t device_display_id;
+} GraphicsDisplayInfo;
+
+// handle the device info message from the server. This will allow us to
+// maintain a mapping from spice display id to xrandr output
+void vdagent_x11_handle_graphics_device_info(struct vdagent_x11 *x11, uint8_t 
*data, size_t size)
+{
+VDAgentGraphicsDeviceInfo *graphics_device_info = 
(VDAgentGraphicsDeviceInfo *)data;
+VDAgentDeviceDisplayInfo *device_display_info = 
graphics_device_info->device_info;
+
+void *buffer_end = data + size;
+
+syslog(LOG_INFO, "Received Graphics Device Info:");
+
+for (size_t i = 0; i < graphics_device_info->count; ++i) {
+if ((void*) device_display_info > buffer_end ||
+(void*) (_display_info->device_address +
+device_display_info->device_address_len) > buffer_end) {
+syslog(LOG_ERR, "Malformed graphics_display_info message, "
+   "extends beyond the end of the buffer");
+break;
+}
+
+GraphicsDisplayInfo *value = g_malloc(sizeof(GraphicsDisplayInfo));
+
+size_t device_address_len = device_display_info->device_address_len;
+if (device_address_len > sizeof(value->device_address)) {
+syslog(LOG_ERR, "Received a device address longer than %lu, "
+   "will be truncated!", device_address_len);
+device_address_len = sizeof(value->device_address);
+}
+
+strncpy(value->device_address,
+(char*) device_display_info->device_address,
+device_address_len);
+value->device_address[device_address_len - 1] = '\0';  // make sure 
the string is terminated
+value->device_display_id = device_display_info->device_display_id;
+
+syslog(LOG_INFO, "   channel_id: %u monitor_id: %u device_address: %s, 
"
+   "device_display_id: %u",
+   device_display_info->channel_id,
+   device_display_info->monitor_id,
+   value->device_address,
+   value->device_display_id);
+
+g_hash_table_insert(x11->graphics_display_infos,
+GUINT_TO_POINTER(device_display_info->channel_id + 
device_display_info->monitor_id),
+value);
+
+device_display_info = (VDAgentDeviceDisplayInfo*) ((char*) 
device_display_info +
+sizeof(VDAgentDeviceDisplayInfo) + 
device_display_info->device_address_len);
+}
+}
+
+
 /*
  * Set monitor configuration according to client request.
  *
diff --git a/src/vdagent/x11.c b/src/vdagent/x11.c
index 53d3c48..2473383 100644
--- a/src/vdagent/x11.c
+++ b/src/vdagent/x11.c
@@ -196,6 +196,12 @@ static gchar *vdagent_x11_get_wm_name(struct vdagent_x11 
*x11)
 #endif
 }
 
+sta

[Spice-devel] [PATCH spice 4/8] Receive the GraphicsDeviceInfo message from the streaming agent

2019-01-08 Thread Lukáš Hrázký
Receives the GraphicsDeviceInfo message from the streaming agent and
stores the data in a list on the streaming device.

Signed-off-by: Lukáš Hrázký 
---
 server/red-qxl.c   |  1 -
 server/red-stream-device.c | 66 --
 server/red-stream-device.h |  8 +
 server/reds.h  |  3 ++
 4 files changed, 74 insertions(+), 4 deletions(-)

diff --git a/server/red-qxl.c b/server/red-qxl.c
index ebc14a46..e174758f 100644
--- a/server/red-qxl.c
+++ b/server/red-qxl.c
@@ -41,7 +41,6 @@
 #include "red-qxl.h"
 
 
-#define MAX_DEVICE_ADDRESS_LEN 256
 #define MAX_MONITORS_COUNT 16
 
 struct QXLState {
diff --git a/server/red-stream-device.c b/server/red-stream-device.c
index 215ddbe7..bbd6874f 100644
--- a/server/red-stream-device.c
+++ b/server/red-stream-device.c
@@ -23,7 +23,6 @@
 
 #include "stream-channel.h"
 #include "cursor-channel.h"
-#include "reds.h"
 
 #define MAX_GUEST_CAPABILITIES_BYTES ((STREAM_CAP_END+7)/8)
 
@@ -37,6 +36,7 @@ struct StreamDevice {
 StreamMsgCapabilities capabilities;
 StreamMsgCursorSet cursor_set;
 StreamMsgCursorMove cursor_move;
+StreamMsgDeviceDisplayInfo device_display_info;
 uint8_t buf[STREAM_MSG_CAPABILITIES_MAX_BYTES];
 } *msg;
 uint32_t msg_pos;
@@ -49,6 +49,7 @@ struct StreamDevice {
 CursorChannel *cursor_channel;
 SpiceTimer *close_timer;
 uint32_t frame_mmtime;
+StreamDeviceDisplayInfo device_display_info;
 };
 
 struct StreamDeviceClass {
@@ -64,8 +65,8 @@ static void char_device_set_state(RedCharDevice *char_dev, 
int state);
 typedef bool StreamMsgHandler(StreamDevice *dev, SpiceCharDeviceInstance *sin)
 SPICE_GNUC_WARN_UNUSED_RESULT;
 
-static StreamMsgHandler handle_msg_format, handle_msg_data, 
handle_msg_cursor_set,
-handle_msg_cursor_move, handle_msg_capabilities;
+static StreamMsgHandler handle_msg_format, handle_msg_device_display_info, 
handle_msg_data,
+handle_msg_cursor_set, handle_msg_cursor_move, handle_msg_capabilities;
 
 static bool handle_msg_invalid(StreamDevice *dev, SpiceCharDeviceInstance *sin,
const char *error_msg) 
SPICE_GNUC_WARN_UNUSED_RESULT;
@@ -146,6 +147,13 @@ stream_device_partial_read(StreamDevice *dev, 
SpiceCharDeviceInstance *sin)
 handled = handle_msg_format(dev, sin);
 }
 break;
+case STREAM_TYPE_DEVICE_DISPLAY_INFO:
+if (dev->hdr.size > sizeof(StreamMsgDeviceDisplayInfo) + 
MAX_DEVICE_ADDRESS_LEN) {
+handled = handle_msg_invalid(dev, sin, "StreamMsgDeviceDisplayInfo 
too large");
+} else {
+handled = handle_msg_device_display_info(dev, sin);
+}
+break;
 case STREAM_TYPE_DATA:
 if (dev->hdr.size > 32*1024*1024) {
 handled = handle_msg_invalid(dev, sin, "STREAM_DATA too large");
@@ -271,6 +279,58 @@ handle_msg_format(StreamDevice *dev, 
SpiceCharDeviceInstance *sin)
 return true;
 }
 
+static bool
+handle_msg_device_display_info(StreamDevice *dev, SpiceCharDeviceInstance *sin)
+{
+SpiceCharDeviceInterface *sif = spice_char_device_get_interface(sin);
+
+if (spice_extra_checks) {
+spice_assert(dev->hdr_pos >= sizeof(StreamDevHeader));
+spice_assert(dev->hdr.type == STREAM_TYPE_DEVICE_DISPLAY_INFO);
+}
+
+if (dev->msg_len < dev->hdr.size) {
+dev->msg = g_realloc(dev->msg, dev->hdr.size);
+dev->msg_len = dev->hdr.size;
+}
+
+/* read from device */
+ssize_t n = sif->read(sin, dev->msg->buf + dev->msg_pos, dev->hdr.size - 
dev->msg_pos);
+if (n <= 0) {
+return dev->msg_pos == dev->hdr.size;
+}
+
+dev->msg_pos += n;
+if (dev->msg_pos != dev->hdr.size) { /* some bytes are still missing */
+return false;
+}
+
+StreamMsgDeviceDisplayInfo *display_info_msg = 
>msg->device_display_info;
+
+size_t device_address_len = display_info_msg->device_address_len;
+if (device_address_len > MAX_DEVICE_ADDRESS_LEN) {
+g_error("Received a device address longer than %u (%lu), "
+"will be truncated!", MAX_DEVICE_ADDRESS_LEN, 
device_address_len);
+device_address_len = sizeof(dev->device_display_info.device_address);
+}
+
+strncpy(dev->device_display_info.device_address,
+(char*) display_info_msg->device_address,
+device_address_len);
+
+dev->device_display_info.device_address[device_address_len] = '\0';  // 
terminate the string
+dev->device_display_info.id = display_info_msg->id;
+dev->device_display_info.device_display_id = 
display_info_msg->device_display_id;
+
+g_debug("Received DeviceDisplayInfo from the streaming agent: id %u, "
+"device_address %s, device_display_id %u",

[Spice-devel] [PATCH spice 3/8] Send the graphics device info to the vd_agent

2019-01-08 Thread Lukáš Hrázký
Sends the device address and device display IDs to the vdagent. The
message is sent either in reaction to the SPICE_MSGC_MAIN_AGENT_START
message or when the graphics device info changes.

TODO: doesn't resend the message on agent reconnect, FIXIT.

Signed-off-by: Lukáš Hrázký 
---
 server/red-qxl.c  | 20 +
 server/red-qxl.h  |  3 ++
 server/reds-private.h |  1 +
 server/reds.c | 67 +++
 server/reds.h |  1 +
 5 files changed, 92 insertions(+)

diff --git a/server/red-qxl.c b/server/red-qxl.c
index 6ffd8286..ebc14a46 100644
--- a/server/red-qxl.c
+++ b/server/red-qxl.c
@@ -889,6 +889,26 @@ void spice_qxl_set_device_info(QXLInstance *instance,
 
 instance->st->monitors_count = device_display_id_count;
 instance->st->max_monitors = device_display_id_count;
+
+reds_send_device_display_info(red_qxl_get_server(instance->st));
+}
+
+const char* red_qxl_get_device_address(const QXLInstance *qxl)
+{
+const QXLState *qxl_state = qxl->st;
+return qxl_state->device_address;
+}
+
+const uint32_t* red_qxl_get_device_display_ids(const QXLInstance *qxl)
+{
+const QXLState *qxl_state = qxl->st;
+return qxl_state->device_display_ids;
+}
+
+size_t red_qxl_get_monitors_count(const QXLInstance *qxl)
+{
+const QXLState *qxl_state = qxl->st;
+return qxl_state->monitors_count;
 }
 
 void red_qxl_init(RedsState *reds, QXLInstance *qxl)
diff --git a/server/red-qxl.h b/server/red-qxl.h
index 6014d32a..94753948 100644
--- a/server/red-qxl.h
+++ b/server/red-qxl.h
@@ -40,6 +40,9 @@ void red_qxl_put_gl_scanout(QXLInstance *qxl, 
SpiceMsgDisplayGlScanoutUnix *scan
 void red_qxl_gl_draw_async_complete(QXLInstance *qxl);
 int red_qxl_check_qxl_version(QXLInstance *qxl, int major, int minor);
 SpiceServer* red_qxl_get_server(QXLState *qxl);
+const char* red_qxl_get_device_address(const QXLInstance *qxl);
+const uint32_t* red_qxl_get_device_display_ids(const QXLInstance *qxl);
+size_t red_qxl_get_monitors_count(const QXLInstance *qxl);
 
 /* Wrappers around QXLInterface vfuncs */
 void red_qxl_get_init_info(QXLInstance *qxl, QXLDevInitInfo *info);
diff --git a/server/reds-private.h b/server/reds-private.h
index 920edc5c..9dbc7fa9 100644
--- a/server/reds-private.h
+++ b/server/reds-private.h
@@ -81,6 +81,7 @@ struct RedsState {
 SpiceWatch *secure_listen_watch;
 RedCharDeviceVDIPort *agent_dev;
 int pending_mouse_event;
+bool pending_device_display_info_message;
 GList *clients;
 MainChannel *main_channel;
 InputsChannel *inputs_channel;
diff --git a/server/reds.c b/server/reds.c
index cdbb94cb..b85758b6 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -257,6 +257,7 @@ typedef struct __attribute__ ((__packed__)) VDInternalBuf {
 VDAgentMessage header;
 union {
 VDAgentMouseState mouse_state;
+VDAgentGraphicsDeviceInfo graphics_device_info;
 }
 u;
 } VDInternalBuf;
@@ -894,6 +895,65 @@ static RedPipeItem 
*vdi_port_read_one_msg_from_device(RedCharDevice *self,
 return NULL;
 }
 
+void reds_send_device_display_info(RedsState *reds)
+{
+if (!reds->agent_dev->priv->agent_attached) {
+return;
+}
+g_debug("Sending device display info to the agent:");
+
+size_t message_size = sizeof(VDAgentGraphicsDeviceInfo);
+QXLInstance *qxl;
+FOREACH_QXL_INSTANCE(reds, qxl) {
+message_size +=
+(sizeof(VDAgentDeviceDisplayInfo) + 
strlen(red_qxl_get_device_address(qxl)) + 1) *
+red_qxl_get_monitors_count(qxl);
+}
+
+RedCharDeviceWriteBuffer *char_dev_buf = 
vdagent_new_write_buffer(reds->agent_dev,
+ VD_AGENT_GRAPHICS_DEVICE_INFO,
+ message_size,
+ true);
+
+if (!char_dev_buf) {
+reds->pending_device_display_info_message = true;
+return;
+}
+
+VDInternalBuf *internal_buf = (VDInternalBuf *)char_dev_buf->buf;
+VDAgentGraphicsDeviceInfo *graphics_device_info = 
_buf->u.graphics_device_info;
+graphics_device_info->count = 0;
+
+VDAgentDeviceDisplayInfo *device_display_info = 
graphics_device_info->device_info;
+FOREACH_QXL_INSTANCE(reds, qxl) {
+for (size_t i = 0; i < red_qxl_get_monitors_count(qxl); ++i) {
+device_display_info->channel_id = qxl->id;
+device_display_info->monitor_id = i;
+device_display_info->device_display_id = 
red_qxl_get_device_display_ids(qxl)[i];
+
+strcpy((char*) device_display_info->device_address, 
red_qxl_get_device_address(qxl));
+
+device_display_info->device_address_len =
+strlen((char*) device_display_info->device_address) + 1;
+
+g_debug("   channel_id: %u monitor_id: %u, device_address: %s, 
device_display_id: %u",
+ 

[Spice-devel] [PATCH spice-protocol 2/8] Add the StreamMsgGraphicsDeviceInfo message

2019-01-08 Thread Lukáš Hrázký
The message contains information about the graphics device and monitor
belonging to a particular video stream (which maps to a channel) from
the streaming agent.

Signed-off-by: Lukáš Hrázký 
---
 spice/stream-device.h | 9 +
 1 file changed, 9 insertions(+)

diff --git a/spice/stream-device.h b/spice/stream-device.h
index 6add42b..77d76af 100644
--- a/spice/stream-device.h
+++ b/spice/stream-device.h
@@ -90,6 +90,8 @@ typedef enum StreamMsgType {
 STREAM_TYPE_CURSOR_SET,
 /* guest cursor position */
 STREAM_TYPE_CURSOR_MOVE,
+/* the graphics device display information message (device address and 
display id) */
+STREAM_TYPE_DEVICE_DISPLAY_INFO,
 } StreamMsgType;
 
 typedef enum StreamCapabilities {
@@ -140,6 +142,13 @@ typedef struct StreamMsgData {
 uint8_t data[0];
 } StreamMsgData;
 
+typedef struct StreamMsgDeviceDisplayInfo {
+uint32_t id;
+uint32_t device_display_id;
+uint32_t device_address_len;
+uint8_t device_address[0];  // a zero-terminated string
+} StreamMsgDeviceDisplayInfo;
+
 /* Tell to stop current stream and possibly start a new one.
  * This message is sent by the host to the guest.
  * Allows to communicate the codecs supported by the clients.
-- 
2.20.1

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH spice 5/8] Send the graphics device info from streaming agent to the vd_agent

2019-01-08 Thread Lukáš Hrázký
Adds the graphics device info from the streaming device(s) to the
VDAgentGraphicsDeviceInfo message sent to the vd_agent.

Signed-off-by: Lukáš Hrázký 
---
 server/red-stream-device.c | 14 ++
 server/red-stream-device.h |  4 +++
 server/reds.c  | 56 --
 3 files changed, 72 insertions(+), 2 deletions(-)

diff --git a/server/red-stream-device.c b/server/red-stream-device.c
index bbd6874f..567e7485 100644
--- a/server/red-stream-device.c
+++ b/server/red-stream-device.c
@@ -328,6 +328,8 @@ handle_msg_device_display_info(StreamDevice *dev, 
SpiceCharDeviceInstance *sin)
 dev->device_display_info.device_address,
 dev->device_display_info.device_display_id);
 
+
reds_send_device_display_info(red_char_device_get_server(RED_CHAR_DEVICE(dev)));
+
 return true;
 }
 
@@ -785,6 +787,18 @@ stream_device_init(StreamDevice *dev)
 dev->msg_len = sizeof(*dev->msg);
 }
 
+StreamDeviceDisplayInfo *stream_device_get_device_display_info(StreamDevice 
*dev)
+{
+return >device_display_info;
+}
+
+uint32_t stream_device_get_stream_channel_id(StreamDevice *dev)
+{
+uint32_t channel_id;
+g_object_get(dev->stream_channel, "id", _id, NULL);
+return channel_id;
+}
+
 static StreamDevice *
 stream_device_new(SpiceCharDeviceInstance *sin, RedsState *reds)
 {
diff --git a/server/red-stream-device.h b/server/red-stream-device.h
index 9e71cb88..0a3ac7f7 100644
--- a/server/red-stream-device.h
+++ b/server/red-stream-device.h
@@ -56,6 +56,10 @@ StreamDevice *stream_device_connect(RedsState *reds, 
SpiceCharDeviceInstance *si
  */
 void stream_device_create_channel(StreamDevice *dev);
 
+StreamDeviceDisplayInfo *stream_device_get_device_display_info(StreamDevice 
*dev);
+
+uint32_t stream_device_get_stream_channel_id(StreamDevice *dev);
+
 G_END_DECLS
 
 #endif /* STREAM_DEVICE_H */
diff --git a/server/reds.c b/server/reds.c
index b85758b6..d26fdf65 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -902,14 +902,33 @@ void reds_send_device_display_info(RedsState *reds)
 }
 g_debug("Sending device display info to the agent:");
 
-size_t message_size = sizeof(VDAgentGraphicsDeviceInfo);
 QXLInstance *qxl;
+RedCharDevice *dev;
+
+size_t message_size = sizeof(VDAgentGraphicsDeviceInfo);
+
+// size for the qxl device info
 FOREACH_QXL_INSTANCE(reds, qxl) {
 message_size +=
 (sizeof(VDAgentDeviceDisplayInfo) + 
strlen(red_qxl_get_device_address(qxl)) + 1) *
 red_qxl_get_monitors_count(qxl);
 }
 
+// size for the stream device info
+GLIST_FOREACH(reds->char_devices, RedCharDevice, dev) {
+if (IS_STREAM_DEVICE(dev)) {
+size_t device_address_len =
+
strlen(stream_device_get_device_display_info(STREAM_DEVICE(dev))->device_address);
+
+if (device_address_len == 0) {
+// the device info wasn't set (yet), don't send it
+continue;
+}
+
+message_size += (sizeof(VDAgentDeviceDisplayInfo) + 
device_address_len + 1);
+}
+}
+
 RedCharDeviceWriteBuffer *char_dev_buf = 
vdagent_new_write_buffer(reds->agent_dev,
  VD_AGENT_GRAPHICS_DEVICE_INFO,
  message_size,
@@ -925,6 +944,8 @@ void reds_send_device_display_info(RedsState *reds)
 graphics_device_info->count = 0;
 
 VDAgentDeviceDisplayInfo *device_display_info = 
graphics_device_info->device_info;
+
+// add the qxl devices to the message
 FOREACH_QXL_INSTANCE(reds, qxl) {
 for (size_t i = 0; i < red_qxl_get_monitors_count(qxl); ++i) {
 device_display_info->channel_id = qxl->id;
@@ -936,7 +957,38 @@ void reds_send_device_display_info(RedsState *reds)
 device_display_info->device_address_len =
 strlen((char*) device_display_info->device_address) + 1;
 
-g_debug("   channel_id: %u monitor_id: %u, device_address: %s, 
device_display_id: %u",
+g_debug("   (qxl)channel_id: %u monitor_id: %u, 
device_address: %s, device_display_id: %u",
+device_display_info->channel_id,
+device_display_info->monitor_id,
+device_display_info->device_address,
+device_display_info->device_display_id);
+
+device_display_info = (VDAgentDeviceDisplayInfo*) ((char*) 
device_display_info +
+sizeof(VDAgentDeviceDisplayInfo) + 
device_display_info->device_address_len);
+
+graphics_device_info->count++;
+}
+}
+
+// add the stream devices to the message
+GLIST_FOREACH(reds->char_devices, RedCharDevice, dev) {
+if (IS_STREAM_DEVICE(dev)) {
+StreamDevice *stream_dev = STREAM_DEVICE(dev);
+Strea

[Spice-devel] [PATCH 0/8] Monitor ID between host and guest

2019-01-08 Thread Lukáš Hrázký
Hello,

this series introduces a new mechanism to identify monitors across the
host and guest boundary, using the pair (device_address and
device_display_id). device_address is a HW address of a graphics device
(a PCI address to be specific, though other address domains can be
used as well), device_display_id is an ID of the monitor on that device.

This information is gathered from QEMU (regular spice) or
spice-streaming-agent (for the streaming channels) and a mapping of
(channel_id, monitor_id) -> (device_address, device_display_id) is sent
from spice server to the vd_agent. vd_agent uses this mapping to
translate the former ID in incoming messages to the latter.

This series follows up on the "QXL interface to set monitor ID" series
[1] and then Jonathon Jongsma's "Use the PCI addr and display ID" [2]
follows up on this to make a complete solution.

Cheers,
Lukas

[1] https://lists.freedesktop.org/archives/spice-devel/2019-January/046997.html
[2] https://lists.freedesktop.org/archives/spice-devel/2019-January/046939.html

-- 
2.20.1

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH spice-protocol 1/8] Add the VDAgentGraphicsDeviceInfo message

2019-01-08 Thread Lukáš Hrázký
The message serves for passing the device address and device display ID
information for all display channels from SPICE server to the vd_agent.

Signed-off-by: Lukáš Hrázký 
---
 spice/vd_agent.h | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/spice/vd_agent.h b/spice/vd_agent.h
index dda7044..5e618b7 100644
--- a/spice/vd_agent.h
+++ b/spice/vd_agent.h
@@ -91,6 +91,7 @@ enum {
 VD_AGENT_CLIENT_DISCONNECTED,
 VD_AGENT_MAX_CLIPBOARD,
 VD_AGENT_AUDIO_VOLUME_SYNC,
+VD_AGENT_GRAPHICS_DEVICE_INFO,
 VD_AGENT_END_MESSAGE,
 };
 
@@ -248,6 +249,19 @@ typedef struct SPICE_ATTR_PACKED VDAgentAudioVolumeSync {
 uint16_t volume[0];
 } VDAgentAudioVolumeSync;
 
+typedef struct SPICE_ATTR_PACKED VDAgentDeviceDisplayInfo {
+uint32_t channel_id;
+uint32_t monitor_id;
+uint32_t device_display_id;
+uint32_t device_address_len;
+uint8_t device_address[0];  // a zero-terminated string
+} VDAgentDeviceDisplayInfo;
+
+typedef struct SPICE_ATTR_PACKED VDAgentGraphicsDeviceInfo {
+uint32_t count;
+VDAgentDeviceDisplayInfo device_info[0];
+} VDAgentGraphicsDeviceInfo;
+
 enum {
 VD_AGENT_CAP_MOUSE_STATE = 0,
 VD_AGENT_CAP_MONITORS_CONFIG,
@@ -264,6 +278,7 @@ enum {
 VD_AGENT_CAP_MONITORS_CONFIG_POSITION,
 VD_AGENT_CAP_FILE_XFER_DISABLED,
 VD_AGENT_CAP_FILE_XFER_DETAILED_ERRORS,
+VD_AGENT_CAP_GRAPHICS_DEVICE_INFO,
 VD_AGENT_END_CAP,
 };
 
-- 
2.20.1

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH qemu 3/3] spice: set device address and device display ID in QXL interface

2019-01-08 Thread Lukáš Hrázký
Calls the new SPICE QXL interface function spice_qxl_set_device_info to
set the hardware address of the graphics device represented by the QXL
interface (e.g. a PCI path) and the device display IDs (the IDs of the
device's monitors that belong to this QXL interface).

Also stops using the deprecated spice_qxl_set_max_monitors, the new
interface function replaces it.

Signed-off-by: Lukáš Hrázký 
---
 hw/display/qxl.c   | 14 -
 include/ui/spice-display.h |  2 ++
 ui/spice-core.c| 42 ++
 ui/spice-display.c | 11 ++
 4 files changed, 68 insertions(+), 1 deletion(-)

diff --git a/hw/display/qxl.c b/hw/display/qxl.c
index 9087db5dee..b1c9e856f5 100644
--- a/hw/display/qxl.c
+++ b/hw/display/qxl.c
@@ -276,7 +276,8 @@ static void qxl_spice_monitors_config_async(PCIQXLDevice 
*qxl, int replay)
 QXL_COOKIE_TYPE_POST_LOAD_MONITORS_CONFIG,
 0));
 } else {
-#if SPICE_SERVER_VERSION >= 0x000c06 /* release 0.12.6 */
+#if SPICE_SERVER_VERSION >= 0x000c06 /* release 0.12.6 */ && \
+SPICE_SERVER_VERSION < 0x000e02
 if (qxl->max_outputs) {
 spice_qxl_set_max_monitors(>ssd.qxl, qxl->max_outputs);
 }
@@ -2184,6 +2185,17 @@ static void qxl_realize_common(PCIQXLDevice *qxl, Error 
**errp)
SPICE_INTERFACE_QXL_MAJOR, SPICE_INTERFACE_QXL_MINOR);
 return;
 }
+
+#if SPICE_SERVER_VERSION >= 0x000e02 /* release 0.14.2 */
+char device_address[256] = "";
+if (qemu_spice_fill_device_address(qxl->vga.con, device_address, 256)) {
+spice_qxl_set_device_info(>ssd.qxl,
+  device_address,
+  0,
+  qxl->max_outputs);
+}
+#endif
+
 qemu_add_vm_change_state_handler(qxl_vm_change_state_handler, qxl);
 
 qxl->update_irq = qemu_bh_new(qxl_update_irq_bh, qxl);
diff --git a/include/ui/spice-display.h b/include/ui/spice-display.h
index 87a84a59d4..7608fa7ebd 100644
--- a/include/ui/spice-display.h
+++ b/include/ui/spice-display.h
@@ -179,3 +179,5 @@ void qemu_spice_wakeup(SimpleSpiceDisplay *ssd);
 void qemu_spice_display_start(void);
 void qemu_spice_display_stop(void);
 int qemu_spice_display_is_running(SimpleSpiceDisplay *ssd);
+
+bool qemu_spice_fill_device_address(QemuConsole *con, char *device_address, 
size_t size);
diff --git a/ui/spice-core.c b/ui/spice-core.c
index ebaae24643..43a7435cd9 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -35,6 +35,8 @@
 #include "qemu/option.h"
 #include "migration/misc.h"
 #include "hw/hw.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_bus.h"
 #include "ui/spice-display.h"
 
 /* core bits */
@@ -872,6 +874,46 @@ bool qemu_spice_have_display_interface(QemuConsole *con)
 return false;
 }
 
+/*
+ * Recursively (in reverse order) appends addresses of PCI devices as it moves
+ * up in the PCI hierarchy.
+ *
+ * @returns true on success, false when the buffer wasn't large enough
+ */
+static bool append_pci_address(char *buf, size_t buf_size, const PCIDevice 
*pci)
+{
+PCIBus *bus = pci_get_bus(pci);
+if (!pci_bus_is_root(bus)) {
+append_pci_address(buf, buf_size, bus->parent_dev);
+}
+
+size_t len = strlen(buf);
+ssize_t written = snprintf(buf + len, buf_size - len, "/%02x.%x",
+PCI_SLOT(pci->devfn), PCI_FUNC(pci->devfn));
+
+return written > 0 && written < buf_size - len;
+}
+
+bool qemu_spice_fill_device_address(QemuConsole *con, char *device_address, 
size_t size)
+{
+DeviceState *dev = DEVICE(object_property_get_link(OBJECT(con), "device", 
_abort));
+PCIDevice *pci = (PCIDevice *) object_dynamic_cast(OBJECT(dev), 
TYPE_PCI_DEVICE);
+
+if (pci == NULL) {
+warn_report("Setting device address of a display device to SPICE: Not 
a PCI device.");
+return false;
+}
+
+strncpy(device_address, "pci/", size);
+if (!append_pci_address(device_address, size, pci)) {
+warn_report("Setting device address of a display device to SPICE: "
+"Too many PCI devices in the chain.");
+return false;
+}
+
+return true;
+}
+
 int qemu_spice_add_display_interface(QXLInstance *qxlin, QemuConsole *con)
 {
 if (g_slist_find(spice_consoles, con)) {
diff --git a/ui/spice-display.c b/ui/spice-display.c
index 52f8cb5ae1..c1605b3bc9 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -1147,6 +1147,17 @@ static void qemu_spice_display_init_one(QemuConsole *con)
 
 ssd->qxl.base.sif = _interface.base;
 qemu_spice_add_display_interface(>qxl, con);
+
+#if SPICE_SERVER_VERSION >= 0x000e02 /* release 0.14.2 */
+char device_address[256] = "";
+if 

[Spice-devel] [PATCH spice/qemu 0/3] QXL interface to set monitor ID

2019-01-08 Thread Lukáš Hrázký
Hello,

this is the final version of the new QXL interface to identify the
graphics device monitors in the guest. This interface adds a function
that allows to set the device path (e.g. a PCI path) and the IDs of the
device's displays from QEMU to SPICE server. The server will forward
this information to the guest agent, which can use it to identify the
displays in the guest context (a follow-up series on the spice-devel
mailing list).

-- 
2.20.1

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH spice 2/3] QXL interface: deprecate spice_qxl_set_max_monitors

2019-01-08 Thread Lukáš Hrázký
Replace it by spice_qxl_set_device_info. Note we can't use
monitors_count for what's stored in max_monitors, because monitors_count
denotes the length of the device_display_ids array, which
spice_qxl_set_max_monitors doesn't touch.

Signed-off-by: Lukáš Hrázký 
---
 server/red-qxl.c   | 1 +
 server/spice-qxl.h | 4 ++--
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/server/red-qxl.c b/server/red-qxl.c
index 0ea424cd..6ffd8286 100644
--- a/server/red-qxl.c
+++ b/server/red-qxl.c
@@ -888,6 +888,7 @@ void spice_qxl_set_device_info(QXLInstance *instance,
 }
 
 instance->st->monitors_count = device_display_id_count;
+instance->st->max_monitors = device_display_id_count;
 }
 
 void red_qxl_init(RedsState *reds, QXLInstance *qxl)
diff --git a/server/spice-qxl.h b/server/spice-qxl.h
index 547d3d93..e7af5e5e 100644
--- a/server/spice-qxl.h
+++ b/server/spice-qxl.h
@@ -101,9 +101,9 @@ void spice_qxl_monitors_config_async(QXLInstance *instance, 
QXLPHYSICAL monitors
  int group_id, uint64_t cookie);
 /* since spice 0.12.3 */
 void spice_qxl_driver_unload(QXLInstance *instance);
-/* since spice 0.12.6 */
+/* since spice 0.12.6, deprecated since 0.14.2, spice_qxl_set_device_info 
replaces it */
 void spice_qxl_set_max_monitors(QXLInstance *instance,
-unsigned int max_monitors);
+unsigned int max_monitors) 
SPICE_GNUC_DEPRECATED;
 /* since spice 0.13.1 */
 void spice_qxl_gl_scanout(QXLInstance *instance,
   int fd,
-- 
2.20.1

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH spice 1/3] QXL interface: add a function to identify monitors in the guest

2019-01-08 Thread Lukáš Hrázký
Adds a function to let QEMU provide information to identify graphics
devices and their monitors in the guest. The function
(spice_qxl_set_device_info) sets the device address (e.g. a PCI path)
and monitor ID -> device display ID mapping of displays exposed by given
QXL interface.

Signed-off-by: Lukáš Hrázký 
---
 server/red-qxl.c | 44 ++
 server/spice-qxl.h   | 46 
 server/spice-server.syms |  5 +
 3 files changed, 95 insertions(+)

diff --git a/server/red-qxl.c b/server/red-qxl.c
index 97940611..0ea424cd 100644
--- a/server/red-qxl.c
+++ b/server/red-qxl.c
@@ -41,6 +41,9 @@
 #include "red-qxl.h"
 
 
+#define MAX_DEVICE_ADDRESS_LEN 256
+#define MAX_MONITORS_COUNT 16
+
 struct QXLState {
 QXLWorker qxl_worker;
 QXLInstance *qxl;
@@ -53,6 +56,9 @@ struct QXLState {
 unsigned int max_monitors;
 RedsState *reds;
 RedWorker *worker;
+char device_address[MAX_DEVICE_ADDRESS_LEN];
+uint32_t device_display_ids[MAX_MONITORS_COUNT];
+size_t monitors_count;  // length of ^^^
 
 pthread_mutex_t scanout_mutex;
 SpiceMsgDisplayGlScanoutUnix scanout;
@@ -846,6 +852,44 @@ void red_qxl_gl_draw_async_complete(QXLInstance *qxl)
 red_qxl_async_complete(qxl, cookie);
 }
 
+SPICE_GNUC_VISIBLE
+void spice_qxl_set_device_info(QXLInstance *instance,
+   const char *device_address,
+   uint32_t device_display_id_start,
+   uint32_t device_display_id_count)
+{
+g_return_if_fail(device_address != NULL);
+
+size_t da_len = strnlen(device_address, MAX_DEVICE_ADDRESS_LEN);
+if (da_len >= MAX_DEVICE_ADDRESS_LEN) {
+spice_error("Device address too long: %lu > %u", da_len, 
MAX_DEVICE_ADDRESS_LEN);
+return;
+}
+
+if (device_display_id_count > MAX_MONITORS_COUNT) {
+spice_error("Device display ID count (%u) is greater than limit %u",
+device_display_id_count,
+MAX_MONITORS_COUNT);
+return;
+}
+
+strncpy(instance->st->device_address, device_address, 
MAX_DEVICE_ADDRESS_LEN);
+
+g_debug("QXL Instance %d setting device address \"%s\" and monitor -> 
device display mapping:",
+instance->id,
+device_address);
+
+// store the mapping monitor_id -> device_display_id
+for (uint32_t monitor_id = 0; monitor_id < device_display_id_count; 
++monitor_id) {
+uint32_t device_display_id = device_display_id_start + monitor_id;
+instance->st->device_display_ids[monitor_id] = device_display_id;
+g_debug("   monitor ID %u -> device display ID %u",
+monitor_id, device_display_id);
+}
+
+instance->st->monitors_count = device_display_id_count;
+}
+
 void red_qxl_init(RedsState *reds, QXLInstance *qxl)
 {
 QXLState *qxl_state;
diff --git a/server/spice-qxl.h b/server/spice-qxl.h
index 0c4e75fc..547d3d93 100644
--- a/server/spice-qxl.h
+++ b/server/spice-qxl.h
@@ -115,6 +115,52 @@ void spice_qxl_gl_draw_async(QXLInstance *instance,
  uint32_t w, uint32_t h,
  uint64_t cookie);
 
+/* since spice 0.14.2 */
+
+/**
+ * spice_qxl_set_device_info:
+ * @instance the QXL instance to set the path to
+ * @device_address the path of the device this QXL instance belongs to
+ * @device_display_id_start the starting device display ID of this interface,
+ *  i.e. the one monitor ID 0 maps to
+ * @device_display_id_count the total number of device display IDs on this
+ *  interface
+ *
+ * Sets the device information for this QXL interface, i.e. the hardware
+ * address (e.g. PCI) of the graphics device and the IDs of the displays of the
+ * graphics device that are exposed by this interface (device display IDs).
+ *
+ * The supported device address format is:
+ * "pci//./.../."
+ *
+ * The "pci" identifies the rest of the string as a PCI address. It is the only
+ * supported address at the moment, other identifiers can be introduced later.
+ *  is the PCI domain, followed by . of any PCI bridges
+ * in the chain leading to the device. The last . is the
+ * graphics device. All of , ,  are hexadecimal numbers
+ * with the following number of digits:
+ *   : 4
+ *   : 2
+ *   : 1
+ *
+ * The device_display_id_{start,count} denotes the sequence of device display
+ * IDs that map to the zero-based sequence of monitor IDs provided by monitors
+ * config on this interface. For example with device_display_id_start = 2 and
+ * device_display_id_count = 3 you get the following mapping:
+ * monitor_id  ->  device_display_id
+ *  0  ->  2
+ *  1  ->  3
+ *  2  ->  4
+ *
+ * Note this example is unsupported in practice. The on

Re: [Spice-devel] [PATCH linux vdagent 01/10] Add lookup_xrand_output_for_device_info()

2018-12-18 Thread Lukáš Hrázký
Hi,

sorry about piecemealing this.

On Thu, 2018-12-13 at 16:46 -0600, Jonathon Jongsma wrote:
> Add a function to look up an xrandr output for a given device display
> id. This uses sysfs and the drm subsystem to lookup information about a
> graphics device output. It then compares the drm output name to xrandr
> output names to try to match that device output to an xrandr output.
> This is necesary for guests that have multiple graphics devices.
> ---
>  Makefile.am   |  14 ++
>  configure.ac  |   1 +
>  src/vdagent/device-info.c | 516 ++
>  src/vdagent/device-info.h |  26 ++
>  tests/test-device-info.c  | 262 +++
>  5 files changed, 819 insertions(+)
>  create mode 100644 src/vdagent/device-info.c
>  create mode 100644 src/vdagent/device-info.h
>  create mode 100644 tests/test-device-info.c
> 
> diff --git a/Makefile.am b/Makefile.am
> index 3e405bc..d2f2258 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -12,6 +12,7 @@ common_sources =\
>   $(NULL)
>  
>  src_spice_vdagent_CFLAGS =   \
> + $(DRM_CFLAGS)   \
>   $(X_CFLAGS) \
>   $(SPICE_CFLAGS) \
>   $(GLIB2_CFLAGS) \
> @@ -22,6 +23,7 @@ src_spice_vdagent_CFLAGS =  \
>   $(NULL)
>  
>  src_spice_vdagent_LDADD =\
> + $(DRM_LIBS) \
>   $(X_LIBS)   \
>   $(SPICE_LIBS)   \
>   $(GLIB2_LIBS)   \
> @@ -35,6 +37,8 @@ src_spice_vdagent_SOURCES = \
>   src/vdagent/audio.h \
>   src/vdagent/clipboard.c \
>   src/vdagent/clipboard.h \
> + src/vdagent/device-info.c   \
> + src/vdagent/device-info.h   \
>   src/vdagent/file-xfers.c\
>   src/vdagent/file-xfers.h\
>   src/vdagent/x11-priv.h  \
> @@ -137,3 +141,13 @@ EXTRA_DIST = \
>  DISTCHECK_CONFIGURE_FLAGS =  \
>   --with-init-script=redhat   \
>   $(NULL)
> +
> +tests_test_device_info_LDADD = $(src_spice_vdagent_LDADD)
> +tests_test_device_info_CFLAGS = $(src_spice_vdagent_CFLAGS)
> +
> +check_PROGRAMS = \
> + tests/test-device-info  \
> + $(NULL)
> +
> +TESTS = $(check_PROGRAMS)
> +
> diff --git a/configure.ac b/configure.ac
> index 7cb44db..55b031e 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -105,6 +105,7 @@ PKG_CHECK_MODULES(X, [xfixes xrandr >= 1.3 xinerama x11])
>  PKG_CHECK_MODULES(SPICE, [spice-protocol >= 0.12.13])
>  PKG_CHECK_MODULES(ALSA, [alsa >= 1.0.22])
>  PKG_CHECK_MODULES([DBUS], [dbus-1])
> +PKG_CHECK_MODULES([DRM], [libdrm])
>  
>  if test "$with_session_info" = "auto" || test "$with_session_info" = 
> "systemd"; then
>  PKG_CHECK_MODULES([LIBSYSTEMD_LOGIN],
> diff --git a/src/vdagent/device-info.c b/src/vdagent/device-info.c
> new file mode 100644
> index 000..c519741
> --- /dev/null
> +++ b/src/vdagent/device-info.c
> @@ -0,0 +1,516 @@
> +/*  device-info.c utility function for looking up the xrandr output id for a
> + *  given device address and display id
> + *
> + * Copyright 2018 Red Hat, Inc.
> + *
> + * Red Hat Authors:
> + * Jonathon Jongsma 
> + *
> + * This program is free software: you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation, either version 3 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see .
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include "device-info.h"
> +
> +typedef struct PciDevice {
> +int domain;
> +uint8_t bus;
> +uint8_t slot;
> +uint8_t function;
> +} PciDevice;
> +
> +typedef struct PciAddress {
> +int domain;
> +GList *devices; /* PciDevice */
> +} PciAddress;
> +
> +static PciAddress* pci_address_new()
> +{
> +return g_new0(PciAddress, 1);
> +}
> +
> +static void pci_address_free(PciAddress *addr)
> +{
> +g_list_free_full(addr->devices, g_free);
> +g_free(addr);
> +}
> +
> +
> +static int read_next_hex_number(const char *input, char delim, char **endptr)
> +{
> +

Re: [Spice-devel] [PATCH linux vdagent 06/10] Make clearer distinctions between output ids

2018-12-17 Thread Lukáš Hrázký
ht != old_height)
> -delete_mode(x11, output, old_width, old_height);
> +delete_mode(x11, output_index, old_width, old_height);
>  
>  return 1;
>  }
>  
> -static void xrandr_disable_output(struct vdagent_x11 *x11, int output)
> +static void xrandr_disable_nth_output(struct vdagent_x11 *x11, int 
> output_index)
>  {
>  Status s;
>  
> -if (!x11->randr.res || output >= x11->randr.res->noutput || output < 0) {
> +if (!x11->randr.res || output_index >= x11->randr.res->noutput || 
> output_index < 0) {
>  syslog(LOG_ERR, "%s: program error: missing RANDR or bad output",
> __FUNCTION__);
>  return;
>  }
>  
> -XRROutputInfo *oinfo = x11->randr.outputs[output];
> +XRROutputInfo *oinfo = x11->randr.outputs[output_index];
>  if (oinfo->ncrtc == 0) {
> -syslog(LOG_WARNING, "Output index %i doesn't have any associated 
> CRTCs", output);
> +syslog(LOG_WARNING, "Output index %i doesn't have any associated 
> CRTCs", output_index);
>  return;
>  }
>  
> @@ -415,10 +415,10 @@ static void xrandr_disable_output(struct vdagent_x11 
> *x11, int output)
>  if (s != RRSetConfigSuccess)
>  syslog(LOG_ERR, "failed to disable monitor");
>  
> -delete_mode(x11, output, x11->randr.monitor_sizes[output].width,
> - x11->randr.monitor_sizes[output].height);
> -x11->randr.monitor_sizes[output].width  = 0;
> -x11->randr.monitor_sizes[output].height = 0;
> +delete_mode(x11, output_index, 
> x11->randr.monitor_sizes[output_index].width,
> + x11->randr.monitor_sizes[output_index].height);
> +x11->randr.monitor_sizes[output_index].width  = 0;
> +x11->randr.monitor_sizes[output_index].height = 0;
>  }
>  
>  static int set_screen_to_best_size(struct vdagent_x11 *x11, int width, int 
> height,
> @@ -842,12 +842,12 @@ void vdagent_x11_set_monitor_config(struct vdagent_x11 
> *x11,
>  g_free(config);
>  
>  for (i = mon_config->num_of_monitors; i < x11->randr.res->noutput; i++)
> -xrandr_disable_output(x11, i);
> +xrandr_disable_nth_output(x11, i);
>  
>  /* First, disable disabled CRTCs... */
>  for (i = 0; i < mon_config->num_of_monitors; ++i) {
>  if (!monitor_enabled(_config->monitors[i])) {
> -xrandr_disable_output(x11, i);
> +xrandr_disable_nth_output(x11, i);
>  }
>  }
>  
> @@ -870,7 +870,7 @@ void vdagent_x11_set_monitor_config(struct vdagent_x11 
> *x11,
>  syslog(LOG_DEBUG, "Disabling monitor %d: %dx%d+%d+%d > 
> (%d,%d)",
> i, width, height, x, y, primary_w, primary_h);
>  
> -xrandr_disable_output(x11, i);
> +xrandr_disable_nth_output(x11, i);
>  }
>  }
> 

Acked-by: Lukáš Hrázký 

Maybe explicitly mention in the commit message this patch only renames
some variables and a function.
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH linux vdagent 02/10] Fix confusion between output index and crtc index

2018-12-17 Thread Lukáš Hrázký
On Thu, 2018-12-13 at 16:46 -0600, Jonathon Jongsma wrote:
> Get the CRTC ID from the output struct rather than using the
> output_index as an index into the array of crtcs
> ---
>  src/vdagent/x11-randr.c | 9 -
>  1 file changed, 8 insertions(+), 1 deletion(-)
> 
> diff --git a/src/vdagent/x11-randr.c b/src/vdagent/x11-randr.c
> index 88f723f..802af5c 100644
> --- a/src/vdagent/x11-randr.c
> +++ b/src/vdagent/x11-randr.c
> @@ -399,8 +399,15 @@ static void xrandr_disable_output(struct vdagent_x11 
> *x11, int output)
>  return;
>  }
>  
> +XRROutputInfo *oinfo = x11->randr.outputs[output];
> +if (oinfo->ncrtc == 0) {
> +syslog(LOG_WARNING, "Output index %i doesn't have any associated 
> CRTCs", output);
> +return;
> +}
> +
> +// assume output only has a single crtc
>  s = XRRSetCrtcConfig(x11->display, x11->randr.res,
> - x11->randr.res->crtcs[output],
> + oinfo->crtcs[0],
>       CurrentTime, 0, 0, None, RR_Rotate_0,
>   NULL, 0);
>  

Acked-by: Lukáš Hrázký 
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH linux vdagent 01/10] Add lookup_xrand_output_for_device_info()

2018-12-17 Thread Lukáš Hrázký
 * Hello,

On Thu, 2018-12-13 at 16:46 -0600, Jonathon Jongsma wrote:
> Add a function to look up an xrandr output for a given device display
> id. This uses sysfs and the drm subsystem to lookup information about a
> graphics device output. It then compares the drm output name to xrandr
> output names to try to match that device output to an xrandr output.
> This is necesary for guests that have multiple graphics devices.

All in all, the logging here seems a bit too verbose... I tried to make
some suggestions below. I would also change the lines representing
errors from LOG_WARNING to LOG_ERR.

> ---
>  Makefile.am   |  14 ++
>  configure.ac  |   1 +
>  src/vdagent/device-info.c | 516 ++
>  src/vdagent/device-info.h |  26 ++
>  tests/test-device-info.c  | 262 +++
>  5 files changed, 819 insertions(+)
>  create mode 100644 src/vdagent/device-info.c
>  create mode 100644 src/vdagent/device-info.h
>  create mode 100644 tests/test-device-info.c
> 
> diff --git a/Makefile.am b/Makefile.am
> index 3e405bc..d2f2258 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -12,6 +12,7 @@ common_sources =\
>   $(NULL)
>  
>  src_spice_vdagent_CFLAGS =   \
> + $(DRM_CFLAGS)   \
>   $(X_CFLAGS) \
>   $(SPICE_CFLAGS) \
>   $(GLIB2_CFLAGS) \
> @@ -22,6 +23,7 @@ src_spice_vdagent_CFLAGS =  \
>   $(NULL)
>  
>  src_spice_vdagent_LDADD =\
> + $(DRM_LIBS) \
>   $(X_LIBS)   \
>   $(SPICE_LIBS)   \
>   $(GLIB2_LIBS)   \
> @@ -35,6 +37,8 @@ src_spice_vdagent_SOURCES = \
>   src/vdagent/audio.h \
>   src/vdagent/clipboard.c \
>   src/vdagent/clipboard.h \
> + src/vdagent/device-info.c   \
> + src/vdagent/device-info.h   \
>   src/vdagent/file-xfers.c\
>   src/vdagent/file-xfers.h\
>   src/vdagent/x11-priv.h  \
> @@ -137,3 +141,13 @@ EXTRA_DIST = \
>  DISTCHECK_CONFIGURE_FLAGS =  \
>   --with-init-script=redhat   \
>   $(NULL)
> +
> +tests_test_device_info_LDADD = $(src_spice_vdagent_LDADD)
> +tests_test_device_info_CFLAGS = $(src_spice_vdagent_CFLAGS)
> +
> +check_PROGRAMS = \
> + tests/test-device-info  \
> + $(NULL)
> +
> +TESTS = $(check_PROGRAMS)
> +
> diff --git a/configure.ac b/configure.ac
> index 7cb44db..55b031e 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -105,6 +105,7 @@ PKG_CHECK_MODULES(X, [xfixes xrandr >= 1.3 xinerama x11])
>  PKG_CHECK_MODULES(SPICE, [spice-protocol >= 0.12.13])
>  PKG_CHECK_MODULES(ALSA, [alsa >= 1.0.22])
>  PKG_CHECK_MODULES([DBUS], [dbus-1])
> +PKG_CHECK_MODULES([DRM], [libdrm])
>  
>  if test "$with_session_info" = "auto" || test "$with_session_info" = 
> "systemd"; then
>  PKG_CHECK_MODULES([LIBSYSTEMD_LOGIN],
> diff --git a/src/vdagent/device-info.c b/src/vdagent/device-info.c
> new file mode 100644
> index 000..c519741
> --- /dev/null
> +++ b/src/vdagent/device-info.c
> @@ -0,0 +1,516 @@
> +/*  device-info.c utility function for looking up the xrandr output id for a
> + *  given device address and display id
> + *
> + * Copyright 2018 Red Hat, Inc.
> + *
> + * Red Hat Authors:
> + * Jonathon Jongsma 
> + *
> + * This program is free software: you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation, either version 3 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see .
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include "device-info.h"
> +
> +typedef struct PciDevice {
> +int domain;
> +uint8_t bus;
> +uint8_t slot;
> +uint8_t function;
> +} PciDevice;
> +
> +typedef struct PciAddress {
> +int domain;
> +GList *devices; /* PciDevice */
> +} PciAddress;
> +
> +static PciAddress* pci_address_new()
> +{
> +return g_new0(PciAddress, 1);
> +}
> +
> +static void pci_address_free(PciAddress *addr)
> +{
> +

[Spice-devel] [PATCH spice-streaming-agent 2/3] Move the syslog() helper for errors to a new utils module

2018-12-04 Thread Lukáš Hrázký
The syslog() helper for logging an error is not necessary, leave it out
of the API and move it to a new private utils module.

Signed-off-by: Lukáš Hrázký 
---
 include/spice-streaming-agent/error.hpp |  8 
 src/Makefile.am |  1 +
 src/cursor-updater.cpp  |  1 +
 src/spice-streaming-agent.cpp   |  3 ++-
 src/utils.hpp   | 24 
 5 files changed, 28 insertions(+), 9 deletions(-)
 create mode 100644 src/utils.hpp

diff --git a/include/spice-streaming-agent/error.hpp 
b/include/spice-streaming-agent/error.hpp
index 2993dbb..3202d78 100644
--- a/include/spice-streaming-agent/error.hpp
+++ b/include/spice-streaming-agent/error.hpp
@@ -9,7 +9,6 @@
 
 #include 
 #include 
-#include 
 
 
 namespace spice {
@@ -21,13 +20,6 @@ public:
 Error(const std::string ) : std::runtime_error(message) {}
 };
 
-template
-const T (const T ) noexcept
-{
-::syslog(LOG_ERR, "%s\n", error.what());
-return error;
-}
-
 }} // namespace spice::streaming_agent
 
 #endif // SPICE_STREAMING_AGENT_ERROR_HPP
diff --git a/src/Makefile.am b/src/Makefile.am
index 36a5d8a..dc64c29 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -65,6 +65,7 @@ spice_streaming_agent_SOURCES = \
jpeg.hpp \
stream-port.cpp \
stream-port.hpp \
+   utils.hpp \
$(NULL)
 
 if HAVE_GST
diff --git a/src/cursor-updater.cpp b/src/cursor-updater.cpp
index c27131b..779f878 100644
--- a/src/cursor-updater.cpp
+++ b/src/cursor-updater.cpp
@@ -14,6 +14,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 
diff --git a/src/spice-streaming-agent.cpp b/src/spice-streaming-agent.cpp
index 4b44df3..1eb8e1b 100644
--- a/src/spice-streaming-agent.cpp
+++ b/src/spice-streaming-agent.cpp
@@ -9,6 +9,7 @@
 #include "cursor-updater.hpp"
 #include "frame-log.hpp"
 #include "stream-port.hpp"
+#include "utils.hpp"
 #include 
 
 #include 
@@ -254,7 +255,7 @@ do_capture(StreamPort _port, FrameLog _log)
 try {
 stream_port.send(frame.buffer, 
frame.buffer_size);
 } catch (const WriteError& e) {
-syslog(e);
+utils::syslog(e);
 break;
 }
 frame_log.log_stat("Sent frame");
diff --git a/src/utils.hpp b/src/utils.hpp
new file mode 100644
index 000..64cb538
--- /dev/null
+++ b/src/utils.hpp
@@ -0,0 +1,24 @@
+/* \copyright
+ * Copyright 2018 Red Hat Inc. All rights reserved.
+ */
+
+#ifndef SPICE_STREAMING_AGENT_UTILS_HPP
+#define SPICE_STREAMING_AGENT_UTILS_HPP
+
+#include 
+
+
+namespace spice {
+namespace streaming_agent {
+namespace utils {
+
+template
+const T (const T ) noexcept
+{
+::syslog(LOG_ERR, "%s\n", error.what());
+return error;
+}
+
+}}} // namespace spice::streaming_agent::utils
+
+#endif // SPICE_STREAMING_AGENT_UTILS_HPP
-- 
2.19.2

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH spice-streaming-agent 3/3] Export symbols in the binary to use by the plugins

2018-12-04 Thread Lukáš Hrázký
This commits adds the -export-dynamic linker flag to export dynamic
symbols to be used by the streaming agent's plugins. It also adds the
-fvisibility=hidden compiler flag to hide all symbols by default (along
with -fvisibility-inline-hidden for C++ inline functions).

Then it adds the visibility("default") attribute to the namespace
containing the Error class, as that one needs to be exported and have
its typeinfo defined for exception catching to work.

Signed-off-by: Lukáš Hrázký 
---
 include/spice-streaming-agent/error.hpp | 2 +-
 src/Makefile.am | 4 
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/include/spice-streaming-agent/error.hpp 
b/include/spice-streaming-agent/error.hpp
index 3202d78..c0d4755 100644
--- a/include/spice-streaming-agent/error.hpp
+++ b/include/spice-streaming-agent/error.hpp
@@ -11,7 +11,7 @@
 #include 
 
 
-namespace spice {
+namespace spice __attribute__ ((visibility ("default"))) {
 namespace streaming_agent {
 
 class Error : public std::runtime_error
diff --git a/src/Makefile.am b/src/Makefile.am
index dc64c29..bae3f9d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -22,10 +22,13 @@ AM_CPPFLAGS = \
$(NULL)
 
 AM_CFLAGS = \
+   -fvisibility=hidden \
$(WARN_CFLAGS) \
$(NULL)
 
 AM_CXXFLAGS = \
+   -fvisibility=hidden \
+   -fvisibility-inlines-hidden \
$(WARN_CXXFLAGS) \
$(NULL)
 
@@ -38,6 +41,7 @@ libstreaming_utils_a_SOURCES = \
$(NULL)
 
 spice_streaming_agent_LDFLAGS = \
+   -export-dynamic \
$(RELRO_LDFLAGS) \
$(NO_INDIRECT_LDFLAGS) \
$(NULL)
-- 
2.19.2

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH spice-streaming-agent 1/3] Make error.hpp and the Error class a public API

2018-12-04 Thread Lukáš Hrázký
Moves IOError and its descendants to stream-port.hpp, as those are I/O
errors related to that. Makes the Error class a public base class for
exceptions thrown across the API boundary.

Note exception ABI conpatibility is not guaranteed between different
compilers, but it is compatible between gcc and clang so for these two
compilers it is safe.

Signed-off-by: Lukáš Hrázký 
---
 include/spice-streaming-agent/Makefile.am |  1 +
 .../spice-streaming-agent}/error.hpp  | 22 +--
 src/Makefile.am   |  2 --
 src/cursor-updater.cpp|  2 +-
 src/error.cpp | 21 --
 src/frame-log.cpp |  2 +-
 src/spice-streaming-agent.cpp |  2 +-
 src/stream-port.cpp   |  5 -
 src/stream-port.hpp   | 22 +++
 src/unittests/Makefile.am |  1 -
 src/unittests/test-stream-port.cpp|  2 +-
 11 files changed, 32 insertions(+), 50 deletions(-)
 rename {src => include/spice-streaming-agent}/error.hpp (63%)
 delete mode 100644 src/error.cpp

diff --git a/include/spice-streaming-agent/Makefile.am 
b/include/spice-streaming-agent/Makefile.am
index 844f791..bcd679b 100644
--- a/include/spice-streaming-agent/Makefile.am
+++ b/include/spice-streaming-agent/Makefile.am
@@ -1,6 +1,7 @@
 NULL =
 public_includedir = $(includedir)/spice-streaming-agent
 public_include_HEADERS = \
+   error.hpp \
frame-capture.hpp \
plugin.hpp \
$(NULL)
diff --git a/src/error.hpp b/include/spice-streaming-agent/error.hpp
similarity index 63%
rename from src/error.hpp
rename to include/spice-streaming-agent/error.hpp
index e30990f..2993dbb 100644
--- a/src/error.hpp
+++ b/include/spice-streaming-agent/error.hpp
@@ -18,27 +18,7 @@ namespace streaming_agent {
 class Error : public std::runtime_error
 {
 public:
-Error(const std::string );
-};
-
-class IOError : public Error
-{
-public:
-using Error::Error;
-
-IOError(const std::string , int sys_errno);
-};
-
-class ReadError : public IOError
-{
-public:
-using IOError::IOError;
-};
-
-class WriteError : public IOError
-{
-public:
-using IOError::IOError;
+Error(const std::string ) : std::runtime_error(message) {}
 };
 
 template
diff --git a/src/Makefile.am b/src/Makefile.am
index 104da47..36a5d8a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -57,8 +57,6 @@ spice_streaming_agent_SOURCES = \
concrete-agent.hpp \
cursor-updater.cpp \
cursor-updater.hpp \
-   error.cpp \
-   error.hpp \
frame-log.cpp \
frame-log.hpp \
mjpeg-fallback.cpp \
diff --git a/src/cursor-updater.cpp b/src/cursor-updater.cpp
index f0412db..c27131b 100644
--- a/src/cursor-updater.cpp
+++ b/src/cursor-updater.cpp
@@ -7,7 +7,7 @@
 
 #include "cursor-updater.hpp"
 
-#include "error.hpp"
+#include 
 
 #include 
 #include 
diff --git a/src/error.cpp b/src/error.cpp
deleted file mode 100644
index 561537d..000
--- a/src/error.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-/* The errors module.
- *
- * \copyright
- * Copyright 2018 Red Hat Inc. All rights reserved.
- */
-
-#include "error.hpp"
-
-#include 
-
-
-namespace spice {
-namespace streaming_agent {
-
-Error::Error(const std::string ) : std::runtime_error(message) {}
-
-IOError::IOError(const std::string , int sys_errno) :
-Error(msg + ": " + std::to_string(sys_errno) + " - " + strerror(sys_errno))
-{}
-
-}} // namespace spice::streaming_agent
diff --git a/src/frame-log.cpp b/src/frame-log.cpp
index cc993cd..62fffc3 100644
--- a/src/frame-log.cpp
+++ b/src/frame-log.cpp
@@ -6,8 +6,8 @@
 
 #include "frame-log.hpp"
 
-#include "error.hpp"
 #include "hexdump.h"
+#include 
 
 #include 
 #include 
diff --git a/src/spice-streaming-agent.cpp b/src/spice-streaming-agent.cpp
index 36d0692..4b44df3 100644
--- a/src/spice-streaming-agent.cpp
+++ b/src/spice-streaming-agent.cpp
@@ -9,7 +9,7 @@
 #include "cursor-updater.hpp"
 #include "frame-log.hpp"
 #include "stream-port.hpp"
-#include "error.hpp"
+#include 
 
 #include 
 #include 
diff --git a/src/stream-port.cpp b/src/stream-port.cpp
index afef2e9..2670120 100644
--- a/src/stream-port.cpp
+++ b/src/stream-port.cpp
@@ -5,7 +5,6 @@
  */
 
 #include "stream-port.hpp"
-#include "error.hpp"
 
 #include 
 #include 
@@ -19,6 +18,10 @@
 namespace spice {
 namespace streaming_agent {
 
+IOError::IOError(const std::string , int sys_errno) :
+Error(msg + ": " + std::to_string(sys_errno) + " - " + strerror(sys_errno))
+{}
+
 InboundMessage::InboundMessage(const StreamDevHeader , 
std::unique_ptr &) :
 header(header),
 data(std::move(data))
diff --git a/src/stream-port.hpp b/src/stream-port.hpp
index cf010a4..084

[Spice-devel] [PATCH spice-streaming-agent 0/3] Add an Error to the API

2018-12-04 Thread Lukáš Hrázký
Hello,

this series adds an Error class to the plugin API, to be thrown across
the API boundary. It also makes sure the symbols are properly exported
and the class has RTTI (or more precisely the information used to
identify the exceptions equivalent to RTTI) so that the exception can be
properly caught.

Cheers,
Lukas

Lukáš Hrázký (3):
  Make error.hpp and the Error class a public API
  Move the syslog() helper for errors to a new utils module
  Export symbols in the binary to use by the plugins

 include/spice-streaming-agent/Makefile.am |  1 +
 include/spice-streaming-agent/error.hpp   | 25 +++
 src/Makefile.am   |  7 ++-
 src/cursor-updater.cpp|  3 +-
 src/error.cpp | 21 -
 src/error.hpp | 53 ---
 src/frame-log.cpp |  2 +-
 src/spice-streaming-agent.cpp |  5 ++-
 src/stream-port.cpp   |  5 ++-
 src/stream-port.hpp   | 22 ++
 src/unittests/Makefile.am |  1 -
 src/unittests/test-stream-port.cpp|  2 +-
 src/utils.hpp | 24 ++
 13 files changed, 88 insertions(+), 83 deletions(-)
 create mode 100644 include/spice-streaming-agent/error.hpp
 delete mode 100644 src/error.cpp
 delete mode 100644 src/error.hpp
 create mode 100644 src/utils.hpp

-- 
2.19.2

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH vd_agent_linux v2] vdagent: Stop trying to connect to the daemon after a while

2018-11-20 Thread Lukáš Hrázký
On Mon, 2018-11-19 at 11:42 -0500, Frediano Ziglio wrote:
> > 
> > On Mon, 2018-11-19 at 10:23 +, Frediano Ziglio wrote:
> > > Do not try  indefinitely to connect to the daemon, should not
> > > take long to activate.
> > > 
> > > Signed-off-by: Frediano Ziglio 
> > > ---
> > >  src/vdagent/vdagent.c | 6 ++
> > >  1 file changed, 6 insertions(+)
> > > 
> > > Changes since v1:
> > > - log error when we reach the limit
> > > 
> > > diff --git a/src/vdagent/vdagent.c b/src/vdagent/vdagent.c
> > > index f7c8b72..7a58150 100644
> > > --- a/src/vdagent/vdagent.c
> > > +++ b/src/vdagent/vdagent.c
> > > @@ -53,6 +53,7 @@ typedef struct VDAgent {
> > >  struct vdagent_file_xfers *xfers;
> > >  struct udscs_connection *conn;
> > >  GIOChannel *x11_channel;
> > > +guint connection_attempts;
> > >  
> > >  GMainLoop *loop;
> > >  } VDAgent;
> > > @@ -370,6 +371,11 @@ static gboolean vdagent_init_async_cb(gpointer
> > > user_data)
> > >  daemon_read_complete,
> > >  daemon_disconnect_cb,
> > >  debug);
> > >  if (agent->conn == NULL) {
> > > +// limit connection attempts, this will try for 5 minutes
> > > +if (++agent->connection_attempts > 5 * 60) {
> > > +syslog(LOG_ERR, "Attempted to contact daemon for 5 minutes,
> > > giving up");
> > > +goto err_init;
> > > +}
> > 
> > (in reference to trying to keep it simple from v1 thread:)
> > I think using 60 instead of 1 in g_timeout_add_seconds() wouldn't be
> > much of a complication... unless there's something else I'm missing.
> > I'm also thinking this is being launched from a .desktop file so AFAIK
> > there is no easy way for a user to restart the service, a relogin is
> > needed?
> > 
> 
> It reconnects to the new daemon after detecting the disconnection.
> Not sure what will happen if the agent is updated... I think nothing
> or possibly the agent will end if not compatible with the new daemon.
> If you retry every minute is possible that the user has to wait 1
> minute instead of 1 second.
> Probably the optimal way would be to use inotify on the socket to
> wait for the new daemon, so something like:
> - try 10 times with 1 second delay
> - setup inotify
> - try once to avoid races
> - wait inotify
> - attempt connection again (repeat from first step)
> This way if the daemon is restored after even hours you don't have to
> keep polling.

Well, you wanted a simple solution and I agree with that. I suggested
something that keeps the agent running and doesn't really make it more
complicated. Now you're suggesting a much more complex solution... :)

> > I also just realized you should reset connection_attempts to 0 after a
> > successful connect?
> > 
> 
> The object is created again so will be 0 again (not that would hurt
> to reset on a successful connection).

Right, didn't notice that...

Cheers,
Lukas

> > Cheers,
> > Lukas
> > 
> > >  g_timeout_add_seconds(1, vdagent_init_async_cb, agent);
> > >  return G_SOURCE_REMOVE;
> > >  }
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH vd_agent_linux v2] vdagent: Stop trying to connect to the daemon after a while

2018-11-19 Thread Lukáš Hrázký
On Mon, 2018-11-19 at 10:23 +, Frediano Ziglio wrote:
> Do not try  indefinitely to connect to the daemon, should not
> take long to activate.
> 
> Signed-off-by: Frediano Ziglio 
> ---
>  src/vdagent/vdagent.c | 6 ++
>  1 file changed, 6 insertions(+)
> 
> Changes since v1:
> - log error when we reach the limit
> 
> diff --git a/src/vdagent/vdagent.c b/src/vdagent/vdagent.c
> index f7c8b72..7a58150 100644
> --- a/src/vdagent/vdagent.c
> +++ b/src/vdagent/vdagent.c
> @@ -53,6 +53,7 @@ typedef struct VDAgent {
>  struct vdagent_file_xfers *xfers;
>  struct udscs_connection *conn;
>  GIOChannel *x11_channel;
> +guint connection_attempts;
>  
>  GMainLoop *loop;
>  } VDAgent;
> @@ -370,6 +371,11 @@ static gboolean vdagent_init_async_cb(gpointer user_data)
>  daemon_read_complete, daemon_disconnect_cb,
>  debug);
>  if (agent->conn == NULL) {
> +// limit connection attempts, this will try for 5 minutes
> +if (++agent->connection_attempts > 5 * 60) {
> +syslog(LOG_ERR, "Attempted to contact daemon for 5 minutes, 
> giving up");
> +goto err_init;
> +}

(in reference to trying to keep it simple from v1 thread:)
I think using 60 instead of 1 in g_timeout_add_seconds() wouldn't be
much of a complication... unless there's something else I'm missing.
I'm also thinking this is being launched from a .desktop file so AFAIK
there is no easy way for a user to restart the service, a relogin is
needed?

I also just realized you should reset connection_attempts to 0 after a
successful connect?

Cheers,
Lukas

>  g_timeout_add_seconds(1, vdagent_init_async_cb, agent);
>  return G_SOURCE_REMOVE;
>  }
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH vd_agent_linux] vdagent: Stop trying to connect to the daemon after a while

2018-11-19 Thread Lukáš Hrázký
Hi,

On Fri, 2018-11-16 at 16:21 +, Frediano Ziglio wrote:
> Do not try  indefinitely to connect to the daemon, should not
> take long to activate.
> 
> Signed-off-by: Frediano Ziglio 
> ---
>  src/vdagent/vdagent.c | 5 +
>  1 file changed, 5 insertions(+)
> 
> diff --git a/src/vdagent/vdagent.c b/src/vdagent/vdagent.c
> index f7c8b72..e0228d7 100644
> --- a/src/vdagent/vdagent.c
> +++ b/src/vdagent/vdagent.c
> @@ -53,6 +53,7 @@ typedef struct VDAgent {
>  struct vdagent_file_xfers *xfers;
>  struct udscs_connection *conn;
>  GIOChannel *x11_channel;
> +guint connection_attempts;
>  
>  GMainLoop *loop;
>  } VDAgent;
> @@ -370,6 +371,10 @@ static gboolean vdagent_init_async_cb(gpointer user_data)
>  daemon_read_complete, daemon_disconnect_cb,
>  debug);
>  if (agent->conn == NULL) {
> +// limit connection attempts, this will try for 5 minutes
> +if (++agent->connection_attempts > 5 * 60) {
> +goto err_init;
> +}

Please add a log message saying you're giving up trying to connect...

Though would it not be better to just increase the interval to ~30-60
seconds instead of giving up altogether after some amount of quick
tries?

Cheers,
Lukas

>  g_timeout_add_seconds(1, vdagent_init_async_cb, agent);
>  return G_SOURCE_REMOVE;
>  }
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [RFC PATCH spice-protocol 1/3] Add a graphics device info message

2018-11-13 Thread Lukáš Hrázký
On Mon, 2018-11-12 at 14:44 -0600, Jonathon Jongsma wrote:
> On Mon, 2018-11-12 at 11:01 +0100, Lukáš Hrázký wrote:
> > On Thu, 2018-11-08 at 11:36 -0600, Jonathon Jongsma wrote:
> > > On Wed, 2018-11-07 at 18:23 +0100, Lukáš Hrázký wrote:
> > > > The message serves for passing the device address and device
> > > > display
> > > > ID
> > > 
> > > "serves for passing..." is a little strange to my ear. "serves to
> > > pass..." sounds OK. Or "is used for passing..." 
> > 
> > Ok, thanks :)
> > 
> > > > information for all display channels from SPICE server to the
> > > > vd_agent.
> > > > 
> > > > Signed-off-by: Lukáš Hrázký 
> > > > ---
> > > >  spice/vd_agent.h | 15 +++
> > > >  1 file changed, 15 insertions(+)
> > > > 
> > > > diff --git a/spice/vd_agent.h b/spice/vd_agent.h
> > > > index dda7044..a35f827 100644
> > > > --- a/spice/vd_agent.h
> > > > +++ b/spice/vd_agent.h
> > > > @@ -91,6 +91,7 @@ enum {
> > > >  VD_AGENT_CLIENT_DISCONNECTED,
> > > >  VD_AGENT_MAX_CLIPBOARD,
> > > >  VD_AGENT_AUDIO_VOLUME_SYNC,
> > > > +VD_AGENT_GRAPHICS_DEVICE_INFO,
> > > >  VD_AGENT_END_MESSAGE,
> > > >  };
> > > >  
> > > > @@ -248,6 +249,19 @@ typedef struct SPICE_ATTR_PACKED
> > > > VDAgentAudioVolumeSync {
> > > >  uint16_t volume[0];
> > > >  } VDAgentAudioVolumeSync;
> > > >  
> > > > +typedef struct SPICE_ATTR_PACKED  {
> > > > +uint32_t channel_id;
> > > > +uint32_t monitor_id;
> > > > +uint32_t device_display_id;
> > > > +uint32_t device_address_len;
> > > > +uint8_t device_address[0];  // a zero-terminated string
> > > > +} VDAgentGraphicsDeviceInfo;
> > > > +
> > > > +typedef struct SPICE_ATTR_PACKED VDAgentGraphicsDeviceInfos {
> > > > +uint32_t count;
> > > > +VDAgentGraphicsDeviceInfo graphics_device_infos[0];
> > > > +} VDAgentGraphicsDeviceInfos;
> > > > +
> > > 
> > > I'm not a big fan of this name. "Information" is slightly irregular
> > > word which doesn't really have singular and plural forms. So
> > > "Informations" or "Infos" sounds wrong to me. 
> > 
> > Yes, I know it's incorrect in english. I just followed the same
> > convention I always use, name a struct and then use the plural to
> > name
> > the container for it... What am I supposed to do if it doesn't work
> > for
> > "Info"? :) I need to name the inner struct and then the one
> > containing
> > the list, I prefer this to some arbitrary plays on the name...
> > 
> > > In addition, the VDAgentGraphicsDeviceInfo name implies to me that
> > > this
> > > struct represents information about a single device. But in
> > > reality, it
> > > represents information about a single spice display -- specifically
> > > which device display is associated with the spice display. So a
> > > single
> > > device with multiple displays would be represented by multiple info
> > > structs. So maybe a better name might be... (just brainstorming
> > > here):
> > > VDAgentSpiceDisplayInfo
> > > VDAgentChannelDisplayInfo
> > > VDAgentSpiceDisplayDeviceInfo
> > > 
> > > None of them are very nice, but I feel like the 'focus' of the name
> > > should be the on the spice display rather than the device...
> > 
> > What I did was take the name we used for the QEMU interface method:
> > spice_qxl_set_device_info. I thought "device_info" is too generic
> > outside a QXL interface context so I added the "graphics" to the
> > "device".
> 
> Right, except the data we're passing is not exactly the same thing that
> qemu passed to us. Qemu passed us a device address and a list of
> displays associated with a QXL instance. We took that information and
> essentially created a table which maps from a spice protocol display id
> to some information that describes a guest device display. That
> *mapping* is the important concept that we're passing down to the
> guest. After all, the device information is already essentially known
> to the guest. So it feels slightly misleading to call it
> VDAgentGraphicsDeviceInfo. Maybe something like
> VDAgentDeviceDisplayMap

Re: [Spice-devel] [RFC linux vdagent] Add POC for getting xrandr output from monitor ID

2018-11-13 Thread Lukáš Hrázký
Hi,

On Tue, 2018-11-13 at 09:04 +0100, Gerd Hoffmann wrote:
>   Hi,
> 
> > To look up a PCI device by address, I could use the /sys filesystem. So
> > for pci//02.0, I would translate the domain  into the
> > filesystem path '/sys/devices/pci:00/' assuming bus '00'?  And then
> > look inside that directory for the the path ':00:02.0'. And then
> > look for a path named 'drm' within that directory to determine whether
> > it's a drm card or not? Is the existence of the 'drm' directory the
> > thing that we should use to determine whether this is a drm card? 
> 
> Typically yes, except virtio-gpu which has an additional virtio level,
> i.e. /sys/devices/pci:00/:00:02.0/virtio/drm.

Why the exception? Doesn't make this check look that great and
reliable...

> > Or a slightly more complicated example (based on my laptop): Let's look
> > for this device:
> > 
> > 02:00.0 3D controller: NVIDIA Corporation GM108M [GeForce 940MX] (rev
> > a2)
> > 
> > So it's device 00.0 on bus 02. Here's the first part of lspci -t:
> > -[:00]-+-00.0
> >+-01.0-[01]--
> >+-01.2-[02]00.0
> > 
> > So it's attached to the PCI bridge at 01.2. Since the bus number ('02')
> > is not a part of our device address format, we would only be provided
> > the following address: pci//01.2/00.0
> > 
> > From this we can look for the PCI bridge at path
> > /sys/devices/pci:00/:00:01.2. Within this directory, we can
> > look for a path of ... it's unclear because we're not provided the bus
> > number, so we can't necessarily construct the path ':02:00.0' that
> > represents this device. We could simply look for files within the
> > directory that end with '00.0' and just assume that the one we find is
> > the correct one. But that doesn't seem cleaner and more elegant to me.
> 
> You can translate the path into a sysfs shell globbing pattern, then
> feed that into glob (see "man glob").
> 
> For "pci//01.2/00.0" the glob pattern would be
> "/sys/devices/pci:*/*:01.2/*:00.0"

That's what I had in mind.

Cheers,
Lukas

> HTH,
>   Gerd
> 
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [RFC PATCH spice-protocol 1/3] Add a graphics device info message

2018-11-12 Thread Lukáš Hrázký
On Thu, 2018-11-08 at 11:36 -0600, Jonathon Jongsma wrote:
> On Wed, 2018-11-07 at 18:23 +0100, Lukáš Hrázký wrote:
> > The message serves for passing the device address and device display
> > ID
> 
> "serves for passing..." is a little strange to my ear. "serves to
> pass..." sounds OK. Or "is used for passing..." 

Ok, thanks :)

> > information for all display channels from SPICE server to the
> > vd_agent.
> > 
> > Signed-off-by: Lukáš Hrázký 
> > ---
> >  spice/vd_agent.h | 15 +++
> >  1 file changed, 15 insertions(+)
> > 
> > diff --git a/spice/vd_agent.h b/spice/vd_agent.h
> > index dda7044..a35f827 100644
> > --- a/spice/vd_agent.h
> > +++ b/spice/vd_agent.h
> > @@ -91,6 +91,7 @@ enum {
> >  VD_AGENT_CLIENT_DISCONNECTED,
> >  VD_AGENT_MAX_CLIPBOARD,
> >  VD_AGENT_AUDIO_VOLUME_SYNC,
> > +VD_AGENT_GRAPHICS_DEVICE_INFO,
> >  VD_AGENT_END_MESSAGE,
> >  };
> >  
> > @@ -248,6 +249,19 @@ typedef struct SPICE_ATTR_PACKED
> > VDAgentAudioVolumeSync {
> >  uint16_t volume[0];
> >  } VDAgentAudioVolumeSync;
> >  
> > +typedef struct SPICE_ATTR_PACKED  {
> > +uint32_t channel_id;
> > +uint32_t monitor_id;
> > +uint32_t device_display_id;
> > +uint32_t device_address_len;
> > +uint8_t device_address[0];  // a zero-terminated string
> > +} VDAgentGraphicsDeviceInfo;
> > +
> > +typedef struct SPICE_ATTR_PACKED VDAgentGraphicsDeviceInfos {
> > +uint32_t count;
> > +VDAgentGraphicsDeviceInfo graphics_device_infos[0];
> > +} VDAgentGraphicsDeviceInfos;
> > +
> 
> I'm not a big fan of this name. "Information" is slightly irregular
> word which doesn't really have singular and plural forms. So
> "Informations" or "Infos" sounds wrong to me. 

Yes, I know it's incorrect in english. I just followed the same
convention I always use, name a struct and then use the plural to name
the container for it... What am I supposed to do if it doesn't work for
"Info"? :) I need to name the inner struct and then the one containing
the list, I prefer this to some arbitrary plays on the name...

> In addition, the VDAgentGraphicsDeviceInfo name implies to me that this
> struct represents information about a single device. But in reality, it
> represents information about a single spice display -- specifically
> which device display is associated with the spice display. So a single
> device with multiple displays would be represented by multiple info
> structs. So maybe a better name might be... (just brainstorming here):
> VDAgentSpiceDisplayInfo
> VDAgentChannelDisplayInfo
> VDAgentSpiceDisplayDeviceInfo
> 
> None of them are very nice, but I feel like the 'focus' of the name
> should be the on the spice display rather than the device...

What I did was take the name we used for the QEMU interface method:
spice_qxl_set_device_info. I thought "device_info" is too generic
outside a QXL interface context so I added the "graphics" to the
"device".

I don't find your suggestions particularly better :) Especially those
containing the word "Spice", I think that's redundant?

The outer struct with the array kind of does contain all the device
info, while the inner one is per display/monitor, so what about:

struct VDAgentGraphicsDeviceInfo {
...
VDAgentGraphicsDeviceDisplayInfo graphics_device_display_info[0];
};

We can still discuss the "GraphicsDevice" part (I'm not too happy about
it myself), but I still can't think of a better one...

> Also, I was comparing this message to the monitors config message and
> noticed that that message has a 'flags' field to accomodate different
> behavior that was added over time. If we add a 'flags' field, it would
> give us some future-proofing that may allow us to interpret the data
> slightly differently based on the existence of different flags.
> Worthwhile?

I don't know. The flags add the possibility to pass boolean values,
which is a very limited set of cases you are preparing for. Since we
can't predict the future... I'd lean towards not adding it. We can also
get into the (non)extesibility debate and perhaps add some generic
"padding" to the structs which could be used for anything later, but...

Thanks,
Lukas

> >  enum {
> >  VD_AGENT_CAP_MOUSE_STATE = 0,
> >  VD_AGENT_CAP_MONITORS_CONFIG,
> > @@ -264,6 +278,7 @@ enum {
> >  VD_AGENT_CAP_MONITORS_CONFIG_POSITION,
> >  VD_AGENT_CAP_FILE_XFER_DISABLED,
> >  VD_AGENT_CAP_FILE_XFER_DETAILED_ERRORS,
> > +VD_AGENT_CAP_GRAPHICS_DEVICE_INFO,
> >  VD_AGENT_END_CAP,
> >  };
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [RFC linux vdagent] Add POC for getting xrandr output from monitor ID

2018-11-08 Thread Lukáš Hrázký
Hello,

On Mon, 2018-11-05 at 17:09 -0600, Jonathon Jongsma wrote:
> This is just a proof of concept utility that takes a PCI device address
> and a monitor ID and finds the xrandr output associated with that
> monitor id.
> ---
> 
> Changes in v2:
>  - used different format for specifying the PCI address
>(pci/$domain/$dev.$fn)
>  - used err()/errx() to report errors (from err.h)
>  - Added some debug output (export DEBUG=1)
>  - read PCI address from sysfs by getting the link for
>/sys/class/drm/card0 instead of /sys/class/drm/card0/device
>  - handle the full PCI heirarchy (including bridges)
>  - handle different vendor/device types by customizing the expected
>xrandr names
>  - Query X outputs outside the loop so they don't get looked up for
>every different device
>  - handle Nvidia devices that don't provide outputs via the DRM
>subsystem by assuming that it's the only device being used by X and
>simply looking up the Nth Xrandr output.
>  - added tests
>  - various other fixes
> 
>  Makefile.am |  18 +
>  configure.ac|   1 +
>  src/vdagent/get-xrandr-output.c | 806 
>  3 files changed, 825 insertions(+)
>  create mode 100644 src/vdagent/get-xrandr-output.c
> 
> diff --git a/Makefile.am b/Makefile.am
> index 3e405bc..b159650 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -3,6 +3,7 @@ NULL =
>  
>  bin_PROGRAMS = src/spice-vdagent
>  sbin_PROGRAMS = src/spice-vdagentd
> +noinst_PROGRAMS = src/get-xrandr-output
>  
>  common_sources = \
>   src/udscs.c \
> @@ -77,6 +78,23 @@ src_spice_vdagentd_SOURCES =   \
>   src/vdagentd/virtio-port.h  \
>   $(NULL)
>  
> +src_get_xrandr_output_SOURCES = \
> + src/vdagent/get-xrandr-output.c \
> + $(NULL)
> +
> +src_get_xrandr_output_CFLAGS = \
> + $(AM_CPPFLAGS) \
> + $(DRM_CFLAGS) \
> + $(X_CFLAGS) \
> + $(GLIB2_CFLAGS) \
> + $(NULL)
> +
> +src_get_xrandr_output_LDADD = \
> + $(DRM_LIBS) \
> + $(X_LIBS) \
> + $(GLIB2_LIBS) \
> + $(NULL)
> +
>  if HAVE_CONSOLE_KIT
>  src_spice_vdagentd_SOURCES += src/vdagentd/console-kit.c
>  else
> diff --git a/configure.ac b/configure.ac
> index 7cb44db..55b031e 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -105,6 +105,7 @@ PKG_CHECK_MODULES(X, [xfixes xrandr >= 1.3 xinerama x11])
>  PKG_CHECK_MODULES(SPICE, [spice-protocol >= 0.12.13])
>  PKG_CHECK_MODULES(ALSA, [alsa >= 1.0.22])
>  PKG_CHECK_MODULES([DBUS], [dbus-1])
> +PKG_CHECK_MODULES([DRM], [libdrm])
>  
>  if test "$with_session_info" = "auto" || test "$with_session_info" = 
> "systemd"; then
>  PKG_CHECK_MODULES([LIBSYSTEMD_LOGIN],
> diff --git a/src/vdagent/get-xrandr-output.c b/src/vdagent/get-xrandr-output.c
> new file mode 100644
> index 000..c2116d2
> --- /dev/null
> +++ b/src/vdagent/get-xrandr-output.c
> @@ -0,0 +1,806 @@
> +/*  get-xrandr-output.c proof of concept for converting PCI address and 
> device
> + *  display id to an xrandr output in the guest.
> + *
> + * Copyright 2018 Red Hat, Inc.
> + *
> + * Red Hat Authors:
> + * Jonathon Jongsma 
> + *
> + * This program is free software: you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation, either version 3 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see .
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +static bool debug = false;
> +#define DEBUG(...) \
> +if (G_UNLIKELY(debug)) printf(__VA_ARGS__);
> +
> +typedef struct PciDevice {
> +int domain;
> +uint8_t bus;
> +uint8_t slot;
> +uint8_t function;
> +} PciDevice;
> +
> +typedef struct PciAddress {
> +int domain;
> +GList *devices; /* PciDevice */
> +} PciAddress;
> +
> +PciAddress* pci_address_new()
> +{
> +return g_new0(PciAddress, 1);
> +}
> +
> +void pci_address_free(PciAddress *addr)
> +{
> +g_list_free_full(addr->devices, g_free);
> +g_free(addr);
> +}
> +
> +
> +int read_next_hex_number(const char *input, char delim, char **endptr)
> +{
> +assert(input != NULL);
> +assert(endptr != NULL);
> +
> +const char *pos = strchr(input, delim);
> +int n;
> +if (!pos) {
> +*endptr = NULL;
> +return 0;
> +}
> +
> +char *endpos;
> +n = 

Re: [Spice-devel] [RFC PATCH vd_agent 3/3] Receive the graphics_device_info message

2018-11-08 Thread Lukáš Hrázký
On Thu, 2018-11-08 at 05:18 -0500, Frediano Ziglio wrote:
> > 
> > The graphics_device_info message contains the device display ID
> > information (device address and device display ID). Stores the data in a
> > hash table in vdagent.
> > 
> > Signed-off-by: Lukáš Hrázký 
> > ---
> >  src/vdagent/vdagent.c| 69 
> >  src/vdagentd-proto-strings.h |  1 +
> >  src/vdagentd-proto.h |  1 +
> >  src/vdagentd/vdagentd.c  | 16 +
> >  4 files changed, 87 insertions(+)
> > 
> > diff --git a/src/vdagent/vdagent.c b/src/vdagent/vdagent.c
> > index f7c8b72..d1af57f 100644
> > --- a/src/vdagent/vdagent.c
> > +++ b/src/vdagent/vdagent.c
> > @@ -53,6 +53,7 @@ typedef struct VDAgent {
> >  struct vdagent_file_xfers *xfers;
> >  struct udscs_connection *conn;
> >  GIOChannel *x11_channel;
> > +GHashTable *graphics_display_infos;
> >  
> >  GMainLoop *loop;
> >  } VDAgent;
> > @@ -95,6 +96,16 @@ static GOptionEntry entries[] = {
> >  { NULL }
> >  };
> >  
> > +typedef struct GraphicsDisplayInfo {
> 
> Why this name went from GraphicsDevice to GraphicsDisplay ?

Ah, sorry, a mistake in renaming...

> > +char device_address[256];
> > +uint32_t device_display_id;
> > +} GraphicsDisplayInfo;
> > +
> > +static void graphics_display_info_destroy(gpointer gdi)
> > +{
> > +g_free(gdi);
> > +}
> > +
> >  /**
> >   * xfer_get_download_directory
> >   *
> > @@ -159,6 +170,55 @@ static gboolean vdagent_finalize_file_xfer(VDAgent
> > *agent)
> >  return TRUE;
> >  }
> >  
> > +static void vdagent_handle_graphics_device_info(VDAgent *agent, uint8_t
> > *data, size_t size)
> > +{
> > +VDAgentGraphicsDeviceInfos *graphics_device_infos =
> > (VDAgentGraphicsDeviceInfos *)data;
> > +VDAgentGraphicsDeviceInfo *graphics_device_info =
> > graphics_device_infos->graphics_device_infos;
> > +
> > +void *buffer_end = data + size;
> > +
> > +syslog(LOG_INFO, "Received Graphics Device Info:");
> > +
> > +for (size_t i = 0; i < graphics_device_infos->count; ++i) {
> > +if ((void*) graphics_device_info > buffer_end ||
> > +(void*) (_device_info->device_address +
> > +graphics_device_info->device_address_len) > buffer_end)
> > {
> > +syslog(LOG_ERR, "Malformed graphics_display_info message, "
> > +   "extends beyond the end of the buffer");
> > +break;
> > +}
> > +
> > +syslog(LOG_INFO, "   channel_id: %u monitor_id: %u device_address:
> > %s, "
> > +   "device_display_id: %u",
> > +   graphics_device_info->channel_id,
> > +   graphics_device_info->monitor_id,
> > +   graphics_device_info->device_address,
> > +   graphics_device_info->device_display_id);
> > +
> > +GraphicsDisplayInfo *value = g_malloc(sizeof(GraphicsDisplayInfo));
> 
> You can use g_new.
> 
> > +
> > +size_t device_address_len =
> > graphics_device_info->device_address_len;
> > +if (device_address_len > sizeof(value->device_address)) {
> > +syslog(LOG_ERR, "Received a device address longer than %lu, "
> > +   "will be truncated!", device_address_len);
> > +device_address_len = sizeof(value->device_address);
> > +}
> > +
> > +strncpy(value->device_address,
> > +(char*) graphics_device_info->device_address,
> > +device_address_len);
> > +value->device_address[device_address_len] = '\0';  // make sure the
> > string is terminated
> 
> Can overflow if device_address_len == sizeof(value->device_address), will
> overflow on the ID which probably will contain a 0 inside so not a big deal
> but still overflow. Better to write the above condition as:
> 
>if (device_address_len >= sizeof(value->device_address)) {
>   syslog(LOG_ERR, "Received a device address longer than %lu, "
>  "will be truncated!", device_address_len);
>   device_address_len = sizeof(value->device_address) - 1;
>   }

Good catch!

> > +value->device_display_id = graphics_device_info->device_display_id;
> > +
> > +

Re: [Spice-devel] spice-streaming-agent can't work correctly

2018-11-08 Thread Lukáš Hrázký
Hello,

On Thu, 2018-11-08 at 17:38 +0800, wangjiedong wrote:
> Recently I compile spice-protocol-0.12.15 and 
> spice-server-0.14.1(--enable-lz4=yes --enable-gstreamer=yes 
> --enable-smartcard=yes --with-sasl=yes) on host Ubuntu 18.04, and compile  
> spice-protocol-0.12.15 and spice-streaming-agent-0.2 on guest VM.
> 
> 
> I use remote-viewer to connect guest VM , and the command 
> spice-streaming-agent can exec successfully. then another remote-viewer 
> window named display 2 appears, and the video becomes more stalling than 
> never using spice-streaming-agent.

Is the display 2 showing the same content as display 1?

The second display is streaming your VM desktop using the MJPEG plugin.
This uses SW encoding in the guest and SW decoding on the client, so
it's adding significant CPU load and this use case has no actual
practical benefit (classic SPICE performs better).

I'm not sure what is your goal, but at this point, unless you want to
develop your own streaming agent plugin, you probably don't want to use
the streaming agent.

Cheers,
Lukas

> What is the reason for this , any wrong configuration or something wrong else?
> 
> 
> Thanks for help !
> ___
> Spice-devel mailing list
> Spice-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/spice-devel
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [RFC PATCH spice v3 1/3] QXL interface: add a function to identify monitors in the guest

2018-11-08 Thread Lukáš Hrázký
On Wed, 2018-11-07 at 16:01 -0600, Jonathon Jongsma wrote:
> On Wed, 2018-11-07 at 11:49 +0100, Lukáš Hrázký wrote:
> > Adds a function to let QEMU provide information to identify graphics
> > devices and their monitors in the guest. The function
> > (spice_qxl_set_device_info) sets the device address (e.g. a PCI path)
> > and monitor ID -> device display ID mapping of displays exposed by
> > given
> > QXL interface.
> 
> The phrase "monitor ID" should be described / explained more explicitly
> in the commit log, I think. As far as I can tell, we're using the term
> "monitor ID" to mean a 0-based index of monitors that are associated
> with this QXL instance. Right?

I can add some description of what monitor ID is to the commit log, I
felt the detailed description is more useful in code and didn't want to
repeat myself here.

> > Signed-off-by: Lukáš Hrázký 
> > ---
> >  server/red-qxl.c | 44 ++
> >  server/spice-qxl.h   | 46
> > 
> >  server/spice-server.syms |  5 +
> >  3 files changed, 95 insertions(+)
> > 
> > diff --git a/server/red-qxl.c b/server/red-qxl.c
> > index 97940611..0ea424cd 100644
> > --- a/server/red-qxl.c
> > +++ b/server/red-qxl.c
> > @@ -41,6 +41,9 @@
> >  #include "red-qxl.h"
> >  
> >  
> > +#define MAX_DEVICE_ADDRESS_LEN 256
> > +#define MAX_MONITORS_COUNT 16
> > +
> >  struct QXLState {
> >  QXLWorker qxl_worker;
> >  QXLInstance *qxl;
> > @@ -53,6 +56,9 @@ struct QXLState {
> >  unsigned int max_monitors;
> >  RedsState *reds;
> >  RedWorker *worker;
> > +char device_address[MAX_DEVICE_ADDRESS_LEN];
> > +uint32_t device_display_ids[MAX_MONITORS_COUNT];
> > +size_t monitors_count;  // length of ^^^
> >  
> >  pthread_mutex_t scanout_mutex;
> >  SpiceMsgDisplayGlScanoutUnix scanout;
> > @@ -846,6 +852,44 @@ void red_qxl_gl_draw_async_complete(QXLInstance
> > *qxl)
> >  red_qxl_async_complete(qxl, cookie);
> >  }
> >  
> > +SPICE_GNUC_VISIBLE
> > +void spice_qxl_set_device_info(QXLInstance *instance,
> > +   const char *device_address,
> > +   uint32_t device_display_id_start,
> > +   uint32_t device_display_id_count)
> > +{
> > +g_return_if_fail(device_address != NULL);
> > +
> > +size_t da_len = strnlen(device_address, MAX_DEVICE_ADDRESS_LEN);
> > +if (da_len >= MAX_DEVICE_ADDRESS_LEN) {
> > +spice_error("Device address too long: %lu > %u", da_len,
> > MAX_DEVICE_ADDRESS_LEN);
> > +return;
> > +}
> > +
> > +if (device_display_id_count > MAX_MONITORS_COUNT) {
> > +spice_error("Device display ID count (%u) is greater
> > thanbelieve limit %u",
> > +device_display_id_count,
> > +MAX_MONITORS_COUNT);
> > +return;
> > +}
> > +
> > +strncpy(instance->st->device_address, device_address,
> > MAX_DEVICE_ADDRESS_LEN);
> > +
> > +g_debug("QXL Instance %d setting device address \"%s\" and
> > monitor -> device display mapping:",
> > +instance->id,
> > +device_address);
> > +
> > +// store the mapping monitor_id -> device_display_id
> > +for (uint32_t monitor_id = 0; monitor_id <
> > device_display_id_count; ++monitor_id) {
> 
> In theory, you could simply use instance->st->monitors_count here
> instead of a separate monitor_id variable. Probably clearer the way you
> wrote it though...

Right... :)

> > +uint32_t device_display_id = device_display_id_start +
> > monitor_id;
> > +instance->st->device_display_ids[monitor_id] =
> > device_display_id;
> > +g_debug("   monitor ID %u -> device display ID %u",
> > +monitor_id, device_display_id);
> > +}
> > +
> > +instance->st->monitors_count = device_display_id_count;
> > +}
> > +
> >  void red_qxl_init(RedsState *reds, QXLInstance *qxl)
> >  {
> >  QXLState *qxl_state;
> > diff --git a/server/spice-qxl.h b/server/spice-qxl.h
> > index 0c4e75fc..547d3d93 100644
> > --- a/server/spice-qxl.h
> > +++ b/server/spice-qxl.h
> > @@ -115,6 +115,52 @@ void spice_qxl_gl_draw_async(QXLInstance
> > *instance,
> >  

Re: [Spice-devel] [RFC PATCH spice v3 1/3] QXL interface: add a function to identify monitors in the guest

2018-11-08 Thread Lukáš Hrázký
Hello,

On Thu, 2018-11-08 at 07:49 +0100, Gerd Hoffmann wrote:
>   Hi,
> 
> > + * The device_display_id_{start,count} denotes the sequence of device 
> > display
> > + * IDs that map to the zero-based sequence of monitor IDs provided by 
> > monitors
> > + * config on this interface. For example with device_display_id_start = 2 
> > and
> > + * device_display_id_count = 3 you get the following mapping:
> > + * monitor_id  ->  device_display_id
> > + *  0  ->  2
> > + *  1  ->  3
> > + *  2  ->  4
> > + *
> > + * Note this example is unsupported in practice. The only supported cases 
> > are
> > + * either a single device display ID (count = 1) or multiple device 
> > display IDs
> > + * in a sequence starting from 0.
> 
> This is confusing.  The usage of this api in the qemu counterpart looks
> sane though.

Not sure what you find confusing in particular... The example? Using an
example and then saying it's not supported? (I wated to use a
nontrivial example that will show the concept...) Suggestions for
improvement?

Thanks,
Lukas

> cheers,
>   Gerd
> 
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH spice-server] char-device: Remove initial underscores from __red_char_device_write_buffer_get

2018-11-08 Thread Lukáš Hrázký
On Thu, 2018-11-08 at 08:53 +, Frediano Ziglio wrote:
> Just cosmetic changes, the static function had underscores to
> distinguish from the exported one which was recently renamed.
> 
> Signed-off-by: Frediano Ziglio 
> ---
>  server/char-device.c | 19 +--
>  1 file changed, 9 insertions(+), 10 deletions(-)
> 
> diff --git a/server/char-device.c b/server/char-device.c
> index 6df04660..64b41a94 100644
> --- a/server/char-device.c
> +++ b/server/char-device.c
> @@ -531,9 +531,9 @@ static void red_char_device_write_retry(void *opaque)
>  red_char_device_write_to_device(dev);
>  }
>  
> -static RedCharDeviceWriteBuffer *__red_char_device_write_buffer_get(
> -RedCharDevice *dev, RedClient *client,
> -int size, WriteBufferOrigin origin, int migrated_data_tokens)
> +static RedCharDeviceWriteBuffer *
> +red_char_device_write_buffer_get(RedCharDevice *dev, RedClient *client, int 
> size,
> + WriteBufferOrigin origin, int 
> migrated_data_tokens)
>  {
>  RedCharDeviceWriteBuffer *ret;
>  
> @@ -600,17 +600,16 @@ RedCharDeviceWriteBuffer 
> *red_char_device_write_buffer_get_client(RedCharDevice
>int size)
>  {
>  spice_assert(client);
> -return  __red_char_device_write_buffer_get(dev, client, size,
> -WRITE_BUFFER_ORIGIN_CLIENT,
> -0);
> +return  red_char_device_write_buffer_get(dev, client, size, 
> WRITE_BUFFER_ORIGIN_CLIENT, 0);
>  }
>  
>  RedCharDeviceWriteBuffer 
> *red_char_device_write_buffer_get_server(RedCharDevice *dev,
>int size,
>bool 
> use_token)
>  {
> -return  __red_char_device_write_buffer_get(dev, NULL, size,
> -use_token ? WRITE_BUFFER_ORIGIN_SERVER : 
> WRITE_BUFFER_ORIGIN_SERVER_NO_TOKEN, 0);
> +WriteBufferOrigin origin =
> +use_token ? WRITE_BUFFER_ORIGIN_SERVER : 
> WRITE_BUFFER_ORIGIN_SERVER_NO_TOKEN;
> +return  red_char_device_write_buffer_get(dev, NULL, size, origin, 0);
>  }
>  
>  static RedCharDeviceWriteBuffer 
> *red_char_device_write_buffer_ref(RedCharDeviceWriteBuffer *write_buf)
> @@ -964,12 +963,12 @@ bool red_char_device_restore(RedCharDevice *dev,
>  if (mig_data->write_size > 0) {
>  if (mig_data->write_num_client_tokens) {
>  dev->priv->cur_write_buf =
> -__red_char_device_write_buffer_get(dev, dev_client->client,
> +red_char_device_write_buffer_get(dev, dev_client->client,
>  mig_data->write_size, WRITE_BUFFER_ORIGIN_CLIENT,
>  mig_data->write_num_client_tokens);
>  } else {
>  dev->priv->cur_write_buf =
> -__red_char_device_write_buffer_get(dev, NULL,
> +red_char_device_write_buffer_get(dev, NULL,
>  mig_data->write_size, WRITE_BUFFER_ORIGIN_SERVER, 0);
>  }
>  /* the first write buffer contains all the data that was saved for 
> migration */

Acked-by: Lukáš Hrázký 
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [RFC PATCH 0/3] Send the device display info to the vd_agent

2018-11-07 Thread Lukáš Hrázký
Hello,

this series follows these two:
https://lists.freedesktop.org/archives/spice-devel/2018-November/046088.html
https://lists.freedesktop.org/archives/spice-devel/2018-November/046093.html

It sends the graphics device info (I've added the "graphics" to the name
here, as "device info" seems too generic out of QXL interface context)
from the SPICE server to the vd_agent.

I didn't add a capability for this, as the agent accepts unknown
messages and only logs a warning. Therefore the capability is not
strictly necessary and I think we're probably better without it?

The info is stored in a hash map in the vd_agent and ready for later
use.

Cheers,
Lukas


-- 
2.19.1

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [RFC PATCH vd_agent 3/3] Receive the graphics_device_info message

2018-11-07 Thread Lukáš Hrázký
The graphics_device_info message contains the device display ID
information (device address and device display ID). Stores the data in a
hash table in vdagent.

Signed-off-by: Lukáš Hrázký 
---
 src/vdagent/vdagent.c| 69 
 src/vdagentd-proto-strings.h |  1 +
 src/vdagentd-proto.h |  1 +
 src/vdagentd/vdagentd.c  | 16 +
 4 files changed, 87 insertions(+)

diff --git a/src/vdagent/vdagent.c b/src/vdagent/vdagent.c
index f7c8b72..d1af57f 100644
--- a/src/vdagent/vdagent.c
+++ b/src/vdagent/vdagent.c
@@ -53,6 +53,7 @@ typedef struct VDAgent {
 struct vdagent_file_xfers *xfers;
 struct udscs_connection *conn;
 GIOChannel *x11_channel;
+GHashTable *graphics_display_infos;
 
 GMainLoop *loop;
 } VDAgent;
@@ -95,6 +96,16 @@ static GOptionEntry entries[] = {
 { NULL }
 };
 
+typedef struct GraphicsDisplayInfo {
+char device_address[256];
+uint32_t device_display_id;
+} GraphicsDisplayInfo;
+
+static void graphics_display_info_destroy(gpointer gdi)
+{
+g_free(gdi);
+}
+
 /**
  * xfer_get_download_directory
  *
@@ -159,6 +170,55 @@ static gboolean vdagent_finalize_file_xfer(VDAgent *agent)
 return TRUE;
 }
 
+static void vdagent_handle_graphics_device_info(VDAgent *agent, uint8_t *data, 
size_t size)
+{
+VDAgentGraphicsDeviceInfos *graphics_device_infos = 
(VDAgentGraphicsDeviceInfos *)data;
+VDAgentGraphicsDeviceInfo *graphics_device_info = 
graphics_device_infos->graphics_device_infos;
+
+void *buffer_end = data + size;
+
+syslog(LOG_INFO, "Received Graphics Device Info:");
+
+for (size_t i = 0; i < graphics_device_infos->count; ++i) {
+if ((void*) graphics_device_info > buffer_end ||
+(void*) (_device_info->device_address +
+graphics_device_info->device_address_len) > buffer_end) {
+syslog(LOG_ERR, "Malformed graphics_display_info message, "
+   "extends beyond the end of the buffer");
+break;
+}
+
+syslog(LOG_INFO, "   channel_id: %u monitor_id: %u device_address: %s, 
"
+   "device_display_id: %u",
+   graphics_device_info->channel_id,
+   graphics_device_info->monitor_id,
+   graphics_device_info->device_address,
+   graphics_device_info->device_display_id);
+
+GraphicsDisplayInfo *value = g_malloc(sizeof(GraphicsDisplayInfo));
+
+size_t device_address_len = graphics_device_info->device_address_len;
+if (device_address_len > sizeof(value->device_address)) {
+syslog(LOG_ERR, "Received a device address longer than %lu, "
+   "will be truncated!", device_address_len);
+device_address_len = sizeof(value->device_address);
+}
+
+strncpy(value->device_address,
+(char*) graphics_device_info->device_address,
+device_address_len);
+value->device_address[device_address_len] = '\0';  // make sure the 
string is terminated
+value->device_display_id = graphics_device_info->device_display_id;
+
+g_hash_table_insert(agent->graphics_display_infos,
+GUINT_TO_POINTER(graphics_device_info->channel_id + 
graphics_device_info->monitor_id),
+value);
+
+graphics_device_info = (VDAgentGraphicsDeviceInfo*) ((char*) 
graphics_device_info +
+sizeof(VDAgentGraphicsDeviceInfo) + 
graphics_device_info->device_address_len);
+}
+}
+
 static void vdagent_quit_loop(VDAgent *agent)
 {
 /* other GMainLoop(s) might be running, quit them before agent->loop */
@@ -243,6 +303,9 @@ static void daemon_read_complete(struct udscs_connection 
**connp,
   ((VDAgentFileXferDataMessage 
*)data)->id);
 }
 break;
+case VDAGENTD_GRAPHICS_DEVICE_INFO:
+vdagent_handle_graphics_device_info(agent, data, header->size);
+break;
 case VDAGENTD_CLIENT_DISCONNECTED:
 vdagent_clipboards_release_all(agent->clipboards);
 if (vdagent_finalize_file_xfer(agent)) {
@@ -345,6 +408,11 @@ static VDAgent *vdagent_new(void)
 g_unix_signal_add(SIGHUP, vdagent_signal_handler, agent);
 g_unix_signal_add(SIGTERM, vdagent_signal_handler, agent);
 
+agent->graphics_display_infos = g_hash_table_new_full(_direct_hash,
+  _direct_equal,
+  NULL,
+  
_display_info_destroy);
+
 return agent;
 }
 
@@ -359,6 +427,7 @@ static void vdagent_destroy(VDAgent *agent)
 
 g_clear_pointer(>x11_channel, g_io_channel_unref);
 g_clear_pointer(>loop, g_main_loop_unref);
+g_hash_tab

[Spice-devel] [RFC PATCH spice 2/3] Send the graphics device info to the vd_agent

2018-11-07 Thread Lukáš Hrázký
Sends the device address and device display IDs to the vdagent. The
message is sent either in reaction to the SPICE_MSGC_MAIN_AGENT_START
message or when the graphics device ino changes.

Signed-off-by: Lukáš Hrázký 
---
 server/red-qxl.c  | 20 +
 server/red-qxl.h  |  3 ++
 server/reds-private.h |  1 +
 server/reds.c | 68 +++
 server/reds.h |  1 +
 5 files changed, 93 insertions(+)

diff --git a/server/red-qxl.c b/server/red-qxl.c
index 6ffd8286..ebc14a46 100644
--- a/server/red-qxl.c
+++ b/server/red-qxl.c
@@ -889,6 +889,26 @@ void spice_qxl_set_device_info(QXLInstance *instance,
 
 instance->st->monitors_count = device_display_id_count;
 instance->st->max_monitors = device_display_id_count;
+
+reds_send_device_display_info(red_qxl_get_server(instance->st));
+}
+
+const char* red_qxl_get_device_address(const QXLInstance *qxl)
+{
+const QXLState *qxl_state = qxl->st;
+return qxl_state->device_address;
+}
+
+const uint32_t* red_qxl_get_device_display_ids(const QXLInstance *qxl)
+{
+const QXLState *qxl_state = qxl->st;
+return qxl_state->device_display_ids;
+}
+
+size_t red_qxl_get_monitors_count(const QXLInstance *qxl)
+{
+const QXLState *qxl_state = qxl->st;
+return qxl_state->monitors_count;
 }
 
 void red_qxl_init(RedsState *reds, QXLInstance *qxl)
diff --git a/server/red-qxl.h b/server/red-qxl.h
index 6014d32a..94753948 100644
--- a/server/red-qxl.h
+++ b/server/red-qxl.h
@@ -40,6 +40,9 @@ void red_qxl_put_gl_scanout(QXLInstance *qxl, 
SpiceMsgDisplayGlScanoutUnix *scan
 void red_qxl_gl_draw_async_complete(QXLInstance *qxl);
 int red_qxl_check_qxl_version(QXLInstance *qxl, int major, int minor);
 SpiceServer* red_qxl_get_server(QXLState *qxl);
+const char* red_qxl_get_device_address(const QXLInstance *qxl);
+const uint32_t* red_qxl_get_device_display_ids(const QXLInstance *qxl);
+size_t red_qxl_get_monitors_count(const QXLInstance *qxl);
 
 /* Wrappers around QXLInterface vfuncs */
 void red_qxl_get_init_info(QXLInstance *qxl, QXLDevInitInfo *info);
diff --git a/server/reds-private.h b/server/reds-private.h
index 920edc5c..9dbc7fa9 100644
--- a/server/reds-private.h
+++ b/server/reds-private.h
@@ -81,6 +81,7 @@ struct RedsState {
 SpiceWatch *secure_listen_watch;
 RedCharDeviceVDIPort *agent_dev;
 int pending_mouse_event;
+bool pending_device_display_info_message;
 GList *clients;
 MainChannel *main_channel;
 InputsChannel *inputs_channel;
diff --git a/server/reds.c b/server/reds.c
index 1ea5897b..a6d3fd73 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -257,6 +257,7 @@ typedef struct __attribute__ ((__packed__)) VDInternalBuf {
 VDAgentMessage header;
 union {
 VDAgentMouseState mouse_state;
+VDAgentGraphicsDeviceInfos graphics_device_info;
 }
 u;
 } VDInternalBuf;
@@ -894,6 +895,66 @@ static RedPipeItem 
*vdi_port_read_one_msg_from_device(RedCharDevice *self,
 return NULL;
 }
 
+void reds_send_device_display_info(RedsState *reds)
+{
+g_info("Sending device display info to the agent:");
+if (!reds->agent_dev->priv->agent_attached) {
+g_warning("   no agent attached!");
+return;
+}
+
+size_t message_size = sizeof(VDAgentGraphicsDeviceInfos);
+QXLInstance *qxl;
+FOREACH_QXL_INSTANCE(reds, qxl) {
+message_size +=
+(sizeof(VDAgentGraphicsDeviceInfo) + 
strlen(red_qxl_get_device_address(qxl)) + 1) *
+red_qxl_get_monitors_count(qxl);
+}
+
+RedCharDeviceWriteBuffer *char_dev_buf = 
vdagent_new_write_buffer(reds->agent_dev,
+ VD_AGENT_GRAPHICS_DEVICE_INFO,
+ message_size,
+ true);
+
+if (!char_dev_buf) {
+reds->pending_device_display_info_message = true;
+return;
+}
+
+VDInternalBuf *internal_buf = (VDInternalBuf *)char_dev_buf->buf;
+VDAgentGraphicsDeviceInfos *graphics_device_infos = 
_buf->u.graphics_device_info;
+graphics_device_infos->count = 0;
+
+VDAgentGraphicsDeviceInfo *graphics_device_info = 
graphics_device_infos->graphics_device_infos;
+FOREACH_QXL_INSTANCE(reds, qxl) {
+for (size_t i = 0; i < red_qxl_get_monitors_count(qxl); ++i) {
+graphics_device_info->channel_id = qxl->id;
+graphics_device_info->monitor_id = i;
+graphics_device_info->device_display_id = 
red_qxl_get_device_display_ids(qxl)[i];
+
+strcpy((char*) graphics_device_info->device_address, 
red_qxl_get_device_address(qxl));
+
+graphics_device_info->device_address_len =
+strlen((char*) graphics_device_info->device_address) + 1;
+
+g_info("   channel_id: %u monitor_id: %u, device_address: %s, 
device_display_

[Spice-devel] [RFC PATCH spice-protocol 1/3] Add a graphics device info message

2018-11-07 Thread Lukáš Hrázký
The message serves for passing the device address and device display ID
information for all display channels from SPICE server to the vd_agent.

Signed-off-by: Lukáš Hrázký 
---
 spice/vd_agent.h | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/spice/vd_agent.h b/spice/vd_agent.h
index dda7044..a35f827 100644
--- a/spice/vd_agent.h
+++ b/spice/vd_agent.h
@@ -91,6 +91,7 @@ enum {
 VD_AGENT_CLIENT_DISCONNECTED,
 VD_AGENT_MAX_CLIPBOARD,
 VD_AGENT_AUDIO_VOLUME_SYNC,
+VD_AGENT_GRAPHICS_DEVICE_INFO,
 VD_AGENT_END_MESSAGE,
 };
 
@@ -248,6 +249,19 @@ typedef struct SPICE_ATTR_PACKED VDAgentAudioVolumeSync {
 uint16_t volume[0];
 } VDAgentAudioVolumeSync;
 
+typedef struct SPICE_ATTR_PACKED VDAgentGraphicsDeviceInfo {
+uint32_t channel_id;
+uint32_t monitor_id;
+uint32_t device_display_id;
+uint32_t device_address_len;
+uint8_t device_address[0];  // a zero-terminated string
+} VDAgentGraphicsDeviceInfo;
+
+typedef struct SPICE_ATTR_PACKED VDAgentGraphicsDeviceInfos {
+uint32_t count;
+VDAgentGraphicsDeviceInfo graphics_device_infos[0];
+} VDAgentGraphicsDeviceInfos;
+
 enum {
 VD_AGENT_CAP_MOUSE_STATE = 0,
 VD_AGENT_CAP_MONITORS_CONFIG,
@@ -264,6 +278,7 @@ enum {
 VD_AGENT_CAP_MONITORS_CONFIG_POSITION,
 VD_AGENT_CAP_FILE_XFER_DISABLED,
 VD_AGENT_CAP_FILE_XFER_DETAILED_ERRORS,
+VD_AGENT_CAP_GRAPHICS_DEVICE_INFO,
 VD_AGENT_END_CAP,
 };
 
-- 
2.19.1

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH spice 1/2] char-device: separate functions to get write buffer for client and server

2018-11-07 Thread Lukáš Hrázký
Instead of having a single red_char_device_write_buffer_get function to
get both client and server buffers and decide by testing client == NULL,
have separate function for a client and for a server. The situation
should always be clear (you're either on the client or on the server
side) and you shouldn't need to parametrize that.

For the server case, add a use_token parameter instead of a separate
red_char_device_write_buffer_get_server_no_token function, as you may
want to parametrize that.

Signed-off-by: Lukáš Hrázký 
---
 server/char-device.c  | 22 --
 server/char-device.h  | 12 
 server/red-stream-device.c|  6 +++---
 server/reds.c | 17 +
 server/smartcard-channel-client.c |  3 +--
 server/smartcard.c|  8 ++--
 server/spicevmc.c | 12 ++--
 7 files changed, 45 insertions(+), 35 deletions(-)

diff --git a/server/char-device.c b/server/char-device.c
index ae538fab..6df04660 100644
--- a/server/char-device.c
+++ b/server/char-device.c
@@ -595,20 +595,22 @@ error:
 return NULL;
 }
 
-RedCharDeviceWriteBuffer *red_char_device_write_buffer_get(RedCharDevice *dev,
-   RedClient *client,
-   int size)
+RedCharDeviceWriteBuffer 
*red_char_device_write_buffer_get_client(RedCharDevice *dev,
+  RedClient 
*client,
+  int size)
 {
-   return  __red_char_device_write_buffer_get(dev, client, size,
- client ? WRITE_BUFFER_ORIGIN_CLIENT : WRITE_BUFFER_ORIGIN_SERVER,
- 0);
+spice_assert(client);
+return  __red_char_device_write_buffer_get(dev, client, size,
+WRITE_BUFFER_ORIGIN_CLIENT,
+0);
 }
 
-RedCharDeviceWriteBuffer *red_char_device_write_buffer_get_server_no_token(
-RedCharDevice *dev, int size)
+RedCharDeviceWriteBuffer 
*red_char_device_write_buffer_get_server(RedCharDevice *dev,
+  int size,
+  bool 
use_token)
 {
-   return  __red_char_device_write_buffer_get(dev, NULL, size,
- WRITE_BUFFER_ORIGIN_SERVER_NO_TOKEN, 0);
+return  __red_char_device_write_buffer_get(dev, NULL, size,
+use_token ? WRITE_BUFFER_ORIGIN_SERVER : 
WRITE_BUFFER_ORIGIN_SERVER_NO_TOKEN, 0);
 }
 
 static RedCharDeviceWriteBuffer 
*red_char_device_write_buffer_ref(RedCharDeviceWriteBuffer *write_buf)
diff --git a/server/char-device.h b/server/char-device.h
index dccd576d..893d3e4b 100644
--- a/server/char-device.h
+++ b/server/char-device.h
@@ -218,10 +218,14 @@ void 
red_char_device_send_to_client_tokens_set(RedCharDevice *dev,
uint32_t tokens);
 /** Write to device **/
 
-RedCharDeviceWriteBuffer *red_char_device_write_buffer_get(RedCharDevice *dev,
-   RedClient *client, 
int size);
-RedCharDeviceWriteBuffer *red_char_device_write_buffer_get_server_no_token(
-RedCharDevice *dev, int size);
+RedCharDeviceWriteBuffer 
*red_char_device_write_buffer_get_client(RedCharDevice *dev,
+  RedClient 
*client,
+  int size);
+
+/* Returns NULL if use_token == true and no tokens are available */
+RedCharDeviceWriteBuffer 
*red_char_device_write_buffer_get_server(RedCharDevice *dev,
+  int size,
+  bool 
use_token);
 
 /* Either add the buffer to the write queue or release it */
 void red_char_device_write_buffer_add(RedCharDevice *dev,
diff --git a/server/red-stream-device.c b/server/red-stream-device.c
index fb036b93..215ddbe7 100644
--- a/server/red-stream-device.c
+++ b/server/red-stream-device.c
@@ -228,7 +228,7 @@ handle_msg_invalid(StreamDevice *dev, 
SpiceCharDeviceInstance *sin, const char *
 
 RedCharDevice *char_dev = RED_CHAR_DEVICE(dev);
 RedCharDeviceWriteBuffer *buf =
-red_char_device_write_buffer_get_server_no_token(char_dev, total_size);
+red_char_device_write_buffer_get_server(char_dev, total_size, false);
 buf->buf_used = total_size;
 
 StreamDevHeader *const hdr = (StreamDevHeader *)buf->buf;
@@ -517,7 +517,7 @@ stream_device_stream_start(void *opaque, StreamMsgStartStop 
*start,
 
 RedCharDevice *char_dev = RED_CHAR_DEVICE(dev);
 RedCharDeviceWriteBuffer *buf =
-red_char_device_write_buffer_get_server_no_token(char_dev, total_size);
+red_char_device_write_buffer_get_server(char_dev, total_size, false);
 buf->

[Spice-devel] [PATCH spice 0/2] small refactor of char-device buffer creation

2018-11-07 Thread Lukáš Hrázký
Hello,

this is a small refactor I did for the char-device write buffer
creation, in particular for creating a write buffer for the vd_agent.

Of note, I didn't know how to test the smartcard and spicevmc codepaths,
I just assume they should be fine...

Lukáš Hrázký (2):
  char-device: separate functions to get write buffer for client and
server
  reds: move vdagent write buffer creation into a function

 server/char-device.c  | 22 
 server/char-device.h  | 12 +++--
 server/red-stream-device.c|  6 +--
 server/reds.c | 83 ---
 server/smartcard-channel-client.c |  3 +-
 server/smartcard.c|  8 ++-
 server/spicevmc.c | 12 ++---
 7 files changed, 80 insertions(+), 66 deletions(-)

-- 
2.19.1

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH spice 2/2] reds: move vdagent write buffer creation into a function

2018-11-07 Thread Lukáš Hrázký
Adds a function to create a write buffer for sending a message to
vdagent from the server to prevent code duplication.

Signed-off-by: Lukáš Hrázký 
---
 server/reds.c | 76 +++
 1 file changed, 40 insertions(+), 36 deletions(-)

diff --git a/server/reds.c b/server/reds.c
index b5fc8e1c..1ea5897b 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -504,6 +504,33 @@ static void reds_reset_vdp(RedsState *reds)
 }
 }
 
+static RedCharDeviceWriteBuffer *vdagent_new_write_buffer(RedCharDeviceVDIPort 
*agent_dev,
+  uint32_t type,
+  size_t size,
+  bool use_token)
+{
+uint32_t total_msg_size = sizeof(VDIChunkHeader) + sizeof(VDAgentMessage) 
+ size;
+
+RedCharDeviceWriteBuffer *char_dev_buf;
+char_dev_buf = 
red_char_device_write_buffer_get_server(RED_CHAR_DEVICE(agent_dev),
+   total_msg_size,
+   use_token);
+if (!char_dev_buf) {
+return NULL;  // no token was available
+}
+
+char_dev_buf->buf_used = total_msg_size;
+VDInternalBuf *internal_buf = (VDInternalBuf *)char_dev_buf->buf;
+internal_buf->chunk_header.port = VDP_SERVER_PORT;
+internal_buf->chunk_header.size = sizeof(VDAgentMessage) + size;
+internal_buf->header.protocol = VD_AGENT_PROTOCOL;
+internal_buf->header.type = type;
+internal_buf->header.opaque = 0;
+internal_buf->header.size = size;
+
+return char_dev_buf;
+}
+
 static int reds_main_channel_connected(RedsState *reds)
 {
 return main_channel_is_connected(reds->main_channel);
@@ -557,24 +584,13 @@ void reds_client_disconnect(RedsState *reds, RedClient 
*client)
 if (g_list_length(reds->clients) == 0) {
 /* Let the agent know the client is disconnected */
 if (reds->agent_dev->priv->agent_attached) {
-RedCharDeviceWriteBuffer *char_dev_buf;
-VDInternalBuf *internal_buf;
-uint32_t total_msg_size;
-
-total_msg_size = sizeof(VDIChunkHeader) + sizeof(VDAgentMessage);
-char_dev_buf = red_char_device_write_buffer_get_server(
-   RED_CHAR_DEVICE(reds->agent_dev), 
total_msg_size, false);
-char_dev_buf->buf_used = total_msg_size;
-internal_buf = (VDInternalBuf *)char_dev_buf->buf;
-internal_buf->chunk_header.port = VDP_SERVER_PORT;
-internal_buf->chunk_header.size = sizeof(VDAgentMessage);
-internal_buf->header.protocol = VD_AGENT_PROTOCOL;
-internal_buf->header.type = VD_AGENT_CLIENT_DISCONNECTED;
-internal_buf->header.opaque = 0;
-internal_buf->header.size = 0;
-
-red_char_device_write_buffer_add(RED_CHAR_DEVICE(reds->agent_dev),
- char_dev_buf);
+RedCharDeviceWriteBuffer *char_dev_buf =
+vdagent_new_write_buffer(reds->agent_dev,
+ VD_AGENT_CLIENT_DISCONNECTED,
+ 0,
+ false);
+
+red_char_device_write_buffer_add(RED_CHAR_DEVICE(reds->agent_dev), 
char_dev_buf);
 }
 
 /* Reset write filter to start with clean state on client reconnect */
@@ -926,37 +942,25 @@ int reds_has_vdagent(RedsState *reds)
 
 void reds_handle_agent_mouse_event(RedsState *reds, const VDAgentMouseState 
*mouse_state)
 {
-RedCharDeviceWriteBuffer *char_dev_buf;
-VDInternalBuf *internal_buf;
-uint32_t total_msg_size;
-
 if (!reds->inputs_channel || !reds->agent_dev->priv->agent_attached) {
 return;
 }
 
-total_msg_size = sizeof(VDIChunkHeader) + sizeof(VDAgentMessage) +
- sizeof(VDAgentMouseState);
-char_dev_buf = 
red_char_device_write_buffer_get_server(RED_CHAR_DEVICE(reds->agent_dev),
-   total_msg_size,
-   true);
+RedCharDeviceWriteBuffer *char_dev_buf = 
vdagent_new_write_buffer(reds->agent_dev,
+  
VD_AGENT_MOUSE_STATE,
+  
sizeof(VDAgentMouseState),
+  true);
 
 if (!char_dev_buf) {
 reds->pending_mouse_event = TRUE;
-
 return;
 }
+
 reds->pending_mouse_event = FALSE;
 
-internal_buf = (VDInternalBuf *)char_dev_buf->buf;
-internal_buf->chunk_header.port = VDP_SERVER_PORT;
-   

[Spice-devel] [RFC PATCH qemu v3 3/3] spice: set device address and device display ID in QXL interface

2018-11-07 Thread Lukáš Hrázký
Calls the new SPICE QXL interface function spice_qxl_set_device_info to
set the hardware address of the graphics device represented by the QXL
interface (e.g. a PCI path) and the device display IDs (the IDs of the
device's monitors that belong to this QXL interface).

Also stops using the deprecated spice_qxl_set_max_monitors, the new
interface function replaces it.

Signed-off-by: Lukáš Hrázký 
---
 hw/display/qxl.c   | 14 -
 include/ui/spice-display.h |  2 ++
 ui/spice-core.c| 42 ++
 ui/spice-display.c | 11 ++
 4 files changed, 68 insertions(+), 1 deletion(-)

diff --git a/hw/display/qxl.c b/hw/display/qxl.c
index f608abc769..f4bef8e4da 100644
--- a/hw/display/qxl.c
+++ b/hw/display/qxl.c
@@ -276,7 +276,8 @@ static void qxl_spice_monitors_config_async(PCIQXLDevice 
*qxl, int replay)
 QXL_COOKIE_TYPE_POST_LOAD_MONITORS_CONFIG,
 0));
 } else {
-#if SPICE_SERVER_VERSION >= 0x000c06 /* release 0.12.6 */
+#if SPICE_SERVER_VERSION >= 0x000c06 /* release 0.12.6 */ && \
+SPICE_SERVER_VERSION < 0x000e02
 if (qxl->max_outputs) {
 spice_qxl_set_max_monitors(>ssd.qxl, qxl->max_outputs);
 }
@@ -2184,6 +2185,17 @@ static void qxl_realize_common(PCIQXLDevice *qxl, Error 
**errp)
SPICE_INTERFACE_QXL_MAJOR, SPICE_INTERFACE_QXL_MINOR);
 return;
 }
+
+#if SPICE_SERVER_VERSION >= 0x000e02 /* release 0.14.2 */
+char device_address[256] = "";
+if (qemu_spice_fill_device_address(qxl->vga.con, device_address, 256)) {
+spice_qxl_set_device_info(>ssd.qxl,
+  device_address,
+  0,
+  qxl->max_outputs);
+}
+#endif
+
 qemu_add_vm_change_state_handler(qxl_vm_change_state_handler, qxl);
 
 qxl->update_irq = qemu_bh_new(qxl_update_irq_bh, qxl);
diff --git a/include/ui/spice-display.h b/include/ui/spice-display.h
index 87a84a59d4..7608fa7ebd 100644
--- a/include/ui/spice-display.h
+++ b/include/ui/spice-display.h
@@ -179,3 +179,5 @@ void qemu_spice_wakeup(SimpleSpiceDisplay *ssd);
 void qemu_spice_display_start(void);
 void qemu_spice_display_stop(void);
 int qemu_spice_display_is_running(SimpleSpiceDisplay *ssd);
+
+bool qemu_spice_fill_device_address(QemuConsole *con, char *device_address, 
size_t size);
diff --git a/ui/spice-core.c b/ui/spice-core.c
index a4fbbc3898..0bc8b002ec 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -35,6 +35,8 @@
 #include "qemu/option.h"
 #include "migration/misc.h"
 #include "hw/hw.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_bus.h"
 #include "ui/spice-display.h"
 
 /* core bits */
@@ -871,6 +873,46 @@ bool qemu_spice_have_display_interface(QemuConsole *con)
 return false;
 }
 
+/*
+ * Recursively (in reverse order) appends addresses of PCI devices as it moves
+ * up in the PCI hierarchy.
+ *
+ * @returns true on success, false when the buffer wasn't large enough
+ */
+static bool append_pci_address(char *buf, size_t buf_size, const PCIDevice 
*pci)
+{
+PCIBus *bus = pci_get_bus(pci);
+if (!pci_bus_is_root(bus)) {
+append_pci_address(buf, buf_size, bus->parent_dev);
+}
+
+size_t len = strlen(buf);
+ssize_t written = snprintf(buf + len, buf_size - len, "/%02x.%x",
+PCI_SLOT(pci->devfn), PCI_FUNC(pci->devfn));
+
+return written > 0 && written < buf_size - len;
+}
+
+bool qemu_spice_fill_device_address(QemuConsole *con, char *device_address, 
size_t size)
+{
+DeviceState *dev = DEVICE(object_property_get_link(OBJECT(con), "device", 
_abort));
+PCIDevice *pci = (PCIDevice *) object_dynamic_cast(OBJECT(dev), 
TYPE_PCI_DEVICE);
+
+if (pci == NULL) {
+warn_report("Setting device address of a display device to SPICE: Not 
a PCI device.");
+return false;
+}
+
+strncpy(device_address, "pci/", size);
+if (!append_pci_address(device_address, size, pci)) {
+warn_report("Setting device address of a display device to SPICE: "
+"Too many PCI devices in the chain.");
+return false;
+}
+
+return true;
+}
+
 int qemu_spice_add_display_interface(QXLInstance *qxlin, QemuConsole *con)
 {
 if (g_slist_find(spice_consoles, con)) {
diff --git a/ui/spice-display.c b/ui/spice-display.c
index 2f8adb6b9f..578ec6bf8b 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -1129,6 +1129,17 @@ static void qemu_spice_display_init_one(QemuConsole *con)
 
 ssd->qxl.base.sif = _interface.base;
 qemu_spice_add_display_interface(>qxl, con);
+
+#if SPICE_SERVER_VERSION >= 0x000e02 /* release 0.14.2 */
+char device_address[256] = "";
+if 

[Spice-devel] [RFC PATCH spice/qemu v3 0/3] QXL interface to set monitor ID

2018-11-07 Thread Lukáš Hrázký
Hello,

another version of the proposed API for monitor identification
information. Still not for merge yet, the plan is to merge when it's
complete.

Changes since v2:
* Merged the two API functions into one:
  spice_qxl_set_device_info(QXLInstance *instance,
const char *device_address,
uint32_t device_display_id_start,
uint32_t device_display_id_count)

* Minor fixes and documentation adjustments

-- 
2.19.1

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [RFC PATCH spice v3 2/3] QXL interface: deprecate spice_qxl_set_max_monitors

2018-11-07 Thread Lukáš Hrázký
Replace it by spice_qxl_set_device_info. Note we can't use
monitors_count for what's stored in max_monitors, because monitors_count
denotes the length of the device_display_ids array, which
spice_qxl_set_max_monitors doesn't touch.

Signed-off-by: Lukáš Hrázký 
---
 server/red-qxl.c   | 1 +
 server/spice-qxl.h | 4 ++--
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/server/red-qxl.c b/server/red-qxl.c
index 0ea424cd..6ffd8286 100644
--- a/server/red-qxl.c
+++ b/server/red-qxl.c
@@ -888,6 +888,7 @@ void spice_qxl_set_device_info(QXLInstance *instance,
 }
 
 instance->st->monitors_count = device_display_id_count;
+instance->st->max_monitors = device_display_id_count;
 }
 
 void red_qxl_init(RedsState *reds, QXLInstance *qxl)
diff --git a/server/spice-qxl.h b/server/spice-qxl.h
index 547d3d93..e7af5e5e 100644
--- a/server/spice-qxl.h
+++ b/server/spice-qxl.h
@@ -101,9 +101,9 @@ void spice_qxl_monitors_config_async(QXLInstance *instance, 
QXLPHYSICAL monitors
  int group_id, uint64_t cookie);
 /* since spice 0.12.3 */
 void spice_qxl_driver_unload(QXLInstance *instance);
-/* since spice 0.12.6 */
+/* since spice 0.12.6, deprecated since 0.14.2, spice_qxl_set_device_info 
replaces it */
 void spice_qxl_set_max_monitors(QXLInstance *instance,
-unsigned int max_monitors);
+unsigned int max_monitors) 
SPICE_GNUC_DEPRECATED;
 /* since spice 0.13.1 */
 void spice_qxl_gl_scanout(QXLInstance *instance,
   int fd,
-- 
2.19.1

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [RFC PATCH spice v3 1/3] QXL interface: add a function to identify monitors in the guest

2018-11-07 Thread Lukáš Hrázký
Adds a function to let QEMU provide information to identify graphics
devices and their monitors in the guest. The function
(spice_qxl_set_device_info) sets the device address (e.g. a PCI path)
and monitor ID -> device display ID mapping of displays exposed by given
QXL interface.

Signed-off-by: Lukáš Hrázký 
---
 server/red-qxl.c | 44 ++
 server/spice-qxl.h   | 46 
 server/spice-server.syms |  5 +
 3 files changed, 95 insertions(+)

diff --git a/server/red-qxl.c b/server/red-qxl.c
index 97940611..0ea424cd 100644
--- a/server/red-qxl.c
+++ b/server/red-qxl.c
@@ -41,6 +41,9 @@
 #include "red-qxl.h"
 
 
+#define MAX_DEVICE_ADDRESS_LEN 256
+#define MAX_MONITORS_COUNT 16
+
 struct QXLState {
 QXLWorker qxl_worker;
 QXLInstance *qxl;
@@ -53,6 +56,9 @@ struct QXLState {
 unsigned int max_monitors;
 RedsState *reds;
 RedWorker *worker;
+char device_address[MAX_DEVICE_ADDRESS_LEN];
+uint32_t device_display_ids[MAX_MONITORS_COUNT];
+size_t monitors_count;  // length of ^^^
 
 pthread_mutex_t scanout_mutex;
 SpiceMsgDisplayGlScanoutUnix scanout;
@@ -846,6 +852,44 @@ void red_qxl_gl_draw_async_complete(QXLInstance *qxl)
 red_qxl_async_complete(qxl, cookie);
 }
 
+SPICE_GNUC_VISIBLE
+void spice_qxl_set_device_info(QXLInstance *instance,
+   const char *device_address,
+   uint32_t device_display_id_start,
+   uint32_t device_display_id_count)
+{
+g_return_if_fail(device_address != NULL);
+
+size_t da_len = strnlen(device_address, MAX_DEVICE_ADDRESS_LEN);
+if (da_len >= MAX_DEVICE_ADDRESS_LEN) {
+spice_error("Device address too long: %lu > %u", da_len, 
MAX_DEVICE_ADDRESS_LEN);
+return;
+}
+
+if (device_display_id_count > MAX_MONITORS_COUNT) {
+spice_error("Device display ID count (%u) is greater than limit %u",
+device_display_id_count,
+MAX_MONITORS_COUNT);
+return;
+}
+
+strncpy(instance->st->device_address, device_address, 
MAX_DEVICE_ADDRESS_LEN);
+
+g_debug("QXL Instance %d setting device address \"%s\" and monitor -> 
device display mapping:",
+instance->id,
+device_address);
+
+// store the mapping monitor_id -> device_display_id
+for (uint32_t monitor_id = 0; monitor_id < device_display_id_count; 
++monitor_id) {
+uint32_t device_display_id = device_display_id_start + monitor_id;
+instance->st->device_display_ids[monitor_id] = device_display_id;
+g_debug("   monitor ID %u -> device display ID %u",
+monitor_id, device_display_id);
+}
+
+instance->st->monitors_count = device_display_id_count;
+}
+
 void red_qxl_init(RedsState *reds, QXLInstance *qxl)
 {
 QXLState *qxl_state;
diff --git a/server/spice-qxl.h b/server/spice-qxl.h
index 0c4e75fc..547d3d93 100644
--- a/server/spice-qxl.h
+++ b/server/spice-qxl.h
@@ -115,6 +115,52 @@ void spice_qxl_gl_draw_async(QXLInstance *instance,
  uint32_t w, uint32_t h,
  uint64_t cookie);
 
+/* since spice 0.14.2 */
+
+/**
+ * spice_qxl_set_device_info:
+ * @instance the QXL instance to set the path to
+ * @device_address the path of the device this QXL instance belongs to
+ * @device_display_id_start the starting device display ID of this interface,
+ *  i.e. the one monitor ID 0 maps to
+ * @device_display_id_count the total number of device display IDs on this
+ *  interface
+ *
+ * Sets the device information for this QXL interface, i.e. the hardware
+ * address (e.g. PCI) of the graphics device and the IDs of the displays of the
+ * graphics device that are exposed by this interface (device display IDs).
+ *
+ * The supported device address format is:
+ * "pci//./.../."
+ *
+ * The "pci" identifies the rest of the string as a PCI address. It is the only
+ * supported address at the moment, other identifiers can be introduced later.
+ *  is the PCI domain, followed by . of any PCI bridges
+ * in the chain leading to the device. The last . is the
+ * graphics device. All of , ,  are hexadecimal numbers
+ * with the following number of digits:
+ *   : 4
+ *   : 2
+ *   : 1
+ *
+ * The device_display_id_{start,count} denotes the sequence of device display
+ * IDs that map to the zero-based sequence of monitor IDs provided by monitors
+ * config on this interface. For example with device_display_id_start = 2 and
+ * device_display_id_count = 3 you get the following mapping:
+ * monitor_id  ->  device_display_id
+ *  0  ->  2
+ *  1  ->  3
+ *  2  ->  4
+ *
+ * Note this example is unsupported in practice. The on

  1   2   3   4   5   6   >