diff --git a/repos/ports/ports/virtualbox.hash b/repos/ports/ports/virtualbox.hash
index c3a0e9566..b31dd355d 100644
--- a/repos/ports/ports/virtualbox.hash
+++ b/repos/ports/ports/virtualbox.hash
@@ -1 +1 @@
-2fc156a977246088b14dc9acad72ea3013c9e596
+d0f14330729a8ef3234c8a569e183e230c28e100
diff --git a/repos/ports/ports/virtualbox.port b/repos/ports/ports/virtualbox.port
index f3b08c119..db4928aba 100644
--- a/repos/ports/ports/virtualbox.port
+++ b/repos/ports/ports/virtualbox.port
@@ -65,6 +65,7 @@ VBOX_MAIN_INC += USBDeviceImpl HostUSBDeviceImpl Matching Wrapper
VBOX_SRC_VBOX := VMM Devices Runtime GuestHost/HGSMI Storage Disassembler
VBOX_SRC_VBOX += HostDrivers/VBoxUSB/USBFilter.cpp
VBOX_SRC_VBOX += HostServices/SharedFolders Main/xml/Settings.cpp
+VBOX_SRC_VBOX += HostServices/SharedClipboard
VBOX_SRC_VBOX += Main/xml/VirtualBox-settings.xsd Main/xml/SchemaDefs.xsl
VBOX_SRC_VBOX += $(addsuffix .h, $(addprefix Main/include/, $(VBOX_MAIN_INC)))
VBOX_SRC_VBOX += $(addsuffix .cpp, $(addprefix Main/src-client/, $(VBOX_MAIN_CLI)))
@@ -83,9 +84,12 @@ VBOX_INC += usb.h usbfilter.h
VBOX_INC_COM := array.h assert.h AutoLock.h ErrorInfo.h EventQueue.h Guid.h
VBOX_INC_COM += list.h MultiResult.h string.h
-VBOX_CONTENT += $(addprefix src/VBox/, $(VBOX_SRC_VBOX))
-VBOX_CONTENT += $(addprefix include/VBox/, $(VBOX_INC))
+VBOX_INC_HOST := VBoxClipboardExt.h VBoxClipboardSvc.h
+
+VBOX_CONTENT += $(addprefix src/VBox/,$(VBOX_SRC_VBOX))
+VBOX_CONTENT += $(addprefix include/VBox/, $(VBOX_INC))
VBOX_CONTENT += $(addprefix include/VBox/com/, $(VBOX_INC_COM))
+VBOX_CONTENT += $(addprefix include/VBox/HostServices/, $(VBOX_INC_HOST))
VBOX_CONTENT += src/libs/zlib-1.2.6 src/libs/liblzf-3.4 src/libs/libxml2-2.6.31
VBOX_CONTENT += src/recompiler include/VBox/vmm include/iprt Config.kmk
diff --git a/repos/ports/src/virtualbox/dynlib.cc b/repos/ports/src/virtualbox/dynlib.cc
index ad846b59c..ed44778a8 100644
--- a/repos/ports/src/virtualbox/dynlib.cc
+++ b/repos/ports/src/virtualbox/dynlib.cc
@@ -22,14 +22,18 @@
extern "C" {
-DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad (VBOXHGCMSVCFNTABLE *ptable);
+DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad_sf (VBOXHGCMSVCFNTABLE *ptable);
+DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad_cb (VBOXHGCMSVCFNTABLE *ptable);
static struct shared {
const char * name;
const char * symbol;
void * func;
-} shared[] = {{ "VBoxSharedFolders", VBOX_HGCM_SVCLOAD_NAME, (void *)VBoxHGCMSvcLoad }};
+} shared[] = {
+ { "VBoxSharedFolders", VBOX_HGCM_SVCLOAD_NAME, (void *)VBoxHGCMSvcLoad_sf },
+ { "VBoxSharedClipboard", VBOX_HGCM_SVCLOAD_NAME, (void *)VBoxHGCMSvcLoad_cb }
+};
int RTLdrLoad(const char *pszFilename, PRTLDRMOD phLdrMod)
diff --git a/repos/ports/src/virtualbox/frontend/console.cc b/repos/ports/src/virtualbox/frontend/console.cc
index 5c1c20be0..25e634418 100644
--- a/repos/ports/src/virtualbox/frontend/console.cc
+++ b/repos/ports/src/virtualbox/frontend/console.cc
@@ -1,6 +1,22 @@
+/*
+ * \brief Port of VirtualBox to Genode
+ * \author Norman Feske
+ * \author Alexander Boettcher
+ */
+
+/*
+ * Copyright (C) 2013-2015 Genode Labs GmbH
+ *
+ * This file is distributed under the terms of the GNU General Public License
+ * version 2.
+ */
+
#include
+#include
#include
+#include
+#include
#include "ConsoleImpl.h"
#include "MachineImpl.h"
@@ -15,11 +31,13 @@
static const bool debug = false;
+static Genode::Attached_rom_dataspace *clipboard_rom = nullptr;
+static Genode::Reporter *clipboard_reporter = nullptr;
+
void Console::uninit() DUMMY()
HRESULT Console::resume(Reason_T aReason) DUMMY(E_FAIL)
HRESULT Console::pause(Reason_T aReason) DUMMY(E_FAIL)
void Console::enableVMMStatistics(BOOL aEnable) DUMMY()
-void Console::changeClipboardMode(ClipboardMode_T aClipboardMode) DUMMY()
HRESULT Console::updateMachineState(MachineState_T aMachineState) DUMMY(E_FAIL)
HRESULT Console::attachToTapInterface(INetworkAdapter *networkAdapter)
@@ -314,6 +332,41 @@ void GenodeConsole::handle_mode_change(unsigned)
update_video_mode();
}
+void GenodeConsole::init_clipboard()
+{
+ if (!&*machine())
+ return;
+
+ ClipboardMode_T mode;
+ machine()->COMGETTER(ClipboardMode)(&mode);
+
+ if (mode == ClipboardMode_Bidirectional ||
+ mode == ClipboardMode_HostToGuest) {
+
+ _clipboard_rom = new Genode::Attached_rom_dataspace("clipboard");
+ _clipboard_rom->sigh(_clipboard_signal_dispatcher);
+
+ clipboard_rom = _clipboard_rom;
+ }
+
+ if (mode == ClipboardMode_Bidirectional ||
+ mode == ClipboardMode_GuestToHost) {
+
+ _clipboard_reporter = new Genode::Reporter("clipboard");
+ _clipboard_reporter->enabled(true);
+
+ clipboard_reporter = _clipboard_reporter;
+ }
+}
+
+void GenodeConsole::handle_cb_rom_change(unsigned)
+{
+ if (!_clipboard_rom)
+ return;
+
+ vboxClipboardSync(nullptr);
+}
+
void GenodeConsole::event_loop(IKeyboard * gKeyboard, IMouse * gMouse)
{
_vbox_keyboard = gKeyboard;
@@ -345,3 +398,151 @@ void GenodeConsole::onMouseCapabilityChange(BOOL supportsAbsolute, BOOL supports
gMouse->PutMouseEventAbsolute(-1, -1, 0, 0, 0);
}
}
+
+
+
+
+/**********************
+ * Clipboard handling *
+ **********************/
+
+struct _VBOXCLIPBOARDCONTEXT
+{
+ VBOXCLIPBOARDCLIENTDATA *pClient;
+};
+
+static VBOXCLIPBOARDCONTEXT context;
+
+int vboxClipboardInit (void) { return VINF_SUCCESS; }
+
+void vboxClipboardDestroy (void)
+{
+ clipboard_rom = nullptr;
+}
+
+int vboxClipboardConnect (VBOXCLIPBOARDCLIENTDATA *pClient, bool fHeadless)
+{
+ if (!pClient || context.pClient != NULL)
+ return VERR_NOT_SUPPORTED;
+
+ vboxSvcClipboardLock();
+
+ pClient->pCtx = &context;
+ pClient->pCtx->pClient = pClient;
+
+ vboxSvcClipboardUnlock();
+
+ int rc = vboxClipboardSync (pClient);
+
+ return rc;
+}
+
+void vboxClipboardDisconnect (VBOXCLIPBOARDCLIENTDATA *pClient)
+{
+ if (!pClient || !pClient->pCtx)
+ return;
+
+ vboxSvcClipboardLock();
+ pClient->pCtx->pClient = NULL;
+ vboxSvcClipboardUnlock();
+}
+
+void vboxClipboardFormatAnnounce (VBOXCLIPBOARDCLIENTDATA *pClient,
+ uint32_t formats)
+{
+ if (!pClient)
+ return;
+
+ vboxSvcClipboardReportMsg (pClient,
+ VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA,
+ formats);
+}
+
+int vboxClipboardReadData (VBOXCLIPBOARDCLIENTDATA *pClient, uint32_t format,
+ void *pv, uint32_t const cb, uint32_t *pcbActual)
+{
+ if (!clipboard_rom || format != VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
+ return VERR_NOT_SUPPORTED;
+
+ if (!pv || !pcbActual || cb == 0)
+ return VERR_INVALID_PARAMETER;
+
+ clipboard_rom->update();
+
+ if (!clipboard_rom->is_valid()) {
+ PERR("invalid clipboard dataspace");
+ return VERR_NOT_SUPPORTED;
+ }
+
+ char * data = clipboard_rom->local_addr();
+
+ try {
+
+ Genode::Xml_node node(data);
+ if (!node.has_type("clipboard")) {
+ PERR("invalid clipboard xml syntax");
+ return VERR_INVALID_PARAMETER;
+ }
+
+ size_t const len = node.content_size();
+ size_t written = 0;
+
+ PRTUTF16 utf16_string = reinterpret_cast(pv);
+ int rc = RTStrToUtf16Ex(node.content_base(), len, &utf16_string, cb, &written);
+
+ if (RT_SUCCESS(rc)) {
+ if ((written * 2) + 2 > cb)
+ written = (cb - 2) / 2;
+
+ /* +1 stuff required for Windows guests ... linux guest doesn't care */
+ *pcbActual = (written + 1) * 2;
+ utf16_string[written] = 0;
+ } else
+ *pcbActual = 0;
+
+ } catch (Genode::Xml_node::Invalid_syntax) {
+ PERR("invalid clipboard xml syntax");
+ return VERR_INVALID_PARAMETER;
+ }
+
+ return VINF_SUCCESS;
+}
+
+void vboxClipboardWriteData (VBOXCLIPBOARDCLIENTDATA *pClient, void *pv,
+ uint32_t cb, uint32_t format)
+{
+ if (format != VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT || !pv || !pClient ||
+ !clipboard_reporter)
+ return;
+
+ PCRTUTF16 utf16str = reinterpret_cast(pv);
+ char * message = 0;
+
+ int rc = RTUtf16ToUtf8(utf16str, &message);
+
+ if (!RT_SUCCESS(rc) || !message)
+ return;
+
+ try {
+ Genode::Reporter::Xml_generator xml(*clipboard_reporter, [&] () {
+ xml.append_sanitized(message, strlen(message)); });
+ } catch (...) {
+ PERR("could not write clipboard data");
+ }
+
+ RTStrFree(message);
+}
+
+int vboxClipboardSync (VBOXCLIPBOARDCLIENTDATA *pClient)
+{
+ if (!pClient)
+ pClient = context.pClient;
+
+ if (!pClient)
+ return VERR_NOT_SUPPORTED;
+
+ vboxSvcClipboardReportMsg (pClient, VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS,
+ VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT);
+
+ return VINF_SUCCESS;
+}
diff --git a/repos/ports/src/virtualbox/frontend/console.h b/repos/ports/src/virtualbox/frontend/console.h
index d0edc5065..89926c30d 100644
--- a/repos/ports/src/virtualbox/frontend/console.h
+++ b/repos/ports/src/virtualbox/frontend/console.h
@@ -13,20 +13,24 @@
*/
/* Genode includes */
+#include
#include
#include
#include
+#include
+#include
+#include
+#include
#include
/* included from os/src/drivers/input/spec/ps2 */
#include
+/* repos/ports includes */
+#include
+
/* VirtualBox includes */
#include "ConsoleImpl.h"
-#include
-#include
-#include
-#include
class Scan_code
@@ -115,10 +119,13 @@ class GenodeConsole : public Console {
Report::Connection _shape_report_connection;
Genode::Attached_dataspace _shape_report_ds;
Vbox_pointer::Shape_report *_shape_report;
+ Genode::Reporter *_clipboard_reporter;
+ Genode::Attached_rom_dataspace *_clipboard_rom;
IKeyboard *_vbox_keyboard;
IMouse *_vbox_mouse;
Genode::Signal_dispatcher _input_signal_dispatcher;
Genode::Signal_dispatcher _mode_change_signal_dispatcher;
+ Genode::Signal_dispatcher _clipboard_signal_dispatcher;
bool _key_status[Input::KEY_MAX + 1];
@@ -140,10 +147,13 @@ class GenodeConsole : public Console {
_shape_report_connection("shape", sizeof(Vbox_pointer::Shape_report)),
_shape_report_ds(_shape_report_connection.dataspace()),
_shape_report(_shape_report_ds.local_addr()),
+ _clipboard_reporter(nullptr),
+ _clipboard_rom(nullptr),
_vbox_keyboard(0),
_vbox_mouse(0),
_input_signal_dispatcher(_receiver, *this, &GenodeConsole::handle_input),
- _mode_change_signal_dispatcher(_receiver, *this, &GenodeConsole::handle_mode_change)
+ _mode_change_signal_dispatcher(_receiver, *this, &GenodeConsole::handle_mode_change),
+ _clipboard_signal_dispatcher(_receiver, *this, &GenodeConsole::handle_cb_rom_change)
{
for (unsigned i = 0; i <= Input::KEY_MAX; i++)
_key_status[i] = 0;
@@ -151,6 +161,8 @@ class GenodeConsole : public Console {
_input.sigh(_input_signal_dispatcher);
}
+ void init_clipboard();
+
void event_loop(IKeyboard * gKeyboard, IMouse * gMouse);
void onMouseCapabilityChange(BOOL supportsAbsolute, BOOL supportsRelative,
@@ -219,4 +231,5 @@ class GenodeConsole : public Console {
void handle_input(unsigned);
void handle_mode_change(unsigned);
+ void handle_cb_rom_change(unsigned);
};
diff --git a/repos/ports/src/virtualbox/frontend/main.cc b/repos/ports/src/virtualbox/frontend/main.cc
index 9db1fd65d..bdef5a971 100644
--- a/repos/ports/src/virtualbox/frontend/main.cc
+++ b/repos/ports/src/virtualbox/frontend/main.cc
@@ -145,6 +145,12 @@ HRESULT setupmachine()
ComPtr gConsole;
rc = session->COMGETTER(Console)(gConsole.asOutParam());
+ /* handle input of Genode and forward it to VMM layer */
+ ComPtr genodeConsole = gConsole;
+ RTLogPrintf("genodeConsole = %p\n", genodeConsole);
+
+ genodeConsole->init_clipboard();
+
/* Display object */
ComPtr display;
rc = gConsole->COMGETTER(Display)(display.asOutParam());
@@ -194,10 +200,6 @@ HRESULT setupmachine()
return rc;
Assert (&*gKeyboard);
- /* handle input of Genode and forward it to VMM layer */
- ComPtr genodeConsole = gConsole;
- RTLogPrintf("genodeConsole = %p\n", genodeConsole);
-
genodeConsole->event_loop(gKeyboard, gMouse);
Assert(!"return not expected");
diff --git a/repos/ports/src/virtualbox/include/VBox/HostServices/VBoxClipboardSvc.h b/repos/ports/src/virtualbox/include/VBox/HostServices/VBoxClipboardSvc.h
deleted file mode 100644
index 14565a70a..000000000
--- a/repos/ports/src/virtualbox/include/VBox/HostServices/VBoxClipboardSvc.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef ___VBox_HostService_VBoxClipboardSvc_h
-#define ___VBox_HostService_VBoxClipboardSvc_h
-
-#define VBOX_SHARED_CLIPBOARD_HOST_FN_SET_HEADLESS 2
-
-#endif
diff --git a/repos/ports/src/virtualbox/patches/hostservice.patch b/repos/ports/src/virtualbox/patches/hostservice.patch
new file mode 100644
index 000000000..85301fe2c
--- /dev/null
+++ b/repos/ports/src/virtualbox/patches/hostservice.patch
@@ -0,0 +1,20 @@
++++ a/src/app/virtualbox/src/VBox/HostServices/SharedFolders/service.cpp
+@@ -1445,7 +1489,7 @@
+ return rc;
+ }
+
+-extern "C" DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad (VBOXHGCMSVCFNTABLE *ptable)
++extern "C" DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad_sf (VBOXHGCMSVCFNTABLE *ptable)
+ {
+ int rc = VINF_SUCCESS;
+
++++ a/src/app/virtualbox/src/VBox/HostServices/SharedClipboard/service.cpp
+@@ -966,7 +966,7 @@
+ return VINF_SUCCESS;
+ }
+
+-extern "C" DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad (VBOXHGCMSVCFNTABLE *ptable)
++extern "C" DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad_cb (VBOXHGCMSVCFNTABLE *ptable)
+ {
+ int rc = VINF_SUCCESS;
+
diff --git a/repos/ports/src/virtualbox/patches/series b/repos/ports/src/virtualbox/patches/series
index 4eb5ca280..5523f9407 100644
--- a/repos/ports/src/virtualbox/patches/series
+++ b/repos/ports/src/virtualbox/patches/series
@@ -22,3 +22,4 @@ rem_irq.patch
usb.patch
tm_smp.patch
posix.patch
+hostservice.patch
diff --git a/repos/ports/src/virtualbox/patches/vbox_main.patch b/repos/ports/src/virtualbox/patches/vbox_main.patch
index 6df439977..e78f42160 100644
--- a/repos/ports/src/virtualbox/patches/vbox_main.patch
+++ b/repos/ports/src/virtualbox/patches/vbox_main.patch
@@ -772,14 +772,14 @@ index 69e3109..141bb98 100644
/**
* Fetches the list of global or machine shared folders from the server.
*
-@@ -8353,6 +8437,8 @@ DECLCALLBACK(void) Console::vmstateChangeCallback(PUVM pUVM, VMSTATE enmState, V
- }
+@@ -8390,6 +8474,8 @@
+ pVMMDev->hgcmHostCall("VBoxSharedClipboard", VBOX_SHARED_CLIPBOARD_HOST_FN_SET_MODE, 1, &parm);
}
+#if 0
+
/**
- * Changes the clipboard mode.
+ * Changes the drag'n_drop mode.
*
@@ -8426,7 +8512,7 @@ void Console::changeDragAndDropMode(DragAndDropMode_T aDragAndDropMode)
diff --git a/repos/ports/src/virtualbox/target.mk b/repos/ports/src/virtualbox/target.mk
index 7b456a66a..7ebb0e071 100644
--- a/repos/ports/src/virtualbox/target.mk
+++ b/repos/ports/src/virtualbox/target.mk
@@ -13,7 +13,7 @@ SRC_CC = frontend/main.cc frontend/console.cc \
frontend/USBProxyDevice-genode.cpp \
devices.cc drivers.cc dummies.cc libc.cc \
logger.cc mm.cc pdm.cc pgm.cc rt.cc sup.cc iommio.cc ioport.cc \
- hm.cc thread.cc dynlib.cc unimpl.cc
+ hm.cc thread.cc dynlib.cc unimpl.cc
LIBS += base
LIBS += config_args
@@ -38,6 +38,8 @@ SRC_CC += HostServices/SharedFolders/mappings.cpp
SRC_CC += HostServices/SharedFolders/vbsf.cpp
SRC_CC += HostServices/SharedFolders/shflhandle.cpp
+SRC_CC += HostServices/SharedClipboard/service.cpp
+
SRC_CC += frontend/dummy/errorinfo.cc frontend/dummy/virtualboxbase.cc
SRC_CC += frontend/dummy/autostart.cc frontend/dummy/rest.cc
SRC_CC += frontend/dummy/host.cc
@@ -50,6 +52,7 @@ INC_DIR += $(REP_DIR)/src/virtualbox/frontend/VBoxAPIWrap
INC_DIR += $(VBOX_DIR)/Main/xml
INC_DIR += $(VBOX_DIR)/Devices/USB
+INC_DIR += $(VBOX_DIR)/HostServices
# search path to 'scan_code_set_2.h'
INC_DIR += $(call select_from_repositories,src/drivers/input/spec/ps2)